[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree

zrouter-src-freebsd at zrouter.org zrouter-src-freebsd at zrouter.org
Wed Jul 25 14:36:06 UTC 2012


details:   http://zrouter.org/hg/FreeBSD/head//rev/91983250c121
changeset: 490:91983250c121
user:      Aleksandr Rybalko <ray at ddteam.net>
date:      Wed Jul 25 16:29:58 2012 +0300
description:
Lazy update

diffstat:

 head/usr.sbin/Makefile                                      |    17 +-
 head/usr.sbin/acpi/acpidb/Makefile                          |     9 +-
 head/usr.sbin/acpi/acpidump/acpi.c                          |    18 +-
 head/usr.sbin/acpi/iasl/Makefile                            |    17 +-
 head/usr.sbin/adduser/rmuser.8                              |     4 +-
 head/usr.sbin/ancontrol/ancontrol.c                         |     4 +-
 head/usr.sbin/apmd/apmd.8                                   |     8 +-
 head/usr.sbin/arp/arp.4                                     |     6 +-
 head/usr.sbin/bluetooth/bthidcontrol/bthidcontrol.8         |     4 +-
 head/usr.sbin/bluetooth/bthidd/parser.y                     |     4 +-
 head/usr.sbin/bluetooth/btpand/btpand.8                     |     8 +-
 head/usr.sbin/bluetooth/hccontrol/hccontrol.8               |     6 +-
 head/usr.sbin/bluetooth/hcsecd/parser.y                     |     3 +-
 head/usr.sbin/bluetooth/l2control/l2control.8               |     4 +-
 head/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8             |     4 +-
 head/usr.sbin/bsdconfig/Makefile                            |    32 +
 head/usr.sbin/bsdconfig/USAGE                               |    40 +
 head/usr.sbin/bsdconfig/bsdconfig                           |   313 ++
 head/usr.sbin/bsdconfig/bsdconfig.8                         |   233 +
 head/usr.sbin/bsdconfig/console/INDEX                       |    59 +
 head/usr.sbin/bsdconfig/console/Makefile                    |    16 +
 head/usr.sbin/bsdconfig/console/USAGE                       |    33 +
 head/usr.sbin/bsdconfig/console/console                     |   137 +
 head/usr.sbin/bsdconfig/console/font                        |   205 +
 head/usr.sbin/bsdconfig/console/include/Makefile            |    11 +
 head/usr.sbin/bsdconfig/console/include/messages.subr       |   264 +
 head/usr.sbin/bsdconfig/console/keymap                      |   365 ++
 head/usr.sbin/bsdconfig/console/repeat                      |   134 +
 head/usr.sbin/bsdconfig/console/saver                       |   198 +
 head/usr.sbin/bsdconfig/console/screenmap                   |   142 +
 head/usr.sbin/bsdconfig/console/ttys                        |   197 +
 head/usr.sbin/bsdconfig/diskmgmt/INDEX                      |    53 +
 head/usr.sbin/bsdconfig/diskmgmt/Makefile                   |    16 +
 head/usr.sbin/bsdconfig/diskmgmt/USAGE                      |    33 +
 head/usr.sbin/bsdconfig/diskmgmt/diskmgmt                   |    85 +
 head/usr.sbin/bsdconfig/diskmgmt/include/Makefile           |    11 +
 head/usr.sbin/bsdconfig/diskmgmt/include/messages.subr      |    27 +
 head/usr.sbin/bsdconfig/docsinstall/INDEX                   |    53 +
 head/usr.sbin/bsdconfig/docsinstall/Makefile                |    16 +
 head/usr.sbin/bsdconfig/docsinstall/USAGE                   |    33 +
 head/usr.sbin/bsdconfig/docsinstall/docsinstall             |    97 +
 head/usr.sbin/bsdconfig/docsinstall/include/Makefile        |    11 +
 head/usr.sbin/bsdconfig/docsinstall/include/messages.subr   |    28 +
 head/usr.sbin/bsdconfig/dot/INDEX                           |    53 +
 head/usr.sbin/bsdconfig/dot/Makefile                        |    16 +
 head/usr.sbin/bsdconfig/dot/USAGE                           |   143 +
 head/usr.sbin/bsdconfig/dot/dot                             |   646 ++++
 head/usr.sbin/bsdconfig/dot/include/Makefile                |    11 +
 head/usr.sbin/bsdconfig/dot/include/messages.subr           |    30 +
 head/usr.sbin/bsdconfig/examples/Makefile                   |    11 +
 head/usr.sbin/bsdconfig/examples/bsdconfigrc                |    35 +
 head/usr.sbin/bsdconfig/include/Makefile                    |    12 +
 head/usr.sbin/bsdconfig/include/common.subr                 |   299 +
 head/usr.sbin/bsdconfig/include/dialog.subr                 |  1441 +++++++++
 head/usr.sbin/bsdconfig/include/messages.subr               |    56 +
 head/usr.sbin/bsdconfig/include/mustberoot.subr             |   360 ++
 head/usr.sbin/bsdconfig/include/strings.subr                |   104 +
 head/usr.sbin/bsdconfig/include/sysrc.subr                  |   616 ++++
 head/usr.sbin/bsdconfig/mouse/INDEX                         |    58 +
 head/usr.sbin/bsdconfig/mouse/Makefile                      |    16 +
 head/usr.sbin/bsdconfig/mouse/USAGE                         |    33 +
 head/usr.sbin/bsdconfig/mouse/disable                       |   104 +
 head/usr.sbin/bsdconfig/mouse/enable                        |   118 +
 head/usr.sbin/bsdconfig/mouse/flags                         |   116 +
 head/usr.sbin/bsdconfig/mouse/include/Makefile              |    11 +
 head/usr.sbin/bsdconfig/mouse/include/messages.subr         |    90 +
 head/usr.sbin/bsdconfig/mouse/mouse                         |   134 +
 head/usr.sbin/bsdconfig/mouse/port                          |   142 +
 head/usr.sbin/bsdconfig/mouse/type                          |   158 +
 head/usr.sbin/bsdconfig/networking/INDEX                    |    57 +
 head/usr.sbin/bsdconfig/networking/Makefile                 |    16 +
 head/usr.sbin/bsdconfig/networking/USAGE                    |    33 +
 head/usr.sbin/bsdconfig/networking/defaultrouter            |    73 +
 head/usr.sbin/bsdconfig/networking/devices                  |   158 +
 head/usr.sbin/bsdconfig/networking/hostname                 |    73 +
 head/usr.sbin/bsdconfig/networking/include/Makefile         |    12 +
 head/usr.sbin/bsdconfig/networking/include/common.subr      |    65 +
 head/usr.sbin/bsdconfig/networking/include/device.subr      |   489 +++
 head/usr.sbin/bsdconfig/networking/include/hostname.subr    |   211 +
 head/usr.sbin/bsdconfig/networking/include/ipaddr.subr      |   236 +
 head/usr.sbin/bsdconfig/networking/include/media.subr       |   235 +
 head/usr.sbin/bsdconfig/networking/include/messages.subr    |   100 +
 head/usr.sbin/bsdconfig/networking/include/netmask.subr     |   215 +
 head/usr.sbin/bsdconfig/networking/include/resolv.subr      |   509 +++
 head/usr.sbin/bsdconfig/networking/include/routing.subr     |   168 +
 head/usr.sbin/bsdconfig/networking/nameservers              |    73 +
 head/usr.sbin/bsdconfig/networking/networking               |   146 +
 head/usr.sbin/bsdconfig/password/INDEX                      |    53 +
 head/usr.sbin/bsdconfig/password/Makefile                   |    16 +
 head/usr.sbin/bsdconfig/password/USAGE                      |    33 +
 head/usr.sbin/bsdconfig/password/include/Makefile           |    11 +
 head/usr.sbin/bsdconfig/password/include/messages.subr      |    35 +
 head/usr.sbin/bsdconfig/password/include/password.subr      |   122 +
 head/usr.sbin/bsdconfig/password/password                   |    82 +
 head/usr.sbin/bsdconfig/security/INDEX                      |    54 +
 head/usr.sbin/bsdconfig/security/Makefile                   |    16 +
 head/usr.sbin/bsdconfig/security/USAGE                      |    33 +
 head/usr.sbin/bsdconfig/security/include/Makefile           |    11 +
 head/usr.sbin/bsdconfig/security/include/messages.subr      |    48 +
 head/usr.sbin/bsdconfig/security/kern_securelevel           |   135 +
 head/usr.sbin/bsdconfig/security/security                   |   149 +
 head/usr.sbin/bsdconfig/startup/INDEX                       |    58 +
 head/usr.sbin/bsdconfig/startup/Makefile                    |    16 +
 head/usr.sbin/bsdconfig/startup/USAGE                       |    33 +
 head/usr.sbin/bsdconfig/startup/include/Makefile            |    11 +
 head/usr.sbin/bsdconfig/startup/include/messages.subr       |   112 +
 head/usr.sbin/bsdconfig/startup/include/rcconf.subr         |   466 +++
 head/usr.sbin/bsdconfig/startup/include/rcedit.subr         |   106 +
 head/usr.sbin/bsdconfig/startup/include/rcvar.subr          |   206 +
 head/usr.sbin/bsdconfig/startup/misc                        |   406 ++
 head/usr.sbin/bsdconfig/startup/rcadd                       |   153 +
 head/usr.sbin/bsdconfig/startup/rcconf                      |   246 +
 head/usr.sbin/bsdconfig/startup/rcdelete                    |   355 ++
 head/usr.sbin/bsdconfig/startup/rcedit                      |    69 +
 head/usr.sbin/bsdconfig/startup/rcvar                       |   200 +
 head/usr.sbin/bsdconfig/startup/startup                     |   128 +
 head/usr.sbin/bsdconfig/timezone/INDEX                      |    53 +
 head/usr.sbin/bsdconfig/timezone/Makefile                   |    16 +
 head/usr.sbin/bsdconfig/timezone/USAGE                      |    42 +
 head/usr.sbin/bsdconfig/timezone/include/Makefile           |    12 +
 head/usr.sbin/bsdconfig/timezone/include/continents.subr    |   138 +
 head/usr.sbin/bsdconfig/timezone/include/countries.subr     |    78 +
 head/usr.sbin/bsdconfig/timezone/include/iso3166.subr       |   197 +
 head/usr.sbin/bsdconfig/timezone/include/menus.subr         |   220 +
 head/usr.sbin/bsdconfig/timezone/include/messages.subr      |    78 +
 head/usr.sbin/bsdconfig/timezone/include/zones.subr         |   670 ++++
 head/usr.sbin/bsdconfig/timezone/timezone                   |   448 ++
 head/usr.sbin/bsdconfig/ttys/INDEX                          |    53 +
 head/usr.sbin/bsdconfig/ttys/Makefile                       |    16 +
 head/usr.sbin/bsdconfig/ttys/USAGE                          |    33 +
 head/usr.sbin/bsdconfig/ttys/include/Makefile               |    11 +
 head/usr.sbin/bsdconfig/ttys/include/messages.subr          |    31 +
 head/usr.sbin/bsdconfig/ttys/ttys                           |   128 +
 head/usr.sbin/bsdconfig/usermgmt/INDEX                      |    60 +
 head/usr.sbin/bsdconfig/usermgmt/Makefile                   |    17 +
 head/usr.sbin/bsdconfig/usermgmt/USAGE                      |    33 +
 head/usr.sbin/bsdconfig/usermgmt/groupadd                   |    64 +
 head/usr.sbin/bsdconfig/usermgmt/groupdel                   |    93 +
 head/usr.sbin/bsdconfig/usermgmt/groupedit                  |    93 +
 head/usr.sbin/bsdconfig/usermgmt/groupinput                 |   295 +
 head/usr.sbin/bsdconfig/usermgmt/include/Makefile           |    11 +
 head/usr.sbin/bsdconfig/usermgmt/include/group_input.subr   |   437 ++
 head/usr.sbin/bsdconfig/usermgmt/include/messages.subr      |   111 +
 head/usr.sbin/bsdconfig/usermgmt/include/user_input.subr    |  1180 +++++++
 head/usr.sbin/bsdconfig/usermgmt/useradd                    |    64 +
 head/usr.sbin/bsdconfig/usermgmt/userdel                    |    93 +
 head/usr.sbin/bsdconfig/usermgmt/useredit                   |    93 +
 head/usr.sbin/bsdconfig/usermgmt/userinput                  |   515 +++
 head/usr.sbin/bsdconfig/usermgmt/usermgmt                   |   150 +
 head/usr.sbin/bsdinstall/partedit/diskeditor.c              |     5 +-
 head/usr.sbin/bsdinstall/partedit/part_wizard.c             |     8 +-
 head/usr.sbin/bsdinstall/scripts/mirrorselect               |     4 +-
 head/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3  |     7 +-
 head/usr.sbin/bsnmpd/modules/snmp_wlan/snmp_wlan.3          |     6 +-
 head/usr.sbin/config/config.h                               |     3 +-
 head/usr.sbin/config/main.c                                 |     3 +-
 head/usr.sbin/cpucontrol/amd.c                              |     4 +-
 head/usr.sbin/cpucontrol/cpucontrol.8                       |     4 +-
 head/usr.sbin/cpucontrol/cpucontrol.c                       |    12 +-
 head/usr.sbin/cron/crontab/crontab.5                        |    21 +-
 head/usr.sbin/cron/crontab/crontab.c                        |    11 +-
 head/usr.sbin/crunch/crunchgen/crunched_main.c              |    19 +-
 head/usr.sbin/crunch/crunchgen/crunchgen.c                  |   115 +-
 head/usr.sbin/crunch/crunchide/crunchide.c                  |    29 +-
 head/usr.sbin/crunch/crunchide/exec_elf32.c                 |     5 +-
 head/usr.sbin/ctladm/ctladm.8                               |    16 +-
 head/usr.sbin/ctladm/ctladm.c                               |    10 +-
 head/usr.sbin/daemon/daemon.8                               |     6 +-
 head/usr.sbin/daemon/daemon.c                               |     8 +-
 head/usr.sbin/digictl/digictl.8                             |     4 +-
 head/usr.sbin/etcupdate/Makefile                            |     6 +
 head/usr.sbin/etcupdate/etcupdate.8                         |   789 +++++
 head/usr.sbin/etcupdate/etcupdate.sh                        |  1675 +++++++++++
 head/usr.sbin/fifolog/lib/getdate.y                         |     4 +-
 head/usr.sbin/flowctl/flowctl.8                             |    12 +-
 head/usr.sbin/flowctl/flowctl.c                             |    41 +-
 head/usr.sbin/freebsd-update/freebsd-update.8               |     4 +-
 head/usr.sbin/fwcontrol/fwcontrol.8                         |     4 +-
 head/usr.sbin/gssd/gssd.8                                   |     4 +-
 head/usr.sbin/i2c/i2c.8                                     |     4 +-
 head/usr.sbin/ifmcstat/ifmcstat.c                           |     7 +-
 head/usr.sbin/inetd/inetd.c                                 |     8 +-
 head/usr.sbin/inetd/inetd.h                                 |     4 +-
 head/usr.sbin/ipfwpcap/ipfwpcap.8                           |     6 +-
 head/usr.sbin/jail/Makefile                                 |    15 +-
 head/usr.sbin/jail/command.c                                |   860 +++++
 head/usr.sbin/jail/config.c                                 |   833 +++++
 head/usr.sbin/jail/jail.8                                   |   708 +++-
 head/usr.sbin/jail/jail.c                                   |  1283 +++++--
 head/usr.sbin/jail/jail.conf.5                              |   231 +
 head/usr.sbin/jail/jaillex.l                                |   233 +
 head/usr.sbin/jail/jailp.h                                  |   233 +
 head/usr.sbin/jail/jailparse.y                              |   216 +
 head/usr.sbin/jail/state.c                                  |   469 +++
 head/usr.sbin/kbdmap/kbdmap.c                               |     5 +-
 head/usr.sbin/kldxref/ef.c                                  |     6 +-
 head/usr.sbin/lpr/common_source/common.c                    |    14 +-
 head/usr.sbin/lpr/lpc/cmds.c                                |    28 +-
 head/usr.sbin/lpr/lpr/lpr.c                                 |     4 +-
 head/usr.sbin/mfiutil/Makefile                              |     3 +-
 head/usr.sbin/mfiutil/mfi_cmd.c                             |     6 +-
 head/usr.sbin/mfiutil/mfi_config.c                          |    21 +-
 head/usr.sbin/mfiutil/mfi_drive.c                           |    23 +-
 head/usr.sbin/mfiutil/mfi_evt.c                             |     9 +-
 head/usr.sbin/mfiutil/mfi_flash.c                           |     4 +-
 head/usr.sbin/mfiutil/mfi_patrol.c                          |    17 +-
 head/usr.sbin/mfiutil/mfi_show.c                            |    53 +-
 head/usr.sbin/mfiutil/mfi_volume.c                          |     9 +-
 head/usr.sbin/mfiutil/mfiutil.c                             |     6 +-
 head/usr.sbin/mfiutil/mfiutil.h                             |     4 +-
 head/usr.sbin/mptutil/mpt_show.c                            |     4 +-
 head/usr.sbin/nandsim/Makefile                              |     8 +
 head/usr.sbin/nandsim/nandsim.8                             |   229 +
 head/usr.sbin/nandsim/nandsim.c                             |  1397 +++++++++
 head/usr.sbin/nandsim/nandsim_cfgparse.c                    |   959 ++++++
 head/usr.sbin/nandsim/nandsim_cfgparse.h                    |    86 +
 head/usr.sbin/nandsim/nandsim_rcfile.c                      |   440 ++
 head/usr.sbin/nandsim/nandsim_rcfile.h                      |    70 +
 head/usr.sbin/nandsim/sample.conf                           |   174 +
 head/usr.sbin/nandtool/Makefile                             |    11 +
 head/usr.sbin/nandtool/nand_erase.c                         |   114 +
 head/usr.sbin/nandtool/nand_info.c                          |    86 +
 head/usr.sbin/nandtool/nand_read.c                          |   139 +
 head/usr.sbin/nandtool/nand_readoob.c                       |   111 +
 head/usr.sbin/nandtool/nand_write.c                         |   143 +
 head/usr.sbin/nandtool/nand_writeoob.c                      |   113 +
 head/usr.sbin/nandtool/nandtool.8                           |   184 +
 head/usr.sbin/nandtool/nandtool.c                           |   283 +
 head/usr.sbin/nandtool/nandtool.h                           |    57 +
 head/usr.sbin/nandtool/usage.h                              |   112 +
 head/usr.sbin/ndiscvt/ndiscvt.8                             |     4 +-
 head/usr.sbin/ndp/ndp.8                                     |    13 +-
 head/usr.sbin/ndp/ndp.c                                     |     9 +-
 head/usr.sbin/newsyslog/newsyslog.8                         |     4 +-
 head/usr.sbin/newsyslog/newsyslog.c                         |    11 +-
 head/usr.sbin/newsyslog/newsyslog.conf.5                    |    17 +-
 head/usr.sbin/nfsd/nfsv4.4                                  |     4 +-
 head/usr.sbin/nscd/cachelib.c                               |    28 +-
 head/usr.sbin/nscd/cachelib.h                               |     4 +-
 head/usr.sbin/nscd/config.c                                 |     4 +-
 head/usr.sbin/nscd/config.h                                 |     4 +-
 head/usr.sbin/nscd/nscd.conf.5                              |    13 +-
 head/usr.sbin/nscd/parser.c                                 |    46 +-
 head/usr.sbin/ntp/doc/ntp.conf.5                            |    33 +-
 head/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh   |   111 +-
 head/usr.sbin/pc-sysinstall/backend/functions-disk.sh       |    50 +-
 head/usr.sbin/pc-sysinstall/backend/functions-localize.sh   |     3 +-
 head/usr.sbin/pc-sysinstall/backend/functions-networking.sh |    58 +-
 head/usr.sbin/pc-sysinstall/backend/functions-newfs.sh      |    46 +-
 head/usr.sbin/pc-sysinstall/backend/functions-parse.sh      |    14 +-
 head/usr.sbin/pc-sysinstall/backend/functions.sh            |    21 +-
 head/usr.sbin/pciconf/Makefile                              |     4 +-
 head/usr.sbin/pciconf/cap.c                                 |    58 +-
 head/usr.sbin/pciconf/err.c                                 |   167 +
 head/usr.sbin/pciconf/pciconf.8                             |    15 +-
 head/usr.sbin/pciconf/pciconf.c                             |    26 +-
 head/usr.sbin/pciconf/pciconf.h                             |     5 +-
 head/usr.sbin/pkg/pkg.c                                     |    68 +-
 head/usr.sbin/pkg_install/add/main.c                        |    17 +-
 head/usr.sbin/pkg_install/add/perform.c                     |    19 +-
 head/usr.sbin/pkg_install/add/pkg_add.1                     |     7 +-
 head/usr.sbin/pkg_install/lib/exec.c                        |     4 +-
 head/usr.sbin/pkg_install/lib/file.c                        |     4 +-
 head/usr.sbin/pkg_install/lib/lib.h                         |     4 +-
 head/usr.sbin/pkg_install/lib/msg.c                         |     3 +-
 head/usr.sbin/pkg_install/lib/plist.c                       |     5 +-
 head/usr.sbin/pkg_install/lib/url.c                         |    12 +-
 head/usr.sbin/pkg_install/updating/pkg_updating.1           |     4 +-
 head/usr.sbin/pmcstat/pmcstat.8                             |     4 +-
 head/usr.sbin/pmcstat/pmcstat_log.c                         |    12 +-
 head/usr.sbin/portsnap/portsnap/portsnap.sh                 |     5 +-
 head/usr.sbin/ppp/throughput.c                              |    16 +-
 head/usr.sbin/rarpd/Makefile                                |     5 +-
 head/usr.sbin/rarpd/rarpd.8                                 |    16 +-
 head/usr.sbin/rarpd/rarpd.c                                 |    82 +-
 head/usr.sbin/rpc.lockd/kern.c                              |     4 +-
 head/usr.sbin/rtadvctl/rtadvctl.8                           |     5 +-
 head/usr.sbin/rtadvd/rtadvd.8                               |     4 +-
 head/usr.sbin/rtprio/rtprio.c                               |    11 +-
 head/usr.sbin/setfib/setfib.1                               |     4 +-
 head/usr.sbin/smbmsg/smbmsg.8                               |     4 +-
 head/usr.sbin/syslogd/syslogd.8                             |     4 +-
 head/usr.sbin/tcpdump/tcpdump/Makefile                      |    15 +-
 head/usr.sbin/tcpdump/tcpdump/config.h                      |    50 +-
 head/usr.sbin/tcpdump/tcpdump/tcpdump.1                     |    69 +-
 head/usr.sbin/traceroute6/traceroute6.c                     |     7 +-
 head/usr.sbin/usbdump/usbdump.8                             |    14 +-
 head/usr.sbin/usbdump/usbdump.c                             |   134 +-
 head/usr.sbin/utx/utx.8                                     |     4 +-
 head/usr.sbin/vidcontrol/vidcontrol.c                       |    14 +-
 head/usr.sbin/wpa/Makefile.crypto                           |   121 +
 head/usr.sbin/wpa/Makefile.inc                              |    11 +-
 head/usr.sbin/wpa/hostapd/Makefile                          |   186 +-
 head/usr.sbin/wpa/hostapd/hostapd.8                         |     6 +-
 head/usr.sbin/wpa/hostapd/hostapd.conf.5                    |     9 +-
 head/usr.sbin/wpa/ndis_events/ndis_events.8                 |     4 +-
 head/usr.sbin/wpa/wpa_supplicant/Makefile                   |   178 +-
 head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5      |     6 +-
 298 files changed, 32854 insertions(+), 1486 deletions(-)

diffs (39741 lines):

diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/Makefile
--- a/head/usr.sbin/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,5 +1,5 @@
 #	From: @(#)Makefile	5.20 (Berkeley) 6/12/93
-# $FreeBSD: head/usr.sbin/Makefile 234313 2012-04-15 15:13:36Z bapt $
+# $FreeBSD: head/usr.sbin/Makefile 238438 2012-07-14 03:16:57Z dteske $
 
 .include <bsd.own.mk>
 
@@ -23,6 +23,7 @@
 	digictl \
 	diskinfo \
 	dumpcis \
+	etcupdate \
 	extattr \
 	extattrctl \
 	fifolog \
@@ -143,6 +144,10 @@
 SUBDIR+=	bluetooth
 .endif
 
+.if ${MK_BSDCONFIG} != "no"
+SUBDIR+=	bsdconfig
+.endif
+
 .if ${MK_BSNMP} != "no"
 SUBDIR+=	bsnmpd
 .endif
@@ -223,6 +228,11 @@
 SUBDIR+=	manctl
 .endif
 
+.if ${MK_NAND} != "no"
+SUBDIR+=	nandsim
+SUBDIR+=	nandtool
+.endif
+
 .if ${MK_NETGRAPH} != "no"
 SUBDIR+=	flowctl
 SUBDIR+=	lmcconfig
@@ -254,9 +264,12 @@
 SUBDIR+=	ftp-proxy
 .endif
 
+.if ${MK_PKGBOOTSTRAP} != "no"
+SUBDIR+=	pkg
+.endif
+
 .if ${MK_PKGTOOLS} != "no"
 SUBDIR+=	pkg_install
-SUBDIR+=	pkg
 .endif
 
 # XXX MK_TOOLCHAIN?
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/acpi/acpidb/Makefile
--- a/head/usr.sbin/acpi/acpidb/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/acpi/acpidb/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD: head/usr.sbin/acpi/acpidb/Makefile 231844 2012-02-16 22:59:29Z jkim $
+# $FreeBSD: head/usr.sbin/acpi/acpidb/Makefile 238381 2012-07-11 23:18:35Z jkim $
 
 PROG=	acpidb
 SRCS=	acpidb.c
@@ -52,12 +52,13 @@
 	rsserial.c rsutils.c rsxface.c
 
 # components/tables
-SRCS+=	tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c
+SRCS+=	tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c	\
+	tbxfload.c
 
 # components/utilities
 SRCS+=	utaddress.c utalloc.c utcache.c utcopy.c utdebug.c	\
-	utdecode.c utdelete.c uteval.c utglobal.c utids.c	\
-	utinit.c utlock.c utmath.c utmisc.c utmutex.c		\
+	utdecode.c utdelete.c uteval.c utexcep.c utglobal.c	\
+	utids.c	utinit.c utlock.c utmath.c utmisc.c utmutex.c	\
 	utobject.c utosi.c utresrc.c utstate.c uttrack.c	\
 	utxface.c utxferror.c
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/acpi/acpidump/acpi.c
--- a/head/usr.sbin/acpi/acpidump/acpi.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/acpi/acpidump/acpi.c	Wed Jul 25 16:29:58 2012 +0300
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *	$FreeBSD$
+ *	$FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 238288 2012-07-09 09:38:53Z takawata $
  */
 
 #include <sys/param.h>
@@ -654,16 +654,24 @@
 		printf(END_COMMENT);
 		return;
 	}
+	if(sdp->Revision == 1){
+		printf("\tOLD TCPA spec log found. Dumping not supported.\n");
+		printf(END_COMMENT);
+		return;
+	}
 
 	vaddr = (unsigned char *)acpi_map_physical(paddr, len);
 	vend = vaddr + len;
 
 	while (vaddr != NULL) {
-		if (vaddr + sizeof(struct TCPAevent) >= vend)
+		if ((vaddr + sizeof(struct TCPAevent) >= vend)||
+		    (vaddr + sizeof(struct TCPAevent) < vaddr))
 			break;
 		event = (struct TCPAevent *)(void *)vaddr;
 		if (vaddr + event->event_size >= vend)
 			break;
+		if (vaddr + event->event_size < vaddr)
+			break;
 		if (event->event_type == 0 && event->event_size == 0)
 			break;
 #if 0
@@ -1196,13 +1204,13 @@
 	if (tmpdir == NULL)
 		tmpdir = _PATH_TMP;
 	strncpy(tmpstr, tmpdir, sizeof(tmpstr));
-	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(tmpdir));
 	if (realpath(tmpstr, buf) == NULL) {
-		perror("realpath tmp file");
+		perror("realpath tmp dir");
 		return;
 	}
 	strncpy(tmpstr, buf, sizeof(tmpstr));
-	len = strlen(buf);
+	strncat(tmpstr, "/acpidump.", sizeof(tmpstr) - strlen(buf));
+	len = strlen(tmpstr);
 	tmpext = tmpstr + len;
 	strncpy(tmpext, "XXXXXX", sizeof(tmpstr) - len);
 	fd = mkstemp(tmpstr);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/acpi/iasl/Makefile
--- a/head/usr.sbin/acpi/iasl/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/acpi/iasl/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,11 +1,11 @@
-# $FreeBSD: head/usr.sbin/acpi/iasl/Makefile 233250 2012-03-20 21:37:52Z jkim $
+# $FreeBSD: head/usr.sbin/acpi/iasl/Makefile 238381 2012-07-11 23:18:35Z jkim $
 
 PROG=	iasl
 SRCS=	adfile.c adisasm.c adwalk.c
 
 # common
-SRCS+=	dmextern.c dmrestag.c dmtable.c dmtbdump.c dmtbinfo.c	\
-	getopt.c
+SRCS+=	ahpredef.c dmextern.c dmrestag.c dmtable.c dmtbdump.c	\
+	dmtbinfo.c getopt.c
 
 # compiler
 SRCS+=	aslanalyze.c aslbtypes.c aslcodegen.c aslcompile.c	\
@@ -54,9 +54,9 @@
 
 # components/utilities
 SRCS+=	utaddress.c utalloc.c utcache.c utcopy.c utdebug.c	\
-	utdecode.c utdelete.c utglobal.c utinit.c utlock.c	\
-	utmath.c utmisc.c utmutex.c utobject.c utresrc.c	\
-	utstate.c utxface.c utxferror.c
+	utdecode.c utdelete.c utexcep.c utglobal.c utinit.c	\
+	utlock.c utmath.c utmisc.c utmutex.c utobject.c		\
+	utresrc.c utstate.c utxface.c utxferror.c
 
 # os_specific/service_layers
 SRCS+=	osunixxf.c
@@ -73,8 +73,9 @@
 	aslcompilerparse.h dtparser.y.h dtparserlex.c		\
 	dtparserparse.c dtparserparse.h
 
-aslcompilerlex.c: aslcompiler.l
-	${LEX} ${LFLAGS} -PAslCompiler -o${.TARGET} ${.ALLSRC}
+aslcompilerlex.c: aslcompiler.l aslsupport.l
+	${LEX} ${LFLAGS} -PAslCompiler -o${.TARGET} \
+	    ${ACPICA_DIR}/compiler/aslcompiler.l
 
 .ORDER: aslcompilerparse.c aslcompilerparse.h
 aslcompilerparse.c aslcompilerparse.h: aslcompiler.y
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/adduser/rmuser.8
--- a/head/usr.sbin/adduser/rmuser.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/adduser/rmuser.8	Wed Jul 25 16:29:58 2012 +0300
@@ -24,7 +24,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/adduser/rmuser.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd May 10, 2002
 .Dt RMUSER 8
@@ -157,7 +157,7 @@
 interactively asks for one or more users to be removed.
 .El
 .Sh FILES
-.Bl -tag -compact
+.Bl -tag -width "Pa /etc/master.passwd" -compact
 .It Pa /etc/master.passwd
 .It Pa /etc/passwd
 .It Pa /etc/group
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ancontrol/ancontrol.c
--- a/head/usr.sbin/ancontrol/ancontrol.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ancontrol/ancontrol.c	Wed Jul 25 16:29:58 2012 +0300
@@ -37,7 +37,7 @@
 #endif
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/ancontrol/ancontrol.c 223492 2011-06-24 07:05:20Z kevlo $");
+__FBSDID("$FreeBSD: head/usr.sbin/ancontrol/ancontrol.c 238221 2012-07-08 00:52:54Z eadler $");
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -1443,7 +1443,7 @@
 
 	caps = (struct an_ltv_caps *)&areq;
 
-	if (!caps->an_softcaps & AN_AUTHTYPE_LEAP) {
+	if (!(caps->an_softcaps & AN_AUTHTYPE_LEAP)) {
 		fprintf(stderr, "Firmware does not support LEAP\n");
 		exit(1);
 	}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/apmd/apmd.8
--- a/head/usr.sbin/apmd/apmd.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/apmd/apmd.8	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)apmd.8	1.1 (FreeBSD) 6/28/99
-.\" $FreeBSD: head/usr.sbin/apmd/apmd.8 233522 2012-03-26 21:22:53Z joel $
+.\" $FreeBSD: head/usr.sbin/apmd/apmd.8 237015 2012-06-13 18:57:27Z joel $
 .\"
 .Dd June 28, 1999
 .Dt APMD 8 i386
@@ -245,13 +245,13 @@
 The following built-in functions are currently supported:
 .Bl -item
 .It
-- reject:
-.Bd -ragged -offset indent
+.Bl -tag -width ".It - reject"
+.It - reject
 Reject last request posted by APM BIOS.
 This can be used to reject
 a SUSPEND request when the LCD is closed and put the system in a
 STANDBY state instead.
-.Ed
+.El
 .El
 .Ed
 .El
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/arp/arp.4
--- a/head/usr.sbin/arp/arp.4	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/arp/arp.4	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"	@(#)arp4.4	6.5 (Berkeley) 4/18/94
-.\" $FreeBSD: head/usr.sbin/arp/arp.4 233510 2012-03-26 15:18:14Z joel $
+.\" $FreeBSD: head/usr.sbin/arp/arp.4 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd March 28, 2007
 .Dt ARP 4
@@ -113,13 +113,13 @@
 .Va net.link.ether.inet.proxyall
 to 1.
 .Sh MIB Variables
-The ARP protocol implements a number of configrable variables in
+The ARP protocol implements a number of configurable variables in
 .Va net.link.ether.inet
 branch
 of the
 .Xr sysctl 3
 MIB.
-.Bl -tag
+.Bl -tag -width "useloopback"
 .It Va max_age
 How long an ARP entry is held in the cache until it needs to be refreshed.
 .It Va maxtries
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/bthidcontrol/bthidcontrol.8
--- a/head/usr.sbin/bluetooth/bthidcontrol/bthidcontrol.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/bthidcontrol/bthidcontrol.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $Id: bthidcontrol.8,v 1.1 2004/02/13 21:44:41 max Exp $
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/bluetooth/bthidcontrol/bthidcontrol.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd October 30, 2006
 .Dt BTHIDCONTROL 8
@@ -83,7 +83,7 @@
 .Nm
 are:
 .Pp
-.Bl -tag -offset indent -compact
+.Bl -tag -width "Forget" -offset indent -compact
 .It Cm Query
 .It Cm Dump
 .It Cm Known
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/bthidd/parser.y
--- a/head/usr.sbin/bluetooth/bthidd/parser.y	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/bthidd/parser.y	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
  * SUCH DAMAGE.
  *
  * $Id: parser.y,v 1.7 2006/09/07 21:06:53 max Exp $
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/bluetooth/bthidd/parser.y 235789 2012-05-22 16:33:10Z bapt $
  */
 
 #include <sys/queue.h>
@@ -39,6 +39,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <usbhid.h>
@@ -61,7 +62,6 @@
 
 #include "bthid_config.h"
 
-	int	yyparse		(void);
 	int	yylex		(void);
 	void	yyerror		(char const *);
 static	int32_t	check_hid_device(hid_device_p hid_device);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/btpand/btpand.8
--- a/head/usr.sbin/bluetooth/btpand/btpand.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/btpand/btpand.8	Wed Jul 25 16:29:58 2012 +0300
@@ -1,5 +1,5 @@
 .\" $NetBSD: btpand.8,v 1.3 2008/08/17 14:43:07 plunky Exp $
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/bluetooth/btpand/btpand.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .\" Copyright (c) 2008 Iain Hibbert
 .\" All rights reserved.
@@ -128,7 +128,7 @@
 Set L2CAP connection link mode.
 Supported modes are:
 .Pp
-.Bl -tag -compact
+.Bl -tag -width 8n -compact
 .It auth
 require devices to be paired.
 .It encrypt
@@ -151,7 +151,7 @@
 .Ar service
 to provide or connect to, the following services are recognised:
 .Pp
-.Bl -tag -compact
+.Bl -tag -width 8n -compact
 .It GN
 Group ad-hoc Network.
 .It NAP
@@ -182,7 +182,7 @@
 .Xr tap 4
 interface, it will create a pid file and detach.
 .Sh FILES
-.Bl -tag -compact
+.Bl -tag -width "Pa /etc/bluetooth/hosts" -compact
 .It Pa /dev/tap
 .It Pa /etc/bluetooth/hosts
 .It Pa /var/run/sdp
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/hccontrol/hccontrol.8
--- a/head/usr.sbin/bluetooth/hccontrol/hccontrol.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/hccontrol/hccontrol.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $Id: hccontrol.8,v 1.6 2003/08/06 21:26:38 max Exp $
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/bluetooth/hccontrol/hccontrol.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd June 14, 2002
 .Dt HCCONTROL 8
@@ -81,7 +81,7 @@
 .Nm
 are:
 .Pp
-.Bl -tag -offset indent -compact
+.Bl -tag -width 40n -offset indent -compact
 .It Cm Inquiry
 .It Cm Create_Connection
 .It Cm Disconnect
@@ -148,7 +148,7 @@
 .Nm
 are:
 .Pp
-.Bl -tag -offset indent -compact
+.Bl -tag -width 40n -offset indent -compact
 .It Cm Read_Node_State
 .It Cm Initialize
 .It Cm Read_Debug_Level
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/hcsecd/parser.y
--- a/head/usr.sbin/bluetooth/hcsecd/parser.y	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/hcsecd/parser.y	Wed Jul 25 16:29:58 2012 +0300
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $Id: parser.y,v 1.5 2003/06/07 21:22:30 max Exp $
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/bluetooth/hcsecd/parser.y 235789 2012-05-22 16:33:10Z bapt $
  */
 
 #include <sys/fcntl.h>
@@ -36,6 +36,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
 #include <syslog.h>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/l2control/l2control.8
--- a/head/usr.sbin/bluetooth/l2control/l2control.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/l2control/l2control.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $Id: l2control.8,v 1.5 2003/05/21 00:53:00 max Exp $
-.\" $FreeBSD: head/usr.sbin/bluetooth/l2control/l2control.8 220840 2011-04-19 16:21:57Z emax $
+.\" $FreeBSD: head/usr.sbin/bluetooth/l2control/l2control.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd April 9, 2011
 .Dt L2CONTROL 8
@@ -77,7 +77,7 @@
 .Nm
 are:
 .Pp
-.Bl -tag -offset indent -compact
+.Bl -tag -width "Write_Auto_Disconnect_Timeout" -offset indent -compact
 .It Cm Read_Node_Flags
 .It Cm Read_Debug_Level
 .It Cm Write_Debug_Level
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8
--- a/head/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\" $Id: sdpcontrol.8,v 1.1 2003/09/08 02:27:27 max Exp $
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd September 7, 2003
 .Dt SDPCONTROL 8
@@ -86,7 +86,7 @@
 .Nm
 are:
 .Pp
-.Bl -tag -offset indent -compact
+.Bl -tag -width "Browse" -offset indent -compact
 .It Cm Browse
 .It Cm Search
 .El
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,32 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR=	console \
+	diskmgmt \
+	docsinstall \
+	dot \
+	examples \
+	include \
+	mouse \
+	networking \
+	password \
+	security \
+	startup \
+	timezone \
+	ttys \
+	usermgmt
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig
+FILES=		USAGE
+
+SCRIPTS= bsdconfig
+
+MAN= bsdconfig.8
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+	mkdir -p ${DESTDIR}${SCRIPTSDIR}
+	mkdir -p ${DESTDIR}${MANDIR}8
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,40 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage:
+	@PROGRAM_NAME@ [-h]
+	@PROGRAM_NAME@ command [-h]
+	@PROGRAM_NAME@ [OPTIONS] [command [OPTIONS]]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
+
+COMMANDS:
+ at COMMAND_LIST@
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/bsdconfig
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/bsdconfig	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,313 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/bsdconfig 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# usage
+#
+# display usage and exit
+#
+usage()
+{
+	local index="INDEX" cmd_list=""
+
+	cd $BSDCFG_LIBE
+
+	# Test for language-specific indices
+	f_quietly ls */"$index.${LANG:-$LC_ALL}" &&
+		index="$index.${LANG:-$LC_ALL}"
+
+	cmd_list=$(
+		awk '/^menu_selection="/ {
+			sub(/\|.*/, "")
+			sub(/^menu_selection="/, "")
+			print
+		}' */$index | sort
+	)
+
+	#
+	# Determine the longest command-length (in characters)
+	#
+	local longest_cmd
+	longest_cmd=$( echo "$cmd_list" | f_longest_line_length )
+	f_dprintf "longest_cmd=[$longest_cmd]"
+
+	#
+	# Determine the maximum width of terminal/console
+	#
+	local max_size max_width
+	max_size=$( stty size 2> /dev/null )
+	: ${max_size:="24 80"}
+	max_width="${max_size#*[$IFS]}"
+	f_dprintf "max_width=[$max_width]"
+
+	#
+	# Using the longest command-length as the width of a single column,
+	# determine if we can use more than one column to display commands.
+	#
+	local x=$longest_cmd ncols=1
+	x=$(( $x + 8 )) # Accomodate leading tab character
+	x=$(( $x + 3 + $longest_cmd )) # Preload end of next column
+	while [ $x -lt $max_width ]; do
+		ncols=$(( $ncols + 1 ))
+		x=$(( $x + 3 + $longest_cmd ))
+	done
+	f_dprintf "ncols=[$ncols] x=[$x]"
+
+	#
+	# Re-format the command-list into multiple columns
+	#
+	cmd_list=$( eval "$( echo "$cmd_list" |
+		awk -v ncols=$ncols -v size=$longest_cmd '
+		BEGIN {
+			n = 0
+			row_item[1] = ""
+		}
+		function print_row()
+		{
+			fmt = "printf \"\\t%-" size "s"
+			for (i = 1; i < cur_col; i++)
+				fmt = fmt "   %-" size "s"
+			fmt = fmt "\\n\""
+			printf "%s", fmt
+			for (i = 1; i <= cur_col; i++)
+				printf " \"%s\"", row_item[i]
+			print ""
+		}
+		{
+			n++
+			cur_col = (( n - 1 ) % ncols ) + 1
+			printf "f_dprintf \"row_item[%u]=[%s]\"\n", cur_col, $0
+			row_item[cur_col] = $0
+			if ( cur_col == ncols ) print_row()
+		}
+		END {
+			if ( cur_col < ncols ) print_row()
+		}' )"
+	)
+
+	f_usage $BSDCFG_LIBE/USAGE \
+	        "PROGRAM_NAME" "$pgm" \
+	        "COMMAND_LIST" "$cmd_list"
+}
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local title="$DIALOG_TITLE"
+	local btitle="$DIALOG_BACKTITLE"
+	local prompt="$msg_menu_text"
+	local menu_list size
+
+	menu_list="
+		'X' '$msg_exit' '$msg_exit_bsdconfig'
+	" # END-QUOTE
+
+	local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }"
+
+	local menuitem menu_title menu_help menu_selection index=1
+	for menuitem in $( ls -d [0-9][0-9][0-9].* ); do
+		[ $index -lt ${#DIALOG_MENU_TAGS} ] || break
+		tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
+
+		menu_program=
+		menu_title=
+		menu_help=
+		f_include_lang $menuitem/INDEX
+		[ "$menu_program" ] || continue
+
+		case "$menu_program" in
+		/*) : already fully qualified ;;
+		*)
+			menu_program="$menuitem/$menu_program"
+		esac
+
+		menu_title=$( echo "$menu_title" | awk "$sanitize_awk" )
+		menu_help=$( echo "$menu_help" | awk "$sanitize_awk" )
+		setvar "menu_program$tag" "$menu_program"
+		menu_list="$menu_list '$tag' '$menu_title' '$menu_help'"
+
+		index=$(( $index + 1 ))
+	done
+
+	size=$( eval f_dialog_menu_with_help_size \
+	        	\"\$title\"  \
+	        	\"\$btitle\" \
+	        	\"\$prompt\" \
+	        	\"\"         \
+	        	$menu_list   )
+
+	eval $DIALOG \
+		--clear                                 \
+		--title \"\$title\"                     \
+		--backtitle \"\$btitle\"                \
+		--item-help                             \
+		--ok-label \"\$msg_ok\"                 \
+		--cancel-label \"\$msg_exit_bsdconfig\" \
+		--menu \"\$prompt\" $size $menu_list    \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) usage;;
+	esac
+done
+shift $(( $OPTIND -1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_main_menu"
+
+[ "$SECURE" ] && f_mustberoot_init
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Log our operating environment for debugging purposes
+#
+export UNAME_S="$(uname -s)" # Operating System (i.e. FreeBSD)
+export UNAME_P="$(uname -p)" # Processor Architecture (i.e. i386)
+export UNAME_R="$(uname -r)" # Release Level (i.e. X.Y-RELEASE)
+f_dprintf "UNAME_S=[$UNAME_S] UNAME_P=[$UNAME_P] UNAME_R=[$UNAME_R]"
+
+cd $BSDCFG_LIBE || f_die 1 "$msg_directory_not_found" "$BSDCFG_LIBE"
+
+#
+# If a non-option argument was passed, process it as a menuitem selection...
+#
+if [ "$1" ]; then
+	#
+	# ...unless it's a long-option for usage.
+	#
+	case "$1" in
+	-help|--help|-\?) usage;;
+	esac
+
+	#
+	# Find the INDEX (possibly i18n) claiming this keyword
+	#
+	lang="${LANG:-$LC_ALL}"
+	if [ "$lang" ]; then
+		sel=$( grep "^menu_selection=\"$1|" */INDEX.$lang \
+		       		2> /dev/null | tail -1 )
+
+		# Fall-back to non-i18n sources if nothing was found
+		[ "$sel" ] ||
+			sel=$( grep "^menu_selection=\"$1|" */INDEX | tail -1 )
+	else
+		sel=$( grep "^menu_selection=\"$1|" */INDEX | tail -1 )
+	fi
+
+	#
+	# If no matches, display usage (which shows valid keywords)
+	#
+	if [ ! "$sel" ]; then
+		f_err "%s: %s: $msg_not_found\n" "$pgm" "$1"
+		usage
+	fi
+
+	#
+	# The command to execute is after the pipe-character (|) in the
+	# menu_selection property of the INDEX file for the menuitem.
+	#
+	cmd="${sel#*|}"
+	cmd="${cmd%\"}"
+	if [ ! "$cmd" ]; then
+		echo "$pgm: $1: $msg_not_found"
+		usage
+	fi
+	shift
+
+	#
+	# If the command pathname is not fully qualified fix-up/force to be
+	# relative to the menuitem directory.
+	#
+	case "$cmd" in
+	/*) : already fully qualified ;;
+	*)
+		dir="${sel%%/*}"
+		cmd="$dir/$cmd"
+	esac
+
+	exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
+fi
+
+[ -f "$HOME/.bsdconfigrc" ] || f_dialog_msgbox "$msg_help_text"
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	X) # Exit
+	   break
+	   ;;
+
+	*) # Dynamically loaded menuitem
+	   cmd=$( eval echo \"\$menu_program$mtag\" )
+	   f_dprintf "cmd=[$cmd]"
+	   $cmd ${USE_XDIALOG:+-X}
+	   ;;
+
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/bsdconfig.8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/bsdconfig.8	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,233 @@
+.\" Copyright (c) 2012 Ron McDowell
+.\" Copyright (c) 2012 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 ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, 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.
+.\"
+.\"            docsinstall
+.\"            password
+.\"            diskmgmt
+.\"            usermgmt
+.\"              useradd
+.\"              useredit
+.\"              userdel
+.\"            groupmgmt
+.\"              groupadd
+.\"              groupedit
+.\"              groupdel
+.\"            console
+.\"              syscons_font
+.\"              syscons_keymap
+.\"              syscons_repeat
+.\"              syscons_saver
+.\"              syscons_screenmap
+.\"              syscons_ttys
+.\"            timezone
+.\"            mouse
+.\"              mouse_enable
+.\"              mouse_type
+.\"              mouse_port
+.\"              mouse_flags
+.\"              mouse_disable
+.\"            networking
+.\"              defaultrouter
+.\"              hostname
+.\"              nameservers
+.\"              netdev
+.\"            security
+.\"            ttys
+.\"            [dot]
+.\" 
+.\" $FreeBSD: head/usr.sbin/bsdconfig/bsdconfig.8 238444 2012-07-14 06:17:17Z joel $
+.\"
+.Dd Mar 20, 2012
+.Dt BSDCONFIG 8
+.Os
+.Sh NAME
+.Nm bsdconfig
+.Nd system configuration utility
+.Sh SYNOPSIS
+.Nm
+.Op Fl h
+.Nm
+.Ar command
+.Op Fl h
+.Nm
+.Op OPTIONS
+.Op command Op OPTIONS
+.Sh DESCRIPTION
+.Nm
+is used to set up many system configuration settings, both for new systems, as
+well as changing configuration settings of existing systems.
+.Pp
+.Nm
+takes a command as an argument. If invoked with no arguments, it will bring up
+a master menu listing the available commands.
+.Pp
+The following options are available:
+.Bl -tag -width indent+
+.It Fl h
+Print usage statement and exit.
+.It Fl S
+Secure X11 mode
+.Pq implies Fl X .
+As root, always prompt-for and validate
+.Xr sudo 8
+username/password before starting.
+.It Fl X
+Use
+.Xr Xdialog 1
+in place of
+.Xr dialog 1 .
+.El
+.Sh COMMANDS
+The following commands
+.Pq sorted alphabetically
+are currently included in the base
+.Nm
+program, with more to be added soon.  Other commands can be added, as detailed
+below in the
+.Cm ADDING COMMANDS
+section, and once added, will appear in the master menu as well as in the
+.Cm -h
+listing.
+.Bl -tag -width ".Cm syscons_screenmap"
+.It Cm console
+Utilities to customize the behavior of the system console.
+.It Cm defaultrouter
+Shortcut to the Default Router/Gateway menu under networking.
+.It Cm diskmgmt
+Manage disk partitions and/or labels. Executes
+.Xr sade 8 .
+.It Cm docsinstall
+Executes the
+.Cm bsdinstall docsinstall
+sub-utility to allow installation/re-installation of the FreeBSD Documentation
+set(s).
+.It Cm dot
+Generate a graphviz
+.Xr dot 1
+language file
+.Pq printed on stdout
+visualizing the
+.Xr bsdconfig 8
+menu, include, and shortcut structure and relationships.  See
+.Dq bsdconfig dot -h
+for more details.
+.It Cm groupadd
+Shortcut to the Add Groups menu under groupmgmt.
+.It Cm groupdel
+Shortcut to the Delete Groups menu under groupmgmt.
+.It Cm groupedit
+Shortcut to the Edit/View Groups menu under groupmgmt.
+.It Cm groupmgmt
+Utilities to Add/Change/View/Delete Group Accounts.
+.It Cm hostname
+Shortcut to the Hostname/Domain menu under networking.
+.It Cm mouse
+Utilities for configuring, exploring, and enabling console mouse support.
+.It Cm mouse_disable
+Shortcut to the Disable menu under mouse.
+.It Cm mouse_enable
+Shortcut to the Enable menu under mouse.
+.It Cm mouse_flags
+Shortcut to the Flags menu under mouse.
+.It Cm mouse_port
+Shortcut to the Port menu under mouse.
+.It Cm mouse_type
+Shortcut to the Type menu under mouse.
+.It Cm nameservers
+Shortcut to the DNS Nameservers menu under networking.
+.It Cm netdev
+Shortcut to the Network Interfaces menu under networking.
+.It Cm networking
+Utilities to set/change Hostname/Domain, Network Interfaces, Default
+Router/Gateway, and DNS Nameservers.
+.It Cm password
+Set the system administrator
+.Pq root
+password.
+.It Cm security
+Configure various system security settings.
+.It Cm syscons_font
+Shortcut to the Font menu under console.
+.It Cm syscons_keymap
+Shortcut to the Keymap menu under console.
+.It Cm syscons_repeat
+Shortcut to the Repeat menu under console.
+.It Cm syscons_saver
+Shortcut to the Saver menu under console.
+.It Cm syscons_screenmap
+Shortcut to the Screenmap menu under console.
+.It Cm syscons_ttys
+Shortcut to the Ttys menu under console.
+.It Cm timezone
+Set the regional timezone of the local machine.
+.It Cm useradd
+Shortcut to the Add Users menu under usermgmt.
+.It Cm userdel
+Shortcut to the Delete Users menu under usermgmt.
+.It Cm useredit
+Shortcut to the Edit/View Users menu under usermgmt.
+.It Cm usermgmt
+Utilities to Add/Edit/View/Delete User Accounts.
+.El
+.Sh INTERNATIONALIZATION
+i18n features are built into
+.Nm
+and language-specific translation files will be added as they become available.
+In the absence of language-specific translation files, the default
+.Pq en_US.ISO8859-1
+files will be used.
+.Sh ADDING COMMANDS
+To be documented later. Document menu_selection="command|*" syntax of INDEX
+files.
+.Sh ENVIRONMENT VARIABLES
+The following environment variables affect the execution of
+.Nm :
+.Bl -tag -width ".Ev LC_ALL"
+.It Ev LANG
+If LANG is set, messages and index information will be read from files named
+messages.$LANG and INDEX.$LANG and fall back to files named messages and INDEX if
+messages.$LANG and INDEX.$LANG do not exist.  LANG takes precedence over LC_ALL.
+.It Ev LC_ALL
+If LC_ALL is set, messages and index information will be read from files named
+messages.$LC_ALL and INDEX.$LC_ALL and fall back to files named messages and INDEX if
+messages.$LC_ALL and INDEX.$LC_ALL do not exist.
+.El
+.Sh FILES
+/usr/share/examples/bsdconfig/bsdconfigrc can be copied to $HOME/.bsdconfigrc and
+customized as needed.
+.Sh EXIT STATUS
+.Ex -std
+.Sh SEE ALSO
+.Xr host-setup 8 ,
+.Xr sade 8
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An Ron McDowell Aq rcm at FuzzWad.ORG
+.An Devin Teske Aq devinteske at hotmail.com
+.Sh BUGS
+Undoubtedly.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,59 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Console"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Customize system console behavior"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="console|console"
+menu_selection="syscons_font|font"
+menu_selection="syscons_keymap|keymap"
+menu_selection="syscons_repeat|repeat"
+menu_selection="syscons_saver|saver"
+menu_selection="syscons_screenmap|screenmap"
+menu_selection="syscons_ttys|ttys"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="console"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/console/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/080.console
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	console font keymap repeat saver screenmap ttys
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/console
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/console	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,137 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/console 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_configure_system_console_settings"
+	local prompt="$msg_console_menu_text"
+
+	menu_list="
+		'X $msg_exit'      '$msg_exit_this_menu'
+		'2 $msg_font'      '$msg_choose_alternate_screen_font'
+		'3 $msg_keymap'    '$msg_choose_alternate_keyboard_map'
+		'4 $msg_repeat'    '$msg_set_repeat_rate'
+		'5 $msg_saver'     '$msg_configure_screen_saver'
+		'6 $msg_screenmap' '$msg_choose_alternate_screenmap'
+		'7 $msg_ttys'      '$msg_choose_console_terminal_type'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_configuration"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+	"2 $msg_font") # Choose an alternate screen font
+		$BSDCFG_LIBE/$APP_DIR/font ${USE_XDIALOG:+-X} ;;
+	"3 $msg_keymap") # Choose an alternate keyboard map
+		$BSDCFG_LIBE/$APP_DIR/keymap ${USE_XDIALOG:+-X} ;;
+	"4 $msg_repeat") # Set the rate at which keys repeat
+		$BSDCFG_LIBE/$APP_DIR/repeat ${USE_XDIALOG:+-X} ;;
+	"5 $msg_saver") # Configure the screen saver
+		$BSDCFG_LIBE/$APP_DIR/saver ${USE_XDIALOG:+-X} ;;
+	"6 $msg_screenmap") # Choose an alternate screenmap
+		$BSDCFG_LIBE/$APP_DIR/screenmap ${USE_XDIALOG:+-X} ;;
+	"7 $msg_ttys") # Choose console terminal type
+		$BSDCFG_LIBE/$APP_DIR/ttys ${USE_XDIALOG:+-X} ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/font
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/font	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,205 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/font 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_choose_a_font"
+	local prompt="$msg_font_menu_text"
+
+	menu_list="
+		'1 $msg_none'        '$msg_use_hardware_default_font'
+		'2 $msg_ibm_437'     '$msg_ibm_437_desc'
+		'3 $msg_ibm_850'     '$msg_ibm_850_desc'
+		'4 $msg_ibm_865'     '$msg_ibm_865_desc'
+		'5 $msg_ibm_866'     '$msg_ibm_866_desc'
+		'6 $msg_ibm_866u'    '$msg_ibm_866u_desc'
+		'7 $msg_ibm_1251'    '$msg_ibm_1251_desc'
+		'8 $msg_iso_8859_1'  '$msg_iso_8859_1_desc'
+		'9 $msg_iso_8859_2'  '$msg_iso_8859_2_desc'
+		'a $msg_iso_8859_4'  '$msg_iso_8859_4_desc'
+		'b $msg_iso_8859_7'  '$msg_iso_8859_7_desc'
+		'c $msg_iso_8859_8'  '$msg_iso_8859_8_desc'
+		'd $msg_iso_8859_15' '$msg_iso_8859_15_desc'
+		'e $msg_swiss'       '$msg_swiss_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_font"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"1 $msg_none") # Use hardware default font
+		f_sysrc_set font8x8 "NO" || f_die
+		f_sysrc_set font8x14 "NO" || f_die
+		f_sysrc_set font8x16 "NO" || f_die
+		break ;;
+	"2 $msg_ibm_437") # English and others, VGA default
+		f_sysrc_set font8x8 "cp437-8x8" || f_die
+		f_sysrc_set font8x14 "cp437-8x14" || f_die
+		f_sysrc_set font8x16 "cp437-8x16" || f_die
+		break ;;
+	"3 $msg_ibm_850") # Western Europe, IBM encoding
+		f_sysrc_set font8x8 "cp850-8x8" || f_die
+		f_sysrc_set font8x14 "cp850-8x14" || f_die
+		f_sysrc_set font8x16 "cp850-8x16" || f_die
+		break ;;
+	"4 $msg_ibm_865") # Norwegian, IBM encoding
+		f_sysrc_set font8x8 "cp865-8x8" || f_die
+		f_sysrc_set font8x14 "cp865-8x14" || f_die
+		f_sysrc_set font8x16 "cp865-8x16" || f_die
+		break ;;
+	"5 $msg_ibm_866") # Russian, IBM encoding (use with KOI8-R screenmap)
+		f_sysrc_set font8x8 "cp866-8x8" || f_die
+		f_sysrc_set font8x14 "cp866-8x14" || f_die
+		f_sysrc_set font8x16 "cp866b-8x16" || f_die
+		f_sysrc_set mousechar_start 3 || f_die
+		break ;;
+	"6 $msg_ibm_866u") # Ukrainian, IBM encoding (use w/ KOI8-U screenmap)
+		f_sysrc_set font8x8 "cp866u-8x8" || f_die
+		f_sysrc_set font8x14 "cp866u-8x14" || f_die
+		f_sysrc_set font8x16 "cp866u-8x16" || f_die
+		f_sysrc_set mousechar_start 3 || f_die
+		break ;;
+	"7 $msg_ibm_1251") # Cyrillic, MS Windows encoding
+		f_sysrc_set font8x8 "cp1251-8x8" || f_die
+		f_sysrc_set font8x14 "cp1251-8x14" || f_die
+		f_sysrc_set font8x16 "cp1251-8x16" || f_die
+		f_sysrc_set mousechar_start 3 || f_die
+		break ;;
+	"8 $msg_iso_8859_1") # Western Europe, ISO encoding
+		f_sysrc_set font8x8 "iso-8x8" || f_die
+		f_sysrc_set font8x14 "iso-8x14" || f_die
+		f_sysrc_set font8x16 "iso-8x16" || f_die
+		break ;;
+	"9 $msg_iso_8859_2") # Eastern Europe, ISO encoding
+		f_sysrc_set font8x8 "iso02-8x8" || f_die
+		f_sysrc_set font8x14 "iso02-8x14" || f_die
+		f_sysrc_set font8x16 "iso02-8x16" || f_die
+		break ;;
+	"a $msg_iso_8859_4") # Baltic, ISO encoding
+		f_sysrc_set font8x8 "iso04-8x8" || f_die
+		f_sysrc_set font8x14 "iso04-8x14" || f_die
+		f_sysrc_set font8x16 "iso04-8x16" || f_die
+		break ;;
+	"b $msg_iso_8859_7") # Greek, ISO encoding
+		f_sysrc_set font8x8 "iso07-8x8" || f_die
+		f_sysrc_set font8x14 "iso07-8x14" || f_die
+		f_sysrc_set font8x16 "iso07-8x16" || f_die
+		break ;;
+	"c $msg_iso_8859_8") # Hebrew, ISO encoding
+		f_sysrc_set font8x8 "iso08-8x8" || f_die
+		f_sysrc_set font8x14 "iso08-8x14" || f_die
+		f_sysrc_set font8x16 "iso08-8x16" || f_die
+		break ;;
+	"d $msg_iso_8859_15") # Europe, ISO encoding
+		f_sysrc_set font8x8 "iso15-8x8" || f_die
+		f_sysrc_set font8x14 "iso15-8x14" || f_die
+		f_sysrc_set font8x16 "iso15-8x16" || f_die
+		break ;;
+	"e $msg_swiss") # English, better resolution
+		f_sysrc_set font8x8 "swiss-8x8" || f_die
+		f_sysrc_set font8x14 "NO" || f_die
+		f_sysrc_set font8x16 "swiss-8x16" || f_die
+		break ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/console/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/080.console/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,264 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_choose_a_font="Choose a font"
+hline_choose_a_keyboard_map="Choose a keyboard map"
+hline_choose_a_keyboard_repeat_rate="Choose a keyboard repeat rate"
+hline_choose_a_screen_map="Choose a screen map"
+hline_choose_a_screen_saver="Choose a nifty-looking screen saver"
+hline_choose_a_terminal_type="Choose a terminal type"
+hline_configure_system_console_settings="Configure your system console settings"
+msg_beastie="Beastie"
+msg_beastie_desc="\"BSD Daemon\" animated screen saver (graphics)"
+msg_belgian="Belgian"
+msg_belgian_desc="Belgian ISO keymap"
+msg_blank="Blank"
+msg_blank_desc="Simply blank the screen"
+msg_brazil_cp850="Brazil CP850"
+msg_brazil_cp850_desc="Brazil CP850 keymap"
+msg_brazil_iso="Brazil ISO"
+msg_brazil_iso_accent="Brazil ISO (accent)"
+msg_brazil_iso_accent_desc="Brazil ISO keymap (accent keys)"
+msg_brazil_iso_desc="Brazil ISO keymap"
+msg_bulgarian_bds="Bulgarian BDS"
+msg_bulgarian_bds_desc="Bulgarian BDS keymap"
+msg_bulgarian_phonetic="Bulgarian Phonetic"
+msg_bulgarian_phonetic_desc="Bulgarian Phonetic keymap"
+msg_cancel="Cancel"
+msg_central_european_iso="Central European ISO"
+msg_central_european_iso_desc="Central European ISO keymap"
+msg_choose_alternate_keyboard_map="Choose an alternate keyboard map"
+msg_choose_alternate_screenmap="Choose an alternate screenmap"
+msg_choose_alternate_screen_font="Choose an alternate screen font"
+msg_choose_console_terminal_type="Choose console terminal type"
+msg_configure_screen_saver="Configure the screen saver"
+msg_console_menu_text="The system console driver for FreeBSD has a number of configuration\noptions which may be set according to your preference.\n\nWhen you are done setting configuration options, select Cancel."
+msg_croatian_iso="Croation ISO"
+msg_croatian_iso_desc="Croation ISO keymap"
+msg_czech_iso_accent="Czech ISO (accent)"
+msg_czech_iso_accent_desc="Czech ISO keymap (accent keys)"
+msg_daemon="Daemon"
+msg_daemon_desc="\"BSD Daemon\" animated screen saver (text)"
+msg_danish_cp865="Danish CP865"
+msg_danish_cp865_desc="Danish Code Page 865 keymap"
+msg_danish_iso="Danish ISO"
+msg_danish_iso_desc="Danish ISO keymap"
+msg_default="Default"
+msg_default_desc="Use default keyboard repeat rate"
+msg_dragon="Dragon"
+msg_dragon_desc="Dragon screensaver (graphics)"
+msg_enter_timeout_period="Enter time-out period in seconds for screen saver"
+msg_estonian_cp850="Estonian CP850"
+msg_estonian_cp850_desc="Estonian Code Page 850 keymap"
+msg_estonian_iso="Estonian ISO"
+msg_estonian_iso_desc="Estonian ISO keymap"
+msg_estonian_iso_15="Estonian ISO 15"
+msg_estonian_iso_15_desc="Estonian ISO 8859-15 keymap"
+msg_exit="Exit"
+msg_exit_this_menu="Exit this menu (returning to previous)"
+msg_fade="Fade"
+msg_fade_desc="Fade out effect screen saver"
+msg_fast="Fast"
+msg_fast_desc="Fast keyboard repeat rate"
+msg_finnish_cp850="Finnish CP850"
+msg_finnish_cp850_desc="Finnish Code Page 850 keymap"
+msg_finnish_iso="Finnish ISO"
+msg_finnish_iso_desc="Finnish ISO keymap"
+msg_fire="Fire"
+msg_fire_desc="Flames effect screen saver"
+msg_font="Font"
+msg_font_menu_text="Most PC hardware defaults to displaying characters in the\nIBM 437 character set.  However, in the Unix world, this\ncharacter set is very rarely used.  Most Western European\ncountries, for example, prefer ISO 8859-1.\nAmerican users won't notice the difference since the bottom half\nof all these charactersets is ANSI anyway.  However, they might\nwant to load a font anyway to use the 30- or 50-line displays.\nIf your hardware is capable of downloading a new display font,\nyou can select the appropriate font below."
+msg_french_iso="French ISO"
+msg_french_iso_accent="French ISO (accent)"
+msg_french_iso_accent_desc="French ISO keymap (accent keys)"
+msg_french_iso_desc="French ISO keymap"
+msg_french_iso_macbook="French ISO/Macbook"
+msg_french_iso_macbook_desc="French ISO keymap on macbook"
+msg_green="Green"
+msg_green_desc="\"Green\" power saving mode (if supported by monitor)"
+msg_german_cp850="German CP850"
+msg_german_cp850_desc="German Code Page 850 keymap"
+msg_german_iso="German ISO"
+msg_german_iso_desc="German ISO keymap"
+msg_greek_101="Greek 101"
+msg_greek_101_desc="Greek ISO keymap (101 keys)"
+msg_greek_104="Greek 104"
+msg_greek_104_desc="Greek ISO keymap (104 keys)"
+msg_greek_elot="Greek ELOT"
+msg_greek_elot_desc="Greek ISO keymap (ELOT 1000)"
+msg_hungarian_101="Hungarian 101"
+msg_hungarian_101_desc="Hungarian ISO keymap (101 key)"
+msg_hungarian_102="Hungarian 102"
+msg_hungarian_102_desc="Hungarian ISO keymap (102 key)"
+msg_ibm_437="IBM 437"
+msg_ibm_437_desc="English and others, VGA default"
+msg_ibm_437_vga_default="IBM437 (VGA default)"
+msg_ibm_850="IBM 850"
+msg_ibm_850_desc="Western Europe, IBM encoding"
+msg_ibm_865="IBM 865"
+msg_ibm_865_desc="Norwegian, IBM encoding"
+msg_ibm_866="IBM 866"
+msg_ibm_866_desc="Russian, IBM encoding (use with KOI8-R screenmap)"
+msg_ibm_866u="IBM 866u"
+msg_ibm_866u_desc="Ukrainian, IBM encoding (use with KOI8-U screenmap)"
+msg_ibm_1251="IBM 1251"
+msg_ibm_1251_desc="Cyrillic, MS Windows encoding"
+msg_icelandic="Icelandic"
+msg_icelandic_accent="Icelandic (accent)"
+msg_icelandic_accent_desc="Icelandic ISO keymap (accent keys)"
+msg_icelandic_desc="Icelandic ISO keymap"
+msg_iso_8859_1="ISO 8859-1"
+msg_iso_8859_1_desc="Western Europe, ISO encoding"
+msg_iso_8859_1_to_ibm437="ISO 8859-1 to IBM437"
+msg_iso_8859_1_to_ibm437_desc="W-Europe ISO 8859-1 to IBM 437 screenmap"
+msg_iso_8859_2="ISO 8859-2"
+msg_iso_8859_2_desc="Eastern Europe, ISO encoding"
+msg_iso_8859_4="ISO 8859-4"
+msg_iso_8859_4_desc="Baltic, ISO encoding"
+msg_iso_8859_7="ISO 8859-7"
+msg_iso_8859_7_desc="Greek, ISO encoding"
+msg_iso_8859_7_to_ibm437="ISO 8859-7 to IBM437"
+msg_iso_8859_7_to_ibm437_desc="Greek ISO 8859-1 to IBM 437 screenmap"
+msg_iso_8859_8="ISO 8859-8"
+msg_iso_8859_8_desc="Hebrew, ISO encoding"
+msg_iso_8859_15="ISO 8859-15"
+msg_iso_8859_15_desc="Europe, ISO encoding"
+msg_italian="Italian"
+msg_italian_desc="Italian ISO keymap"
+msg_japanese_106="Japanese 106"
+msg_japanese_106_desc="Japanese 106 keymap"
+msg_keymap="Keymap"
+msg_keymap_menu_text="The system console driver for FreeBSD defaults to a standard\n\"US\" keyboard map.  Users may wish to choose one of the\nother keymaps below."
+msg_koi8_r="KOI8-R"
+msg_koi8_u="KOI8-U"
+msg_koi8_r_to_ibm866="KOI8-R to IBM866"
+msg_koi8_r_to_ibm866_desc="Russian KOI8-R to IBM 866 screenmap"
+msg_koi8_u_to_ibm866u="KOI8-U to IBM866u"
+msg_koi8_u_to_ibm866u_desc="Ukrainian KOI8-U to IBM 866u screenmap"
+msg_latin_american="Latin American"
+msg_latin_american_accent="Latin American (accent)"
+msg_latin_american_accent_desc="Latin American ISO keymap (accent keys)"
+msg_latin_american_desc="Latin American ISO keymap"
+msg_logo="Logo"
+msg_logo_desc="FreeBSD \"logo\" animated screen saver (graphics)"
+msg_none="None"
+msg_none_saver_desc="Disable the screensaver"
+msg_none_screenmap_desc="No screenmap, don'\''t touch font"
+msg_none_ttys_desc="Don'\''t touch anything"
+msg_normal="Normal"
+msg_normal_desc="\"Normal\" keyboard repeat rate"
+msg_norway_iso="Norway ISO"
+msg_norway_iso_desc="Norwegian ISO keymap"
+msg_ok="OK"
+msg_polish_iso="Polish ISO"
+msg_polish_iso_desc="Polish ISO keymap"
+msg_portuguese="Portuguese"
+msg_portuguese_accent="Portuguese (accent)"
+msg_portuguese_accent_desc="Portuguese ISO keymap (accent keys)"
+msg_portuguese_desc="Portuguese ISO keymap"
+msg_rain="Rain"
+msg_rain_desc="Rain drops screen saver"
+msg_repeat="Repeat"
+msg_repeat_menu_text="This menu allows you to set the speed at which keys repeat\nwhen held down."
+msg_russia_koi8_r="Russia KOI8-R"
+msg_russia_koi8_r_desc="Russia KOI8-R keymap"
+msg_saver="Saver"
+msg_saver_menu_text="By default, the console driver will not attempt to do anything\nspecial with your screen when it's idle.  If you expect to leave your\nmonitor switched on and idle for long periods of time then you should\nprobably enable one of these screen savers to prevent burn-in."
+msg_screenmap="Screenmap"
+msg_screenmap_menu_text="Unless you load a specific font, most PC hardware defaults to\ndisplaying characters in the IBM 437 character set.  However,\nin the Unix world, this character set is very rarely used.  Most\nWestern European countries, for example, prefer ISO 8859-1.\nAmerican users won't notice the difference since the bottom half\nof all these character sets is ANSI anyway.\nIf your hardware is capable of downloading a new display font,\nyou should probably choose that option.  However, for hardware\nwhere this is not possible (e.g. monochrome adapters), a screen\nmap will give you the best approximation that your hardware can\ndisplay at all."
+msg_set_repeat_rate="Set the rate at which keys repeat"
+msg_slovak="Slovak"
+msg_slovak_desc="Slovak ISO keymap"
+msg_slovenian="Slovenian"
+msg_slovenian_desc="Slovenian ISO keymap"
+msg_slow="Slow"
+msg_slow_desc="Slow keyboard repeat rate"
+msg_snake="Snake"
+msg_snake_desc="Draw a FreeBSD \"snake\" on your screen"
+msg_spanish="Spanish"
+msg_spanish_accent="Spanish (accent)"
+msg_spanish_accent_desc="Spanish ISO keymap (accent keys)"
+msg_spanish_desc="Spanish ISO keymap"
+msg_star="Star"
+msg_star_desc="A \"twinkling stars\" effect"
+msg_swedish_cp850="Swedish CP850"
+msg_swedish_cp850_desc="Swedish Code Page 850 keymap"
+msg_swedish_iso="Swedish ISO"
+msg_swedish_iso_desc="Swedish ISO keymap"
+msg_swiss="SWISS"
+msg_swiss_desc="English, better resolution"
+msg_swiss_french_cp850="Swiss French CP850"
+msg_swiss_french_cp850_desc="Swiss French Code Page 850 keymap"
+msg_swiss_french_iso="Swiss French ISO"
+msg_swiss_french_iso_accent="Swiss French ISO (accent)"
+msg_swiss_french_iso_accent_desc="Swiss French ISO keymap (accent keys)"
+msg_swiss_french_iso_desc="Swiss French ISO keymap"
+msg_swiss_german_cp850="Swiss German CP850"
+msg_swiss_german_cp850_desc="Swiss German Code Page 850 keymap"
+msg_swiss_german_iso="Swiss German ISO"
+msg_swiss_german_iso_accent="Swiss German ISO (accent)"
+msg_swiss_german_iso_accent_desc="Swiss German ISO keymap (accent keys)"
+msg_swiss_german_iso_desc="Swiss German ISO keymap"
+msg_system_console_configuration="System Console Configuration"
+msg_system_console_font="System Console Font"
+msg_system_console_keymap="System Console Keymap"
+msg_system_console_keyboard_repeat_rate="System Console Keyboard Repeat Rate"
+msg_system_console_screen_saver="System Console Screen Saver"
+msg_system_console_screenmap="System Console Screenmap"
+msg_system_console_terminal_type="System Console Terminal Type"
+msg_timeout="Timeout"
+msg_timeout_desc="Set the screen saver timeout interval"
+msg_ttys="Ttys"
+msg_ttys_menu_text="For various console encodings, a corresponding terminal type\nmust be chosen in /etc/ttys.\n\nWARNING: For compatibility reasons, only entries starting with\nttyv and terminal types starting with cons[0-9] can be changed\nvia this menu."
+msg_uk_cp850="UK CP850"
+msg_uk_cp850_desc="UK Code Page 850 keymap"
+msg_uk_iso="UK ISO"
+msg_uk_iso_desc="UK ISO keymap"
+msg_ukrainian_koi8_u="Ukranian KOI8-U"
+msg_ukrainian_koi8_u_desc="Ukranian KOI8-U keymap"
+msg_ukrainian_koi8_u_koi8_r="Ukranian KOI8-U+KOI8-R"
+msg_ukrainian_koi8_u_koi8_r_desc="Ukranian KOI8-U+KOI8-R keymap (alter)"
+msg_us_ascii="US-ASCII"
+msg_us_ascii_to_ibm327="US-ASCII to IBM437"
+msg_us_ascii_to_ibm327_desc="US-ASCII to IBM 437 screenmap"
+msg_usa_capslock_ctrl="USA CapsLock->Ctrl"
+msg_usa_capslock_ctrl_desc="US standard (Caps as L-Control)"
+msg_usa_dvorak="USA Dvorak"
+msg_usa_dvorak_desc="US Dvorak keymap"
+msg_usa_dvorak_left="USA Dvorak (left)"
+msg_usa_dvorak_left_desc="US left handed Dvorak keymap"
+msg_usa_dvorak_right="USA Dvorak (right)"
+msg_usa_dvorak_right_desc="US right handed Dvorak keymap"
+msg_usa_emacs="USA Emacs"
+msg_usa_emacs_desc="US standard optimized for EMACS"
+msg_usa_iso="USA ISO"
+msg_usa_iso_desc="US ISO keymap"
+msg_usa_unix="USA UNIX"
+msg_usa_unix_desc="US traditional UNIX-workstation"
+msg_use_hardware_default_font="Use hardware default font"
+msg_value_required="Value Required"
+msg_warp="Warp"
+msg_warp_desc="A \"stars warping\" effect"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/keymap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/keymap	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,365 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/keymap 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# List of keymap names
+#
+KEYMAP_NAMES="
+	belgian                  brazil_cp850             brazil_iso
+	brazil_iso_accent        bulgarian_bds            bulgarian_phonetic
+	central_european_iso     croatian_iso             czech_iso_accent
+	danish_cp865             danish_iso               estonian_cp850
+	estonian_iso             estonian_iso_15          finnish_cp850
+	finnish_iso              french_iso               french_iso_accent
+	french_iso_macbook       german_cp850             german_iso
+	greek_101                greek_104                greek_elot
+	hungarian_101            hungarian_102            icelandic
+	icelandic_accent         italian                  japanese_106
+	latin_american           latin_american_accent    norway_iso
+	polish_iso               portuguese               portuguese_accent
+	russia_koi8_r            slovak                   slovenian
+	spanish                  spanish_accent           swedish_cp850
+	swedish_iso              swiss_french_cp850       swiss_french_iso
+	swiss_french_iso_accent  swiss_german_cp850       swiss_german_iso
+	swiss_german_iso_accent  uk_cp850                 uk_iso
+	ukrainian_koi8_u         ukrainian_koi8_u_koi8_r  usa_capslock_ctrl
+	usa_dvorak               usa_dvorak_left          usa_dvorak_right
+	usa_emacs                usa_iso                  usa_unix
+" # END-QUOTE
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_choose_a_keyboard_map"
+	local prompt="$msg_keymap_menu_text"
+
+	#
+	# Export variables for awk(1) ENVIRON visibility
+	#
+	local name
+	for name in $KEYMAP_NAMES; do
+		export msg_$name msg_${name}_desc
+	done
+
+	#
+	# Generate a sorted list of keymaps. If the first letter of the keymap
+	# name is unique (case-insensitive) then it is used as the tag to allow
+	# the user to jump to that entry.
+	#
+	menu_list=$(
+		for name in $KEYMAP_NAMES; do
+			eval echo \"\$msg_$name\" msg_$name
+		done | sort | awk 'BEGIN { prefix = "" }
+		{
+			cur_prefix = tolower(substr(ENVIRON[$NF], 1, 1))
+			printf "'\''"
+			if ( prefix != cur_prefix )
+				prefix = cur_prefix
+			else
+				printf " "
+			printf "%s'\'' '\''%s'\''\n",
+			       ENVIRON[$NF], ENVIRON[$NF"_desc"]
+		}'
+	)
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_keymap"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	#
+	# Reverse the users choice into the variable name
+	#
+	keymap_name=
+	mtag="${mtag# }" # remove single leading-space if-present
+	for name in $KEYMAP_NAMES; do
+		if [ "$( eval echo \"\$msg_$name\" )" = "$mtag" ]; then
+			keymap_name="$name"
+			break
+		fi
+	done
+
+	[ "$keymap_name" ] || continue
+
+	case "$keymap_name" in
+	belgian)
+		f_sysrc_set keymap "be.iso" || f_die
+		break ;;
+	brazil_cp850)
+		f_sysrc_set keymap "br275.cp850" || f_die
+		break ;;
+	brazil_iso)
+		f_sysrc_set keymap "br275.iso" || f_die
+		break ;;
+	brazil_iso_accent)
+		f_sysrc_set keymap "br275.iso.acc" || f_die
+		break ;;
+	bulgarian_bds)
+		f_sysrc_set keymap "bg.bds.ctrlcaps" || f_die
+		break ;;
+	bulgarian_phonetic)
+		f_sysrc_set keymap "bg.phonetic.ctrlcaps" || f_die
+		break ;;
+	central_european_iso)
+		f_sysrc_set keymap "ce.iso2" || f_die
+		break ;;
+	croatian_iso)
+		f_sysrc_set keymap "hr.iso" || f_die
+		break ;;
+	czech_iso_accent)
+		f_sysrc_set keymap "cs.latin2.qwertz" || f_die
+		break ;;
+	danish_cp865)
+		f_sysrc_set keymap "danish.cp865" || f_die
+		break ;;
+	danish_iso)
+		f_sysrc_set keymap "danish.iso" || f_die
+		break ;;
+	estonian_cp850)
+		f_sysrc_set keymap "estonian.cp850" || f_die
+		break ;;
+	estonian_iso)
+		f_sysrc_set keymap "estonian.iso" || f_die
+		break ;;
+	estonian_iso_15)
+		f_sysrc_set keymap "estonian.iso15" || f_die
+		break ;;
+	finnish_cp850)
+		f_sysrc_set keymap "finnish.cp850" || f_die
+		break ;;
+	finnish_iso)
+		f_sysrc_set keymap "finnish.iso" || f_die
+		break ;;
+	french_iso)
+		f_sysrc_set keymap "fr.iso" || f_die
+		break ;;
+	french_iso_accent)
+		f_sysrc_set keymap "fr.iso.acc" || f_die
+		break ;;
+	french_iso_macbook)
+		f_sysrc_set keymap "fr.macbook.acc" || f_die
+		break ;;
+	german_cp850)
+		f_sysrc_set keymap "german.cp850" || f_die
+		break ;;
+	german_iso)
+		f_sysrc_set keymap "german.iso" || f_die
+		break ;;
+	greek_101)
+		f_sysrc_set keymap "gr.us101.acc" || f_die
+		break ;;
+	greek_104)
+		f_sysrc_set keymap "el.iso07" || f_die
+		break ;;
+	greek_elot)
+		f_sysrc_set keymap "gr.elot.acc" || f_die
+		break ;;
+	hungarian_101)
+		f_sysrc_set keymap "hu.iso2.101keys" || f_die
+		break ;;
+	hungarian_102)
+		f_sysrc_set keymap "hu.iso2.102keys" || f_die
+		break ;;
+	icelandic)
+		f_sysrc_set keymap "icelandic.iso" || f_die
+		break ;;
+	icelandic_accent)
+		f_sysrc_set keymap "icelandic.iso.acc" || f_die
+		break ;;
+	italian)
+		f_sysrc_set keymap "it.iso" || f_die
+		break ;;
+	japanese_106)
+		f_sysrc_set keymap "jp.106" || f_die
+		break ;;
+	latin_american)
+		f_sysrc_set keymap "latinamerican" || f_die
+		break ;;
+	latin_american_accent)
+		f_sysrc_set keymap "latinamerican.iso.acc" || f_die
+		break ;;
+	norway_iso)
+		f_sysrc_set keymap "norwegian.iso" || f_die
+		break ;;
+	polish_iso)
+		f_sysrc_set keymap "pl_PL.ISO8859-2" || f_die
+		break ;;
+	portuguese)
+		f_sysrc_set keymap "pt.iso" || f_die
+		break ;;
+	portuguese_accent)
+		f_sysrc_set keymap "pt.iso.acc" || f_die
+		break ;;
+	russia_koi8_r)
+		f_sysrc_set keymap "ru.koi8-r" || f_die
+		break ;;
+	slovak) 
+		f_sysrc_set keymap "sk.iso2" || f_die
+		break ;;
+	slovenian)
+		f_sysrc_set keymap "si.iso" || f_die
+		break ;;
+	spanish)
+		f_sysrc_set keymap "spanish.iso" || f_die
+		break ;;
+	spanish_accent)
+		f_sysrc_set keymap "spanish.iso.acc" || f_die
+		break ;;
+	swedish_cp850)
+		f_sysrc_set keymap "swedish.cp850" || f_die
+		break ;;
+	swedish_iso)
+		f_sysrc_set keymap "swedish.iso" || f_die
+		break ;;
+	swiss_french_cp850)
+		f_sysrc_set keymap "swissfrench.cp850" || f_die
+		break ;;
+	swiss_french_iso)
+		f_sysrc_set keymap "swissfrench.iso" || f_die
+		break ;;
+	swiss_french_iso_accent)
+		f_sysrc_set keymap "swissfrench.iso.acc" || f_die
+		break ;;
+	swiss_german_cp850)
+		f_sysrc_set keymap "swissgerman.cp850" || f_die
+		break ;;
+	swiss_german_iso)
+		f_sysrc_set keymap "swissgerman.iso" || f_die
+		break ;;
+	swiss_german_iso_accent)
+		f_sysrc_set keymap "swissgerman.iso.acc" || f_die
+		break ;;
+	uk_cp850)
+		f_sysrc_set keymap "uk.cp850" || f_die
+		break ;;
+	uk_iso)
+		f_sysrc_set keymap "uk.iso" || f_die
+		break ;;
+	ukrainian_koi8_u)
+		f_sysrc_set keymap "ua.koi8-u" || f_die
+		break ;;
+	ukrainian_koi8_u_koi8_r)
+		f_sysrc_set keymap "ua.koi8-u.shift.alt" || f_die
+		break ;;
+	usa_capslock_ctrl)
+		f_sysrc_set keymap "us.pc-ctrl" || f_die
+		break ;;
+	usa_dvorak)
+		f_sysrc_set keymap "us.dvorak" || f_die
+		break ;;
+	usa_dvorak_left)
+		f_sysrc_set keymap "us.dvorakl" || f_die
+		break ;;
+	usa_dvorak_right)
+		f_sysrc_set keymap "us.dvorakr" || f_die
+		break ;;
+	usa_emacs)
+		f_sysrc_set keymap "us.emacs" || f_die
+		break ;;
+	usa_iso)
+		f_sysrc_set keymap "us.iso" || f_die
+		break ;;
+	usa_unix)
+		f_sysrc_set keymap "us.unix" || f_die
+		break ;;
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/repeat
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/repeat	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,134 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/repeat 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_choose_a_keyboard_repeat_rate"
+	local prompt="$msg_repeat_menu_text"
+
+	menu_list="
+		'$msg_slow'    '$msg_slow_desc'
+		'$msg_normal'  '$msg_normal_desc'
+		'$msg_fast'    '$msg_fast_desc'
+		'$msg_default' '$msg_default_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_keyboard_repeat_rate"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"$msg_slow") # Slow keyboard repeat rate
+		f_sysrc_set keyrate "slow" || f_die
+		break ;;
+	"$msg_normal") # "Normal" keyboard repeat rate
+		f_sysrc_set keyrate "normal" || f_die
+		break ;;
+	"$msg_fast") # Fast keyboard repeat rate
+		f_sysrc_set keyrate "fast" || f_die
+		break ;;
+	"$msg_default") # Use default keyboard repeat rate
+		f_sysrc_set keyrate "NO" || f_die
+		break ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/saver
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/saver	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,198 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/saver 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_choose_a_screen_saver"
+	local prompt="$msg_saver_menu_text"
+
+	menu_list="
+		'1 $msg_blank'   '$msg_blank_desc'
+		'2 $msg_beastie' '$msg_beastie_desc'
+		'3 $msg_daemon'  '$msg_daemon_desc'
+		'4 $msg_dragon'  '$msg_dragon_desc'
+		'5 $msg_fade'    '$msg_fade_desc'
+		'6 $msg_fire'    '$msg_fire_desc'
+		'7 $msg_green'   '$msg_green_desc'
+		'8 $msg_logo'    '$msg_logo_desc'
+		'9 $msg_rain'    '$msg_rain_desc'
+		'a $msg_snake'   '$msg_snake_desc'
+		'b $msg_star'    '$msg_star_desc'
+		'c $msg_warp'    '$msg_warp_desc'
+		'd $msg_none'    '$msg_none_saver_desc'
+		'$msg_timeout'   '$msg_timeout_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_screen_saver"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"1 $msg_blank") # Simply blank the screen
+		f_sysrc_set saver "blank" || f_die
+		break ;;
+	"2 $msg_beastie") # "BSD Daemon" animated screen saver (graphics)
+		f_sysrc_set saver "beastie" || f_die
+		break ;;
+	"3 $msg_daemon") # "BSD Daemon" animated screen saver (text)
+		f_sysrc_set saver "daemon" || f_die
+		break ;;
+	"4 $msg_dragon") # Dragon screensaver (graphics)
+		f_sysrc_set saver "dragon" || f_die
+		break ;;
+	"5 $msg_fade") # Fade out effect screen saver
+		f_sysrc_set saver "fade" || f_die
+		break ;;
+	"6 $msg_fire") # Flames effect screen saver
+		f_sysrc_set saver "fire" || f_die
+		break ;;
+	"7 $msg_green") # "Green" power saving mode (if supported by monitor)
+		f_sysrc_set saver "green" || f_die
+		break ;;
+	"8 $msg_logo") # FreeBSD "logo" animated screen saver (graphics)
+		f_sysrc_set saver "logo" || f_die
+		break ;;
+	"9 $msg_rain") # Rain drops screen saver
+		f_sysrc_set saver "rain" || f_die
+		break ;;
+	"a $msg_snake") # Draw a FreeBSD "snake" on your screen
+		f_sysrc_set saver "snake" || f_die
+		break ;;
+	"b $msg_star") # A "twinkling stars" effect
+		f_sysrc_set saver "star" || f_die
+		break ;;
+	"c $msg_warp") # A "stars warping" effect
+		f_sysrc_set saver "warp" || f_die
+		break ;;
+	"d $msg_none") # Disable the screensaver
+		f_sysrc_set saver "NO" || f_die
+		break ;;
+	"$msg_timeout") # Set the screen saver timeout interval
+		f_dialog_title "$msg_value_required"
+		title="$DIALOG_TITLE"
+		btitle="$DIALOG_BACKTITLE"
+		f_dialog_title_restore
+		prompt="$msg_enter_timeout_period"
+		blanktime=$( f_sysrc_get blanktime )
+		hline=""
+		size=$( f_dialog_inputbox_size \
+		        	"$title"     \
+		        	"$btitle"    \
+		        	"$prompt"    \
+		        	"$blanktime" \
+		        	"$hline"     )
+		$DIALOG \
+			--title "$title"             \
+			--backtitle "$btitle"        \
+			--hline "$hline"             \
+			--ok-label "$msg_ok"         \
+			--cancel-label "$msg_cancel" \
+			--inputbox "$prompt" $size   \
+			"$blanktime"                 \
+			2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+		retval=$?
+		blanktime=$( f_dialog_inputstr )
+		[ $retval -eq $SUCCESS ] &&
+			f_sysrc_set blanktime "$blanktime"
+		;;
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/screenmap
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/screenmap	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,142 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/screenmap 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_choose_a_screen_map"
+	local prompt="$msg_screenmap_menu_text"
+
+	menu_list="
+		'1 $msg_none'                 '$msg_none_screenmap_desc'
+		'2 $msg_iso_8859_1_to_ibm437' '$msg_iso_8859_1_to_ibm437_desc'
+		'3 $msg_iso_8859_7_to_ibm437' '$msg_iso_8859_7_to_ibm437_desc'
+		'4 $msg_us_ascii_to_ibm327'   '$msg_us_ascii_to_ibm327_desc'
+		'5 $msg_koi8_r_to_ibm866'     '$msg_koi8_r_to_ibm866_desc'
+		'6 $msg_koi8_u_to_ibm866u'    '$msg_koi8_u_to_ibm866u_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_screenmap"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"1 $msg_none") # No screenmap, don't touch font
+		f_sysrc_set scrnmap "NO" || f_die
+		break ;;
+	"2 $msg_iso_8859_1_to_ibm437") # W-Europe ISO 8859-1 to IBM 437 scrnmap
+		f_sysrc_set scrnmap "iso-8859-1_to_cp437" || f_die
+		break ;;
+	"3 $msg_iso_8859_7_to_ibm437") # Greek ISO 8859-7 to IBM 437 screenmap
+		f_sysrc_set scrnmap "iso-8859-7_to_cp437" || f_die
+		break ;;
+	"4 $msg_us_ascii_to_ibm327") # US-ASCII to IBM 437 screenmap
+		f_sysrc_set scrnmap "us-ascii_to_cp437" || f_die
+		break ;;
+	"5 $msg_koi8_r_to_ibm866") # Russian KOI8-R to IBM 866 screenmap
+		f_sysrc_set scrnmap "koi8-r2cp866" || f_die
+		break ;;
+	"6 $msg_koi8_u_to_ibm866u") # Ukrainian KOI8-U to IBM 866u screenmap
+		f_sysrc_set scrnmap "koi8-u2cp866u" || f_die
+		break ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/console/ttys
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/console/ttys	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,197 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/console/ttys 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Location of ttys(5)
+#
+ETC_TTYS=/etc/ttys
+
+############################################################ GLOBALS
+
+#
+# Terminal-type map/menu-item list
+#
+TTY_MENU_LIST="
+	'1 $msg_none'                '$msg_none_ttys_desc'
+	'2 $msg_ibm_437_vga_default' 'cons25'
+	'3 $msg_iso_8859_1'          'cons25l1'
+	'4 $msg_iso_8859_2'          'cons25l2'
+	'5 $msg_iso_8859_7'          'cons25l7'
+	'6 $msg_koi8_r'              'cons25r'
+	'7 $msg_koi8_u'              'cons25u'
+	'8 $msg_us_ascii'            'cons25w'
+" # END-QUOTE
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local size
+	local hline="$hline_choose_a_terminal_type"
+	local prompt="$msg_ttys_menu_text"
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$TTY_MENU_LIST         )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$TTY_MENU_LIST                     \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# ttys_set_type $consterm
+#
+# Set terminal type of `ttyv*' and `cons[0-9]' entries in ttys(5) to $consterm.
+#
+ttys_set_type()
+{
+	local consterm="$1"
+
+	#
+	# Create new temporary file to write our ttys(5) update with new types.
+	#
+	local tmpfile="$( mktemp -t "pgm" )"
+	[ "$tmpfile" ] || return $FAILURE
+
+	#
+	# Fixup permissions and ownership (mktemp(1) creates the temporary file
+	# with 0600 permissions -- change the permissions and ownership to
+	# match ttys(5) before we write it out and mv(1) it into place).
+	#
+	local mode="$( stat -f '%#Lp' "$ETC_TTYS" 2> /dev/null )"
+	local owner="$( stat -f '%u:%g' "$ETC_TTYS" 2> /dev/null )"
+	f_quietly chmod "${mode:-0644}" "$tmpfile"
+	f_quietly chown "${owner:-root:wheel}" "$tmpfile"
+
+	#
+	# Operate on ttys(5), replacing only the types of `ttyv*' and
+	# `cons[0-9]' terminals with the new type.
+	#
+	awk -v consterm="$consterm" '
+	BEGIN {
+	}
+	{
+		# "Skip" blank-lines, lines containing only whitespace, and
+		# lines containing only a comment or whitespace-then-comment.
+		#
+		if ( $0 ~ /^[[:space:]]*(#|$)/ ) { print; next }
+
+		# "Skip" terminal types other than those supported
+		#
+		if ( $1 !~ /^(ttyv.*|cons[0-9])$/ ) { print; next }
+
+		# Change the terminal type to the new value
+		#
+		match($0, /[[:alnum:]\.\+-_]+[[:space:]]+(on|off).*$/)
+		if ( ! RSTART ) { print; next }
+		left = substr($0, 0, RSTART - 1)
+		match($0, /[[:space:]]+(on|off).*$/)
+		right = substr($0, RSTART)
+		printf "%s%s%s\n", left, consterm, right
+	}
+	' "$ETC_TTYS" > "$tmpfile" || return $FAILURE
+	f_quietly mv "$tmpfile" "$ETC_TTYS" || return $FAILURE
+
+	return $SUCCESS
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_console_terminal_type"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+	[ "$mtag" = "1 $msg_none" ] && break
+
+	consterm=$( eval f_dialog_menutag2item \"\$mtag\" $TTY_MENU_LIST )
+	err=$( ttys_set_type "$consterm" 2>&1 )
+	[ "$err" ] || break
+
+	f_show_msg "%s" "$err"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/diskmgmt/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/diskmgmt/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/diskmgmt/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Disk Management"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Manage disk partitions and/or labels"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="diskmgmt|diskmgmt"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="diskmgmt"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/diskmgmt/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/diskmgmt/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/diskmgmt/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/050.diskmgmt
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	diskmgmt
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/diskmgmt/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/diskmgmt/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/diskmgmt/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/diskmgmt/diskmgmt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/diskmgmt/diskmgmt	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,85 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/diskmgmt/diskmgmt 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="050.diskmgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# If X11 is requested, which terminal and what options should we use?
+#
+X11TERM=xterm
+X11TERM_OPTS=
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_mustberoot_init
+
+#
+# If Xdialog(1) is requested, we'll need to wrap bsdinstall(8) into xterm(1)
+#
+if [ "$USE_XDIALOG" ]; then
+	f_have "$X11TERM" || f_die 1 \
+		"$msg_no_such_file_or_directory" "$pgm" "$X11TERM"
+
+	exec $X11TERM $X11TERM_OPTS -e /usr/sbin/sade
+else
+	exec /usr/sbin/sade
+fi
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/diskmgmt/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/diskmgmt/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/diskmgmt/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/050.diskmgmt/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/diskmgmt/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/diskmgmt/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,27 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/diskmgmt/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/docsinstall/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/docsinstall/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/docsinstall/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Documentation installation"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Install FreeBSD Documentation set"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="docsinstall|docsinstall"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="docsinstall"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/docsinstall/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/docsinstall/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/docsinstall/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/020.docsinstall
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	docsinstall
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/docsinstall/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/docsinstall/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/docsinstall/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/docsinstall/docsinstall
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/docsinstall/docsinstall	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,97 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/docsinstall/docsinstall 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="020.docsinstall"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# If X11 is requested, which terminal and what options should we use?
+#
+X11TERM=xterm
+X11TERM_OPTS=
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_mustberoot_init
+
+#
+# If Xdialog(1) is requested, we'll need to wrap bsdinstall(8) into xterm(1)
+#
+if [ "$USE_XDIALOG" ]; then
+	#
+	# Make sure $X11TERM exists and is executable
+	#
+	case "$X11TERM" in
+	*/*)
+		[ -e "$X11TERM" ] || f_die 1 \
+			"$msg_no_such_file_or_directory" "$pgm" "$X11TERM"
+		[ -x "$X11TERM" ] || f_die 1 \
+			"$msg_permission_denied" "$pgm" "$X11TERM"
+		;;
+	*)
+		f_have "$X11TERM" || f_die 1 \
+			"$msg_no_such_file_or_directory" "$pgm" "$X11TERM"
+	esac
+
+	exec $X11TERM $X11TERM_OPTS -e /usr/sbin/bsdinstall docsinstall
+else
+	exec /usr/sbin/bsdinstall docsinstall
+fi
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/docsinstall/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/docsinstall/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/docsinstall/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/020.docsinstall/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/docsinstall/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/docsinstall/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/docsinstall/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
+msg_permission_denied="%s: %s: permission denied"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/dot/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/dot/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/dot/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title=""
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help=""
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="dot|dot"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program=""
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/dot/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/dot/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/dot/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/dot
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	dot
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/dot/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/dot/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,143 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/dot/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h    Print usage statement and exit.
+	-c    Don't show command-line shortcut relationships.
+	-d    Don't show the date in the graph label.
+	-i    Don't show include relationships.
+
+EXAMPLES:
+	View dot(1) language output describing bsdconfig(8) layout/make-up:
+
+		bsdconfig @PROGRAM_NAME@ | less
+
+	Render dot(1) output in SVG format (displays in most modern browsers):
+
+		bsdconfig @PROGRAM_NAME@ | dot -Tsvg -o bsdconfig.svg
+
+		NOTE: Requires `graphics/graphviz' from ports/packages.
+
+	View the above-rendered SVG file using your favorite X11-based viewer:
+
+		gimmage bsdconfig.svg
+
+			NOTE: Requires `graphics/gimmage' from ports/packages.
+
+		or
+
+		gthumb bsdconfig.svg
+
+			NOTE: Image is scaled to fit window on launch.
+			NOTE: Requires `graphics/gthumb' from ports/packages.
+
+		or
+
+		gqview bsdconfig.svg
+
+			NOTE: Requires `graphics/gqview' from ports/packages.
+
+		or
+
+		gx bsdconfig.svg
+
+			NOTE: Image is scaled to fit window on launch.
+			NOTE: Requires `graphics/gx' from ports/packages.
+
+		or
+
+		eog bsdconfig.svg
+
+			NOTE: Requires `graphics/eog' from ports/packages.
+
+	Render dot(1) output as PostScript print output consisting of multiple
+	US-Letter sized pages that can be assembled into a large poster (using
+	traditional tools such as scissors and tape):
+
+		bsdconfig @PROGRAM_NAME@ | dot -Teps -o bsdconfig.eps
+		poster -v -mLet -s1 -o bsdconfig.ps bsdconfig.eps
+
+		NOTE: Change "-s1" above to "-s0.5" to halve the size of the
+		      poster or "-s2", for example, to double the poster size.
+
+		NOTE: Requires both `graphics/graphviz' and `print/poster' from
+		      ports/packages.
+
+	Render dot(1) output as PostScript scaled to fit on a poster consisting
+	of 2x-wide and 4x-tall US-Letter sized pages:
+
+		bsdconfig @PROGRAM_NAME@ | dot -Teps -o bsdconfig.eps
+		poster -v -mLet -p2x4Letter -o bsdconfig.ps bsdconfig.eps
+
+		NOTE: Requires both `graphics/graphviz' and `print/poster' from
+		      ports/packages.
+
+	View the above-rendered PostScript poster using X11:
+
+		gsview bsdconfig.ps
+
+			NOTE: Requires `print/gsview' from ports/packages.
+
+		or
+
+		convert bsdconfig.ps bsdconfig.pdf
+		xpdf bsdconfig.pdf
+
+			NOTE: Requires both `graphics/ImageMagick' and
+			      `graphics/xdpf' from ports/packages.
+
+			NOTE: The converted PDF file is not suitable for
+			      printing due to loss of quality during the
+			      conversion process.
+
+	Print the above-rendered PostScript poster:
+
+		lpr -h bsdconfig.ps
+
+		NOTE: Requires configuration of a printer in `/etc/printcap'.
+
+	Extract each page of the poster into a separate PNG file:
+
+		gs -q -dNOPAUSE -dBATCH -sPAPERSIZE=letter \
+		   -dTextAlphaBits=4 -dGraphicsAlphaBits=4 \
+		   -sDEVICE=png16m -sOutputFile=bsdconfig%03d.png \
+		   bsdconfig.ps
+
+		NOTE: Requires `print/ghostscript9' from ports/packages.
+
+		NOTE: The converted PNG files are not suitable for printing
+		      due to loss of quality during the conversion process.
+
+	Extract a single page of the poster into a separate PostScript file for
+	printing individual pages from the command-line:
+
+		psselect 1 bsdconfig.ps bsdconfig-page1.ps
+		lpr -h bsdconfig-page1.ps
+
+		NOTE: Change "1" to "2" for the second page, ad-infinitum.
+		NOTE: Requires `print/psutils-letter' from ports/packages.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/dot/dot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/dot/dot	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,646 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/dot/dot 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+APP_DIR="dot"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Locataion of bsdconfig(8)
+#
+BSDCONFIG=/usr/sbin/bsdconfig
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+SHOW_GRAPH_LABEL_DATE=1
+SHOW_INCLUDES=1
+SHOW_CMDLINE=1
+
+############################################################ FUNCTIONS
+
+# begin_nodelist $shape $color $fillcolor $style
+#
+# Create a new multi-node list rendering nodes in a specific style described by
+# the arguments passed.
+#
+begin_nodelist()
+{
+	local shape="$1" color="$2" fillcolor="$3" style="$4"
+
+	printf "\tnode [\n"
+	[ "$shape" ] &&
+		printf '\t\tshape = "%s",\n' "$shape"
+	[ "$color" ] &&
+		printf '\t\tcolor = "%s",\n' "$color"
+	[ "$fillcolor" ] &&
+		printf '\t\tfillcolor = "%s",\n' "$fillcolor"
+	[ "$style" ] &&
+		printf '\t\tstyle = "%s",\n' "$style"
+	printf "\t] {\n"
+}
+
+# print_node $node [$attributes ...]
+#
+# Print a node within a multi-node list.
+#
+print_node()
+{
+	local node="$1"
+
+	shift 1 # node
+
+	case "$node" in
+	edge) printf '\t\t%s' "$node";;
+	   *) printf '\t\t"%s"' "$node";;
+	esac
+
+	if [ $# -gt 0 ]; then
+		echo -n ' ['
+		while [ $# -gt 0 ]; do
+			printf " %s" "$1"
+			shift 1
+			[ $# -gt 0 ] && echo -n ","
+		done
+		echo -n " ]"
+	fi
+
+	echo ";"
+}
+
+# print_node2 $node $node [$attributes ...]
+#
+# Print a directed node-node connection within a multi-node list.
+#
+print_node2()
+{
+	local node1="$1" node2="$2"
+
+	shift 2 # node1 node2
+
+	printf '\t\t"%s" -> "%s"' "$node1" "$node2"
+
+	if [ $# -gt 0 ]; then
+		echo -n ' ['
+		while [ $# -gt 0 ]; do
+			printf " %s" "$1"
+			shift 1
+			[ $# -gt 0 ] && echo -n ","
+		done
+		echo -n " ]"
+	fi
+
+	echo ";"
+}
+
+# end_nodelist
+#
+# Close a multi-node list.
+#
+end_nodelist()
+{
+	printf "\t};\n"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts cdhi flag; do
+	case "$flag" in
+	i) SHOW_INCLUDES=;;
+	d) SHOW_GRAPH_LABEL_DATE=;;
+	c) SHOW_CMDLINE=;;
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+cd $BSDCFG_LIBE || f_die 1 "$msg_directory_not_found" "$BSDCFG_LIB"
+
+#
+# Get a list of menu programs
+#
+menu_program_list=
+for file in [0-9][0-9][0-9].*/INDEX; do
+	menu_program_list="$menu_program_list $(
+		tail -r "$file" | awk -v item="${file%%/*}" '
+			/^[[:space:]]*menu_program="/ {
+				sub(/^.*="/, "")
+				sub(/"$/, "")
+				if ( ! $0 ) next
+				if ( $0 !~ "^/" ) sub(/^/, item "/")
+				print; exit
+			}'
+	)"
+done
+
+#
+# Get a list of submenu programs
+#
+submenu_program_list=
+for menu_program in $menu_program_list; do
+	case "$menu_program" in
+	[0-9][0-9][0-9].*/*) : fall-through ;;
+	*) continue # No sub-menus we can process
+	esac
+
+	submenu_program_list="$submenu_program_list $(
+		awk -v menu_program="$menu_program" \
+		    -v item="${menu_program%%/*}" \
+		'
+			/^menu_selection="/ {
+				sub(/.*\|/, "")
+				sub(/"$/, "")
+				if ( ! $0 ) next
+				if ( $0 !~ "^/" )
+					sub(/^/, item "/")
+				if ( $0 == menu_program ) next
+				print
+			}
+		' "${menu_program%%/*}/INDEX"
+	)"
+done
+
+#
+# Get a list of command-line programs
+#
+cmd_program_list=
+for file in */INDEX; do
+	cmd_program_list="$cmd_program_list $(
+		awk -v item="${file%%/*}" '
+			/^menu_selection="/ {
+				sub(/.*\|/, "")
+				sub(/"$/, "")
+
+				if ( ! $0 ) next
+
+				if ( $0 !~ "^/" )
+					sub(/^/, item "/")
+
+				print
+			}
+		' $file
+	)"
+done
+
+#
+# [Optionally] Calculate list of include files
+#
+if [ "$SHOW_INCLUDES" ]; then
+	#
+	# Build list of files in which to search for includes
+	#
+	file_list=$(
+		for file in \
+			$BSDCONFIG \
+			$menu_program_list \
+			$submenu_program_list \
+			$cmd_program_list \
+		; do
+			[ -e "$file" ] && echo $file
+		done | sort -u
+	)
+
+	#
+	# Build list of includes used by the above files
+	#
+	include_file_list=
+	for file in $file_list; do
+		include_file_list="$include_file_list $(
+			awk -v file="$file" -v item="${file%%/*}" '
+				BEGIN { regex = "^f_include \\$BSDCFG_LIBE/" }
+				( $0 ~ regex "include/" ) {
+					sub(regex, "")
+					print
+				}
+				( $0 ~ regex "\\$APP_DIR/include/" ) {
+					sub(regex "\\$APP_DIR", item)
+					print
+				}
+			' $file
+		)"
+	done
+
+	#
+	# Sort the list of includes and remove duplicate entries
+	#
+	include_file_list=$(
+		for include_file in $include_file_list; do
+			echo "$include_file"
+		done | sort -u
+	)
+
+	#
+	# Search previously-discovered include files for further includes
+	#
+	for file in $include_file_list; do
+		include_file_list="$include_file_list $(
+			awk -v file="$file" -v item="${file%%/*}" '
+				BEGIN { regex = "^f_include \\$BSDCFG_LIBE/" }
+				( $0 ~ regex "include/" ) {
+					sub(regex, "")
+					print
+				}
+				( $0 ~ regex "\\$APP_DIR/include/" ) {
+					sub(regex "\\$APP_DIR", item)
+					print
+				}
+			' $file
+		)"
+	done
+
+	#
+	# Sort the list of includes and remove duplicate entries [again]
+	#
+	include_file_list=$(
+		for include_file in $include_file_list; do
+			echo "$include_file"
+		done | sort -u
+	)
+fi
+
+#
+# Start the directional-graph (digraph) output
+#
+printf 'strict digraph "" { // Empty name to prevent SVG Auto-Tooltip\n'
+label_format="$msg_graph_label_with_command"
+[ "$SHOW_GRAPH_LABEL_DATE" ] &&
+	label_format="$msg_graph_label_with_command_and_date"
+lang="${LANG:-$LC_ALL}"
+printf "\n\tlabel = \"$label_format\"\n" \
+       "${lang:+LANG=${lang%%[$IFS]*} }bsdconfig $pgm${ARGV:+ $ARGV}" \
+       "$( date +"%c %Z" )"
+
+#
+# Print graph-specific properties
+#
+printf '\n\t/*\n\t * Graph setup and orientation\n\t */\n'
+printf '\tlabelloc = top;\t\t// display above label at top of graph\n'
+printf '\trankdir = LR;\t\t// create ranks left-to-right\n'
+printf '\torientation = portrait;\t// default\n'
+printf '\tratio = fill;\t\t// approximate aspect ratio\n'
+printf '\tcenter = 1;\t\t// center drawing on page\n'
+
+#
+# Perform edge-concentration when displaying a lot of information
+#
+# NOTE: This is disabled because dot version 2.28.0 (current) and older have a
+#       bug that causes a crash when rankdir = LR and concentrate = true
+#
+# NOTE: Do not re-enable until said bug is fixed in some future revision.
+#
+#[ "$SHOW_INCLUDES" -a "$SHOW_CMDLINE" ] &&
+#	printf '\tconcentrate = true;\t// enable edge concentrators\n'
+
+#
+# Print font details for graph/cluster label(s)
+#
+printf '\n\t/*\n\t * Font details for graph/cluster label(s)\n\t */\n'
+printf '\tfontname = "Times-Italic";\n'
+printf '\tfontsize = 14;\n'
+
+#
+# Print default node attributes
+#
+printf '\n\t/*\n\t * Default node attributes\n\t */\n'
+printf '\tnode [\n'
+printf '\t\tfontname = "Times-Roman",\n'
+printf '\t\tfontsize = 12,\n'
+printf '\t\twidth = 2.5, // arbitrary minimum width for all nodes\n'
+printf '\t\tfixedsize,   // turn minimum width into exact width\n'
+printf '\t];\n'
+
+#
+# Print top-level item(s)
+#
+printf '\n\t/*\n\t * bsdconfig(8)\n\t */\n'
+shape=circle color=black fillcolor=yellow style=filled
+begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+print_node "bsdconfig" "fontname = \"Times-Bold\"" "fontsize = 16"
+end_nodelist
+
+#
+# Print menus
+#
+printf '\n\t/*\n\t * Menu items\n\t */\n'
+shape=box color=black fillcolor=lightblue style=filled
+begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+for menu_program in $menu_program_list; do
+	print_node "$menu_program" "label = \"${menu_program#*/}\""
+done
+end_nodelist
+
+#
+# Print sub-menus
+#
+printf '\n\t/*\n\t * Sub-menu items\n\t */\n'
+shape=box color=black fillcolor=lightblue style=filled
+begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+for submenu_program in $submenu_program_list; do
+	print_node "$submenu_program" "label = \"${submenu_program#*/}\""
+done
+end_nodelist
+
+#
+# Print menu relationships
+#
+printf '\n\t/*\n\t * Menu item relationships\n\t */\n'
+shape=box color=black fillcolor=lightblue style=filled edge_color=blue
+begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+print_node edge "penwidth = 5.0" "style = bold" "color = $edge_color"
+for menu_program in $menu_program_list; do
+	print_node2 "bsdconfig" "$menu_program"
+done
+end_nodelist
+
+#
+# Print sub-menu relationships
+#
+printf '\n\t/*\n\t * Sub-menu item relationships\n\t */\n'
+shape=box color=black fillcolor=lightblue style=filled edge_color=blue
+begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+# Lock sub-menu headport to the West (unless `-c' was passed)
+[ "$SHOW_CMDLINE" -o ! "$SHOW_INCLUDES" ] && print_node edge "headport = w"
+print_node edge "style = bold" "color = $edge_color"
+for submenu_program in $submenu_program_list; do
+	for menu_program in $menu_program_list; do
+		case "$menu_program" in
+		[0-9][0-9][0-9].*/*) : fall-through ;;
+		*) continue # Not a menu item
+		esac
+
+		# Continue if program directories do not match
+		[ "${menu_program%%/*}" = "${submenu_program%%/*}" ] ||
+			continue
+
+		print_node2 "$menu_program" "$submenu_program"
+		break
+	done
+done
+end_nodelist
+
+#
+# [Optionally] Print include files
+#
+if [ "$SHOW_INCLUDES" ]; then
+	printf '\n\t/*\n\t * Include files\n\t */\n'
+	shape=oval color=black fillcolor=white style=filled
+	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+	printf '\t\tconstraint = false;\n'
+	for include_file in $include_file_list; do
+		print_node "$include_file" \
+		           "label = \"${include_file#*include/}\""
+	done
+	end_nodelist
+fi
+
+#
+# [Optionally] Print f_include() usage/relationships
+#
+if [ "$SHOW_INCLUDES" ]; then
+	printf '\n\t/*\n\t * Include usage\n\t */\n'
+	shape=oval color=black fillcolor=white style=filled edge_color=grey
+	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+	print_node edge "style = dashed" "color = $edge_color"
+	file_list=$(
+		for file in \
+			$BSDCONFIG \
+			$menu_program_list \
+			$submenu_program_list \
+			$cmd_program_list \
+			$include_file_list \
+		; do
+			[ -e "$file" ] && echo $file
+		done | sort -u
+	)
+	for file in $file_list; do
+		# Skip binary files and text files that don't use f_include()
+		grep -qlI f_include $file || continue
+
+		awk \
+			-v file="$file" \
+			-v item="${file%%/*}" \
+			-v bsdconfig="$BSDCONFIG" \
+		'
+			BEGIN { regex = "^f_include \\$BSDCFG_LIBE/" }
+			( $0 ~ regex "include/" ) {
+				sub(regex, "")
+				if ( file == bsdconfig ) sub(".*/", "", file)
+				printf "\t\t\"%s\" -> \"%s\";\n", $0, file
+			}
+			( $0 ~ regex "\\$APP_DIR/include/" ) {
+				sub(regex "\\$APP_DIR", item)
+				if ( file == bsdconfig ) sub(".*/", "", file)
+				printf "\t\t\"%s\" -> \"%s\";\n", $0, file
+			}
+		' $file
+	done | sort | awk '
+		BEGIN { found = 0 }
+		{
+			# If already found or no-match... just spew
+			if ( found ) { print; next }
+			if ( $0 !~ /^[[:space:]]*"include\// ) { print; next }
+			printf "\t\tedge [ label = \"\\T\", fontsize = 9 ];\n"
+			print; found = 1
+		}'
+	end_nodelist
+fi
+
+#
+# Print command-line shortcuts
+#
+if [ "$SHOW_CMDLINE" ]; then
+	printf '\n\t/*\n\t * Command-line shortcuts\n\t */\n'
+	shape=parallelogram color=black fillcolor=lightseagreen style=filled
+	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+	for file in */INDEX; do
+		awk -v item="${file%%/*}" '
+			/^menu_selection="/ {
+				sub(/^.*="/, "")
+				sub(/\|.*/, "")
+				printf "\t\t\"bsdconfig %s\"", $0
+				printf " [ label = \"%s\" ];\n", $0
+			}
+		' $file
+	done
+	end_nodelist
+fi
+
+#
+# Print command-line shortcut relationships
+#
+if [ "$SHOW_CMDLINE" ]; then
+	printf '\n\t/*\n\t * Command-line shortcut relationships\n\t */\n'
+	shape=box color=black fillcolor=lightseagreen style=filled
+	begin_nodelist "$shape" "$color" "$fillcolor" "$style"
+	print_node edge "headport = w" "weight = 100.0"
+	print_node edge "style = bold" "color = $fillcolor"
+	for file in */INDEX; do
+		awk -v item="${file%%/*}" \
+		    -v node_fillcolor="$node_fillcolor" \
+		    -v edge_color="$edge_color" \
+		'
+			/^menu_selection="/ {
+				sub(/^.*="/, "")
+				sub(/"$/, "")
+
+				if ( ! $0 ) next
+
+				split($0, menusel, "|")
+				if ( menusel[2] !~ "^/" )
+					sub(/^/, item "/", menusel[2])
+
+				printf "\t\t\"bsdconfig %s\" -> \"%s\";\n",
+				       menusel[1], menusel[2]
+			}
+		' $file
+	done
+	end_nodelist
+fi
+
+#
+# Print clusters
+#
+bgcolor_bsdconfig="lightyellow"
+bgcolor_includes="gray98"
+bgcolor_menuitem="aliceblue"
+bgcolor_shortcuts="honeydew"
+printf '\n\t/*\n\t * Clusters\n\t */\n'
+printf '\tsubgraph "cluster_bsdconfig" {\n'
+printf '\t\tbgcolor = "%s";\n' "$bgcolor_bsdconfig"
+printf '\t\tlabel = "bsdconfig(8)";\n'
+printf '\t\ttooltip = "bsdconfig(8)";\n'
+print_node "bsdconfig"
+if [ "$SHOW_INCLUDES" ]; then
+	printf '\t\tsubgraph "cluster_bsdconfig_includes" {\n'
+	printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_includes"
+	printf '\t\t\tlabel = "%s";\n' "$msg_includes"
+	for include_file in $include_file_list; do
+		case "$include_file" in
+		include/*) printf '\t\t\t"%s";\n' "$include_file";;
+		esac
+	done
+	printf '\t\t};\n'
+fi
+end_nodelist
+for INDEX in */INDEX; do
+	menu_title=
+	menu_help=
+	f_include_lang "$INDEX"
+
+	item="${INDEX%%/*}"
+	printf '\tsubgraph "cluster_%s" {\n' "$item"
+
+	case "$item" in
+	[0-9][0-9][0-9].*) bgcolor="$bgcolor_menuitem";;
+	*) bgcolor="$bgcolor_shortcuts"
+	esac
+	printf '\t\tbgcolor = "%s";\n' "$bgcolor"
+	if [ "$menu_title" ]; then
+		printf '\t\tlabel = "%s\\n\\"%s\\"";\n' "$item" "$menu_title"
+	else
+		printf '\t\tlabel = "%s";\n' "$item"
+	fi
+	printf '\t\ttooltip = "%s";\n' "${menu_help:-$item}"
+
+	program_list=$(
+		for program in \
+			$menu_program_list \
+			$submenu_program_list \
+			$cmd_program_list \
+		; do
+			echo "$program"
+		done | sort -u
+	)
+	for program in $program_list; do
+		case "$program" in "$item"/*)
+			print_node "$program" "label = \"${program#*/}\""
+		esac
+	done
+
+	if [ "$SHOW_INCLUDES" ]; then
+		item_include_list=
+		[ -d "$item/include" ] &&
+			item_include_list=$( find "$item/include" -type f )
+		item_include_list=$(
+			for item_include in $item_include_list; do
+				for include_file in $include_file_list; do
+					[ "$item_include" = "$include_file" ] ||
+						continue
+					echo "$item_include"; break
+				done
+			done
+		)
+		if [ "$item_include_list" ]; then
+			printf '\t\tsubgraph "cluster_%s_includes" {\n' "$item"
+			printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_includes"
+			printf '\t\t\tlabel = "%s";\n' "$msg_includes"
+		fi
+		for item_include in $item_include_list; do
+			printf '\t\t\t"%s";\n' "$item_include"
+		done
+		[ "$item_include_list" ] && printf '\t\t};\n'
+	fi
+
+	if [ "$SHOW_CMDLINE" ]; then
+		printf '\t\tsubgraph "cluster_%s_shortcuts" {\n' "$item"
+		printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_shortcuts"
+		printf '\t\t\tlabel = "%s";\n' "$msg_shortcuts"
+		awk '/^menu_selection="/ {
+			sub(/^.*="/, "")
+			sub(/\|.*/, "")
+			printf "\t\t\t\"bsdconfig %s\";\n", $0
+		}' "$INDEX"
+		printf '\t\t};\n'
+	fi
+
+	end_nodelist
+done
+
+printf '\n};\n'
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/dot/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/dot/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/dot/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/dot/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/dot/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/dot/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,30 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/dot/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+msg_graph_label_with_command="bsdconfig(8)\\\ndot(1) output generated by \`\`%s''"
+msg_graph_label_with_command_and_date="bsdconfig(8)\\\ndot(1) output generated by \`\`%s'' on\\\n%s"
+msg_includes="Includes"
+msg_shortcuts="Shortcuts"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/examples/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/examples/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/examples/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${SHAREDIR}/examples/bsdconfig
+FILES=		bsdconfigrc
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/examples/bsdconfigrc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/examples/bsdconfigrc	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/examples/bsdconfigrc 238438 2012-07-14 03:16:57Z dteske $
+
+# This file allows you to customize the behavior of bsdconfig.
+#   Copy it to your $HOME/.bsdconfigrc and edit to suit.
+#   defaults are shown.
+
+# debugging aid for development
+# f_dprintf() {
+#   echo "$(date):$pgm: $1" >> $HOME/out
+# }
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,12 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/include
+FILES=		common.subr dialog.subr messages.subr mustberoot.subr \
+		strings.subr sysrc.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/common.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/common.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,299 @@
+if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/include/common.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ GLOBALS
+
+#
+# Program name
+#
+pgm="${0##*/}"
+
+#
+# Program arguments
+#
+ARGC="$#"
+ARGV="$@"
+
+#
+# Global exit status variables
+#
+SUCCESS=0
+FAILURE=1
+
+############################################################ FUNCTIONS
+
+#
+# This is an empty function by default, to use it, copy
+# /usr/share/examples/bsdconfig/bsdconfigrc to $HOME/.bsdconfigrc
+#
+f_dprintf()
+{
+	: this page intentionally left blank
+}
+
+# f_err $fmt [ $opts ... ]
+#
+# Print a message to stderr (fd=2).
+#
+f_err()
+{
+	printf "$@" >&2 
+}
+
+# f_quietly $command [ $arguments ... ]
+#
+# run a command quietly (quell any output to stdout or stderr)
+#
+f_quietly()
+{
+	"$@" > /dev/null 2>&1
+}
+
+# f_have $anything ...
+# 
+# A wrapper to the `type' built-in. Returns true if argument is a valid shell
+# built-in, keyword, or externally-tracked binary, otherwise false.
+#
+f_have()
+{
+	f_quietly type "$@"
+}
+
+# f_die [ $status [ $fmt [ $opts ... ]]]
+#
+# Abruptly terminate due to an error optionally displaying a message in a
+# dialog box using printf(1) syntax.
+#
+f_die()
+{
+	local status=$FAILURE
+
+	# If there is at least one argument, take it as the status
+	if [ $# -gt 0 ]; then
+		status=$1
+		shift 1 # status
+	fi
+
+	# If there are still arguments left, pass them to f_show_msg
+	[ $# -gt 0 ] && f_show_msg "$@"
+
+	# Optionally call f_clean_up() function if it exists
+	f_have f_clean_up && f_clean_up
+
+	exit $status
+}
+
+# f_interrupt
+#
+# Interrupt handler.
+#
+f_interrupt()
+{
+	exec 2>&1 # fix sh(1) bug where stderr gets lost within async-trap
+	f_die
+}
+
+# f_show_msg $fmt [ $opts ... ]
+#
+# Display a message in a dialog box using printf(1) syntax.
+#
+f_show_msg()
+{
+	local msg
+	msg=$( printf "$@" )
+
+	#
+	# Use f_dialog_msgbox from dialog.subr if possible, otherwise fall
+	# back to dialog(1) (without options, making it obvious when using
+	# un-aided system dialog).
+	#
+	if f_have f_dialog_msgbox; then
+		f_dialog_msgbox "$msg"
+	else
+		dialog --msgbox "$msg" 0 0
+	fi
+}
+
+# f_include $file
+#
+# Include a shell subroutine file.
+#
+# If the subroutine file exists but returns error status during loading, exit
+# is called and execution is prematurely terminated with the same error status.
+#
+f_include()
+{
+	local file="$1"
+	. "$file" || exit $?
+}
+
+# f_include_lang $file
+#
+# Include a language file. Automatically takes $LANG and $LC_ALL into
+# considerationg when including $file (suffix ".$LC_ALL" or ".$LANG" will
+# automatically by added prior to loading the language file).
+#
+# No error is produced if (a) a language has been requested (by setting either
+# $LANG or $LC_ALL in the environment) and (b) the language file does not
+# exist -- in which case we will fall back to loading $file without-suffix.
+#
+# If the language file exists but returns error status during loading, exit
+# is called and execution is prematurely terminated with the same error status.
+#
+f_include_lang()
+{
+	local file="$1"
+	local lang="${LANG:-$LC_ALL}"
+
+	f_dprintf "lang=[$lang]"
+	if [ -f "$file.$lang" ]; then
+		. "$file.$lang" || exit $?
+	else
+		. "$file" || exit $?
+	fi
+}
+
+# f_usage $file [ $key1 $value1 ... ]
+#
+# Display USAGE file with optional pre-processor macro definitions. The first
+# argument is the template file containing the usage text to be displayed. If
+# $LANG or $LC_ALL (in order of preference, respectively) is set, ".encoding"
+# will automatically be appended as a suffix to the provided $file pathname.
+#
+# When processing $file, output begins at the first line containing that is
+# (a) not a comment, (b) not empty, and (c) is not pure-whitespace. All lines
+# appearing after this first-line are output, including (a) comments (b) empty
+# lines, and (c) lines that are purely whitespace-only.
+#
+# If additional arguments appear after $file, substitutions are made while
+# printing the contents of the USAGE file. The pre-processor macro syntax is in
+# the style of autoconf(1), for example:
+#
+# 	f_usage $file "FOO" "BAR"
+#
+# Will cause instances of "@FOO@" appearing in $file to be replaced with the
+# text "BAR" before bering printed to the screen.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_usage_awk='
+BEGIN { found = 0 }
+{
+	if ( !found && $0 ~ /^[[:space:]]*($|#)/ ) next
+	found = 1
+	print
+}
+'
+f_usage()
+{
+	local file="$1"
+	local lang="${LANG:-$LC_ALL}"
+
+	f_dprintf "lang=[$lang]"
+
+	shift 1 # file
+
+	local usage
+	if [ -f "$file.$lang" ]; then
+		usage=$( awk "$f_usage_awk" "$file.$lang" ) || exit $FAILURE
+	else
+		usage=$( awk "$f_usage_awk" "$file" ) || exit $FAILURE
+	fi
+
+	while [ $# -gt 0 ]; do
+		local key="$1"
+		export value="$2"
+		usage=$( echo "$usage" | awk \
+			"{ gsub(/@$key@/, ENVIRON[\"value\"]); print }" )
+		shift 2
+	done
+
+	f_err "%s\n" "$usage"
+
+	exit $FAILURE
+}
+
+# f_index_menu_selection $file $pgm
+#
+# Process $file looking for $menu_selection values that correspond to $pgm.
+# This function is for internationalization (i18n) mapping of the on-disk
+# scriptname ($pgm) into the localized language (given language-specific
+# $file). If $LANG or $LC_ALL (in orderder of preference, respectively) is set,
+# ".encoding" will automatically be appended as a suffix to the provided $file
+# pathname.
+#
+# If, within $file, multiple $menu_selection values map to $pgm, only the first
+# one will be returned. If no mapping can be made, the NULL string is returned.
+#
+# If $file does not exist, error status is returned along with the NULL string.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_index_menusel_awk='
+# Variables that should be defined on the invocation line:
+# 	-v pgm="program_name"
+#
+( $0 ~ "^menu_selection=.*\\|" pgm "\"" ) {
+	sub(/\|.*/, "")
+	sub(/^menu_selection="/, "")
+	print
+	exit
+}
+'
+f_index_menu_selection()
+{
+	local file="$1" pgm="$2"
+	local lang="${LANG:-$LC_ALL}"
+
+	f_dprintf "lang=[$lang]"
+
+	if [ -f "$file.$lang" ]; then
+		awk -v pgm="$pgm" "$f_index_menusel_awk" "$file.$lang" ||
+			exit $FAILURE
+	elif [ -f "$file" ]; then
+		awk -v pgm="$pgm" "$f_index_menusel_awk" "$file" ||
+			exit $FAILURE
+	else
+		return $FAILURE
+	fi
+}
+
+############################################################ MAIN
+
+#
+# Trap signals so we can recover gracefully
+#
+trap 'f_interrupt' SIGINT
+trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \
+             SIGFPE SIGTRAP SIGABRT SIGSEGV
+trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM
+
+fi # ! $_COMMON_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/dialog.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/dialog.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,1441 @@
+if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/include/dialog.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/strings.subr
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default directory to store dialog(1) temporary files
+#
+: ${DIALOG_TMPDIR:="/tmp"}
+
+############################################################ GLOBALS
+
+#
+# Default name of dialog(1) utility
+# NOTE: This is changed to "Xdialog" by the optional `-X' argument
+#
+DIALOG="dialog"
+
+#
+# Default dialog(1) title and backtitle text
+#
+DIALOG_TITLE="$pgm"
+DIALOG_BACKTITLE="bsdconfig"
+
+#
+# Settings used while interacting with dialog(1)
+#
+DIALOG_MENU_TAGS="123456789ABCDEFGHIJKLMNOPQRSTUVWYZabcdefghijklmnopqrstuvwxyz"
+
+#
+# Declare that we are fully-compliant with Xdialog(1) by unset'ing all
+# compatibility settings.
+#
+unset XDIALOG_HIGH_DIALOG_COMPAT
+unset XDIALOG_FORCE_AUTOSIZE
+unset XDIALOG_INFOBOX_TIMEOUT
+
+#
+# Default behavior is to call f_dialog_init() automatically if not already
+# called manually by the time the first f_dialog_*() function is used.
+#
+: ${DIALOG_SELF_INITIALIZE=1}
+
+############################################################ GENERIC FUNCTIONS
+
+# f_dialog_title [$new_title]
+#
+# Set the title of future dialog(1) ($DIALOG_TITLE) or backtitle of Xdialog(1)
+# ($DIALOG_BACKTITLE) invocations. If no arguments are given or the first
+# argument is NULL, the current title is returned.
+#
+# Each time this function is called, a backup of the current values is made
+# allowing a one-time (single-level) restoration of the previous title using the
+# f_dialog_title_restore() function (below).
+#
+f_dialog_title()
+{
+	local new_title="$1"
+
+	if [ "$new_title" ]; then
+		if [ "$USE_XDIALOG" ]; then
+			_DIALOG_BACKTITLE="$DIALOG_BACKTITLE"
+			DIALOG_BACKTITLE="$new_title"
+		else
+			_DIALOG_TITLE="$DIALOG_TITLE"
+			DIALOG_TITLE="$new_title"
+		fi
+	else
+		if [ "$USE_XDIALOG" ]; then
+			echo "$DIALOG_BACKTITLE"
+		else
+			echo "$DIALOG_TITLE"
+		fi
+	fi
+}
+
+# f_dialog_title_restore
+#
+# Restore the previous title set by the last call to f_dialog_title().
+# Restoration is non-recursive and only works to restore the most-recent title.
+#
+f_dialog_title_restore()
+{
+	if [ "$USE_XDIALOG" ]; then
+		DIALOG_BACKTITLE="$_DIALOG_BACKTITLE"
+	else
+		DIALOG_TITLE="$_DIALOG_TITLE"
+	fi
+}
+
+# f_dialog_backtitle [$new_backtitle]
+#
+# Set the backtitle of future dialog(1) ($DIALOG_BACKTITLE) or title of
+# Xdialog(1) ($DIALOG_TITLE) invocations. If no arguments are given or the
+# first argument is NULL, the current backtitle is returned.
+#
+f_dialog_backtitle()
+{
+	local new_backtitle="$1"
+
+	if [ "$new_backtitle" ]; then
+		if [ "$USE_XDIALOG" ]; then
+			_DIALOG_TITLE="$DIALOG_TITLE"
+			DIALOG_TITLE="$new_backtitle"
+		else
+			_DIALOG_BACKTITLE="$DIALOG_BACKTITLE"
+			DIALOG_BACKTITLE="$new_backtitle"
+		fi
+	else
+		if [ "$USE_XDIALOG" ]; then
+			echo "$DIALOG_TITLE"
+		else
+			echo "$DIALOG_BACKTITLE"
+		fi
+	fi
+}
+
+# f_dialog_backtitle_restore
+#
+# Restore the previous backtitle set by the last call to f_dialog_backtitle().
+# Restoration is non-recursive and only works to restore the most-recent
+# backtitle.
+#
+f_dialog_backtitle_restore()
+{
+	if [ "$USE_XDIALOG" ]; then
+		DIALOG_TITLE="$_DIALOG_TITLE"
+	else
+		DIALOG_BACKTITLE="$_DIALOG_BACKTITLE"
+	fi
+}
+
+############################################################ SIZE FUNCTIONS
+
+# f_dialog_infobox_size $title $backtitle $prompt [$hline]
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--infobox' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, and [optionally] hline returning
+# the optimal width and height for the box (not exceeding the actual terminal
+# width or height).
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+# Output is in the format of "height width".
+#
+f_dialog_infobox_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
+	local min_width max_size
+
+	if [ "$USE_XDIALOG" ]; then
+		min_width=35
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_width=24
+		max_size=$( stty size ) # usually "24 80"
+	fi
+
+	local max_height="${max_size%%[$IFS]*}"
+	local max_width="${max_size##*[$IFS]}"
+	local height width=$min_width
+
+	#
+	# Bump width for long titles (but don't exceed terminal width).
+	#
+	n=$(( ${#title} + 4 ))
+	if [ $n -gt $width -a $n -gt $min_width ]; then
+		# Add 16.6% width for Xdialog(1)
+		[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 ))
+
+		if [ $n -lt $max_width ]; then
+			width=$n
+		else
+			width=$max_width
+		fi
+	fi
+
+	#
+	# For Xdialog(1), bump width for long backtitles (which appear within
+	# the window; don't exceed maximum width).
+	#
+	if [ "$USE_XDIALOG" ]; then
+		n=$(( ${#btitle} + 4 ))
+		n=$(( $n + $n / 6 ))
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	#
+	# Bump width for long prompts (if not already at maximum width).
+	#
+	if [ $width -lt $max_width ]; then
+		n=$( echo "$prompt" | f_longest_line_length )
+		n=$(( $n + 4 ))
+
+		# Add 16.6% width for Xdialog(1)
+		[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 ))
+
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	#
+	# Bump width for long hlines (if not already at maximum width).
+	# NOTE: Though Xdialog(1) supports `--hline', it's not currently used.
+	#
+	if [ ! "$USE_XDIALOG" ]; then
+		if [ $width -lt $max_width ]; then
+			n=$(( ${#hline} + 10 ))
+			if [ $n -gt $width -a $n -gt $min_width ]; then
+				if [ $n -lt $max_width ]; then
+					width=$n
+				else
+					width=$max_width
+				fi
+			fi
+		fi
+	fi
+
+	#
+	# Set height based on number of rows in prompt
+	#
+	height=$( echo "$prompt" | f_number_of_lines )
+	height=$(( $height + 2 ))
+
+	#
+	# For Xdialog(1) bump height if backtitle is enabled (displayed in the
+	# X11 window with a separator line between the backtitle and msg text)
+	#
+	if [ "$USE_XDIALOG" -a "$btitle" ]; then
+		n=$( echo "$btitle" | f_number_of_lines )
+		height=$(( $height + $n + 2 ))
+	fi
+	
+	# Make sure height is less than maximum screen size
+	[ $height -le $max_height ] || height=$max_height
+
+	# Return both
+	echo "$height $width"
+}
+
+# f_dialog_buttonbox_size $title $backtitle $prompt [$hline]
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--msgbox' and `--yesno' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, and [optionally] hline returning
+# the optimal width and height for the box (not exceeding the actual terminal
+# width or height).
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+# Output is in the format of "height width".
+#
+f_dialog_buttonbox_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4"
+	local size="$( f_dialog_infobox_size \
+	               		"$title" "$btitle" "$prompt" "$hline" )"
+	local height="${size%%[$IFS]*}"
+	local width="${size##*[$IFS]}"
+
+	# Add height to accomodate the buttons
+	height=$(( $height + 2 ))
+
+	# Adjust for clipping with Xdialog(1) on Linux/GTK2
+	[ "$USE_XDIALOG" ] && height=$(( $height + 3 ))
+
+	#
+	# Enforce maximum height regardless
+	#
+	local max_size
+	if [ "$USE_XDIALOG" ]; then
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		max_size=$( stty size ) # usually "24 80"
+	fi
+	local max_height="${max_size%%[$IFS]*}"
+	[ $height -le $max_height ] || height=$max_height
+
+	# Return both
+	echo "$height $width"
+}
+
+# f_dialog_inputbox_size $title $backtitle $prompt $init [$hline]
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--inputbox' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, initial text, and [optionally]
+# hline returning the optimal width and height for the box (not exceeding the
+# actual terminal width and height).
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+# Output is in the format of "height width".
+#
+f_dialog_inputbox_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" init="$4" hline="$5" n
+	local size="$( f_dialog_buttonbox_size \
+	               		"$title" "$btitle" "$prompt" "$hline" )"
+	local height="${size%%[$IFS]*}"
+	local width="${size##*[$IFS]}"
+
+	local min_width max_size
+	if [ "$USE_XDIALOG" ]; then
+		min_width=35
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_width=24
+		max_size=$( stty size ) # usually "24 80"
+	fi
+	local max_height="${max_size%%[$IFS]*}"
+	local max_width="${max_size##*[$IFS]}"
+
+	#
+	# Add height to accomodate the input box
+	#
+	[ ! "$USE_XDIALOG" ] && height=$(( $height + 3 ))
+	[ $height -le $max_height ] || height=$max_height
+
+	#
+	# Bump width for initial text (if not already at maximum width).
+	# NOTE: Something neither dialog(1)/Xdialog(1) do, but worth it!
+	#
+	if [ $width -lt $max_width ]; then
+		n=$(( ${#init} + 7 ))
+
+		# Add 16.6% width for Xdialog(1)
+		[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 ))
+
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	# Return both
+	echo "$height $width"
+}
+
+# f_xdialog_2inputsbox_size $title $backtitle $prompt \
+#                           $label1 $init1 $label2 $init2
+#
+# Xdialog(1) does not perform auto-sizing of the width and height of
+# `--2inputsbox' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, label for the first field, initial
+# text for said field, label for the second field, and initial text for said
+# field returning the optimal width and height for the box (not exceeding the
+# actual terminal width and height).
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# Xdialog(1).
+#
+# Output is in the format of "height width".
+#
+f_xdialog_2inputsbox_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3"
+	local label1="$4" init1="$5" label2="$6" init2="$7" n
+	local size="$( f_dialog_inputbox_size \
+	               		"$title" "$btitle" "$prompt" "$init1" )"
+	local height="${size%%[$IFS]*}"
+	local width="${size##*[$IFS]}"
+
+	local min_width=35
+	local max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	local max_height="${max_size%%[$IFS]*}"
+	local max_width="${max_size##*[$IFS]}"
+
+	# Add height for first label
+	height=$(( $height + 2 ))
+
+	#
+	# Bump width for first label text (if not already at maximum width).
+	#
+	if [ $width -lt $max_width ]; then
+		n=$(( ${#label1} + 7 ))
+
+		# Add 16.6% width for Xdialog(1)
+		n=$(( $n + $n / 6 ))
+
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	# Add height for second label
+	height=$(( $height + 2 ))
+
+	#
+	# Bump width for second label text (if not already at maximum width).
+	#
+	if [ $width -lt $max_width ]; then
+		n=$(( ${#label2} + 7 ))
+
+		# Add 16.6% width for Xdialog(1)
+		n=$(( $n + $n / 6 ))
+
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	# Add height for a second inputbox
+	height=$(( $height + 2 ))
+
+	#
+	# Bump width for second initial text (if not already at maximum width).
+	# NOTE: Something neither dialog(1)/Xdialog(1) do, but worth it!
+	#
+	if [ $width -lt $max_width ]; then
+		n=$(( ${#init2} + 7 ))
+
+		# Add 16.6% width for Xdialog(1)
+		n=$(( $n + $n / 6 ))
+
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	# Return both
+	echo "$height $width"
+}
+
+# f_dialog_menu_size $title $backtitle $prompt $hline \
+#                    $tag1 $item1 $tag2 $item2 ...
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--menu' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, hline and list of tag/item pairs,
+# returning the optimal width and height for the menu (not exceeding the actual
+# terminal width or height).
+#
+# Output is in the format of "height width rows".
+#
+f_dialog_menu_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
+	local min_width min_rows max_size
+
+	if [ "$USE_XDIALOG" ]; then
+		min_width=35
+		min_rows=1
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_width=24
+		min_rows=0
+		max_size=$( stty size ) # usually "24 80"
+	fi
+
+	local max_width="${max_size##*[$IFS]}"
+	local max_height="${max_size%%[$IFS]*}"
+	local box_size="$( f_dialog_infobox_size \
+	                   	"$title" "$btitle" "$prompt" "$hline" )"
+	local box_height="${box_size%%[$IFS]*}"
+	local box_width="${box_size##*[$IFS]}"
+	local max_rows=$(( $max_height - 8 ))
+	local height width=$box_width rows=$min_rows
+
+	shift 4 # title/btitle/prompt/hline
+
+	# If there's no prompt, bump the max-rows by 1
+	[ "$prompt" ] || max_rows=$(( $max_rows + 1 ))
+
+	#
+	# The sum total between the longest tag-length and longest item-length
+	# should be used for the menu width (not to exceed terminal width).
+	#
+	# Also, calculate the number of rows (not to exceed terminal height).
+	#
+	local longest_tag=0 longest_item=0
+	while [ $# -ge 2 ]; do
+		local tag="$1" item="$2"
+		shift 2 # tag/item
+
+		[ ${#tag} -gt $longest_tag ] && longest_tag=${#tag}
+		[ ${#item} -gt $longest_item ] && longest_item=${#item}
+		[ $rows -lt $max_rows ] && rows=$(( $rows + 1 ))
+	done
+
+	# Update width
+	n=$(( $longest_tag + $longest_item + 10 ))
+	[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1)
+	if [ $n -gt $width -a $n -gt $min_width ]; then
+		if [ $n -lt $max_width ]; then
+			width=$n
+		else
+			width=$max_width
+		fi
+	fi
+
+	# Fix rows and set height
+	[ $rows -gt 0 ] || rows=1
+	if [ "$USE_XDIALOG" ]; then
+		height=$(( $rows + $box_height + 7 ))
+	else
+		height=$(( $rows + $box_height + 4 ))
+	fi
+	[ $height -le $max_height ] || height=$max_height
+
+	# Return all three
+	echo "$height $width $rows"
+}
+
+# f_dialog_menu_with_help_size $title $backtitle $prompt $hline \
+#                              $tag1 $item1 $help1 $tag2 $item2 $help2 ...
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--menu' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, hline and list of tag/item/help
+# triplets, returning the optimal width and height for the menu (not exceeding
+# the actual terminal width or height).
+#
+# Output is in the format of "height width rows".
+#
+f_dialog_menu_with_help_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
+	local min_width min_rows max_size
+
+	if [ "$USE_XDIALOG" ]; then
+		min_width=35
+		min_rows=1
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_width=24
+		min_rows=0
+		max_size=$( stty size ) # usually "24 80"
+	fi
+
+	local max_width="${max_size##*[$IFS]}"
+	local max_height="${max_size%%[$IFS]*}"
+	local box_size="$( f_dialog_infobox_size \
+	                   	"$title" "$btitle" "$prompt" "$hline" )"
+	local box_height="${box_size%%[$IFS]*}"
+	local box_width="${box_size##*[$IFS]}"
+	local max_rows=$(( $max_height - 8 ))
+	local height width=$box_width rows=$min_rows
+
+	shift 4 # title/btitle/prompt/hline
+
+	# If there's no prompt, bump the max-rows by 1
+	[ "$prompt" ] || max_rows=$(( $max_rows + 1 ))
+
+	#
+	# The sum total between the longest tag-length and longest item-length
+	# should be used for the menu width (not to exceed terminal width).
+	#
+	# Also, calculate the number of rows (not to exceed terminal height).
+	#
+	# Also, calculate the longest help while we're here. This will be used
+	# to influence the width of the menu if (and only-if) using Xdialog(1).
+	#
+	local longest_tag=0 longest_item=0 longest_help=0
+	while [ $# -ge 3 ]; do
+		local tag="$1" item="$2" help="$3"
+		shift 3 # tag/item/help
+
+		[ ${#tag} -gt $longest_tag ] && longest_tag=${#tag}
+		[ ${#item} -gt $longest_item ] && longest_item=${#item}
+		[ ${#help} -gt $longest_help ] && longest_help=${#help}
+		[ $rows -lt $max_rows ] && rows=$(( $rows + 1 ))
+	done
+
+	# Update width
+	n=$(( $longest_tag + $longest_item + 10 ))
+	[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1)
+	if [ $n -gt $width -a $n -gt $min_width ]; then
+		if [ $n -lt $max_width ]; then
+			width=$n
+		else
+			width=$max_width
+		fi
+	fi
+
+	# Update width for help text if using Xdialog(1)
+	if [ "$USE_XDIALOG" ]; then
+		n=$(( $longest_help + 10 ))
+		n=$(( $n + $n / 6 )) # +16.6%
+		if [ $n -gt $width -a $n -gt $min_width ]; then
+			if [ $n -lt $max_width ]; then
+				width=$n
+			else
+				width=$max_width
+			fi
+		fi
+	fi
+
+	# Fix rows and set height
+	[ $rows -gt 0 ] || rows=1
+	if [ "$USE_XDIALOG" ]; then
+		height=$(( $rows + $box_height + 8 ))
+	else
+		height=$(( $rows + $box_height + 4 ))
+	fi
+	[ $height -le $max_height ] || height=$max_height
+
+	# Return all three
+	echo "$height $width $rows"
+}
+
+# f_dialog_radiolist_size $title $backtitle $prompt $hline \
+#                         $tag1 $item1 $status1 $tag2 $item2 $status2 ...
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--radiolist' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, hline and list of tag/item/status
+# triplets, returning the optimal width and height for the radiolist (not
+# exceeding the actual terminal width or height).
+#
+# Output is in the format of "height width rows".
+#
+f_dialog_radiolist_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4" n=0
+	local min_width min_rows max_size
+
+	if [ "$USE_XDIALOG" ]; then
+		min_width=35
+		min_rows=1
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_width=24
+		min_rows=0
+		max_size=$( stty size ) # usually "24 80"
+	fi
+
+	local max_width="${max_size##*[$IFS]}"
+	local max_height="${max_size%%[$IFS]*}"
+	local box_size="$( f_dialog_infobox_size \
+	                   	"$title" "$btitle" "$prompt" "$hline" )"
+	local box_height="${box_size%%[$IFS]*}"
+	local box_width="${box_size##*[$IFS]}"
+	local max_rows=$(( $max_height - 8 ))
+	local height width=$box_width rows=$min_rows
+
+	shift 4 # title/btitle/prompt/hline
+
+	#
+	# The sum total between the longest tag-length, longest item-length,
+	# and radio-button width should be used for the menu width (not to
+	# exceed terminal width).
+	#
+	# Also, calculate the number of rows (not to exceed terminal height).
+	#
+	local longest_tag=0 longest_item=0
+	while [ $# -ge 2 ]; do
+		local tag="$1" item="$2" help="$3"
+		shift 3 # tag/item/status
+
+		[ ${#tag} -gt $longest_tag ] && longest_tag=${#tag}
+		[ ${#item} -gt $longest_item ] && longest_item=${#item}
+		[ $rows -lt $max_rows ] && rows=$(( $rows + 1 ))
+	done
+
+	# Update width
+	n=$(( $longest_tag + $longest_item + 13 ))
+	[ "$USE_XDIALOG" ] && n=$(( $n + $n / 6 )) # Add 16.6% for Xdialog(1)
+	if [ $n -gt $width -a $n -gt $min_width ]; then
+		if [ $n -lt $max_width ]; then
+			width=$n
+		else
+			width=$max_width
+		fi
+	fi
+
+	# Fix rows and set height
+	[ $rows -gt 0 ] || rows=1
+	if [ "$USE_XDIALOG" ]; then
+		height=$(( $rows + $box_height + 7 ))
+	else
+		height=$(( $rows + $box_height + 4 ))
+	fi
+	[ $height -le $max_height ] || height=$max_height
+
+	# Return all three
+	echo "$height $width $rows"
+}
+
+# f_dialog_calendar_size $title $backtitle $prompt [$hline]
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--calendar' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, and [optionally] hline returning
+# the optimal width and height for the box (not exceeding the actual terminal
+# width and height).
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+# Output is in the format of "height width".
+#
+f_dialog_calendar_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4" n
+	local size="$( f_dialog_infobox_size \
+	               		"$title" "$btitle" "$prompt" "$hline" )"
+	local height="${size%%[$IFS]*}"
+	local width="${size##*[$IFS]}"
+
+	local min_width min_height max_size
+	if [ "$USE_XDIALOG" ]; then
+		min_height=15
+		min_width=55
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_height=0
+		min_width=40
+		max_size=$( stty size ) # usually "24 80"
+	fi
+	local max_height="${max_size%%[$IFS]*}"
+	local max_width="${max_size##*[$IFS]}"
+
+	#
+	# Enforce the minimum width for displaying the calendar
+	#
+	[ $width -ge $min_width ] || width=$min_width
+
+	#
+	# When using dialog(1), the calendar box is unique from other dialog(1)
+	# boxes in-that the height passed should not accomodate the 15-lines
+	# required to display the calendar. This does not apply to Xdialog(1).
+	#
+	# When using Xdialog(1), the height must accomodate the 15-lines
+	# required to display the calendar.
+	#
+	# NOTE: Also under dialog(1), because we can't predict whether the user
+	# has disabled shadow's in their `$HOME/.dialogrc' file, we'll subtract
+	# 16 rather than 15. This does not apply to Xdialog(1).
+	#
+	max_height=$(( $max_height - 16 ))
+	height=$( echo "$prompt" | f_number_of_lines )
+	if [ "$USE_XDIALOG" ]; then
+		# Add height to accomodate for the embedded calendar widget
+		height=$(( $height + $min_height - 1 ))
+
+		# Also, bump height if backtitle is enabled
+		if [ "$btitle" ]; then
+			local n="$( echo "$btitle" | f_number_of_lines )"
+			height=$(( $height + $n + 2 ))
+		fi
+	else
+		[ "$prompt" ] && height=$(( $height + 1 ))
+	fi
+	[ $height -le $max_height ] || height=$max_height
+
+	#
+	# The calendar box refuses to display if too large.
+	#
+	max_width=$(( $max_width - 2 ))
+	[ $width -le $max_width ] || width=$max_width
+
+	# Return both
+	echo "$height $width"
+}
+
+# f_dialog_timebox_size $title $backtitle $prompt [$hline]
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--timebox' boxes sensibly.
+#
+# This function helps solve this issue by taking as arguments (in order of
+# appearance) the title, backtitle, prompt, and [optionally] hline returning
+# the optimal width and height for the box (not exceeding the actual terminal
+# width and height).
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+# Output is in the format of "height width".
+#
+f_dialog_timebox_size()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local title="$1" btitle="$2" prompt="$3" hline="$4" n
+	local size="$( f_dialog_infobox_size \
+	               		"$title" "$btitle" "$prompt" "$hline" )"
+	local height="${size%%[$IFS]*}"
+	local width="${size##*[$IFS]}"
+
+	local min_width min_height max_size
+	if [ "$USE_XDIALOG" ]; then
+		min_width=40
+		max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+	else
+		min_height=0
+		min_width=20
+		max_size=$( stty size ) # usually "24 80"
+	fi
+	local max_height="${max_size%%[$IFS]*}"
+	local max_width="${max_size##*[$IFS]}"
+
+	#
+	# Enforce the minimum width for displaying the timebox
+	#
+	[ $width -ge $min_width ] || width=$min_width
+
+	#
+	# When using dialog(1), the timebox box is unique from other dialog(1)
+	# boxes in-that the height passed should not accomodate the 6-lines
+	# required to display the timebox. This does not apply to Xdialog(1).
+	#
+	# When using Xdialog(1), the height seems to have no effect. All values
+	# provide the same results.
+	#
+	# NOTE: Also under dialog(1), because we can't predict whether the user
+	# has disabled shadow's in their `$HOME/.dialogrc' file, we'll subtract
+	# 7 rather than 6. This does not apply to Xdialog(1).
+	#
+	if [ "$USE_XDIALOG" ]; then
+		height=0 # Autosize; all values produce same results
+	else
+		max_height=$(( $max_height - 7 ))
+		height=$( echo "$prompt" | f_number_of_lines )
+		height=$(( $height + 1 ))
+		[ $height -le $max_height ] || height=$max_height
+		[ "$prompt" ] && height=$(( $height + 1 ))
+	fi
+
+	#
+	# The timebox box refuses to display if too large.
+	#
+	max_width=$(( $max_width - 2 ))
+	[ $width -le $max_width ] || width=$max_width
+
+	# Return both
+	echo "$height $width"
+}
+
+############################################################ CLEAR FUNCTIONS
+
+# f_dialog_clear
+#
+# Clears any/all previous dialog(1) displays.
+#
+f_dialog_clear()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	$DIALOG --clear
+}
+
+############################################################ INFO FUNCTIONS
+
+# f_dialog_info $info_text ...
+#
+# Throw up a dialog(1) infobox. The infobox remains until another dialog is
+# displayed or `dialog --clear' (or dialog_clear) is called.
+#
+f_dialog_info()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local info_text="$*"
+	local size="$( f_dialog_infobox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$info_text"        )"
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		${USE_XDIALOG:+--ignore-eof}       \
+		${USE_XDIALOG:+--no-buttons}       \
+		--infobox \"\$info_text\" $size
+}
+
+# f_xdialog_info $info_text ...
+#
+# Throw up an Xdialog(1) infobox and do not dismiss it until stdin produces
+# EOF. This implies that you must execute this either as an rvalue to a pipe,
+# lvalue to indirection or in a sub-shell that provides data on stdin.
+#
+f_xdialog_info()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local info_text="$*"
+	local size="$( f_dialog_infobox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$info_text"        )"
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--no-close --no-buttons            \
+		--infobox \"\$info_text\" $size    \
+		-1 # timeout of -1 means abort when EOF on stdin
+}
+
+############################################################ MSGBOX FUNCTIONS
+
+# f_dialog_msgbox $msg_text ...
+#
+# Throw up a dialog(1) msgbox. The msgbox remains until the user presses ENTER
+# or ESC, acknowledging the modal dialog.
+#
+# If the user presses ENTER, the exit status is zero (success), otherwise if
+# the user presses ESC the exit status is 255.
+#
+f_dialog_msgbox()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local msg_text="$*"
+	local size="$( f_dialog_buttonbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg_text"         )"
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--ok-label \"\$msg_ok\"            \
+		--msgbox \"\$msg_text\" $size
+}
+
+############################################################ YESNO FUNCTIONS
+
+# f_dialog_yesno $msg_text ...
+#
+# Display a dialog(1) Yes/No prompt to allow the user to make some decision.
+# The yesno prompt remains until the user presses ENTER or ESC, acknowledging
+# the modal dialog.
+#
+# If the user chooses YES the exit status is zero, or chooses NO the exit
+# status is one, or presses ESC the exit status is 255.
+#
+f_dialog_yesno()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local msg_text="$*"
+	local hline="$hline_arrows_tab_enter"
+	local size="$( f_dialog_buttonbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg_text"         \
+	               		"$hline"            )"
+
+	if [ "$USE_XDIALOG" ]; then
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_yes\"           \
+			--cancel-label \"\$msg_no\"        \
+			--yesno \"\$msg_text\" $size
+	else
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--yes-label \"\$msg_yes\"          \
+			--no-label \"\$msg_no\"            \
+			--yesno \"\$msg_text\" $size
+	fi
+}
+
+# f_dialog_noyes $msg_text ...
+#
+# Display a dialog(1) No/Yes prompt to allow the user to make some decision.
+# The noyes prompt remains until the user presses ENTER or ESC, acknowledging
+# the modal dialog.
+#
+# If the user chooses YES the exit status is zero, or chooses NO the exit
+# status is one, or presses ESC the exit status is 255.
+#
+# NOTE: This is just like the f_dialog_yesno function except "No" is default.
+#
+f_dialog_noyes()
+{
+	[ "$DIALOG_SELF_INITIALIZE" ] && f_dialog_init
+
+	local msg_text="$*"
+	local hline="$hline_arrows_tab_enter"
+	local size="$( f_dialog_buttonbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg_text"         \
+	               		"$hline"            )"
+
+	if [ "$USE_XDIALOG" ]; then
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--default-no                       \
+			--ok-label \"\$msg_yes\"           \
+			--cancel-label \"\$msg_no\"        \
+			--yesno \"\$msg_text\" $size
+	else
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--defaultno                        \
+			--yes-label \"\$msg_yes\"          \
+			--no-label \"\$msg_no\"            \
+			--yesno \"\$msg_text\" $size
+	fi
+}
+
+############################################################ INPUT FUNCTIONS
+
+# f_dialog_inputstr
+#
+# Obtain the inputstr entered by the user from the most recently displayed
+# dialog(1) inputbox and clean up any temporary files.
+#
+f_dialog_inputstr()
+{
+	local tmpfile="$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+	[ -f "$tmpfile" ] || return $FAILURE
+
+	# Skip warnings and trim leading/trailing whitespace from user input
+	awk '
+		BEGIN { found = 0 }
+		{
+			if ( ! found )
+			{
+				if ( $0 ~ /^$/ ) next
+				if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next
+				found = 1
+			}
+			sub(/^[[:space:]]*/, "")
+			sub(/[[:space:]]*$/, "")
+			print
+		}
+	' "$tmpfile" 2> /dev/null
+	f_quietly rm -f "$tmpfile"
+
+	return $SUCCESS
+}
+
+############################################################ MENU FUNCTIONS
+
+# f_dialog_menutag
+#
+# Obtain the menutag chosen by the user from the most recently displayed
+# dialog(1) menu and clean up any temporary files.
+#
+f_dialog_menutag()
+{
+	local tmpfile="$DIALOG_TMPDIR/dialog.menu.$$"
+
+	[ -f "$tmpfile" ] || return $FAILURE
+
+	awk '
+		BEGIN { found = 0 }
+		{
+			if ( found ) # ... just spew
+			{
+				print
+				next
+			}
+			if ( $0 ~ /^$/ ) next
+			if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next
+			found = 1
+			print
+		}
+	' "$tmpfile" 2> /dev/null
+	f_quietly rm -f "$tmpfile"
+
+	return $SUCCESS
+}
+
+# f_dialog_menutag2item $tag_chosen $tag1 $item1 $tag2 $item2 ...
+#
+# To use the `--menu' option of dialog(1) you must pass an ordered list of
+# tag/item pairs on the command-line. When the user selects a menu option the
+# tag for that item is printed to stderr.
+#
+# This function allows you to dereference the tag chosen by the user back into
+# the item associated with said tag.
+#
+# Pass the tag chosen by the user as the first argument, followed by the
+# ordered list of tag/item pairs (HINT: use the same tag/item list as was
+# passed to dialog(1) for consistency).
+#
+# If the tag cannot be found, NULL is returned.
+#
+f_dialog_menutag2item()
+{
+	local tag="$1" tagn item
+	shift 1 # tag
+
+	while [ $# -gt 0 ]; do
+		tagn="$1"
+		item="$2"
+		shift 2 # tagn/item
+
+		if [ "$tag" = "$tagn" ]; then
+			echo "$item"
+			return $SUCCESS
+		fi
+	done
+	return $FAILURE
+}
+
+# f_dialog_menutag2item_with_help $tag_chosen $tag1 $item1 $help1 \
+#                                             $tag2 $item2 $help2 ...
+#
+# To use the `--menu' option of dialog(1) with the `--item-help' option, you
+# must pass an ordered list of tag/item/help triplets on the command-line. When
+# the user selects a menu option the tag for that item is printed to stderr.
+#
+# This function allows you to dereference the tag chosen by the user back into
+# the item associated with said tag (help is discarded/ignored).
+#
+# Pass the tag chosen by the user as the first argument, followed by the
+# ordered list of tag/item/help triplets (HINT: use the same tag/item/help list
+# as was passed to dialog(1) for consistency).
+#
+# If the tag cannot be found, NULL is returned.
+#
+f_dialog_menutag2item_with_help()
+{
+	local tag="$1" tagn item
+	shift 1 # tag
+
+	while [ $# -gt 0 ]; do
+		tagn="$1"
+		item="$2"
+		shift 3 # tagn/item/help
+
+		if [ "$tag" = "$tagn" ]; then
+			echo "$item"
+			return $SUCCESS
+		fi
+	done
+	return $FAILURE
+}
+
+# f_dialog_menutag2index $tag_chosen $tag1 $item1 $tag2 $item2 ...
+#
+# To use the `--menu' option of dialog(1) you must pass an ordered list of
+# tag/item pairs on the command-line. When the user selects a menu option the
+# tag for that item is printed to stderr.
+#
+# This function allows you to dereference the tag chosen by the user back into
+# the index associated with said tag. The index is the one-based tag/item pair
+# array position within the ordered list of tag/item pairs passed to dialog(1).
+#
+# Pass the tag chosen by the user as the first argument, followed by the
+# ordered list of tag/item pairs (HINT: use the same tag/item list as was
+# passed to dialog(1) for consistency).
+#
+# If the tag cannot be found, NULL is returned.
+#
+f_dialog_menutag2index()
+{
+	local tag="$1" tagn n=1
+	shift 1 # tag
+
+	while [ $# -gt 0 ]; do
+		tagn="$1"
+		shift 2 # tagn/item
+
+		if [ "$tag" = "$tagn" ]; then
+			echo $n
+			return $SUCCESS
+		fi
+		n=$(( $n + 1 ))
+	done
+	return $FAILURE
+}
+
+# f_dialog_menutag2index_with_help $tag_chosen $tag1 $item1 $help1 \
+#                                              $tag2 $item2 $help2 ...
+#
+# To use the `--menu' option of dialog(1) with the `--item-help' option, you
+# must pass an ordered list of tag/item/help triplets on the command-line. When
+# the user selects a menu option the tag for that item is printed to stderr.
+#
+# This function allows you to dereference the tag chosen by the user back into
+# the index associated with said tag. The index is the one-based tag/item/help
+# triplet array position within the ordered list of tag/item/help triplets
+# passed to dialog(1).
+#
+# Pass the tag chosen by the user as the first argument, followed by the
+# ordered list of tag/item/help triplets (HINT: use the same tag/item/help list
+# as was passed to dialog(1) for consistency).
+#
+# If the tag cannot be found, NULL is returned.
+#
+f_dialog_menutag2index_with_help()
+{
+	local tag="$1" tagn n=1
+	shift 1 # tag
+
+	while [ $# -gt 0 ]; do
+		tagn="$1"
+		shift 3 # tagn/item/help
+
+		if [ "$tag" = "$tagn" ]; then
+			echo $n
+			return $SUCCESS
+		fi
+		n=$(( $n + 1 ))
+	done
+	return $FAILURE
+}
+
+############################################################ INIT FUNCTIONS
+
+# f_dialog_init
+#
+# Initialize (or re-initialize) the dialog module after setting/changing any
+# of the following environment variables:
+#
+# 	USE_XDIALOG   Either NULL or Non-NULL. If given a value will indicate
+# 	              that Xdialog(1) should be used instead of dialog(1).
+#
+# 	SECURE        Either NULL or Non-NULL. If given a value will indicate
+# 	              that (while running as root) sudo(8) authentication is
+# 	              required to proceed.
+#
+f_dialog_init()
+{
+	DIALOG_SELF_INITIALIZE=
+
+	#
+	# Process stored command-line arguments
+	#
+	SECURE=$( set -- "$ARGV"
+		while getopts S flag > /dev/null; do
+			case "$flag" in
+			S) echo 1;;
+			\?) continue;;
+			esac
+		done
+	)
+	USE_XDIALOG=$( set -- "$ARGV"
+		while getopts SX flag > /dev/null; do
+			case "$flag" in
+			S|X) echo 1;;
+			\?) continue;;
+			esac
+		done
+	)
+
+	#
+	# Process `-X' command-line option
+	#
+	[ "$USE_XDIALOG" ] && DIALOG=Xdialog
+
+	#
+	# Sanity check, or die gracefully
+	#
+	if ! f_have $DIALOG; then
+		unset USE_XDIALOG
+		failed_dialog="$DIALOG"
+		DIALOG=dialog
+		f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$failed_dialog"
+	fi
+
+	#
+	# If we're already running as root but we got there by way of sudo(8)
+	# and we have X11, we should merge the xauth(1) credentials from our
+	# original user.
+	#
+	if [ "$USE_XDIALOG" ] &&
+	   [ "$( id -u )" = "0" ] &&
+	   [ "$SUDO_USER" -a "$DISPLAY" ]
+	then
+		if ! f_have xauth; then
+			# Die gracefully, as we [likely] can't use Xdialog(1)
+			unset USE_XDIALOG
+			DIALOG=dialog
+			f_die 1 "$msg_no_such_file_or_directory" "$pgm" "xauth"
+		fi
+		HOSTNAME=$(hostname)
+		displaynum="${DISPLAY#*:}"
+		eval xauth -if \~$SUDO_USER/.Xauthority extract - \
+			\"\$HOSTNAME/unix:\$displaynum\" \
+			\"\$HOSTNAME:\$displaynum\" | sudo sh -c 'xauth -ivf \
+			~root/.Xauthority merge - > /dev/null 2>&1'
+	fi
+
+	#
+	# Probe Xdialog(1) for maximum height/width constraints, or die
+	# gracefully
+	#
+	if [ "$USE_XDIALOG" ]; then
+		if ! maxsize=$( LANG= LC_ALL= $DIALOG --print-maxsize 2>&1 )
+		then
+			# Xdialog(1) failed, fall back to dialog(1)
+			unset USE_XDIALOG
+			size=$( f_dialog_buttonbox_size "$DIALOG_TITLE" \
+			                                "$DIALOG_BACKTITLE" \
+			                                "$maxsize" "" )
+			eval dialog \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--ok-label \"\$msg_ok\"            \
+				--msgbox \"\$maxsize\" $size
+			exit $FAILURE
+		fi
+
+		XDIALOG_MAXSIZE=$(
+			set -- ${maxsize##*:}
+
+			height=${1%,}
+			width=$2
+
+			echo $height $width
+		)
+		unset maxsize
+	fi
+
+	#
+	# If using Xdialog(1), swap DIALOG_TITLE with DIALOG_BACKTITLE.
+	# The reason for this is because many dialog(1) applications use
+	# --backtitle for the program name (which is better suited as
+	# --title with Xdialog(1)).
+	#
+	if [ "$USE_XDIALOG" ]; then
+		_DIALOG_TITLE="$DIALOG_TITLE"
+		DIALOG_TITLE="$DIALOG_BACKTITLE"
+		DIALOG_BACKTITLE="$_DIALOG_TITLE"
+		unset _DIALOG_TITLE
+	fi
+}
+
+############################################################ CLEAN-UP FUNCTIONS
+
+# f_clean_up
+#
+# Clean-up routines (run when script exits or is killed).
+#
+f_clean_up()
+{
+	f_quietly rm -f "$DIALOG_TMPDIR"/dialog.*.$$
+}
+
+############################################################ MAIN
+
+#
+# Trap signals so we can recover gracefully
+#
+trap 'f_clean_up' EXIT
+
+fi # ! $_DIALOG_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,56 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+field_username="Username:"
+field_password="Password:"
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_cancel="Cancel"
+msg_cannot_create_permission_denied="%s: cannot create %s: Permission denied"
+msg_directory_not_found="%s: Directory not found."
+msg_exit="Exit"
+msg_exit_bsdconfig="Exit bsdconfig"
+msg_help_text="This menu allows you to configure your system after the installation\nprocess is complete.  At the minimum, you should probably set the root\npassword and the system time zone.\n\nFor extra goodies like bash, emacs, firefox, etc., you should look at the\n'Packages' item in this menu.\n\nFor setting the timezone after the system is installed, use the 'Time\nZone' item in this menu.\n\nFor more information on the overall general system configuration, see the\n/etc/rc.conf and /etc/defaults/rc.conf files. (Note: to inhibit displaying\nof this message, create an empty file: \$HOME/.bsdconfigrc or copy it from\n/usr/share/examples/bsdconfig/bsdconfigrc)"
+msg_main_menu="Main Menu"
+msg_menu_text="If you've already installed FreeBSD, you may use\nthis menu to customize it somewhat to suit your\nparticular configuration.  Most importantly, you\ncan use the Packages utility to load extra '3rd\nparty' software not provided in the base\ndistributions."
+msg_must_be_root_to_execute="%s: must be root to execute"
+msg_nfailed_attempts="%u incorrect password attempts"
+msg_no="No"
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
+msg_no_username="No username provided!"
+msg_not_found="not found"
+msg_ok="OK"
+msg_permission_denied="%s: %s: permission denied"
+msg_please_enter_password="Please enter your password for sudo(8):"
+msg_please_enter_username_password="Please enter a username and password for sudo(8):"
+msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors"
+msg_secure_mode_requires_x11="Secure-mode requires X11 (use \`-X')!"
+msg_secure_mode_requires_root="Secure-mode requires root-access!"
+msg_sorry_try_again="Sorry, try again."
+msg_unknown_user="Unknown user: %s"
+msg_user_disallowed="User disallowed: %s"
+msg_yes="Yes"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/mustberoot.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/mustberoot.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,360 @@
+if [ ! "$_MUSTBEROOT_SUBR" ]; then _MUSTBEROOT_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/include/mustberoot.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ CONFIGURATION
+# NOTE: These are not able to be overridden/inherited for security purposes.
+
+#
+# Number of tries a user gets to enter his/her password before we log the
+# sudo(8) failure and exit.
+#
+PASSWD_TRIES=3
+
+#
+# While in SECURE mode, should authentication as `root' be allowed? Set to
+# non-NULL to enable authentication as `root', otherwise disabled.
+#
+# WARNING: 
+# Unless using a custom sudo(8) configuration, user `root' should not be
+# allowed because no password is required to become `root' when already `root'
+# and therefore, any value entered as password will work.
+#
+SECURE_ALLOW_ROOT=
+
+#
+# While in SECURE mode, should we divulge (through error message) when the
+# requested authentication user does not exist? Set to non-NULL to enable,
+# otherwise a non-existent user is treated like an invalid password.
+#
+SECURE_DIVULGE_UNKNOWN_USER=
+
+############################################################ FUNCTIONS
+
+# f_become_root_via_sudo
+#
+# If not running as root, prompt for sudo(8) credentials to become root.
+# Re-execution of the current program via sudo is automatically handled.
+#
+# The following environment variables effect functionality:
+#
+# 	USE_XDIALOG   Either NULL or Non-NULL. If given a value will indicate
+# 	              that Xdialog(1) should be used instead of dialog(1).
+#
+f_become_root_via_sudo()
+{
+	local msg hline size
+
+	[ "$( id -u )" = "0" ] && return $SUCCESS
+
+	f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
+
+	#
+	# Check sudo(8) access before prompting for password.
+	#
+	:| sudo -S -v 2> /dev/null
+	if [ $? -ne $SUCCESS ]; then
+		#
+		# sudo(8) access denied. Prompt for their password.
+		#
+		msg="$msg_please_enter_password"
+		hline="$hline_alnum_punc_tab_enter"
+		size=$( f_dialog_inputbox_size \
+		        	"$DIALOG_TITLE"     \
+		        	"$DIALOG_BACKTITLE" \
+		        	"$msg"              \
+		        	"$hline"            )
+
+		#
+		# Continue prompting until they either Cancel, succeed
+		# or exceed the number of allowed failures.
+		#
+		local password nfailures=0 retval
+		while [ $nfailures -lt $PASSWD_TRIES ]; do
+			if [ "$USE_XDIALOG" ]; then
+				password=$( $DIALOG \
+					--title "$DIALOG_TITLE"            \
+					--backtitle "$DIALOG_BACKTITLE"    \
+					--hline "$hline"                   \
+					--ok-label "$msg_ok"               \
+					--cancel-label "$msg_cancel"       \
+					--password --inputbox "$msg" $size \
+					2>&1 > /dev/null )
+				retval=$?
+
+				# Catch X11-related errors
+				[ $retval -eq 255 ] &&
+					f_die $retval "$password"
+			else
+				$DIALOG \
+					--title "$DIALOG_TITLE"         \
+					--backtitle "$DIALOG_BACKTITLE" \
+					--hline "$hline"                \
+					--ok-label "$msg_ok"            \
+					--cancel-label "$msg_cancel"    \
+					--insecure                      \
+					--passwordbox "$msg" $size      \
+					2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+				retval=$?
+				password=$( f_dialog_inputstr )
+			fi
+
+			# Exit if the user cancelled.
+			[ $retval -eq $SUCCESS ] || exit $retval
+
+			#
+			# Validate sudo(8) credentials
+			#
+			sudo -S -v 2> /dev/null <<-EOF
+			$password
+			EOF
+			retval=$?
+			unset password # scrub memory
+			if [ $retval -eq $SUCCESS ]; then
+				# Access granted...
+				break
+			else
+				# Access denied...
+				nfailures=$(( $nfailures + 1 ))
+
+				# introduce a short delay
+				if [ $nfailures -lt $PASSWD_TRIES ]; then
+					f_dialog_info "$msg_sorry_try_again"
+					sleep 1
+				fi
+			fi
+		done
+
+		#
+		# If user exhausted number of allowed password tries, log
+		# the security event and exit immediately.
+		#
+		if [ $nfailures -ge $PASSWD_TRIES ]; then
+			msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
+			logger -p auth.notice -t sudo " " \
+				"$USER : $msg" \
+				"; TTY=$(tty)" \
+				"; PWD=$PWD"   \
+				"; USER=root"  \
+				"; COMMAND=$0"
+			f_die 1 "sudo: $msg"
+		fi
+	fi
+
+	# Use xauth(1) to grant root the ability to use this X11/SSH session
+	if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" -a "$DISPLAY" ]; then
+		f_have xauth || f_die 1 \
+			"$msg_no_such_file_or_directory" "$pgm" "xauth"
+		local HOSTNAME displaynum
+		HOSTNAME=$(hostname)
+		displaynum="${DISPLAY#*:}"
+		xauth -f ~/.Xauthority extract - $HOSTNAME/unix:$displaynum \
+			$HOSTNAME:$displaynum | sudo sh -c 'xauth -ivf \
+			~root/.Xauthority merge - > /dev/null 2>&1'
+	fi
+
+	# Re-execute ourselves with sudo(8)
+	if [ $ARGC -gt 0 ]; then
+		exec sudo "$0" $ARGV
+	else
+		exec sudo "$0"
+	fi
+	exit $? # Never reached unless error
+}
+
+# f_authenticate_some_user
+#
+# Only used if running as root and requires X11 (see USE_XDIALOG below).
+# Prompts the user to enter a username and password to be authenticated via
+# sudo(8) to proceed.
+#
+# The following environment variables effect functionality:
+#
+# 	USE_XDIALOG   Either NULL or Non-NULL. If given a value will indicate
+# 	              that Xdialog(1) should be used instead of dialog(1).
+#
+f_authenticate_some_user()
+{
+	local msg hline size width height
+
+	f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
+
+	#
+	# Secure-mode has been requested.
+	#
+ 
+	[ "$USE_XDIALOG" ] || f_die 1 "$msg_secure_mode_requires_x11"
+	[ "$(id -u)" = "0" ] || f_die 1 "$msg_secure_mode_requires_root"
+
+	#
+	# Prompt for sudo(8) credentials.
+	#
+
+	msg="$msg_please_enter_username_password"
+	hline="$hline_alnum_punc_tab_enter"
+	size=$( f_xdialog_2inputsbox_size \
+	        	"$DIALOG_TITLE"      \
+	        	"$DIALOG_BACKTITLE"  \
+	        	"$msg"               \
+	        	"$field_username" "" \
+	        	"$field_password" "" )
+	width="${size##*[$IFS]}"
+	height="${size%%[$IFS]*}"
+	height=$(( $height + 2 )) # Add height for --password
+
+	#
+	# Continue prompting until they either Cancel, succeed or exceed the
+	# number of allowed failures.
+	#
+	local user_pass nfailures=0 retval
+	while [ $nfailures -lt $PASSWD_TRIES ]; do
+		user_pass=$( $DIALOG \
+			--title "$DIALOG_TITLE"         \
+			--backtitle "$DIALOG_BACKTITLE" \
+			--hline "$hline"                \
+			--ok-label "$msg_ok"            \
+			--cancel-label "$msg_cancel"    \
+			--password --2inputsbox "$msg"  \
+			$height $width                  \
+			"$field_username" ""            \
+			"$field_password" ""            \
+			2>&1 > /dev/null )
+		retval=$?
+
+		# Catch X11-related errors
+		[ $retval -eq 255 ] && f_die $retval "$user_pass"
+
+		# Exit if the user cancelled.
+		[ $retval -eq $SUCCESS ] || exit $retval
+
+		#
+		# Make sure the user exists and is non-root
+		#
+		local user password
+		user="${user_pass%%/*}"
+		password="${user_pass#*/}"
+		unset user_pass # scrub memory
+		if [ ! "$user" ]; then
+			nfailures=$(( $nfailures + 1 ))
+			f_dialog_msgbox "$msg_no_username"
+			continue
+		fi
+		if [ ! "$SECURE_ALLOW_ROOT" ]; then
+			case "$user" in
+			root|toor)
+				nfailures=$(( $nfailures + 1 ))
+				f_dialog_msgbox "$( printf \
+					"$msg_user_disallowed" "$user" )"
+				continue
+			esac
+		fi
+		if ! f_quietly id "$user"; then
+			nfailures=$(( $nfailures + 1 ))
+			if [ "$SECURE_DIVULGE_UNKNOWN_USER" ]; then
+				f_dialog_msgbox "$( printf \
+					"$msg_unknown_user" "$user" )"
+			elif [ $nfailures -lt $PASSWD_TRIES ]; then
+				f_dialog_info "$msg_sorry_try_again"
+				sleep 1
+			fi
+			continue
+		fi
+
+		#
+		# Validate sudo(8) credentials for given user
+		#
+		su -m "$user" <<-EOF
+			sh <<EOS
+				sudo -k
+				sudo -S -v 2> /dev/null <<EOP
+				$password
+				EOP
+			EOS
+		EOF
+		retval=$?
+		unset user
+		unset password # scrub memory
+
+		if [ $retval -eq $SUCCESS ]; then
+			# Access granted...
+			break
+		else
+			# Access denied...
+			nfailures=$(( $nfailures + 1 ))
+
+			# introduce a short delay
+			if [ $nfailures -lt $PASSWD_TRIES ]; then
+				f_dialog_info "$msg_sorry_try_again"
+				sleep 1
+			fi
+		fi
+	done
+
+	#
+	# If user exhausted number of allowed password tries, log
+	# the security event and exit immediately.
+	#
+	if [ $nfailures -ge $PASSWD_TRIES ]; then
+		msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
+		logger -p auth.notice -t sudo " " \
+			"${SUDO_USER:-$USER} : $msg" \
+			"; TTY=$(tty)"               \
+			"; PWD=$PWD"                 \
+			"; USER=root"                \
+			"; COMMAND=$0"
+		f_die 1 "sudo: $message"
+	fi
+}
+
+# f_mustberoot_init
+#
+# If not already root, make the switch to root by re-executing ourselves via
+# sudo(8) using user-supplied credentials.
+#
+# The following environment variables effect functionality:
+#
+# 	SECURE        Either NULL or Non-NULL. If given a value will indicate
+# 	              that (while running as root) sudo(8) authentication is
+# 	              required to proceed.
+#
+f_mustberoot_init()
+{
+	if [ "$(id -u)" != "0" -a ! "$SECURE" ]; then
+		f_become_root_via_sudo
+	elif [ "$SECURE" ]; then
+		f_authenticate_some_user
+	fi
+}
+
+fi # ! $_MUSTBEROOT_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/strings.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/strings.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,104 @@
+if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/include/strings.subr 238438 2012-07-14 03:16:57Z dteske $
+
+# f_substr "$string" $start [ $length ]
+#
+# Simple wrapper to awk(1)'s `substr' function.
+#
+f_substr()
+{
+	local string="$1" start="${2:-0}" len="${3:-0}"
+	echo "$string" | awk "{ print substr(\$0, $start, $len) }"
+}
+
+# f_longest_line_length
+#
+# Simple wrapper to an awk(1) script to print the length of the longest line of
+# input (read from stdin). Supports the newline escape-sequence `\n' for
+# splitting a single line into multiple lines.
+#
+f_longest_line_length_awk='
+BEGIN { longest = 0 }
+{
+	if (split($0, lines, /\\n/) > 1)
+	{
+		for (n in lines)
+		{
+			len = length(lines[n])
+			longest = ( len > longest ? len : longest )
+		}
+	}
+	else
+	{
+		len = length($0)
+		longest = ( len > longest ? len : longest )
+	}
+}
+END { print longest }
+'
+f_longest_line_length()
+{
+	awk "$f_longest_line_length_awk"
+}
+
+# f_number_of_lines
+#
+# Simple wrapper to an awk(1) script to print the number of lines read from
+# stdin. Supports newline escape-sequence `\n' for splitting a single line into
+# multiple lines.
+#
+f_number_of_lines_awk='
+BEGIN { num_lines = 0 }
+{
+	num_lines += split($0, unused, /\\n/)
+}
+END { print num_lines }
+'
+f_number_of_lines()
+{
+	awk "$f_number_of_lines_awk"
+}
+
+# f_isinteger $arg
+#
+# Returns true if argument is a positive/negative whole integer.
+#
+f_isinteger()
+{
+	local arg="$1"
+
+	# Prevent division-by-zero
+	[ "$arg" = "0" ] && return $SUCCESS
+
+	# Attempt to perform arithmetic divison (an operation which will exit
+	# with error unless arg is a valid positive/negative whole integer).
+	#
+	( : $((0/$arg)) ) > /dev/null 2>&1
+}
+
+fi # ! $_STRINGS_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/include/sysrc.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/include/sysrc.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,616 @@
+if [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/include/sysrc.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames (inherit values from shell if available)
+#
+: ${RC_DEFAULTS:="/etc/defaults/rc.conf"}
+
+############################################################ GLOBALS
+
+#
+# Global exit status variables
+#
+SUCCESS=0
+FAILURE=1
+
+############################################################ FUNCTIONS
+
+# f_clean_env [ --except $varname ... ]
+#
+# Unset all environment variables in the current scope. An optional list of
+# arguments can be passed, indicating which variables to avoid unsetting; the
+# `--except' is required to enable the exclusion-list as the remainder of
+# positional arguments.
+#
+# Be careful not to call this in a shell that you still expect to perform
+# $PATH expansion in, because this will blow $PATH away. This is best used
+# within a sub-shell block "(...)" or "$(...)" or "`...`".
+#
+f_clean_env()
+{
+	local var arg except=
+
+	#
+	# Should we process an exclusion-list?
+	#
+	if [ "$1" = "--except" ]; then
+		except=1
+		shift 1
+	fi
+
+	#
+	# Loop over a list of variable names from set(1) built-in.
+	#
+	for var in $( set | awk -F= \
+		'/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' \
+		| grep -v '^except$'
+	); do
+		#
+		# In POSIX bourne-shell, attempting to unset(1) OPTIND results
+		# in "unset: Illegal number:" and causes abrupt termination.
+		#
+		[ "$var" = OPTIND ] && continue
+
+		#
+		# Process the exclusion-list?
+		#
+		if [ "$except" ]; then
+			for arg in "$@" ""; do
+				[ "$var" = "$arg" ] && break
+			done
+			[ "$arg" ] && continue
+		fi
+
+		unset "$var"
+	done
+}
+
+# f_sysrc_get $varname
+#
+# Get a system configuration setting from the collection of system-
+# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf
+# and /etc/rc.conf).
+#
+# NOTE: Additional shell parameter-expansion formats are supported. For
+# example, passing an argument of "hostname%%.*" (properly quoted) will
+# return the hostname up to (but not including) the first `.' (see sh(1),
+# "Parameter Expansion" for more information on additional formats).
+#
+f_sysrc_get()
+{
+	# Sanity check
+	[ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE
+
+	# Taint-check variable name
+	case "$1" in
+	[0-9]*)
+		# Don't expand possible positional parameters
+		return $FAILURE;;
+	*)
+		[ "$1" ] || return $FAILURE
+	esac
+
+	( # Execute within sub-shell to protect parent environment
+
+		#
+		# Clear the environment of all variables, preventing the
+		# expansion of normals such as `PS1', `TERM', etc.
+		#
+		f_clean_env --except RC_CONFS RC_DEFAULTS SUCCESS
+
+		. "$RC_DEFAULTS" > /dev/null 2>&1
+
+		unset RC_DEFAULTS
+			# no longer needed
+
+		#
+		# If the query is for `rc_conf_files' then store the value that
+		# we inherited from sourcing RC_DEFAULTS (above) so that we may
+		# conditionally restore this value after source_rc_confs in the
+		# event that RC_CONFS does not customize the value.
+		#
+		if [ "$1" = "rc_conf_files" ]; then
+			_rc_conf_files="$rc_conf_files"
+		fi
+
+		#
+		# If RC_CONFS is defined, set $rc_conf_files to an explicit
+		# value, modifying the default behavior of source_rc_confs().
+		#
+		( : ${RC_CONFS?} ) > /dev/null 2>&1
+		if [ $? -eq ${SUCCESS:-0} ]; then
+			rc_conf_files="$RC_CONFS"
+			_rc_confs_set=1
+		fi
+
+		unset SUCCESS
+			# no longer needed
+
+		source_rc_confs > /dev/null 2>&1
+
+		#
+		# If the query was for `rc_conf_files' AND after calling
+		# source_rc_confs the vaue has not changed, then we should
+		# restore the value to the one inherited from RC_DEFAULTS
+		# before performing the final query (preventing us from
+		# returning what was set via RC_CONFS when the intent was
+		# instead to query the value from the file(s) specified).
+		#
+		if [ "$1" = "rc_conf_files" -a \
+		     "$_rc_confs_set" -a \
+		     "$rc_conf_files" = "$RC_CONFS" \
+		]; then
+			rc_conf_files="$_rc_conf_files"
+			unset _rc_conf_files
+			unset _rc_confs_set
+		fi
+
+		unset RC_CONFS
+			# no longer needed
+
+		#
+		# This must be the last functional line for both the sub-shell
+		# and the function to preserve the return status from formats
+		# such as "${varname?}" and "${varname:?}" (see "Parameter
+		# Expansion" in sh(1) for more information).
+		#
+		eval echo '"${'"$1"'}"' 2> /dev/null
+	)
+}
+
+# f_sysrc_get_default $varname
+#
+# Get a system configuration default setting from the default rc.conf(5) file
+# (or whatever RC_DEFAULTS points at).
+#
+f_sysrc_get_default()
+{
+	# Sanity check
+	[ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE
+
+	# Taint-check variable name
+	case "$1" in
+	[0-9]*)
+		# Don't expand possible positional parameters
+		return $FAILURE;;
+	*)
+		[ "$1" ] || return $FAILURE
+	esac
+
+	( # Execute within sub-shell to protect parent environment
+
+		#
+		# Clear the environment of all variables, preventing the
+		# expansion of normals such as `PS1', `TERM', etc.
+		#
+		f_clean_env --except RC_DEFAULTS
+
+		. "$RC_DEFAULTS" > /dev/null 2>&1
+
+		unset RC_DEFAULTS
+			# no longer needed
+
+		#
+		# This must be the last functional line for both the sub-shell
+		# and the function to preserve the return status from formats
+		# such as "${varname?}" and "${varname:?}" (see "Parameter
+		# Expansion" in sh(1) for more information).
+		#
+		eval echo '"${'"$1"'}"' 2> /dev/null
+	)
+}
+
+# f_sysrc_find $varname
+#
+# Find which file holds the effective last-assignment to a given variable
+# within the rc.conf(5) file(s).
+#
+# If the variable is found in any of the rc.conf(5) files, the function prints
+# the filename it was found in and then returns success. Otherwise output is
+# NULL and the function returns with error status.
+#
+f_sysrc_find()
+{
+	local varname="$1"
+	local regex="^[[:space:]]*$varname="
+	local rc_conf_files="$( f_sysrc_get rc_conf_files )"
+	local conf_files=
+	local file
+
+	# Check parameters
+	[ "$varname" ] || return $FAILURE
+
+	#
+	# If RC_CONFS is defined, set $rc_conf_files to an explicit
+	# value, modifying the default behavior of source_rc_confs().
+	#
+	[ "$RC_CONFS" ] && rc_conf_files="$RC_CONFS"
+
+	#
+	# Reverse the order of files in rc_conf_files (the boot process sources
+	# these in order, so we will search them in reverse-order to find the
+	# last-assignment -- the one that ultimately effects the environment).
+	#
+	for file in $rc_conf_files; do
+		conf_files="$file${conf_files:+ }$conf_files"
+	done
+
+	#
+	# Append the defaults file (since directives in the defaults file
+	# indeed affect the boot process, we'll want to know when a directive
+	# is found there).
+	#
+	conf_files="$conf_files${conf_files:+ }$RC_DEFAULTS"
+
+	#
+	# Find which file matches assignment to the given variable name.
+	#
+	for file in $conf_files; do
+		[ -f "$file" -a -r "$file" ] || continue
+		if grep -Eq "$regex" $file; then
+			echo $file
+			return $SUCCESS
+		fi
+	done
+
+	return $FAILURE # Not found
+}
+
+# f_sysrc_desc $varname
+#
+# Attempts to return the comments associated with varname from the rc.conf(5)
+# defaults file `/etc/defaults/rc.conf' (or whatever RC_DEFAULTS points to).
+#
+# Multi-line comments are joined together. Results are NULL if no description
+# could be found.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_sysrc_desc_awk='
+# Variables that should be defined on the invocation line:
+# 	-v varname="varname"
+#
+BEGIN {
+	regex = "^[[:space:]]*"varname"="
+	found = 0
+	buffer = ""
+}
+{
+	if ( ! found )
+	{
+		if ( ! match($0, regex) ) next
+
+		found = 1
+		sub(/^[^#]*(#[[:space:]]*)?/, "")
+		buffer = $0
+		next
+	}
+
+	if ( !/^[[:space:]]*#/ ||
+	      /^[[:space:]]*[[:alpha:]_][[:alnum:]_]*=/ ||
+	      /^[[:space:]]*#[[:alpha:]_][[:alnum:]_]*=/ ||
+	      /^[[:space:]]*$/ ) exit
+
+	sub(/(.*#)*[[:space:]]*/, "")
+	buffer = buffer" "$0
+}
+END {
+	# Clean up the buffer
+	sub(/^[[:space:]]*/, "", buffer)
+	sub(/[[:space:]]*$/, "", buffer)
+
+	print buffer
+	exit ! found
+}
+'
+f_sysrc_desc()
+{
+	awk -v varname="$1" "$f_sysrc_desc_awk" < "$RC_DEFAULTS"
+}
+
+# f_sysrc_set $varname $new_value
+#
+# Change a setting in the system configuration files (edits the files in-place
+# to change the value in the last assignment to the variable). If the variable
+# does not appear in the source file, it is appended to the end of the primary
+# system configuration file `/etc/rc.conf'.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_sysrc_set_awk='
+# Variables that should be defined on the invocation line:
+# 	-v varname="varname"
+# 	-v new_value="new_value"
+#
+BEGIN {
+	regex = "^[[:space:]]*"varname"="
+	found = retval = 0
+}
+{
+	# If already found... just spew
+	if ( found ) { print; next }
+
+	# Does this line match an assignment to our variable?
+	if ( ! match($0, regex) ) { print; next }
+
+	# Save important match information
+	found = 1
+	matchlen = RSTART + RLENGTH - 1
+
+	# Store the value text for later munging
+	value = substr($0, matchlen + 1, length($0) - matchlen)
+
+	# Store the first character of the value
+	t1 = t2 = substr(value, 0, 1)
+
+	# Assignment w/ back-ticks, expression, or misc.
+	# We ignore these since we did not generate them
+	#
+	if ( t1 ~ /[`$\\]/ ) { retval = 1; print; next }
+
+	# Assignment w/ single-quoted value
+	else if ( t1 == "'\''" ) {
+		sub(/^'\''[^'\'']*/, "", value)
+		if ( length(value) == 0 ) t2 = ""
+		sub(/^'\''/, "", value)
+	}
+
+	# Assignment w/ double-quoted value
+	else if ( t1 == "\"" ) {
+		sub(/^"(.*\\\\+")*[^"]*/, "", value)
+		if ( length(value) == 0 ) t2 = ""
+		sub(/^"/, "", value)
+	}
+
+	# Assignment w/ non-quoted value
+	else if ( t1 ~ /[^[:space:];]/ ) {
+		t1 = t2 = "\""
+		sub(/^[^[:space:]]*/, "", value)
+	}
+
+	# Null-assignment
+	else if ( t1 ~ /[[:space:];]/ ) { t1 = t2 = "\"" }
+
+	printf "%s%c%s%c%s\n", substr($0, 0, matchlen), \
+		t1, new_value, t2, value
+}
+END { exit retval }
+'
+f_sysrc_set()
+{
+	local varname="$1" new_value="$2"
+
+	# Check arguments
+	[ "$varname" ] || return $FAILURE
+
+	#
+	# Find which rc.conf(5) file contains the last-assignment
+	#
+	local not_found=
+	local file="$( f_sysrc_find "$varname" )"
+	if [ "$file" = "$RC_DEFAULTS" -o ! "$file" ]; then
+		#
+		# We either got a null response (not found) or the variable
+		# was only found in the rc.conf(5) defaults. In either case,
+		# let's instead modify the first file from $rc_conf_files.
+		#
+
+		not_found=1
+
+		#
+		# If RC_CONFS is defined, use $RC_CONFS
+		# rather than $rc_conf_files.
+		#
+		if [ "$RC_CONFS" ]; then
+			file="${RC_CONFS%%[$IFS]*}"
+		else
+			file=$( f_sysrc_get rc_conf_files )
+			file="${file%%[$IFS]*}"
+		fi
+	fi
+
+	#
+	# If not found, append new value to last file and return.
+	#
+	if [ "$not_found" ]; then
+		echo "$varname=\"$new_value\"" >> "$file"
+		return $?
+	fi
+
+	#
+	# Perform sanity checks.
+	#
+	if [ ! -w "$file" ]; then
+		f_err "$msg_cannot_create_permission_denied\n" \
+		      "$pgm" "$file"
+		return $FAILURE
+	fi
+
+	#
+	# Create a new temporary file to write to.
+	#
+	local tmpfile="$( mktemp -t "$pgm" )"
+	[ "$tmpfile" ] || return $FAILURE
+
+	#
+	# Fixup permissions (else we're in for a surprise, as mktemp(1) creates
+	# the temporary file with 0600 permissions, and if we simply mv(1) the
+	# temporary file over the destination, the destination will inherit the
+	# permissions from the temporary file).
+	#
+	local mode
+	mode=$( stat -f '%#Lp' "$file" 2> /dev/null )
+	f_quietly chmod "${mode:-0644}" "$tmpfile"
+
+	#
+	# Fixup ownership. The destination file _is_ writable (we tested
+	# earlier above). However, this will fail if we don't have sufficient
+	# permissions (so we throw stderr into the bit-bucket).
+	#
+	local owner
+	owner=$( stat -f '%u:%g' "$file" 2> /dev/null )
+	f_quietly chown "${owner:-root:wheel}" "$tmpfile"
+
+	#
+	# Operate on the matching file, replacing only the last occurrence.
+	#
+	local new_contents retval
+	new_contents=$( tail -r $file 2> /dev/null )
+	new_contents=$( echo "$new_contents" | awk -v varname="$varname" \
+		-v new_value="$new_value" "$f_sysrc_set_awk" )
+	retval=$?
+
+	#
+	# Write the temporary file contents.
+	#
+	echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE
+	if [ $retval -ne $SUCCESS ]; then
+		echo "$varname=\"$new_value\"" >> "$tmpfile"
+	fi
+
+	#
+	# Taint-check our results.
+	#
+	if ! /bin/sh -n "$tmpfile"; then
+		f_err "$msg_previous_syntax_errors\n" "$pgm" "$file"
+		rm -f "$tmpfile"
+		return $FAILURE
+	fi
+
+	#
+	# Finally, move the temporary file into place.
+	#
+	mv "$tmpfile" "$file"
+}
+
+# f_sysrc_delete $varname
+#
+# Remove a setting from the system configuration files (edits files in-place).
+# Deletes all assignments to the given variable in all config files. If the
+# `-f file' option is passed, the removal is restricted to only those files
+# specified, otherwise the system collection of rc_conf_files is used.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_sysrc_delete_awk='
+# Variables that should be defined on the invocation line:
+# 	-v varname="varname"
+#
+BEGIN {
+	regex = "^[[:space:]]*"varname"="
+	found = 0
+}
+{
+	if ( $0 ~ regex )
+		found = 1
+	else
+		print
+}
+END { exit ! found }
+'
+f_sysrc_delete()
+{
+	local varname="$1"
+	local file
+
+	# Check arguments
+	[ "$varname" ] || return $FAILURE
+
+	#
+	# Operate on each of the specified files
+	#
+	for file in ${RC_CONFS:-$( f_sysrc_get rc_conf_files )}; do
+		[ -e "$file" ] || continue
+
+		#
+		# Create a new temporary file to write to.
+		#
+		local tmpfile="$( mktemp -t "$pgm" )"
+		[ "$tmpfile" ] || return $FAILURE
+
+		#
+		# Fixup permissions and ownership (mktemp(1) defaults to 0600
+		# permissions) to instead match the destination file.
+		#
+		local mode owner
+		mode=$( stat -f '%#Lp' "$file" 2> /dev/null )
+		owner=$( stat -f '%u:%g' "$file" 2> /dev/null )
+		f_quietly chmod "${mode:-0644}" "$tmpfile"
+		f_quietly chown "${owner:-root:wheel}" "$tmpfile"
+
+		#
+		# Operate on the file, removing all occurrences, saving the
+		# output in our temporary file.
+		#
+		awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \
+			> "$tmpfile"
+		if [ $? -ne $SUCCESS ]; then
+			# The file didn't contain any assignments
+			rm -f "$tmpfile"
+			continue
+		fi
+
+		#
+		# Taint-check our results.
+		#
+		if ! /bin/sh -n "$tmpfile"; then
+			f_err "$msg_previous_syntax_errors\n" \
+			      "$pgm" "$file"
+			rm -f "$tmpfile"
+			return $FAILURE
+		fi
+
+		#
+		# Perform sanity checks
+		#
+		if [ ! -w "$file" ]; then
+			f_err "$msg_permission_denied\n" "$pgm" "$file"
+			rm -f "$tmpfile"
+			return $FAILURE
+		fi
+
+		#
+		# Finally, move the temporary file into place.
+		#
+		mv "$tmpfile" "$file"
+	done
+}
+
+fi # ! $_SYSRC_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Mouse"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Configure the Mouse"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="mouse|mouse"
+menu_selection="mouse_enable|enable"
+menu_selection="mouse_type|type"
+menu_selection="mouse_port|port"
+menu_selection="mouse_flags|flags"
+menu_selection="mouse_disable|disable"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="mouse"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/110.mouse
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	disable enable flags mouse port type
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/disable
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/disable	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,104 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/disable 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Location of moused(8) pidfile
+#
+MOUSED_PIDFILE=/var/run/moused.pid
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_mouse_disable"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Stop the mouse daemon
+#
+[ -r "$MOUSED_PIDFILE" ] &&
+	f_quietly kill "$( cat "$MOUSED_PIDFILE" )"
+f_sysrc_set moused_enable "NO" || f_die
+f_sysrc_set moused_type "NO" || f_die
+f_sysrc_delete moused_port || f_die
+f_sysrc_delete moused_flags || f_die
+
+#
+# Message box
+#
+f_dialog_title "$msg_message"
+hline="$hline_press_enter_or_space"
+prompt="$msg_mouse_daemon_is_disabled"
+size=$( f_dialog_buttonbox_size \
+        	"$DIALOG_TITLE"     \
+        	"$DIALOG_BACKTITLE" \
+        	"$prompt"           )
+eval $DIALOG \
+	--title \"\$DIALOG_TITLE\"         \
+	--backtitle \"\$DIALOG_BACKTITLE\" \
+	--hline \"\$hline\"                \
+	--ok-label \"\$msg_ok\"            \
+	--msgbox \"\$prompt\" $size
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/enable
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/enable	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,118 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/enable 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Location of moused(8) pidfile
+#
+MOUSED_PIDFILE=/var/run/moused.pid
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_mouse_enable"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Get the type, port, and flags
+#
+type=$( f_sysrc_get moused_type )
+case "$type" in
+[Nn][Oo]|"") f_die 1 "$msg_please_select_protocol_and_port_first" ;;
+esac
+port=$( f_sysrc_get moused_port )
+[ "$port" ] || f_die 1 "$msg_please_select_protocol_and_port_first"
+flags=$( f_sysrc_get moused_flags )
+
+#
+# Start the mouse daemon
+#
+f_dialog_info "$msg_trying_to_start_the_mouse_daemon"
+[ -r "$MOUSED_PIDFILE" ] &&
+	f_quietly kill "$( cat "$MOUSED_PIDFILE" 2> /dev/null )"
+f_quietly vidcontrol -m on
+f_quietly moused -t "$type" -p "$port" $flags
+
+#
+# Confirm with the user that the mouse is working
+#
+f_dialog_title "$msg_user_confirmation_requested"
+f_dialog_yesno "$msg_now_move_the_mouse"
+retval=$?
+f_dialog_title_restore
+
+#
+# Stop the mouse daemon
+#
+f_quietly vidcontrol -m off
+if [ $retval -eq $SUCCESS ]; then
+	f_sysrc_set moused_enable "YES" || f_die
+	ln -fs /dev/sysmouse /dev/mouse || f_die # backwards compat
+else
+	[ -r "$MOUSED_PIDFILE" ] &&
+		f_quietly kill "$( cat "$MOUSED_PIDFILE" )"
+	f_sysrc_set moused_enable "NO" || f_die
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/flags
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/flags	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,116 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/flags 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Location of moused(8) pidfile
+#
+MOUSED_PIDFILE=/var/run/moused.pid
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_mouse_flags"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Get the current flags
+#
+flags=$( f_sysrc_get moused_flags )
+
+#
+# Prompt the user with the current value
+#
+f_dialog_title "$msg_value_required"
+title="$DIALOG_TITLE"
+btitle="$DIALOG_BACKTITLE"
+f_dialog_title_restore
+hline=
+prompt="$msg_please_specify_the_mouse_daemon_flags"
+size=$( f_dialog_inputbox_size \
+        	"$title"  \
+        	"$btitle" \
+        	"$prompt" \
+        	"$flags"  \
+        	"$hline"  )
+eval $DIALOG \
+	--title \"\$title\"             \
+	--backtitle \"\$btitle\"        \
+	--hline \"\$hline\"             \
+	--ok-label \"\$msg_ok\"         \
+	--cancel-label \"\$msg_cancel\" \
+	--inputbox \"\$prompt\" $size   \
+	\"\$flags\"                     \
+	2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+retval=$?
+flags=$( f_dialog_inputstr )
+
+[ $retval -eq $SUCCESS ] || f_die
+
+#
+# Save the new value
+#
+f_sysrc_set moused_flags "$flags" || f_die
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/110.mouse/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,90 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_press_enter_or_space="Press enter or space"
+msg_auto="Auto"
+msg_auto_desc="Bus mouse, PS/2 style mouse or PnP serial mouse"
+msg_busmouse="BusMouse"
+msg_busmouse_desc="Logitech, ATI or MS bus mouse (/dev/mse0)"
+msg_cancel="Cancel"
+msg_com1="COM1"
+msg_com1_desc="Serial mouse on COM1 (/dev/cuau0)"
+msg_com2="COM2"
+msg_com2_desc="Serial mouse on COM2 (/dev/cuau1)"
+msg_com3="COM3"
+msg_com3_desc="Serial mouse on COM3 (/dev/cuau2)"
+msg_com4="COM4"
+msg_com4_desc="Serial mouse on COM4 (/dev/cuau3)"
+msg_disable="Disable"
+msg_disable_the_mouse_daemon="Disable the mouse daemon"
+msg_enable="Enable"
+msg_exit="Exit"
+msg_exit_this_menu="Exit this menu (returning to previous)"
+msg_flags="Flags"
+msg_glidepoint="GlidePoint"
+msg_glidepoint_desc="ALPS GlidePoint pad (serial)"
+msg_hitachi="Hitachi"
+msg_hitachi_desc="Hitachi tablet (serial)"
+msg_intellimouse="IntelliMouse"
+msg_intellimouse_desc="Microsoft IntelliMouse (serial)"
+msg_logitech="Logitech"
+msg_logitech_desc="Logitech protocol (old models) (serial)"
+msg_menu_text="You can cut and paste text in the text console by running the mouse\ndaemon.  Specify a port and a protocol type of your mouse and enable\nthe mouse daemon.  If you don't want this feature, select 6 to disable\nthe daemon.\nOnce you've enabled the mouse daemon, you can specify \"/dev/sysmouse\"\nas your mouse device and \"SysMouse\" or \"MouseSystems\" as mouse\nprotocol when running the X configuration utility (see Configuration\nmenu)."
+msg_message="Message"
+msg_microsoft="Microsoft"
+msg_microsoft_desc="Microsoft protocol (serial)"
+msg_mm_series="MM Series"
+msg_mm_series_desc="MM Series protocol (serial)"
+msg_mouseman="MouseMan"
+msg_mouseman_desc="Logitech MouseMan/TrackMan models (serial)"
+msg_mousesystems="MouseSystems"
+msg_mousesystems_desc="MouseSystems protocol (serial)"
+msg_mouse_daemon_is_disabled="The mouse daemon is disabled."
+msg_mouse_disable="Mouse Disable"
+msg_mouse_enable="Mouse Enable"
+msg_mouse_flags="Mouse Flags"
+msg_now_move_the_mouse="Now move the mouse and see if it works.\n(Note that buttons don't have any effect for now.)\n\n         Is the mouse cursor moving?\n"
+msg_ok="OK"
+msg_please_configure_your_mouse="Please configure your mouse"
+msg_please_select_protocol_and_port_first="Please select a mouse protocol and a port first."
+msg_please_specify_the_mouse_daemon_flags="Please specify the mouse daemon flags.  If you would like to\nemulate 3 buttons, use -3 here.\n "
+msg_port="Port"
+msg_port_menu_text="The built-in pointing device of laptop/notebook computers is usually\na PS/2 style device."
+msg_protocol_menu_text="If your mouse is attached to the PS/2 mouse port or the bus mouse port,\nyou should always choose \"Auto\", regardless of the model and the brand\nof the mouse.  All other protocol types are for serial mice and should\nnot be used with the PS/2 port mouse or the bus mouse.  If you have\na serial mouse and are not sure about its protocol, you should also try\n\"Auto\".  It may not work for the serial mouse if the mouse does not\nsupport the PnP standard.  But, it won't hurt.  Many 2-button serial mice\nare compatible with \"Microsoft\" or \"MouseMan\". 3-button serial mice\nmay be compatible with \"MouseSystems\" or \"MouseMan\".  If the serial\nmouse has a wheel, it may be compatible with \"IntelliMouse\"."
+msg_ps2="PS/2"
+msg_ps2_desc="PS/2 style mouse (/dev/psm0)"
+msg_select_a_protocol_type_for_your_mouse="Select a protocol type for your mouse"
+msg_select_mouse_port="Select mouse port"
+msg_select_mouse_protocol_type="Select mouse protocol type"
+msg_select_your_mouse_port_from_the_following_menu="Select your mouse port from the following menu"
+msg_set_additional_flags="Set additional flags"
+msg_test_and_run_the_mouse_daemon="Test and run the mouse daemon"
+msg_thinkingmouse="ThinkingMouse"
+msg_thinkingmouse_desc="Kensington ThinkingMouse (serial)"
+msg_trying_to_start_the_mouse_daemon="Trying to start the mouse daemon..."
+msg_type="Type"
+msg_user_confirmation_requested="User Confirmation Requested"
+msg_value_required="Value Required"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/mouse
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/mouse	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,134 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/mouse 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline=""
+	local prompt="$msg_menu_text"
+
+	menu_list="
+		'X $msg_exit'    '$msg_exit_this_menu'
+		'2 $msg_enable'  '$msg_test_and_run_the_mouse_daemon'
+		'3 $msg_type'    '$msg_select_mouse_protocol_type'
+		'4 $msg_port'    '$msg_select_mouse_port'
+		'5 $msg_flags'   '$msg_set_additional_flags'
+		'6 $msg_disable' '$msg_disable_the_mouse_daemon'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_please_configure_your_mouse"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+	"2 $msg_enable") # Test and run the mouse daemon
+		$BSDCFG_LIBE/$APP_DIR/enable ${USE_XDIALOG:+-X} ;;
+	"3 $msg_type") # Select mouse protocol type
+		$BSDCFG_LIBE/$APP_DIR/type ${USE_XDIALOG:+-X} ;;
+	"4 $msg_port") # Select mouse port
+		$BSDCFG_LIBE/$APP_DIR/port ${USE_XDIALOG:+-X} ;;
+	"5 $msg_flags") # Set additional flags
+		$BSDCFG_LIBE/$APP_DIR/flags ${USE_XDIALOG:+-X} ;;
+	"6 $msg_disable") # Disable the mouse daemon
+		$BSDCFG_LIBE/$APP_DIR/disable ${USE_XDIALOG:+-X} ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/port
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/port	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,142 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/port 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline=""
+	local prompt="$msg_port_menu_text"
+
+	menu_list="
+		'1 $msg_ps2'      '$msg_ps2_desc'
+		'2 $msg_com1'     '$msg_com1_desc'
+		'3 $msg_com2'     '$msg_com2_desc'
+		'4 $msg_com3'     '$msg_com3_desc'
+		'5 $msg_com4'     '$msg_com4_desc'
+		'6 $msg_busmouse' '$msg_busmouse_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_select_your_mouse_port_from_the_following_menu"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"1 $msg_ps2") # PS/2 style mouse (/dev/psm0)
+		f_sysrc_set moused_port "/dev/psm0" || f_die
+		break ;;
+	"2 $msg_com1") # Serial mouse on COM1 (/dev/cuau0)
+		f_sysrc_set moused_port "/dev/cuau0" || f_die
+		break ;;
+	"3 $msg_com2") # Serial mouse on COM2 (/dev/cuau1)
+		f_sysrc_set moused_port "/dev/cuau1" || f_die
+		break ;;
+	"4 $msg_com3") # Serial mouse on COM3 (/dev/cuau2)
+		f_sysrc_set moused_port "/dev/cuau2" || f_die
+		break ;;
+	"5 $msg_com4") # Serial mouse on COM4 (/dev/cuau3)
+		f_sysrc_set moused_port "/dev/cuau3" || f_die
+		break ;;
+	"6 $msg_busmouse") # Logitech, ATI or MS bus mouse (/dev/mse0)
+		f_sysrc_set moused_port "/dev/mse0" || f_die
+		break ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/mouse/type
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/mouse/type	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,158 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/mouse/type 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline=""
+	local prompt="$msg_protocol_menu_text"
+
+	menu_list="
+		'1 $msg_auto'          '$msg_auto_desc'
+		'2 $msg_glidepoint'    '$msg_glidepoint_desc'
+		'3 $msg_hitachi'       '$msg_hitachi_desc'
+		'4 $msg_intellimouse'  '$msg_intellimouse_desc'
+		'5 $msg_logitech'      '$msg_logitech_desc'
+		'6 $msg_microsoft'     '$msg_microsoft_desc'
+		'7 $msg_mm_series'     '$msg_mm_series_desc'
+		'8 $msg_mouseman'      '$msg_mouseman_desc'
+		'9 $msg_mousesystems'  '$msg_mousesystems_desc'
+		'A $msg_thinkingmouse' '$msg_thinkingmouse_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_select_a_protocol_type_for_your_mouse"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"1 $msg_auto") # Bus mouse, PS/2 style mouse or PnP serial mouse
+		f_sysrc_set moused_type "auto" || f_die
+		break ;;
+	"2 $msg_glidepoint") # ALPS GlidePoint pad (serial)
+		f_sysrc_set moused_type "glidepoint" || f_die
+		break ;;
+	"3 $msg_hitachi") # Hitachi tablet (serial)
+		f_sysrc_set moused_type "mmhittab" || f_die
+		break ;;
+	"4 $msg_intellimouse") # Microsoft Intellimouse (serial)
+		f_sysrc_set moused_type "intellimouse" || f_die
+		break ;;
+	"5 $msg_logitech") # Logitech protocol (old models) (serial)
+		f_sysrc_set moused_type "logitech" || f_die
+		break ;;
+	"6 $msg_microsoft") # Microsoft protocol (serial)
+		f_sysrc_set moused_type "microsoft" || f_die
+		break ;;
+	"7 $msg_mm_series") # MM Series protocol (serial)
+		f_sysrc_set moused_type "mmseries" || f_die
+		break ;;
+	"8 $msg_mouseman") # Logitech MouseMan/TrackMan models (serial)
+		f_sysrc_set moused_type "mouseman" || f_die
+		break ;;
+	"9 $msg_mousesystems") # MouseSystems protocol (serial)
+		f_sysrc_set moused_type "mousesystems" || f_die
+		break ;;
+	"A $msg_thinkingmouse") # Kensignton ThinkingMouse (serial)
+		f_sysrc_set moused_type "thinkingmouse" || f_die
+		break ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,57 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Networking Management"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Setup Networking interfaces, services, etc."
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="networking|networking"
+menu_selection="defaultrouter|defaultrouter"
+menu_selection="hostname|hostname"
+menu_selection="nameservers|nameservers"
+menu_selection="netdev|devices"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="networking"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/120.networking
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	defaultrouter devices hostname nameservers networking
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/defaultrouter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/defaultrouter	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,73 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/defaultrouter 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/routing.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_default_router"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Change the default router/gateway
+#
+f_dialog_input_defaultrouter
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/devices
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/devices	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,158 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/devices 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/device.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/ipaddr.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/media.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/netmask.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line options
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_networking_devices"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	f_dialog_menu_netdev
+	retval=$?
+	interface=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || break
+
+	#
+	# dialog_menu_netdev adds an asterisk (*) to the right of the
+	# device name if the interface is active. Remove the asterisk
+	# from the device name if present.
+	#
+	case "$interface" in
+	*\*) interface="${interface%?}";;
+	esac
+
+	#
+	# Obtain initial interface settings to be configured. These will be
+	# passed to the f_dialog_menu_netdev_edit function-call below which
+	# will block until the user has either cancelled or finished editing
+	# the values.
+	#
+	# First, attempt to read stored configuration from rc.conf(5) and
+	# fallback to reading the active configuration if not configured in
+	# the rc.conf(5) file(s).
+	#
+	_ipaddr=
+	_netmask=
+	_ifconfig=$( f_sysrc_get ifconfig_$interface )
+	if [ "$_ifconfig" ]; then
+		# If DHCP get IP address/netmask later from ifconfig(8)
+		glob="[Dd][Hh][Cc][Pp]"
+		case "$_ifconfig" in
+		$glob) dhcp=1;;
+		[Ss][Yy][Nn][Cc]$glob) dhcp=1;;
+		[Nn][Oo][Ss][Yy][Nn][Cc]$glob) dhcp=1;;
+		*)
+			#
+			# Get IP address/netmask from rc.conf(5)
+			# configuration
+			#
+			dhcp=
+			eval "$( exec 2> /dev/null
+			         set -- $_ifconfig
+			         while [ $# -gt 0 ]; do
+			         	case "$1" in
+			         	inet)
+			         		shift 1
+			         		echo "_ipaddr='$1'"
+			         		;;
+			         	netmask)
+			         		shift 1
+			         		echo "_netmask='$1'"
+			         		;;
+			         	esac
+			         	shift 1
+			         done
+			       )"
+			;;
+		esac
+	fi
+
+	#
+	# Fill in IP address/netmask from active settings if no
+	# configuration could be extrapolated from rc.conf(5)
+	#
+	[ "$_ipaddr"  ] || _ipaddr=$( f_ifconfig_inet $interface )
+	[ "$_netmask" ] || _netmask=$( f_ifconfig_netmask $interface )
+
+	# Get the extra options (this always comes from rc.conf(5))
+	_options=$( f_ifconfig_options $interface )
+
+	# Block on user-configuration of the probed settings
+	f_dialog_menu_netdev_edit \
+		$interface $_ipaddr $_netmask "$_options" $dhcp
+
+	# Return to root menu if above returns success
+	[ $? -eq $SUCCESS ] && break
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/hostname
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/hostname	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,73 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/hostname 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/hostname.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_hostname_domain"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Change the local hostname
+#
+f_dialog_input_hostname
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,12 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/120.networking/include
+FILES=		common.subr device.subr hostname.subr ipaddr.subr media.subr \
+		messages.subr netmask.subr resolv.subr routing.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/common.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/common.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,65 @@
+if [ ! "$_NETWORKING_COMMON_SUBR" ]; then _NETWORKING_COMMON_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/common.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+
+############################################################ FUNCTIONS
+
+# f_mounted $local_directory
+#
+# Return success if a filesystem is mounted on a particular directory.
+#
+f_mounted()
+{
+	local dir="$1"
+	[ -d "$dir" ] || return $FAILURE
+	mount | grep -Eq " on $dir \([^)]+\)$"
+}
+
+# f_jailed
+#
+# Returns true if the current process is jail(8)ed.
+#
+f_jailed()
+{
+	! f_quietly ps 1
+}
+
+# f_nfs_mounted
+#
+# Returns true if there are any NFS mounts currently active, otherwise false.
+#
+f_nfs_mounted()
+{
+	[ "$( df -t nfs )" ]
+}
+
+fi # ! $_NETWORKING_COMMON_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/device.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/device.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,489 @@
+if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/device.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/ipaddr.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/media.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/netmask.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/resolv.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/routing.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ GLOBALS
+
+#
+# Settings used while interacting with various dialog(1) menus
+#
+: ${DIALOG_MENU_NETDEV_KICK_INTERFACES=1}
+: ${DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK=3}
+
+############################################################ FUNCTIONS
+
+# f_device_desc $device_name
+#
+# Print a description for a device name (eg., `fxp0').
+#
+f_device_desc()
+{
+	local device="$1" d="[1234567890]" desc=""
+
+	# Check variables
+	[ "$device" ] || return $SUCCESS
+
+	#
+	# Return sysctl MIB dev.NAME.UNIT.%desc if it exists,
+	# otherwise fall through to below static list.
+	#
+	if f_have sysctl; then
+		local devname devunit
+		devname="${device%%$d*}"
+		devunit="${device#$devname}"
+		devunit="${devunit%%[a-zA-Z_]*}"
+		sysctl -n "dev.$devname.$devunit.%desc" 2> /dev/null &&
+			return $SUCCESS
+	fi
+
+	case "$device" in
+	# Network devices
+	ae$d)    desc="Attansic/Atheros L2 Fast Ethernet";;
+	age$d)   desc="Attansic/Atheros L1 Gigabit Ethernet";;
+	alc$d)   desc="Atheros AR8131/AR8132 PCIe Ethernet";;
+	ale$d)   desc="Atheros AR8121/AR8113/AR8114 PCIe Ethernet";;
+	an$d)    desc="Aironet 4500/4800 802.11 wireless adapter";;
+	ath$d)   desc="Atheros IEEE 802.11 wireless adapter";;
+	aue$d)   desc="ADMtek USB Ethernet adapter";;
+	axe$d)   desc="ASIX Electronics USB Ethernet adapter";;
+	bce$d)   desc="Broadcom NetXtreme II Gigabit Ethernet card";;
+	bfe$d)   desc="Broadcom BCM440x PCI Ethernet card";;
+	bge$d)   desc="Broadcom BCM570x PCI Gigabit Ethernet card";;
+	bm$d)    desc="Apple BMAC Built-in Ethernet";;
+	bwn$d)   desc="Broadcom BCM43xx IEEE 802.11 wireless adapter";;
+	cas$d)   desc="Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet";;
+	cc3i$d)  desc="SDL HSSI sync serial PCI card";;
+	cue$d)   desc="CATC USB Ethernet adapter";;
+	cxgb$d)  desc="Chelsio T3 10Gb Ethernet card";;
+	dc$d)    desc="DEC/Intel 21143 (and clones) PCI Fast Ethernet card";;
+	de$d)    desc="DEC DE435 PCI NIC or other DC21040-AA based card";;
+	disc$d)  desc="Software discard network interface";;
+	ed$d)    desc="Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA";;
+	el$d)    desc="3Com 3C501 Ethernet card";;
+	em$d)    desc="Intel(R) PRO/1000 Ethernet card";;
+	en$d)    desc="Efficient Networks ATM PCI card";;
+	ep$d)    desc="3Com 3C509 Ethernet card/3C589 PCMCIA";;
+	et$d)    desc="Agere ET1310 based PCI Express Gigabit Ethernet card";;
+	ex$d)    desc="Intel EtherExpress Pro/10 Ethernet card";;
+	fe$d)    desc="Fujitsu MB86960A/MB86965A Ethernet card";;
+	fpa$d)   desc="DEC DEFPA PCI FDDI card";;
+	fwe$d)   desc="FireWire Ethernet emulation";;
+	fwip$d)  desc="IP over FireWire";;
+	fxp$d)   desc="Intel EtherExpress Pro/100B PCI Fast Ethernet card";;
+	gem$d)   desc="Apple GMAC or Sun ERI/GEM Ethernet adapter";;
+	hme$d)   desc="Sun HME (Happy Meal Ethernet) Ethernet adapter";;
+	ie$d)    desc="AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210";;
+	igb$d)   desc="Intel(R) PRO/1000 PCI Express Gigabit Ethernet card";;
+	ipw$d)   desc="Intel PRO/Wireless 2100 IEEE 802.11 adapter";;
+	iwi$d)   desc="Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter";;
+	iwn$d)   desc="Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter";;
+	ix$d)    desc="Intel Etherexpress Ethernet card";;
+	ixgb$d)  desc="Intel(R) PRO/10Gb Ethernet card";;
+	ixgbe$d) desc="Intel(R) PRO/10Gb Ethernet card";;
+	jme$d)   desc="JMicron JMC250 Gigabit/JMC260 Fast Ethernet";;
+	kue$d)   desc="Kawasaki LSI USB Ethernet adapter";;
+	le$d)    desc="AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter";;
+	lge$d)   desc="Level 1 LXT1001 Gigabit Ethernet card";;
+	lnc$d)   desc="Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet";;
+	lp$d)    desc="Parallel Port IP (PLIP) peer connection";;
+	lo$d)    desc="Loop-back (local) network interface";;
+	malo$d)  desc="Marvell Libertas 88W8335 802.11 wireless adapter";;
+	msk$d)   desc="Marvell/SysKonnect Yukon II Gigabit Ethernet";;
+	mxge$d)  desc="Myricom Myri10GE 10Gb Ethernet card";;
+	nfe$d)   desc="NVIDIA nForce MCP Ethernet";;
+	ng${d}_*|ng$d${d}_*|ng$d$d${d}_*|ng$d$d$d${d}_*|ng$d$d$d$d${d}_*)
+	         desc="Vimage netgraph(4) bridged Ethernet device";;
+	nge$d)   desc="NatSemi PCI Gigabit Ethernet card";;
+	nve$d)   desc="NVIDIA nForce MCP Ethernet";;
+	nxge$d)  desc="Neterion Xframe 10GbE Server/Storage adapter";;
+	pcn$d)   desc="AMD Am79c79x PCI Ethernet card";;
+	plip$d)  desc="Parallel Port IP (PLIP) peer connection";;
+	ral$d)   desc="Ralink Technology IEEE 802.11 wireless adapter";;
+	ray$d)   desc="Raytheon Raylink 802.11 wireless adapter";;
+	re$d)    desc="RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter";;
+	rl$d)    desc="RealTek 8129/8139 PCI Ethernet card";;
+	rue$d)   desc="RealTek USB Ethernet card";;
+	rum$d)   desc="Ralink Technology USB IEEE 802.11 wireless adapter";;
+	sf$d)    desc="Adaptec AIC-6915 PCI Ethernet card";;
+	sge$d)   desc="Silicon Integrated Systems SiS190/191 Ethernet";;
+	sis$d)   desc="SiS 900/SiS 7016 PCI Ethernet card";;
+	sk$d)    desc="SysKonnect PCI Gigabit Ethernet card";;
+	sn$d)    desc="SMC/Megahertz Ethernet card";;
+	snc$d)   desc="SONIC Ethernet card";;
+	sr$d)    desc="SDL T1/E1 sync serial PCI card";;
+	ste$d)   desc="Sundance ST201 PCI Ethernet card";;
+	stge$d)  desc="Sundance/Tamarack TC9021 Gigabit Ethernet";;
+	ti$d)    desc="Alteon Networks PCI Gigabit Ethernet card";;
+	tl$d)    desc="Texas Instruments ThunderLAN PCI Ethernet card";;
+	tx$d)    desc="SMC 9432TX Ethernet card";;
+	txp$d)   desc="3Com 3cR990 Ethernet card";;
+	uath$d)  desc="Atheros AR5005UG and AR5005UX USB wireless adapter";;
+	upgt$d)  desc="Conexant/Intersil PrismGT USB wireless adapter";;
+	ural$d)  desc="Ralink Technology RT2500USB 802.11 wireless adapter";;
+	urtw$d)  desc="Realtek 8187L USB wireless adapter";;
+	vge$d)   desc="VIA VT612x PCI Gigabit Ethernet card";;
+	vlan$d|vlan$d$d|vlan$d$d$d|vlan$d$d$d$d|vlan$d$d$d$d$d)
+	         desc="IEEE 802.1Q VLAN network interface";;
+	vr$d)    desc="VIA VT3043/VT86C100A Rhine PCI Ethernet card";;
+	vx$d)    desc="3COM 3c590 / 3c595 Ethernet card";;
+	wb$d)    desc="Winbond W89C840F PCI Ethernet card";;
+	wi$d)    desc="Lucent WaveLAN/IEEE 802.11 wireless adapter";;
+	wpi$d)   desc="Intel 3945ABG IEEE 802.11 wireless adapter";;
+	wx$d)    desc="Intel Gigabit Ethernet (82452) card";;
+	xe$d)    desc="Xircom/Intel EtherExpress Pro100/16 Ethernet card";;
+	xl$d)    desc="3COM 3c90x / 3c90xB PCI Ethernet card";;
+	zyd$d)   desc="ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter";;
+	# Unknown device
+	*)       desc="<unknown network interface type>";;
+	esac
+	printf "%s\n" "$desc"
+}
+
+# f_dialog_menu_netdev
+#
+# Display a list of network devices with descriptions.
+#
+f_dialog_menu_netdev()
+{
+	#
+	# Display a message to let the user know we're working...
+	# (message will remain until we throw up the next dialog)
+	#
+	f_dialog_info "$msg_probing_network_interfaces"
+
+	#
+	# Get list of usable network interfaces
+	#
+	local d='[[:digit:]]+:'
+	local iflist="`echo "$(ifconfig -l):" | sed -E -e "
+		# Convert all spaces to colons
+		y/ /:/
+
+		# Prune unsavory interfaces
+		s/lo$d//g
+		s/ppp$d//g
+		s/sl$d//g
+		s/lp$d//g
+		s/fwe$d//g
+		s/faith$d//g
+		s/plip$d//g
+
+		# Convert all colons back into spaces
+		y/:/ /
+	"`"
+
+	#
+	# Optionally kick interfaces in the head to get them to accurately
+	# track the carrier status in realtime (required on FreeBSD).
+	#
+	if [ "$DIALOG_MENU_NETDEV_KICK_INTERFACES" ]; then
+		DIALOG_MENU_NETDEV_KICK_INTERFACES=
+
+		local ifn
+		for ifn in $iflist; do
+			f_quietly ifconfig $ifn up
+		done
+
+		if [ "$DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK" ]; then
+			# interfaces need time to update carrier status
+			sleep $DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK
+		fi
+	fi
+
+	#
+	# Mark any "active" interfaces with an asterisk (*)
+	# to the right of the device name.
+	#
+	interfaces=$(
+		for ifn in $iflist; do
+			active=$( ifconfig $ifn | awk \
+			'
+				( $1 == "status:" ) \
+				{
+					if ( $2 == "active" ) { print 1; exit }
+				}
+			' )
+			printf "'%s%s' '%s'\n" \
+				"$ifn" "${active:+*}" "$(f_device_desc "$ifn")"
+		done
+	)
+	if [ ! "$interfaces" ]; then
+		f_dialog_msgbox "$msg_no_network_interfaces"
+		return $FAILURE
+	fi
+
+	local hline="$hline_arrows_tab_enter"
+
+	#
+	# Ask user to select an interface
+	#
+	local prompt size
+	prompt="$msg_select_network_interface"
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$interfaces            )
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$interfaces                        \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# f_dialog_menu_netdev_edit $interface $ipaddr $netmask $options $dhcp
+#
+# Allow a user to edit network interface settings. Current values are not
+# probed but rather taken from the positional arguments.
+#
+f_dialog_menu_netdev_edit()
+{
+	local interface="$1" ipaddr="$2" netmask="$3" options="$4" dhcp="$5"
+	local prompt menu_list size
+
+	#
+	# Create a duplicate set of variables for change-tracking...
+	#
+	local ipaddr_orig="$2"  \
+	      netmask_orig="$3" \
+	      options_orig="$4" \
+	      dhcp_orig="$5"
+
+	local hline="$hline_arrows_tab_enter"
+	prompt=$( printf "$msg_network_configuration" "$interface" )
+
+	#
+	# Loop forever until the user has finished configuring the different
+	# components of the network interface.
+	#
+	# To apply the settings, we need to know each of the following:
+	# 	- IP Address
+	# 	- Network subnet mask
+	# 	- Additional ifconfig(8) options
+	#
+	# It is only when we have all of the above values that we can make the
+	# changes effective because all three options must be specified at-once
+	# to ifconfig(8).
+	#
+	while :; do
+		local dhcp_status="$msg_disabled"
+		[ "$dhcp" ] && dhcp_status="$msg_enabled"
+
+		#
+		# Display configuration-edit menu
+		#
+		menu_list="
+			'X $msg_save_exit' '$msg_return_to_previous_menu'
+			'2 $msg_dhcp'      '$dhcp_status'
+			'3 $msg_ipaddr4'   '$ipaddr'
+			'4 $msg_netmask'   '$netmask'
+			'5 $msg_options'   '$options'
+		"
+		size=$( eval f_dialog_menu_size \
+		        	\"\$DIALOG_TITLE\"     \
+		        	\"\$DIALOG_BACKTITLE\" \
+		        	\"\$prompt\"           \
+		        	\"\$hline\"            \
+		        	$menu_list             )
+		eval $DIALOG \
+			--clear --title \"\$DIALOG_TITLE\" \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--menu \"\$prompt\" $size          \
+			$menu_list                         \
+			2> "$DIALOG_TMPDIR/dialog.menu.$$"
+
+		local retval=$?
+		local tag="$( f_dialog_menutag )"
+
+		# Return if "Cancel" was chosen (-1) or ESC was pressed (255)
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		#
+		# Call the below ``modifier functions'' whose job it is to take
+		# input from the user and assign the newly-acquired values back
+		# to the ipaddr, netmask, and options variables for us to re-
+		# read and display in the summary dialog.
+		#
+		case "$tag" in
+		X\ *) break;;
+		2\ *) #
+		      # Do not proceed if/when there are NFS-mounts currently
+		      # active. If the network is changed while NFS-exported
+		      # directories are mounted, the system may hang (if any
+		      # NFS mounts are using that interface).
+		      #
+		      if f_nfs_mounted && ! f_jailed; then
+		      	local setting="$( printf "$msg_current_dhcp_status" \
+		      	                         "$interface" "$dhcp_status" )"
+		      	local message="$(
+		      		printf "$msg_nfs_mounts_may_cause_hang" \
+		      		       "$setting"
+		      	)"
+		      	f_dialog_msgbox "$message"
+		      	continue
+		      fi
+
+		      #
+		      # Toggle DHCP status
+		      #
+		      if [ "$dhcp_status" = "$msg_enabled" ]; then
+		      	dhcp=
+		      else
+		      	trap - SIGINT
+		      	( # Execute within sub-shell to allow/catch Ctrl-C
+		      	  trap 'exit $FAILURE' SIGINT
+		      	  msg=$( printf "$msg_scanning_for_dhcp" "$interface" )
+		      	  if [ "$USE_XDIALOG" ]; then
+		      	  	(
+		      	  	  f_quietly ifconfig $interface delete
+		      	  	  f_quietly dhclient $interface
+		      	  	) |
+		      	  	  f_xdialog_info "$msg"
+		      	  else
+		      	  	f_dialog_info "$msg"
+		      	  	f_quietly ifconfig $interface delete
+		      	  	f_quietly dhclient $interface
+		      	  fi
+		      	)
+		      	retval=$?
+		      	trap 'interrupt' SIGINT
+		      	if [ $retval -eq $SUCCESS ]; then
+		      		dhcp=1
+		      		ipaddr=$( f_ifconfig_inet $interface )
+		      		netmask=$( f_ifconfig_netmask $interface )
+		      		options=
+
+		      		# Fixup search/domain in resolv.conf(5)
+		      		hostname=$( f_sysrc_get \
+				            	'hostname:-$(hostname)' )
+		      		f_dialog_resolv_conf_update "$hostname"
+		      	fi
+		      fi
+		      ;;
+		3\ *) f_dialog_input_ipaddr "$interface" "$ipaddr"
+		      [ $? -eq $SUCCESS ] && dhcp=;;
+		4\ *) f_dialog_input_netmask "$interface" "$netmask"
+		      [ $? -eq $SUCCESS -a "$_netmask" ] && dhcp=;;
+		5\ *) f_dialog_menu_media_options "$interface" "$options"
+		      [ $? -eq $SUCCESS ] && dhcp=;;
+		esac
+	done
+
+	#
+	# Save only if the user changed at least one feature of the interface
+	#
+	if [ "$ipaddr"  != "$ipaddr_orig"  -o \
+	     "$netmask" != "$netmask_orig" -o \
+	     "$options" != "$options_orig" -o \
+	     "$dhcp"    != "$dhcp_orig" ]
+	then
+		f_dialog_info "$( printf "$msg_saving_network_interface" \
+		                         "$interface" )"
+
+		local value=
+		if [ "$dhcp" ]; then
+			f_sysrc_delete defaultrouter
+			value=DHCP
+		else
+			value="inet $ipaddr netmask $netmask"
+			value="$value${options:+ }$options"
+		fi
+
+		f_sysrc_set ifconfig_$interface "$value"
+	fi
+
+	#
+	# Re/Apply the settings if desired
+	#
+	if [ ! "$dhcp" ]; then
+		f_dialog_yesno "Would you like to bring the $interface" \
+		               "interface up right now?"
+		if [ $? -eq $SUCCESS ]; then
+			f_dialog_info "$( printf "$msg_bring_interface_up" \
+			                         "$interface" )"
+
+			local dr="$( f_sysrc_get defaultrouter )" err
+			if [ "$dr" = "NO" -o ! "$dr" ]; then
+				dr=$( f_route_get_default )
+				[ "$dr" ] && f_sysrc_set defaultrouter "$dr"
+			fi
+			#
+			# Make a backup of resolv.conf(5) before using
+			# ifconfig(8) and then restore it afterward. This
+			# allows preservation of nameservers acquired via
+			# DHCP on FreeBSD-8.x (normally lost as ifconfig(8)
+			# usage causes dhclient(8) to exit which scrubs
+			# resolv.conf(5) by-default upon termination).
+			#
+			f_quietly cp -fp "$RESOLV_CONF" "$RESOLV_CONF.$$"
+			err=$( ifconfig $interface inet $ipaddr \
+			       	netmask $netmask $options 2>&1 )
+			if [ $? -eq $SUCCESS ]; then
+				if [ "$dr" -a "$dr" != "NO" ]; then
+					err=$( route add default "$dr" 2>&1 )
+					[ $? -eq $SUCCESS ] || \
+						dialog_msgbox "$err"
+				fi
+			else
+				dialog_msgbox "$err"
+			fi
+			if cmp -s "$RESOLV_CONF" "$RESOLV_CONF.$$"; then
+				f_quietly rm -f "$RESOLV_CONF.$$"
+			else
+				f_quietly mv -f "$RESOLV_CONF.$$" "$RESOLV_CONF"
+			fi
+		fi
+	fi
+
+	return $SUCCESS
+}
+
+fi # ! $_NETWORKING_DEVICE_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/hostname.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/hostname.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,211 @@
+if [ ! "$_NETWORKING_HOSTNAME_SUBR" ]; then _NETWORKING_HOSTNAME_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/hostname.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/sysrc.subr
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/resolv.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_validate_hostname $hostname
+#
+# Returns zero if the given argument (a fully-qualified hostname) is compliant
+# with standards set-forth in RFC's 952 and 1123 of the Network Working Group:
+#
+# RFC 952 - DoD Internet host table specification
+# http://tools.ietf.org/html/rfc952
+#
+# RFC 1123 - Requirements for Internet Hosts - Application and Support
+# http://tools.ietf.org/html/rfc1123
+#
+# See http://en.wikipedia.org/wiki/Hostname for a brief overview.
+#
+# The return status for invalid hostnames is one of:
+# 	255	Entire hostname exceeds the maximum length of 255 characters.
+# 	 63	One or more individual labels within the hostname (separated by
+# 	   	dots) exceeds the maximum of 63 characters.
+# 	  1	One or more individual labels within the hostname contains one
+# 	   	or more invalid characters.
+# 	  2	One or more individual labels within the hostname starts or
+# 	   	ends with a hyphen (hyphens are allowed, but a label cannot
+# 	   	begin or end with a hyphen).
+# 	  3	One or more individual labels within the hostname are null.
+#
+# If the hostname is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_msgbox function.
+#
+f_dialog_validate_hostname()
+{
+	local fqhn="$1"
+
+	( # Operate within a sub-shell to protect the parent environment
+
+		# Return error if the hostname exceeds 255 characters
+		[ ${#fqhn} -gt 255 ] && exit 255
+
+		IFS="." # Split on `dot'
+		for label in $fqhn; do
+
+			# Return error if the label exceeds 63 characters
+			[ ${#label} -gt 63 ] && exit 63
+
+			# Return error if the label is null
+			[ "$label" ] || exit 3
+
+			# Return error if label begins/ends with dash
+			case "$label" in
+			-*|*-) exit 2
+			esac
+
+			# Return error if the label contains any invalid chars
+			echo "$label" | grep -q '^[[:alnum:]-]*$' || exit 1
+
+		done
+	)
+
+	#
+	# Produce an appropriate error message if necessary.
+	#
+	local retval=$?
+	case $retval in
+	1) f_dialog_msgbox "$( printf \
+		"$msg_hostname_label_contains_invalid_chars" "$fqhn" )";;
+	2) f_dialog_msgbox "$( printf \
+		"$msg_hostname_label_starts_or_ends_with_hyphen" "$fqhn" )";;
+	3) f_dialog_msgbox "$( printf \
+		"$msg_hostname_label_is_null" "$fqhn" )";;
+	63) f_dialog_msgbox "$( printf \
+		"$msg_hostname_label_exceeds_max_length" "$fqhn" )";;
+	255) f_dialog_msgbox "$( printf \
+		"$msg_hostname_exceeds_max_length" "$fqhn" )";;
+	esac
+
+	return $retval
+}
+
+# f_dialog_input_hostname
+#
+# Edits the current hostname.
+#
+f_dialog_input_hostname()
+{
+	local hostname="$( f_sysrc_get 'hostname:-$(hostname)' )"
+	local hostname_orig="$hostname" # for change-tracking
+
+	local msg
+	if [ "$USE_XDIALOG" ]; then
+		msg="$xmsg_please_enter_fqhn"
+	else
+		msg="$msg_please_enter_fqhn"
+	fi
+
+	local hline="$hline_alnum_punc_tab_enter"
+
+	#
+	# Loop until the user provides taint-free input.
+	#
+	local size height width
+	while :; do
+
+		size=$( f_dialog_inputbox_size \
+		         	"$DIALOG_TITLE"     \
+		         	"$DIALOG_BACKTITLE" \
+		         	"$msg"              \
+		         	"$hostname"         \
+		         	"$hline"            )
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$hostname\"                     \
+			2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+		local retval=$?
+		hostname=$( f_dialog_inputstr )
+
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Taint-check the user's input
+		f_dialog_validate_hostname "$hostname" && break
+
+	done
+
+	#
+	# Save hostname only if the user changed the hostname.
+	#
+	if [ "$hostname" != "$hostname_orig" ]; then
+		f_dialog_info "$msg_saving_hostname"
+		f_sysrc_set hostname "$hostname"
+	fi
+
+	#
+	# Update resolv.conf(5) search/domain directives
+	#
+	f_dialog_resolv_conf_update "$hostname"
+
+	#
+	# Only ask to apply setting if the current hostname is different than
+	# the stored configuration (in rc.conf(5)).
+	#
+	if [ "$( hostname )" != "$( f_sysrc_get hostname )" ]; then
+		[ ! "$USE_XDIALOG" ] && dialog_clear
+
+		#
+		# If connected via ssh(1) and performing X11-Forwarding, don't
+		# allow the hostname to be changed to prevent the fatal error
+		# "X11 connection rejected because of wrong authentication."
+		#
+		if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" ]; then
+			f_dialog_msgbox "$(
+				printf "$msg_activate_hostname_x11warning" \
+				       "$( hostname )" "$hostname"
+			)"
+		else
+			f_dialog_yesno "$(
+				printf "$msg_activate_hostname" \
+				       "$( hostname )" "$hostname" \
+			)" \
+			&& hostname "$hostname"
+		fi
+	fi
+
+	return $SUCCESS
+}
+
+fi # ! $_NETWORKING_HOSTNAME_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/ipaddr.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/ipaddr.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,236 @@
+if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/ipaddr.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/sysrc.subr
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_ifconfig_inet $interface
+#
+# Returns the IPv4 address associated with $interface.
+#
+f_ifconfig_inet()
+{
+	local interface="$1"
+	ifconfig "$interface" 2> /dev/null | awk \
+	'
+		BEGIN { found = 0 }
+		( $1 == "inet" ) \
+		{
+			print $2
+			found = 1
+			exit
+		}
+		END { exit ! found }
+	'
+}
+
+# f_dialog_validate_ipaddr $ipaddr
+#
+# Returns zero if the given argument (an IP address) is of the proper format.
+#
+# The return status for invalid IP address is one of:
+# 	1	One or more individual octets within the IP address (separated
+# 	 	by dots) contains one or more invalid characters.
+# 	2	One or more individual octets within the IP address are null
+# 	 	and/or missing.
+# 	3	One or more individual octets within the IP address exceeds the
+# 	 	maximum of 255 (or 2^8, being an octet comprised of 8 bits).
+# 	4	The IP address has either too few or too many octets.
+#
+# If the IP address is determined to be invalid, the appropriate error will be
+# displayed using the above dialog_msgbox function.
+#
+f_dialog_validate_ipaddr()
+{
+	local ip="$1"
+
+	( # Operate within a sub-shell to protect the parent environment
+
+		# Track number of octets for error checking
+		noctets=0
+
+		IFS="." # Split on `dot'
+		for octet in $ip; do
+
+			# Return error if the octet is null
+			[ "$octet" ] || exit 2
+
+			# Return error if not a whole integer
+			f_isinteger "$octet" || exit 1
+
+			# Return error if not a positive integer
+			[ $octet -ge 0 ] || exit 1
+
+			# Return error if the octet exceeds 255
+			[ $octet -gt 255 ] && exit 3
+
+			noctets=$(( $noctets + 1 ))
+
+		done
+
+		[ $noctets -eq 4 ] || exit 4
+	)
+
+	#
+	# Produce an appropriate error message if necessary.
+	#
+	local retval=$?
+	case $retval in
+	1) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_addr_octet_contains_invalid_chars" "$ip" )";;
+	2) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_addr_octet_is_null" "$ip" )";;
+	3) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_addr_octet_exceeds_max_value" "$ip" )";;
+	4) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_addr_octet_missing_or_extra" "$ip" )";;
+	esac
+
+	return $retval
+}
+
+# f_dialog_input_ipaddr $interface $ipaddr
+#
+# Allows the user to edit a given IP address. If the user does not cancel or
+# press ESC, the $ipaddr environment variable will hold the newly-configured
+# value upon return.
+#
+# Optionally, the user can enter the format "IP_ADDRESS/NBITS" to set the
+# netmask at the same time as the IP address. If such a format is entered by
+# the user, the $netmask environment variable will hold the newly-configured
+# netmask upon return.
+#
+f_dialog_input_ipaddr()
+{
+	local interface="$1" _ipaddr="$2" _input
+
+	#
+	# Return with-error when there are NFS-mounts currently active. If the
+	# IP address is changed while NFS-exported directories are mounted, the
+	# system may hang (if any NFS mounts are using that interface).
+	#
+	if f_nfs_mounted && ! f_jailed; then
+		local setting="$( printf "$msg_current_ipaddr" \
+		                         "$interface" "$_ipaddr" )"
+		local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
+		                         "$setting" )"
+		f_dialog_msgbox "$message"
+		return $FAILURE
+	fi
+
+	local msg="$( printf "$msg_please_enter_new_ip_addr" "$interface" )"
+	local hline="$hline_num_punc_tab_enter"
+	local size="$( f_dialog_inputbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg"              \
+	               		"$_ipaddr"          \
+	               		"$hline"            )"
+
+	#
+	# Loop until the user provides taint-free input.
+	#
+	while :; do
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+		        --backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$_ipaddr\"                      \
+			2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+		local retval=$?
+		_input=$( f_dialog_inputstr )
+
+		#
+		# Return error status if:
+		# - User has not made any changes to the given value
+		# - User has either pressed ESC or chosen Cancel/No
+		#
+		[ "$_ipaddr" = "$_input" ] && return $FAILURE
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Return success if NULL value was entered
+		[ "$_input" ] || return $SUCCESS
+
+		# Take only the first "word" of the user's input
+		_ipaddr="$_input"
+		_ipaddr="${_ipaddr%%[$IFS]*}"
+
+		# Taint-check the user's input
+		f_dialog_validate_ipaddr "${_ipaddr%%/*}" && break
+	done
+
+	#
+	# Support the syntax: IP_ADDRESS/NBITS
+	#
+	local _netmask=""
+	case "$_ipaddr" in
+	*/*)
+		local nbits="${_ipaddr#*/}" n=0
+		_ipaddr="${_ipaddr%%/*}"
+
+		#
+		# Taint-check $nbits to be (a) a positive whole-integer,
+		# and (b) to be less than or equal to 32. Otherwise, set
+		# $n so that the below loop never executes.
+		#
+		( f_isinteger "$nbits" && [ $nbits -ge 0 -a $nbits -le 32 ] ) \
+			|| n=4
+
+		while [ $n -lt 4 ]; do
+			_netmask="$_netmask${_netmask:+.}$((
+				(65280 >> ($nbits - 8 * $n) & 255)
+				* ((8*$n) < $nbits & $nbits <= (8*($n+1)))
+				+ 255 * ($nbits > (8*($n+1)))
+			))"
+			n=$(( $n + 1 ))
+		done
+		;;
+	esac
+
+	ipaddr="$_ipaddr"
+	[ "$_netmask" ] && netmask="$_netmask"
+
+	return $SUCCESS
+}
+
+fi # ! $_NETWORKING_IPADDR_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/media.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/media.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,235 @@
+if [ ! "$_NETWORKING_MEDIA_SUBR" ]; then _NETWORKING_MEDIA_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/media.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_ifconfig_options $interface
+#
+# Returns any/all extra ifconfig(8) parameters associated with $interface.
+#
+f_ifconfig_options()
+{
+	local interface="$1"
+	[ "$interface" ] || return $SUCCESS
+
+	#
+	# Loop over the options, removing what we don't want
+	#
+	(
+		set -- $( f_sysrc_get ifconfig_$interface )
+
+		#
+		# Return if the the interface is configured for DHCP
+		#
+		glob="[Dd][Hh][Cc][Pp]"
+		case "$*" in
+		$glob|[Ss][Yy][Nn][Cc]$glob|[Nn][Oo][Ss][Yy][Nn][Cc]$glob)
+			exit $SUCCESS
+		esac
+
+		output=
+		while [ $# -gt 0 ]; do
+			case "$1" in
+			inet|netmask) shift 1;;
+			*) output="$output${output:+ }$1"
+			esac
+			shift 1
+		done
+		echo "$output"
+	)
+}
+
+# f_ifconfig_media $interface
+#
+# Returns list of supported media for $interface.
+#
+f_ifconfig_media()
+{
+	local interface="$1"
+	ifconfig -m "$interface" 2> /dev/null | awk \
+	'
+		BEGIN { media_found = 0 }
+		{
+			if ( media_found == 1 ) { print; next }
+		}
+		( $1 $2 == "supported" "media:" ) \
+		{
+			media_found = 1
+			next
+		}
+		END { exit ! media_found }
+	'
+}
+
+# f_dialog_input_options $interface
+#
+# Input custom interface options.
+#
+f_dialog_input_options()
+{
+	local interface="$1"
+
+	#
+	# Return with-error when there are NFS-mounts currently active. If the
+	# options are changed while NFS-exported directories are mounted,
+	# the system may hang (if any NFS mounts are using that interface).
+	#
+	if f_nfs_mounted && ! f_jailed; then
+		local setting="$( printf "$msg_current_options" \
+		                         "$interface" "$options" )"
+		local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
+		                         "$setting" )"
+		f_dialog_msgbox "$message"
+		return $FAILURE
+	fi
+
+	local msg="$( printf "$msg_please_enter_mediaopts" "$interface" )"
+	local hline="$hline_alnum_punc_tab_enter"
+
+	$DIALOG \
+		--title "$DIALOG_TITLE"         \
+		--backtitle "$DIALOG_BACKTITLE" \
+		--hline "$hline"                \
+		--ok-label "$msg_ok"            \
+		--cancel-label "$msg_cancel"    \
+		--inputbox "$msg" 9 70          \
+		"$options"                      \
+		2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+	local retval=$?
+	local _options="$( f_dialog_inputstr )"
+
+	[ $retval -eq $SUCCESS ] && options="$_options"
+
+	return $retval
+}
+
+# f_dialog_menu_media_options $interface
+#
+# Display a menu of additional media options for the given network interface.
+#
+f_dialog_menu_media_options()
+{
+	local interface="$1" _options="$2"
+	#
+	# Not all network interfaces support additional media options, but
+	# when available we should prompt the user to select from a list
+	# of available options (or none, as is the first/default option).
+	#
+
+	#
+	# Return with-error when there are NFS-mounts currently active. If the
+	# media options are changed while NFS-exported directories are mounted,
+	# the system may hang (if any NFS mounts are using that interface).
+	#
+	if f_nfs_mounted && ! f_jailed; then
+		local setting="$( printf "$msg_current_options" \
+		                         "$interface" "$_options" )"
+		local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
+		                         "$setting" )"
+		f_dialog_msgbox "$message"
+		return $FAILURE
+	fi
+
+	#
+	# Build list of additional media options
+	#
+	local opt_none="$msg_no_options"
+	local opt_cust="$msg_custom"
+	local supported_media="$(
+		f_ifconfig_media $interface | \
+		( index=1
+
+		  echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'"
+		  echo "'$opt_none'" 
+		  index=$(( $index + 1 ))
+
+		  echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'"
+		  echo "'$opt_cust'" 
+		  index=$(( $index + 1 ))
+
+		  while read media_options; do
+		  	[ $index -lt ${#DIALOG_MENU_TAGS} ] || break
+		  	echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'"
+		  	echo "'$media_options'"
+		  	index=$(( $index + 1 ))
+		  done
+		)
+	)"
+
+	local msg
+	if [ "$USE_XDIALOG" ]; then
+		msg=$( printf "$xmsg_supported_media_options" \
+		       		"$interface" "$interface" )
+	else
+		msg=$( printf "$msg_supported_media_options" \
+		       		"$interface" "$interface" )
+	fi
+
+	local hline="$hline_arrows_tab_enter"
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$msg\" 21 60 12          \
+		$supported_media                   \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+
+	local retval=$?
+	if [ $retval -eq $SUCCESS ]; then
+		local tag="$( f_dialog_menutag )"
+		options=$( eval f_dialog_menutag2item \"\$tag\" \
+		                                      $supported_media )
+		[ "$options" = "$opt_none" ] && options=
+
+		if [ "$options" = "$opt_cust" ]; then
+			options="$_options"
+			f_dialog_input_options "$interface"
+			retval=$?
+		fi
+	fi
+
+	return $retval
+}
+
+fi # ! $_NETWORKING_MEDIA_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,100 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+hline_num_punc_tab_enter="Use numbers, punctuation, TAB or ENTER"
+msg_activate_default_router="Would you like to activate the new defaultrouter right now?\nIf you choose NO or press ESC, changes will be applied\nduring the next boot.\n\n     Current Default Router: %s\n         New Default Router: %s\n"
+msg_activate_hostname="Would you like to activate the new hostname right now?\nIf you choose NO or press ESC, changes will be applied\nduring the next boot.\n\n     Current Hostname: %s\n         New Hostname: %s\n\nNOTE: Your shell prompt may still reflect the original\nhostname until your next login."
+msg_activate_hostname_x11warning="WARNING! Activating the new hostname during an X11-Forwarded\n ssh(1) session will cause an X11 authentication error.\n\n     Current Hostname: %s\n         New Hostname: %s\n\nNOTE: Settings will become active upon reboot or if you\n relaunch this utility either locally or on the console."
+msg_add="Add"
+msg_add_nameserver="Add a new nameserver"
+msg_bring_interface_up="Would you like to bring the %s interface up right now?"
+msg_cancel="Cancel"
+msg_current_default_router="Current Default Route/Gateway: %s"
+msg_current_dhcp_status="Current DHCP status for %s: %s"
+msg_current_ipaddr="Current IP Address for %s: %s"
+msg_current_options="Current Options for %s: %s"
+msg_current_subnet="Current Subnet Mask for %s: %s"
+msg_custom="Custom (Manual)"
+msg_default_router="Default Router/Gateway"
+msg_dhcp="DHCP"
+msg_disabled="Disabled"
+msg_dns_configuration="DNS Nameserver Configuration:\nChoose Exit when finished else Cancel."
+msg_dns_nameservers="DNS nameservers"
+msg_enabled="Enabled"
+msg_exit="Exit"
+msg_hostname_domain="Hostname/Domain"
+msg_hostname_exceeds_max_length="ERROR! The hostname entered exceeds the maximum length of\n255 characters.\n\nInvalid Hostname: %s"
+msg_hostname_label_contains_invalid_chars="ERROR! One or more individual labels within the hostname\n(separated by dots) contains one or more invalid characters.\nLabels are case-insensitive and must contain only 0-9, a-z,\n or dash (though must not begin with or end with a dash).\n\nInvalid Hostname: %s"
+msg_hostname_label_exceeds_max_length="ERROR! One or more individual labels within the hostname\n(separated by dots) exceeds the maximum of 63 characters.\n\nInvalid Hostname: %s"
+msg_hostname_label_is_null="ERROR! One or more individual labels within the hostname\n(separated by dots) are null.\n\nInvalid Hostname: %s"
+msg_hostname_label_starts_or_ends_with_hyphen="ERROR! One or more individual labels within the hostname\n(separated by dots) starts or ends with a hyphen (hyphens\nare allowed, but a label cannot begin or end with a hyphen).\n\nInvalid Hostname: %s"
+msg_internal_error_nsindex_value="FATAL! dialog_input_nameserver_edit_awk: variable\nnsindex must be a whole positive integer greater-\nthan or equal-to zero.\n\nInvalid nsindex: %s"
+msg_ipaddr4="ipaddr"
+msg_ipv4_addr_octet_contains_invalid_chars="ERROR! One or more individual octets within the IP address\n(separated by dots) contains one or more invalid characters.\nOctets must contain only the characters 0-9.\n\nInvalid IP Address: %s"
+msg_ipv4_addr_octet_exceeds_max_value="ERROR! One or more individual octets within the IP address\n(separated by dots) exceeds the maximum of 255.\n\nInvalid IP Address: %s"
+msg_ipv4_addr_octet_is_null="ERROR! One or more individual octets within the IP address\n(separated by dots) are null and/or missing.\n\nInvalid IP Address: %s"
+msg_ipv4_addr_octet_missing_or_extra="ERROR! The IP address entered has either too few or too many\noctets.\n\nInvalid IP Address: %s"
+msg_ipv4_mask_field_contains_invalid_chars="ERROR! One or more individual fields within the subnet mask\n(separated by dots) contains one or more invalid characters.\n\nInvalid Subnet Mask: %s"
+msg_ipv4_mask_field_exceeds_max_value="ERROR! One or more individual fields within the subnet mask\n(separated by dots) exceeds the maximum of 255.\n\nInvalid Subnet Mask: %s"
+msg_ipv4_mask_field_invalid_value="ERROR! One or more individual fields within the subnet mask\n(separated by dots) contains one or more invalid integers.\nFields must be one of 0/128/192/224/240/248/252/254/255.\n\nInvalid Subnet Mask: %s"
+msg_ipv4_mask_field_is_null="ERROR! One or more individual fields within the subnet mask\n(separated by dots) are null and/or missing.\n\nInvalid Subnet Mask: %s"
+msg_ipv4_mask_field_missing_or_extra="ERROR! The subnet mask entered has either too few or too many\nfields.\n\nInvalid Subnet Mask: %s"
+msg_netmask="netmask"
+msg_network_configuration="%s Network Configuration:\nChoose Save/Exit when finished or Cancel."
+msg_network_interfaces="Network Interfaces"
+msg_network_management="Network Management"
+msg_networking_devices="Networking Devices"
+msg_nfs_mounts_may_cause_hang="WARNING! Changing this setting while NFS directories are\nmounted may cause the system to hang. Please exit this\nutility and dismount any/all remaining NFS-mounts before\nattempting to change this setting.\n\n%s"
+msg_no_network_interfaces="No network interfaces detected."
+msg_no_options="No options (Default)"
+msg_ok="OK"
+msg_options="options"
+msg_please_enter_default_router="Please enter the IP address of your default\nrouter/gateway.  The address entered will be\napplied as the default gateway for all interfaces\nusing route(4)."
+msg_please_enter_fqhn="Please enter your fully qualified hostname (e.g. full.example.com). The\ndomain portion of the hostname will be configured in resolv.conf(5)."
+msg_please_enter_mediaopts="Please enter additional network media options to be passed to ifconfig(8) for the %s interface:"
+msg_please_enter_nameserver="Please enter the new IP address of the DNS nameserver:"
+msg_please_enter_nameserver_existing="Please enter the new IP address of the DNS nameserver\n(set to the NULL string [Ctrl-U] to remove entry):"
+msg_please_enter_new_ip_addr="Please enter the new IP address of the %s interface:"
+msg_please_enter_subnet_mask="Please enter the new network subnet mask for the %s interface:"
+msg_probing_network_interfaces="Probing network interface devices..."
+msg_removing_nameserver="Removing DNS nameserver from resolv.conf(5)..."
+msg_resolv_conf_changed_while_editing="ERROR! resolv.conf(5) has changed while editing this\nvalue. Please try again after waiting a few seconds."
+msg_resolv_conf_entry_no_longer_exists="ERROR! The entry you are trying to edit no longer\nexists in resolv.conf(5). Please try again after\nwaiting a few seconds."
+msg_return_to_previous_menu="Return to previous menu"
+msg_save_exit="Save/Exit"
+msg_saving_default_router="Saving new default router/gateway settings..."
+msg_saving_hostname="Saving new hostname/domain settings..."
+msg_saving_nameserver="Saving new DNS nameserver to resolv.conf(5)..."
+msg_saving_nameserver_existing="Editing DNS nameserver in resolv.conf(5)..."
+msg_saving_network_interface="Saving %s network interface settings..."
+msg_scanning_for_dhcp="Scanning for DHCP servers on %s interface..."
+msg_select_network_interface="Select a network interface to configure.\n\n* Interface is marked as \"active\""
+msg_supported_media_options="Below is a list of supported media options for the %s interface. Please select the options that you would like to set for the %s network interface"
+xmsg_please_enter_fqhn="Please enter your fully qualified hostname (e.g. foo.bar.com).\n The domain portion of the hostname will be configured in resolv.conf(5)."
+xmsg_please_enter_nameserver_existing="Please enter the new IP address of the DNS nameserver\n(set to the NULL string to remove entry):"
+xmsg_supported_media_options="Below is a list of supported media options for the %s interface. Please\nselect the options that you would like to set for the %s network interface"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/netmask.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/netmask.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,215 @@
+if [ ! "$_NETWORKING_NETMASK_SUBR" ]; then _NETWORKING_NETMASK_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/netmask.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_ifconfig_netmask $interface
+#
+# Returns the IPv4 subnet mask associated with $interface.
+#
+f_ifconfig_netmask()
+{
+	local interface="$1" octets
+	octets=$( ifconfig "$interface" 2> /dev/null | awk \
+	'
+		BEGIN { found = 0 }
+		( $1 == "inet" ) \
+		{
+			printf "%s %s %s %s\n",
+				substr($4,3,2),
+				substr($4,5,2),
+				substr($4,7,2),
+				substr($4,9,2)
+			found = 1
+			exit
+		}
+		END { exit ! found }
+	' ) || return $FAILURE
+
+	local octet netmask=
+	for octet in $octets; do
+		netmask="$netmask${netmask:+.}$( printf "%u" "0x$octet" )"
+	done
+	echo $netmask
+}
+
+# f_dialog_validate_netmask $netmask
+#
+# Returns zero if the given argument (a subnet mask) is of the proper format.
+#
+# The return status for invalid IP address is one of:
+# 	1	One or more individual fields within the subnet mask (separated
+# 	 	by dots) contains one or more invalid characters.
+# 	2	One or more individual fields within the subnet mask are null
+# 	 	and/or missing.
+# 	3	One or more individual fields within the subnet mask exceeds
+# 	 	the maximum of 255 (a full 8-bit register).
+# 	4	The subnet mask has either too few or too many fields.
+# 	5	One or more individual fields within the subnet mask is an
+# 	 	invalid integer (only 0,128,192,224,240,248,252,254,255 are
+# 	 	valid integers).
+#
+# If the subnet mask is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_msgbox function.
+#
+f_dialog_validate_netmask()
+{
+	local mask="$1"
+
+	( # Operate within a sub-shell to protect the parent environment
+
+		# Track number of fields for error checking
+		nfields=0
+
+		IFS="." # Split on `dot'
+		for field in $mask; do
+
+			# Return error if the field is null
+			[ "$field" ] || exit 2
+
+			# Return error if not a whole positive integer
+			f_isinteger "$field" || exit 1
+
+			# Return error if the field exceeds 255
+			[ $field -gt 255 ] && exit 3
+
+			# Return error if the field is an invalid integer
+			case "$field" in
+			0|128|192|224|240|248|252|254|255) :;;
+			*) exit 5;;
+			esac
+
+			nfields=$(( $nfields + 1 ))
+
+		done
+
+		[ $nfields -eq 4 ] || exit 4
+	)
+
+	#
+	# Produce an appropriate error message if necessary.
+	#
+	local retval=$?
+	case $retval in
+	1) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_mask_field_contains_invalid_chars" "$mask" )";;
+	2) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_mask_field_is_null" "$mask" )";;
+	3) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_mask_field_exceeds_max_value" "$mask" )";;
+	4) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_mask_field_missing_or_extra" "$mask" )";;
+	5) f_dialog_msgbox "$( printf \
+		"$msg_ipv4_mask_field_invalid_value" "$mask" )";;
+	esac
+
+	return $retval
+}
+
+# f_dialog_input_netmask $interface $netmask
+#
+# Edits the IP netmask of the given interface.
+#
+f_dialog_input_netmask()
+{
+	local interface="$1" _netmask="$2" _input
+
+	#
+	# Return with-error when there are NFS-mounts currently active. If the
+	# subnet mask is changed while NFS-exported directories are mounted,
+	# the system may hang (if any NFS mounts are using that interface).
+	#
+	if f_nfs_mounted && ! f_jailed; then
+		local setting="$( printf "$msg_current_subnet" \
+		                         "$interface" "$_netmask" )"
+		local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
+		                         "$setting" )"
+		f_dialog_msgbox "$message"
+		return $FAILURE
+	fi
+
+	local msg="$( printf "$msg_please_enter_subnet_mask" "$interface" )"
+	local hline="$hline_num_punc_tab_enter"
+	local size="$( f_dialog_inputbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg"              \
+	               		"$_netmask"         \
+	               		"$hline"            )"
+
+	#
+	# Loop until the user provides taint-free input.
+	#
+	while :; do
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+		        --backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$_netmask\"                     \
+			2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+		local retval=$?
+		_input=$( f_dialog_inputstr )
+
+		#
+		# Return error status if:
+		# - User has not made any changes to the given value
+		# - User has either pressed ESC or chosen Cancel/No
+		#
+		[ "$_netmask" = "$_input" ] && return $FAILURE
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Return success if NULL value was entered
+		[ "$_input" ] || return $SUCCESS
+
+		# Take only the first "word" of the user's input
+		_netmask="$_input"
+		_netmask="${_netmask%%[$IFS]*}"
+
+		# Taint-check the user's input
+		f_dialog_validate_netmask "$_netmask" && break
+	done
+
+	netmask="$_netmask"
+}
+
+fi # ! $_NETWORKING_NETMASK_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/resolv.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/resolv.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,509 @@
+if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/resolv.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/ipaddr.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Path to resolv.conf(5).
+#
+: ${RESOLV_CONF:="/etc/resolv.conf"}
+
+#
+# When updating resolv.conf(5), should we populate the `search' directive with
+# all possible sub-domains? In example, if the domain is "sub.domain.com", when
+# the below option is set to 1, include both "sub.domain.com" and "domain.com"
+# in the `search' directive, otherwise use only "sub.domain.com".
+#
+# When enabled (set to 1), specify the minimum number of dots required for each
+# `search' domain by setting the second option below, `RESOLVER_SEARCH_NDOTS'.
+#
+: ${RESOLVER_SEARCH_DOMAINS_ALL:=1}
+: ${RESOLVER_SEARCH_NDOTS:=1}
+
+############################################################ FUNCTIONS
+
+# f_resolv_conf_domain
+#
+# Returns the domain configured in resolv.conf(5).
+#
+f_resolv_conf_domain()
+{
+	tail -r "$RESOLV_CONF" 2> /dev/null | awk \
+	'
+		BEGIN { found = 0 }
+		( tolower($1) == "domain" ) \
+		{
+			print $2
+			found = 1
+			exit
+		}
+		END { exit ! found }
+	'
+}
+
+# f_resolv_conf_search
+#
+# Returns the search configured in resolv.conf(5).
+#
+f_resolv_conf_search()
+{
+	tail -r "$RESOLV_CONF" 2> /dev/null | awk \
+	'
+		BEGIN { found = 0 }
+		{
+			tl0 = tolower($0)
+			if ( match(tl0, /^[[:space:]]*search[[:space:]]+/) ) {
+				search = substr($0, RLENGTH + 1)
+				sub(/[[:space:]]*#.*$/, "", search)
+				gsub(/[[:space:]]+/, " ", search)
+				print search
+				found = 1
+				exit
+			}
+		}
+		END { exit ! found }
+	'
+}
+
+# f_resolv_conf_nameservers
+#
+# Returns nameserver(s) configured in resolv.conf(5).
+#
+f_resolv_conf_nameservers()
+{
+	awk \
+	'
+		BEGIN { found = 0 }
+		( $1 == "nameserver" ) \
+		{
+			print $2
+			found = 1
+		}
+		END { exit ! found }
+	' \
+	"$RESOLV_CONF" 2> /dev/null
+}
+
+# f_dialog_resolv_conf_update $hostname
+#
+# Updates the search/domain directives in resolv.conf(5) given a valid fully-
+# qualified hostname.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_dialog_resolv_conf_update_awk='
+# Variables that should be defined on the invocation line:
+# 	-v domain="domain"
+# 	-v search_all="0|1"
+# 	-v search_ndots="1+"
+#
+BEGIN {
+	domain_found = search_found = 0
+
+	if ( search_all ) {
+		search = ""
+		subdomain = domain
+		if ( search_ndots < 1 )
+			search_ndots = 1
+
+		ndots = split(subdomain, labels, ".") - 1
+		while ( ndots-- >= search_ndots ) {
+			if ( length(search) ) search = search " "
+			search = search subdomain
+			sub(/[^.]*\./, "", subdomain)
+		}
+	}
+	else search = domain
+}
+{
+	if ( domain_found && search_found ) { print; next }
+
+	tl0 = tolower($0)
+	if ( ! domain_found && \
+	     match(tl0, /^[[:space:]]*domain[[:space:]]+/) ) \
+	{
+		if ( length(domain) ) {
+			printf "%s%s\n", substr($0, 0, RLENGTH), domain
+			domain_found = 1
+		}
+	}
+	else if ( ! search_found && \
+	          match(tl0, /^[[:space:]]*search[[:space:]]+/) ) \
+	{
+		if ( length(search) ) {
+			printf "%s%s\n", substr($0, 0, RLENGTH), search
+			search_found = 1
+		}
+	}
+	else print
+}
+END {
+	if ( ! search_found && length(search) )
+		printf "search\t%s\n", search
+	if ( ! domain_found && length(domain) )
+		printf "domain\t%s\n", domain
+}
+'
+f_dialog_resolv_conf_update()
+{
+	local hostname="$1"
+
+	#
+	# Extrapolate the desired domain search parameter for resolv.conf(5)
+	#
+	local search ndots domain="${hostname#*.}"
+	if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then
+		search=""
+		ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) )
+		while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do
+			search="$search${search:+ }$domain"
+			domain="${domain#*.}"
+			ndots=$(( $ndots - 1 ))
+		done
+		domain="${hostname#*.}"
+	else
+		search="$domain"
+	fi
+
+	#
+	# Save domain/search information only if different from resolv.conf(5)
+	#
+	if [ "$domain" != "$( f_resolv_conf_domain )" -o \
+	     "$search" != "$( f_resolv_conf_search )" ]
+	then
+		f_dialog_info "Saving new domain/search settings" \
+		              "to resolv.conf(5)..."
+
+		#
+		# Create a new temporary file to write our resolv.conf(5)
+		# update with our new `domain' and `search' directives.
+		#
+		local tmpfile="$( mktemp -t "$pgm" )"
+		[ "$tmpfile" ] || return $FAILURE
+
+		#
+		# Fixup permissions and ownership (mktemp(1) creates the
+		# temporary file with 0600 permissions -- change the
+		# permissions and ownership to match resolv.conf(5) before
+		# we write it out and mv(1) it into place).
+		#
+		local mode="$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )"
+		local owner="$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )"
+		f_quietly chmod "${mode:-0644}" "$tmpfile"
+		f_quietly chown "${owner:-root:wheel}" "$tmpfile"
+
+		#
+		# Operate on resolv.conf(5), replacing only the last
+		# occurrences of `domain' and `search' directives (or add
+		# them to the top if not found), in strict-adherence to the
+		# following entry in resolver(5):
+		#
+		# 	The domain and search keywords are mutually exclusive.
+		# 	If more than one instance of these keywords is present,
+		# 	the last instance will override.
+		#
+		# NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the
+		# environment, all sub-domains will be added to the `search'
+		# directive, not just the FQDN.
+		#
+		local domain="${hostname#*.}" new_contents
+		[ "$domain" = "$hostname" ] && domain=
+		new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null )
+		new_contents=$( echo "$new_contents" | awk \
+			-v domain="$domain" \
+			-v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \
+			-v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \
+			"$f_dialog_resolv_conf_update_awk" )
+
+		#
+		# Write the temporary file contents and move the temporary
+		# file into place.
+		#
+		echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE
+		f_quietly mv "$tmpfile" "$RESOLV_CONF"
+
+	fi
+}
+
+# f_dialog_input_nameserver [ $n $nameserver ]
+#
+# Allows the user to edit a given nameserver. The first argument is the
+# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one
+# if editing the first nameserver instance, two if editing the second, three if
+# the third, ad nauseum. If this argument is zero, null, or missing, the value
+# entered by the user (if non-null) will be added to resolv.conf(5) as a new
+# `nameserver' entry. The second argument is the IPv4 address of the nameserver
+# to be edited -- this will be displayed as the initial value during the edit.
+#
+# Taint-checking is performed when editing an existing entry (when the second
+# argument is one or higher) in that the first argument must match the current
+# value of the Nth `nameserver' instance in resolv.conf(5) else an error is
+# generated discarding any/all changes.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_dialog_input_nameserver_edit_awk='
+# Variables that should be defined on the invocation line:
+# 	-v nsindex="1+"
+# 	-v old_value="..."
+# 	-v new_value="..."
+#
+BEGIN {
+	if ( nsindex < 1 ) exit 1
+	found = n = 0
+}
+{
+	if ( found ) { print; next }
+
+	if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) {
+		if ( ++n == nsindex ) {
+			if ( $2 != old_value ) exit 2
+			if ( new_value != "" ) printf "%s%s\n", \
+				substr($0, 0, RLENGTH), new_value
+			found = 1
+		}
+		else print
+	}
+	else print
+}
+END { if ( ! found ) exit 3 }
+'
+f_dialog_input_nameserver()
+{
+	local index="${1:-0}" old_ns="$2" new_ns
+	local ns="$old_ns"
+
+	#
+	# Perform sanity checks
+	#
+	f_isinteger "$index" || return $FAILURE
+	[ $index -ge 0 ] || return $FAILURE
+
+	local msg
+	if [ $index -gt 0 ]; then
+		if [ "$USE_XDIALOG" ]; then
+			msg="$xmsg_please_enter_nameserver_existing"
+		else
+			msg="$msg_please_enter_nameserver_existing"
+		fi
+	else
+		msg="$msg_please_enter_nameserver"
+	fi
+
+	local hline="$hline_num_punc_tab_enter"
+	local size="$( f_dialog_inputbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg"              \
+	               		"$ns"               \
+	               		"$hline"            )"
+
+	#
+	# Loop until the user provides taint-free input.
+	#
+	while :; do
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+		        --backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$ns\"                           \
+			2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+		local retval=$?
+		new_ns=$( f_dialog_inputstr )
+
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Take only the first "word" of the user's input
+		new_ns="${new_ns%%[$IFS]*}"
+
+		# Taint-check the user's input
+		[ "$new_ns" ] || break
+		f_dialog_validate_ipaddr "$new_ns" && break
+
+		# Update prompt to allow user to re-edit previous entry
+		ns="$new_ns"
+
+	done
+
+	#
+	# Save only if the user changed the nameserver.
+	#
+	if [ $index -eq "0" -a "$new_ns" ]; then
+		f_dialog_info "$msg_saving_nameserver"
+		printf "nameserver\t%s\n" "$new_ns" >> "$RESOLV_CONF"
+		return $SUCCESS
+	elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then
+		if [ "$new_ns" ]; then
+			msg="$msg_saving_nameserver_existing"
+		else
+			msg="$msg_removing_nameserver"
+		fi
+		f_dialog_info "$msg"
+
+		#
+		# Create a new temporary file to write our new resolv.conf(5)
+		#
+		local tmpfile="$( mktemp -t "$pgm" )"
+		[ "$tmpfile" ] || return $FAILURE
+
+		#
+		# Quietly fixup permissions and ownership
+		#
+		local mode owner
+		mode=$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )
+		owner=$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )
+		f_quietly chmod "${mode:-0644}" "$tmpfile"
+		f_quietly chown "${owner:-root:wheel}" "$tmpfile"
+
+		#
+		# Operate on resolv.conf(5)
+		#
+		local new_contents
+		new_contents=$( awk -v nsindex="$index"    \
+		                    -v old_value="$old_ns" \
+		                    -v new_value="$new_ns" \
+		                    "$f_dialog_input_nameserver_edit_awk" \
+		                    "$RESOLV_CONF" )
+
+		#
+		# Produce an appropriate error message if necessary.
+		#
+		local retval=$?
+		case $retval in
+		1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex";;
+		2) f_dialog_msgbox "$msg_resolv_conf_changed_while_editing"
+		   return $retval;;
+		3) f_dialog_msgbox "$msg_resolv_conf_entry_no_longer_exists"
+		   return $retval;;
+		esac
+
+		#
+		# Write the temporary file contents and move the temporary
+		# file into place.
+		#
+		echo "$new_contents" > "$tmpfile" || return $FAILURE
+		f_quietly mv "$tmpfile" "$RESOLV_CONF"
+	fi
+}
+
+# f_dialog_menu_nameservers
+#
+# Edit the nameservers in resolv.conf(5).
+#
+f_dialog_menu_nameservers()
+{
+	local opt_exit="$msg_return_to_previous_menu"
+	local opt_add="$msg_add_nameserver"
+	local hline="$hline_arrows_tab_enter"
+	local prompt size
+
+	#
+	# Loop forever until the user has finished configuring nameservers
+	#
+	prompt="$msg_dns_configuration"
+	while :; do
+		#
+		# Re/Build list of nameservers
+		#
+		local nameservers="$( f_resolv_conf_nameservers )"
+		local menu_list="$(
+			index=1
+
+			echo "'X $msg_exit' '$opt_exit'" 
+			index=$(( $index + 1 ))
+
+			echo "'A $msg_add'  '$opt_add'" 
+			index=$(( $index + 1 ))
+
+			for ns in $nameservers; do
+				[ $index -lt ${#DIALOG_MENU_TAGS} ] || break
+				tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
+				echo "'$tag nameserver' '$ns'"
+				index=$(( $index + 1 ))
+			done
+		)"
+
+		#
+		# Display configuration-edit menu
+		#
+		size=$( eval f_dialog_menu_size \
+		        	\"\$DIALOG_TITLE\"     \
+		        	\"\$DIALOG_BACKTITLE\" \
+		        	\"\$prompt\"           \
+		        	\"\$hline\"            \
+		        	$menu_list             )
+		eval $DIALOG \
+			--clear --title \"\$DIALOG_TITLE\" \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--menu \"\$prompt\" $size          \
+			$menu_list                         \
+			2> "$DIALOG_TMPDIR/dialog.menu.$$"
+
+		local retval=$?
+		local tag="$( f_dialog_menutag )" ns=""
+
+		# Return if "Cancel" was chosen (-1) or ESC was pressed (255)
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		case "$tag" in
+		"X $msg_exit") break;;
+		"A $msg_add")
+			f_dialog_input_nameserver
+			;;
+		*)
+			n=$( eval f_dialog_menutag2index \"\$tag\" $menu_list )
+			ns=$( eval f_dialog_menutag2item \"\$tag\" $menu_list )
+			f_dialog_input_nameserver $(( $n - 2 )) "$ns"
+			;;
+		esac
+	done
+}
+
+fi # ! $_NETWORKING_RESOLV_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/include/routing.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/include/routing.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,168 @@
+if [ ! "$_NETWORKING_ROUTING_SUBR" ]; then _NETWORKING_ROUTING_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/include/routing.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/sysrc.subr
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/common.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/ipaddr.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_route_get_default
+#
+# Returns the IP address of the currently active default router.
+#
+f_route_get_default()
+{
+	route -n get default 2> /dev/null | awk \
+	'
+		BEGIN { found = 0 }
+		( $1 == "gateway:" ) \
+		{
+			print $2
+			found = 1
+			exit
+		}
+		END { exit ! found }
+	'
+}
+
+# f_dialog_input_defaultrouter
+#
+# Edits the default router.
+#
+f_dialog_input_defaultrouter()
+{
+	#
+	# Get the defaultrouter. When this is not configured, the default is
+	# "NO", however we don't ever want to present this default to the user
+	# in the following dialog. If the current value is "NO", then try to
+	# obtain the value from the running system using route(8).
+	#
+	# NOTE: Our `f_route_get_default' function will return NULL if the
+	# system does not have an active default router set (which is what we
+	# want).
+	#
+	local defaultrouter="$( f_sysrc_get 'defaultrouter:-NO' )"
+	local defaultrouter_orig="$defaultrouter" # for change-tracking
+	case "$defaultrouter" in
+	[Nn][Oo])
+		defaultrouter=$( f_route_get_default )
+		;;
+	esac
+
+	#
+	# Return with-error when there are NFS-mounts currently active. If the
+	# default router/gateway is changed while NFS-exported directories are
+	# mounted, the system will hang.
+	#
+	if f_nfs_mounted && ! f_jailed; then
+		local setting="$( printf "$msg_current_default_router" \
+		                         "$defaultrouter" )"
+		local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
+		                         "$setting" )"
+		f_dialog_msgbox "$message"
+		return $FAILURE
+	fi
+
+	local msg="$msg_please_enter_default_router"
+	local hline="$hline_num_punc_tab_enter"
+	local size="$( f_dialog_inputbox_size \
+	               		"$DIALOG_TITLE"     \
+	               		"$DIALOG_BACKTITLE" \
+	               		"$msg"              \
+	               		"$defaultrouter"    \
+	               		"$hline"            )"
+
+	#
+	# Loop until the user provides taint-free input.
+	#
+	while :; do
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$defaultrouter\"                \
+			2> "$DIALOG_TMPDIR/dialog.inputbox.$$"
+
+		local retval=$?
+		defaultrouter=$( f_dialog_inputstr )
+
+		[ "$defaultrouter" ] || return $SUCCESS
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Taint-check the user's input
+		f_dialog_validate_ipaddr "$defaultrouter" && break
+	done
+
+	#
+	# Save only if the user changed the default router/gateway.
+	#
+	if [ "$defaultrouter" != "$defaultrouter_orig" ]; then
+		f_dialog_info "$msg_saving_default_router"
+
+		# Save the default router/gateway
+		f_sysrc_set defaultrouter "$defaultrouter"
+	fi
+
+	#
+	# Only ask to apply setting if the current defaultrouter is different
+	# than the stored configuration (in rc.conf(5)).
+	#
+	if [ "$( f_route_get_default )" != "$defaultrouter" ]; then
+		f_dialog_clear
+		f_dialog_yesno "$(
+			printf "$msg_activate_default_router" \
+			       "$( f_route_get_default )" "$defaultrouter"
+		)"
+
+		if [ $? -eq $SUCCESS ]; then
+			local err
+
+			# Apply the default router/gateway
+			f_quietly route delete default
+			err=$( route add default "$defaultrouter" 2>&1 )
+			if [ $? -ne $SUCCESS ]; then
+				f_dialog_msgbox "$err"
+				return $FAILURE
+			fi
+		fi
+	fi
+}
+
+fi # ! $_NETWORKING_ROUTING_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/nameservers
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/nameservers	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,73 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/nameservers 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="120.networking"
+f_include $BSDCFG_LIBE/$APP_DIR/include/resolv.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_dns_nameservers"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Change the DNS nameservers
+#
+f_dialog_menu_nameservers
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/networking/networking
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/networking/networking	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,146 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/networking/networking 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_arrows_tab_enter"
+
+	menu_list="
+		'X' '$msg_exit'
+		'1' '$msg_hostname_domain'
+		'2' '$msg_network_interfaces'
+		'3' '$msg_default_router'
+		'4' '$msg_dns_nameservers'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\"                   \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\" $size $menu_list       \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_network_management"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	X) # Exit
+	   break
+	   ;;
+
+	1) # Hostname/Domain
+	   $BSDCFG_LIBE/$APP_DIR/hostname ${USE_XDIALOG:+-X}
+	   ;;
+
+	2) # Network Interfaces
+	   $BSDCFG_LIBE/$APP_DIR/devices ${USE_XDIALOG:+-X}
+
+	   # Make subsequent uses of this menu faster by not performing
+	   # "ifconfig up" (limiting the pain one must endure). See also
+	   # `$BSDCFG_LIBE/$APP_DIR/include/device.subr'.
+	   #
+	   export DIALOG_MENU_NETDEV_KICK_INTERFACES=
+	   ;;
+
+	3) # Default Router/Gateway
+	   $BSDCFG_LIBE/$APP_DIR/defaultrouter ${USE_XDIALOG:+-X}
+	   ;;
+
+	4) # DNS nameservers
+	   $BSDCFG_LIBE/$APP_DIR/nameservers ${USE_XDIALOG:+-X}
+	   ;;
+
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/password/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Root Password"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Set the system manager's password"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="password|password"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="password"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/password/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/040.password
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	password
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/password/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/password/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/040.password/include
+FILES=		messages.subr password.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,35 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/password/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+msg_cancel="Cancel"
+msg_ok="OK"
+msg_password="Password"
+msg_password_changed="Password successfully changed."
+msg_password_is_empty="Password is empty."
+msg_passwords_do_not_match="Passwords do not match."
+msg_reenter_password="Re-enter Password"
+msg_root_password="Root Password"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/include/password.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/include/password.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,122 @@
+if [ ! "$_PASSWORD_PASSWORD_SUBR" ]; then _PASSWORD_PASSWORD_SUBR=1
+#
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/password/include/password.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+APP_DIR="040.password"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_input_password
+#
+# Prompt the user to enter a password (twice). If the user does not cancel or
+# press ESC, the $pw_password environment variable will hold the password.
+#
+f_dialog_input_password()
+{
+	local hline="$hline_alnum_punc_tab_enter"
+	local msg size rmsg rsize
+
+	msg=$( printf "$msg_password" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	""                  \
+	        	"$hline"            )
+
+	rmsg=$( printf "$msg_reenter_password" )
+	rsize=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$rmsg"             \
+	        	""                  \
+	        	"$hline"            )
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local retval _password1 _password2
+	while :; do
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--insecure                         \
+			--passwordbox \"\$msg\" $size      \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_password1=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--insecure                         \
+			--passwordbox \"\$rmsg\" $rsize    \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_password2=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Check for NULL entry
+		if ! [ "$_password1" -o "$_password2" ]; then
+			f_show_msg "$msg_password_is_empty"
+			continue
+		fi
+
+		# Check for password mismatch
+		if [ "$_password1" != "$_password2" ]; then
+			f_show_msg "$msg_passwords_do_not_match"
+			continue
+		fi
+
+		pw_password="$_password1"
+		break
+	done
+
+	return $SUCCESS
+}
+
+fi # ! $_PASSWORD_PASSWORD_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/password/password
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/password/password	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,82 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/password/password 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="040.password"
+f_include $BSDCFG_LIBE/$APP_DIR/include/password.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Default login of system manager
+#
+USER_ROOT=root
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_root_password"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+if f_dialog_input_password; then
+	err=$( echo "$pw_password" | pw usermod $USER_ROOT -h 0 2>&1 ) ||
+		f_die $? "%s" "$err"
+	f_show_msg "$msg_password_changed"
+fi
+
+return $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,54 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/security/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Security"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Set Security Parameters"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="security|security"
+menu_selection="kern_securelevel|kern_securelevel"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="security"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/security/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/130.security
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	kern_securelevel security
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/security/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/security/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/130.security/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,48 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/security/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+hline_select_securelevel_to_operate_at="Select a securelevel to operate at"
+msg_cancel="Cancel"
+msg_disable_securelevels="Disable securelevels"
+msg_disabled="Disabled"
+msg_exit="Exit"
+msg_exit_this_menu="Exit this menu (returning to previous)"
+msg_highly_secure="Highly Secure"
+msg_highly_secure_mode="Highly secure mode"
+msg_menu_text="This menu allows you to configure aspects of the operating system security\npolicy.  Please read the system documentation carefully before modifying\nthese settings, as they may cause service disruption if used improperly.\n\nMost settings will take affect only following a system reboot."
+msg_network_secure="Network Secure"
+msg_network_secure_mode="Network secure mode"
+msg_nfs_port="NFS port"
+msg_nfs_port_desc="Require that the NFS clients use reserved ports"
+msg_ok="OK"
+msg_secure="Secure"
+msg_secure_mode="Secure mode"
+msg_securelevel="Securelevel"
+msg_securelevel_desc="Configure securelevels for the system"
+msg_securelevels_menu_text="This menu allows you to select the securelevel your system runs with.\nWhen operating at a securelevel, certain root privileges are disabled,\nwhich may increase resistance to exploits and protect system integrity.\nIn secure mode system flags may not be overridden by the root user,\naccess to direct kernel memory is limited, and kernel modules may not\nbe changed.  In highly secure mode, mounted file systems may not be\nmodified on-disk, tampering with the system clock is prohibited.  In\nnetwork secure mode configuration changes to firewalling are prohibited.\n "
+msg_securelevels_menu_title="Securelevel Configuration Menu"
+msg_system_security_options_menu="System Security Options Menu"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/kern_securelevel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/kern_securelevel	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,135 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/security/kern_securelevel 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="130.security"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_select_securelevel_to_operate_at"
+	local prompt="$msg_securelevels_menu_text"
+
+	menu_list="
+		'X $msg_exit'         '$msg_exit_this_menu'
+		'$msg_disabled'       '$msg_disable_securelevels'
+		'$msg_secure'         '$msg_secure_mode'
+		'$msg_highly_secure'  '$msg_highly_secure_mode'
+		'$msg_network_secure' '$msg_network_secure_mode'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_securelevels_menu_title"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main
+retval=$?
+mtag=$( f_dialog_menutag )
+
+[ $retval -eq 0 ] || f_die
+
+case "$mtag" in
+"$msg_disabled")
+	f_sysrc_set kern_securelevel_enable "NO"
+	;;
+"$msg_secure")
+	f_sysrc_set kern_securelevel_enable "YES"
+	f_sysrc_set kern_securelevel "1" 
+	;;
+"$msg_highly_secure")
+	f_sysrc_set kern_securelevel_enable "YES"
+	f_sysrc_set kern_securelevel "2" 
+	;;
+"$msg_network_secure")
+	f_sysrc_set kern_securelevel_enable "YES"
+	f_sysrc_set kern_securelevel "3" 
+	;;
+esac
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/security/security
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/security/security	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,149 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/security/security 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="130.security"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_arrows_tab_enter"
+	local prompt="$msg_menu_text"
+
+	menu_list="
+		'X <<< $msg_exit' '$msg_exit_this_menu'
+	" # END-QUOTE
+
+	case "$( f_sysrc_get kern_securelevel_enable )" in
+	[Yy][Ee][Ss])
+		local kern_securelevel="$( f_sysrc_get kern_securelevel )"
+		if [ ${#kern_securelevel} -eq 1 ] &&
+		   f_isinteger "$kern_securelevel"
+		then menu_list="$menu_list
+			'2 [$kern_securelevel] $msg_securelevel'"
+		else menu_list="$menu_list
+			'2 [X] $msg_securelevel'"
+		fi
+		menu_list="$menu_list '$msg_securelevel_desc'"
+		;;
+	*) menu_list="$menu_list
+		'2 [ ] $msg_securelevel' '$msg_securelevel_desc'"
+	esac
+
+	case "$( f_sysrc_get nfs_reserved_port_only )" in
+	[Yy][Ee][Ss]) menu_list="$menu_list
+		'3 [X] $msg_nfs_port' '$msg_nfs_port_desc'";;
+	*) menu_list="$menu_list
+		'3 [ ] $msg_nfs_port' '$msg_nfs_port_desc'";;
+	esac
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_system_security_options_menu"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X <<< $msg_exit") break ;;
+	"2 ["?"] $msg_securelevel") # Configure securelevels for the system
+		$BSDCFG_LIBE/$APP_DIR/kern_securelevel ${USE_XDIALOG:+-X} ;;
+	"3 [X] $msg_nfs_port") # Require that NFS clients use reserved ports
+		f_sysrc_set nfs_reserved_port_only "NO";;
+	"3 [ ] $msg_nfs_port") # Same; Toggle value
+		f_sysrc_set nfs_reserved_port_only "YES";;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Startup"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Set Startup Parameters"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="startup|startup"
+menu_selection="startup_misc|misc"
+menu_selection="startup_rcadd|rcadd"
+menu_selection="startup_rcconf|rcconf"
+menu_selection="startup_rcdelete|rcdelete"
+menu_selection="startup_rcvar|rcvar"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="startup"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/140.startup
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	misc rcadd rcconf rcdelete rcedit rcvar startup
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/140.startup/include
+FILES=		messages.subr rcconf.subr rcedit.subr rcvar.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,112 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_accounting="Accounting"
+msg_accounting_desc="This host wishes to run process accounting."
+msg_add_custom="Add Custom"
+msg_add_from_list="Add From List"
+msg_add_new="Add New"
+msg_add_new_desc="Add new directive"
+msg_add_new_help="Add new rc.conf(5) configuration directive"
+msg_add_startup_directive="Add Startup Directive"
+msg_all="All"
+msg_all_desc="Select all directives"
+msg_all_help="Select all displayed rc.conf(5) configuration directives"
+msg_apm="APM"
+msg_apm_desc="Auto-power management services (typically laptops)"
+msg_are_you_sure_you_want_to_delete="Are you sure you want to delete the \`%s' directive\nfrom the rc.conf(5) collection of system configuration files?"
+msg_are_you_sure_you_want_delete_the_following="Are you sure you want to delete the following directives\nfrom the rc.conf(5) collection of system configuration files?"
+msg_cancel="Cancel"
+msg_choose_view_details="Choose View Details"
+msg_creating_menu_list="Creating menu list...\nThis may take a while."
+msg_creating_rcconf_map="Creating rc.conf(5) map...\nThis may take a while."
+msg_creating_rcvar_map="Creating rcvar map...\nThis may take a while."
+msg_default_value="Default: %s"
+msg_delete="Delete"
+msg_delete_desc="Delete directive(s)"
+msg_delete_help="Select one or more directives from a list to delete"
+msg_delete_selected="Delete Selected"
+msg_delete_selected_desc="Delete selected directive(s)"
+msg_delete_selected_help="Delete each of the selected rc.conf(5) configuration directives"
+msg_delete_startup_directives="Delete Startup Directive(s)"
+msg_deleting_selected_directives="Deleting selected directive(s)..."
+msg_desc="Description"
+msg_desc_desc="Toggle display of system description"
+msg_details="Details"
+msg_exit="Exit"
+msg_exit_cancel="Exit/Cancel"
+msg_exit_cancel_desc="Return to previous menu"
+msg_exit_cancel_help="Return to the previous menu (selected items are untouched)"
+msg_exit_desc="Return to previous menu"
+msg_exit_help="Exit this menu (returning to previous)"
+msg_exit_this_menu="Exit this menu (returning to previous)"
+msg_info="Info"
+msg_lpd="lpd"
+msg_lpd_desc="This host has a printer and wants to run lpd."
+msg_miscellaneous_startup_services="Miscellaneous Startup Services"
+msg_miscellaneous_menu_text="This menu allows you to configure various aspects of your system's\nstartup configuration.  Use [SPACE] or [ENTER] to select items, and\n[TAB] to move to the buttons.  Select Exit to leave this menu."
+msg_named="named"
+msg_named_desc="Run a local name server on this host"
+msg_named_flags="named flags"
+msg_named_flags_desc="Set default flags to named (if enabled)"
+msg_nis_client="NIS client"
+msg_nis_client_desc="This host wishes to be an NIS client."
+msg_nis_domainname="NIS domainname"
+msg_nis_domainname_desc="Set NIS domainname (if enabled)"
+msg_nis_server="NIS Server"
+msg_nis_server_desc="This host wishes to be an NIS server."
+msg_none="None"
+msg_none_desc="Un-Select all directives"
+msg_none_help="Un-Select all rc.conf(5) configuration directives"
+msg_ok="OK"
+msg_please_enter_a_new_value="Please enter a new value for \`%s' (Default: %s):"
+msg_please_enter_rcvar_name="Please enter rc.conf(5) variable name:"
+msg_please_select_an_rcconf_directive="Please select an rc.conf(5) directive:"
+msg_rcvar_contains_invalid_chars="ERROR! rc.conf(5) variable name contains invalid characters.\n Name may only consist of letters [a-zA-Z], numbers [0-9],\n or underscore [_] and must not start with a number."
+msg_rcvar_must_start_with="ERROR! rc.conf(5) variable name must start with\n a letter [a-zA-Z] or underscore [_]."
+msg_reset="Reset"
+msg_reset_desc="Reset to default view settings"
+msg_sco="SCO"
+msg_sco_desc="This host wants to be able to run IBCS2 binaries."
+msg_show_configured="Show Configured"
+msg_show_configured_desc="Calculate rc.conf(5) locations (slow)"
+msg_show_default_value="Show Default/Value"
+msg_show_default_value_desc="Show default/configured values"
+msg_show_value="Show Value"
+msg_show_value_desc="Show configured startup value"
+msg_startup="Startup"
+msg_startup_dirs="Startup dirs"
+msg_startup_dirs_desc="Set the list of dirs to look for startup scripts"
+msg_svr4="SVR4"
+msg_svr4_desc="This host wants to be able to run SVR4 binaries."
+msg_toggle_startup_services="Toggle Startup Services"
+msg_value_required="Value Required"
+msg_view_details="View Details"
+msg_view_details_desc="Choose view details"
+msg_view_details_help="Choose which details are shown in the current view"
+msg_view_edit_startup_configuration="View/Edit Startup Configuration"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/include/rcconf.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/include/rcconf.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,466 @@
+if [ ! "$_STARTUP_RCCONF_SUBR" ]; then _STARTUP_RCCONF_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/include/rcconf.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ GLOBALS
+
+#
+# Initialize in-memory cache variables
+#
+STARTUP_RCCONF_MAP=
+_STARTUP_RCCONF_MAP=
+
+#
+# Define what a variable looks like
+#
+STARTUP_RCCONF_REGEX="^[[:alpha:]_][[:alnum:]_]*="
+
+#
+# Default path to on-disk cache file(s)
+#
+STARTUP_RCCONF_MAP_CACHEFILE="/var/run/bsdconfig/startup_rcconf_map.cache"
+
+############################################################ FUNCTIONS
+
+# f_startup_rcconf_list
+#
+# Produce a list of non-default configuration variables configured in the
+# rc.conf(5) collection of files.
+#
+f_startup_rcconf_list()
+{
+	( # Operate within a sub-shell to protect the parent environment
+		. "$RC_DEFAULTS" > /dev/null
+		f_clean_env --except PATH STARTUP_RCCONF_REGEX rc_conf_files
+		source_rc_confs > /dev/null
+		export _rc_conf_files_file="$( f_sysrc_find rc_conf_files )"
+		export RC_DEFAULTS
+		set | awk -F= "
+		function test_print(var)
+		{
+			if ( var == \"OPTIND\" ) return
+			if ( var == \"PATH\" ) return
+			if ( var == \"RC_DEFAULTS\" ) return
+			if ( var == \"STARTUP_RCCONF_REGEX\" ) return
+			if ( var == \"_rc_conf_files_file\" ) return
+			if ( var == \"rc_conf_files\" )
+			{
+				if ( ENVIRON[\"_rc_conf_files_file\"] == \
+				     ENVIRON[\"RC_DEFAULTS\"] ) return
+			}
+			print var
+		}
+		/$STARTUP_RCCONF_REGEX/ { test_print(\$1) }"
+	)
+}
+
+# f_startup_rcconf_map
+#
+# Produce a map (beit from in-memory cache or on-disk cache) of rc.conf(5)
+# variables and their descriptions. The map returned has the following format:
+#
+# 	var description
+#
+# With each as follows:
+#
+# 	var           the rc.conf(5) variable
+# 	description   description of the variable
+#
+f_startup_rcconf_map()
+{
+	# If the in-memory cached value is available, return it immediately
+	if [ "$_STARTUP_RCCONF_MAP" ]; then
+		echo "$STARTUP_RCCONF_MAP"
+		return $SUCCESS
+	fi
+
+	#
+	# create the in-memory cache (potentially from validated on-disk cache)
+	#
+
+	#
+	# Calculate digest used to determine if the on-disk global persistant
+	# cache file (containg this digest on the first line) is valid and can
+	# be used to quickly populate the cache value for immediate return.
+	#
+	local rc_defaults_digest
+	rc_defaults_digest=$( md5 < "$RC_DEFAULTS" )
+
+	#
+	# Check to see if the global persistant cache file exists
+	#
+	if [ -f "$STARTUP_RCCONF_MAP_CACHEFILE" ]; then
+		#
+		# Attempt to populate the in-memory cache with the (soon to be)
+		# be validated on-disk cache. If validation fails, fall-back to
+		# the current value and provide error exit status.
+		#
+		STARTUP_RCCONF_MAP=$(
+			(	# Get digest as the first word on the first line
+				read digest rest_ignored
+
+				#
+				# If the stored digest matches the calculated-
+				# one populate the in-memory cache from the on-
+				# disk cache and provide success exit status.
+				#
+				if [ "$digest" = "$rc_defaults_digest" ]; then
+					cat
+					exit $SUCCESS
+				else
+					# Otherwise, return the current value
+					echo "$STARTUP_RCCONF_MAP"
+					exit $FAILURE
+				fi
+			) < "$STARTUP_RCCONF_MAP_CACHEFILE"
+		)
+		export STARTUP_RCCONF_MAP
+		if [ $? -eq $SUCCESS ]; then
+			export _STARTUP_RCCONF_MAP=1
+			echo "$STARTUP_RCCONF_MAP"
+			return $SUCCESS
+		fi
+		# Otherwise, fall-thru to create in-memory cache from scratch
+	fi
+
+	#
+	# If we reach this point, we need to generate the data from scratch
+	# (and after we do, we'll attempt to create the global persistant
+	# cache file to speed up future executions).
+	#
+
+	STARTUP_RCCONF_MAP=$(
+		f_clean_env --except \
+			PATH                 \
+			RC_DEFAULTS          \
+			STARTUP_RCCONF_REGEX \
+			f_sysrc_desc_awk
+		. "$RC_DEFAULTS"
+
+		# Unset variables we don't want reported
+		unset source_rc_confs_defined
+
+		for var in $( set | awk -F= "
+			function test_print(var)
+			{
+				if ( var == \"OPTIND\" ) return 
+				if ( var == \"PATH\" ) return 
+				if ( var == \"RC_DEFAULTS\" ) return 
+				if ( var == \"STARTUP_RCCONF_REGEX\" ) return 
+				if ( var == \"f_sysrc_desc_awk\" ) return
+				print var
+			}
+			/$STARTUP_RCCONF_REGEX/ { test_print(\$1) }
+		" ); do
+			echo $var "$( f_sysrc_desc $var )"
+		done
+	)
+	export STARTUP_RCCONF_MAP
+	export _STARTUP_RCCONF_MAP=1
+	echo "$STARTUP_RCCONF_MAP"
+
+	#
+	# Attempt to create the persistant global cache
+	#
+
+	# Create a new temporary file to write to
+	local tmpfile="$( mktemp -t "$pgm" )"
+	[ "$tmpfile" ] || return $FAILURE
+
+	# Write the temporary file contents
+	echo "$rc_defaults_digest" > "$tmpfile"
+	echo "$STARTUP_RCCONF_MAP" >> "$tmpfile"
+
+	# Finally, move the temporary file into place
+	case "$STARTUP_RCCONF_MAP_CACHEFILE" in
+	*/*) f_quietly mkdir -p "${STARTUP_RCCONF_MAP_CACHEFILE%/*}"
+	esac
+	mv "$tmpfile" "$STARTUP_RCCONF_MAP_CACHEFILE"
+}
+
+# f_startup_rcconf_map_expand
+#
+# Expands the map ($RCCONF_MAP) into the shell environment namespace by
+# creating _${var}_desc variables containing the description of each variable
+# encountered.
+#
+# NOTE: Variables are exported for later-required awk(1) ENVIRON visibility.
+#
+f_startup_rcconf_map_expand()
+{
+	eval "$( echo "$RCCONF_MAP" | awk '
+	BEGIN {
+		rword = "^[[:space:]]*[^[:space:]]*[[:space:]]*"
+	}
+	{
+		var  = $1
+		desc = $0
+		sub(rword, "", desc)
+		gsub(/'\''/, "'\''\\'\'\''", desc)
+		printf "_%s_desc='\''%s'\''\n", var, desc
+		printf "export _%s_desc\n", var
+	}' )"
+}
+
+# f_dialog_input_view_details
+#
+# Display a menu for selecting which details are to be displayed. The following
+# variables are tracked/modified by the menu/user's selection:
+#
+# 	SHOW_DESC		Show or hide descriptions
+#
+# Mutually exclusive options:
+#
+# 	SHOW_VALUE		Show the value (default; override only)
+# 	SHOW_VALUE_DEFAULT	Show both value and default
+# 	SHOW_CONFIGURED		Show rc.conf(5) file variable is configured in
+#
+# Each variable is treated as a boolean (NULL for false, non-NULL for true).
+#
+# Variables are exported for later-required awk(1) ENVIRON visibility.
+#
+f_dialog_input_view_details()
+{
+	local menu_list size
+	local hline="$hline_arrows_tab_enter"
+	local prompt=""
+
+	local md=" " m1=" " m2=" " m3=" "
+	[ "$SHOW_DESC"          ] && md="X"
+	[ "$SHOW_VALUE"         ] && m1="*"
+	[ "$SHOW_DEFAULT_VALUE" ] && m2="*"
+	[ "$SHOW_CONFIGURED"    ] && m3="*"
+
+	menu_list="
+		'X $msg_exit'                     '$msg_exit_this_menu'
+		'R $msg_reset'                    '$msg_reset_desc'
+		'D [$md] $msg_desc'               '$msg_desc_desc'
+		'1 ($m1) $msg_show_value'         '$msg_show_value_desc'
+		'2 ($m2) $msg_show_default_value' '$msg_show_default_value_desc'
+		'3 ($m3) $msg_show_configured'    '$msg_show_configured_desc'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	f_dialog_title "$msg_choose_view_details"
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+
+	local retval=$?
+	local mtag="$( f_dialog_menutag )"
+
+	f_dialog_title_restore
+
+	[ $retval -eq 0 ] || return $SUCCESS
+	[ "$mtag" = "X $msg_exit" ] && return $SUCCESS
+
+	case "$mtag" in
+	"R $msg_reset")
+		SHOW_VALUE=1
+		SHOW_DESC=1
+		SHOW_DEFAULT_VALUE=
+		SHOW_CONFIGURED=
+		;;
+	"D [X] $msg_desc") SHOW_DESC=  ;;
+	"D [ ] $msg_desc") SHOW_DESC=1 ;;
+	"1 ("?") $msg_show_value")
+		SHOW_VALUE=1
+		SHOW_DEFAULT_VALUE=
+		SHOW_CONFIGURED=
+		;;
+	"2 ("?") $msg_show_default_value")
+		SHOW_VALUE=
+		SHOW_DEFAULT_VALUE=1
+		SHOW_CONFIGURED=
+		;;
+	"3 ("?") $msg_show_configured")
+		SHOW_VALUE=
+		SHOW_DEFAULT_VALUE=
+		SHOW_CONFIGURED=1
+		;;
+	esac
+}
+
+# f_dialog_input_rclist
+#
+# Presents a menu of rc.conf(5) defaults (with, or without descriptions). This
+# function should be treated like a call to dialog(1) (the exit status should
+# be captured and f_dialog_menutag() should be used to clean-up and get the
+# user's response).
+#
+f_dialog_input_rclist()
+{
+	local size
+	local hline="$hline_arrows_tab_enter"
+	local prompt="$msg_please_select_an_rcconf_directive"
+	local menu_list
+
+	menu_list="
+		'X $msg_exit' '' ${SHOW_DESC:+'$msg_exit_help'}
+	" # END-QUOTE
+
+	if [ ! "$_RCCONF_MAP" ]; then
+		# Generate RCCONF_MAP of `var desc ...' per-line
+		f_dialog_info "$msg_creating_rcconf_map"
+		RCCONF_MAP=$( f_startup_rcconf_map )
+		export RCCONF_MAP
+		# Generate _${var}_desc variables from $RCCONF_MAP
+		f_startup_rcconf_map_expand
+		export _RCCONF_MAP=1
+	fi
+
+	menu_list="$menu_list $(
+		export SHOW_DESC
+		echo "$RCCONF_MAP" | awk '
+		BEGIN {
+			prefix = ""
+			rword  = "^[[:space:]]*[^[:space:]]*[[:space:]]*"
+		}
+		{
+			cur_prefix = tolower(substr($1, 1, 1))
+			printf "'\''"
+			if ( prefix != cur_prefix )
+				prefix = cur_prefix
+			else
+				printf " "
+			rcvar  = $1
+			printf "%s'\'' '\'\''", rcvar
+			if ( ENVIRON["SHOW_DESC"] ) {
+				desc = $0
+				sub(rword, "", desc)
+				gsub(/'\''/, "'\''\\'\'\''", desc)
+				printf " '\''%s'\''", desc
+			}
+			printf "\n"
+		}'
+	)"
+
+	set -f # noglob
+
+	size=$( eval f_dialog_menu_${SHOW_DESC:+with_help_}size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		${SHOW_DESC:+--item-help}          \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# f_dialog_input_rcvar [$init]
+#
+# Allows the user to enter the name for a new rc.conf(5) variable. If the user
+# does not cancel or press ESC, the $rcvar variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_rcvar()
+{
+	local msg="$msg_please_enter_rcvar_name"
+	local hline="$hline_alnum_tab_enter"
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local size _input="$1"
+	while :; do
+		size=$( f_dialog_inputbox_size \
+		        	"$DIALOG_TITLE"     \
+		        	"$DIALOG_BACKTITLE" \
+		        	"$msg"              \
+		        	"$_input"           \
+		        	"$hline"            )
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$_input\"                       \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_input=$( f_dialog_inputstr )
+
+		# Return if user either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Check for invalid entry (1of2)
+		if ! echo "$_input" | grep -q "^[[:alpha:]_]"; then
+			f_show_msg "$msg_rcvar_must_start_with"
+			continue
+		fi
+
+		# Check for invalid entry (2of2)
+		if ! echo "$_input" | grep -q "^[[:alpha:]_][[:alnum:]_]*$"
+		then
+			f_show_msg "$msg_rcvar_contains_invalid_chars"
+			continue
+		fi
+
+		rcvar="$_input"
+		break
+	done
+
+	f_dprintf "f_dialog_input_rcvar: rcvar->[$rcvar]"
+
+	return $SUCCESS
+}
+
+fi # ! $_STARTUP_RCCONF_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/include/rcedit.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/include/rcedit.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,106 @@
+if [ ! "$_STARTUP_RCEDIT_SUBR" ]; then _STARTUP_RCEDIT_SUBR=1
+#
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/include/rcedit.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_rcedit $var [[--] $init ...]
+#
+# Allow the user to enter a new value for a given rc.conf(5) variable. If the
+# user does not cancel or press ESC, the variable will be saved without
+# confirmation.
+#
+# If the second argument is non-NULL, it will be processed as the initial text
+# to be displayed, overriding the default behavior to display the currently
+# configured value as the initial text.
+#
+# If instead the second argument is "--", then the third argument (NULL or
+# otherwise) will be treated as the initial text.
+#
+f_dialog_rcedit()
+{
+	local msg size retval var="$1" _input
+	local hline="$hline_alnum_punc_tab_enter"
+
+	msg=$( printf "$msg_please_enter_a_new_value" \
+	              "$var" "$( f_sysrc_get_default "$var" )" )
+
+	shift 1 # var
+	if [ "$1" ]; then
+		[ "$1" = "--" ] && shift 1 # --
+		_input="$1"
+	else
+		_input=$( f_sysrc_get "$var" )
+	fi
+
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	local opterm="--"
+	[ "$USE_XDIALOG" ] && opterm=
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		$opterm \"\$_input\"               \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	# Return if the value has not changed from current
+	local cur_val="$( f_sysrc_get "$var" )"
+	[ "$_input" = "$cur_val" ] && return $SUCCESS
+	
+	f_dprintf "$var: [$cur_val]->[$_input]"
+
+	err=$( f_sysrc_set "$var" "$_input" 2>&1 ) ||
+		f_show_msg "$err"
+}
+
+fi # ! $_STARTUP_RCEDIT_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/include/rcvar.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/include/rcvar.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,206 @@
+if [ ! "$_STARTUP_RCVAR_SUBR" ]; then _STARTUP_RCVAR_SUBR=1
+#
+# Copyright (c) 2006-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/include/rcvar.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default path to the `/etc/rc.d' directory where service(8) scripts are stored
+#
+: ${ETC_RC_D:=/etc/rc.d}
+
+#
+# Default path to `/etc/rc.subr' (for find_local_scripts_new())
+#
+: ${ETC_RC_SUBR:=/etc/rc.subr}
+
+############################################################ GLOBALS
+
+#
+# Initialize in-memory cache variables
+#
+STARTUP_RCVAR_MAP=
+_STARTUP_RCVAR_MAP=
+
+#
+# Define what an rcvar looks like
+#
+STARTUP_RCVAR_REGEX='[[:alpha:]_][[:alnum:]_]*="([Yy][Ee][Ss]|[Nn][Oo])"'
+
+#
+# Default path to on-disk cache file(s)
+#
+STARTUP_RCVAR_MAP_CACHEFILE="/var/run/bsdconfig/startup_rcvar_map.cache"
+
+############################################################ FUNCTIONS
+
+# f_startup_rcvar_map
+#
+# Produce a map (beit from in-memory cache or on-disk cache) of rc.d scripts
+# and their associated rcvar's. The map returned has the following format:
+#
+# 	rcvar default script description
+#
+# With each as follows:
+#
+# 	rcvar         the variable used to enable this rc.d script
+# 	default       default value for this variable
+# 	script        the rc.d script in-question
+# 	description   description of the variable from rc.conf(5) defaults
+#
+f_startup_rcvar_map()
+{
+	# If the in-memory cached value is available, return it immediately
+	if [ "$_STARTUP_RCVAR_MAP" ]; then
+		echo "$STARTUP_RCVAR_MAP"
+		return $SUCCESS
+	fi
+
+	#
+	# create the in-memory cache (potentially from validated on-disk cache)
+	#
+
+	# Get a list of /etc/rc.d scripts ...
+	local file rc_script_list=
+	for file in "$ETC_RC_D"/*; do
+		[ -f "$file" ] || continue
+		[ -x "$file" ] || continue
+		rc_script_list="$rc_script_list${rc_script_list:+ }$file"
+	done
+	# ... and /usr/local/etc/rc.d scripts
+	rc_script_list="$rc_script_list${rc_script_list:+ }$(
+		local_startup=$( f_sysrc_get local_startup )
+		f_include "$ETC_RC_SUBR"
+		find_local_scripts_new
+		echo $local_rc
+	)"
+
+	#
+	# Calculate a digest given the checksums of all dependencies (scripts and
+	# the defaults file). This digest will be used to determine if an on-disk
+	# global persistant cache file (containg this digest on the first line)
+	# is valid and can be used to quickly populate the cache value for
+	# immediate return.
+	#
+	local rc_script_list_digest
+	rc_script_list_digest=$( cd "$ETC_RC_D" &&
+		cksum "$RC_DEFAULTS" $rc_script_list | md5 )
+
+	#
+	# Check to see if the global persistant cache file exists
+	#
+	if [ -f "$STARTUP_RCVAR_MAP_CACHEFILE" ]; then
+		#
+		# Attempt to populate the in-memory cache with the (soon to be)
+		# be validated on-disk cache. If validation fails, fall-back to
+		# the current value and provide error exit status.
+		#
+		STARTUP_RCVAR_MAP=$(
+			(	# Get digest as the first word on the first line
+				read digest rest_ignored
+
+				#
+				# If the stored digest matches the calculated-one
+				# populate the in-memory cache from the on-disk
+				# cache and provide success exit status.
+				#
+				if [ "$digest" = "$rc_script_list_digest" ]; then
+					cat
+					exit $SUCCESS
+				else
+					# Otherwise, return the current value
+					echo "$STARTUP_RCVAR_MAP"
+					exit $FAILURE
+				fi
+			) < "$STARTUP_RCVAR_MAP_CACHEFILE"
+		)
+		export STARTUP_RCVAR_MAP
+		if [ $? -eq $SUCCESS ]; then
+			export _STARTUP_RCVAR_MAP=1
+			echo "$STARTUP_RCVAR_MAP"
+			return $SUCCESS
+		fi
+		# Otherwise, fall-through to create in-memory cache from scratch
+	fi
+
+	#
+	# If we reach this point, we need to generate the data from scratch
+	# (and after we do, we'll attempt to create the global persistant
+	# cache file to speed up future executions).
+	#
+
+	STARTUP_RCVAR_MAP=$(
+		for script in $rc_script_list; do
+			rcvar_list=$( $script rcvar | awk -F= \
+				-v script="$script" '
+		              	/^'"$STARTUP_RCVAR_REGEX"'/ {
+		              		if ( $2 ~ /^"[Yy][Ee][Ss]"$/ )
+		              			print $1 ",YES"
+		              		else
+		              			print $1 ",NO"
+		              	}' )
+			for entry in $rcvar_list; do
+				rcvar="${entry%%,*}"
+				rcvar_default=$( f_sysrc_get_default "$rcvar" )
+				[ "$rcvar_default" ] ||
+					rcvar_default="${entry#*,}"
+				rcvar_desc=$( f_sysrc_desc "$rcvar" )
+				echo $rcvar ${rcvar_default:-NO} \
+				     $script "$rcvar_desc"
+			done
+		done | sort -u
+	)
+	export STARTUP_RCVAR_MAP
+	export _STARTUP_RCVAR_MAP=1
+	echo "$STARTUP_RCVAR_MAP"
+
+	#
+	# Attempt to create the persistant global cache
+	#
+
+	# Create a new temporary file to write to
+	local tmpfile="$( mktemp -t "$pgm" )"
+	[ "$tmpfile" ] || return $FAILURE
+
+	# Write the temporary file contents
+	echo "$rc_script_list_digest" > "$tmpfile"
+	echo "$STARTUP_RCVAR_MAP" >> "$tmpfile"
+
+	# Finally, move the temporary file into place
+	case "$STARTUP_RCVAR_MAP_CACHEFILE" in
+	*/*) f_quietly mkdir -p "${STARTUP_RCVAR_MAP_CACHEFILE%/*}"
+	esac
+	mv "$tmpfile" "$STARTUP_RCVAR_MAP_CACHEFILE"
+}
+
+fi # ! $_STARTUP_RCVAR_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/misc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/misc	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,406 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/misc 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ GLOBALS
+
+#
+# Operating environment
+#
+UNAME_P=$( uname -p ) # Processor Architecture (i.e. i386)
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list var_list size
+	local hline="$hline_arrows_tab_enter"
+	local prompt="$msg_miscellaneous_menu_text"
+
+	menu_list="
+		'X <<< $msg_exit' '$msg_exit_this_menu'
+	" # END-QUOTE
+
+	var_list="
+		accounting_enable
+		local_startup
+		lpd_enable
+		named_enable
+		named_flags
+		nis_client_enable
+		nis_server_enable
+		nisdomainname
+		startup_dirs
+	" # END-QUOTE
+
+	if [ "$UNAME_P" = "i386" ]; then
+		var_list="$var_list
+			apm_enable
+			ibcs2_enable
+			svr4_enable
+		" # END-QUOTE
+	fi
+
+	menu_list="$menu_list $(
+		. "$RC_DEFAULTS"
+		source_rc_confs
+		export $var_list
+		export msg_apm            msg_apm_desc
+		export msg_startup_dirs   msg_startup_dirs_desc
+		export msg_named          msg_named_desc
+		export msg_named_flags    msg_named_flags_desc
+		export msg_nis_client     msg_nis_client_desc
+		export msg_nis_domainname msg_nis_domainname_desc
+		export msg_nis_server     msg_nis_server_desc
+		export msg_accounting     msg_accounting_desc
+		export msg_lpd            msg_lpd_desc
+		export msg_sco            msg_sco_desc
+		export msg_svr4           msg_svr4_desc
+		:| awk \
+			-v uname_p="$UNAME_P"             \
+			-v menu_tags="$DIALOG_MENU_TAGS"  \
+			-v menu_fmt="'%c [%c] %s' '%s'\n" \
+			-v sep_fmt="' ' ' -- '\n"         \
+		'END {
+			i = 1
+			if ( uname_p == "i386" )
+			{
+				#
+				# APM: Auto-power management services
+				#      (typically laptops)
+				#
+				printf menu_fmt, substr(menu_tags, i++, 1),
+					( ENVIRON["apm_enable"] ~ \
+					  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+					ENVIRON["msg_apm"],
+					ENVIRON["msg_apm_desc"]
+			}
+
+			# Separator
+			printf sep_fmt
+
+			#
+			# Startup dirs: Set the list of dirs to look for
+			#               startup scripts
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( length(ENVIRON["local_startup"]) > 0 \
+				  ? "X" : " " ),
+				ENVIRON["msg_startup_dirs"],
+				ENVIRON["msg_startup_dirs_desc"]
+
+			#
+			# named: Run a local name server on this host
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( ENVIRON["named_enable"] ~ \
+				  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+				ENVIRON["msg_named"],
+				ENVIRON["msg_named_desc"]
+
+			#
+			# named flags: Set default flags to named (if enabled)
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( length(ENVIRON["named_flags"]) > 0 \
+				  ? "X" : " " ),
+				ENVIRON["msg_named_flags"],
+				ENVIRON["msg_named_flags_desc"]
+
+			#
+			# NIS client: This host wishes to be an NIS client.
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( ENVIRON["nis_client_enable"] ~ \
+				  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+				ENVIRON["msg_nis_client"],
+				ENVIRON["msg_nis_client_desc"]
+
+			#
+			# NIS domainname: Set NIS domainname (if enabled)
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( length(ENVIRON["nisdomainname"]) > 0 \
+				  ? "X" : " " ),
+				ENVIRON["msg_nis_domainname"],
+				ENVIRON["msg_nis_domainname_desc"]
+
+			#
+			# NIS server: This host wishes to be an NIS server.
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( ENVIRON["nis_server_enable"] ~ \
+				  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+				ENVIRON["msg_nis_server"],
+				ENVIRON["msg_nis_server_desc"]
+
+			# Separator
+			printf sep_fmt
+
+			#
+			# Accounting: This host wishes to run process
+			#             accounting.
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( ENVIRON["accounting_enable"] ~ \
+				  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+				ENVIRON["msg_accounting"],
+				ENVIRON["msg_accounting_desc"]
+
+			#
+			# lpd: This host has a printer and wants to run lpd.
+			#
+			printf menu_fmt, substr(menu_tags, i++, 1),
+				( ENVIRON["lpd_enable"] ~ \
+				  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+				ENVIRON["msg_lpd"],
+				ENVIRON["msg_lpd_desc"]
+
+			if ( uname_p == "i386" )
+			{
+				#
+				# SCO: This host wants to be able to run IBCS2
+				#      binaries.
+				#
+				printf menu_fmt, substr(menu_tags, i++, 1),
+					( ENVIRON["ibcs2_enable"] ~ \
+					  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+					ENVIRON["msg_sco"],
+					ENVIRON["msg_sco_desc"]
+
+				#
+				# SVR4: This host wants to be able to run SVR4
+				#       binaries.
+				#
+				printf menu_fmt, substr(menu_tags, i++, 1),
+					( ENVIRON["svr4_enable"] ~ \
+					  /^[Yy][Ee][Ss]$/ ? "X" : " " ),
+					ENVIRON["msg_svr4"],
+					ENVIRON["msg_svr4_desc"]
+			}
+		}'
+	)"
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# dialog_input_value [ $prompt [ $init ] ]
+#
+# Prompt the user to input a value. If the user does not cancel or press ESC,
+# the return value is zero ($SUCCESS) and $value holds the user's input.
+#
+dialog_input_value()
+{
+	local hline="$hline_alnum_tab_enter"
+	local size prompt="$1" _input="$2"
+
+	f_dialog_title "$msg_value_required"
+
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$prompt"           \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$prompt\" $size      \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	f_dialog_title_restore
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	value="$_input"
+	return $SUCCESS
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_miscellaneous_startup_services"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X <<< $msg_exit") break ;;
+	?" ["?"] $msg_apm")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set apm_enable NO 2>&1 ) ;;
+		?" [ ] "*) err=$( f_sysrc_set apm_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_startup_dirs")
+		dialog_input_value \
+			"$msg_startup_dirs_desc" \
+			"$( f_sysrc_get local_startup )"
+		if [ $? -eq $SUCCESS ]; then
+			err=$( f_sysrc_set local_startup "$value" ) ||
+				f_show_msg "%s\n" "$err"
+		fi
+		;;
+	?" ["?"] $msg_named")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set named_enable NO 2>&1 ) ;;
+		?" [ ] "*) err=$( f_sysrc_set named_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_named_flags")
+		dialog_input_value \
+			"$msg_named_flags_desc" \
+			"$( f_sysrc_get named_flags )"
+		if [ $? -eq $SUCCESS ]; then
+			err=$( f_sysrc_set named_flags "$value" ) ||
+				f_show_msg "%s\n" "$err"
+		fi
+		;;
+	?" ["?"] $msg_nis_client")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set nis_client_enable NO 2>&1 ) ;;
+		?" [ ] "*)
+			err=$( f_sysrc_set nis_client_enable YES 2>&1 ) \
+			&& err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_nis_domainname")
+		dialog_input_value \
+			"$msg_nis_domainname_desc" \
+			"$( f_sysrc_get nisdomainname )"
+		if [ $? -eq $SUCCESS ]; then
+			err=$( f_sysrc_set nisdomainname "$value" ) ||
+				f_show_msg "%s\n" "$err"
+		fi
+		;;
+	?" ["?"] $msg_nis_server")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set nis_server_enable NO 2>&1 ) ;;
+		?" [ ] "*)
+			err=$( f_sysrc_set nis_server_enable YES 2>&1 ) \
+			&& err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_accounting")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set accounting_enable NO 2>&1 ) ;;
+		?" [ ] "*) err=$( f_sysrc_set accounting_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_lpd")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set lpd_enable NO 2>&1 ) ;;
+		?" [ ] "*) err=$( f_sysrc_set lpd_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_sco")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set ibcs2_enable NO 2>&1 ) ;;
+		?" [ ] "*) err=$( f_sysrc_set ibcs2_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	?" ["?"] $msg_svr4")
+		case "$mtag" in
+		?" [X] "*) err=$( f_sysrc_set svr4_enable NO 2>&1 ) ;;
+		?" [ ] "*) err=$( f_sysrc_set svr4_enable YES 2>&1 ) ;;
+		esac
+		[ $? -eq $SUCCESS ] || f_show_msg "%s\n" "$err" ;;
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/rcadd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/rcadd	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,153 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcadd 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="140.startup"
+f_include $BSDCFG_LIBE/$APP_DIR/include/rcconf.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+( : ${SHOW_DESC?} ) > /dev/null 2>&1 || SHOW_DESC=1
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_arrows_tab_enter"
+	local prompt=""
+
+	menu_list="
+		'1' '$msg_add_from_list'
+		'2' '$msg_add_custom'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_add_startup_directive"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	1) # Add From List
+		# Loop for easy return
+		while :; do
+			f_dialog_input_rclist
+			retval=$?
+			mtag=$( f_dialog_menutag )
+
+			[ $retval -eq 0 ] || break
+
+			case "$mtag" in
+			"X $msg_exit" ) break ;;
+			*) # Anything else is a directive
+				rcvar="${mtag# }"
+				$BSDCFG_LIBE/$APP_DIR/rcedit \
+					${USE_XDIALOG:+-X} \
+					"$rcvar" || continue
+			esac
+			break
+		done
+		[ $retval -eq 0 ] || continue
+		;;
+	2) # Add Custom
+		f_dialog_input_rcvar || continue
+		$BSDCFG_LIBE/$APP_DIR/rcedit ${USE_XDIALOG:+-X} "$rcvar" ||
+			continue
+		;;
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/rcconf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/rcconf	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,246 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcconf 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="140.startup"
+f_include $BSDCFG_LIBE/$APP_DIR/include/rcconf.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ GLOBALS
+
+#
+# Global map/menu-list for the main menu
+#
+RCCONF_MAP=
+_RCCONF_MAP=
+RCCONF_MENU_LIST=
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+( : ${SHOW_DESC?} ) > /dev/null 2>&1 || SHOW_DESC=1
+# Selectively inherit SHOW_* value (in order of preference)
+if [ "$SHOW_DEFAULT_VALUE" ]; then
+	SHOW_DEFAULT_VALUE=1
+	SHOW_CONFIGURED=
+	SHOW_VALUE=
+elif [ "$SHOW_CONFIGURED" ]; then
+	SHOW_DEFAULT_VALUE=
+	SHOW_CONFIGURED=1
+	SHOW_VALUE=
+else
+	SHOW_DEFAULT_VALUE=
+	SHOW_CONFIGURED=
+	SHOW_VALUE=1
+fi
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local size
+	local hline="$hline_arrows_tab_enter"
+	local prompt=""
+
+	RCCONF_MENU_LIST="
+		'X $msg_exit'    '$msg_exit_desc'
+		                  ${SHOW_DESC:+'$msg_exit_help'}
+		'> $msg_add_new' '$msg_add_new_desc'
+		                  ${SHOW_DESC:+'$msg_add_new_help'}
+		'> $msg_delete'  '$msg_delete_desc'
+		                  ${SHOW_DESC:+'$msg_delete_help'}
+	${USE_XDIALOG:+
+		'> $msg_view_details' '$msg_view_details_desc'
+		                       ${SHOW_DESC:+'$msg_view_details_help'}
+	}
+	" # END-QUOTE
+
+	if [ ! "$_RCCONF_MAP" ]; then
+		# Genreate RCCONF_MAP of `var desc ...' per-line
+		f_dialog_info "$msg_creating_rcconf_map"
+		RCCONF_MAP=$( f_startup_rcconf_map )
+		export RCCONF_MAP
+		# Generate _${var}_desc variables from $RCCONF_MAP
+		f_startup_rcconf_map_expand
+		export _RCCONF_MAP=1
+	fi
+
+	# Show infobox for modes that take a while to calculate/display
+	[ "$SHOW_DEFAULT_VALUE" -o "$SHOW_CONFIGURED" ] &&
+		f_dialog_info "$msg_creating_menu_list"
+
+	RCCONF_MENU_LIST="$RCCONF_MENU_LIST $(
+		. "$RC_DEFAULTS" > /dev/null
+		source_rc_confs > /dev/null
+		var_list=$( f_startup_rcconf_list )
+		for var in $var_list; do
+			eval export $var
+			[ "$SHOW_DEFAULT_VALUE" ] && export \
+				_${var}_default="$( f_sysrc_get_default $var )"
+			[ "$SHOW_CONFIGURED" ] && export \
+				_${var}_file="$( f_sysrc_find $var )"
+		done
+		export SHOW_VALUE SHOW_DESC SHOW_DEFAULT_VALUE SHOW_CONFIGURED
+		export msg_default_value
+		echo "$var_list" | awk '
+		BEGIN {
+			prefix = ""
+		}
+		{
+			cur_prefix = tolower(substr($1, 1, 1))
+			printf "'\''"
+			if ( prefix != cur_prefix )
+				prefix = cur_prefix
+			else
+				printf " "
+			var = $1
+			printf "%s'\'' '\''", var
+			if ( ENVIRON["SHOW_DEFAULT_VALUE"] ) {
+				default = ENVIRON["_" var "_default"]
+				gsub(/'\''/, "'\''\\'\'\''", default)
+				value = ENVIRON[var]
+				gsub(/'\''/, "'\''\\'\'\''", value)
+				printf ENVIRON["msg_default_value"] "; %s",
+				       default, value
+			} else if ( ENVIRON["SHOW_CONFIGURED"] ) {
+				printf "%s", ENVIRON["_" var "_file"]
+			} else { # SHOW_VALUE (default behavior)
+				value = ENVIRON[var]
+				gsub(/'\''/, "'\''\\'\'\''", value)
+				printf "%s", value
+			}
+			printf "'\''"
+			if ( ENVIRON["SHOW_DESC"] ) {
+				desc = ENVIRON["_" var "_desc"]
+				gsub(/'\''/, "'\''\\'\'\''", desc)
+				printf " '\''%s'\''", desc
+			}
+			printf "\n"
+		}'
+	)"
+
+	set -f # noglob
+
+	size=$( eval f_dialog_menu_${SHOW_DESC:+with_help_}size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$RCCONF_MENU_LIST      )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--help-button                      \
+		--help-label \"\$msg_details\"     \
+		${SHOW_DESC:+--item-help}          \
+		--menu \"\$prompt\" $size          \
+		$RCCONF_MENU_LIST                  \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_view_edit_startup_configuration"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	if [ "$USE_XDIALOG" ]; then
+		case "$mtag" in
+		"> $msg_view_details")
+			f_dialog_input_view_details
+			continue
+		esac
+	elif [ $retval -eq 2 ]; then
+		# The ``Help'' button (labeled "Details") was pressed
+		f_dialog_input_view_details
+		continue
+	fi
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+	"> $msg_add_new")
+		$BSDCFG_LIBE/$APP_DIR/rcadd ${USE_XDIALOG:+-X}
+		;;
+	"> $msg_delete")
+		# rcdelete has a similar interface that can inherit the below:
+		export SHOW_VALUE SHOW_DESC SHOW_DEFAULT_VALUE SHOW_CONFIGURED
+		$BSDCFG_LIBE/$APP_DIR/rcdelete ${USE_XDIALOG:+-X}
+		;;
+	*) # Anything else is a variable to edit
+		$BSDCFG_LIBE/$APP_DIR/rcedit ${USE_XDIALOG:+-X} "${mtag# }"
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/rcdelete
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/rcdelete	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,355 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcdelete 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="140.startup"
+f_include $BSDCFG_LIBE/$APP_DIR/include/rcconf.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ GLOBALS
+
+#
+# Global map/menu-list for the main menu
+#
+RCCONF_MAP=
+_RCCONF_MAP=
+RCCONF_MENU_LIST=
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+( : ${SHOW_DESC?} ) > /dev/null 2>&1 || SHOW_DESC=1
+# Selectively inherit SHOW_* value (in order of preference)
+if [ "$SHOW_DEFAULT_VALUE" ]; then
+	SHOW_DEFAULT_VALUE=1
+	SHOW_CONFIGURED=
+	SHOW_VALUE=
+elif [ "$SHOW_CONFIGURED" ]; then
+	SHOW_DEFAULT_VALUE=
+	SHOW_CONFIGURED=1
+	SHOW_VALUE=
+else
+	SHOW_DEFAULT_VALUE=
+	SHOW_CONFIGURED=
+	SHOW_VALUE=1
+fi
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local size
+	local hline="$hline_arrows_tab_enter"
+	local prompt=""
+
+	RCCONF_MENU_LIST="
+		'X $msg_exit_cancel'     '$msg_exit_cancel_desc'
+		            ${SHOW_DESC:+'$msg_exit_cancel_help'}
+		'> $msg_delete_selected' '$msg_delete_selected_desc'
+		            ${SHOW_DESC:+'$msg_delete_selected_help'}
+		'> $msg_all'             '$msg_all_desc'
+		            ${SHOW_DESC:+'$msg_all_help'}
+		'> $msg_none'            '$msg_none_desc'
+		            ${SHOW_DESC:+'$msg_none_help'}
+	${USE_XDIALOG:+
+		'> $msg_view_details' '$msg_view_details_desc'
+		                       ${SHOW_DESC:+'$msg_view_details_help'}
+	}
+	" # END-QUOTE
+
+	if [ ! "$_RCCONF_MAP" ]; then
+		# Genreate RCCONF_MAP of `var desc ...' per-line
+		f_dialog_info "$msg_creating_rcconf_map"
+		RCCONF_MAP=$( f_startup_rcconf_map )
+		export RCCONF_MAP
+		# Generate _${var}_desc variables from $RCCONF_MAP
+		f_startup_rcconf_map_expand
+		export _RCCONF_MAP=1
+	fi
+
+	# Show infobox for modes that take a while to calculate/display
+	[ "$SHOW_DEFAULT_VALUE" -o "$SHOW_CONFIGURED" ] &&
+		f_dialog_info "$msg_creating_menu_list"
+
+	RCCONF_MENU_LIST="$RCCONF_MENU_LIST $(
+		. "$RC_DEFAULTS" > /dev/null
+		source_rc_confs > /dev/null
+		var_list=$( f_startup_rcconf_list )
+		for var in $var_list; do
+			eval export $var
+			[ "$SHOW_DEFAULT_VALUE" ] && export \
+				_${var}_default="$( f_sysrc_get_default $var )"
+			[ "$SHOW_CONFIGURED" ] && export \
+				_${var}_file="$( f_sysrc_find $var )"
+		done
+		export SHOW_VALUE SHOW_DESC SHOW_DEFAULT_VALUE SHOW_CONFIGURED
+		export msg_default_value
+		echo "$var_list" | awk '
+		BEGIN {
+			prefix = ""
+		}
+		{
+			cur_prefix = tolower(substr($1, 1, 1))
+			printf "'\''"
+			if ( prefix != cur_prefix )
+				prefix = cur_prefix
+			else
+				printf " "
+			var = $1
+			printf "%s'\'' '\''[", var
+			if ( ENVIRON["_" var "_delete"] )
+				printf "X"
+			else
+				printf " "
+			printf "] "
+			if ( ENVIRON["SHOW_DEFAULT_VALUE"] ) {
+				default = ENVIRON["_" var "_default"]
+				gsub(/'\''/, "'\''\\'\'\''", default)
+				value = ENVIRON[var]
+				gsub(/'\''/, "'\''\\'\'\''", value)
+				printf ENVIRON["msg_default_value"] "; %s",
+				       default, value
+			} else if ( ENVIRON["SHOW_CONFIGURED"] ) {
+				printf "%s", ENVIRON["_" var "_file"]
+			} else { # SHOW_VALUE (default behavior)
+				value = ENVIRON[var]
+				gsub(/'\''/, "'\''\\'\'\''", value)
+				printf "%s", value
+			}
+			printf "'\''"
+			if ( ENVIRON["SHOW_DESC"] ) {
+				desc = ENVIRON["_" var "_desc"]
+				gsub(/'\''/, "'\''\\'\'\''", desc)
+				printf " '\''%s'\''", desc
+			}
+			printf "\n"
+		}'
+	)"
+
+	set -f # noglob
+
+	size=$( eval f_dialog_menu_${SHOW_DESC:+with_help_}size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$RCCONF_MENU_LIST      )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--help-button                      \
+		--help-label \"\$msg_details\"     \
+		${SHOW_DESC:+--item-help}          \
+		--menu \"\$prompt\" $size          \
+		$RCCONF_MENU_LIST                  \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# dialog_menu_delete $var1 [$var2 ...]
+#
+# Get the user's blessing to delete one or more variables.
+# if (and only-if) the user confirms (does not press ESC or Cancel/NO).
+#
+dialog_menu_delete()
+{
+	local size
+	local hline="$hline_arrows_tab_enter"
+	local prompt="$msg_are_you_sure_you_want_delete_the_following"
+	local var_list menu_list
+
+	[ $# -ge 1 ] || return $FAILURE
+
+	if [ $# -eq 1 ]; then
+		msg=$( printf "$msg_are_you_sure_you_want_to_delete" \
+		              "$delete_vars" )
+		f_dialog_noyes "$msg"
+		return $?
+	fi
+
+	var_list=$( for var in $*; do echo "$var"; done | sort -u )
+	menu_list=$(
+		. "$RC_DEFAULTS"
+		source_rc_confs
+		echo "$var_list" | awk '
+		BEGIN {
+			prefix = ""
+		}
+		{
+			cur_prefix = tolower(substr($1, 1, 1))
+			printf "'\''"
+			if ( prefix != cur_prefix )
+				prefix = cur_prefix
+			else
+				printf " "
+			var = $1
+			printf "%s'\'' '\'\''\n", var
+		}'
+	)
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	local defaultno="defaultno"
+	[ "$USE_XDIALOG" ] && defaultno="default-no"
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--$defaultno                       \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_delete_startup_directives"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	if [ "$USE_XDIALOG" ]; then
+		case "$mtag" in
+		"> $msg_view_details")
+			f_dialog_input_view_details
+			continue
+		esac
+	elif [ $retval -eq 2 ]; then
+		# The ``Help'' button (labeled "Details") was pressed
+		f_dialog_input_view_details
+		continue
+	fi
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit_cancel") break ;;
+	"> $msg_delete_selected")
+		delete_vars=
+		for var in $( f_startup_rcconf_list ); do
+			[ "$( eval echo \$_${var}_delete )" ] || continue
+			delete_vars="$delete_vars${delete_vars:+ }$var"
+		done
+		unset var # no longer needed
+		if dialog_menu_delete $delete_vars; then
+			f_dialog_title "$msg_info"
+			f_dialog_info "$msg_deleting_selected_directives"
+			f_dialog_title_restore
+			for var in $delete_vars; do
+				err=$( f_sysrc_delete $var 2>&1 )
+				if [ $? -ne $SUCCESS ]; then
+					f_show_msg "%s\n" "$err"
+					break
+				fi
+			done
+			unset var # no longer needed
+		fi
+		;;
+	"> $msg_all")
+		for var in $( f_startup_rcconf_list ); do
+			setvar _${var}_delete 1
+			export _${var}_delete
+		done
+		unset var # no longer needed
+		;;
+	"> $msg_none")
+		var_list=$( set | awk -F= "
+			/$STARTUP_RCCONF_REGEX/ {
+				if (\$1 ~ /^_[[:alpha:]_][[:alnum:]_]*_delete/)
+					print \$1
+			}"
+		)
+		[ "$var_list" ] && unset $var_list
+		unset var_list # no longer needed
+		;;
+	*) # Anything else is a variable to edit
+		var="${mtag# }"
+
+		# Toggle the state-variable and loop back to menu
+		if ( eval : \${_${var}_delete?} ) > /dev/null 2>&1; then
+			unset _${var}_delete
+		else
+			setvar _${var}_delete 1
+			export _${var}_delete
+		fi
+		unset var # no longer needed
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/rcedit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/rcedit	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,69 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcedit 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="140.startup"
+f_include $BSDCFG_LIBE/$APP_DIR/include/rcedit.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+f_dialog_rcedit "$@"
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/rcvar
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/rcvar	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,200 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/rcvar 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/sysrc.subr
+
+APP_DIR="140.startup"
+f_include $BSDCFG_LIBE/$APP_DIR/include/rcvar.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ GLOBALS
+
+#
+# Global map/menu-list for the main menu
+#
+RCVAR_MAP=
+_RCVAR_MAP=
+RCVAR_MENU_LIST=
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+( ${SHOW_DESC?} ) > /dev/null 2>&1 || SHOW_DESC=1
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local size
+	local hline="$hline_arrows_tab_enter"
+	local prompt=""
+
+	RCVAR_MENU_LIST="
+		'X $msg_exit' '$msg_exit_this_menu'
+		              ${SHOW_DESC:+'$msg_exit_this_menu'}
+	" # END-QUOTE
+
+	if [ ! "$_RCVAR_MAP" ]; then
+		# Genreate RCVAR_MAP of `rcvar dflt script desc ...' per-line
+		f_dialog_info "$msg_creating_rcvar_map"
+		RCVAR_MAP=$( f_startup_rcvar_map )
+		export RCVAR_MAP
+		export _RCVAR_MAP=1
+	fi
+
+	RCVAR_MENU_LIST="$RCVAR_MENU_LIST $(
+		. "$RC_DEFAULTS" > /dev/null
+		source_rc_confs > /dev/null
+		for rcvar in $( echo "$RCVAR_MAP" | awk '{print $1}' ); do
+			eval export $rcvar
+		done
+		export SHOW_DESC msg_default_value
+		echo "$RCVAR_MAP" | awk '
+		BEGIN {
+			prefix = ""
+			rword  = "^[[:space:]]*[^[:space:]]*[[:space:]]*"
+		}
+		{
+			cur_prefix = tolower(substr($1, 1, 1))
+			printf "'\''"
+			if ( prefix != cur_prefix )
+				prefix = cur_prefix
+			else
+				printf " "
+			rcvar   = $1
+			default = $2
+			script  = $3
+			printf "%s'\'' '\''", rcvar
+			if ( ENVIRON[rcvar] ~ /[Yy][Ee][Ss]/ )
+				printf "[X] "
+			else
+				printf "[ ] "
+			printf "%s; " ENVIRON["msg_default_value"],
+			       script, default
+			printf "'\''"
+			if ( ENVIRON["SHOW_DESC"] ) {
+				desc = $0
+				sub(rword, "", desc)
+				sub(rword, "", desc)
+				sub(rword, "", desc)
+				gsub(/'\''/, "'\''\\'\'\''", desc)
+				printf " '\''%s'\''", desc
+			}
+			printf "\n"
+		}'
+	)"
+
+	set -f # noglob
+
+	size=$( eval f_dialog_menu_${SHOW_DESC:+with_help_}size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$RCVAR_MENU_LIST       )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		${SHOW_DESC:+--item-help}          \
+		--menu \"\$prompt\" $size          \
+		$RCVAR_MENU_LIST                   \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_toggle_startup_services"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+	*) # Anything else is an rcvar to toggle
+
+		rcvar="${mtag# }"
+		value=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \
+		         	\"\$mtag\" $RCVAR_MENU_LIST )
+
+		# Determine the new [toggled] value to use
+		case "$value" in
+		"[X]"*) value="NO";;
+		     *) value="YES";;
+		esac
+
+		err=$( f_sysrc_set "$rcvar" "$value" 2>&1 ) ||
+			f_show_msg "$err"
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/startup/startup
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/startup/startup	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,128 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/startup/startup 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_arrows_tab_enter"
+	local prompt=""
+
+	menu_list="
+		'X' '$msg_exit'
+		'1' '$msg_toggle_startup_services'
+		'2' '$msg_view_edit_startup_configuration'
+		'3' '$msg_miscellaneous_startup_services'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	                \"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$prompt\" $size          \
+		$menu_list                         \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_startup"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	X) # Exit
+		break ;;
+	1) # Toggle Startup Services
+		$BSDCFG_LIBE/$APP_DIR/rcvar ${USE_XDIALOG:+-X} ;;
+	2) # View/Edit Startup Configuration
+		$BSDCFG_LIBE/$APP_DIR/rcconf ${USE_XDIALOG:+-X} ;;
+	3) # Miscellaneous Startup Services
+		$BSDCFG_LIBE/$APP_DIR/misc ${USE_XDIALOG:+-X} ;;
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Timezone"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Set up Time Zone"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="timezone|timezone"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="timezone"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/090.timezone
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	timezone
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,42 @@
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [-ehnrSsvX] [-C chroot_dir] [zinfo_file | zinfo_name]
+OPTIONS:
+	-h         Print usage statement and exit.
+	-e         Only return success on exit if user selects a timezone AND
+	           the selected timezone was successfully installed. By default
+	           (without this flag), success is always returned unless an
+	           error has occurred.
+	-n         Do not create or copy files.
+	-r         Reinstall the zoneinfo file installed last time. The name is
+	           obtained from /var/db/zoneinfo.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-s         Skip the initial question about adjusting the clock if
+	           not set to UTC.
+	-v         Verbose. Enable extra output when installing the zone file.
+	-X         Enable the use of Xdialog(1) instead of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,12 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/090.timezone/include
+FILES=		continents.subr countries.subr iso3166.subr menus.subr \
+		messages.subr zones.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/continents.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/continents.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,138 @@
+if [ ! "$_TIMEZONE_CONTINENTS_SUBR" ]; then _TIMEZONE_CONTINENTS_SUBR=1
+#
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/continents.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+
+APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# List of worldly continents/oceans (export'ed for awk(1) ENVIRON visibility)
+#
+export CONTINENTS="
+	africa
+	america
+	antarctica
+	arctic
+	asia
+	atlantic
+	australia
+	europe
+	indian
+	pacific
+	utc
+"
+
+#
+# Directory name of each continent/ocean (in _PATH_ZONEINFO)
+#
+export continent_africa_name="Africa"
+export continent_america_name="America"
+export continent_antarctica_name="Antarctica"
+export continent_arctic_name="Arctic"
+export continent_asia_name="Asia"
+export continent_atlantic_name="Atlantic"
+export continent_australia_name="Australia"
+export continent_europe_name="Europe"
+export continent_indian_name="Indian"
+export continent_pacific_name="Pacific"
+export continent_utc_name="UTC"
+
+#
+# Export i18n menu texts of continents/oceans for awk(1) ENVIRON visibility
+# NOTE: These are defined in messages.subr included above.
+#
+export continent_africa_title
+export continent_america_title
+export continent_antarctica_title
+export continent_arctic_title
+export continent_asia_title
+export continent_atlantic_title
+export continent_australia_title
+export continent_europe_title
+export continent_indian_title
+export continent_pacific_title
+export continent_utc_title
+
+############################################################ FUNCTIONS
+
+# f_continent $cont $property
+#
+# Returns a single property of a given continent. Available properties are:
+#
+# 	name        Directory name of continent/ocean as it appears in
+# 	            _PATH_ZONEINFO.
+# 	title       Menu text of this continent/ocean to be displayed in the
+# 	            continent-selection menu.
+# 	nitems      Number of submenu items associated with this
+# 	            continent/ocean.
+# 	tlc_N       2-character country code of the Nth submenu item associated
+# 	            with this continent displayed in the country-selection menu
+# 	            (which appears after continent selection).
+# 	menu_list   Menu-list of regions for this continent.
+#
+f_continent()
+{
+	local cont="$1" property="$2"
+	eval echo \"\${continent_${cont}_$property}\"
+}
+
+# f_find_continent $title
+#
+# Returns continent identifier given continent title.
+#
+f_find_continent()
+{
+	local cont
+	for cont in $CONTINENTS; do
+		if [ "$1" = "$( f_continent $cont title )" ]; then
+			echo "$cont"
+			return $SUCCESS
+		fi
+	done
+	return $FAILURE
+}
+
+# f_OCEANP $cont
+#
+# Returns "1" if the first argument is an ocean, otherwise NULL.
+#
+f_OCEANP()
+{
+	case "$1" in
+	arctic|atlantic|indian|pacific)
+		echo 1
+	esac
+}
+
+fi # ! $_TIMEZONE_CONTINENTS_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/countries.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/countries.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,78 @@
+if [ ! "$_TIMEZONE_COUNTRIES_SUBR" ]; then _TIMEZONE_COUNTRIES_SUBR=1
+#
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/countries.subr 238438 2012-07-14 03:16:57Z dteske $
+
+# f_country $code $property
+#
+# Returns a single property of a given country. Available properties are:
+#
+# 	name         Name of the country as read from _PATH_ISO3166.
+# 	nzones       Number of zones within the country (-1 if country has
+# 	             only a single zone).
+# 	filename     The filename portion of the TZ field (after the `/') as
+# 	             read from _PATH_ZONETAB.
+# 	cont         The principal continent in which the country lies (appears
+# 	             before the `/' in the TZ field of _PATH_ZONETAB).
+# 	filename_N   Like filename, but for the Nth zone when the country has
+# 	             multiple zones (nzones > 0).
+# 	cont_N       Like cont, but for the Nth zone when the country has
+# 	             multiple zones (nzones > 0).
+# 	descr_N      Like name, but for the Nth zone when the country has
+# 	             multiple zones (nzones > 0)
+#
+f_country()
+{
+	local code="$1" property="$2"
+	eval echo \"\${country_${code}_$property}\"
+}
+
+# f_sort_countries
+#
+# Sorts alphabetically the 2-character country codes listed in $COUNTRIES based
+# on the name of each country.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_sort_countries_awk='
+{
+	split($0, array, /[[:space:]]+/)
+	for (item in array)
+	{
+		tlc = array[item]
+		print ENVIRON["country_" tlc "_name"] " " tlc
+	}
+}
+'
+f_sort_countries()
+{
+	COUNTRIES=$( echo "$COUNTRIES" | awk "$f_sort_countries_awk" |
+	             	sort | awk '{print $NF}' )
+	export COUNTRIES
+}
+
+fi # ! $_TIMEZONE_COUNTRIES_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/iso3166.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/iso3166.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,197 @@
+if [ ! "$_TIMEZONE_ISO3166_SUBR" ]; then _TIMEZONE_ISO3166_SUBR=1
+#
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/iso3166.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+
+APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_ISO3166="/usr/share/misc/iso3166"
+
+#
+# Export required i18n messages for awk(1) ENVIRON visibility
+#
+export msg_country_code_multiply_defined
+export msg_invalid_code
+export msg_invalid_format
+
+############################################################ FUNCTIONS
+
+# f_read_iso3166_table
+#
+# Read the ISO 3166 country code database in _PATH_ISO3166:
+# 	/usr/share/misc/iso3166 on FreeBSD
+# 	/usr/share/zoneinfo/iso3166.tab on Linux, Mac OS X, and Cygwin
+#
+# The format of this file on FreeBSD is:
+# 	two	three	number	name
+#
+# The format of this file on Linux, Mac OS X, and Cygwin is:
+# 	two	name
+#
+# With each of the following elements (described below) being separated by a
+# single tab character:
+#
+# 	two      ISO 3166 2-character country code
+# 	three    ISO 3166 3-character country code (if provided)
+# 	number   ISO 3166 numeric country code (if provided)
+# 	name     Human-readable country name (may contain spaces)
+#
+# Variables created by this function:
+#
+# 	COUNTRIES
+# 		A space-separated list of 2-character country codes.
+# 	country_CODE_name
+# 		The country `name' (as described above).
+#
+# where CODE is the 2-character country code.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_read_iso3166_table_awk='
+# Variables that should be defined on the invocation line:
+# 	-v progname="progname"
+#
+BEGIN {
+	lineno = 0
+	failed = 0
+}
+function die(fmt, argc, argv)
+{
+	printf "f_die 1 \"%%s: %s\" \"%s\"", fmt, progname
+	for (n = 1; n <= argc; n++)
+		printf " \"%s\"", argv[n]
+	print ""
+	failed++
+	exit 1
+}
+function add_country(tlc, name)
+{
+	if (country_name[tlc])
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = tlc
+		argv[4] = name
+		die(ENVIRON["msg_country_code_multiply_defined"], 4, argv)
+	}
+
+	country_name[tlc] = name
+}
+function print_country_name(tlc)
+{
+	name = country_name[tlc]
+	gsub(/"/, "\\\"", name)
+	printf "country_%s_name=\"%s\"\n", tlc, name
+	printf "export country_%s_name\n", tlc
+}
+/^#/ {
+	lineno++
+	next
+}
+!/^#/ {
+	lineno++
+
+	# Split the current record (on TAB) into an array
+	split($0, line, /\t/)
+
+	# Get the ISO3166-1 (Alpha 1) 2-letter country code
+	tlc = line[1]
+
+	#
+	# Validate the two-character country code
+	#
+	if (length(tlc) != 2)
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		die(ENVIRON["msg_invalid_format"], 2, argv)
+	}
+	if (!match(tlc, /^[A-Z][A-Z]$/))
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = tlc
+		die(ENVIRON["msg_invalid_code"], 3, argv)
+	}
+
+	#
+	# Calculate the substr start-position of the name
+	#
+	name_start = 0
+	n = 4
+	if (FILENAME ~ /\.tab$/)
+		n = 2
+	while (--n)
+	{
+		#
+		# Validate field-length of 2nd/3rd columns while we are here
+		#
+		if (n > 1  && length(line[n]) != 3)
+		{
+			argv[1] = FILENAME
+			argv[2] = lineno
+			die(ENVIRON["msg_invalid_format"], 2, argv)
+		}
+
+		name_start += length(line[n]) + 1
+	}
+
+	# Get the name field
+	name = substr($0, name_start + 1)
+
+	add_country(tlc, name)
+}
+END {
+	list = ""
+	for (tlc in country_name)
+	{
+		list = list (length(list) > 0 ? " " : "") tlc
+		print_country_name(tlc)
+	}
+	printf "COUNTRIES=\"%s\"\n", list
+	print "export COUNTRIES"
+}
+'
+f_read_iso3166_table()
+{
+	eval $( awk -v progname="$pgm"          \
+	            "$f_read_iso3166_table_awk" \
+	            "$_PATH_ISO3166"            )
+}
+
+fi # ! $_TIMEZONE_ISO3166_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/menus.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/menus.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,220 @@
+if [ ! "$_TIMEZONE_MENUS_SUBR" ]; then _TIMEZONE_MENUS_SUBR=1
+#
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/menus.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+############################################################ GLOBALS
+
+#
+# Export special included variables required by awk(1) for `ENVIRON' visibility
+#
+export DIALOG_MENU_TAGS
+
+############################################################ FUNCTIONS
+
+# f_make_menus
+#
+# Creates the tag/item ordered-pair list environment variables for the
+# continent and country menus.
+#
+# Required variables [from continents.subr]:
+#
+# 	CONTINENTS
+# 		Space-separated list of continents.
+# 	continent_*_title
+# 		Desired menu text for the continent represented by *.
+#
+# Required variables [created by f_read_iso3166_table from iso3166.subr]:
+#
+# 	COUNTRIES
+# 		Space-separated list of 2-character country codes.
+# 	country_*_name :: when country_*_nzones < 0
+# 		Desired menu text for the country-zone represented by *, the 2-
+# 		character country code.
+#
+# Required variables [created by f_read_zones from zones.subr]:
+#
+# 	country_*_nzones
+# 		Number of zones for the country represented by *, the 2-
+# 		character country code. Should be -1 if the country has only
+# 		one single zone, otherwise 1 or greater to indicate how many
+# 		zones the country has.
+# 	country_*_cont :: when country_*_nzones < 0
+# 		Principal continent (or ocean) in which the country-zone
+# 		represented by *, the 2-character country code, resides.
+# 	country_*_cont_N :: when country_*_nzones > 0
+# 		Principal continent (or ocean) in which zone-N of the country
+# 		represented by * resides, the 2-character country code.
+# 	country_*_descr_N :: when country_*_nzones > 0
+# 		Desired submenu text for zone-N of the country represented by
+# 		*, the 2-character country code.
+#
+# Variables created by this function:
+#
+# 	continent_menu_list
+# 		Menu-list of continents.
+# 	continent_*_nitems
+# 		Number of items associated with the continent represented by *,
+# 		the continent identifier.
+# 	continent_*_tlc_N
+# 		2-character country code of the Nth item in the continent menu
+# 		for the continent represented by *, the continent identifier.
+# 	continent_*_menu_list
+# 		Menu-list of countries/zones for each continent represented by
+# 		*, the continent identifier.
+# 	country_*_menu_list
+# 		For countries that have multiple zones, this is the submenu-
+# 		list of zones for said country represented by *, the 2-
+# 		character country code.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_make_menus_awk='
+function add_zone_n_to_country_menu(tlc, n)
+{
+	zone_title = ENVIRON["country_" tlc "_descr_" n]
+	gsub(/'\''/, "'\''\\'\'''\''", zone_title)
+	country_menu_list[tlc] = country_menu_list[tlc] \
+		( length(country_menu_list[tlc]) > 0 ? "\n" : "" ) \
+		n " '\''" zone_title "'\''"
+}
+BEGIN {
+	#
+	# First, count up all the countries in each continent/ocean.
+	# Be careful to count those countries which have multiple zones
+	# only once for each.  NB: some countries are in multiple
+	# continents/oceans.
+	#
+	i = split(ENVIRON["COUNTRIES"], countries, /[[:space:]]+/)
+	for (cp = 1; cp <= i; cp++)
+	{
+		tlc = countries[cp]
+		title = ENVIRON["country_" tlc "_name"]
+		gsub(/'\''/, "'\''\\'\'''\''", title)
+		nzones = ENVIRON["country_" tlc "_nzones"]
+		if (!nzones)
+		{
+			# Country has no zones
+			continue
+		}
+		else if (nzones < 0)
+		{
+			# Country has only one zone
+			cont = ENVIRON["country_" tlc "_cont"]
+			nitems = ++continent_nitems[cont]
+			continent_tlc[cont,nitems] = tlc
+			continent_title[cont,nitems] = title
+		}
+		else
+		{
+			# Country has one or more zones
+			for (n = 1; n <= nzones; n++)
+			{
+				add_zone_n_to_country_menu(tlc, n)
+				cont = ENVIRON["country_" tlc "_cont_" n]
+				for (x = 1; x < n; x++)
+				{
+					contx = ENVIRON["country_"tlc"_cont_"x]
+					if (cont == contx) break
+				}
+				if (x == n)
+				{
+					nitems = ++continent_nitems[cont]
+					continent_tlc[cont,nitems] = tlc
+					continent_title[cont,nitems] = title
+				}
+			}
+		}
+	}
+}
+END {
+	tags = ENVIRON["DIALOG_MENU_TAGS"]
+	cont_menu_list = ""
+	tagn = 0
+
+	#
+	# Assemble the menu items in the menu list for each continent/ocean.
+	#
+	i = split(ENVIRON["CONTINENTS"], array, /[[:space:]]+/)
+	for (item = 1; item <= i; item++)
+	{
+		cont = array[item]
+		if (!cont) continue
+
+		if (++tagn >= length(tags)) break
+		tag = substr(tags, tagn, 1)
+		cont_menu_list = cont_menu_list \
+			( length(cont_menu_list) > 0 ? "\n" : "" ) \
+			"'\''" tag "'\'' '\''" \
+			ENVIRON["continent_" cont "_title"] "'\''"
+
+		nitems = continent_nitems[cont]
+		printf "continent_%s_nitems=%d\n", cont, nitems
+
+		menu_list = ""
+		for (n = 1; n <= nitems; n++)
+		{
+			printf "continent_%s_tlc_%d=%s\n",
+			       cont, n, continent_tlc[cont,n]
+
+			title = continent_title[cont,n]
+			menu_list = menu_list \
+				( length(menu_list) > 0 ? "\n" : "" ) \
+				n " '\''" title "'\''"
+		}
+
+		gsub(/"/, "\\\"", menu_list)
+		printf "continent_%s_menu_list=\"%s\"\n", cont, menu_list
+	}
+
+	gsub(/"/, "\\\"", continent_menu_list)
+	printf "continent_menu_list=\"%s\"\n", cont_menu_list
+	print "export continent_menu_list"
+
+	#
+	# Dump the submenus of countries with multiple zones
+	#
+	for (tlc in country_menu_list)
+	{
+		menu_list = country_menu_list[tlc]
+		gsub(/"/, "\\\"", menu_list)
+		printf "country_%s_menu_list=\"%s\"\n", tlc, menu_list
+	}
+}
+'
+f_make_menus()
+{
+	eval $( :| awk "$f_make_menus_awk" )
+}
+
+fi # ! $_TIMEZONE_MENUS_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,78 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+continent_africa_title="Africa"
+continent_america_title="America -- North and South"
+continent_antarctica_title="Antarctica"
+continent_arctic_title="Arctic Ocean"
+continent_asia_title="Asia"
+continent_atlantic_title="Atlantic Ocean"
+continent_australia_title="Australia"
+continent_europe_title="Europe"
+continent_indian_title="Indian Ocean"
+continent_pacific_title="Pacific Ocean"
+continent_utc_title="UTC"
+msg_cancel="Cancel"
+msg_cannot_open_for_reading="Cannot open %s for reading. Does it exist?"
+msg_confirmation="Confirmation"
+msg_conflicting_zone_definition="%s:%d: conflicting zone definition"
+msg_copied_timezone_file="Copied timezone file from %s to %s"
+msg_copying_file="Copying %s to %s"
+msg_country_code_invalid="%s:%d: country code \`%s' invalid"
+msg_country_code_multiply_defined="%s:%d: country code \`%s' multiply defined: %s"
+msg_country_code_unknown="%s:%d: country code \`%s' unknown"
+msg_country_time_zones="%s Time Zones"
+msg_country_title="Countries in %s"
+msg_created_symlink="Created symbolic link from %s to %s"
+msg_creating_symlink="Creating symbolic link %s to %s"
+msg_default_zone_provided="Default timezone provided"
+msg_done="Done"
+msg_error="Error"
+msg_error_reading="Error reading %s."
+msg_info="Info"
+msg_invalid_code="%s:%d: invalid code \`%s'"
+msg_invalid_country_code="%s:%d: invalid country code \`%s'"
+msg_invalid_format="%s:%d: invalid format"
+msg_invalid_region="%s:%d: invalid region \`%s'"
+msg_invalid_zone_name="%s:%d: invalid zone name \`%s'"
+msg_is_machine_clock_utc="Is the machine's CMOS clock set to UTC? If it is set to local time,\nor you don't know, please choose NO here!"
+msg_island_and_group_title="Islands and groups in the %s"
+msg_look_reasonable="Does the abbreviation \`%s' look reasonable?"
+msg_no="No"
+msg_ok="OK"
+msg_removed_file="Removed %s"
+msg_removing_file="Removing %s"
+msg_select_country="Select a country"
+msg_select_island_or_group="Select an island or group"
+msg_select_local_or_utc="Select local or UTC (Greenwhich Mean Time) clock"
+msg_select_region="Select a region"
+msg_select_zone="Select a zone which observes the same time as your locality."
+msg_time_zone="Time Zone"
+msg_unable_to_determine_name_from_db="Unable to determine earlier installed zoneinfo name. Check %s"
+msg_use_default_zone="Use the default \`%s' zone?"
+msg_yes="Yes"
+msg_zone_multiply_defined="%s:%d: zone multiply defined"
+msg_zone_must_have_description="%s:%d: zone must have description"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/include/zones.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/include/zones.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,670 @@
+if [ ! "$_TIMEZONE_ZONES_SUBR" ]; then _TIMEZONE_ZONES_SUBR=1
+#
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/include/zones.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+APP_DIR="090.timezone"
+f_include $BSDCFG_LIBE/$APP_DIR/include/continents.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_ZONETAB="/usr/share/zoneinfo/zone.tab"
+_PATH_ZONEINFO="/usr/share/zoneinfo"
+_PATH_LOCALTIME="/etc/localtime"
+_PATH_DB="/var/db/zoneinfo"
+
+#
+# Export required i18n messages for awk(1) ENVIRON visibility
+#
+export msg_conflicting_zone_definition
+export msg_country_code_invalid
+export msg_country_code_unknown
+export msg_invalid_country_code
+export msg_invalid_format
+export msg_invalid_region
+export msg_invalid_zone_name
+export msg_zone_multiply_defined
+export msg_zone_must_have_description
+
+############################################################ FUNCTIONS
+
+# f_read_zones
+#
+# Read the zone descriptions database in _PATH_ZONETAB:
+# 	/usr/share/zoneinfo/zone.tab on all OSes
+#
+# The format of this file (on all OSes) is:
+# 	code	coordinates	TZ	comments
+#
+# With each of the following elements (described below) being separated by a
+# single tab character:
+#
+# 	code
+# 		The ISO 3166 2-character country code.
+# 	coordinates
+# 		Latitude and logitude of the zone's principal location in ISO
+# 		6709 sign-degrees-minutes-seconds format, either +-DDMM+-DDDMM
+# 		or +-DDMMSS+-DDDMMSS, first latitude (+ is north), then long-
+# 		itude (+ is east).
+# 	TZ
+# 		Zone name used in value of TZ environment variable.
+# 	comments
+# 		Comments; present if and only if the country has multiple rows.
+#
+# Required variables [from continents.subr]:
+#
+# 	CONTINENTS
+# 		Space-separated list of continents.
+# 	continent_*_name
+# 		Directory element in _PATH_ZONEINFO for the continent
+# 		represented by *.
+#
+# Required variables [created by f_read_iso3166_table from iso3166.subr]:
+#
+# 	country_CODE_name
+# 		Country name of the country represented by CODE, the 2-
+# 		character country code.
+#
+# Variables created by this function:
+#
+# 	country_CODE_nzones
+# 		Either set to `-1' to indicate that the 2-character country
+# 		code has only a single zone associated with it (and therefore
+# 		you should query the `country_CODE_*' environment variables),
+# 		or set to `0' or higher to indicate how many zones are assoc-
+# 		iated with the given country code. When multiple zones are
+# 		configured for a single code, you should instead query the
+# 		`country_CODE_*_N' environment variables (e.g., `echo
+# 		$country_AQ_descr_1' prints the description of the first
+# 		timezone in Antarctica).
+# 	country_CODE_filename
+# 		The ``filename'' portion of the TZ value that appears after the
+# 		`/' (e.g., `Hong_Kong' from `Asia/Hong_Kong' or `Isle_of_Man'
+# 		from `Europe/Isle_of_Man').
+# 	country_CODE_cont
+# 		The ``continent'' portion of the TZ value that appears before
+# 		the `/' (e.g., `Asia' from `Asia/Hong_Kong' or `Europe' from
+# 		`Europe/Isle_of_Man').
+# 	country_CODE_descr
+# 		The comments associated with the ISO 3166 code entry (if any).
+#
+# 	NOTE: CODE is the 2-character country code.
+# 	
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_read_zones_awk='
+# Variables that should be defined on the invocation line:
+# 	-v progname="progname"
+#
+BEGIN {
+	lineno = 0
+	failed = 0
+
+	#
+	# Initialize continents array/map (name => id)
+	#
+	split(ENVIRON["CONTINENTS"], array, /[[:space:]]+/)
+	for (item in array)
+	{
+		cont = array[item]
+		if (!cont) continue
+		name = ENVIRON["continent_" cont "_name"]
+		continents[name] = cont
+	}
+}
+function die(fmt, argc, argv)
+{
+	printf "f_die 1 \"%%s: %s\" \"%s\"", fmt, progname
+	for (n = 1; n <= argc; n++)
+		printf " \"%s\"", argv[n]
+	print ""
+	failed++
+	exit 1
+}
+function find_continent(name)
+{
+	return continents[name]
+}
+function add_zone_to_country(lineno, tlc, descr, file, cont)
+{
+	#
+	# Validate the two-character country code
+	#
+	if (!match(tlc, /^[A-Z][A-Z]$/))
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = tlc
+		die(ENVRION["msg_country_code_invalid"], 3, argv)
+	}
+	if (!ENVIRON["country_" tlc "_name"])
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = tlc
+		die(ENVIRON["msg_country_code_unknown"], 3, argv)
+	}
+
+	#
+	# Add Zone to an array that we will parse at the end
+	#
+	if (length(descr) > 0)
+	{
+		if (country_nzones[tlc] < 0)
+		{
+			argv[1] = FILENAME
+			argv[2] = lineno
+			die(ENVIRON["msg_conflicting_zone_definition"], 2, argv)
+		}
+
+		n = ++country_nzones[tlc]
+		country_cont[tlc,n] = cont
+		country_filename[tlc,n] = file
+		country_descr[tlc,n] = descr
+	}
+	else
+	{
+		if (country_nzones[tlc] > 0)
+		{
+			argv[1] = FILENAME
+			argv[2] = lineno
+			die(ENVIRON["msg_zone_must_have_description"], 2, argv)
+		}
+		if (country_nzones[tlc] < 0)
+		{
+			argv[1] = FILENAME
+			argv[2] = lineno
+			die(ENVIRON["msg_zone_multiply_defined"], 2, argv)
+		}
+
+		country_nzones[tlc] = -1
+		country_cont[tlc] = cont
+		country_filename[tlc] = file
+	}
+}
+function print_country_code(tlc)
+{
+	nz = country_nzones[tlc]
+
+	printf "country_%s_nzones=%d\n", tlc, nz
+	printf "export country_%s_nzones\n", tlc
+
+	if (nz < 0)
+	{
+		printf "country_%s_cont=\"%s\"\n", tlc, country_cont[tlc]
+		printf "export country_%s_cont\n", tlc
+		printf "country_%s_filename=\"%s\"\n",
+		       tlc, country_filename[tlc]
+	}
+	else
+	{
+		n = 0
+		while ( ++n <= nz )
+		{
+			printf "country_%s_cont_%d=\"%s\"\n",
+			       tlc, n, country_cont[tlc,n]
+			printf "export country_%s_cont_%d\n", tlc, n
+			printf "country_%s_filename_%d=\"%s\"\n",
+			       tlc, n, country_filename[tlc,n]
+			printf "country_%s_descr_%d=\"%s\"\n",
+			       tlc, n, country_descr[tlc,n]
+		}
+	}
+}
+/^#/ {
+	lineno++
+	next
+}
+!/^#/ {
+	lineno++
+
+	#
+	# Split the current record (on TAB) into an array
+	#
+	if (split($0, line, /\t/) < 2)
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		die(ENVIRON["msg_invalid_format"], 2, argv)
+	}
+
+	# Get the ISO3166-1 (Alpha 1) 2-letter country code
+	tlc = line[1]
+
+	#
+	# Validate the two-character country code
+	#
+	if (length(tlc) != 2)
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = tlc
+		die(ENVIRON["msg_invalid_country_code"], 3, argv)
+	}
+
+	# Get the TZ field
+	tz = line[3]
+
+	#
+	# Validate the TZ field
+	#
+	if (!match(tz, "/"))
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = tz
+		die(ENVIRON["msg_invalid_zone_name"], 3, argv)
+	}
+
+	#
+	# Get the continent portion of the TZ field
+	#
+	contbuf = tz
+	sub("/.*$", "", contbuf)
+
+	#
+	# Validate the continent
+	#
+	cont = find_continent(contbuf)
+	if (!cont)
+	{
+		argv[1] = FILENAME
+		argv[2] = lineno
+		argv[3] = contbuf
+		die(ENVIRON["msg_invalid_region"], 3, argv)
+	}
+
+	#
+	# Get the filename portion of the TZ field
+	#
+	filename = tz
+	sub("^[^/]*/", "", filename)
+
+	#
+	# Calculate the substr start-position of the comment
+	#
+	descr_start = 0
+	n = 4
+	while (--n)
+		descr_start += length(line[n]) + 1
+
+	# Get the comment field
+	descr = substr($0, descr_start + 1)
+
+	add_zone_to_country(lineno, tlc, descr, filename, cont)
+}
+END {
+	if (failed) exit failed
+	for (tlc in country_nzones)
+		print_country_code(tlc)
+}
+'
+f_read_zones()
+{
+	eval $( awk -v progname="$pgm"   \
+	            "$f_read_zones_awk"  \
+	            "$_PATH_ZONETAB"     )
+}
+
+# f_install_zoneinfo_file $filename
+#
+# Installs a zone file to _PATH_LOCALTIME.
+#
+f_install_zoneinfo_file()
+{
+	local zoneinfo_file="$1"
+	local copymode title msg err size
+
+	if [ -L "$_PATH_LOCALTIME" ]; then
+		copymode=
+	elif [ ! -e "$_PATH_LOCALTIME" ]; then
+		# Nothing there yet...
+		copymode=1
+	else
+		copymode=1
+	fi
+
+	if [ "$VERBOSE" ]; then
+		if [ ! "$zoneinfo_file" ]; then
+			msg=$( printf "$msg_removing_file" "$_PATH_LOCALTIME" )
+		elif [ "$copymode" ]; then
+			msg=$( printf "$msg_copying_file" \
+			              "$zoneinfo_file" "$_PATH_LOCALTIME" )
+		else
+			msg=$( printf "$msg_creating_symlink" \
+			              "$_PATH_LOCALTIME" "$zoneinfo_file" )
+		fi
+		if [ "$USEDIALOG" ]; then
+			f_dialog_title "$msg_info"
+			title="$DIALOG_TITLE"
+			btitle="$DIALOG_BACKTITLE"
+			f_dialog_title_restore
+			size=$( f_dialog_buttonbox_size "$title" \
+			        	"$btitle" "$msg" )
+			eval $DIALOG \
+				--title \"\$title\"      \
+				--backtitle \"\$btitle\" \
+				--ok-label \"\$msg_ok\"  \
+				--msgbox \"\$msg\" $size
+		else
+			printf "%s\n" "$msg"
+		fi
+	fi
+
+	if [ "$REALLYDOIT" ]; then
+		f_dialog_title "$msg_error"
+		title="$DIALOG_TITLE"
+		btitle="$DIALOG_BACKTITLE"
+		f_dialog_title_restore
+
+		if [ ! "$zoneinfo_file" ]; then
+
+			err=$( rm -f "$_PATH_LOCALTIME" 2>&1 )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+			err=$( rm -f "$_PATH_DB" 2>&1 )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+			if [ "$VERBOSE" ]; then
+				title="$msg_done"
+				msg=$( printf "$msg_removed_file" \
+				              "$_PATH_LOCALTIME" )
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$msg" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$msg\" $size
+				else
+					printf "%s\n" "$msg"
+				fi
+			fi
+
+			return $SUCCESS
+
+		fi # ! zoneinfo_file
+
+		if [ "$copymode" ]; then
+
+			err=$( rm -f "$_PATH_LOCALTIME" 2>&1 )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"     \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+			err=$( umask 222 && : 2>&1 > "$_PATH_LOCALTIME" )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+			err=$( cat "$zoneinfo_file" 2>&1 > "$_PATH_LOCALTIME" )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+		else # ! copymode
+
+			err=$( ( :< "$zoneinfo_file" ) 2>&1 )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+			err=$( rm -f "$_PATH_LOCALTIME" 2>&1 )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+			err=$( ln -s "$zoneinfo_file" "$_PATH_LOCALTIME" 2>&1 )
+			if [ "$err" ]; then
+				if [ "$USEDIALOG" ]; then
+					size=$( f_dialog_buttonbox_size \
+					        	"$title"  \
+					        	"$btitle" \
+					        	"$err" )
+					eval $DIALOG \
+						--title \"\$title\"      \
+						--backtitle \"\$btitle\" \
+						--ok-label \"\$msg_ok\"  \
+						--msgbox \"\$err\" $size
+				else
+					f_err "%s\n" "$err"
+				fi
+				return $FAILURE
+			fi
+
+		fi # copymode
+
+		if [ "$VERBOSE" ]; then
+			title="$msg_done"
+			if [ "$copymode" ]; then
+				msg=$( printf "$msg_copied_timezone_file" \
+				              "$zoneinfo_file" \
+				              "$_PATH_LOCALTIME" )
+			else
+				msg=$( printf "$msg_created_symlink" \
+				              "$_PATH_LOCALTIME" \
+				              "$zoneinfo_file" )
+			fi
+			if [ "$USEDIALOG" ]; then
+				size=$( f_dialog_buttonbox_size \
+				        	"$title" "$btitle" "$msg" )
+				eval $DIALOG \
+					--title \"\$title\"      \
+					--backtitle \"\$btitle\" \
+					--ok-label \"\$msg_ok\"  \
+					--msgbox \"\$msg\" $size
+			else
+				printf "%s\n" "$msg"
+			fi
+		fi
+
+	fi # REALLYDOIT
+
+	return $SUCCESS
+}
+
+# f_install_zoneinfo $zoneinfo
+#
+# Install a zoneinfo file relative to _PATH_ZONEINFO. The given $zoneinfo
+# will be written to _PATH_DB (usable later with the `-r' flag).
+#
+f_install_zoneinfo()
+{
+	local zoneinfo="$1"
+	local rv
+
+	f_install_zoneinfo_file "$_PATH_ZONEINFO/$zoneinfo"
+	rv=$?
+
+	# Save knowledge for later
+	if [ "$REALLYDOIT" -a $rv -eq $SUCCESS ]; then
+		if : 2> /dev/null > "$_PATH_DB"; then
+			cat <<-EOF > "$_PATH_DB"
+			$zoneinfo
+			EOF
+		fi
+	fi
+
+	return $rv
+}
+ 
+# f_confirm_zone $filename
+#
+# Prompt the user to confirm the new timezone data. The first (and only)
+# argument should be the pathname to the zoneinfo file, either absolute or
+# relative to `/usr/share/zoneinfo' (e.g., "America/Los_Angeles").
+#
+# The return status is 0 if "Yes" is chosen, 1 if "No", and 255 if Esc is
+# pressed (see dialog(1) for additional details).
+# 
+f_confirm_zone()
+{
+	local filename="$1"
+	f_dialog_title "$msg_confirmation"
+	local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+	f_dialog_title_restore
+	local tm_zone="$( TZ="$filename" date +%Z )"
+	local prompt="$( printf "$msg_look_reasonable" "$tm_zone" )"
+	local height=5 width=72
+
+	if [ "$USE_XDIALOG" ]; then
+		height=$(( $height + 4 ))
+		$DIALOG \
+			--title "$title"       \
+			--backtitle "$btitle"  \
+			--ok-label "$msg_yes" \
+			--cancel-label "$msg_no"   \
+			--yesno "$prompt" $height $width
+	else
+		$DIALOG \
+			--title "$title"       \
+			--backtitle "$btitle"  \
+			--yes-label "$msg_yes" \
+			--no-label "$msg_no"   \
+			--yesno "$prompt" $height $width
+	fi
+}
+
+# f_set_zone_utc
+#
+# Resets to the UTC timezone.
+#
+f_set_zone_utc()
+{
+	f_confirm_zone "" || return $FAILURE
+	f_install_zoneinfo_file ""
+}
+
+fi # ! $_TIMEZONE_ZONES_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/timezone/timezone
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/timezone/timezone	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,448 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011-2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/timezone/timezone 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+
+APP_DIR="090.timezone"
+f_include $BSDCFG_LIBE/$APP_DIR/include/continents.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/countries.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/iso3166.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/menus.subr
+f_include $BSDCFG_LIBE/$APP_DIR/include/zones.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_DB="/var/db/zoneinfo"
+_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+REALLYDOIT=1
+REINSTALL=
+USEDIALOG=1
+SKIPUTC=
+VERBOSE=
+TZ_OR_FAIL=
+CHROOTENV=
+
+#
+# Dummy vars (populated dynamically)
+#
+COUNTRIES= # list of 2-character country codes created by f_read_iso3166_table
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local title="$DIALOG_TITLE"
+	local btitle="$DIALOG_BACKTITLE"
+	local prompt="$msg_select_region"
+	local size
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$title\"  \
+	        	\"\$btitle\" \
+	        	\"\$prompt\" \
+			\"\"         \
+	        	$continent_menu_list )
+
+	eval $DIALOG \
+		--title \"\$title\"             \
+		--backtitle \"\$btitle\"        \
+		--ok-label \"\$msg_ok\"         \
+		--cancel-label \"\$msg_cancel\" \
+		--menu \"\$prompt\" $size       \
+		$continent_menu_list            \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts C:ehnrsSvX flag; do
+	case "$flag" in
+	C) CHROOTENV="$OPTARG";;
+	e) TZ_OR_FAIL=1;;
+	n) REALLYDOIT=;;
+	r) REINSTALL=1
+	   USEDIALOG=;;
+	s) SKIPUTC=1;;
+	v) VERBOSE=1;;
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_time_zone"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Process `-C chroot_directory' command-line argument
+#
+if [ "$CHROOTENV" ]; then
+	_PATH_ZONETAB="$CHROOTENV$_PATH_ZONETAB"
+	_PATH_ISO3166="$CHROOTENV$_PATH_ISO3166"
+	_PATH_ZONEINFO="$CHROOTENV$_PATH_ZONEINFO"
+	_PATH_LOCALTIME="$CHROOTENV$_PATH_LOCALTIME"
+	_PATH_DB="$CHROOTENV$_PATH_DB"
+	_PATH_WALL_CMOS_CLOCK="$CHROOTENV$_PATH_WALL_CMOS_CLOCK"
+fi
+
+#
+# Process `-r' command-line option
+#
+if [ "$REINSTALL" ]; then
+	[ -f "$_PATH_DB" -a -r "$_PATH_DB" ] ||
+		f_die 1 "$msg_cannot_open_for_reading" "$_PATH_DB"
+	zoneinfo=$( cat "$_PATH_DB" ) ||
+		f_die 1 "$msg_error_reading" "$_PATH_DB"
+	[ "$zoneinfo" ] ||
+		f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB"
+	f_install_zoneinfo "$zoneinfo"
+	exit $?
+fi
+
+#
+# If the arguments on the command-line do not specify a file,
+# then interpret it as a zoneinfo name
+#
+if [ $# -ge 1 ]; then
+	zoneinfo="$1"
+
+	if [ ! -f "$zoneinfo" ]; then
+		USEDIALOG=
+		f_install_zoneinfo "$zoneinfo"
+		exit $?
+	fi
+
+	# FALLTHROUGH
+fi
+
+#
+# Process the UTC option
+#
+if [ "$_PATH_WALL_CMOS_CLOCK" -a ! "$SKIPUTC" ]; then
+	f_dialog_title "$msg_select_local_or_utc"
+	title="$DIALOG_TITLE"
+	btitle="$DIALOG_BACKTITLE"
+	f_dialog_title_restore
+	msg="$msg_is_machine_clock_utc"
+
+	if [ "$USE_XDIALOG" ]; then
+		defaultno="default-no"
+		height=10 width=77
+	else
+		defaultno="defaultno"
+		height=7 width=73
+	fi
+
+	if [ "$USE_XDIALOG" ]; then
+		$DIALOG \
+			--title "$title"         \
+			--backtitle "$btitle"    \
+			--$defaultno             \
+			--ok-label "$msg_yes"    \
+			--cancel-label "$msg_no" \
+			--yesno "$msg" $height $width
+		result=$?
+	else
+		$DIALOG \
+			--title "$title"       \
+			--backtitle "$btitle"  \
+			--$defaultno           \
+			--yes-label "$msg_yes" \
+			--no-label "$msg_no"   \
+			--yesno "$msg" $height $width
+		result=$?
+	fi
+
+	if [ $result -eq 0 ]; then
+		# User chose YES
+		[ "$REALLYDOIT" ] &&
+			f_quietly rm -f "$_PATH_WALL_CMOS_CLOCK"
+	else
+		# User chose NO, pressed ESC (or Ctrl-C), or closed box
+		[ "$REALLYDOIT" ] &&
+			( umask 222 && :> "$_PATH_WALL_CMOS_CLOCK" )
+	fi
+fi
+
+#
+# Process optional default zone argument
+#
+if [ $# -ge 1 ]; then
+	default="$1"
+
+	f_dialog_title "$msg_default_zone_provided"
+	title="$DIALOG_TITLE"
+	btitle="$DIALOG_BACKTITLE"
+	f_dialog_title_restore
+	msg=$( printf "\n$msg_use_default_zone" "$default" )
+	size=$( f_dialog_buttonbox_size "$title" "$btitle" "$msg" )
+
+	if [ "$USE_XDIALOG" ]; then
+		eval $DIALOG \
+			--title \"\$title\"         \
+			--backtitle \"\$btitle\"    \
+			--ok-label \"\$msg_yes\"    \
+			--cancel-label \"\$msg_no\" \
+			--yesno \"\$msg\" $size
+		result=$?
+	else
+		eval $DIALOG \
+			--title \"\$title\"       \
+			--backtitle \"\$btitle\"  \
+			--yes-label \"\$msg_yes\" \
+			--no-label \"\$msg_no\"   \
+			--yesno \"\$msg\" $size
+		result=$?
+	fi
+
+	if [ $result -eq 0 ]; then
+		# User chose YES
+		f_install_zoneinfo_file "$default"
+		result=$?
+		[ ! "$USE_XDIALOG" ] && f_dialog_clear
+		exit $result
+	fi
+
+	[ ! "$USE_XDIALOG" ] && f_dialog_clear
+fi
+
+#
+# Override the user-supplied umask
+#
+umask 022
+
+#
+# Read databases and perform initialization
+#
+f_read_iso3166_table # creates $COUNTRIES and $country_*_name
+f_read_zones         # creates $country_*_{descr,cont,filename}
+f_sort_countries     # sorts the countries listed for each continent
+f_make_menus         # creates $continent_menu_list and $continent_*_menu_list
+
+#
+# Launch application main menu
+#
+NEED_CONTINENT=1
+NEED_COUNTRY=1
+while :; do
+	if [ "$NEED_CONTINENT" ]; then
+		dialog_menu_main # prompt the user to select a continent/ocean
+		retval=$?
+		mtag=$( f_dialog_menutag )
+
+		if [ $retval -ne 0 ]; then
+			[ "$TZ_OR_FAIL" ] && f_die
+			exit $SUCCESS
+		fi
+
+		NEED_CONTINENT=
+
+		continent=$( eval f_dialog_menutag2item \"\$mtag\" \
+		                  	$continent_menu_list )
+		cont=$( f_find_continent "$continent" )
+		cont_title=$( f_continent $cont title )
+		nitems=$( f_continent $cont nitems )
+		isocean=$( f_OCEANP $cont )
+	fi
+
+	if [ "$NEED_COUNTRY" ]; then
+		if [ "$cont_title" = "$continent_utc_title" ]; then
+			if f_set_zone_utc; then
+				break
+			else
+				NEED_CONTINENT=1
+				continue
+			fi
+		fi
+
+		#
+		# Short cut -- if there's only one country, don't post a menu.
+		#
+		if [ $nitems -eq 1 ]; then
+			tag=1
+		else
+			#
+			# It's amazing how much good grammar really matters...
+			#
+			if [ ! "$isocean" ]; then
+				title=$( printf "$msg_country_title" \
+				                "$cont_title" )
+				f_dialog_title "$title"
+				title="$DIALOG_TITLE"
+				btitle="$DIALOG_BACKTITLE"
+				f_dialog_title_restore
+				prompt="$msg_select_country"
+			else
+				title=$( printf "$msg_island_and_group_title" \
+				                "$cont_title" )
+				f_dialog_title "$title"
+				title="$DIALOG_TITLE"
+				btitle="$DIALOG_BACKTITLE"
+				f_dialog_title_restore
+				prompt="$msg_select_island_or_group"
+			fi
+
+			#
+			# Calculate size of menu
+			#
+			menu_list=$( f_continent $cont menu_list )
+			size=$( eval f_dialog_menu_size \
+			        	\"\$title\"  \
+			        	\"\$btitle\" \
+			        	\"\$prompt\" \
+			        	\"\"         \
+			        	$menu_list   )
+
+			#
+			# Launch the country selection menu
+			#
+			eval $DIALOG \
+				--title \"\$title\"             \
+				--backtitle \"\$btitle\"        \
+				--ok-label \"\$msg_ok\"         \
+				--cancel-label \"\$msg_cancel\" \
+				--menu \"\$prompt\" $size       \
+				$menu_list                      \
+				2> "$DIALOG_TMPDIR/dialog.menu.$$"
+			retval=$?
+			tag=$( f_dialog_menutag )
+
+			if [ $retval -ne 0 ]; then
+				NEED_CONTINENT=1
+				continue # back to main menu
+			fi
+		fi
+
+		# Get the country code from the user's selection 
+		tlc=$( f_continent $cont tlc_$tag )
+
+		NEED_COUNTRY=
+	fi
+
+	#
+	# If the selection has only one zone (nzones == -1),
+	# just set it.
+	#
+	nzones=$( f_country $tlc nzones )
+	if [ $nzones -lt 0 ]; then
+		real_cont=$( f_country $tlc cont )
+		real_continent=$( f_continent $real_cont name )
+		name=$( f_country $tlc name )
+		filename=$( f_country $tlc filename )
+
+		if ! f_confirm_zone "$real_continent/$filename"; then
+			[ $nitems -eq 1 ] && NEED_CONTINENT=1
+			NEED_COUNTRY=1
+			continue
+		fi
+	else
+		title=$( printf "$msg_country_time_zones" \
+		                "$( f_country $tlc name )" )
+		f_dialog_title "$title"
+		title="$DIALOG_TITLE"
+		btitle="$DIALOG_BACKTITLE"
+		f_dialog_title_restore
+		prompt="$msg_select_zone"
+		menu_list=$( f_country $tlc menu_list )
+		size=$( eval f_dialog_menu_size \"\$title\"  \"\$btitle\" \
+		        	\"\$prompt\" \"\" $menu_list )
+
+		#
+		# Launch the zone selection menu
+		# NOTE: This is as deep as we go
+		#
+		eval $DIALOG \
+			--title \"\$title\"             \
+			--backtitle \"\$btitle\"        \
+			--ok-label \"\$msg_ok\"         \
+			--cancel-label \"\$msg_cancel\" \
+			--menu \"\$prompt\" $size       \
+			$menu_list                      \
+			2> "$DIALOG_TMPDIR/dialog.menu.$$"
+		retval=$?
+		n=$( f_dialog_menutag )
+
+		if [ $retval -ne 0 ]; then
+			[ $nitems -eq 1 ] && NEED_CONTINENT=1
+			NEED_COUNTRY=1
+			continue
+		fi
+
+		real_cont=$( f_country $tlc cont_$n )
+		real_continent=$( f_continent $real_cont name )
+		name=$( f_country $tlc name )
+		filename=$( f_country $tlc filename_$n )
+
+		f_confirm_zone "$real_continent/$filename" || continue
+	fi
+
+	[ $retval -eq 0 ] || continue # back to main menu
+
+	if ! f_install_zoneinfo "$real_continent/$filename"; then
+		[ $nzones -lt 0 ] && NEED_COUNTRY=1
+	else
+		break
+	fi
+done
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/ttys/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/ttys/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,53 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/ttys/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Ttys"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Configure Ttys"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable
+#   (with different 'keyword's, or different 'keyword's AND 'command's)
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="ttys|ttys"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="ttys"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/ttys/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/ttys/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,16 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/ttys/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/150.ttys
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	ttys
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/ttys/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/ttys/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/ttys/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/ttys/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/ttys/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/ttys/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/150.ttys/include
+FILES=		messages.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/ttys/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/ttys/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,31 @@
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/ttys/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+msg_configure_ttys="Configure TTYs"
+msg_help_text="Configuration of system TTYs requires editing the /etc/ttys file.\nTypical configuration activities might include enabling getty(8)\non the first serial port to allow login via serial console after\nreboot, or to enable xdm.  The default ttys file enables normal\nvirtual consoles, and most sites will not need to perform manual\nconfiguration.\n\nTo load /etc/ttys in the editor, select [Yes], otherwise, [No]."
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
+msg_permission_denied="%s: %s: permission denied"
+msg_user_confirmation_requested="User Confirmation Requested"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/ttys/ttys
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/ttys/ttys	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,128 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/ttys/ttys 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="150.ttys"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+#
+# Default text-editor to use
+#
+: ${EDITOR:=ee}
+
+
+#
+# If X11 is requested, which terminal and what options should we use?
+#
+X11TERM=xterm
+X11TERM_OPTS=
+
+#
+# Location of ttys(5)
+#
+ETC_TTYS=/etc/ttys
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_configure_ttys"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+f_dialog_title "$msg_user_confirmation_requested"
+f_dialog_yesno "$msg_help_text" || exit $SUCCESS
+f_dialog_title_restore
+
+#
+# Make sure $EDITOR exists and is executable
+#
+case "$EDITOR" in
+*/*)
+	[ -e "$EDITOR" ] ||
+		f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$EDITOR"
+	[ -x "$EDITOR" ] ||
+		f_die 1 "$msg_permission_denied" "$pgm" "$EDITOR"
+	;;
+*)
+	f_have "$EDITOR" || 
+		f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$EDITOR"
+esac
+
+#
+# If Xdialog(1) is requested, we'll need to wrap bsdinstall(8) into xterm(1)
+#
+if [ "$USE_XDIALOG" ]; then
+	#
+	# Make sure $X11TERM exists and is executable
+	#
+	case "$X11TERM" in
+	*/*)
+		[ -e "$X11TERM" ] || f_die 1 \
+			"$msg_no_such_file_or_directory" "$pgm" "$X11TERM"
+		[ -x "$X11TERM" ] || f_die 1 \
+			"$msg_permission_denied" "$pgm" "$X11TERM"
+		;;
+	*)
+		f_have "$X11TERM" || f_die 1 \
+			"$msg_no_such_file_or_directory" "$pgm" "$X11TERM"
+	esac
+
+	exec $X11TERM $X11TERM_OPTS -e $EDITOR $ETC_TTYS
+else
+	exec $EDITOR $ETC_TTYS
+fi
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/INDEX
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/INDEX	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,60 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/INDEX 238438 2012-07-14 03:16:57Z dteske $
+
+#
+# Title that will be shown on the bsdconfig menu
+menu_title="Login/Group Management"
+#
+# a short descriptive line shown at the bottom of the bsdconfig menu.
+# keep it short because any line longer than the terminal width will
+#   be truncated.
+menu_help="Manage system user and/or group information"
+#
+# two-part variable that defines an action to take when 'keyword'
+#   is passed on a bsdconfig command line. variable takes the form
+#   "keyword|command" and multiple occurrences of the variable 
+#   (with different 'keyword's, or different 'keyword's AND 'command's) 
+#   are allowed.  If 'command' begins with a '/' then the full
+#   path to the program is needed. If 'command' begins with anything
+#   else it is a path relative to the directory this INDEX file is in.
+#   'keyword' can be i18n'ed but 'command' is the name of a script.
+menu_selection="usermgmt|usermgmt"
+menu_selection="useradd|useradd"
+menu_selection="useredit|useredit"
+menu_selection="userdel|userdel"
+menu_selection="groupmgmt|usermgmt"
+menu_selection="groupadd|groupadd"
+menu_selection="groupedit|groupedit"
+menu_selection="groupdel|groupdel"
+#
+# Items below this line do NOT need i18n translation----------------------
+#
+# Name of the program to be run when this menu choice is selected.
+#   if it begins with a '/' then the full path to the program is needed.
+#   if it begins with anything else it is a path relative to the directory
+#     this INDEX file is in.
+menu_program="usermgmt"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,17 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/070.usermgmt
+FILES=		INDEX USAGE
+
+SCRIPTSDIR=	${FILESDIR}
+SCRIPTS=	groupadd groupdel groupedit groupinput \
+		useradd userdel useredit userinput usermgmt
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/USAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/USAGE	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,33 @@
+# Copyright (c) 2012 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 (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/USAGE 238438 2012-07-14 03:16:57Z dteske $
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+	-h         Print usage statement and exit.
+	-S         Secure X11 mode (implies `-X'). As root, always prompt-for
+	           and validate sudo(8) username/password before starting.
+	-X         Use Xdialog(1) in place of dialog(1).
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/groupadd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/groupadd	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,64 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/groupadd 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+APP_DIR="070.usermgmt"
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Chain-load to groupinput to centralize code and minimize duplication
+#
+f_dialog_init
+$BSDCFG_LIBE/$APP_DIR/groupinput ${USE_XDIALOG:+-X} mode="Add"
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/groupdel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/groupdel	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,93 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/groupdel 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include $BSDCFG_LIBE/$APP_DIR/include/group_input.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_delete $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Loop until the user Exits, Cancels or presses ESC
+#
+while :; do
+	f_dialog_menu_group_list
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+
+	*) # anything else is a group name
+	   $BSDCFG_LIBE/$APP_DIR/groupinput \
+	   	${USE_XDIALOG:+-X} mode="Delete" group="$mtag"
+	   ;;
+
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/groupedit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/groupedit	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,93 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/groupedit 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include $BSDCFG_LIBE/$APP_DIR/include/group_input.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_edit_view $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Loop until the user Exits, Cancels or presses ESC
+#
+while :; do
+	f_dialog_menu_group_list
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+
+	*) # anything else is a group name
+	   $BSDCFG_LIBE/$APP_DIR/groupinput \
+	   	${USE_XDIALOG:+-X} mode="Edit/View" group="$mtag"
+	   ;;
+
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/groupinput
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/groupinput	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,295 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/groupinput 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include $BSDCFG_LIBE/$APP_DIR/include/group_input.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${passwdtype:="yes"}
+
+############################################################ FUNCTIONS
+
+# save_changes
+#
+# Save any/all settings (actions performed depend on $mode value).
+#
+save_changes()
+{
+	local err retval=$SUCCESS
+
+	case "$mode" in
+	Delete)
+		err=$( pw groupdel "$group_name" 2>&1 )
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_msg "%s %s\n" "$msg_error" "$err"
+			return $retval
+		fi
+		f_show_msg "$msg_group_deleted"
+		;;
+	Add)
+		local cmd="pw groupadd -n '$group_name'"
+		[ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+		[ "$group_members" != "$cur_group_members" ] &&
+			cmd="$cmd -M '$group_members'"
+		if [ "$pw_group_password_disable" ]; then
+			cmd="$cmd -h -"
+		elif [ "$group_password" ]; then
+			cmd="echo \"\$group_password\" | $cmd -h 0"
+		fi
+		f_dprintf "cmd=$cmd"
+		err=$( eval $cmd 2>&1 )
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_msg "%s %s\n" "$msg_error" "$err"
+			return $retval
+		fi
+		f_show_msg "$msg_group_added"
+		;;
+	Edit/View)
+		local cmd="pw groupmod -n '$group_name'"
+		[ "$group_gid" ] && cmd="$cmd -g '$group_gid'"
+		[ "$group_members" != "$cur_group_members" ] &&
+			cmd="$cmd -M '$group_members'"
+		if [ "$pw_group_password_disable" ]; then
+			cmd="$cmd -h -"
+		elif [ "$group_password" ]; then
+			cmd="echo \"\$group_password\" | $cmd -h 0"
+		fi
+		f_dprintf "cmd=$cmd"
+		err=$( eval $cmd 2>&1 )
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_msg "%s %s\n" "$msg_error" "$err"
+			return $retval
+		fi
+		f_show_msg "$msg_group_updated"
+		;;
+	esac
+
+	save_flag=
+	return $SUCCESS
+}
+
+# dialog_title_update $mode
+#
+# Set the title based on the given $mode.
+# 
+dialog_title_update()
+{
+	local mode="$1"
+	case "$mode" in
+	Add)       f_dialog_title "$msg_add $msg_group" ;;
+	Edit/View) f_dialog_title "$msg_edit_view $msg_group: $group" ;;
+	Delete)    f_dialog_title "$msg_delete $msg_group: $group" ;;
+	esac
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while [ $# -gt 0 ]; do
+	key="${1%%=*}"
+	value="${1#*=}"
+	f_dprintf "key=[$key] value=[$value]"
+	case "$key" in
+	mode) mode="$value";;
+	group) group="$value";;
+	esac
+	shift
+done
+f_dprintf "mode=[$mode] group=[$group]"
+
+#
+# Initialize
+#
+f_dialog_init
+dialog_title_update "$mode"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+menu_text=
+save_flag=
+hline="$hline_arrows_tab_enter"
+
+if [ "$mode" = "Add" ]; then
+	#
+	# Ask a series of questions to pre-fill the editor screen.
+	#
+	# The defaults used in each dialog should allow the user to simply
+	#   hit ENTER to proceed, because cancelling a single dialog will
+	#   cause them to be returned to the main groupmenu.
+	#
+
+	f_dialog_input_group_name || exit 0
+	[ "$passwdtype" = "yes" ] &&
+		{ f_dialog_input_group_password || exit 0; }
+	f_dialog_input_group_gid  || exit 0
+	f_dialog_input_group_members || exit 0
+fi
+
+if [ "$mode" = "Edit/View" -o "$mode" = "Delete" ]; then
+	f_input_group "$group" || f_die 1 "$msg_group_not_found"
+fi
+
+cur_group_name="$group_name"
+cur_group_password="$group_password"
+cur_group_gid="$group_gid"
+cur_group_members="$group_members"
+
+[ "$mode" = "Delete" ] && save_flag=1
+
+#
+# Loop until the user decides to Exit, Cancel, or presses ESC
+#
+while :; do
+	dialog_title_update "$mode"
+
+	menu_text=
+	menu_exit="$msg_exit"
+	if [ "$save_flag" ]; then
+		if [ "$mode" = "Delete" ]; then
+			menu_exit="$msg_delete/$msg_exit"
+			menu_text="$msg_delete_exit_or_cancel"
+		else
+			menu_exit="$msg_save/$msg_exit"
+			menu_text="$msg_save_exit_or_cancel"
+		fi
+	fi
+
+	case "$mode" in
+	Delete)
+		menu_items="
+			'X' '$menu_exit'
+			'1' '$msg_group: $group_name'
+			'-' '$msg_password: -----'
+			'-' '$msg_group_id: $group_gid'
+			'-' '$msg_group_members: $group_members'
+		" # END-QUOTE
+		;;
+	*)
+		menu_items="
+			'X' '$menu_exit'
+			'1' '$msg_group: $group_name'
+			'2' '$msg_password: -----'
+			'3' '$msg_group_id: $group_gid'
+			'4' '$msg_group_members: $group_members'
+		" # END-QUOTE
+	esac
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\$menu_text\"        \
+	        	\"\$hline\"            \
+	        	$menu_items            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$menu_text\" $size       \
+		$menu_items                        \
+		2> $DIALOG_TMPDIR/dialog.menu.$$
+
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	# Exit if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || f_die
+
+	case "$mtag" in
+	X) # Exit
+	   if [ "$save_flag" ]; then
+	   	save_changes || continue
+	   fi
+	   break
+	   ;;
+	1) # Group Name
+	   case "$mode" in
+	   Add) f_dialog_input_group_name "$group_name" ;;
+	   Edit/View|Delete)
+	   	f_dialog_menu_group_list
+	   	retval=$?
+	   	mtag=$( f_dialog_menutag )
+	   	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	   	# Loop if user has either pressed ESC or chosen Cancel/No
+	   	[ $retval -eq $SUCCESS ] || continue
+
+	   	[ "$mtag" = "X $msg_exit" ] && continue
+
+	   	group="$mtag"
+	   	f_input_group "$group" || f_die 1 "$msg_group_not_found"
+	   	cur_group_name="$group_name"
+	   	cur_group_password="$group_password"
+	   	cur_group_gid="$group_gid"
+	   	cur_group_members="$group_members"
+	   	[ "$mode" != "Delete" ] && save_flag=
+	   esac
+	   ;;
+	2) # Password
+	   f_dialog_input_group_password
+	   ;;
+	3) # GID
+	   f_dialog_input_group_gid "$group_gid"
+	   ;;
+	4) # Users in Group
+	   f_dialog_input_group_members "$group_members"
+	   ;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/include/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/include/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/include/Makefile 238438 2012-07-14 03:16:57Z dteske $
+
+NO_OBJ=
+
+FILESDIR=	${LIBEXECDIR}/bsdconfig/070.usermgmt/include
+FILES=		group_input.subr messages.subr user_input.subr
+
+beforeinstall:
+	mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/include/group_input.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/include/group_input.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,437 @@
+if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/include/group_input.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_input_group $group
+#
+# Given $group name or id, create the environment variables group_name,
+# group_gid, and group_members (and group_password is reset to NULL).
+#
+f_input_group()
+{
+	eval $( pw groupshow "$1" | awk -F: '
+	{
+		printf "group_name='\'%s\''\n", $1
+		printf "group_password=\n"
+		printf "group_gid='\'%s\''\n", $3
+		printf "group_members='\'%s\''\n", $4
+		exit
+	}' )
+}
+
+# f_dialog_menu_group_list
+#
+# Allows the user to select a group from a list.
+#
+f_dialog_menu_group_list()
+{
+	local menu_list size
+	local hline="$hline_alnum_punc_tab_enter"
+
+	menu_list="
+		'X $msg_exit' ''
+	" # END-QUOTE
+
+	# Add groups from group(5)
+	menu_list="$menu_list $( pw groupshow -a | awk -F: '
+		!/^[[:space:]]*(#|$)/ {
+			printf "'\'%s\'\ \'%s\''\n", $1, $1
+		}'
+	)"
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\"                   \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\" $size $menu_list       \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# f_dialog_input_group_name [$group_name]
+#
+# Allows the user to enter a new groupname for a given group. If the user does
+# not cancel or press ESC, the $group_name variable will hold the
+# newly-configured value upon return.
+#
+# If $cur_group_name is defined, the user can enter that and by-pass error-
+# checking (allowing the user to "revert" to an old value without, for example,
+# being told that the groupname already exists).
+#
+f_dialog_input_group_name()
+{
+	local msg="$( printf "$msg_group" )"
+	local hline="$hline_alnum_tab_enter"
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local size retval _name="$1" _input="$1"
+	while :; do
+		size=$( f_dialog_inputbox_size \
+		        	"$DIALOG_TITLE"     \
+		        	"$DIALOG_BACKTITLE" \
+		        	"$msg"              \
+		        	"$_input"           \
+		        	"$hline"            )
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$_input\"                       \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_input=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Check for no-change
+		[ "$_input" = "$_name" ] && return $SUCCESS
+
+		# Check for reversion
+		if [ "$_input" = "$cur_group_name" ]; then
+			group_name="$cur_group_name"
+			return $SUCCESS
+		fi
+
+		# Check for NULL entry
+		if [ ! "$_input" ]; then
+			f_show_msg "$msg_group_is_empty"
+			continue
+		fi
+
+		# Check for invalid entry
+		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
+			f_show_msg "$msg_group_must_start_with_letter"
+			continue
+		fi
+
+		# Check for duplicate entry
+		if f_quietly pw groupshow -n "$_input"; then
+			f_show_msg "$msg_group_already_used" "$_input"
+			continue
+		fi
+
+		group_name="$_input"
+		break
+	done
+	save_flag=1
+
+	f_dprintf "group_name: [$cur_group_name]->[$group_name]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_group_password
+#
+# Prompt the user to enter a password (twice).
+#
+f_dialog_input_group_password()
+{
+	local hline="$hline_alnum_punc_tab_enter"
+	local msg size rmsg rsize
+
+	msg=$( printf "$msg_group_password" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	""                  \
+	        	"$hline"            )
+
+	rmsg=$( printf "$msg_reenter_group_password" )
+	rsize=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$rmsg"             \
+	        	""                  \
+	        	"$hline"            )
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local retval _password1 _password2
+	while :; do
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--insecure                         \
+			--passwordbox \"\$msg\" $size      \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_password1=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--insecure                         \
+			--passwordbox \"\$rmsg\" $rsize    \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_password2=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Check for password mismatch
+		if [ "$_password1" != "$_password2" ]; then
+			f_show_msg "$msg_group_passwords_do_not_match"
+			continue
+		fi
+
+		# Check for NULL entry
+		if [ ! "$_password1" ]; then
+			f_dialog_yesno \
+				"$msg_disable_password_auth_for_group" ||
+				continue
+			pw_group_password_disable=1
+		else
+			pw_group_password_disable=
+		fi
+
+		group_password="$_password1"
+		break
+	done
+	save_flag=1
+
+	f_dprintf "group_password: [$cur_group_password]->[$group_password]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_group_gid [$group_gid]
+#
+# Allow the user to enter a new GID for a given group. If the user does not
+# cancel or press ESC, the $group_gid variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_group_gid()
+{
+	local msg size retval _input="$1"
+	local hline="$hline_num_tab_enter"
+
+	msg=$( printf "$msg_group_id_leave_empty_for_default" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	group_gid="$_input"
+	save_flag=1
+
+	f_dprintf "group_gid: [$cur_group_gid]->[$group_gid]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_group_members [$group_members]
+#
+# Allow the user to modify a list of members for a given group. If the user does
+# not cancel or press ESC, the $group_members variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_group_members()
+{
+	local menu_choice msg size retval _input="$1"
+	local hline="$hline_num_arrows_tab_enter"
+	local user 
+	local menu_list
+	local all_users_valid
+	local _group_members
+	local checklist_users
+
+	menu_list="
+		'X' '$msg_continue'
+		'1' '$msg_select_group_members_from_list'
+		'2' '$msg_enter_group_members_manually'
+	" # END-QUOTE
+
+	while :; do
+		msg="$msg_group_members:"
+		menu_size=$( eval f_dialog_menu_size \
+				\"\$DIALOG_TITLE\"     \
+				\"\$DIALOG_BACKTITLE\" \
+				\"\$msg\"              \
+				\"\$hline\"            \
+				$menu_list             )
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--menu \"\$msg\" $menu_size        \
+			$menu_list                         \
+			2> $DIALOG_TMPDIR/dialog.menu.$$
+		retval=$?
+		menu_choice=$( f_dialog_menutag )
+		f_dprintf "retval=$retval menu_choice=[$menu_choice]"
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		case "$menu_choice" in
+		X) # Exit
+			break ;;
+		1) # Select Group Members from a list
+			user_list=$( pw usershow -a | awk -F: '
+				!/^[[:space:]]*(#|$)/ { printf "%s\n", $1 }' )
+			checklist_users=
+			for user in $user_list; do
+				checklist_users="$checklist_users $user \"\""
+				if echo "$_input" | grep -q "\<$user\>"; then
+					checklist_users="$checklist_users on"
+				else
+					checklist_users="$checklist_users off"
+				fi
+			done
+
+			size=$( eval f_dialog_radiolist_size \
+			        	\"\$DIALOG_TITLE\"     \
+			        	\"\$DIALOG_BACKTITLE\" \
+			        	\"\"                   \
+			        	\"\$hline\"            \
+			        	$checklist_users       )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--separate-output                  \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--checklist \"\$msg\" $size        \
+				$checklist_users                   \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			_group_members=$( f_dialog_inputstr | tr '\n' ' ' |
+				sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' )
+
+			# Return to previous menu if user has either
+			#     pressed ESC or chosen Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input="$_group_members"
+			;;
+		2) # Enter Group Members manually
+			hline="$hline_num_tab_enter"
+			msg=$(
+			  printf "$msg_group_members ($msg_separated_by_commas)"
+			)
+			size=$( f_dialog_inputbox_size \
+	        		"$DIALOG_TITLE"     \
+	        		"$DIALOG_BACKTITLE" \
+	        		"$msg"              \
+	        		"$_input"           \
+	        		"$hline"            )
+
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--inputbox \"\$msg\" $size         \
+				\"\$_input\"                       \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+			retval=$?
+			_group_members=$( f_dialog_inputstr )
+
+			# Return to previous menu if user has either
+			#     pressed ESC or chosen Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input="$_group_members"
+			;;
+		esac
+	done
+
+	group_members="$_input"
+	save_flag=1
+	f_dprintf "group_members: [$cur_group_members]->[$group_members]"
+
+	return $SUCCESS
+}
+
+fi # ! $_USERMGMT_GROUP_INPUT_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/include/messages.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/include/messages.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,111 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/include/messages.subr 238438 2012-07-14 03:16:57Z dteske $
+
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+hline_alnum_tab_enter="Use alpha-numeric, TAB or ENTER"
+hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+hline_num_arrows_tab_enter="Use numbers, arrows, TAB or ENTER"
+hline_num_tab_enter="Use numbers, TAB or ENTER"
+msg_account_expires_in_how_many_days="Account expires in how many days?"
+msg_account_expires_on="Account Expires on"
+msg_account_does_not_expire="Account does not expire"
+msg_add="Add"
+msg_add_group="Add Group"
+msg_add_login="Add Login"
+msg_cancel="Cancel"
+msg_continue="Continue"
+msg_create_dotfiles="Create Dotfiles"
+msg_create_home_directory="Create Home Directory"
+msg_delete="Delete"
+msg_delete_exit_or_cancel="Choose Delete/Exit when finished or Cancel."
+msg_delete_group="Delete Group"
+msg_delete_home_directory="Delete Home Directory"
+msg_delete_login="Delete Login"
+msg_delete_primary_group="Delete Primary Group"
+msg_deleting_home_directory="Deleting home directory..."
+msg_disable_password_auth_for_account="Disable password authentication for this account?"
+msg_disable_password_auth_for_group="Disable password authentication for this group?"
+msg_edit_date_time_with_a_calendar="Edit date/time with a calendar"
+msg_edit_group="Edit/View Group"
+msg_edit_login="Edit/View Login"
+msg_edit_view="Edit/View"
+msg_enter_group_members_manually="Enter Group Members manually"
+msg_enter_number_of_days_into_the_future="Enter number of days into the future"
+msg_enter_value_manually="Edit value manually"
+msg_error="ERROR!"
+msg_exit="Exit"
+msg_full_name="Full Name"
+msg_group="Group"
+msg_group_added="Group Added"
+msg_group_already_used="%s: Group is already used."
+msg_group_deleted="Group Deleted"
+msg_group_is_empty="Group is empty."
+msg_group_id="Group ID"
+msg_group_id_leave_empty_for_default="Group ID (Leave empty for default)"
+msg_group_members="Group Members"
+msg_group_must_start_with_letter="Group must start with a letter."
+msg_group_not_found="%s: Group not found."
+msg_group_password="Group Password"
+msg_group_passwords_do_not_match="Group Passwords do not match."
+msg_group_updated="Group Updated"
+msg_home_directory="Home Directory"
+msg_invalid_number_of_days="Invalid number of days."
+msg_invalid_number_of_seconds="Invalid number of seconds."
+msg_login="Login"
+msg_login_added="Login Added"
+msg_login_already_used="%s: Login is already used."
+msg_login_class="Login Class"
+msg_login_deleted="Login Deleted"
+msg_login_is_empty="Login is empty."
+msg_login_management="Login/Group Management"
+msg_login_must_start_with_letter="Login must start with a letter."
+msg_login_not_found="Login not found."
+msg_login_updated="Login Updated"
+msg_member_of_groups="Member of Groups"
+msg_n_a="N/A"
+msg_number_of_seconds_since_epoch="Number of seconds since the Epoch\n(1 = %s)\nNULL or zero to disable:"
+msg_no="No"
+msg_ok="OK"
+msg_password="Password"
+msg_password_expires_in_how_many_days="Password expires in how many days?"
+msg_password_expires_on="Password Expires on"
+msg_passwords_do_not_match="Passwords do not match."
+msg_password_does_not_expire="Password does not expire"
+msg_reenter_group_password="Re-enter Group Password"
+msg_reenter_password="Re-enter Password"
+msg_save="Save"
+msg_save_exit_or_cancel="Choose Save/Exit when finished or Cancel."
+msg_separated_by_commas="Separated by commas"
+msg_select_group_members_from_list="Select Group Members from a list"
+msg_select_login_shell="Select Login Shell"
+msg_shell="Shell"
+msg_user="User"
+msg_user_id="UID"
+msg_user_id_leave_empty_for_default="UID (Leave empty for default)"
+msg_warning="WARNING!"
+msg_yes="Yes"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/include/user_input.subr
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/include/user_input.subr	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,1180 @@
+if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/include/user_input.subr 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/strings.subr
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default location of shells(5)
+#
+: ${ETC_SHELLS:=/etc/shells}
+
+############################################################ FUNCTIONS
+
+# f_get_member_groups $user
+#
+# Get a list of additional groups $user is a member of in group(5).
+#
+f_get_member_groups()
+{
+	echo $( pw groupshow -a | awk -F: "/[:,]$1(,|\$)/{print \$1}" )
+}
+
+# f_input_user $user
+#
+# Given $user name or id, create the environment variables pw_name, pw_uid,
+# pw_gid, pw_class, pw_password_expire, pw_account_expire, pw_gecos,
+# pw_home_dir, pw_shell, and pw_member_groups (and pw_password is reset to
+# NULL).
+#
+f_input_user()
+{
+	local user="$1"
+	eval $( pw usershow "$user" | awk -F: '
+	{
+		printf "pw_name='\'%s\''\n", $1
+		printf "pw_password=\n"
+		printf "pw_uid='\'%s\''\n", $3
+		printf "pw_gid='\'%s\''\n", $4
+		printf "pw_class='\'%s\''\n", $5
+		printf "pw_password_expire='\'%s\''\n", $6
+		printf "pw_account_expire='\'%s\''\n", $7
+		printf "pw_gecos='\'%s\''\n", $8
+		printf "pw_home_dir='\'%s\''\n", $9
+		printf "pw_shell='\'%s\''\n", $10
+	}' )
+	pw_member_groups=$( f_get_member_groups "$user" )
+}
+
+# f_dialog_menu_user_list
+#
+# Allows the user to select a login from a list.
+#
+f_dialog_menu_user_list()
+{
+	local menu_list size
+	local hline="$hline_alnum_punc_tab_enter"
+
+	menu_list="
+		'X $msg_exit' ''
+	" # END-QUOTE
+
+	# Add users from passwd(5)
+	menu_list="$menu_list $( pw usershow -a | awk -F: '
+		!/^[[:space:]]*(#|$)/ {
+			printf "'\'%s\'\ \'%s\''\n", $1, $8
+		}'
+	)"
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\"                   \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\" $size $menu_list       \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+# f_dialog_input_member_groups [$member_groups]
+#
+# Allows the user to edit group memberships for a given user. If the user does
+# not cancel or press ESC, the $pw_member_groups variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_member_groups()
+{
+	local msg="$( printf "$msg_member_of_groups" )"
+	local hline="$hline_alnum_tab_enter"
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local size retval all_groups checklist_groups="" _member_groups="$1"
+	all_groups=$( pw groupshow -a | awk -F: '
+		!/^[[:space:]]*(#|$)/ {
+			printf "%s\n", $1
+                }'
+        )
+	for grp in $all_groups; do
+		checklist_groups="$checklist_groups $grp $grp"
+		if echo "$_member_groups" | grep -q "\<$grp\>"; then
+			checklist_groups="$checklist_groups on"
+		else
+			checklist_groups="$checklist_groups off"
+		fi
+	done
+
+	while :; do
+		size=$( eval f_dialog_radiolist_size \
+		        	\"\$DIALOG_TITLE\"     \
+		        	\"\$DIALOG_BACKTITLE\" \
+		        	\"\"                   \
+		        	\"\$hline\"            \
+		        	$checklist_groups      )
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--separate-output                  \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--checklist \"\$msg\" $size        \
+			$checklist_groups                  \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_member_groups=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		#
+		# Validate each of the groups the user has entered
+		#
+		local group all_groups_valid=1
+		for group in $_member_groups; do
+			if ! f_quietly pw groupshow -n "$group"; then
+				f_show_msg "$msg_group_not_found" "$group"
+				all_groups_valid=
+				break
+			fi
+		done
+		[ "$all_groups_valid" ] || continue
+
+		pw_member_groups="$_member_groups"
+		break
+	done
+	save_flag=1
+
+	local debug="pw_member_groups:"
+	f_dprintf "$debug [$cur_pw_member_groups]->[$pw_member_groups]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_name [$name]
+#
+# Allows the user to enter a new username for a given user. If the user does
+# not cancel or press ESC, the $pw_name variable will hold the newly-configured
+# value upon return.
+#
+# If $cur_pw_name is defined, the user can enter that and by-pass error-
+# checking (allowing the user to "revert" to an old value without, for example,
+# being told that the username already exists).
+#
+f_dialog_input_name()
+{
+	local msg="$( printf "$msg_login" )"
+	local hline="$hline_alnum_tab_enter"
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local size retval _name="$1" _input="$1"
+	while :; do
+		size=$( f_dialog_inputbox_size \
+		        	"$DIALOG_TITLE"     \
+		        	"$DIALOG_BACKTITLE" \
+		        	"$msg"              \
+		        	"$_input"           \
+		        	"$hline"            )
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--inputbox \"\$msg\" $size         \
+			\"\$_input\"                       \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_input=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Check for no-change
+		[ "$_input" = "$_name" ] && return $SUCCESS
+
+		# Check for reversion
+		if [ "$_input" = "$cur_pw_name" ]; then
+			pw_name="$cur_pw_name"
+			return $SUCCESS
+		fi
+
+		# Check for NULL entry
+		if [ ! "$_input" ]; then
+			f_show_msg "$msg_login_is_empty"
+			continue
+		fi
+
+		# Check for invalid entry
+		if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
+			f_show_msg "$msg_login_must_start_with_letter"
+			continue
+		fi
+
+		# Check for duplicate entry
+		if f_quietly pw usershow -n "$_input"; then
+			f_show_msg "$msg_login_already_used" "$_input"
+			continue
+		fi
+
+		pw_name="$_input"
+		break
+	done
+	save_flag=1
+
+	f_dprintf "pw_name: [$cur_pw_name]->[$pw_name]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_password
+#
+# Prompt the user to enter a password (twice).
+#
+f_dialog_input_password()
+{
+	local hline="$hline_alnum_punc_tab_enter"
+	local msg size rmsg rsize
+
+	msg=$( printf "$msg_password" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	""                  \
+	        	"$hline"            )
+
+	rmsg=$( printf "$msg_reenter_password" )
+	rsize=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$rmsg"             \
+	        	""                  \
+	        	"$hline"            )
+
+	#
+	# Loop until the user provides taint-free/valid input
+	#
+	local retval _password1 _password2
+	while :; do
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--insecure                         \
+			--passwordbox \"\$msg\" $size      \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_password1=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--insecure                         \
+			--passwordbox \"\$rmsg\" $rsize    \
+			2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+		retval=$?
+		_password2=$( f_dialog_inputstr )
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		# Check for password mismatch
+		if [ "$_password1" != "$_password2" ]; then
+			f_show_msg "$msg_passwords_do_not_match"
+			continue
+		fi
+
+		# Check for NULL entry
+		if [ ! "$_password1" ]; then
+			f_dialog_yesno \
+				"$msg_disable_password_auth_for_account" ||
+				continue
+			pw_password_disable=1
+		else
+			pw_password_disable=
+		fi
+
+		pw_password="$_password1"
+		break
+	done
+	save_flag=1
+
+	f_dprintf "pw_password: [$cur_pw_password]->[$pw_password]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_gecos [$gecos]
+#
+# Allow the user to enter new GECOS information for a given user. This
+# information is commonly used to store the ``Full Name'' of the user. If the
+# user does not cancel or press ESC, the $pw_gecos variable will hold the
+# newly-configured value upon return.
+#
+f_dialog_input_gecos()
+{
+	local msg size retval _input="$1"
+	local hline="$hline_alnum_punc_tab_enter"
+
+	msg=$( printf "$msg_full_name" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	pw_gecos="$_input"
+	save_flag=1
+
+	f_dprintf "pw_gecos: [$cur_pw_gecos]->[$pw_gecos]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_uid [$uid]
+#
+# Allow the user to enter a new UID for a given user. If the user does not
+# cancel or press ESC, the $pw_uid variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_uid()
+{
+	local msg size retval _input="$1"
+	local hline="$hline_num_tab_enter"
+
+	msg=$( printf "$msg_user_id_leave_empty_for_default" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	pw_uid="$_input"
+	save_flag=1
+
+	f_dprintf "pw_uid: [$cur_pw_uid]->[$pw_uid]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_gid [$gid]
+#
+# Allow the user to enter a new primary GID for a given user. If the user does
+# not cancel or press ESC, the $pw_gid variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_gid()
+{
+	local msg size retval _input="$1"
+	local hline="$hline_num_tab_enter"
+
+	msg=$( printf "$msg_group_id_leave_empty_for_default" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	pw_gid="$_input"
+	save_flag=1
+
+	f_dprintf "pw_gid: [$cur_pw_gid]->[$pw_gid]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_class [$class]
+#
+# Allow the user to enter a new login class for a given user. If the user does
+# not cancel or press ESC, the $pw_class variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_class()
+{
+	local msg size retval _input="$1"
+	local hline="$hline_alnum_tab_enter"
+
+	msg=$( printf "$msg_login_class" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	pw_class="$_input"
+	save_flag=1
+
+	f_dprintf "pw_class: [$cur_pw_class]->[$pw_class]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_change [$seconds]
+#
+# Allow the user to enter a date/time (in number-of-seconds since the `epoch')
+# for when a given user's password must be changed. If the user does not cancel
+# or press ESC, the $pw_password_expire variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_change()
+{
+	local calendar_size timebox_size
+	local msg menu_size size retval _input="$1"
+	local hline="$hline_num_arrows_tab_enter"
+
+	local menu_list="
+		'1' '$msg_password_does_not_expire'
+		'2' '$msg_edit_date_time_with_a_calendar'
+		'3' '$msg_enter_number_of_days_into_the_future'
+		'4' '$msg_enter_value_manually'
+	" # END-QUOTE
+
+	#
+	# Loop until the user provides taint-free/cancellation-free input
+	#
+	while :; do
+		msg="$msg_password_expires_on"
+		menu_size=$( eval f_dialog_menu_size \
+		        	\"\$DIALOG_TITLE\"     \
+		        	\"\$DIALOG_BACKTITLE\" \
+		        	\"\$msg\"              \
+		        	\"\$hline\"            \
+		        	$menu_list             )
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--menu \"\$msg\" $menu_size        \
+			$menu_list                         \
+			2> $DIALOG_TMPDIR/dialog.menu.$$
+	        retval=$?
+	        date_type=$( f_dialog_menutag )
+	        f_dprintf "retval=$retval date_type=[$date_type]"
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		case "$date_type" in
+		1) # Password does not expire
+			_input=""
+			break ;;
+
+		2) # Edit date/time with a calendar
+			local _input_date _input_time ret_date ret_time
+
+			local secs="$_input"
+			{ f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs=
+			_input_date=$( date -j -f "%s" -- "$secs" \
+			               		"+%d %m %Y" 2> /dev/null )
+			calendar_size=$( f_dialog_calendar_size \
+			                 	"$DIALOG_TITLE"     \
+			                 	"$DIALOG_BACKTITLE" \
+			                 	"$msg"              \
+			                 	"$hline"            )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"          \
+				--backtitle \"\$DIALOG_BACKTITLE\"  \
+				--hline \"\$hline\"                 \
+				--ok-label \"\$msg_ok\"             \
+				--cancel-label \"\$msg_cancel\"     \
+				--calendar \"\$msg\" $calendar_size \
+				$_input_date                        \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			ret_date=$( f_dialog_inputstr )
+			f_dprintf "retval=$retval ret_date=[$ret_date]"
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input_time=
+			[ "$secs" ] && _input_time=$( date -j \
+				-f %s -- "$_input" "+%H %M %S" 2> /dev/null )
+			timebox_size=$( f_dialog_timebox_size \
+			                	"$DIALOG_TITLE"     \
+			                	"$DIALOG_BACKTITLE" \
+			                	"$msg"              \
+			                	"$hline"            )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--timebox \"\$msg\" $timebox_size  \
+				$_input_time                       \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			ret_time=$( f_dialog_inputstr )
+			f_dprintf "retval=$retval ret_time=[$ret_time]"
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input=$( date \
+			          	-j -f "%d/%m/%Y %T" \
+			          	-- "$ret_date $ret_time" \
+			          	+%s 2> /dev/null )
+			f_dprintf "_input=[$_input]"
+			break ;;
+
+		3) # Enter number of days into the future
+			local ret_days seconds="$( date +%s )"
+
+			f_isinteger "$_input" || _input=0
+			[ $_input -gt 0 -a $_input -gt $seconds ] &&
+				ret_days=$(( ( $_input - $seconds ) / 86400 ))
+			f_isinteger "$ret_days" &&
+				ret_days=$(( $ret_days + 1 ))
+
+			msg="$msg_password_expires_in_how_many_days"
+			size=$( f_dialog_inputbox_size \
+			        	"$DIALOG_TITLE"     \
+			        	"$DIALOG_BACKTITLE" \
+			        	"$msg"              \
+			        	"$ret_days"         \
+			        	"$hline"            )
+
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--inputbox \"\$msg\" $size         \
+				\"\$ret_days\"                     \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			ret_days=$( f_dialog_inputstr )
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			# Taint-check the user's input
+			if ! f_isinteger "$ret_days"; then
+				f_show_msg "$msg_invalid_number_of_days"
+				continue
+			fi
+
+			f_dprintf "ret_days=[$ret_days]"
+			case "$ret_days" in
+			[-+]*) _input=$( date -v${ret_days}d +%s );;
+			    0) _input=$( date +%s );;
+			    *) _input=$( date -v+${ret_days}d +%s );;
+			esac
+			f_dprintf "_input=[$_input]"
+			break ;;
+
+		4) # Enter value manually
+			local ret_secs
+
+			msg=$( printf "$msg_number_of_seconds_since_epoch" \
+			              "$( date -r 1 "+%c %Z" )" )
+			size=$( f_dialog_inputbox_size \
+			        	"$DIALOG_TITLE"     \
+			        	"$DIALOG_BACKTITLE" \
+			        	"$msg"              \
+			        	"$_input"           \
+			        	"$hline"            )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--inputbox \"\$msg\" $size         \
+				\"\$_input\"                       \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+			retval=$?
+			ret_secs=$( f_dialog_inputstr )
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input="$ret_secs"
+
+			# Taint-check the user's input
+			if ! f_isinteger "${_input:-0}"; then
+				f_show_msg "$msg_invalid_number_of_seconds"
+				continue
+			fi
+
+			f_dprintf "_input=[$_input]"
+			break ;;
+
+		esac
+
+	done # Loop forever
+
+	pw_password_expire="$_input"
+	save_flag=1
+
+	local debug=pw_password_expire
+	f_dprintf "$debug: [$cur_pw_password_expire]->[$pw_password_expire]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_expire [$seconds]
+#
+# Allow the user to enter a date/time (in number-of-seconds since the `epoch')
+# for when a given user's account should become expired. If the user does not
+# cancel or press ESC, the $pw_account_expire variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_expire()
+{
+	local calendar_size timebox_size
+	local msg menu_size size retval _input="$1"
+	local hline="$hline_num_arrows_tab_enter"
+
+	local menu_list="
+		'1' '$msg_account_does_not_expire'
+		'2' '$msg_edit_date_time_with_a_calendar'
+		'3' '$msg_enter_number_of_days_into_the_future'
+		'4' '$msg_enter_value_manually'
+	" # END-QUOTE
+
+	#
+	# Loop until the user provides taint-free/cancellation-free input
+	#
+	while :; do
+		msg="$msg_account_expires_on"
+		menu_size=$( eval f_dialog_menu_size \
+		        	\"\$DIALOG_TITLE\"     \
+		        	\"\$DIALOG_BACKTITLE\" \
+		        	\"\$msg\"              \
+		        	\"\$hline\"            \
+		        	$menu_list             )
+
+		eval $DIALOG \
+			--title \"\$DIALOG_TITLE\"         \
+			--backtitle \"\$DIALOG_BACKTITLE\" \
+			--hline \"\$hline\"                \
+			--ok-label \"\$msg_ok\"            \
+			--cancel-label \"\$msg_cancel\"    \
+			--menu \"\$msg\" $menu_size        \
+			$menu_list                         \
+			2> $DIALOG_TMPDIR/dialog.menu.$$
+	        retval=$?
+	        date_type=$( f_dialog_menutag )
+	        f_dprintf "retval=$retval date_type=[$date_type]"
+
+		# Return if user has either pressed ESC or chosen Cancel/No
+		[ $retval -eq $SUCCESS ] || return $retval
+
+		case "$date_type" in
+		1) # Account does not expire
+			_input=""
+			break ;;
+
+		2) # Edit date/time with a calendar
+			local _input_date _input_time ret_date ret_time
+
+			local secs="$_input"
+			{ f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs=
+			_input_date=$( date -j -f "%s" -- "$secs" \
+			               		"+%d %m %Y" 2> /dev/null )
+			calendar_size=$( f_dialog_calendar_size \
+			                 	"$DIALOG_TITLE"     \
+			                 	"$DIALOG_BACKTITLE" \
+			                 	"$msg"              \
+			                 	"$hline"            )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"          \
+				--backtitle \"\$DIALOG_BACKTITLE\"  \
+				--hline \"\$hline\"                 \
+				--ok-label \"\$msg_ok\"             \
+				--cancel-label \"\$msg_cancel\"     \
+				--calendar \"\$msg\" $calendar_size \
+				$_input_date                        \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			ret_date=$( f_dialog_inputstr )
+			f_dprintf "retval=$retval ret_date=[$ret_date]"
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input_time=
+			[ "$secs" ] && _input_time=$( date -j \
+				-f %s -- "$_input" "+%H %M %S" 2> /dev/null )
+			timebox_size=$( f_dialog_timebox_size \
+			                	"$DIALOG_TITLE"     \
+			                	"$DIALOG_BACKTITLE" \
+			                	"$msg"              \
+			                	"$hline"            )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--timebox \"\$msg\" $timebox_size  \
+				$_input_time                       \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			ret_time=$( f_dialog_inputstr )
+			f_dprintf "retval=$retval ret_time=[$ret_time]"
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input=$( date \
+			          	-j -f "%d/%m/%Y %T" \
+			          	-- "$ret_date $ret_time" \
+			          	+%s 2> /dev/null )
+			f_dprintf "_input=[$_input]"
+			break ;;
+
+		3) # Enter number of days into the future
+			local ret_days seconds="$( date +%s )"
+
+			f_isinteger "$_input" || _input=0
+			[ $_input -gt 0 -a $_input -gt $seconds ] &&
+				ret_days=$(( ( $_input - $seconds ) / 86400 ))
+			f_isinteger "$ret_days" &&
+				ret_days=$(( $ret_days + 1 ))
+
+			msg="$msg_account_expires_in_how_many_days"
+			size=$( f_dialog_inputbox_size \
+			        	"$DIALOG_TITLE"     \
+			        	"$DIALOG_BACKTITLE" \
+			        	"$msg"              \
+			        	"$ret_days"         \
+			        	"$hline"            )
+
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--inputbox \"\$msg\" $size         \
+				\"\$ret_days\"                     \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+			retval=$?
+			ret_days=$( f_dialog_inputstr )
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			# Taint-check the user's input
+			if ! f_isinteger "$ret_days"; then
+				f_show_msg "$msg_invalid_number_of_days"
+				continue
+			fi
+
+			f_dprintf "ret_days=[$ret_days]"
+			case "$ret_days" in
+			[-+]*) _input=$( date -v${ret_days}d +%s );;
+			    0) _input=$( date +%s );;
+			    *) _input=$( date -v+${ret_days}d +%s );;
+			esac
+			f_dprintf "_input=[$_input]"
+			break ;;
+
+		4) # Enter value manually
+			local ret_secs
+
+			msg=$( printf "$msg_number_of_seconds_since_epoch" \
+			              "$( date -r 1 "+%c %Z" )" )
+			size=$( f_dialog_inputbox_size \
+			        	"$DIALOG_TITLE"     \
+			        	"$DIALOG_BACKTITLE" \
+			        	"$msg"              \
+			        	"$_input"           \
+			        	"$hline"            )
+			eval $DIALOG \
+				--title \"\$DIALOG_TITLE\"         \
+				--backtitle \"\$DIALOG_BACKTITLE\" \
+				--hline \"\$hline\"                \
+				--ok-label \"\$msg_ok\"            \
+				--cancel-label \"\$msg_cancel\"    \
+				--inputbox \"\$msg\" $size         \
+				\"\$_input\"                       \
+				2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+			retval=$?
+			ret_secs=$( f_dialog_inputstr )
+
+			# Return to menu if either ESC or Cancel/No
+			[ $retval -eq $SUCCESS ] || continue
+
+			_input="$ret_secs"
+
+			# Taint-check the user's input
+			if ! f_isinteger "${_input:-0}"; then
+				f_show_msg "$msg_invalid_number_of_seconds"
+				continue
+			fi
+
+			f_dprintf "_input=[$_input]"
+			break ;;
+
+		esac
+
+	done # Loop forever
+
+	pw_account_expire="$_input"
+	save_flag=1
+
+	local debug=pw_account_expire
+	f_dprintf "$debug: [$cur_pw_account_expire]->[$pw_account_expire]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_home_dir [$home_dir]
+#
+# Allow the user to enter a new home directory for a given user. If the user
+# does not cancel or press ESC, the $pw_home_dir variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_home_dir()
+{
+	local msg size retval _input="$1"
+	local hline="$hline_alnum_punc_tab_enter"
+
+	msg=$( printf "$msg_home_directory" )
+	size=$( f_dialog_inputbox_size \
+	        	"$DIALOG_TITLE"     \
+	        	"$DIALOG_BACKTITLE" \
+	        	"$msg"              \
+	        	"$_input"           \
+	        	"$hline"            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--inputbox \"\$msg\" $size         \
+		\"\$_input\"                       \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	pw_home_dir="$_input"
+	save_flag=1
+
+	f_dprintf "pw_home_dir: [$cur_pw_home_dir]->[$pw_home_dir]"
+
+	return $SUCCESS
+}
+
+# f_dialog_input_home_create
+#
+# Prompt the user to confirm creation of a given user's home directory. If the
+# user does not cancel (by choosing "No") or press ESC, the $pw_home_create
+# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return
+# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible.
+#
+f_dialog_input_home_create()
+{
+	local retval
+
+	f_dialog_yesno "$msg_create_home_directory"
+	retval=$?
+
+	if [ $retval -eq $SUCCESS ]; then
+		pw_home_create="$msg_yes"
+	else
+		pw_home_create="$msg_no"
+	fi
+	save_flag=1
+
+	f_dprintf "pw_home_create: [$cur_pw_home_create]->[$pw_home_create]"
+
+	[ $retval -ne 255 ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_group_delete
+#
+# Prompt the user to confirm deletion of a given user's primary group. If the
+# user does not cancel (by choosing "No") or press ESC, the $pw_group_delete
+# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return
+# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible.
+#
+f_dialog_input_group_delete()
+{
+	local retval
+
+	if f_isinteger "$pw_gid"; then
+		if [ $pw_gid -lt 1000 ]; then
+			f_dialog_noyes "$msg_delete_primary_group"
+		else
+			f_dialog_yesno "$msg_delete_primary_group"
+		fi
+	elif [ "$pw_gid" ]; then
+		local gid=0
+		gid=$( pw groupshow "$pw_gid" | awk -F: '{print $3}' )
+		if f_isinteger "$gid" && [ $gid -lt 1000 ]; then
+			f_dialog_noyes "$msg_delete_primary_group"
+		else
+			f_dialog_yesno "$msg_delete_primary_group"
+		fi
+	else
+		f_dialog_yesno "$msg_delete_primary_group"
+	fi
+	retval=$?
+
+	if [ $retval -eq $SUCCESS ]; then
+		pw_group_delete="$msg_yes"
+	else
+		pw_group_delete="$msg_no"
+	fi
+	save_flag=1
+
+	f_dprintf "pw_group_delete: [$cur_pw_group_delete]->[$pw_group_delete]"
+
+	[ $retval -ne 255 ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_home_delete
+#
+# Prompt the user to confirm deletion of a given user's home directory. If the
+# user does not cancel (by choosing "No") or press ESC, the $pw_home_delete
+# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return
+# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible.
+#
+f_dialog_input_home_delete()
+{
+	local retval
+
+	f_dialog_yesno "$msg_delete_home_directory"
+	retval=$?
+
+	if [ $retval -eq $SUCCESS ]; then
+		pw_home_delete="$msg_yes"
+	else
+		pw_home_delete="$msg_no"
+	fi
+	save_flag=1
+
+	f_dprintf "pw_home_delete: [$cur_pw_home_delete]->[$pw_home_delete]"
+
+	[ $retval -ne 255 ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_dotfiles_create
+#
+# Prompt the user to confirm population of a given user's home directory with
+# sample dotfiles. If the user does not cancel (by choosing "No") or press ESC,
+# the $pw_dotfiles_create variable will hold $msg_yes upon return, otherwise
+# $msg_no. Use these return variables ($msg_yes and $msg_no) for comparison to
+# be i18n-compatible.
+#
+f_dialog_input_dotfiles_create()
+{
+	local retval
+
+	f_dialog_yesno "$msg_create_dotfiles"
+	retval=$?
+
+	if [ $retval -eq $SUCCESS ]; then
+		pw_dotfiles_create="$msg_yes"
+	else
+		pw_dotfiles_create="$msg_no"
+	fi
+	save_flag=1
+
+	local debug="pw_dotfiles_create:"
+	f_dprintf "$debug: [$cur_pw_dotfiles_create]->[$pw_dotfiles_create]"
+
+	[ $retval -ne 255 ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_shell [$shell]
+#
+# Allow the user to select a new login shell for a given user. If the user does
+# not cancel or press ESC, the $pw_home_dir variable will hold the newly-
+# configured value upon return.
+#
+#
+f_dialog_input_shell()
+{
+	local size retval shells shell_list _input="$1"
+	local hline="$hline_arrows_space_tab_enter"
+	local prompt="$msg_select_login_shell"
+
+	shells=$( awk '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" )
+	shell_list=$(
+		for shell in $shells; do
+			if [ "$shell" = "$_input" ]; then
+				echo "'$shell' '' 'on'"
+			else
+				echo "'$shell' '' 'off'"
+			fi
+		done
+	)
+
+	size=$( eval f_dialog_radiolist_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\$prompt\"           \
+	        	\"\$hline\"            \
+	        	$shell_list            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--radiolist \"\$prompt\" $size     \
+		$shell_list                        \
+		2> $DIALOG_TMPDIR/dialog.inputbox.$$
+
+	retval=$?
+	_input=$( f_dialog_inputstr )
+
+	# Return if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || return $retval
+
+	pw_shell="$_input"
+	save_flag=1
+
+	f_dprintf "pw_shell: [$cur_pw_shell]->[$pw_shell]"
+
+	return $SUCCESS
+}
+
+fi # ! $_USERMGMT_USER_INPUT_SUBR
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/useradd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/useradd	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,64 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/useradd 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+
+APP_DIR="070.usermgmt"
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Chain-load to userinput to centralize code and minimize duplication
+#
+f_dialog_init
+$BSDCFG_LIBE/$APP_DIR/userinput ${USE_XDIALOG:+-X} mode="Add"
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/userdel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/userdel	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,93 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/userdel 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include $BSDCFG_LIBE/$APP_DIR/include/user_input.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_delete $msg_login"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Loop until the user Exits, Cancels or presses ESC
+#
+while :; do
+	f_dialog_menu_user_list
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+
+	*) # anything else is a userid
+	   $BSDCFG_LIBE/$APP_DIR/userinput \
+	   	${USE_XDIALOG:+-X} mode="Delete" user="$mtag"
+	   ;;
+
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/useredit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/useredit	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,93 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/useredit 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include $BSDCFG_LIBE/$APP_DIR/include/user_input.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_edit_view $msg_login"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Loop until the user Exits, Cancels or presses ESC
+#
+while :; do
+	f_dialog_menu_user_list
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	"X $msg_exit") break ;;
+
+	*) # anything else is a userid
+	   $BSDCFG_LIBE/$APP_DIR/userinput \
+	   	${USE_XDIALOG:+-X} mode="Edit/View" user="$mtag"
+	   ;;
+
+	esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/userinput
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/userinput	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,515 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/userinput 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include $BSDCFG_LIBE/$APP_DIR/include/user_input.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${passwdtype:="yes"}
+: ${homeprefix:="/home"}
+: ${defaultshell:="/bin/sh"}
+: ${udotdir:="/usr/share/skel"}
+
+############################################################ FUNCTIONS
+
+# copy_dotfiles
+#
+# Copy `skel' dot-files to a new home directory.
+#
+copy_dotfiles()
+{
+	( # Operate within sub-shell to protect CWD/glob of parent
+		cd "$udotdir" || exit $?
+		set +f # glob
+		for file in dot.*; do
+			cp -n "$file" "$pw_home_dir/${file#dot}" || exit $?
+		done
+	)
+}
+
+# save_changes
+#
+# Save any/all settings (actions performed depend on $mode value).
+#
+save_changes()
+{
+	local err retval=$SUCCESS
+
+	case "$mode" in
+	Delete)
+		err=$( pw userdel -u "$pw_uid" 2>&1 )
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_msg "%s %s\n" "$msg_error" "$err"
+			return $retval
+		fi
+		f_show_msg "$msg_login_deleted"
+
+		if [ "$pw_group_delete" = "$msg_yes" ] &&
+		   f_quietly pw groupshow -g "$pw_gid"
+		then
+			err=$( pw groupdel -g "$pw_gid" 2>&1 ) ||
+				f_show_msg "%s %s\n" "$msg_warning" "$err"
+		fi
+
+		if [ "$pw_home_delete" = "$msg_yes" ]; then
+			f_dialog_info "$msg_deleting_home_directory"
+			err=$( rm -Rf "$pw_home_dir" 2>&1 ) ||
+				f_show_msg "%s %s\n" "$msg_warning" "$err"
+		fi
+		;;
+	Add)
+		local cmd="pw useradd -n '$pw_name'"
+		[ "$pw_member_groups"   ] && cmd="$cmd -G '$pw_member_groups'"
+		[ "$pw_class"           ] && cmd="$cmd -L '$pw_class'"
+		[ "$pw_gecos"           ] && cmd="$cmd -c '$pw_gecos'"
+		[ "$pw_home_dir"        ] && cmd="$cmd -d '$pw_home_dir'"
+		[ "$pw_account_expire"  ] && cmd="$cmd -e '$pw_account_expire'"
+		[ "$pw_gid"             ] && cmd="$cmd -g '$pw_gid'"
+		[ "$pw_password_expire" ] && cmd="$cmd -p '$pw_password_expire'"
+		[ "$pw_shell"           ] && cmd="$cmd -s '$pw_shell'"
+		[ "$pw_uid"             ] && cmd="$cmd -u '$pw_uid'"
+		if [ "$pw_password_disable" ]; then
+			cmd="$cmd -h -"
+		elif [ "$pw_password" ]; then
+			cmd="echo \"\$pw_password\" | $cmd -h 0"
+		fi
+		f_dprintf "cmd=$cmd"
+		err=$( eval $cmd 2>&1 )
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_msg "%s %s\n" "$msg_error" "$err"
+			return $retval
+		fi
+		f_show_msg "$msg_login_added"
+
+		if [ "$pw_home_create" = "$msg_yes" ]; then
+			err=$( mkdir -p "$pw_home_dir" 2>&1 )
+			if [ $? -ne $SUCCESS ]; then
+				f_show_msg "%s %s\n" "$msg_warning" "$err"
+			elif [ -e "$pw_home_dir" ]; then
+				err=$( chown -R "$pw_uid:$pw_gid" \
+				                "$pw_home_dir" 2>&1 )
+				[ $? -eq $SUCCESS ] || f_show_msg \
+					"%s %s\n" "$msg_warning" "$err"
+			fi
+		fi
+
+		if [ "$pw_dotfiles_create" = "$msg_yes" ]; then
+			err=$( copy_dotfiles 2>&1 ) ||
+				f_show_msg "%s %s\n" "$msg_warning" "$err"
+		fi
+
+		user="$pw_name"
+		f_quietly pw usershow -n "$pw_name" &&
+			mode="Edit/View" # Change mode
+		;;
+	Edit/View)
+		local cmd="pw usermod -n '$pw_name'"
+		[ "$pw_member_groups"   ] && cmd="$cmd -G '$pw_member_groups'"
+		[ "$pw_class"           ] && cmd="$cmd -L '$pw_class'"
+		[ "$pw_gecos"           ] && cmd="$cmd -c '$pw_gecos'"
+		[ "$pw_home_dir"        ] && cmd="$cmd -d '$pw_home_dir'"
+		[ "$pw_account_expire"  ] && cmd="$cmd -e '$pw_account_expire'"
+		[ "$pw_gid"             ] && cmd="$cmd -g '$pw_gid'"
+		[ "$pw_password_expire" ] && cmd="$cmd -p '$pw_password_expire'"
+		[ "$pw_shell"           ] && cmd="$cmd -s '$pw_shell'"
+		[ "$pw_uid"             ] && cmd="$cmd -u '$pw_uid'"
+		if [ "$pw_password_disable" ]; then
+			cmd="$cmd -h -"
+		elif [ "$pw_password" ]; then
+			cmd="echo \"\$pw_password\" | $cmd -h 0"
+		fi
+		f_dprintf "cmd=$cmd"
+		err=$( eval $cmd 2>&1 )
+		retval=$?
+		if [ $retval -ne $SUCCESS ]; then
+			f_show_msg "%s %s\n" "$msg_error" "$err"
+			return $retval
+		fi
+		f_show_msg "$msg_login_updated"
+
+		if [ "$pw_home_create" = "$msg_yes" ]; then
+			err=$( mkdir -p "$pw_home_dir" )
+			if [ $? -ne $SUCCESS ]; then
+				f_show_msg "%s %s\n" "$msg_warning" "$err"
+			elif [ -e "$pw_home_dir" ]; then
+				err=$( chown -R "$pw_uid:$pw_gid" \
+				                "$pw_home_dir" 2>&1 )
+				[ $? -eq $SUCCESS ] || f_show_msg \
+					"%s %s\n" "$msg_warning" "$err"
+			fi
+		fi
+
+		if [ "$pw_dotfiles_create" = "$msg_yes" ]; then
+			err=$( copy_dotfiles 2>&1 ) ||
+				f_show_msg "%s %s\n" "$msg_warning" "$err"
+		fi
+		;;
+	esac
+
+	save_flag=
+	return $SUCCESS
+}
+
+# dialog_title_update $mode
+#
+# Set the title based on the given $mode.
+#
+dialog_title_update()
+{
+	local mode="$1"
+	case "$mode" in
+	Add)       f_dialog_title "$msg_add $msg_user" ;;
+	Edit/View) f_dialog_title "$msg_edit_view $msg_user: $user" ;;
+	Delete)    f_dialog_title "$msg_delete $msg_user: $user" ;;
+	esac
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while [ $# -gt 0 ]; do
+	key="${1%%=*}"
+	value="${1#*=}"
+	f_dprintf "key=[$key] value=[$value]"
+	case "$key" in
+	mode) mode="$value";;
+	user) user="$value";;
+	esac
+	shift
+done
+f_dprintf "mode=[$mode] user=[$user]"
+
+#
+# Initialize
+#
+f_dialog_init
+dialog_title_update "$mode"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+menu_text=
+save_flag=
+hline="$hline_arrows_tab_enter"
+
+if [ "$mode" = "Add" ]; then
+	#
+	# Ask a series of questions to pre-fill the editor screen.
+	#
+	# The defaults used in each dialog should allow the user to simply
+	#   hit ENTER to proceed, because cancelling a single dialog will
+	#   cause them to be returned to the main usermenu.
+	#
+
+	f_dialog_input_name || exit 0
+	f_dialog_input_gecos "$pw_name" || exit 0
+	[ "$passwdtype" = "yes" ] &&
+		{ f_dialog_input_password || exit 0; }
+	f_dialog_input_uid || exit 0
+	f_dialog_input_gid || exit 0
+	f_dialog_input_member_groups || exit 0
+	f_dialog_input_class || exit 0
+	f_dialog_input_change || exit 0
+	f_dialog_input_expire || exit 0
+	f_dialog_input_home_dir "$homeprefix/$pw_name" || exit 0
+	pw_dotfiles_create="$msg_no"
+	if [ ! -d "$homeprefix/$pw_name" ]; then
+		f_dialog_input_home_create || exit 0
+		[ "$pw_home_create" = "$msg_yes" ] &&
+			{ f_dialog_input_dotfiles_create || exit 0; }
+	fi
+	f_dialog_input_shell "$defaultshell" || exit 0
+fi
+
+if [ "$mode" = "Edit/View" -o "$mode" = "Delete" ]; then
+	f_input_user "$user" || f_die 1 "$msg_login_not_found"
+fi
+
+if [ "$mode" = "Edit/View" ]; then
+	[ -d "$pw_home_dir" ] || pw_home_create="$msg_no"
+	pw_dotfiles_create="$msg_no"
+fi
+
+if [ "$mode" = "Delete" ]; then
+	f_dialog_input_group_delete || exit 0
+	pw_home_delete="$msg_no"
+	[ -d "$pw_home_dir" ] &&
+		{ f_dialog_input_home_delete || exit 0; }
+fi
+
+cur_pw_name="$pw_name"
+cur_pw_password="$pw_password"
+cur_pw_uid="$pw_uid"
+cur_pw_gid="$pw_gid"
+cur_pw_member_groups="$pw_member_groups"
+cur_pw_class="$pw_class"
+cur_pw_password_expire="$pw_password_expire"
+cur_pw_account_expire="$pw_account_expire"
+cur_pw_gecos="$pw_gecos"
+cur_pw_home_dir="$pw_home_dir"
+cur_pw_shell="$pw_shell"
+cur_pw_group_delete="$pw_group_delete"
+cur_pw_home_create="$pw_home_create"
+cur_pw_home_delete="$pw_home_delete"
+cur_pw_dotfiles_create="$pw_dotfiles_create"
+
+[ "$mode" = "Delete" ] && save_flag=1
+
+#
+# Loop until the user decides to Exit, Cancel, or presses ESC
+#
+while :; do
+	dialog_title_update "$mode"
+
+	menu_text=
+	menu_exit="$msg_exit"
+	if [ "$save_flag" ]; then
+		if [ "$mode" = "Delete" ]; then
+			menu_exit="$msg_delete/$msg_exit"
+			menu_text="$msg_delete_exit_or_cancel"
+		else
+			menu_exit="$msg_save/$msg_exit"
+			menu_text="$msg_save_exit_or_cancel"
+		fi
+	fi
+
+	pw_password_expires_on="$pw_password_expire"
+	f_isinteger "$pw_password_expire" && [ $pw_password_expire -ne 0 ] &&
+		pw_password_expires_on=$(
+			date -r "$pw_password_expire" "+%F %T %Z"
+		)
+	pw_account_expires_on="$pw_account_expire"
+	f_isinteger "$pw_account_expire" && [ "$pw_account_expire" -ne 0 ] &&
+		pw_account_expires_on=$(
+			date -r "$pw_account_expire" "+%F %T %Z"
+		)
+
+	case "$mode" in
+	Delete)
+		menu_items="
+			'X' '$menu_exit'
+			'1' '$msg_login: $pw_name'
+			'-' '$msg_full_name: $pw_gecos'
+			'-' '$msg_password: -----'
+			'-' '$msg_user_id: $pw_uid'
+			'-' '$msg_group_id: $pw_gid'
+			'-' '$msg_member_of_groups: $pw_member_groups'
+			'-' '$msg_login_class: $pw_class'
+			'-' '$msg_password_expires_on: $pw_password_expires_on'
+			'-' '$msg_account_expires_on: $pw_account_expires_on'
+			'-' '$msg_home_directory: $pw_home_dir'
+			'-' '$msg_shell: $pw_shell'
+		" # END-QUOTE
+		;;
+	*)
+		menu_items="
+			'X' '$menu_exit'
+			'1' '$msg_login: $pw_name'
+			'2' '$msg_full_name: $pw_gecos'
+			'3' '$msg_password: -----'
+			'4' '$msg_user_id: $pw_uid'
+			'5' '$msg_group_id: $pw_gid'
+			'6' '$msg_member_of_groups: $pw_member_groups'
+			'7' '$msg_login_class: $pw_class'
+			'8' '$msg_password_expires_on: $pw_password_expires_on'
+			'9' '$msg_account_expires_on: $pw_account_expires_on'
+			'A' '$msg_home_directory: $pw_home_dir'
+			'B' '$msg_shell: $pw_shell'
+		" # END-QUOTE
+	esac
+
+	case "$mode" in
+	Add|Edit/View)
+		if [ -d "$pw_home_dir" ]; then menu_items="$menu_items
+			'-' '$msg_create_home_directory: $msg_n_a'
+			'D' '$msg_create_dotfiles: $pw_dotfiles_create'
+		"; else menu_items="$menu_items
+			'C' '$msg_create_home_directory: $pw_home_create'
+			'D' '$msg_create_dotfiles: $pw_dotfiles_create'
+		"; fi
+		;;
+	Delete)
+		if [ -d "$pw_home_dir" ]; then menu_items="$menu_items
+			'C' '$msg_delete_primary_group: $pw_group_delete'
+			'D' '$msg_delete_home_directory: $pw_home_delete'
+		"; else menu_items="$menu_items
+			'C' '$msg_delete_primary_group: $pw_group_delete'
+			'-' '$msg_delete_home_directory: $msg_n_a'
+		"; fi
+		;;
+	esac
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\$menu_text\"        \
+	        	\"\$hline\"            \
+	        	$menu_items            )
+
+	eval $DIALOG \
+		--title \"\$DIALOG_TITLE\"         \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\$menu_text\" $size       \
+		$menu_items                        \
+		2> $DIALOG_TMPDIR/dialog.menu.$$
+
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	# Exit if user has either pressed ESC or chosen Cancel/No
+	[ $retval -eq $SUCCESS ] || f_die
+
+	case "$mtag" in
+	X) # Exit
+	   if [ "$save_flag" ]; then
+	   	save_changes || continue
+	   fi
+	   break
+	   ;;
+	1) # Login
+	   case "$mode" in
+	   Add) f_dialog_input_name "$pw_name" ;;
+	   Edit/View|Delete)
+	   	f_dialog_menu_user_list
+	   	retval=$?
+	   	mtag=$( f_dialog_menutag )
+	   	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	   	# Loop if user has either pressed ESC or chosen Cancel/No
+	   	[ $retval -eq $SUCCESS ] || continue
+
+	   	[ "$mtag" = "X $msg_exit" ] && continue
+
+	   	user="$mtag"
+	   	f_input_user "$user" || f_die 1 "$msg_login_not_found"
+	   	cur_pw_name="$pw_name"
+	   	cur_pw_password="$pw_password"
+	   	cur_pw_uid="$pw_uid"
+	   	cur_pw_gid="$pw_gid"
+	   	cur_pw_member_groups="$pw_member_groups"
+	   	cur_pw_class="$pw_class"
+	   	cur_pw_password_expire="$pw_password_expire"
+	   	cur_pw_account_expire="$pw_account_expire"
+	   	cur_pw_gecos="$pw_gecos"
+	   	cur_pw_home_dir="$pw_home_dir"
+	   	cur_pw_shell="$pw_shell"
+	   	cur_pw_group_delete="$pw_group_delete"
+	   	cur_pw_home_create="$pw_home_create"
+	   	cur_pw_home_delete="$pw_home_delete"
+	   	cur_pw_dotfiles_create="$pw_dotfiles_create"
+	   	[ "$mode" != "Delete" ] && save_flag=
+	   esac
+	   ;;
+	2) # Full Name
+	   f_dialog_input_gecos "$pw_gecos"
+	   ;;
+	3) # Password
+	   f_dialog_input_password
+	   ;;
+	4) # UID
+	   f_dialog_input_uid "$pw_uid"
+	   ;;
+	5) # Default Group
+	   f_dialog_input_gid "$pw_gid"
+	   ;;
+	6) # Member of Groups
+	   f_dialog_input_member_groups "$pw_member_groups"
+	   ;;
+	7) # Login Class
+	   f_dialog_input_class "$pw_class"
+	   ;;
+	8) # Password Expire on
+	   f_dialog_input_change "$pw_password_expire"
+	   ;;
+	9) # Account Expire on
+	   f_dialog_input_expire "$pw_account_expire"
+	   ;;
+	A) # Home Directory
+	   f_dialog_input_home_dir "$pw_home_dir"
+	   ;;
+	B) # Shell
+	   f_dialog_input_shell "$pw_shell"
+	   ;;
+	esac
+
+	case "$mode" in
+	Delete)
+		case "$mtag" in
+		C) # Delete Primary Group
+		   f_dialog_input_group_delete ;;
+		D) # Delete Home Directory
+		   f_dialog_input_home_delete ;;
+		esac
+		;;
+	Add|Edit/View)
+		case "$mtag" in
+		C) # Create Home Directory
+		   f_dialog_input_home_create
+		   [ "$pw_home_create" = "$msg_no" ] &&
+		   	pw_dotfiles_create="$msg_no"
+		   ;;
+		D) # Create Dotfiles
+		   f_dialog_input_dotfiles_create
+		   [ "$pw_dotfiles_create" = "$msg_yes" ] &&
+		   	pw_home_create="$msg_yes"
+		   ;;
+		esac
+		;;
+	esac
+
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdconfig/usermgmt/usermgmt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/bsdconfig/usermgmt/usermgmt	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,150 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012 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.
+#
+# $FreeBSD: head/usr.sbin/bsdconfig/usermgmt/usermgmt 238438 2012-07-14 03:16:57Z dteske $
+#
+############################################################ INCLUDES
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+. $BSDCFG_LIBE/include/common.subr || exit 1
+f_include $BSDCFG_LIBE/include/dialog.subr
+f_include $BSDCFG_LIBE/include/mustberoot.subr
+
+APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+ipgm=$( f_index_menu_selection $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
+[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+	local menu_list size
+	local hline="$hline_arrows_tab_enter"
+
+	menu_list="
+		'X' '$msg_exit'
+		'1' '$msg_add_login'
+		'2' '$msg_edit_login'
+		'3' '$msg_delete_login'
+		'-' '-'
+		'4' '$msg_add_group'
+		'5' '$msg_edit_group'
+		'6' '$msg_delete_group'
+	" # END-QUOTE
+
+	size=$( eval f_dialog_menu_size \
+	        	\"\$DIALOG_TITLE\"     \
+	        	\"\$DIALOG_BACKTITLE\" \
+	        	\"\"                   \
+	        	\"\$hline\"            \
+	        	$menu_list             )
+
+	eval $DIALOG \
+		--clear --title \"\$DIALOG_TITLE\" \
+		--backtitle \"\$DIALOG_BACKTITLE\" \
+		--hline \"\$hline\"                \
+		--ok-label \"\$msg_ok\"            \
+		--cancel-label \"\$msg_cancel\"    \
+		--menu \"\" $size $menu_list       \
+		2> "$DIALOG_TMPDIR/dialog.menu.$$"
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts hSX flag; do
+	case "$flag" in
+	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm";;
+	esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_init
+f_dialog_title "$msg_login_management"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+	dialog_menu_main
+	retval=$?
+	mtag=$( f_dialog_menutag )
+	f_dprintf "retval=$retval mtag=[$mtag]"
+
+	[ $retval -eq 0 ] || f_die
+
+	case "$mtag" in
+	X) # Exit
+	   exit 0
+	   ;;
+
+	1) # Add User
+	   $BSDCFG_LIBE/$APP_DIR/useradd ${USE_XDIALOG:+-X}
+	   ;;
+
+	2) # Edit/View User
+	   $BSDCFG_LIBE/$APP_DIR/useredit ${USE_XDIALOG:+-X}
+	   ;;
+
+	3) # Delete User
+	   $BSDCFG_LIBE/$APP_DIR/userdel ${USE_XDIALOG:+-X}
+	   ;;
+
+	4) # Add Group
+	   $BSDCFG_LIBE/$APP_DIR/groupadd ${USE_XDIALOG:+-X}
+	   ;;
+
+	5) # Edit/View Group
+	   $BSDCFG_LIBE/$APP_DIR/groupedit ${USE_XDIALOG:+-X}
+	   ;;
+
+	6) # Delete Group
+	   $BSDCFG_LIBE/$APP_DIR/groupdel ${USE_XDIALOG:+-X}
+	   ;;
+
+	esac
+done
+
+################################################################################
+# END
+################################################################################
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdinstall/partedit/diskeditor.c
--- a/head/usr.sbin/bsdinstall/partedit/diskeditor.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bsdinstall/partedit/diskeditor.c	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/bsdinstall/partedit/diskeditor.c 226083 2011-10-07 01:40:30Z nwhitehorn $
+ * $FreeBSD: head/usr.sbin/bsdinstall/partedit/diskeditor.c 237253 2012-06-19 06:09:47Z eadler $
  */
 
 #include <stdio.h>
@@ -74,7 +74,7 @@
 	int x, y;
 	int i;
 	int height, width, min_width;
-	int partlist_height, partlist_width, min_partlist_width;
+	int partlist_height, partlist_width;
 	int cur_scroll = 0;
 	int key, fkey;
 	int cur_button = 0, cur_part = 0;
@@ -102,7 +102,6 @@
 	min_width = 50;
 	height = width = 0;
 	partlist_height = 10;
-	min_partlist_width = 0;
 	dlg_tab_correct_str(prompt);
 	dlg_button_layout(buttons, &min_width);
 	dlg_auto_size(title, prompt, &height, &width, 2, min_width);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdinstall/partedit/part_wizard.c
--- a/head/usr.sbin/bsdinstall/partedit/part_wizard.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bsdinstall/partedit/part_wizard.c	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/bsdinstall/partedit/part_wizard.c 226083 2011-10-07 01:40:30Z nwhitehorn $
+ * $FreeBSD: head/usr.sbin/bsdinstall/partedit/part_wizard.c 237253 2012-06-19 06:09:47Z eadler $
  */
 
 #include <sys/param.h>
@@ -294,8 +294,6 @@
 	struct gmesh submesh;
 	struct gclass *classp;
 	struct ggeom *gp;
-	struct gconfig *gc;
-	const char *scheme;
 	struct gprovider *pp;
 	intmax_t swapsize, available;
 	char swapsizestr[10], rootsizestr[10];
@@ -309,10 +307,6 @@
 		if (strcmp(gp->lg_name, disk) == 0)
 			break;
 
-	LIST_FOREACH(gc, &gp->lg_config, lg_config) 
-		if (strcmp(gc->lg_name, "scheme") == 0) 
-			scheme = gc->lg_val;
-
 	pp = provider_for_name(mesh, disk);
 
 	available = gpart_max_free(gp, NULL)*pp->lg_sectorsize;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsdinstall/scripts/mirrorselect
--- a/head/usr.sbin/bsdinstall/scripts/mirrorselect	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bsdinstall/scripts/mirrorselect	Wed Jul 25 16:29:58 2012 +0300
@@ -24,7 +24,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/bsdinstall/scripts/mirrorselect 225467 2011-09-10 09:40:00Z brueffer $
+# $FreeBSD: head/usr.sbin/bsdinstall/scripts/mirrorselect 235228 2012-05-10 13:30:42Z roberto $
 
 : ${DIALOG_OK=0}
 : ${DIALOG_CANCEL=1}
@@ -87,7 +87,7 @@
 	ftp://ftp.fr.freebsd.org 	"France"\
 	ftp://ftp2.fr.freebsd.org 	"IPv6 France #2"\
 	ftp://ftp3.fr.freebsd.org 	"France #3"\
-	ftp://ftp4.fr.freebsd.org 	"France #4"\
+	ftp://ftp4.fr.freebsd.org 	"IPv6 France #4"\
 	ftp://ftp5.fr.freebsd.org 	"France #5"\
 	ftp://ftp6.fr.freebsd.org 	"France #6"\
 	ftp://ftp8.fr.freebsd.org 	"IPv6 France #8"\
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3
--- a/head/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3	Wed Jul 25 16:29:58 2012 +0300
@@ -27,7 +27,7 @@
 .\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 233510 2012-03-26 15:18:14Z joel $
+.\" $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_netgraph/snmp_netgraph.3 235286 2012-05-11 20:06:46Z gjb $
 .\"
 .Dd November 14, 2003
 .Dt SNMP_NETGRAPH 3
@@ -305,7 +305,7 @@
 .Li NG_NODESIZ
 bytes long.
 The function returns the node id or 0 if the
-node is not found
+node is not found.
 .Pp
 The function
 .Fn ng_node_type
@@ -396,7 +396,8 @@
 .Fa peer .
 The functions return 0 on success or -1 otherwise.
 The function
-.Fn ng_connect2_tee_id does the same as
+.Fn ng_connect2_tee_id
+does the same as
 .Fn ng_connect2_id
 except, that it puts an unnamed tee node between the two nodes.
 .Pp
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/bsnmpd/modules/snmp_wlan/snmp_wlan.3
--- a/head/usr.sbin/bsnmpd/modules/snmp_wlan/snmp_wlan.3	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/bsnmpd/modules/snmp_wlan/snmp_wlan.3	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_wlan/snmp_wlan.3 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_wlan/snmp_wlan.3 235286 2012-05-11 20:06:46Z gjb $
 .\"
 .Dd June 28, 2010
 .Dt SNMP_WLAN 3
@@ -61,8 +61,8 @@
 .Va wlanParentIfName
 column. Any optional parameters may be set
 via the
-.Va wlanIfaceOperatingMode,
-.Va wlanIfaceFlags,
+.Va wlanIfaceOperatingMode ,
+.Va wlanIfaceFlags ,
 .Va wlanIfaceBssid
 and
 .Va wlanIfaceLocalAddress
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/config/config.h
--- a/head/usr.sbin/config/config.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/config/config.h	Wed Jul 25 16:29:58 2012 +0300
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *	@(#)config.h	8.1 (Berkeley) 6/6/93
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/config/config.h 235789 2012-05-22 16:33:10Z bapt $
  */
 
 /*
@@ -171,7 +171,6 @@
 char	*raisestr(char *);
 void	remember(const char *);
 void	moveifchanged(const char *, const char *);
-int	yyparse(void);
 int	yylex(void);
 void	options(void);
 void	makefile(void);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/config/main.c
--- a/head/usr.sbin/config/main.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/config/main.c	Wed Jul 25 16:29:58 2012 +0300
@@ -38,7 +38,7 @@
 static char sccsid[] = "@(#)main.c	8.1 (Berkeley) 6/6/93";
 #endif
 static const char rcsid[] =
-  "$FreeBSD: head/usr.sbin/config/main.c 229403 2012-01-03 18:51:58Z ed $";
+  "$FreeBSD: head/usr.sbin/config/main.c 235789 2012-05-22 16:33:10Z bapt $";
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -91,6 +91,7 @@
 static void cleanheaders(char *);
 static void kernconfdump(const char *);
 static void checkversion(void);
+extern int yyparse(void);
 
 struct hdr_list {
 	char *h_name;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/cpucontrol/amd.c
--- a/head/usr.sbin/cpucontrol/amd.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/cpucontrol/amd.c	Wed Jul 25 16:29:58 2012 +0300
@@ -24,7 +24,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/cpucontrol/amd.c 236504 2012-06-03 08:30:00Z avg $");
 
 #include <assert.h>
 #include <stdio.h>
@@ -160,7 +160,7 @@
 
 		args.data = fw_image;
 		args.size = st.st_size;
-		error = ioctl(fd, CPUCTL_UPDATE, &args);
+		error = ioctl(devfd, CPUCTL_UPDATE, &args);
 		if (error < 0) {
 			fprintf(stderr, "failed.\n");
 			warn("ioctl()");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/cpucontrol/cpucontrol.8
--- a/head/usr.sbin/cpucontrol/cpucontrol.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/cpucontrol/cpucontrol.8	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/cpucontrol/cpucontrol.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd June 30, 2009
 .Dt CPUCONTROL 8
@@ -31,7 +31,7 @@
 .Nm cpucontrol
 .Nd control utility for the
 .Xr cpuctl 4
-device.
+device
 .Sh SYNOPSIS
 .Nm
 .Op Fl vh
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/cpucontrol/cpucontrol.c
--- a/head/usr.sbin/cpucontrol/cpucontrol.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/cpucontrol/cpucontrol.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/cpucontrol/cpucontrol.c 228436 2011-12-12 12:30:44Z fabient $");
+__FBSDID("$FreeBSD: head/usr.sbin/cpucontrol/cpucontrol.c 235647 2012-05-19 12:44:27Z gleb $");
 
 #include <assert.h>
 #include <stdio.h>
@@ -292,7 +292,7 @@
 	int error;
 	struct ucode_handler *handler;
 	struct datadir *dir;
-	DIR *dirfd;
+	DIR *dirp;
 	struct dirent *direntry;
 	char buf[MAXPATHLEN];
 
@@ -321,12 +321,12 @@
 	 * Process every image in specified data directories.
 	 */
 	SLIST_FOREACH(dir, &datadirs, next) {
-		dirfd  = opendir(dir->path);
-		if (dirfd == NULL) {
+		dirp = opendir(dir->path);
+		if (dirp == NULL) {
 			WARNX(1, "skipping directory %s: not accessible", dir->path);
 			continue;
 		}
-		while ((direntry = readdir(dirfd)) != NULL) {
+		while ((direntry = readdir(dirp)) != NULL) {
 			if (direntry->d_namlen == 0)
 				continue;
 			error = snprintf(buf, sizeof(buf), "%s/%s", dir->path,
@@ -340,7 +340,7 @@
 			}
 			handler->update(dev, buf);
 		}
-		error = closedir(dirfd);
+		error = closedir(dirp);
 		if (error != 0)
 			WARN(0, "closedir(%s)", dir->path);
 	}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/cron/crontab/crontab.5
--- a/head/usr.sbin/cron/crontab/crontab.5	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/cron/crontab/crontab.5	Wed Jul 25 16:29:58 2012 +0300
@@ -15,9 +15,9 @@
 .\" * Paul Vixie          <paul at vix.com>          uunet!decwrl!vixie!paul
 .\" */
 .\"
-.\" $FreeBSD: head/usr.sbin/cron/crontab/crontab.5 230655 2012-01-28 21:06:45Z scf $
+.\" $FreeBSD: head/usr.sbin/cron/crontab/crontab.5 234775 2012-04-28 22:48:00Z gjb $
 .\"
-.Dd January 28, 2012
+.Dd April 28, 2012
 .Dt CRONTAB 5
 .Os
 .Sh NAME
@@ -296,10 +296,21 @@
 .An Paul Vixie Aq paul at vix.com
 .Sh BUGS
 If you are in one of the 70-odd countries that observe Daylight
-Savings Time, jobs scheduled during the rollback or advance will be
-affected.
+Savings Time, jobs scheduled during the rollback or advance may be
+affected if
+.Xr cron 8
+is not started with the
+.Fl s
+flag.
 In general, it is not a good idea to schedule jobs during
-this period.
+this period if
+.Xr cron 8
+is not started with the
+.Fl s
+flag, which is enabled by default.
+See
+.Xr cron 8
+for more details.
 .Pp
 For US timezones (except parts of AZ and HI) the time shift occurs at
 2AM local time.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/cron/crontab/crontab.c
--- a/head/usr.sbin/cron/crontab/crontab.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/cron/crontab/crontab.c	Wed Jul 25 16:29:58 2012 +0300
@@ -18,7 +18,7 @@
 
 #if !defined(lint) && !defined(LINT)
 static const char rcsid[] =
-  "$FreeBSD: head/usr.sbin/cron/crontab/crontab.c 232202 2012-02-27 05:49:00Z delphij $";
+  "$FreeBSD: head/usr.sbin/cron/crontab/crontab.c 238024 2012-07-02 20:27:37Z jhb $";
 #endif
 
 /* crontab - install and manage per-user crontab files
@@ -608,6 +608,15 @@
 
 	log_it(RealUser, Pid, "REPLACE", User);
 
+	/*
+	 * Creating the 'tn' temp file has already updated the
+	 * modification time of the spool directory.  Sleep for a
+	 * second to ensure that poke_daemon() sets a later
+	 * modification time.  Otherwise, this can race with the cron
+	 * daemon scanning for updated crontabs.
+	 */
+	sleep(1);
+
 	poke_daemon();
 
 	return (0);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/crunch/crunchgen/crunched_main.c
--- a/head/usr.sbin/crunch/crunchgen/crunched_main.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/crunch/crunchgen/crunched_main.c	Wed Jul 25 16:29:58 2012 +0300
@@ -22,8 +22,6 @@
  * Author: James da Silva, Systems Design and Analysis Group
  *			   Computer Science Department
  *			   University of Maryland at College Park
- *
- * $FreeBSD$
  */
 /*
  * crunched_main.c - main program for crunched binaries, it branches to a
@@ -33,6 +31,10 @@
  *	or calls one of them based on argv[1].   This allows the testing of
  *	the crunched binary without creating all the links.
  */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/usr.sbin/crunch/crunchgen/crunched_main.c 237625 2012-06-27 04:39:30Z obrien $");
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -45,7 +47,8 @@
 extern char *__progname;
 extern struct stub entry_points[];
 
-int main(int argc, char **argv, char **envp)
+int
+main(int argc, char **argv, char **envp)
 {
     char *slash, *basename;
     struct stub *ep;
@@ -68,7 +71,8 @@
 }
 
 
-int crunched_here(char *path)
+int
+crunched_here(char *path)
 {
     char *slash, *basename;
     struct stub *ep;
@@ -83,7 +87,8 @@
 }
 
 
-int crunched_main(int argc, char **argv, char **envp)
+int
+crunched_main(int argc, char **argv, char **envp)
 {
     char *slash;
     struct stub *ep;
@@ -99,7 +104,8 @@
 }
 
 
-int crunched_usage()
+int
+crunched_usage()
 {
     int columns, len;
     struct stub *ep;
@@ -122,4 +128,3 @@
 }
 
 /* end of crunched_main.c */
-
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/crunch/crunchgen/crunchgen.c
--- a/head/usr.sbin/crunch/crunchgen/crunchgen.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/crunch/crunchgen/crunchgen.c	Wed Jul 25 16:29:58 2012 +0300
@@ -22,8 +22,6 @@
  * Author: James da Silva, Systems Design and Analysis Group
  *			   Computer Science Department
  *			   University of Maryland at College Park
- *
- * $FreeBSD$
  */
 /*
  * ========================================================================
@@ -32,9 +30,12 @@
  * Generates a Makefile and main C file for a crunched executable,
  * from specs given in a .conf file.
  */
-#include <sys/types.h>
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/usr.sbin/crunch/crunchgen/crunchgen.c 237625 2012-06-27 04:39:30Z obrien $");
+
+#include <sys/param.h>
 #include <sys/stat.h>
-#include <sys/param.h>
 
 #include <ctype.h>
 #include <err.h>
@@ -92,6 +93,7 @@
 char tempfname[MAXPATHLEN], cachename[MAXPATHLEN], curfilename[MAXPATHLEN];
 char outhdrname[MAXPATHLEN] ;	/* user-supplied header for *.mk */
 char *objprefix;		/* where are the objects ? */
+char *path_make;
 int linenum = -1;
 int goterror = 0;
 
@@ -118,7 +120,8 @@
 void gen_outputs(void);
 
 
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
 {
 	char *p;
 	int optc;
@@ -127,6 +130,10 @@
 	readcache = 1;
 	*outmkname = *outcfname = *execfname = '\0';
 
+	path_make = getenv("MAKE");
+	if (path_make == NULL || *path_make == '\0')
+		path_make = "make";
+
 	p = getenv("MAKEOBJDIRPREFIX");
 	if (p == NULL || *p == '\0')
 		objprefix = "/usr/obj"; /* default */
@@ -218,7 +225,8 @@
 }
 
 
-void usage(void)
+void
+usage(void)
 {
 	fprintf(stderr, "%s%s\n\t%s%s\n", "usage: crunchgen [-foq] ",
 	    "[-h <makefile-header-name>] [-m <makefile>]",
@@ -250,7 +258,8 @@
 void add_prog(char *progname);
 
 
-void parse_conf_file(void)
+void
+parse_conf_file(void)
 {
 	if (!is_nonempty_file(infilename))
 		errx(1, "fatal: input file \"%s\" not found", infilename);
@@ -263,7 +272,8 @@
 }
 
 
-void parse_one_file(char *filename)
+void
+parse_one_file(char *filename)
 {
 	char *fieldv[MAXFIELDS];
 	int fieldc;
@@ -329,7 +339,8 @@
 }
 
 
-void parse_line(char *line, int *fc, char **fv, int nf)
+void
+parse_line(char *line, int *fc, char **fv, int nf)
 {
 	char *p;
 
@@ -360,7 +371,8 @@
 }
 
 
-void add_srcdirs(int argc, char **argv)
+void
+add_srcdirs(int argc, char **argv)
 {
 	int i;
 
@@ -376,7 +388,8 @@
 }
 
 
-void add_progs(int argc, char **argv)
+void
+add_progs(int argc, char **argv)
 {
 	int i;
 
@@ -385,7 +398,8 @@
 }
 
 
-void add_prog(char *progname)
+void
+add_prog(char *progname)
 {
 	prog_t *p1, *p2;
 
@@ -426,7 +440,8 @@
 }
 
 
-void add_link(int argc, char **argv)
+void
+add_link(int argc, char **argv)
 {
 	int i;
 	prog_t *p = find_prog(argv[1]);
@@ -447,7 +462,8 @@
 }
 
 
-void add_libs(int argc, char **argv)
+void
+add_libs(int argc, char **argv)
 {
 	int i;
 
@@ -461,7 +477,8 @@
 }
 
 
-void add_libs_so(int argc, char **argv)
+void
+add_libs_so(int argc, char **argv)
 {
 	int i;
 
@@ -475,7 +492,8 @@
 }
 
 
-void add_buildopts(int argc, char **argv)
+void
+add_buildopts(int argc, char **argv)
 {
 	int i;
 
@@ -484,7 +502,8 @@
 }
 
 
-void add_special(int argc, char **argv)
+void
+add_special(int argc, char **argv)
 {
 	int i;
 	prog_t *p = find_prog(argv[1]);
@@ -586,7 +605,8 @@
 char *dir_search(char *progname);
 
 
-void gen_outputs(void)
+void
+gen_outputs(void)
 {
 	prog_t *p;
 
@@ -599,13 +619,15 @@
 	gen_output_makefile();
 	status("");
 	fprintf(stderr,
-	    "Run \"make -f %s\" to build crunched binary.\n", outmkname);
+	    "Run \"%s -f %s\" to build crunched binary.\n",
+	    path_make, outmkname);
 }
 
 /*
  * run the makefile for the program to find which objects are necessary
  */
-void fillin_program(prog_t *p)
+void
+fillin_program(prog_t *p)
 {
 	char path[MAXPATHLEN];
 	char line[MAXLINELEN];
@@ -680,7 +702,8 @@
 		p->goterror = 1;
 }
 
-void fillin_program_objs(prog_t *p, char *path)
+void
+fillin_program_objs(prog_t *p, char *path)
 {
 	char *obj, *cp;
 	int fd, rc;
@@ -720,16 +743,16 @@
 	fprintf(f, "loop:\n\t at echo 'OBJS= '${%s}\n", objvar);
 
 	fprintf(f, "crunchgen_objs:\n"
-	    "\t at cd %s && make -f %s $(BUILDOPTS) $(%s_OPTS)",
-	    p->srcdir, tempfname, p->ident);
+	    "\t at cd %s && %s -f %s $(BUILDOPTS) $(%s_OPTS)",
+	    p->srcdir, path_make, tempfname, p->ident);
 	for (s = p->buildopts; s != NULL; s = s->next)
 		fprintf(f, " %s", s->str);
 	fprintf(f, " loop\n");
 
 	fclose(f);
 
-	snprintf(line, MAXLINELEN, "cd %s && make -f %s -B crunchgen_objs",
-	    p->srcdir, tempfname);
+	snprintf(line, MAXLINELEN, "cd %s && %s -f %s -B crunchgen_objs",
+	     p->srcdir, path_make, tempfname);
 	if ((f = popen(line, "r")) == NULL) {
 		warn("submake pipe");
 		goterror = 1;
@@ -767,7 +790,8 @@
 	unlink(tempfname);
 }
 
-void remove_error_progs(void)
+void
+remove_error_progs(void)
 {
 	prog_t *p1, *p2;
 
@@ -788,7 +812,8 @@
 	}
 }
 
-void gen_specials_cache(void)
+void
+gen_specials_cache(void)
 {
 	FILE *cachef;
 	prog_t *p;
@@ -828,7 +853,8 @@
 }
 
 
-void gen_output_makefile(void)
+void
+gen_output_makefile(void)
 {
 	prog_t *p;
 	FILE *outmk;
@@ -858,7 +884,8 @@
 }
 
 
-void gen_output_cfile(void)
+void
+gen_output_cfile(void)
 {
 	extern char *crunched_skel[];
 	char **cp;
@@ -946,7 +973,8 @@
 }
 
 
-void top_makefile_rules(FILE *outmk)
+void
+top_makefile_rules(FILE *outmk)
 {
 	prog_t *p;
 
@@ -1004,7 +1032,8 @@
 }
 
 
-void prog_makefile_rules(FILE *outmk, prog_t *p)
+void
+prog_makefile_rules(FILE *outmk, prog_t *p)
 {
 	strlst_t *lst;
 
@@ -1089,7 +1118,8 @@
 	fprintf(outmk, "%s.lo\n", p->name);
 }
 
-void output_strlst(FILE *outf, strlst_t *lst)
+void
+output_strlst(FILE *outf, strlst_t *lst)
 {
 	for (; lst != NULL; lst = lst->next)
 		if ( strlen(lst->str) )
@@ -1104,7 +1134,8 @@
  *
  */
 
-void status(char *str)
+void
+status(char *str)
 {
 	static int lastlen = 0;
 	int len, spaces;
@@ -1123,13 +1154,15 @@
 }
 
 
-void out_of_memory(void)
+void
+out_of_memory(void)
 {
 	err(1, "%s: %d: out of memory, stopping", infilename, linenum);
 }
 
 
-void add_string(strlst_t **listp, char *str)
+void
+add_string(strlst_t **listp, char *str)
 {
 	strlst_t *p1, *p2;
 
@@ -1153,7 +1186,8 @@
 		p1->next = p2;
 }
 
-int subtract_strlst(strlst_t **lista, strlst_t **listb)
+int
+subtract_strlst(strlst_t **lista, strlst_t **listb)
 {
 	int subtract_count = 0;
 	strlst_t *p1;
@@ -1166,7 +1200,8 @@
 	return subtract_count;
 }
 
-int in_list(strlst_t **listp, char *str)
+int
+in_list(strlst_t **listp, char *str)
 {
 	strlst_t *p1;
 	for (p1 = *listp; p1 != NULL; p1 = p1->next)
@@ -1175,7 +1210,8 @@
 	return 0;
 }
 
-int is_dir(char *pathname)
+int
+is_dir(char *pathname)
 {
 	struct stat buf;
 
@@ -1185,7 +1221,8 @@
 	return S_ISDIR(buf.st_mode);
 }
 
-int is_nonempty_file(char *pathname)
+int
+is_nonempty_file(char *pathname)
 {
 	struct stat buf;
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/crunch/crunchide/crunchide.c
--- a/head/usr.sbin/crunch/crunchide/crunchide.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/crunch/crunchide/crunchide.c	Wed Jul 25 16:29:58 2012 +0300
@@ -1,5 +1,4 @@
 /*	$NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $	*/
-/* $FreeBSD$ */
 /*
  * Copyright (c) 1997 Christopher G. Demetriou.  All rights reserved.
  * Copyright (c) 1994 University of Maryland
@@ -59,20 +58,22 @@
  *	  that the final crunched binary BSS size is the max of all the
  *	  component programs' BSS sizes, rather than their sum.
  */
+
 #include <sys/cdefs.h>
 #ifndef lint
 __RCSID("$NetBSD: crunchide.c,v 1.8 1997/11/01 06:51:45 lukem Exp $");
 #endif
+__FBSDID("$FreeBSD: head/usr.sbin/crunch/crunchide/crunchide.c 237625 2012-06-27 04:39:30Z obrien $");
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
 #include <a.out.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
 
 #include "extern.h"
 
@@ -89,9 +90,8 @@
 
 int main(int, char *[]);
 
-int main(argc, argv)
-int argc;
-char **argv;
+int
+main(int argc, char **argv)
 {
     int ch, errors;
 
@@ -127,7 +127,8 @@
     return errors;
 }
 
-void usage(void)
+void
+usage(void)
 {
     fprintf(stderr,
 	    "usage: %s [-k <symbol-name>] [-f <keep-list-file>] <files> ...\n",
@@ -142,7 +143,8 @@
     char *sym;
 } *keep_list;
 
-void add_to_keep_list(char *symbol)
+void
+add_to_keep_list(char *symbol)
 {
     struct keep *newp, *prevp, *curp;
     int cmp;
@@ -167,7 +169,8 @@
     else keep_list = newp;
 }
 
-int in_keep_list(const char *symbol)
+int
+in_keep_list(const char *symbol)
 {
     struct keep *curp;
     int cmp;
@@ -180,7 +183,8 @@
     return curp && cmp == 0;
 }
 
-void add_file_to_keep_list(char *filename)
+void
+add_file_to_keep_list(char *filename)
 {
     FILE *keepf;
     char symbol[1024];
@@ -222,7 +226,8 @@
 #endif
 };
 
-int hide_syms(const char *filename)
+int
+hide_syms(const char *filename)
 {
 	int fd, i, n, rv;
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/crunch/crunchide/exec_elf32.c
--- a/head/usr.sbin/crunch/crunchide/exec_elf32.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/crunch/crunchide/exec_elf32.c	Wed Jul 25 16:29:58 2012 +0300
@@ -34,7 +34,7 @@
 __RCSID("$NetBSD: exec_elf32.c,v 1.4 1997/08/12 06:07:24 mikel Exp $");
 #endif
 #endif
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/crunch/crunchide/exec_elf32.c 237254 2012-06-19 06:09:58Z eadler $");
  
 #ifndef ELFSIZE
 #define ELFSIZE         32
@@ -238,7 +238,7 @@
 	Elf_Shdr *shdrp = NULL, *symtabshdr, *strtabshdr;
 	Elf_Sym *symtabp = NULL;
 	char *strtabp = NULL;
-	Elf_Size  nsyms, nlocalsyms, ewi;
+	Elf_Size  nsyms, ewi;
 	ssize_t shdrsize;
 	int rv, i, weird;
 	size_t nstrtab_size, nstrtab_nextoff, fn_size;
@@ -327,7 +327,6 @@
 
 	/* Prepare data structures for symbol movement. */
 	nsyms = xewtoh(symtabshdr->sh_size) / xewtoh(symtabshdr->sh_entsize);
-	nlocalsyms = xe32toh(symtabshdr->sh_info);
 
 	/* move symbols, making them local */
 	for (ewi = 0; ewi < nsyms; ewi++) {
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ctladm/ctladm.8
--- a/head/usr.sbin/ctladm/ctladm.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ctladm/ctladm.8	Wed Jul 25 16:29:58 2012 +0300
@@ -32,7 +32,7 @@
 .\" Author: Ken Merry <ken at FreeBSD.org>
 .\"
 .\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
-.\" $FreeBSD: head/usr.sbin/ctladm/ctladm.8 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/ctladm/ctladm.8 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd March 6, 2012
 .Dt CTLADM 8
@@ -401,7 +401,7 @@
 .Fl m
 option are mutually exclusive.  One of the two must be specified, though.
 .It Fl P Ar pc
-Specify the mode page page control value.  Possible values are:
+Specify the mode page control value.  Possible values are:
 .Bl -tag -width 2n -compact
 .It 0
 Current values.
@@ -542,7 +542,7 @@
 Because this command uses the ioctl port, it will only work when the FETDs
 (Front End Target Drivers) are enabled.
 This command is the equivalent of doing a REPORT LUNS on one LUN and then
-and then an INQUIRY on each LUN in the system.
+an INQUIRY on each LUN in the system.
 .It Ic delay
 Delay commands at the given location.  There are two places where commands
 may be delayed currently: before data is transferred
@@ -749,7 +749,7 @@
 As a general rule, the WWNN should be the same across all ports on the
 system.
 .It Fl W Ar wwpn
-Set the World Wide Node Name for the given port.
+Set the World Wide Port Name for the given port.
 The
 .Fl n
 argument must be specified, since this is only possible to implement on a
@@ -939,10 +939,10 @@
 .Pa src/usr.sbin/ctladm/ctladm.8
 as the backing store, and specify the
 .Tn SCSI
-VPD page 0x80 and 0x83 serial number (
-.Fl S)
-and device ID (
-.Fl d).
+VPD page 0x80 and 0x83 serial number
+.Fl ( S )
+and device ID
+.Fl ( d ) .
 .Pp
 .Dl ctladm remove -b block -l 12
 .Pp
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ctladm/ctladm.c
--- a/head/usr.sbin/ctladm/ctladm.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ctladm/ctladm.c	Wed Jul 25 16:29:58 2012 +0300
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/ctladm/ctladm.c 232604 2012-03-06 13:43:57Z trasz $");
+__FBSDID("$FreeBSD: head/usr.sbin/ctladm/ctladm.c 237255 2012-06-19 06:10:24Z eadler $");
 
 #include <sys/ioctl.h>
 #include <sys/types.h>
@@ -772,7 +772,6 @@
 cctl_delay(int fd, int target, int lun, int argc, char **argv,
 	   char *combinedopt)
 {
-	int datamove_delay;
 	struct ctl_io_delay_info delay_info;
 	char *delayloc = NULL;
 	char *delaytype = NULL;
@@ -781,7 +780,6 @@
 	int c;
 
 	retval = 0;
-	datamove_delay = 0;
 
 	memset(&delay_info, 0, sizeof(delay_info));
 
@@ -3803,7 +3801,7 @@
 int
 main(int argc, char **argv)
 {
-	int option_index, c;
+	int c;
 	ctladm_cmdfunction command;
 	ctladm_cmdargs cmdargs;
 	ctladm_optret optreturn;
@@ -3814,10 +3812,9 @@
 	int target, lun;
 	int optstart = 2;
 	int retval, fd;
-	int retries, timeout;
+	int retries;
 	int initid;
 
-	option_index = 0;
 	retval = 0;
 	cmdargs = CTLADM_ARG_NONE;
 	command = CTLADM_CMD_HELP;
@@ -3826,7 +3823,6 @@
 	retries = 0;
 	target = 0;
 	lun = 0;
-	timeout = 0;
 	initid = 7;
 
 	if (argc < 2) {
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/daemon/daemon.8
--- a/head/usr.sbin/daemon/daemon.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/daemon/daemon.8	Wed Jul 25 16:29:58 2012 +0300
@@ -24,9 +24,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/daemon/daemon.8 231911 2012-02-19 10:36:29Z trociny $
+.\" $FreeBSD: head/usr.sbin/daemon/daemon.8 236551 2012-06-04 09:25:01Z trociny $
 .\"
-.Dd February 19, 2012
+.Dd June 4, 2012
 .Dt DAEMON 8
 .Os
 .Sh NAME
@@ -34,7 +34,7 @@
 .Nd run detached from the controlling terminal
 .Sh SYNOPSIS
 .Nm
-.Op Fl cf
+.Op Fl cfr
 .Op Fl p Ar pidfile
 .Op Fl u Ar user
 .Ar command arguments ...
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/daemon/daemon.c
--- a/head/usr.sbin/daemon/daemon.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/daemon/daemon.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/daemon/daemon.c 231912 2012-02-19 10:38:55Z trociny $");
+__FBSDID("$FreeBSD: head/usr.sbin/daemon/daemon.c 236551 2012-06-04 09:25:01Z trociny $");
 
 #include <sys/param.h>
 #include <sys/mman.h>
@@ -217,6 +217,10 @@
 		}
 		switch (signo) {
 		case SIGCHLD:
+			if (waitpid(pid, NULL, WNOHANG) == -1) {
+				warn("waitpid");
+				return (-1);
+			}
 			return (terminate);
 		case SIGTERM:
 			terminate = 1;
@@ -236,7 +240,7 @@
 usage(void)
 {
 	(void)fprintf(stderr,
-	    "usage: daemon [-cf] [-p pidfile] [-u user] command "
+	    "usage: daemon [-cfr] [-p pidfile] [-u user] command "
 		"arguments ...\n");
 	exit(1);
 }
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/digictl/digictl.8
--- a/head/usr.sbin/digictl/digictl.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/digictl/digictl.8	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/digictl/digictl.8 236500 2012-06-03 06:57:47Z joel $
 .Dd June 20, 2001
 .Dt DIGICTL 8
 .Os
@@ -53,7 +53,7 @@
 is the port number.
 .Pp
 The following flags are recognized:
-.Bl -tag
+.Bl -tag -width 10n
 .It Fl a Cm disable | enable | query
 Disable, enable or query the
 .Em ALTPIN
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/etcupdate/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/etcupdate/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,6 @@
+# $FreeBSD: head/usr.sbin/etcupdate/Makefile 238423 2012-07-13 13:23:48Z jhb $
+
+SCRIPTS=etcupdate.sh
+MAN=	etcupdate.8
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/etcupdate/etcupdate.8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/etcupdate/etcupdate.8	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,789 @@
+.\" Copyright (c) 2010-2012 Advanced Computing Technologies LLC
+.\" Written by: John H. Baldwin <jhb at 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.
+.\"
+.\" $FreeBSD: head/usr.sbin/etcupdate/etcupdate.8 238428 2012-07-13 21:27:18Z joel $
+.\"
+.Dd March 16, 2012
+.Dt ETCUPDATE 8
+.Os
+.Sh NAME
+.Nm etcupdate
+.Nd "manage updates to system files not updated by installworld"
+.Sh SYNOPSIS
+.Nm
+.Op Fl nBF
+.Op Fl d Ar workdir
+.Op Fl r | Fl s Ar source | Fl t Ar tarball
+.Op Fl A Ar patterns
+.Op Fl D Ar destdir
+.Op Fl I Ar patterns
+.Op Fl L Ar logfile
+.Op Fl M Ar options
+.Nm
+.Cm build
+.Op Fl B
+.Op Fl d Ar workdir
+.Op Fl s Ar source
+.Op Fl L Ar logfile
+.Op Fl M Ar options
+.Ar tarball
+.Nm
+.Cm diff
+.Op Fl d Ar workdir
+.Op Fl D Ar destdir
+.Op Fl I Ar patterns
+.Op Fl L Ar logfile
+.Nm
+.Cm extract
+.Op Fl B
+.Op Fl d Ar workdir
+.Op Fl s Ar source | Fl t Ar tarball
+.Op Fl L Ar logfile
+.Op Fl M Ar options
+.Nm
+.Cm resolve
+.Op Fl d Ar workdir
+.Op Fl D Ar destdir
+.Op Fl L Ar logfile
+.Nm
+.Cm status
+.Op Fl d Ar workdir
+.Op Fl D Ar destdir
+.Sh DESCRIPTION
+The
+.Nm
+utility is a tool for managing updates to files that are not updated as
+part of
+.Sq make installworld
+such as files in
+.Pa /etc .
+It manages updates by doing a three-way merge of changes made to these
+files against the local versions.
+It is also designed to minimize the amount of user intervention with
+the goal of simplifying upgrades for clusters of machines.
+.Pp
+To perform a three-way merge,
+.Nm
+keeps copies of the current and previous versions of files that it manages.
+These copies are stored in two trees known as the
+.Dq current
+and
+.Dq previous
+trees.
+During a merge,
+.Nm
+compares the
+.Dq current
+and
+.Dq previous
+copies of each file to determine which changes need to be merged into the
+local version of each file.
+If a file can be updated without generating a conflict,
+.Nm
+will update the file automatically.
+If the local changes to a file conflict with the changes made to a file in
+the source tree,
+then a merge conflict is generated.
+The conflict must be resolved after the merge has finished.
+The
+.Nm
+utility will not perform a new merge until all conflicts from an earlier
+merge are resolved.
+.Sh MODES
+The
+.Nm
+utility supports several modes of operation.
+The mode is specified via an optional command argument.
+If present, the command must be the first argument on the command line.
+If a command is not specified, the default mode is used.
+.Ss Default Mode
+The default mode merges changes from the source tree to the destination
+directory.
+First,
+it updates the
+.Dq current
+and
+.Dq previous
+trees.
+Next,
+it compares the two trees merging changes into the destination directory.
+Finally,
+it displays warnings for any conditions it could not handle automatically.
+.Pp
+If the
+.Fl r
+option is not specified,
+then the first step taken is to update the
+.Dq current
+and
+.Dq previous
+trees.
+If a
+.Dq current
+tree already exists,
+then that tree is saved as the
+.Dq previous
+tree.
+An older
+.Dq previous
+tree is removed if it exists.
+By default the new
+.Dq current
+tree is built from a source tree.
+However,
+if a tarball is specified via the
+.Fl t
+option,
+then the tree is extracted from that tarball instead.
+.Pp
+Next,
+.Nm
+compares the files in the
+.Dq current
+and
+.Dq previous
+trees.
+If a file was removed from the
+.Dq current
+tree,
+then it will be removed from the destination directory only if it
+does not have any local modifications.
+If a file was added to the
+.Dq current
+tree,
+then it will be copied to the destination directory only if it
+would not clobber an existing file.
+If a file is changed in the
+.Dq current
+tree,
+then
+.Nm
+will attempt to merge the changes into the version of the file in the
+destination directory.
+If the merge encounters conflicts,
+then a version of the file with conflict markers will be saved for
+future resolution.
+If the merge does not encounter conflicts,
+then the merged version of the file will be saved in the destination
+directory.
+If
+.Nm
+is not able to safely merge in changes to a file other than a merge conflict,
+it will generate a warning.
+.Pp
+For each file that is updated a line will be output with a leading character
+to indicate the action taken.
+The possible actions follow:
+.Pp
+.Bl -tag -width "A" -compact -offset indent
+.It A
+Added
+.It C
+Conflict
+.It D
+Deleted
+.It M
+Merged
+.It U
+Updated
+.El
+.Pp
+Finally,
+if any warnings were encountered they are displayed after the merge has
+completed.
+.Pp
+Note that for certain files
+.Nm
+will perform post-install actions any time that the file is updated.
+Specifically,
+.Xr pwd_mkdb 8
+is invoked if
+.Pa /etc/master.passwd
+is changed,
+.Xr cap_mkdb 1
+is invoked to update
+.Pa /etc/login.conf.db
+if
+.Pa /etc/login.conf
+is changed,
+.Xr newaliases 1
+is invoked if
+.Pa /etc/mail/aliases
+is changed,
+and
+.Pa /etc/rc.d/motd
+is invoked if
+.Pa /etc/motd
+is changed.
+One exception is that if
+.Pa /etc/mail/aliases
+is changed and the destination directory is not the default,
+then a warning will be issued instead.
+This is due to a limitation of the
+.Xr newaliases 1
+command.
+Similarly,
+if
+.Pa /etc/motd
+is changed and the destination directory is not the default,
+then
+.Pa /etc/rc.d/motd
+will not be executed due to a limitation of that script.
+In this case no warning is issued as the result of
+.Pa /etc/rc.d/motd
+is merely cosmetic and will be corrected on the next reboot.
+.Ss Build Mode
+The
+.Cm build
+mode is used to build a tarball that contains a snapshot of a
+.Dq current
+tree.
+This tarball can be used by the default and extract modes.
+Using a tarball can allow
+.Nm
+to perform a merge without requiring a source tree that matches the
+currently installed world.
+The
+.Fa tarball
+argument specifies the name of the file to create.
+The file will be a
+.Xr tar 5
+file compressed with
+.Xr bzip2 1 .
+.Ss Diff Mode
+The
+.Cm diff
+mode compares the versions of files in the destination directory to the
+.Dq current
+tree and generates a unified format diff of the changes.
+This can be used to determine which files have been locally modified and how.
+Note that
+.Nm
+does not manage files that are not maintained in the source tree such as
+.Pa /etc/fstab
+and
+.Pa /etc/rc.conf .
+.Ss Extract Mode
+The
+.Cm extract
+mode generates a new
+.Dq current
+tree.
+Unlike the default mode,
+it does not save any existing
+.Dq current
+tree and does not modify any existing
+.Dq previous
+tree.
+The new
+.Dq current
+tree can either be built from a source tree or extracted from a tarball.
+.Ss Resolve Mode
+The
+.Cm resolve
+mode is used to resolve any conflicts encountered during a merge.
+In this mode,
+.Nm
+iterates over any existing conflicts prompting the user for actions to take
+on each conflicted file.
+For each file, the following actions are available:
+.Pp
+.Bl -tag -width "(tf) theirs-full" -compact
+.It (p)  postpone
+Ignore this conflict for now.
+.It (df) diff-full
+Show all changes made to the merged file as a unified diff.
+.It (e)  edit
+Change the merged file in an editor.
+.It (r)  resolved
+Install the merged version of the file into the destination directory.
+.It (mf) mine-full
+Use the version of the file in the destination directory and ignore any
+changes made to the file in the
+.Dq current
+tree.
+.It (tf) theirs-full
+Use the version of the file from the
+.Dq current
+tree and discard any local changes made to the file.
+.It (h)  help
+Display the list of commands.
+.El
+.Ss Status Mode
+The
+.Cm status
+mode shows a summary of the results of the most recent merge.
+First it lists any files for which there are unresolved conflicts.
+Next it lists any warnings generated during the last merge.
+If the last merge did not generate any conflicts or warnings,
+then nothing will be output.
+.Sh OPTIONS
+The following options are available.
+Note that most options do not apply to all modes.
+.Bl -tag -width ".Fl d Ar workdir"
+.It Fl B
+Do not build generated files in a private object tree.
+Instead,
+reuse the generated files from a previously built object tree that matches
+the source tree.
+This can be useful to avoid gratuitous conflicts in
+.Xr sendmail 8
+configuration
+files when bootstrapping.
+It can also be useful for building a tarball that matches a specific
+world build.
+.It Fl d Ar workdir
+Specify an alternate directory to use as the work directory.
+The work directory is used to store the
+.Dq current
+and
+.Dq previous
+trees as well as unresolved conflicts.
+The default work directory is
+.Pa <destdir>/var/db/etcupdate .
+.It Fl A Ar patterns
+Always install the new version of any files that match any of the patterns
+listed in
+.Ar patterns .
+Each pattern is evaluated as an
+.Xr sh 1
+shell pattern.
+This option may be specified multiple times to specify multiple patterns.
+Multiple space-separated patterns may also be specified in a single
+option.
+Note that ignored files specified via the
+.Ev IGNORE_FILES
+variable or the
+.Fl I
+option will not be installed.
+.It Fl D Ar destdir
+Specify an alternate destination directory as the target of a merge.
+This is analogous to the
+.Dv DESTDIR
+variable used with
+.Sq make installworld .
+The default destination directory is an empty string which results in
+merges updating
+.Pa /etc
+on the local machine.
+.It Fl F
+Ignore changes in the FreeBSD ID string when comparing files in the
+destination directory to files in either of the
+.Dq current
+or
+.Dq previous
+trees.
+In
+.Cm diff
+mode,
+this reduces noise due to FreeBSD ID string changes in the output.
+During an update this can simplify handling for harmless conflicts caused
+by FreeBSD ID string changes.
+.Pp
+Specifically,
+if a file in the destination directory is identical to the same file in the
+.Dq previous
+tree modulo the FreeBSD ID string,
+then the file is treated as if it was unmodified and the
+.Dq current
+version of the file will be installed.
+Similarly,
+if a file in the destination directory is identical to the same file in the
+.Dq current
+tree modulo the FreeBSD ID string,
+then the
+.Dq current
+version of the file will be installed to update the ID string.
+If the
+.Dq previous
+and
+.Dq current
+versions of the file are identical,
+then
+.Nm
+will not change the file in the destination directory.
+.Pp
+Due to limitations in the
+.Xr diff 1
+command,
+this option may not have an effect if there are other changes in a file that
+are close to the FreeBSD ID string.
+.It Fl I Ar patterns
+Ignore any files that match any of the patterns listed in
+.Ar patterns .
+No warnings or other messages will be generated for those files during a
+merge.
+Each pattern is evaluated as an
+.Xr sh 1
+shell pattern.
+This option may be specified multiple times to specify multiple patterns.
+Multiple space-separated patterns may also be specified in a single
+option.
+.It Fl L Ar logfile
+Specify an alternate path for the log file.
+The
+.Nm
+utility logs each command that it invokes along with the standard output
+and standard error to this file.
+By default the log file is stored in a file named
+.Pa log
+in the work directory.
+.It Fl M Ar options
+Pass
+.Ar options
+as additional parameters to
+.Xr make 1
+when building a
+.Dq current
+tree.
+This can be used for to set the
+.Dv TARGET
+or
+.Dv TARGET_ARCH
+variables for a cross-build.
+.It Fl n
+Enable
+.Dq dry-run
+mode.
+Do not merge any changes to the destination directory.
+Instead,
+report what actions would be taken during a merge.
+Note that the existing
+.Dq current
+and
+.Dq previous
+trees will not be changed.
+If the
+.Fl r
+option is not specified,
+then a temporary
+.Dq current
+tree will be extracted to perform the comparison.
+.It Fl r
+Do not update the
+.Dq current
+and
+.Dq previous
+trees during a merge.
+This can be used to
+.Dq re-run
+a previous merge operation.
+.It Fl s Ar source
+Specify an alternate source tree to use when building or extracting a
+.Dq current
+tree.
+The default source tree is
+.Pa /usr/src .
+.It Fl t Ar tarball
+Extract a new
+.Dq current
+tree from a tarball previously generated by the
+.Cm build
+command rather than building the tree from a source tree.
+.El
+.Sh CONFIG FILE
+The
+.Nm
+utility can also be configured by setting variables in an optional
+configuration file named
+.Pa /etc/etcupdate.conf .
+Note that command line options override settings in the configuration file.
+The configuration file is executed by
+.Xr sh 1 ,
+so it uses that syntax to set configuration variables.
+The following variables can be set:
+.Bl -tag -width ".Ev ALWAYS_INSTALL"
+.It Ev ALWAYS_INSTALL
+Always install files that match any of the patterns listed in this variable
+similar to the
+.Fl A
+option.
+.It Ev DESTDIR
+Specify an alternate destination directory similar to the
+.Fl D
+option.
+.It Ev EDITOR
+Specify a program to edit merge conflicts.
+.It Ev FREEBSD_ID
+Ignore changes in the FreeBSD ID string similar to the
+.Fl F
+option.
+This is enabled by setting the variable to a non-empty value.
+.It Ev IGNORE_FILES
+Ignore files that match any of the patterns listed in this variable
+similar to the
+.Fl I
+option.
+.It Ev LOGFILE
+Specify an alternate path for the log file similar to the
+.Fl L
+option.
+.It Ev MAKE_OPTIONS
+Pass additional options to
+.Xr make 1
+when building a
+.Dq current
+tree similar to the
+.Fl M
+option.
+.It Ev SRCDIR
+Specify an alternate source tree similar to the
+.Fl s
+option.
+.It Ev WORKDIR
+Specify an alternate work directory similar to the
+.Fl d
+option.
+.El
+.Sh ENVIRONMENT
+The
+.Nm
+utility uses the program identified in the
+.Ev EDITOR
+environment variable to edit merge conflicts.
+If
+.Ev EDITOR
+is not set,
+.Xr vi 1
+is used as the default editor.
+.Sh FILES
+.Bl -tag -width ".Pa /var/db/etcupdate/log" -compact
+.It Pa /etc/etcupdate.conf
+Optional config file.
+.It Pa /var/db/etcupdate
+Default work directory used to store trees and other data.
+.It Pa /var/db/etcupdate/log
+Default log file.
+.El
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+If the source tree matches the currently installed world,
+then the following can be used to bootstrap
+.Nm
+so that it can be used for future upgrades:
+.Pp
+.Dl "etcupdate extract"
+.Pp
+To merge changes after an upgrade via the buildworld and installworld process:
+.Pp
+.Dl "etcupdate"
+.Pp
+To resolve any conflicts generated during a merge:
+.Pp
+.Dl "etcupdate resolve"
+.Sh DIAGNOSTICS
+The following warning messages may be generated during a merge.
+Note that several of these warnings cover obscure cases that should occur
+rarely if at all in practice.
+For example,
+if a file changes from a file to a directory in the
+.Dq current
+tree
+and the file was modified in the destination directory,
+then a warning will be triggered.
+In general,
+when a warning references a pathname,
+the corresponding file in the destination directory is not changed by a
+merge operation.
+.Bl -diag
+.It "Directory mismatch: <path> (<type>)"
+An attempt was made to create a directory at
+.Pa path
+but an existing file of type
+.Dq type
+already exists for that path name.
+.It "Modified link changed: <file> (<old> became <new>)"
+The target of a symbolic link named
+.Pa file
+was changed from
+.Dq old
+to
+.Dq new
+in the
+.Dq current
+tree.
+The symbolic link has been modified to point to a target that is neither
+.Dq old
+nor
+.Dq new
+in the destination directory.
+.It "Modified mismatch: <file> (<new> vs <dest>)"
+A file named
+.Pa file
+of type
+.Dq new
+was modified in the
+.Dq current
+tree,
+but the file exists as a different type
+.Dq dest
+in the destination directory.
+.It "Modified <type> changed: <file> (<old> became <new>)"
+A file named
+.Pa file
+changed type from
+.Dq old
+in the
+.Dq previous
+tree to type
+.Dq new
+in the
+.Dq current
+tree.
+The file in the destination directory of type
+.Dq type
+has been modified,
+so it could not be merged automatically.
+.It "Modified <type> remains: <file>"
+The file of type
+.Dq type
+named
+.Pa file
+has been removed from the
+.Dq current
+tree,
+but it has been locally modified.
+The modified version of the file remains in the destination directory.
+.It "Needs update: /etc/mail/aliases.db (required manual update via newaliases(1))"
+The file
+.Pa /etc/mail/aliases
+was updated during a merge with a non-empty destination directory.
+Due to a limitation of the
+.Xr newaliases 1
+command,
+.Nm
+was not able to automatically update the corresponding aliases database.
+.It "New file mismatch: <file> (<new> vs <dest>)"
+A new file named
+.Pa file
+of type
+.Dq new
+has been added to the
+.Dq current
+tree.
+A file of that name already exists in the destination directory,
+but it is of a different type
+.Dq dest .
+.It "New link conflict: <file> (<new> vs <dest>)"
+A symbolic link named
+.Pa file
+has been added to the
+.Dq current
+tree that links to
+.Dq new .
+A symbolic link of the same name already exists in the destination
+directory,
+but it links to a different target
+.Dq dest .
+.It "Non-empty directory remains: <file>"
+The directory
+.Pa file
+was removed from the
+.Dq current
+tree,
+but it contains additional files in the destination directory.
+These additional files as well as the directory remain.
+.It "Remove mismatch: <file> (<old> became <new>)"
+A file named
+.Pa file
+changed from type
+.Dq old
+in the
+.Dq previous
+tree to type
+.Dq new
+in the
+.Dq current
+tree,
+but it has been removed in the destination directory.
+.It "Removed file changed: <file>"
+A file named
+.Pa file
+was modified in the
+.Dq current
+tree,
+but it has been removed in the destination directory.
+.It "Removed link changed: <file> (<old> became <new>)"
+The target of a symbolic link named
+.Pa file
+was changed from
+.Dq old
+to
+.Dq new
+in the
+.Dq current
+tree,
+but it has been removed in the destination directory.
+.El
+.Sh SEE ALSO
+.Xr cap_mkdb 1 ,
+.Xr diff 1 ,
+.Xr make 1 ,
+.Xr newaliases 1 ,
+.Xr sh 1 ,
+.Xr pwd_mkdb 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An John Baldwin Aq jhb at FreeBSD.org .
+.Sh BUGS
+Rerunning a merge does not automatically delete conflicts left over from a
+previous merge.
+Any conflicts must be resolved before the merge can be rerun.
+It it is not clear if this is a feature or a bug.
+.Pp
+There is no way to easily automate conflict resolution for specific files.
+For example, one can imagine a syntax along the lines of
+.Pp
+.Dl "etcupdate resolve tf /some/file"
+.Pp
+to resolve a specific conflict in an automated fashion.
+.Pp
+It might be nice to have something like a
+.Sq revert
+command to replace a locally modified version of a file with the stock
+version of the file.
+For example:
+.Pp
+.Dl "etcupdate revert /etc/mail/freebsd.cf"
+.Pp
+Bootstrapping
+.Nm
+often results in gratuitous diffs in
+.Pa /etc/mail/*.cf
+that cause conflicts in the first merge.
+If an object tree that matches the source tree is present when bootstrapping,
+then passing the
+.Fl B
+flag to the
+.Cm extract
+command can work around this.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/etcupdate/etcupdate.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/etcupdate/etcupdate.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,1675 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb at 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.
+#
+# $FreeBSD: head/usr.sbin/etcupdate/etcupdate.sh 238423 2012-07-13 13:23:48Z jhb $
+
+# This is a tool to manage updating files that are not updated as part
+# of 'make installworld' such as files in /etc.  Unlike other tools,
+# this one is specifically tailored to assisting with mass upgrades.
+# To that end it does not require user intervention while running.
+#
+# Theory of operation:
+#
+# The most reliable way to update changes to files that have local
+# modifications is to perform a three-way merge between the original
+# unmodified file, the new version of the file, and the modified file.
+# This requires having all three versions of the file available when
+# performing an update.
+#
+# To that end, etcupdate uses a strategy where the current unmodified
+# tree is kept in WORKDIR/current and the previous unmodified tree is
+# kept in WORKDIR/old.  When performing a merge, a new tree is built
+# if needed and then the changes are merged into DESTDIR.  Any files
+# with unresolved conflicts after the merge are left in a tree rooted
+# at WORKDIR/conflicts.
+#
+# To provide extra flexibility, etcupdate can also build tarballs of
+# root trees that can later be used.  It can also use a tarball as the
+# source of a new tree instead of building it from /usr/src.
+
+# Global settings.  These can be adjusted by config files and in some
+# cases by command line options.
+
+# TODO:
+# - automatable conflict resolution
+# - a 'revert' command to make a file "stock"
+
+usage()
+{
+	cat <<EOF
+usage: etcupdate [-nBF] [-d workdir] [-r | -s source | -t tarball] [-A patterns]
+                 [-D destdir] [-I patterns] [-L logfile] [-M options]
+       etcupdate build [-B] [-d workdir] [-s source] [-L logfile] [-M options]
+                 <tarball>
+       etcupdate diff [-d workdir] [-D destdir] [-I patterns] [-L logfile]
+       etcupdate extract [-B] [-d workdir] [-s source | -t tarball] [-L logfile]
+                 [-M options]
+       etcupdate resolve [-d workdir] [-D destdir] [-L logfile]
+       etcupdate status [-d workdir] [-D destdir]
+EOF
+	exit 1
+}
+
+# Used to write a message prepended with '>>>' to the logfile.
+log()
+{
+	echo ">>>" "$@" >&3
+}
+
+# Used for assertion conditions that should never happen.
+panic()
+{
+	echo "PANIC:" "$@"
+	exit 10
+}
+
+# Used to write a warning message.  These are saved to the WARNINGS
+# file with "  " prepended.
+warn()
+{
+	echo -n "  " >> $WARNINGS
+	echo "$@" >> $WARNINGS
+}
+
+# Output a horizontal rule using the passed-in character.  Matches the
+# length used for Index lines in CVS and SVN diffs.
+#
+# $1 - character
+rule()
+{
+	jot -b "$1" -s "" 67
+}
+
+# Output a text description of a specified file's type.
+#
+# $1 - file pathname.
+file_type()
+{
+	stat -f "%HT" $1 | tr "[:upper:]" "[:lower:]"
+}
+
+# Returns true (0) if a file exists
+#
+# $1 - file pathname.
+exists()
+{
+	[ -e $1 -o -L $1 ]
+}
+
+# Returns true (0) if a file should be ignored, false otherwise.
+#
+# $1 - file pathname
+ignore()
+{
+	local pattern -
+
+	set -o noglob
+	for pattern in $IGNORE_FILES; do
+		set +o noglob
+		case $1 in
+			$pattern)
+				return 0
+				;;
+		esac
+		set -o noglob
+	done
+
+	# Ignore /.cshrc and /.profile if they are hardlinked to the
+	# same file in /root.  This ensures we only compare those
+	# files once in that case.
+	case $1 in
+		/.cshrc|/.profile)
+			if [ ${DESTDIR}$1 -ef ${DESTDIR}/root$1 ]; then
+				return 0
+			fi
+			;;
+		*)
+			;;
+	esac
+
+	return 1
+}
+
+# Returns true (0) if the new version of a file should always be
+# installed rather than attempting to do a merge.
+#
+# $1 - file pathname
+always_install()
+{
+	local pattern -
+
+	set -o noglob
+	for pattern in $ALWAYS_INSTALL; do
+		set +o noglob
+		case $1 in
+			$pattern)
+				return 0
+				;;
+		esac
+		set -o noglob
+	done
+
+	return 1
+}
+
+# Build a new tree
+#
+# $1 - directory to store new tree in
+build_tree()
+{
+	local make
+
+	make="make $MAKE_OPTIONS"
+
+	log "Building tree at $1 with $make"
+	mkdir -p $1/usr/obj >&3 2>&1
+	(cd $SRCDIR; $make DESTDIR=$1 distrib-dirs) >&3 2>&1 || return 1
+
+	if ! [ -n "$nobuild" ]; then
+		(cd $SRCDIR; \
+	    MAKEOBJDIRPREFIX=$1/usr/obj $make _obj SUBDIR_OVERRIDE=etc &&
+	    MAKEOBJDIRPREFIX=$1/usr/obj $make everything SUBDIR_OVERRIDE=etc &&
+	    MAKEOBJDIRPREFIX=$1/usr/obj $make DESTDIR=$1 distribution) \
+		    >&3 2>&1 || return 1
+	else
+		(cd $SRCDIR; $make DESTDIR=$1 distribution) >&3 2>&1 || return 1
+	fi
+	chflags -R noschg $1 >&3 2>&1 || return 1
+	rm -rf $1/usr/obj >&3 2>&1 || return 1
+
+	# Purge auto-generated files.  Only the source files need to
+	# be updated after which these files are regenerated.
+	rm -f $1/etc/*.db $1/etc/passwd >&3 2>&1 || return 1
+
+	# Remove empty files.  These just clutter the output of 'diff'.
+	find $1 -type f -size 0 -delete >&3 2>&1 || return 1
+
+	# Trim empty directories.
+	find -d $1 -type d -empty -delete >&3 2>&1 || return 1
+	return 0
+}
+
+# Generate a new NEWTREE tree.  If tarball is set, then the tree is
+# extracted from the tarball.  Otherwise the tree is built from a
+# source tree.
+extract_tree()
+{
+	# If we have a tarball, extract that into the new directory.
+	if [ -n "$tarball" ]; then
+		if ! (mkdir -p $NEWTREE && tar xf $tarball -C $NEWTREE) \
+		    >&3 2>&1; then
+			echo "Failed to extract new tree."
+			remove_tree $NEWTREE
+			exit 1
+		fi
+	else
+		if ! build_tree $NEWTREE; then
+			echo "Failed to build new tree."
+			remove_tree $NEWTREE
+			exit 1
+		fi
+	fi
+}
+
+# Forcefully remove a tree.  Returns true (0) if the operation succeeds.
+#
+# $1 - path to tree
+remove_tree()
+{
+
+	rm -rf $1 >&3 2>&1
+	if [ -e $1 ]; then
+		chflags -R noschg $1 >&3 2>&1
+		rm -rf $1 >&3 2>&1
+	fi
+	[ ! -e $1 ]
+}
+
+# Return values for compare()
+COMPARE_EQUAL=0
+COMPARE_ONLYFIRST=1
+COMPARE_ONLYSECOND=2
+COMPARE_DIFFTYPE=3
+COMPARE_DIFFLINKS=4
+COMPARE_DIFFFILES=5
+
+# Compare two files/directories/symlinks.  Note that this does not
+# recurse into subdirectories.  Instead, if two nodes are both
+# directories, they are assumed to be equivalent.
+#
+# Returns true (0) if the nodes are identical.  If only one of the two
+# nodes are present, return one of the COMPARE_ONLY* constants.  If
+# the nodes are different, return one of the COMPARE_DIFF* constants
+# to indicate the type of difference.
+#
+# $1 - first node
+# $2 - second node
+compare()
+{
+	local first second
+
+	# If the first node doesn't exist, then check for the second
+	# node.  Note that -e will fail for a symbolic link that
+	# points to a missing target.
+	if ! exists $1; then
+		if exists $2; then
+			return $COMPARE_ONLYSECOND
+		else
+			return $COMPARE_EQUAL
+		fi
+	elif ! exists $2; then
+		return $COMPARE_ONLYFIRST
+	fi
+
+	# If the two nodes are different file types fail.
+	first=`stat -f "%Hp" $1`
+	second=`stat -f "%Hp" $2`
+	if [ "$first" != "$second" ]; then
+		return $COMPARE_DIFFTYPE
+	fi
+
+	# If both are symlinks, compare the link values.
+	if [ -L $1 ]; then
+		first=`readlink $1`
+		second=`readlink $2`
+		if [ "$first" = "$second" ]; then
+			return $COMPARE_EQUAL
+		else
+			return $COMPARE_DIFFLINKS
+		fi
+	fi
+
+	# If both are files, compare the file contents.
+	if [ -f $1 ]; then
+		if cmp -s $1 $2; then
+			return $COMPARE_EQUAL
+		else
+			return $COMPARE_DIFFFILES
+		fi
+	fi
+
+	# As long as the two nodes are the same type of file, consider
+	# them equivalent.
+	return $COMPARE_EQUAL
+}
+
+# Returns true (0) if the only difference between two regular files is a
+# change in the FreeBSD ID string.
+#
+# $1 - path of first file
+# $2 - path of second file
+fbsdid_only()
+{
+
+	diff -qI '\$FreeBSD.*\$' $1 $2 >/dev/null 2>&1
+}
+
+# This is a wrapper around compare that will return COMPARE_EQUAL if
+# the only difference between two regular files is a change in the
+# FreeBSD ID string.  It only makes this adjustment if the -F flag has
+# been specified.
+#
+# $1 - first node
+# $2 - second node
+compare_fbsdid()
+{
+	local cmp
+
+	compare $1 $2
+	cmp=$?
+
+	if [ -n "$FREEBSD_ID" -a "$cmp" -eq $COMPARE_DIFFFILES ] && \
+	    fbsdid_only $1 $2; then
+		return $COMPARE_EQUAL
+	fi
+
+	return $cmp
+}
+
+# Returns true (0) if a directory is empty.
+#
+# $1 - pathname of the directory to check
+empty_dir()
+{
+	local contents
+
+	contents=`ls -A $1`
+	[ -z "$contents" ]
+}
+
+# Returns true (0) if one directories contents are a subset of the
+# other.  This will recurse to handle subdirectories and compares
+# individual files in the trees.  Its purpose is to quiet spurious
+# directory warnings for dryrun invocations.
+#
+# $1 - first directory (sub)
+# $2 - second directory (super)
+dir_subset()
+{
+	local contents file
+
+	if ! [ -d $1 -a -d $2 ]; then
+		return 1
+	fi
+
+	# Ignore files that are present in the second directory but not
+	# in the first.
+	contents=`ls -A $1`
+	for file in $contents; do
+		if ! compare $1/$file $2/$file; then
+			return 1
+		fi
+
+		if [ -d $1/$file ]; then
+			if ! dir_subset $1/$file $2/$file; then
+				return 1
+			fi
+		fi
+	done
+	return 0
+}
+
+# Returns true (0) if a directory in the destination tree is empty.
+# If this is a dryrun, then this returns true as long as the contents
+# of the directory are a subset of the contents in the old tree
+# (meaning that the directory would be empty in a non-dryrun when this
+# was invoked) to quiet spurious warnings.
+#
+# $1 - pathname of the directory to check relative to DESTDIR.
+empty_destdir()
+{
+
+	if [ -n "$dryrun" ]; then
+		dir_subset $DESTDIR/$1 $OLDTREE/$1
+		return
+	fi
+
+	empty_dir $DESTDIR/$1
+}
+
+# Output a diff of two directory entries with the same relative name
+# in different trees.  Note that as with compare(), this does not
+# recurse into subdirectories.  If the nodes are identical, nothing is
+# output.
+#
+# $1 - first tree
+# $2 - second tree
+# $3 - node name 
+# $4 - label for first tree
+# $5 - label for second tree
+diffnode()
+{
+	local first second file old new diffargs
+
+	if [ -n "$FREEBSD_ID" ]; then
+		diffargs="-I \\\$FreeBSD.*\\\$"
+	else
+		diffargs=""
+	fi
+
+	compare_fbsdid $1/$3 $2/$3
+	case $? in
+		$COMPARE_EQUAL)
+			;;
+		$COMPARE_ONLYFIRST)
+			echo
+			echo "Removed: $3"
+			echo
+			;;
+		$COMPARE_ONLYSECOND)
+			echo
+			echo "Added: $3"
+			echo
+			;;
+		$COMPARE_DIFFTYPE)
+			first=`file_type $1/$3`
+			second=`file_type $2/$3`
+			echo
+			echo "Node changed from a $first to a $second: $3"
+			echo
+			;;
+		$COMPARE_DIFFLINKS)
+			first=`readlink $1/$file`
+			second=`readlink $2/$file`
+			echo
+			echo "Link changed: $file"
+			rule "="
+			echo "-$first"
+			echo "+$second"
+			echo
+			;;
+		$COMPARE_DIFFFILES)
+			echo "Index: $3"
+			rule "="
+			diff -u $diffargs -L "$3 ($4)" $1/$3 -L "$3 ($5)" $2/$3
+			;;
+	esac
+}
+
+# Create missing parent directories of a node in a target tree
+# preserving the owner, group, and permissions from a specified
+# template tree.
+#
+# $1 - template tree
+# $2 - target tree
+# $3 - pathname of the node (relative to both trees)
+install_dirs()
+{
+	local args dir
+
+	dir=`dirname $3`
+
+	# Nothing to do if the parent directory exists.  This also
+	# catches the degenerate cases when the path is just a simple
+	# filename.
+	if [ -d ${2}$dir ]; then
+		return 0
+	fi
+
+	# If non-directory file exists with the desired directory
+	# name, then fail.
+	if exists ${2}$dir; then
+		# If this is a dryrun and we are installing the
+		# directory in the DESTDIR and the file in the DESTDIR
+		# matches the file in the old tree, then fake success
+		# to quiet spurious warnings.
+		if [ -n "$dryrun" -a "$2" = "$DESTDIR" ]; then
+			if compare $OLDTREE/$dir $DESTDIR/$dir; then
+				return 0
+			fi
+		fi
+
+		args=`file_type ${2}$dir`
+		warn "Directory mismatch: ${2}$dir ($args)"
+		return 1
+	fi
+
+	# Ensure the parent directory of the directory is present
+	# first.
+	if ! install_dirs $1 "$2" $dir; then
+		return 1
+	fi
+
+	# Format attributes from template directory as install(1)
+	# arguments.
+	args=`stat -f "-o %Su -g %Sg -m %0Mp%0Lp" $1/$dir`
+
+	log "install -d $args ${2}$dir"
+	if [ -z "$dryrun" ]; then
+		install -d $args ${2}$dir >&3 2>&1
+	fi
+	return 0
+}
+
+# Perform post-install fixups for a file.  This largely consists of
+# regenerating any files that depend on the newly installed file.
+#
+# $1 - pathname of the updated file (relative to DESTDIR)
+post_install_file()
+{
+	case $1 in
+		/etc/mail/aliases)
+			# Grr, newaliases only works for an empty DESTDIR.
+			if [ -z "$DESTDIR" ]; then
+				log "newaliases"
+				if [ -z "$dryrun" ]; then
+					newaliases >&3 2>&1
+				fi
+			else
+				NEWALIAS_WARN=yes
+			fi
+			;;
+		/etc/login.conf)
+			log "cap_mkdb ${DESTDIR}$1"
+			if [ -z "$dryrun" ]; then
+				cap_mkdb ${DESTDIR}$1 >&3 2>&1
+			fi
+			;;
+		/etc/master.passwd)
+			log "pwd_mkdb -p -d $DESTDIR/etc ${DESTDIR}$1"
+			if [ -z "$dryrun" ]; then
+				pwd_mkdb -p -d $DESTDIR/etc ${DESTDIR}$1 \
+				    >&3 2>&1
+			fi
+			;;
+		/etc/motd)
+			# /etc/rc.d/motd hardcodes the /etc/motd path.
+			# Don't warn about non-empty DESTDIR's since this
+			# change is only cosmetic anyway.
+			if [ -z "$DESTDIR" ]; then
+				log "sh /etc/rc.d/motd start"
+				if [ -z "$dryrun" ]; then
+					sh /etc/rc.d/motd start >&3 2>&1
+				fi
+			fi
+			;;
+	esac
+}
+
+# Install the "new" version of a file.  Returns true if it succeeds
+# and false otherwise.
+#
+# $1 - pathname of the file to install (relative to DESTDIR)
+install_new()
+{
+
+	if ! install_dirs $NEWTREE "$DESTDIR" $1; then
+		return 1
+	fi
+	log "cp -Rp ${NEWTREE}$1 ${DESTDIR}$1"
+	if [ -z "$dryrun" ]; then
+		cp -Rp ${NEWTREE}$1 ${DESTDIR}$1 >&3 2>&1
+	fi
+	post_install_file $1
+	return 0
+}
+
+# Install the "resolved" version of a file.  Returns true if it succeeds
+# and false otherwise.
+#
+# $1 - pathname of the file to install (relative to DESTDIR)
+install_resolved()
+{
+
+	# This should always be present since the file is already
+	# there (it caused a conflict).  However, it doesn't hurt to
+	# just be safe.
+	if ! install_dirs $NEWTREE "$DESTDIR" $1; then
+		return 1
+	fi
+
+	log "cp -Rp ${CONFLICTS}$1 ${DESTDIR}$1"
+	cp -Rp ${CONFLICTS}$1 ${DESTDIR}$1 >&3 2>&1
+	post_install_file $1
+	return 0
+}
+
+# Generate a conflict file when a "new" file conflicts with an
+# existing file in DESTDIR.
+#
+# $1 - pathname of the file that conflicts (relative to DESTDIR)
+new_conflict()
+{
+
+	if [ -n "$dryrun" ]; then
+		return
+	fi
+
+	install_dirs $NEWTREE $CONFLICTS $1
+	diff --changed-group-format='<<<<<<< (local)
+%<=======
+%>>>>>>>> (stock)
+' $DESTDIR/$1 $NEWTREE/$1 > $CONFLICTS/$1
+}
+
+# Remove the "old" version of a file.
+#
+# $1 - pathname of the old file to remove (relative to DESTDIR)
+remove_old()
+{
+	log "rm -f ${DESTDIR}$1"
+	if [ -z "$dryrun" ]; then
+		rm -f ${DESTDIR}$1 >&3 2>&1
+	fi
+	echo "  D $1"
+}
+
+# Update a file that has no local modifications.
+#
+# $1 - pathname of the file to update (relative to DESTDIR)
+update_unmodified()
+{
+	local new old
+
+	# If the old file is a directory, then remove it with rmdir
+	# (this should only happen if the file has changed its type
+	# from a directory to a non-directory).  If the directory
+	# isn't empty, then fail.  This will be reported as a warning
+	# later.
+	if [ -d $DESTDIR/$1 ]; then
+		if empty_destdir $1; then
+			log "rmdir ${DESTDIR}$1"
+			if [ -z "$dryrun" ]; then
+				rmdir ${DESTDIR}$1 >&3 2>&1
+			fi
+		else
+			return 1
+		fi
+
+	# If both the old and new files are regular files, leave the
+	# existing file.  This avoids breaking hard links for /.cshrc
+	# and /.profile.  Otherwise, explicitly remove the old file.
+	elif ! [ -f ${DESTDIR}$1 -a -f ${NEWTREE}$1 ]; then
+		log "rm -f ${DESTDIR}$1"
+		if [ -z "$dryrun" ]; then
+			rm -f ${DESTDIR}$1 >&3 2>&1
+		fi
+	fi
+
+	# If the new file is a directory, note that the old file has
+	# been removed, but don't do anything else for now.  The
+	# directory will be installed if needed when new files within
+	# that directory are installed.
+	if [ -d $NEWTREE/$1 ]; then
+		if empty_dir $NEWTREE/$1; then
+			echo "  D $file"
+		else
+			echo "  U $file"
+		fi
+	elif install_new $1; then
+		echo "  U $file"
+	fi
+	return 0
+}
+
+# Update the FreeBSD ID string in a locally modified file to match the
+# FreeBSD ID string from the "new" version of the file.
+#
+# $1 - pathname of the file to update (relative to DESTDIR)
+update_freebsdid()
+{
+	local new dest file
+
+	# If the FreeBSD ID string is removed from the local file,
+	# there is nothing to do.  In this case, treat the file as
+	# updated.  Otherwise, if either file has more than one
+	# FreeBSD ID string, just punt and let the user handle the
+	# conflict manually.
+	new=`grep -c '\$FreeBSD.*\$' ${NEWTREE}$1`
+	dest=`grep -c '\$FreeBSD.*\$' ${DESTDIR}$1`
+	if [ "$dest" -eq 0 ]; then
+		return 0
+	fi
+	if [ "$dest" -ne 1 -o "$dest" -ne 1 ]; then
+		return 1
+	fi
+
+	# If the FreeBSD ID string in the new file matches the FreeBSD ID
+	# string in the local file, there is nothing to do.
+	new=`grep '\$FreeBSD.*\$' ${NEWTREE}$1`
+	dest=`grep '\$FreeBSD.*\$' ${DESTDIR}$1`
+	if [ "$new" = "$dest" ]; then
+		return 0
+	fi
+
+	# Build the new file in three passes.  First, copy all the
+	# lines preceding the FreeBSD ID string from the local version
+	# of the file.  Second, append the FreeBSD ID string line from
+	# the new version.  Finally, append all the lines after the
+	# FreeBSD ID string from the local version of the file.
+	file=`mktemp $WORKDIR/etcupdate-XXXXXXX`
+	awk '/\$FreeBSD.*\$/ { exit } { print }' ${DESTDIR}$1 >> $file
+	awk '/\$FreeBSD.*\$/ { print }' ${NEWTREE}$1 >> $file
+	awk '/\$FreeBSD.*\$/ { ok = 1; next } { if (ok) print }' \
+	    ${DESTDIR}$1 >> $file
+
+	# As an extra sanity check, fail the attempt if the updated
+	# version of the file has any differences aside from the
+	# FreeBSD ID string.
+	if ! fbsdid_only ${DESTDIR}$1 $file; then
+		rm -f $file
+		return 1
+	fi
+
+	log "cp $file ${DESTDIR}$1"
+	if [ -z "$dryrun" ]; then
+		cp $file ${DESTDIR}$1 >&3 2>&1
+	fi
+	rm -f $file
+	post_install_file $1
+	echo "  M $1"
+	return 0
+}
+
+# Attempt to update a file that has local modifications.  This routine
+# only handles regular files.  If the 3-way merge succeeds without
+# conflicts, the updated file is installed.  If the merge fails, the
+# merged version with conflict markers is left in the CONFLICTS tree.
+#
+# $1 - pathname of the file to merge (relative to DESTDIR)
+merge_file()
+{
+	local res
+
+	# Try the merge to see if there is a conflict.
+	merge -q -p ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1 >/dev/null 2>&3
+	res=$?
+	case $res in
+		0)
+			# No conflicts, so just redo the merge to the
+			# real file.
+			log "merge ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1"
+			if [ -z "$dryrun" ]; then
+				merge ${DESTDIR}$1 ${OLDTREE}$1 ${NEWTREE}$1
+			fi
+			post_install_file $1
+			echo "  M $1"
+			;;
+		1)
+			# Conflicts, save a version with conflict markers in
+			# the conflicts directory.
+			if [ -z "$dryrun" ]; then
+				install_dirs $NEWTREE $CONFLICTS $1
+				log "cp -Rp ${DESTDIR}$1 ${CONFLICTS}$1"
+				cp -Rp ${DESTDIR}$1 ${CONFLICTS}$1 >&3 2>&1
+				merge -A -q -L "yours" -L "original" -L "new" \
+				    ${CONFLICTS}$1 ${OLDTREE}$1 ${NEWTREE}$1
+			fi
+			echo "  C $1"
+			;;
+		*)
+			panic "merge failed with status $res"
+			;;
+	esac
+}
+
+# Returns true if a file contains conflict markers from a merge conflict.
+#
+# $1 - pathname of the file to resolve (relative to DESTDIR)
+has_conflicts()
+{
+	
+	egrep -q '^(<{7}|\|{7}|={7}|>{7}) ' $CONFLICTS/$1
+}
+
+# Attempt to resolve a conflict.  The user is prompted to choose an
+# action for each conflict.  If the user edits the file, they are
+# prompted again for an action.  The process is very similar to
+# resolving conflicts after an update or merge with Perforce or
+# Subversion.  The prompts are modelled on a subset of the available
+# commands for resolving conflicts with Subversion.
+#
+# $1 - pathname of the file to resolve (relative to DESTDIR)
+resolve_conflict()
+{
+	local command junk
+
+	echo "Resolving conflict in '$1':"
+	edit=
+	while true; do
+		# Only display the resolved command if the file
+		# doesn't contain any conflicts.
+		echo -n "Select: (p) postpone, (df) diff-full, (e) edit,"
+		if ! has_conflicts $1; then
+			echo -n " (r) resolved,"
+		fi
+		echo
+		echo -n "        (h) help for more options: "
+		read command
+		case $command in
+			df)
+				diff -u ${DESTDIR}$1 ${CONFLICTS}$1
+				;;
+			e)
+				$EDITOR ${CONFLICTS}$1
+				;;
+			h)
+				cat <<EOF
+  (p)  postpone    - ignore this conflict for now
+  (df) diff-full   - show all changes made to merged file
+  (e)  edit        - change merged file in an editor
+  (r)  resolved    - accept merged version of file
+  (mf) mine-full   - accept local version of entire file (ignore new changes)
+  (tf) theirs-full - accept new version of entire file (lose local changes)
+  (h)  help        - show this list
+EOF
+				;;
+			mf)
+				# For mine-full, just delete the
+				# merged file and leave the local
+				# version of the file as-is.
+				rm ${CONFLICTS}$1
+				return
+				;;
+			p)
+				return
+				;;
+			r)
+				# If the merged file has conflict
+				# markers, require confirmation.
+				if has_conflicts $1; then
+					echo "File '$1' still has conflicts," \
+					    "are you sure? (y/n) "
+					read junk
+					if [ "$junk" != "y" ]; then
+						continue
+					fi
+				fi
+
+				if ! install_resolved $1; then
+					panic "Unable to install merged" \
+					    "version of $1"
+				fi
+				rm ${CONFLICTS}$1
+				return
+				;;
+			tf)
+				# For theirs-full, install the new
+				# version of the file over top of the
+				# existing file.
+				if ! install_new $1; then
+					panic "Unable to install new" \
+					    "version of $1"
+				fi
+				rm ${CONFLICTS}$1
+				return
+				;;
+			*)
+				echo "Invalid command."
+				;;
+		esac
+	done
+}
+
+# Handle a file that has been removed from the new tree.  If the file
+# does not exist in DESTDIR, then there is nothing to do.  If the file
+# exists in DESTDIR and is identical to the old version, remove it
+# from DESTDIR.  Otherwise, whine about the conflict but leave the
+# file in DESTDIR.  To handle directories, this uses two passes.  The
+# first pass handles all non-directory files.  The second pass handles
+# just directories and removes them if they are empty.
+#
+# If -F is specified, and the only difference in the file in DESTDIR
+# is a change in the FreeBSD ID string, then remove the file.
+#
+# $1 - pathname of the file (relative to DESTDIR)
+handle_removed_file()
+{
+	local dest file
+
+	file=$1
+	if ignore $file; then
+		log "IGNORE: removed file $file"
+		return
+	fi
+
+	compare_fbsdid $DESTDIR/$file $OLDTREE/$file
+	case $? in
+		$COMPARE_EQUAL)
+			if ! [ -d $DESTDIR/$file ]; then
+				remove_old $file
+			fi
+			;;
+		$COMPARE_ONLYFIRST)
+			panic "Removed file now missing"
+			;;
+		$COMPARE_ONLYSECOND)
+			# Already removed, nothing to do.
+			;;
+		$COMPARE_DIFFTYPE|$COMPARE_DIFFLINKS|$COMPARE_DIFFFILES)
+			dest=`file_type $DESTDIR/$file`
+			warn "Modified $dest remains: $file"
+			;;
+	esac
+}
+
+# Handle a directory that has been removed from the new tree.  Only
+# remove the directory if it is empty.
+#
+# $1 - pathname of the directory (relative to DESTDIR)
+handle_removed_directory()
+{
+	local dir
+
+	dir=$1
+	if ignore $dir; then
+		log "IGNORE: removed dir $dir"
+		return
+	fi
+
+	if [ -d $DESTDIR/$dir -a -d $OLDTREE/$dir ]; then
+		if empty_destdir $dir; then
+			log "rmdir ${DESTDIR}$dir"
+			if [ -z "$dryrun" ]; then
+				rmdir ${DESTDIR}$dir >/dev/null 2>&1
+			fi
+			echo "  D $dir"
+		else
+			warn "Non-empty directory remains: $dir"
+		fi
+	fi
+}
+
+# Handle a file that exists in both the old and new trees.  If the
+# file has not changed in the old and new trees, there is nothing to
+# do.  If the file in the destination directory matches the new file,
+# there is nothing to do.  If the file in the destination directory
+# matches the old file, then the new file should be installed.
+# Everything else becomes some sort of conflict with more detailed
+# handling.
+#
+# $1 - pathname of the file (relative to DESTDIR)
+handle_modified_file()
+{
+	local cmp dest file new newdestcmp old
+
+	file=$1
+	if ignore $file; then
+		log "IGNORE: modified file $file"
+		return
+	fi
+
+	compare $OLDTREE/$file $NEWTREE/$file
+	cmp=$?
+	if [ $cmp -eq $COMPARE_EQUAL ]; then
+		return
+	fi
+
+	if [ $cmp -eq $COMPARE_ONLYFIRST -o $cmp -eq $COMPARE_ONLYSECOND ]; then
+		panic "Changed file now missing"
+	fi
+
+	compare $NEWTREE/$file $DESTDIR/$file
+	newdestcmp=$?
+	if [ $newdestcmp -eq $COMPARE_EQUAL ]; then
+		return
+	fi
+
+	# If the only change in the new file versus the destination
+	# file is a change in the FreeBSD ID string and -F is
+	# specified, just install the new file.
+	if [ -n "$FREEBSD_ID" -a $newdestcmp -eq $COMPARE_DIFFFILES ] && \
+	    fbsdid_only $NEWTREE/$file $DESTDIR/$file; then
+		if update_unmodified $file; then
+			return
+		else
+			panic "Updating FreeBSD ID string failed"
+		fi
+	fi
+
+	# If the local file is the same as the old file, install the
+	# new file.  If -F is specified and the only local change is
+	# in the FreeBSD ID string, then install the new file as well.
+	if compare_fbsdid $OLDTREE/$file $DESTDIR/$file; then
+		if update_unmodified $file; then
+			return
+		fi
+	fi
+
+	# If the only change in the new file versus the old file is a
+	# change in the FreeBSD ID string and -F is specified, just
+	# update the FreeBSD ID string in the local file.
+	if [ -n "$FREEBSD_ID" -a $cmp -eq $COMPARE_DIFFFILES ] && \
+	    fbsdid_only $OLDTREE/$file $NEWTREE/$file; then
+		if update_freebsdid $file; then
+			continue
+		fi
+	fi
+
+	# If the file was removed from the dest tree, just whine.
+	if [ $newdestcmp -eq $COMPARE_ONLYFIRST ]; then
+		# If the removed file matches an ALWAYS_INSTALL glob,
+		# then just install the new version of the file.
+		if always_install $file; then
+			log "ALWAYS: adding $file"
+			if ! [ -d $NEWTREE/$file ]; then
+				if install_new $file; then
+					echo "  A $file"
+				fi
+			fi
+			return
+		fi
+
+		case $cmp in
+			$COMPARE_DIFFTYPE)
+				old=`file_type $OLDTREE/$file`
+				new=`file_type $NEWTREE/$file`
+				warn "Remove mismatch: $file ($old became $new)"
+				;;
+			$COMPARE_DIFFLINKS)
+				old=`readlink $OLDTREE/$file`
+				new=`readlink $NEWTREE/$file`
+				warn \
+		"Removed link changed: $file (\"$old\" became \"$new\")"
+				;;
+			$COMPARE_DIFFFILES)
+				warn "Removed file changed: $file"
+				;;
+		esac
+		return
+	fi
+
+	# Treat the file as unmodified and force install of the new
+	# file if it matches an ALWAYS_INSTALL glob.  If the update
+	# attempt fails, then fall through to the normal case so a
+	# warning is generated.
+	if always_install $file; then
+		log "ALWAYS: updating $file"
+		if update_unmodified $file; then
+			return
+		fi
+	fi
+
+	# If the file changed types between the old and new trees but
+	# the files in the new and dest tree are both of the same
+	# type, treat it like an added file just comparing the new and
+	# dest files.
+	if [ $cmp -eq $COMPARE_DIFFTYPE ]; then
+		case $newdestcmp in
+			$COMPARE_DIFFLINKS)
+				new=`readlink $NEWTREE/$file`
+				dest=`readlink $DESTDIR/$file`
+				warn \
+			"New link conflict: $file (\"$new\" vs \"$dest\")"
+				return
+				;;
+			$COMPARE_DIFFFILES)
+				new_conflict $file
+				echo "  C $file"
+				return
+				;;
+		esac
+	else
+		# If the file has not changed types between the old
+		# and new trees, but it is a different type in
+		# DESTDIR, then just warn.
+		if [ $newdestcmp -eq $COMPARE_DIFFTYPE ]; then
+			new=`file_type $NEWTREE/$file`
+			dest=`file_type $DESTDIR/$file`
+			warn "Modified mismatch: $file ($new vs $dest)"
+			return
+		fi
+	fi
+
+	case $cmp in
+		$COMPARE_DIFFTYPE)
+			old=`file_type $OLDTREE/$file`
+			new=`file_type $NEWTREE/$file`
+			dest=`file_type $DESTDIR/$file`
+			warn "Modified $dest changed: $file ($old became $new)"
+			;;
+		$COMPARE_DIFFLINKS)
+			old=`readlink $OLDTREE/$file`
+			new=`readlink $NEWTREE/$file`
+			warn \
+		"Modified link changed: $file (\"$old\" became \"$new\")"
+			;;
+		$COMPARE_DIFFFILES)
+			merge_file $file
+			;;
+	esac
+}
+
+# Handle a file that has been added in the new tree.  If the file does
+# not exist in DESTDIR, simply copy the file into DESTDIR.  If the
+# file exists in the DESTDIR and is identical to the new version, do
+# nothing.  Otherwise, generate a diff of the two versions of the file
+# and mark it as a conflict.
+#
+# $1 - pathname of the file (relative to DESTDIR)
+handle_added_file()
+{
+	local cmp dest file new
+
+	file=$1
+	if ignore $file; then
+		log "IGNORE: added file $file"
+		return
+	fi
+
+	compare $DESTDIR/$file $NEWTREE/$file
+	cmp=$?
+	case $cmp in
+		$COMPARE_EQUAL)
+			return
+			;;
+		$COMPARE_ONLYFIRST)
+			panic "Added file now missing"
+			;;
+		$COMPARE_ONLYSECOND)
+			# Ignore new directories.  They will be
+			# created as needed when non-directory nodes
+			# are installed.
+			if ! [ -d $NEWTREE/$file ]; then
+				if install_new $file; then
+					echo "  A $file"
+				fi
+			fi
+			return
+			;;
+	esac
+
+
+	# Treat the file as unmodified and force install of the new
+	# file if it matches an ALWAYS_INSTALL glob.  If the update
+	# attempt fails, then fall through to the normal case so a
+	# warning is generated.
+	if always_install $file; then
+		log "ALWAYS: updating $file"
+		if update_unmodified $file; then
+			return
+		fi
+	fi
+
+	case $cmp in
+		$COMPARE_DIFFTYPE)
+			new=`file_type $NEWTREE/$file`
+			dest=`file_type $DESTDIR/$file`
+			warn "New file mismatch: $file ($new vs $dest)"
+			;;
+		$COMPARE_DIFFLINKS)
+			new=`readlink $NEWTREE/$file`
+			dest=`readlink $DESTDIR/$file`
+			warn "New link conflict: $file (\"$new\" vs \"$dest\")"
+			;;
+		$COMPARE_DIFFFILES)
+			# If the only change in the new file versus
+			# the destination file is a change in the
+			# FreeBSD ID string and -F is specified, just
+			# install the new file.
+			if [ -n "$FREEBSD_ID" ] && \
+			    fbsdid_only $NEWTREE/$file $DESTDIR/$file; then
+				if update_unmodified $file; then
+					return
+				else
+					panic \
+					"Updating FreeBSD ID string failed"
+				fi
+			fi
+
+			new_conflict $file
+			echo "  C $file"
+			;;
+	esac
+}
+
+# Main routines for each command
+
+# Build a new tree and save it in a tarball.
+build_cmd()
+{
+	local dir
+
+	if [ $# -ne 1 ]; then
+		echo "Missing required tarball."
+		echo
+		usage
+	fi
+
+	log "build command: $1"
+
+	# Create a temporary directory to hold the tree
+	dir=`mktemp -d $WORKDIR/etcupdate-XXXXXXX`
+	if [ $? -ne 0 ]; then
+		echo "Unable to create temporary directory."
+		exit 1
+	fi
+	if ! build_tree $dir; then
+		echo "Failed to build tree."
+		remove_tree $dir
+		exit 1
+	fi
+	if ! tar cfj $1 -C $dir . >&3 2>&1; then
+		echo "Failed to create tarball."
+		remove_tree $dir
+		exit 1
+	fi
+	remove_tree $dir
+}
+
+# Output a diff comparing the tree at DESTDIR to the current
+# unmodified tree.  Note that this diff does not include files that
+# are present in DESTDIR but not in the unmodified tree.
+diff_cmd()
+{
+	local file
+
+	if [ $# -ne 0 ]; then
+		usage
+	fi
+
+	# Requires an unmodified tree to diff against.
+	if ! [ -d $NEWTREE ]; then
+		echo "Reference tree to diff against unavailable."
+		exit 1
+	fi
+
+	# Unfortunately, diff alone does not quite provide the right
+	# level of options that we want, so improvise.
+	for file in `(cd $NEWTREE; find .) | sed -e 's/^\.//'`; do
+		if ignore $file; then
+			continue
+		fi
+
+		diffnode $NEWTREE "$DESTDIR" $file "stock" "local"
+	done
+}
+
+# Just extract a new tree into NEWTREE either by building a tree or
+# extracting a tarball.  This can be used to bootstrap updates by
+# initializing the current "stock" tree to match the currently
+# installed system.
+#
+# Unlike 'update', this command does not rotate or preserve an
+# existing NEWTREE, it just replaces any existing tree.
+extract_cmd()
+{
+
+	if [ $# -ne 0 ]; then
+		usage
+	fi
+
+	log "extract command: tarball=$tarball"
+
+	if [ -d $NEWTREE ]; then
+		if ! remove_tree $NEWTREE; then
+			echo "Unable to remove current tree."
+			exit 1
+		fi
+	fi
+
+	extract_tree
+}
+
+# Resolve conflicts left from an earlier merge.
+resolve_cmd()
+{
+	local conflicts
+
+	if [ $# -ne 0 ]; then
+		usage
+	fi
+
+	if ! [ -d $CONFLICTS ]; then
+		return
+	fi
+
+	conflicts=`(cd $CONFLICTS; find . ! -type d) | sed -e 's/^\.//'`
+	for file in $conflicts; do
+		resolve_conflict $file
+	done
+
+	if [ -n "$NEWALIAS_WARN" ]; then
+		warn "Needs update: /etc/mail/aliases.db" \
+		    "(requires manual update via newaliases(1))"
+		echo
+		echo "Warnings:"
+		echo "  Needs update: /etc/mail/aliases.db" \
+		    "(requires manual update via newaliases(1))"
+	fi
+}
+
+# Report a summary of the previous merge.  Specifically, list any
+# remaining conflicts followed by any warnings from the previous
+# update.
+status_cmd()
+{
+
+	if [ $# -ne 0 ]; then
+		usage
+	fi
+
+	if [ -d $CONFLICTS ]; then
+		(cd $CONFLICTS; find . ! -type d) | sed -e 's/^\./  C /'
+	fi
+	if [ -s $WARNINGS ]; then
+		echo "Warnings:"
+		cat $WARNINGS
+	fi
+}
+
+# Perform an actual merge.  The new tree can either already exist (if
+# rerunning a merge), be extracted from a tarball, or generated from a
+# source tree.
+update_cmd()
+{
+	local dir
+
+	if [ $# -ne 0 ]; then
+		usage
+	fi
+
+	log "update command: rerun=$rerun tarball=$tarball"
+
+	if [ `id -u` -ne 0 ]; then
+		echo "Must be root to update a tree."
+		exit 1
+	fi
+
+	# Enforce a sane umask
+	umask 022
+
+	# XXX: Should existing conflicts be ignored and removed during
+	# a rerun?
+
+	# Trim the conflicts tree.  Whine if there is anything left.
+	if [ -e $CONFLICTS ]; then
+		find -d $CONFLICTS -type d -empty -delete >&3 2>&1
+		rmdir $CONFLICTS >&3 2>&1
+	fi
+	if [ -d $CONFLICTS ]; then
+		echo "Conflicts remain from previous update, aborting."
+		exit 1
+	fi
+
+	if [ -z "$rerun" ]; then
+		# For a dryrun that is not a rerun, do not rotate the existing
+		# stock tree.  Instead, extract a tree to a temporary directory
+		# and use that for the comparison.
+		if [ -n "$dryrun" ]; then
+			dir=`mktemp -d $WORKDIR/etcupdate-XXXXXXX`
+			if [ $? -ne 0 ]; then
+				echo "Unable to create temporary directory."
+				exit 1
+			fi
+			OLDTREE=$NEWTREE
+			NEWTREE=$dir
+
+		# Rotate the existing stock tree to the old tree.
+		elif [ -d $NEWTREE ]; then
+			# First, delete the previous old tree if it exists.
+			if ! remove_tree $OLDTREE; then
+				echo "Unable to remove old tree."
+				exit 1
+			fi
+
+			# Move the current stock tree.
+			if ! mv $NEWTREE $OLDTREE >&3 2>&1; then
+				echo "Unable to rename current stock tree."
+				exit 1
+			fi
+		fi
+
+		if ! [ -d $OLDTREE ]; then
+			cat <<EOF
+No previous tree to compare against, a sane comparison is not possible.
+EOF
+			log "No previous tree to compare against."
+			if [ -n "$dir" ]; then
+				rmdir $dir
+			fi
+			exit 1
+		fi
+
+		# Populate the new tree.
+		extract_tree
+	fi
+
+	# Build lists of nodes in the old and new trees.
+	(cd $OLDTREE; find .) | sed -e 's/^\.//' | sort > $WORKDIR/old.files
+	(cd $NEWTREE; find .) | sed -e 's/^\.//' | sort > $WORKDIR/new.files
+
+	# Split the files up into three groups using comm.
+	comm -23 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/removed.files
+	comm -13 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/added.files
+	comm -12 $WORKDIR/old.files $WORKDIR/new.files > $WORKDIR/both.files
+
+	# Initialize conflicts and warnings handling.
+	rm -f $WARNINGS
+	mkdir -p $CONFLICTS
+	
+	# The order for the following sections is important.  In the
+	# odd case that a directory is converted into a file, the
+	# existing subfiles need to be removed if possible before the
+	# file is converted.  Similarly, in the case that a file is
+	# converted into a directory, the file needs to be converted
+	# into a directory if possible before the new files are added.
+
+	# First, handle removed files.
+	for file in `cat $WORKDIR/removed.files`; do
+		handle_removed_file $file
+	done
+
+	# For the directory pass, reverse sort the list to effect a
+	# depth-first traversal.  This is needed to ensure that if a
+	# directory with subdirectories is removed, the entire
+	# directory is removed if there are no local modifications.
+	for file in `sort -r $WORKDIR/removed.files`; do
+		handle_removed_directory $file
+	done
+
+	# Second, handle files that exist in both the old and new
+	# trees.
+	for file in `cat $WORKDIR/both.files`; do
+		handle_modified_file $file
+	done
+
+	# Finally, handle newly added files.
+	for file in `cat $WORKDIR/added.files`; do
+		handle_added_file $file
+	done
+
+	if [ -n "$NEWALIAS_WARN" ]; then
+		warn "Needs update: /etc/mail/aliases.db" \
+		    "(requires manual update via newaliases(1))"
+	fi
+
+	if [ -s $WARNINGS ]; then
+		echo "Warnings:"
+		cat $WARNINGS
+	fi
+
+	if [ -n "$dir" ]; then
+		if [ -z "$dryrun" -o -n "$rerun" ]; then
+			panic "Should not have a temporary directory"
+		fi
+		
+		remove_tree $dir
+	fi
+}
+
+# Determine which command we are executing.  A command may be
+# specified as the first word.  If one is not specified then 'update'
+# is assumed as the default command.
+command="update"
+if [ $# -gt 0 ]; then
+	case "$1" in
+		build|diff|extract|status|resolve)
+			command="$1"
+			shift
+			;;
+		-*)
+			# If first arg is an option, assume the
+			# default command.
+			;;
+		*)
+			usage
+			;;
+	esac
+fi
+
+# Set default variable values.
+
+# The path to the source tree used to build trees.
+SRCDIR=/usr/src
+
+# The destination directory where the modified files live.
+DESTDIR=
+
+# Ignore changes in the FreeBSD ID string.
+FREEBSD_ID=
+
+# Files that should always have the new version of the file installed.
+ALWAYS_INSTALL=
+
+# Files to ignore and never update during a merge.
+IGNORE_FILES=
+
+# Flags to pass to 'make' when building a tree.
+MAKE_OPTIONS=
+
+# Include a config file if it exists.  Note that command line options
+# override any settings in the config file.  More details are in the
+# manual, but in general the following variables can be set:
+# - ALWAYS_INSTALL
+# - DESTDIR
+# - EDITOR
+# - FREEBSD_ID
+# - IGNORE_FILES
+# - LOGFILE
+# - MAKE_OPTIONS
+# - SRCDIR
+# - WORKDIR
+if [ -r /etc/etcupdate.conf ]; then
+	. /etc/etcupdate.conf
+fi
+
+# Parse command line options
+tarball=
+rerun=
+always=
+dryrun=
+ignore=
+nobuild=
+while getopts "d:nrs:t:A:BD:FI:L:M:" option; do
+	case "$option" in
+		d)
+			WORKDIR=$OPTARG
+			;;
+		n)
+			dryrun=YES
+			;;
+		r)
+			rerun=YES
+			;;
+		s)
+			SRCDIR=$OPTARG
+			;;
+		t)
+			tarball=$OPTARG
+			;;
+		A)
+			# To allow this option to be specified
+			# multiple times, accumulate command-line
+			# specified patterns in an 'always' variable
+			# and use that to overwrite ALWAYS_INSTALL
+			# after parsing all options.  Need to be
+			# careful here with globbing expansion.
+			set -o noglob
+			always="$always $OPTARG"
+			set +o noglob
+			;;
+		B)
+			nobuild=YES
+			;;
+		D)
+			DESTDIR=$OPTARG
+			;;
+		F)
+			FREEBSD_ID=YES
+			;;
+		I)
+			# To allow this option to be specified
+			# multiple times, accumulate command-line
+			# specified patterns in an 'ignore' variable
+			# and use that to overwrite IGNORE_FILES after
+			# parsing all options.  Need to be careful
+			# here with globbing expansion.
+			set -o noglob
+			ignore="$ignore $OPTARG"
+			set +o noglob
+			;;
+		L)
+			LOGFILE=$OPTARG
+			;;
+		M)
+			MAKE_OPTIONS="$OPTARG"
+			;;
+		*)
+			echo
+			usage
+			;;
+	esac
+done
+shift $((OPTIND - 1))
+
+# Allow -A command line options to override ALWAYS_INSTALL set from
+# the config file.
+set -o noglob
+if [ -n "$always" ]; then
+	ALWAYS_INSTALL="$always"
+fi
+
+# Allow -I command line options to override IGNORE_FILES set from the
+# config file.
+if [ -n "$ignore" ]; then
+	IGNORE_FILES="$ignore"
+fi
+set +o noglob
+
+# Where the "old" and "new" trees are stored.
+WORKDIR=${WORKDIR:-$DESTDIR/var/db/etcupdate}
+
+# Log file for verbose output from program that are run.  The log file
+# is opened on fd '3'.
+LOGFILE=${LOGFILE:-$WORKDIR/log}
+
+# The path of the "old" tree
+OLDTREE=$WORKDIR/old
+
+# The path of the "new" tree
+NEWTREE=$WORKDIR/current
+
+# The path of the "conflicts" tree where files with merge conflicts are saved.
+CONFLICTS=$WORKDIR/conflicts
+
+# The path of the "warnings" file that accumulates warning notes from an update.
+WARNINGS=$WORKDIR/warnings
+
+# Use $EDITOR for resolving conflicts.  If it is not set, default to vi.
+EDITOR=${EDITOR:-/usr/bin/vi}
+
+# Handle command-specific argument processing such as complaining
+# about unsupported options.  Since the configuration file is always
+# included, do not complain about extra command line arguments that
+# may have been set via the config file rather than the command line.
+case $command in
+	update)
+		if [ -n "$rerun" -a -n "$tarball" ]; then
+			echo "Only one of -r or -t can be specified."
+			echo
+			usage
+		fi
+		;;
+	build|diff|resolve|status)
+		if [ -n "$dryrun" -o -n "$rerun" -o -n "$tarball" ]; then
+			usage
+		fi
+		;;
+	extract)
+		if [ -n "$dryrun" -o -n "$rerun" ]; then
+			usage
+		fi
+		;;
+esac
+
+# Open the log file.  Don't truncate it if doing a minor operation so
+# that a minor operation doesn't lose log info from a major operation.
+if ! mkdir -p $WORKDIR 2>/dev/null; then
+	echo "Failed to create work directory $WORKDIR"
+fi
+
+case $command in
+	diff|resolve|status)
+		exec 3>>$LOGFILE
+		;;
+	*)
+		exec 3>$LOGFILE
+		;;
+esac
+
+${command}_cmd "$@"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/fifolog/lib/getdate.y
--- a/head/usr.sbin/fifolog/lib/getdate.y	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/fifolog/lib/getdate.y	Wed Jul 25 16:29:58 2012 +0300
@@ -12,7 +12,7 @@
 **  Picked up from CVS and slightly cleaned up by to WARNS=5 level by
 **  Poul-Henning Kamp <phk at FreeBSD.org>
 **
-** $FreeBSD$
+** $FreeBSD: head/usr.sbin/fifolog/lib/getdate.y 235789 2012-05-22 16:33:10Z bapt $
 */
 
 #include <stdio.h>
@@ -24,11 +24,9 @@
 
 #include "libfifolog.h"
 
-#define yyparse getdate_yyparse
 #define yylex getdate_yylex
 #define yyerror getdate_yyerror
 
-static int yyparse(void);
 static int yylex(void);
 static int yyerror(const char *);
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/flowctl/flowctl.8
--- a/head/usr.sbin/flowctl/flowctl.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/flowctl/flowctl.8	Wed Jul 25 16:29:58 2012 +0300
@@ -22,9 +22,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/flowctl/flowctl.8 223790 2011-07-05 14:55:17Z glebius $
+.\" $FreeBSD: head/usr.sbin/flowctl/flowctl.8 236808 2012-06-09 10:10:12Z melifaro $
 .\"
-.Dd July 5, 2011
+.Dd June 8, 2012
 .Dt FLOWCTL 8
 .Os
 .Sh NAME
@@ -55,12 +55,12 @@
 .Nm
 supports only one command.
 .Bl -tag -width ".Cm show"
-.It Cm show Op Cm ipv4|ipv6
+.It Cm show Oo Cm ipv4|ipv6 Oc Op Cm human|verbose
 This command is the analog of the
 .Dq "show ip cache flow"
 command of a Cisco router.
 It dumps the contents of the flow cache in Cisco-like format.
-Specifing either
+Specifying either
 .Cm ipv4
 or
 .Cm ipv6
@@ -69,7 +69,9 @@
 .Cm verbose ,
 which is analog of the
 .Dq "show ip cache verbose flow"
-command.
+command. Additionally,
+.Cm human
+parameter can be specify to show selected flows in human-readable format.
 .El
 .Sh EXIT STATUS
 .Ex -std
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/flowctl/flowctl.c
--- a/head/usr.sbin/flowctl/flowctl.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/flowctl/flowctl.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
 
 #ifndef lint
 static const char rcs_id[] =
-    "@(#) $FreeBSD: head/usr.sbin/flowctl/flowctl.c 223824 2011-07-06 15:18:32Z pluknet $";
+    "@(#) $FreeBSD: head/usr.sbin/flowctl/flowctl.c 236808 2012-06-09 10:10:12Z melifaro $";
 #endif
 
 #include <sys/types.h>
@@ -52,19 +52,33 @@
 #include <netgraph.h>
 #include <netgraph/netflow/ng_netflow.h>
 
-#define	CISCO_SH_FLOW_HEADER	"SrcIf         SrcIPaddress    DstIf         DstIPaddress    Pr SrcP DstP  Pkts\n"
+#define	CISCO_SH_FLOW_HEADER	"SrcIf         SrcIPaddress    " \
+"DstIf         DstIPaddress    Pr SrcP DstP  Pkts\n"
 #define	CISCO_SH_FLOW	"%-13s %-15s %-13s %-15s %2u %4.4x %4.4x %6lu\n"
 
-#define	CISCO_SH_FLOW6_HEADER	"SrcIf         SrcIPaddress                   DstIf         DstIPaddress                   Pr SrcP DstP  Pkts\n"
-#define	CISCO_SH_FLOW6	"%-13s %-30s %-13s %-30s %2u %4.4x %4.4x %6lu\n"
+/* human-readable IPv4 header */
+#define	CISCO_SH_FLOW_HHEADER	"SrcIf         SrcIPaddress    " \
+"DstIf         DstIPaddress    Proto  SrcPort  DstPort     Pkts\n"
+#define	CISCO_SH_FLOW_H	"%-13s %-15s %-13s %-15s %5u %8d %8d %8lu\n"
 
-#define	CISCO_SH_VERB_FLOW_HEADER "SrcIf          SrcIPaddress    DstIf          DstIPaddress    Pr TOS Flgs  Pkts\n" \
+#define	CISCO_SH_FLOW6_HEADER	"SrcIf         SrcIPaddress                   " \
+"DstIf         DstIPaddress                   Pr SrcP DstP  Pkts\n"
+#define	CISCO_SH_FLOW6		"%-13s %-30s %-13s %-30s %2u %4.4x %4.4x %6lu\n"
+
+/* Human-readable IPv6 headers */
+#define	CISCO_SH_FLOW6_HHEADER	"SrcIf         SrcIPaddress                         " \
+"DstIf         DstIPaddress                         Proto  SrcPort  DstPort     Pkts\n"
+#define	CISCO_SH_FLOW6_H	"%-13s %-36s %-13s %-36s %5u %8d %8d %8lu\n"
+
+#define	CISCO_SH_VERB_FLOW_HEADER "SrcIf          SrcIPaddress    " \
+"DstIf          DstIPaddress    Pr TOS Flgs  Pkts\n" \
 "Port Msk AS                    Port Msk AS    NextHop              B/Pk  Active\n"
 
 #define	CISCO_SH_VERB_FLOW "%-14s %-15s %-14s %-15s %2u %3x %4x %6lu\n" \
 	"%4.4x /%-2u %-5u                 %4.4x /%-2u %-5u %-15s %9u %8u\n\n"
 
-#define	CISCO_SH_VERB_FLOW6_HEADER "SrcIf          SrcIPaddress                   DstIf          DstIPaddress                   Pr TOS Flgs  Pkts\n" \
+#define	CISCO_SH_VERB_FLOW6_HEADER "SrcIf          SrcIPaddress                   " \
+"DstIf          DstIPaddress                   Pr TOS Flgs  Pkts\n" \
 "Port Msk AS                    Port Msk AS    NextHop                             B/Pk  Active\n"
 
 #define	CISCO_SH_VERB_FLOW6 "%-14s %-30s %-14s %-30s %2u %3x %4x %6lu\n" \
@@ -94,7 +108,7 @@
     {NULL,	NULL},
 };
 
-int	cs;
+int	cs, human = 0;
 char	*ng_path;
 
 int
@@ -182,6 +196,9 @@
 	if (argc > 0 && !strncmp(argv[0], "verbose", strlen(argv[0])))
 		verbose = 1;
 
+	if (argc > 0 && !strncmp(argv[0], "human", strlen(argv[0])))
+		human = 1;
+
 #ifdef INET
 	if (ipv4) {
 		if (verbose)
@@ -259,13 +276,14 @@
 		errx(EX_SOFTWARE, "%s: version mismatch: %u",
 		    __func__, resp->version);
 
-	printf(CISCO_SH_FLOW_HEADER);
+	if (resp->nentries > 0)
+		printf(human ? CISCO_SH_FLOW_HHEADER : CISCO_SH_FLOW_HEADER);
 
 	fle = (struct flow_entry_data *)(resp + 1);
 	for (i = 0; i < resp->nentries; i++, fle++) {
 		inet_ntop(AF_INET, &fle->r.r_src, src, sizeof(src));
 		inet_ntop(AF_INET, &fle->r.r_dst, dst, sizeof(dst));
-		printf(CISCO_SH_FLOW,
+		printf(human ? CISCO_SH_FLOW_H : CISCO_SH_FLOW,
 			if_indextoname(fle->fle_i_ifx, src_if),
 			src,
 			if_indextoname(fle->fle_o_ifx, dst_if),
@@ -292,13 +310,14 @@
 		errx(EX_SOFTWARE, "%s: version mismatch: %u",
 		    __func__, resp->version);
 
-	printf(CISCO_SH_FLOW6_HEADER);
+	if (resp->nentries > 0)
+		printf(human ? CISCO_SH_FLOW6_HHEADER : CISCO_SH_FLOW6_HEADER);
 
 	fle6 = (struct flow6_entry_data *)(resp + 1);
 	for (i = 0; i < resp->nentries; i++, fle6++) {
 		inet_ntop(AF_INET6, &fle6->r.src.r_src6, src6, sizeof(src6));
 		inet_ntop(AF_INET6, &fle6->r.dst.r_dst6, dst6, sizeof(dst6));
-		printf(CISCO_SH_FLOW6,
+		printf(human ? CISCO_SH_FLOW6_H : CISCO_SH_FLOW6,
 			if_indextoname(fle6->fle_i_ifx, src_if),
 			src6,
 			if_indextoname(fle6->fle_o_ifx, dst_if),
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/freebsd-update/freebsd-update.8
--- a/head/usr.sbin/freebsd-update/freebsd-update.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/freebsd-update/freebsd-update.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/freebsd-update/freebsd-update.8 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/freebsd-update/freebsd-update.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd July 14, 2010
 .Dt FREEBSD-UPDATE 8
@@ -62,7 +62,7 @@
 .Fx
 9.0-CURRENT.
 .Sh OPTIONS
-The following options are supported
+The following options are supported:
 .Bl -tag -width "-f conffile"
 .It Fl b Ar basedir
 Operate on a system mounted at
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/fwcontrol/fwcontrol.8
--- a/head/usr.sbin/fwcontrol/fwcontrol.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/fwcontrol/fwcontrol.8	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/fwcontrol/fwcontrol.8 233510 2012-03-26 15:18:14Z joel $
+.\" $FreeBSD: head/usr.sbin/fwcontrol/fwcontrol.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd September 12, 2008
 .Dt FWCONTROL 8
@@ -144,7 +144,7 @@
 .Xr eui64 5 .
 .El
 .Sh FILES
-.Bl -tag
+.Bl -tag -width "Pa /dev/fw0.0"
 .It Pa /dev/fw0.0
 .El
 .Sh EXAMPLES
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/gssd/gssd.8
--- a/head/usr.sbin/gssd/gssd.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/gssd/gssd.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/gssd/gssd.8 236500 2012-06-03 06:57:47Z joel $
 .\"
 .Dd November 5, 2008
 .Dt GSSD 8
@@ -40,7 +40,7 @@
 program provides support for the kernel GSS-API implementation.
 .Pp
 The options are as follows:
-.Bl -tag
+.Bl -tag -width indent
 .It Fl d
 Run in debug mode.
 In this mode,
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/i2c/i2c.8
--- a/head/usr.sbin/i2c/i2c.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/i2c/i2c.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/i2c/i2c.8 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/i2c/i2c.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd January 23, 2009
 .Dt I2C 8
@@ -88,7 +88,7 @@
 .It Fl s
 scan the bus for devices.
 .It Fl v
-be verbose
+be verbose.
 .It Fl w Ar 0|8|16
 device addressing width (in bits).
 .El
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ifmcstat/ifmcstat.c
--- a/head/usr.sbin/ifmcstat/ifmcstat.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ifmcstat/ifmcstat.c	Wed Jul 25 16:29:58 2012 +0300
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/ifmcstat/ifmcstat.c 230617 2012-01-27 17:16:44Z maxim $");
+__FBSDID("$FreeBSD: head/usr.sbin/ifmcstat/ifmcstat.c 237256 2012-06-19 06:10:27Z eadler $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -387,7 +387,6 @@
 	struct sockaddr sa;
 	struct sockaddr_dl sdl;
 	struct ifaddr *ifap0;
-	int error;
 
 	if (af && af != AF_LINK)
 		return;
@@ -404,7 +403,7 @@
 		if (sdl.sdl_alen == 0)
 			goto nextifap;
 		addrbuf[0] = '\0';
-		error = getnameinfo((struct sockaddr *)&sdl, sdl.sdl_len,
+		getnameinfo((struct sockaddr *)&sdl, sdl.sdl_len,
 		    addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
 		printf("\tlink %s\n", addrbuf);
 	nextifap:
@@ -427,7 +426,7 @@
 				goto nextmulti;
 			KREAD(ifm.ifma_addr, &sdl, struct sockaddr_dl);
 			addrbuf[0] = '\0';
-			error = getnameinfo((struct sockaddr *)&sdl,
+			getnameinfo((struct sockaddr *)&sdl,
 			    sdl.sdl_len, addrbuf, sizeof(addrbuf),
 			    NULL, 0, NI_NUMERICHOST);
 			printf("\t\tgroup %s refcnt %d\n",
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/inetd/inetd.c
--- a/head/usr.sbin/inetd/inetd.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/inetd/inetd.c	Wed Jul 25 16:29:58 2012 +0300
@@ -40,7 +40,7 @@
 #endif /* not lint */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/inetd/inetd.c 229403 2012-01-03 18:51:58Z ed $");
+__FBSDID("$FreeBSD: head/usr.sbin/inetd/inetd.c 236572 2012-06-04 18:02:09Z delphij $");
 
 /*
  * Inetd - Internet super-server
@@ -688,11 +688,11 @@
 		     */
 		    if (dofork) {
 			    if (sep->se_count++ == 0)
-				(void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
+				(void)clock_gettime(CLOCK_MONOTONIC_FAST, &sep->se_time);
 			    else if (toomany > 0 && sep->se_count >= toomany) {
-				struct timeval now;
+				struct timespec now;
 
-				(void)gettimeofday(&now, (struct timezone *)NULL);
+				(void)clock_gettime(CLOCK_MONOTONIC_FAST, &now);
 				if (now.tv_sec - sep->se_time.tv_sec >
 				    CNT_INTVL) {
 					sep->se_time = now;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/inetd/inetd.h
--- a/head/usr.sbin/inetd/inetd.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/inetd/inetd.h	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/inetd/inetd.h 236572 2012-06-04 18:02:09Z delphij $
  */
 
 #include <sys/time.h>
@@ -109,7 +109,7 @@
 	u_int	se_rpc_lowvers;		/* RPC low version */
 	u_int	se_rpc_highvers;	/* RPC high version */
 	int	se_count;		/* number started since se_time */
-	struct	timeval se_time;	/* start of se_count */
+	struct	timespec se_time;	/* start of se_count */
 	struct	servtab *se_next;
 	struct se_flags {
 		u_int se_nomapped : 1;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ipfwpcap/ipfwpcap.8
--- a/head/usr.sbin/ipfwpcap/ipfwpcap.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ipfwpcap/ipfwpcap.8	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2006 Niclas Zeising
+.\" Copyright (c) 2006 Niclas Zeising <zeising at FreeBSD.org>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/ipfwpcap/ipfwpcap.8 238612 2012-07-19 08:56:30Z zeising $
 .\"
 .Dd May 22, 2006
 .Dt IPFWPCAP 8
@@ -129,4 +129,4 @@
 was written by
 .An P. Kern Aq pkern at cns.utoronto.ca .
 This manual page was written by
-.An Niclas Zeising Aq niclas.zeising at gmail.com .
+.An Niclas Zeising Aq zeising at FreeBSD.org .
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/Makefile
--- a/head/usr.sbin/jail/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/jail/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,11 +1,16 @@
-# $FreeBSD: head/usr.sbin/jail/Makefile 222465 2011-05-29 21:03:40Z bz $
+# $FreeBSD: head/usr.sbin/jail/Makefile 234712 2012-04-26 17:36:05Z jamie $
 
 .include <bsd.own.mk>
 
 PROG=	jail
-MAN=	jail.8
-DPADD=	${LIBJAIL} ${LIBUTIL}
-LDADD=	-ljail -lutil
+MAN=	jail.8 jail.conf.5
+SRCS=	jail.c command.c config.c state.c jailp.h jaillex.l jailparse.y y.tab.h
+
+DPADD=	${LIBJAIL} ${LIBKVM} ${LIBUTIL} ${LIBL}
+LDADD=	-ljail -lkvm -lutil -ll
+
+YFLAGS+=-v
+CFLAGS+=-I. -I${.CURDIR}
 
 .if ${MK_INET6_SUPPORT} != "no"
 CFLAGS+= -DINET6
@@ -14,4 +19,6 @@
 CFLAGS+= -DINET
 .endif
 
+CLEANFILES= y.output
+
 .include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/command.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/command.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,860 @@
+/*-
+ * Copyright (c) 2011 James Gritton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/jail/command.c 236198 2012-05-28 20:44:11Z jamie $");
+
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <kvm.h>
+#include <login_cap.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "jailp.h"
+
+#define DEFAULT_STOP_TIMEOUT	10
+#define PHASH_SIZE		256
+
+LIST_HEAD(phhead, phash);
+
+struct phash {
+	LIST_ENTRY(phash)	le;
+	struct cfjail		*j;
+	pid_t			pid;
+};
+
+int paralimit = -1;
+
+extern char **environ;
+
+static int run_command(struct cfjail *j);
+static void add_proc(struct cfjail *j, pid_t pid);
+static void clear_procs(struct cfjail *j);
+static struct cfjail *find_proc(pid_t pid);
+static int term_procs(struct cfjail *j);
+static int get_user_info(struct cfjail *j, const char *username,
+    const struct passwd **pwdp, login_cap_t **lcapp);
+static int check_path(struct cfjail *j, const char *pname, const char *path,
+    int isfile, const char *umount_type);
+
+static struct cfjails sleeping = TAILQ_HEAD_INITIALIZER(sleeping);
+static struct cfjails runnable = TAILQ_HEAD_INITIALIZER(runnable);
+static struct cfstring dummystring = { .len = 1 };
+static struct phhead phash[PHASH_SIZE];
+static int kq;
+
+/*
+ * Run the next command associated with a jail.
+ */
+int
+next_command(struct cfjail *j)
+{
+	enum intparam comparam;
+	int create_failed;
+
+	if (paralimit == 0) {
+		requeue(j, &runnable);
+		return 1;
+	}
+	create_failed = (j->flags & (JF_STOP | JF_FAILED)) == JF_FAILED;
+	comparam = *j->comparam;
+	for (;;) {
+		if (j->comstring == NULL) {
+			j->comparam += create_failed ? -1 : 1;
+			switch ((comparam = *j->comparam)) {
+			case IP__NULL:
+				return 0;
+			case IP_MOUNT_DEVFS:
+				if (!bool_param(j->intparams[IP_MOUNT_DEVFS]))
+					continue;
+				/* FALLTHROUGH */
+			case IP__OP:
+			case IP_STOP_TIMEOUT:
+				j->comstring = &dummystring;
+				break;
+			default:
+				if (j->intparams[comparam] == NULL)
+					continue;
+				j->comstring = create_failed
+				    ? TAILQ_LAST(&j->intparams[comparam]->val,
+					cfstrings)
+				    : TAILQ_FIRST(&j->intparams[comparam]->val);
+			}
+		} else {
+			j->comstring = j->comstring == &dummystring ? NULL :
+			    create_failed
+			    ? TAILQ_PREV(j->comstring, cfstrings, tq)
+			    : TAILQ_NEXT(j->comstring, tq);
+		}
+		if (j->comstring == NULL || j->comstring->len == 0 ||
+		    (create_failed && (comparam == IP_EXEC_PRESTART ||
+		    comparam == IP_EXEC_START || comparam == IP_COMMAND ||
+		    comparam == IP_EXEC_POSTSTART)))
+			continue;
+		switch (run_command(j)) {
+		case -1:
+			failed(j);
+			/* FALLTHROUGH */
+		case 1:
+			return 1;
+		}
+	}
+}
+
+/*
+ * Check command exit status
+ */
+int
+finish_command(struct cfjail *j)
+{
+	int error;
+
+	if (!(j->flags & JF_SLEEPQ))
+		return 0;
+	j->flags &= ~JF_SLEEPQ;
+	if (*j->comparam == IP_STOP_TIMEOUT)
+	{
+		j->flags &= ~JF_TIMEOUT;
+		j->pstatus = 0;
+		return 0;
+	}
+	paralimit++;
+	if (!TAILQ_EMPTY(&runnable))
+		requeue(TAILQ_FIRST(&runnable), &ready);
+	error = 0;
+	if (j->flags & JF_TIMEOUT) {
+		j->flags &= ~JF_TIMEOUT;
+		if (*j->comparam != IP_STOP_TIMEOUT) {
+			jail_warnx(j, "%s: timed out", j->comline);
+			failed(j);
+			error = -1;
+		} else if (verbose > 0)
+			jail_note(j, "timed out\n");
+	} else if (j->pstatus != 0) {
+		if (WIFSIGNALED(j->pstatus))
+			jail_warnx(j, "%s: exited on signal %d",
+			    j->comline, WTERMSIG(j->pstatus));
+		else
+			jail_warnx(j, "%s: failed", j->comline);
+		j->pstatus = 0;
+		failed(j);
+		error = -1;
+	}
+	free(j->comline);
+	j->comline = NULL;
+	return error;
+}
+
+/*
+ * Check for finished processes or timeouts.
+ */
+struct cfjail *
+next_proc(int nonblock)
+{
+	struct kevent ke;
+	struct timespec ts;
+	struct timespec *tsp;
+	struct cfjail *j;
+
+	if (!TAILQ_EMPTY(&sleeping)) {
+	again:
+		tsp = NULL;
+		if ((j = TAILQ_FIRST(&sleeping)) && j->timeout.tv_sec) {
+			clock_gettime(CLOCK_REALTIME, &ts);
+			ts.tv_sec = j->timeout.tv_sec - ts.tv_sec;
+			ts.tv_nsec = j->timeout.tv_nsec - ts.tv_nsec;
+			if (ts.tv_nsec < 0) {
+				ts.tv_sec--;
+				ts.tv_nsec += 1000000000;
+			}
+			if (ts.tv_sec < 0 ||
+			    (ts.tv_sec == 0 && ts.tv_nsec == 0)) {
+				j->flags |= JF_TIMEOUT;
+				clear_procs(j);
+				return j;
+			}
+			tsp = &ts;
+		}
+		if (nonblock) {
+			ts.tv_sec = 0;
+			ts.tv_nsec = 0;
+			tsp = &ts;
+		}
+		switch (kevent(kq, NULL, 0, &ke, 1, tsp)) {
+		case -1:
+			if (errno != EINTR)
+				err(1, "kevent");
+			goto again;
+		case 0:
+			if (!nonblock) {
+				j = TAILQ_FIRST(&sleeping);
+				j->flags |= JF_TIMEOUT;
+				clear_procs(j);
+				return j;
+			}
+			break;
+		case 1:
+			(void)waitpid(ke.ident, NULL, WNOHANG);
+			if ((j = find_proc(ke.ident))) {
+				j->pstatus = ke.data;
+				return j;
+			}
+			goto again;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Run a single command for a jail, possible inside the jail.
+ */
+static int
+run_command(struct cfjail *j)
+{
+	const struct passwd *pwd;
+	const struct cfstring *comstring, *s;
+	login_cap_t *lcap;
+	char **argv;
+	char *cs, *comcs, *devpath;
+	const char *jidstr, *conslog, *path, *ruleset, *term, *username;
+	enum intparam comparam;
+	size_t comlen;
+	pid_t pid;
+	int argc, bg, clean, consfd, down, fib, i, injail, sjuser, timeout;
+#if defined(INET) || defined(INET6)
+	char *addr;
+#endif
+
+	static char *cleanenv;
+
+	/* Perform some operations that aren't actually commands */
+	comparam = *j->comparam;
+	down = j->flags & (JF_STOP | JF_FAILED);
+	switch (comparam) {
+	case IP_STOP_TIMEOUT:
+		return term_procs(j);
+
+	case IP__OP:
+		if (down) {
+			if (jail_remove(j->jid) < 0 && errno == EPERM) {
+				jail_warnx(j, "jail_remove: %s",
+					   strerror(errno));
+				return -1;
+			}
+			if (verbose > 0 || (verbose == 0 && (j->flags & JF_STOP
+			    ? note_remove : j->name != NULL)))
+			    jail_note(j, "removed\n");
+			j->jid = -1;
+			if (j->flags & JF_STOP)
+				dep_done(j, DF_LIGHT);
+			else
+				j->flags &= ~JF_PERSIST;
+		} else {
+			if (create_jail(j) < 0)
+				return -1;
+			if (iflag)
+				printf("%d\n", j->jid);
+			if (verbose >= 0 && (j->name || verbose > 0))
+				jail_note(j, "created\n");
+			dep_done(j, DF_LIGHT);
+		}
+		return 0;
+
+	default: ;
+	}
+	/*
+	 * Collect exec arguments.  Internal commands for network and
+	 * mounting build their own argument lists.
+	 */
+	comstring = j->comstring;
+	bg = 0;
+	switch (comparam) {
+#ifdef INET
+	case IP__IP4_IFADDR:
+		argv = alloca(8 * sizeof(char *));
+		*(const char **)&argv[0] = _PATH_IFCONFIG;
+		if ((cs = strchr(comstring->s, '|'))) {
+			argv[1] = alloca(cs - comstring->s + 1);
+			strlcpy(argv[1], comstring->s, cs - comstring->s + 1);
+			addr = cs + 1;
+		} else {
+			*(const char **)&argv[1] =
+			    string_param(j->intparams[IP_INTERFACE]);
+			addr = comstring->s;
+		}
+		*(const char **)&argv[2] = "inet";
+		if (!(cs = strchr(addr, '/'))) {
+			argv[3] = addr;
+			*(const char **)&argv[4] = "netmask";
+			*(const char **)&argv[5] = "255.255.255.255";
+			argc = 6;
+		} else if (strchr(cs + 1, '.')) {
+			argv[3] = alloca(cs - addr + 1);
+			strlcpy(argv[3], addr, cs - addr + 1);
+			*(const char **)&argv[4] = "netmask";
+			*(const char **)&argv[5] = cs + 1;
+			argc = 6;
+		} else {
+			argv[3] = addr;
+			argc = 4;
+		}
+		*(const char **)&argv[argc] = down ? "-alias" : "alias";
+		argv[argc + 1] = NULL;
+		break;
+#endif
+
+#ifdef INET6
+	case IP__IP6_IFADDR:
+		argv = alloca(8 * sizeof(char *));
+		*(const char **)&argv[0] = _PATH_IFCONFIG;
+		if ((cs = strchr(comstring->s, '|'))) {
+			argv[1] = alloca(cs - comstring->s + 1);
+			strlcpy(argv[1], comstring->s, cs - comstring->s + 1);
+			addr = cs + 1;
+		} else {
+			*(const char **)&argv[1] =
+			    string_param(j->intparams[IP_INTERFACE]);
+			addr = comstring->s;
+		}
+		*(const char **)&argv[2] = "inet6";
+		argv[3] = addr;
+		if (!(cs = strchr(addr, '/'))) {
+			*(const char **)&argv[4] = "prefixlen";
+			*(const char **)&argv[5] = "128";
+			argc = 6;
+		} else
+			argc = 4;
+		*(const char **)&argv[argc] = down ? "-alias" : "alias";
+		argv[argc + 1] = NULL;
+		break;	
+#endif
+
+	case IP_VNET_INTERFACE:
+		argv = alloca(5 * sizeof(char *));
+		*(const char **)&argv[0] = _PATH_IFCONFIG;
+		argv[1] = comstring->s;
+		*(const char **)&argv[2] = down ? "-vnet" : "vnet";
+		jidstr = string_param(j->intparams[KP_JID]);
+		*(const char **)&argv[3] =
+			jidstr ? jidstr : string_param(j->intparams[KP_NAME]);
+		argv[4] = NULL;
+		break;
+
+	case IP_MOUNT:
+	case IP__MOUNT_FROM_FSTAB:
+		argv = alloca(8 * sizeof(char *));
+		comcs = alloca(comstring->len + 1);
+		strcpy(comcs, comstring->s);
+		argc = 0;
+		for (cs = strtok(comcs, " \t\f\v\r\n"); cs && argc < 4;
+		     cs = strtok(NULL, " \t\f\v\r\n"))
+			argv[argc++] = cs;
+		if (argc == 0)
+			return 0;
+		if (argc < 3) {
+			jail_warnx(j, "%s: %s: missing information",
+			    j->intparams[comparam]->name, comstring->s);
+			return -1;
+		}
+		if (check_path(j, j->intparams[comparam]->name, argv[1], 0,
+		    down ? argv[2] : NULL) < 0)
+			return -1;
+		if (down) {
+			argv[4] = NULL;
+			argv[3] = argv[1];
+			*(const char **)&argv[0] = "/sbin/umount";
+		} else {
+			if (argc == 4) {
+				argv[7] = NULL;
+				argv[6] = argv[1];
+				argv[5] = argv[0];
+				argv[4] = argv[3];
+				*(const char **)&argv[3] = "-o";
+			} else {
+				argv[5] = NULL;
+				argv[4] = argv[1];
+				argv[3] = argv[0];
+			}
+			*(const char **)&argv[0] = _PATH_MOUNT;
+		}
+		*(const char **)&argv[1] = "-t";
+		break;
+
+	case IP_MOUNT_DEVFS:
+		argv = alloca(7 * sizeof(char *));
+		path = string_param(j->intparams[KP_PATH]);
+		if (path == NULL) {
+			jail_warnx(j, "mount.devfs: no path");
+			return -1;
+		}
+		devpath = alloca(strlen(path) + 5);
+		sprintf(devpath, "%s/dev", path);
+		if (check_path(j, "mount.devfs", devpath, 0,
+		    down ? "devfs" : NULL) < 0)
+			return -1;
+		if (down) {
+			*(const char **)&argv[0] = "/sbin/umount";
+			argv[1] = devpath;
+			argv[2] = NULL;
+		} else {
+			*(const char **)&argv[0] = _PATH_MOUNT;
+			*(const char **)&argv[1] = "-t";
+			*(const char **)&argv[2] = "devfs";
+			ruleset = string_param(j->intparams[KP_DEVFS_RULESET]);
+			if (!ruleset)
+			    ruleset = "4";	/* devfsrules_jail */
+			argv[3] = alloca(11 + strlen(ruleset));
+			sprintf(argv[3], "-oruleset=%s", ruleset);
+			*(const char **)&argv[4] = ".";
+			argv[5] = devpath;
+			argv[6] = NULL;
+		}
+		break;
+
+	case IP_COMMAND:
+		if (j->name != NULL)
+			goto default_command;
+		argc = 0;
+		TAILQ_FOREACH(s, &j->intparams[IP_COMMAND]->val, tq)
+			argc++;
+		argv = alloca((argc + 1) * sizeof(char *));
+		argc = 0;
+		TAILQ_FOREACH(s, &j->intparams[IP_COMMAND]->val, tq)
+			argv[argc++] = s->s;
+		argv[argc] = NULL;
+		j->comstring = &dummystring;
+		break;
+
+	default:
+	default_command:
+		if ((cs = strpbrk(comstring->s, "!\"$&'()*;<>?[\\]`{|}~")) &&
+		    !(cs[0] == '&' && cs[1] == '\0')) {
+			argv = alloca(4 * sizeof(char *));
+			*(const char **)&argv[0] = _PATH_BSHELL;
+			*(const char **)&argv[1] = "-c";
+			argv[2] = comstring->s;
+			argv[3] = NULL;
+		} else {
+			if (cs) {
+				*cs = 0;
+				bg = 1;
+			}
+			comcs = alloca(comstring->len + 1);
+			strcpy(comcs, comstring->s);	
+			argc = 0;
+			for (cs = strtok(comcs, " \t\f\v\r\n"); cs;
+			     cs = strtok(NULL, " \t\f\v\r\n"))
+				argc++;
+			argv = alloca((argc + 1) * sizeof(char *));
+			strcpy(comcs, comstring->s);	
+			argc = 0;
+			for (cs = strtok(comcs, " \t\f\v\r\n"); cs;
+			     cs = strtok(NULL, " \t\f\v\r\n"))
+				argv[argc++] = cs;
+			argv[argc] = NULL;
+		}
+	}
+	if (argv[0] == NULL)
+		return 0;
+
+	if (int_param(j->intparams[IP_EXEC_TIMEOUT], &timeout) &&
+	    timeout != 0) {
+		clock_gettime(CLOCK_REALTIME, &j->timeout);
+		j->timeout.tv_sec += timeout;
+	} else
+		j->timeout.tv_sec = 0;
+
+	injail = comparam == IP_EXEC_START || comparam == IP_COMMAND ||
+	    comparam == IP_EXEC_STOP;
+	clean = bool_param(j->intparams[IP_EXEC_CLEAN]);
+	username = string_param(j->intparams[injail
+	    ? IP_EXEC_JAIL_USER : IP_EXEC_SYSTEM_USER]);
+	sjuser = bool_param(j->intparams[IP_EXEC_SYSTEM_JAIL_USER]);
+
+	consfd = 0;
+	if (injail &&
+	    (conslog = string_param(j->intparams[IP_EXEC_CONSOLELOG]))) {
+		if (check_path(j, "exec.consolelog", conslog, 1, NULL) < 0)
+			return -1;
+		consfd =
+		    open(conslog, O_WRONLY | O_CREAT | O_APPEND, DEFFILEMODE);
+		if (consfd < 0) {
+			jail_warnx(j, "open %s: %s", conslog, strerror(errno));
+			return -1;
+		}
+	}
+
+	comlen = 0;
+	for (i = 0; argv[i]; i++)
+		comlen += strlen(argv[i]) + 1;
+	j->comline = cs = emalloc(comlen);
+	for (i = 0; argv[i]; i++) {
+		strcpy(cs, argv[i]);
+		if (argv[i + 1]) {
+			cs += strlen(argv[i]) + 1;
+			cs[-1] = ' ';
+		}
+	}
+	if (verbose > 0)
+		jail_note(j, "run command%s%s%s: %s\n",
+		    injail ? " in jail" : "", username ? " as " : "",
+		    username ? username : "", j->comline);
+
+	pid = fork();
+	if (pid < 0)
+		err(1, "fork");
+	if (pid > 0) {
+		if (bg) {
+			free(j->comline);
+			j->comline = NULL;
+			return 0;
+		} else {
+			paralimit--;
+			add_proc(j, pid);
+			return 1;
+		}
+	}
+	if (bg)
+		setsid();
+
+	/* Set up the environment and run the command */
+	pwd = NULL;
+	lcap = NULL;
+	if ((clean || username) && injail && sjuser &&
+	    get_user_info(j, username, &pwd, &lcap) < 0)
+		exit(1);
+	if (injail) {
+		/* jail_attach won't chdir along with its chroot. */
+		path = string_param(j->intparams[KP_PATH]);
+		if (path && chdir(path) < 0) {
+			jail_warnx(j, "chdir %s: %s", path, strerror(errno));
+			exit(1);
+		}
+		if (int_param(j->intparams[IP_EXEC_FIB], &fib) &&
+		    setfib(fib) < 0) {
+			jail_warnx(j, "setfib: %s", strerror(errno));
+			exit(1);
+		}
+		if (jail_attach(j->jid) < 0) {
+			jail_warnx(j, "jail_attach: %s", strerror(errno));
+			exit(1);
+		}
+	}
+	if (clean || username) {
+		if (!(injail && sjuser) &&
+		    get_user_info(j, username, &pwd, &lcap) < 0)
+			exit(1);
+		if (clean) {
+			term = getenv("TERM");
+			environ = &cleanenv;
+			setenv("PATH", "/bin:/usr/bin", 0);
+			if (term != NULL)
+				setenv("TERM", term, 1);
+		}
+		if (setusercontext(lcap, pwd, pwd->pw_uid, username
+		    ? LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN
+		    : LOGIN_SETPATH | LOGIN_SETENV) < 0) {
+			jail_warnx(j, "setusercontext %s: %s", pwd->pw_name,
+			    strerror(errno));
+			exit(1);
+		}
+		login_close(lcap);
+		setenv("USER", pwd->pw_name, 1);
+		setenv("HOME", pwd->pw_dir, 1);
+		setenv("SHELL",
+		    *pwd->pw_shell ? pwd->pw_shell : _PATH_BSHELL, 1);
+		if (clean && chdir(pwd->pw_dir) < 0) {
+			jail_warnx(j, "chdir %s: %s",
+			    pwd->pw_dir, strerror(errno));
+			exit(1);
+		}
+		endpwent();
+	}
+
+	if (consfd != 0 && (dup2(consfd, 1) < 0 || dup2(consfd, 2) < 0)) {
+		jail_warnx(j, "exec.consolelog: %s", strerror(errno));
+		exit(1);
+	}
+	closefrom(3);
+	execvp(argv[0], argv);
+	jail_warnx(j, "exec %s: %s", argv[0], strerror(errno));
+	exit(1);
+}
+
+/*
+ * Add a process to the hash, tied to a jail.
+ */
+static void
+add_proc(struct cfjail *j, pid_t pid)
+{
+	struct kevent ke;
+	struct cfjail *tj;
+	struct phash *ph;
+
+	if (!kq && (kq = kqueue()) < 0)
+		err(1, "kqueue");
+	EV_SET(&ke, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
+	if (kevent(kq, &ke, 1, NULL, 0, NULL) < 0)
+		err(1, "kevent");
+	ph = emalloc(sizeof(struct phash));
+	ph->j = j;
+	ph->pid = pid;
+	LIST_INSERT_HEAD(&phash[pid % PHASH_SIZE], ph, le);
+	j->nprocs++;
+	j->flags |= JF_SLEEPQ;
+	if (j->timeout.tv_sec == 0)
+		requeue(j, &sleeping);
+	else {
+		/* File the jail in the sleep queue acording to its timeout. */
+		TAILQ_REMOVE(j->queue, j, tq);
+		TAILQ_FOREACH(tj, &sleeping, tq) {
+			if (!tj->timeout.tv_sec ||
+			    j->timeout.tv_sec < tj->timeout.tv_sec ||
+			    (j->timeout.tv_sec == tj->timeout.tv_sec &&
+			    j->timeout.tv_nsec <= tj->timeout.tv_nsec)) {
+				TAILQ_INSERT_BEFORE(tj, j, tq);
+				break;
+			}
+		}
+		if (tj == NULL)
+			TAILQ_INSERT_TAIL(&sleeping, j, tq);
+		j->queue = &sleeping;
+	}
+}
+
+/*
+ * Remove any processes from the hash that correspond to a jail.
+ */
+static void
+clear_procs(struct cfjail *j)
+{
+	struct kevent ke;
+	struct phash *ph, *tph;
+	int i;
+
+	j->nprocs = 0;
+	for (i = 0; i < PHASH_SIZE; i++)
+		LIST_FOREACH_SAFE(ph, &phash[i], le, tph)
+			if (ph->j == j) {
+				EV_SET(&ke, ph->pid, EVFILT_PROC, EV_DELETE,
+				    NOTE_EXIT, 0, NULL);
+				(void)kevent(kq, &ke, 1, NULL, 0, NULL);
+				LIST_REMOVE(ph, le);
+				free(ph);
+			}
+}
+
+/*
+ * Find the jail that corresponds to an exited process.
+ */
+static struct cfjail *
+find_proc(pid_t pid)
+{
+	struct cfjail *j;
+	struct phash *ph;
+
+	LIST_FOREACH(ph, &phash[pid % PHASH_SIZE], le)
+		if (ph->pid == pid) {
+			j = ph->j;
+			LIST_REMOVE(ph, le);
+			free(ph);
+			return --j->nprocs ? NULL : j;
+		}
+	return NULL;
+}
+
+/*
+ * Send SIGTERM to all processes in a jail and wait for them to die.
+ */
+static int
+term_procs(struct cfjail *j)
+{
+	struct kinfo_proc *ki;
+	int i, noted, pcnt, timeout;
+
+	static kvm_t *kd;
+
+	if (!int_param(j->intparams[IP_STOP_TIMEOUT], &timeout))
+		timeout = DEFAULT_STOP_TIMEOUT;
+	else if (timeout == 0)
+		return 0;
+
+	if (kd == NULL) {
+		kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL);
+		if (kd == NULL)
+			return 0;
+	}
+
+	ki = kvm_getprocs(kd, KERN_PROC_PROC, 0, &pcnt);
+	if (ki == NULL)
+		return 0;
+	noted = 0;
+	for (i = 0; i < pcnt; i++)
+		if (ki[i].ki_jid == j->jid &&
+		    kill(ki[i].ki_pid, SIGTERM) == 0) {
+			add_proc(j, ki[i].ki_pid);
+			if (verbose > 0) {
+				if (!noted) {
+					noted = 1;
+					jail_note(j, "sent SIGTERM to:");
+				}
+				printf(" %d", ki[i].ki_pid);
+			}
+		}
+	if (noted)
+		printf("\n");
+	if (j->nprocs > 0) {
+		clock_gettime(CLOCK_REALTIME, &j->timeout);
+		j->timeout.tv_sec += timeout;
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * Look up a user in the passwd and login.conf files.
+ */
+static int
+get_user_info(struct cfjail *j, const char *username,
+    const struct passwd **pwdp, login_cap_t **lcapp)
+{
+	const struct passwd *pwd;
+
+	*pwdp = pwd = username ? getpwnam(username) : getpwuid(getuid());
+	if (pwd == NULL) {
+		if (errno)
+			jail_warnx(j, "getpwnam%s%s: %s", username ? " " : "",
+			    username ? username : "", strerror(errno));
+		else if (username)
+			jail_warnx(j, "%s: no such user", username);
+		else
+			jail_warnx(j, "unknown uid %d", getuid());
+		return -1;
+	}
+	*lcapp = login_getpwclass(pwd);
+	if (*lcapp == NULL) {
+		jail_warnx(j, "getpwclass %s: %s", pwd->pw_name,
+		    strerror(errno));
+		return -1;
+	}
+	/* Set the groups while the group file is still available */
+	if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
+		jail_warnx(j, "initgroups %s: %s", pwd->pw_name,
+		    strerror(errno));
+		return -1;
+	}
+	return 0;
+}
+
+/*
+ * Make sure a mount or consolelog path is a valid absolute pathname
+ * with no symlinks.
+ */
+static int
+check_path(struct cfjail *j, const char *pname, const char *path, int isfile,
+    const char *umount_type)
+{
+	struct stat st, mpst;
+	struct statfs stfs;
+	char *tpath, *p;
+	const char *jailpath;
+	size_t jplen;
+
+	if (path[0] != '/') {
+		jail_warnx(j, "%s: %s: not an absolute pathname",
+		    pname, path);
+		return -1;
+	}
+	/*
+	 * Only check for symlinks in components below the jail's path,
+	 * since that's where the security risk lies.
+	 */
+	jailpath = string_param(j->intparams[KP_PATH]);
+	if (jailpath == NULL)
+		jailpath = "";
+	jplen = strlen(jailpath);
+	if (!strncmp(path, jailpath, jplen) && path[jplen] == '/') {
+		tpath = alloca(strlen(path) + 1);
+		strcpy(tpath, path);
+		for (p = tpath + jplen; p != NULL; ) {
+			p = strchr(p + 1, '/');
+			if (p)
+				*p = '\0';
+			if (lstat(tpath, &st) < 0) {
+				if (errno == ENOENT && isfile && !p)
+					break;
+				jail_warnx(j, "%s: %s: %s", pname, tpath,
+				    strerror(errno));
+				return -1;
+			}
+			if (S_ISLNK(st.st_mode)) {
+				jail_warnx(j, "%s: %s is a symbolic link",
+				    pname, tpath);
+				return -1;
+			}
+			if (p)
+				*p = '/';
+		}
+	}
+	if (umount_type != NULL) {
+		if (stat(path, &st) < 0 || statfs(path, &stfs) < 0) {
+			jail_warnx(j, "%s: %s: %s", pname, path,
+			    strerror(errno));
+			return -1;
+		}
+		if (stat(stfs.f_mntonname, &mpst) < 0) {
+			jail_warnx(j, "%s: %s: %s", pname, stfs.f_mntonname,
+			    strerror(errno));
+			return -1;
+		}
+		if (st.st_ino != mpst.st_ino) {
+			jail_warnx(j, "%s: %s: not a mount point",
+			    pname, path);
+			return -1;
+		}
+		if (strcmp(stfs.f_fstypename, umount_type)) {
+			jail_warnx(j, "%s: %s: not a %s mount",
+			    pname, path, umount_type);
+			return -1;
+		}
+	}
+	return 0;
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/config.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/config.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,833 @@
+/*-
+ * Copyright (c) 2011 James Gritton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/jail/config.c 235789 2012-05-22 16:33:10Z bapt $");
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "jailp.h"
+
+struct ipspec {
+	const char	*name;
+	unsigned	flags;
+};
+
+extern FILE *yyin;
+extern int yynerrs;
+
+extern int yyparse(void);
+
+struct cfjails cfjails = TAILQ_HEAD_INITIALIZER(cfjails);
+
+static void free_param(struct cfparams *pp, struct cfparam *p);
+static void free_param_strings(struct cfparam *p);
+
+static const struct ipspec intparams[] = {
+    [IP_ALLOW_DYING] =		{"allow.dying",		PF_INTERNAL | PF_BOOL},
+    [IP_COMMAND] =		{"command",		PF_INTERNAL},
+    [IP_DEPEND] =		{"depend",		PF_INTERNAL},
+    [IP_EXEC_CLEAN] =		{"exec.clean",		PF_INTERNAL | PF_BOOL},
+    [IP_EXEC_CONSOLELOG] =	{"exec.consolelog",	PF_INTERNAL},
+    [IP_EXEC_FIB] =		{"exec.fib",		PF_INTERNAL | PF_INT},
+    [IP_EXEC_JAIL_USER] =	{"exec.jail_user",	PF_INTERNAL},
+    [IP_EXEC_POSTSTART] =	{"exec.poststart",	PF_INTERNAL},
+    [IP_EXEC_POSTSTOP] =	{"exec.poststop",	PF_INTERNAL},
+    [IP_EXEC_PRESTART] =	{"exec.prestart",	PF_INTERNAL},
+    [IP_EXEC_PRESTOP] =		{"exec.prestop",	PF_INTERNAL},
+    [IP_EXEC_START] =		{"exec.start",		PF_INTERNAL},
+    [IP_EXEC_STOP] =		{"exec.stop",		PF_INTERNAL},
+    [IP_EXEC_SYSTEM_JAIL_USER]=	{"exec.system_jail_user",
+							PF_INTERNAL | PF_BOOL},
+    [IP_EXEC_SYSTEM_USER] =	{"exec.system_user",	PF_INTERNAL},
+    [IP_EXEC_TIMEOUT] =		{"exec.timeout",	PF_INTERNAL | PF_INT},
+#if defined(INET) || defined(INET6)
+    [IP_INTERFACE] =		{"interface",		PF_INTERNAL},
+    [IP_IP_HOSTNAME] =		{"ip_hostname",		PF_INTERNAL | PF_BOOL},
+#endif
+    [IP_MOUNT] =		{"mount",		PF_INTERNAL},
+    [IP_MOUNT_DEVFS] =		{"mount.devfs",		PF_INTERNAL | PF_BOOL},
+    [IP_MOUNT_FSTAB] =		{"mount.fstab",		PF_INTERNAL},
+    [IP_STOP_TIMEOUT] =		{"stop.timeout",	PF_INTERNAL | PF_INT},
+    [IP_VNET_INTERFACE] =	{"vnet.interface",	PF_INTERNAL},
+#ifdef INET
+    [IP__IP4_IFADDR] =		{"ip4.addr",		PF_INTERNAL | PF_CONV},
+#endif
+#ifdef INET6
+    [IP__IP6_IFADDR] =		{"ip6.addr",		PF_INTERNAL | PF_CONV},
+#endif
+    [IP__MOUNT_FROM_FSTAB] =	{"mount.fstab",		PF_INTERNAL | PF_CONV},
+    [IP__OP] =			{NULL,			PF_CONV},
+    [KP_ALLOW_CHFLAGS] =	{"allow.chflags",	0},
+    [KP_ALLOW_MOUNT] =		{"allow.mount",		0},
+    [KP_ALLOW_RAW_SOCKETS] =	{"allow.raw_sockets",	0},
+    [KP_ALLOW_SET_HOSTNAME]=	{"allow.set_hostname",	0},
+    [KP_ALLOW_SOCKET_AF] =	{"allow.socket_af",	0},
+    [KP_ALLOW_SYSVIPC] =	{"allow.sysvipc",	0},
+    [KP_DEVFS_RULESET] =	{"devfs_ruleset",	0},
+    [KP_ENFORCE_STATFS] =	{"enforce_statfs",	0},
+    [KP_HOST_HOSTNAME] =	{"host.hostname",	0},
+#ifdef INET
+    [KP_IP4_ADDR] =		{"ip4.addr",		0},
+#endif
+#ifdef INET6
+    [KP_IP6_ADDR] =		{"ip6.addr",		0},
+#endif
+    [KP_JID] =			{"jid",			0},
+    [KP_NAME] =			{"name",		0},
+    [KP_PATH] =			{"path",		0},
+    [KP_PERSIST] =		{"persist",		0},
+    [KP_SECURELEVEL] =		{"securelevel",		0},
+    [KP_VNET] =			{"vnet",		0},
+};
+
+/*
+ * Parse the jail configuration file.
+ */
+void
+load_config(void)
+{
+	struct cfjails wild;
+	struct cfparams opp;
+	struct cfjail *j, *tj, *wj;
+	struct cfparam *p, *vp, *tp;
+	struct cfstring *s, *vs, *ns;
+	struct cfvar *v;
+	char *ep;
+	size_t varoff;
+	int did_self, jseq, pgen;
+
+	if (!strcmp(cfname, "-")) {
+		cfname = "STDIN";
+		yyin = stdin;
+	} else {
+		yyin = fopen(cfname, "r");
+		if (!yyin)
+			err(1, "%s", cfname);
+	}
+	if (yyparse() || yynerrs)
+		exit(1);
+
+	/* Separate the wildcard jails out from the actual jails. */
+	jseq = 0;
+	TAILQ_INIT(&wild);
+	TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
+		j->seq = ++jseq;
+		if (wild_jail_name(j->name))
+			requeue(j, &wild);
+	}
+
+	TAILQ_FOREACH(j, &cfjails, tq) {
+		/* Set aside the jail's parameters. */
+		TAILQ_INIT(&opp);
+		TAILQ_CONCAT(&opp, &j->params, tq);
+		/*
+		 * The jail name implies its "name" or "jid" parameter,
+		 * though they may also be explicitly set later on.
+		 */
+		add_param(j, NULL,
+		    strtol(j->name, &ep, 10) && !*ep ? KP_JID : KP_NAME,
+		    j->name);
+		/*
+		 * Collect parameters for the jail, global parameters/variables,
+		 * and any matching wildcard jails.
+		 */
+		did_self = 0;
+		TAILQ_FOREACH(wj, &wild, tq) {
+			if (j->seq < wj->seq && !did_self) {
+				TAILQ_FOREACH(p, &opp, tq)
+					add_param(j, p, 0, NULL);
+				did_self = 1;
+			}
+			if (wild_jail_match(j->name, wj->name))
+				TAILQ_FOREACH(p, &wj->params, tq)
+					add_param(j, p, 0, NULL);
+		}
+		if (!did_self)
+			TAILQ_FOREACH(p, &opp, tq)
+				add_param(j, p, 0, NULL);
+
+		/* Resolve any variable substitutions. */
+		pgen = 0;
+		TAILQ_FOREACH(p, &j->params, tq) {
+		    p->gen = ++pgen;
+		find_vars:
+		    TAILQ_FOREACH(s, &p->val, tq) {
+			varoff = 0;
+			while ((v = STAILQ_FIRST(&s->vars))) {
+				TAILQ_FOREACH(vp, &j->params, tq)
+					if (!strcmp(vp->name, v->name))
+						break;
+				if (!vp) {
+					jail_warnx(j,
+					    "%s: variable \"%s\" not found",
+					    p->name, v->name);
+				bad_var:
+					j->flags |= JF_FAILED;
+					TAILQ_FOREACH(vp, &j->params, tq)
+						if (vp->gen == pgen)
+							vp->flags |= PF_BAD;
+					goto free_var;
+				}
+				if (vp->flags & PF_BAD)
+					goto bad_var;
+				if (vp->gen == pgen) {
+					jail_warnx(j, "%s: variable loop",
+					    v->name);
+					goto bad_var;
+				}
+				TAILQ_FOREACH(vs, &vp->val, tq)
+					if (!STAILQ_EMPTY(&vs->vars)) {
+						vp->gen = pgen;
+						TAILQ_REMOVE(&j->params, vp,
+						    tq);
+						TAILQ_INSERT_BEFORE(p, vp, tq);
+						p = vp;
+						goto find_vars;
+					}
+				vs = TAILQ_FIRST(&vp->val);
+				if (TAILQ_NEXT(vs, tq) != NULL &&
+				    (s->s[0] != '\0' ||
+				     STAILQ_NEXT(v, tq))) {
+					jail_warnx(j, "%s: array cannot be "
+					    "substituted inline",
+					    p->name);
+					goto bad_var;
+				}
+				s->s = erealloc(s->s, s->len + vs->len + 1);
+				memmove(s->s + v->pos + varoff + vs->len,
+				    s->s + v->pos + varoff,
+				    s->len - (v->pos + varoff) + 1);
+				memcpy(s->s + v->pos + varoff, vs->s, vs->len);
+				varoff += vs->len;
+				s->len += vs->len;
+				while ((vs = TAILQ_NEXT(vs, tq))) {
+					ns = emalloc(sizeof(struct cfstring));
+					ns->s = estrdup(vs->s);
+					ns->len = vs->len;
+					STAILQ_INIT(&ns->vars);
+					TAILQ_INSERT_AFTER(&p->val, s, ns, tq);
+					s = ns;
+				}
+			free_var:
+				free(v->name);
+				STAILQ_REMOVE_HEAD(&s->vars, tq);
+				free(v);
+			}
+		    }
+		}
+
+		/* Free the jail's original parameter list and any variables. */
+		while ((p = TAILQ_FIRST(&opp)))
+			free_param(&opp, p);
+		TAILQ_FOREACH_SAFE(p, &j->params, tq, tp)
+			if (p->flags & PF_VAR)
+				free_param(&j->params, p);
+	}
+	while ((wj = TAILQ_FIRST(&wild))) {
+		free(wj->name);
+		while ((p = TAILQ_FIRST(&wj->params)))
+			free_param(&wj->params, p);
+		TAILQ_REMOVE(&wild, wj, tq);
+	}
+}
+
+/*
+ * Create a new jail record.
+ */
+struct cfjail *
+add_jail(void)
+{
+	struct cfjail *j;
+
+	j = emalloc(sizeof(struct cfjail));
+	memset(j, 0, sizeof(struct cfjail));
+	TAILQ_INIT(&j->params);
+	STAILQ_INIT(&j->dep[DEP_FROM]);
+	STAILQ_INIT(&j->dep[DEP_TO]);
+	j->queue = &cfjails;
+	TAILQ_INSERT_TAIL(&cfjails, j, tq);
+	return j;
+}
+
+/*
+ * Add a parameter to a jail.
+ */
+void
+add_param(struct cfjail *j, const struct cfparam *p, enum intparam ipnum,
+    const char *value)
+{
+	struct cfstrings nss;
+	struct cfparam *dp, *np;
+	struct cfstring *s, *ns;
+	struct cfvar *v, *nv;
+	const char *name;
+	char *cs, *tname;
+	unsigned flags;
+
+	if (j == NULL) {
+		/* Create a single anonymous jail if one doesn't yet exist. */
+		j = TAILQ_LAST(&cfjails, cfjails);
+		if (j == NULL)
+			j = add_jail();
+	}
+	TAILQ_INIT(&nss);
+	if (p != NULL) {
+		name = p->name;
+		flags = p->flags;
+		/*
+		 * Make a copy of the parameter's string list,
+		 * which may be freed if it's overridden later.
+		 */
+		TAILQ_FOREACH(s, &p->val, tq) {
+			ns = emalloc(sizeof(struct cfstring));
+			ns->s = estrdup(s->s);
+			ns->len = s->len;
+			STAILQ_INIT(&ns->vars);
+			STAILQ_FOREACH(v, &s->vars, tq) {
+				nv = emalloc(sizeof(struct cfvar));
+				nv->name = strdup(v->name);
+				nv->pos = v->pos;
+				STAILQ_INSERT_TAIL(&ns->vars, nv, tq);
+			}
+			TAILQ_INSERT_TAIL(&nss, ns, tq);
+		}
+	} else {
+		flags = PF_APPEND;
+		if (ipnum != IP__NULL) {
+			name = intparams[ipnum].name;
+			flags |= intparams[ipnum].flags;
+		} else if ((cs = strchr(value, '='))) {
+			tname = alloca(cs - value + 1);
+			strlcpy(tname, value, cs - value + 1);
+			name = tname;
+			value = cs + 1;
+		} else {
+			name = value;
+			value = NULL;
+		}
+		if (value != NULL) {
+			ns = emalloc(sizeof(struct cfstring));
+			ns->s = estrdup(value);
+			ns->len = strlen(value);
+			STAILQ_INIT(&ns->vars);
+			TAILQ_INSERT_TAIL(&nss, ns, tq);
+		}
+	}
+
+	/* See if this parameter has already been added. */
+	if (ipnum != IP__NULL)
+		dp = j->intparams[ipnum];
+	else
+		TAILQ_FOREACH(dp, &j->params, tq)
+			if (!(dp->flags & PF_CONV) && equalopts(dp->name, name))
+				break;
+	if (dp != NULL) {
+		/* Found it - append or replace. */
+		if (strcmp(dp->name, name)) {
+			free(dp->name);
+			dp->name = estrdup(name);
+		}
+		if (!(flags & PF_APPEND) || TAILQ_EMPTY(&nss))
+			free_param_strings(dp);
+		TAILQ_CONCAT(&dp->val, &nss, tq);
+		dp->flags |= flags;
+	} else {
+		/* Not found - add it. */
+		np = emalloc(sizeof(struct cfparam));
+		np->name = estrdup(name);
+		TAILQ_INIT(&np->val);
+		TAILQ_CONCAT(&np->val, &nss, tq);
+		np->flags = flags;
+		np->gen = 0;
+		TAILQ_INSERT_TAIL(&j->params, np, tq);
+		if (ipnum != IP__NULL)
+			j->intparams[ipnum] = np;
+		else
+			for (ipnum = IP__NULL + 1; ipnum < IP_NPARAM; ipnum++)
+				if (!(intparams[ipnum].flags & PF_CONV) &&
+				    equalopts(name, intparams[ipnum].name)) {
+					j->intparams[ipnum] = np;
+					np->flags |= intparams[ipnum].flags;
+					break;
+				}
+	}
+}
+
+/*
+ * Return if a boolean parameter exists and is true.
+ */
+int
+bool_param(const struct cfparam *p)
+{
+	const char *cs;
+
+	if (p == NULL)
+		return 0;
+	cs = strrchr(p->name, '.');
+	return !strncmp(cs ? cs + 1 : p->name, "no", 2) ^
+	    (TAILQ_EMPTY(&p->val) ||
+	     !strcasecmp(TAILQ_LAST(&p->val, cfstrings)->s, "true") ||
+	     (strtol(TAILQ_LAST(&p->val, cfstrings)->s, NULL, 10)));
+}
+
+/*
+ * Set an integer if a parameter if it exists.
+ */
+int
+int_param(const struct cfparam *p, int *ip)
+{
+	if (p == NULL || TAILQ_EMPTY(&p->val))
+		return 0;
+	*ip = strtol(TAILQ_LAST(&p->val, cfstrings)->s, NULL, 10);
+	return 1;
+}
+
+/*
+ * Return the string value of a scalar parameter if it exists.
+ */
+const char *
+string_param(const struct cfparam *p)
+{
+	return (p && !TAILQ_EMPTY(&p->val)
+	    ? TAILQ_LAST(&p->val, cfstrings)->s : NULL);
+}
+
+/*
+ * Check syntax and values of internal parameters.  Set some internal
+ * parameters based on the values of others.
+ */
+int
+check_intparams(struct cfjail *j)
+{
+	struct cfparam *p;
+	struct cfstring *s;
+	FILE *f;
+	const char *val;
+	char *cs, *ep, *ln;
+	size_t lnlen;
+	int error;
+#if defined(INET) || defined(INET6)
+	struct addrinfo hints;
+	struct addrinfo *ai0, *ai;
+	const char *hostname;
+	int gicode, defif, prefix;
+#endif
+#ifdef INET
+	struct in_addr addr4;
+	int ip4ok;
+	char avalue4[INET_ADDRSTRLEN];
+#endif
+#ifdef INET6
+	struct in6_addr addr6;
+	int ip6ok;
+	char avalue6[INET6_ADDRSTRLEN];
+#endif
+
+	error = 0;
+	/* Check format of boolan and integer values. */
+	TAILQ_FOREACH(p, &j->params, tq) {
+		if (!TAILQ_EMPTY(&p->val) && (p->flags & (PF_BOOL | PF_INT))) {
+			val = TAILQ_LAST(&p->val, cfstrings)->s;
+			if (p->flags & PF_BOOL) {
+				if (strcasecmp(val, "false") &&
+				    strcasecmp(val, "true") &&
+				    ((void)strtol(val, &ep, 10), *ep)) {
+					jail_warnx(j,
+					    "%s: unknown boolean value \"%s\"",
+					    p->name, val);
+					error = -1;
+				}
+			} else {
+				(void)strtol(val, &ep, 10);
+				if (ep == val || *ep) {
+					jail_warnx(j,
+					    "%s: non-integer value \"%s\"",
+					    p->name, val);
+					error = -1;
+				}
+			}
+		}
+	}
+
+#if defined(INET) || defined(INET6)
+	/*
+	 * The ip_hostname parameter looks up the hostname, and adds parameters
+	 * for any IP addresses it finds.
+	 */
+	if (((j->flags & JF_OP_MASK) != JF_STOP ||
+	    j->intparams[IP_INTERFACE] != NULL) &&
+	    bool_param(j->intparams[IP_IP_HOSTNAME]) &&
+	    (hostname = string_param(j->intparams[KP_HOST_HOSTNAME]))) {
+		j->intparams[IP_IP_HOSTNAME] = NULL;
+		/*
+		 * Silently ignore unsupported address families from
+		 * DNS lookups.
+		 */
+#ifdef INET
+		ip4ok = feature_present("inet");
+#endif
+#ifdef INET6
+		ip6ok = feature_present("inet6");
+#endif
+		if (
+#if defined(INET) && defined(INET6)
+		    ip4ok || ip6ok
+#elif defined(INET)
+		    ip4ok
+#elif defined(INET6)
+		    ip6ok
+#endif
+			 ) {
+			/* Look up the hostname (or get the address) */
+			memset(&hints, 0, sizeof(hints));
+			hints.ai_socktype = SOCK_STREAM;
+			hints.ai_family =
+#if defined(INET) && defined(INET6)
+			    ip4ok ? (ip6ok ? PF_UNSPEC : PF_INET) :  PF_INET6;
+#elif defined(INET)
+			    PF_INET;
+#elif defined(INET6)
+			    PF_INET6;
+#endif
+			gicode = getaddrinfo(hostname, NULL, &hints, &ai0);
+			if (gicode != 0) {
+				jail_warnx(j, "host.hostname %s: %s", hostname,
+				    gai_strerror(gicode));
+				error = -1;
+			} else {
+				/*
+				 * Convert the addresses to ASCII so jailparam
+				 * can convert them back.  Errors are not
+				 * expected here.
+				 */
+				for (ai = ai0; ai; ai = ai->ai_next)
+					switch (ai->ai_family) {
+#ifdef INET
+					case AF_INET:
+						memcpy(&addr4,
+						    &((struct sockaddr_in *)
+						    (void *)ai->ai_addr)->
+						    sin_addr, sizeof(addr4));
+						if (inet_ntop(AF_INET,
+						    &addr4, avalue4,
+						    INET_ADDRSTRLEN) == NULL)
+							err(1, "inet_ntop");
+						add_param(j, NULL, KP_IP4_ADDR,
+						    avalue4);
+						break;
+#endif
+#ifdef INET6
+					case AF_INET6:
+						memcpy(&addr6,
+						    &((struct sockaddr_in6 *)
+						    (void *)ai->ai_addr)->
+						    sin6_addr, sizeof(addr6));
+						if (inet_ntop(AF_INET6,
+						    &addr6, avalue6,
+						    INET6_ADDRSTRLEN) == NULL)
+							err(1, "inet_ntop");
+						add_param(j, NULL, KP_IP6_ADDR,
+						    avalue6);
+						break;
+#endif
+					}
+				freeaddrinfo(ai0);
+			}
+		}
+	}
+
+	/*
+	 * IP addresses may include an interface to set that address on,
+	 * and a netmask/suffix for that address.
+	 */
+	defif = string_param(j->intparams[IP_INTERFACE]) != NULL;
+#ifdef INET
+	if (j->intparams[KP_IP4_ADDR] != NULL) {
+		TAILQ_FOREACH(s, &j->intparams[KP_IP4_ADDR]->val, tq) {
+			cs = strchr(s->s, '|');
+			if (cs || defif)
+				add_param(j, NULL, IP__IP4_IFADDR, s->s);
+			if (cs) {
+				strcpy(s->s, cs + 1);
+				s->len -= cs + 1 - s->s;
+			}
+			if ((cs = strchr(s->s, '/'))) {
+				prefix = strtol(cs + 1, &ep, 10);
+				if (*ep == '.'
+				    ? inet_pton(AF_INET, cs + 1, &addr4) != 1
+				    : *ep || prefix < 0 || prefix > 32) {
+					jail_warnx(j,
+					    "ip4.addr: bad netmask \"%s\"", cs);
+					error = -1;	
+				}
+				*cs = '\0';
+				s->len = cs - s->s + 1;
+			}
+		}
+	}
+#endif
+#ifdef INET6
+	if (j->intparams[KP_IP6_ADDR] != NULL) {
+		TAILQ_FOREACH(s, &j->intparams[KP_IP6_ADDR]->val, tq) {
+			cs = strchr(s->s, '|');
+			if (cs || defif)
+				add_param(j, NULL, IP__IP6_IFADDR, s->s);
+			if (cs) {
+				strcpy(s->s, cs + 1);
+				s->len -= cs + 1 - s->s;
+			}
+			if ((cs = strchr(s->s, '/'))) {
+				prefix = strtol(cs + 1, &ep, 10);
+				if (*ep || prefix < 0 || prefix > 128) {
+					jail_warnx(j,
+					    "ip6.addr: bad prefixlen \"%s\"",
+					    cs);
+					error = -1;	
+				}
+				*cs = '\0';
+				s->len = cs - s->s + 1;
+			}
+		}
+	}
+#endif
+#endif
+
+	/*
+	 * Read mount.fstab file(s), and treat each line as its own mount
+	 * parameter.
+	 */
+	if (j->intparams[IP_MOUNT_FSTAB] != NULL) {
+		TAILQ_FOREACH(s, &j->intparams[IP_MOUNT_FSTAB]->val, tq) {
+			if (s->len == 0)
+				continue;
+			f = fopen(s->s, "r");
+			if (f == NULL) {
+				jail_warnx(j, "mount.fstab: %s: %s",
+				    s->s, strerror(errno));
+				error = -1;
+				continue;
+			}
+			while ((ln = fgetln(f, &lnlen))) {
+				if ((cs = memchr(ln, '#', lnlen - 1)))
+					lnlen = cs - ln + 1;
+				if (ln[lnlen - 1] == '\n' ||
+				    ln[lnlen - 1] == '#')
+					ln[lnlen - 1] = '\0';
+				else {
+					cs = alloca(lnlen + 1);
+					strlcpy(cs, ln, lnlen + 1);
+					ln = cs;
+				}
+				add_param(j, NULL, IP__MOUNT_FROM_FSTAB, ln);
+			}
+			fclose(f);
+		}
+	}
+	if (error)
+		failed(j);
+	return error;
+}
+
+/*
+ * Import parameters into libjail's binary jailparam format.
+ */
+int
+import_params(struct cfjail *j)
+{
+	struct cfparam *p;
+	struct cfstring *s, *ts;
+	struct jailparam *jp;
+	char *value, *cs;
+	size_t vallen;
+	int error;
+
+	error = 0;
+	j->njp = 0;
+	TAILQ_FOREACH(p, &j->params, tq)
+		if (!(p->flags & PF_INTERNAL))
+			j->njp++;
+	j->jp = jp = emalloc(j->njp * sizeof(struct jailparam));
+	TAILQ_FOREACH(p, &j->params, tq) {
+		if (p->flags & PF_INTERNAL)
+			continue;
+		if (jailparam_init(jp, p->name) < 0) {
+			error = -1;
+			jail_warnx(j, "%s", jail_errmsg);
+			continue;
+		}
+		if (TAILQ_EMPTY(&p->val))
+			value = NULL;
+		else if (!jp->jp_elemlen ||
+			 !TAILQ_NEXT(TAILQ_FIRST(&p->val), tq)) {
+			/*
+			 * Scalar parameters silently discard multiple (array)
+			 * values, keeping only the last value added.  This
+			 * lets values added from the command line append to
+			 * arrays wthout pre-checking the type.
+			 */
+			value = TAILQ_LAST(&p->val, cfstrings)->s;
+		} else {
+			/*
+			 * Convert arrays into comma-separated strings, which
+			 * jailparam_import will then convert back into arrays.
+			 */
+			vallen = 0;
+			TAILQ_FOREACH(s, &p->val, tq)
+				vallen += s->len + 1;
+			value = alloca(vallen);
+			cs = value;
+			TAILQ_FOREACH_SAFE(s, &p->val, tq, ts) {
+				strcpy(cs, s->s);
+				if (ts != NULL) {
+					cs += s->len + 1;
+					cs[-1] = ',';
+				}
+			}
+		}
+		if (jailparam_import(jp, value) < 0) {
+			error = -1;
+			jail_warnx(j, "%s", jail_errmsg);
+		}
+		jp++;
+	}
+	if (error) {
+		jailparam_free(j->jp, j->njp);
+		free(j->jp);
+		j->jp = NULL;
+		failed(j);
+	}
+	return error;
+}
+
+/*
+ * Check if options are equal (with or without the "no" prefix).
+ */
+int
+equalopts(const char *opt1, const char *opt2)
+{
+	char *p;
+
+	/* "opt" vs. "opt" or "noopt" vs. "noopt" */
+	if (strcmp(opt1, opt2) == 0)
+		return (1);
+	/* "noopt" vs. "opt" */
+	if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
+		return (1);
+	/* "opt" vs. "noopt" */
+	if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
+		return (1);
+	while ((p = strchr(opt1, '.')) != NULL &&
+	    !strncmp(opt1, opt2, ++p - opt1)) {
+		opt2 += p - opt1;
+		opt1 = p;
+		/* "foo.noopt" vs. "foo.opt" */
+		if (strncmp(opt1, "no", 2) == 0 && strcmp(opt1 + 2, opt2) == 0)
+			return (1);
+		/* "foo.opt" vs. "foo.noopt" */
+		if (strncmp(opt2, "no", 2) == 0 && strcmp(opt1, opt2 + 2) == 0)
+			return (1);
+	}
+	return (0);
+}
+
+/*
+ * See if a jail name matches a wildcard.
+ */
+int
+wild_jail_match(const char *jname, const char *wname)
+{
+	const char *jc, *jd, *wc, *wd;
+
+	/*
+	 * A non-final "*" component in the wild name matches a single jail
+	 * component, and a final "*" matches one or more jail components.
+	 */
+	for (jc = jname, wc = wname;
+	     (jd = strchr(jc, '.')) && (wd = strchr(wc, '.'));
+	     jc = jd + 1, wc = wd + 1)
+		if (strncmp(jc, wc, jd - jc + 1) && strncmp(wc, "*.", 2))
+			return 0;
+	return (!strcmp(jc, wc) || !strcmp(wc, "*"));
+}
+
+/*
+ * Return if a jail name is a wildcard.
+ */
+int
+wild_jail_name(const char *wname)
+{
+	const char *wc;
+
+	for (wc = strchr(wname, '*'); wc; wc = strchr(wc + 1, '*'))
+		if ((wc == wname || wc[-1] == '.') &&
+		    (wc[1] == '\0' || wc[1] == '.'))
+			return 1;
+	return 0;
+}
+
+/*
+ * Free a parameter record and all its strings and variables.
+ */
+static void
+free_param(struct cfparams *pp, struct cfparam *p)
+{
+	free(p->name);
+	free_param_strings(p);
+	TAILQ_REMOVE(pp, p, tq);
+	free(p);
+}
+
+static void
+free_param_strings(struct cfparam *p)
+{
+	struct cfstring *s;
+	struct cfvar *v;
+
+	while ((s = TAILQ_FIRST(&p->val))) {
+		free(s->s);
+		while ((v = STAILQ_FIRST(&s->vars))) {
+			free(v->name);
+			STAILQ_REMOVE_HEAD(&s->vars, tq);
+			free(v);
+		}
+		TAILQ_REMOVE(&p->val, s, tq);
+		free(s);
+	}
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/jail.8
--- a/head/usr.sbin/jail/jail.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/jail/jail.8	Wed Jul 25 16:29:58 2012 +0300
@@ -1,6 +1,5 @@
-.\"
 .\" Copyright (c) 2000, 2003 Robert N. M. Watson
-.\" Copyright (c) 2008 James Gritton
+.\" Copyright (c) 2008-2012 James Gritton
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -24,116 +23,68 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
+.\" $FreeBSD: head/usr.sbin/jail/jail.8 236509 2012-06-03 11:29:48Z joel $
 .\"
-.\" ----------------------------------------------------------------------------
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <phk at 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
-.\" ----------------------------------------------------------------------------
-.\"
-.\" $FreeBSD: head/usr.sbin/jail/jail.8 232291 2012-02-29 07:33:07Z mm $
-.\"
-.Dd February 29, 2012
+.Dd May 23, 2012
 .Dt JAIL 8
 .Os
 .Sh NAME
 .Nm jail
-.Nd "create or modify a system jail"
+.Nd "manage system jails"
 .Sh SYNOPSIS
 .Nm
-.Op Fl dhi
+.Op Fl dhilqv
 .Op Fl J Ar jid_file
-.Op Fl l u Ar username | Fl U Ar username
-.Op Fl c | m
-.Op Ar parameter=value ...
+.Op Fl u Ar username
+.Op Fl U Ar username
+.Op Fl cmr
+.Ar param Ns = Ns Ar value ...
+.Op Cm command Ns = Ns Ar command ...
 .Nm
-.Op Fl hi
+.Op Fl dqv
+.Op Fl f Ar conf_file
+.Op Fl p Ar limit
+.Op Fl cmr
+.Op Ar jail
+.Nm
+.Op Fl qv
+.Op Fl f Ar conf_file
+.Op Fl rR
+.Op Cm * | Ar jail ...
+.Nm
+.Op Fl dhilqv
+.Op Fl J Ar jid_file
+.Op Fl u Ar username
+.Op Fl U Ar username
 .Op Fl n Ar jailname
-.Op Fl J Ar jid_file
 .Op Fl s Ar securelevel
-.Op Fl l u Ar username | Fl U Ar username
-.Op Ar path hostname [ip[,..]] command ...
-.Nm
-.Op Fl r Ar jail
+.Op Ar path hostname [ Ar ip Ns [ Ns Ar ,... Ns ]] Ar command ...
 .Sh DESCRIPTION
 The
 .Nm
-utility creates a new jail or modifies an existing jail, optionally
-imprisoning the current process (and future descendants) inside it.
+utility creates new jails, or modifies or removes existing jails.
+A jail is specified via parameters on the command line, or in the
+.Xr jail.conf 5
+file.
 .Pp
-The options are as follows:
+At least one of the options
+.Fl c ,
+.Fl m
+or
+.Fl r
+must be specified.
+These options are used alone or in combination describe the operation to
+perform:
 .Bl -tag -width indent
-.It Fl d
-Allow making changes to a dying jail.
-.It Fl h
-Resolve the
-.Va host.hostname
-parameter (or
-.Va hostname )
-and add all IP addresses returned by the resolver
-to the list of
-.Va ip
-addresses for this prison.
-This may affect default address selection for outgoing IPv4 connections
-of prisons.
-The address first returned by the resolver for each address family
-will be used as primary address.
-See the
-.Va ip4.addr
-and
-.Va ip6.addr
-parameters further down for details.
-.It Fl i
-Output the jail identifier of the newly created jail.
-.It Fl n Ar jailname
-Set the jail's name.
-This is deprecated and is equivalent to setting the
-.Va name
-parameter.
-.It Fl J Ar jid_file
-Write a
-.Ar jid_file
-file, containing jail identifier, path, hostname, IP and
-command used to start the jail.
-.It Fl l
-Run program in the clean environment.
-The environment is discarded except for
-.Ev HOME , SHELL , TERM
-and
-.Ev USER .
-.Ev HOME
-and
-.Ev SHELL
-are set to the target login's default values.
-.Ev USER
-is set to the target login.
-.Ev TERM
-is imported from the current environment.
-The environment variables from the login class capability database for the
-target login are also set.
-.It Fl s Ar securelevel
-Set the
-.Va kern.securelevel
-MIB entry to the specified value inside the newly created jail.
-This is deprecated and is equivalent to setting the
-.Va securelevel
-parameter.
-.It Fl u Ar username
-The user name from host environment as whom the
-.Ar command
-should run.
-.It Fl U Ar username
-The user name from jailed environment as whom the
-.Ar command
-should run.
 .It Fl c
 Create a new jail.
-The
+The jail
 .Va jid
 and
 .Va name
-parameters (if specified) must not refer to an existing jail.
+parameters (if specified) on the command line,
+or any jails
+must not refer to an existing jail.
 .It Fl m
 Modify an existing jail.
 One of the
@@ -141,27 +92,158 @@
 or
 .Va name
 parameters must exist and refer to an existing jail.
-.It Fl cm
-Create a jail if it does not exist, or modify a jail if it does exist.
+Some parameters may not be changed on a running jail.
 .It Fl r
 Remove the
 .Ar jail
 specified by jid or name.
 All jailed processes are killed, and all children of this jail are also
 removed.
+.It Fl rc
+Restart an existing jail.
+The jail is first removed and then re-created, as if
+.Dq Nm Fl c
+and
+.Dq Nm Fl r
+were run in succession.
+.It Fl cm
+Create a jail if it does not exist, or modify the jail if it does exist.
+.It Fl mr
+Modify an existing jail.
+The jail may be restarted if necessary to modify parameters than could
+not otherwise be changed.
+.It Fl cmr
+Create a jail if it doesn't exist, or modify (and possibly restart) the
+jail if it does exist.
 .El
 .Pp
-At least one of the
-.Fl c ,
+Other available options are:
+.Bl -tag -width indent
+.It Fl d
+Allow making changes to a dying jail, equivalent to the
+.Va allow.dying
+parameter.
+.It Fl f Ar conf_file
+Use configuration file
+.Ar conf_file
+instead of the default
+.Pa /etc/jail.conf .
+.It Fl h
+Resolve the
+.Va host.hostname
+parameter (or
+.Va hostname )
+and add all IP addresses returned by the resolver
+to the list of addresses for this prison.
+This is equivalent to the
+.Va ip_hostname
+parameter.
+.It Fl i
+Output (only) the jail identifier of the newly created jail(s).
+This implies the
+.Fl q
+option.
+.It Fl J Ar jid_file
+Write a
+.Ar jid_file
+file, containing parameters used to start the jail.
+.It Fl l
+Run commands in a clean environment.
+This is deprecated and is equivalent to the exec.clean parameter.
+.It Fl n Ar jailname
+Set the jail's name.
+This is deprecated and is equivalent to the
+.Va name
+parameter.
+.It Fl p Ar limit
+Limit the number of commands from
+.Va  exec.*
+that can run simultaneously.
+.It Fl q
+Suppress the message printed whenever a jail is created, modified or removed.
+Only error messages will be printed.
+.It Fl R
+A variation of the
+.Fl r
+option that removes an existing jail without using the configuration file.
+No removal-related parameters for this jail will be used - the jail will
+simply be removed.
+.It Fl s Ar securelevel
+Set the
+.Va kern.securelevel
+MIB entry to the specified value inside the newly created jail.
+This is deprecated and is equivalent to the
+.Va securelevel
+parameter.
+.It Fl u Ar username
+The user name from host environment as whom jailed commands should run.
+This is deprecated and is equivalent to the
+.Va exec.jail_user
+and
+.Va exec.system_jail_user
+parameters.
+.It Fl U Ar username
+The user name from jailed environment as whom jailed commands should run.
+This is deprecated and is equivalent to the
+.Va exec.jail_user
+parameter.
+.It Fl v
+Print a message on every operation, such as running commands and
+mounting filesystems.
+.El
+.Pp
+If no arguments are given after the options, the operation (except
+remove) will be performed on all jails specified in the
+.Xr jail.conf 5
+file.
+A single argument of a jail name will operate only on the specified jail.
+The
+.Fl r
+and
+.Fl R
+options can also remove running jails that aren't in the
+.Xr jail.conf 5
+file, specified by name or jid.
+.Pp
+An argument of
+.Dq *
+is a wildcard that will operate on all jails, regardless of whether
+they appear in
+.Xr jail.conf 5 ;
+this is the surest way for
+.Fl r
+to remove all jails.
+If hierarchical jails exist, a partial-matching wildcard definition may
+be specified.
+For example, an argument of
+.Dq foo.*
+would apply to jails with names like
+.Dq foo.bar
+and
+.Dq foo.bar.baz .
+.Pp
+A jail may be specified with parameters directly on the command line.
+In this case, the
+.Xr jail.conf 5
+file will not be used.
+For backward compatibility, the command line may also have four fixed
+parameters, without names:
+.Ar path ,
+.Ar hostname ,
+.Ar ip ,
+and
+.Ar command .
+This mode will always create a new jail, and the
+.Fl c
+and
 .Fl m
-or
-.Fl r
-options must be specified.
-.Pp
-.Ar Parameters
-are listed in
+options don't apply (and must not exist).
+.Ss Jail Parameters
+Parameters in the
+.Xr jail.conf 5
+file, or on the command line, are generally in
 .Dq name=value
-form, following the options.
+form.
 Some parameters are boolean, and do not have a value but are set by the
 name alone with or without a
 .Dq no
@@ -169,41 +251,35 @@
 .Va persist
 or
 .Va nopersist .
+They can also be given the values
+.Dq true
+and
+.Dq false .
+Other parameters may have more than one value, specified as a
+comma-separated list or with
+.Dq +=
+in the configuration file (see
+.Xr jail.conf 5
+for details).
+.Pp
+The
+.Nm
+utility recognizes two classes of parameters.  There are the true jail
+parameters that are passed to the kernel when the jail is created,
+can be seen with
+.Xr jls 8 ,
+and can (usually) be changed with
+.Dq Nm Fl m .
+Then there are pseudo-parameters that are only used by
+.Nm
+itself.
+.Pp
+Jails have a set a core parameters, and kernel modules can add their own
+jail parameters.
+The current set of available parameters can be retrieved via
+.Dq Nm sysctl Fl d Va security.jail.param .
 Any parameters not set will be given default values, often based on the
 current environment.
-.Pp
-The pseudo-parameter
-.Va command
-specifies that the current process should enter the new (or modified) jail,
-and run the specified command.
-It must be the last parameter specified, because it includes not only
-the value following the
-.Sq =
-sign, but also passes the rest of the arguments to the command.
-.Pp
-Instead of supplying named
-.Ar parameters ,
-four fixed parameters may be supplied in order on the command line:
-.Ar path ,
-.Ar hostname ,
-.Ar ip ,
-and
-.Ar command .
-As the
-.Va jid
-and
-.Va name
-parameters aren't in this list, this mode will always create a new jail, and
-the
-.Fl c
-and
-.Fl m
-options don't apply (and must not exist).
-.Pp
-Jails have a set a core parameters, and modules can add their own jail
-parameters.
-The current set of available parameters can be retrieved via
-.Dq Nm sysctl Fl d Va security.jail.param .
 The core parameters are:
 .Bl -tag -width indent
 .It Va jid
@@ -231,14 +307,21 @@
 .Va name
 is supplied, a default is assumed that is the same as the
 .Va jid .
+The
+.Va name
+parameter is implied by the
+.Xr jail.conf 5
+file format, and need not be explicitly set when using the configuration
+file.
 .It Va path
-Directory which is to be the root of the prison.
-The
-.Va command
-(if any) is run from this directory, as are commands from
-.Xr jexec 8 .
+The directory which is to be the root of the prison.
+Any commands run inside the prison, either by
+.Nm
+or from
+.Xr jexec 8 ,
+are run from this directory.
 .It Va ip4.addr
-A comma-separated list of IPv4 addresses assigned to the prison.
+A list of IPv4 addresses assigned to the prison.
 If this is set, the jail is restricted to using only these addresses.
 Any attempts to use other addresses fail, and attempts to use wildcard
 addresses silently use the jailed address instead.
@@ -252,7 +335,7 @@
 A boolean option to change the formerly mentioned behaviour and disable
 IPv4 source address selection for the prison in favour of the primary
 IPv4 address of the jail.
-Source address selection is enabled by default for all jails and a
+Source address selection is enabled by default for all jails and the
 .Va ip4.nosaddrsel
 setting of a parent jail is not inherited for any child jails.
 .It Va ip4
@@ -277,8 +360,20 @@
 and
 .Va ip4
 above.
+.It vnet
+Create the prison with its own virtual network stack,
+with its own network interfaces, addresses, routing table, etc.
+The kernel must have been compiled with the
+.Sy VIMAGE option
+for this to be available.
+Possible values are
+.Dq inherit
+to use the system network stack, possibly with restricted IP addresses,
+and
+.Dq new
+to create a new network stack.
 .It Va host.hostname
-Hostname of the prison.
+The hostname of the prison.
 Other similar parameters are
 .Va host.domainname ,
 .Va host.hostuuid
@@ -314,16 +409,27 @@
 .Va enforce_statfs
 is set to a value lower than 2.
 Devfs rules and rulesets cannot be viewed or modified from inside a jail.
+.Pp
+NOTE: It is important that only appropriate device nodes in devfs be
+exposed to a jail; access to disk devices in the jail may permit processes
+in the jail to bypass the jail sandboxing by modifying files outside of
+the jail.
+See
+.Xr devfs 8
+for information on how to use devfs rules to limit access to entries
+in the per-jail devfs.
+A simple devfs ruleset for jails is available as ruleset #4 in
+.Pa /etc/defaults/devfs.rules .
 .It Va children.max
 The number of child jails allowed to be created by this jail (or by
 other jails under this jail).
 This limit is zero by default, indicating the jail is not allowed to
 create child jails.
 See the
-.Va "Hierarchical Jails"
+.Sx "Hierarchical Jails"
 section for more information.
 .It Va children.cur
-The number of descendents of this jail, including its own child jails
+The number of descendants of this jail, including its own child jails
 and any jails created under them.
 .It Va enforce_statfs
 This determines which information processes in a jail are able to get
@@ -345,10 +451,13 @@
 .It Va persist
 Setting this boolean parameter allows a jail to exist without any
 processes.
-Normally, a jail is destroyed as its last process exits.
+Normally, a command is run as part of jail creation, and then the jail
+is destroyed as its last process exits.
 A new jail must have either the
 .Va persist
 parameter or
+.Va exec.start
+or
 .Va command
 pseudo-parameter set.
 .It Va cpuset.id
@@ -459,6 +568,172 @@
 .El
 .El
 .Pp
+There are pseudo-parameters that aren't passed to the kernel, but are
+used by
+.Nm
+to set up the prison environment, often by running specified commands
+when jails are created or removed.
+The
+.Va exec.*
+command parameters are
+.Xr sh 1
+command lines that are run in either the system or prison environment.
+They may be given multiple values, which run would the specified
+commands in sequence.
+All commands must succeed (return a zero exit status), or the jail will
+not be created or removed.
+.Pp
+The pseudo-parameters are:
+.Bl -tag -width indent
+.It Va exec.prestart
+Command(s) to run in the system environment before a prison is created.
+.It Va exec.start
+Command(s) to run in the prison environment when a jail is created.
+A typical command to run is
+.Dq sh /etc/rc .
+.It Va command
+A synonym for
+.Va exec.start
+for use when specifying a prison directly on the command line.
+Unlike other parameters whose value is a single string,
+.Va command
+uses the remainder of the
+.Nm
+command line as its own arguments.
+.It Va exec.poststart
+Command(s) to run in the system environment after a jail is created,
+and after any
+.Va exec.start
+commands have completed.
+.It Va exec.prestop
+Command(s) to run in the system environment before a jail is removed.
+.It Va exec.stop
+Command(s) to run in the prison environment before a jail is removed,
+and after any
+.Va exec.prestop
+commands have completed.
+A typical command to run is
+.Dq sh /etc/rc.shutdown .
+.It Va exec.poststop
+Command(s) to run in the system environment after a jail is removed.
+.It Va exec.clean
+Run commands in a clean environment.
+The environment is discarded except for
+.Ev HOME , SHELL , TERM
+and
+.Ev USER .
+.Ev HOME
+and
+.Ev SHELL
+are set to the target login's default values.
+.Ev USER
+is set to the target login.
+.Ev TERM
+is imported from the current environment.
+The environment variables from the login class capability database for the
+target login are also set.
+.It Va exec.jail_user
+The user to run commands as, when running in the prison environment.
+The default is to run the commands as the current user.
+.It Va exec.system_jail_user
+This boolean option looks for the
+.Va exec.jail_user
+in the system
+.Xr passwd 5
+file, instead of in the prison's file.
+.It Va exec.system_user
+The user to run commands as, when running in the system environment.
+The default is to run the commands as the current user.
+.It Va exec.timeout
+The maximum amount of time to wait for a command to complete.
+If a command is still running after this many seconds have passed,
+the jail not be created or removed.
+.It Va exec.consolelog
+A file to direct command output (stdout and stderr) to.
+.It Va exec.fib
+The FIB (routing table) to set when running commands inside the prison.
+.It Va stop.timeout
+The maximum amount of time to wait for a prison's processes to exit
+after sending them a
+.Dv SIGTERM
+signal (which happens after the
+.Va exec.stop
+commands have completed).
+After this many seconds have passed, the prison will be removed, which
+will kill any remaining processes.
+If this is set to zero, no
+.Dv SIGTERM
+is sent and the prison is immediately removed.
+The default is 10 seconds.
+.It Va interface
+A network interface to add the prison's IP addresses
+.Va ( ip4.addr
+and
+.Va ip6.addr )
+to.
+An alias for each address will be added to the interface before the
+prison is created, and will be removed from the interface after the
+prison is removed.
+.It Op Va ip4.addr
+In addition to the IP addresses that are passed to the kernel, and
+interface and/or a netmask may also be specified, in the form
+.Dq Ar interface Ns | Ns Ar ip-address Ns / Ns Ar netmask .
+If an interface is given before the IP address, an alias for the address
+will be added to that interface, as it is with the
+.Va interface
+parameter.  If a netmask in either dotted-quad or CIDR form is given
+after IP address, it will be used when adding the IP alias.
+.It Op Va ip6.addr
+In addition to the IP addresses that are passed to the kernel,
+and interface and/or a prefix may also be specified, in the form
+.Dq Ar interface Ns | Ns Ar ip-address Ns / Ns Ar prefix .
+.It Va vnet.interface
+A network interface to give to a vnet-enabled jail after is it created.
+The interface will automatically be returned when the jail is removed.
+.It Va ip_hostname
+Resolve the
+.Va host.hostname
+parameter and add all IP addresses returned by the resolver
+to the list of addresses
+.Va ( ip4.addr
+or
+.Va ip6.addr )
+for this prison.
+This may affect default address selection for outgoing IPv4 connections
+of prisons.
+The address first returned by the resolver for each address family
+will be used as primary address.
+.It Va mount
+A filesystem to mount before creating the jail (and to unmount after
+removing it), given as a single
+.Xr fstab 5
+line.
+.It Va mount.fstab
+An
+.Xr fstab 5
+format file containing filesystems to mount before creating a jail.
+.It Va mount.devfs
+Mount a
+.Xr devfs
+filesystem on the chrooted /dev directory, and apply the ruleset in the
+.Va devfs_ruleset
+parameter (or a default of ruleset 4: devfsrules_jail)
+to restrict the devices visible inside the prison.
+.It Va allow.dying
+Allow making changes to a
+.Va dying
+jail.
+.It Va depend
+Specify a jail (or jails) that this jail depends on.
+Any such jails must be fully created, up to the last
+.Va exec.poststart
+command, before any action will taken to create this jail.
+When jails are removed the opposite is true:
+this jail must be fully removed, up to the last
+.Va exec.poststop
+command, before the jail(s) it depends on are stopped.
+.El
+.Sh EXAMPLES
 Jails are typically set up using one of two philosophies: either to
 constrain a specific application (possibly running with privilege), or
 to create a
@@ -476,7 +751,6 @@
 This manual page documents the configuration steps necessary to support
 either of these steps, although the configuration steps may be
 refined based on local requirements.
-.Sh EXAMPLES
 .Ss "Setting up a Jail Directory Tree"
 To set up a jail directory tree containing an entire
 .Fx
@@ -489,20 +763,8 @@
 mkdir -p $D
 make world DESTDIR=$D
 make distribution DESTDIR=$D
-mount -t devfs devfs $D/dev
 .Ed
 .Pp
-NOTE: It is important that only appropriate device nodes in devfs be
-exposed to a jail; access to disk devices in the jail may permit processes
-in the jail to bypass the jail sandboxing by modifying files outside of
-the jail.
-See
-.Xr devfs 8
-for information on how to use devfs rules to limit access to entries
-in the per-jail devfs.
-A simple devfs ruleset for jails is available as ruleset #4 in
-.Pa /etc/defaults/devfs.rules .
-.Pp
 In many cases this example would put far more in the jail than needed.
 In the other extreme case a jail might contain only one file:
 the executable to be run in the jail.
@@ -520,8 +782,9 @@
 to build the jail directory tree.
 For the sake of this example, we will
 assume you built it in
-.Pa /data/jail/192.0.2.100 ,
-named for the jailed IP address.
+.Pa /data/jail/testjail ,
+for a jail named
+.Dq testjail .
 Substitute below as needed with your
 own directory, IP address, and hostname.
 .Ss "Setting up the Host Environment"
@@ -619,7 +882,7 @@
 .Pp
 Start a shell in the jail:
 .Bd -literal -offset indent
-jail -c path=/data/jail/192.0.2.100 host.hostname=testhostname \\
+jail -c path=/data/jail/testjail mount.devfs host.hostname=testhostname \\
 	ip4.addr=192.0.2.100 command=/bin/sh
 .Ed
 .Pp
@@ -633,15 +896,6 @@
 .Pp
 .Bl -bullet -offset indent -compact
 .It
-Create an empty
-.Pa /etc/fstab
-to quell startup warnings about missing fstab (virtual server only)
-.It
-Disable the port mapper
-.Pa ( /etc/rc.conf :
-.Li rpcbind_enable="NO" )
-(virtual server only)
-.It
 Configure
 .Pa /etc/resolv.conf
 so that name resolution within the jail will work correctly
@@ -652,11 +906,6 @@
 .Xr sendmail 8
 warnings.
 .It
-Disable interface configuration to quell startup warnings about
-.Xr ifconfig 8
-.Pq Li network_interfaces=""
-(virtual server only)
-.It
 Set a root password, probably different from the real host system
 .It
 Set the timezone
@@ -674,36 +923,47 @@
 .Xr syslogd 8
 in the host environment to listen on the syslog socket in the jail
 environment; in this example, the syslog socket would be stored in
-.Pa /data/jail/192.0.2.100/var/run/log .
+.Pa /data/jail/testjail/var/run/log .
 .Pp
 Exit from the shell, and the jail will be shut down.
 .Ss "Starting the Jail"
 You are now ready to restart the jail and bring up the environment with
 all of its daemons and other programs.
-If you are running a single application in the jail, substitute the
-command used to start the application for
-.Pa /etc/rc
-in the examples below.
+Create an entry for the jail in
+.Pa /etc/jail.conf :
+.Bd -literal -offset indent
+testjail {
+	path = /tmp/jail/testjail;
+	mount.devfs;
+	host.hostname = testhostname;
+	ip4.addr = 192.0.2.100;
+	interface = ed0;
+	exec.start = "/bin/sh /etc/rc";
+	exec.stop = "/bin/sh /etc/rc.shutdown";
+}
+.Ed
+.Pp
 To start a virtual server environment,
 .Pa /etc/rc
-is run to launch various daemons and services.
-To do this, first bring up the
-virtual host interface, and then start the jail's
-.Pa /etc/rc
-script from within the jail.
+is run to launch various daemons and services, and
+.Pa /etc/rc.shutdown
+is run to shut them down when the jail is removed.
+If you are running a single application in the jail,
+substitute the command used to start the application for
+.Dq /bin/sh /etc/rc ;
+there may be some script available to cleanly shut down the application,
+or it may be sufficient to go without a stop command, and have
+.Nm
+send
+.Dv SIGTERM
+to the application.
+.Pp
+Start the jail by running:
 .Bd -literal -offset indent
-ifconfig ed0 inet alias 192.0.2.100/32
-mount -t procfs proc /data/jail/192.0.2.100/proc
-jail -c path=/data/jail/192.0.2.100 host.hostname=testhostname \\
-	ip4.addr=192.0.2.100 command=/bin/sh /etc/rc
+jail -c testjail
 .Ed
 .Pp
-A few warnings will be produced, because most
-.Xr sysctl 8
-configuration variables cannot be set from within the jail, as they are
-global across all jails and the host environment.
-However, it should all
-work properly.
+A few warnings may be produced; however, it should all work properly.
 You should be able to see
 .Xr inetd 8 ,
 .Xr syslogd 8 ,
@@ -726,15 +986,6 @@
 variables in
 .Xr rc.conf 5
 for more information.
-The
-.Xr rc 8
-jail script provides a flexible system to start/stop jails:
-.Bd -literal
-/etc/rc.d/jail start
-/etc/rc.d/jail stop
-/etc/rc.d/jail start myjail
-/etc/rc.d/jail stop myjail
-.Ed
 .Ss "Managing the Jail"
 Normal machine shutdown commands, such as
 .Xr halt 8 ,
@@ -742,9 +993,8 @@
 and
 .Xr shutdown 8 ,
 cannot be used successfully within the jail.
-To kill all processes in a
-jail, you may log into the jail and, as root, use one of the following
-commands, depending on what you want to accomplish:
+To kill all processes from within a jail, you may use one of the
+following commands, depending on what you want to accomplish:
 .Bd -literal -offset indent
 kill -TERM -1
 kill -KILL -1
@@ -754,21 +1004,27 @@
 .Dv SIGTERM
 or
 .Dv SIGKILL
-signals to all processes in the jail from within the jail.
+signals to all processes in the jail - be careful not to run this from
+the host environment!
+Once all of the jail's processes have died, unless the jail was created
+with the
+.Va persist
+parameter, the jail will be removed.
 Depending on
 the intended use of the jail, you may also want to run
 .Pa /etc/rc.shutdown
 from within the jail.
-To kill processes from outside the jail, use the
-.Xr jexec 8
-utility in conjunction with the one of the
-.Xr kill 1
-commands above.
-You may also remove the jail with
+.Pp
+To shut down the jail from the outside, simply remove it with
 .Nm
 .Ar -r ,
-which will killall the jail's processes with
-.Dv SIGKILL .
+which will run any commands specified by
+.Va exec.stop ,
+and then send
+.Dv SIGTERM
+and eventually
+.Dv SIGKILL
+to any remaining jailed processes.
 .Pp
 The
 .Pa /proc/ Ns Ar pid Ns Pa /status
@@ -888,7 +1144,7 @@
 .Pp
 Like the names, a child jail's
 .Va path
-is relative to its creator's own
+appears relative to its creator's own
 .Va path .
 This is by virtue of the child jail being created in the chrooted
 environment of the first jail.
@@ -900,12 +1156,12 @@
 .Xr pkill 1 ,
 .Xr ps 1 ,
 .Xr quota 1 ,
-.Xr chroot 2 ,
 .Xr jail_set 2 ,
-.Xr jail_attach 2 ,
+.Xr jail.conf 5 ,
 .Xr procfs 5 ,
 .Xr rc.conf 5 ,
 .Xr sysctl.conf 5 ,
+.Xr chroot 8 ,
 .Xr devfs 8 ,
 .Xr halt 8 ,
 .Xr inetd 8 ,
@@ -927,6 +1183,8 @@
 .Fx 4.0 .
 Hierarchical/extensible jails were introduced in
 .Fx 8.0 .
+The configuration file was introduced in
+.Fx 9.1 .
 .Sh AUTHORS
 .An -nosplit
 The jail feature was written by
@@ -947,14 +1205,10 @@
 for IPv4.
 .Pp
 .An James Gritton
-added the extensible jail parameters and hierarchical jails.
+added the extensible jail parameters, hierarchical jails,
+and the configuration file.
 .Sh BUGS
-Jail currently lacks the ability to allow access to
-specific jail information via
-.Xr ps 1
-as opposed to
-.Xr procfs 5 .
-Similarly, it might be a good idea to add an
+It might be a good idea to add an
 address alias flag such that daemons listening on all IPs
 .Pq Dv INADDR_ANY
 will not bind on that address, which would facilitate building a safe
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/jail.c
--- a/head/usr.sbin/jail/jail.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/jail/jail.c	Wed Jul 25 16:29:58 2012 +0300
@@ -1,6 +1,6 @@
 /*-
  * Copyright (c) 1999 Poul-Henning Kamp.
- * Copyright (c) 2009 James Gritton
+ * Copyright (c) 2009-2012 James Gritton
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,157 +26,192 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/jail/jail.c 230495 2012-01-24 08:04:38Z mm $");
+__FBSDID("$FreeBSD: head/usr.sbin/jail/jail.c 237697 2012-06-28 08:25:19Z maxim $");
 
-#include <sys/param.h>
-#include <sys/jail.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-#include <ctype.h>
 #include <err.h>
 #include <errno.h>
-#include <grp.h>
-#include <jail.h>
-#include <login_cap.h>
-#include <netdb.h>
-#include <paths.h>
-#include <pwd.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-static struct jailparam *params;
-static char **param_values;
-static int nparams;
+#include "jailp.h"
 
+#define JP_RDTUN(jp)	(((jp)->jp_ctltype & CTLFLAG_RDTUN) == CTLFLAG_RDTUN)
+
+struct permspec {
+	const char	*name;
+	enum intparam	ipnum;
+	int		rev;
+};
+
+const char *cfname;
+int iflag;
+int note_remove;
+int verbose;
+
+static void clear_persist(struct cfjail *j);
+static int update_jail(struct cfjail *j);
+static int rdtun_params(struct cfjail *j, int dofail);
+static void running_jid(struct cfjail *j, int dflag);
+static void jail_quoted_warnx(const struct cfjail *j, const char *name_msg,
+    const char *noname_msg);
+static int jailparam_set_note(const struct cfjail *j, struct jailparam *jp,
+    unsigned njp, int flags);
+static void print_jail(FILE *fp, struct cfjail *j, int oldcl);
+static void print_param(FILE *fp, const struct cfparam *p, int sep, int doname);
+static void quoted_print(FILE *fp, char *str);
+static void usage(void);
+
+static struct permspec perm_sysctl[] = {
+    { "security.jail.set_hostname_allowed", KP_ALLOW_SET_HOSTNAME, 0 },
+    { "security.jail.sysvipc_allowed", KP_ALLOW_SYSVIPC, 0 },
+    { "security.jail.allow_raw_sockets", KP_ALLOW_RAW_SOCKETS, 0 },
+    { "security.jail.chflags_allowed", KP_ALLOW_CHFLAGS, 0 },
+    { "security.jail.mount_allowed", KP_ALLOW_MOUNT, 0 },
+    { "security.jail.socket_unixiproute_only", KP_ALLOW_SOCKET_AF, 1 },
+};
+
+static const enum intparam startcommands[] = {
+    IP__NULL,
+#ifdef INET
+    IP__IP4_IFADDR,
+#endif
 #ifdef INET6
-static int ip6_ok;
-static char *ip6_addr;
+    IP__IP6_IFADDR,
+#endif
+    IP_MOUNT,
+    IP__MOUNT_FROM_FSTAB,
+    IP_MOUNT_DEVFS,
+    IP_EXEC_PRESTART, 
+    IP__OP,
+    IP_VNET_INTERFACE,
+    IP_EXEC_START,
+    IP_COMMAND,
+    IP_EXEC_POSTSTART,
+    IP__NULL
+};
+
+static const enum intparam stopcommands[] = {
+    IP__NULL,
+    IP_EXEC_PRESTOP,
+    IP_EXEC_STOP,
+    IP_STOP_TIMEOUT,
+    IP__OP,
+    IP_EXEC_POSTSTOP,
+    IP_MOUNT_DEVFS,
+    IP__MOUNT_FROM_FSTAB,
+    IP_MOUNT,
+#ifdef INET6
+    IP__IP6_IFADDR,
 #endif
 #ifdef INET
-static int ip4_ok;
-static char *ip4_addr;
+    IP__IP4_IFADDR,
 #endif
-
-#if defined(INET6) || defined(INET)
-static void add_ip_addr(char **addrp, char *newaddr);
-#endif
-#ifdef INET6
-static void add_ip_addr46(char *newaddr);
-#endif
-static void add_ip_addrinfo(int ai_flags, char *value);
-static void quoted_print(FILE *fp, char *str);
-static void set_param(const char *name, char *value);
-static void usage(void);
-
-static const char *perm_sysctl[][3] = {
-	{ "security.jail.set_hostname_allowed",
-	  "allow.noset_hostname", "allow.set_hostname" },
-	{ "security.jail.sysvipc_allowed",
-	  "allow.nosysvipc", "allow.sysvipc" },
-	{ "security.jail.allow_raw_sockets",
-	  "allow.noraw_sockets", "allow.raw_sockets" },
-	{ "security.jail.chflags_allowed",
-	  "allow.nochflags", "allow.chflags" },
-	{ "security.jail.mount_allowed",
-	  "allow.nomount", "allow.mount" },
-	{ "security.jail.socket_unixiproute_only",
-	  "allow.socket_af", "allow.nosocket_af" },
+    IP__NULL
 };
 
-extern char **environ;
-
-#define GET_USER_INFO do {						\
-	pwd = getpwnam(username);					\
-	if (pwd == NULL) {						\
-		if (errno)						\
-			err(1, "getpwnam: %s", username);		\
-		else							\
-			errx(1, "%s: no such user", username);		\
-	}								\
-	lcap = login_getpwclass(pwd);					\
-	if (lcap == NULL)						\
-		err(1, "getpwclass: %s", username);			\
-	ngroups = ngroups_max;						\
-	if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0)	\
-		err(1, "getgrouplist: %s", username);			\
-} while (0)
-
 int
 main(int argc, char **argv)
 {
-	login_cap_t *lcap = NULL;
-	struct passwd *pwd = NULL;
-	gid_t *groups;
+	struct stat st;
+	FILE *jfp;
+	struct cfjail *j;
+	char *JidFile;
 	size_t sysvallen;
-	int ch, cmdarg, i, jail_set_flags, jid, ngroups, sysval;
-	int hflag, iflag, Jflag, lflag, rflag, uflag, Uflag;
-	long ngroups_max;
-	unsigned pi;
-	char *jailname, *securelevel, *username, *JidFile;
+	unsigned op, pi;
+	int ch, docf, error, i, oldcl, sysval;
+	int dflag, Rflag;
 	char enforce_statfs[4];
-	static char *cleanenv;
-	const char *shell, *p = NULL;
-	FILE *fp;
+#if defined(INET) || defined(INET6)
+	char *cs, *ncs;
+#endif
+#if defined(INET) && defined(INET6)
+	struct in6_addr addr6;
+#endif
 
-	hflag = iflag = Jflag = lflag = rflag = uflag = Uflag =
-	    jail_set_flags = 0;
-	cmdarg = jid = -1;
-	jailname = securelevel = username = JidFile = cleanenv = NULL;
-	fp = NULL;
+	op = 0;
+	dflag = Rflag = 0;
+	docf = 1;
+	cfname = CONF_FILE;
+	JidFile = NULL;
 
-	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;	
-	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
-		err(1, "malloc");
-
-	while ((ch = getopt(argc, argv, "cdhilmn:r:s:u:U:J:")) != -1) {
+	while ((ch = getopt(argc, argv, "cdf:hiJ:lmn:p:qrRs:u:U:v")) != -1) {
 		switch (ch) {
+		case 'c':
+			op |= JF_START;
+			break;
 		case 'd':
-			jail_set_flags |= JAIL_DYING;
+			dflag = 1;
+			break;
+		case 'f':
+			cfname = optarg;
 			break;
 		case 'h':
-			hflag = 1;
+#if defined(INET) || defined(INET6)
+			add_param(NULL, NULL, IP_IP_HOSTNAME, NULL);
+#endif
+			docf = 0;
 			break;
 		case 'i':
 			iflag = 1;
+			verbose = -1;
 			break;
 		case 'J':
 			JidFile = optarg;
-			Jflag = 1;
+			break;
+		case 'l':
+			add_param(NULL, NULL, IP_EXEC_CLEAN, NULL);
+			docf = 0;
+			break;
+		case 'm':
+			op |= JF_SET;
 			break;
 		case 'n':
-			jailname = optarg;
+			add_param(NULL, NULL, KP_NAME, optarg);
+			docf = 0;
+			break;
+		case 'p':
+			paralimit = strtol(optarg, NULL, 10);
+			if (paralimit == 0)
+				paralimit = -1;
+			break;
+		case 'q':
+			verbose = -1;
+			break;
+		case 'r':
+			op |= JF_STOP;
+			break;
+		case 'R':
+			op |= JF_STOP;
+			Rflag = 1;
 			break;
 		case 's':
-			securelevel = optarg;
+			add_param(NULL, NULL, KP_SECURELEVEL, optarg);
+			docf = 0;
 			break;
 		case 'u':
-			username = optarg;
-			uflag = 1;
+			add_param(NULL, NULL, IP_EXEC_JAIL_USER, optarg);
+			add_param(NULL, NULL, IP_EXEC_SYSTEM_JAIL_USER, NULL);
+			docf = 0;
 			break;
 		case 'U':
-			username = optarg;
-			Uflag = 1;
+			add_param(NULL, NULL, IP_EXEC_JAIL_USER, optarg);
+			add_param(NULL, NULL, IP_EXEC_SYSTEM_JAIL_USER,
+			    "false");
+			docf = 0;
 			break;
-		case 'l':
-			lflag = 1;
-			break;
-		case 'c':
-			jail_set_flags |= JAIL_CREATE;
-			break;
-		case 'm':
-			jail_set_flags |= JAIL_UPDATE;
-			break;
-		case 'r':
-			jid = jail_getid(optarg);
-			if (jid < 0)
-				errx(1, "%s", jail_errmsg);
-			rflag = 1;
+		case 'v':
+			verbose = 1;
 			break;
 		default:
 			usage();
@@ -184,312 +219,745 @@
 	}
 	argc -= optind;
 	argv += optind;
-	if (rflag) {
-		if (argc > 0 || iflag || Jflag || lflag || uflag || Uflag)
+
+	/* Find out which of the four command line styles this is. */
+	oldcl = 0;
+	if (!op) {
+		/* Old-style command line with four fixed parameters */
+		if (argc < 4 || argv[0][0] != '/')
 			usage();
-		if (jail_remove(jid) < 0)
-			err(1, "jail_remove");
-		exit (0);
-	}
-	if (argc == 0)
-		usage();
-	if (uflag && Uflag)
-		usage();
-	if (lflag && username == NULL)
-		usage();
-	if (uflag)
-		GET_USER_INFO;
-
-#ifdef INET6
-	ip6_ok = feature_present("inet6");
+		op = JF_START;
+		docf = 0;
+		oldcl = 1;
+		add_param(NULL, NULL, KP_PATH, argv[0]);
+		add_param(NULL, NULL, KP_HOST_HOSTNAME, argv[1]);
+#if defined(INET) || defined(INET6)
+		if (argv[2][0] != '\0') {
+			for (cs = argv[2];; cs = ncs + 1) {
+				ncs = strchr(cs, ',');
+				if (ncs)
+					*ncs = '\0';
+				add_param(NULL, NULL,
+#if defined(INET) && defined(INET6)
+				    inet_pton(AF_INET6, cs, &addr6) == 1
+				    ? KP_IP6_ADDR : KP_IP4_ADDR,
+#elif defined(INET)
+				    KP_IP4_ADDR,
+#elif defined(INET6)
+				    KP_IP6_ADDR,
 #endif
-#ifdef INET
-	ip4_ok = feature_present("inet");
+				    cs);
+				if (!ncs)
+					break;
+			}
+		}
 #endif
-
-	if (jailname)
-		set_param("name", jailname);
-	if (securelevel)
-		set_param("securelevel", securelevel);
-	if (jail_set_flags) {
-		for (i = 0; i < argc; i++) {
-			if (!strncmp(argv[i], "command=", 8)) {
-				cmdarg = i;
-				argv[cmdarg] += 8;
-				jail_set_flags |= JAIL_ATTACH;
-				break;
-			}
-			if (hflag) {
-#ifdef INET
-				if (!strncmp(argv[i], "ip4.addr=", 9)) {
-					add_ip_addr(&ip4_addr, argv[i] + 9);
-					break;
-				}
-#endif
-#ifdef INET6
-				if (!strncmp(argv[i], "ip6.addr=", 9)) {
-					add_ip_addr(&ip6_addr, argv[i] + 9);
-					break;
-				}
-#endif
-				if (!strncmp(argv[i], "host.hostname=", 14))
-					add_ip_addrinfo(0, argv[i] + 14);
-			}
-			set_param(NULL, argv[i]);
-		}
-	} else {
-		if (argc < 4 || argv[0][0] != '/')
-			errx(1, "%s\n%s",
-			   "no -c or -m, so this must be an old-style command.",
-			   "But it doesn't look like one.");
-		set_param("path", argv[0]);
-		set_param("host.hostname", argv[1]);
-		if (hflag)
-			add_ip_addrinfo(0, argv[1]);
-#if defined(INET6) || defined(INET)
-		if (argv[2][0] != '\0')
-#ifdef INET6
-			add_ip_addr46(argv[2]);
-#else
-			add_ip_addr(&ip4_addr, argv[2]);
-#endif
-#endif
-		cmdarg = 3;
-		/* Emulate the defaults from security.jail.* sysctls */
+		for (i = 3; i < argc; i++)
+			add_param(NULL, NULL, IP_COMMAND, argv[i]);
+		/* Emulate the defaults from security.jail.* sysctls. */
 		sysvallen = sizeof(sysval);
 		if (sysctlbyname("security.jail.jailed", &sysval, &sysvallen,
 		    NULL, 0) == 0 && sysval == 0) {
 			for (pi = 0; pi < sizeof(perm_sysctl) /
 			     sizeof(perm_sysctl[0]); pi++) {
 				sysvallen = sizeof(sysval);
-				if (sysctlbyname(perm_sysctl[pi][0],
+				if (sysctlbyname(perm_sysctl[pi].name,
 				    &sysval, &sysvallen, NULL, 0) == 0)
-					set_param(perm_sysctl[pi]
-					    [sysval ? 2 : 1], NULL);
+					add_param(NULL, NULL,
+					    perm_sysctl[pi].ipnum,
+					    (sysval ? 1 : 0) ^ 
+					    perm_sysctl[pi].rev
+					    ? NULL : "false");
 			}
 			sysvallen = sizeof(sysval);
 			if (sysctlbyname("security.jail.enforce_statfs",
 			    &sysval, &sysvallen, NULL, 0) == 0) {
 				snprintf(enforce_statfs,
 				    sizeof(enforce_statfs), "%d", sysval);
-				set_param("enforce_statfs", enforce_statfs);
+				add_param(NULL, NULL, KP_ENFORCE_STATFS,
+				    enforce_statfs);
+			}
+		}
+	} else if (op == JF_STOP) {
+		/* Jail remove, perhaps using the config file */
+		if (!docf || argc == 0)
+			usage();
+		if (!Rflag)
+			for (i = 0; i < argc; i++)
+				if (strchr(argv[i], '='))
+					usage();
+		if ((docf = !Rflag &&
+		     (!strcmp(cfname, "-") || stat(cfname, &st) == 0)))
+			load_config();
+		note_remove = docf || argc > 1 || wild_jail_name(argv[0]);
+	} else if (argc > 1 || (argc == 1 && strchr(argv[0], '='))) {
+		/* Single jail specified on the command line */
+		if (Rflag)
+			usage();
+		docf = 0;
+		for (i = 0; i < argc; i++) {
+			if (!strncmp(argv[i], "command", 7) &&
+			    (argv[i][7] == '\0' || argv[i][7] == '=')) {
+				if (argv[i][7]  == '=')
+					add_param(NULL, NULL, IP_COMMAND,
+					    argv[i] + 8);
+				for (i++; i < argc; i++)
+					add_param(NULL, NULL, IP_COMMAND,
+					    argv[i]);
+				break;
+			}
+			add_param(NULL, NULL, 0, argv[i]);
+		}
+	} else {
+		/* From the config file, perhaps with a specified jail */
+		if (Rflag || !docf)
+			usage();
+		load_config();
+	}
+
+	/* Find out which jails will be run. */
+	dep_setup(docf);
+	error = 0;
+	if (op == JF_STOP) {
+		for (i = 0; i < argc; i++)
+			if (start_state(argv[i], docf, op, Rflag) < 0)
+				error = 1;
+	} else {
+		if (start_state(argv[0], docf, op, 0) < 0)
+			exit(1);
+	}
+
+	jfp = NULL;
+	if (JidFile != NULL) {
+		jfp = fopen(JidFile, "w");
+		if (jfp == NULL)
+			err(1, "open %s", JidFile);
+		setlinebuf(jfp);
+	}
+	setlinebuf(stdout);
+
+	/*
+	 * The main loop: Get an available jail and perform the required
+	 * operation on it.  When that is done, the jail may be finished,
+	 * or it may go back for the next step.
+	 */
+	while ((j = next_jail()))
+	{
+		if (j->flags & JF_FAILED) {
+			error = 1;
+			if (j->comparam == NULL) {
+				dep_done(j, 0);
+				continue;
+			}
+		}
+		if (!(j->flags & JF_PARAMS))
+		{
+			j->flags |= JF_PARAMS;
+			if (dflag)
+				add_param(j, NULL, IP_ALLOW_DYING, NULL);
+			if (check_intparams(j) < 0)
+				continue;
+			if ((j->flags & (JF_START | JF_SET)) &&
+			    import_params(j) < 0)
+				continue;
+		}
+		if (!j->jid)
+			running_jid(j,
+			    (j->flags & (JF_SET | JF_DEPEND)) == JF_SET
+			    ? dflag || bool_param(j->intparams[IP_ALLOW_DYING])
+			    : 0);
+		if (finish_command(j))
+			continue;
+
+		switch (j->flags & JF_OP_MASK) {
+			/*
+			 * These operations just turn into a different op
+			 * depending on the jail's current status.
+			 */
+		case JF_START_SET:
+			j->flags = j->jid < 0 ? JF_START : JF_SET;
+			break;
+		case JF_SET_RESTART:
+			if (j->jid < 0) {
+				jail_quoted_warnx(j, "not found",
+				    "no jail specified");
+				failed(j);
+				continue;
+			}
+			j->flags = rdtun_params(j, 0) ? JF_RESTART : JF_SET;
+			if (j->flags == JF_RESTART)
+				dep_reset(j);
+			break;
+		case JF_START_SET_RESTART:
+			j->flags = j->jid < 0 ? JF_START
+			    : rdtun_params(j, 0) ? JF_RESTART : JF_SET;
+			if (j->flags == JF_RESTART)
+				dep_reset(j);
+		}
+
+		switch (j->flags & JF_OP_MASK) {
+		case JF_START:
+			if (j->comparam == NULL) {
+				if (j->jid > 0 &&
+				    !(j->flags & (JF_DEPEND | JF_WILD))) {
+					jail_quoted_warnx(j, "already exists",
+					    NULL);
+					failed(j);
+					continue;
+				}
+				if (dep_check(j))
+					continue;
+				if (j->jid > 0)
+					goto jail_create_done;
+				j->comparam = startcommands;
+				j->comstring = NULL;
+			}
+			if (next_command(j))
+				continue;
+		jail_create_done:
+			clear_persist(j);
+			if (jfp != NULL)
+				print_jail(jfp, j, oldcl);
+			dep_done(j, 0);
+			break;
+
+		case JF_SET:
+			if (j->jid < 0 && !(j->flags & JF_DEPEND)) {
+				jail_quoted_warnx(j, "not found",
+				    "no jail specified");
+				failed(j);
+				continue;
+			}
+			if (dep_check(j))
+				continue;
+			if (!(j->flags & JF_DEPEND)) {
+				if (rdtun_params(j, 1) < 0 ||
+				    update_jail(j) < 0)
+					continue;
+				if (verbose >= 0 && (j->name || verbose > 0))
+					jail_note(j, "updated\n");
+			}
+			dep_done(j, 0);
+			break;
+
+		case JF_STOP:
+		case JF_RESTART:
+			if (j->comparam == NULL) {
+				if (dep_check(j))
+					continue;
+				if (j->jid < 0) {
+					if (!(j->flags & (JF_DEPEND | JF_WILD))
+					    && verbose >= 0)
+						jail_quoted_warnx(j,
+						    "not found", NULL);
+					goto jail_remove_done;
+				}
+				j->comparam = stopcommands;
+				j->comstring = NULL;
+			} else if ((j->flags & JF_FAILED) && j->jid > 0)
+				goto jail_remove_done;
+			if (next_command(j))
+				continue;
+		jail_remove_done:
+			dep_done(j, 0);
+			if ((j->flags & (JF_START | JF_FAILED)) == JF_START) {
+				j->comparam = NULL;
+				j->flags &= ~JF_STOP;
+				dep_reset(j);
+				requeue(j, j->ndeps ? &depend : &ready);
+			}
+			break;
+		}
+	}
+
+	if (jfp != NULL)
+		fclose(jfp);
+	exit(error);
+}
+
+/*
+ * Mark a jail's failure for future handling.
+ */
+void
+failed(struct cfjail *j)
+{
+	j->flags |= JF_FAILED;
+	TAILQ_REMOVE(j->queue, j, tq);
+	TAILQ_INSERT_HEAD(&ready, j, tq);
+	j->queue = &ready;
+}
+
+/*
+ * Exit slightly more gracefully when out of memory.
+ */
+void *
+emalloc(size_t size)
+{
+	void *p;
+
+	p = malloc(size);
+	if (!p)
+		err(1, "malloc");
+	return p;
+}
+
+void *
+erealloc(void *ptr, size_t size)
+{
+	void *p;
+
+	p = realloc(ptr, size);
+	if (!p)
+		err(1, "malloc");
+	return p;
+}
+
+char *
+estrdup(const char *str)
+{
+	char *ns;
+
+	ns = strdup(str);
+	if (!ns)
+		err(1, "malloc");
+	return ns;
+}
+
+/*
+ * Print a message including an optional jail name.
+ */
+void
+jail_note(const struct cfjail *j, const char *fmt, ...)
+{
+	va_list ap, tap;
+	char *cs;
+	size_t len;
+
+	va_start(ap, fmt);
+	va_copy(tap, ap);
+	len = vsnprintf(NULL, 0, fmt, tap);
+	va_end(tap);
+	cs = alloca(len + 1);
+	(void)vsnprintf(cs, len + 1, fmt, ap);
+	va_end(ap);
+	if (j->name)
+		printf("%s: %s", j->name, cs);
+	else
+		printf("%s", cs);
+}
+
+/*
+ * Print a warning message including an optional jail name.
+ */
+void
+jail_warnx(const struct cfjail *j, const char *fmt, ...)
+{
+	va_list ap, tap;
+	char *cs;
+	size_t len;
+
+	va_start(ap, fmt);
+	va_copy(tap, ap);
+	len = vsnprintf(NULL, 0, fmt, tap);
+	va_end(tap);
+	cs = alloca(len + 1);
+	(void)vsnprintf(cs, len + 1, fmt, ap);
+	va_end(ap);
+	if (j->name)
+		warnx("%s: %s", j->name, cs);
+	else
+		warnx("%s", cs);
+}
+
+/*
+ * Create a new jail.
+ */
+int
+create_jail(struct cfjail *j)
+{
+	struct iovec jiov[4];
+	struct stat st;
+	struct jailparam *jp, *setparams, *setparams2, *sjp;
+	const char *path;
+	int dopersist, ns, jid, dying, didfail;
+
+	/*
+	 * Check the jail's path, with a better error message than jail_set
+	 * gives.
+	 */
+	if ((path = string_param(j->intparams[KP_PATH]))) {
+		if (j->name != NULL && path[0] != '/') {
+			jail_warnx(j, "path %s: not an absolute pathname",
+			    path);
+			return -1;
+		}
+		if (stat(path, &st) < 0) {
+			jail_warnx(j, "path %s: %s", path, strerror(errno));
+			return -1;
+		}
+		if (!S_ISDIR(st.st_mode)) {
+			jail_warnx(j, "path %s: %s", path, strerror(ENOTDIR));
+			return -1;
+		}
+	}
+
+	/*
+	 * Copy all the parameters, except that "persist" is always set when
+	 * there are commands to run later.
+	 */
+	dopersist = !bool_param(j->intparams[KP_PERSIST]) &&
+	    (j->intparams[IP_EXEC_START] || j->intparams[IP_COMMAND] ||
+	     j->intparams[IP_EXEC_POSTSTART]);
+	sjp = setparams =
+	    alloca((j->njp + dopersist) * sizeof(struct jailparam));
+	if (dopersist && jailparam_init(sjp++, "persist") < 0) {
+		jail_warnx(j, "%s", jail_errmsg);
+		return -1;
+	}
+	for (jp = j->jp; jp < j->jp + j->njp; jp++)
+		if (!dopersist || !equalopts(jp->jp_name, "persist"))
+			*sjp++ = *jp;
+	ns = sjp - setparams;
+
+	didfail = 0;
+	j->jid = jailparam_set_note(j, setparams, ns, JAIL_CREATE);
+	if (j->jid < 0 && errno == EEXIST &&
+	    bool_param(j->intparams[IP_ALLOW_DYING]) &&
+	    int_param(j->intparams[KP_JID], &jid) && jid != 0) {
+		/*
+		 * The jail already exists, but may be dying.
+		 * Make sure it is, in which case an update is appropriate.
+		 */
+		*(const void **)&jiov[0].iov_base = "jid";
+		jiov[0].iov_len = sizeof("jid");
+		jiov[1].iov_base = &jid;
+		jiov[1].iov_len = sizeof(jid);
+		*(const void **)&jiov[2].iov_base = "dying";
+		jiov[2].iov_len = sizeof("dying");
+		jiov[3].iov_base = &dying;
+		jiov[3].iov_len = sizeof(dying);
+		if (jail_get(jiov, 4, JAIL_DYING) < 0) {
+			/*
+			 * It could be that the jail just barely finished
+			 * dying, or it could be that the jid never existed
+			 * but the name does.  In either case, another try
+			 * at creating the jail should do the right thing.
+			 */
+			if (errno == ENOENT)
+				j->jid = jailparam_set_note(j, setparams, ns,
+				    JAIL_CREATE);
+		} else if (dying) {
+			j->jid = jid;
+			if (rdtun_params(j, 1) < 0) {
+				j->jid = -1;
+				didfail = 1;
+			} else {
+				sjp = setparams2 = alloca((j->njp + dopersist) *
+				    sizeof(struct jailparam));
+				for (jp = setparams; jp < setparams + ns; jp++)
+					if (!JP_RDTUN(jp) ||
+					    !strcmp(jp->jp_name, "jid"))
+						*sjp++ = *jp;
+				j->jid = jailparam_set_note(j, setparams2,
+				    sjp - setparams2, JAIL_UPDATE | JAIL_DYING);
+				/*
+				 * Again, perhaps the jail just finished dying.
+				 */
+				if (j->jid < 0 && errno == ENOENT)
+					j->jid = jailparam_set_note(j,
+					    setparams, ns, JAIL_CREATE);
 			}
 		}
 	}
+	if (j->jid < 0 && !didfail) {
+		jail_warnx(j, "%s", jail_errmsg);
+		failed(j);
+	}
+	if (dopersist) {
+		jailparam_free(setparams, 1);
+		if (j->jid > 0)
+			j->flags |= JF_PERSIST;
+	}
+	return j->jid;
+}
+
+/*
+ * Remove a temporarily set "persist" parameter.
+ */
+static void
+clear_persist(struct cfjail *j)
+{
+	struct iovec jiov[4];
+	int jid;
+
+	if (!(j->flags & JF_PERSIST))
+		return;
+	j->flags &= ~JF_PERSIST;
+	*(const void **)&jiov[0].iov_base = "jid";
+	jiov[0].iov_len = sizeof("jid");
+	jiov[1].iov_base = &j->jid;
+	jiov[1].iov_len = sizeof(j->jid);
+	*(const void **)&jiov[2].iov_base = "nopersist";
+	jiov[2].iov_len = sizeof("nopersist");
+	jiov[3].iov_base = NULL;
+	jiov[3].iov_len = 0;
+	jid = jail_set(jiov, 4, JAIL_UPDATE);
+	if (verbose > 0)
+		jail_note(j, "jail_set(JAIL_UPDATE) jid=%d nopersist%s%s\n",
+		    j->jid, jid < 0 ? ": " : "",
+		    jid < 0 ? strerror(errno) : "");
+}
+
+/*
+ * Set a jail's parameters.
+ */
+static int
+update_jail(struct cfjail *j)
+{
+	struct jailparam *jp, *setparams, *sjp;
+	int ns, jid;
+
+	ns = 0;
+	for (jp = j->jp; jp < j->jp + j->njp; jp++)
+		if (!JP_RDTUN(jp))
+			ns++;
+	if (ns == 0)
+		return 0;
+	sjp = setparams = alloca(++ns * sizeof(struct jailparam));
+	if (jailparam_init(sjp, "jid") < 0 ||
+	    jailparam_import_raw(sjp, &j->jid, sizeof j->jid) < 0) {
+		jail_warnx(j, "%s", jail_errmsg);
+		failed(j);
+		return -1;
+	}
+	for (jp = j->jp; jp < j->jp + j->njp; jp++)
+		if (!JP_RDTUN(jp))
+			*++sjp = *jp;
+
+	jid = jailparam_set_note(j, setparams, ns,
+	    bool_param(j->intparams[IP_ALLOW_DYING])
+	    ? JAIL_UPDATE | JAIL_DYING : JAIL_UPDATE);
+	if (jid < 0) {
+		jail_warnx(j, "%s", jail_errmsg);
+		failed(j);
+	}
+	jailparam_free(setparams, 1);
+	return jid;
+}
+
+/*
+ * Return if a jail set would change any create-only parameters.
+ */
+static int
+rdtun_params(struct cfjail *j, int dofail)
+{
+	struct jailparam *jp, *rtparams, *rtjp;
+	int nrt, rval;
+
+	if (j->flags & JF_RDTUN)
+		return 0;
+	j->flags |= JF_RDTUN;
+	nrt = 0;
+	for (jp = j->jp; jp < j->jp + j->njp; jp++)
+		if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid"))
+			nrt++;
+	if (nrt == 0)
+		return 0;
+	rtjp = rtparams = alloca(++nrt * sizeof(struct jailparam));
+	if (jailparam_init(rtjp, "jid") < 0 ||
+	    jailparam_import_raw(rtjp, &j->jid, sizeof j->jid) < 0) {
+		jail_warnx(j, "%s", jail_errmsg);
+		exit(1);
+	}
+	for (jp = j->jp; jp < j->jp + j->njp; jp++)
+		if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid"))
+			*++rtjp = *jp;
+	rval = 0;
+	if (jailparam_get(rtparams, nrt,
+	    bool_param(j->intparams[IP_ALLOW_DYING]) ? JAIL_DYING : 0) > 0) {
+		rtjp = rtparams + 1;
+		for (jp = j->jp, rtjp = rtparams + 1; rtjp < rtparams + nrt;
+		     jp++) {
+			if (JP_RDTUN(jp) && strcmp(jp->jp_name, "jid")) {
+				if (!((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) &&
+				    jp->jp_valuelen == 0 &&
+				    *(int *)jp->jp_value) &&
+				    !(rtjp->jp_valuelen == jp->jp_valuelen &&
+				    !memcmp(rtjp->jp_value, jp->jp_value,
+				    jp->jp_valuelen))) {
+					if (dofail) {
+						jail_warnx(j, "%s cannot be "
+						    "changed after creation",
+						    jp->jp_name);
+						failed(j);
+						rval = -1;
+					} else
+						rval = 1;
+					break;
+				}
+				rtjp++;
+			}
+		}
+	}
+	for (rtjp = rtparams + 1; rtjp < rtparams + nrt; rtjp++)
+		rtjp->jp_name = NULL;
+	jailparam_free(rtparams, nrt);
+	return rval;
+}
+
+/*
+ * Get the jail's jid if it is running.
+ */
+static void
+running_jid(struct cfjail *j, int dflag)
+{
+	struct iovec jiov[2];
+	const char *pval;
+	char *ep;
+	int jid;
+
+	if ((pval = string_param(j->intparams[KP_JID]))) {
+		if (!(jid = strtol(pval, &ep, 10)) || *ep) {
+			j->jid = -1;
+			return;
+		}
+		*(const void **)&jiov[0].iov_base = "jid";
+		jiov[0].iov_len = sizeof("jid");
+		jiov[1].iov_base = &jid;
+		jiov[1].iov_len = sizeof(jid);
+	} else if ((pval = string_param(j->intparams[KP_NAME]))) {
+		*(const void **)&jiov[0].iov_base = "name";
+		jiov[0].iov_len = sizeof("name");
+		jiov[1].iov_len = strlen(pval) + 1;
+		jiov[1].iov_base = alloca(jiov[1].iov_len);
+		strcpy(jiov[1].iov_base, pval);
+	} else {
+		j->jid = -1;
+		return;
+	}
+	j->jid = jail_get(jiov, 2, dflag ? JAIL_DYING : 0);
+}
+
+static void
+jail_quoted_warnx(const struct cfjail *j, const char *name_msg,
+    const char *noname_msg)
+{
+	const char *pval;
+
+	if ((pval = j->name) || (pval = string_param(j->intparams[KP_JID])) ||
+	    (pval = string_param(j->intparams[KP_NAME])))
+		warnx("\"%s\" %s", pval, name_msg);
+	else
+		warnx("%s", noname_msg);
+}
+
+/*
+ * Set jail parameters and possible print them out.
+ */
+static int
+jailparam_set_note(const struct cfjail *j, struct jailparam *jp, unsigned njp,
+    int flags)
+{
+	char *value;
+	int jid;
+	unsigned i;
+
+	jid = jailparam_set(jp, njp, flags);
+	if (verbose > 0) {
+		jail_note(j, "jail_set(%s%s)",
+		    (flags & (JAIL_CREATE | JAIL_UPDATE)) == JAIL_CREATE
+		    ? "JAIL_CREATE" : "JAIL_UPDATE",
+		    (flags & JAIL_DYING) ? " | JAIL_DYING" : "");
+		for (i = 0; i < njp; i++) {
+			printf(" %s", jp[i].jp_name);
+			if (jp[i].jp_value == NULL)
+				continue;
+			putchar('=');
+			value = jailparam_export(jp + i);
+			if (value == NULL)
+				err(1, "jailparam_export");
+			quoted_print(stdout, value);
+			free(value);
+		}
+		if (jid < 0)
+			printf(": %s", strerror(errno));
+		printf("\n");
+	}
+	return jid;
+}
+
+/*
+ * Print a jail record.
+ */
+static void
+print_jail(FILE *fp, struct cfjail *j, int oldcl)
+{
+	struct cfparam *p;
+
+	if (oldcl) {
+		fprintf(fp, "%d\t", j->jid);
+		print_param(fp, j->intparams[KP_PATH], ',', 0);
+		putc('\t', fp);
+		print_param(fp, j->intparams[KP_HOST_HOSTNAME], ',', 0);
+		putc('\t', fp);
 #ifdef INET
-	if (ip4_addr != NULL)
-		set_param("ip4.addr", ip4_addr);
+		print_param(fp, j->intparams[KP_IP4_ADDR], ',', 0);
+#ifdef INET6
+		if (j->intparams[KP_IP4_ADDR] &&
+		    !TAILQ_EMPTY(&j->intparams[KP_IP4_ADDR]->val) &&
+		    j->intparams[KP_IP6_ADDR] &&
+		    !TAILQ_EMPTY(&j->intparams[KP_IP6_ADDR]->val))
+		    putc(',', fp);
+#endif
 #endif
 #ifdef INET6
-	if (ip6_addr != NULL)
-		set_param("ip6.addr", ip6_addr);
+		print_param(fp, j->intparams[KP_IP6_ADDR], ',', 0);
 #endif
-
-	if (Jflag) {
-		fp = fopen(JidFile, "w");
-		if (fp == NULL)
-			errx(1, "Could not create JidFile: %s", JidFile);
+		putc('\t', fp);
+		print_param(fp, j->intparams[IP_COMMAND], ' ', 0);
+	} else {
+		fprintf(fp, "jid=%d", j->jid);
+		TAILQ_FOREACH(p, &j->params, tq)
+			if (strcmp(p->name, "jid")) {
+				putc(' ', fp);
+				print_param(fp, p, ',', 1);
+			}
 	}
-	jid = jailparam_set(params, nparams, 
-	    jail_set_flags ? jail_set_flags : JAIL_CREATE | JAIL_ATTACH);
-	if (jid < 0)
-		errx(1, "%s", jail_errmsg);
-	if (iflag) {
-		printf("%d\n", jid);
-		fflush(stdout);
-	}
-	if (Jflag) {
-		if (jail_set_flags) {
-			fprintf(fp, "jid=%d", jid);
-			for (i = 0; i < nparams; i++)
-				if (strcmp(params[i].jp_name, "jid")) {
-					fprintf(fp, " %s",
-					    (char *)params[i].jp_name);
-					if (param_values[i]) {
-						putc('=', fp);
-						quoted_print(fp,
-						    param_values[i]);
-					}
-				}
-			fprintf(fp, "\n");
-		} else {
-			for (i = 0; i < nparams; i++)
-				if (!strcmp(params[i].jp_name, "path"))
-					break;
-#if defined(INET6) && defined(INET)
-			fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n",
-			    jid, i < nparams
-			    ? (char *)params[i].jp_value : argv[0],
-			    argv[1], ip4_addr ? ip4_addr : "",
-			    ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0]
-			    ? "," : "", ip6_addr ? ip6_addr : "", argv[3]);
-#elif defined(INET6)
-			fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
-			    jid, i < nparams
-			    ?  (char *)params[i].jp_value : argv[0],
-			    argv[1], ip6_addr ? ip6_addr : "", argv[3]);
-#elif defined(INET)
-			fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
-			    jid, i < nparams
-			    ? (char *)params[i].jp_value : argv[0],
-			    argv[1], ip4_addr ? ip4_addr : "", argv[3]);
-#endif
-		}
-		(void)fclose(fp);
-	}
-	if (cmdarg < 0)
-		exit(0);
-	if (username != NULL) {
-		if (Uflag)
-			GET_USER_INFO;
-		if (lflag) {
-			p = getenv("TERM");
-			environ = &cleanenv;
-		}
-		if (setgroups(ngroups, groups) != 0)
-			err(1, "setgroups");
-		if (setgid(pwd->pw_gid) != 0)
-			err(1, "setgid");
-		if (setusercontext(lcap, pwd, pwd->pw_uid,
-		    LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0)
-			err(1, "setusercontext");
-		login_close(lcap);
-	}
-	if (lflag) {
-		if (*pwd->pw_shell)
-			shell = pwd->pw_shell;
-		else
-			shell = _PATH_BSHELL;
-		if (chdir(pwd->pw_dir) < 0)
-			errx(1, "no home directory");
-		setenv("HOME", pwd->pw_dir, 1);
-		setenv("SHELL", shell, 1);
-		setenv("USER", pwd->pw_name, 1);
-		if (p)
-			setenv("TERM", p, 1);
-	}
-	execvp(argv[cmdarg], argv + cmdarg);
-	err(1, "execvp: %s", argv[cmdarg]);
+	putc('\n', fp);
 }
 
-#if defined(INET6) || defined(INET)
+/*
+ * Print a parameter value, or a name=value pair.
+ */
 static void
-add_ip_addr(char **addrp, char *value)
+print_param(FILE *fp, const struct cfparam *p, int sep, int doname)
 {
-	int addrlen;
-	char *addr;
+	const struct cfstring *s, *ts;
 
-	if (!*addrp) {
-		*addrp = strdup(value);
-		if (!*addrp)
-			err(1, "malloc");
-	} else if (value[0]) {
-		addrlen = strlen(*addrp) + strlen(value) + 2;
-		addr = malloc(addrlen);
-		if (!addr)
-			err(1, "malloc");
-		snprintf(addr, addrlen, "%s,%s", *addrp, value);
-		free(*addrp);
-		*addrp = addr;
+	if (doname)
+		fputs(p->name, fp);
+	if (p == NULL || TAILQ_EMPTY(&p->val))
+		return;
+	if (doname)
+		putc('=', fp);
+	TAILQ_FOREACH_SAFE(s, &p->val, tq, ts) {
+		quoted_print(fp, s->s);
+		if (ts != NULL)
+			putc(sep, fp);
 	}
 }
-#endif
 
-#ifdef INET6
-static void
-add_ip_addr46(char *value)
-{
-	char *p, *np;
-
-	for (p = value;; p = np + 1)
-	{
-		np = strchr(p, ',');
-		if (np)
-			*np = '\0';
-		add_ip_addrinfo(AI_NUMERICHOST, p);
-		if (!np)
-			break;
-	}
-}
-#endif
-
-static void
-add_ip_addrinfo(int ai_flags, char *value)
-{
-	struct addrinfo hints, *ai0, *ai;
-	int error;
-#ifdef INET
-	char avalue4[INET_ADDRSTRLEN];
-	struct in_addr addr4;
-#endif
-#ifdef INET6
-	char avalue6[INET6_ADDRSTRLEN];
-	struct in6_addr addr6;
-#endif
-
-	/* Look up the hostname (or get the address) */
-	memset(&hints, 0, sizeof(hints));
-	hints.ai_socktype = SOCK_STREAM;
-#if defined(INET6) && defined(INET)
-	hints.ai_family = PF_UNSPEC;
-#elif defined(INET6)
-	hints.ai_family = PF_INET6;
-#elif defined(INET)
-	hints.ai_family = PF_INET;
-#endif
-	hints.ai_flags = ai_flags;
-	error = getaddrinfo(value, NULL, &hints, &ai0);
-	if (error != 0)
-		errx(1, "hostname %s: %s", value, gai_strerror(error));
-
-	/* Convert the addresses to ASCII so set_param can convert them back. */
-	for (ai = ai0; ai; ai = ai->ai_next)
-		switch (ai->ai_family) {
-#ifdef INET
-		case AF_INET:
-			if (!ip4_ok && (ai_flags & AI_NUMERICHOST) == 0)
-				break;
-			memcpy(&addr4, &((struct sockaddr_in *)
-			    (void *)ai->ai_addr)->sin_addr, sizeof(addr4));
-			if (inet_ntop(AF_INET, &addr4, avalue4,
-			    INET_ADDRSTRLEN) == NULL)
-				err(1, "inet_ntop");
-			add_ip_addr(&ip4_addr, avalue4);
-			break;
-#endif
-#ifdef INET6
-		case AF_INET6:
-			if (!ip6_ok && (ai_flags & AI_NUMERICHOST) == 0)
-				break;
-			memcpy(&addr6, &((struct sockaddr_in6 *)
-			    (void *)ai->ai_addr)->sin6_addr, sizeof(addr6));
-			if (inet_ntop(AF_INET6, &addr6, avalue6,
-			    INET6_ADDRSTRLEN) == NULL)
-				err(1, "inet_ntop");
-			add_ip_addr(&ip6_addr, avalue6);
-			break;
-#endif
-		}
-	freeaddrinfo(ai0);
-}
-
+/*
+ * Print a string with quotes around spaces.
+ */
 static void
 quoted_print(FILE *fp, char *str)
 {
 	int c, qc;
 	char *p = str;
 
-	/* An empty string needs quoting. */
-	if (!*p) {
-		fputs("\"\"", fp);
-		return;
-	}
-
-	/*
-	 * The value will be surrounded by quotes if it contains spaces
-	 * or quotes.
-	 */
-	qc = strchr(p, '\'') ? '"'
+	qc = !*p ? '"'
+	    : strchr(p, '\'') ? '"'
 	    : strchr(p, '"') ? '\''
 	    : strchr(p, ' ') || strchr(p, '\t') ? '"'
 	    : 0;
@@ -505,71 +973,16 @@
 }
 
 static void
-set_param(const char *name, char *value)
-{
-	struct jailparam *param;
-	char path[PATH_MAX];
-	int i;
-
-	static int paramlistsize;
-
-	/* Separate the name from the value, if not done already. */
-	if (name == NULL) {
-		name = value;
-		if ((value = strchr(value, '=')))
-			*value++ = '\0';
-	}
-
-	/* jail_set won't chdir along with its chroot, so do it here. */
-	if (!strcmp(name, "path")) {
-		/* resolve the path with realpath(3) */
-		if (realpath(value, path) != NULL)
-			value = path;
-		if (chdir(value) < 0)
-			err(1, "chdir: %s", value);
-	}
-
-	/* Check for repeat parameters */
-	for (i = 0; i < nparams; i++)
-		if (!strcmp(name, params[i].jp_name)) {
-			jailparam_free(params + i, 1);
-			memcpy(params + i, params + i + 1,
-			    (--nparams - i) * sizeof(struct jailparam));
-			break;
-		}
-
-	/* Make sure there is room for the new param record. */
-	if (!nparams) {
-		paramlistsize = 32;
-		params = malloc(paramlistsize * sizeof(*params));
-		param_values = malloc(paramlistsize * sizeof(*param_values));
-		if (params == NULL || param_values == NULL)
-			err(1, "malloc");
-	} else if (nparams >= paramlistsize) {
-		paramlistsize *= 2;
-		params = realloc(params, paramlistsize * sizeof(*params));
-		param_values = realloc(param_values,
-		    paramlistsize * sizeof(*param_values));
-		if (params == NULL)
-			err(1, "realloc");
-	}
-
-	/* Look up the paramter. */
-	param_values[nparams] = value;
-	param = params + nparams++;
-	if (jailparam_init(param, name) < 0 ||
-	    jailparam_import(param, value) < 0)
-		errx(1, "%s", jail_errmsg);
-}
-
-static void
 usage(void)
 {
 
 	(void)fprintf(stderr,
-	    "usage: jail [-d] [-h] [-i] [-J jid_file] "
-			"[-l -u username | -U username]\n"
-	    "            [-c | -m] param=value ... [command=command ...]\n"
-	    "       jail [-r jail]\n");
+	    "usage: jail [-dhilqv] [-J jid_file] [-u username] [-U username]\n"
+	    "            -[cmr] param=value ... [command=command ...]\n"
+	    "       jail [-dqv] [-f file] -[cmr] [jail]\n"
+	    "       jail [-qv] [-f file] -[rR] ['*' | jail ...]\n"
+	    "       jail [-dhilqv] [-J jid_file] [-u username] [-U username]\n"
+	    "            [-n jailname] [-s securelevel]\n"
+	    "            path hostname [ip[,...]] command ...\n");
 	exit(1);
 }
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/jail.conf.5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/jail.conf.5	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,231 @@
+.\" Copyright (c) 2012 James Gritton
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: head/usr.sbin/jail/jail.conf.5 236509 2012-06-03 11:29:48Z joel $
+.\"
+.Dd May 23, 2012
+.Dt JAIL.CONF 5
+.Os
+.Sh NAME
+.Nm jail.conf
+.Nd configuration file for
+.Xr jail 8
+.Sh DESCRIPTION
+A
+.Xr jail 8
+configuration file consists of one or more jail definitions statements,
+and parameter or variable statements within those jail definitions.
+A jail definition statement looks something like a C compound statement.
+A parameter statement looks like a C assignment,
+including a terminating semicolon.
+.Pp
+The general syntax of a jail definition is:
+.Bd -literal -offset indent
+jailname {
+	parameter = "value";
+	parameter = "value";
+	...
+}
+.Ed
+.Pp
+Each jail is required to have a
+.Va name
+at the front of its definition.
+This is used by
+.Xr jail 8
+to specify a jail on the command line and report the jail status,
+and is also passed to the kernel when creating the jail.
+.Ss Parameters
+A jail is defined by a set of named parameters, specified inside the
+jail definition.
+See
+.Xr jail 8
+for a list of jail parameters passed to the kernel,
+as well as internal parameters used when creating and removing jails.
+.Pp
+A typical parameter has a name and a value.
+Some parameters are boolean and may be specified with values of
+.Dq true
+or
+.Dq false ,
+or as valueless shortcuts, with a
+.Dq no
+prefix indicating a false value.
+For example, these are equivalent:
+.Bd -literal -offset indent
+allow.mount = "false";
+allow.nomount;
+.Ed
+.Pp
+Other parameters may have more than one value.
+A comma-separated list of values may be set in a single statement,
+or an existing parameter list may be appended to using
+.Dq += :
+.Bd -literal -offset indent
+ip4.addr = 10.1.1.1, 10.1.1.2, 10.1.1.3;
+
+ip4.addr = 10.1.1.1;
+ip4.addr += 10.1.1.2;
+ip4.addr += 10.1.1.3;
+.Ed
+.Pp
+Note the
+.Va name
+parameter is implicitly set to the name in the jail definition.
+.Ss String format
+Parameter values, including jail names, can be single tokens or quoted
+strings.
+A token is any sequence of characters that aren't considered special in
+the syntax of the configuration file (such as a semicolon or
+whitespace).
+If a value contains anything more than letters, numbers, dots, dashes
+and underscores, it is advisable to put quote marks around that value.
+Either single or double quotes may be used.
+.Pp
+Special characters may be quoted by preceding them with a backslash.
+Common C-style backslash character codes are also supported, including
+control characters and octal or hex ASCII codes.
+A backslash at the end of a line will ignore the subsequent newline and
+continue the string at the start of the next line.
+.Ss Variables
+A string may use shell-style variable substitution.
+A parameter or variable name preceded by a dollar sign, and possibly
+enclosed in braces, will be replaced with the value of that parameter or
+variable.
+For example, a jail's path may be defined in terms of its name or
+hostname:
+.Bd -literal -offset indent
+path = "/var/jail/$name";
+
+path = "/var/jail/${host.hostname}";
+.Ed
+.Pp
+Variable substitution occurs in unquoted tokens or in double-quoted
+strings, but not in single-quote strings.
+.Pp
+A variable is defined in the same way a parameter is, except that the
+variable name is preceded with a dollar sign:
+.Bd -literal -offset indent
+$parentdir = "/var/jail";
+path = "$parentdir/$name";
+.Ed
+.Pp
+The difference between parameters and variables is that variables are
+only used for substitution, while parameters are used both for
+substitution and for passing to the kernel.
+.Ss Wildcards
+A jail definition with a name of
+.Dq *
+is used to define wildcard parameters.
+Every defined jail will contain both the parameters from its own
+definition statement, as well as any parameters in a wildcard
+definition.
+.Pp
+Variable substitution is done on a per-jail basis, even when that
+substitution is for a parameter defined in a wildcard section.
+This is useful for wildcard parameters based on e.g. a jail's name.
+.Pp
+Later definitions in the configuration file supersede earlier ones, so a
+wildcard section placed before (above) a jail definition defines
+parameters that could be changed on a per-jail basis.
+Or a wildcard section placed after (below) all jails would contain
+parameters that always apply to every jail.
+Multiple wildcard statements are allowed, and wildcard parameters may
+also be specified outside of a jail definition statement.
+.Pp
+If hierarchical jails are defined, a partial-matching wildcard
+definition may be specified.
+For example, a definition with a name of
+.Dq foo.*
+would apply to jails with names like
+.Dq foo.bar
+and
+.Dq foo.bar.baz .
+.Ss Comments
+The configuration file may contain comments in the common C, C++, and
+shell formats:
+.Bd -literal -offset indent
+/* This is a C style comment.
+ * It may span multiple lines.
+ */
+
+// This is a C++ style comment.
+
+#  This is a shell style comment.
+.Ed
+.Pp
+Comments are legal wherever whitespace is allowed, i.e. anywhere except
+in the middle of a string or a token.
+.Sh EXAMPLES
+.Bd -literal
+# Typical static defaults:
+# Use the rc scripts to start and stop jails.  Mount jail's /dev.
+exec.start = "/bin/sh /etc/rc";
+exec.stop = "/bin/sh /etc/rc.shutdown";
+exec.clean;
+mount.devfs;
+
+# Dynamic wildcard parameter:
+# Base the path off the jail name.
+path = "/var/jail/$name";
+
+# A typical jail.
+foo {
+	host.hostname = "foo.com";
+	ip4.addr = 10.1.1.1, 10.1.1.2, 10.1.1.3;
+}
+
+# This jail overrides the defaults defined above.
+bar {
+	exec.start = '';
+	exec.stop = '';
+	path = /;
+	mount.nodevfs;
+	persist;	// Required because there are no processes
+}
+.Ed
+.Sh SEE ALSO
+.Xr jail_set 2
+.Xr jail 8
+.Xr jls 8
+.Sh HISTORY
+The
+.Xr jail 8
+utility appeared in
+.Fx 4.0 .
+The
+.Nm
+file was added in
+.Fx 9.1 .
+.Sh AUTHORS
+.An -nosplit
+The jail feature was written by
+.An Poul-Henning Kamp
+for R&D Associates
+.Pa http://www.rndassociates.com/
+who contributed it to
+.Fx .
+.Pp
+.An James Gritton
+added the extensible jail parameters and configuration file.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/jaillex.l
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/jaillex.l	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,233 @@
+%{
+/*-
+ * Copyright (c) 2011 James Gritton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/jail/jaillex.l 234934 2012-05-02 21:24:08Z jamie $");
+
+#include <err.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jailp.h"
+#include "y.tab.h"
+
+#define YY_NO_INPUT
+#define YY_NO_UNPUT
+
+extern int yynerrs;
+
+static ssize_t text2lval(size_t triml, size_t trimr, int tovar);
+
+static int instr;
+static int lineno = 1;
+%}
+
+%start _ DQ
+
+%%
+
+			/* Whitespace or equivalent */
+<_>[ \t]+		instr = 0;
+<_>#.*			;
+<_>\/\/.*		;
+<_>\/\*([^*]|(\*+([^*\/])))*\*+\/ {
+				const char *s;
+
+				for (s = yytext; s < yytext + yyleng; s++)
+					if (*s == '\n')
+						lineno++;
+				instr = 0;
+			}
+<_>\n			{
+				lineno++;
+				instr = 0;
+			}
+
+			/* Reserved tokens */
+<_>\+=			{
+				instr = 0;
+				return PLEQ;
+			}
+<_>[,;={}]		{
+				instr = 0;
+				return yytext[0];
+			}
+
+			/* Atomic (unquoted) strings */
+<_,DQ>[A-Za-z0-9_!%&()\-.:<>?@\[\]^`|~]+ |
+<_,DQ>\\(.|\n|[0-7]{1,3}|x[0-9A-Fa-f]{1,2}) |
+<_,DQ>[$*+/\\]		{
+				(void)text2lval(0, 0, 0);
+				return instr ? STR1 : (instr = 1, STR);
+			}
+
+			/* Single and double quoted strings */
+<_>'([^\'\\]|\\(.|\n))*' {
+				(void)text2lval(1, 1, 0);
+				return instr ? STR1 : (instr = 1, STR);
+			}
+<_>\"([^"\\]|\\(.|\n))*\" |
+<DQ>[^\"$\\]([^"\\]|\\(.|\n))*\" {
+				size_t skip;
+				ssize_t atvar;
+
+				skip = yytext[0] == '"' ? 1 : 0;
+				atvar = text2lval(skip, 1, 1);
+				if (atvar < 0)
+					BEGIN _;
+				else {
+					/*
+					 * The string has a variable inside it.
+					 * Go into DQ mode to get the variable
+					 * and then the rest of the string.
+					 */
+					BEGIN DQ;
+					yyless(atvar);
+				}
+				return instr ? STR1 : (instr = 1, STR);
+			}
+<DQ>\"			BEGIN _;
+
+			/* Variables, single-word or bracketed */
+<_,DQ>$[A-Za-z_][A-Za-z_0-9]* {
+				(void)text2lval(1, 0, 0);
+				return instr ? VAR1 : (instr = 1, VAR);
+			}
+<_>$\{([^\n{}]|\\(.|\n))*\} |
+<DQ>$\{([^\n\"{}]|\\(.|\n))*\} {
+				(void)text2lval(2, 1, 0);
+				return instr ? VAR1 : (instr = 1, VAR);
+			}
+
+			/* Partially formed bits worth complaining about */
+<_>\/\*([^*]|(\*+([^*\/])))*\** {
+				warnx("%s line %d: unterminated comment",
+				    cfname, lineno);
+				yynerrs++;
+			}
+<_>'([^\n'\\]|\\.)*	|
+<_>\"([^\n\"\\]|\\.)*	{
+				warnx("%s line %d: unterminated string",
+				    cfname, lineno);
+				yynerrs++;
+			}
+<_>$\{([^\n{}]|\\.)*	|
+<DQ>$\{([^\n\"{}]|\\.)*	{
+				warnx("%s line %d: unterminated variable",
+				    cfname, lineno);
+				yynerrs++;
+			}
+
+			/* A hack because "<0>" rules aren't allowed */
+<_>.			return yytext[0];
+.|\n			{
+				BEGIN _;
+				yyless(0);
+			}
+
+%%
+
+void
+yyerror(const char *s)
+{
+	if (!yytext)
+		warnx("%s line %d: %s", cfname, lineno, s);
+	else if (!yytext[0])
+		warnx("%s: unexpected EOF", cfname);
+	else
+		warnx("%s line %d: %s: %s", cfname, lineno, yytext, s);
+}
+
+/*
+ * Copy string from yytext to yylval, handling backslash escapes,
+ * and optionally stopping at the beginning of a variable.
+ */
+static ssize_t
+text2lval(size_t triml, size_t trimr, int tovar)
+{
+	char *d;
+	const char *s, *se;
+
+	yylval.cs = d = emalloc(yyleng - trimr - triml + 1);
+	se = yytext + (yyleng - trimr);
+	for (s = yytext + triml; s < se; s++, d++) {
+		if (*s != '\\') {
+			if (tovar && *s == '$') {
+				*d = '\0';
+				return s - yytext;
+			}
+			if (*s == '\n')
+				lineno++;
+			*d = *s;
+			continue;
+		}
+		s++;
+		if (*s >= '0' && *s <= '7') {
+			*d = *s - '0';
+			if (s + 1 < se && s[1] >= '0' && s[1] <= '7') {
+				*d = 010 * *d + (*++s - '0');
+				if (s + 1 < se && s[1] >= '0' && s[1] <= '7')
+					*d = 010 * *d + (*++s - '0');
+			}
+			continue;
+		}
+		switch (*s) {
+		case 'a':	*d = '\a';	break;
+		case 'b':	*d = '\b';	break;
+		case 'f':	*d = '\f';	break;
+		case 'n':	*d = '\n';	break;
+		case 'r':	*d = '\r';	break;
+		case 't':	*d = '\t';	break;
+		case 'v':	*d = '\v';	break;
+		case '\n':	d--; lineno++;	break;
+		default:	*d = *s;	break;
+		case 'x':
+			*d = 0;
+			if (s + 1 >= se)
+				break;
+			if (s[1] >= '0' && s[1] <= '9')
+				*d = *++s - '0';
+			else if (s[1] >= 'A' && s[1] <= 'F')
+				*d = *++s + (0xA - 'A');
+			else if (s[1] >= 'a' && s[1] <= 'a')
+				*d = *++s + (0xa - 'a');
+			else
+				break;
+			if (s + 1 >= se)
+				break;
+			if (s[1] >= '0' && s[1] <= '9')
+				*d = *d * 0x10 + (*++s - '0');
+			else if (s[1] >= 'A' && s[1] <= 'F')
+				*d = *d * 0x10 + (*++s + (0xA - 'A'));
+			else if (s[1] >= 'a' && s[1] <= 'a')
+				*d = *d * 0x10 + (*++s + (0xa - 'a'));
+		}
+	}
+	*d = '\0';
+	return -1;
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/jailp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/jailp.h	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 2011 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/usr.sbin/jail/jailp.h 236198 2012-05-28 20:44:11Z jamie $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/jail.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <jail.h>
+
+#define CONF_FILE	"/etc/jail.conf"
+
+#define DEP_FROM	0
+#define DEP_TO		1
+
+#define DF_SEEN		0x01	/* Dependency has been followed */
+#define DF_LIGHT	0x02	/* Implied dependency on jail existence only */
+#define DF_NOFAIL	0x04	/* Don't propigate failed jails */
+
+#define PF_VAR		0x01	/* This is a variable, not a true parameter */
+#define PF_APPEND	0x02	/* Append to existing parameter list */
+#define PF_BAD		0x04	/* Unable to resolve parameter value */
+#define PF_INTERNAL	0x08	/* Internal parameter, not passed to kernel */
+#define PF_BOOL		0x10	/* Boolean parameter */
+#define PF_INT		0x20	/* Integer parameter */
+#define PF_CONV		0x40	/* Parameter duplicated in converted form */
+
+#define JF_START	0x0001	/* -c */
+#define JF_SET		0x0002	/* -m */
+#define JF_STOP		0x0004	/* -r */
+#define JF_DEPEND	0x0008	/* Operation required by dependency */
+#define JF_WILD		0x0010	/* Not specified on the command line */
+#define JF_FAILED	0x0020	/* Operation failed */
+#define JF_PARAMS	0x0040	/* Parameters checked and imported */
+#define JF_RDTUN	0x0080	/* Create-only parameter check has been done */
+#define JF_PERSIST	0x0100	/* Jail is temporarily persistent */
+#define JF_TIMEOUT	0x0200	/* A command (or process kill) timed out */
+#define JF_SLEEPQ	0x0400	/* Waiting on a command and/or timeout */
+
+#define JF_OP_MASK		(JF_START | JF_SET | JF_STOP)
+#define JF_RESTART		(JF_START | JF_STOP)
+#define JF_START_SET		(JF_START | JF_SET)
+#define JF_SET_RESTART		(JF_SET | JF_STOP)
+#define JF_START_SET_RESTART	(JF_START | JF_SET | JF_STOP)
+#define JF_DO_STOP(js)		(((js) & (JF_SET | JF_STOP)) == JF_STOP)
+
+enum intparam {
+	IP__NULL = 0,		/* Null command */
+	IP_ALLOW_DYING,		/* Allow making changes to a dying jail */
+	IP_COMMAND,		/* Command run inside jail at creation */
+	IP_DEPEND,		/* Jail starts after (stops before) another */
+	IP_EXEC_CLEAN,		/* Run commands in a clean environment */
+	IP_EXEC_CONSOLELOG,	/* Redirect optput for commands run in jail */
+	IP_EXEC_FIB,		/* Run jailed commands with this FIB */
+	IP_EXEC_JAIL_USER,	/* Run jailed commands as this user */
+	IP_EXEC_POSTSTART,	/* Commands run outside jail after creating */
+	IP_EXEC_POSTSTOP,	/* Commands run outside jail after removing */
+	IP_EXEC_PRESTART,	/* Commands run outside jail before creating */
+	IP_EXEC_PRESTOP,	/* Commands run outside jail before removing */
+	IP_EXEC_START,		/* Commands run inside jail on creation */
+	IP_EXEC_STOP,		/* Commands run inside jail on removal */
+	IP_EXEC_SYSTEM_JAIL_USER,/* Get jail_user from system passwd file */
+	IP_EXEC_SYSTEM_USER,	/* Run non-jailed commands as this user */
+	IP_EXEC_TIMEOUT,	/* Time to wait for a command to complete */
+#if defined(INET) || defined(INET6)
+	IP_INTERFACE,		/* Add IP addresses to this interface */
+	IP_IP_HOSTNAME,		/* Get jail IP address(es) from hostname */
+#endif
+	IP_MOUNT,		/* Mount points in fstab(5) form */
+	IP_MOUNT_DEVFS,		/* Mount /dev under prison root */
+	IP_MOUNT_FSTAB,		/* A standard fstab(5) file */
+	IP_STOP_TIMEOUT,	/* Time to wait after sending SIGTERM */
+	IP_VNET_INTERFACE,	/* Assign interface(s) to vnet jail */
+#ifdef INET
+	IP__IP4_IFADDR,		/* Copy of ip4.addr with interface/netmask */
+#endif
+#ifdef INET6
+	IP__IP6_IFADDR,		/* Copy of ip6.addr with interface/prefixlen */
+#endif
+	IP__MOUNT_FROM_FSTAB,	/* Line from mount.fstab file */
+	IP__OP,			/* Placeholder for requested operation */
+	KP_ALLOW_CHFLAGS,
+	KP_ALLOW_MOUNT,
+	KP_ALLOW_RAW_SOCKETS,
+	KP_ALLOW_SET_HOSTNAME,
+	KP_ALLOW_SOCKET_AF,
+	KP_ALLOW_SYSVIPC,
+	KP_DEVFS_RULESET,
+	KP_ENFORCE_STATFS,
+	KP_HOST_HOSTNAME,
+#ifdef INET
+	KP_IP4_ADDR,
+#endif
+#ifdef INET6
+	KP_IP6_ADDR,
+#endif
+	KP_JID,
+	KP_NAME,
+	KP_PATH,
+	KP_PERSIST,
+	KP_SECURELEVEL,
+	KP_VNET,
+	IP_NPARAM
+};
+
+STAILQ_HEAD(cfvars, cfvar);
+
+struct cfvar {
+	STAILQ_ENTRY(cfvar)	tq;
+	char			*name;
+	size_t			pos;
+};
+
+TAILQ_HEAD(cfstrings, cfstring);
+
+struct cfstring {
+	TAILQ_ENTRY(cfstring)	tq;
+	char			*s;
+	size_t			len;
+	struct cfvars		vars;
+};
+
+TAILQ_HEAD(cfparams, cfparam);
+
+struct cfparam {
+	TAILQ_ENTRY(cfparam)	tq;
+	char			*name;
+	struct cfstrings	val;
+	unsigned		flags;
+	int			gen;
+};
+
+TAILQ_HEAD(cfjails, cfjail);
+STAILQ_HEAD(cfdepends, cfdepend);
+
+struct cfjail {
+	TAILQ_ENTRY(cfjail)	tq;
+	char			*name;
+	char			*comline;
+	struct cfparams		params;
+	struct cfdepends	dep[2];
+	struct cfjails		*queue;
+	struct cfparam		*intparams[IP_NPARAM];
+	struct cfstring		*comstring;
+	struct jailparam	*jp;
+	struct timespec		timeout;
+	const enum intparam	*comparam;
+	unsigned		flags;
+	int			jid;
+	int			seq;
+	int			pstatus;
+	int			ndeps;
+	int			njp;
+	int			nprocs;
+};
+
+struct cfdepend {
+	STAILQ_ENTRY(cfdepend)	tq[2];
+	struct cfjail		*j[2];
+	unsigned		flags;
+};
+
+extern void *emalloc(size_t);
+extern void *erealloc(void *, size_t);
+extern char *estrdup(const char *);
+extern int create_jail(struct cfjail *j);
+extern void failed(struct cfjail *j);
+extern void jail_note(const struct cfjail *j, const char *fmt, ...);
+extern void jail_warnx(const struct cfjail *j, const char *fmt, ...);
+
+extern int next_command(struct cfjail *j);
+extern int finish_command(struct cfjail *j);
+extern struct cfjail *next_proc(int nonblock);
+
+extern void load_config(void);
+extern struct cfjail *add_jail(void);
+extern void add_param(struct cfjail *j, const struct cfparam *p,
+    enum intparam ipnum, const char *value);
+extern int bool_param(const struct cfparam *p);
+extern int int_param(const struct cfparam *p, int *ip);
+extern const char *string_param(const struct cfparam *p);
+extern int check_intparams(struct cfjail *j);
+extern int import_params(struct cfjail *j);
+extern int equalopts(const char *opt1, const char *opt2);
+extern int wild_jail_name(const char *wname);
+extern int wild_jail_match(const char *jname, const char *wname);
+
+extern void dep_setup(int docf);
+extern int dep_check(struct cfjail *j);
+extern void dep_done(struct cfjail *j, unsigned flags);
+extern void dep_reset(struct cfjail *j);
+extern struct cfjail *next_jail(void);
+extern int start_state(const char *target, int docf, unsigned state,
+    int running);
+extern void requeue(struct cfjail *j, struct cfjails *queue);
+
+extern void yyerror(const char *);
+extern int yylex(void);
+
+extern struct cfjails cfjails;
+extern struct cfjails ready;
+extern struct cfjails depend;
+extern const char *cfname;
+extern int iflag;
+extern int note_remove;
+extern int paralimit;
+extern int verbose;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/jailparse.y
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/jailparse.y	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,216 @@
+%{
+/*-
+ * Copyright (c) 2011 James Gritton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/jail/jailparse.y 234712 2012-04-26 17:36:05Z jamie $");
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "jailp.h"
+
+#ifdef DEBUG
+#define YYDEBUG 1
+#endif
+%}
+
+%union {
+	struct cfjail		*j;
+	struct cfparams		*pp;
+	struct cfparam		*p;
+	struct cfstrings	*ss;
+	struct cfstring		*s;
+	char			*cs;
+}
+
+%token      PLEQ
+%token <cs> STR STR1 VAR VAR1
+
+%type <j>  jail
+%type <pp> param_l
+%type <p>  param name
+%type <ss> value
+%type <s>  string
+
+%%
+
+/*
+ * A config file is a series of jails (containing parameters) and jail-less
+ * parameters which realy belong to a global pseudo-jail.
+ */
+conf	:
+	;
+	| conf jail
+	;
+	| conf param ';'
+	{
+		struct cfjail *j;
+
+		j = TAILQ_LAST(&cfjails, cfjails);
+		if (!j || strcmp(j->name, "*")) {
+			j = add_jail();
+			j->name = estrdup("*");
+		}
+		TAILQ_INSERT_TAIL(&j->params, $2, tq);
+	}
+	| conf ';'
+
+jail	: STR '{' param_l '}'
+	{
+		$$ = add_jail();
+		$$->name = $1;
+		TAILQ_CONCAT(&$$->params, $3, tq);
+		free($3);
+	}
+	;
+
+param_l	:
+	{
+		$$ = emalloc(sizeof(struct cfparams));
+		TAILQ_INIT($$);
+	}
+	| param_l param ';'
+	{
+		$$ = $1;
+		TAILQ_INSERT_TAIL($$, $2, tq);
+	}
+	| param_l ';'
+	;
+
+/*
+ * Parameters have a name and an optional list of value strings,
+ * which may have "+=" or "=" preceeding them.
+ */
+param	: name
+	{
+		$$ = $1;
+	}
+	| name '=' value
+	{
+		$$ = $1;
+		TAILQ_CONCAT(&$$->val, $3, tq);
+		free($3);
+	}
+	| name PLEQ value
+	{
+		$$ = $1;
+		TAILQ_CONCAT(&$$->val, $3, tq);
+		$$->flags |= PF_APPEND;
+		free($3);
+	}
+	| name value
+	{
+		$$ = $1;
+		TAILQ_CONCAT(&$$->val, $2, tq);
+		free($2);
+	}
+	| error
+	{
+	}
+	;
+
+/*
+ * A parameter has a fixed name.  A variable definition looks just like a
+ * parameter except that the name is a variable.
+ */
+name	: STR
+	{
+		$$ = emalloc(sizeof(struct cfparam));
+		$$->name = $1;
+		TAILQ_INIT(&$$->val);
+		$$->flags = 0;
+	}
+	| VAR
+	{
+		$$ = emalloc(sizeof(struct cfparam));
+		$$->name = $1;
+		TAILQ_INIT(&$$->val);
+		$$->flags = PF_VAR;
+	}
+	;
+
+value	: string
+	{
+		$$ = emalloc(sizeof(struct cfstrings));
+		TAILQ_INIT($$);
+		TAILQ_INSERT_TAIL($$, $1, tq);
+	}
+	| value ',' string
+	{
+		$$ = $1;
+		TAILQ_INSERT_TAIL($$, $3, tq);
+	}
+	;
+
+/*
+ * Strings may be passed in pieces, because of quoting and/or variable
+ * interpolation.  Reassemble them into a single string.
+ */
+string	: STR
+	{
+		$$ = emalloc(sizeof(struct cfstring));
+		$$->s = $1;
+		$$->len = strlen($1);
+		STAILQ_INIT(&$$->vars);
+	}
+	| VAR
+	{
+		struct cfvar *v;
+
+		$$ = emalloc(sizeof(struct cfstring));
+		$$->s = estrdup("");
+		$$->len = 0;
+		STAILQ_INIT(&$$->vars);
+		v = emalloc(sizeof(struct cfvar));
+		v->name = $1;
+		v->pos = 0;
+		STAILQ_INSERT_TAIL(&$$->vars, v, tq);
+	}
+	| string STR1
+	{
+		size_t len1;
+
+		$$ = $1;
+		len1 = strlen($2);
+		$$->s = erealloc($$->s, $$->len + len1 + 1);
+		strcpy($$->s + $$->len, $2);
+		free($2);
+		$$->len += len1;
+	}
+	| string VAR1
+	{
+		struct cfvar *v;
+
+		$$ = $1;
+		v = emalloc(sizeof(struct cfvar));
+		v->name = $2;
+		v->pos = $$->len;
+		STAILQ_INSERT_TAIL(&$$->vars, v, tq);
+	}
+	;
+
+%%
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/jail/state.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/jail/state.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,469 @@
+/*-
+ * Copyright (c) 2011 James Gritton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/jail/state.c 234712 2012-04-26 17:36:05Z jamie $");
+
+#include <sys/uio.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jailp.h"
+
+struct cfjails ready = TAILQ_HEAD_INITIALIZER(ready);
+struct cfjails depend = TAILQ_HEAD_INITIALIZER(depend);
+
+static void dep_add(struct cfjail *from, struct cfjail *to, unsigned flags);
+static int cmp_jailptr(const void *a, const void *b);
+static int cmp_jailptr_name(const void *a, const void *b);
+static struct cfjail *find_jail(const char *name);
+static int running_jid(const char *name, int flags);
+
+static struct cfjail **jails_byname;
+static size_t njails;
+
+/*
+ * Set up jail dependency lists.
+ */
+void
+dep_setup(int docf)
+{
+	struct cfjail *j, *dj;
+	struct cfparam *p;
+	struct cfstring *s;
+	struct cfdepend *d;
+	const char *cs;
+	char *pname;
+	size_t plen;
+	int error, deps, ldeps;
+
+	if (!docf) {
+		/*
+		 * With no config file, let "depend" for a single jail
+		 * look at currently running jails.
+		 */
+		if ((j = TAILQ_FIRST(&cfjails)) &&
+		    (p = j->intparams[IP_DEPEND])) {
+			TAILQ_FOREACH(s, &p->val, tq) {
+				if (running_jid(s->s, 0) < 0) {
+					warnx("depends on nonexistent jail "
+					    "\"%s\"", s->s);
+					j->flags |= JF_FAILED;
+				}
+			}
+		}
+		return;
+	}
+
+	njails = 0;
+	TAILQ_FOREACH(j, &cfjails, tq)
+		njails++;
+	jails_byname = emalloc(njails * sizeof(struct cfjail *));
+	njails = 0;
+	TAILQ_FOREACH(j, &cfjails, tq)
+		jails_byname[njails++] = j;
+	qsort(jails_byname, njails, sizeof(struct cfjail *), cmp_jailptr);
+	error = 0;
+	deps = 0;
+	ldeps = 0;
+	plen = 0;
+	pname = NULL;
+	TAILQ_FOREACH(j, &cfjails, tq) {
+		if (j->flags & JF_FAILED)
+			continue;
+		if ((p = j->intparams[IP_DEPEND])) {
+			TAILQ_FOREACH(s, &p->val, tq) {
+				dj = find_jail(s->s);
+				if (dj != NULL) {
+					deps++;
+					dep_add(j, dj, 0);
+				} else {
+					jail_warnx(j,
+					    "depends on undefined jail \"%s\"",
+					    s->s);
+					j->flags |= JF_FAILED;
+				}
+			}
+		}
+		/* A jail has an implied dependency on its parent. */
+		if ((cs = strrchr(j->name, '.')))
+		{
+			if (plen < (size_t)(cs - j->name + 1)) {
+				plen = (cs - j->name) + 1;
+				pname = erealloc(pname, plen);
+			}
+			strlcpy(pname, j->name, plen);
+			dj = find_jail(pname);
+			if (dj != NULL) {
+				ldeps++;
+				dep_add(j, dj, DF_LIGHT);
+			}
+		}
+	}
+
+	/* Look for dependency loops. */
+	if (deps && (deps > 1 || ldeps)) {
+		(void)start_state(NULL, 0, 0, 0);
+		while ((j = TAILQ_FIRST(&ready))) {
+			requeue(j, &cfjails);
+			dep_done(j, DF_NOFAIL);
+		}
+		while ((j = TAILQ_FIRST(&depend)) != NULL) {
+			jail_warnx(j, "dependency loop");
+			j->flags |= JF_FAILED;
+			do {
+				requeue(j, &cfjails);
+				dep_done(j, DF_NOFAIL);
+			} while ((j = TAILQ_FIRST(&ready)));
+		}
+		TAILQ_FOREACH(j, &cfjails, tq)
+			STAILQ_FOREACH(d, &j->dep[DEP_FROM], tq[DEP_FROM])
+				d->flags &= ~DF_SEEN;
+	}
+	if (pname != NULL)
+		free(pname);
+}
+
+/*
+ * Return if a jail has dependencies.
+ */
+int
+dep_check(struct cfjail *j)
+{
+	int reset, depfrom, depto, ndeps, rev;
+	struct cfjail *dj;
+	struct cfdepend *d;
+
+	static int bits[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
+
+	if (j->ndeps == 0)
+		return 0;
+	ndeps = 0;
+	if ((rev = JF_DO_STOP(j->flags))) {
+		depfrom = DEP_TO;
+		depto = DEP_FROM;
+	} else {
+		depfrom = DEP_FROM;
+		depto = DEP_TO;
+	}
+	STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom]) {
+		if (d->flags & DF_SEEN)
+			continue;
+		dj = d->j[depto];
+		if (dj->flags & JF_FAILED) {
+			if (!(j->flags & (JF_DEPEND | JF_FAILED)) &&
+			    verbose >= 0)
+				jail_warnx(j, "skipped");
+			j->flags |= JF_FAILED;
+			continue;
+		}
+		/*
+		 * The dependee's state may be set (or changed) as a result of
+		 * being in a dependency it wasn't in earlier.
+		 */
+		reset = 0;
+		if (bits[dj->flags & JF_OP_MASK] <= 1) {
+			if (!(dj->flags & JF_OP_MASK)) {
+				reset = 1;
+				dj->flags |= JF_DEPEND;
+				requeue(dj, &ready);
+			}
+			/* Set or change the dependee's state. */
+			switch (j->flags & JF_OP_MASK) {
+			case JF_START:
+				dj->flags |= JF_START;
+				break;
+			case JF_SET:
+				if (!(dj->flags & JF_OP_MASK))
+					dj->flags |= JF_SET;
+				else if (dj->flags & JF_STOP)
+					dj->flags |= JF_START;
+				break;
+			case JF_STOP:
+			case JF_RESTART:
+				if (!(dj->flags & JF_STOP))
+					reset = 1;
+				dj->flags |= JF_STOP;
+				if (dj->flags & JF_SET)
+					dj->flags ^= (JF_START | JF_SET);
+				break;
+			}
+		}
+		if (reset)
+			dep_reset(dj);
+		if (!((d->flags & DF_LIGHT) &&
+		    (rev ? dj->jid < 0 : dj->jid > 0)))
+			ndeps++;
+	}
+	if (ndeps == 0)
+		return 0;
+	requeue(j, &depend);
+	return 1;
+}
+
+/*
+ * Resolve any dependencies from a finished jail.
+ */
+void
+dep_done(struct cfjail *j, unsigned flags)
+{
+	struct cfjail *dj;
+	struct cfdepend *d;
+	int depfrom, depto;
+
+	if (JF_DO_STOP(j->flags)) {
+		depfrom = DEP_TO;
+		depto = DEP_FROM;
+	} else {
+		depfrom = DEP_FROM;
+		depto = DEP_TO;
+	}
+	STAILQ_FOREACH(d, &j->dep[depto], tq[depto]) {
+		if ((d->flags & DF_SEEN) | (flags & ~d->flags & DF_LIGHT))
+			continue;
+		d->flags |= DF_SEEN;
+		dj = d->j[depfrom];
+		if (!(flags & DF_NOFAIL) && (j->flags & JF_FAILED) &&
+		    (j->flags & (JF_OP_MASK | JF_DEPEND)) !=
+		    (JF_SET | JF_DEPEND)) {
+			if (!(dj->flags & (JF_DEPEND | JF_FAILED)) &&
+			    verbose >= 0)
+				jail_warnx(dj, "skipped");
+			dj->flags |= JF_FAILED;
+		}
+		if (!--dj->ndeps && dj->queue == &depend)
+			requeue(dj, &ready);
+	}
+}
+
+/*
+ * Count a jail's dependencies and mark them as unseen.
+ */
+void
+dep_reset(struct cfjail *j)
+{
+	int depfrom;
+	struct cfdepend *d;
+
+	depfrom = JF_DO_STOP(j->flags) ? DEP_TO : DEP_FROM;
+	j->ndeps = 0;
+	STAILQ_FOREACH(d, &j->dep[depfrom], tq[depfrom])
+		j->ndeps++;
+}
+
+/*
+ * Find the next jail ready to do something.
+ */
+struct cfjail *
+next_jail(void)
+{
+	struct cfjail *j;
+
+	if (!(j = next_proc(!TAILQ_EMPTY(&ready))) &&
+	    (j = TAILQ_FIRST(&ready)) && JF_DO_STOP(j->flags) &&
+	    (j = TAILQ_LAST(&ready, cfjails)) && !JF_DO_STOP(j->flags)) {
+		TAILQ_FOREACH_REVERSE(j, &ready, cfjails, tq)
+			if (JF_DO_STOP(j->flags))
+				break;
+	}
+	if (j != NULL)
+		requeue(j, &cfjails);
+	return j;
+}
+
+/*
+ * Set jails to the proper start state.
+ */
+int
+start_state(const char *target, int docf, unsigned state, int running)
+{
+	struct iovec jiov[6];
+	struct cfjail *j, *tj;
+	int jid;
+	char namebuf[MAXHOSTNAMELEN];
+
+	if (!target || (!docf && state != JF_STOP) ||
+	    (!running && !strcmp(target, "*"))) {
+		/*
+		 * For a global wildcard (including no target specified),
+		 * set the state on all jails and start with those that
+		 * have no dependencies.
+		 */
+		TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
+			j->flags = (j->flags & JF_FAILED) | state |
+			    (docf ? JF_WILD : 0);
+			dep_reset(j);
+			requeue(j, j->ndeps ? &depend : &ready);
+		}
+	} else if (wild_jail_name(target)) {
+		/*
+		 * For targets specified singly, or with a non-global wildcard,
+		 * set their state and call them ready (even if there are
+		 * dependencies).  Leave everything else unqueued for now.
+		 */
+		if (running) {
+			/*
+			 * -R matches its wildcards against currently running
+			 * jails, not against the config file.
+			 */
+			*(const void **)&jiov[0].iov_base = "lastjid";
+			jiov[0].iov_len = sizeof("lastjid");
+			jiov[1].iov_base = &jid;
+			jiov[1].iov_len = sizeof(jid);
+			*(const void **)&jiov[2].iov_base = "jid";
+			jiov[2].iov_len = sizeof("jid");
+			jiov[3].iov_base = &jid;
+			jiov[3].iov_len = sizeof(jid);
+			*(const void **)&jiov[4].iov_base = "name";
+			jiov[4].iov_len = sizeof("name");
+			jiov[5].iov_base = &namebuf;
+			jiov[5].iov_len = sizeof(namebuf);
+			for (jid = 0; jail_get(jiov, 6, 0) > 0; ) {
+				if (wild_jail_match(namebuf, target)) {
+					j = add_jail();
+					j->name = estrdup(namebuf);
+					j->jid = jid;
+					j->flags = (j->flags & JF_FAILED) |
+					    state | JF_WILD;
+					dep_reset(j);
+					requeue(j, &ready);
+				}
+			}
+		} else {
+			TAILQ_FOREACH_SAFE(j, &cfjails, tq, tj) {
+				if (wild_jail_match(j->name, target)) {
+					j->flags = (j->flags & JF_FAILED) |
+					    state | JF_WILD;
+					dep_reset(j);
+					requeue(j, &ready);
+				}
+			}
+		}
+	} else {
+		j = find_jail(target);
+		if (j == NULL && state == JF_STOP) {
+			/* Allow -[rR] to specify a currently running jail. */
+			if ((jid = running_jid(target, JAIL_DYING)) > 0) {
+				j = add_jail();
+				j->name = estrdup(target);
+				j->jid = jid;
+			}
+		}
+		if (j == NULL) {
+			warnx("\"%s\" not found", target);
+			return -1;
+		}
+		j->flags = (j->flags & JF_FAILED) | state;
+		dep_reset(j);
+		requeue(j, &ready);
+	}
+	return 0;
+}
+
+/*
+ * Move a jail to a new list.
+ */
+void
+requeue(struct cfjail *j, struct cfjails *queue)
+{
+	if (j->queue != queue) {
+		TAILQ_REMOVE(j->queue, j, tq);
+		TAILQ_INSERT_TAIL(queue, j, tq);
+		j->queue = queue;
+	}
+}
+
+/*
+ * Add a dependency edge between two jails.
+ */
+static void
+dep_add(struct cfjail *from, struct cfjail *to, unsigned flags)
+{
+	struct cfdepend *d;
+
+	d = emalloc(sizeof(struct cfdepend));
+	d->flags = flags;
+	d->j[DEP_FROM] = from;
+	d->j[DEP_TO] = to;
+	STAILQ_INSERT_TAIL(&from->dep[DEP_FROM], d, tq[DEP_FROM]);
+	STAILQ_INSERT_TAIL(&to->dep[DEP_TO], d, tq[DEP_TO]);
+}
+
+/*
+ * Compare jail pointers for qsort/bsearch.
+ */
+static int
+cmp_jailptr(const void *a, const void *b)
+{
+	return strcmp((*((struct cfjail * const *)a))->name,
+	    ((*(struct cfjail * const *)b))->name);
+}
+
+static int
+cmp_jailptr_name(const void *a, const void *b)
+{
+	return strcmp((const char *)a, ((*(struct cfjail * const *)b))->name);
+}
+
+/*
+ * Find a jail object by name.
+ */
+static struct cfjail *
+find_jail(const char *name)
+{
+	struct cfjail **jp;
+
+	jp = bsearch(name, jails_byname, njails, sizeof(struct cfjail *),
+	    cmp_jailptr_name);
+	return jp ? *jp : NULL;
+}
+
+/*
+ * Return the named jail's jid if it is running, and -1 if it isn't.
+ */
+static int
+running_jid(const char *name, int flags)
+{
+	struct iovec jiov[2];
+	char *ep;
+	int jid;
+
+	if ((jid = strtol(name, &ep, 10)) && !*ep) {
+		*(const void **)&jiov[0].iov_base = "jid";
+		jiov[0].iov_len = sizeof("jid");
+		jiov[1].iov_base = &jid;
+		jiov[1].iov_len = sizeof(jid);
+	} else {
+		*(const void **)&jiov[0].iov_base = "name";
+		jiov[0].iov_len = sizeof("name");
+		jiov[1].iov_len = strlen(name) + 1;
+		jiov[1].iov_base = alloca(jiov[1].iov_len);
+		strcpy(jiov[1].iov_base, name);
+	}
+	return jail_get(jiov, 2, flags);
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/kbdmap/kbdmap.c
--- a/head/usr.sbin/kbdmap/kbdmap.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/kbdmap/kbdmap.c	Wed Jul 25 16:29:58 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/kbdmap/kbdmap.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/kbdmap/kbdmap.c 237257 2012-06-19 06:10:31Z eadler $");
 
 #include <sys/types.h>
 #include <sys/queue.h>
@@ -327,7 +327,6 @@
 	FILE *fp;
 	char *cmd, *dialog;
 	char tmp_name[] = "/tmp/_kbd_lang.XXXX";
-	const char *ext;
 	int fd, i, size;
 
 	fd = mkstemp(tmp_name);
@@ -339,8 +338,6 @@
 	asprintf(&dialog, "/usr/bin/dialog --clear --title \"Keyboard Menu\" "
 			  "--menu \"%s\" 0 0 0", menu);
 
-	ext = extract_name(dir);
-
 	/* start right font, assume that current font is equal
 	 * to default font in /etc/rc.conf
 	 *	
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/kldxref/ef.c
--- a/head/usr.sbin/kldxref/ef.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/kldxref/ef.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/kldxref/ef.c 237258 2012-06-19 06:10:34Z eadler $
  */
 
 #include <sys/param.h>
@@ -532,7 +532,7 @@
 	int error;
 	int phlen, res;
 	int nsegs;
-	Elf_Phdr *phdr, *phdyn, *phphdr, *phlimit;
+	Elf_Phdr *phdr, *phdyn, *phlimit;
 
 	if (filename == NULL)
 		return EFTYPE;
@@ -576,7 +576,6 @@
 		phlimit = phdr + hdr->e_phnum;
 		nsegs = 0;
 		phdyn = NULL;
-		phphdr = NULL;
 		while (phdr < phlimit) {
 			if (verbose > 1)
 				ef_print_phdr(phdr);
@@ -590,7 +589,6 @@
 				ef->ef_segs[nsegs++] = phdr;
 				break;
 			case PT_PHDR:
-				phphdr = phdr;
 				break;
 			case PT_DYNAMIC:
 				phdyn = phdr;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/lpr/common_source/common.c
--- a/head/usr.sbin/lpr/common_source/common.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/lpr/common_source/common.c	Wed Jul 25 16:29:58 2012 +0300
@@ -43,7 +43,7 @@
 #endif
 
 #include "lp.cdefs.h"		/* A cross-platform version of <sys/cdefs.h> */
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/lpr/common_source/common.c 238547 2012-07-17 09:34:52Z jh $");
 
 #include <sys/param.h>
 #include <sys/stat.h>
@@ -130,15 +130,17 @@
 		seteuid(uid);
 		return (-1);
 	}
-	if (fstat(dirp->dd_fd, &stbuf) < 0)
+	if (fstat(dirfd(dirp), &stbuf) < 0)
 		goto errdone;
 	seteuid(uid);
 
 	/*
 	 * Estimate the array size by taking the size of the directory file
-	 * and dividing it by a multiple of the minimum size entry. 
+	 * and dividing it by a multiple of the minimum size entry.
 	 */
 	arraysz = (stbuf.st_size / 24);
+	if (arraysz < 16)
+		arraysz = 16;
 	queue = (struct jobqueue **)malloc(arraysz * sizeof(struct jobqueue *));
 	if (queue == NULL)
 		goto errdone;
@@ -641,7 +643,7 @@
 	 *   secs=<n>      - seconds it took to transfer the file
 	 *   bytes=<n>     - number of bytes transfered (ie, "bytecount")
 	 *   bps=<n.n>e<n> - Bytes/sec (if the transfer was "big enough"
-	 *		     for this to be useful) 
+	 *		     for this to be useful)
 	 * ! top=<str>     - type of printer (if the type is defined in
 	 *		     printcap, and if this statline is for sending
 	 *		     a file to that ptr)
@@ -719,7 +721,7 @@
 	if (remspace > 1) {
 		strcpy(eostat, "\n");
 	} else {
-		/* probably should back up to just before the final " x=".. */  
+		/* probably should back up to just before the final " x=".. */
 		strcpy(statline+STATLINE_SIZE-2, "\n");
 	}
 	statfile = open(statfname, O_WRONLY|O_APPEND, 0664);
@@ -732,7 +734,7 @@
 	close(statfile);
 
 	return;
-#undef UPD_EOSTAT	
+#undef UPD_EOSTAT
 }
 
 #include <stdarg.h>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/lpr/lpc/cmds.c
--- a/head/usr.sbin/lpr/lpc/cmds.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/lpr/lpc/cmds.c	Wed Jul 25 16:29:58 2012 +0300
@@ -41,7 +41,7 @@
 #endif
 
 #include "lp.cdefs.h"		/* A cross-platform version of <sys/cdefs.h> */
-__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpc/cmds.c 234244 2012-04-13 22:34:01Z delphij $");
+__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpc/cmds.c 234826 2012-04-30 01:10:13Z gad $");
 
 /*
  * lpc -- line printer control program -- commands:
@@ -163,6 +163,14 @@
 				break;
 			}
 		}
+		if (argc < 1) {
+			printf("error: No printer name(s) specified before"
+			    " '-msg'.\n");
+			printf("usage: %s  {all | printer ...}",
+			    generic_cmdname);
+			printf(" [-msg <text> ...]\n");
+			return;
+		}
 	}
 
 	/* call initialization routine, if there is one for this cmd */
@@ -1001,12 +1009,30 @@
 void
 setstatus_q(struct printer *pp)
 {
+	struct stat stbuf;
+	int not_shown;
 	char lf[MAXPATHLEN];
 
 	lock_file_name(pp, lf, sizeof lf);
 	printf("%s:\n", pp->printer);
 
 	upstat(pp, generic_msg, 1);
+
+	/*
+	 * Warn the user if 'lpq' will not display this new status-message.
+	 * Note that if lock file does not exist, then the queue is enabled
+	 * for both queuing and printing.
+	 */
+	not_shown = 1;
+	if (stat(lf, &stbuf) >= 0) {
+		if (stbuf.st_mode & LFM_PRINT_DIS)
+			not_shown = 0;
+	}
+	if (not_shown) {
+		printf("\tnote: This queue currently has printing enabled,\n");
+		printf("\t    so this -msg will only be shown by 'lpq' if\n");
+		printf("\t    a job is actively printing on it.\n");
+	}
 }
 
 /*
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/lpr/lpr/lpr.c
--- a/head/usr.sbin/lpr/lpr/lpr.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/lpr/lpr/lpr.c	Wed Jul 25 16:29:58 2012 +0300
@@ -50,7 +50,7 @@
 #endif
 
 #include "lp.cdefs.h"		/* A cross-platform version of <sys/cdefs.h> */
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpr/lpr.c 236289 2012-05-30 04:08:29Z eadler $");
 
 /*
  *      lpr -- off line print
@@ -846,7 +846,7 @@
 
 	(void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir);
 	seteuid(euid);
-	if ((fd = open(buf, O_RDWR|O_CREAT, 0661)) < 0) {
+	if ((fd = open(buf, O_RDWR|O_CREAT, 0664)) < 0) {
 		printf("%s: cannot create %s\n", progname, buf);
 		exit(1);
 	}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/Makefile
--- a/head/usr.sbin/mfiutil/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/usr.sbin/mfiutil/Makefile 237260 2012-06-19 06:18:42Z eadler $
 PROG=	mfiutil
 
 SRCS=	mfiutil.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c mfi_flash.c \
@@ -6,7 +6,6 @@
 MAN8=	mfiutil.8
 
 CFLAGS+= -fno-builtin-strftime
-WARNS?=3
 
 DPADD=	${LIBUTIL}
 LDADD=	-lutil
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_cmd.c
--- a/head/usr.sbin/mfiutil/mfi_cmd.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_cmd.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_cmd.c 237259 2012-06-19 06:18:37Z eadler $
  */
 
 #include <sys/errno.h>
@@ -301,12 +301,12 @@
 }
 
 int
-mfi_open(int unit)
+mfi_open(int unit, int acs)
 {
 	char path[MAXPATHLEN];
 
 	snprintf(path, sizeof(path), "/dev/mfi%d", unit);
-	return (open(path, O_RDWR));
+	return (open(path, acs));
 }
 
 void
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_config.c
--- a/head/usr.sbin/mfiutil/mfi_config.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_config.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_config.c 233713 2012-03-30 23:39:39Z ambrisko $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_config.c 237260 2012-06-19 06:18:42Z eadler $
  */
 
 #include <sys/param.h>
@@ -35,6 +35,7 @@
 #endif
 #include <err.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <libutil.h>
 #ifdef DEBUG
 #include <stdint.h>
@@ -151,13 +152,13 @@
 }
 
 static int
-clear_config(int ac, char **av)
+clear_config(int ac __unused, char **av __unused)
 {
 	struct mfi_ld_list list;
 	int ch, error, fd;
 	u_int i;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -410,7 +411,7 @@
 
 /* Populate an array with drives. */
 static void
-build_array(int fd, char *arrayp, struct array_info *array_info,
+build_array(int fd __unused, char *arrayp, struct array_info *array_info,
     struct config_id_state *state, int verbose)
 {
 	struct mfi_array *ar = (struct mfi_array *)arrayp;
@@ -575,7 +576,7 @@
 	narrays = 0;
 	error = 0;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -857,7 +858,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -925,7 +926,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -1050,7 +1051,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -1196,7 +1197,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -1233,7 +1234,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_drive.c
--- a/head/usr.sbin/mfiutil/mfi_drive.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_drive.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,13 +26,14 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_drive.c 233713 2012-03-30 23:39:39Z ambrisko $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_drive.c 237329 2012-06-20 17:20:25Z mjacob $
  */
 
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <ctype.h>
 #include <err.h>
+#include <fcntl.h>
 #include <libutil.h>
 #include <limits.h>
 #include <stdio.h>
@@ -71,7 +72,7 @@
 		else
 			snprintf(buf, sizeof(buf), "%2u", device_id);
 
-		fd = mfi_open(mfi_unit);
+		fd = mfi_open(mfi_unit, O_RDWR);
 		if (fd < 0) {
 			warn("mfi_open");
 			return (buf);
@@ -329,11 +330,13 @@
 const char *
 mfi_pd_inq_string(struct mfi_pd_info *info)
 {
-	struct scsi_inquiry_data *inq_data;
+	struct scsi_inquiry_data iqd, *inq_data = &iqd;
 	char vendor[16], product[48], revision[16], rstr[12], serial[SID_VENDOR_SPECIFIC_0_SIZE];
 	static char inq_string[64];
 
-	inq_data = (struct scsi_inquiry_data *)info->inquiry_data;
+	memcpy(inq_data, info->inquiry_data,
+	    (sizeof (iqd) <  sizeof (info->inquiry_data))?
+	    sizeof (iqd) : sizeof (info->inquiry_data));
 	if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data))
 		return (NULL);
 	if (SID_TYPE(inq_data) != T_DIRECT)
@@ -383,7 +386,7 @@
 	uint8_t mbox[6];
 	int error, fd;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -484,7 +487,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -541,7 +544,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -597,7 +600,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -663,7 +666,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -723,7 +726,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_evt.c
--- a/head/usr.sbin/mfiutil/mfi_evt.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_evt.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,12 +26,13 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_evt.c 228278 2011-12-05 15:11:35Z jhb $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_evt.c 237260 2012-06-19 06:18:42Z eadler $
  */
 
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <err.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
@@ -63,7 +64,7 @@
 }
 
 static int
-show_logstate(int ac, char **av)
+show_logstate(int ac, char **av __unused)
 {
 	struct mfi_evt_log_state info;
 	int error, fd;
@@ -73,7 +74,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -541,7 +542,7 @@
 	int ch, error, fd, num_events, verbose;
 	u_int i;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_flash.c
--- a/head/usr.sbin/mfiutil/mfi_flash.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_flash.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_flash.c 222899 2011-06-09 19:52:28Z bz $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_flash.c 237259 2012-06-19 06:18:37Z eadler $
  */
 
 #include <sys/param.h>
@@ -150,7 +150,7 @@
 		goto error;
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_patrol.c
--- a/head/usr.sbin/mfiutil/mfi_patrol.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_patrol.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,12 +26,13 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_patrol.c 223345 2011-06-20 21:28:50Z bz $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_patrol.c 237260 2012-06-19 06:18:42Z eadler $
  */
 
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <err.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -74,7 +75,7 @@
 }
 
 static int
-show_patrol(int ac, char **av)
+show_patrol(int ac __unused, char **av __unused)
 {
 	struct mfi_pr_properties prop;
 	struct mfi_pr_status status;
@@ -86,7 +87,7 @@
 	int error, fd;
 	u_int i;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -192,11 +193,11 @@
 MFI_COMMAND(show, patrol, show_patrol);
 
 static int
-start_patrol(int ac, char **av)
+start_patrol(int ac __unused, char **av __unused)
 {
 	int error, fd;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -218,11 +219,11 @@
 MFI_COMMAND(start, patrol, start_patrol);
 
 static int
-stop_patrol(int ac, char **av)
+stop_patrol(int ac __unused, char **av __unused)
 {
 	int error, fd;
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -292,7 +293,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_show.c
--- a/head/usr.sbin/mfiutil/mfi_show.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_show.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,12 +26,13 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_show.c 225798 2011-09-27 14:28:07Z emaste $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_show.c 237260 2012-06-19 06:18:42Z eadler $
  */
 
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <err.h>
+#include <fcntl.h>
 #include <libutil.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -50,7 +51,7 @@
 }
 
 static int
-show_adapter(int ac, char **av)
+show_adapter(int ac, char **av __unused)
 {
 	struct mfi_ctrl_info info;
 	char stripe[5];
@@ -61,7 +62,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -135,7 +136,7 @@
 MFI_COMMAND(show, adapter, show_adapter);
 
 static int
-show_battery(int ac, char **av)
+show_battery(int ac, char **av __unused)
 {
 	struct mfi_bbu_capacity_info cap;
 	struct mfi_bbu_design_info design;
@@ -148,7 +149,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -224,7 +225,29 @@
 	}
 	if (stat.fw_status & MFI_BBU_STATE_DISCHARGE_ACTIVE) {
 		printf("%s DISCHARGING", comma ? "," : "");
+		comma = 1;
 	}
+	if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_REQ) {
+		printf("%s LEARN_CYCLE_REQUESTED", comma ? "," : "");
+		comma = 1;
+	}
+	if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_ACTIVE) {
+		printf("%s LEARN_CYCLE_ACTIVE", comma ? "," : "");
+		comma = 1;
+	}
+	if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_FAIL) {
+		printf("%s LEARN_CYCLE_FAIL", comma ? "," : "");
+		comma = 1;
+	}
+	if (stat.fw_status & MFI_BBU_STATE_LEARN_CYC_TIMEOUT) {
+		printf("%s LEARN_CYCLE_TIMEOUT", comma ? "," : "");
+		comma = 1;
+	}
+	if (stat.fw_status & MFI_BBU_STATE_I2C_ERR_DETECT) {
+		printf("%s I2C_ERROR_DETECT", comma ? "," : "");
+		comma = 1;
+	}
+
 	if (!comma)
 		printf(" normal");
 	printf("\n");
@@ -281,7 +304,7 @@
 }
 
 static int
-show_config(int ac, char **av)
+show_config(int ac, char **av __unused)
 {
 	struct mfi_config_data *config;
 	struct mfi_array *ar;
@@ -298,7 +321,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -387,7 +410,7 @@
 MFI_COMMAND(show, config, show_config);
 
 static int
-show_volumes(int ac, char **av)
+show_volumes(int ac, char **av __unused)
 {
 	struct mfi_ld_list list;
 	struct mfi_ld_info info;
@@ -399,7 +422,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -470,7 +493,7 @@
 MFI_COMMAND(show, volumes, show_volumes);
 
 static int
-show_drives(int ac, char **av)
+show_drives(int ac, char **av __unused)
 {
 	struct mfi_pd_list *list;
 	struct mfi_pd_info info;
@@ -482,7 +505,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -578,7 +601,7 @@
 }
 
 static int
-show_firmware(int ac, char **av)
+show_firmware(int ac, char **av __unused)
 {
 	struct mfi_ctrl_info info;
 	struct mfi_info_component header;
@@ -590,7 +613,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -634,7 +657,7 @@
 MFI_COMMAND(show, firmware, show_firmware);
 
 static int
-show_progress(int ac, char **av)
+show_progress(int ac, char **av __unused)
 {
 	struct mfi_ld_list llist;
 	struct mfi_pd_list *plist;
@@ -650,7 +673,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfi_volume.c
--- a/head/usr.sbin/mfiutil/mfi_volume.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfi_volume.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,12 +26,13 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfi_volume.c 225331 2011-09-02 16:00:51Z jhb $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfi_volume.c 237259 2012-06-19 06:18:37Z eadler $
  */
 
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <err.h>
+#include <fcntl.h>
 #include <libutil.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -294,7 +295,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -402,7 +403,7 @@
 		return (ENOSPC);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDWR);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
@@ -453,7 +454,7 @@
 		return (EINVAL);
 	}
 
-	fd = mfi_open(mfi_unit);
+	fd = mfi_open(mfi_unit, O_RDONLY);
 	if (fd < 0) {
 		error = errno;
 		warn("mfi_open");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfiutil.c
--- a/head/usr.sbin/mfiutil/mfiutil.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfiutil.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfiutil.c 223345 2011-06-20 21:28:50Z bz $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfiutil.c 237260 2012-06-19 06:18:42Z eadler $
  */
 
 #include <sys/errno.h>
@@ -92,10 +92,10 @@
 }
 
 static int
-version(int ac, char **av)
+version(int ac __unused, char **av __unused)
 {
 
-	printf("mfiutil version 1.0.13");
+	printf("mfiutil version 1.0.14");
 #ifdef DEBUG
 	printf(" (DEBUG)");
 #endif
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mfiutil/mfiutil.h
--- a/head/usr.sbin/mfiutil/mfiutil.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mfiutil/mfiutil.h	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: head/usr.sbin/mfiutil/mfiutil.h 223345 2011-06-20 21:28:50Z bz $
+ * $FreeBSD: head/usr.sbin/mfiutil/mfiutil.h 237259 2012-06-19 06:18:37Z eadler $
  */
 
 #ifndef __MFIUTIL_H__
@@ -139,7 +139,7 @@
 int	mfi_lookup_volume(int fd, const char *name, uint8_t *target_id);
 int	mfi_dcmd_command(int fd, uint32_t opcode, void *buf, size_t bufsize,
     uint8_t *mbox, size_t mboxlen, uint8_t *statusp);
-int	mfi_open(int unit);
+int	mfi_open(int unit, int acs);
 int	mfi_ctrl_get_info(int fd, struct mfi_ctrl_info *info, uint8_t *statusp);
 int	mfi_ld_get_info(int fd, uint8_t target_id, struct mfi_ld_info *info,
     uint8_t *statusp);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/mptutil/mpt_show.c
--- a/head/usr.sbin/mptutil/mpt_show.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/mptutil/mpt_show.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$FreeBSD$");
+__RCSID("$FreeBSD: head/usr.sbin/mptutil/mpt_show.c 236287 2012-05-30 03:57:49Z eadler $");
 
 #include <sys/param.h>
 #include <sys/errno.h>
@@ -538,7 +538,7 @@
 {
 	CONFIG_PAGE_RAID_PHYS_DISK_0 *pinfo;
 	U16 IOCStatus;
-	int fd, i;
+	int error, fd, i;
 
 	if (ac != 1) {
 		warnx("show drives: extra arguments");
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,8 @@
+# $FreeBSD: head/usr.sbin/nandsim/Makefile 235537 2012-05-17 10:11:18Z gber $
+
+PROG=	nandsim
+SRCS=	nandsim.c nandsim_rcfile.c nandsim_cfgparse.c
+BINDIR=	/usr/sbin
+MAN=	nandsim.8
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/nandsim.8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/nandsim.8	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,229 @@
+.\" Copyright (c) 2010 Semihalf
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: head/usr.sbin/nandsim/nandsim.8 235542 2012-05-17 11:29:22Z joel $
+.\"
+.Dd August 10, 2010
+.Dt NANDSIM 8
+.Os
+.Sh NAME
+.Nm nandsim
+.Nd NAND simulator control program
+.Sh SYNOPSIS
+.Nm
+.Ic status
+.Aq ctrl_no | Fl -all  | Fl a
+.Op Fl v
+.Nm
+.Ic conf
+.Aq filename
+.Nm
+.Ic start
+.Aq ctrl_no
+.Nm
+.Ic mod
+.Aq ctrl_no:cs_no | Fl l Aq loglevel
+.Op Fl p Aq prog_time
+.Op Fl e Aq erase_time
+.Op Fl r Aq read_time
+.Op Fl E Aq error_ratio
+.Op Fl h
+.Nm
+.Ic stop
+.Aq ctrl_no
+.Nm
+.Ic error
+.Aq ctrl_no:cs_no
+.Aq page_num
+.Aq column
+.Aq length
+.Aq pattern
+.Nm
+.Ic bb
+.Aq ctrl_no:cs_no
+.Op blk_num,blk_num2,...
+.Op Fl U
+.Op Fl L
+.Nm
+.Ic freeze
+.Op ctrl_no
+.Nm
+.Ic log
+.Aq ctrl_no | Fl -all  | Fl a
+.Nm
+.Ic stats
+.Aq ctrl_no:cs_no
+.Aq page_num
+.Nm
+.Ic dump
+.Aq ctrl_no:cs_no
+.Aq filename
+.Nm
+.Ic restore
+.Aq ctrl_no:chip_no
+.Aq filename
+.Nm
+.Ic destroy
+.Aq ctrl_no[:cs_no] | Fl -all | Fl a
+.Nm
+.Ic help
+.Op Fl v
+.Sh COMMAND DESCRIPTION
+Controllers and chips are arranged into a simple hierarchy.
+There can be up to 4 controllers configured, each with 4 chip select (CS) lines.
+A given chip is connected to one of the chip selects.
+.Pp
+Controllers are specified as
+.Aq ctrl_no ;
+chip selects are specified as
+.Aq cs_no .
+.Bl -tag -width periphlist
+.It Ic status
+Gets controller(s) status. If
+.Fl a
+or
+.Fl -all
+flag is specified - command will print status of every controller
+currently available.
+Optional flag
+.Fl v
+causes printing complete information about the controller, and all
+chips attached to it.
+.It Ic conf
+Reads simulator configuration from a specified file (this includes
+the simulation "layout" i.e. controllers-chips assignments).
+Configuration changes for an already started simulation require a
+full stop-start cycle in order to take effect i.e.:
+.Bl -column
+.It nandsim stop ...
+.It nandsim destroy ...
+.Pp
+.It << edit config file >>
+.Pp
+.It nandsim conf ...
+.It nandsim start ...
+.El
+.It Ic mod
+Alters simulator parameters on-the-fly.
+If controller number and CS pair is not specified, the general
+simulator parameters (not specific to a controller or a chip) will be modified.
+Changing chip's parameters requires specifying both controller number and CS
+to which the given chip is connected.
+Parameters which can be altered:
+.Pp
+General simulator related:
+.Bl -tag -width flag
+.It Fl l Aq log_level
+change logging level to
+.Aq log_level
+.El
+.Pp
+Chip related:
+.Bl -tag -width flag
+.It Fl p Aq prog_time
+change prog time for specified chip to
+.Aq prog_time
+.It Fl e Aq erase_time
+change erase time for specified chip to
+.Aq erase_time
+.It Fl r Aq read_time
+change read time for specified chip to
+.Aq read_time
+.It Fl E Aq error_ratio
+change error ratio for specified chip to
+.Aq error_ratio .
+Error ratio is a number of errors per million read/write bytes.
+.El
+.Pp
+Additionally, flag
+.Fl h
+will list parameters which can be altered.
+.El
+.Bl -tag -width periphlist
+.It Ic bb
+Marks/unmarks a specified block as bad.
+To mark/unmark the bad condition an a block, the following parameters
+have to be supplied: controller number, CS number, and at least one
+block number.
+It is possible to specify multiple blocks, by separating blocks numbers
+with a comma.
+The following options can be used for the 'bb' command:
+.Bl -tag -width flag
+.It Fl U
+unmark the bad previously marked block as bad.
+.It Fl L
+list all blocks marked as bad on a given chip.
+.El
+.It Ic log
+Prints activity log of the specified controller to stdout; if
+controller number is not specifed, logs for all available
+controllers are printed.
+.It Ic stats
+Print statistics of the selected controller, chip and page.
+Statistics includes read count, write count, raw read count, raw
+write count, ECC stats (succeeded corrections, failed correction).
+.It Ic dump
+Dumps a snaphot of a single chip (including data and bad blocks
+information, wearout level) into the file.
+.It Ic restore
+Restores chip state from a dump-file snapshot (produced previously
+with the 'dump' command).
+.It Ic start
+Starts a controller i.e. the simulation.
+.It Ic stop
+Stops an already started controller; if the controller number is not
+supplied, attempts to stop all currently working controllers.
+.It Ic destroy
+Removes existing active chip/controller and its configuration from
+memory and releases the resources.
+Specifying flag
+.Fl a
+or
+.Fl -all
+causes removal of every chip and controller.
+Controller must be stopped in order to be destroyed.
+.It Ic error
+Directly overwrites a certain number of bytes in the specified page
+at a given offset with a supplied pattern (which mimics the
+corruption of flash contents).
+.It Ic help
+Prints synopsis,
+.Fl v
+gives more verbose output.
+.It Ic freeze
+Stops simulation of given controller (simulates power-loss).
+All commands issues to any chip on this controller are ignored.
+.El
+.Sh SEE ALSO
+.Xr nand 4 ,
+.Xr nandsim 4
+.Xr nandsim.conf 5
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 10.0 .
+.Sh AUTHOR
+This utility was written by
+.An Lukasz Wojcik .
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/nandsim.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/nandsim.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,1397 @@
+/*-
+ * Copyright (C) 2009-2012 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Control application for the NAND simulator.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/usr.sbin/nandsim/nandsim.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <dev/nand/nandsim.h>
+#include <dev/nand/nand_dev.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sysexits.h>
+
+#include "nandsim_cfgparse.h"
+
+#define SIMDEVICE	"/dev/nandsim.ioctl"
+
+#define error(fmt, args...) do { \
+    printf("ERROR: " fmt "\n", ##args); } while (0)
+
+#define warn(fmt, args...) do { \
+    printf("WARNING: " fmt "\n", ##args); } while (0)
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debug(fmt, args...) do { \
+    printf("NANDSIM_CONF:" fmt "\n", ##args); } while (0)
+#else
+#define debug(fmt, args...) do {} while(0)
+#endif
+
+#define NANDSIM_RAM_LOG_SIZE 16384
+
+#define MSG_NOTRUNNING		"Controller#%d is not running.Please start" \
+    " it first."
+#define MSG_RUNNING		"Controller#%d is already running!"
+#define MSG_CTRLCHIPNEEDED	"You have to specify ctrl_no:cs_no pair!"
+#define MSG_STATUSACQCTRLCHIP	"Could not acquire status for ctrl#%d chip#%d"
+#define MSG_STATUSACQCTRL	"Could not acquire status for ctrl#%d"
+#define MSG_NOCHIP		"There is no such chip configured (chip#%d "\
+    "at ctrl#%d)!"
+
+#define MSG_NOCTRL		"Controller#%d is not configured!"
+#define MSG_NOTCONFIGDCTRLCHIP	"Chip connected to ctrl#%d at cs#%d " \
+    "is not configured."
+
+typedef int (commandfunc_t)(int , char **);
+
+static struct nandsim_command *getcommand(char *);
+static int parse_devstring(char *, int *, int *);
+static void printchip(struct sim_chip *, uint8_t);
+static void printctrl(struct sim_ctrl *);
+static int opendev(int *);
+static commandfunc_t cmdstatus;
+static commandfunc_t cmdconf;
+static commandfunc_t cmdstart;
+static commandfunc_t cmdstop;
+static commandfunc_t cmdmod;
+static commandfunc_t cmderror;
+static commandfunc_t cmdbb;
+static commandfunc_t cmdfreeze;
+static commandfunc_t cmdlog;
+static commandfunc_t cmdstats;
+static commandfunc_t cmddump;
+static commandfunc_t cmdrestore;
+static commandfunc_t cmddestroy;
+static commandfunc_t cmdhelp;
+static int checkusage(int, int, char **);
+static int is_chip_created(int, int, int *);
+static int is_ctrl_created(int, int *);
+static int is_ctrl_running(int, int *);
+static int assert_chip_connected(int , int);
+static int printstats(int, int, uint32_t, int);
+
+struct nandsim_command {
+	const char	*cmd_name;	/* Command name */
+	commandfunc_t	*commandfunc;	/* Ptr to command function */
+	uint8_t		req_argc;	/* Mandatory arguments count */
+	const char	*usagestring;	/* Usage string */
+};
+
+static struct nandsim_command commands[] = {
+	{"status", cmdstatus, 1,
+	    "status <ctl_no|--all|-a> [-v]\n" },
+	{"conf", cmdconf, 1,
+	    "conf <filename>\n" },
+	{"start", cmdstart, 1,
+	    "start <ctrl_no>\n" },
+	{"mod", cmdmod, 2,
+	    "mod [-l <loglevel>] | <ctl_no:cs_no> [-p <prog_time>]\n"
+	    "\t[-e <erase_time>] [-r <read_time>]\n"
+	    "\t[-E <error_ratio>] | [-h]\n" },
+	{"stop", cmdstop, 1,
+	    "stop <ctrl_no>\n" },
+	{"error", cmderror, 5,
+	    "error <ctrl_no:cs_no> <page_num> <column> <length> <pattern>\n" },
+	{"bb", cmdbb, 2,
+	    "bb <ctl_no:cs_no>  [blk_num1,blk_num2,..] [-U] [-L]\n" },
+	{"freeze", cmdfreeze, 1,
+	    "freeze [ctrl_no]\n" },
+	{"log", cmdlog, 1,
+	    "log <ctrl_no|--all|-a>\n" },
+	{"stats", cmdstats, 2,
+	    "stats <ctrl_no:cs_no> <pagenumber>\n" },
+	{"dump", cmddump, 2,
+	    "dump <ctrl_no:cs_no> <filename>\n" },
+	{"restore", cmdrestore, 2,
+	    "restore <ctrl_no:chip_no> <filename>\n" },
+	{"destroy", cmddestroy, 1,
+	    "destroy <ctrl_no[:cs_no]|--all|-a>\n" },
+	{"help", cmdhelp, 0,
+	    "help [-v]" },
+	{NULL, NULL, 0, NULL},
+};
+
+
+/* Parse command name, and start appropriate function */
+static struct nandsim_command*
+getcommand(char *arg)
+{
+	struct nandsim_command *opts;
+
+	for (opts = commands; (opts != NULL) &&
+	    (opts->cmd_name != NULL); opts++) {
+		if (strcmp(opts->cmd_name, arg) == 0)
+			return (opts);
+	}
+	return (NULL);
+}
+
+/*
+ * Parse given string in format <ctrl_no>:<cs_no>, if possible -- set
+ * ctrl and/or cs, and return 0 (success) or 1 (in case of error).
+ *
+ * ctrl == 0xff && chip == 0xff  : '--all' flag specified
+ * ctrl != 0xff && chip != 0xff  : both ctrl & chip were specified
+ * ctrl != 0xff && chip == 0xff  : only ctrl was specified
+ */
+static int
+parse_devstring(char *str, int *ctrl, int *cs)
+{
+	char *tmpstr;
+	unsigned int num = 0;
+
+	/* Ignore white spaces at the beginning */
+	while (isspace(*str) && (*str != '\0'))
+		str++;
+
+	*ctrl = 0xff;
+	*cs = 0xff;
+	if (strcmp(str, "--all") == 0 ||
+	    strcmp(str, "-a") == 0) {
+		/* If --all or -a is specified, ctl==chip==0xff */
+		debug("CTRL=%d CHIP=%d\n", *ctrl, *cs);
+		return (0);
+	}
+	/* Separate token and try to convert it to int */
+	tmpstr = (char *)strtok(str, ":");
+	if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+		if (convert_arguint(tmpstr, &num) != 0)
+			return (1);
+
+		if (num > MAX_SIM_DEV - 1) {
+			error("Invalid ctrl_no supplied: %s. Valid ctrl_no "
+			    "value must lie between 0 and 3!", tmpstr);
+			return (1);
+		}
+
+		*ctrl = num;
+		tmpstr = (char *)strtok(NULL, ":");
+
+		if ((tmpstr != NULL) && (*tmpstr != '\0')) {
+			if (convert_arguint(tmpstr, &num) != 0)
+				return (1);
+
+			/* Check if chip_no is valid */
+			if (num > MAX_CTRL_CS - 1) {
+				error("Invalid chip_no supplied: %s. Valid "
+				    "chip_no value must lie between 0 and 3!",
+				    tmpstr);
+				return (1);
+			}
+			*cs = num;
+		}
+	} else
+		/* Empty devstring supplied */
+		return (1);
+
+	debug("CTRL=%d CHIP=%d\n", *ctrl, *cs);
+	return (0);
+}
+
+static int
+opendev(int *fd)
+{
+
+	*fd = open(SIMDEVICE, O_RDWR);
+	if (*fd == -1) {
+		error("Could not open simulator device file (%s)!",
+		    SIMDEVICE);
+		return (EX_OSFILE);
+	}
+	return (EX_OK);
+}
+
+static int
+opencdev(int *cdevd, int ctrl, int chip)
+{
+	char fname[255];
+
+	sprintf(fname, "/dev/nandsim%d.%d", ctrl, chip);
+	*cdevd = open(fname, O_RDWR);
+	if (*cdevd == -1)
+		return (EX_NOINPUT);
+
+	return (EX_OK);
+}
+
+/*
+ * Check if given arguments count match requirements. If no, or
+ * --help (-h) flag is specified -- return 1 (print usage)
+ */
+static int
+checkusage(int gargc, int argsreqd, char **gargv)
+{
+
+	if (gargc < argsreqd + 2 || (gargc >= (argsreqd + 2) &&
+	    (strcmp(gargv[1], "--help") == 0 ||
+	    strcmp(gargv[1], "-h") == 0)))
+		return (1);
+
+	return (0);
+}
+
+static int
+cmdstatus(int gargc, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, idx, idx2, start, stop;
+	uint8_t verbose = 0;
+	struct sim_ctrl ctrlconf;
+	struct sim_chip chipconf;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err) {
+		return (EX_USAGE);
+	} else if (ctl == 0xff) {
+		/* Every controller */
+		start = 0;
+		stop = MAX_SIM_DEV-1;
+	} else {
+		/* Specified controller only */
+		start = ctl;
+		stop = ctl;
+	}
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	for (idx = 0; idx < gargc; idx ++)
+		if (strcmp(gargv[idx], "-v") == 0 ||
+		    strcmp(gargv[idx], "--verbose") == 0)
+			verbose = 1;
+
+	for (idx = start; idx <= stop; idx++) {
+		ctrlconf.num = idx;
+		err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrlconf);
+		if (err) {
+			err = EX_SOFTWARE;
+			error(MSG_STATUSACQCTRL, idx);
+			continue;
+		}
+
+		printctrl(&ctrlconf);
+
+		for (idx2 = 0; idx2 < MAX_CTRL_CS; idx2++) {
+			chipconf.num = idx2;
+			chipconf.ctrl_num = idx;
+
+			err = ioctl(fd, NANDSIM_STATUS_CHIP, &chipconf);
+			if (err) {
+				err = EX_SOFTWARE;
+				error(MSG_STATUSACQCTRL, idx);
+				continue;
+			}
+
+			printchip(&chipconf, verbose);
+		}
+	}
+	close(fd);
+	return (err);
+}
+
+static int
+cmdconf(int gargc __unused, char **gargv)
+{
+	int err;
+
+	err = parse_config(gargv[2], SIMDEVICE);
+	if (err)
+		return (EX_DATAERR);
+
+	return (EX_OK);
+}
+
+static int
+cmdstart(int gargc __unused, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, running, state;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	err = is_ctrl_created(ctl, &state);
+	if (err) {
+		return (EX_SOFTWARE);
+	} else if (state == 0) {
+		error(MSG_NOCTRL, ctl);
+		return (EX_SOFTWARE);
+	}
+
+	err = is_ctrl_running(ctl, &running);
+	if (err)
+		return (EX_SOFTWARE);
+
+	if (running) {
+		warn(MSG_RUNNING, ctl);
+	} else {
+		if (opendev(&fd) != EX_OK)
+			return (EX_OSFILE);
+
+		err = ioctl(fd, NANDSIM_START_CTRL, &ctl);
+		close(fd);
+		if (err) {
+			error("Cannot start controller#%d", ctl);
+			err = EX_SOFTWARE;
+		}
+	}
+	return (err);
+}
+
+static int
+cmdstop(int gargc __unused, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, running;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	err = is_ctrl_running(ctl, &running);
+	if (err)
+		return (EX_SOFTWARE);
+
+	if (!running) {
+		error(MSG_NOTRUNNING, ctl);
+	} else {
+		if (opendev(&fd) != EX_OK)
+			return (EX_OSFILE);
+
+		err = ioctl(fd, NANDSIM_STOP_CTRL, &ctl);
+		close(fd);
+		if (err) {
+			error("Cannot stop controller#%d", ctl);
+			err = EX_SOFTWARE;
+		}
+	}
+
+	return (err);
+}
+
+static int
+cmdmod(int gargc __unused, char **gargv)
+{
+	int chip, ctl, err = 0, fd = -1, i;
+	struct sim_mod mods;
+
+	if (gargc >= 4) {
+		if (strcmp(gargv[2], "--loglevel") == 0 || strcmp(gargv[2],
+		    "-l") == 0) {
+			/* Set loglevel (ctrl:chip pair independant) */
+			mods.field = SIM_MOD_LOG_LEVEL;
+
+			if (convert_arguint(gargv[3], &mods.new_value) != 0)
+				return (EX_SOFTWARE);
+
+			if (opendev(&fd) != EX_OK)
+				return (EX_OSFILE);
+
+			err = ioctl(fd, NANDSIM_MODIFY, &mods);
+			if (err) {
+				error("simulator parameter %s could not be "
+				    "modified !", gargv[3]);
+				close(fd);
+				return (EX_SOFTWARE);
+			}
+
+			debug("request : loglevel = %d\n", mods.new_value);
+			close(fd);
+			return (EX_OK);
+		}
+	}
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	else if (chip == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	/* Find out which flags were passed */
+	for (i = 3; i < gargc; i++) {
+
+		if (convert_arguint(gargv[i + 1], &mods.new_value) != 0)
+			continue;
+
+		if (strcmp(gargv[i], "--prog-time") == 0 ||
+		    strcmp(gargv[i], "-p") == 0) {
+
+			mods.field = SIM_MOD_PROG_TIME;
+			debug("request : progtime = %d\n", mods.new_value);
+
+		} else if (strcmp(gargv[i], "--erase-time") == 0 ||
+		    strcmp(gargv[i], "-e") == 0) {
+
+			mods.field = SIM_MOD_ERASE_TIME;
+			debug("request : eraseime = %d\n", mods.new_value);
+
+		} else if (strcmp(gargv[i], "--read-time") == 0 ||
+		    strcmp(gargv[i], "-r") == 0) {
+
+			mods.field = SIM_MOD_READ_TIME;
+			debug("request : read_time = %d\n", mods.new_value);
+
+		} else if (strcmp(gargv[i], "--error-ratio") == 0 ||
+		    strcmp(gargv[i], "-E") == 0) {
+
+			mods.field = SIM_MOD_ERROR_RATIO;
+			debug("request : error_ratio = %d\n", mods.new_value);
+
+		} else {
+			/* Flag not recognized, or nothing specified. */
+			error("Unrecognized flag:%s\n", gargv[i]);
+			if (fd >= 0)
+				close(fd);
+			return (EX_USAGE);
+		}
+
+		mods.chip_num = chip;
+		mods.ctrl_num = ctl;
+
+		/* Call appropriate ioctl */
+		err = ioctl(fd, NANDSIM_MODIFY, &mods);
+		if (err) {
+			error("simulator parameter %s could not be modified! ",
+			    gargv[i]);
+			continue;
+		}
+		i++;
+	}
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+cmderror(int gargc __unused, char **gargv)
+{
+	uint32_t page, column, len, pattern;
+	int chip = 0, ctl = 0, err = 0, fd;
+	struct sim_error sim_err;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	if (chip == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (convert_arguint(gargv[3], &page) ||
+	    convert_arguint(gargv[4], &column) ||
+	    convert_arguint(gargv[5], &len) ||
+	    convert_arguint(gargv[6], &pattern))
+		return (EX_SOFTWARE);
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	sim_err.page_num = page;
+	sim_err.column = column;
+	sim_err.len = len;
+	sim_err.pattern = pattern;
+	sim_err.ctrl_num = ctl;
+	sim_err.chip_num = chip;
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NANDSIM_INJECT_ERROR, &sim_err);
+
+	close(fd);
+	if (err) {
+		error("Could not inject error !");
+		return (EX_SOFTWARE);
+	}
+	return (EX_OK);
+}
+
+static int
+cmdbb(int gargc, char **gargv)
+{
+	struct sim_block_state bs;
+	struct chip_param_io cparams;
+	uint32_t blkidx;
+	int c, cdevd, chip = 0, ctl = 0, err = 0, fd, idx;
+	uint8_t flagL = 0, flagU = 0;
+	int *badblocks = NULL;
+
+	/* Check for --list/-L or --unmark/-U flags */
+	for (idx = 3; idx < gargc; idx++) {
+		if (strcmp(gargv[idx], "--list") == 0 ||
+		    strcmp(gargv[idx], "-L") == 0)
+			flagL = idx;
+		if (strcmp(gargv[idx], "--unmark") == 0 ||
+		    strcmp(gargv[idx], "-U") == 0)
+			flagU = idx;
+	}
+
+	if (flagL == 2 || flagU == 2 || flagU == 3)
+		return (EX_USAGE);
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err) {
+		return (EX_USAGE);
+	}
+	if (chip == 0xff || ctl == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	bs.ctrl_num = ctl;
+	bs.chip_num = chip;
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	if (opencdev(&cdevd, ctl, chip) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(cdevd, NAND_IO_GET_CHIP_PARAM, &cparams);
+	if (err)
+		return (EX_SOFTWARE);
+
+	close(cdevd);
+
+	bs.ctrl_num = ctl;
+	bs.chip_num = chip;
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	if (flagL != 3) {
+		/*
+		 * Flag -L was specified either after blocklist or was not
+		 * specified at all.
+		 */
+		c = parse_intarray(gargv[3], &badblocks);
+
+		for (idx = 0; idx < c; idx++) {
+			bs.block_num = badblocks[idx];
+			/* Do not change wearout */
+			bs.wearout = -1;
+			bs.state = (flagU == 0) ? NANDSIM_BAD_BLOCK :
+			    NANDSIM_GOOD_BLOCK;
+
+			err = ioctl(fd, NANDSIM_SET_BLOCK_STATE, &bs);
+			if (err) {
+				error("Could not set bad block(%d) for "
+				    "controller (%d)!",
+				    badblocks[idx], ctl);
+				err = EX_SOFTWARE;
+				break;
+			}
+		}
+	}
+	if (flagL != 0) {
+		/* If flag -L was specified (anywhere) */
+		for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
+			bs.block_num = blkidx;
+			/* Do not change the wearout */
+			bs.wearout = -1;
+			err = ioctl(fd, NANDSIM_GET_BLOCK_STATE, &bs);
+			if (err) {
+				error("Could not acquire block state");
+				err = EX_SOFTWARE;
+				continue;
+			}
+			printf("Block#%d: wear count: %d %s\n", blkidx,
+			    bs.wearout,
+			    (bs.state == NANDSIM_BAD_BLOCK) ? "BAD":"GOOD");
+		}
+	}
+	close(fd);
+	return (err);
+}
+
+static int
+cmdfreeze(int gargc __unused, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, i, start = 0, state, stop = 0;
+	struct sim_ctrl_chip ctrlchip;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	if (ctl == 0xff) {
+		error("You have to specify at least controller number");
+		return (EX_USAGE);
+	}
+
+	if (ctl != 0xff && chip == 0xff) {
+		start = 0;
+		stop = MAX_CTRL_CS - 1;
+	} else {
+		start = chip;
+		stop = chip;
+	}
+
+	ctrlchip.ctrl_num = ctl;
+
+	err = is_ctrl_running(ctl, &state);
+	if (err)
+		return (EX_SOFTWARE);
+	if (state == 0) {
+		error(MSG_NOTRUNNING, ctl);
+		return (EX_SOFTWARE);
+	}
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	for (i = start; i <= stop; i++) {
+		err = is_chip_created(ctl, i, &state);
+		if (err)
+			return (EX_SOFTWARE);
+		else if (state == 0) {
+			continue;
+		}
+
+		ctrlchip.chip_num = i;
+		err = ioctl(fd, NANDSIM_FREEZE, &ctrlchip);
+		if (err) {
+			error("Could not freeze ctrl#%d chip#%d", ctl, i);
+			close(fd);
+			return (EX_SOFTWARE);
+		}
+	}
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+cmdlog(int gargc __unused, char **gargv)
+{
+	struct sim_log log;
+	int chip = 0, ctl = 0, err = 0, fd, idx, start = 0, stop = 0;
+	char *logbuf;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	logbuf = (char *)malloc(sizeof(char) * NANDSIM_RAM_LOG_SIZE);
+	if (logbuf == NULL) {
+		error("Not enough memory to create log buffer");
+		return (EX_SOFTWARE);
+	}
+
+	memset(logbuf, 0, NANDSIM_RAM_LOG_SIZE);
+	log.log = logbuf;
+	log.len = NANDSIM_RAM_LOG_SIZE;
+
+	if (ctl == 0xff) {
+		start = 0;
+		stop = MAX_SIM_DEV-1;
+	} else {
+		start = ctl;
+		stop = ctl;
+	}
+
+	if (opendev(&fd) != EX_OK) {
+		free(logbuf);
+		return (EX_OSFILE);
+	}
+
+	/* Print logs for selected controller(s) */
+	for (idx = start; idx <= stop; idx++) {
+		log.ctrl_num = idx;
+
+		err = ioctl(fd, NANDSIM_PRINT_LOG, &log);
+		if (err) {
+			error("Could not get log for controller %d!", idx);
+			continue;
+		}
+
+		printf("Logs for controller#%d:\n%s\n", idx, logbuf);
+	}
+
+	free(logbuf);
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+cmdstats(int gargc __unused, char **gargv)
+{
+	int cdevd, chip = 0, ctl = 0, err = 0;
+	uint32_t pageno = 0;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+
+	if (err)
+		return (EX_USAGE);
+
+	if (chip == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (convert_arguint(gargv[3], &pageno) != 0)
+		return (EX_USAGE);
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	if (opencdev(&cdevd, ctl, chip) != EX_OK)
+		return (EX_OSFILE);
+
+	err = printstats(ctl, chip, pageno, cdevd);
+	if (err) {
+		close(cdevd);
+		return (EX_SOFTWARE);
+	}
+	close(cdevd);
+	return (EX_OK);
+}
+
+static int
+cmddump(int gargc __unused, char **gargv)
+{
+	struct sim_dump dump;
+	struct sim_block_state bs;
+	struct chip_param_io cparams;
+	int chip = 0, ctl = 0, err = EX_OK, fd, dumpfd;
+	uint32_t blkidx, bwritten = 0, totalwritten = 0;
+	void *buf;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+
+	if (chip == 0xff || ctl == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	if (opencdev(&fd, ctl, chip) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NAND_IO_GET_CHIP_PARAM, &cparams);
+	if (err) {
+		error("Cannot get parameters for chip %d:%d", ctl, chip);
+		close(fd);
+		return (EX_SOFTWARE);
+	}
+	close(fd);
+
+	dump.ctrl_num = ctl;
+	dump.chip_num = chip;
+
+	dump.len = cparams.pages_per_block * (cparams.page_size +
+	    cparams.oob_size);
+
+	buf = malloc(dump.len);
+	if (buf == NULL) {
+		error("Could not allocate memory!");
+		return (EX_SOFTWARE);
+	}
+	dump.data = buf;
+
+	errno = 0;
+	dumpfd = open(gargv[3], O_WRONLY | O_CREAT, 0666);
+	if (dumpfd == -1) {
+		error("Cannot create dump file.");
+		free(buf);
+		return (EX_SOFTWARE);
+	}
+
+	if (opendev(&fd)) {
+		close(dumpfd);
+		free(buf);
+		return (EX_SOFTWARE);
+	}
+
+	bs.ctrl_num = ctl;
+	bs.chip_num = chip;
+
+	/* First uint32_t in file shall contain block count */
+	if (write(dumpfd, &cparams, sizeof(cparams)) < (int)sizeof(cparams)) {
+		error("Error writing to dumpfile!");
+		close(fd);
+		close(dumpfd);
+		free(buf);
+		return (EX_SOFTWARE);
+	}
+
+	/*
+	 * First loop acquires blocks states and writes them to
+	 * the dump file.
+	 */
+	for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
+		bs.block_num = blkidx;
+		err = ioctl(fd, NANDSIM_GET_BLOCK_STATE, &bs);
+		if (err) {
+			error("Could not get bad block(%d) for "
+			    "controller (%d)!", blkidx, ctl);
+			close(fd);
+			close(dumpfd);
+			free(buf);
+			return (EX_SOFTWARE);
+		}
+
+		bwritten = write(dumpfd, &bs, sizeof(bs));
+		if (bwritten != sizeof(bs)) {
+			error("Error writing to dumpfile");
+			close(fd);
+			close(dumpfd);
+			free(buf);
+			return (EX_SOFTWARE);
+		}
+	}
+
+	/* Second loop dumps the data */
+	for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
+		debug("Block#%d...", blkidx);
+		dump.block_num = blkidx;
+
+		err = ioctl(fd, NANDSIM_DUMP, &dump);
+		if (err) {
+			error("Could not dump ctrl#%d chip#%d "
+			    "block#%d", ctl, chip, blkidx);
+			err = EX_SOFTWARE;
+			break;
+		}
+
+		bwritten = write(dumpfd, dump.data, dump.len);
+		if (bwritten != dump.len) {
+			error("Error writing to dumpfile");
+			err = EX_SOFTWARE;
+			break;
+		}
+		debug("OK!\n");
+		totalwritten += bwritten;
+	}
+	printf("%d out of %d B written.\n", totalwritten, dump.len * blkidx);
+
+	close(fd);
+	close(dumpfd);
+	free(buf);
+	return (err);
+}
+
+static int
+cmdrestore(int gargc __unused, char **gargv)
+{
+	struct sim_dump dump;
+	struct sim_block_state bs;
+	struct stat filestat;
+	int chip = 0, ctl = 0, err = 0, fd, dumpfd = -1;
+	uint32_t blkidx, blksz, fsize = 0, expfilesz;
+	void *buf;
+	struct chip_param_io cparams, dumpcparams;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+	if (err)
+		return (EX_USAGE);
+	else if (ctl == 0xff) {
+		error(MSG_CTRLCHIPNEEDED);
+		return (EX_USAGE);
+	}
+
+	if (!assert_chip_connected(ctl, chip))
+		return (EX_SOFTWARE);
+
+	/* Get chip geometry */
+	if (opencdev(&fd, ctl, chip) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NAND_IO_GET_CHIP_PARAM, &cparams);
+	if (err) {
+		error("Cannot get parameters for chip %d:%d", ctl, chip);
+		close(fd);
+		return (err);
+	}
+	close(fd);
+
+	/* Obtain dump file size */
+	errno = 0;
+	if (stat(gargv[3], &filestat) != 0) {
+		error("Could not acquire file size! : %s",
+		    strerror(errno));
+		return (EX_IOERR);
+	}
+
+	fsize = filestat.st_size;
+	blksz = cparams.pages_per_block * (cparams.page_size +
+	    cparams.oob_size);
+
+	/* Expected dump file size for chip */
+	expfilesz = cparams.blocks * (blksz + sizeof(bs)) + sizeof(cparams);
+
+	if (fsize != expfilesz) {
+		error("File size does not match chip geometry (file size: %d"
+		    ", dump size: %d)", fsize, expfilesz);
+		return (EX_SOFTWARE);
+	}
+
+	dumpfd = open(gargv[3], O_RDONLY);
+	if (dumpfd == -1) {
+		error("Could not open dump file!");
+		return (EX_IOERR);
+	}
+
+	/* Read chip params saved in dumpfile */
+	read(dumpfd, &dumpcparams, sizeof(dumpcparams));
+
+	/* XXX */
+	if (bcmp(&dumpcparams, &cparams, sizeof(cparams)) != 0) {
+		error("Supplied dump is created for a chip with different "
+		    "chip configuration!");
+		close(dumpfd);
+		return (EX_SOFTWARE);
+	}
+
+	if (opendev(&fd) != EX_OK) {
+		close(dumpfd);
+		return (EX_OSFILE);
+	}
+
+	buf = malloc(blksz);
+	if (buf == NULL) {
+		error("Could not allocate memory for block buffer");
+		close(dumpfd);
+		close(fd);
+		return (EX_SOFTWARE);
+	}
+
+	dump.ctrl_num = ctl;
+	dump.chip_num = chip;
+	dump.data = buf;
+	/* Restore block states and wearouts */
+	for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
+		dump.block_num = blkidx;
+		if (read(dumpfd, &bs, sizeof(bs)) != sizeof(bs)) {
+			error("Error reading dumpfile");
+			close(dumpfd);
+			close(fd);
+			free(buf);
+			return (EX_SOFTWARE);
+		}
+		bs.ctrl_num = ctl;
+		bs.chip_num = chip;
+		debug("BLKIDX=%d BLOCKS=%d CTRL=%d CHIP=%d STATE=%d\n"
+		    "WEAROUT=%d BS.CTRL_NUM=%d BS.CHIP_NUM=%d\n",
+		    blkidx, cparams.blocks, dump.ctrl_num, dump.chip_num,
+		    bs.state, bs.wearout, bs.ctrl_num, bs.chip_num);
+
+		err = ioctl(fd, NANDSIM_SET_BLOCK_STATE, &bs);
+		if (err) {
+			error("Could not set bad block(%d) for "
+			    "controller: %d, chip: %d!", blkidx, ctl, chip);
+			close(dumpfd);
+			close(fd);
+			free(buf);
+			return (EX_SOFTWARE);
+		}
+	}
+	/* Restore data */
+	for (blkidx = 0; blkidx < cparams.blocks; blkidx++) {
+		errno = 0;
+		dump.len = read(dumpfd, buf, blksz);
+		if (errno) {
+			error("Failed to read block#%d from dumpfile.", blkidx);
+			err = EX_SOFTWARE;
+			break;
+		}
+		dump.block_num = blkidx;
+		err = ioctl(fd, NANDSIM_RESTORE, &dump);
+		if (err) {
+			error("Could not restore block#%d of ctrl#%d chip#%d"
+			    ": %s", blkidx, ctl, chip, strerror(errno));
+			err = EX_SOFTWARE;
+			break;
+		}
+	}
+
+	free(buf);
+	close(dumpfd);
+	close(fd);
+	return (err);
+
+}
+
+static int
+cmddestroy(int gargc __unused, char **gargv)
+{
+	int chip = 0, ctl = 0, err = 0, fd, idx, idx2, state;
+	int chipstart, chipstop, ctrlstart, ctrlstop;
+	struct sim_chip_destroy chip_destroy;
+
+	err = parse_devstring(gargv[2], &ctl, &chip);
+
+	if (err)
+		return (EX_USAGE);
+
+	if (ctl == 0xff) {
+		/* Every chip at every controller */
+		ctrlstart = chipstart = 0;
+		ctrlstop = MAX_SIM_DEV - 1;
+		chipstop = MAX_CTRL_CS - 1;
+	} else {
+		ctrlstart = ctrlstop = ctl;
+		if (chip == 0xff) {
+			/* Every chip at selected controller */
+			chipstart = 0;
+			chipstop = MAX_CTRL_CS - 1;
+		} else
+			/* Selected chip at selected controller */
+			chipstart = chipstop = chip;
+	}
+	debug("CTRLSTART=%d CTRLSTOP=%d CHIPSTART=%d CHIPSTOP=%d\n",
+	    ctrlstart, ctrlstop, chipstart, chipstop);
+	for (idx = ctrlstart; idx <= ctrlstop; idx++) {
+		err = is_ctrl_created(idx, &state);
+		if (err) {
+			error("Could not acquire ctrl#%d state. Cannot "
+			    "destroy controller.", idx);
+			return (EX_SOFTWARE);
+		}
+		if (state == 0) {
+			continue;
+		}
+		err = is_ctrl_running(idx, &state);
+		if (err) {
+			error(MSG_STATUSACQCTRL, idx);
+			return (EX_SOFTWARE);
+		}
+		if (state != 0) {
+			error(MSG_RUNNING, ctl);
+			return (EX_SOFTWARE);
+		}
+		if (opendev(&fd) != EX_OK)
+			return (EX_OSFILE);
+
+		for (idx2 = chipstart; idx2 <= chipstop; idx2++) {
+			err = is_chip_created(idx, idx2, &state);
+			if (err) {
+				error(MSG_STATUSACQCTRLCHIP, idx2, idx);
+				continue;
+			}
+			if (state == 0)
+				/* There is no such chip running */
+				continue;
+			chip_destroy.ctrl_num = idx;
+			chip_destroy.chip_num = idx2;
+			ioctl(fd, NANDSIM_DESTROY_CHIP,
+			    &chip_destroy);
+		}
+		/* If chip isn't explicitly specified -- destroy ctrl */
+		if (chip == 0xff) {
+			err = ioctl(fd, NANDSIM_DESTROY_CTRL, &idx);
+			if (err) {
+				error("Could not destroy ctrl#%d", idx);
+				continue;
+			}
+		}
+		close(fd);
+	}
+	return (err);
+}
+
+int
+main(int argc, char **argv)
+{
+	struct nandsim_command *cmdopts;
+	int retcode = 0;
+
+	if (argc < 2) {
+		cmdhelp(argc, argv);
+		retcode = EX_USAGE;
+	} else {
+		cmdopts = getcommand(argv[1]);
+		if (cmdopts != NULL && cmdopts->commandfunc != NULL) {
+			if (checkusage(argc, cmdopts->req_argc, argv) == 1) {
+				/* Print command specific usage */
+				printf("nandsim %s", cmdopts->usagestring);
+				return (EX_USAGE);
+			}
+			retcode = cmdopts->commandfunc(argc, argv);
+
+			if (retcode == EX_USAGE) {
+				/* Print command-specific usage */
+				printf("nandsim %s", cmdopts->usagestring);
+			} else if (retcode == EX_OSFILE) {
+				error("Could not open device file");
+			}
+
+		} else {
+			error("Unknown command!");
+			retcode = EX_USAGE;
+		}
+	}
+	return (retcode);
+}
+
+static int
+cmdhelp(int gargc __unused, char **gargv __unused)
+{
+	struct nandsim_command *opts;
+
+	printf("usage:  nandsim <command> [command params] [params]\n\n");
+
+	for (opts = commands; (opts != NULL) &&
+	    (opts->cmd_name != NULL); opts++)
+		printf("nandsim %s", opts->usagestring);
+
+	printf("\n");
+	return (EX_OK);
+}
+
+static void
+printchip(struct sim_chip *chip, uint8_t verbose)
+{
+
+	if (chip->created == 0)
+		return;
+	if (verbose > 0) {
+		printf("\n[Chip info]\n");
+		printf("num= %d\nctrl_num=%d\ndevice_id=%02x"
+		    "\tmanufacturer_id=%02x\ndevice_model=%s\nmanufacturer="
+		    "%s\ncol_addr_cycles=%d\nrow_addr_cycles=%d"
+		    "\npage_size=%d\noob_size=%d\npages_per_block=%d\n"
+		    "blocks_per_lun=%d\nluns=%d\n\nprog_time=%d\n"
+		    "erase_time=%d\nread_time=%d\n"
+		    "error_ratio=%d\nwear_level=%d\nwrite_protect=%c\n"
+		    "chip_width=%db\n", chip->num, chip->ctrl_num,
+		    chip->device_id, chip->manufact_id,chip->device_model,
+		    chip->manufacturer, chip->col_addr_cycles,
+		    chip->row_addr_cycles, chip->page_size,
+		    chip->oob_size, chip->pgs_per_blk, chip->blks_per_lun,
+		    chip->luns,chip->prog_time, chip->erase_time,
+		    chip->read_time, chip->error_ratio, chip->wear_level,
+		    (chip->is_wp == 0) ? 'N':'Y', chip->width);
+	} else {
+		printf("[Chip info]\n");
+		printf("\tnum=%d\n\tdevice_model=%s\n\tmanufacturer=%s\n"
+		    "\tpage_size=%d\n\twrite_protect=%s\n",
+		    chip->num, chip->device_model, chip->manufacturer,
+		    chip->page_size, (chip->is_wp == 0) ? "NO":"YES");
+	}
+}
+
+static void
+printctrl(struct sim_ctrl *ctrl)
+{
+	int i;
+
+	if (ctrl->created == 0) {
+		printf(MSG_NOCTRL "\n", ctrl->num);
+		return;
+	}
+	printf("\n[Controller info]\n");
+	printf("\trunning: %s\n", ctrl->running ? "yes" : "no");
+	printf("\tnum cs: %d\n", ctrl->num_cs);
+	printf("\tecc: %d\n", ctrl->ecc);
+	printf("\tlog_filename: %s\n", ctrl->filename);
+	printf("\tecc_layout:");
+	for (i = 0; i < MAX_ECC_BYTES; i++) {
+		if (ctrl->ecc_layout[i] == 0xffff)
+			break;
+		else
+			printf("%c%d", i%16 ? ' ' : '\n',
+			    ctrl->ecc_layout[i]);
+	}
+	printf("\n");
+}
+
+static int
+is_ctrl_running(int ctrl_no, int *running)
+{
+	struct sim_ctrl ctrl;
+	int err, fd;
+
+	ctrl.num = ctrl_no;
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrl);
+	if (err) {
+		error(MSG_STATUSACQCTRL, ctrl_no);
+		close(fd);
+		return (err);
+	}
+	*running = ctrl.running;
+	close(fd);
+	return (0);
+}
+
+static int
+is_ctrl_created(int ctrl_no, int *created)
+{
+	struct sim_ctrl ctrl;
+	int err, fd;
+
+	ctrl.num = ctrl_no;
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NANDSIM_STATUS_CTRL, &ctrl);
+	if (err) {
+		error("Could not acquire conf for ctrl#%d", ctrl_no);
+		close(fd);
+		return (err);
+	}
+	*created = ctrl.created;
+	close(fd);
+	return (0);
+}
+
+static int
+is_chip_created(int ctrl_no, int chip_no, int *created)
+{
+	struct sim_chip chip;
+	int err, fd;
+
+	chip.ctrl_num = ctrl_no;
+	chip.num = chip_no;
+
+	if (opendev(&fd) != EX_OK)
+		return (EX_OSFILE);
+
+	err = ioctl(fd, NANDSIM_STATUS_CHIP, &chip);
+	if (err) {
+		error("Could not acquire conf for chip#%d", chip_no);
+		close(fd);
+		return (err);
+	}
+	*created = chip.created;
+	close(fd);
+	return (0);
+}
+
+static int
+assert_chip_connected(int ctrl_no, int chip_no)
+{
+	int created, running;
+
+	if (is_ctrl_created(ctrl_no, &created))
+		return (0);
+
+	if (!created) {
+		error(MSG_NOCTRL, ctrl_no);
+		return (0);
+	}
+
+	if (is_chip_created(ctrl_no, chip_no, &created))
+		return (0);
+
+	if (!created) {
+		error(MSG_NOTCONFIGDCTRLCHIP, ctrl_no, chip_no);
+		return (0);
+	}
+
+	if (is_ctrl_running(ctrl_no, &running))
+		return (0);
+
+	if (!running) {
+		error(MSG_NOTRUNNING, ctrl_no);
+		return (0);
+	}
+
+	return (1);
+}
+
+static int
+printstats(int ctrlno, int chipno, uint32_t pageno, int cdevd)
+{
+	struct page_stat_io pstats;
+	struct block_stat_io bstats;
+	struct chip_param_io cparams;
+	uint32_t blkidx;
+	int err;
+
+	/* Gather information about chip */
+	err = ioctl(cdevd, NAND_IO_GET_CHIP_PARAM, &cparams);
+
+	if (err) {
+		error("Could not acquire chip info for chip attached to cs#"
+		    "%d, ctrl#%d", chipno, ctrlno);
+		return (EX_SOFTWARE);
+	}
+
+	blkidx = (pageno / cparams.pages_per_block);
+	bstats.block_num = blkidx;
+
+	err = ioctl(cdevd, NAND_IO_BLOCK_STAT, &bstats);
+	if (err) {
+		error("Could not acquire block#%d statistics!", blkidx);
+		return (ENXIO);
+	}
+
+	printf("Block #%d erased: %d\n", blkidx, bstats.block_erased);
+	pstats.page_num = pageno;
+
+	err = ioctl(cdevd, NAND_IO_PAGE_STAT, &pstats);
+	if (err) {
+		error("Could not acquire page statistics!");
+		return (ENXIO);
+	}
+
+	debug("BLOCKIDX = %d PAGENO (REL. TO BLK) = %d\n", blkidx,
+	    pstats.page_num);
+
+	printf("Page#%d : reads:%d writes:%d \n\traw reads:%d raw writes:%d "
+	    "\n\tecc_succeeded:%d ecc_corrected:%d ecc_failed:%d\n",
+	    pstats.page_num, pstats.page_read, pstats.page_written,
+	    pstats.page_raw_read, pstats.page_raw_written,
+	    pstats.ecc_succeded, pstats.ecc_corrected, pstats.ecc_failed);
+	return (0);
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/nandsim_cfgparse.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/nandsim_cfgparse.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,959 @@
+/*-
+ * Copyright (C) 2009-2012 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandsim/nandsim_cfgparse.c 235607 2012-05-18 14:12:17Z gber $");
+
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <dev/nand/nandsim.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include "nandsim_cfgparse.h"
+
+#define warn(fmt, args...) do { \
+    printf("WARNING: " fmt "\n", ##args); } while (0)
+
+#define error(fmt, args...) do { \
+    printf("ERROR: " fmt "\n", ##args); } while (0)
+
+#define MSG_MANDATORYKEYMISSING "mandatory key \"%s\" value belonging to " \
+    "section \"%s\" is missing!\n"
+
+#define DEBUG
+#undef DEBUG
+
+#ifdef DEBUG
+#define debug(fmt, args...) do { \
+    printf("NANDSIM_CONF:" fmt "\n", ##args); } while (0)
+#else
+#define debug(fmt, args...) do {} while(0)
+#endif
+
+#define STRBUFSIZ 2000
+
+/* Macros extracts type and type size */
+#define TYPE(x) ((x) & 0xf8)
+#define SIZE(x) (((x) & 0x07))
+
+/* Erase/Prog/Read time max and min values */
+#define DELAYTIME_MIN	10000
+#define DELAYTIME_MAX	10000000
+
+/* Structure holding configuration for controller. */
+static struct sim_ctrl ctrl_conf;
+/* Structure holding configuration for chip. */
+static struct sim_chip chip_conf;
+
+static struct nandsim_key nandsim_ctrl_keys[] = {
+	{"num_cs", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num_cs, 0},
+	{"ctrl_num", 1, VALUE_UINT | SIZE_8, (void *)&ctrl_conf.num, 0},
+
+	{"ecc_layout", 1, VALUE_UINTARRAY | SIZE_16,
+	    (void *)&ctrl_conf.ecc_layout, MAX_ECC_BYTES},
+
+	{"filename", 0, VALUE_STRING,
+	    (void *)&ctrl_conf.filename, FILENAME_SIZE},
+
+	{"ecc", 0, VALUE_BOOL, (void *)&ctrl_conf.ecc, 0},
+	{NULL, 0, 0, NULL, 0},
+};
+
+static struct nandsim_key nandsim_chip_keys[] = {
+	{"chip_cs", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.num, 0},
+	{"chip_ctrl", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.ctrl_num,
+	    0},
+	{"device_id", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.device_id,
+	    0},
+	{"manufacturer_id", 1, VALUE_UINT | SIZE_8,
+	    (void *)&chip_conf.manufact_id, 0},
+	{"model", 0, VALUE_STRING, (void *)&chip_conf.device_model,
+	    DEV_MODEL_STR_SIZE},
+	{"manufacturer", 0, VALUE_STRING, (void *)&chip_conf.manufacturer,
+	    MAN_STR_SIZE},
+	{"page_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.page_size,
+	    0},
+	{"oob_size", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.oob_size,
+	    0},
+	{"pages_per_block", 1, VALUE_UINT | SIZE_32,
+	    (void *)&chip_conf.pgs_per_blk, 0},
+	{"blocks_per_lun", 1, VALUE_UINT | SIZE_32,
+	    (void *)&chip_conf.blks_per_lun, 0},
+	{"luns", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.luns, 0},
+	{"column_addr_cycle", 1,VALUE_UINT | SIZE_8,
+	    (void *)&chip_conf.col_addr_cycles, 0},
+	{"row_addr_cycle", 1, VALUE_UINT | SIZE_8,
+	    (void *)&chip_conf.row_addr_cycles, 0},
+	{"program_time", 0, VALUE_UINT | SIZE_32,
+	    (void *)&chip_conf.prog_time, 0},
+	{"erase_time", 0, VALUE_UINT | SIZE_32,
+	    (void *)&chip_conf.erase_time, 0},
+	{"read_time", 0, VALUE_UINT | SIZE_32,
+	    (void *)&chip_conf.read_time, 0},
+	{"width", 1, VALUE_UINT | SIZE_8, (void *)&chip_conf.width, 0},
+	{"wear_out", 1, VALUE_UINT | SIZE_32, (void *)&chip_conf.wear_level,
+	    0},
+	{"bad_block_map", 0, VALUE_UINTARRAY | SIZE_32,
+	    (void *)&chip_conf.bad_block_map, MAX_BAD_BLOCKS},
+	{NULL, 0, 0, NULL, 0},
+};
+
+struct nandsim_section sections[] = {
+	{"ctrl", (struct nandsim_key *)&nandsim_ctrl_keys},
+	{"chip", (struct nandsim_key *)&nandsim_chip_keys},
+	{NULL, NULL},
+};
+
+static uint8_t logoutputtoint(char *, int *);
+static uint8_t validate_chips(struct sim_chip *, int, struct sim_ctrl *, int);
+static uint8_t validate_ctrls(struct sim_ctrl *, int);
+static int configure_sim(const char *, struct rcfile *);
+static int create_ctrls(struct rcfile *, struct sim_ctrl **, int *);
+static int create_chips(struct rcfile *, struct sim_chip **, int *);
+static void destroy_ctrls(struct sim_ctrl *);
+static void destroy_chips(struct sim_chip *);
+static int validate_section_config(struct rcfile *, const char *, int);
+
+int
+convert_argint(char *arg, int *value)
+{
+
+	if (arg == NULL || value == NULL)
+		return (EINVAL);
+
+	errno = 0;
+	*value = (int)strtol(arg, NULL, 0);
+	if (*value == 0 && errno != 0) {
+		error("Cannot convert to number argument \'%s\'", arg);
+		return (EINVAL);
+	}
+	return (0);
+}
+
+int
+convert_arguint(char *arg, unsigned int *value)
+{
+
+	if (arg == NULL || value == NULL)
+		return (EINVAL);
+
+	errno = 0;
+	*value = (unsigned int)strtol(arg, NULL, 0);
+	if (*value == 0 && errno != 0) {
+		error("Cannot convert to number argument \'%s\'", arg);
+		return (EINVAL);
+	}
+	return (0);
+}
+
+/* Parse given ',' separated list of bytes into buffer. */
+int
+parse_intarray(char *array, int **buffer)
+{
+	char *tmp, *tmpstr, *origstr;
+	unsigned int currbufp = 0, i;
+	unsigned int count = 0, from  = 0, to = 0;
+
+	/* Remove square braces */
+	if (array[0] == '[')
+		array ++;
+	if (array[strlen(array)-1] == ']')
+		array[strlen(array)-1] = ',';
+
+	from = strlen(array);
+	origstr = (char *)malloc(sizeof(char) * from);
+	strcpy(origstr, array);
+
+	tmpstr = (char *)strtok(array, ",");
+	/* First loop checks for how big int array we need to allocate */
+	while (tmpstr != NULL) {
+		errno = 0;
+		if ((tmp = strchr(tmpstr, '-')) != NULL) {
+			*tmp = ' ';
+			if (convert_arguint(tmpstr, &from) ||
+			    convert_arguint(tmp, &to)) {
+				free(origstr);
+				return (EINVAL);
+			}
+
+			count += to - from + 1;
+		} else {
+			if (convert_arguint(tmpstr, &from)) {
+				free(origstr);
+				return (EINVAL);
+			}
+			count++;
+		}
+		tmpstr = (char *)strtok(NULL, ",");
+	}
+
+	if (count == 0)
+		goto out;
+
+	/* Allocate buffer of ints */
+	tmpstr = (char *)strtok(origstr, ",");
+	*buffer = malloc(count * sizeof(int));
+
+	/* Second loop is just inserting converted values into int array */
+	while (tmpstr != NULL) {
+		errno = 0;
+		if ((tmp = strchr(tmpstr, '-')) != NULL) {
+			*tmp = ' ';
+			from = strtol(tmpstr, NULL, 0);
+			to = strtol(tmp, NULL, 0);
+			tmpstr = strtok(NULL, ",");
+			for (i = from; i <= to; i ++)
+				(*buffer)[currbufp++] = i;
+			continue;
+		}
+		errno = 0;
+		from = (int)strtol(tmpstr, NULL, 0);
+		(*buffer)[currbufp++] = from;
+		tmpstr = (char *)strtok(NULL, ",");
+	}
+out:
+	free(origstr);
+	return (count);
+}
+
+/* Convert logoutput strings literals into appropriate ints. */
+static uint8_t
+logoutputtoint(char *logoutput, int *output)
+{
+	int out;
+
+	if (strcmp(logoutput, "file") == 0)
+		out = NANDSIM_OUTPUT_FILE;
+
+	else if (strcmp(logoutput, "console") == 0)
+		out = NANDSIM_OUTPUT_CONSOLE;
+
+	else if (strcmp(logoutput, "ram") == 0)
+		out = NANDSIM_OUTPUT_RAM;
+
+	else if (strcmp(logoutput, "none") == 0)
+		out = NANDSIM_OUTPUT_NONE;
+	else
+		out = -1;
+
+	*output = out;
+
+	if (out == -1)
+		return (EINVAL);
+	else
+		return (0);
+}
+
+static int
+configure_sim(const char *devfname, struct rcfile *f)
+{
+	struct sim_param sim_conf;
+	char buf[255];
+	int err, tmpv, fd;
+
+	err = rc_getint(f, "sim", 0, "log_level", &tmpv);
+
+	if (tmpv < 0 || tmpv > 255 || err) {
+		error("Bad log level specified (%d)\n", tmpv);
+		return (ENOTSUP);
+	} else
+		sim_conf.log_level = tmpv;
+
+	rc_getstring(f, "sim", 0, "log_output", 255, (char *)&buf);
+
+	tmpv = -1;
+	err = logoutputtoint((char *)&buf, &tmpv);
+	if (err) {
+		error("Log output specified in config file does not seem to "
+		    "be valid (%s)!", (char *)&buf);
+		return (ENOTSUP);
+	}
+
+	sim_conf.log_output = tmpv;
+
+	fd = open(devfname, O_RDWR);
+	if (fd == -1) {
+		error("could not open simulator device file (%s)!",
+		    devfname);
+		return (EX_OSFILE);
+	}
+
+	err = ioctl(fd, NANDSIM_SIM_PARAM, &sim_conf);
+	if (err) {
+		error("simulator parameters could not be modified: %s",
+		    strerror(errno));
+		close(fd);
+		return (ENXIO);
+	}
+
+	close(fd);
+	return (EX_OK);
+}
+
+static int
+create_ctrls(struct rcfile *f, struct sim_ctrl **ctrls, int *cnt)
+{
+	int count, i;
+	struct sim_ctrl *ctrlsptr;
+
+	count = rc_getsectionscount(f, "ctrl");
+	if (count > MAX_SIM_DEV) {
+		error("Too many CTRL sections specified(%d)", count);
+		return (ENOTSUP);
+	} else if (count == 0) {
+		error("No ctrl sections specified");
+		return (ENOENT);
+	}
+
+	ctrlsptr = (struct sim_ctrl *)malloc(sizeof(struct sim_ctrl) * count);
+	if (ctrlsptr == NULL) {
+		error("Could not allocate memory for ctrl configuration");
+		return (ENOMEM);
+	}
+
+	for (i = 0; i < count; i++) {
+		bzero((void *)&ctrl_conf, sizeof(ctrl_conf));
+
+		/*
+		 * ECC layout have to end up with 0xffff, so
+		 * we're filling buffer with 0xff. If ecc_layout is
+		 * defined in config file, values will be overriden.
+		 */
+		memset((void *)&ctrl_conf.ecc_layout, 0xff,
+		    sizeof(ctrl_conf.ecc_layout));
+
+		if (validate_section_config(f, "ctrl", i) != 0) {
+			free(ctrlsptr);
+			return (EINVAL);
+		}
+
+		if (parse_section(f, "ctrl", i) != 0) {
+			free(ctrlsptr);
+			return (EINVAL);
+		}
+
+		memcpy(&ctrlsptr[i], &ctrl_conf, sizeof(ctrl_conf));
+		/* Try to create ctrl with config parsed */
+		debug("NUM=%d\nNUM_CS=%d\nECC=%d\nFILENAME=%s\nECC_LAYOUT[0]"
+		    "=%d\nECC_LAYOUT[1]=%d\n\n",
+		    ctrlsptr[i].num, ctrlsptr[i].num_cs, ctrlsptr[i].ecc,
+		    ctrlsptr[i].filename, ctrlsptr[i].ecc_layout[0],
+		    ctrlsptr[i].ecc_layout[1]);
+	}
+	*cnt = count;
+	*ctrls = ctrlsptr;
+	return (0);
+}
+
+static void
+destroy_ctrls(struct sim_ctrl *ctrls)
+{
+
+	free(ctrls);
+}
+
+static int
+create_chips(struct rcfile *f, struct sim_chip **chips, int *cnt)
+{
+	struct sim_chip *chipsptr;
+	int count, i;
+
+	count = rc_getsectionscount(f, "chip");
+	if (count > (MAX_CTRL_CS * MAX_SIM_DEV)) {
+		error("Too many chip sections specified(%d)", count);
+		return (ENOTSUP);
+	} else if (count == 0) {
+		error("No chip sections specified");
+		return (ENOENT);
+	}
+
+	chipsptr = (struct sim_chip *)malloc(sizeof(struct sim_chip) * count);
+	if (chipsptr == NULL) {
+		error("Could not allocate memory for chip configuration");
+		return (ENOMEM);
+	}
+
+	for (i = 0; i < count; i++) {
+		bzero((void *)&chip_conf, sizeof(chip_conf));
+
+		/*
+		 * Bad block map have to end up with 0xffff, so
+		 * we're filling array with 0xff. If bad block map is
+		 * defined in config file, values will be overriden.
+		 */
+		memset((void *)&chip_conf.bad_block_map, 0xff,
+		    sizeof(chip_conf.bad_block_map));
+
+		if (validate_section_config(f, "chip", i) != 0) {
+			free(chipsptr);
+			return (EINVAL);
+		}
+
+		if (parse_section(f, "chip", i) != 0) {
+			free(chipsptr);
+			return (EINVAL);
+		}
+
+		memcpy(&chipsptr[i], &chip_conf, sizeof(chip_conf));
+
+		/* Try to create chip with config parsed */
+		debug("CHIP:\nNUM=%d\nCTRL_NUM=%d\nDEVID=%d\nMANID=%d\n"
+		    "PAGE_SZ=%d\nOOBSZ=%d\nREAD_T=%d\nDEVMODEL=%s\n"
+		    "MAN=%s\nCOLADDRCYCLES=%d\nROWADDRCYCLES=%d\nCHWIDTH=%d\n"
+		    "PGS/BLK=%d\nBLK/LUN=%d\nLUNS=%d\nERR_RATIO=%d\n"
+		    "WEARLEVEL=%d\nISWP=%d\n\n\n\n",
+		    chipsptr[i].num, chipsptr[i].ctrl_num,
+		    chipsptr[i].device_id, chipsptr[i].manufact_id,
+		    chipsptr[i].page_size, chipsptr[i].oob_size,
+		    chipsptr[i].read_time, chipsptr[i].device_model,
+		    chipsptr[i].manufacturer, chipsptr[i].col_addr_cycles,
+		    chipsptr[i].row_addr_cycles, chipsptr[i].width,
+		    chipsptr[i].pgs_per_blk, chipsptr[i].blks_per_lun,
+		    chipsptr[i].luns, chipsptr[i].error_ratio,
+		    chipsptr[i].wear_level, chipsptr[i].is_wp);
+	}
+	*cnt = count;
+	*chips = chipsptr;
+	return (0);
+}
+
+static void
+destroy_chips(struct sim_chip *chips)
+{
+
+	free(chips);
+}
+
+int
+parse_config(char *cfgfname, const char *devfname)
+{
+	int err = 0, fd;
+	unsigned int chipsectionscnt, ctrlsectionscnt, i;
+	struct rcfile *f;
+	struct sim_chip *chips;
+	struct sim_ctrl *ctrls;
+
+	err = rc_open(cfgfname, "r", &f);
+	if (err) {
+		error("could not open configuration file (%s)", cfgfname);
+		return (EX_NOINPUT);
+	}
+
+	/* First, try to configure simulator itself. */
+	if (configure_sim(devfname, f) != EX_OK) {
+		rc_close(f);
+		return (EINVAL);
+	}
+
+	debug("SIM CONFIGURED!\n");
+	/* Then create controllers' configs */
+	if (create_ctrls(f, &ctrls, &ctrlsectionscnt) != 0) {
+		rc_close(f);
+		return (ENXIO);
+	}
+	debug("CTRLS CONFIG READ!\n");
+
+	/* Then create chips' configs */
+	if (create_chips(f, &chips, &chipsectionscnt) != 0) {
+		destroy_ctrls(ctrls);
+		rc_close(f);
+		return (ENXIO);
+	}
+	debug("CHIPS CONFIG READ!\n");
+
+	if (validate_ctrls(ctrls, ctrlsectionscnt) != 0) {
+		destroy_ctrls(ctrls);
+		destroy_chips(chips);
+		rc_close(f);
+		return (EX_SOFTWARE);
+	}
+	if (validate_chips(chips, chipsectionscnt, ctrls,
+	    ctrlsectionscnt) != 0) {
+		destroy_ctrls(ctrls);
+		destroy_chips(chips);
+		rc_close(f);
+		return (EX_SOFTWARE);
+	}
+
+	/* Open device */
+	fd = open(devfname, O_RDWR);
+	if (fd == -1) {
+		error("could not open simulator device file (%s)!",
+		    devfname);
+		rc_close(f);
+		destroy_chips(chips);
+		destroy_ctrls(ctrls);
+		return (EX_OSFILE);
+	}
+
+	debug("SIM CONFIG STARTED!\n");
+
+	/* At this stage, both ctrls' and chips' configs should be valid */
+	for (i = 0; i < ctrlsectionscnt; i++) {
+		err = ioctl(fd, NANDSIM_CREATE_CTRL, &ctrls[i]);
+		if (err) {
+			if (err == EEXIST)
+				error("Controller#%d already created\n",
+				    ctrls[i].num);
+			else if (err == EINVAL)
+				error("Incorrect controler number (%d)\n",
+				    ctrls[i].num);
+			else
+				error("Could not created controller#%d\n",
+				    ctrls[i].num);
+			/* Errors during controller creation stops parsing */
+			close(fd);
+			rc_close(f);
+			destroy_ctrls(ctrls);
+			destroy_chips(chips);
+			return (ENXIO);
+		}
+		debug("CTRL#%d CONFIG STARTED!\n", i);
+	}
+
+	for (i = 0; i < chipsectionscnt; i++) {
+		err = ioctl(fd, NANDSIM_CREATE_CHIP, &chips[i]);
+		if (err) {
+			if (err == EEXIST)
+				error("Chip#%d for controller#%d already "
+				    "created\n", chips[i].num,
+				    chips[i].ctrl_num);
+			else if (err == EINVAL)
+				error("Incorrect chip number (%d:%d)\n",
+				    chips[i].num, chips[i].ctrl_num);
+			else
+				error("Could not create chip (%d:%d)\n",
+				    chips[i].num, chips[i].ctrl_num);
+			error("Could not start chip#%d\n", i);
+			destroy_chips(chips);
+			destroy_ctrls(ctrls);
+			close(fd);
+			rc_close(f);
+			return (ENXIO);
+		}
+	}
+	debug("CHIPS CONFIG STARTED!\n");
+
+	close(fd);
+	rc_close(f);
+	destroy_chips(chips);
+	destroy_ctrls(ctrls);
+	return (0);
+}
+
+/*
+ * Function tries to get appropriate value for given key, convert it to
+ * array of ints (of given size), and perform all the neccesary checks and
+ * conversions.
+ */
+static int
+get_argument_intarray(const char *sect_name, int sectno,
+    struct nandsim_key *key, struct rcfile *f)
+{
+	char strbuf[STRBUFSIZ];
+	int *intbuf;
+	int getres;
+	uint32_t cnt, i = 0;
+
+	getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ,
+	    (char *)&strbuf);
+
+	if (getres != 0) {
+		if (key->mandatory != 0) {
+			error(MSG_MANDATORYKEYMISSING, key->keyname,
+			    sect_name);
+			return (EINVAL);
+		} else
+			/* Non-mandatory key, not present -- skip */
+			return (0);
+	}
+	cnt = parse_intarray((char *)&strbuf, &intbuf);
+	cnt = (cnt <= key->maxlength) ? cnt : key->maxlength;
+
+	for (i = 0; i < cnt; i++) {
+		if (SIZE(key->valuetype) == SIZE_8)
+			*((uint8_t *)(key->field) + i) =
+			    (uint8_t)intbuf[i];
+		else if (SIZE(key->valuetype) == SIZE_16)
+			*((uint16_t *)(key->field) + i) =
+			    (uint16_t)intbuf[i];
+		else
+			*((uint32_t *)(key->field) + i) =
+			    (uint32_t)intbuf[i];
+	}
+	free(intbuf);
+	return (0);
+}
+
+/*
+ *  Function tries to get appropriate value for given key, convert it to
+ *  int of certain length.
+ */
+static int
+get_argument_int(const char *sect_name, int sectno, struct nandsim_key *key,
+    struct rcfile *f)
+{
+	int getres;
+	uint32_t val;
+
+	getres = rc_getint(f, sect_name, sectno, key->keyname, &val);
+	if (getres != 0) {
+
+		if (key->mandatory != 0) {
+			error(MSG_MANDATORYKEYMISSING, key->keyname,
+			    sect_name);
+
+			return (EINVAL);
+		} else
+			/* Non-mandatory key, not present -- skip */
+			return (0);
+	}
+	if (SIZE(key->valuetype) == SIZE_8)
+		*(uint8_t *)(key->field) = (uint8_t)val;
+	else if (SIZE(key->valuetype) == SIZE_16)
+		*(uint16_t *)(key->field) = (uint16_t)val;
+	else
+		*(uint32_t *)(key->field) = (uint32_t)val;
+	return (0);
+}
+
+/* Function tries to get string value for given key */
+static int
+get_argument_string(const char *sect_name, int sectno,
+    struct nandsim_key *key, struct rcfile *f)
+{
+	char strbuf[STRBUFSIZ];
+	int getres;
+
+	getres = rc_getstring(f, sect_name, sectno, key->keyname, STRBUFSIZ,
+	    strbuf);
+
+	if (getres != 0) {
+		if (key->mandatory != 0) {
+			error(MSG_MANDATORYKEYMISSING, key->keyname,
+			    sect_name);
+			return (1);
+		} else
+			/* Non-mandatory key, not present -- skip */
+			return (0);
+	}
+	strncpy(key->field, (char *)&strbuf, (size_t)(key->maxlength - 1));
+	return (0);
+}
+
+/* Function tries to get on/off value for given key */
+static int
+get_argument_bool(const char *sect_name, int sectno, struct nandsim_key *key,
+    struct rcfile *f)
+{
+	int getres, val;
+
+	getres = rc_getbool(f, sect_name, sectno, key->keyname, &val);
+	if (getres != 0) {
+		if (key->mandatory != 0) {
+			error(MSG_MANDATORYKEYMISSING, key->keyname,
+			    sect_name);
+			return (1);
+		} else
+			/* Non-mandatory key, not present -- skip */
+			return (0);
+	}
+	*(uint8_t *)key->field = (uint8_t)val;
+	return (0);
+}
+
+int
+parse_section(struct rcfile *f, const char *sect_name, int sectno)
+{
+	struct nandsim_key *key;
+	struct nandsim_section *sect = (struct nandsim_section *)§ions;
+	int getres = 0;
+
+	while (1) {
+		if (sect == NULL)
+			return (EINVAL);
+
+		if (strcmp(sect->name, sect_name) == 0)
+			break;
+		else
+			sect++;
+	}
+	key = sect->keys;
+	do {
+		debug("->Section: %s, Key: %s, type: %d, size: %d",
+		    sect_name, key->keyname, TYPE(key->valuetype),
+		    SIZE(key->valuetype)/2);
+
+		switch (TYPE(key->valuetype)) {
+		case VALUE_UINT:
+			/* Single int value */
+			getres = get_argument_int(sect_name, sectno, key, f);
+
+			if (getres != 0)
+				return (getres);
+
+			break;
+		case VALUE_UINTARRAY:
+			/* Array of ints */
+			getres = get_argument_intarray(sect_name,
+			    sectno, key, f);
+
+			if (getres != 0)
+				return (getres);
+
+			break;
+		case VALUE_STRING:
+			/* Array of chars */
+			getres = get_argument_string(sect_name, sectno, key,
+			    f);
+
+			if (getres != 0)
+				return (getres);
+
+			break;
+		case VALUE_BOOL:
+			/* Boolean value (true/false/on/off/yes/no) */
+			getres = get_argument_bool(sect_name, sectno, key,
+			    f);
+
+			if (getres != 0)
+				return (getres);
+
+			break;
+		}
+	} while ((++key)->keyname != NULL);
+
+	return (0);
+}
+
+static uint8_t
+validate_chips(struct sim_chip *chips, int chipcnt,
+    struct sim_ctrl *ctrls, int ctrlcnt)
+{
+	int cchipcnt, i, width, j, id, max;
+
+	cchipcnt = chipcnt;
+	for (chipcnt -= 1; chipcnt >= 0; chipcnt--) {
+		if (chips[chipcnt].num >= MAX_CTRL_CS) {
+			error("chip no. too high (%d)!!\n",
+			    chips[chipcnt].num);
+			return (EINVAL);
+		}
+
+		if (chips[chipcnt].ctrl_num >= MAX_SIM_DEV) {
+			error("controller no. too high (%d)!!\n",
+			    chips[chipcnt].ctrl_num);
+			return (EINVAL);
+		}
+
+		if (chips[chipcnt].width != 8 &&
+		    chips[chipcnt].width != 16) {
+			error("invalid width:%d for chip#%d",
+			    chips[chipcnt].width, chips[chipcnt].num);
+			return (EINVAL);
+		}
+
+		/* Check if page size is > 512 and if its power of 2 */
+		if (chips[chipcnt].page_size < 512 ||
+		    (chips[chipcnt].page_size &
+		    (chips[chipcnt].page_size - 1)) != 0) {
+			error("invalid page size:%d for chip#%d at ctrl#%d!!"
+			    "\n", chips[chipcnt].page_size,
+			    chips[chipcnt].num,
+			    chips[chipcnt].ctrl_num);
+			return (EINVAL);
+		}
+
+		/* Check if controller no. ctrl_num is configured */
+		for (i = 0, id = -1; i < ctrlcnt && id == -1; i++)
+			if (ctrls[i].num == chips[chipcnt].ctrl_num)
+				id = i;
+
+		if (i == ctrlcnt && id == -1) {
+			error("Missing configuration for controller %d"
+			    " (at least one chip is connected to it)",
+			    chips[chipcnt].ctrl_num);
+			return (EINVAL);
+		} else {
+			/*
+			 * Controller is configured -> check oob_size
+			 * validity
+			 */
+			i = 0;
+			max = ctrls[id].ecc_layout[0];
+			while (i < MAX_ECC_BYTES &&
+			    ctrls[id].ecc_layout[i] != 0xffff) {
+
+				if (ctrls[id].ecc_layout[i] > max)
+					max = ctrls[id].ecc_layout[i];
+				i++;
+			}
+
+			if (chips[chipcnt].oob_size < (unsigned)i) {
+				error("OOB size for chip#%d at ctrl#%d is "
+				    "smaller than ecc layout length!",
+				    chips[chipcnt].num,
+				    chips[chipcnt].ctrl_num);
+				exit(EINVAL);
+			}
+
+			if (chips[chipcnt].oob_size < (unsigned)max) {
+				error("OOB size for chip#%d at ctrl#%d is "
+				    "smaller than maximal ecc position in "
+				    "defined layout!", chips[chipcnt].num,
+				    chips[chipcnt].ctrl_num);
+				exit(EINVAL);
+			}
+
+
+		}
+
+		if ((chips[chipcnt].erase_time < DELAYTIME_MIN ||
+		    chips[chipcnt].erase_time > DELAYTIME_MAX) &&
+		    chips[chipcnt].erase_time != 0) {
+			error("Invalid erase time value for chip#%d at "
+			    "ctrl#%d",
+			    chips[chipcnt].num,
+			    chips[chipcnt].ctrl_num);
+			return (EINVAL);
+		}
+
+		if ((chips[chipcnt].prog_time < DELAYTIME_MIN ||
+		    chips[chipcnt].prog_time > DELAYTIME_MAX) &&
+		    chips[chipcnt].prog_time != 0) {
+			error("Invalid prog time value for chip#%d at "
+			    "ctr#%d!",
+			    chips[chipcnt].num,
+			    chips[chipcnt].ctrl_num);
+			return (EINVAL);
+		}
+
+		if ((chips[chipcnt].read_time < DELAYTIME_MIN ||
+		    chips[chipcnt].read_time > DELAYTIME_MAX) &&
+		    chips[chipcnt].read_time != 0) {
+			error("Invalid read time value for chip#%d at "
+			    "ctrl#%d!",
+			    chips[chipcnt].num,
+			    chips[chipcnt].ctrl_num);
+			return (EINVAL);
+		}
+	}
+	/* Check if chips attached to the same controller, have same width */
+	for (i = 0; i < ctrlcnt; i++) {
+		width = -1;
+		for (j = 0; j < cchipcnt; j++) {
+			if (chips[j].ctrl_num == i) {
+				if (width == -1) {
+					width = chips[j].width;
+				} else {
+					if (width != chips[j].width) {
+						error("Chips attached to "
+						    "ctrl#%d have different "
+						    "widths!\n", i);
+						return (EINVAL);
+					}
+				}
+			}
+		}
+	}
+
+	return (0);
+}
+
+static uint8_t
+validate_ctrls(struct sim_ctrl *ctrl, int ctrlcnt)
+{
+	for (ctrlcnt -= 1; ctrlcnt >= 0; ctrlcnt--) {
+		if (ctrl[ctrlcnt].num > MAX_SIM_DEV) {
+			error("Controller no. too high (%d)!!\n",
+			    ctrl[ctrlcnt].num);
+			return (EINVAL);
+		}
+		if (ctrl[ctrlcnt].num_cs > MAX_CTRL_CS) {
+			error("Too many CS (%d)!!\n", ctrl[ctrlcnt].num_cs);
+			return (EINVAL);
+		}
+		if (ctrl[ctrlcnt].ecc != 0 && ctrl[ctrlcnt].ecc != 1) {
+			error("ECC is set to neither 0 nor 1 !\n");
+			return (EINVAL);
+		}
+	}
+
+	return (0);
+}
+
+static int validate_section_config(struct rcfile *f, const char *sect_name,
+    int sectno)
+{
+	struct nandsim_key *key;
+	struct nandsim_section *sect;
+	char **keys_tbl;
+	int i, match;
+
+	for (match = 0, sect = (struct nandsim_section *)§ions;
+	    sect != NULL; sect++) {
+		if (strcmp(sect->name, sect_name) == 0) {
+			match = 1;
+			break;
+		}
+	}
+
+	if (match == 0)
+		return (EINVAL);
+
+	keys_tbl = rc_getkeys(f, sect_name, sectno);
+	if (keys_tbl == NULL)
+		return (ENOMEM);
+
+	for (i = 0; keys_tbl[i] != NULL; i++) {
+		key = sect->keys;
+		match = 0;
+		do {
+			if (strcmp(keys_tbl[i], key->keyname) == 0) {
+				match = 1;
+				break;
+			}
+		} while ((++key)->keyname != NULL);
+
+		if (match == 0) {
+			error("Invalid key in config file: %s\n", keys_tbl[i]);
+			free(keys_tbl);
+			return (EINVAL);
+		}
+	}
+
+	free(keys_tbl);
+	return (0);
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/nandsim_cfgparse.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/nandsim_cfgparse.h	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (C) 2009-2012 Semihalf
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/usr.sbin/nandsim/nandsim_cfgparse.h 235537 2012-05-17 10:11:18Z gber $
+ */
+
+#ifndef _NANDSIM_CONFPARSER_H_
+#define _NANDSIM_CONFPARSER_H_
+
+#define VALUE_UINT	0x08
+#define VALUE_INT	0x10
+#define VALUE_UINTARRAY	0x18
+#define VALUE_INTARRAY	0x20
+#define VALUE_STRING	0x28
+#define VALUE_CHAR	0x40
+#define VALUE_BOOL	0x48
+
+#define SIZE_8	0x01
+#define SIZE_16	0x02
+#define SIZE_32	0x04
+
+#include "nandsim_rcfile.h"
+
+/*
+ * keyname	= name of a key,
+ * mandatory	= is key mandatory in section belonging to, 0=false 1=true
+ * valuetype	= what kind of value is assigned to that key, e.g.
+ *		  VALUE_UINT | SIZE_8 -- unsigned uint size 8 bits;
+ *		  VALUE_UINTARRAY | SIZE_8 -- array of uints 8-bit long;
+ *		  VALUE_BOOL -- 'on', 'off','true','false','yes' or 'no'
+ *		  literals;
+ *		  VALUE_STRING -- strings
+ * field	= ptr to the field that should hold value for parsed value
+ * maxlength	= contains maximum length of an array (used only with either
+ *		  VALUE_STRING or VALUE_(U)INTARRAY value types.
+ */
+struct nandsim_key {
+	const char	*keyname;
+	uint8_t		mandatory;
+	uint8_t		valuetype;
+	void		*field;
+	uint32_t	maxlength;
+};
+struct nandsim_section {
+	const char		*name;
+	struct nandsim_key	*keys;
+};
+
+struct nandsim_config {
+	struct sim_param	**simparams;
+	struct sim_chip		**simchips;
+	struct sim_ctrl		**simctrls;
+	int			chipcnt;
+	int			ctrlcnt;
+};
+
+int parse_intarray(char *, int **);
+int parse_config(char *, const char *);
+int parse_section(struct rcfile *, const char *, int);
+int compare_configs(struct nandsim_config *, struct nandsim_config *);
+int convert_argint(char *, int *);
+int convert_arguint(char *, unsigned int *);
+
+#endif /* _NANDSIM_CONFPARSER_H_ */
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/nandsim_rcfile.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/nandsim_rcfile.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 1999, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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/lib/libncp/ncpl_rcfile.c,v 1.5 2007/01/09 23:27:39 imp Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/usr.sbin/nandsim/nandsim_rcfile.c 235537 2012-05-17 10:11:18Z gber $");
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+
+#include "nandsim_rcfile.h"
+
+SLIST_HEAD(rcfile_head, rcfile);
+static struct rcfile_head pf_head = {NULL};
+static struct rcsection *rc_findsect(struct rcfile *rcp,
+    const char *sectname, int sect_id);
+static struct rcsection *rc_addsect(struct rcfile *rcp,
+    const char *sectname);
+static int rc_sect_free(struct rcsection *rsp);
+static struct rckey *rc_sect_findkey(struct rcsection *rsp,
+    const char *keyname);
+static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name,
+    char *value);
+static void rc_key_free(struct rckey *p);
+static void rc_parse(struct rcfile *rcp);
+
+static struct rcfile* rc_find(const char *filename);
+
+/*
+ * open rcfile and load its content, if already open - return previous handle
+ */
+int
+rc_open(const char *filename, const char *mode,struct rcfile **rcfile)
+{
+	struct rcfile *rcp;
+	FILE *f;
+	rcp = rc_find(filename);
+	if (rcp) {
+		*rcfile = rcp;
+		return (0);
+	}
+	f = fopen (filename, mode);
+	if (f == NULL)
+		return errno;
+	rcp = malloc(sizeof(struct rcfile));
+	if (rcp == NULL) {
+		fclose(f);
+		return ENOMEM;
+	}
+	bzero(rcp, sizeof(struct rcfile));
+	rcp->rf_name = strdup(filename);
+	rcp->rf_f = f;
+	SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
+	rc_parse(rcp);
+	*rcfile = rcp;
+	return (0);
+}
+
+int
+rc_close(struct rcfile *rcp)
+{
+	struct rcsection *p,*n;
+
+	fclose(rcp->rf_f);
+	for (p = SLIST_FIRST(&rcp->rf_sect); p; ) {
+		n = p;
+		p = SLIST_NEXT(p,rs_next);
+		rc_sect_free(n);
+	}
+	free(rcp->rf_name);
+	SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
+	free(rcp);
+	return (0);
+}
+
+static struct rcfile*
+rc_find(const char *filename)
+{
+	struct rcfile *p;
+
+	SLIST_FOREACH(p, &pf_head, rf_next)
+		if (strcmp (filename, p->rf_name) == 0)
+			return (p);
+	return (0);
+}
+
+/* Find section with given name and id */
+static struct rcsection *
+rc_findsect(struct rcfile *rcp, const char *sectname, int sect_id)
+{
+	struct rcsection *p;
+
+	SLIST_FOREACH(p, &rcp->rf_sect, rs_next)
+		if (strcmp(p->rs_name, sectname) == 0 && p->rs_id == sect_id)
+			return (p);
+	return (NULL);
+}
+
+static struct rcsection *
+rc_addsect(struct rcfile *rcp, const char *sectname)
+{
+	struct rcsection *p;
+	int id = 0;
+	p = rc_findsect(rcp, sectname, 0);
+	if (p) {
+		/*
+		 * If section with that name already exists -- add one more,
+		 * same named, but with different id (higher by one)
+		 */
+		while (p != NULL) {
+			id = p->rs_id + 1;
+			p = rc_findsect(rcp, sectname, id);
+		}
+	}
+	p = malloc(sizeof(*p));
+	if (!p)
+		return (NULL);
+	p->rs_name = strdup(sectname);
+	p->rs_id = id;
+	SLIST_INIT(&p->rs_keys);
+	SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next);
+	return (p);
+}
+
+static int
+rc_sect_free(struct rcsection *rsp)
+{
+	struct rckey *p,*n;
+
+	for (p = SLIST_FIRST(&rsp->rs_keys); p; ) {
+		n = p;
+		p = SLIST_NEXT(p,rk_next);
+		rc_key_free(n);
+	}
+	free(rsp->rs_name);
+	free(rsp);
+	return (0);
+}
+
+static struct rckey *
+rc_sect_findkey(struct rcsection *rsp, const char *keyname)
+{
+	struct rckey *p;
+
+	SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
+		if (strcmp(p->rk_name, keyname)==0)
+			return (p);
+	return (NULL);
+}
+
+static struct rckey *
+rc_sect_addkey(struct rcsection *rsp, const char *name, char *value)
+{
+	struct rckey *p;
+	p = rc_sect_findkey(rsp, name);
+	if (p) {
+		free(p->rk_value);
+	} else {
+		p = malloc(sizeof(*p));
+		if (!p)
+			return (NULL);
+		SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next);
+		p->rk_name = strdup(name);
+	}
+	p->rk_value = value ? strdup(value) : strdup("");
+	return (p);
+}
+
+static void
+rc_key_free(struct rckey *p)
+{
+	free(p->rk_value);
+	free(p->rk_name);
+	free(p);
+}
+
+enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue};
+
+static void
+rc_parse(struct rcfile *rcp)
+{
+	FILE *f = rcp->rf_f;
+	int state = stNewLine, c;
+	struct rcsection *rsp = NULL;
+	struct rckey *rkp = NULL;
+	char buf[2048];
+	char *next = buf, *last = &buf[sizeof(buf)-1];
+
+	while ((c = getc (f)) != EOF) {
+		if (c == '\r')
+			continue;
+		if (state == stNewLine) {
+			next = buf;
+			if (isspace(c))
+				continue;	/* skip leading junk */
+			if (c == '[') {
+				state = stHeader;
+				rsp = NULL;
+				continue;
+			}
+			if (c == '#' || c == ';') {
+				state = stSkipToEOL;
+			} else {		/* something meaningful */
+				state = stGetKey;
+			}
+		}
+		if (state == stSkipToEOL || next == last) {/* ignore long lines */
+			if (c == '\n') {
+				state = stNewLine;
+				next = buf;
+			}
+			continue;
+		}
+		if (state == stHeader) {
+			if (c == ']') {
+				*next = 0;
+				next = buf;
+				rsp = rc_addsect(rcp, buf);
+				state = stSkipToEOL;
+			} else
+				*next++ = c;
+			continue;
+		}
+		if (state == stGetKey) {
+			if (c == ' ' || c == '\t')/* side effect: 'key name='*/
+				continue;	  /* become 'keyname='	     */
+			if (c == '\n') {	  /* silently ignore ... */
+				state = stNewLine;
+				continue;
+			}
+			if (c != '=') {
+				*next++ = c;
+				continue;
+			}
+			*next = 0;
+			if (rsp == NULL) {
+				fprintf(stderr, "Key '%s' defined before "
+				    "section\n", buf);
+				state = stSkipToEOL;
+				continue;
+			}
+			rkp = rc_sect_addkey(rsp, buf, NULL);
+			next = buf;
+			state = stGetValue;
+			continue;
+		}
+		/* only stGetValue left */
+		if (state != stGetValue) {
+			fprintf(stderr, "Well, I can't parse file "
+			    "'%s'\n",rcp->rf_name);
+			state = stSkipToEOL;
+		}
+		if (c != '\n') {
+			*next++ = c;
+			continue;
+		}
+		*next = 0;
+		rkp->rk_value = strdup(buf);
+		state = stNewLine;
+		rkp = NULL;
+	}	/* while */
+	if (c == EOF && state == stGetValue) {
+		*next = 0;
+		rkp->rk_value = strdup(buf);
+	}
+}
+
+int
+rc_getstringptr(struct rcfile *rcp, const char *section, int sect_id,
+    const char *key, char **dest)
+{
+	struct rcsection *rsp;
+	struct rckey *rkp;
+
+	*dest = NULL;
+	rsp = rc_findsect(rcp, section, sect_id);
+	if (!rsp)
+		return (ENOENT);
+	rkp = rc_sect_findkey(rsp,key);
+	if (!rkp)
+		return (ENOENT);
+	*dest = rkp->rk_value;
+	return (0);
+}
+
+int
+rc_getstring(struct rcfile *rcp, const char *section, int sect_id,
+    const char *key, unsigned int maxlen, char *dest)
+{
+	char *value;
+	int error;
+
+	error = rc_getstringptr(rcp, section, sect_id, key, &value);
+	if (error)
+		return (error);
+	if (strlen(value) >= maxlen) {
+		fprintf(stderr, "line too long for key '%s' in section '%s',"
+		    "max = %d\n",key, section, maxlen);
+		return (EINVAL);
+	}
+	strcpy(dest,value);
+	return (0);
+}
+
+int
+rc_getint(struct rcfile *rcp, const char *section, int sect_id,
+    const char *key, int *value)
+{
+	struct rcsection *rsp;
+	struct rckey *rkp;
+
+	rsp = rc_findsect(rcp, section, sect_id);
+	if (!rsp)
+		return (ENOENT);
+	rkp = rc_sect_findkey(rsp,key);
+	if (!rkp)
+		return (ENOENT);
+	errno = 0;
+	*value = strtol(rkp->rk_value,NULL,0);
+	if (errno) {
+		fprintf(stderr, "invalid int value '%s' for key '%s' in "
+		    "section '%s'\n",rkp->rk_value,key,section);
+		return (errno);
+	}
+	return (0);
+}
+
+/*
+ * 1,yes,true
+ * 0,no,false
+ */
+int
+rc_getbool(struct rcfile *rcp, const char *section, int sect_id,
+    const char *key, int *value)
+{
+	struct rcsection *rsp;
+	struct rckey *rkp;
+	char *p;
+
+	rsp = rc_findsect(rcp, section, sect_id);
+	if (!rsp)
+		return (ENOENT);
+	rkp = rc_sect_findkey(rsp,key);
+	if (!rkp)
+		return (ENOENT);
+	p = rkp->rk_value;
+	while (*p && isspace(*p)) p++;
+	if (*p == '0' || strcasecmp(p,"no") == 0 ||
+	    strcasecmp(p, "false") == 0 ||
+	    strcasecmp(p, "off") == 0) {
+		*value = 0;
+		return (0);
+	}
+	if (*p == '1' || strcasecmp(p,"yes") == 0 ||
+	    strcasecmp(p, "true") == 0 ||
+	    strcasecmp(p, "on") == 0) {
+		*value = 1;
+		return (0);
+	}
+	fprintf(stderr, "invalid boolean value '%s' for key '%s' in section "
+	    "'%s' \n",p, key, section);
+	return (EINVAL);
+}
+
+/* Count how many sections with given name exists in configuration. */
+int rc_getsectionscount(struct rcfile *f, const char *sectname)
+{
+	struct rcsection *p;
+	int count = 0;
+
+	p = rc_findsect(f, sectname, 0);
+	if (p) {
+		while (p != NULL) {
+			count = p->rs_id + 1;
+			p = rc_findsect(f, sectname, count);
+		}
+		return (count);
+	} else
+		return (0);
+}
+
+char **
+rc_getkeys(struct rcfile *rcp, const char *sectname, int sect_id)
+{
+	struct rcsection *rsp;
+	struct rckey *p;
+	char **names_tbl;
+	int i = 0, count = 0;
+
+	rsp = rc_findsect(rcp, sectname, sect_id);
+	if (rsp == NULL)
+		return (NULL);
+
+	SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
+		count++;
+
+	names_tbl = malloc(sizeof(char *) * (count + 1));
+	if (names_tbl == NULL)
+		return (NULL);
+
+	SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
+		names_tbl[i++] = p->rk_name;
+
+	names_tbl[i] = NULL;
+	return (names_tbl);
+}
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/nandsim_rcfile.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/nandsim_rcfile.h	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1999, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-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 AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/usr.sbin/nandsim/nandsim_rcfile.h 235537 2012-05-17 10:11:18Z gber $
+ *
+ * from: FreeBSD: src/lib/libncp/ncpl_rcfile.c,v 1.5 2007/01/09 23:27:39 imp Exp
+ */
+
+#ifndef _SIMRC_H_
+#define _SIMRC_H_
+
+#include <sys/queue.h>
+
+struct rckey {
+	SLIST_ENTRY(rckey)	rk_next;
+	char			*rk_name;	/* key name */
+	char			*rk_value;	/* key value */
+};
+
+struct rcsection {
+	SLIST_ENTRY(rcsection)	rs_next;
+	SLIST_HEAD(rckey_head,rckey) rs_keys;	/* key list */
+	char			*rs_name;	/* section name */
+	int			rs_id;		/* allow few same named */
+};
+
+struct rcfile {
+	SLIST_ENTRY(rcfile)	rf_next;
+	SLIST_HEAD(rcsec_head, rcsection) rf_sect;	/* sections list */
+	char			*rf_name;		/* file name */
+	FILE			*rf_f;			/* file desc */
+};
+
+int rc_open(const char *, const char *,struct rcfile **);
+int rc_close(struct rcfile *);
+int rc_getstringptr(struct rcfile *, const char *, int, const char *,
+    char **);
+int rc_getstring(struct rcfile *, const char *, int, const char *,
+    unsigned int, char *);
+int rc_getint(struct rcfile *, const char *, int, const char *, int *);
+int rc_getbool(struct rcfile *, const char *, int, const char *, int *);
+int rc_getsectionscount(struct rcfile *, const char *);
+char **rc_getkeys(struct rcfile *, const char *, int);
+
+#endif /* _SIMRC_H_ */
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandsim/sample.conf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandsim/sample.conf	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,174 @@
+#-
+# Copyright (C) 2009-2012 Semihalf
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD: head/usr.sbin/nandsim/sample.conf 235537 2012-05-17 10:11:18Z gber $
+
+#
+# Sample NANDsim configuration file.
+#
+
+#############################################################################
+#
+# [sim] General (common) simulator configuration section.
+#
+[sim]
+# log_level=0..255
+log_level=11
+
+# log_output=[none, console, ram, file]
+#
+# When log_output=file is specified, each [ctrl] section must have a
+# corresponding 'log_filename' field provided, which specifies log file name
+# to be used.
+log_output=none
+
+#############################################################################
+#
+# [ctrl] Controller configuration section.
+#
+# There can be a number of controllers defined for simulation, each has a
+# dedicated [ctrl] section. With a given controller there are associated
+# subordinate NAND chips, which are tied to chip select lines.
+#
+[ctrl]
+# The number of this controller.
+# ctrl_num=0..3
+ctrl_num=0
+
+# The number of chip selects available at this controller.
+# num_cs=1..4
+num_cs=1
+
+# ECC enable flag.
+# ecc=[on|off]
+ecc=on
+
+# ECC layout. This is the list of byte offsets within OOB area, which comprise
+# the ECC contents set.
+#
+# ecc_layout=[byte1, byte2-byte3, ..byten]
+ecc_layout=[0-53]
+
+# Absolute path to the log file for this controller.
+#log_filename=/var/log/nandsim-ctl0.log
+
+
+#############################################################################
+#
+# [chip] Chip configuration section.
+#
+# There can be a number of individual NAND chip devices defined for
+# simulation, and each has a dedicated [chip] section.
+#
+# A particular chip needs to be associated with its parent NAND controller by
+# specifying the following fields: controller number (chip_ctrl) and the chip
+# select line it is connected to (chip_cs). The chip can be connected to only
+# a single (and unique) controller:cs pair.
+#
+[chip]
+# The number of parent controller. This has to fit one of the controller
+# instance number (ctrl_num from [ctrl] section).
+# chip_ctrl=0..3
+chip_ctrl=0
+
+# Chip select line.
+# chip_cs=0..3
+chip_cs=0
+
+# ONFI device identifier.
+# device_id=0x00..0xff
+device_id=0xd3
+
+# ONFI manufacturer identifier.
+# manufacturer_id=0x00..0xff
+manufacturer_id=0xec
+
+# Textual description of the chip.
+# model="model_name"
+model="k9xxg08uxM:1GiB 3,3V 8-bit"
+
+# Textual name of the chip manufacturer.
+# manufacturer="manufacturer name"
+manufacturer="SAMSUNG"
+
+# page_size=[must be power of 2 and >= 512]  (in bytes)
+page_size=2048
+# oob_size=[>0]
+oob_size=64
+# pages_per_block=n*32
+pages_per_block=64
+# blocks_per_lun=[>0]
+blocks_per_lun=4096
+# luns=1..N
+luns=1
+# column_addr_cycle=[1,2]
+column_addr_cycle=2
+# row_addr_cycle=[1,2,3]
+row_addr_cycle=3
+
+# program_time=  (in us)
+program_time=0
+# erase_time=    (in us)
+erase_time=0
+# read_time=     (in us)
+read_time=0
+# ccs_time=      (in us)
+#ccs_time=200
+
+# Simulate write-protect on the chip.
+# write_protect=[yes|no]
+#write_protect=no
+
+# Blocks wear-out threshold. Each block has a counter of program-erase cycles;
+# when this counter reaches 'wear_out' value a given block is treated as a bad
+# block (access will report error).
+#
+# Setting wear_out to 0 means that blocks will never wear out.
+#
+# wear_out=0..100000
+wear_out=50000
+
+# Errors per million read/write bytes. This simulates an accidental read/write
+# block error, which can happen in real devices with certain probability. Note
+# this isn't a bad block condition i.e. the block at which the read/write
+# operation is simulated to fail here remains usable, only the operation has
+# not succeeded (this is where ECC comes into play and is supposed to correct
+# such problems).
+#
+# error_ratio=0..1000000
+#error_ratio=50
+
+# Chip data bus width. All chips connected to the same controller must have
+# the same bus width.
+#
+# width=[8|16]
+width=8
+
+# Bad block map. NANDsim emulates bad block behavior upon accessing a block 
+# with number from the specified list.
+#
+# bad_block_map=[bad_block1, bad_block2-bad_block3, ..bad_blockn]
+bad_block_map=[100-200]
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/Makefile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,11 @@
+# $FreeBSD: head/usr.sbin/nandtool/Makefile 235537 2012-05-17 10:11:18Z gber $
+
+PROG=	nandtool
+SRCS=	nandtool.c nand_read.c nand_write.c nand_erase.c nand_info.c
+SRCS+=	nand_readoob.c nand_writeoob.c
+BINDIR=	/usr/sbin
+DPADD=	${LIBGEOM}
+LDADD=	-lgeom
+MAN=	nandtool.8
+
+.include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nand_erase.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nand_erase.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,114 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nand_erase.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/disk.h>
+#include <libgeom.h>
+#include <dev/nand/nand_dev.h>
+#include "nandtool.h"
+
+int nand_erase(struct cmd_param *params)
+{
+	struct chip_param_io chip_params;
+	char *dev;
+	int fd = -1, ret = 0;
+	off_t pos, count;
+	off_t start, nblocks, i;
+	int block_size, mult;
+
+	if (!(dev = param_get_string(params, "dev"))) {
+		fprintf(stderr, "Please supply valid 'dev' parameter.\n");
+		return (1);
+	}
+
+	if (param_has_value(params, "count"))
+		count = param_get_intx(params, "count");
+	else
+		count = 1;
+
+	if ((fd = g_open(dev, 1)) < 0) {
+		perrorf("Cannot open %s", dev);
+		return (1);
+	}
+
+	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
+		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
+		ret = 1;
+		goto out;
+	}
+
+	block_size = chip_params.page_size * chip_params.pages_per_block;
+
+	if (param_has_value(params, "page")) {
+		pos = chip_params.page_size * param_get_intx(params, "page");
+		mult = chip_params.page_size;
+	} else if (param_has_value(params, "block")) {
+		pos = block_size * param_get_intx(params, "block");
+		mult = block_size;
+	} else if (param_has_value(params, "pos")) {
+		pos = param_get_intx(params, "pos");
+		mult = 1;
+	} else {
+		/* Erase whole chip */
+		if (ioctl(fd, DIOCGMEDIASIZE, &count) == -1) {
+			ret = 1;
+			goto out;
+		}
+
+		pos = 0;
+		mult = 1;
+	}
+
+	if (pos % block_size) {
+		fprintf(stderr, "Position must be block-size aligned!\n");
+		ret = 1;
+		goto out;
+	}
+
+	count *= mult;
+	start = pos / block_size;
+	nblocks = count / block_size;
+
+	for (i = 0; i < nblocks; i++) {
+		if (g_delete(fd, (start + i) * block_size, block_size) == -1) {
+			perrorf("Cannot erase block %d - probably a bad block",
+			    start + i);
+			ret = 1;
+		}
+	}
+
+out:
+	g_close(fd);
+
+	return (ret);
+}
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nand_info.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nand_info.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nand_info.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <libgeom.h>
+#include <sys/disk.h>
+#include <dev/nand/nand_dev.h>
+#include "nandtool.h"
+
+int nand_info(struct cmd_param *params)
+{
+	struct chip_param_io chip_params;
+	int fd = -1, ret = 0;
+	int block_size;
+	off_t chip_size, media_size;
+	const char *dev;
+
+	if ((dev = param_get_string(params, "dev")) == NULL) {
+		fprintf(stderr, "Please supply 'dev' parameter, eg. "
+		    "'dev=/dev/gnand0'\n");
+		return (1);
+	}
+
+	if ((fd = g_open(dev, 1)) == -1) {
+		perrorf("Cannot open %s", dev);
+		return (1);
+	}
+
+	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
+		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
+		ret = 1;
+		goto out;
+	}
+
+	if (ioctl(fd, DIOCGMEDIASIZE, &media_size) == -1) {
+		perrorf("Cannot ioctl(DIOCGMEDIASIZE)");
+		ret = 1;
+		goto out;
+	}
+
+	block_size = chip_params.page_size * chip_params.pages_per_block;
+	chip_size = block_size * chip_params.blocks;
+
+	printf("Device:\t\t\t%s\n", dev);
+	printf("Page size:\t\t%d bytes\n", chip_params.page_size);
+	printf("Block size:\t\t%d bytes (%d KB)\n", block_size,
+	    block_size / 1024);
+	printf("OOB size per page:\t%d bytes\n", chip_params.oob_size);
+	printf("Chip size:\t\t%jd MB\n", (uintmax_t)(chip_size / 1024 / 1024));
+	printf("Slice size:\t\t%jd MB\n",
+	    (uintmax_t)(media_size / 1024 / 1024));
+
+out:
+	g_close(fd);
+
+	return (ret);
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nand_read.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nand_read.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nand_read.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libgeom.h>
+#include <sys/disk.h>
+#include <dev/nand/nand_dev.h>
+#include "nandtool.h"
+
+int nand_read(struct cmd_param *params)
+{
+	struct chip_param_io chip_params;
+	int fd = -1, out_fd = -1, done = 0, ret = 0;
+	char *dev, *out;
+	int pos, count, mult, block_size;
+	uint8_t *buf = NULL;
+
+	if (!(dev = param_get_string(params, "dev"))) {
+		fprintf(stderr, "You must specify 'dev' parameter\n");
+		return (1);
+	}
+
+	if ((out = param_get_string(params, "out"))) {
+		out_fd = open(out, O_WRONLY|O_CREAT);
+		if (out_fd == -1) {
+			perrorf("Cannot open %s for writing", out);
+			return (1);
+		}
+	}
+
+	if ((fd = g_open(dev, 1)) == -1) {
+		perrorf("Cannot open %s", dev);
+		ret = 1;
+		goto out;
+	}
+
+	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
+		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
+		ret = 1;
+		goto out;
+	}
+
+	block_size = chip_params.page_size * chip_params.pages_per_block;
+
+	if (param_has_value(params, "page")) {
+		pos = chip_params.page_size * param_get_int(params, "page");
+		mult = chip_params.page_size;
+	} else if (param_has_value(params, "block")) {
+		pos = block_size * param_get_int(params, "block");
+		mult = block_size;
+	} else if (param_has_value(params, "pos")) {
+		pos = param_get_int(params, "pos");
+		mult = 1;
+		if (pos % chip_params.page_size) {
+			fprintf(stderr, "Position must be page-size aligned!\n");
+			ret = 1;
+			goto out;
+		}
+	} else {
+		fprintf(stderr, "You must specify one of: 'block', 'page',"
+		    "'pos' arguments\n");
+		ret = 1;
+		goto out;
+	}
+
+	if (!(param_has_value(params, "count")))
+		count = mult;
+	else
+		count = param_get_int(params, "count") * mult;
+
+	if (!(buf = malloc(chip_params.page_size))) {
+		perrorf("Cannot allocate buffer [size %x]",
+		    chip_params.page_size);
+		ret = 1;
+		goto out;
+	}
+
+	lseek(fd, pos, SEEK_SET);
+
+	while (done < count) {
+		if ((ret = read(fd, buf, chip_params.page_size)) !=
+		    (int32_t)chip_params.page_size) {
+			perrorf("read error (read %d bytes)", ret);
+			goto out;
+		}
+
+		if (out_fd != -1) {
+			done += ret;
+			if ((ret = write(out_fd, buf, chip_params.page_size)) !=
+			    (int32_t)chip_params.page_size) {
+				perrorf("write error (written %d bytes)", ret);
+				ret = 1;
+				goto out;
+			}
+		} else {
+			hexdumpoffset(buf, chip_params.page_size, done);
+			done += ret;
+		}
+	}
+
+out:
+	g_close(fd);
+	if (out_fd != -1)
+		close(out_fd);
+	if (buf)
+		free(buf);
+
+	return (ret);
+}
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nand_readoob.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nand_readoob.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,111 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nand_readoob.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libgeom.h>
+#include <sys/types.h>
+#include <sys/disk.h>
+#include <dev/nand/nand_dev.h>
+#include "nandtool.h"
+
+int nand_read_oob(struct cmd_param *params)
+{
+	struct chip_param_io chip_params;
+	struct nand_oob_rw req;
+	char *dev, *out;
+	int fd = -1, fd_out = -1, ret = 0;
+	int page;
+	uint8_t *buf = NULL;
+
+	if ((page = param_get_int(params, "page")) < 0) {
+		fprintf(stderr, "You must supply valid 'page' argument.\n");
+		return (1);
+	}
+
+	if (!(dev = param_get_string(params, "dev"))) {
+		fprintf(stderr, "You must supply 'dev' argument.\n");
+		return (1);
+	}
+
+	if ((out = param_get_string(params, "out"))) {
+		if ((fd_out = open(out, O_WRONLY | O_CREAT)) == -1) {
+			perrorf("Cannot open %s", out);
+			ret = 1;
+			goto out;
+		}
+	}
+
+	if ((fd = g_open(dev, 1)) == -1) {
+		perrorf("Cannot open %s", dev);
+		ret = 1;
+		goto out;
+	}
+
+	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
+		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
+		ret = 1;
+		goto out;
+	}
+
+	buf = malloc(chip_params.oob_size);
+	if (buf == NULL) {
+		perrorf("Cannot allocate %d bytes\n", chip_params.oob_size);
+		ret = 1;
+		goto out;
+	}
+
+	req.page = page;
+	req.len = chip_params.oob_size;
+	req.data = buf;
+
+	if (ioctl(fd, NAND_IO_OOB_READ, &req) == -1) {
+		perrorf("Cannot read OOB from %s", dev);
+		ret = 1;
+		goto out;
+	}
+
+	if (fd_out != -1)
+		write(fd_out, buf, chip_params.oob_size);
+	else
+		hexdump(buf, chip_params.oob_size);
+
+out:
+	close(fd_out);
+
+	if (fd != -1)
+		g_close(fd);
+	if (buf)
+		free(buf);
+
+	return (ret);
+}
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nand_write.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nand_write.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,143 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nand_write.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libgeom.h>
+#include <sys/disk.h>
+#include <dev/nand/nand_dev.h>
+#include "nandtool.h"
+
+int nand_write(struct cmd_param *params)
+{
+	struct chip_param_io chip_params;
+	char *dev, *file;
+	int in_fd = -1, ret = 0, done = 0;
+	int fd, block_size, mult, pos, count;
+	uint8_t *buf = NULL;
+
+	if (!(dev = param_get_string(params, "dev"))) {
+		fprintf(stderr, "Please supply 'dev' argument.\n");
+		return (1);
+	}
+
+	if (!(file = param_get_string(params, "in"))) {
+		fprintf(stderr, "Please supply 'in' argument.\n");
+		return (1);
+	}
+
+	if ((fd = g_open(dev, 1)) == -1) {
+		perrorf("Cannot open %s", dev);
+		return (1);
+	}
+
+	if ((in_fd = open(file, O_RDONLY)) == -1) {
+		perrorf("Cannot open file %s", file);
+		ret = 1;
+		goto out;
+	}
+
+	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
+		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
+		ret = 1;
+		goto out;
+	}
+
+	block_size = chip_params.page_size * chip_params.pages_per_block;
+
+	if (param_has_value(params, "page")) {
+		pos = chip_params.page_size * param_get_int(params, "page");
+		mult = chip_params.page_size;
+	} else if (param_has_value(params, "block")) {
+		pos = block_size * param_get_int(params, "block");
+		mult = block_size;
+	} else if (param_has_value(params, "pos")) {
+		pos = param_get_int(params, "pos");
+		mult = 1;
+		if (pos % chip_params.page_size) {
+			fprintf(stderr, "Position must be page-size "
+			    "aligned!\n");
+			ret = 1;
+			goto out;
+		}
+	} else {
+		fprintf(stderr, "You must specify one of: 'block', 'page',"
+		    "'pos' arguments\n");
+		ret = 1;
+		goto out;
+	}
+
+	if (!(param_has_value(params, "count")))
+		count = mult;
+	else
+		count = param_get_int(params, "count") * mult;
+
+	if (!(buf = malloc(chip_params.page_size))) {
+		perrorf("Cannot allocate buffer [size %x]",
+		    chip_params.page_size);
+		ret = 1;
+		goto out;
+	}
+
+	lseek(fd, pos, SEEK_SET);
+
+	while (done < count) {
+		if ((ret = read(in_fd, buf, chip_params.page_size)) !=
+		    (int32_t)chip_params.page_size) {
+			if (ret > 0) {
+				/* End of file ahead, truncate here */
+				break;
+			} else {
+				perrorf("Cannot read from %s", file);
+				ret = 1;
+				goto out;
+			}
+		}
+
+		if ((ret = write(fd, buf, chip_params.page_size)) !=
+		    (int32_t)chip_params.page_size) {
+			ret = 1;
+			goto out;
+		}
+
+		done += ret;
+	}
+
+out:
+	g_close(fd);
+	if (in_fd != -1)
+		close(in_fd);
+	if (buf)
+		free(buf);
+
+	return (ret);
+}
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nand_writeoob.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nand_writeoob.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nand_writeoob.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libgeom.h>
+#include <sys/disk.h>
+#include <dev/nand/nand_dev.h>
+#include "nandtool.h"
+
+int nand_write_oob(struct cmd_param *params)
+{
+	struct chip_param_io chip_params;
+	struct nand_oob_rw req;
+	char *dev, *in;
+	int fd = -1, fd_in = -1, ret = 0;
+	uint8_t *buf = NULL;
+	int page;
+
+	if (!(dev = param_get_string(params, "dev"))) {
+		fprintf(stderr, "Please supply valid 'dev' parameter.\n");
+		return (1);
+	}
+
+	if (!(in = param_get_string(params, "in"))) {
+		fprintf(stderr, "Please supply valid 'in' parameter.\n");
+		return (1);
+	}
+
+	if ((page = param_get_int(params, "page")) < 0) {
+		fprintf(stderr, "Please supply valid 'page' parameter.\n");
+		return (1);
+	}
+
+	if ((fd = g_open(dev, 1)) == -1) {
+		perrorf("Cannot open %s", dev);
+		return (1);
+	}
+
+	if ((fd_in = open(in, O_RDONLY)) == -1) {
+		perrorf("Cannot open %s", in);
+		ret = 1;
+		goto out;
+	}
+
+	if (ioctl(fd, NAND_IO_GET_CHIP_PARAM, &chip_params) == -1) {
+		perrorf("Cannot ioctl(NAND_IO_GET_CHIP_PARAM)");
+		ret = 1;
+		goto out;
+	}
+
+	buf = malloc(chip_params.oob_size);
+	if (buf == NULL) {
+		perrorf("Cannot allocate %d bytes\n", chip_params.oob_size);
+		ret = 1;
+		goto out;
+	}
+
+	if (read(fd_in, buf, chip_params.oob_size) == -1) {
+		perrorf("Cannot read from %s", in);
+		ret = 1;
+		goto out;
+	}
+
+	req.page = page;
+	req.len = chip_params.oob_size;
+	req.data = buf;
+
+	if (ioctl(fd, NAND_IO_OOB_PROG, &req) == -1) {
+		perrorf("Cannot write OOB to %s", dev);
+		ret = 1;
+		goto out;
+	}
+
+out:
+	g_close(fd);
+	if (fd_in != -1)
+		close(fd_in);
+	if (buf)
+		free(buf);
+
+	return (ret);
+}
+
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nandtool.8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nandtool.8	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,184 @@
+.\" Copyright (c) 2010 Semihalf
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: head/usr.sbin/nandtool/nandtool.8 235544 2012-05-17 11:50:12Z joel $
+.\"
+.Dd April 10, 2012
+.Dt NANDTOOL 8
+.Os
+.Sh NAME
+.Nm nandtool
+.Nd NAND devices swiss army knife
+.Sh SYNOPSIS
+.Nm
+.Ar command
+.Op Ar operands ...
+.Sh DESCRIPTION
+The
+.Nm
+utility can be used to perform various operations on
+.Xr gnand 4
+devices (read, write, erase,
+read and write OOB area and to get info about NAND flash chip).
+.Pp
+The following commands are available:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm read Ns
+Read pages from NAND device.
+.It Cm write Ns
+Write pages to NAND device.
+.It Cm erase Ns
+Erase blocks.
+Requires offset aligned to block granularity.
+.It Cm info Ns
+Get information about NAND chip (page size, block size, OOB area size, chip size
+and media size)
+.It Cm readoob Ns
+Read OOB area from specified page.
+.It Cm writeoob Ns
+Write OOB area bound to specified page.
+.It Cm help Ns
+Get usage info.
+.El
+.Sh COMMAND read
+The following operands are available for
+.Nm
+.Cm read
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm dev Ns = Ns Ar <path>
+Path to a
+.Xr gnand 4
+device node, required for all operations.
+.It Cm out Ns = Ns Ar <file>
+Output file path. If not specified, page contents
+will be dumped to stdout in format similar to
+.Xr hexdump 1
+.It Cm page Ns = Ns Ar <n>
+Offset on device, expressed as page number.
+.It Cm block Ns = Ns Ar <n>
+Offset on device, expressed as block number.
+.It Cm pos Ns = Ns Ar <n>
+Offset on device, expressed in bytes (however, must be aligned
+to page granularity).
+.It Cm count Ns = Ns Ar <n>
+Count of objects (pages, blocks, bytes).
+.El
+.Sh COMMAND readoob
+The following operands are available for
+.Nm
+.Cm readoob
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm dev Ns = Ns Ar <path>
+Path to NAND device node.
+.It Cm page Ns = Ns Ar <n>
+Offset on device, expressed as page number.
+.It Cm out Ns = Ns Ar <file>
+Output file path, optional.
+.El
+.Sh COMMAND write
+The following operands are available for
+.Nm
+.Cm write
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm dev Ns = Ns Ar <path>
+Path to NAND device node.
+.It Cm page Ns = Ns Ar <n>
+Offset on device, expressed as page number.
+.It Cm block Ns = Ns Ar <n>
+Offset on device, expressed as block number.
+.It Cm pos Ns = Ns Ar <n>
+Offset on device, expressed in bytes (however, must be aligned
+to page granularity).
+.It Cm in Ns = Ns Ar <file>
+Input file path.
+.El
+.Sh COMMAND writeoob
+The following operands are available for
+.Nm
+.Cm writeoob
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm dev Ns = Ns Ar <path>
+Path to NAND device node.
+.It Cm page Ns = Ns Ar <n>
+Offset on device, expressed as page number.
+.It Cm in Ns = Ns Ar <file>
+Input file path.
+.El
+.Sh COMMAND erase
+The following operands are available for
+.Nm
+.Cm erase
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm dev Ns = Ns Ar <path>
+Path to NAND device node.
+.It Cm page Ns = Ns Ar <n>
+Offset on device, expressed as page number.
+.It Cm block Ns = Ns Ar <n>
+Offset on device, expressed as block number.
+.It Cm pos Ns = Ns Ar <n>
+Offset on device, epressed in bytes (however, must be aligned
+to block granularity).
+.It Cm count Ns = Ns Ar <n>
+Count of objects (pages, blocks, bytes).
+.El
+.Pp
+WARNING: The only required parameter for the \fBerase\fP command is
+.Ar dev .
+When no other arguments are provided the whole device is erased!
+.Sh COMMAND info
+There is only one operand available for
+.Nm
+.Cm info
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm dev Ns = Ns Ar <path>
+Path to NAND device node.
+.El
+.Sh COMMAND help
+There is only one operand available for
+.Nm
+.Cm help
+command:
+.Bl -tag -width ".Cm of Ns = Ns Ar file"
+.It Cm topic Ns = Ns Ar <name>
+Help topic.
+.El
+.Sh EXIT STATUS
+.Ex -std
+If the supplied argument
+.Ar dev
+points to a device node other than gnand<num> or gnand.raw<num> both
+.Nm
+.Cm readoob
+and
+.Nm
+.Cm writeoob
+return error.
+.Sh SEE ALSO
+.Xr gnand 4
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nandtool.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nandtool.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE 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>
+__FBSDID("$FreeBSD: head/usr.sbin/nandtool/nandtool.c 235537 2012-05-17 10:11:18Z gber $");
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sysexits.h>
+#include <libgeom.h>
+#include "nandtool.h"
+#include "usage.h"
+
+int usage(struct cmd_param *);
+
+static const struct {
+	const char	*name;
+	const char	*usage;
+	int		(*handler)(struct cmd_param *);
+} commands[] = {
+	{ "help", nand_help_usage, usage },
+	{ "read", nand_read_usage, nand_read },
+	{ "write", nand_write_usage, nand_write },
+	{ "erase", nand_erase_usage, nand_erase },
+	{ "readoob", nand_read_oob_usage, nand_read_oob },
+	{ "writeoob", nand_write_oob_usage, nand_write_oob },
+	{ "info", nand_info_usage, nand_info },
+	{ NULL, NULL, NULL },
+};
+
+static char *
+_param_get_stringx(struct cmd_param *params, const char *name, int doexit)
+{
+	int i;
+
+	for (i = 0; params[i].name[0] != '\0'; i++) {
+		if (!strcmp(params[i].name, name))
+			return params[i].value;
+	}
+
+	if (doexit) {
+		perrorf("Missing parameter %s", name);
+		exit(1);
+	}
+	return (NULL);
+}
+
+char *
+param_get_string(struct cmd_param *params, const char *name)
+{
+
+	return (_param_get_stringx(params, name, 0));
+}
+
+static int
+_param_get_intx(struct cmd_param *params, const char *name, int doexit)
+{
+	int ret;
+	char *str = _param_get_stringx(params, name, doexit);
+
+	if (!str)
+		return (-1);
+
+	errno = 0;
+	ret = (int)strtol(str, (char **)NULL, 10);
+	if (errno) {
+		if (doexit) {
+			perrorf("Invalid value for parameter %s", name);
+			exit(1);
+		}
+		return (-1);
+	}
+
+	return (ret);
+}
+
+int
+param_get_intx(struct cmd_param *params, const char *name)
+{
+
+	return (_param_get_intx(params, name, 1));
+}
+
+int
+param_get_int(struct cmd_param *params, const char *name)
+{
+
+	return (_param_get_intx(params, name, 0));
+}
+
+int
+param_get_boolean(struct cmd_param *params, const char *name)
+{
+	char *str = param_get_string(params, name);
+
+	if (!str)
+		return (0);
+
+	if (!strcmp(str, "true") || !strcmp(str, "yes"))
+		return (1);
+
+	return (0);
+}
+
+int
+param_has_value(struct cmd_param *params, const char *name)
+{
+	int i;
+
+	for (i = 0; params[i].name[0] != '\0'; i++) {
+		if (!strcmp(params[i].name, name))
+			return (1);
+	}
+
+	return (0);
+}
+
+int
+param_get_count(struct cmd_param *params)
+{
+	int i;
+
+	for (i = 0; params[i].name[0] != '\0'; i++);
+
+	return (i);
+}
+
+void
+hexdumpoffset(uint8_t *buf, int length, int off)
+{
+	int i, j;
+	for (i = 0; i < length; i += 16) {
+		printf("%08x: ", off + i);
+
+		for (j = 0; j < 16; j++)
+			printf("%02x ", buf[i+j]);
+
+		printf("| ");
+
+		for (j = 0; j < 16; j++) {
+			printf("%c", isalnum(buf[i+j])
+			    ? buf[i+j]
+			    : '.');
+		}
+
+		printf("\n");
+	}
+}
+
+void
+hexdump(uint8_t *buf, int length)
+{
+
+	hexdumpoffset(buf, length, 0);
+}
+
+void *
+xmalloc(size_t len)
+{
+	void *ret = malloc(len);
+
+	if (!ret) {
+		fprintf(stderr, "Cannot allocate buffer of %zd bytes. "
+		    "Exiting.\n", len);
+		exit(EX_OSERR);
+	}
+
+	return (ret);
+}
+
+void
+perrorf(const char *format, ...)
+{
+	va_list args;
+
+	va_start(args, format);
+	vfprintf(stderr, format, args);
+	va_end(args);
+	fprintf(stderr, ": %s\n", strerror(errno));
+}
+
+int
+usage(struct cmd_param *params)
+{
+	int i;
+
+	if (!params || !param_get_count(params)) {
+		fprintf(stderr, "Usage: nandtool <command> [arguments...]\n");
+		fprintf(stderr, "Arguments are in form 'name=value'.\n\n");
+		fprintf(stderr, "Available commands:\n");
+
+		for (i = 0; commands[i].name != NULL; i++)
+			fprintf(stderr, "\t%s\n", commands[i].name);
+
+		fprintf(stderr, "\n");
+		fprintf(stderr, "For information about particular command, "
+		    "type:\n");
+		fprintf(stderr, "'nandtool help topic=<command>'\n");
+	} else if (param_has_value(params, "topic")) {
+		for (i = 0; commands[i].name != NULL; i++) {
+			if (!strcmp(param_get_string(params, "topic"),
+			    commands[i].name)) {
+				fprintf(stderr, commands[i].usage, "nandtool");
+				return (0);
+			}
+		}
+
+		fprintf(stderr, "No such command\n");
+		return (EX_SOFTWARE);
+	} else {
+		fprintf(stderr, "Wrong arguments given. Try: 'nandtool help'\n");
+	}
+
+	return (EX_USAGE);
+}
+
+int
+main(int argc, const char *argv[])
+{
+	struct cmd_param *params;
+	int i, ret, idx;
+
+	if (argc < 2) {
+		usage(NULL);
+		return (0);
+	}
+
+	params = malloc(sizeof(struct cmd_param) * (argc - 1));
+
+	for (i = 2, idx = 0; i < argc; i++, idx++) {
+		if (sscanf(argv[i], "%63[^=]=%63s", params[idx].name,
+		    params[idx].value) < 2) {
+			fprintf(stderr, "Syntax error in argument %d. "
+			    "Argument should be in form 'name=value'.\n", i);
+			free(params);
+			return (-1);
+		}
+	}
+
+	params[idx].name[0] = '\0';
+	params[idx].value[0] = '\0';
+
+	for (i = 0; commands[i].name != NULL; i++) {
+		if (!strcmp(commands[i].name, argv[1])) {
+			ret = commands[i].handler(params);
+			free(params);
+			return (ret);
+		}
+	}
+
+	free(params);
+	fprintf(stderr, "Unknown command. Try '%s help'\n", argv[0]);
+
+	return (-1);
+}
+
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/nandtool.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/nandtool.h	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/usr.sbin/nandtool/nandtool.h 235537 2012-05-17 10:11:18Z gber $
+ */
+
+#ifndef	__UTILS_H
+#define	__UTILS_H
+
+struct cmd_param
+{
+	char	name[64];
+	char	value[64];
+};
+
+char *param_get_string(struct cmd_param *, const char *);
+int param_get_int(struct cmd_param *, const char *);
+int param_get_intx(struct cmd_param *, const char *);
+int param_get_boolean(struct cmd_param *, const char *);
+int param_has_value(struct cmd_param *, const char *);
+int param_get_count(struct cmd_param *);
+void perrorf(const char *, ...);
+void hexdumpoffset(uint8_t *, int, int);
+void hexdump(uint8_t *, int);
+void *xmalloc(size_t);
+
+/* Command handlers */
+int nand_read(struct cmd_param *);
+int nand_write(struct cmd_param *);
+int nand_read_oob(struct cmd_param *);
+int nand_write_oob(struct cmd_param *);
+int nand_erase(struct cmd_param *);
+int nand_info(struct cmd_param *);
+
+#endif	/* __UTILS_H */
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nandtool/usage.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/nandtool/usage.h	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 2010-2012 Semihalf.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: head/usr.sbin/nandtool/usage.h 235537 2012-05-17 10:11:18Z gber $
+ */
+
+#ifndef	__USAGE_H
+#define	__USAGE_H
+
+static const char nand_help_usage[] =
+	"Usage: %s help topic=<cmd>\n"
+	"\n"
+	"Arguments:\n"
+	"\tcmd\t- [help|read|write|erase|readoob|writeoob|info]\n"
+	"\n";
+
+static const char nand_read_usage[] =
+	"Usage: %s read dev=<gnand_device> (block|page|pos)=n [count=n]\n"
+	"\n"
+	"Arguments:\n"
+	"\tdev\t- path to gnand device node\n"
+	"\tblock\t- starting block or\n"
+	"\tpage\t- starting page or\n"
+	"\tpos\t- starting position (in bytes, must be page-aligned)\n"
+	"\tout\t- output file (hexdump to stdout if not supplied)\n"
+	"\n"
+	"Note that you can only specify only one of: 'block', 'page', 'pos'\n"
+	"parameters at once. 'count' parameter is meaningful in terms of used\n"
+	"unit (page, block or byte).\n";
+
+static const char nand_write_usage[] =
+	"Usage: %s write dev=<gnand_device> in=<file> (block|page|pos)=n [count=n]\n"
+	"\n"
+	"Arguments:\n"
+	"\tdev\t- path to gnand device node\n"
+	"\tin\t- path to input file which be writed to gnand\n"
+	"\tblock\t- starting block or\n"
+	"\tpage\t- starting page or\n"
+	"\tpos\t- starting position (in bytes, must be page-aligned)\n"
+	"\tcount\t- byte/page/block count\n"
+	"\n"
+	"";
+
+static const char nand_erase_usage[] =
+	"Usage: %s erase dev=<gnand_device> (block|page|pos)=n [count=n]\n"
+	"\n"
+	"Arguments:\n"
+	"\tdev\t- path to gnand device node\n"
+	"\tblock\t- starting block or\n"
+	"\tpage\t- starting page or\n"
+	"\tpos\t- starting position (in bytes, muse be block-aligned)\n"
+	"\tcount\t- byte/page/block count\n"
+	"\n"
+	"NOTE: position and count for erase operation MUST be block-aligned\n";
+
+static const char nand_read_oob_usage[] =
+	"Usage: %s readoob dev=<gnand_device> page=n [out=file] [count=n]\n"
+	"\n"
+	"Arguments:\n"
+	"\tdev\t- path to gnand device node\n"
+	"\tpage\t- page (page) number\n"
+	"\tout\t- outut file (hexdump to stdout if not supplied)\n"
+	"\tcount\t- page count (default is 1)\n"
+	"\n"
+	"If you supply count parameter with value other than 1, data will be\n"
+	"read from subsequent page's OOB areas\n";
+
+static const char nand_write_oob_usage[] =
+	"Usage: %s writeoob dev=<gnand_device> in=<file> page=n [count=n]\n"
+	"\n"
+	"\tdev\t- path to gnand device node\n"
+	"\tin\t- path to file containing data which will be written\n"
+	"\tpage\t- page (page) number\n"
+	"\n"
+	"If you supply count parameter with value other than 1, data will be\n"
+	"written to subsequent page's OOB areas\n";
+
+static const char nand_info_usage[] =
+	"Usage: %s info dev=<gnand_device>\n"
+	"\n"
+	"Arguments:\n"
+	"\tdev\t- path to gnand device node\n";
+
+static const char nand_stats_usage[] =
+	"Usage: %s stats dev=<gnand_device> (page|block)=<n>\n"
+	"\n"
+	"Arguments:\n"
+	"\tdev\t- path to gnand device node\n";
+
+#endif	/* __USAGE_H */
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ndiscvt/ndiscvt.8
--- a/head/usr.sbin/ndiscvt/ndiscvt.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ndiscvt/ndiscvt.8	Wed Jul 25 16:29:58 2012 +0300
@@ -28,7 +28,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/ndiscvt/ndiscvt.8 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd December 10, 2003
 .Dt NDISCVT 8
@@ -187,7 +187,7 @@
 the extra files can simply be copied to the
 .Pa /compat/ndis
 directory, and they will be loaded into the kernel on demand when the
-the driver needs them.
+driver needs them.
 .Pp
 If however the driver is required to bootstrap the system
 (i.e., if
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ndp/ndp.8
--- a/head/usr.sbin/ndp/ndp.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ndp/ndp.8	Wed Jul 25 16:29:58 2012 +0300
@@ -27,9 +27,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/ndp/ndp.8 238273 2012-07-09 06:21:46Z hrs $
 .\"
-.Dd September 2, 2009
+.Dd July 9, 2012
 .Dt NDP 8
 .Os
 .\"
@@ -192,15 +192,6 @@
 This flag is set by
 .Va net.inet6.ip6.auto_linklocal
 sysctl variable.
-.It Ic prefer_source
-Prefer addresses on the
-.Ar interface
-as candidates of the source address for outgoing packets.
-The default value of this flag is off.
-For more details about the entire algorithm of source address
-selection, see the
-.Pa IMPLEMENTATION
-file supplied with the KAME kit.
 .It Ic disabled
 Disable IPv6 operation on the interface.
 When disabled, the interface discards any IPv6 packets
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ndp/ndp.c
--- a/head/usr.sbin/ndp/ndp.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ndp/ndp.c	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-/*	$FreeBSD$	*/
+/*	$FreeBSD: head/usr.sbin/ndp/ndp.c 238273 2012-07-09 06:21:46Z hrs $	*/
 /*	$KAME: ndp.c,v 1.104 2003/06/27 07:48:39 itojun Exp $	*/
 
 /*
@@ -1008,9 +1008,6 @@
 #ifdef ND6_IFF_AUTO_LINKLOCAL
 		SETFLAG("auto_linklocal", ND6_IFF_AUTO_LINKLOCAL);
 #endif
-#ifdef ND6_IFF_PREFER_SOURCE
-		SETFLAG("prefer_source", ND6_IFF_PREFER_SOURCE);
-#endif
 		SETVALUE("basereachable", ND.basereachable);
 		SETVALUE("retrans", ND.retrans);
 		SETVALUE("curhlim", ND.chlim);
@@ -1084,10 +1081,6 @@
 		if ((ND.flags & ND6_IFF_AUTO_LINKLOCAL))
 			printf("auto_linklocal ");
 #endif
-#ifdef ND6_IFF_PREFER_SOURCE
-		if ((ND.flags & ND6_IFF_PREFER_SOURCE))
-			printf("prefer_source ");
-#endif
 	}
 	putc('\n', stdout);
 #undef ND
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/newsyslog/newsyslog.8
--- a/head/usr.sbin/newsyslog/newsyslog.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/newsyslog/newsyslog.8	Wed Jul 25 16:29:58 2012 +0300
@@ -1,7 +1,7 @@
 .\" This file contains changes from the Open Software Foundation.
 .\"
 .\"	from: @(#)newsyslog.8
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/newsyslog/newsyslog.8 236509 2012-06-03 11:29:48Z joel $
 .\"
 .\" Copyright 1988, 1989 by the Massachusetts Institute of Technology
 .\"
@@ -166,7 +166,7 @@
 If the
 .Ar timefmt
 string is changed the old files created using the previous time format
-will not be be automatically removed (unless the new format is very
+will not be automatically removed (unless the new format is very
 similar to the old format).
 This is also the case when changing from sequential filenames to time
 based file names, and the other way around.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/newsyslog/newsyslog.c
--- a/head/usr.sbin/newsyslog/newsyslog.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/newsyslog/newsyslog.c	Wed Jul 25 16:29:58 2012 +0300
@@ -54,7 +54,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/newsyslog/newsyslog.c 233257 2012-03-21 06:51:45Z glebius $");
+__FBSDID("$FreeBSD: head/usr.sbin/newsyslog/newsyslog.c 238281 2012-07-09 07:37:10Z ae $");
 
 #define	OSF
 
@@ -1451,7 +1451,7 @@
 delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
 {
 	char *logfname, *s, *dir, errbuf[80];
-	int dirfd, i, logcnt, max_logcnt, valid;
+	int dir_fd, i, logcnt, max_logcnt, valid;
 	struct oldlog_entry *oldlogs;
 	size_t logfname_len;
 	struct dirent *dp;
@@ -1486,7 +1486,7 @@
 	/* First we create a 'list' of all archived logfiles */
 	if ((dirp = opendir(dir)) == NULL)
 		err(1, "Cannot open log directory '%s'", dir);
-	dirfd = dirfd(dirp);
+	dir_fd = dirfd(dirp);
 	while ((dp = readdir(dirp)) != NULL) {
 		if (dp->d_type != DT_REG)
 			continue;
@@ -1578,7 +1578,7 @@
 			if (noaction)
 				printf("\trm -f %s/%s\n", dir,
 				    oldlogs[i].fname);
-			else if (unlinkat(dirfd, oldlogs[i].fname, 0) != 0) {
+			else if (unlinkat(dir_fd, oldlogs[i].fname, 0) != 0) {
 				snprintf(errbuf, sizeof(errbuf),
 				    "Could not delet old logfile '%s'",
 				    oldlogs[i].fname);
@@ -1972,7 +1972,8 @@
 	else
 		pgm_name++;
 
-	if (zwork->zw_swork != NULL && zwork->zw_swork->sw_pidok <= 0) {
+	if (zwork->zw_swork != NULL && zwork->zw_swork->run_cmd == 0 &&
+	    zwork->zw_swork->sw_pidok <= 0) {
 		warnx(
 		    "log %s not compressed because daemon(s) not notified",
 		    zwork->zw_fname);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/newsyslog/newsyslog.conf.5
--- a/head/usr.sbin/newsyslog/newsyslog.conf.5	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/newsyslog/newsyslog.conf.5	Wed Jul 25 16:29:58 2012 +0300
@@ -5,7 +5,7 @@
 .\" This file contains changes from the Open Software Foundation.
 .\"
 .\"     from: @(#)newsyslog.8
-.\" $FreeBSD: head/usr.sbin/newsyslog/newsyslog.conf.5 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/newsyslog/newsyslog.conf.5 236805 2012-06-09 09:54:07Z joel $
 .\"
 .\" Copyright 1988, 1989 by the Massachusetts Institute of Technology
 .\"
@@ -155,12 +155,17 @@
 .Tn ISO 8601
 is:
 .Sm off
+.Oo Oo Oo Oo Oo
+.Va cc Oc
+.Va yy Oc
+.Va mm Oc
+.Va dd Oc
 .Oo
-.Op Oo Oo Oo Va cc Oc Va yy Oc Va mm Oc Va dd
-.Oo
-.Li T
-.Op Va hh Oo Va mm Oo Va ss Oc Oc Oc
-.Oc .
+.Li T Oo
+.Va hh Oo
+.Va mm Oo
+.Va ss
+.Oc Oc Oc Oc Oc .
 .Sm on
 Optional date fields default to the appropriate component of the
 current date; optional time fields default to midnight; hence if today
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nfsd/nfsv4.4
--- a/head/usr.sbin/nfsd/nfsv4.4	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nfsd/nfsv4.4	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/nfsd/nfsv4.4 233455 2012-03-25 09:18:34Z joel $
+.\" $FreeBSD: head/usr.sbin/nfsd/nfsv4.4 235317 2012-05-12 03:25:46Z gjb $
 .\"
 .Dd May 15, 2011
 .Dt NFSV4 4
@@ -299,7 +299,7 @@
 .Xr nfsd 8 ,
 .Xr nfsdumpstate 8 ,
 .Xr nfsrevoke 8 ,
-.Xr nfsuserd 8 ,
+.Xr nfsuserd 8
 .Sh BUGS
 At this time, there is no recall of delegations for local file system
 operations.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nscd/cachelib.c
--- a/head/usr.sbin/nscd/cachelib.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nscd/cachelib.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/nscd/cachelib.c 238094 2012-07-04 09:02:12Z se $");
 
 #include <sys/time.h>
 
@@ -726,6 +726,12 @@
 		TRACE_OUT(cache_read);
 		return (-1);
 	}
+	/* pretend that entry was not found if confidence is below threshold*/
+	if (find_res->confidence < 
+	    common_entry->common_params.confidence_threshold) {
+		TRACE_OUT(cache_read);
+		return (-1);
+	}
 
 	if ((common_entry->common_params.max_lifetime.tv_sec != 0) ||
 		(common_entry->common_params.max_lifetime.tv_usec != 0)) {
@@ -826,6 +832,24 @@
 	item = HASHTABLE_GET_ENTRY(&(common_entry->items), hash);
 	find_res = HASHTABLE_ENTRY_FIND(cache_ht_, item, &item_data);
 	if (find_res != NULL) {
+		if (find_res->confidence < common_entry->common_params.confidence_threshold) {
+		  	/* duplicate entry is no error, if confidence is low */
+			if ((find_res->value_size == value_size) &&
+			    (memcmp(find_res->value, value, value_size) == 0)) {
+				/* increase confidence on exact match (key and values) */
+				find_res->confidence++;
+			} else {
+				/* create new entry with low confidence, if value changed */
+				free(item_data.value);
+				item_data.value = malloc(value_size);
+				assert(item_data.value != NULL);
+				memcpy(item_data.value, value, value_size);
+				item_data.value_size = value_size;
+				find_res->confidence = 1;
+			}
+			TRACE_OUT(cache_write);
+			return (0);
+		}
 		TRACE_OUT(cache_write);
 		return (-1);
 	}
@@ -839,6 +863,8 @@
 	memcpy(item_data.value, value, value_size);
 	item_data.value_size = value_size;
 
+	item_data.confidence = 1;
+
 	policy_item = common_entry->policies[0]->create_item_func();
 	policy_item->key = item_data.key;
 	policy_item->key_size = item_data.key_size;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nscd/cachelib.h
--- a/head/usr.sbin/nscd/cachelib.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nscd/cachelib.h	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/nscd/cachelib.h 238094 2012-07-04 09:02:12Z se $
  */
 
 #ifndef __NSCD_CACHELIB_H__
@@ -92,6 +92,7 @@
 	size_t	satisf_elemsize;	/* if entry size is exceeded,
 					 * this number of elements will be left,
 					 * others will be deleted */
+	int	confidence_threshold;	/* number matching replies required */
 	struct timeval	max_lifetime;	/* if 0 then no check is made */
 	enum cache_policy_t policy;	/* policy used for transformations */
 };
@@ -116,6 +117,7 @@
 	size_t	value_size;
 
 	struct cache_policy_item_ *fifo_policy_item;
+	int	confidence;	/* incremented for each verification */
 };
 
 struct cache_ht_item_ {
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nscd/config.c
--- a/head/usr.sbin/nscd/config.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nscd/config.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/nscd/config.c 238094 2012-07-04 09:02:12Z se $");
 
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -209,6 +209,7 @@
 	positive_params.max_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE;
 	positive_params.satisf_elemsize = DEFAULT_POSITIVE_ELEMENTS_SIZE / 2;
 	positive_params.max_lifetime.tv_sec = DEFAULT_POSITIVE_LIFETIME;
+	positive_params.confidence_threshold = DEFAULT_POSITIVE_CONF_THRESH;
 	positive_params.policy = CPT_LRU;
 
 	memcpy(&negative_params, &positive_params,
@@ -216,6 +217,7 @@
 	negative_params.max_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE;
 	negative_params.satisf_elemsize = DEFAULT_NEGATIVE_ELEMENTS_SIZE / 2;
 	negative_params.max_lifetime.tv_sec = DEFAULT_NEGATIVE_LIFETIME;
+	negative_params.confidence_threshold = DEFAULT_NEGATIVE_CONF_THRESH;
 	negative_params.policy = CPT_FIFO;
 
 	memset(&default_common_timeout, 0, sizeof(struct timeval));
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nscd/config.h
--- a/head/usr.sbin/nscd/config.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nscd/config.h	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/nscd/config.h 238094 2012-07-04 09:02:12Z se $
  */
 
 #ifndef __NSCD_CONFIG_H__
@@ -44,9 +44,11 @@
 
 #define DEFAULT_POSITIVE_ELEMENTS_SIZE	(2048)
 #define DEFAULT_POSITIVE_LIFETIME 	(3600)
+#define DEFAULT_POSITIVE_CONF_THRESH 	(1)
 
 #define DEFAULT_NEGATIVE_ELEMENTS_SIZE	(2048)
 #define DEFAULT_NEGATIVE_LIFETIME	(60)
+#define DEFAULT_NEGATIVE_CONF_THRESH 	(1) /* (2) ??? */
 
 #define DEFAULT_MULTIPART_ELEMENTS_SIZE	(1024 * 8)
 #define DEFAULT_MULITPART_SESSIONS_SIZE	(1024)
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nscd/nscd.conf.5
--- a/head/usr.sbin/nscd/nscd.conf.5	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nscd/nscd.conf.5	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/nscd/nscd.conf.5 238095 2012-07-04 10:17:02Z joel $
 .\"
 .Dd April 30, 2006
 .Dt NSCD.CONF 5
@@ -102,6 +102,17 @@
 elements of the given
 .Ar cachename .
 The default policy is fifo.
+.It Va negative-confidence-threshold Oo Ar cachename Oc Op Ar value
+The number of times a query must have failed before the cache accepts
+that the element can not be found.
+At the default value of 1 each negative query result is cached and
+immediately returned from the cache on further queries.
+Higher numbers cause queries to be retried at the configured data
+sources the given number of times, before the negative result is
+returned from the cache on further queries.
+This allows to probe for the existence of an entry, and then to create
+it if it did not exist, without the negative probe result preventing
+access to the new entry for the duration of the negative TTL.
 .It Va suggested-size Oo Ar cachename Oc Op Ar value
 This is the internal hash table size.
 The value should be a prime number for optimum performance.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/nscd/parser.c
--- a/head/usr.sbin/nscd/parser.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/nscd/parser.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/usr.sbin/nscd/parser.c 238094 2012-07-04 09:02:12Z se $");
 
 #include <sys/time.h>
 
@@ -167,6 +167,38 @@
 	TRACE_OUT(set_negative_time_to_live);
 }
 
+static void
+set_positive_confidence_threshold(struct configuration *config,
+	const char *entry_name, int conf_thresh)
+{
+	struct configuration_entry *entry;
+
+	TRACE_IN(set_positive_conf_thresh);
+	assert(conf_thresh > 0);
+	assert(entry_name != NULL);
+
+	entry = find_create_entry(config, entry_name);
+	assert(entry != NULL);
+	entry->positive_cache_params.confidence_threshold = conf_thresh;
+
+	TRACE_OUT(set_positive_conf_thresh);
+}
+
+static void
+set_negative_confidence_threshold(struct configuration *config,
+	const char *entry_name, int conf_thresh)
+{
+	struct configuration_entry *entry;
+
+	TRACE_IN(set_negative_conf_thresh);
+	assert(conf_thresh > 0);
+	assert(entry_name != NULL);
+	entry = find_create_entry(config, entry_name);
+	assert(entry != NULL);
+	entry->negative_cache_params.confidence_threshold = conf_thresh;
+	TRACE_OUT(set_negative_conf_thresh);
+}
+
 /*
  * Hot count is actually the elements size limit.
  */
@@ -393,6 +425,12 @@
 					fields[1], value);
 				continue;
 			} else if ((field_count == 3) &&
+			(strcmp(fields[0], "positive-confidence-threshold") == 0) &&
+			((value = get_number(fields[2], 1, -1)) != -1)) {
+				set_positive_confidence_threshold(config,
+					fields[1], value);
+				continue;
+			} else if ((field_count == 3) &&
 			(strcmp(fields[0], "positive-policy") == 0) &&
 			(check_cachename(fields[1]) == 0) &&
 			((value = get_policy(fields[2])) != -1)) {
@@ -416,6 +454,12 @@
 					fields[1], value);
 				continue;
 			} else if ((field_count == 3) &&
+			(strcmp(fields[0], "negative-confidence-threshold") == 0) &&
+			((value = get_number(fields[2], 1, -1)) != -1)) {
+				set_negative_confidence_threshold(config,
+					fields[1], value);
+				continue;
+			} else if ((field_count == 3) &&
 			(strcmp(fields[0], "negative-policy") == 0) &&
 			(check_cachename(fields[1]) == 0) &&
 			((value = get_policy(fields[2])) != -1)) {
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ntp/doc/ntp.conf.5
--- a/head/usr.sbin/ntp/doc/ntp.conf.5	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ntp/doc/ntp.conf.5	Wed Jul 25 16:29:58 2012 +0300
@@ -1,5 +1,5 @@
 .\"
-.\" $FreeBSD: head/usr.sbin/ntp/doc/ntp.conf.5 228990 2011-12-30 10:58:14Z uqs $
+.\" $FreeBSD: head/usr.sbin/ntp/doc/ntp.conf.5 235337 2012-05-12 15:08:22Z gjb $
 .\"
 .Dd December 21, 2006
 .Dt NTP.CONF 5
@@ -268,7 +268,7 @@
 All packets sent to and received from the server or peer are to
 include authentication fields encrypted using the autokey scheme
 described in
-.Sx Authentication Options .
+.Sx Authentication Commands .
 .It Cm burst
 when the server is reachable, send a burst of eight packets
 instead of the usual one.
@@ -305,7 +305,7 @@
 .It Cm minpoll Ar minpoll
 .It Cm maxpoll Ar maxpoll
 These options specify the minimum and maximum poll intervals
-for NTP messages, as a power of 2 in seconds
+for NTP messages, as a power of 2 in seconds.
 The maximum poll
 interval defaults to 10 (1,024 s), but can be increased by the
 .Cm maxpoll
@@ -363,7 +363,7 @@
 to avoid accidental or malicious disruption in this mode, both the
 server and client should operate using symmetric-key or public-key
 authentication as described in
-.Sx Authentication Options .
+.Sx Authentication Commands .
 .It Ic manycastserver Ar address ...
 This command enables reception of manycast client messages to
 the multicast group address(es) (type m) specified.
@@ -376,7 +376,7 @@
 accidental or malicious disruption in this mode, both the server
 and client should operate using symmetric-key or public-key
 authentication as described in
-.Sx Authentication Options .
+.Sx Authentication Commands .
 .It Ic multicastclient Ar address ...
 This command enables reception of multicast server messages to
 the multicast group address(es) (type m) specified.
@@ -389,7 +389,7 @@
 in order to avoid accidental or malicious disruption in this mode,
 both the server and client should operate using symmetric-key or
 public-key authentication as described in
-.Sx Authentication Options .
+.Sx Authentication Commands .
 .El
 .Sh Authentication Support
 Authentication support allows the NTP client to verify that the
@@ -466,7 +466,7 @@
 Furthermore, the Autokey scheme requires a
 preliminary protocol exchange to obtain
 the server certificate, verify its
-credentials and initialize the protocol
+credentials and initialize the protocol.
 .Pp
 The
 .Cm auth
@@ -669,7 +669,7 @@
 all of which are bound together by the protocol specifically
 to deflect masquerade attacks.
 For this reason Autokey
-includes the source and destinatino IP addresses in message digest
+includes the source and destination IP addresses in message digest
 computations and so the same addresses must be available
 at both the server and client.
 For this reason operation
@@ -796,7 +796,7 @@
 a subject key identifier or a issuer key identifier field;
 however, an extended key usage field for a trusted host must
 contain the value
-.Cm trustRoot ; .
+.Cm trustRoot .
 Other extension fields are ignored.
 .Ss Authentication Commands
 .Bl -tag -width indent
@@ -1068,10 +1068,11 @@
 The first two fields show the date (Modified Julian Day) and time
 (seconds and fraction past UTC midnight).
 The next field shows the peer
-address in dotted-quad notation, The final message field includes the
+address in dotted-quad notation.
+The final message field includes the
 message type and certain ancillary information.
 See the
-.Sx Authentication Options
+.Sx Authentication Commands
 section for further information.
 .It Cm loopstats
 Enables recording of loop filter statistics information.
@@ -1155,7 +1156,7 @@
 .It Packets received Cm 81965
 Total number of packets received.
 .It Packets processed Cm 0
-Number of packets received in response to previous packets sent
+Number of packets received in response to previous packets sent.
 .It Current version Cm 9546
 Number of packets matching the current NTP version.
 .It Previous version Cm 56
@@ -1461,7 +1462,7 @@
 spacing, while the
 .Cm minimum
 subcommand specifies the minimum packet spacing.
-Packets that violate these minima are discarded
+Packets that violate these minimum are discarded
 and a kiss-o'-death packet returned if enabled.
 The default
 minimum average and minimum are 5 and 2, respectively.
@@ -1775,7 +1776,7 @@
 servers which can be found by manycast client associations.
 Because manycast servers respond only when the client
 stratum is equal to or greater than the server stratum,
-primary (stratum 1) servers fill find only primary servers
+primary (stratum 1) servers will find only primary servers
 in TTL range, which is probably the most common objective.
 However, unless configured otherwise, all manycast clients
 in TTL range will eventually find all primary servers
@@ -1955,7 +1956,7 @@
 This value defaults to 1, but can be changed
 to any number from 1 to 15.
 .It Cm minclock Ar minclock
-The clustering algorithm repeatedly casts out outlyer
+The clustering algorithm repeatedly casts out outerlayer
 associations until no more than
 .Cm minclock
 associations remain.
@@ -1965,7 +1966,7 @@
 .It Cm minsane Ar minsane
 This is the minimum number of candidates available
 to the clock selection algorithm in order to produce
-one or more truechimers for the clustering algorithm.
+one or more true chimers for the clustering algorithm.
 If fewer than this number are available, the clock is
 undisciplined and allowed to run free.
 The default is 1
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh 232901 2012-03-12 21:41:29Z jpaetzel $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh 235006 2012-05-04 15:36:51Z jpaetzel $
 
 # Functions related to disk operations using bsdlabel
 
@@ -50,41 +50,39 @@
   ACTIVEDEV="${1}"
   LINE="${2}"
 
-  echo $LINE | cut -d ' ' -f 4 | grep -q ' (' 2>/dev/null
+  echo $LINE | cut -d ' ' -f 4 | grep -q '(' 2>/dev/null
+  if [ $? -ne 0 ] ; then return ; fi
+
+  # See if we are looking for ZFS specific options
+  echo $LINE | grep -q '^ZFS' 2>/dev/null
   if [ $? -eq 0 ] ; then
+    ZTYPE="NONE"
+    ZFSVARS="`echo $LINE | cut -d ' ' -f 4-20 |cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
 
-    # See if we are looking for ZFS specific options
-    echo $LINE | grep -q '^ZFS' 2>/dev/null
+    echo $ZFSVARS | grep -qE "^(disk|file|mirror|raidz(1|2|3)?|spare|log|cache):" 2>/dev/null
     if [ $? -eq 0 ] ; then
-      ZTYPE="NONE"
-      ZFSVARS="`echo $LINE | cut -d ' ' -f 4 |cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
-
-      echo $ZFSVARS | grep -qE "^(disk|file|mirror|raidz(1|2|3)?|spare|log|cache):" 2>/dev/null
-	  if [ $? -eq 0 ] ; then
        ZTYPE=`echo $ZFSVARS | cut -f1 -d:`
        ZFSVARS=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"`
-	  fi
-
-      # Return the ZFS options
-      if [ "${ZTYPE}" = "NONE" ] ; then
-        VAR="${ACTIVEDEV} ${ZFSVARS}"
-      else
-        VAR="${ZTYPE} ${ACTIVEDEV} ${ZFSVARS}"
-      fi
-      export VAR
-      return
-    fi # End of ZFS block
-
-    # See if we are looking for UFS specific newfs options
-    echo $LINE | grep -q '^UFS' 2>/dev/null
-    if [ $? -eq 0 ] ; then
-      FSVARS="`echo $LINE | cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
-      VAR="${FSVARS}"
-      export VAR
-      return
     fi
 
-  fi # End of xtra-options block
+    # Return the ZFS options
+    if [ "${ZTYPE}" = "NONE" ] ; then
+      VAR="${ACTIVEDEV} ${ZFSVARS}"
+    else
+      VAR="${ZTYPE} ${ACTIVEDEV} ${ZFSVARS}"
+    fi
+    export VAR
+    return
+  fi # End of ZFS block
+
+  # See if we are looking for UFS specific newfs options
+  echo $LINE | grep -q '^UFS' 2>/dev/null
+  if [ $? -eq 0 ] ; then
+    FSVARS="`echo $LINE | cut -d '(' -f 2- | cut -d ')' -f 1 | xargs`"
+    VAR="${FSVARS}"
+    export VAR
+    return
+  fi
 
   # If we got here, set VAR to empty and export
   export VAR=""
@@ -96,8 +94,10 @@
 {
   _nZFS=""
 
+  ZTYPE="`echo ${1} | awk '{print $1}'`"
+
   # Using mirroring, setup boot partitions on each disk
-  _mirrline="`echo ${1} | sed 's|mirror ||g'`"
+  _mirrline="`echo ${1} | sed 's|mirror ||g' | sed 's|raidz1 ||g' | sed 's|raidz2 ||g' | sed 's|raidz3 ||g' | sed 's|raidz ||g'`"
   for _zvars in $_mirrline
   do
     echo "Looping through _zvars: $_zvars" >>${LOGOUT}
@@ -107,15 +107,16 @@
 
     is_disk "$_zvars" >/dev/null 2>/dev/null
     if [ $? -eq 0 ] ; then
-      echo "Setting up ZFS mirror disk $_zvars" >>${LOGOUT}
+      echo "Setting up ZFS disk $_zvars" >>${LOGOUT}
       init_gpt_full_disk "$_zvars" >/dev/null 2>/dev/null
-      rc_halt "gpart add -t freebsd-zfs ${_zvars}" >/dev/null 2>/dev/null
+      rc_halt "gpart add -a 4k -t freebsd-zfs ${_zvars}" >/dev/null 2>/dev/null
+      rc_halt "gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ${_zvars}" >/dev/null 2>/dev/null
       _nZFS="$_nZFS ${_zvars}p2"	
     else
       _nZFS="$_nZFS ${_zvars}"	
     fi	
   done
-  echo "mirror $2 `echo $_nZFS | tr -s ' '`"
+  echo "$ZTYPE $2 `echo $_nZFS | tr -s ' '`"
 } ;
 
 # Function which creates a unique label name for the specified mount
@@ -176,6 +177,8 @@
   # Lets read in the config file now and setup our partitions
   if [ "${_pType}" = "gpt" ] ; then
     CURPART="2"
+  elif [ "${_pType}" = "apm" ] ; then
+    CURPART="3"
   else
     PARTLETTER="a"
     CURPART="1"
@@ -254,6 +257,9 @@
         if [ "${CURPART}" = "2" -a "$_pType" = "gpt" ] ; then
           export FOUNDROOT="0"
         fi
+        if [ "${CURPART}" = "3" -a "$_pType" = "apm" ] ; then
+          export FOUNDROOT="0"
+        fi
         if [ "${CURPART}" = "1" -a "$_pType" = "mbr" ] ; then
           export FOUNDROOT="0"
         fi
@@ -268,6 +274,9 @@
         if [ "${CURPART}" != "2" -a "${_pType}" = "gpt" ] ; then
             exit_err "/boot partition must be first partition"
         fi
+        if [ "${CURPART}" != "3" -a "${_pType}" = "apm" ] ; then
+            exit_err "/boot partition must be first partition"
+        fi
         if [ "${CURPART}" != "1" -a "${_pType}" = "mbr" ] ; then
             exit_err "/boot partition must be first partition"
         fi
@@ -287,18 +296,22 @@
       # Get any extra options for this fs / line
       if [ "${_pType}" = "gpt" ] ; then
         get_fs_line_xvars "${_pDisk}p${CURPART}" "${STRING}"
+      elif [ "${_pType}" = "apm" ] ; then
+        get_fs_line_xvars "${_pDisk}s${CURPART}" "${STRING}"
       else
         get_fs_line_xvars "${_wSlice}${PARTLETTER}" "${STRING}"
       fi
-      XTRAOPTS="${VAR}"
+      XTRAOPTS="$VAR"
 
       # Check if using zfs mirror
-      echo ${XTRAOPTS} | grep -q "mirror" 2>/dev/null
+      echo ${XTRAOPTS} | grep -q -e "mirror" -e "raidz"
       if [ $? -eq 0 -a "$FS" = "ZFS" ] ; then
         if [ "${_pType}" = "gpt" -o "${_pType}" = "gptslice" ] ; then
        	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_pDisk}p${CURPART}")
+        elif [ "${_pType}" = "apm" ] ; then
+       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_pDisk}s${CURPART}")
         else
-       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_wSlice}")
+       	  XTRAOPTS=$(setup_zfs_mirror_parts "$XTRAOPTS" "${_wSlice}${PARTLETTER}")
         fi
       fi
 
@@ -322,6 +335,9 @@
       elif [ "${_pType}" = "gptslice" ]; then
         sleep 2
         rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_wSlice}"
+      elif [ "${_pType}" = "apm" ]; then
+        sleep 2
+        rc_halt "gpart add ${SOUT} -t ${PARTYPE} ${_pDisk}"
       else
         sleep 2
         rc_halt "gpart add ${SOUT} -t ${PARTYPE} -i ${CURPART} ${_wSlice}"
@@ -351,6 +367,18 @@
         if [ -n "${ENCPASS}" ] ; then
           echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}p${CURPART}-encpass
         fi
+      elif [ "${_pType}" = "apm" ] ; then
+	_dFile="`echo $_pDisk | sed 's|/|-|g'`"
+        echo "${FS}#${MNT}#${ENC}#${PLABEL}#GPT#${XTRAOPTS}" >${PARTDIR}/${_dFile}s${CURPART}
+
+        # Clear out any headers
+        sleep 2
+        dd if=/dev/zero of=${_pDisk}s${CURPART} count=2048 2>/dev/null
+
+        # If we have a enc password, save it as well
+        if [ -n "${ENCPASS}" ] ; then
+          echo "${ENCPASS}" >${PARTDIR}-enc/${_dFile}s${CURPART}-encpass
+        fi
       else
 	# MBR Partition or GPT slice
 	_dFile="`echo $_wSlice | sed 's|/|-|g'`"
@@ -367,9 +395,10 @@
 
 
       # Increment our parts counter
-      if [ "$_pType" = "gpt" ] ; then 
+      if [ "$_pType" = "gpt" -o "$_pType" = "apm" ] ; then 
           CURPART=$((CURPART+1))
-        # If this is a gpt partition, we can continue and skip the MBR part letter stuff
+        # If this is a gpt/apm partition, 
+        # we can continue and skip the MBR part letter stuff
         continue
       else
           CURPART=$((CURPART+1))
@@ -436,6 +465,9 @@
   if [ "$type" = "mbr" ] ; then
     wrkslice="${diskid}s${slicenum}"
   fi
+  if [ "$type" = "apm" ] ; then
+    wrkslice="${diskid}s${slicenum}"
+  fi
   if [ "$type" = "gpt" -o "$type" = "gptslice" ] ; then
     wrkslice="${diskid}p${slicenum}"
   fi
@@ -473,6 +505,9 @@
     if [ "$type" = "gpt" -a ! -e "${disk}p${pnum}" ] ; then
       exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
     fi
+    if [ "$type" = "apm" -a ! -e "${disk}s${pnum}" ] ; then
+      exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
+    fi
     if [ "$type" = "gptslice" -a ! -e "${disk}p${pnum}" ] ; then
       exit_err "ERROR: The partition ${i} doesn't exist! gpart failure!"
     fi
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions-disk.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions-disk.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions-disk.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-disk.sh 232901 2012-03-12 21:41:29Z jpaetzel $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-disk.sh 235452 2012-05-14 18:03:59Z jpaetzel $
 
 # Functions related to disk operations using gpart
 
@@ -464,6 +464,12 @@
       # Found our flag to commit this disk setup / lets do sanity check and do it
       if [ ! -z "${DISK}" -a ! -z "${PTYPE}" ]
       then
+	# Make sure we are only installing ppc to full disk
+	if [ `uname -m` = "powerpc" -o `uname -m` = "powerpc64" ]; then
+	  if [ "$PTYPE" != "all" ] ; then
+	    exit_err "powerpc can only be installed to a full disk"
+	  fi
+	fi
 
         case ${PTYPE} in
           all)
@@ -488,6 +494,12 @@
               tmpSLICE="${DISK}p1"  
             fi
 
+	    if [ `uname -m` = "powerpc" -o `uname -m` = "powerpc64" ]
+	    then
+              PSCHEME="APM"
+              tmpSLICE="${DISK}s1"  
+	    fi
+
             run_gpart_full "${DISK}" "${BMANAGER}" "${PSCHEME}"
             ;;
 
@@ -597,6 +609,30 @@
   rc_nohalt "dd if=/dev/zero of=${1} bs=1m oseek=`diskinfo ${1} | awk '{print int($3 / (1024*1024)) - 4;}'`"
 } ;
 
+# Function which runs gpart and creates a single large APM partition scheme
+init_apm_full_disk()
+{
+  _intDISK=$1
+ 
+  # Set our sysctl so we can overwrite any geom using drives
+  sysctl kern.geom.debugflags=16 >>${LOGOUT} 2>>${LOGOUT}
+
+  # Stop any journaling
+  stop_gjournal "${_intDISK}"
+
+  # Remove any existing partitions
+  delete_all_gpart "${_intDISK}"
+
+  sleep 2
+
+  echo_log "Running gpart on ${_intDISK}"
+  rc_halt "gpart create -s APM ${_intDISK}"
+  rc_halt "gpart add -s 800k -t freebsd-boot ${_intDISK}"
+  
+  echo_log "Stamping boot sector on ${_intDISK}"
+  rc_halt "gpart bootcode -p /boot/boot1.hfs -i 1 ${_intDISK}"
+
+}
 
 # Function which runs gpart and creates a single large GPT partition scheme
 init_gpt_full_disk()
@@ -653,6 +689,9 @@
   echo_log "Cleaning up ${_intDISK}s1"
   rc_halt "dd if=/dev/zero of=${_intDISK}s1 count=1024"
   
+  # Make the partition active
+  rc_halt "gpart set -a active -i 1 ${_intDISK}"
+
   if [ "$_intBOOT" = "bsd" ] ; then
     echo_log "Stamping boot0 on ${_intDISK}"
     rc_halt "gpart bootcode -b /boot/boot0 ${_intDISK}"
@@ -670,7 +709,10 @@
   BOOT=$2
   SCHEME=$3
 
-  if [ "$SCHEME" = "MBR" ] ; then
+  if [ "$SCHEME" = "APM" ] ; then
+    init_apm_full_disk "$DISK"
+    slice=`echo "${DISK}:1:apm" | sed 's|/|-|g'`
+  elif [ "$SCHEME" = "MBR" ] ; then
     init_mbr_full_disk "$DISK" "$BOOT"
     slice=`echo "${DISK}:1:mbr" | sed 's|/|-|g'`
   else
@@ -727,6 +769,10 @@
   # Init the MBR partition
   rc_halt "gpart create -s BSD ${DISK}p${slicenum}"
 
+  # Stamp the bootloader
+  sleep 4
+  rc_halt "gpart bootcode -b /boot/boot ${DISK}p${slicenum}"
+
   # Set the slice to the format we'll be using for gpart later
   slice=`echo "${1}:${3}:gptslice" | sed 's|/|-|g'`
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions-localize.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions-localize.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions-localize.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-localize.sh 225657 2011-09-19 05:12:53Z jpaetzel $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-localize.sh 236330 2012-05-30 20:44:04Z jpaetzel $
 
 # Functions which runs commands on the system
 
@@ -168,6 +168,7 @@
   # Set the keylayout in rc.conf
   case ${KEYLAYOUT} in
     am) KEYLAYOUT_CONSOLE="hy.armscii-8" ;;
+    ca) KEYLAYOUT_CONSOLE="fr_CA.acc.iso" ;;
     ch) KEYLAYOUT_CONSOLE="swissgerman.iso" ;;
     cz) KEYLAYOUT_CONSOLE="cz.iso2" ;;
     de) KEYLAYOUT_CONSOLE="german.iso" ;;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions-networking.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions-networking.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions-networking.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -28,7 +28,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-networking.sh 232890 2012-03-12 20:44:44Z jpaetzel $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-networking.sh 234987 2012-05-03 21:21:45Z jpaetzel $
 
 # Functions which perform our networking setup
 
@@ -192,7 +192,7 @@
   # Get the target nic
   NIC="$1"
 
-  get_value_from_cfg netSaveIP
+  get_value_from_cfg netSaveIP_${NIC}
   NETIP="${VAL}"
  
   if [ "$NETIP" = "DHCP" ]
@@ -212,7 +212,7 @@
     IFARGS="inet ${NETIP}"
 
     # Check if we have a netmask to set
-    get_value_from_cfg netSaveMask
+    get_value_from_cfg netSaveMask_${NIC}
     NETMASK="${VAL}"
     if [ -n "${NETMASK}" ]
     then
@@ -220,7 +220,7 @@
     fi
   fi
 
-  get_value_from_cfg netSaveIPv6
+  get_value_from_cfg netSaveIPv6_${NIC}
   NETIP6="${VAL}"
   if [ -n "${NETIP6}" ]
   then
@@ -239,6 +239,12 @@
     echo "ifconfig_${NIC}_ipv6=\"${IF6ARGS}\"" >>${FSMNT}/etc/rc.conf
   fi
 
+};
+
+# Function which saves a manual gateway router setup to the installed system
+save_manual_router()
+{
+
   # Check if we have a default router to set
   get_value_from_cfg netSaveDefaultRouter
   NETROUTE="${VAL}"
@@ -253,19 +259,30 @@
     echo "ipv6_defaultrouter=\"${NETROUTE}\"" >>${FSMNT}/etc/rc.conf
   fi
 
+};
+
+save_manual_nameserver()
+{
   # Check if we have a nameserver to enable
   : > ${FSMNT}/etc/resolv.conf
-  get_value_from_cfg netSaveNameServer
-  NAMESERVER="${VAL}"
-  if [ -n "${NAMESERVER}" ]
+  get_value_from_cfg_with_spaces netSaveNameServer
+  NAMESERVERLIST="${VAL}"
+  if [ ! -z "${NAMESERVERLIST}" ]
   then
-    echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
+    for NAMESERVER in ${NAMESERVERLIST}
+    do
+      echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
+    done
   fi
-  get_value_from_cfg netSaveIPv6NameServer
-  NAMESERVER="${VAL}"
-  if [ -n "${NAMESERVER}" ]
+
+  get_value_from_cfg_with_spaces netSaveIPv6NameServer
+  NAMESERVERLIST="${VAL}"
+  if [ ! -z "${NAMESERVERLIST}" ]
   then
-    echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
+    for NAMESERVER in ${NAMESERVERLIST}
+    do
+      echo "nameserver ${NAMESERVER}" >>${FSMNT}/etc/resolv.conf
+    done
   fi
 
 };
@@ -454,25 +471,30 @@
 {
 
   # Check if we have any networking requested to save
-  get_value_from_cfg netSaveDev
+  get_value_from_cfg_with_spaces netSaveDev
   if [ -z "${VAL}" ]
   then
     return 0
   fi
 
-  NETDEV="${VAL}"
-  if [ "$NETDEV" = "AUTO-DHCP" ]
+  NETDEVLIST="${VAL}"
+  if [ "$NETDEVLIST" = "AUTO-DHCP" ]
   then
     save_auto_dhcp
-  elif [ "$NETDEV" = "IPv6-SLAAC" ]
+  elif [ "$NETDEVLIST" = "IPv6-SLAAC" ]
   then
     save_auto_slaac
-  elif [ "$NETDEV" = "AUTO-DHCP-SLAAC" ]
+  elif [ "$NETDEVLIST" = "AUTO-DHCP-SLAAC" ]
   then
     save_auto_dhcp
     save_auto_slaac
   else
-    save_manual_nic ${NETDEV}
+    for NETDEV in ${NETDEVLIST}
+    do
+      save_manual_nic ${NETDEV}
+    done
+    save_manual_router
+    save_manual_nameserver
   fi
 
 };
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions-newfs.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions-newfs.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions-newfs.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-newfs.sh 232899 2012-03-12 21:32:43Z jpaetzel $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-newfs.sh 234990 2012-05-03 21:53:25Z jpaetzel $
 
 # Functions related to disk operations using newfs
 
@@ -44,6 +44,23 @@
   sleep 5
   sync
 
+  # Check if we have multiple zfs mounts specified
+  for i in `echo ${PARTMNT} | sed 's|,| |g'`
+  do
+    # Check if we ended up with needing a zfs bootable partition
+    if [ "${i}" = "/" -o "${i}" = "/boot" ]
+    then
+      if [ "$HAVEBOOT" = "YES" ] ; then continue ; fi
+      if [ "${PARTGEOM}" = "MBR" ] ; then
+        # Lets stamp the proper ZFS boot loader
+        echo_log "Setting up ZFS boot loader support" 
+        rc_halt "dd if=/boot/zfsboot of=${ROOTSLICE} count=1"
+        rc_halt "dd if=/boot/zfsboot of=${PART}${EXT} skip=1 seek=1024"
+      fi
+    fi
+  done 
+
+
   # Check if we have some custom zpool arguments and use them if so
   if [ ! -z "${ZPOOLOPTS}" ] ; then
     rc_halt "zpool create -m none -f ${ZPOOLNAME} ${ZPOOLOPTS}"
@@ -55,23 +72,13 @@
   # Disable atime for this zfs partition, speed increase
   rc_nohalt "zfs set atime=off ${ZPOOLNAME}"
 
-  # Check if we have multiple zfs mounts specified
+  # Check if we need to set a bootable zpool
   for i in `echo ${PARTMNT} | sed 's|,| |g'`
   do
-    # Check if we ended up with needing a zfs bootable partition
-    if [ "${i}" = "/" -o "${i}" = "/boot" ]
-    then
+    if [ "${i}" = "/" -o "${i}" = "/boot" ] ; then
       if [ "$HAVEBOOT" = "YES" ] ; then continue ; fi
-      if [ "${PARTGEOM}" = "MBR" ]
-      then
-        # Lets stamp the proper ZFS boot loader
-        echo_log "Setting up ZFS boot loader support" 
-        rc_halt "zpool set bootfs=${ZPOOLNAME} ${ZPOOLNAME}"
-        rc_halt "zpool export ${ZPOOLNAME}"
-        rc_halt "dd if=/boot/zfsboot of=${ROOTSLICE} count=1"
-        rc_halt "dd if=/boot/zfsboot of=${PART}${EXT} skip=1 seek=1024"
-        rc_halt "zpool import ${ZPOOLNAME}"
-      fi
+      echo_log "Stamping zpool as bootfs" 
+      rc_halt "zpool set bootfs=${ZPOOLNAME} ${ZPOOLNAME}"
     fi
   done 
 
@@ -90,11 +97,6 @@
   for PART in `ls ${PARTDIR}`
   do
     PARTDEV="`echo $PART | sed 's|-|/|g'`"
-    if [ ! -e "${PARTDEV}" ]
-    then
-      exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?"
-    fi 
-     
     PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
     PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`"
     PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`"
@@ -103,6 +105,10 @@
     PARTXTRAOPTS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 6`"
     PARTIMAGE="`cat ${PARTDIR}/${PART} | cut -d '#' -f 7`"
 
+    if [ ! -e "${PARTDEV}" ] ; then
+      exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?"
+    fi 
+
     # Make sure journaling isn't enabled on this device
     if [ -e "${PARTDEV}.journal" ]
     then
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions-parse.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions-parse.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions-parse.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-parse.sh 228990 2011-12-30 10:58:14Z uqs $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions-parse.sh 234985 2012-05-03 21:15:47Z jpaetzel $
 
 # functions.sh
 # Library of functions which pc-sysinstall may call upon for parsing the config
@@ -33,7 +33,7 @@
 {
   if [ -n "${1}" ]
   then
-    export VAL="`echo ${1} | cut -d '=' -f 2-15`"
+    export VAL="`echo ${1} | cut -d '=' -f 2-`"
   else
     echo "Error: Did we forgot to supply a string to parse?"
     exit 1
@@ -45,7 +45,7 @@
 {
   if [ -n "${1}" ]
   then
-    export VAL=`grep "^${1}=" ${CFGF} | head -n 1 | cut -d '=' -f 2-15`
+    export VAL=`grep "^${1}=" ${CFGF} | head -n 1 | cut -d '=' -f 2-`
   else
     exit_err "Error: Did we forgot to supply a setting to grab?"
   fi
@@ -57,7 +57,7 @@
 {
   if [ -n "${1}" ]
   then
-    export VAL=`grep "^${1}=" ${CFGF} | head -n 1 | cut -d '=' -f 2-15 | tr -d ' '`
+    export VAL=`grep "^${1}=" ${CFGF} | head -n 1 | cut -d '=' -f 2- | tr -d ' '`
   else
     exit_err "Error: Did we forgot to supply a setting to grab?"
   fi
@@ -71,7 +71,7 @@
   then
     # Get the first occurrence of the setting from the config, strip out whitespace
 
-    VAL=`grep "^${1}" ${CFGF} | head -n 1 | cut -d '=' -f 2 | tr -d ' '`
+    VAL=`grep "^${1}" ${CFGF} | head -n 1 | cut -d '=' -f 2- | tr -d ' '`
     if [ -z "${VAL}" ]
     then
       # This value doesn't exist, lets return
@@ -104,7 +104,7 @@
   if [ -n "${1}" -a -n "${2}" ]
   then
     # Get the first occurrence of the setting from the config, strip out whitespace
-    VAL=`grep "^${1}" ${CFGF} | head -n 1 | cut -d '=' -f 2 | tr -d ' '`
+    VAL=`grep "^${1}" ${CFGF} | head -n 1 | cut -d '=' -f 2- | tr -d ' '`
     VALID="1"
     for i in ${2}
     do
@@ -133,7 +133,7 @@
       grep -q "^${i}=" $CFGF 2>/dev/null
       if [ $? -eq 0 ]
       then
-        LN=`grep "^${i}=" ${CFGF} | head -n 1 | cut -d '=' -f 2 | tr -d ' '`
+        LN=`grep "^${i}=" ${CFGF} | head -n 1 | cut -d '=' -f 2- | tr -d ' '`
         if [ -z "${LN}" ]
         then
           echo "Error: Config fails sanity test! ${i}= is empty"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pc-sysinstall/backend/functions.sh
--- a/head/usr.sbin/pc-sysinstall/backend/functions.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pc-sysinstall/backend/functions.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 #
-# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions.sh 225657 2011-09-19 05:12:53Z jpaetzel $
+# $FreeBSD: head/usr.sbin/pc-sysinstall/backend/functions.sh 236331 2012-05-30 20:49:28Z jpaetzel $
 
 # functions.sh
 # Library of functions which pc-sysinstall may call upon
@@ -208,15 +208,11 @@
   FETCHOUTFILE="$2"
   EXITFAILED="$3"
 
-  SIZEFILE="${TMPDIR}/.fetchSize"
   EXITFILE="${TMPDIR}/.fetchExit"
 
-  rm ${SIZEFILE} 2>/dev/null >/dev/null
   rm ${FETCHOUTFILE} 2>/dev/null >/dev/null
 
-  fetch -s "${FETCHFILE}" >${SIZEFILE}
-  SIZE="`cat ${SIZEFILE}`"
-  SIZE="`expr ${SIZE} / 1024`"
+  SIZE=$(( `fetch -s "${FETCHFILE}"` / 1024 ))
   echo "FETCH: ${FETCHFILE}"
   echo "FETCH: ${FETCHOUTFILE}" >>${LOGOUT}
 
@@ -276,11 +272,20 @@
   else
     # Need to generate a zpool name for this device
     NUM=`ls ${TMPDIR}/.zpools/ | wc -l | sed 's| ||g'`
-    NEWNAME="${BASENAME}${NUM}"
+
+    # Is it used in another zpool?
+    while :
+    do
+      NEWNAME="${BASENAME}${NUM}"
+      zpool import | grep -qw "${NEWNAME}" || break
+      NUM=$((NUM+1))
+    done
+
+    # Now save the new tank name
     mkdir -p ${TMPDIR}/.zpools/`dirname $DEVICE`
     echo "$NEWNAME" >${TMPDIR}/.zpools/${DEVICE} 
     echo "${NEWNAME}"
-    return
+    return 0
   fi
 };
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pciconf/Makefile
--- a/head/usr.sbin/pciconf/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pciconf/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,8 +1,8 @@
 #	$ANA: Makefile,v 1.1.1.1 1996/09/25 21:12:57 wollman Exp $
-# $FreeBSD$
+# $FreeBSD: head/usr.sbin/pciconf/Makefile 236415 2012-06-01 18:33:40Z jhb $
 
 PROG=	pciconf
-SRCS=	pciconf.c cap.c
+SRCS=	pciconf.c cap.c err.c
 MAN=	pciconf.8
 
 CFLAGS+= -I${.CURDIR}/../../sys
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pciconf/cap.c
--- a/head/usr.sbin/pciconf/cap.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pciconf/cap.c	Wed Jul 25 16:29:58 2012 +0300
@@ -30,7 +30,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-  "$FreeBSD$";
+  "$FreeBSD: head/usr.sbin/pciconf/cap.c 236415 2012-06-01 18:33:40Z jhb $";
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -630,3 +630,59 @@
 		ecap = read_config(fd, &p->pc_sel, ptr, 4);
 	}
 }
+
+/* Find offset of a specific capability.  Returns 0 on failure. */
+uint8_t
+pci_find_cap(int fd, struct pci_conf *p, uint8_t id)
+{
+	uint16_t sta;
+	uint8_t ptr, cap;
+
+	/* Are capabilities present for this device? */
+	sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2);
+	if (!(sta & PCIM_STATUS_CAPPRESENT))
+		return (0);
+
+	switch (p->pc_hdr & PCIM_HDRTYPE) {
+	case PCIM_HDRTYPE_NORMAL:
+	case PCIM_HDRTYPE_BRIDGE:
+		ptr = PCIR_CAP_PTR;
+		break;
+	case PCIM_HDRTYPE_CARDBUS:
+		ptr = PCIR_CAP_PTR_2;
+		break;
+	default:
+		return (0);
+	}
+
+	ptr = read_config(fd, &p->pc_sel, ptr, 1);
+	while (ptr != 0 && ptr != 0xff) {
+		cap = read_config(fd, &p->pc_sel, ptr + PCICAP_ID, 1);
+		if (cap == id)
+			return (ptr);
+		ptr = read_config(fd, &p->pc_sel, ptr + PCICAP_NEXTPTR, 1);
+	}
+	return (0);
+}
+
+/* Find offset of a specific extended capability.  Returns 0 on failure. */
+uint16_t
+pcie_find_cap(int fd, struct pci_conf *p, uint16_t id)
+{
+	uint32_t ecap;
+	uint16_t ptr;
+
+	ptr = PCIR_EXTCAP;
+	ecap = read_config(fd, &p->pc_sel, ptr, 4);
+	if (ecap == 0xffffffff || ecap == 0)
+		return (0);
+	for (;;) {
+		if (PCI_EXTCAP_ID(ecap) == id)
+			return (ptr);
+		ptr = PCI_EXTCAP_NEXTPTR(ecap);
+		if (ptr == 0)
+			break;
+		ecap = read_config(fd, &p->pc_sel, ptr, 4);
+	}
+	return (0);
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pciconf/err.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/pciconf/err.c	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 2012 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb at 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 lint
+static const char rcsid[] =
+    "$FreeBSD: head/usr.sbin/pciconf/err.c 236415 2012-06-01 18:33:40Z jhb $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/pciio.h>
+
+#include <err.h>
+#include <stdio.h>
+
+#include <dev/pci/pcireg.h>
+
+#include "pciconf.h"
+
+struct bit_table {
+	uint32_t mask;
+	const char *desc;
+};
+
+/* Error indicators in the PCI status register (PCIR_STATUS). */
+static struct bit_table pci_status[] = {
+	{ PCIM_STATUS_MDPERR, "Master Data Parity Error" },
+	{ PCIM_STATUS_STABORT, "Sent Target-Abort" },
+	{ PCIM_STATUS_RTABORT, "Received Target-Abort" },
+	{ PCIM_STATUS_RMABORT, "Received Master-Abort" },
+	{ PCIM_STATUS_SERR, "Signalled System Error" },
+	{ PCIM_STATUS_PERR, "Detected Parity Error" },
+	{ 0, NULL },
+};
+
+/* Valid error indicator bits in PCIR_STATUS. */
+#define	PCI_ERRORS	(PCIM_STATUS_MDPERR | PCIM_STATUS_STABORT |	\
+			 PCIM_STATUS_RTABORT | PCIM_STATUS_RMABORT |	\
+			 PCIM_STATUS_SERR | PCIM_STATUS_PERR)
+
+/* Error indicators in the PCI-Express device status register. */
+static struct bit_table pcie_device_status[] = {
+	{ PCIM_EXP_STA_CORRECTABLE_ERROR, "Correctable Error Detected" },
+	{ PCIM_EXP_STA_NON_FATAL_ERROR, "Non-Fatal Error Detected" },	
+	{ PCIM_EXP_STA_FATAL_ERROR, "Fatal Error Detected" },	
+	{ PCIM_EXP_STA_UNSUPPORTED_REQ, "Unsupported Request Detected" },	
+	{ 0, NULL },
+};
+
+/* Valid error indicator bits in the PCI-Express device status register. */
+#define	PCIE_ERRORS	(PCIM_EXP_STA_CORRECTABLE_ERROR |		\
+			 PCIM_EXP_STA_NON_FATAL_ERROR |			\
+			 PCIM_EXP_STA_FATAL_ERROR |			\
+			 PCIM_EXP_STA_UNSUPPORTED_REQ)
+
+/* AER Uncorrected errors. */
+static struct bit_table aer_uc[] = {
+	{ PCIM_AER_UC_TRAINING_ERROR, "Link Training Error" },
+	{ PCIM_AER_UC_DL_PROTOCOL_ERROR, "Data Link Protocol Error" },
+	{ PCIM_AER_UC_SURPRISE_LINK_DOWN, "Surprise Link Down Error" },
+	{ PCIM_AER_UC_POISONED_TLP, "Poisoned TLP" },
+	{ PCIM_AER_UC_FC_PROTOCOL_ERROR, "Flow Control Protocol Error" },
+	{ PCIM_AER_UC_COMPLETION_TIMEOUT, "Completion Timeout" },
+	{ PCIM_AER_UC_COMPLETER_ABORT, "Completer Abort" },
+	{ PCIM_AER_UC_UNEXPECTED_COMPLETION, "Unexpected Completion" },
+	{ PCIM_AER_UC_RECEIVER_OVERFLOW, "Receiver Overflow Error" },
+	{ PCIM_AER_UC_MALFORMED_TLP, "Malformed TLP" },
+	{ PCIM_AER_UC_ECRC_ERROR, "ECRC Error" },
+	{ PCIM_AER_UC_UNSUPPORTED_REQUEST, "Unsupported Request" },
+	{ PCIM_AER_UC_ACS_VIOLATION, "ACS Violation" },
+	{ 0, NULL },
+};
+
+/* AER Corrected errors. */
+static struct bit_table aer_cor[] = {
+	{ PCIM_AER_COR_RECEIVER_ERROR, "Receiver Error" },
+	{ PCIM_AER_COR_BAD_TLP, "Bad TLP" },
+	{ PCIM_AER_COR_BAD_DLLP, "Bad DLLP" },
+	{ PCIM_AER_COR_REPLAY_ROLLOVER, "REPLAY_NUM Rollover" },
+	{ PCIM_AER_COR_REPLAY_TIMEOUT, "Replay Timer Timeout" },
+	{ PCIM_AER_COR_ADVISORY_NF_ERROR, "Advisory Non-Fatal Error" },
+	{ 0, NULL },
+};
+
+static void
+print_bits(const char *header, struct bit_table *table, uint32_t mask)
+{
+	int first;
+
+	first = 1;
+	for (; table->desc != NULL; table++)
+		if (mask & table->mask) {
+			if (first) {
+				printf("%14s = ", header);
+				first = 0;
+			} else
+				printf("                 ");
+			printf("%s\n", table->desc);
+			mask &= ~table->mask;
+		}
+	if (mask != 0) {
+		if (first)
+			printf("%14s = ", header);
+		else
+			printf("                 ");
+		printf("Unknown: 0x%08x\n", mask);
+	}
+}
+
+void
+list_errors(int fd, struct pci_conf *p)
+{
+	uint32_t mask, severity;
+	uint16_t sta, aer;
+	uint8_t pcie;
+
+	/* First check for standard PCI errors. */
+	sta = read_config(fd, &p->pc_sel, PCIR_STATUS, 2);
+	print_bits("PCI errors", pci_status, sta & PCI_ERRORS);
+
+	/* See if this is a PCI-express device. */
+	pcie = pci_find_cap(fd, p, PCIY_EXPRESS);
+	if (pcie == 0)
+		return;
+
+	/* Check for PCI-e errors. */
+	sta = read_config(fd, &p->pc_sel, pcie + PCIR_EXPRESS_DEVICE_STA, 2);
+	print_bits("PCI-e errors", pcie_device_status, sta & PCIE_ERRORS);
+
+	/* See if this device supports AER. */
+	aer = pcie_find_cap(fd, p, PCIZ_AER);
+	if (aer == 0)
+		return;
+
+	/* Check for uncorrected errors. */
+	mask = read_config(fd, &p->pc_sel, aer + PCIR_AER_UC_STATUS, 4);
+        severity = read_config(fd, &p->pc_sel, aer + PCIR_AER_UC_SEVERITY, 4);
+	print_bits("Fatal", aer_uc, mask & severity);
+	print_bits("Non-fatal", aer_uc, mask & ~severity);
+
+	/* Check for corrected errors. */
+	mask = read_config(fd, &p->pc_sel, aer + PCIR_AER_COR_STATUS, 4);
+	print_bits("Corrected", aer_cor, mask);
+}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pciconf/pciconf.8
--- a/head/usr.sbin/pciconf/pciconf.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pciconf/pciconf.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,9 +23,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/pciconf/pciconf.8 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/pciconf/pciconf.8 236415 2012-06-01 18:33:40Z jhb $
 .\"
-.Dd November 7, 2007
+.Dd June 1, 2012
 .Dt PCICONF 8
 .Os
 .Sh NAME
@@ -33,7 +33,7 @@
 .Nd diagnostic utility for the PCI bus
 .Sh SYNOPSIS
 .Nm
-.Fl l Op Fl bcv
+.Fl l Op Fl bcev
 .Nm
 .Fl a Ar selector
 .Nm
@@ -167,6 +167,15 @@
 The format of the text after the equals sign is capability-specific.
 .Pp
 If the
+.Fl e
+option is supplied,
+.Nm
+will list any errors reported for this device in standard PCI error registers.
+Errors are checked for in the PCI status register,
+the PCI-express device status register,
+and the Advanced Error Reporting status registers.
+.Pp
+If the
 .Fl v
 option is supplied,
 .Nm
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pciconf/pciconf.c
--- a/head/usr.sbin/pciconf/pciconf.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pciconf/pciconf.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-  "$FreeBSD: head/usr.sbin/pciconf/pciconf.c 228990 2011-12-30 10:58:14Z uqs $";
+  "$FreeBSD: head/usr.sbin/pciconf/pciconf.c 236415 2012-06-01 18:33:40Z jhb $";
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -68,7 +68,7 @@
 TAILQ_HEAD(,pci_vendor_info)	pci_vendors;
 
 static void list_bars(int fd, struct pci_conf *p);
-static void list_devs(int verbose, int bars, int caps);
+static void list_devs(int verbose, int bars, int caps, int errors);
 static void list_verbose(struct pci_conf *p);
 static const char *guess_class(struct pci_conf *p);
 static const char *guess_subclass(struct pci_conf *p);
@@ -83,7 +83,7 @@
 usage(void)
 {
 	fprintf(stderr, "%s\n%s\n%s\n%s\n",
-		"usage: pciconf -l [-bcv]",
+		"usage: pciconf -l [-bcev]",
 		"       pciconf -a selector",
 		"       pciconf -r [-b | -h] selector addr[:addr2]",
 		"       pciconf -w [-b | -h] selector addr value");
@@ -94,12 +94,14 @@
 main(int argc, char **argv)
 {
 	int c;
-	int listmode, readmode, writemode, attachedmode, bars, caps, verbose;
+	int listmode, readmode, writemode, attachedmode;
+	int bars, caps, errors, verbose;
 	int byte, isshort;
 
-	listmode = readmode = writemode = attachedmode = bars = caps = verbose = byte = isshort = 0;
+	listmode = readmode = writemode = attachedmode = 0;
+	bars = caps = errors = verbose = byte = isshort = 0;
 
-	while ((c = getopt(argc, argv, "abchlrwv")) != -1) {
+	while ((c = getopt(argc, argv, "abcehlrwv")) != -1) {
 		switch(c) {
 		case 'a':
 			attachedmode = 1;
@@ -114,6 +116,10 @@
 			caps = 1;
 			break;
 
+		case 'e':
+			errors = 1;
+			break;
+
 		case 'h':
 			isshort = 1;
 			break;
@@ -146,7 +152,7 @@
 		usage();
 
 	if (listmode) {
-		list_devs(verbose, bars, caps);
+		list_devs(verbose, bars, caps, errors);
 	} else if (attachedmode) {
 		chkattached(argv[optind]);
 	} else if (readmode) {
@@ -163,7 +169,7 @@
 }
 
 static void
-list_devs(int verbose, int bars, int caps)
+list_devs(int verbose, int bars, int caps, int errors)
 {
 	int fd;
 	struct pci_conf_io pc;
@@ -173,7 +179,7 @@
 	if (verbose)
 		load_vendors();
 
-	fd = open(_PATH_DEVPCI, caps ? O_RDWR : O_RDONLY, 0);
+	fd = open(_PATH_DEVPCI, (caps || errors) ? O_RDWR : O_RDONLY, 0);
 	if (fd < 0)
 		err(1, "%s", _PATH_DEVPCI);
 
@@ -223,6 +229,8 @@
 				list_bars(fd, p);
 			if (caps)
 				list_caps(fd, p);
+			if (errors)
+				list_errors(fd, p);
 		}
 	} while (pc.status == PCI_GETCONF_MORE_DEVS);
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pciconf/pciconf.h
--- a/head/usr.sbin/pciconf/pciconf.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pciconf/pciconf.h	Wed Jul 25 16:29:58 2012 +0300
@@ -27,13 +27,16 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/pciconf/pciconf.h 236415 2012-06-01 18:33:40Z jhb $
  */
 
 #ifndef __PCICONF_H__
 #define	__PCICONF_H__
 
 void	list_caps(int fd, struct pci_conf *p);
+void	list_errors(int fd, struct pci_conf *p);
+uint8_t	pci_find_cap(int fd, struct pci_conf *p, uint8_t id);
+uint16_t pcie_find_cap(int fd, struct pci_conf *p, uint16_t id);
 uint32_t read_config(int fd, struct pcisel *sel, long reg, int width);
 
 #endif
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg/pkg.c
--- a/head/usr.sbin/pkg/pkg.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg/pkg.c	Wed Jul 25 16:29:58 2012 +0300
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg/pkg.c 234351 2012-04-16 20:41:25Z bapt $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg/pkg.c 238461 2012-07-15 04:15:27Z kan $");
 
 #include <sys/param.h>
 #include <sys/elf_common.h>
@@ -282,7 +282,10 @@
 bootstrap_pkg(void)
 {
 	FILE *remote;
+	FILE *config;
+	char *site;
 	char url[MAXPATHLEN];
+	char conf[MAXPATHLEN];
 	char abi[BUFSIZ];
 	char tmppkg[MAXPATHLEN];
 	char buf[10240];
@@ -290,7 +293,6 @@
 	int fd, retry, ret;
 	struct url_stat st;
 	off_t done, r;
-	time_t begin_dl;
 	time_t now;
 	time_t last;
 
@@ -298,6 +300,7 @@
 	last = 0;
 	ret = -1;
 	remote = NULL;
+	config = NULL;
 
 	printf("Bootstrapping pkg please wait\n");
 
@@ -307,7 +310,7 @@
 	}
 
 	if (getenv("PACKAGESITE") != NULL)
-		snprintf(url, MAXPATHLEN, "%s/pkg.txz", getenv("PACKAGESITE"));
+		snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", getenv("PACKAGESITE"));
 	else
 		snprintf(url, MAXPATHLEN, "%s/%s/latest/Latest/pkg.txz",
 		    getenv("PACKAGEROOT") ? getenv("PACKAGEROOT") : _PKGS_URL,
@@ -331,7 +334,6 @@
 	if (remote == NULL)
 		goto fetchfail;
 
-	begin_dl = time(NULL);
 	while (done < st.size) {
 		if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
 			break;
@@ -353,18 +355,62 @@
 	if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0)
 		ret = install_pkg_static(pkgstatic, tmppkg);
 
+	snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf",
+	    getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
+
+	if (access(conf, R_OK) == -1) {
+		site = strrchr(url, '/');
+		if (site == NULL)
+			goto cleanup;
+		site[0] = '\0';
+		site = strrchr(url, '/');
+		if (site == NULL)
+			goto cleanup;
+		site[0] = '\0';
+
+		config = fopen(conf, "w+");
+		if (config == NULL)
+			goto cleanup;
+		fprintf(config, "packagesite: %s\n", url);
+		fclose(config);
+	}
+
 	goto cleanup;
 
 fetchfail:
 	warnx("Error fetching %s: %s", url, fetchLastErrString);
 
 cleanup:
+	if (remote != NULL)
+		fclose(remote);
 	close(fd);
 	unlink(tmppkg);
 
 	return (ret);
 }
 
+static const char confirmation_message[] =
+"The package management tool is not yet installed on your system.\n"
+"Do you want to fetch and install it now? [y/N]: ";
+
+static int
+pkg_query_yes_no(void)
+{
+	int ret, c;
+
+	c = getchar();
+
+	if (c == 'y' || c == 'Y')
+		ret = 1;
+	else
+		ret = 0;
+
+	while (c != '\n' && c != EOF)
+		c = getchar();
+
+	return (ret);
+}
+
 int
 main(__unused int argc, char *argv[])
 {
@@ -373,9 +419,21 @@
 	snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg",
 	    getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
 
-	if (access(pkgpath, X_OK) == -1)
+	if (access(pkgpath, X_OK) == -1) {
+		/*
+		 * Do not ask for confirmation if either of stdin or stdout is
+		 * not tty. Check the environment to see if user has answer
+		 * tucked in there already.
+		 */
+		if (getenv("ALWAYS_ASSUME_YES") == NULL &&
+		    isatty(fileno(stdin))) {
+			printf("%s", confirmation_message);
+			if (pkg_query_yes_no() == 0)
+				exit(EXIT_FAILURE);
+		}
 		if (bootstrap_pkg() != 0)
 			exit(EXIT_FAILURE);
+	}
 
 	execv(pkgpath, argv);
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/add/main.c
--- a/head/usr.sbin/pkg_install/add/main.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/add/main.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 232435 2012-03-03 05:04:47Z kensmith $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 236333 2012-05-30 21:01:06Z jpaetzel $");
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -234,10 +234,17 @@
 		remotepkg = temppackageroot;
 		if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' &&
 			(ptr[2] == 'b' || ptr[2] == 'g' || ptr[2] == 'x') &&
-			ptr[3] == 'z' && !ptr[4]))
-		    if (strlcat(remotepkg, ".tbz",
-			sizeof(temppackageroot)) >= sizeof(temppackageroot))
-			errx(1, "package name too long");
+			ptr[3] == 'z' && !ptr[4])) {
+    		    if (getenv("PACKAGESUFFIX")) {
+		       if (strlcat(remotepkg, getenv("PACKAGESUFFIX"),
+			   sizeof(temppackageroot)) >= sizeof(temppackageroot))
+			   errx(1, "package name too long");
+		    } else {
+		       if (strlcat(remotepkg, ".tbz",
+			   sizeof(temppackageroot)) >= sizeof(temppackageroot))
+			   errx(1, "package name too long");
+		    }
+		}
     	    }
 	    if (!strcmp(*argv, "-"))	/* stdin? */
 		pkgs[ch] = (char *)"-";
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/add/perform.c
--- a/head/usr.sbin/pkg_install/add/perform.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/add/perform.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/perform.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/perform.c 236333 2012-05-30 21:01:06Z jpaetzel $");
 
 #include <err.h>
 #include <paths.h>
@@ -307,8 +307,12 @@
 		    *sep = '\0';
 		    strlcat(subpkg, "/All/", sizeof subpkg);
 		    strlcat(subpkg, p->name, sizeof subpkg);
-		    if ((ext = strrchr(pkg, '.')) == NULL)
-			ext = ".tbz";
+		    if ((ext = strrchr(pkg, '.')) == NULL) {
+			if (getenv("PACKAGESUFFIX"))
+			  ext = getenv("PACKAGESUFFIX");
+			else
+			  ext = ".tbz";
+		    }
 		    strlcat(subpkg, ext, sizeof subpkg);
 		    pkg_do(subpkg);
 		}
@@ -345,8 +349,13 @@
 		    const char *ext;
 
 		    ext = strrchr(pkg_fullname, '.');
-		    if (ext == NULL)
-			ext = ".tbz";
+		    if (ext == NULL) {
+			if (getenv("PACKAGESUFFIX")) {
+			  ext = getenv("PACKAGESUFFIX");
+			} else {
+			  ext = ".tbz";
+			}
+		    }
 		    snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), p->name, ext);
 		    if (fexists(path))
 			cp = path;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/add/pkg_add.1
--- a/head/usr.sbin/pkg_install/add/pkg_add.1	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/add/pkg_add.1	Wed Jul 25 16:29:58 2012 +0300
@@ -13,7 +13,7 @@
 .\"
 .\" Jordan K. Hubbard
 .\"
-.\" $FreeBSD: head/usr.sbin/pkg_install/add/pkg_add.1 228990 2011-12-30 10:58:14Z uqs $
+.\" $FreeBSD: head/usr.sbin/pkg_install/add/pkg_add.1 236333 2012-05-30 21:01:06Z jpaetzel $
 .\"
 .Dd January 4, 2009
 .Dt PKG_ADD 1
@@ -553,6 +553,11 @@
 specifies an alternative location to save downloaded packages to when
 .Fl K
 option is used.
+.Pp
+The environment variable
+.Ev PACKAGESUFFIX
+specifies an alternative file extension to use when fetching remote
+packages. Default is .tbz
 .Sh FILES
 .Bl -tag -width /var/db/pkg -compact
 .It Pa /var/tmp
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/lib/exec.c
--- a/head/usr.sbin/pkg_install/lib/exec.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/lib/exec.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/exec.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/exec.c 236213 2012-05-29 01:48:06Z kevlo $");
 
 #include "lib.h"
 #include <err.h>
@@ -47,6 +47,7 @@
     va_start(args, fmt);
     if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
 	warnx("vsystem args are too long");
+	va_end(args);
 	return 1;
     }
 #ifdef DEBUG
@@ -82,6 +83,7 @@
     va_start(args, fmt);
     if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
 	warnx("vsystem args are too long");
+	va_end(args);
 	return NULL;
     }
 #ifdef DEBUG
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/lib/file.c
--- a/head/usr.sbin/pkg_install/lib/file.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/lib/file.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/file.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/file.c 236333 2012-05-30 21:01:06Z jpaetzel $");
 
 #include "lib.h"
 #include <err.h>
@@ -140,7 +140,7 @@
 {
     static char tmp[FILENAME_MAX];
     char *cp;
-    const char *suffixes[] = {".tbz", ".tgz", ".tar", NULL};
+    const char *suffixes[] = {".tbz", ".tgz", ".tar", ".txz", NULL};
     int i;
 
     if (fexists(fname) && isfile(fname)) {
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/lib/lib.h
--- a/head/usr.sbin/pkg_install/lib/lib.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/lib/lib.h	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD: head/usr.sbin/pkg_install/lib/lib.h 228990 2011-12-30 10:58:14Z uqs $ */
+/* $FreeBSD: head/usr.sbin/pkg_install/lib/lib.h 236336 2012-05-30 21:28:37Z jpaetzel $ */
 
 /*
  * FreeBSD install - a package for the installation and maintenance
@@ -99,7 +99,7 @@
  * Version of the package tools - increase whenever you make a change
  * in the code that is not cosmetic only.
  */
-#define PKG_INSTALL_VERSION	20100403
+#define PKG_INSTALL_VERSION	20120530
 
 #define PKG_WRAPCONF_FNAME	"/var/db/pkg_install.conf"
 #define main(argc, argv)	real_main(argc, argv)
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/lib/msg.c
--- a/head/usr.sbin/pkg_install/lib/msg.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/lib/msg.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/msg.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/msg.c 236213 2012-05-29 01:48:06Z kevlo $");
 
 #include "lib.h"
 #include <err.h>
@@ -71,5 +71,6 @@
 	    ch = (def) ? 'Y' : 'N';
     }
     fclose(tty) ;
+    va_end(args);
     return (ch == 'Y') ? TRUE : FALSE;
 }
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/lib/plist.c
--- a/head/usr.sbin/pkg_install/lib/plist.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/lib/plist.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/plist.c 229655 2012-01-05 21:36:45Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/plist.c 235276 2012-05-11 16:09:12Z beat $");
 
 #include "lib.h"
 #include <err.h>
@@ -286,7 +286,8 @@
 	if (*cp == '\0') {
 	    cp = NULL;
 	    if (cmd == PLIST_PKGDEP) {
-		warnx("corrupted record (pkgdep line without argument), ignoring");
+		warnx("corrupted record for package %s (pkgdep line without "
+			"argument), ignoring", pkg->name);
 		cmd = FAIL;
 	    }
 	    goto bottom;
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/lib/url.c
--- a/head/usr.sbin/pkg_install/lib/url.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/lib/url.c	Wed Jul 25 16:29:58 2012 +0300
@@ -19,7 +19,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/url.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/url.c 236333 2012-05-30 21:01:06Z jpaetzel $");
 
 #include "lib.h"
 #include <err.h>
@@ -73,7 +73,10 @@
 		*(cp + 1) = '\0';
 		strcat(cp, "All/");
 		strcat(cp, spec);
-		strcat(cp, ".tbz");
+		if (getenv("PACKAGESUFFIX"))
+		   strcat(cp, getenv("PACKAGESUFFIX"));
+                else
+		   strcat(cp, ".tbz");
 	    }
 	    else
 		return NULL;
@@ -85,7 +88,10 @@
 	     */
 	    strcpy(fname, hint);
 	    strcat(fname, spec);
-	    strcat(fname, ".tbz");
+	    if (getenv("PACKAGESUFFIX"))
+	       strcat(fname, getenv("PACKAGESUFFIX"));
+            else
+	       strcat(fname, ".tbz");
 	}
     }
     else
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pkg_install/updating/pkg_updating.1
--- a/head/usr.sbin/pkg_install/updating/pkg_updating.1	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pkg_install/updating/pkg_updating.1	Wed Jul 25 16:29:58 2012 +0300
@@ -8,7 +8,7 @@
 .\" 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.          Beat Gätzi
 .\"
-.\" $FreeBSD: head/usr.sbin/pkg_install/updating/pkg_updating.1 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/pkg_install/updating/pkg_updating.1 235211 2012-05-10 02:07:00Z gjb $
 .\"
 .Dd May 30, 2008
 .Dt PKG_UPDATING 1
@@ -55,7 +55,7 @@
 .It Pa /var/db/pkg
 Default location of the installed package database.
 .It Pa /usr/ports
-The default ports directory and default location of the UPDATING file
+The default ports directory and default location of the UPDATING file.
 .El
 .Sh EXAMPLES
 Shows all entries of all installed ports:
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pmcstat/pmcstat.8
--- a/head/usr.sbin/pmcstat/pmcstat.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pmcstat/pmcstat.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" out of the use of this software, even if advised of the possibility of
 .\" such damage.
 .\"
-.\" $FreeBSD: head/usr.sbin/pmcstat/pmcstat.8 233522 2012-03-26 21:22:53Z joel $
+.\" $FreeBSD: head/usr.sbin/pmcstat/pmcstat.8 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd September 19, 2008
 .Dt PMCSTAT 8
@@ -263,7 +263,7 @@
 of the function within they live.
 The
 .Ar pathname
-argument is mandatory and indicates where informations will be stored.
+argument is mandatory and indicates where the information will be stored.
 If argument
 .Ar pathname
 is a
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/pmcstat/pmcstat_log.c
--- a/head/usr.sbin/pmcstat/pmcstat_log.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/pmcstat/pmcstat_log.c	Wed Jul 25 16:29:58 2012 +0300
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat_log.c 233628 2012-03-28 20:58:30Z fabient $");
+__FBSDID("$FreeBSD: head/usr.sbin/pmcstat/pmcstat_log.c 236669 2012-06-06 08:58:31Z fabient $");
 
 #include <sys/param.h>
 #include <sys/endian.h>
@@ -554,6 +554,14 @@
 		if ((fnname = elf_strptr(e, sh->sh_link, sym.st_name))
 		    == NULL)
 			continue;
+#ifdef __arm__
+		/* Remove spurious ARM function name. */
+		if (fnname[0] == '$' &&
+		    (fnname[1] == 'a' || fnname[1] == 't' ||
+		    fnname[1] == 'd') &&
+		    fnname[2] == '\0')
+			continue;
+#endif
 
 		symptr->ps_name  = pmcstat_string_intern(fnname);
 		symptr->ps_start = sym.st_value - image->pi_vaddr;
@@ -564,6 +572,8 @@
 	}
 
 	image->pi_symcount += newsyms;
+	if (image->pi_symcount == 0)
+		return;
 
 	assert(newsyms <= nfuncsyms);
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/portsnap/portsnap/portsnap.sh
--- a/head/usr.sbin/portsnap/portsnap/portsnap.sh	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/portsnap/portsnap/portsnap.sh	Wed Jul 25 16:29:58 2012 +0300
@@ -25,7 +25,7 @@
 # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 # POSSIBILITY OF SUCH DAMAGE.
 
-# $FreeBSD: head/usr.sbin/portsnap/portsnap/portsnap.sh 227484 2011-11-13 06:39:49Z alfred $
+# $FreeBSD: head/usr.sbin/portsnap/portsnap/portsnap.sh 235208 2012-05-09 21:56:10Z eadler $
 
 #### Usage function -- called from command-line handling code.
 
@@ -143,6 +143,9 @@
 		cron | extract | fetch | update | alfred)
 			COMMANDS="${COMMANDS} $1"
 			;;
+		up)
+			COMMANDS="${COMMANDS} update"
+			;;
 		*)
 			if [ $# -gt 1 ]; then usage; fi
 			if echo ${COMMANDS} | grep -vq extract; then
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/ppp/throughput.c
--- a/head/usr.sbin/ppp/throughput.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/ppp/throughput.c	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/usr.sbin/ppp/throughput.c 235822 2012-05-23 06:49:50Z delphij $
  */
 
 #include <sys/types.h>
@@ -115,14 +115,14 @@
   prompt_Printf(prompt, "%llu packets in, %llu packets out\n",
                 t->PacketsIn, t->PacketsOut);
   if (t->rolling) {
-    prompt_Printf(prompt, "  overall   %6qu bytes/sec\n",
+    prompt_Printf(prompt, "  overall   %6llu bytes/sec\n",
                   (t->OctetsIn + t->OctetsOut) / divisor);
-    prompt_Printf(prompt, "  %s %6qu bytes/sec in, %6qu bytes/sec out "
+    prompt_Printf(prompt, "  %s %6llu bytes/sec in, %6llu bytes/sec out "
                   "(over the last %d secs)\n",
                   t->downtime ? "average  " : "currently",
                   t->in.OctetsPerSecond, t->out.OctetsPerSecond,
                   secs_up > t->SamplePeriod ? t->SamplePeriod : secs_up);
-    prompt_Printf(prompt, "  peak      %6qu bytes/sec on %s",
+    prompt_Printf(prompt, "  peak      %6llu bytes/sec on %s",
                   t->BestOctetsPerSecond, ctime(&t->BestOctetsPerSecondTime));
   } else
     prompt_Printf(prompt, "Overall %llu bytes/sec\n",
@@ -266,7 +266,7 @@
 
     if ((divisor = throughput_uptime(t)) == 0)
       divisor = 1;
-    prompt_Printf(prompt, "overall cleared (was %6qu bytes/sec)\n",
+    prompt_Printf(prompt, "overall cleared (was %6llu bytes/sec)\n",
                   (t->OctetsIn + t->OctetsOut) / divisor);
     t->OctetsIn = t->OctetsOut = t->PacketsIn = t->PacketsOut = 0;
     t->downtime = 0;
@@ -274,8 +274,8 @@
   }
 
   if (clear_type & THROUGHPUT_CURRENT) {
-    prompt_Printf(prompt, "current cleared (was %6qu bytes/sec in,"
-                  " %6qu bytes/sec out)\n",
+    prompt_Printf(prompt, "current cleared (was %6llu bytes/sec in,"
+                  " %6llu bytes/sec out)\n",
                   t->in.OctetsPerSecond, t->out.OctetsPerSecond);
     t->in.OctetsPerSecond = t->out.OctetsPerSecond = 0;
   }
@@ -287,7 +287,7 @@
     last = time_buf + strlen(time_buf);
     if (last > time_buf && *--last == '\n')
       *last = '\0';
-    prompt_Printf(prompt, "peak    cleared (was %6qu bytes/sec on %s)\n",
+    prompt_Printf(prompt, "peak    cleared (was %6llu bytes/sec on %s)\n",
                   t->BestOctetsPerSecond, time_buf);
     t->BestOctetsPerSecond = 0;
     time(&t->BestOctetsPerSecondTime);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rarpd/Makefile
--- a/head/usr.sbin/rarpd/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rarpd/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,9 +1,12 @@
 #	from: @(#)Makefile	5.8 (Berkeley) 7/28/90
-# $FreeBSD$
+# $FreeBSD: head/usr.sbin/rarpd/Makefile 238282 2012-07-09 08:11:16Z hrs $
 
 PROG=	rarpd
 MAN=	rarpd.8
 
+DPADD=	${LIBUTIL}
+LDADD=	-lutil
+
 WARNS?=	3
 # This breaks with format strings returned by expand_syslog_m().. argh!
 #FORMAT_AUDIT?=	1
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rarpd/rarpd.8
--- a/head/usr.sbin/rarpd/rarpd.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rarpd/rarpd.8	Wed Jul 25 16:29:58 2012 +0300
@@ -14,9 +14,9 @@
 .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/rarpd/rarpd.8 238300 2012-07-09 15:44:35Z joel $
 .\"
-.Dd November 16, 2001
+.Dd July 9, 2012
 .Dt RARPD 8
 .Os
 .Sh NAME
@@ -27,9 +27,11 @@
 .Fl a
 .Op Fl dfsv
 .Op Fl t Ar directory
+.Op Fl P Ar pidfile
 .Nm
 .Op Fl dfsv
 .Op Fl t Ar directory
+.Op Fl P Ar pidfile
 .Ar interface
 .Sh DESCRIPTION
 The
@@ -92,6 +94,15 @@
 .Xr syslog 3 .
 .It Fl f
 Run in the foreground.
+.It Fl P
+Specify the pathname of the PID file.
+If not specified,
+.Pa /var/run/rarpd.pid
+or
+.Pa /var/run/rarpd.ifname.pid
+will be used depending on the
+.Fl a
+flag or the specified interface name.
 .It Fl s
 Supply a response to any RARP request for which an ethernet to IP address
 mapping exists; do not depend on the existence of
@@ -115,6 +126,7 @@
 .It Pa /etc/ethers
 .It Pa /etc/hosts
 .It Pa /tftpboot
+.It Pa /var/run/rarpd.pid
 .El
 .Sh SEE ALSO
 .Xr bpf 4
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rarpd/rarpd.c
--- a/head/usr.sbin/rarpd/rarpd.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rarpd/rarpd.c	Wed Jul 25 16:29:58 2012 +0300
@@ -22,13 +22,13 @@
 #endif /* not lint */
 #endif
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/rarpd/rarpd.c 230346 2012-01-20 01:37:23Z eadler $");
+__FBSDID("$FreeBSD: head/usr.sbin/rarpd/rarpd.c 238282 2012-07-09 08:11:16Z hrs $");
 
 /*
  * rarpd - Reverse ARP Daemon
  *
- * Usage:	rarpd -a [-dfsv] [-t directory] [hostname]
- *		rarpd [-dfsv] [-t directory] interface [hostname]
+ * Usage:	rarpd -a [-dfsv] [-t directory] [-P pidfile] [hostname]
+ *		rarpd [-dfsv] [-t directory] [-P pidfile] interface [hostname]
  *
  * 'hostname' is optional solely for backwards compatibility with Sun's rarpd.
  * Currently, the argument is ignored.
@@ -61,6 +61,7 @@
 #include <syslog.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <libutil.h>
 
 /* Cast a struct sockaddr to a struct sockaddr_in */
 #define SATOSIN(sa) ((struct sockaddr_in *)(sa))
@@ -99,6 +100,11 @@
 
 static	u_char zero[6];
 
+static char pidfile_buf[PATH_MAX];
+static char *pidfile;
+#define	RARPD_PIDFILE	"/var/run/rarpd.%s.pid"
+static struct pidfh *pidfile_fh;
+
 static int	bpf_open(void);
 static in_addr_t	choose_ipaddr(in_addr_t **, in_addr_t, in_addr_t);
 static char	*eatoa(u_char *);
@@ -140,7 +146,7 @@
 	openlog(name, LOG_PID | LOG_CONS, LOG_DAEMON);
 
 	opterr = 0;
-	while ((op = getopt(argc, argv, "adfst:v")) != -1)
+	while ((op = getopt(argc, argv, "adfsP:t:v")) != -1)
 		switch (op) {
 		case 'a':
 			++aflag;
@@ -158,6 +164,12 @@
 			++sflag;
 			break;
 
+		case 'P':
+			strncpy(pidfile_buf, optarg, sizeof(pidfile_buf) - 1);
+			pidfile_buf[sizeof(pidfile_buf) - 1] = '\0';
+			pidfile = pidfile_buf;
+			break;
+
 		case 't':
 			tftp_dir = optarg;
 			break;
@@ -181,10 +193,23 @@
 	init(ifname);
 
 	if (!fflag) {
+		if (pidfile == NULL && ifname != NULL && aflag == 0) {
+			snprintf(pidfile_buf, sizeof(pidfile_buf) - 1,
+			    RARPD_PIDFILE, ifname);
+			pidfile_buf[sizeof(pidfile_buf) - 1] = '\0';
+			pidfile = pidfile_buf;
+		}
+		/* If pidfile == NULL, /var/run/<progname>.pid will be used. */
+		pidfile_fh = pidfile_open(pidfile, 0600, NULL);
+		if (pidfile_fh == NULL)
+			logmsg(LOG_ERR, "Cannot open or create pidfile: %s",
+			    (pidfile == NULL) ? "/var/run/rarpd.pid" : pidfile);
 		if (daemon(0,0)) {
 			logmsg(LOG_ERR, "cannot fork");
+			pidfile_remove(pidfile_fh);
 			exit(1);
 		}
+		pidfile_write(pidfile_fh);
 	}
 	rarp_loop();
 	return(0);
@@ -234,6 +259,7 @@
 		ii = (struct if_info *)malloc(sizeof(*ii));
 		if (ii == NULL) {
 			logmsg(LOG_ERR, "malloc: %m");
+			pidfile_remove(pidfile_fh);
 			exit(1);
 		}
 		bzero(ii, sizeof(*ii));
@@ -251,6 +277,7 @@
 		ii2 = (struct if_info *)malloc(sizeof(*ii2));
 		if (ii2 == NULL) {
 			logmsg(LOG_ERR, "malloc: %m");
+			pidfile_remove(pidfile_fh);
 			exit(1);
 		}
 		memcpy(ii2, ii, sizeof(*ii2));
@@ -273,8 +300,11 @@
 
 	case AF_LINK:
 		ll = (struct sockaddr_dl *)ifa->ifa_addr;
-		if (ll->sdl_type == IFT_ETHER)
+		switch (ll->sdl_type) {
+		case IFT_ETHER:
+		case IFT_L2VLAN:
 			bcopy(LLADDR(ll), ii->ii_eaddr, 6);
+		}
 		break;
 	}
 }
@@ -293,6 +323,7 @@
 	error = getifaddrs(&ifhead);
 	if (error) {
 		logmsg(LOG_ERR, "getifaddrs: %m");
+		pidfile_remove(pidfile_fh);
 		exit(1);
 	}
 	/*
@@ -339,8 +370,8 @@
 usage(void)
 {
 	(void)fprintf(stderr, "%s\n%s\n",
-	    "usage: rarpd -a [-dfsv] [-t directory]",
-	    "       rarpd [-dfsv] [-t directory] interface");
+	    "usage: rarpd -a [-dfsv] [-t directory] [-P pidfile]",
+	    "       rarpd [-dfsv] [-t directory] [-P pidfile] interface");
 	exit(1);
 }
 
@@ -361,6 +392,7 @@
 
 	if (fd == -1) {
 		logmsg(LOG_ERR, "%s: %m", device);
+		pidfile_remove(pidfile_fh);
 		exit(1);
 	}
 	return fd;
@@ -399,12 +431,12 @@
 	immediate = 1;
 	if (ioctl(fd, BIOCIMMEDIATE, &immediate) == -1) {
 		logmsg(LOG_ERR, "BIOCIMMEDIATE: %m");
-		exit(1);
+		goto rarp_open_err;
 	}
 	strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
 	if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) == -1) {
 		logmsg(LOG_ERR, "BIOCSETIF: %m");
-		exit(1);
+		goto rarp_open_err;
 	}
 	/*
 	 * Check that the data link layer is an Ethernet; this code won't
@@ -412,20 +444,24 @@
 	 */
 	if (ioctl(fd, BIOCGDLT, (caddr_t)&dlt) == -1) {
 		logmsg(LOG_ERR, "BIOCGDLT: %m");
-		exit(1);
+		goto rarp_open_err;
 	}
 	if (dlt != DLT_EN10MB) {
 		logmsg(LOG_ERR, "%s is not an ethernet", device);
-		exit(1);
+		goto rarp_open_err;
 	}
 	/*
 	 * Set filter program.
 	 */
 	if (ioctl(fd, BIOCSETF, (caddr_t)&filter) == -1) {
 		logmsg(LOG_ERR, "BIOCSETF: %m");
-		exit(1);
+		goto rarp_open_err;
 	}
 	return fd;
+
+rarp_open_err:
+	pidfile_remove(pidfile_fh);
+	exit(1);
 }
 
 /*
@@ -480,16 +516,16 @@
 
 	if (iflist == NULL) {
 		logmsg(LOG_ERR, "no interfaces");
-		exit(1);
+		goto rarpd_loop_err;
 	}
 	if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t)&bufsize) == -1) {
 		logmsg(LOG_ERR, "BIOCGBLEN: %m");
-		exit(1);
+		goto rarpd_loop_err;
 	}
 	buf = malloc(bufsize);
 	if (buf == NULL) {
 		logmsg(LOG_ERR, "malloc: %m");
-		exit(1);
+		goto rarpd_loop_err;
 	}
 
 	while (1) {
@@ -509,7 +545,7 @@
 			if (errno == EINTR)
 				continue;
 			logmsg(LOG_ERR, "select: %m");
-			exit(1);
+			goto rarpd_loop_err;
 		}
 		for (ii = iflist; ii != NULL; ii = ii->ii_next) {
 			fd = ii->ii_fd;
@@ -537,6 +573,11 @@
 		}
 	}
 #undef bhp
+	return;
+
+rarpd_loop_err:
+	pidfile_remove(pidfile_fh);
+	exit(1);
 }
 
 /*
@@ -562,12 +603,12 @@
 	else {
 		if (chdir(tftp_dir) == -1) {
 			logmsg(LOG_ERR, "chdir: %s: %m", tftp_dir);
-			exit(1);
+			goto rarp_bootable_err;
 		}
 		d = opendir(".");
 		if (d == NULL) {
 			logmsg(LOG_ERR, "opendir: %m");
-			exit(1);
+			goto rarp_bootable_err;
 		}
 		dd = d;
 	}
@@ -575,6 +616,10 @@
 		if (strncmp(dent->d_name, ipname, 8) == 0)
 			return 1;
 	return 0;
+
+rarp_bootable_err:
+	pidfile_remove(pidfile_fh);
+	exit(1);
 }
 
 /*
@@ -678,6 +723,7 @@
 	r = socket(PF_ROUTE, SOCK_RAW, 0);
 	if (r == -1) {
 		logmsg(LOG_ERR, "raw route socket: %m");
+		pidfile_remove(pidfile_fh);
 		exit(1);
 	}
 	pid = getpid();
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rpc.lockd/kern.c
--- a/head/usr.sbin/rpc.lockd/kern.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rpc.lockd/kern.c	Wed Jul 25 16:29:58 2012 +0300
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/rpc.lockd/kern.c 228990 2011-12-30 10:58:14Z uqs $");
+__FBSDID("$FreeBSD: head/usr.sbin/rpc.lockd/kern.c 235822 2012-05-23 06:49:50Z delphij $");
 
 #include <sys/param.h>
 #include <sys/mount.h>
@@ -595,7 +595,7 @@
 	syslog(LOG_DEBUG, "fh_len %d, fh %s\n", (int)mp->lm_fh_len, buf);
 
 	/* Show flock structure. */
-	syslog(LOG_DEBUG, "start %qu; len %qu; pid %lu; type %d; whence %d\n",
+	syslog(LOG_DEBUG, "start %llu; len %llu; pid %lu; type %d; whence %d\n",
 	    (unsigned long long)mp->lm_fl.l_start,
 	    (unsigned long long)mp->lm_fl.l_len, (u_long)mp->lm_fl.l_pid,
 	    mp->lm_fl.l_type, mp->lm_fl.l_whence);
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rtadvctl/rtadvctl.8
--- a/head/usr.sbin/rtadvctl/rtadvctl.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rtadvctl/rtadvctl.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 .\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/rtadvctl/rtadvctl.8 224148 2011-07-17 20:47:34Z gjb $
+.\" $FreeBSD: head/usr.sbin/rtadvctl/rtadvctl.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd July 16, 2011
 .Dt RTADVCTL 8
@@ -31,7 +31,8 @@
 .Sh NAME
 .Nm rtadvctl
 .Nd control program for
-.Xr rtadvd 8 daemon
+.Xr rtadvd 8
+daemon
 .Sh SYNOPSIS
 .Nm
 .Op Fl v
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rtadvd/rtadvd.8
--- a/head/usr.sbin/rtadvd/rtadvd.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rtadvd/rtadvd.8	Wed Jul 25 16:29:58 2012 +0300
@@ -27,7 +27,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/rtadvd/rtadvd.8 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/rtadvd/rtadvd.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd July 14, 2011
 .Dt RTADVD 8
@@ -140,7 +140,7 @@
 .It Fl p
 Specify an alternative file in which to store the process ID.
 The default is
-.Pa /var/run/rtadvd.pid.
+.Pa /var/run/rtadvd.pid .
 .It Fl R
 Accept router renumbering requests.
 If you enable it, certain IPsec setup is suggested for security reasons.
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/rtprio/rtprio.c
--- a/head/usr.sbin/rtprio/rtprio.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/rtprio/rtprio.c	Wed Jul 25 16:29:58 2012 +0300
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/usr.sbin/rtprio/rtprio.c 228917 2011-12-27 20:03:57Z delphij $");
+__FBSDID("$FreeBSD: head/usr.sbin/rtprio/rtprio.c 235293 2012-05-11 21:52:05Z delphij $");
 
 #include <sys/param.h>
 #include <sys/rtprio.h>
@@ -109,9 +109,12 @@
 		if (argv[2][0] == '-') {
 			proc = parseint(argv[2], "pid");
 			proc = abs(proc);
-			if (rtprio(RTP_SET, proc, &rtp) != 0)
-				err(1, "RTP_SET");
-		} else {
+		}
+
+		if (rtprio(RTP_SET, proc, &rtp) != 0)
+			err(1, "RTP_SET");
+
+		if (proc == 0) {
 			execvp(argv[2], &argv[2]);
 			err(1, "execvp: %s", argv[2]);
 		}
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/setfib/setfib.1
--- a/head/usr.sbin/setfib/setfib.1	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/setfib/setfib.1	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/setfib/setfib.1 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/setfib/setfib.1 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd April 9, 2008
 .Dt SETFIB 1
@@ -45,7 +45,7 @@
 The table number
 .Dq Ar fib
 will be used by default for all sockets started by this
-process or descendents.
+process or descendants.
 .Sh ENVIRONMENT
 The
 .Ev PATH
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/smbmsg/smbmsg.8
--- a/head/usr.sbin/smbmsg/smbmsg.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/smbmsg/smbmsg.8	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/smbmsg/smbmsg.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd May 16, 2004
 .Dt SMBMSG 8
@@ -70,7 +70,7 @@
 The only valid additional option for this modus of operation (besides
 the
 .Fl p
-option that choses the modus) is
+option that chooses the modus) is
 .Fl f Ar dev .
 See below for a description.
 .Pp
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/syslogd/syslogd.8
--- a/head/usr.sbin/syslogd/syslogd.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/syslogd/syslogd.8	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)syslogd.8	8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: head/usr.sbin/syslogd/syslogd.8 232986 2012-03-14 21:26:06Z sbruno $
+.\" $FreeBSD: head/usr.sbin/syslogd/syslogd.8 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd May 13, 2008
 .Dt SYSLOGD 8
@@ -344,7 +344,7 @@
 The date and time are taken from the received message.
 If the format of the timestamp field is incorrect,
 time obtained from the local host is used instead.
-This can be overriden by the
+This can be overridden by the
 .Fl T
 flag.
 .Sh FILES
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/tcpdump/tcpdump/Makefile
--- a/head/usr.sbin/tcpdump/tcpdump/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/tcpdump/tcpdump/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/usr.sbin/tcpdump/tcpdump/Makefile 235530 2012-05-17 05:11:57Z delphij $
 
 .include <bsd.own.mk>
 
@@ -8,10 +8,11 @@
 PROG=	tcpdump
 
 SRCS =	addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c \
-        ipproto.c nlpid.c l2vpn.c machdep.c parsenfsfh.c \
-	print-802_11.c print-ap1394.c print-ah.c print-arcnet.c \
+        ipproto.c nlpid.c l2vpn.c machdep.c parsenfsfh.c in_cksum.c \
+	print-802_11.c print-802_15_4.c print-ap1394.c print-ah.c print-arcnet.c \
 	print-aodv.c print-arp.c print-ascii.c print-atalk.c print-atm.c \
-	print-beep.c print-bfd.c print-bgp.c print-bootp.c print-cdp.c \
+	print-beep.c print-bfd.c print-bgp.c print-bootp.c print-bt.c \
+	print-carp.c print-cdp.c \
 	print-cfm.c print-chdlc.c print-cip.c print-cnfp.c print-dccp.c \
 	print-decnet.c print-domain.c print-dtp.c print-dvmrp.c print-enc.c \
 	print-egp.c print-eap.c print-eigrp.c \
@@ -24,8 +25,9 @@
 	print-lwapp.c print-lwres.c print-mobile.c print-mpls.c print-msdp.c \
 	print-mpcp.c \
 	print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
-	print-pgm.c print-pim.c print-ppp.c print-pppoe.c \
+	print-pgm.c print-pim.c print-ppi.c print-ppp.c print-pppoe.c \
 	print-pptp.c print-radius.c print-raw.c print-rip.c \
+	print-rpki-rtr.c \
 	print-rrcp.c print-rsvp.c print-rx.c print-sctp.c print-sflow.c \
 	print-sip.c print-sl.c print-sll.c \
 	print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
@@ -43,7 +45,8 @@
 
 .if ${MK_INET6_SUPPORT} != "no"
 SRCS+=	print-ip6.c print-ip6opts.c print-mobility.c print-ripng.c \
-	print-icmp6.c print-frag6.c print-rt6.c print-ospf6.c print-dhcp6.c
+	print-icmp6.c print-babel.c print-frag6.c print-rt6.c print-ospf6.c \
+	print-dhcp6.c
 CFLAGS+=	-DINET6
 .endif
 .if ${MACHINE_CPUARCH} != "i386"
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/tcpdump/tcpdump/config.h
--- a/head/usr.sbin/tcpdump/tcpdump/config.h	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/tcpdump/tcpdump/config.h	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-/* $FreeBSD$ */
+/* $FreeBSD: head/usr.sbin/tcpdump/tcpdump/config.h 235530 2012-05-17 05:11:57Z delphij $ */
 /* This is an edited copy of the config.h generated by configure. */
 
 /* config.h.  Generated from config.h.in by configure.  */
@@ -13,12 +13,6 @@
 /* Define if you enable support for the libsmi. */
 /* #undef LIBSMI */
 
-/* define if you have struct __res_state_ext */
-/* #undef HAVE_RES_STATE_EXT */
-
-/* define if your struct __res_state has the nsort member */
-/* #undef HAVE_NEW_RES_STATE */
-
 /* define if you have the addrinfo function. */
 #define HAVE_ADDRINFO 1
 
@@ -28,15 +22,6 @@
 /* define ifyou have the h_errno variable. */
 #define HAVE_H_ERRNO 1
 
-/* define if IN6ADDRSZ is defined (XXX not used!) */
-#define HAVE_IN6ADDRSZ 1
-
-/* define if INADDRSZ is defined (XXX not used!) */
-#define HAVE_INADDRSZ 1
-
-/* define if RES_USE_INET6 is defined */
-#define HAVE_RES_USE_INET6 1
-
 /* define if you have struct sockaddr_storage */
 #define HAVE_SOCKADDR_STORAGE 1
 
@@ -73,9 +58,6 @@
 /* define if you have getrpcbynumber() */
 #define HAVE_GETRPCBYNUMBER 1
 
-/* AIX hack. */
-/* #undef _SUN */
-
 /* Workaround for missing 64-bit formats */
 /* #undef PRId64 */
 /* #undef PRIo64 */
@@ -113,6 +95,9 @@
 /* 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 `getnameinfo' function. */
 #define HAVE_GETNAMEINFO 1
 
@@ -173,6 +158,9 @@
 /* Define to 1 if you have the `pcap_lib_version' function. */
 #define HAVE_PCAP_LIB_VERSION 1
 
+/* Define to 1 if you have the `pcap_set_tstamp_type' function. */
+#define HAVE_PCAP_SET_TSTAMP_TYPE 1
+
 /* Define to 1 if you have the <pcap/usb.h> header file. */
 /* #undef HAVE_PCAP_USB_H */
 
@@ -182,6 +170,9 @@
 /* Define to 1 if you have the <rpc/rpcent.h> header file. */
 #define HAVE_RPC_RPCENT_H 1
 
+/* Define to 1 if you have the <rpc/rpc.h> header file. */
+#define HAVE_RPC_RPC_H 1
+
 /* Define to 1 if you have the `setlinebuf' function. */
 #define HAVE_SETLINEBUF 1
 
@@ -245,6 +236,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #define HAVE_UNISTD_H 1
 
+/* Define to 1 if you have the `vfork' function. */
+#define HAVE_VFORK 1
+
 /* Define to 1 if you have the `vfprintf' function. */
 #define HAVE_VFPRINTF 1
 
@@ -284,21 +278,6 @@
 /* return value of signal handlers */
 #define RETSIGVAL 
 
-/* The size of `char', as computed by sizeof. */
-#undef SIZEOF_CHAR
-
-/* The size of `int', as computed by sizeof. */
-#undef SIZEOF_INT
-
-/* The size of `long', as computed by sizeof. */
-#undef SIZEOF_LONG
-
-/* The size of `long long', as computed by sizeof. */
-#undef SIZEOF_LONG_LONG
-
-/* The size of `short', as computed by sizeof. */
-#undef SIZEOF_SHORT
-
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
@@ -311,6 +290,9 @@
 /* needed on HP-UX */
 /* #undef _HPUX_SOURCE */
 
+/* define on AIX to get certain functions */
+/* #undef _SUN */
+
 /* define if your compiler allows __attribute__((format)) to be applied to
    function pointers */
 #define __ATTRIBUTE___FORMAT_OK_FOR_FUNCTION_POINTERS 1
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/tcpdump/tcpdump/tcpdump.1
--- a/head/usr.sbin/tcpdump/tcpdump/tcpdump.1	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/tcpdump/tcpdump/tcpdump.1	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-.\" $FreeBSD: head/usr.sbin/tcpdump/tcpdump/tcpdump.1 233648 2012-03-29 05:02:12Z eadler $
+.\" $FreeBSD: head/usr.sbin/tcpdump/tcpdump/tcpdump.1 235530 2012-05-17 05:11:57Z delphij $
 .\" @(#) $Header: /tcpdump/master/tcpdump/tcpdump.1.in,v 1.2 2008-11-09 23:35:03 mcr Exp $ (LBL)
 .\"
 .\"	$NetBSD: tcpdump.8,v 1.9 2003/03/31 00:18:17 perry Exp $
@@ -30,7 +30,7 @@
 .na
 .B tcpdump
 [
-.B \-AbdDefIKlLnNOpqRStuUvxX
+.B \-AbdDefhHIJKlLnNOpqRStuUvxX
 ] [
 .B \-B
 .I buffer_size
@@ -57,6 +57,10 @@
 .I interface
 ]
 [
+.B \-j
+.I tstamp_type
+]
+[
 .B \-m
 .I module
 ]
@@ -272,7 +276,7 @@
 The ability to decrypt packets is only present if \fItcpdump\fP was compiled
 with cryptography enabled.
 .IP
-\fIsecret\fP is the ASCII text for ESP secret key.
+\fIsecret\fP is the ASCII text for ESP secret key. 
 If preceded by 0x, then a hex value will be read.
 .IP
 The option assumes RFC2406 ESP, not RFC1827 ESP.
@@ -284,7 +288,7 @@
 and other occasions.
 .IP
 In addition to the above syntax, the syntax \fIfile name\fP may be used
-to have tcpdump read the provided file in. The file is opened upon
+to have tcpdump read the provided file in. The file is opened upon 
 receiving the first ESP packet, so any special permissions that tcpdump
 may have been given should already have been given up.
 .TP
@@ -320,6 +324,13 @@
 .B \-C
 option, filenames will take the form of `\fIfile\fP<count>'.
 .TP
+.B \-h
+Print the tcpdump and libpcap version strings, print a usage message,
+and exit.
+.TP
+.B \-H
+Attempt to detect 802.11s draft mesh headers.
+.TP
 .B \-i
 Listen on \fIinterface\fP.
 If unspecified, \fItcpdump\fP searches the system interface list for the
@@ -360,6 +371,18 @@
 is specified, only those link-layer types available when in monitor mode
 will be shown.
 .TP
+.B \-j
+Set the time stamp type for the capture to \fItstamp_type\fP.  The names
+to use for the time stamp types are given in
+.BR pcap-tstamp-type (7);
+not all the types listed there will necessarily be valid for any given
+interface.
+.TP
+.B \-J
+List the supported time stamp types for the interface and exit.  If the
+time stamp type cannot be set for the interface, no time stamp types are
+listed.
+.TP
 .B \-K
 Don't attempt to verify IP, TCP, or UDP checksums.  This is useful for
 interfaces that perform some or all of those checksum calculation in
@@ -540,16 +563,16 @@
 for a description of the file format.
 .TP
 .B \-W
-Used in conjunction with the
-.B \-C
+Used in conjunction with the 
+.B \-C 
 option, this will limit the number
 of files created to the specified number, and begin overwriting files
-from the beginning, thus creating a 'rotating' buffer.
+from the beginning, thus creating a 'rotating' buffer. 
 In addition, it will name
 the files with enough leading 0s to support the maximum number of
 files, allowing them to sort correctly.
 .IP
-Used in conjunction with the
+Used in conjunction with the 
 .B \-G
 option, this will limit the number of rotated dump files that get
 created, exiting with status 0 when reaching the limit. If used with
@@ -559,7 +582,7 @@
 .B \-x
 When parsing and printing,
 in addition to printing the headers of each packet, print the data of
-each packet (minus its link level header) in hex.
+each packet (minus its link level header) in hex. 
 The smaller of the entire packet or
 .I snaplen
 bytes will be printed.  Note that this is the entire link-layer
@@ -616,7 +639,10 @@
 and execute the command that you want.
 .TP
 .B \-Z
-Drops privileges (if root) and changes user ID to
+If
+.I tcpdump
+is running as root, after opening the capture device or input savefile,
+but before opening any savefiles for output, change the user ID to
 .I user
 and the group ID to the primary group of
 .IR user .
@@ -872,8 +898,8 @@
 \fISrc\fP and \fIdst\fP are the source and destination IP
 addresses and ports.
 \fIFlags\fP are some combination of S (SYN),
-F (FIN), P (PUSH), R (RST), W (ECN CWR) or E (ECN-Echo), or a single
-`.' (no flags).
+F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) or
+`.' (ACK), or `none' if no flags are set.
 \fIData-seqno\fP describes the portion of sequence space covered
 by the data in this packet (see example below).
 \fIAck\fP is sequence number of the next data expected the other
@@ -920,8 +946,7 @@
 Csam replies with a similar packet except it includes a piggy-backed
 ack for rtsg's SYN.
 Rtsg then acks csam's SYN.
-The `.' means no
-flags were set.
+The `.' means the ACK flag was set.
 The packet contained no data so there is no data sequence number.
 Note that the ack sequence
 number is a small integer (1).
@@ -1156,7 +1181,7 @@
 .PP
 This can be demonstrated as:
 .RS
-.B
+.B 
      tcpdump -i xl0 'tcp[tcpflags] & tcp-push != 0'
 .RE
 .PP
@@ -1267,7 +1292,6 @@
 If the
 `question' section doesn't contain exactly one entry, `[\fIn\fPq]'
 is printed.
-
 .HD
 SMB/CIFS decoding
 .LP
@@ -1275,19 +1299,18 @@
 on UDP/137, UDP/138 and TCP/139.
 Some primitive decoding of IPX and
 NetBEUI SMB data is also done.
-
+.LP
 By default a fairly minimal decode is done, with a much more detailed
 decode done if -v is used.
 Be warned that with -v a single SMB packet
 may take up a page or more, so only use -v if you really want all the
 gory details.
-
-For information on SMB packet formats and what all te fields mean see
+.LP
+For information on SMB packet formats and what all the fields mean see
 www.cifs.org or the pub/samba/specs/ directory on your favorite
 samba.org mirror site.
 The SMB patches were written by Andrew Tridgell
 (tridge at samba.org).
-
 .HD
 NFS Requests and Replies
 .LP
@@ -1413,11 +1436,11 @@
 AFS and RX.
 .LP
 If the -v (verbose) flag is given twice, acknowledgement packets and
-additional header information is printed, such as the RX call ID,
+additional header information is printed, such as the the RX call ID,
 call number, sequence number, serial number, and the RX packet flags.
 .LP
 If the -v flag is given twice, additional information is printed,
-such as the RX call ID, serial number, and the RX packet flags.
+such as the the RX call ID, serial number, and the RX packet flags.
 The MTU negotiation information is also printed from RX ack packets.
 .LP
 If the -v flag is given three times, the security index and service id
@@ -1640,7 +1663,7 @@
 serviced the `new packet' interrupt.
 .SH "SEE ALSO"
 stty(1), pcap(3PCAP), bpf(4), nit(4P), pcap-savefile(5),
-pcap-filter(7)
+pcap-filter(7), pcap-tstamp-type(7)
 .SH AUTHORS
 The original authors are:
 .LP
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/traceroute6/traceroute6.c
--- a/head/usr.sbin/traceroute6/traceroute6.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/traceroute6/traceroute6.c	Wed Jul 25 16:29:58 2012 +0300
@@ -72,7 +72,7 @@
 static char sccsid[] = "@(#)traceroute.c	8.1 (Berkeley) 6/6/93";
 #endif
 static const char rcsid[] =
-  "$FreeBSD$";
+  "$FreeBSD: head/usr.sbin/traceroute6/traceroute6.c 235138 2012-05-08 15:18:35Z ume $";
 #endif /* not lint */
 
 /*
@@ -1448,7 +1448,8 @@
 {
 
 	fprintf(stderr,
-"usage: traceroute6 [-dIlnNrUv] [-f firsthop] [-g gateway] [-m hoplimit]\n"
-"       [-p port] [-q probes] [-s src] [-w waittime] target [datalen]\n");
+"usage: traceroute6 [-adIlnNrUv] [-A as_server] [-f firsthop] [-g gateway]\n"
+"       [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"
+"       [datalen]\n");
 	exit(1);
 }
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/usbdump/usbdump.8
--- a/head/usr.sbin/usbdump/usbdump.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/usbdump/usbdump.8	Wed Jul 25 16:29:58 2012 +0300
@@ -23,9 +23,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/usbdump/usbdump.8 231835 2012-02-16 21:18:36Z hselasky $
+.\" $FreeBSD: head/usr.sbin/usbdump/usbdump.8 234655 2012-04-24 14:06:07Z hselasky $
 .\"
-.Dd February 16, 2012
+.Dd April 24, 2012
 .Dt USBDUMP 8
 .Os
 .Sh NAME
@@ -39,6 +39,8 @@
 .Op Fl v
 .Op Fl w Ar file
 .Op Fl f Ar filter
+.Op Fl b Ar file
+.Op Fl h
 .Sh DESCRIPTION
 The
 .Nm
@@ -46,12 +48,17 @@
 .Pp
 The following options are accepted:
 .Bl -tag -width ".Fl f Ar file"
+.It Fl b Ar file
+Store data part of the USB trace in binary format to the given
+.Ar file .
+This option also works with the -r and -f options.
 .It Fl i Ar ifname
 Listen on USB bus interface
 .Ar ifname .
 .It Fl r Ar file
 Read the raw packets from
 .Ar file .
+This option also works with the -f option.
 .It Fl s Ar snaplen
 Snapshot
 .Ar snaplen
@@ -62,6 +69,7 @@
 .It Fl w Ar file
 Write the raw packets to
 .Ar file .
+This option also works with the -s and -v options.
 .It Fl f Ar filter
 The filter argument consists of either one or two numbers separated by a dot.
 The first indicates the device unit number which should be traced.
@@ -72,6 +80,8 @@
 A device unit or endpoint value of -1 means ignore this field.
 If no filters are specified, all packets are passed through using the default -1,-1 filter.
 This option can be specified multiple times.
+.It Fl h
+This option displays a summary of the command line options.
 .El
 .Sh EXAMPLES
 Capture the USB raw packets on usbus2:
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/usbdump/usbdump.c
--- a/head/usr.sbin/usbdump/usbdump.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/usbdump/usbdump.c	Wed Jul 25 16:29:58 2012 +0300
@@ -26,7 +26,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  * THE POSSIBILITY OF SUCH DAMAGES.
  *
- * $FreeBSD: head/usr.sbin/usbdump/usbdump.c 233039 2012-03-16 17:30:22Z hselasky $
+ * $FreeBSD: head/usr.sbin/usbdump/usbdump.c 238279 2012-07-09 07:25:09Z hrs $
  */
 
 #include <sys/param.h>
@@ -82,6 +82,8 @@
 	int		wfd;
 	/* for -r option */
 	int		rfd;
+	/* for -b option */
+	int		bfd;
 };
 
 struct usbcap_filehdr {
@@ -112,6 +114,8 @@
 static const char *i_arg = "usbus0";
 static const char *r_arg = NULL;
 static const char *w_arg = NULL;
+static const char *b_arg = NULL;
+static struct usbcap uc;
 static const char *errstr_table[USB_ERR_MAX] = {
 	[USB_ERR_NORMAL_COMPLETION]	= "0",
 	[USB_ERR_PENDING_REQUESTS]	= "PENDING_REQUESTS",
@@ -255,6 +259,22 @@
 	pprog->bf_insns = dynamic_insn;
 }
 
+static int
+match_filter(int unit, int endpoint)
+{
+	struct usb_filt *puf;
+
+	if (STAILQ_FIRST(&usb_filt_head) == NULL)
+		return (1);
+
+	STAILQ_FOREACH(puf, &usb_filt_head, entry) {
+		if ((puf->unit == -1 || puf->unit == unit) &&
+		    (puf->endpoint == -1 || puf->endpoint == endpoint))
+			return (1);
+	}
+	return (0);
+}
+
 static void
 free_filter(struct bpf_program *pprog)
 {
@@ -462,28 +482,33 @@
 	up->up_packet_count = le32toh(up->up_packet_count);
 	up->up_endpoint = le32toh(up->up_endpoint);
 
+	if (!match_filter(up->up_address, up->up_endpoint))
+		return;
+
 	tv.tv_sec = hdr->ts_sec;
 	tv.tv_usec = hdr->ts_usec;
 	tm = localtime(&tv.tv_sec);
 
 	len = strftime(buf, sizeof(buf), "%H:%M:%S", tm);
 
-	printf("%.*s.%06ld usbus%d.%d %s-%s-EP=%08x,SPD=%s,NFR=%d,SLEN=%d,IVAL=%d%s%s\n",
-	    (int)len, buf, tv.tv_usec,
-	    (int)up->up_busunit, (int)up->up_address,
-	    (up->up_type == USBPF_XFERTAP_SUBMIT) ? "SUBM" : "DONE",
-	    xfertype_table[up->up_xfertype],
-	    (unsigned int)up->up_endpoint,
-	    usb_speedstr(up->up_speed),
-	    (int)up->up_frames,
-	    (int)(up->up_totlen - USBPF_HDR_LEN -
-	    (USBPF_FRAME_HDR_LEN * up->up_frames)),
-	    (int)up->up_interval,
-	    (up->up_type == USBPF_XFERTAP_DONE) ? ",ERR=" : "",
-	    (up->up_type == USBPF_XFERTAP_DONE) ?
-	    usb_errstr(up->up_error) : "");
+	if (verbose >= 0) {
+		printf("%.*s.%06ld usbus%d.%d %s-%s-EP=%08x,SPD=%s,NFR=%d,SLEN=%d,IVAL=%d%s%s\n",
+		    (int)len, buf, tv.tv_usec,
+		    (int)up->up_busunit, (int)up->up_address,
+		    (up->up_type == USBPF_XFERTAP_SUBMIT) ? "SUBM" : "DONE",
+		    xfertype_table[up->up_xfertype],
+		    (unsigned int)up->up_endpoint,
+		    usb_speedstr(up->up_speed),
+		    (int)up->up_frames,
+		    (int)(up->up_totlen - USBPF_HDR_LEN -
+		    (USBPF_FRAME_HDR_LEN * up->up_frames)),
+		    (int)up->up_interval,
+		    (up->up_type == USBPF_XFERTAP_DONE) ? ",ERR=" : "",
+		    (up->up_type == USBPF_XFERTAP_DONE) ?
+		    usb_errstr(up->up_error) : "");
+	}
 
-	if (verbose >= 1) {
+	if (verbose >= 1 || b_arg != NULL) {
 		for (x = 0; x != up->up_frames; x++) {
 			const struct usbpf_framehdr *uf;
 			uint32_t framelen;
@@ -498,10 +523,12 @@
 			framelen = le32toh(uf->length);
 			flags = le32toh(uf->flags);
 
-			printf(" frame[%u] %s %d bytes\n",
-			    (unsigned int)x,
-			    (flags & USBPF_FRAMEFLAG_READ) ? "READ" : "WRITE",
-			    (int)framelen);
+			if (verbose >= 1) {
+				printf(" frame[%u] %s %d bytes\n",
+				    (unsigned int)x,
+				    (flags & USBPF_FRAMEFLAG_READ) ? "READ" : "WRITE",
+				    (int)framelen);
+			}
 
 			if (flags & USBPF_FRAMEFLAG_DATA_FOLLOWS) {
 
@@ -515,7 +542,15 @@
 				    (int)framelen < 0 || (int)ptr_len < 0)
 					break;
 
-				hexdump(ptr, framelen);
+				if (b_arg != NULL) {
+					struct usbcap *p = &uc;
+					int ret;
+					ret = write(p->bfd, ptr, framelen);
+					if (ret != (int)framelen)
+						err(EXIT_FAILURE, "Could not write binary data");
+				}
+				if (verbose >= 1)
+					hexdump(ptr, framelen);
 
 				ptr += tot_frame_len;
 			}
@@ -592,7 +627,7 @@
 		if (next <= ptr)
 			err(EXIT_FAILURE, "Invalid length");
 
-		if (w_arg == NULL || r_arg != NULL) {
+		if (verbose >= 0 || r_arg != NULL || b_arg != NULL) {
 			print_apacket(&temp, ptr +
 			    temp.hdrlen, temp.caplen);
 		}
@@ -738,7 +773,9 @@
 	fprintf(stderr, FMT, "-r <file>", "Read the raw packets from file");
 	fprintf(stderr, FMT, "-s <snaplen>", "Snapshot bytes from each packet");
 	fprintf(stderr, FMT, "-v", "Increase the verbose level");
+	fprintf(stderr, FMT, "-b <file>", "Save raw version of all recorded data to file");
 	fprintf(stderr, FMT, "-w <file>", "Write the raw packets to file");
+	fprintf(stderr, FMT, "-h", "Display summary of command line options");
 #undef FMT
 	exit(EX_USAGE);
 }
@@ -750,7 +787,7 @@
 	struct bpf_program total_prog;
 	struct bpf_stat us;
 	struct bpf_version bv;
-	struct usbcap uc, *p = &uc;
+	struct usbcap *p = &uc;
 	struct ifreq ifr;
 	long snapshot = 192;
 	uint32_t v;
@@ -758,12 +795,12 @@
 	int o;
 	int filt_unit;
 	int filt_ep;
+	int s;
+	int ifindex;
 	const char *optstring;
 	char *pp;
 
-	memset(&uc, 0, sizeof(struct usbcap));
-
-	optstring = "i:r:s:vw:f:";
+	optstring = "b:hi:r:s:vw:f:";
 	while ((o = getopt(argc, argv, optstring)) != -1) {
 		switch (o) {
 		case 'i':
@@ -784,6 +821,9 @@
 			if (snapshot == 0)
 				snapshot = -1;
 			break;
+		case 'b':
+			b_arg = optarg;
+			break;
 		case 'v':
 			verbose++;
 			break;
@@ -811,6 +851,22 @@
 		}
 	}
 
+	if (b_arg != NULL) {
+		p->bfd = open(b_arg, O_CREAT | O_TRUNC |
+		    O_WRONLY, S_IRUSR | S_IWUSR);
+		if (p->bfd < 0) {
+			err(EXIT_FAILURE, "Could not open "
+			    "'%s' for write", b_arg);
+		}
+	}
+
+	/*
+	 * Require more verbosity to print anything when -w or -b is
+	 * specified on the command line:
+	 */
+	if (w_arg != NULL || b_arg != NULL)
+		verbose--;
+
 	if (r_arg != NULL) {
 		read_file(p);
 		exit(EXIT_SUCCESS);
@@ -833,9 +889,20 @@
 	/* clear ifr structure */
 	memset(&ifr, 0, sizeof(ifr));
 
+	/* Try to create usbusN interface if it is not available. */
+	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+	if (s < 0)
+		errx(EXIT_FAILURE, "Could not open a socket");
+	ifindex = if_nametoindex(i_arg);
+	if (ifindex == 0) {
+		(void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
+		if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
+			errx(EXIT_FAILURE, "Invalid bus interface: %s", i_arg);
+	}
+
 	for ( ; v >= USBPF_HDR_LEN; v >>= 1) {
 		(void)ioctl(fd, BIOCSBLEN, (caddr_t)&v);
-		(void)strncpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
+		(void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
 		if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
 			break;
 	}
@@ -876,12 +943,25 @@
 	printf("%d packets received by filter\n", us.bs_recv);
 	printf("%d packets dropped by kernel\n", us.bs_drop);
 
+	/*
+	 * Destroy the usbusN interface only if it was created by
+	 * usbdump(8).  Ignore when it was already destroyed.
+	 */
+	if (ifindex == 0 && if_nametoindex(i_arg) > 0) {
+		(void)strlcpy(ifr.ifr_name, i_arg, sizeof(ifr.ifr_name));
+		if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
+			warn("SIOCIFDESTROY ioctl failed");
+	}
+	close(s);
+
 	if (p->fd > 0)
 		close(p->fd);
 	if (p->rfd > 0)
 		close(p->rfd);
 	if (p->wfd > 0)
 		close(p->wfd);
+	if (p->bfd > 0)
+		close(p->bfd);
 
 	return (EXIT_SUCCESS);
 }
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/utx/utx.8
--- a/head/usr.sbin/utx/utx.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/utx/utx.8	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/utx/utx.8 233455 2012-03-25 09:18:34Z joel $
+.\" $FreeBSD: head/usr.sbin/utx/utx.8 235967 2012-05-25 03:46:56Z wblock $
 .\"
 .Dd February 11, 2012
 .Dt UTX 8
@@ -94,7 +94,7 @@
 .Sh SEE ALSO
 .Xr getent 1 ,
 .Xr w 1 ,
-.Xr pututxline 3 .
+.Xr pututxline 3
 .Sh HISTORY
 The
 .Nm
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/vidcontrol/vidcontrol.c
--- a/head/usr.sbin/vidcontrol/vidcontrol.c	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/vidcontrol/vidcontrol.c	Wed Jul 25 16:29:58 2012 +0300
@@ -33,7 +33,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-  "$FreeBSD: head/usr.sbin/vidcontrol/vidcontrol.c 228990 2011-12-30 10:58:14Z uqs $";
+  "$FreeBSD: head/usr.sbin/vidcontrol/vidcontrol.c 237777 2012-06-29 12:55:36Z ache $";
 #endif /* not lint */
 
 #include <ctype.h>
@@ -1192,15 +1192,13 @@
 		fprintf(stderr, "\033[=T");
 	else if (strcmp(arg, "cons25") == 0)
 		fprintf(stderr, "\033[=1T");
-	else
-		usage();
 }
 
 
 int
 main(int argc, char **argv)
 {
-	char	*font, *type;
+	char    *font, *type, *termmode;
 	int	dumpmod, dumpopt, opt;
 	int	reterr;
 
@@ -1212,6 +1210,7 @@
 		err(1, "must be on a virtual console");
 	dumpmod = 0;
 	dumpopt = DUMP_FBF;
+	termmode = NULL;
 	while ((opt = getopt(argc, argv,
 	    "b:Cc:df:g:h:Hi:l:LM:m:pPr:S:s:T:t:x")) != -1)
 		switch(opt) {
@@ -1283,7 +1282,10 @@
 			set_console(optarg);
 			break;
 		case 'T':
-			set_terminal_mode(optarg);
+			if (strcmp(optarg, "xterm") != 0 &&
+			    strcmp(optarg, "cons25") != 0)
+				usage();
+			termmode = optarg;
 			break;
 		case 't':
 			set_screensaver_timeout(optarg);
@@ -1306,6 +1308,8 @@
 	}
 
 	video_mode(argc, argv, &optind);
+	if (termmode != NULL)
+		set_terminal_mode(termmode);
 
 	get_normal_colors(argc, argv, &optind);
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/Makefile.crypto
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/head/usr.sbin/wpa/Makefile.crypto	Wed Jul 25 16:29:58 2012 +0300
@@ -0,0 +1,121 @@
+# $FreeBSD: head/usr.sbin/wpa/Makefile.crypto 234759 2012-04-28 11:11:53Z bschmidt $
+
+.if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH)
+SRCS+=	crypto_openssl.c
+DPADD+=	${LIBSSL} ${LIBCRYPTO}
+LDADD+=	-lssl -lcrypto
+.else
+CFLAGS+=-DCONFIG_CRYPTO_INTERNAL
+SRCS+=	crypto_internal.c
+CONFIG_INTERNAL_AES=y
+CONFIG_INTERNAL_DES=y
+CONFIG_INTERNAL_MD4=y
+CONFIG_INTERNAL_MD5=y
+CONFIG_INTERNAL_RC4=y
+CONFIG_INTERNAL_SHA1=y
+CONFIG_INTERNAL_SHA256=y
+CONFIG_INTERNAL_TLS=y
+NEED_AES_ENC=true
+.endif
+
+.if defined(TLS_FUNCS)
+NEED_TLS_PRF=y
+.if defined(CONFIG_INTERNAL_TLS)
+CFLAGS+=-DCONFIG_INTERNAL_LIBTOMMATH \
+	-DCONFIG_TLS_INTERNAL_CLIENT
+SRCS+=	asn1.c \
+	bignum.c \
+	crypto_internal-cipher.c \
+	crypto_internal-modexp.c \
+	crypto_internal-rsa.c \
+	pkcs1.c \
+	pkcs5.c \
+	pkcs8.c \
+	rsa.c \
+	tls_internal.c \
+	tlsv1_common.c \
+	tlsv1_record.c \
+	tlsv1_cred.c \
+	tlsv1_client.c \
+	tlsv1_client_write.c \
+	tlsv1_client_read.c \
+	x509v3.c
+NEED_DES=y
+NEED_MD4=y
+NEED_RC4=y
+.else
+CFLAGS+=-DEAP_TLS_OPENSSL
+SRCS+=	tls_openssl.c
+.endif
+.endif
+
+.if defined(CONFIG_INTERNAL_AES)
+SRCS+=	aes-internal.c \
+	aes-internal-dec.c \
+	aes-internal-enc.c
+.endif
+
+.if defined(NEED_AES_CBC)
+SRCS+=	aes-cbc.c
+.endif
+
+.if defined(NEED_AES_EAX)
+SRCS+=	aes-eax.c
+NEED_AES_CTR=y
+.endif
+
+.if defined(NEED_AES_CTR)
+SRCS+=	aes-ctr.c
+.endif
+
+.if defined(NEED_AES_ENCBLOCK)
+SRCS+=	aes-encblock.c
+.endif
+
+.if defined(NEED_AES_OMAC1)
+SRCS+=	aes-omac1.c
+.endif
+
+.if defined(NEED_DES)
+.if defined(CONFIG_INTERNAL_DES)
+SRCS+=	des-internal.c
+.endif
+.endif
+
+.if defined(NEED_MD4)
+.if defined(CONFIG_INTERNAL_MD4)
+SRCS+=	md4-internal.c
+.endif
+.endif
+
+.if defined(CONFIG_INTERNAL_MD5)
+SRCS+=	md5-internal.c
+.endif
+
+.if defined(NEED_FIPS186_2_PRF)
+.if defined(CONFIG_INTERNAL_SHA1)
+SRCS+=	fips_prf_internal.c
+.else
+SRCS+=	fips_prf_openssl.c
+.endif
+.endif
+
+.if defined(CONFIG_INTERNAL_RC4)
+SRCS+=	rc4.c
+.endif
+
+.if defined(CONFIG_INTERNAL_SHA1)
+SRCS+=	sha1-internal.c
+.endif
+
+.if defined(NEED_SHA256)
+CFLAGS+=-DCONFIG_SHA256
+SRCS+=	sha256.c
+.if defined(CONFIG_INTERNAL_SHA256)
+SRCS+=	sha256-internal.c
+.endif
+.endif
+
+.if defined(NEED_TLS_PRF)
+SRCS+=	sha1-tlsprf.c
+.endif
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/Makefile.inc
--- a/head/usr.sbin/wpa/Makefile.inc	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/Makefile.inc	Wed Jul 25 16:29:58 2012 +0300
@@ -1,4 +1,4 @@
-# $FreeBSD$
+# $FreeBSD: head/usr.sbin/wpa/Makefile.inc 234756 2012-04-28 10:59:29Z bschmidt $
 
 BINDIR?=	/usr/sbin
 
@@ -7,17 +7,26 @@
 HOSTAPD_DISTDIR?=	${WPA_DISTDIR}/hostapd
 
 .PATH.c:${.CURDIR}/.. \
+	${WPA_DISTDIR}/src/ap \
 	${WPA_DISTDIR}/src/common \
 	${WPA_DISTDIR}/src/crypto \
+	${WPA_DISTDIR}/src/eapol_auth \
 	${WPA_DISTDIR}/src/eap_common \
+	${WPA_DISTDIR}/src/eap_peer \
+	${WPA_DISTDIR}/src/eap_server \
 	${WPA_DISTDIR}/src/eapol_supp \
 	${WPA_DISTDIR}/src/l2_packet \
+	${WPA_DISTDIR}/src/radius \
+	${WPA_DISTDIR}/src/rsn_supp \
+	${WPA_DISTDIR}/src/tls \
 	${WPA_DISTDIR}/src/utils
 
 CFLAGS+=-I${.CURDIR}
+CFLAGS+=-I${HOSTAPD_DISTDIR}
 CFLAGS+=-I${WPA_DISTDIR}/src
 CFLAGS+=-I${WPA_DISTDIR}/src/common
 CFLAGS+=-I${WPA_DISTDIR}/src/crypto
+CFLAGS+=-I${WPA_DISTDIR}/src/drivers
 CFLAGS+=-I${WPA_DISTDIR}/src/l2_packet
 CFLAGS+=-I${WPA_DISTDIR}/src/utils
 
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/hostapd/Makefile
--- a/head/usr.sbin/wpa/hostapd/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/hostapd/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,34 +1,60 @@
-# $FreeBSD$
+# $FreeBSD: head/usr.sbin/wpa/hostapd/Makefile 234786 2012-04-29 12:48:52Z bschmidt $
 
 .include "${.CURDIR}/../Makefile.inc"
 
 .PATH.c:${HOSTAPD_DISTDIR} \
-	${WPA_DISTDIR}/src/ap \
-	${WPA_DISTDIR}/src/eap_server \
-	${WPA_DISTDIR}/src/eap_common \
-	${WPA_DISTDIR}/src/eapol_auth \
-	${WPA_DISTDIR}/src/drivers \
-	${WPA_DISTDIR}/src/radius \
-	${WPA_DISTDIR}
+	${WPA_DISTDIR}/src/drivers
 
 PROG=	hostapd
-SRCS=	accounting.c aes-wrap.c ap_config.c \
-	ap_drv_ops.c ap_mlme.c authsrv.c \
-	chap.c common.c config_file.c ctrl_iface.c crypto_openssl.c \
-	ctrl_iface_ap.c drivers.c drv_callbacks.c dump_state.c \
-	eap_common.c eap_peap_common.c eap_register.c eap_server.c \
-	eap_server_gtc.c eap_server_identity.c eap_server_md5.c \
-	eap_server_methods.c eap_server_mschapv2.c eap_server_peap.c \
-	eap_server_tls.c eap_server_tls_common.c eap_server_ttls.c \
-	eapol_auth_dump.c eapol_auth_sm.c eloop.c hostapd.c ieee802_11_auth.c \
-	ieee802_11_common.c ieee802_11_ht.c ieee802_1x.c ip_addr.c \
-	md5.c main.c ms_funcs.c peerkey_auth.c pmksa_cache_auth.c \
-	preauth_auth.c radius.c radius_client.c sta_info.c \
-	sha1-pbkdf2.c sha1-tlsprf.c sha1-tprf.c sha1.c \
-	tkip_countermeasures.c utils.c \
-	vlan_init.c wpa_auth.c wpa_auth_glue.c wpa_auth_ie.c wpa_common.c \
-	wpa_debug.c wpabuf.c
-SRCS+=	l2_packet_freebsd.c driver_freebsd.c os_unix.c
+SRCS=	accounting.c \
+	aes-wrap.c \
+	ap_config.c \
+	ap_drv_ops.c \
+	ap_mlme.c \
+	authsrv.c \
+	base64.c \
+	chap.c \
+	common.c \
+	config_file.c \
+	ctrl_iface.c \
+	ctrl_iface_ap.c \
+	drivers.c \
+	drv_callbacks.c \
+	eap_common.c \
+	eap_peap_common.c \
+	eap_register.c \
+	eapol_auth_dump.c \
+	eapol_auth_sm.c \
+	eap_server.c \
+	eap_server_methods.c \
+	eloop.c \
+	hostapd.c \
+	ieee802_11_auth.c \
+	ieee802_11_common.c \
+	ieee802_1x.c \
+	ip_addr.c \
+	main.c \
+	md5.c \
+	ms_funcs.c \
+	os_unix.c \
+	peerkey_auth.c \
+	pmksa_cache_auth.c \
+	preauth_auth.c \
+	radius.c \
+	radius_client.c \
+	sha1-pbkdf2.c \
+	sha1.c \
+	sta_info.c \
+	tkip_countermeasures.c \
+	utils.c \
+	vlan_init.c \
+	wpa_auth.c \
+	wpa_auth_glue.c \
+	wpa_auth_ie.c \
+	wpa_common.c \
+	wpa_debug.c \
+	wpabuf.c
+SRCS+=	l2_packet_freebsd.c driver_freebsd.c
 
 MAN=	hostapd.8 hostapd.conf.5
 
@@ -38,16 +64,17 @@
 FILES=	hostapd.conf hostapd.eap_user hostapd.wpa_psk
 .endif
 
-CFLAGS+= -I${HOSTAPD_DISTDIR} -I${WPA_DISTDIR}/src/drivers
-
-CFLAGS+= -DCONFIG_DRIVER_BSD -DHOSTAPD
-CFLAGS+= -DCONFIG_DRIVER_RADIUS_ACL
+CFLAGS+=-DCONFIG_DRIVER_BSD \
+	-DHOSTAPD \
+	-DCONFIG_DRIVER_RADIUS_ACL \
+	-DCONFIG_RSN_PREAUTH \
+	-DCONFIG_PEERKEY
 .if ${MK_INET6} != "no"
 CFLAGS+= -DCONFIG_IPV6
 .endif
 #CFLAGS+= -g
-DPADD+=	${LIBPCAP} ${LIBSSL}
-LDADD+=	-lpcap -lssl
+DPADD+=	${LIBPCAP}
+LDADD+=	-lpcap
 
 # User customizations for wpa_supplicant/hostapd build environment
 CFLAGS+=${HOSTAPD_CFLAGS}
@@ -55,74 +82,63 @@
 LDADD+=${HOSTAPD_LDADD}
 #LDFLAGS+=${HOSTAPD_LDFLAGS}
 
-.if !empty(CFLAGS:M*-DEAP_SERVER)
-#SRCS+=	eap.c eap_methods.c eap_identity.c
+CFLAGS+=-DDPKCS12_FUNCS \
+	-DEAP_SERVER \
+	-DEAP_SERVER_GTC \
+	-DEAP_SERVER_IDENTITY \
+	-DEAP_SERVER_MD5 \
+	-DEAP_SERVER_MSCHAPV2 \
+	-DEAP_SERVER_PEAP \
+	-DEAP_SERVER_TLS \
+	-DEAP_SERVER_TTLS \
+	-DEAP_TLS_FUNCS \
+	-DCONFIG_NO_DUMP_STATE
+SRCS+=	dump_state.c \
+	eap_server_gtc.c \
+	eap_server_identity.c \
+	eap_server_md5.c \
+	eap_server_mschapv2.c \
+	eap_server_peap.c \
+	eap_server_tls.c \
+	eap_server_tls_common.c \
+	eap_server_ttls.c
+TLS_FUNCS=y
+NEED_SHA256=y
 
-.if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH)
-
-CFLAGS+=-DEAP_TLS -DEAP_PEAP -DEAP_MSCHAPv2 -DEAP_PSK \
-	-DEAP_TLS_FUNCS -DEAP_TLS_OPENSSL
-SRCS+=	crypto_openssl.c
-SRCS+=	eap_tls.c eap_peap.c eap_peap_common.c eap_mschapv2.c \
-	eap_psk.c eap_psk_common.c \
-	eap_tls_common.c tls_openssl.c ms_funcs.c chap.c
-
-CFLAGS+=-DEAP_TTLS -DEAP_MD5
-SRCS+=	eap_ttls.c eap_md5.c
-
-.if !empty(CFLAGS:M*-DEAP_GTC)
-SRCS+=	eap_gtc.c
+.if !empty(CFLAGS:M*-DEAP_SERVER_AKA)
+SRCS+=	eap_server_aka.c
+NEED_SIM_COMMON=y
 .endif
 
-.if !empty(CFLAGS:M*-DEAP_AKA)
-NEED_SIM_COMMON=	true
-SRCS+=	eap_aka.c
-.endif
-
-.if !empty(CFLAGS:M*-DEAP_SIM)
-NEED_SIM_COMMON=	true
-SRCS+=	eap_sim.c
+.if !empty(CFLAGS:M*-DEAP_SERVER_SIM)
+SRCS+=	eap_server_sim.c
+NEED_SIM_COMMON=y
 .endif
 
 .if defined(NEED_SIM_COMMON)
-SRCS+=	eap_sim_common.c eap_sim_db.c
+SRCS+=	eap_sim_common.c \
+	eap_sim_db.c
+NEED_AES_CBC=y
+NEED_FIPS186_2_PRF=y
 .endif
 
-.if !empty(CFLAGS:M*-DEAP_GPSK)
+.if !empty(CFLAGS:M*-DEAP_SERVER_GPSK)
 CFLAGS+=-DEAP_GPSK_SHA256
-SRCS+=	eap_gpsk.c eap_gpsk_common.c
-NEED_SHA256=	true
+SRCS+=	eap_server_gpsk.c \
+	eap_gpsk_common.c
+NEED_AES_OMAC1=y
 .endif
 
-.if !empty(CFLAGS:M*-DEAP_PAX)
-SRCS+=	eap_pax.c eap_pax_common.c
+.if !empty(CFLAGS:M*-DEAP_SERVER_PAX)
+SRCS+=	eap_server_pax.c \
+	eap_pax_common.c
 .endif
 
-.if !empty(CFLAGS:M*-DEAP_SAKE)
-SRCS+=	eap_sake.c eap_sake_common.c
+.if !empty(CFLAGS:M*-DEAP_SERVER_SAKE)
+SRCS+=	eap_server_sake.c \
+	eap_sake_common.c
 .endif
 
-DPADD+= ${LIBSSL} ${LIBCRYPTO}
-LDADD+= -lssl -lcrypto
-.else
-NEED_TLS_NONE=	true
-.endif
-
-.else
-NEED_TLS_NONE=	true
-.endif
-
-.if defined(NEED_SHA256)
-CFLAGS+=-DINTERNAL_SHA256
-SRCS+=	sha256.c
-.endif
-
-.if defined(NEED_TLS_NONE)
-CFLAGS+= -DEAP_TLS_NONE
-CFLAGS+= -DINTERNAL_AES
-CFLAGS+= -DINTERNAL_SHA1
-CFLAGS+= -DINTERNAL_MD5
-SRCS+=	tls_none.c
-.endif
+.include "${.CURDIR}/../Makefile.crypto"
 
 .include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/hostapd/hostapd.8
--- a/head/usr.sbin/wpa/hostapd/hostapd.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/hostapd/hostapd.8	Wed Jul 25 16:29:58 2012 +0300
@@ -22,9 +22,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: head/usr.sbin/wpa/hostapd/hostapd.8 231257 2012-02-09 08:33:04Z kevlo $
+.\" $FreeBSD: head/usr.sbin/wpa/hostapd/hostapd.8 238606 2012-07-18 23:32:12Z gjb $
 .\"
-.Dd October 26, 2007
+.Dd July 18, 2012
 .Dt HOSTAPD 8
 .Os
 .Sh NAME
@@ -111,7 +111,9 @@
 .Xr ath 4 ,
 .Xr ipw 4 ,
 .Xr iwi 4 ,
+.Xr mwl 4 ,
 .Xr ral 4 ,
+.Xr rum 4 ,
 .Xr run 4 ,
 .Xr ural 4 ,
 .Xr wi 4 ,
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/hostapd/hostapd.conf.5
--- a/head/usr.sbin/wpa/hostapd/hostapd.conf.5	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/hostapd/hostapd.conf.5	Wed Jul 25 16:29:58 2012 +0300
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/wpa/hostapd/hostapd.conf.5 235499 2012-05-16 01:59:09Z gjb $
 .\"
 .Dd September 2, 2006
 .Dt HOSTAPD.CONF 5
@@ -67,7 +67,8 @@
 Interface name.
 Should be set in
 .Dq hostap
-mode.
+mode.  Make certain that there are no spaces after the interface name,
+or hostapd will complain that the interface does not exist.
 .It Va debug
 Debugging mode: 0 = no, 1 = minimal, 2 = verbose, 3 = msg dumps, 4 =
 excessive.
@@ -171,8 +172,8 @@
 This conversion uses SSID so the PSK changes when ASCII passphrase is
 used and the SSID is changed.
 .It Va wpa_psk_file
-Optionally, WPA PSKs can be read from a separate text file (containing a
-list of (PSK,MAC address) pairs.
+Optionally, WPA PSKs can be read from a separate text file containing a
+list of PSK and MAC address pairs.
 .It Va wpa_key_mgmt
 Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both).
 .It Va wpa_pairwise
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/ndis_events/ndis_events.8
--- a/head/usr.sbin/wpa/ndis_events/ndis_events.8	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/ndis_events/ndis_events.8	Wed Jul 25 16:29:58 2012 +0300
@@ -28,7 +28,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 .\" THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/wpa/ndis_events/ndis_events.8 235873 2012-05-24 02:24:03Z wblock $
 .\"
 .Dd August 30, 2007
 .Dt NDIS_EVENTS 8
@@ -71,7 +71,7 @@
 interface, it transmits it via UDP packet on the loopback interface,
 where
 .Xr wpa_supplicant 8
-is presumeably listening.
+is presumably listening.
 The standard
 .Xr wpa_supplicant 8
 distribution includes its own version of this utility for use with
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/wpa_supplicant/Makefile
--- a/head/usr.sbin/wpa/wpa_supplicant/Makefile	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/wpa_supplicant/Makefile	Wed Jul 25 16:29:58 2012 +0300
@@ -1,25 +1,46 @@
-# $FreeBSD: head/usr.sbin/wpa/wpa_supplicant/Makefile 230293 2012-01-18 02:44:22Z emaste $
+# $FreeBSD: head/usr.sbin/wpa/wpa_supplicant/Makefile 234786 2012-04-29 12:48:52Z bschmidt $
 
 .include "${.CURDIR}/../Makefile.inc"
 
 .PATH.c:${WPA_SUPPLICANT_DISTDIR} \
-	${WPA_DISTDIR}/src/drivers \
-	${WPA_DISTDIR}/src/eap_peer \
-	${WPA_DISTDIR}/src/rsn_supp \
-	${WPA_DISTDIR}/src/crypto
+	${WPA_DISTDIR}/src/drivers
 
 PROG=	wpa_supplicant
-SRCS=	aes-cbc.c aes-ctr.c aes-eax.c aes-encblock.c \
-	aes-internal.c aes-omac1.c aes-unwrap.c \
-	aes-wrap.c bss.c blacklist.c common.c config.c ctrl_iface.c \
-	ctrl_iface_unix.c drivers.c eloop.c events.c l2_packet_freebsd.c main.c\
-	md5.c notify.c preauth.c pmksa_cache.c scan.c \
-	sha1-pbkdf2.c sha1-tlsprf.c sha1-tprf.c sha1.c \
-	wpa.c wpa_common.c wpa_debug.c wpa_ie.c wpa_supplicant.c \
-	wpabuf.c wpas_glue.c \
-	driver_ndis.c Packet32.c \
+SRCS=	aes-unwrap.c \
+	base64.c \
+	blacklist.c \
+	bss.c \
+	common.c \
+	config.c \
+	config_file.c \
+	ctrl_iface.c \
+	ctrl_iface_unix.c \
+	driver_ndis.c \
 	driver_wired.c \
-	driver_freebsd.c os_unix.c
+	drivers.c \
+	eap_register.c \
+	eloop.c \
+	events.c \
+	main.c \
+	md5.c \
+	notify.c \
+	os_unix.c \
+	peerkey.c \
+	pmksa_cache.c \
+	preauth.c \
+	scan.c \
+	sha1-pbkdf2.c \
+	sha1.c \
+	wpa.c \
+	wpa_common.c \
+	wpa_debug.c \
+	wpa_ie.c \
+	wpa_supplicant.c \
+	wpabuf.c \
+	wpas_glue.c
+SRCS+=	driver_freebsd.c \
+	l2_packet_freebsd.c \
+	Packet32.c
 
 MAN=	wpa_supplicant.8 wpa_supplicant.conf.5
 
@@ -29,23 +50,19 @@
 FILES=	wpa_supplicant.conf
 .endif
 
-CFLAGS+=-I${WPA_SUPPLICANT_DISTDIR}
-CFLAGS+=-I${WPA_DISTDIR}/src/drivers
-CFLAGS+=-I${WPA_DISTDIR}/src/rsn_supp
-
-CFLAGS+= -DCONFIG_DRIVER_BSD
-CFLAGS+= -DCONFIG_DRIVER_NDIS
-CFLAGS+= -DCONFIG_DRIVER_WIRED
-CFLAGS+= -DCONFIG_TERMINATE_ONLASTIF
-CFLAGS+= -DCONFIG_DEBUG_SYSLOG
+CFLAGS+=-DCONFIG_BACKEND_FILE \
+	-DCONFIG_DEBUG_SYSLOG \
+	-DCONFIG_DRIVER_BSD \
+	-DCONFIG_DRIVER_NDIS \
+	-DCONFIG_DRIVER_WIRED \
+	-DCONFIG_PEERKEY \
+	-DCONFIG_SMARTCARD \
+	-DCONFIG_TERMINATE_ONLASTIF \
+	-DPKCS12_FUNCS
 #CFLAGS+= -g
 DPADD+=	${LIBPCAP}
 LDADD+=	-lpcap
 
-# NB: we only support wpa_supplicant.conf file
-SRCS+=	config_file.c base64.c
-CFLAGS+=-DCONFIG_BACKEND_FILE
-
 # User customizations to the wpa_supplicant build environment
 CFLAGS+=${WPA_SUPPLICANT_CFLAGS}
 #DPADD+=${WPA_SUPPLICANT_DPADD}
@@ -53,43 +70,58 @@
 #LDFLAGS+=${WPA_SUPPLICANT_LDFLAGS}
 
 .if ${MK_WPA_SUPPLICANT_EAPOL} != "no"
-SRCS+=	eapol_supp_sm.c eap.c eap_common.c eap_methods.c eap_register.c
-CFLAGS+= -DIEEE8021X_EAPOL
-
-.if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH)
-CFLAGS+=-DEAP_TLS -DEAP_PEAP -DEAP_MSCHAPv2 -DEAP_LEAP -DEAP_PSK \
-	-DEAP_TLV -DEAP_TLS_FUNCS -DEAP_TLS_OPENSSL
-SRCS+=	chap.c crypto_openssl.c \
+CFLAGS+=-DEAP_GTC \
+	-DEAP_LEAP \
+	-DEAP_MD5 \
+	-DEAP_MSCHAPv2 \
+	-DEAP_OTP \
+	-DEAP_PEAP \
+	-DEAP_PSK \
+	-DEAP_TLS \
+	-DEAP_TTLS \
+	-DIEEE8021X_EAPOL
+SRCS+=	chap.c \
+	eap.c \
+	eap_common.c \
+	eap_gtc.c \
 	eap_leap.c \
+	eap_md5.c \
+	eap_methods.c \
 	eap_mschapv2.c \
-	eap_peap.c eap_peap_common.c \
-	eap_psk.c eap_psk_common.c \
-	eap_tls.c eap_tls_common.c \
-	mschapv2.c ms_funcs.c tls_openssl.c
-
-CFLAGS+=-DEAP_TTLS -DEAP_MD5
-SRCS+=	eap_ttls.c eap_md5.c
-
-.if !empty(CFLAGS:M*-DEAP_GTC)
-SRCS+=	eap_gtc.c
-.endif
-
-.if !empty(CFLAGS:M*-DEAP_OTP)
-SRCS+=	eap_otp.c
+	eap_otp.c \
+	eap_peap.c \
+	eap_peap_common.c \
+	eap_psk.c \
+	eap_psk_common.c \
+	eap_tls.c \
+	eap_tls_common.c \
+	eap_ttls.c \
+	eapol_supp_sm.c \
+	ms_funcs.c \
+	mschapv2.c
+TLS_FUNCS=y
+NEED_AES_EAX=y
+NEED_AES_ENCBLOCK=y
+NEED_AES_OMAC1=y
+NEED_SHA256=y
 .endif
 
 .if !empty(CFLAGS:M*-DEAP_AKA)
-NEED_SIM_COMMON=	true
 SRCS+=	eap_aka.c
+NEED_SIM_COMMON=y
+NEED_AES_CBC=y
 .endif
 
 .if !empty(CFLAGS:M*-DEAP_SIM)
-NEED_SIM_COMMON=	true
 SRCS+=	eap_sim.c
+NEED_SIM_COMMON=y
+NEED_AES_CBC=y
 .endif
 
 .if defined(NEED_SIM_COMMON)
 SRCS+=	eap_sim_common.c
+NEED_FIPS186_2_PRF=y
+.endif
 
 # PC/SC interface for smartcards (USIM, GSM SIM)
 # GSM/UMTS authentication algorithm (for EAP-SIM/EAP-AKA)
@@ -103,52 +135,24 @@
 DPADD+=${LIBPTHREAD}
 LDADD+=-lpcsclite -lpthread
 .endif
-.endif
 
 .if !empty(CFLAGS:M*-DEAP_GPSK)
 CFLAGS+=-DEAP_GPSK_SHA256
-SRCS+=	eap_gpsk.c eap_gpsk_common.c
-NEED_SHA256=	true
+SRCS+=	eap_gpsk.c \
+	eap_gpsk_common.c
+NEED_AES_OMAC1=y
 .endif
 
 .if !empty(CFLAGS:M*-DEAP_PAX)
-SRCS+=	eap_pax.c eap_pax_common.c
+SRCS+=	eap_pax.c \
+	eap_pax_common.c
 .endif
 
 .if !empty(CFLAGS:M*-DEAP_SAKE)
-SRCS+=	eap_sake.c eap_sake_common.c
+SRCS+=	eap_sake.c \
+	eap_sake_common.c
 .endif
 
-# NB: requires patch to openssl
-#CFLAGS+= -DEAP_FAST
-#SRCS+=	eap_fast.c
-
-NEED_LIBSSL=	true
-.else
-CFLAGS+= -DEAP_TLS_NONE
-SRCS+=	tls_none.c
-.endif
-
-.endif
-
-#
-# Configure crypto/cipher support.
-#
-# EAPOL support requires openssl in which case we use their
-# cipher code.  Otherwise we use our internal versions.
-#
-.if !defined(NEED_LIBSSL)
-CFLAGS+= -DINTERNAL_AES
-CFLAGS+= -DINTERNAL_SHA1
-CFLAGS+= -DINTERNAL_MD5
-.else
-DPADD+= ${LIBSSL} ${LIBCRYPTO}
-LDADD+= -lssl -lcrypto
-.endif
-
-.if defined(NEED_SHA256)
-CFLAGS+=-DINTERNAL_SHA256
-SRCS+=	sha256.c
-.endif
+.include "${.CURDIR}/../Makefile.crypto"
 
 .include <bsd.prog.mk>
diff -r 4936d08172d1 -r 91983250c121 head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5
--- a/head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5	Wed Jul 25 16:24:55 2012 +0300
+++ b/head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5	Wed Jul 25 16:29:58 2012 +0300
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/usr.sbin/wpa/wpa_supplicant/wpa_supplicant.conf.5 235337 2012-05-12 15:08:22Z gjb $
 .\"
 .Dd April 10, 2010
 .Dt WPA_SUPPLICANT.CONF 5
@@ -316,7 +316,7 @@
 If the
 .Va dh_file
 is in DSA parameters format, it will be automatically converted
-into DH params.
+into DH parameters.
 .It Va subject_match
 Substring to be matched against the subject of the
 authentication server certificate.
@@ -370,7 +370,7 @@
 fragmented.
 .It Li sim_min_num_chal=3
 can be used to configure EAP-SIM to require three
-challenges (by default, it accepts 2 or 3)
+challenges (by default, it accepts 2 or 3).
 .It Li fast_provisioning=1
 option enables in-line provisioning of EAP-FAST
 credentials (PAC).



More information about the Zrouter-src-freebsd mailing list