aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorBaptiste Daroussin <bapt@FreeBSD.org>2021-12-06 10:42:36 +0000
committerBaptiste Daroussin <bapt@FreeBSD.org>2021-12-06 10:43:34 +0000
commitf499134dd403eeeba8283e2640e2654c8da62430 (patch)
treed965ecea32e42cc00de00fd08f7641bd4504f6aa /contrib
parentc59900ee61c3075bd5d5464b2727836b9c9d6dc5 (diff)
parent1b308d0631e5d0d21b631a688cdef1afe378e086 (diff)
downloadsrc-f499134dd403eeeba8283e2640e2654c8da62430.tar.gz
src-f499134dd403eeeba8283e2640e2654c8da62430.zip
bsddialog: import snapshot 2021-12-05
Diffstat (limited to 'contrib')
-rw-r--r--contrib/bsddialog/.gitignore25
-rw-r--r--contrib/bsddialog/README.md105
-rw-r--r--contrib/bsddialog/bsdconfig/Makefile33
-rw-r--r--contrib/bsddialog/bsdconfig/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/USAGE47
-rwxr-xr-xcontrib/bsddialog/bsdconfig/bsdconfig428
-rw-r--r--contrib/bsddialog/bsdconfig/bsdconfig.8256
-rw-r--r--contrib/bsddialog/bsdconfig/console/INDEX70
-rw-r--r--contrib/bsddialog/bsdconfig/console/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/console/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/console/USAGE37
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/console146
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/font193
-rw-r--r--contrib/bsddialog/bsdconfig/console/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/console/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/console/include/messages.subr270
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/keymap338
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/repeat143
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/saver195
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/screenmap155
-rwxr-xr-xcontrib/bsddialog/bsdconfig/console/ttys207
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/USAGE37
-rwxr-xr-xcontrib/bsddialog/bsdconfig/diskmgmt/diskmgmt85
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/diskmgmt/include/messages.subr27
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/USAGE37
-rwxr-xr-xcontrib/bsddialog/bsdconfig/docsinstall/docsinstall97
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/docsinstall/include/messages.subr28
-rw-r--r--contrib/bsddialog/bsdconfig/dot/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/dot/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/dot/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/dot/USAGE143
-rwxr-xr-xcontrib/bsddialog/bsdconfig/dot/dot678
-rw-r--r--contrib/bsddialog/bsdconfig/dot/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/dot/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/dot/include/messages.subr31
-rw-r--r--contrib/bsddialog/bsdconfig/examples/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/examples/Makefile.depend11
-rwxr-xr-xcontrib/bsddialog/bsdconfig/examples/add_some_packages.sh13
-rwxr-xr-xcontrib/bsddialog/bsdconfig/examples/browse_packages_http.sh32
-rw-r--r--contrib/bsddialog/bsdconfig/examples/bsdconfigrc42
-rw-r--r--contrib/bsddialog/bsdconfig/include/Makefile7
-rw-r--r--contrib/bsddialog/bsdconfig/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/include/bsdconfig.hlp12
-rw-r--r--contrib/bsddialog/bsdconfig/include/media.hlp54
-rw-r--r--contrib/bsddialog/bsdconfig/include/messages.subr464
-rw-r--r--contrib/bsddialog/bsdconfig/include/network_device.hlp58
-rw-r--r--contrib/bsddialog/bsdconfig/include/options.hlp115
-rw-r--r--contrib/bsddialog/bsdconfig/include/tcp.hlp33
-rw-r--r--contrib/bsddialog/bsdconfig/include/usage.hlp64
-rw-r--r--contrib/bsddialog/bsdconfig/includes/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/includes/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/includes/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/includes/USAGE71
-rw-r--r--contrib/bsddialog/bsdconfig/includes/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/includes/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/includes/include/messages.subr28
-rwxr-xr-xcontrib/bsddialog/bsdconfig/includes/includes.sh205
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/INDEX62
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/USAGE37
-rwxr-xr-xcontrib/bsddialog/bsdconfig/mouse/disable97
-rwxr-xr-xcontrib/bsddialog/bsdconfig/mouse/enable128
-rwxr-xr-xcontrib/bsddialog/bsdconfig/mouse/flags95
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/mouse/include/messages.subr91
-rwxr-xr-xcontrib/bsddialog/bsdconfig/mouse/mouse144
-rwxr-xr-xcontrib/bsddialog/bsdconfig/mouse/port150
-rwxr-xr-xcontrib/bsddialog/bsdconfig/mouse/type170
-rw-r--r--contrib/bsddialog/bsdconfig/networking/INDEX64
-rw-r--r--contrib/bsddialog/bsdconfig/networking/Makefile12
-rw-r--r--contrib/bsddialog/bsdconfig/networking/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/networking/USAGE37
-rwxr-xr-xcontrib/bsddialog/bsdconfig/networking/defaultrouter76
-rwxr-xr-xcontrib/bsddialog/bsdconfig/networking/devices164
-rwxr-xr-xcontrib/bsddialog/bsdconfig/networking/hostname76
-rw-r--r--contrib/bsddialog/bsdconfig/networking/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/networking/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/networking/include/messages.subr107
-rwxr-xr-xcontrib/bsddialog/bsdconfig/networking/nameservers76
-rwxr-xr-xcontrib/bsddialog/bsdconfig/networking/networking153
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/Makefile7
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/common.subr58
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/device.subr403
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/hostname.subr162
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/ipaddr.subr219
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/media.subr247
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/netmask.subr137
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/resolv.subr502
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/routing.subr133
-rw-r--r--contrib/bsddialog/bsdconfig/networking/share/services.subr55
-rwxr-xr-xcontrib/bsddialog/bsdconfig/networking/wlanconfig78
-rw-r--r--contrib/bsddialog/bsdconfig/packages/INDEX56
-rw-r--r--contrib/bsddialog/bsdconfig/packages/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/packages/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/packages/USAGE37
-rw-r--r--contrib/bsddialog/bsdconfig/packages/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/packages/include/Makefile.depend11
-rwxr-xr-xcontrib/bsddialog/bsdconfig/packages/include/messages.subr27
-rwxr-xr-xcontrib/bsddialog/bsdconfig/packages/packages82
-rw-r--r--contrib/bsddialog/bsdconfig/password/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/password/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/password/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/password/USAGE37
-rw-r--r--contrib/bsddialog/bsdconfig/password/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/password/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/password/include/messages.subr35
-rwxr-xr-xcontrib/bsddialog/bsdconfig/password/password85
-rw-r--r--contrib/bsddialog/bsdconfig/password/share/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/password/share/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/password/share/password.subr124
-rw-r--r--contrib/bsddialog/bsdconfig/security/INDEX58
-rw-r--r--contrib/bsddialog/bsdconfig/security/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/security/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/security/USAGE37
-rw-r--r--contrib/bsddialog/bsdconfig/security/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/security/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/security/include/messages.subr50
-rw-r--r--contrib/bsddialog/bsdconfig/security/include/securelevel.hlp40
-rwxr-xr-xcontrib/bsddialog/bsdconfig/security/kern_securelevel175
-rwxr-xr-xcontrib/bsddialog/bsdconfig/security/security179
-rw-r--r--contrib/bsddialog/bsdconfig/share/Makefile10
-rw-r--r--contrib/bsddialog/bsdconfig/share/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/share/common.subr1046
-rw-r--r--contrib/bsddialog/bsdconfig/share/device.subr1393
-rw-r--r--contrib/bsddialog/bsdconfig/share/dialog.subr2339
-rw-r--r--contrib/bsddialog/bsdconfig/share/geom.subr430
-rw-r--r--contrib/bsddialog/bsdconfig/share/keymap.subr266
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/Makefile8
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/any.subr149
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/cdrom.subr217
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/common.subr155
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/directory.subr151
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/dos.subr165
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/floppy.subr229
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/ftp.subr897
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/http.subr688
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/httpproxy.subr463
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/network.subr182
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/nfs.subr258
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/options.subr327
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/tcpip.subr1713
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/ufs.subr198
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/usb.subr176
-rw-r--r--contrib/bsddialog/bsdconfig/share/media/wlan.subr1392
-rw-r--r--contrib/bsddialog/bsdconfig/share/mustberoot.subr424
-rw-r--r--contrib/bsddialog/bsdconfig/share/packages/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/share/packages/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/share/packages/categories.subr209
-rw-r--r--contrib/bsddialog/bsdconfig/share/packages/index.subr416
-rw-r--r--contrib/bsddialog/bsdconfig/share/packages/musthavepkg.subr91
-rw-r--r--contrib/bsddialog/bsdconfig/share/packages/packages.subr1194
-rw-r--r--contrib/bsddialog/bsdconfig/share/script.subr219
-rw-r--r--contrib/bsddialog/bsdconfig/share/strings.subr577
-rw-r--r--contrib/bsddialog/bsdconfig/share/struct.subr206
-rw-r--r--contrib/bsddialog/bsdconfig/share/sysrc.subr758
-rw-r--r--contrib/bsddialog/bsdconfig/share/variable.subr315
-rw-r--r--contrib/bsddialog/bsdconfig/startup/INDEX62
-rw-r--r--contrib/bsddialog/bsdconfig/startup/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/startup/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/startup/USAGE37
-rw-r--r--contrib/bsddialog/bsdconfig/startup/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/startup/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/startup/include/messages.subr108
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/misc369
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/rcadd149
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/rcconf264
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/rcdelete414
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/rcedit72
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/rcvar220
-rw-r--r--contrib/bsddialog/bsdconfig/startup/share/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/startup/share/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/startup/share/rcconf.subr500
-rw-r--r--contrib/bsddialog/bsdconfig/startup/share/rcedit.subr90
-rw-r--r--contrib/bsddialog/bsdconfig/startup/share/rcvar.subr236
-rwxr-xr-xcontrib/bsddialog/bsdconfig/startup/startup140
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/USAGE46
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/include/messages.subr78
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/Makefile7
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/continents.subr166
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/countries.subr105
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/iso3166.subr202
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/menus.subr225
-rw-r--r--contrib/bsddialog/bsdconfig/timezone/share/zones.subr523
-rwxr-xr-xcontrib/bsddialog/bsdconfig/timezone/timezone457
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/INDEX57
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/USAGE37
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/ttys/include/messages.subr31
-rwxr-xr-xcontrib/bsddialog/bsdconfig/ttys/ttys128
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/INDEX64
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/Makefile11
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/USAGE37
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/groupadd77
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/groupdel100
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/groupedit100
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/include/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/include/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/include/messages.subr119
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/include/usermgmt.hlp76
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/share/Makefile6
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/share/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/share/group.subr518
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/share/group_input.subr596
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/share/user.subr1183
-rw-r--r--contrib/bsddialog/bsdconfig/usermgmt/share/user_input.subr1341
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/useradd77
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/userdel100
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/useredit100
-rwxr-xr-xcontrib/bsddialog/bsdconfig/usermgmt/usermgmt168
-rw-r--r--contrib/bsddialog/bsddialog.142
-rw-r--r--contrib/bsddialog/bsddialog.c951
-rw-r--r--contrib/bsddialog/bsdinstall/Makefile9
-rw-r--r--contrib/bsddialog/bsdinstall/Makefile.depend11
-rw-r--r--contrib/bsddialog/bsdinstall/Makefile.inc1
-rw-r--r--contrib/bsddialog/bsdinstall/README.txt20
-rwxr-xr-xcontrib/bsddialog/bsdinstall/bsdinstall90
-rw-r--r--contrib/bsddialog/bsdinstall/bsdinstall.8639
-rw-r--r--contrib/bsddialog/bsdinstall/distextract/Makefile9
-rw-r--r--contrib/bsddialog/bsdinstall/distextract/Makefile.depend30
-rw-r--r--contrib/bsddialog/bsdinstall/distextract/distextract.c334
-rw-r--r--contrib/bsddialog/bsdinstall/distfetch/Makefile9
-rw-r--r--contrib/bsddialog/bsdinstall/distfetch/Makefile.depend23
-rw-r--r--contrib/bsddialog/bsdinstall/distfetch/distfetch.c225
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/Makefile52
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/Makefile.depend24
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/Makefile_ORIG26
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/diskeditor.c292
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/diskeditor.h (renamed from contrib/bsddialog/lib/editorbox.c)36
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/diskmenu.c99
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/diskmenu.h (renamed from contrib/bsddialog/lib/filebox.c)50
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/gpart_ops.c1460
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/part_wizard.c366
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/partedit.c606
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/partedit.h108
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/partedit_efi.c106
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/partedit_generic.c81
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/partedit_powerpc.c147
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/partedit_x86.c155
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/sade.873
-rw-r--r--contrib/bsddialog/bsdinstall/partedit/scripted.c218
-rw-r--r--contrib/bsddialog/bsdinstall/scripts/Makefile11
-rw-r--r--contrib/bsddialog/bsdinstall/scripts/Makefile.depend11
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/adduser34
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/auto444
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/bootconfig97
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/checksum79
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/config63
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/docsinstall167
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/entropy34
-rw-r--r--contrib/bsddialog/bsdinstall/scripts/fetchmissingdists132
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/hardening91
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/hostname126
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/jail159
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/keymap233
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/mirrorselect179
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/mount55
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/netconfig217
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/netconfig_ipv4103
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/netconfig_ipv6160
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/rootpass37
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/script182
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/services70
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/time67
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/umount44
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/wlanconfig365
-rwxr-xr-xcontrib/bsddialog/bsdinstall/scripts/zfsboot1814
-rw-r--r--contrib/bsddialog/examples_library/buildlist.c (renamed from contrib/bsddialog/library_examples/buildlist.c)2
-rw-r--r--contrib/bsddialog/examples_library/checklist.c (renamed from contrib/bsddialog/library_examples/checklist.c)2
-rwxr-xr-xcontrib/bsddialog/examples_library/compile (renamed from contrib/bsddialog/library_examples/compile)2
-rw-r--r--contrib/bsddialog/examples_library/datebox.c59
-rw-r--r--contrib/bsddialog/examples_library/form.c51
-rw-r--r--contrib/bsddialog/examples_library/infobox.c (renamed from contrib/bsddialog/library_examples/infobox.c)2
-rw-r--r--contrib/bsddialog/examples_library/menu.c (renamed from contrib/bsddialog/library_examples/menu.c)2
-rw-r--r--contrib/bsddialog/examples_library/mixedlist.c (renamed from contrib/bsddialog/library_examples/mixedlist.c)5
-rw-r--r--contrib/bsddialog/examples_library/msgbox.c (renamed from contrib/bsddialog/library_examples/msgbox.c)2
-rw-r--r--contrib/bsddialog/examples_library/pause.c50
-rw-r--r--contrib/bsddialog/examples_library/radiolist.c (renamed from contrib/bsddialog/library_examples/radiolist.c)2
-rw-r--r--contrib/bsddialog/examples_library/rangebox.c35
-rw-r--r--contrib/bsddialog/examples_library/sade.c64
-rw-r--r--contrib/bsddialog/examples_library/theme.c (renamed from contrib/bsddialog/library_examples/theme.c)4
-rw-r--r--contrib/bsddialog/examples_library/timebox.c58
-rw-r--r--contrib/bsddialog/examples_library/treeview.c (renamed from contrib/bsddialog/library_examples/treeview.c)4
-rw-r--r--contrib/bsddialog/examples_library/yesno.c (renamed from contrib/bsddialog/library_examples/yesno.c)2
-rwxr-xr-xcontrib/bsddialog/examples_utility/buildlist.sh17
-rwxr-xr-xcontrib/bsddialog/examples_utility/checklist.sh17
-rwxr-xr-xcontrib/bsddialog/examples_utility/form.sh19
-rwxr-xr-xcontrib/bsddialog/examples_utility/gauge.sh (renamed from contrib/bsddialog/utility_examples/gauge_example.sh)8
-rwxr-xr-xcontrib/bsddialog/examples_utility/infobox.sh12
-rwxr-xr-xcontrib/bsddialog/examples_utility/inputbox.sh12
-rwxr-xr-xcontrib/bsddialog/examples_utility/menu.sh17
-rwxr-xr-xcontrib/bsddialog/examples_utility/mixedform.sh15
-rwxr-xr-xcontrib/bsddialog/examples_utility/mixedgauge.sh33
-rwxr-xr-xcontrib/bsddialog/examples_utility/msgbox.sh11
-rwxr-xr-xcontrib/bsddialog/examples_utility/passwordbox.sh12
-rwxr-xr-xcontrib/bsddialog/examples_utility/passwordform.sh17
-rwxr-xr-xcontrib/bsddialog/examples_utility/radiolist.sh17
-rwxr-xr-xcontrib/bsddialog/examples_utility/treeview.sh17
-rwxr-xr-xcontrib/bsddialog/examples_utility/yesno.sh11
-rw-r--r--contrib/bsddialog/lib/GNUMakefile7
-rw-r--r--contrib/bsddialog/lib/Makefile7
-rw-r--r--contrib/bsddialog/lib/barbox.c498
-rw-r--r--contrib/bsddialog/lib/bsddialog.342
-rw-r--r--contrib/bsddialog/lib/bsddialog.h181
-rw-r--r--contrib/bsddialog/lib/bsddialog_theme.h87
-rw-r--r--contrib/bsddialog/lib/commandbox.c211
-rw-r--r--contrib/bsddialog/lib/formbox.c554
-rw-r--r--contrib/bsddialog/lib/infobox.c10
-rw-r--r--contrib/bsddialog/lib/lib_util.c448
-rw-r--r--contrib/bsddialog/lib/lib_util.h46
-rw-r--r--contrib/bsddialog/lib/libbsddialog.c13
-rw-r--r--contrib/bsddialog/lib/menubox.c221
-rw-r--r--contrib/bsddialog/lib/messagebox.c26
-rw-r--r--contrib/bsddialog/lib/textbox.c67
-rw-r--r--contrib/bsddialog/lib/theme.c354
-rw-r--r--contrib/bsddialog/lib/timebox.c458
-rw-r--r--contrib/bsddialog/library_examples/ports.c97
-rwxr-xr-xcontrib/bsddialog/utility_examples/info_example.sh3
-rwxr-xr-xcontrib/bsddialog/utility_examples/menu_example.sh41
-rwxr-xr-xcontrib/bsddialog/utility_examples/message_example.sh5
-rwxr-xr-xcontrib/bsddialog/utility_examples/mixedform_example.sh25
-rwxr-xr-xcontrib/bsddialog/utility_examples/mixedgauge_example.sh24
345 files changed, 50464 insertions, 2247 deletions
diff --git a/contrib/bsddialog/.gitignore b/contrib/bsddialog/.gitignore
new file mode 100644
index 000000000000..bc53650512de
--- /dev/null
+++ b/contrib/bsddialog/.gitignore
@@ -0,0 +1,25 @@
+bsddialog
+*.o
+*~
+examples_library/buildlist
+examples_library/checklist
+examples_library/datebox
+examples_library/form
+examples_library/menu
+examples_library/mixedlist
+examples_library/radiolist
+examples_library/theme
+examples_library/treeview
+examples_library/infobox
+examples_library/msgbox
+examples_library/pause
+examples_library/rangebox
+examples_library/sade
+examples_library/timebox
+examples_library/yesno
+*.gz
+lib/libbsddialog.so*
+BSDDIALOG.geany
+BSDDIALOG.tags
+*.core
+bsdinstall/partedit/sade
diff --git a/contrib/bsddialog/README.md b/contrib/bsddialog/README.md
index 1d34f3b51099..112d8934f432 100644
--- a/contrib/bsddialog/README.md
+++ b/contrib/bsddialog/README.md
@@ -55,19 +55,43 @@ Examples utility:
% ./bsddialog --backtitle "TITLE" --title yesno --hline "bsddialog" --yesno "Hello World!" 5 25
% ./bsddialog --extra-button --help-button --defaultno --yesno "Hello World!" 0 0
```
+and
+```
+% sh ./examples_utility/buildlist.sh
+% sh ./examples_utility/checklist.sh
+% sh ./examples_utility/form.sh
+% sh ./examples_utility/gauge.sh
+% sh ./examples_utility/infobox.sh
+% sh ./examples_utility/inputbox.sh
+% sh ./examples_utility/menu.sh
+% sh ./examples_utility/mixedform.sh
+% sh ./examples_utility/mixedgauge.sh
+% sh ./examples_utility/msgbox.sh
+% sh ./examples_utility/passwordbox.sh
+% sh ./examples_utility/passwordform.sh
+% sh ./examples_utility/radiolist.sh
+% sh ./examples_utility/treeview.sh
+% sh ./examples_utility/yesno.sh
+```
Examples library:
```
-% cd library_examples
+% cd examples_library
% sh compile
% ./buildlist
+% ./compile
+% ./datebox
+% ./form
% ./infobox
% ./menu
% ./mixedlist
% ./msgbox
-% ./ports
+% ./pause
% ./radiolist
+% ./rangebox
+% ./sade
% ./theme
+% ./timebox
% ./treeview
% ./yesno
```
@@ -87,74 +111,63 @@ Use Cases:
--colors, --date-format *format*, --default-button *string*, --defaultno,
--default-item *string*,
--exit-label *string*, --extra-button, --extra-label *string*,
---hfile *filename* (for completed widgets), n--help-button,
+--hfile *filename* (for completed widgets), --help, --help-button,
--help-label *string*, --help-status, --help-tags, --hline *string*, --ignore,
---item-help, --no-cancel, --nocancel, --no-label *string*, --no-items,
---no-lines, --no-ok,
+--insecure, --item-help, --max-input *size*, --no-cancel, --nocancel,
+--no-label *string*, --no-items, --no-lines, --no-ok,
--nook, --no-shadow, --no-tags, --ok-label *string*, --output-fd *fd*,
--output-separator *string*, --print-version,
--print-size (todo move lib -> utility), --quoted (quotes all != dialog),
--print-maxsize, --shadow, --single-quoted (add --quote-with *ch*?),
--separator *string* (alias --output-separator *string*),
--separate-output (rename --separate-output-withnl?), --sleep *secs*, --stderr,
---stdout, --theme *string* ("bsddialog", "dialog", "blackwhite" and "magenta"),
+--stdout, --theme *string* ("bsddialog", "dialog", "blackwhite"),
--time-format *format*, --title *title*, --version, --yes-label *string*.
**Widgets:**
infobox (do not clear the screen), msgbox,
yesno (dialog renames "yes/no" -> "ok/cancel" with --extra-button --help-button).
- checklist, radiolist, menu, mixedlist, treeview and textbox.
+ checklist, radiolist, menu, mixedlist, treeview, textbox, mixedgauge, datebox,
+ timebox, gauge, rangebox, pause.
+
+
+ Without resize:
+
+ form, inputbox, mixedform, passwordbox, passwordform.
+
+
+ Without autosize, resize, F1:
+
+ buildlist
+
+
## TODO
+
**Common Options:**
| Option | Status | Note |
| ---------------------------- | ----------- | ------------------------------- |
-| --cr-wrap | Coding | |
-| --help | In progress | |
-| --input-fd *fd* | | |
-| --insecure | | |
-| --keep-tite | | |
-| --keep-window | | |
-| --last-key | | |
-| --max-input *size* | | |
-| --no-collapse | Coding | |
-| --no-kill | | |
-| --no-nl-expand | Coding | |
-| --tab-correct | | |
-| --tab-len *n* | | |
-| --trim | Coding | |
-
-
-To evaluate / Not planned in the short term: --column-separator *string*,
+| --cr-wrap | In progress | text |
+| --no-collapse | In progress | text |
+| --no-nl-expand | In progress | text |
+| --trim | In progress | text |
+
+
+To evaluate / Not planned in the short term / not in bsdinstall:
+
--create-rc *file*, --iso-week, --no-mouse, --print-text-only *str h w*,
--print-text-size *str h w*, --reorder, -scrollbar, --separate-widget *string*,
--size-err, --timeout *secs*,--trace *filename*, --visit-items,
---week-start *day*.
+--week-start *day*, --keep-tite, --keep-window, --last-key, --no-kill,
+--column-separator *string*, --input-fd *fd*, --tab-correct, --tab-len *n*
**Widgets:**
-| Widget | Status | Note |
-|--------------- | ----------- | ----------------------------------------------|
-| --buildlist | In progress | todo autosize, resize, F1 |
-| --calendar | In progress | todo autosize, resize, F1, leap year, year <=0, month days |
-| --editbox | | |
-| --form | In progress | implemented via --mixedform |
-| --gauge | In progress | |
-| --inputbox | In progress | implemented via --mixedform, todo \<init\> |
-| --mixedform | In progress | todo autosize, resize, F1 |
-| --mixedgauge | In progress | todo autosize, resize, F1 |
-| --passwordbox | In progress | implemented via --mixedform, todo \<init\> |
-| --passwordform | In progress | implemented via --mixedform |
-| --pause | In progress | todo autosize, resize, F1 |
-| --prgbox | In progress | add command opts |
-| --programbox | Coding | |
-| --progressbox | | |
-| --rangebox | In progress | todo autosize, resize, F1, PAGE-UP/PAGE-DOWN/HOME/END keys |
-| --timebox | In progress | todo autosize, resize, F1 |
-
-To evaluate / Not planned in the short term: tailbox (textbox/fseek), tailboxbg,
-dselect, fselect, inputmenu.
+To evaluate / Not planned in the short term:
+
+tailbox (textbox/fseek), tailboxbg, dselect, fselect, inputmenu, editbox,
+calendar (use datebox), prgbox, programbox, progressbox.
diff --git a/contrib/bsddialog/bsdconfig/Makefile b/contrib/bsddialog/bsdconfig/Makefile
new file mode 100644
index 000000000000..a203c9aab328
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/Makefile
@@ -0,0 +1,33 @@
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+SUBDIR= console \
+ diskmgmt \
+ docsinstall \
+ dot \
+ include \
+ includes \
+ mouse \
+ networking \
+ packages \
+ password \
+ security \
+ share \
+ startup \
+ timezone \
+ ttys \
+ usermgmt
+
+.if ${MK_EXAMPLES} != "no"
+SUBDIR+= examples
+.endif
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig
+FILES= USAGE
+
+SCRIPTS= bsdconfig
+
+MAN= bsdconfig.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/Makefile.depend b/contrib/bsddialog/bsdconfig/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/USAGE b/contrib/bsddialog/bsdconfig/USAGE
new file mode 100644
index 000000000000..6b70bd6450c8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/USAGE
@@ -0,0 +1,47 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2013 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$
+
+Usage:
+ @PROGRAM_NAME@ [-h]
+ @PROGRAM_NAME@ command [-h]
+ @PROGRAM_NAME@ [OPTIONS] [command [OPTIONS]]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -f file Load file as script and then exit. If multiple occurrences,
+ program will only exit after last occurrence. If file is a
+ single dash (`-'), @PROGRAM_NAME@ reads from standard input.
+ -h Print this 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:
+@COMMAND_LIST@
diff --git a/contrib/bsddialog/bsdconfig/bsdconfig b/contrib/bsddialog/bsdconfig/bsdconfig
new file mode 100755
index 000000000000..f132c0370264
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/bsdconfig
@@ -0,0 +1,428 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2021 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$
+#
+############################################################ INCLUDES
+
+# When common.subr is included, it automatically scans "$@" for `-d' and/or
+# `-D file' arguments to conditionally enable debugging. Similarly, when
+# dialog.subr is included, it automatically scans "$@" for `-X' and/or `-S'.
+# To prevent this scanning from becoming confused by extra options, define
+# any/all extra arguments to use in the optstring to getopts when scanning
+# for dedicated options such as those described.
+#
+# NOTE: This needs to be declared before including `common.subr'.
+# NOTE: You really only need to list flags that require an argument as unknown
+# flags are silently accepted unless they take an argument (in which case
+# the following argument will terminate option processing unless it looks
+# like a flag).
+#
+GETOPTS_EXTRA="f:"
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+BSDCONFIG_HELPFILE=$BSDCFG_LIBE/include/bsdconfig.hlp
+USAGE_HELPFILE=$BSDCFG_LIBE/include/usage.hlp
+
+############################################################ CONFIGURATION
+
+#
+# Alternate `local' libexec directory for add-on modules (e.g., from ports)
+#
+BSDCFG_LOCAL_LIBE="/usr/local/libexec/bsdconfig"
+
+############################################################ FUNCTIONS
+
+# usage
+#
+# display usage and exit
+#
+usage()
+{
+ local index="INDEX"
+ local cmd_list # Calculated below
+
+ cd $BSDCFG_LIBE
+ # No need to preserve CWD (headed toward exit)
+
+ # 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
+ )
+
+ local alt_cmd_list # Calculated below (if $BSDCFG_LOCAL_LIBE exists)
+ if f_quietly cd $BSDCFG_LOCAL_LIBE; then
+ # No need to preserve CWD (headed toward exit)
+
+ # Test for language-specific indices
+ f_quietly ls */"$index.${LANG:-$LC_ALL}" &&
+ index="$index.${LANG:-$LC_ALL}"
+
+ alt_cmd_list=$(
+ awk '/^menu_selection="/ {
+ sub(/\|.*/, "")
+ sub(/^menu_selection="/, "")
+ print
+ }' */$index 2> /dev/null | sort
+ )
+
+ # Conflate lists, removing duplicates
+ cmd_list=$( printf "%s\n%s\n" \
+ "$cmd_list" "$alt_cmd_list" | sort -u )
+ fi
+
+ #
+ # Determine the longest command-length (in characters)
+ #
+ local longest_cmd
+ longest_cmd=$( echo "$cmd_list" | f_longest_line_length )
+ f_dprintf "longest_cmd=[%s]" "$longest_cmd"
+
+ #
+ # Determine the maximum width of terminal/console
+ #
+ local max_size="$( stty size 2> /dev/null )"
+ : ${max_size:="24 80"}
+ local max_width="${max_size#*[$IFS]}"
+ f_dprintf "max_width=[%s]" "$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 )) # Accommodate leading tab character
+ x=$(( $x + 3 + $longest_cmd )) # Pre-load end of next column
+ while [ $x -lt $max_width ]; do
+ ncols=$(( $ncols + 1 ))
+ x=$(( $x + 3 + $longest_cmd ))
+ done
+ f_dprintf "ncols=[%u] x=[%u]" $ncols $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]\" \"%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"
+
+ # NOTREACHED
+}
+
+# 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="
+ 'X' '$msg_exit' '$msg_exit_bsdconfig'
+ '1' '$msg_usage' '$msg_quick_start_how_to_use_this_menu_system'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline=
+
+ #
+ # Pick up the base modules (directories named `[0-9][0-9][0-9].*')
+ #
+ local menuitem menu_title menu_help menu_selection index=2
+ for menuitem in $( cd $BSDCFG_LIBE && ls -d [0-9][0-9][0-9].* ); do
+ [ -f "$BSDCFG_LIBE/$menuitem/INDEX" ] || continue
+ [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
+
+ menu_program= menu_title= menu_help=
+ f_include_lang $BSDCFG_LIBE/$menuitem/INDEX
+ [ "$menu_program" ] || continue
+
+ case "$menu_program" in
+ /*) : already fully qualified ;;
+ *) menu_program="$menuitem/$menu_program"
+ esac
+
+ f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
+ setvar "menu_program$tag" "$menu_program"
+
+ f_shell_escape "$menu_title" menu_title
+ f_shell_escape "$menu_help" menu_help
+ menu_list="$menu_list '$tag' '$menu_title' '$menu_help'"
+
+ index=$(( $index + 1 ))
+ done
+
+ #
+ # Process the `local' libexec sources.
+ #
+ # Whereas modules in $BSDCFG_LIBE must be named [0-9][0-9][0-9].*
+ # modules in $BSDCFG_LOCAL_LIBE should NOT be named this way (making it
+ # more practical for port-maintainers).
+ #
+ # This also has the fortunate side-effect of making the de-duplication
+ # effort rather simple (because so-called `base' modules must be named
+ # differently than add-on modules).
+ #
+ local separator_added=
+ for menuitem in $( cd "$BSDCFG_LOCAL_LIBE" 2> /dev/null && ls -d * )
+ do
+ # Skip the module if it looks like a `base' module
+ case "$menuitem" in [0-9][0-9][0-9].*) continue;; esac
+
+ [ -f "$BSDCFG_LOCAL_LIBE/$menuitem/INDEX" ] || continue
+ [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
+
+ menu_program= menu_title= menu_help=
+ f_include_lang $BSDCFG_LOCAL_LIBE/$menuitem/INDEX || continue
+ [ "$menu_program" ] || continue
+
+ if [ ! "$separator_added" ]; then
+ menu_list="$menu_list '-' '-' ''"
+ separator_added=1
+ fi
+
+ case "$menu_program" in
+ /*) : already fully qualified ;;
+ *) menu_program="$BSDCFG_LOCAL_LIBE/$menuitem/$menu_program"
+ esac
+
+ f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
+ setvar "menu_program$tag" "$menu_program"
+
+ f_shell_escape "$menu_title" menu_title
+ f_shell_escape "$menu_help" menu_help
+ menu_list="$menu_list '$tag' '$menu_title' '$menu_help'"
+
+ index=$(( $index + 1 ))
+ done
+
+ local height width rows
+ eval f_dialog_menu_with_help_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --clear \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --item-help \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_exit_bsdconfig\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+############################################################ MAIN
+
+#
+# If $0 is not "bsdconfig", interpret it either as a keyword to a menuitem or
+# as a valid resword (see script.subr for additional details about reswords).
+#
+if [ "$pgm" != "bsdconfig" ]; then
+ if indexfile=$( f_index_file "$pgm" ) &&
+ cmd=$( f_index_menusel_command "$indexfile" "$pgm" )
+ then
+ f_dprintf "pgm=[%s] cmd=[%s] *=[%s]" "$pgm" "$cmd" "$*"
+ exec "$cmd" "$@" || exit 1
+ else
+ f_include $BSDCFG_SHARE/script.subr
+ for resword in $RESWORDS; do
+ [ "$pgm" = "$resword" ] || continue
+ # Found a match
+ f_dprintf "pgm=[%s] A valid resWord!" "$pgm"
+ f_dispatch $resword $resword "$@"
+ exit $?
+ done
+ fi
+fi
+
+#
+# Process command-line arguments
+#
+scripts_loaded=0
+while getopts f:h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ f) [ $scripts_loaded -eq 0 ] && f_include $BSDCFG_SHARE/script.subr
+ f_script_load "$OPTARG"
+ scripts_loaded=$(( $scripts_loaded + 1 )) ;;
+ h|\?) usage ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+# If we've loaded any scripts, do not continue any further
+[ $scripts_loaded -gt 0 ] && exit
+
+#
+# Initialize
+#
+f_dialog_title "$msg_main_menu"
+
+[ "$SECURE" ] && f_mustberoot_init
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# 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
+ # NOTREACHED
+ esac
+
+ #
+ # Find the INDEX (possibly i18n) claiming this keyword and get the
+ # command to execute from the menu_selection line.
+ #
+ if ! { indexfile=$( f_index_file "$1" ) &&
+ cmd=$( f_index_menusel_command "$indexfile" "$1" )
+ }; then
+ # No matches, display usage (which shows valid keywords)
+ f_err "%s: %s: $msg_not_found\n" "$pgm" "$1"
+ usage
+ # NOTREACHED
+ fi
+
+ f_dprintf "cmd=[%s] *=[%s]" "$cmd" "$*"
+ shift
+ exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
+ # NOTREACHED
+fi
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$BSDCONFIG_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ f_die
+ fi
+
+ case "$mtag" in
+ X) break ;;
+ 1) # Usage
+ f_show_help "$USAGE_HELPFILE"
+ continue
+ esac
+
+ # Anything else is a dynamically loaded menuitem
+
+ f_getvar menu_program$mtag menu_program
+ case "$menu_program" in
+ /*) cmd="$menu_program" ;;
+ *) cmd="$BSDCFG_LIBE/$menu_program"
+ esac
+ f_dprintf "cmd=[%s]" "$cmd"
+ $cmd ${USE_XDIALOG:+-X}
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/bsdconfig.8 b/contrib/bsddialog/bsdconfig/bsdconfig.8
new file mode 100644
index 000000000000..9f5481cac65d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/bsdconfig.8
@@ -0,0 +1,256 @@
+.\" Copyright (c) 2012 Ron McDowell
+.\" Copyright (c) 2012-2013 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 12, 2020
+.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
+optionally takes a command as an argument.
+If invoked with no arguments, it will bring up an interactive menu listing the
+available modules.
+.Pp
+The following options are available:
+.Bl -tag -width indent+
+.It Fl d
+Provide lots of debugging info on standard-out when running.
+.It Fl D Ar file
+Send debugging info to file.
+If file begins with a plus-sign debug info is sent to both standard-out and
+file (minus the leading plus).
+.It Fl f Ar file
+Load
+.Ar file
+as script and then exit.
+If multiple occurrences, program will only exit after last occurrence.
+If
+.Ar file
+is a single dash
+.Pq Sq Fl ,
+.Nm
+reads from standard input.
+.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
+.Nm
+menu, include, and shortcut structure 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 kern_securelevel
+Shortcut to the kern.securelevel menu under security.
+.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, Wireless
+Network, Default Router/Gateway, and DNS Nameservers.
+.It Cm packages
+Browse, install, uninstall, or re-install packaged software.
+.It Cm password
+Set the system administrator
+.Pq root
+password.
+.It Cm security
+Configure various system security settings.
+.It Cm startup
+Configure various aspects of system startup.
+.It Cm startup_misc
+Shortcut to the Miscellaneous Startup Services menu under startup.
+.It Cm startup_rcadd
+Shortcut to the Add New menu under the View/Edit Startup Configuration menu
+(startup_rcconf) of startup.
+.It Cm startup_rcconf
+Shortcut to the View/Edit Startup Configuration menu under startup.
+.It Cm startup_rcdelete
+Shortcut to the Delete menu under the View/Edit Startup Configuration menu
+(startup_rcconf) of startup.
+.It Cm startup_rcvar
+Shortcut to the Toggle Startup Services menu under startup.
+.\" use neutral name, e.g. console_keymap instead of syscons_keymap?
+.\" font (encoding) selection not applicable to vt(4)!
+.It Cm syscons_font
+Shortcut to the Font menu under console.
+.\" .It Cm console_keymap
+.\" Shortcut to the Keymap menu under console.
+.It Cm syscons_keymap
+Shortcut to the Keymap menu under console.
+.\" .It Cm vt_repeat
+.\" Shortcut to the Repeat menu under console.
+.It Cm syscons_repeat
+Shortcut to the Repeat menu under console.
+.\" .It Cm vt_saver
+.\" Shortcut to the Saver menu under console.
+.It Cm syscons_saver
+Shortcut to the Saver menu under console.
+.\" screenmap (encoding) selection not applicable to vt(4)!
+.It Cm syscons_screenmap
+Shortcut to the Screenmap menu under console.
+.\" .It Cm vt_syscons_ttys
+.\" Shortcut to the Ttys 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 ttys
+Edit the
+.Xr ttys 5
+database with your favorite editor.
+.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.
+.It Cm wireless
+Shortcut to the Wireless Networks menu under networking.
+.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 bsdinstall 8
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 9.2 .
+.Sh AUTHORS
+.An Ron McDowell
+.An Devin Teske Aq Mt dteske@FreeBSD.org
+.Sh BUGS
+The docsinstall and diskmgmt modules call bsdinstall.
+Bugs found in these modules should be considered those of bsdinstall, not
+.Nm .
diff --git a/contrib/bsddialog/bsdconfig/console/INDEX b/contrib/bsddialog/bsdconfig/console/INDEX
new file mode 100644
index 000000000000..e298f340e63c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/INDEX
@@ -0,0 +1,70 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2015 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$
+
+#
+# Title that will be shown in 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="vt_font|font"
+menu_selection="vt_keymap|keymap"
+menu_selection="vt_repeat|repeat"
+menu_selection="vt_saver|saver"
+menu_selection="vt_screenmap|screenmap"
+menu_selection="vt_ttys|ttys"
+# For backward compatibility
+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 --git a/contrib/bsddialog/bsdconfig/console/Makefile b/contrib/bsddialog/bsdconfig/console/Makefile
new file mode 100644
index 000000000000..bcb2ebd44185
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/080.console
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= console font keymap repeat saver screenmap ttys
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/console/Makefile.depend b/contrib/bsddialog/bsdconfig/console/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/console/USAGE b/contrib/bsddialog/bsdconfig/console/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/console/console b/contrib/bsddialog/bsdconfig/console/console
new file mode 100755
index 000000000000..cfa44bee1abc
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/console
@@ -0,0 +1,146 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_console_menu_text"
+ local 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
+ local defaultitem= # Calculated below
+ local hline="$hline_configure_system_console_settings"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 || f_die
+ f_dialog_menutag_fetch mtag
+
+ command=
+ case "$mtag" in
+ "X $msg_exit") break ;;
+ "2 $msg_font") command=font ;; # Choose alternate screen font
+ "3 $msg_keymap") command=keymap ;; # Choose alt. keyboard map
+ "4 $msg_repeat") command=repeat ;; # Set key repeat rate
+ "5 $msg_saver") command=saver ;; # Configure the screen saver
+ "6 $msg_screenmap") command=screenmap ;; # Choose alternate screenmap
+ "7 $msg_ttys") command=ttys ;; # Choose console terminal type
+ esac
+
+ if [ "$command" ]; then
+ $BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
+ else
+ f_die 1 "$msg_unknown_console_menu_selection"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/console/font b/contrib/bsddialog/bsdconfig/console/font
new file mode 100755
index 000000000000..ce16730dd258
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/font
@@ -0,0 +1,193 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_font_menu_text"
+ local 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
+ local defaultitem= # Calculated below
+ local hline="$hline_choose_a_font"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get font8x8 )" in
+ [Nn][Oo]|'') defaultitem="1 $msg_none" ;;
+ cp437-8x8) defaultitem="2 $msg_ibm_437" ;;
+ cp850-8x8) defaultitem="3 $msg_ibm_850" ;;
+ cp865-8x8) defaultitem="4 $msg_ibm_865" ;;
+ cp866-8x8) defaultitem="5 $msg_ibm_866" ;;
+ cp866u-8x8) defaultitem="6 $msg_ibm_866u" ;;
+ cp1251-8x8) defaultitem="7 $msg_ibm_1251" ;;
+ iso-8x8) defaultitem="8 $msg_iso_8859_1" ;;
+ iso02-8x8) defaultitem="9 $msg_iso_8859_2" ;;
+ iso04-8x8) defaultitem="a $msg_iso_8859_4" ;;
+ iso07-8x8) defaultitem="b $msg_iso_8859_7" ;;
+ iso08-8x8) defaultitem="c $msg_iso_8859_8" ;;
+ iso15-8x8) defaultitem="d $msg_iso_8859_15" ;;
+ swiss-8x8) defaultitem="e $msg_swiss" ;;
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_system_console_font"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+f8= f14= f16= mc_start=
+case "$mtag" in
+"1 $msg_none") # Use hardware default font
+ f8="NO" f14="NO" f16="NO" ;;
+"2 $msg_ibm_437") # English and others, VGA default
+ f8="cp437-8x8" f14="cp437-8x14" f16="cp437-8x16" ;;
+"3 $msg_ibm_850") # Western Europe, IBM encoding
+ f8="cp850-8x8" f14="cp850-8x14" f16="cp850-8x16" ;;
+"4 $msg_ibm_865") # Norwegian, IBM encoding
+ f8="cp865-8x8" f14="cp865-8x14" f16="cp865-8x16" ;;
+"5 $msg_ibm_866") # Russian, IBM encoding (use with KOI8-R screenmap)
+ f8="cp866-8x8" f14="cp866-8x14" f16="cp866b-8x16" mc_start="3" ;;
+"6 $msg_ibm_866u") # Ukrainian, IBM encoding (use w/ KOI8-U screenmap)
+ f8="cp866u-8x8" f14="cp866u-8x14" f16="cp866u-8x16" mc_start="3" ;;
+"7 $msg_ibm_1251") # Cyrillic, MS Windows encoding
+ f8="cp1251-8x8" f14="cp1251-8x14" f16="cp1251-8x16" mc_start="3" ;;
+"8 $msg_iso_8859_1") # Western Europe, ISO encoding
+ f8="iso-8x8" f14="iso-8x14" f16="iso-8x16" ;;
+"9 $msg_iso_8859_2") # Eastern Europe, ISO encoding
+ f8="iso02-8x8" f14="iso02-8x14" f16="iso02-8x16" ;;
+"a $msg_iso_8859_4") # Baltic, ISO encoding
+ f8="iso04-8x8" f14="iso04-8x14" f16="iso04-8x16" ;;
+"b $msg_iso_8859_7") # Greek, ISO encoding
+ f8="iso07-8x8" f14="iso07-8x14" f16="iso07-8x16" ;;
+"c $msg_iso_8859_8") # Hebrew, ISO encoding
+ f8="iso08-8x8" f14="iso08-8x14" f16="iso08-8x16" ;;
+"d $msg_iso_8859_15") # Europe, ISO encoding
+ f8="iso15-8x8" f14="iso15-8x14" f16="iso15-8x16" ;;
+"e $msg_swiss") # English, better resolution
+ f8="swiss-8x8" f14="NO" f16="swiss-8x16" ;;
+esac
+
+[ "$f8" -a "$f14" -a "$f16" ] || f_die 1 "$msg_unknown_font_selection"
+
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set font8x8 "%s"' "$f8" || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set font8x14 "%s"' "$f14" || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set font8x16 "%s"' "$f16" || f_die
+
+if [ "$mc_start" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set mousechar_start "%s"' "$mc_start" || f_die
+else
+ f_eval_catch "$0" f_sysrc_delete \
+ 'f_sysrc_delete mousechar_start' || f_die
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/console/include/Makefile b/contrib/bsddialog/bsdconfig/console/include/Makefile
new file mode 100644
index 000000000000..52cb0be9c6e8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/080.console/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/console/include/Makefile.depend b/contrib/bsddialog/bsdconfig/console/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/console/include/messages.subr b/contrib/bsddialog/bsdconfig/console/include/messages.subr
new file mode 100644
index 000000000000..295f3e302db8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/include/messages.subr
@@ -0,0 +1,270 @@
+# 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$
+
+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="Blank 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_screen_font="Choose an alternate screen font"
+msg_choose_alternate_screenmap="Choose an alternate screenmap"
+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_15="Estonian ISO 15"
+msg_estonian_iso_15_desc="Estonian ISO 8859-15 keymap"
+msg_estonian_iso_desc="Estonian ISO keymap"
+msg_exit="Exit"
+msg_exit_this_menu="Exit this menu"
+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_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_green="Green"
+msg_green_desc="\"Green\" power saving mode (if supported by monitor)"
+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_1251="IBM 1251"
+msg_ibm_1251_desc="Cyrillic, MS Windows encoding"
+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_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_15="ISO 8859-15"
+msg_iso_8859_15_desc="Europe, ISO encoding"
+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_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_r_to_ibm866="KOI8-R to IBM866"
+msg_koi8_r_to_ibm866_desc="Russian KOI8-R to IBM 866 screenmap"
+msg_koi8_u="KOI8-U"
+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_keyboard_repeat_rate="System Console Keyboard Repeat Rate"
+msg_system_console_keymap="System Console Keymap"
+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_unknown_console_menu_selection="Unknown console menu selection"
+msg_unknown_font_selection="Unknown font selection"
+msg_unknown_keymap="Unknown keymap"
+msg_unknown_repeat_rate="Unknown repeat rate"
+msg_unknown_saver="Unknown saver"
+msg_unknown_screenmap_selection="Unknown screenmap selection"
+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 --git a/contrib/bsddialog/bsdconfig/console/keymap b/contrib/bsddialog/bsdconfig/console/keymap
new file mode 100755
index 000000000000..28c0500cf8ac
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/keymap
@@ -0,0 +1,338 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 prompt="$msg_keymap_menu_text"
+ local menu_list defaultitem= # Calculated below
+ local hline="$hline_choose_a_keyboard_map"
+
+ #
+ # 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"]
+ }'
+ )
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get keymap )" in
+ be.iso) defaultitem="$msg_belgian" ;;
+ br275.cp850) defaultitem="$msg_brazil_cp850" ;;
+ br275.iso) defaultitem="$msg_brazil_iso" ;;
+ br275.iso.acc) defaultitem="$msg_brazil_iso_accent" ;;
+ bg.bds.ctrlcaps) defaultitem="$msg_bulgarian_bds" ;;
+ bg.phonetic.ctrlcaps) defaultitem="$msg_bulgarian_phonetic" ;;
+ ce.iso2) defaultitem="$msg_central_european_iso" ;;
+ hr.iso) defaultitem="$msg_croatian_iso" ;;
+ cs.latin2.qwertz) defaultitem="$msg_czech_iso_accent" ;;
+ danish.cp865) defaultitem="$msg_danish_cp865" ;;
+ danish.iso) defaultitem="$msg_danish_iso" ;;
+ estonian.cp850) defaultitem="$msg_estonian_cp850" ;;
+ estonian.iso) defaultitem="$msg_estonian_iso" ;;
+ estonian.iso15) defaultitem="$msg_estonian_iso_15" ;;
+ finnish.cp850) defaultitem="$msg_finnish_cp850" ;;
+ finnish.iso) defaultitem="$msg_finnish_iso" ;;
+ fr.iso) defaultitem="$msg_french_iso" ;;
+ fr.iso.acc) defaultitem="$msg_french_iso_accent" ;;
+ fr.macbook.acc) defaultitem="$msg_french_iso_macbook" ;;
+ german.cp850) defaultitem="$msg_german_cp850" ;;
+ german.iso) defaultitem="$msg_german_iso" ;;
+ gr.us101.acc) defaultitem="$msg_greek_101" ;;
+ el.iso07) defaultitem="$msg_greek_104" ;;
+ gr.elot.acc) defaultitem="$msg_greek_elot" ;;
+ hu.iso2.101keys) defaultitem="$msg_hungarian_101" ;;
+ hu.iso2.102keys) defaultitem="$msg_hungarian_102" ;;
+ icelandic.iso) defaultitem="$msg_icelandic" ;;
+ icelandic.iso.acc) defaultitem="$msg_icelandic_accent" ;;
+ it.iso) defaultitem="$msg_italian" ;;
+ jp.106) defaultitem="$msg_japanese_106" ;;
+ latinamerican) defaultitem="$msg_latin_american" ;;
+ latinamerican.iso.acc) defaultitem="$msg_latin_american_accent" ;;
+ norwegian.iso) defaultitem="$msg_norway_iso" ;;
+ pl_PL.ISO8859-2) defaultitem="$msg_polish_iso" ;;
+ pt.iso) defaultitem="$msg_portuguese" ;;
+ pt.iso.acc) defaultitem="$msg_portuguese_accent" ;;
+ ru.koi8-r) defaultitem="$msg_russia_koi8_r" ;;
+ sk.iso2) defaultitem="$msg_slovak" ;;
+ si.iso) defaultitem="$msg_slovenian" ;;
+ spanish.iso) defaultitem="$msg_spanish" ;;
+ spanish.iso.acc) defaultitem="$msg_spanish_accent" ;;
+ swedish.cp850) defaultitem="$msg_swedish_cp850" ;;
+ swedish.iso) defaultitem="$msg_swedish_iso" ;;
+ swissfrench.cp850) defaultitem="$msg_swiss_french_cp850" ;;
+ swissfrench.iso) defaultitem="$msg_swiss_french_iso" ;;
+ swissfrench.iso.acc) defaultitem="$msg_swiss_french_iso_accent" ;;
+ swissgerman.cp850) defaultitem="$msg_swiss_german_cp850" ;;
+ swissgerman.iso) defaultitem="$msg_swiss_german_iso" ;;
+ swissgerman.iso.acc) defaultitem="$msg_swiss_german_iso_accent" ;;
+ uk.cp850) defaultitem="$msg_uk_cp850" ;;
+ uk.iso) defaultitem="$msg_uk_iso" ;;
+ ua.koi8-u) defaultitem="$msg_ukrainian_koi8_u" ;;
+ ua.koi8-u.shift.alt) defaultitem="$msg_ukrainian_koi8_u_koi8_r" ;;
+ us.ctrl) defaultitem="$msg_usa_capslock_ctrl" ;;
+ us.pc-ctrl) defaultitem="$msg_usa_capslock_ctrl" ;;
+ us.dvorak) defaultitem="$msg_usa_dvorak" ;;
+ us.dvorakl) defaultitem="$msg_usa_dvorak_left" ;;
+ us.dvorakr) defaultitem="$msg_usa_dvorak_right" ;;
+ us.emacs) defaultitem="$msg_usa_emacs" ;;
+ us.iso) defaultitem="$msg_usa_iso" ;;
+ us.unix) defaultitem="$msg_usa_unix" ;;
+ esac
+
+ # The defaultitem may have to be indented to match the menu_list
+ if [ "$defaultitem" ]; then
+ ( eval set -- $menu_list
+ while [ $# -gt 0 ]; do
+ [ "$defaultitem" = "$1" ] && break
+ [ " $defaultitem" = "$1" ] && exit 0
+ shift 2 # tag/item
+ done
+ exit 1 # No modification needed
+ ) && defaultitem=" $defaultitem"
+ fi
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 || f_die
+ f_dialog_menutag_fetch mtag
+
+ #
+ # Reverse the users choice into the variable name
+ #
+ keymap_name=
+ mtag="${mtag# }" # remove single leading-space if-present
+ for name in $KEYMAP_NAMES; do
+ debug= f_getvar msg_$name msg
+ [ "$msg" = "$mtag" ] && keymap_name="$name" break
+ done
+
+ [ "$keymap_name" ] || continue
+
+ keymap_to_set=
+ case "$keymap_name" in
+ belgian) keymap_to_set="be.iso" ;;
+ brazil_cp850) keymap_to_set="br275.cp850" ;;
+ brazil_iso) keymap_to_set="br275.iso" ;;
+ brazil_iso_accent) keymap_to_set="br275.iso.acc" ;;
+ bulgarian_bds) keymap_to_set="bg.bds.ctrlcaps" ;;
+ bulgarian_phonetic) keymap_to_set="bg.phonetic.ctrlcaps" ;;
+ central_european_iso) keymap_to_set="ce.iso2" ;;
+ croatian_iso) keymap_to_set="hr.iso" ;;
+ czech_iso_accent) keymap_to_set="cs.latin2.qwertz" ;;
+ danish_cp865) keymap_to_set="danish.cp865" ;;
+ danish_iso) keymap_to_set="danish.iso" ;;
+ estonian_cp850) keymap_to_set="estonian.cp850" ;;
+ estonian_iso) keymap_to_set="estonian.iso" ;;
+ estonian_iso_15) keymap_to_set="estonian.iso15" ;;
+ finnish_cp850) keymap_to_set="finnish.cp850" ;;
+ finnish_iso) keymap_to_set="finnish.iso" ;;
+ french_iso) keymap_to_set="fr.iso" ;;
+ french_iso_accent) keymap_to_set="fr.iso.acc" ;;
+ french_iso_macbook) keymap_to_set="fr.macbook.acc" ;;
+ german_cp850) keymap_to_set="german.cp850" ;;
+ german_iso) keymap_to_set="german.iso" ;;
+ greek_101) keymap_to_set="gr.us101.acc" ;;
+ greek_104) keymap_to_set="el.iso07" ;;
+ greek_elot) keymap_to_set="gr.elot.acc" ;;
+ hungarian_101) keymap_to_set="hu.iso2.101keys" ;;
+ hungarian_102) keymap_to_set="hu.iso2.102keys" ;;
+ icelandic) keymap_to_set="icelandic.iso" ;;
+ icelandic_accent) keymap_to_set="icelandic.iso.acc" ;;
+ italian) keymap_to_set="it.iso" ;;
+ japanese_106) keymap_to_set="jp.106" ;;
+ latin_american) keymap_to_set="latinamerican" ;;
+ latin_american_accent) keymap_to_set="latinamerican.iso.acc" ;;
+ norway_iso) keymap_to_set="norwegian.iso" ;;
+ polish_iso) keymap_to_set="pl_PL.ISO8859-2" ;;
+ portuguese) keymap_to_set="pt.iso" ;;
+ portuguese_accent) keymap_to_set="pt.iso.acc" ;;
+ russia_koi8_r) keymap_to_set="ru.koi8-r" ;;
+ slovak) keymap_to_set="sk.iso2" ;;
+ slovenian) keymap_to_set="si.iso" ;;
+ spanish) keymap_to_set="spanish.iso" ;;
+ spanish_accent) keymap_to_set="spanish.iso.acc" ;;
+ swedish_cp850) keymap_to_set="swedish.cp850" ;;
+ swedish_iso) keymap_to_set="swedish.iso" ;;
+ swiss_french_cp850) keymap_to_set="swissfrench.cp850" ;;
+ swiss_french_iso) keymap_to_set="swissfrench.iso" ;;
+ swiss_french_iso_accent) keymap_to_set="swissfrench.iso.acc" ;;
+ swiss_german_cp850) keymap_to_set="swissgerman.cp850" ;;
+ swiss_german_iso) keymap_to_set="swissgerman.iso" ;;
+ swiss_german_iso_accent) keymap_to_set="swissgerman.iso.acc" ;;
+ uk_cp850) keymap_to_set="uk.cp850" ;;
+ uk_iso) keymap_to_set="uk.iso" ;;
+ ukrainian_koi8_u) keymap_to_set="ua.koi8-u" ;;
+ ukrainian_koi8_u_koi8_r) keymap_to_set="ua.koi8-u.shift.alt" ;;
+ usa_capslock_ctrl)
+ case "$( sysctl -n kern.vty )" in
+ vt) keymap_to_set="us.ctrl" ;;
+ *) keymap_to_set="us.pc-ctrl" ;;
+ esac
+ ;;
+ usa_dvorak) keymap_to_set="us.dvorak" ;;
+ usa_dvorak_left) keymap_to_set="us.dvorakl" ;;
+ usa_dvorak_right) keymap_to_set="us.dvorakr" ;;
+ usa_emacs) keymap_to_set="us.emacs" ;;
+ usa_iso) keymap_to_set="us.iso" ;;
+ usa_unix) keymap_to_set="us.unix" ;;
+ esac
+
+ if [ "$keymap_to_set" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set keymap "%s"' "$keymap_to_set" || f_die
+ break
+ else
+ f_die 1 "$msg_unknown_keymap"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/console/repeat b/contrib/bsddialog/bsdconfig/console/repeat
new file mode 100755
index 000000000000..ff000234dc74
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/repeat
@@ -0,0 +1,143 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_repeat_menu_text"
+ local menu_list="
+ '$msg_default' '$msg_default_desc'
+ '$msg_slow' '$msg_slow_desc'
+ '$msg_normal' '$msg_normal_desc'
+ '$msg_fast' '$msg_fast_desc'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_choose_a_keyboard_repeat_rate"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get keyrate )" in
+ [Nn][Oo]|'') defaultitem="$msg_default" ;;
+ slow) defaultitem="$msg_slow" ;;
+ normal) defaultitem="$msg_normal" ;;
+ fast) defaultitem="$msg_fast" ;;
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_system_console_keyboard_repeat_rate"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+repeat_rate_to_set=
+case "$mtag" in
+"$msg_default") repeat_rate_to_set="NO" ;; # Use default repeat rate
+"$msg_slow") repeat_rate_to_set="slow" ;; # Slow keyboard repeat rate
+"$msg_normal") repeat_rate_to_set="normal" ;; # "Normal" keyboard repeat rate
+"$msg_fast") repeat_rate_to_set="fast" ;; # Fast keyboard repeat rate
+esac
+
+if [ "$repeat_rate_to_set" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set keyrate "%s"' "$repeat_rate_to_set" || f_die
+ break
+else
+ f_die 1 "$msg_unknown_repeat_rate"
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/console/saver b/contrib/bsddialog/bsdconfig/console/saver
new file mode 100755
index 000000000000..0df487c9583d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/saver
@@ -0,0 +1,195 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_saver_menu_text"
+ local menu_list="
+ '1 $msg_none' '$msg_none_saver_desc'
+ '2 $msg_blank' '$msg_blank_desc'
+ '3 $msg_beastie' '$msg_beastie_desc'
+ '4 $msg_daemon' '$msg_daemon_desc'
+ '5 $msg_dragon' '$msg_dragon_desc'
+ '6 $msg_fade' '$msg_fade_desc'
+ '7 $msg_fire' '$msg_fire_desc'
+ '8 $msg_green' '$msg_green_desc'
+ '9 $msg_logo' '$msg_logo_desc'
+ 'a $msg_rain' '$msg_rain_desc'
+ 'b $msg_snake' '$msg_snake_desc'
+ 'c $msg_star' '$msg_star_desc'
+ 'd $msg_warp' '$msg_warp_desc'
+ '$msg_timeout' '$msg_timeout_desc'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_choose_a_screen_saver"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get saver )" in
+ [Nn][Oo]|'') defaultitem="1 $msg_none" ;;
+ blank) defaultitem="2 $msg_blank" ;;
+ beastie) defaultitem="3 $msg_beastie" ;;
+ daemon) defaultitem="4 $msg_daemon" ;;
+ dragon) defaultitem="5 $msg_dragon" ;;
+ fade) defaultitem="6 $msg_fade" ;;
+ fire) defaultitem="7 $msg_fire" ;;
+ green) defaultitem="8 $msg_green" ;;
+ logo) defaultitem="9 $msg_logo" ;;
+ rain) defaultitem="a $msg_rain" ;;
+ snake) defaultitem="b $msg_snake" ;;
+ star) defaultitem="c $msg_star" ;;
+ warp) defaultitem="d $msg_warp" ;;
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_system_console_screen_saver"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+case "$mtag" in
+"$msg_timeout") # Set the screen saver timeout interval
+ f_dialog_title "$msg_value_required"
+ f_dialog_input blanktime "$msg_enter_timeout_period" \
+ "$( f_sysrc_get blanktime )" &&
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set blanktime "%s"' "$blanktime" || f_die
+ f_dialog_title_restore
+ exit $SUCCESS
+esac
+
+saver_to_set=
+case "$mtag" in
+"1 $msg_none") # Disable the screensaver
+ saver_to_set="NO" ;;
+"2 $msg_blank") # Simply blank the screen
+ saver_to_set="blank" ;;
+"3 $msg_beastie") # "BSD Daemon" animated screen saver (graphics)
+ saver_to_set="beastie" ;;
+"4 $msg_daemon") # "BSD Daemon" animated screen saver (text)
+ saver_to_set="daemon" ;;
+"5 $msg_dragon") # Dragon screensaver (graphics)
+ saver_to_set="dragon" ;;
+"6 $msg_fade") # Fade out effect screen saver
+ saver_to_set="fade" ;;
+"7 $msg_fire") # Flames effect screen saver
+ saver_to_set="fire" ;;
+"8 $msg_green") # "Green" power saving mode (if supported by monitor)
+ saver_to_set="green" ;;
+"9 $msg_logo") # FreeBSD "logo" animated screen saver (graphics)
+ saver_to_set="logo" ;;
+"a $msg_rain") # Rain drops screen saver
+ saver_to_set="rain" ;;
+"b $msg_snake") # Draw a FreeBSD "snake" on your screen
+ saver_to_set="snake" ;;
+"c $msg_star") # A "twinkling stars" effect
+ saver_to_set="star" ;;
+"d $msg_warp") # A "stars warping" effect
+ saver_to_set="warp" ;;
+esac
+
+if [ "$saver_to_set" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set saver "%s"' "$saver_to_set" || f_die
+ break
+else
+ f_die 1 "$msg_unknown_saver"
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/console/screenmap b/contrib/bsddialog/bsdconfig/console/screenmap
new file mode 100755
index 000000000000..5bf5bd872da0
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/screenmap
@@ -0,0 +1,155 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_screenmap_menu_text"
+ local 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
+ local defaultitem= # Calculated below
+ local hline="$hline_choose_a_screen_map"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get scrnmap )" in
+ [Nn][Oo]|'') defaultitem="1 $msg_none" ;;
+ iso-8859-1_to_cp437) defaultitem="2 $msg_iso_8859_1_to_ibm437" ;;
+ iso-8859-7_to_cp437) defaultitem="3 $msg_iso_8859_7_to_ibm437" ;;
+ us-ascii_to_cp437) defaultitem="4 $msg_us_ascii_to_ibm327" ;;
+ koi8-r2cp866) defaultitem="5 $msg_koi8_r_to_ibm866" ;;
+ koi8-u2cp866u) defaultitem="6 $msg_koi8_u_to_ibm866u" ;;
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_system_console_screenmap"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+scrnmap_to_set=
+case "$mtag" in
+"1 $msg_none") # No screenmap, don't touch font
+ scrnmap_to_set="NO" ;;
+"2 $msg_iso_8859_1_to_ibm437") # W-Europe ISO 8859-1 to IBM 437 scrnmap
+ scrnmap_to_set="iso-8859-1_to_cp437" ;;
+"3 $msg_iso_8859_7_to_ibm437") # Greek ISO 8859-7 to IBM 437 screenmap
+ scrnmap_to_set="iso-8859-7_to_cp437" ;;
+"4 $msg_us_ascii_to_ibm327") # US-ASCII to IBM 437 screenmap
+ scrnmap_to_set="us-ascii_to_cp437" ;;
+"5 $msg_koi8_r_to_ibm866") # Russian KOI8-R to IBM 866 screenmap
+ scrnmap_to_set="koi8-r2cp866" ;;
+"6 $msg_koi8_u_to_ibm866u") # Ukrainian KOI8-U to IBM 866u screenmap
+ scrnmap_to_set="koi8-u2cp866u" ;;
+esac
+
+if [ "$scrnmap_to_set" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set scrnmap "%s"' "$scrnmap_to_set" || f_die
+ break
+else
+ f_die 1 "$msg_unknown_screenmap_selection"
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/console/ttys b/contrib/bsddialog/bsdconfig/console/ttys
new file mode 100755
index 000000000000..54dcb66bdd99
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/console/ttys
@@ -0,0 +1,207 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ CONFIGURATION
+
+#
+# Location of ttys(5)
+#
+ETC_TTYS=/etc/ttys
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_ttys_menu_text"
+ local 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
+ local hline="$hline_choose_a_terminal_type"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+
+ if [ $retval -eq $DIALOG_OK ]; then
+ local item
+ item=$( eval f_dialog_menutag2item \
+ \"\$menu_choice\" $menu_list )
+ f_dialog_menuitem_store "$item"
+ fi
+
+ return $retval
+}
+
+# ttys_set_type $consterm
+#
+# Set terminal type of `ttyv*' and `cons[0-9]' entries in ttys(5) to $consterm.
+#
+ttys_set_type()
+{
+ local funcname=ttys_set_type
+ local consterm="$1" err
+
+ #
+ # Create new temporary file to write our ttys(5) update with new types.
+ #
+ local tmpfile
+ f_eval_catch -k tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" ||
+ 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 owner
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$ETC_TTYS" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$ETC_TTYS" || owner="root:wheel"
+ f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile"
+
+ #
+ # Operate on ttys(5), replacing only the types of `ttyv*' and
+ # `cons[0-9]' terminals with the new type.
+ #
+ if ! err=$( 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" 2>&1 ); then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+ f_eval_catch $funcname mv 'mv -f "%s" "%s"' "$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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_system_console_terminal_type"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+[ "$mtag" = "1 $msg_none" ] && exit $SUCCESS
+
+f_dialog_menuitem_fetch consterm
+ttys_set_type "$consterm" || f_die
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/diskmgmt/INDEX b/contrib/bsddialog/bsdconfig/diskmgmt/INDEX
new file mode 100644
index 000000000000..e04bb79dafe2
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/diskmgmt/Makefile b/contrib/bsddialog/bsdconfig/diskmgmt/Makefile
new file mode 100644
index 000000000000..16a89009bb6e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/050.diskmgmt
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= diskmgmt
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/diskmgmt/Makefile.depend b/contrib/bsddialog/bsdconfig/diskmgmt/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/diskmgmt/USAGE b/contrib/bsddialog/bsdconfig/diskmgmt/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/diskmgmt/diskmgmt b/contrib/bsddialog/bsdconfig/diskmgmt/diskmgmt
new file mode 100755
index 000000000000..ec567f550e77
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/diskmgmt
@@ -0,0 +1,85 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="050.diskmgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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/bsdinstall partedit
+else
+ exec /usr/sbin/bsdinstall partedit
+fi
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile b/contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile
new file mode 100644
index 000000000000..c9271532ff8c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/050.diskmgmt/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile.depend b/contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/diskmgmt/include/messages.subr b/contrib/bsddialog/bsdconfig/diskmgmt/include/messages.subr
new file mode 100644
index 000000000000..f0b563f970a8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/diskmgmt/include/messages.subr
@@ -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$
+
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
diff --git a/contrib/bsddialog/bsdconfig/docsinstall/INDEX b/contrib/bsddialog/bsdconfig/docsinstall/INDEX
new file mode 100644
index 000000000000..6308f30cecf7
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/docsinstall/Makefile b/contrib/bsddialog/bsdconfig/docsinstall/Makefile
new file mode 100644
index 000000000000..2ab3a680a4eb
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/020.docsinstall
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= docsinstall
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/docsinstall/Makefile.depend b/contrib/bsddialog/bsdconfig/docsinstall/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/docsinstall/USAGE b/contrib/bsddialog/bsdconfig/docsinstall/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/docsinstall/docsinstall b/contrib/bsddialog/bsdconfig/docsinstall/docsinstall
new file mode 100755
index 000000000000..19128fed6562
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/docsinstall
@@ -0,0 +1,97 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="020.docsinstall"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 --git a/contrib/bsddialog/bsdconfig/docsinstall/include/Makefile b/contrib/bsddialog/bsdconfig/docsinstall/include/Makefile
new file mode 100644
index 000000000000..a3ca529a7cc4
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/020.docsinstall/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/docsinstall/include/Makefile.depend b/contrib/bsddialog/bsdconfig/docsinstall/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/docsinstall/include/messages.subr b/contrib/bsddialog/bsdconfig/docsinstall/include/messages.subr
new file mode 100644
index 000000000000..4c55f0fc078a
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/docsinstall/include/messages.subr
@@ -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$
+
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
+msg_permission_denied="%s: %s: permission denied"
diff --git a/contrib/bsddialog/bsdconfig/dot/INDEX b/contrib/bsddialog/bsdconfig/dot/INDEX
new file mode 100644
index 000000000000..fa641e01f120
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/dot/Makefile b/contrib/bsddialog/bsdconfig/dot/Makefile
new file mode 100644
index 000000000000..ccd10b449cb6
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/dot
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= dot
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/dot/Makefile.depend b/contrib/bsddialog/bsdconfig/dot/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/dot/USAGE b/contrib/bsddialog/bsdconfig/dot/USAGE
new file mode 100644
index 000000000000..5bc38cc57071
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/USAGE
@@ -0,0 +1,143 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/dot/dot b/contrib/bsddialog/bsdconfig/dot/dot
new file mode 100755
index 000000000000..f71c0e81487f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/dot
@@ -0,0 +1,678 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent common.subr from auto initializing debugging (this is not an inter-
+# active utility so does not require debugging; also `-d' has been repurposed).
+#
+DEBUG_SELF_INITIALIZE=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="dot"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ CONFIGURATION
+
+#
+# Location 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 # Pedantic
+
+#
+# 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
+ print_includes_awk='
+ BEGIN { regex = "^f_include \\$BSDCFG_SHARE/" }
+ ( $0 ~ regex ) { sub(regex, ""); print }
+ ' # END-QUOTE
+
+ #
+ # 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 \
+ $BSDCFG_SHARE/script.subr \
+ ; 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 "$print_includes_awk" $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
+ #
+ before="$include_file_list"
+ while :; do
+ for file in $include_file_list; do
+ include_file_list="$include_file_list $(
+ awk "$print_includes_awk" $BSDCFG_SHARE/$file
+ )"
+ done
+
+ #
+ # Sort 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
+ )
+
+ [ "$include_file_list" = "$before" ] && break
+ before="$include_file_list"
+ done
+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(1) 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 = true, // 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##*/}\""
+ 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"
+ #print_node edge "label = \"\\T\"" "fontsize = 9"
+ # NOTE: Edge labels are buggy on large graphs
+ file_list=$(
+ for file in \
+ $BSDCONFIG \
+ $menu_program_list \
+ $submenu_program_list \
+ $cmd_program_list \
+ $include_file_list \
+ ; do
+ [ -f "$BSDCFG_SHARE/$file" ] &&
+ echo $BSDCFG_SHARE/$file
+ [ -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#$BSDCFG_SHARE/}" \
+ -v bsdconfig="$BSDCONFIG" \
+ '
+ BEGIN { regex = "^f_include \\$BSDCFG_SHARE/" }
+ ( $0 ~ regex ) {
+ sub(regex, "")
+ if ( file == bsdconfig ) sub(".*/", "", file)
+ printf "\t\t\"%s\" -> \"%s\";\n", $0, file
+ }
+ ' $file
+ done | sort
+ 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"
+end_nodelist
+if [ "$SHOW_INCLUDES" ]; then
+ for include_file in $include_file_list; do
+ echo $include_file
+ done | awk \
+ -v bgcolor="$bgcolor_bsdconfig" \
+ -v msg_subroutines="$msg_subroutines" \
+ '
+ BEGIN { created = 0 }
+ function end_subgraph() { printf "\t};\n" }
+ ( $0 !~ "/" ) {
+ if ( ! created )
+ {
+ printf "\tsubgraph \"%s\" {\n",
+ "cluster_bsdconfig_includes"
+ printf "\t\tbgcolor = \"%s\";\n", bgcolor
+ printf "\t\tlabel = \"bsdconfig %s\";\n",
+ msg_subroutines
+ created++
+ }
+ printf "\t\t\"%s\";\n", $1
+ }
+ END { created && end_subgraph() }
+ ' # END-QUOTE
+
+ for include_file in $include_file_list; do
+ echo $include_file
+ done | awk -v msg_subroutines="$msg_subroutines" '
+ BEGIN { created = 0 }
+ function end_subgraph() { printf "\t};\n" }
+ ( $0 ~ "/" ) {
+ include_dir_tmp = $1
+ sub("/[^/]*$", "", include_dir_tmp)
+ gsub(/[^[:alnum:]_]/, "_", include_dir_tmp)
+
+ if ( created && include_dir != include_dir_tmp )
+ {
+ end_subgraph()
+ created = 0
+ }
+
+ if ( ! created )
+ {
+ include_dir = include_dir_tmp
+ printf "\tsubgraph \"cluster_%s_includes\" {\n",
+ include_dir
+ printf "\t\tbgcolor = \"thistle\";\n"
+ printf "\t\tlabel = \"%s %s\";\n", include_dir,
+ msg_subroutines
+ created++
+ }
+
+ printf "\t\t\"%s\";\n", $1
+ }
+ END { created && end_subgraph() }'
+fi
+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 --git a/contrib/bsddialog/bsdconfig/dot/include/Makefile b/contrib/bsddialog/bsdconfig/dot/include/Makefile
new file mode 100644
index 000000000000..b687b88cf254
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/dot/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/dot/include/Makefile.depend b/contrib/bsddialog/bsdconfig/dot/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/dot/include/messages.subr b/contrib/bsddialog/bsdconfig/dot/include/messages.subr
new file mode 100644
index 000000000000..f1095f7e4995
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/dot/include/messages.subr
@@ -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$
+
+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"
+msg_subroutines="Subroutines"
diff --git a/contrib/bsddialog/bsdconfig/examples/Makefile b/contrib/bsddialog/bsdconfig/examples/Makefile
new file mode 100644
index 000000000000..f66c2b19eff7
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/examples/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/examples/bsdconfig
+FILES= add_some_packages.sh browse_packages_http.sh bsdconfigrc
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/examples/Makefile.depend b/contrib/bsddialog/bsdconfig/examples/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/examples/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/examples/add_some_packages.sh b/contrib/bsddialog/bsdconfig/examples/add_some_packages.sh
new file mode 100755
index 000000000000..8750908dbb2c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/examples/add_some_packages.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+# $FreeBSD$
+#
+# This sample installs a short list of packages from the main HTTP site.
+#
+[ "$_SCRIPT_SUBR" ] || . /usr/share/bsdconfig/script.subr || exit 1
+nonInteractive=1
+_httpPath=http://pkg.freebsd.org
+mediaSetHTTP
+mediaOpen
+for package in wget bash rsync; do
+ packageAdd
+done
diff --git a/contrib/bsddialog/bsdconfig/examples/browse_packages_http.sh b/contrib/bsddialog/bsdconfig/examples/browse_packages_http.sh
new file mode 100755
index 000000000000..91b928d183bb
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/examples/browse_packages_http.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# $FreeBSD$
+#
+# This sample downloads the package digests.txz and packagesite.txz files from
+# HTTP to /tmp (if they don't already exist) and then displays the package
+# configuration/management screen using the local files (resulting in faster
+# browsing of packages from-start since digests.txz/packagesite.txz can be
+# loaded from local media).
+#
+# NOTE: Packages cannot be installed unless staged to
+# /tmp/packages/$PKG_ABI/All
+#
+[ "$_SCRIPT_SUBR" ] || . /usr/share/bsdconfig/script.subr || exit 1
+nonInteractive=1
+f_musthavepkg_init # Make sure we have a usable pkg(8) with $PKG_ABI
+TMPDIR=/tmp
+PKGDIR=$TMPDIR/packages/$PKG_ABI
+[ -d "$PKGDIR" ] || mkdir -p "$PKGDIR" || exit 1
+for file in digests.txz packagesite.txz; do
+ [ -s "$PKGDIR/$file" ] && continue
+ if [ ! "$HTTP_INITIALIZED" ]; then
+ _httpPath=http://pkg.freebsd.org
+ mediaSetHTTP
+ mediaOpen
+ fi
+ f_show_info "Downloading %s from\n %s" "$file" "$_httpPath"
+ f_device_get device_media "/$PKG_ABI/latest/$file" > $PKGDIR/$file ||
+ exit 1
+done
+_directoryPath=$TMPDIR
+mediaSetDirectory
+configPackages
diff --git a/contrib/bsddialog/bsdconfig/examples/bsdconfigrc b/contrib/bsddialog/bsdconfig/examples/bsdconfigrc
new file mode 100644
index 000000000000..2e3155fda779
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/examples/bsdconfigrc
@@ -0,0 +1,42 @@
+# 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$
+
+# This file allows you to customize the behavior of bsdconfig.
+# Copy it to your $HOME/.bsdconfigrc and edit to suit.
+
+# Debugging aids for development
+#
+#debug=1
+#debugFile=$HOME/out
+#debugFile=+$HOME/out # includes debug to stdout
+
+# Optionally override functions to be more verbose (like including the date)
+#
+# f_dprintf() {
+# local format="$1"; shift
+# printf "$(date):$pgm:$format\n" "$@" >> $HOME/out
+# }
diff --git a/contrib/bsddialog/bsdconfig/include/Makefile b/contrib/bsddialog/bsdconfig/include/Makefile
new file mode 100644
index 000000000000..913481c856ef
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/include
+FILES= bsdconfig.hlp media.hlp messages.subr network_device.hlp \
+ options.hlp tcp.hlp usage.hlp
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/include/Makefile.depend b/contrib/bsddialog/bsdconfig/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/include/bsdconfig.hlp b/contrib/bsddialog/bsdconfig/include/bsdconfig.hlp
new file mode 100644
index 000000000000..b6eeaf3c45a7
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/bsdconfig.hlp
@@ -0,0 +1,12 @@
+This menu allows you to configure your system after the installation
+process is complete. At the minimum, you should probably set the root
+password and the system time zone.
+
+For extra goodies like bash, emacs, firefox, etc., you should look at
+the Packages item in this menu.
+
+For setting the timezone after the system is installed, use the 'Time
+Zone' item in this menu.
+
+For more information on the overall general system configuration, see
+the /etc/rc.conf and /etc/defaults/rc.conf files.
diff --git a/contrib/bsddialog/bsdconfig/include/media.hlp b/contrib/bsddialog/bsdconfig/include/media.hlp
new file mode 100644
index 000000000000..6fd609473810
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/media.hlp
@@ -0,0 +1,54 @@
+You can install from the following types of media:
+
+ CDROM requires one of the following supported CDROM drives:
+ ATAPI - Any standard ATAPI CDROM drive hooked to
+ a supported controller (see Hardware Guide).
+ SCSI - Any standard SCSI CDROM drive hooked to
+ a supported controller (see Hardware Guide).
+
+
+ DOS A DOS primary partition with the required FreeBSD
+ distribution files copied onto it (e.g. C:\FREEBSD\)
+
+
+ UFS Assuming a disk or partition with an existing
+ FreeBSD file system and distribution set on it,
+ get the distribution files from there.
+
+
+ Floppy Get distribution files from one or more DOS or UFS
+ formatted floppies. Such floppies are assumed to
+ contain the appropriate distribution pieces - see
+ ABOUT.TXT for more information about making floppy
+ distribution media.
+
+
+ FTP Get the distribution files from an anonymous ftp server
+ (you will be presented with a list). Please note that
+ you may invoke FTP in "Active"/"Passive" auto-mode, or
+ via an HTTP proxy.
+
+ By default, ftp(1) will automatically use the best mode
+ for the server. Using an HTTP proxy is sometimes necessary
+ for firewalls which block all FTP connections.
+
+ If you chose to enter your own URL in the FTP menu, please
+ note that all paths are *relative* to the home directory
+ of the user being logged in as. By default, this is the
+ user "ftp" (anonymous ftp) but you may change this in the
+ Options screen.
+
+
+ HTTP Direct
+ Get the distribution files directly from an HTTP server.
+
+ If you chose to enter your own URL in the HTTP Direct menu,
+ please note that all paths are *relative* to the root
+ directory of the web server.
+
+
+ NFS Get the distribution files from an NFS server somewhere
+ (make sure that permissions on the server allow this!).
+ If this install method hangs on you or refuses to work
+ properly, you may need to set some special options for
+ your NFS server. See the Options screen for more details.
diff --git a/contrib/bsddialog/bsdconfig/include/messages.subr b/contrib/bsddialog/bsdconfig/include/messages.subr
new file mode 100644
index 000000000000..9d910032616d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/messages.subr
@@ -0,0 +1,464 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+field_password="Password:"
+field_username="Username:"
+hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER"
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+hline_arrows_tab_punc_enter="Use arrows, TAB, punctuation, ENTER"
+hline_choose_help_for_more_information_on_media_types="Choose Help for more information on the various media types"
+msg_accept_continue="Accept/Continue"
+msg_accessibility_desc="Ports to help disabled users."
+msg_adding_package_as_a_dependency_from_media="Adding %s (as a dependency) from %s"
+msg_adding_package_from_media="Adding %s from %s"
+msg_afterstep_desc="Ports to support the AfterStep window manager."
+msg_all="All"
+msg_all_desc="All available packages in all categories."
+msg_always_try_sudo_when_run_as="Always try sudo(8) when run as %s"
+msg_an_unknown_error_occurred="An unknown error occurred"
+msg_arabic_desc="Ported software for Arab countries."
+msg_archivers_desc="Utilities for archiving and unarchiving data."
+msg_armenia="Armenia"
+msg_assume_network_is_already_configured="Running multi-user, assume that the network is already configured?"
+msg_assume_yes_to_all_non_critical_dialogs="Assume \"Yes\" answers to all non-critical dialogs"
+msg_astro_desc="Applications related to astronomy."
+msg_attempt_automatic_dhcp_configuration="Attempt automatic DHCP configuration of interfaces"
+msg_attempt_ipv6_configuration_of_interfaces="Attempt IPv6 configuration of interfaces"
+msg_attempting_to_update_repository_catalogue="Attempting to update repository catalogue from selected media."
+msg_audio_desc="Audio utilities - most require a supported sound card."
+msg_australia="Australia"
+msg_austria="Austria"
+msg_back="Back"
+msg_becoming_root_via_sudo="Becoming root via sudo(8)..."
+msg_benchmarks_desc="Utilities for measuring system performance."
+msg_biology_desc="Software related to biology."
+msg_bootstrapping_pkg="Bootstrapping pkg(8)..."
+msg_brazil="Brazil"
+msg_building_package_menus="Building package menu(s)..."
+msg_building_package_main_menu="Building package main menu..."
+msg_bulgaria="Bulgaria"
+msg_cad_desc="Computer Aided Design utilities."
+msg_canada="Canada"
+msg_cancel="Cancel"
+msg_cancel_exit="Cancel/Exit"
+msg_cannot_create_permission_denied="%s: cannot create %s: Permission denied"
+msg_cannot_edit_wireless_ssid="Cannot edit wireless configuration; no matches for\nSSID \`%s' in wpa_supplicants.conf(5)"
+msg_cannot_resolve_hostname="Cannot resolve \`%s'! Are you sure that your\nname server, gateway and network interface are correctly configured?"
+msg_cant_find_distribution="Warning: Can't find the \`%s' distribution on this\nFTP server. You may need to visit a different server for\nthe release you are trying to fetch or go to the Options\nmenu and set the release name to explicitly match what's\navailable on %s (or set to \"any\").\n\nWould you like to select another FTP server?"
+msg_cant_seem_to_write_out_resolv_conf="Can't seem to write out %s. Net cannot be used."
+msg_cant_start_wpa_supplicant="Can't start wpa_supplicant(8). Please create a wlan(4)\ninterface from the \`wlans' option after selecting your\nfavorite wireless adapter (i.e., %s)."
+msg_cd_dvd="CD/DVD"
+msg_cdrom="CDROM"
+msg_checking_access_to="Checking access to\n %s"
+msg_china="China"
+msg_chinese_desc="Ported software for the Chinese market."
+msg_choose_a_cd_dvd_type="Choose a CD/DVD type"
+msg_choose_a_dos_partition="Choose a DOS partition"
+msg_choose_a_floppy_drive="Choose a Floppy drive"
+msg_choose_a_ufs_partition="Choose a UFS partition"
+msg_choose_a_usb_drive="Choose a USB drive"
+msg_choose_installation_media="Choose Installation Media"
+msg_choose_installation_media_description="FreeBSD can be installed from a variety of different installation\nmedia, ranging from floppies to an Internet FTP server. If you're\ninstalling FreeBSD from a supported CD/DVD drive then this is generally\nthe best media to use if you have no overriding reason for using other\nmedia."
+msg_client_error="Client error, you could try an other server"
+msg_command_failed_rest_of_script_aborted="Command \`%s' failed - rest of script aborted."
+msg_comms_desc="Communications utilities."
+msg_configuration_for_interface="Configuration for Interface"
+msg_configured="Configured"
+msg_configured_lc="configured"
+msg_configured_ssids="Configured SSIDs"
+msg_converters_desc="Format conversion utilities."
+msg_could_not_unmount_the_cdrom_dvd="Could not unmount the CDROM/DVD from %s: %s"
+msg_could_not_unmount_the_dos_partition="Could not unmount the DOS partition from %s: %s"
+msg_could_not_unmount_the_nfs_partition="Could not unmount the NFS partition from %s: %s"
+msg_could_not_unmount_the_ufs_partition="Could not unmount the UFS partition from %s: %s"
+msg_couldnt_connect_to_ftp_server="Couldn't connect to FTP server"
+msg_couldnt_connect_to_proxy="Couldn't connect to proxy"
+msg_couldnt_connect_to_server="Couldn't connect to server"
+msg_couldnt_open_ftp_connection="Couldn't open FTP connection to %s:\n %s."
+msg_create_new="Create New"
+msg_created_path="Created %s"
+msg_czech_republic="Czech Republic"
+msg_databases_desc="Database software."
+msg_debugging="Debugging"
+msg_denmark="Denmark"
+msg_deskutils_desc="Various Desktop utilities."
+msg_destroy="Destroy"
+msg_details="Details"
+msg_devel_desc="Software development utilities and libraries."
+msg_device_is_not_configured="The %s device is not configured. You will need to do so\nin the Networking configuration menu before proceeding."
+msg_dhcp="DHCP"
+msg_dialog_mixedform_navigation_help="Use <up>/<down> arrows to navigate between fields, TAB to focus buttons, and Enter for OK/Cancel."
+msg_directory="Directory"
+msg_directory_not_found="%s: Directory not found."
+msg_directory_where_package_temporary_files_go="The directory where package temporary files should go"
+msg_discovered_ssids="Discovered SSIDs"
+msg_dns_desc="Domain Name Service tools."
+msg_docs_desc="Meta-ports for FreeBSD documentation."
+msg_done="Done"
+msg_dos="DOS"
+msg_editor="Editor"
+msg_editors_desc="Editors."
+msg_elisp_desc="Things related to Emacs Lisp."
+msg_emit_extra_debugging_output="Emit extra debugging output"
+msg_emulators_desc="Utilities for emulating other operating systems."
+msg_enlightenment_desc="Software for the Enlightenment Desktop Environment."
+msg_enter_a_fully_qualified_pathname_for_the_directory="Enter a fully qualified pathname for the directory\ncontaining the FreeBSD distribution files:"
+msg_enter_the_device_name_of_a_ufs_formatted_partition="Enter the device-name of a UFS formatted partition"
+msg_error="Error"
+msg_error_mounting_device="Error mounting %s on %s: %s"
+msg_error_mounting_floppy_device="Error mounting floppy %s (%s) on %s: %s"
+msg_error_mounting_usb_drive="Error mounting USB drive %s on %s: %s"
+msg_error_when_requesting_url="Error when requesting %s, you could try an other server"
+msg_estonia="Estonia"
+msg_exit="Exit"
+msg_exit_bsdconfig="Exit bsdconfig"
+msg_extra_options_to_ifconfig="Extra options to ifconfig (usually empty):"
+msg_failed_to_add_default_route="Failed to add a default route; please check your network configuration"
+msg_failed_to_reach_wpa_supplicant="Failed to reach wpa_supplicant: %s"
+msg_file_system="File System"
+msg_finance_desc="Monetary, financial and related applications."
+msg_finland="Finland"
+msg_floppy="Floppy"
+msg_forget_all="Forget All"
+msg_forget_all_confirm="WARNING! Are you really sure you want to forget all known networks\nby re-initializing wpa_supplicants.conf(5)? This cannot be undone."
+msg_forget_all_help="Reset wpa_supplicant(8) configuration, forgetting all known networks"
+msg_found="found"
+msg_france="France"
+msg_french_desc="Ported software for French countries."
+msg_ftp="FTP"
+msg_ftp_desc="FTP client and server utilities."
+msg_ftp_passive="FTP Passive"
+msg_ftp_username="FTP username"
+msg_generating_index_from_pkg_database="Generating INDEX from pkg(8) database\n(this can take a while)..."
+msg_geography_desc="Geography-related software."
+msg_german_desc="Ported software for Germanic countries."
+msg_germany="Germany"
+msg_gnome_desc="Components of the Gnome Desktop environment."
+msg_gnustep_desc="Software for GNUstep desktop environment."
+msg_graphics_desc="Graphics libraries and utilities."
+msg_greece="Greece"
+msg_hamradio_desc="Software for amateur radio."
+msg_haskell_desc="Software related to the Haskell language."
+msg_hebrew_desc="Ported software for Hebrew language."
+msg_help="Help"
+msg_host_name_including_domain="Host name (including domain)"
+msg_hostname_variable_not_set="WARNING: hostname variable not set and is a non-optional\nparameter. Please add this to your installation script\nor set the netInteractive variable (see bsdconfig man page)"
+msg_http_direct="HTTP Direct"
+msg_http_proxy="HTTP Proxy"
+msg_hungarian_desc="Ported software for the Hungarian market."
+msg_iceland="Iceland"
+msg_install_from_a_dos_partition="Install from a DOS partition"
+msg_install_from_a_floppy_disk_set="Install from a floppy disk set"
+msg_install_from_a_freebsd_cd_dvd="Install from a FreeBSD CD/DVD"
+msg_install_from_a_ufs_partition="Install from a UFS partition"
+msg_install_from_a_usb_drive="Install from a USB drive"
+msg_install_from_an_ftp_server="Install from an FTP server"
+msg_install_from_an_ftp_server_thru_firewall="Install from an FTP server through a firewall"
+msg_install_from_an_ftp_server_thru_proxy="Install from an FTP server through an HTTP proxy"
+msg_install_from_an_http_server="Install from an HTTP server"
+msg_install_from_the_existing_filesystem="Install from the existing filesystem"
+msg_install_over_nfs="Install over NFS"
+msg_installed="Installed"
+msg_installed_desc="Leave package as-is, installed"
+msg_installed_lc="installed"
+msg_invalid_gateway_ipv4_address_specified="Invalid gateway IPv4 address specified"
+msg_invalid_hostname_value="Invalid hostname value"
+msg_invalid_ipv4_address="Invalid IPv4 address"
+msg_invalid_name_server_ip_address_specified="Invalid name server IP address specified"
+msg_invalid_netmask_value="Invalid netmask value"
+msg_invalid_nfs_path_specification="Invalid NFS path specification. Must be of the form:\nhost:/full/pathname/to/FreeBSD/distdir"
+msg_io_error_while_reading_in_the_package="I/O error while reading in the %s package."
+msg_io_or_format_error_on_index_file="I/O or format error on INDEX file.\nPlease verify media (or path to media) and try again."
+msg_ipv4_address="IPv4 Address"
+msg_ipv4_gateway="IPv4 Gateway"
+msg_ipv6="IPv6"
+msg_ipv6_desc="IPv6-related software."
+msg_ipv6_ready="IPv6 ready"
+msg_irc_desc="Internet Relay Chat utilities."
+msg_ireland="Ireland"
+msg_israel="Israel"
+msg_japan="Japan"
+msg_japanese_desc="Ported software for the Japanese market."
+msg_java_desc="Java language support."
+msg_kde_desc="Software for the K Desktop Environment."
+msg_kld_desc="Kernel loadable modules."
+msg_korea="Korea"
+msg_korean_desc="Ported software for the Korean market."
+msg_lang_desc="Computer languages."
+msg_latvia="Latvia"
+msg_length_of_specified_url_is_too_long="Length of specified URL is %u characters. Allowable maximum is %u."
+msg_linux_desc="Linux programs that can run under binary compatibility."
+msg_lisp_desc="Software related to the Lisp language."
+msg_lithuania="Lithuania"
+msg_loading_of_dependent_package_failed="Loading of dependent package %s failed"
+msg_loading_wireless_menu="Loading Wireless Menu..."
+msg_logging_in_to_user_at_host="Logging in to %s@%s.."
+msg_looking_for_keymap_files="Looking for keymap files..."
+msg_looking_up_host="Looking up host %s"
+msg_mail_desc="Electronic mail packages and utilities."
+msg_main_menu="Main Menu"
+msg_main_site="Main Site"
+msg_manually_connect="Manually Connect"
+msg_manually_connect_help="Connect to a wireless network that may be unlisted"
+msg_math_desc="Mathematical computation software."
+msg_mbone_desc="Applications and utilities for the MBONE."
+msg_media_timeout="Media Timeout"
+msg_media_type="Media Type"
+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_misc_desc="Miscellaneous utilities."
+msg_missing_ftp_host_or_directory="Missing FTP host or directory specification. FTP media not initialized."
+msg_multimedia_desc="Multimedia software."
+msg_must_be_root_to_execute="%s: must be root to execute"
+msg_must_have_pkg_to_execute="%s: must have pkg(8) to execute"
+msg_must_specify_a_host_name_of_some_sort="Must specify a host name of some sort!"
+msg_name_server="Name server"
+msg_net_desc="Networking utilities."
+msg_net_device_init_failed="Net device init failed."
+msg_net_im_desc="Instant messaging software."
+msg_net_mgmt_desc="Network management tools."
+msg_net_p2p_desc="Peer to peer network applications."
+msg_netherlands="Netherlands"
+msg_netmask="Netmask"
+msg_network_configuration="Network Configuration"
+msg_network_interface_information_required="Network interface information required"
+msg_new_zealand="New Zealand"
+msg_news_desc="USENET News support software."
+msg_next_page="Next page"
+msg_nfailed_attempts="%u incorrect password attempts"
+msg_nfs="NFS"
+msg_nfs_secure="NFS Secure"
+msg_nfs_server_talks_only_on_a_secure_port="NFS server talks only on a secure port"
+msg_nfs_slow="NFS Slow"
+msg_nfs_tcp="NFS TCP"
+msg_nfs_version_3="NFS version 3"
+msg_no="No"
+msg_no_cd_dvd_devices_found="No CD/DVD devices found! Please check that your system's\nconfiguration is correct and that the CD/DVD drive is of a\nsupported type. For more information, consult the hardware\nguide in the Doc menu."
+msg_no_description_provided="No description provided"
+msg_no_dos_primary_partitions_found="No DOS primary partitions found! This installation method is unavailable"
+msg_no_floppy_devices_found="No floppy devices found! Please check that your system's configuration\nis correct. For more information, consult the hardware guide in the Doc\nmenu."
+msg_no_gateway_has_been_set="No gateway has been set. You will be unable to access hosts\nnot on your local network"
+msg_no_network_devices="No network devices available!"
+msg_no_package_name_passed_in_package_variable="No package name passed in package variable"
+msg_no_packages_were_selected_for_extraction="No packages were selected for extraction."
+msg_no_pkg_database_found="No pkg(8) database found!"
+msg_no_such_file_or_directory="%s: %s: No such file or directory"
+msg_no_usb_devices_found="No USB devices found (try Options/Re-scan Devices)"
+msg_no_username="No username provided!"
+msg_norway="Norway"
+msg_not_a_directory="%s: %s: Not a directory"
+msg_not_found="not found"
+msg_not_yet_set="not yet set"
+msg_ok="OK"
+msg_options="Options"
+msg_options_editor="Options Editor"
+msg_other="other"
+msg_package_is_needed_by_other_installed_packages="Warning: Package %s is needed by\n %d other installed package%s."
+msg_package_not_installed_cannot_delete="Warning: package %s not installed\n No package can be deleted."
+msg_package_temp="Package Temp"
+msg_package_was_added_successfully="Package %s was added successfully"
+msg_packages="packages"
+msg_page_of_npages="(Page %s of %s)"
+msg_palm_desc="Software support for the Palm(tm) series."
+msg_parallel_desc="Applications dealing with parallelism in computing."
+msg_pear_desc="Software related to the Pear PHP framework."
+msg_perl5_desc="Utilities/modules for the PERL5 language."
+msg_permission_denied="%s: %s: Permission denied"
+msg_pick_an_interface_to_destroy="Pick an interface to destroy"
+msg_pkg_delete_failed="Warning: pkg-delete(8) of %s failed.\n Run with debugging for details."
+msg_pkg_install_apparently_did_not_like_the_package="pkg-install(8) apparently did not like the %s package."
+msg_pkg_not_yet_installed_install_now="pkg(8) not yet installed. Install now?"
+msg_plan9_desc="Software from the Plan9 operating system."
+msg_please_check_the_url_and_try_again="No such directory: %s\nplease check the URL and try again.\n"
+msg_please_enter_password="Please enter your password for sudo(8):"
+msg_please_enter_the_address_of_the_http_proxy="Please enter the address of the HTTP proxy in this format:\n hostname:port (the ':port' is optional, default is 3128)"
+msg_please_enter_the_full_nfs_file_specification="Please enter the full NFS file specification for the remote\nhost and directory containing the FreeBSD distribution files.\nThis should be in the format: hostname:/some/freebsd/dir"
+msg_please_enter_the_password_for_this_user="Please enter the password for this user:"
+msg_please_enter_the_username_you_wish_to_login_as="Please enter the username you wish to login as:"
+msg_please_enter_username_password="Please enter a username and password for sudo(8):"
+msg_please_insert_floppy_containing="Please insert floppy containing %s in %s"
+msg_please_insert_floppy_in_drive="Please insert floppy in %s"
+msg_please_select_a_category_to_display="Please select a category to display."
+msg_please_select_a_cd_dvd_drive="FreeBSD can be installed directly from a CD/DVD containing a valid\nFreeBSD distribution. If you are seeing this menu it is because\nmore than one CD/DVD drive was found on your system. Please select\none of the following CD/DVD drives as your installation drive."
+msg_please_select_a_floppy_drive="You have more than one floppy drive. Please choose which drive\nyou would like to use."
+msg_please_select_a_freebsd_ftp_distribution_site="Please select a FreeBSD FTP distribution site"
+msg_please_select_a_freebsd_http_distribution_site="Please select a FreeBSD HTTP distribution site"
+msg_please_select_a_usb_drive="You have more than one USB drive. Please choose which drive\nyou would like to use."
+msg_please_select_dos_partition="FreeBSD can be installed directly from a DOS partition assuming,\nof course, that you have copied the relevant distributions into\nyour DOS partition before starting this installation. If this is\nnot the case then you should reboot DOS at this time and copy the\ndistributions you wish to install into a \"FREEBSD\" subdirectory\non one of your DOS partitions. Otherwise, please select the DOS\npartition containing the FreeBSD distribution files."
+msg_please_select_ethernet_device_to_configure="Please select the ethernet or PLIP device to configure."
+msg_please_select_the_site_closest_to_you_or_other="Please select the site closest to you or \"other\" if you'd like to\nspecify a different choice. Also note that not every site listed here\ncarries more than the base distribution kits. Only Primary sites are\nguaranteed to carry the full range of possible distributions."
+msg_please_select_ufs_partition="FreeBSD can be installed directly from another FreeBSD partition\nthat is UFS formatted assuming, of course, that you have copied\nthe relevant distributions into said partition before starting\ninstallation."
+msg_please_specify_a_temporary_directory="Please specify a temporary directory with lots of free space:"
+msg_please_specify_the_name_of_the_text_editor="Please specify the name of the text editor you wish to use:"
+msg_please_specify_the_number_of_seconds_to_wait="Please specify the number of seconds to wait for slow media:"
+msg_please_specify_the_release_you_wish_to_load="Please specify the release you wish to load or\n\"any\" for a generic release install:"
+msg_please_specify_url_of_a_freebsd_distribution="Please specify the URL of a FreeBSD distribution on a\nremote ftp site. This site must accept either anonymous\nftp or you should have set an ftp username and password\nin the Options screen.\n\nA URL looks like this: ftp://<hostname>/<path>\nWhere <path> is relative to the anonymous ftp directory or the\nhome directory of the user being logged in as."
+msg_please_specify_url_of_freebsd_http_distribution="Please specify the URL of a FreeBSD distribution on a\nremote http site.\nA URL looks like this: http://<hostname>/<path>"
+msg_poland="Poland"
+msg_polish_desc="Ported software for the Polish market."
+msg_ports_mgmt_desc="Utilities for managing ports and packages."
+msg_portuguese_desc="Ported software for the Portuguese market."
+msg_previous_page="Previous page"
+msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors"
+msg_primary="Primary"
+msg_print_desc="Utilities for dealing with printing."
+msg_probing_devices_please_wait_this_can_take_a_while="Probing devices, please wait (this can take a while)..."
+msg_proceed="Proceed"
+msg_processing_selection="Processing selection..."
+msg_python_desc="Software related to the Python language."
+msg_quick_start_how_to_use_this_menu_system="Quick start - How to use this menu system"
+msg_reading_package_index_data="Reading package index data"
+msg_reinstall="Reinstall"
+msg_reinstall_desc="Mark this package for reinstall"
+msg_release_name="Release Name"
+msg_required_package_not_found="Warning: %s is a required package but was not found."
+msg_rerun_bsdconfig_initial_device_probe="Re-run bsdconfig initial device probe"
+msg_rescan_wireless="Rescan Wireless"
+msg_rescan_wireless_help="Scan for new wireless networks"
+msg_rescan_devices="Re-scan Devices"
+msg_reset="RESET!"
+msg_reset_all_values_to_startup_defaults="Reset all values to startup defaults"
+msg_return_to_previous_menu="Return to previous menu"
+msg_reuse_old_ftp_site_selection_values="Re-use old FTP site selection values?"
+msg_reuse_old_http_site_settings="Re-use old HTTP site settings?"
+msg_review="Review"
+msg_review_desc="Review/perform pending actions"
+msg_review_help="Install, Re-Install, or Un-install selected packages and dependencies"
+msg_reviewing_selected_packages="Reviewing %u selected packages:"
+msg_ruby_desc="Software related to the Ruby language."
+msg_rubygems_desc="Ports of RubyGems packages."
+msg_russia="Russia"
+msg_russian_desc="Ported software for the Russian market."
+msg_scanning_for_dhcp_servers="Scanning for DHCP servers..."
+msg_scanning_for_ra_servers="Scanning for RA servers..."
+msg_scanning_wireless_pausing="Scanning Wireless... (pausing for %i seconds)"
+msg_scheme_desc="Software related to the Scheme language."
+msg_science_desc="Scientific software."
+msg_secure_mode_requires_root="Secure-mode requires root-access!"
+msg_secure_mode_requires_x11="Secure-mode requires X11 (use \`-X')!"
+msg_security_desc="System security software."
+msg_select="Select"
+msg_select_a_site_thats_close="Select a site that's close!"
+msg_select_the_configuration_you_would_like="Select the configuration you would like to edit:\nAddional network information displayed in help line."
+msg_select_wlan_interfaces_for="Select wlan interfaces for %s:"
+msg_selected="selected"
+msg_server_error_when_requesting_url="Server error when requesting %s, you could try an other server"
+msg_shells_desc="Various shells (tcsh, bash, etc)."
+msg_show_all="Show All"
+msg_show_all_help="Show wireless networks without an SSID and all BSSIDs"
+msg_show_configured="Show Configured"
+msg_show_configured_help="Show networks configured in wpa_supplicants.conf(5)"
+msg_show_scan_results="Show Scan Results"
+msg_show_scan_results_help="Show wpa_cli(8) scan results"
+msg_skip="Skip"
+msg_slovak_republic="Slovak Republic"
+msg_slovenia="Slovenia"
+msg_sorry_invalid_url="Sorry, %s is an invalid URL!"
+msg_sorry_package_was_not_found_in_the_index="Sorry, package %s was not found in the INDEX."
+msg_sorry_try_again="Sorry, try again."
+msg_south_africa="South Africa"
+msg_spain="Spain"
+msg_spanish_desc="Ported software for the Spanish market."
+msg_specify_some_other_ftp_site="Specify some other ftp site by URL"
+msg_specify_some_other_http_site="Specify some other http site by URL"
+msg_sweden="Sweden"
+msg_switzerland="Switzerland"
+msg_sysutils_desc="Various system utilities."
+msg_taiwan="Taiwan"
+msg_tcl_desc="TCL and packages that depend on it."
+msg_textproc_desc="Text processing/search utilities."
+msg_the_current_installation_media_type="The current installation media type."
+msg_timeout_value_in_seconds_for_slow_media="Timeout value in seconds for slow media."
+msg_tk_desc="Tk and packages that depend on it."
+msg_try_dhcp_configuration="Do you want to try DHCP configuration of the interface?"
+msg_try_ipv6_configuration="Do you want to try IPv6 configuration of the interface?"
+msg_try_sudo_only_this_once="Try sudo(8) only this once"
+msg_ufs="UFS"
+msg_uk="UK"
+msg_ukraine="Ukraine"
+msg_ukrainian_desc="Ported software for the Ukrainian market."
+msg_unable_to_configure_device="Unable to configure the %s interface!\nThis installation method cannot be used."
+msg_unable_to_fetch_package_from_selected_media="Unable to fetch package %s from selected media.\nNo package add will be done."
+msg_unable_to_get_file_from_selected_media="Unable to get %s file from selected media.\n\nThis may be because the packages collection is not available\non the distribution media you've chosen, most likely an FTP site\nwithout the packages collection mirrored. Please verify that\nyour media, or your path to the media, is correct and try again."
+msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not initialized."
+msg_unable_to_initialize_media_type_for_package_extract="Unable to initialize media type for package extract."
+msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!"
+msg_unable_to_open="Unable to open %s"
+msg_unable_to_update_pkg_from_selected_media="Unable to update pkg(8) from selected media."
+msg_unconfigured="Unconfigured"
+msg_uninstall="Uninstall"
+msg_uninstall_desc="Mark this package for deletion"
+msg_uninstalling_package_waiting_for_pkg_delete="Uninstalling %s package - waiting for pkg-delete(8)"
+msg_unknown="unknown"
+msg_unknown_user="Unknown user: %s"
+msg_url_was_not_found="%s was not found,\nmaybe directory or release-version are wrong?"
+msg_usa="USA"
+msg_usage="Usage"
+msg_usb="USB"
+msg_use_defaults="Use Defaults"
+msg_use_nfs_version_3="Use NFS version 3"
+msg_use_tcp_protocol_for_nfs="Use TCP protocol for NFS"
+msg_user_disallowed="User disallowed: %s"
+msg_user_is_using_a_slow_pc_or_ethernet_card="User is using a slow PC or Ethernet card"
+msg_username_and_password_to_use="Username and password to use instead of anonymous"
+msg_using_interface="Using interface %s"
+msg_using_usb_device="Using USB device: %s"
+msg_vietnamese_desc="Ported software for the Vietnamese market."
+msg_view_set_various_media_options="View/Set various media options"
+msg_warning_no_wireless_devices="WARNING! No wireless devices found."
+msg_what_would_you_like_to_do_with="What would you like to do with %s?"
+msg_which_release_to_attempt_to_load="Which release to attempt to load from installation media"
+msg_which_text_editor_to_use="Which text editor to use during installation"
+msg_wireless_networks_text="Select an unmarked ([ ]) entry to join that network.\nSelect a marked ([X]) entry to edit that configuration."
+msg_windowmaker_desc="Ports to support the WindowMaker window manager."
+msg_wireless_network_configuration_for="Wireless network configuration for SSID \`%s'"
+msg_would_you_like_to_bring_interface_up="Would you like to bring the %s interface up right now?"
+msg_wpa_cli_ping_failed="wpa_cli(8) ping failed"
+msg_www_desc="Web utilities (browsers, HTTP servers, etc)."
+msg_x11_clocks_desc="X Window System based clocks."
+msg_x11_desc="X Window System based utilities."
+msg_x11_drivers_desc="X Window System drivers."
+msg_x11_fm_desc="X Window System based file managers."
+msg_x11_fonts_desc="X Window System fonts and font utilities."
+msg_x11_servers_desc="X Window System servers."
+msg_x11_themes_desc="X Window System themes."
+msg_x11_toolkits_desc="X Window System based development toolkits."
+msg_x11_wm_desc="X Window System window managers."
+msg_xfce_desc="Software related to the Xfce Desktop Environment."
+msg_yes="Yes"
+msg_yes_to_all="Yes to All"
+msg_you_are_not_root_but="You are not root but %s can use sudo(8).\nWhat would you like to do?"
+msg_you_may_remove_the_floppy="You may remove the floppy from %s"
+msg_youve_already_done_the_network_configuration="You've already done the network configuration once,\nwould you like to skip over it now?"
+msg_zope_desc="Software related to the Zope platform."
+tcplayout_extras_help="Any interface-specific options to ifconfig you would like to add"
+tcplayout_extras_help_for_plip="For PLIP configuration, you must enter the peer's IP address here."
+tcplayout_gateway_help="IPv4 address of host forwarding packets to non-local destinations"
+tcplayout_hostname_help="Your fully-qualified hostname, e.g. foo.example.com"
+tcplayout_ipaddr_help="The IPv4 address to be used for this interface"
+tcplayout_nameserver_help="IPv4 or IPv6 address of your local DNS server"
+tcplayout_netmask_help="The netmask for this interface, e.g. 255.255.255.0 for a class C network"
diff --git a/contrib/bsddialog/bsdconfig/include/network_device.hlp b/contrib/bsddialog/bsdconfig/include/network_device.hlp
new file mode 100644
index 000000000000..affa86a91ec8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/network_device.hlp
@@ -0,0 +1,58 @@
+You can do network installations over 3 types of communications links:
+
+ Serial port: SLIP / PPP
+ Parallel port: PLIP (laplink cable)
+ Ethernet: A standard Ethernet controller (includes some
+ PCMCIA networking cards).
+
+SLIP support is rather primitive and limited primarily to directly
+connected links, such as a serial cable running between a laptop
+computer and another PC. The link must be hard-wired as the SLIP
+installation doesn't currently offer a dialing capability (that
+facility is offered by the PPP utility, which should be used in
+preference to SLIP whenever possible). When you choose the SLIP
+option, you'll be given the option of later editing the slattach
+command before it's run on the serial line. It is expected that
+you'll run slattach (or some equivalent command) on the other end of
+the link at that time and bring up the line. FreeBSD will then
+install itself at serial speeds of up to 115.2K/baud (the recommended
+speed for a hardwired cable).
+
+If you're using a modem then PPP is almost certainly your only choice.
+Make sure that you have your service provider's information handy as
+you'll need to know it fairly early in the installation process. You
+will need to know your service provider's IP address, the IP address
+of your provider's DNS server, and possibly your own IP address unless
+your ISP supports dynamic negotiation, most do. If you do not choose
+a PAP or CHAP login you will also need to know how to use the various
+"AT commands" to dial the ISP with your particular brand of modem as
+the PPP dialer provides only a very simple terminal emulator and has no
+"modem capabilities database". If you choose a PAP or CHAP login you
+can simply enter `dial' (without the quotes) at the ppp prompt if your
+modem uses the Hayes compatible AT command set.
+
+If a hard-wired connection to another FreeBSD (2.0R or later) machine
+is available, you might also consider installing over a "laplink"
+parallel port cable. The data rate over the parallel port is much
+higher than what is typically possible over a serial line, and speeds
+of over 50KB/sec are not uncommon.
+
+Finally, for the fastest possible network installation, an Ethernet
+adaptor is always a good choice! FreeBSD supports most common PC
+Ethernet cards, a table of which is provided in the FreeBSD Hardware
+Guide (see the `Documentation' entry in the main menu). If you are
+using one of the supported PCMCIA Ethernet cards, also be sure that
+it's plugged in BEFORE the laptop is powered on! Sysinstall does not,
+unfortunately, currently support "hot insertion" of PCMCIA cards.
+
+You will also need to know your IP address on the network, the
+"netmask" value for your address class, and the name of your machine.
+Your system administrator can tell you which values to use for your
+particular network setup. If you will be referring to other hosts by
+name rather than IP address, you'll also need a name server and
+possibly the address of a gateway (if you're using PPP, it's your
+provider's IP address) to use in talking to it. If you do not know
+the answers to all or most of these questions then you should really
+probably talk to your system administrator FIRST before trying this
+type of installation! Choosing the wrong IP address on a busy network
+will NOT make you popular with your systems administrator! :-)
diff --git a/contrib/bsddialog/bsdconfig/include/options.hlp b/contrib/bsddialog/bsdconfig/include/options.hlp
new file mode 100644
index 000000000000..f47df27a6b88
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/options.hlp
@@ -0,0 +1,115 @@
+The following options may be set from this screen.
+
+NFS Secure: NFS server talks only on a secure port
+
+ This is most commonly used when talking to Sun workstations, which
+ will not talk NFS over "non privileged" ports.
+
+
+NFS Slow: User is using a slow PC or Ethernet card
+
+ Use this option if you have a slow PC (386) or an Ethernet card
+ with poor performance being "fed" by NFS on a higher-performance
+ workstation. This will throttle the workstation back to prevent
+ the PC from becoming swamped with data.
+
+
+NFS TCP: Use TCP for the NFS mount
+
+ This option can be used if your NFS server supports TCP
+ connections; not all do! This may be useful if your NFS server
+ is at a remote site in which case it may offer some additional
+ stability.
+
+
+NFS version 3: Use NFS version 3
+
+ This option forces the use of NFS version 3 and is on by default.
+ If your NFS server only supports NFS version 2, disable this option.
+
+
+Debugging: Turn on the extra debugging flag
+
+ This turns on a lot of extra noise in between dialogs (unless
+ debugFile has been set, sending the data to a logfile instead).
+ Optionally, if debugFile begins with a plus sign (`+'), output will
+ occur both on standard output and to debugFile (minus leading plus).
+ If your installation should fail for any reason, PLEASE turn this
+ flag on when attempting to reproduce the problem. It will provide a
+ lot of extra debugging at the failure point and may be very helpful
+ to the developers in tracking such problems down!
+
+
+Yes To All: Assume "Yes" answers to all non-critical dialogs
+
+ This flag should be used with caution. It will essentially
+ decide NOT to ask the user about any "boundary" conditions that
+ might not constitute actual errors but may be warnings indicative
+ of other problems. It's most useful to those who are doing unattended
+ installs.
+
+
+DHCP: Enable DHCP configuration of interfaces
+
+ This option specifies whether DHCP configuration of interfaces
+ may be attempted. The default setting is to interactively ask
+ the user.
+
+
+IPv6: Enable IPv6 router solicitation configuration
+
+ This option specifies whether automatic configuration of IPv6
+ interfaces may be attempted. This uses the router solicitation
+ method of automatic configuration. The default setting is to
+ interactively ask the user.
+
+
+FTP username: Specify username and password instead of anonymous.
+
+ By default, the installation attempts to log in as the
+ anonymous user. If you wish to log in as someone else,
+ specify the username and password with this option.
+
+
+Editor: Specify which screen editor to use.
+
+ At various points during the installation it may be necessary
+ to customize some text file, at which point the user will be
+ thrown unceremoniously into a screen editor. A relatively
+ simplistic editor which shows its command set on-screen is
+ selected by default, but UNIX purists may wish to change this
+ setting to `/usr/bin/vi'.
+
+
+Release Name: Which release to attempt to load from installation media.
+
+ You should only change this option if you're really sure you know
+ what you are doing! This will change the release name used by
+ bsdconfig when fetching components of any distributions, and
+ is a useful way of using a more recent installation boot floppy
+ with an older release (say, on CDROM).
+
+
+Media Type: Which media type is being used.
+
+ This is mostly informational and indicates which media type (if any)
+ was last selected in the Media menu. It's also a convenient short-cut
+ to the media menu itself.
+
+
+Package Temp: Where package temporary files should go
+
+ Some packages, like emacs, can use a LOT of temporary space - up to
+ 20 or 30MB. If you are going to configure a small / directory and no
+ separate /var (and hence a small /var/tmp), then you may wish to set
+ this to point at another location (say, /usr/tmp).
+
+
+Re-scan Devices:
+
+ Reprobe the system for devices.
+
+
+Use Defaults: Use default values.
+
+ Reset all options back to their default values.
diff --git a/contrib/bsddialog/bsdconfig/include/tcp.hlp b/contrib/bsddialog/bsdconfig/include/tcp.hlp
new file mode 100644
index 000000000000..6d0ba10f60f1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/tcp.hlp
@@ -0,0 +1,33 @@
+This screen allows you to set up your general network parameters
+(hostname, domain name, DNS server, etc) as well as the settings for a
+given interface (which was selected from the menu before this screen).
+
+PLIP/SLIP users - please read through to the end of this doc!
+
+The "options" field is kind of special (read: a hack :-):
+
+Any valid options to ifconfig can be specified here, so if you need
+to do something "special" to get your interface working, then here
+is the place to do it.
+
+If you're running SLIP or PLIP, you also need to use it for specifying
+the remote end of the link (simply type the foreign IP address in).
+In the specific case where you're running PLIP with a Linux host peer
+rather than a FreeBSD one, you also must add the "-link0" flag after the
+foreign address.
+
+If you're dealing with an ethernet adaptor with multiple media
+connectors (e.g. AUI, 10BT, 10B2, etc), you can use this field to
+specify which one to use. Examples of valid strings include:
+
+ "media 10base5/AUI" - Select the AUI port.
+ "media 10baseT/UTP" - Select the twisted pair port.
+ "media 10base2/BNC" - Select the BNC connector.
+ "media 100baseTX" - Select 100BaseT on a 100/10 dual adaptor.
+
+If you have a wireless interface and must specify arguments such as a
+WEP key here, you may use something like:
+
+ "wepmode on wepkey 0xFEEDFACE"
+
+When you're done with this form, select OK.
diff --git a/contrib/bsddialog/bsdconfig/include/usage.hlp b/contrib/bsddialog/bsdconfig/include/usage.hlp
new file mode 100644
index 000000000000..4412da7ddcb8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/include/usage.hlp
@@ -0,0 +1,64 @@
+HOW TO USE THIS SYSTEM
+======================
+
+[press the PageDown key to go to the next screen when you finish
+ reading this one]
+
+The following keys are recognized in most of the dialogs you'll
+encounter during this installation:
+
+KEY ACTION
+--- ------
+SPACE Select or toggle the current item.
+ENTER Finish with a menu or item.
+UP ARROW Move to previous item (or up, in a text display box).
+DOWN ARROW Move to next item (or down, in a text display box).
+TAB Move to next item or group.
+RIGHT ARROW Move to next item or group (same as TAB).
+SHIFT-TAB Move to previous item or group.
+LEFT ARROW Move to previous item or group (same as SHIFT-TAB).
+PAGE UP In text display boxes, scrolls up one page.
+PAGE DOWN In text display boxes, scrolls down one page.
+F1 Display associated help text.
+
+If you see small "^(-)" or "v(+)" symbols at the edges of a menu, it
+means that there are more items above or below the current one that
+aren't being shown (due to insufficient screen space). In text
+display boxes, the amount of text above the current point will be
+displayed as a percentage in the lower right corner. Using the
+Up/Down arrow keys will cause the object to scroll by line. The
+PageUp and PageDown keys will scroll by entire screens.
+
+Selecting OK in a menu will confirm whatever action it's controlling.
+Selecting Cancel will cancel the operation and generally return you to
+the previous menu. Use TAB to move the cursor around and select the
+buttons.
+
+Most screens offer a Help button - USE IT! It generally offers useful
+context-specific hints on what to do and if you're at all unsure about
+what to do at a given configuration menu, choose Help!
+
+
+SPECIAL FEATURES:
+=================
+
+It is possible to select a menu item by typing the first character of
+its name, if unique. This will generally be an item number.
+
+The console driver contains a scroll-back buffer for reviewing things
+that may have scrolled off the screen. To use scroll-back, press the
+"Scroll Lock" key on your keyboard and use the arrow or Page Up/Page
+Down keys to move through the saved text. To leave scroll-back mode,
+press the Scroll Lock key again. This feature is most useful for
+reading back through your boot messages (go ahead, try it now!) though
+it's also useful when dealing with sub-shells or other "expert modes"
+that don't use menus and tend to scroll their output off the top of
+the screen.
+
+FreeBSD also supports multiple "virtual consoles" which you can use
+in order to have several active sessions at once. Use ALT-F<n> to
+switch between screens, where `F<n>' is the function key corresponding
+to the screen you wish to see. By default, the system comes with 8
+virtual consoles enabled - you can enable more by editing the
+/etc/ttys file and turning the "off" field to "on" in the relevant vty
+entries (up to 12).
diff --git a/contrib/bsddialog/bsdconfig/includes/INDEX b/contrib/bsddialog/bsdconfig/includes/INDEX
new file mode 100644
index 000000000000..a6a6c49212a4
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/INDEX
@@ -0,0 +1,57 @@
+# Copyright (c) 2013-2015 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$
+
+#
+# Title that will be shown in 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="includes|includes"
+menu_selection="api|includes"
+
+#
+# ------------ 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 --git a/contrib/bsddialog/bsdconfig/includes/Makefile b/contrib/bsddialog/bsdconfig/includes/Makefile
new file mode 100644
index 000000000000..367776c245a8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/includes
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= includes.sh
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/includes/Makefile.depend b/contrib/bsddialog/bsdconfig/includes/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/includes/USAGE b/contrib/bsddialog/bsdconfig/includes/USAGE
new file mode 100644
index 000000000000..4af1b732c718
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/USAGE
@@ -0,0 +1,71 @@
+# Copyright (c) 2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS] [include ...]
+
+OPTIONS:
+ -a Always use color even when output is not to a terminal.
+ -d Print description for each function selected. Implies `-f'.
+ -f Show functions for selected includes.
+ -F pattern
+ If `-f', only print functions matching pattern. Without `-f'
+ print only includes containing functions matching pattern.
+ -h Print this usage statement and exit.
+ -n Disable the use of color.
+
+EXAMPLES:
+ View a list of available includes:
+
+ bsdconfig @PROGRAM_NAME@
+
+ View functions for all available includes (function names are
+ highlighted):
+
+ bsdconfig @PROGRAM_NAME@ -f
+
+ View functions with less(1) (function names are not highlighted):
+
+ bsdconfig @PROGRAM_NAME@ -f | less
+
+ View functions with less(1) and color:
+
+ bsdconfig @PROGRAM_NAME@ -af | less -R
+
+ View functions from `common.subr':
+
+ bsdconfig @PROGRAM_NAME@ common.subr
+
+ NB: The `-f' flag is implied when given an include.
+
+ Show only functions containing the word `show' in common.subr:
+
+ bsdconfig @PROGRAM_NAME@ -F show common
+
+ NB: The `.subr' suffix on the end of the include is optional.
+
+ Show descriptions of each of the `show' functions:
+
+ bsdconfig @PROGRAM_NAME@ -dF show
diff --git a/contrib/bsddialog/bsdconfig/includes/include/Makefile b/contrib/bsddialog/bsdconfig/includes/include/Makefile
new file mode 100644
index 000000000000..3b8b3ec66f27
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/includes/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/includes/include/Makefile.depend b/contrib/bsddialog/bsdconfig/includes/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/includes/include/messages.subr b/contrib/bsddialog/bsdconfig/includes/include/messages.subr
new file mode 100644
index 000000000000..8fa881b4cf15
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/include/messages.subr
@@ -0,0 +1,28 @@
+# Copyright (c) 2013 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$
+
+msg_functions_in="Functions in %s:"
+msg_functions_in_matching="Functions in %s matching \`%s':"
diff --git a/contrib/bsddialog/bsdconfig/includes/includes.sh b/contrib/bsddialog/bsdconfig/includes/includes.sh
new file mode 100755
index 000000000000..6e9906fd0420
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/includes/includes.sh
@@ -0,0 +1,205 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent common.subr from auto initializing debugging (this is not an inter-
+# active utility that requires debugging; also `-d' has been repurposed).
+#
+DEBUG_SELF_INITIALIZE=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="includes"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+USE_COLOR=1
+SHOW_DESC=
+SHOW_FUNCS=
+FUNC_PATTERN=
+
+############################################################ FUNCTIONS
+
+# show_functions $file
+#
+# Show the functions in the given include file.
+#
+show_include()
+{
+ local file="${1#./}"
+
+ local pattern="${FUNC_PATTERN:-.*}"
+ output=$( awk \
+ -v use_color=${USE_COLOR:-0} \
+ -v re="$pattern" \
+ -v show_desc=${SHOW_DESC:-0} '
+ function _asorti(src, dest)
+ {
+ k = nitems = 0;
+
+ # Copy src indices to dest and calculate array length
+ for (i in src) dest[++nitems] = i
+
+ # Sort the array of indices (dest) using insertion sort method
+ for (i = 1; i <= nitems; k = i++)
+ {
+ idx = dest[i]
+ while ((k > 0) && (dest[k] > idx))
+ {
+ dest[k+1] = dest[k]
+ k--
+ }
+ dest[k+1] = idx
+ }
+
+ return nitems
+ }
+ /^$/,/^#/ {
+ if ($0 ~ /^# f_/) {
+ if (!match($2, re)) next
+ fn = $2
+ if (use_color)
+ syntax[fn] = sprintf("+%s%s%s\n",
+ substr($0, 2, RSTART),
+ substr($0, 2 + RSTART, RLENGTH),
+ substr($0, 2 + RSTART + RLENGTH))
+ else
+ syntax[fn] = "+" substr($0, 2) "\n"
+ if (show_desc)
+ print_more = 1
+ else
+ print_more = substr($0, length($0)) == "\\"
+ }
+ if (show_desc && print_more) {
+ getline
+ while ($0 ~ /^#/) {
+ syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
+ getline
+ }
+ print_more = 0
+ } else while (print_more) {
+ getline
+ syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
+ print_more = substr($0, length($0)) == "\\"
+ }
+ }
+ END {
+ n = _asorti(syntax, sorted_indices)
+ for (i = 1; i <= n; i++)
+ printf "%s", syntax[sorted_indices[i]]
+ }' "$file" )
+ if [ "$output" ]; then
+ if [ ! "$SHOW_FUNCS" ]; then
+ echo "$file"
+ return $SUCCESS
+ fi
+ if [ "$FUNC_PATTERN" ]; then
+ printf ">>> $msg_functions_in_matching\n" \
+ "$file" "$FUNC_PATTERN"
+ else
+ printf ">>> $msg_functions_in\n" "$file"
+ fi
+ echo "$output"
+ echo # blank line to simplify awk(1)-based reparse
+ fi
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+# Are we in a terminal?
+[ -t 1 ] || USE_COLOR=
+
+#
+# Process command-line arguments
+#
+while getopts adfF:hn flag; do
+ case "$flag" in
+ a) USE_COLOR=1 ;;
+ d) SHOW_DESC=1 SHOW_FUNCS=1 ;;
+ f) SHOW_FUNCS=1 ;;
+ F) FUNC_PATTERN="$OPTARG" ;;
+ n) USE_COLOR= ;;
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+# cd(1) to `share' dir so relative paths work for find and positional args
+cd $BSDCFG_SHARE || f_die # Pedantic
+
+#
+# If given an argument, operate on it specifically (implied `-f') and exit
+#
+[ $# -gt 0 ] && SHOW_FUNCS=1
+for include in "$@"; do
+ # See if they've just omitted the `*.subr' suffix
+ [ -f "$include.subr" -a ! -f "$include" ] && include="$include.subr"
+ if [ ! -f "$include" ]; then
+ printf "$msg_no_such_file_or_directory\n" "$0" "$include"
+ exit $FAILURE
+ elif [ ! -r "$include" ]; then
+ printf "$msg_permission_denied\n" "$0" "$include"
+ exit $FAILURE
+ fi
+ show_include "$include" || f_die
+done
+
+# Exit if we processed some include arguments
+[ $# -gt 0 ] && exit $SUCCESS
+
+#
+# Operate an all known include files
+# NB: If we get this far, we had no include arguments
+#
+find -s . -type f -and -iname '*.subr' | while read file; do
+ if [ "$SHOW_FUNCS" -o "$FUNC_PATTERN" ]; then
+ show_include "$file"
+ else
+ echo "${file#./}"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/mouse/INDEX b/contrib/bsddialog/bsdconfig/mouse/INDEX
new file mode 100644
index 000000000000..4a33a792976e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/INDEX
@@ -0,0 +1,62 @@
+# 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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/mouse/Makefile b/contrib/bsddialog/bsdconfig/mouse/Makefile
new file mode 100644
index 000000000000..97fa52b60520
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/110.mouse
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= disable enable flags mouse port type
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/mouse/Makefile.depend b/contrib/bsddialog/bsdconfig/mouse/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/mouse/USAGE b/contrib/bsddialog/bsdconfig/mouse/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/mouse/disable b/contrib/bsddialog/bsdconfig/mouse/disable
new file mode 100755
index 000000000000..f2c528f2b7bf
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/disable
@@ -0,0 +1,97 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_mouse_disable"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Stop the mouse daemon
+#
+if [ -r "$MOUSED_PIDFILE" ]; then
+ f_eval_catch -dk pid "$0" cat 'cat "%s"' "$MOUSED_PIDFILE" &&
+ f_isinteger "$pid" &&
+ [ $pid -gt 0 ] &&
+ f_eval_catch -d "$0" kill 'kill %s' $pid
+fi
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_enable NO' || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_type NO' || f_die
+f_eval_catch "$0" f_sysrc_delete 'f_sysrc_delete moused_port' || f_die
+f_eval_catch "$0" f_sysrc_delete 'f_sysrc_delete moused_flags' || f_die
+
+#
+# Message box
+#
+f_dialog_title "$msg_message"
+f_dialog_msgbox "$msg_mouse_daemon_is_disabled" "$hline_press_enter_or_space"
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/mouse/enable b/contrib/bsddialog/bsdconfig/mouse/enable
new file mode 100755
index 000000000000..9ad6857e139b
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/enable
@@ -0,0 +1,128 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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"
+if [ -r "$MOUSED_PIDFILE" ]; then
+ f_eval_catch -dk pid "$0" cat 'cat "%s"' "$MOUSED_PIDFILE" &&
+ f_isinteger "$pid" &&
+ [ $pid -gt 0 ] &&
+ f_eval_catch -d "$0" kill 'kill %s' $pid
+fi
+f_eval_catch -d "$0" vidcontrol 'vidcontrol -m on'
+f_eval_catch -d "$0" moused \
+ 'moused -t "%s" -p "%s" %s' "$type" "$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_eval_catch -d "$0" vidcontrol 'vidcontrol -m off'
+if [ $retval -eq $DIALOG_OK ]; then
+ f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_enable YES' || f_die
+ f_eval_catch "$0" ln \
+ 'ln -fs /dev/sysmouse /dev/mouse' || f_die # backwards compat
+else
+ if [ -r "$MOUSED_PIDFILE" ]; then
+ f_eval_catch -dk pid "$0" cat 'cat "%s"' "$MOUSED_PIDFILE" &&
+ f_isinteger "$pid" &&
+ [ $pid -gt 0 ] &&
+ f_eval_catch -d "$0" kill 'kill %s' $pid
+ fi
+ f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_enable NO' || f_die
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/mouse/flags b/contrib/bsddialog/bsdconfig/mouse/flags
new file mode 100755
index 000000000000..181ee3f41c57
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/flags
@@ -0,0 +1,95 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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"
+f_dialog_input flags "$msg_please_specify_the_mouse_daemon_flags" \
+ "$flags" || f_die
+f_dialog_title_restore
+
+#
+# Save the new value
+#
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_flags "%s"' "$flags" || f_die
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/mouse/include/Makefile b/contrib/bsddialog/bsdconfig/mouse/include/Makefile
new file mode 100644
index 000000000000..2cc852f9ac67
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/110.mouse/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/mouse/include/Makefile.depend b/contrib/bsddialog/bsdconfig/mouse/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/mouse/include/messages.subr b/contrib/bsddialog/bsdconfig/mouse/include/messages.subr
new file mode 100644
index 000000000000..2699b9a5471c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/include/messages.subr
@@ -0,0 +1,91 @@
+# 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$
+
+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_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"
+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_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_mouseman="MouseMan"
+msg_mouseman_desc="Logitech MouseMan/TrackMan models (serial)"
+msg_mousesystems="MouseSystems"
+msg_mousesystems_desc="MouseSystems protocol (serial)"
+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_unknown_mouse_menu_selection="Unknown mouse menu selection"
+msg_unknown_mouse_port_selection="Unknown mouse port selection"
+msg_unknown_mouse_protocol_selection="Unknown mouse protocol selection"
+msg_user_confirmation_requested="User Confirmation Requested"
+msg_value_required="Value Required"
diff --git a/contrib/bsddialog/bsdconfig/mouse/mouse b/contrib/bsddialog/bsdconfig/mouse/mouse
new file mode 100755
index 000000000000..0dce574feea2
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/mouse
@@ -0,0 +1,144 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_menu_text"
+ local 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
+ local defaultitem= # Calculated below
+ local hline=
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 || f_die
+ f_dialog_menutag_fetch mtag
+
+ command=
+ case "$mtag" in
+ "X $msg_exit") break ;;
+ "2 $msg_enable") command=enable ;; # Test and run the mouse daemon
+ "3 $msg_type") command=type ;; # Select mouse protocol type
+ "4 $msg_port") command=port ;; # Select mouse port
+ "5 $msg_flags") command=flags ;; # Set additional flags
+ "6 $msg_disable") command=disable ;; # Disable the mouse daemon
+ esac
+
+ if [ "$command" ]; then
+ $BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
+ else
+ f_die 1 "$msg_unknown_mouse_menu_selection"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/mouse/port b/contrib/bsddialog/bsdconfig/mouse/port
new file mode 100755
index 000000000000..92c7ff25ea1f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/port
@@ -0,0 +1,150 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_port_menu_text"
+ local 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'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline=
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get moused_port )" in
+ /dev/psm0) defaultitem="1 $msg_ps2" ;;
+ /dev/cuau0) defaultitem="2 $msg_com1" ;;
+ /dev/cuau1) defaultitem="3 $msg_com2" ;;
+ /dev/cuau2) defaultitem="4 $msg_com3" ;;
+ /dev/cuau3) defaultitem="5 $msg_com4" ;;
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+moused_port_to_set=
+case "$mtag" in
+"1 $msg_ps2") # PS/2 style mouse (/dev/psm0)
+ moused_port_to_set="/dev/psm0" ;;
+"2 $msg_com1") # Serial mouse on COM1 (/dev/cuau0)
+ moused_port_to_set="/dev/cuau0" ;;
+"3 $msg_com2") # Serial mouse on COM2 (/dev/cuau1)
+ moused_port_to_set="/dev/cuau1" ;;
+"4 $msg_com3") # Serial mouse on COM3 (/dev/cuau2)
+ moused_port_to_set="/dev/cuau2" ;;
+"5 $msg_com4") # Serial mouse on COM4 (/dev/cuau3)
+ moused_port_to_set="/dev/cuau3" ;;
+esac
+
+if [ "$moused_port_to_set" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set moused_port "%s"' "$moused_port_to_set" || f_die
+else
+ f_die 1 "$msg_unknown_mouse_port_selection"
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/mouse/type b/contrib/bsddialog/bsdconfig/mouse/type
new file mode 100755
index 000000000000..7d99753a62be
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/mouse/type
@@ -0,0 +1,170 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="110.mouse"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_protocol_menu_text"
+ local 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
+ local defaultitem= # Calculated below
+ local hline=
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get moused_type )" in
+ auto) defaultitem="1 $msg_auto" ;;
+ glidepoint) defaultitem="2 $msg_glidepoint" ;;
+ mmhittab) defaultitem="3 $msg_hitachi" ;;
+ intellimouse) defaultitem="4 $msg_intellimouse" ;;
+ logitech) defaultitem="5 $msg_logitech" ;;
+ microsoft) defaultitem="6 $msg_microsoft" ;;
+ mmseries) defaultitem="7 $msg_mm_series" ;;
+ mouseman) defaultitem="8 $msg_mouseman" ;;
+ mousesystems) defaultitem="9 $msg_mousesystems" ;;
+ thinkingmouse) defaultitem="A $msg_thinkingmouse" ;;
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_select_a_protocol_type_for_your_mouse"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch mtag
+
+moused_type_to_set=
+case "$mtag" in
+"1 $msg_auto") # Bus mouse, PS/2 style mouse or PnP serial mouse
+ moused_type_to_set="auto" ;;
+"2 $msg_glidepoint") # ALPS GlidePoint pad (serial)
+ moused_type_to_set="glidepoint" ;;
+"3 $msg_hitachi") # Hitachi tablet (serial)
+ moused_type_to_set="mmhittab" ;;
+"4 $msg_intellimouse") # Microsoft Intellimouse (serial)
+ moused_type_to_set="intellimouse" ;;
+"5 $msg_logitech") # Logitech protocol (old models) (serial)
+ moused_type_to_set="logitech" ;;
+"6 $msg_microsoft") # Microsoft protocol (serial)
+ moused_type_to_set="microsoft" ;;
+"7 $msg_mm_series") # MM Series protocol (serial)
+ moused_type_to_set="mmseries" ;;
+"8 $msg_mouseman") # Logitech MouseMan/TrackMan models (serial)
+ moused_type_to_set="mouseman" ;;
+"9 $msg_mousesystems") # MouseSystems protocol (serial)
+ moused_type_to_set="mousesystems" ;;
+"A $msg_thinkingmouse") # Kensignton ThinkingMouse (serial)
+ moused_type_to_set="thinkingmouse" ;;
+esac
+
+if [ "$moused_type_to_set" ]; then
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set moused_type "%s"' "$moused_type_to_set" || f_die
+else
+ f_die 1 "$msg_unknown_mouse_protocol_selection"
+fi
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/networking/INDEX b/contrib/bsddialog/bsdconfig/networking/INDEX
new file mode 100644
index 000000000000..d05d4948606e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/INDEX
@@ -0,0 +1,64 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+#
+# Title that will be shown in 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"
+menu_selection="wireless|wlanconfig"
+menu_selection="wlan|wlanconfig"
+menu_selection="wifi|wlanconfig"
+
+#
+# ------------ 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 --git a/contrib/bsddialog/bsdconfig/networking/Makefile b/contrib/bsddialog/bsdconfig/networking/Makefile
new file mode 100644
index 000000000000..6a1eedda8a9f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= defaultrouter devices hostname nameservers networking \
+ wlanconfig
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/networking/Makefile.depend b/contrib/bsddialog/bsdconfig/networking/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/networking/USAGE b/contrib/bsddialog/bsdconfig/networking/USAGE
new file mode 100644
index 000000000000..872094666bb0
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2006-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/networking/defaultrouter b/contrib/bsddialog/bsdconfig/networking/defaultrouter
new file mode 100755
index 000000000000..b65981f604f2
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/defaultrouter
@@ -0,0 +1,76 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent device.subr (included indirectly) from auto scanning on load
+DEVICE_SELF_SCAN_ALL=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/networking/routing.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 --git a/contrib/bsddialog/bsdconfig/networking/devices b/contrib/bsddialog/bsdconfig/networking/devices
new file mode 100755
index 000000000000..433f25c75fa0
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/devices
@@ -0,0 +1,164 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent device.subr (included indirectly) from auto scanning; this will be
+# performed indirectly later via f_dialog_menu_netdev() -- but only after we've
+# successfully completed f_mustberoot_init().
+#
+DEVICE_SELF_SCAN_ALL=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/networking/device.subr
+f_include $BSDCFG_SHARE/networking/ipaddr.subr
+f_include $BSDCFG_SHARE/networking/media.subr
+f_include $BSDCFG_SHARE/networking/netmask.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line options
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_networking_devices"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+defaultitem=
+while :; do
+ f_dialog_menu_netdev "$defaultitem" || break
+ f_dialog_menutag_fetch interface
+ defaultitem="$interface"
+
+ #
+ # 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).
+ #
+ dhcp=
+ _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" ] || f_ifconfig_inet $interface _ipaddr
+ [ "$_netmask" ] || f_ifconfig_netmask $interface _netmask
+
+ # 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 $DIALOG_OK ] && break
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/networking/hostname b/contrib/bsddialog/bsdconfig/networking/hostname
new file mode 100755
index 000000000000..d0fff0120eea
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/hostname
@@ -0,0 +1,76 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent device.subr (included indirectly) from auto scanning on load
+DEVICE_SELF_SCAN_ALL=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/networking/hostname.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 --git a/contrib/bsddialog/bsdconfig/networking/include/Makefile b/contrib/bsddialog/bsdconfig/networking/include/Makefile
new file mode 100644
index 000000000000..54f66e128407
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/networking/include/Makefile.depend b/contrib/bsddialog/bsdconfig/networking/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/networking/include/messages.subr b/contrib/bsddialog/bsdconfig/networking/include/messages.subr
new file mode 100644
index 000000000000..55881ffa63f7
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/include/messages.subr
@@ -0,0 +1,107 @@
+# Copyright (c) 2012-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+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 IPv4 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 IPv4 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 IPv4 address\n(separated by dots) are null and/or missing.\n\nInvalid IP Address: %s"
+msg_ipv4_addr_octet_missing_or_extra="ERROR! The IPv4 address entered has either too few (less than\nfour) or too many (more than four) octets, separated by dots.\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_ipv6_addr_segment_contains_invalid_chars="ERROR! One or more individual segments within the IP address\n(separated by colons) contains one or more invalid characters.\nSegments must contain only combinations of the characters 0-9,\nA-F, or a-f.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_segment_contains_too_many_chars="ERROR! One or more individual segments within the IP address\n(separated by colons) exceeds the length of 4 hex-digits.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_too_few_or_extra_segments="ERROR! The IP address entered has either too few (less than 3), too\nmany (more than 8), or not enough segments, separated by colons.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_too_many_null_segments="ERROR! Too many/incorrect null segments. A single null\nsegment is allowed within the IP address (separated by\ncolons) but not allowed at the beginning or end (unless\na double-null segment; i.e., \"::*\" or \"*::\").\n\nInvalid IPv6 Address: %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. Are you sure you\nwant to proceed?\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"
+msg_unknown_networking_menu_selection="Unknown networking menu selection"
+msg_wireless_networks="Wireless Networks"
+msg_wlans="wlans"
+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 --git a/contrib/bsddialog/bsdconfig/networking/nameservers b/contrib/bsddialog/bsdconfig/networking/nameservers
new file mode 100755
index 000000000000..e18f00493efb
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/nameservers
@@ -0,0 +1,76 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent device.subr (included indirectly) from auto scanning on load
+DEVICE_SELF_SCAN_ALL=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/networking/resolv.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 --git a/contrib/bsddialog/bsdconfig/networking/networking b/contrib/bsddialog/bsdconfig/networking/networking
new file mode 100755
index 000000000000..af37caaf3d6c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/networking
@@ -0,0 +1,153 @@
+#!/bin/sh
+#-
+# Copyright (c) 2006-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local menu_list="
+ 'X' '$msg_exit'
+ '1' '$msg_hostname_domain'
+ '2' '$msg_network_interfaces'
+ '3' '$msg_wireless_networks'
+ '4' '$msg_default_router'
+ '5' '$msg_dns_nameservers'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_network_management"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main || f_die
+ f_dialog_menutag_fetch mtag
+
+ command=
+ case "$mtag" in
+ X) break ;;
+ 1) command=hostname ;; # Hostname/Domain
+ 2) command=devices ;; # Network Interfaces
+ 3) command=wlanconfig ;; # Wireless Networks
+ 4) command=defaultrouter ;; # Default Router/Gateway
+ 5) command=nameservers ;; # DNS nameservers
+ esac
+
+ if [ "$command" ]; then
+ $BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
+ else
+ f_die 1 "$msg_unknown_networking_menu_selection"
+ fi
+
+ if [ "$mtag" = "devices" ]; then
+ #
+ # Make subsequent uses of this menu faster by not performing
+ # "ifconfig up" (limiting the pain one must endure). See also
+ # `$BSDCFG_SHARE/networking/device.subr'.
+ #
+ export DIALOG_MENU_NETDEV_KICK_INTERFACES=
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/networking/share/Makefile b/contrib/bsddialog/bsdconfig/networking/share/Makefile
new file mode 100644
index 000000000000..6d77f25c5e9e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/networking
+FILES= common.subr device.subr hostname.subr ipaddr.subr media.subr \
+ netmask.subr resolv.subr routing.subr services.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/networking/share/Makefile.depend b/contrib/bsddialog/bsdconfig/networking/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/networking/share/common.subr b/contrib/bsddialog/bsdconfig/networking/share/common.subr
new file mode 100644
index 000000000000..152d1aceb03b
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/common.subr
@@ -0,0 +1,58 @@
+if [ ! "$_NETWORKING_COMMON_SUBR" ]; then _NETWORKING_COMMON_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ FUNCTIONS
+
+# 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 )" ]
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/common.subr
+
+fi # ! $_NETWORKING_COMMON_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/device.subr b/contrib/bsddialog/bsdconfig/networking/share/device.subr
new file mode 100644
index 000000000000..41ea29def67c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/device.subr
@@ -0,0 +1,403 @@
+if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1
+#
+# Copyright (c) 2006-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/device.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/media/wlan.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/networking/ipaddr.subr
+f_include $BSDCFG_SHARE/networking/media.subr
+f_include $BSDCFG_SHARE/networking/netmask.subr
+f_include $BSDCFG_SHARE/networking/resolv.subr
+f_include $BSDCFG_SHARE/networking/routing.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+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_dialog_menu_netdev [$default]
+#
+# Display a list of network devices with descriptions. Optionally, if present
+# and non-NULL, initially highlight $default interface.
+#
+f_dialog_menu_netdev()
+{
+ local menu_list # Calculated below
+ local defaultitem="${1%\*}" # Trim trailing asterisk if present
+
+ #
+ # 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 dev devs if iflist= # Calculated below
+ f_device_rescan_network
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ for dev in $devs; do
+ f_struct "$dev" get name if || continue
+ # Skip unsavory interfaces
+ case "$if" in
+ lo[0-9]*|ppp[0-9]*|sl[0-9]*) continue ;;
+ esac
+ iflist="$iflist $if"
+ done
+ iflist="${iflist# }"
+
+ #
+ # 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=
+
+ for if in $iflist; do
+ f_quietly ifconfig $if 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.
+ #
+ menu_list=$(
+ for if in $iflist; do
+ f_device_desc $if $DEVICE_TYPE_NETWORK desc
+ f_shell_escape "$desc" desc
+ if f_device_is_active $if; then
+ printf "'%s\*' '%s'\n" $if "$desc"
+ else
+ printf "'%s' '%s'\n" $if "$desc"
+ fi
+ done
+ )
+ if [ ! "$menu_list" ]; then
+ f_show_msg "$msg_no_network_interfaces"
+ return $DIALOG_CANCEL
+ fi
+
+ # Maybe the default item was marked as active
+ f_device_is_active "$defaultitem" && defaultitem="$defaultitem*"
+
+ #
+ # Ask user to select an interface
+ #
+ local prompt="$msg_select_network_interface"
+ local hline="$hline_arrows_tab_enter"
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+# 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 funcname=f_dialog_menu_netdev_edit
+ local interface="$1" ipaddr="$2" netmask="$3" options="$4" dhcp="$5"
+ local prompt menu_list height width rows
+
+ #
+ # 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"
+ f_sprintf prompt "$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).
+ #
+ local defaultitem=
+ local wlans wlan_status
+ while :; do
+ local dhcp_status="$msg_disabled"
+ [ "$dhcp" ] && dhcp_status="$msg_enabled"
+
+ if f_device_is_wireless "$interface"; then
+ wlans=$( f_sysrc_get "wlans_$interface" )
+ wlan_status="$msg_unconfigured"
+ [ -e "$( f_sysrc_get wpa_supplicant_conf_file )" ] &&
+ wlan_status="$msg_configured"
+ fi
+
+ #
+ # Display configuration-edit menu
+ #
+ menu_list="
+ 'X $msg_save_exit' '$msg_return_to_previous_menu'
+ " # END-QUOTE
+ f_device_is_wireless "$interface" && menu_list="$menu_list
+ 'W $msg_wireless_networks' '$wlan_status'
+ '1 $msg_wlans' '$wlans'
+ " # END-QUOTE
+ menu_list="$menu_list
+ '2 $msg_dhcp' '$dhcp_status'
+ '3 $msg_ipaddr4' '$ipaddr'
+ '4 $msg_netmask' '$netmask'
+ '5 $msg_options' '$options'
+ " # END-QUOTE
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ local tag
+ tag=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize tag
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$TCP_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ return $retval
+ else
+ # Only update default-item on success
+ defaultitem="$tag"
+ fi
+
+ #
+ # 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 ;;
+ W\ *) f_dialog_menu_wireless_edit ;;
+ 1\ *) f_dialog_menu_wlandev_edit \
+ "$interface" "${wlans%%[$IFS]*}" ;;
+ 2\ *) #
+ # Proceed cautiously (confirm with the user) if/when NFS-
+ # mounts are active. If the network on which these mounts
+ # are made is changed parts of the system may hang.
+ #
+ if f_nfs_mounted && ! f_jailed; then
+ local setting
+ f_sprintf setting "$msg_current_dhcp_status" \
+ "$interface" "$dhcp_status"
+ f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
+ 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
+ f_sprintf msg "$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 $DIALOG_OK ]; then
+ dhcp=1
+ f_ifconfig_inet "$interface" ipaddr
+ f_ifconfig_inet6 "$interface" ipaddr6
+ f_ifconfig_netmask "$interface" netmask
+ 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 $DIALOG_OK ] && dhcp= ;;
+ 4\ *) f_dialog_input_netmask "$interface" "$netmask"
+ [ $? -eq $DIALOG_OK -a "$_netmask" ] && dhcp= ;;
+ 5\ *) f_dialog_menu_media_options "$interface" "$options"
+ [ $? -eq $DIALOG_OK ] && 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_show_info "$msg_saving_network_interface" "$interface"
+
+ local value=
+ if [ "$dhcp" ]; then
+ f_eval_catch $funcname f_sysrc_delete \
+ 'f_sysrc_delete defaultrouter'
+ value=DHCP
+ else
+ value="inet $ipaddr netmask $netmask"
+ value="$value${options:+ }$options"
+ fi
+
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set "ifconfig_%s" "%s"' "$interface" "$value"
+ fi
+
+ #
+ # Re/Apply the settings if desired
+ #
+ if [ ! "$dhcp" ]; then
+ if f_yesno "$msg_bring_interface_up" "$interface"
+ then
+ f_show_info "$msg_bring_interface_up" "$interface"
+
+ local dr="$( f_sysrc_get defaultrouter )"
+ if [ "$dr" = "NO" -o ! "$dr" ]; then
+ f_route_get_default dr
+ [ "$dr" ] && f_eval_catch \
+ $funcname f_sysrc_set \
+ 'f_sysrc_set defaultrouter "%s"' "$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.$$"
+ if f_eval_catch $funcname ifconfig \
+ 'ifconfig "%s" inet "%s" netmask "%s" %s' \
+ "$interface" "$ipaddr" "$netmask" "$options"
+ then
+ [ "$dr" -a "$dr" != "NO" ] &&
+ f_eval_catch $funcname route \
+ 'route add default "%s"' "$dr"
+ 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 $DIALOG_OK
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/device.subr
+
+fi # ! $_NETWORKING_DEVICE_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/hostname.subr b/contrib/bsddialog/bsdconfig/networking/share/hostname.subr
new file mode 100644
index 000000000000..34bfd6e1d572
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/hostname.subr
@@ -0,0 +1,162 @@
+if [ ! "$_NETWORKING_HOSTNAME_SUBR" ]; then _NETWORKING_HOSTNAME_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/hostname.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/networking/resolv.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_hnerror $error $hostname
+#
+# Display a msgbox with the appropriate error message for an error returned by
+# the f_validate_hostname function.
+#
+f_dialog_hnerror()
+{
+ local error="$1" fqhn="$2"
+
+ [ ${error:-0} -ne 0 ] || return $SUCCESS
+
+ case "$error" in
+ 1) f_show_msg "$msg_hostname_label_contains_invalid_chars" "$fqhn" ;;
+ 2) f_show_msg \
+ "$msg_hostname_label_starts_or_ends_with_hyphen" "$fqhn" ;;
+ 3) f_show_msg "$msg_hostname_label_is_null" "$fqhn" ;;
+ 63) f_show_msg "$msg_hostname_label_exceeds_max_length" "$fqhn" ;;
+ 255) f_show_msg "$msg_hostname_exceeds_max_length" "$fqhn" ;;
+ esac
+}
+
+# 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
+# https://tools.ietf.org/html/rfc952
+#
+# RFC 1123 - Requirements for Internet Hosts - Application and Support
+# https://tools.ietf.org/html/rfc1123
+#
+# If the hostname is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_hnerror function above.
+#
+f_dialog_validate_hostname()
+{
+ local fqhn="$1"
+
+ f_validate_hostname "$fqhn"
+ local retval=$?
+
+ # Produce an appropriate error message if necessary.
+ [ $retval -eq $SUCCESS ] || f_dialog_hnerror $retval "$fqhn"
+
+ return $retval
+}
+
+# f_dialog_input_hostname
+#
+# Edits the current hostname.
+#
+f_dialog_input_hostname()
+{
+ local funcname=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
+
+ #
+ # Loop until the user provides taint-free input.
+ #
+ while :; do
+ f_dialog_input hostname "$msg" "$hostname" \
+ "$hline_alnum_punc_tab_enter" || return $?
+ # 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_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set hostname "%s"' "$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" ] && f_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_show_msg "$msg_activate_hostname_x11warning" \
+ "$( hostname )" "$hostname"
+ else
+ f_yesno "$msg_activate_hostname" \
+ "$( hostname )" "$hostname" \
+ && hostname "$hostname"
+ fi
+ fi
+
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/hostname.subr
+
+fi # ! $_NETWORKING_HOSTNAME_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/ipaddr.subr b/contrib/bsddialog/bsdconfig/networking/share/ipaddr.subr
new file mode 100644
index 000000000000..b7624cc792d4
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/ipaddr.subr
@@ -0,0 +1,219 @@
+if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/ipaddr.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_iperror $error $ipaddr
+#
+# Display a msgbox with the appropriate error message for an error returned by
+# the f_validate_ipaddr function.
+#
+f_dialog_iperror()
+{
+ local error="$1" ip="$2"
+
+ [ ${error:-0} -ne 0 ] || return $SUCCESS
+
+ case "$error" in
+ 1) f_show_msg "$msg_ipv4_addr_octet_contains_invalid_chars" "$ip" ;;
+ 2) f_show_msg "$msg_ipv4_addr_octet_is_null" "$ip" ;;
+ 3) f_show_msg "$msg_ipv4_addr_octet_exceeds_max_value" "$ip" ;;
+ 4) f_show_msg "$msg_ipv4_addr_octet_missing_or_extra" "$ip" ;;
+ esac
+}
+
+# f_dialog_validate_ipaddr $ipaddr
+#
+# Returns zero if the given argument (an IP address) is of the proper format.
+#
+# If the IP address is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_iperror function above.
+#
+f_dialog_validate_ipaddr()
+{
+ local ip="$1"
+
+ f_validate_ipaddr "$ip"
+ local retval=$?
+
+ # Produce an appropriate error message if necessary.
+ [ $retval -eq $SUCCESS ] || f_dialog_iperror $retval "$ip"
+
+ return $retval
+}
+
+# f_dialog_ip6error $error $ipv6_addr
+#
+# Display a msgbox with the appropriate error message for an error returned by
+# the f_validate_ipaddr6 function above.
+#
+f_dialog_ip6error()
+{
+ local error="$1" ip="$2"
+
+ [ ${error:-0} -ne 0 ] || return $SUCCESS
+
+ case "$error" in
+ 1) f_show_msg "$msg_ipv6_addr_segment_contains_invalid_chars" "$ip" ;;
+ 2) f_show_msg "$msg_ipv6_addr_too_many_null_segments" "$ip" ;;
+ 3) f_show_msg "$msg_ipv6_addr_segment_contains_too_many_chars" "$ip" ;;
+ 4) f_show_msg "$msg_ipv6_addr_too_few_or_extra_segments" "$ip" ;;
+ *)
+ if [ $(( $error & 0xF )) -eq 5 ]; then
+ # IPv4 at the end of IPv6 address is invalid
+ f_dialog_iperror $(( $error >> 4 )) "$ip"
+ fi
+ esac
+}
+
+# f_dialog_validate_ipaddr6 $ipv6_addr
+#
+# Returns zero if the given argument (an IPv6 address) is of the proper format.
+#
+# If the IP address is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_ip6error function above.
+#
+f_dialog_validate_ipaddr6()
+{
+ local ip="$1"
+
+ f_validate_ipaddr6 "$ip"
+ local retval=$?
+
+ # Produce an appropriate error message if necessary.
+ [ $retval -eq $SUCCESS ] || f_dialog_ip6error $retval "$ip"
+
+ 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
+ f_sprintf setting "$msg_current_ipaddr" "$interface" "$_ipaddr"
+ f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
+ return $DIALOG_CANCEL
+ fi
+
+ local msg
+ f_sprintf msg "$msg_please_enter_new_ip_addr" "$interface"
+
+ #
+ # Loop until the user provides taint-free input.
+ #
+ local retval
+ while :; do
+ #
+ # Return error status if:
+ # - User has either pressed ESC or chosen Cancel/No
+ # - User has not made any changes to the given value
+ #
+ f_dialog_input _input "$msg" "$_ipaddr" \
+ "$hline_num_punc_tab_enter" || return $?
+ [ "$_ipaddr" = "$_input" ] && return $DIALOG_CANCEL
+
+ # Return success if NULL value was entered
+ [ "$_input" ] || return $DIALOG_OK
+
+ # 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 $DIALOG_OK
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/ipaddr.subr
+
+fi # ! $_NETWORKING_IPADDR_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/media.subr b/contrib/bsddialog/bsdconfig/networking/share/media.subr
new file mode 100644
index 000000000000..028944b5eb6b
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/media.subr
@@ -0,0 +1,247 @@
+if [ ! "$_NETWORKING_MEDIA_SUBR" ]; then _NETWORKING_MEDIA_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/media.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+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 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. If the user does not press ESC or choose
+# Cancel/No, $options will hold the user's input. Default input is taken from
+# the same variable ($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
+ f_sprintf setting "$msg_current_options" \
+ "$interface" "$options"
+ f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
+ return $DIALOG_CANCEL
+ fi
+
+ local msg
+ f_sprintf msg "$msg_please_enter_mediaopts" "$interface"
+ local hline="$hline_alnum_punc_tab_enter"
+
+ local _options
+ _options=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --inputbox "$msg" 9 70 \
+ "$options" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_line_sanitize _options
+
+ [ $retval -eq $DIALOG_OK ] && 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
+ f_sprintf setting "$msg_current_options" \
+ "$interface" "$_options"
+ f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
+ return $DIALOG_CANCEL
+ 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
+
+ f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tagn' '$opt_none'"
+ index=$(( $index + 1 ))
+
+ f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tagn' '$opt_cust'"
+ index=$(( $index + 1 ))
+
+ while read media_options; do
+ [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
+ f_substr -v tagn "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tagn' '$media_options'"
+ index=$(( $index + 1 ))
+ done
+ )
+ )"
+
+ local msg
+ if [ "$USE_XDIALOG" ]; then
+ f_sprintf msg "$xmsg_supported_media_options" \
+ "$interface" "$interface"
+ else
+ f_sprintf msg "$msg_supported_media_options" \
+ "$interface" "$interface"
+ fi
+
+ local hline="$hline_arrows_tab_enter"
+
+ local tag
+ tag=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$msg\" 21 60 12 \
+ $supported_media \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize tag
+
+ if [ $retval -eq $DIALOG_OK ]; then
+ options=$( eval f_dialog_menutag2item \"\$tag\" \
+ $supported_media )
+ case "$options" in
+ "$opt_none")
+ options=
+ ;;
+ "$opt_cust")
+ options="$_options"
+ f_dialog_input_options "$interface"
+ retval=$?
+ ;;
+ esac
+ fi
+
+ return $retval
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/media.subr
+
+fi # ! $_NETWORKING_MEDIA_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/netmask.subr b/contrib/bsddialog/bsdconfig/networking/share/netmask.subr
new file mode 100644
index 000000000000..a7d44a55e00a
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/netmask.subr
@@ -0,0 +1,137 @@
+if [ ! "$_NETWORKING_NETMASK_SUBR" ]; then _NETWORKING_NETMASK_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/netmask.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_maskerror $error $netmask
+#
+# Display a msgbox with the appropriate error message for an error returned by
+# the f_validate_netmask function.
+#
+f_dialog_maskerror()
+{
+ local error="$1" netmask="$2"
+
+ [ ${error:-0} -ne 0 ] || return $SUCCESS
+
+ case "$error" in
+ 1) f_show_msg "$msg_ipv4_mask_field_contains_invalid_chars" "$mask" ;;
+ 2) f_show_msg "$msg_ipv4_mask_field_is_null" "$mask" ;;
+ 3) f_show_msg "$msg_ipv4_mask_field_exceeds_max_value" "$mask" ;;
+ 4) f_show_msg "$msg_ipv4_mask_field_missing_or_extra" "$mask" ;;
+ 5) f_show_msg "$msg_ipv4_mask_field_invalid_value" "$mask" ;;
+ esac
+}
+
+# f_dialog_validate_netmask $netmask
+#
+# Returns zero if the given argument (a subnet mask) is of the proper format.
+#
+# If the subnet mask is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_maskerror function above.
+#
+f_dialog_validate_netmask()
+{
+ local netmask="$1"
+
+ f_validate_netmask "$netmask"
+ local retval=$?
+
+ # Produce an appropriate error message if necessary.
+ [ $retval -eq $SUCCESS ] || f_dialog_maskerror $retval "$netmask"
+
+ 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
+ f_sprintf setting "$msg_current_subnet" \
+ "$interface" "$_netmask"
+ f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
+ return $DIALOG_CANCEL
+ fi
+
+ #
+ # Loop until the user provides taint-free input.
+ #
+ local msg
+ f_sprintf msg "$msg_please_enter_subnet_mask" "$interface"
+ while :; do
+ #
+ # Return error status if:
+ # - User has either pressed ESC or chosen Cancel/No
+ # - User has not made any changes to the given value
+ #
+ f_dialog_input _input "$msg" "$_netmask" \
+ "$hline_num_punc_tab_enter" || return $?
+ [ "$_netmask" = "$_input" ] && return $DIALOG_CANCEL
+
+ # Return success if NULL value was entered
+ [ "$_input" ] || return $DIALOG_OK
+
+ # 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"
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/netmask.subr
+
+fi # ! $_NETWORKING_NETMASK_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/resolv.subr b/contrib/bsddialog/bsdconfig/networking/share/resolv.subr
new file mode 100644
index 000000000000..779863c9981d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/resolv.subr
@@ -0,0 +1,502 @@
+if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/resolv.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/networking/ipaddr.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# 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_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 funcname=f_dialog_resolv_conf_update
+ local hostname="$1"
+
+ #
+ # Extrapolate the desired domain search parameter for resolv.conf(5)
+ #
+ local search nfields ndots domain="${hostname#*.}"
+ if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then
+ search=
+ IFS=. f_count_ifs nfields "$domain"
+ ndots=$(( $nfields - 1 ))
+ while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do
+ search="$search $domain"
+ domain="${domain#*.}"
+ ndots=$(( $ndots - 1 ))
+ done
+ search="${search# }"
+ 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
+ f_eval_catch -dk tmpfile $funcname mktemp \
+ 'mktemp -t "%s"' "$tmpfile" || return $DIALOG_CANCEL
+
+ #
+ # 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 owner
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$RESOLV_CONF" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$RESOLV_CONF" ||
+ owner="root:wheel"
+ f_eval_catch -d $funcname chmod \
+ 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown \
+ 'chown "%s" "%s"' "$owner" "$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 $DIALOG_CANCEL
+ f_eval_catch -d $funcname mv \
+ 'mv "%s" "%s"' "$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 funcname=f_dialog_input_nameserver
+ local index="${1:-0}" old_ns="$2" new_ns
+ local ns="$old_ns"
+
+ #
+ # Perform sanity checks
+ #
+ f_isinteger "$index" || return $DIALOG_CANCEL
+ [ $index -ge 0 ] || return $DIALOG_CANCEL
+
+ 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
+
+ #
+ # Loop until the user provides taint-free input.
+ #
+ while :; do
+ f_dialog_input new_ns "$msg" "$ns" \
+ "$hline_num_punc_tab_enter" || return $?
+
+ # 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 $DIALOG_OK
+ 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
+ f_eval_catch -dk tmpfile $funcname mktemp \
+ 'mktemp -t "%s"' "$pgm" || return $DIALOG_CANCEL
+
+ #
+ # Quietly fixup permissions and ownership
+ #
+ local mode owner
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$RESOLV_CONF" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$RESOLV_CONF" ||
+ owner="root:wheel"
+ f_eval_catch -d $funcname chmod \
+ 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown \
+ 'chown "%s" "%s"' "$owner" "$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_show_msg "$msg_resolv_conf_changed_while_editing"
+ return $retval ;;
+ 3) f_show_msg "$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 $DIALOG_CANCEL
+ f_eval_catch -d $funcname mv \
+ 'mv "%s" "%s"' "$tmpfile" "$RESOLV_CONF"
+ fi
+}
+
+# f_dialog_menu_nameservers
+#
+# Edit the nameservers in resolv.conf(5).
+#
+f_dialog_menu_nameservers()
+{
+ local prompt="$msg_dns_configuration"
+ local menu_list # Calculated below
+ local hline="$hline_arrows_tab_enter"
+ local defaultitem=
+
+ local height width rows
+ local opt_exit="$msg_return_to_previous_menu"
+ local opt_add="$msg_add_nameserver"
+
+ #
+ # Loop forever until the user has finished configuring nameservers
+ #
+ while :; do
+ #
+ # Re/Build list of nameservers
+ #
+ local nameservers
+ f_resolv_conf_nameservers nameservers
+ 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
+ f_substr -v tag "$DIALOG_MENU_TAGS" $index 1
+ echo "'$tag nameserver' '$ns'"
+ index=$(( $index + 1 ))
+ done
+ )
+
+ #
+ # Display configuration-edit menu
+ #
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ local tag
+ tag=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize tag
+
+ # Return if "Cancel" was chosen (-1) or ESC was pressed (255)
+ if [ $retval -ne $DIALOG_OK ]; then
+ return $retval
+ else
+ # Only update default-item on success
+ defaultitem="$tag"
+ fi
+
+ case "$tag" in
+ "X $msg_exit") break ;;
+ "A $msg_add")
+ f_dialog_input_nameserver
+ ;;
+ *)
+ local n ns
+ 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
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/resolv.subr
+
+fi # ! $_NETWORKING_RESOLV_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/routing.subr b/contrib/bsddialog/bsdconfig/networking/share/routing.subr
new file mode 100644
index 000000000000..826ac6e10baf
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/routing.subr
@@ -0,0 +1,133 @@
+if [ ! "$_NETWORKING_ROUTING_SUBR" ]; then _NETWORKING_ROUTING_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/routing.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/networking/common.subr
+f_include $BSDCFG_SHARE/networking/ipaddr.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_dialog_input_defaultrouter
+#
+# Edits the default router.
+#
+f_dialog_input_defaultrouter()
+{
+ local funcname=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]) f_route_get_default defaultrouter ;;
+ 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
+ f_sprintf setting "$msg_current_default_router" \
+ "$defaultrouter"
+ f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
+ return $DIALOG_CANCEL
+ fi
+
+ #
+ # Loop until the user provides taint-free input.
+ #
+ local retval
+ while :; do
+ f_dialog_input defaultrouter \
+ "$msg_please_enter_default_router" \
+ "$defaultrouter" "$hline_num_punc_tab_enter"
+ retval=$?
+ [ "$defaultrouter" ] || return $DIALOG_OK
+ [ $retval -eq $DIALOG_OK ] || 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_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set defaultrouter "%s"' "$defaultrouter"
+ fi
+
+ #
+ # Only ask to apply setting if the current defaultrouter is different
+ # than the stored configuration (in rc.conf(5)).
+ #
+ local dr
+ f_route_get_default dr
+ if [ "$dr" != "$defaultrouter" ]; then
+ f_dialog_clear
+ f_yesno "$msg_activate_default_router" "$dr" "$defaultrouter"
+ if [ $? -eq $DIALOG_OK ]; then
+ # Apply the default router/gateway
+ f_eval_catch -d $funcname route 'route delete default'
+ f_eval_catch $funcname route \
+ 'route add default "%s"' "$defaultrouter" ||
+ return $DIALOG_CANCEL
+ fi
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/routing.subr
+
+fi # ! $_NETWORKING_ROUTING_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/share/services.subr b/contrib/bsddialog/bsdconfig/networking/share/services.subr
new file mode 100644
index 000000000000..246d8956e322
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/share/services.subr
@@ -0,0 +1,55 @@
+if [ ! "$_NETWORKING_SERVICES_SUBR" ]; then _NETWORKING_SERVICES_SUBR=1
+#
+# Copyright (c) 2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." networking/services.subr
+f_include $BSDCFG_SHARE/packages/packages.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+############################################################ FUNCTIONS
+
+# f_config_pcnfsd
+#
+# Load pcnfsd package and adjust mountd_flags in rc.conf(5).
+#
+f_config_pcnfsd()
+{
+ local funcname=f_config_pcnfsd
+ f_package_add "pcnfsd" || return $?
+ f_eval_catch $funcname f_sysrc_set 'f_sysrc_set mountd_flags -n'
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." networking/services.subr
+
+fi # ! $_NETWORKING_SERVICES_SUBR
diff --git a/contrib/bsddialog/bsdconfig/networking/wlanconfig b/contrib/bsddialog/bsdconfig/networking/wlanconfig
new file mode 100755
index 000000000000..989bb794fb8e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/networking/wlanconfig
@@ -0,0 +1,78 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Tom Rhodes
+# Copyright (c) 2013-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+# Prevent device.subr (included indirectly) from auto scanning on load
+DEVICE_SELF_SCAN_ALL=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/wlan.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_wireless_networks"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch the wireless network menu
+#
+f_dialog_menu_wireless_edit
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/packages/INDEX b/contrib/bsddialog/bsdconfig/packages/INDEX
new file mode 100644
index 000000000000..80434779f202
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/INDEX
@@ -0,0 +1,56 @@
+# Copyright (c) 2013 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$
+
+#
+# Title that will be shown in the bsdconfig menu.
+#
+menu_title="Packages"
+
+#
+# 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 pre-packaged software for FreeBSD"
+
+#
+# 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="packages|packages"
+
+#
+# ------------ 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="packages"
diff --git a/contrib/bsddialog/bsdconfig/packages/Makefile b/contrib/bsddialog/bsdconfig/packages/Makefile
new file mode 100644
index 000000000000..fa5bd302c6d7
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/030.packages
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= packages
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/packages/Makefile.depend b/contrib/bsddialog/bsdconfig/packages/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/packages/USAGE b/contrib/bsddialog/bsdconfig/packages/USAGE
new file mode 100644
index 000000000000..5f99b3826454
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/packages/include/Makefile b/contrib/bsddialog/bsdconfig/packages/include/Makefile
new file mode 100644
index 000000000000..3d30fd2b4a5f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/030.packages/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/packages/include/Makefile.depend b/contrib/bsddialog/bsdconfig/packages/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/packages/include/messages.subr b/contrib/bsddialog/bsdconfig/packages/include/messages.subr
new file mode 100755
index 000000000000..8e945acc8ab6
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/include/messages.subr
@@ -0,0 +1,27 @@
+# Copyright (c) 2013 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$
+
+msg_package_selection="Package Selection"
diff --git a/contrib/bsddialog/bsdconfig/packages/packages b/contrib/bsddialog/bsdconfig/packages/packages
new file mode 100755
index 000000000000..ec429f282462
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/packages/packages
@@ -0,0 +1,82 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 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$
+#
+############################################################ INCLUDES
+
+# Prevent device.subr (included indirectly via media/*.subr below) from auto
+# scanning; we'll perform this manually using f_device_get_all() during init
+# but only after we've successfully completed f_mustberoot_init().
+#
+DEVICE_SELF_SCAN_ALL=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/packages/packages.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="030.packages"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_package_selection"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+f_device_get_all
+
+#
+# Display the package configuration menu and exit
+#
+trap 'f_media_close' EXIT
+f_package_config
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/password/INDEX b/contrib/bsddialog/bsdconfig/password/INDEX
new file mode 100644
index 000000000000..10f23db67b0b
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/password/Makefile b/contrib/bsddialog/bsdconfig/password/Makefile
new file mode 100644
index 000000000000..d660e452a659
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/040.password
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= password
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/password/Makefile.depend b/contrib/bsddialog/bsdconfig/password/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/password/USAGE b/contrib/bsddialog/bsdconfig/password/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/password/include/Makefile b/contrib/bsddialog/bsdconfig/password/include/Makefile
new file mode 100644
index 000000000000..a146eb230ae9
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/040.password/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/password/include/Makefile.depend b/contrib/bsddialog/bsdconfig/password/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/password/include/messages.subr b/contrib/bsddialog/bsdconfig/password/include/messages.subr
new file mode 100644
index 000000000000..655160de0724
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/include/messages.subr
@@ -0,0 +1,35 @@
+# Copyright (c) 2012-2013 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$
+
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+msg_cancel="Cancel"
+msg_enter_new_password="Enter New Password"
+msg_ok="OK"
+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 --git a/contrib/bsddialog/bsdconfig/password/password b/contrib/bsddialog/bsdconfig/password/password
new file mode 100755
index 000000000000..b73a8d0936f0
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/password
@@ -0,0 +1,85 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/password/password.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="040.password"
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_root_password"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Prompt the user to input a new password (and change it if they don't cancel)
+#
+if f_dialog_input_password; then
+ echo "$pw_password" | f_eval_catch "$0" pw \
+ 'pw usermod "%s" -h 0' "$USER_ROOT" || f_die
+ f_show_msg "$msg_password_changed"
+fi
+
+return $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/password/share/Makefile b/contrib/bsddialog/bsdconfig/password/share/Makefile
new file mode 100644
index 000000000000..65f9e8c5c0f1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/share/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/password
+FILES= password.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/password/share/Makefile.depend b/contrib/bsddialog/bsdconfig/password/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/password/share/password.subr b/contrib/bsddialog/bsdconfig/password/share/password.subr
new file mode 100644
index 000000000000..22803394fc30
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/password/share/password.subr
@@ -0,0 +1,124 @@
+if [ ! "$_PASSWORD_PASSWORD_SUBR" ]; then _PASSWORD_PASSWORD_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." password/password.subr
+f_include $BSDCFG_SHARE/dialog.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" 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 prompt1="$msg_enter_new_password"
+ local prompt2="$msg_reenter_password"
+ local hline="$hline_alnum_punc_tab_enter"
+
+ local height1 width1
+ f_dialog_inputbox_size height1 width1 \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$prompt1" \
+ "" \
+ "$hline"
+
+ local height2 width2
+ f_dialog_inputbox_size height2 width2 \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$prompt2" \
+ "" \
+ "$hline"
+
+ #
+ # Loop until the user provides taint-free/valid input
+ #
+ local _password1 _password2
+ while :; do
+ _password1=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$prompt1" \
+ $height1 $width1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Return if user either pressed ESC or chose Cancel/No
+ debug= f_dialog_line_sanitize _password1
+
+ _password2=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$prompt2" \
+ $height2 $width2 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Return if user either pressed ESC or chose Cancel/No
+ debug= f_dialog_line_sanitize _password2
+
+ # 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 $DIALOG_OK
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." password/password.subr
+
+fi # ! $_PASSWORD_PASSWORD_SUBR
diff --git a/contrib/bsddialog/bsdconfig/security/INDEX b/contrib/bsddialog/bsdconfig/security/INDEX
new file mode 100644
index 000000000000..9e7718690622
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/security/Makefile b/contrib/bsddialog/bsdconfig/security/Makefile
new file mode 100644
index 000000000000..af83cee47158
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/130.security
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= kern_securelevel security
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/security/Makefile.depend b/contrib/bsddialog/bsdconfig/security/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/security/USAGE b/contrib/bsddialog/bsdconfig/security/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/security/include/Makefile b/contrib/bsddialog/bsdconfig/security/include/Makefile
new file mode 100644
index 000000000000..2efcc0f8a399
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/130.security/include
+FILES= messages.subr securelevel.hlp
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/security/include/Makefile.depend b/contrib/bsddialog/bsdconfig/security/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/security/include/messages.subr b/contrib/bsddialog/bsdconfig/security/include/messages.subr
new file mode 100644
index 000000000000..1ab2333c1fb8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/include/messages.subr
@@ -0,0 +1,50 @@
+# 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$
+
+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"
+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 effect 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"
+msg_unknown_kern_securelevel_selection="Unknown kern.securelevel selection"
+msg_unknown_security_menu_selection="Unknown security menu selection"
diff --git a/contrib/bsddialog/bsdconfig/security/include/securelevel.hlp b/contrib/bsddialog/bsdconfig/security/include/securelevel.hlp
new file mode 100644
index 000000000000..27eb1ec231b9
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/include/securelevel.hlp
@@ -0,0 +1,40 @@
+This menu allows you to configure the Securelevel mechanism in FreeBSD.
+
+Securelevels may be used to limit the privileges assigned to the
+root user in multi-user mode, which in turn may limit the effects of
+a root compromise, at the cost of reducing administrative functions.
+Refer to the security(7) and init(8) manual pages for complete details.
+
+ -1 Permanently insecure mode - always run the system in level 0
+ mode. This is the default initial value.
+
+ 0 Insecure mode - immutable and append-only flags may be turned
+ off. All devices may be read or written subject to their
+ permissions.
+
+ 1 Secure mode - the system immutable and system append-only
+ flags may not be turned off; disks for mounted file systems,
+ /dev/mem, /dev/kmem and /dev/io (if your platform has it)
+ may not be opened for writing; kernel modules (see kld(4))
+ may not be loaded or unloaded.
+
+ 2 Highly secure mode - same as secure mode, plus disks may not
+ be opened for writing (except by mount(2)) whether mounted or
+ not. This level precludes tampering with file systems by
+ unmounting them, but also inhibits running newfs(8) while the
+ system is multi-user.
+
+ In addition, kernel time changes are restricted to less than
+ or equal to one second. Attempts to change the time by more
+ than this will log the message ``Time adjustment clamped to +1
+ second''.
+
+ 3 Network secure mode - same as highly secure mode, plus IP
+ packet filter rules (see ipfw(8), ipfirewall(4) and pfctl(8))
+ cannot be changed and dummynet(4) or pf(4) configuration
+ cannot be adjusted.
+
+Securelevels must be used in combination with careful system design and
+application of protective mechanisms to prevent system configuration
+files from being modified in a way that compromises the protections of
+the securelevel variable upon reboot.
diff --git a/contrib/bsddialog/bsdconfig/security/kern_securelevel b/contrib/bsddialog/bsdconfig/security/kern_securelevel
new file mode 100755
index 000000000000..9aa79b7de8f7
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/kern_securelevel
@@ -0,0 +1,175 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="130.security"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+SECURELEVEL_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/securelevel.hlp
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_securelevels_menu_text"
+ local menu_list="
+ '$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
+ local defaultitem= # Calculated below
+ local hline="$hline_select_securelevel_to_operate_at"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ case "$( f_sysrc_get kern_securelevel_enable )" in
+ [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
+ case "$( f_sysrc_get kern_securelevel )" in
+ 1) defaultitem="$msg_secure" ;;
+ 2) defaultitem="$msg_highly_secure" ;;
+ 3) defaultitem="$msg_network_secure" ;;
+ esac ;;
+ *)
+ defaultitem="$msg_disabled"
+ esac
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_securelevels_menu_title"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu (loop for additional `Help' button)
+#
+while :; do
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$SECURELEVEL_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ f_die
+ fi
+
+ break
+done
+
+case "$mtag" in
+"$msg_disabled")
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable NO' || f_die
+ ;;
+"$msg_secure")
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable YES' || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel 1' || f_die
+ ;;
+"$msg_highly_secure")
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable YES' || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel 2' || f_die
+ ;;
+"$msg_network_secure")
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable YES' || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel 3' || f_die
+ ;;
+*)
+ f_die 1 "$msg_unknown_kern_securelevel_selection"
+esac
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/security/security b/contrib/bsddialog/bsdconfig/security/security
new file mode 100755
index 000000000000..e045ad8a2027
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/security/security
@@ -0,0 +1,179 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="130.security"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_menu_text"
+ local menu_list="
+ 'X $msg_exit' '$msg_exit_this_menu'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ # Obtain default-item (adjusted below for dynamic tags)
+ f_dialog_default_fetch defaultitem
+ local ditem="${defaultitem%%[$IFS]*}"
+
+ #
+ # Add dynamically tagged entry for kern_securelevels
+ #
+ local mark=" "
+ 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" &&
+ [ $kern_securelevel -lt 9 ]
+ then
+ mark="$kern_securelevel"
+ else
+ mark="X"
+ fi ;;
+ *)
+ mark=" "
+ esac
+ menu_list="$menu_list
+ '2 [$mark] $msg_securelevel' '$msg_securelevel_desc'"
+
+ # Update default-item if appropriate
+ [ "$ditem" = 2 ] && defaultitem="2 [$mark] $msg_securelevel"
+
+ #
+ # Add dynamically tagged entry for nfs_reserved_port_only
+ #
+ case "$( f_sysrc_get nfs_reserved_port_only )" in
+ [Yy][Ee][Ss]) mark="X" ;;
+ *) mark=" " ;;
+ esac
+ menu_list="$menu_list
+ '3 [$mark] $msg_nfs_port' '$msg_nfs_port_desc'"
+
+ # Update default-item if appropriate
+ [ "$ditem" = 3 ] && defaultitem="3 [$mark] $msg_nfs_port"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_system_security_options_menu"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu (loop for menu update after selection)
+#
+while :; do
+ dialog_menu_main || f_die
+ f_dialog_menutag_fetch mtag
+
+ 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_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set nfs_reserved_port_only NO' ;;
+ "3 [ ] $msg_nfs_port") # Same; Toggle value
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set nfs_reserved_port_only YES' ;;
+ *)
+ f_die 1 "$msg_unknown_security_menu_selection"
+ esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/share/Makefile b/contrib/bsddialog/bsdconfig/share/Makefile
new file mode 100644
index 000000000000..a09697a29d0d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+SUBDIR= media packages
+
+FILESDIR= ${SHAREDIR}/bsdconfig
+FILES= common.subr device.subr dialog.subr geom.subr keymap.subr \
+ mustberoot.subr script.subr strings.subr struct.subr \
+ sysrc.subr variable.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/share/Makefile.depend b/contrib/bsddialog/bsdconfig/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/share/common.subr b/contrib/bsddialog/bsdconfig/share/common.subr
new file mode 100644
index 000000000000..49b9186f548f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/common.subr
@@ -0,0 +1,1046 @@
+if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ CONFIGURATION
+
+#
+# Default file descriptors to link to stdout/stderr for passthru allowing
+# redirection within a sub-shell to bypass directly to the terminal.
+#
+: ${TERMINAL_STDOUT_PASSTHRU:=3}
+: ${TERMINAL_STDERR_PASSTHRU:=4}
+
+############################################################ GLOBALS
+
+#
+# Program name
+#
+pgm="${0##*/}"
+
+#
+# Program arguments
+#
+ARGC="$#"
+ARGV="$@"
+
+#
+# Global exit status variables
+#
+SUCCESS=0
+FAILURE=1
+
+#
+# Operating environment details
+#
+export UNAME_S="$( uname -s )" # Operating System (i.e. FreeBSD)
+export UNAME_P="$( uname -p )" # Processor Architecture (i.e. i386)
+export UNAME_M="$( uname -m )" # Machine platform (i.e. i386)
+export UNAME_R="$( uname -r )" # Release Level (i.e. X.Y-RELEASE)
+
+#
+# Default behavior is to call f_debug_init() automatically when loaded.
+#
+: ${DEBUG_SELF_INITIALIZE=1}
+
+#
+# Default behavior of f_debug_init() is to truncate $debugFile (set to NULL to
+# disable truncating the debug file when initializing). To get child processes
+# to append to the same log file, export this variarable (with a NULL value)
+# and also export debugFile with the desired value.
+#
+: ${DEBUG_INITIALIZE_FILE=1}
+
+#
+# Define standard optstring arguments that should be supported by all programs
+# using this include (unless DEBUG_SELF_INITIALIZE is set to NULL to prevent
+# f_debug_init() from autamatically processing "$@" for the below arguments):
+#
+# d Sets $debug to 1
+# D: Sets $debugFile to $OPTARG
+#
+GETOPTS_STDARGS="dD:"
+
+#
+# The getopts builtin will return 1 either when the end of "$@" or the first
+# invalid flag is reached. This makes it impossible to determine if you've
+# processed all the arguments or simply have hit an invalid flag. In the cases
+# where we want to tolerate invalid flags (f_debug_init() for example), the
+# following variable can be appended to your optstring argument to getopts,
+# preventing it from prematurely returning 1 before the end of the arguments.
+#
+# NOTE: This assumes that all unknown flags are argument-less.
+#
+GETOPTS_ALLFLAGS="abcdefghijklmnopqrstuvwxyz"
+GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}0123456789"
+
+#
+# When we get included, f_debug_init() will fire (unless $DEBUG_SELF_INITIALIZE
+# is set to disable automatic initialization) and process "$@" for a few global
+# options such as `-d' and/or `-D file'. However, if your program takes custom
+# flags that take arguments, this automatic processing may fail unexpectedly.
+#
+# The solution to this problem is to pre-define (before including this file)
+# the following variable (which defaults to NULL) to indicate that there are
+# extra flags that should be considered when performing automatic processing of
+# globally persistent flags.
+#
+: ${GETOPTS_EXTRA:=}
+
+############################################################ FUNCTIONS
+
+# f_dprintf $format [$arguments ...]
+#
+# Sensible debug function. Override in ~/.bsdconfigrc if desired.
+# See /usr/share/examples/bsdconfig/bsdconfigrc for example.
+#
+# If $debug is set and non-NULL, prints DEBUG info using printf(1) syntax:
+# + To $debugFile, if set and non-NULL
+# + To standard output if $debugFile is either NULL or unset
+# + To both if $debugFile begins with a single plus-sign (`+')
+#
+f_dprintf()
+{
+ [ "$debug" ] || return $SUCCESS
+ local fmt="$1"; shift
+ case "$debugFile" in ""|+*)
+ printf "DEBUG: $fmt${fmt:+\n}" "$@" >&${TERMINAL_STDOUT_PASSTHRU:-1}
+ esac
+ [ "${debugFile#+}" ] &&
+ printf "DEBUG: $fmt${fmt:+\n}" "$@" >> "${debugFile#+}"
+ return $SUCCESS
+}
+
+# f_debug_init
+#
+# Initialize debugging. Truncates $debugFile to zero bytes if set.
+#
+f_debug_init()
+{
+ #
+ # Process stored command-line arguments
+ #
+ set -- $ARGV
+ local OPTIND OPTARG flag
+ f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
+ "$ARGV" "$GETOPTS_STDARGS"
+ while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \
+ > /dev/null; do
+ case "$flag" in
+ d) debug=1 ;;
+ D) debugFile="$OPTARG" ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+ f_dprintf "f_debug_init: debug=[%s] debugFile=[%s]" \
+ "$debug" "$debugFile"
+
+ #
+ # Automagically enable debugging if debugFile is set (and non-NULL)
+ #
+ [ "$debugFile" ] && { [ "${debug+set}" ] || debug=1; }
+
+ #
+ # Make debugging persistent if set
+ #
+ [ "$debug" ] && export debug
+ [ "$debugFile" ] && export debugFile
+
+ #
+ # Truncate debug file unless requested otherwise. Note that we will
+ # trim a leading plus (`+') from the value of debugFile to support
+ # persistent meaning that f_dprintf() should print both to standard
+ # output and $debugFile (minus the leading plus, of course).
+ #
+ local _debug_file="${debugFile#+}"
+ if [ "$_debug_file" -a "$DEBUG_INITIALIZE_FILE" ]; then
+ if ( umask 022 && :> "$_debug_file" ); then
+ f_dprintf "Successfully initialized debugFile \`%s'" \
+ "$_debug_file"
+ f_isset debug || debug=1 # turn debugging on if not set
+ else
+ unset debugFile
+ f_dprintf "Unable to initialize debugFile \`%s'" \
+ "$_debug_file"
+ fi
+ fi
+}
+
+# f_err $format [$arguments ...]
+#
+# 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 "$@"
+}
+
+# setvar $var_to_set [$value]
+#
+# Implement setvar for shells unlike FreeBSD sh(1).
+#
+if ! f_have setvar; then
+setvar()
+{
+ [ $# -gt 0 ] || return $SUCCESS
+ local __setvar_var_to_set="$1" __setvar_right="$2" __setvar_left=
+ case $# in
+ 1) unset "$__setvar_var_to_set"
+ return $? ;;
+ 2) : fall through ;;
+ *) f_err "setvar: too many arguments\n"
+ return $FAILURE
+ esac
+ case "$__setvar_var_to_set" in *[!0-9A-Za-z_]*)
+ f_err "setvar: %s: bad variable name\n" "$__setvar_var_to_set"
+ return 2
+ esac
+ while case "$__setvar_r" in *\'*) : ;; *) false ; esac
+ do
+ __setvar_left="$__setvar_left${__setvar_right%%\'*}'\\''"
+ __setvar_right="${__setvar_right#*\'}"
+ done
+ __setvar_left="$__setvar_left${__setvar_right#*\'}"
+ eval "$__setvar_var_to_set='$__setvar_left'"
+}
+fi
+
+# f_which $anything [$var_to_set]
+#
+# A fast built-in replacement for syntaxes such as foo=$( which bar ). In a
+# comparison of 10,000 runs of this function versus which, this function
+# completed in under 3 seconds, while `which' took almost a full minute.
+#
+# If $var_to_set is missing or NULL, output is (like which) to standard out.
+# Returns success if a match was found, failure otherwise.
+#
+f_which()
+{
+ local __name="$1" __var_to_set="$2"
+ case "$__name" in */*|'') return $FAILURE; esac
+ local __p __exec IFS=":" __found=
+ for __p in $PATH; do
+ __exec="$__p/$__name"
+ [ -f "$__exec" -a -x "$__exec" ] && __found=1 break
+ done
+ if [ "$__found" ]; then
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__exec"
+ else
+ echo "$__exec"
+ fi
+ return $SUCCESS
+ fi
+ return $FAILURE
+}
+
+# f_getvar $var_to_get [$var_to_set]
+#
+# Utility function designed to go along with the already-builtin setvar.
+# Allows clean variable name indirection without forking or sub-shells.
+#
+# Returns error status if the requested variable ($var_to_get) is not set.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_getvar()
+{
+ local __var_to_get="$1" __var_to_set="$2"
+ [ "$__var_to_set" ] || local value
+ eval [ \"\${$__var_to_get+set}\" ]
+ local __retval=$?
+ eval ${__var_to_set:-value}=\"\${$__var_to_get}\"
+ eval f_dprintf '"f_getvar: var=[%s] value=[%s] r=%u"' \
+ \"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval
+ [ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; }
+ return $__retval
+}
+
+# f_isset $var
+#
+# Check if variable $var is set. Returns success if variable is set, otherwise
+# returns failure.
+#
+f_isset()
+{
+ eval [ \"\${${1%%[$IFS]*}+set}\" ]
+}
+
+# f_die [$status [$format [$arguments ...]]]
+#
+# 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_info $format [$arguments ...]
+#
+# Display a message in a dialog infobox using printf(1) syntax.
+#
+f_show_info()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ #
+ # Use f_dialog_infobox 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_info; then
+ f_dialog_info "$msg"
+ else
+ dialog --infobox "$msg" 0 0
+ fi
+}
+
+# f_show_msg $format [$arguments ...]
+#
+# 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_show_err $format [$arguments ...]
+#
+# Display a message in a dialog box with ``Error'' i18n title (overridden by
+# setting msg_error) using printf(1) syntax.
+#
+f_show_err()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ : ${msg:=${msg_an_unknown_error_occurred:-An unknown error occurred}}
+
+ if [ "$_DIALOG_SUBR" ]; then
+ f_dialog_title "${msg_error:-Error}"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ dialog --title "${msg_error:-Error}" --msgbox "$msg" 0 0
+ fi
+ return $SUCCESS
+}
+
+# f_yesno $format [$arguments ...]
+#
+# Display a message in a dialog yes/no box using printf(1) syntax.
+#
+f_yesno()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ #
+ # Use f_dialog_yesno 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_yesno; then
+ f_dialog_yesno "$msg"
+ else
+ dialog --yesno "$msg" 0 0
+ fi
+}
+
+# f_noyes $format [$arguments ...]
+#
+# Display a message in a dialog yes/no box using printf(1) syntax.
+# NOTE: THis is just like the f_yesno function except "No" is default.
+#
+f_noyes()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ #
+ # Use f_dialog_noyes 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_noyes; then
+ f_dialog_noyes "$msg"
+ else
+ dialog --defaultno --yesno "$msg" 0 0
+ fi
+}
+
+# f_show_help $file
+#
+# Display a language help-file. Automatically takes $LANG and $LC_ALL into
+# consideration when displaying $file (suffix ".$LC_ALL" or ".$LANG" will
+# automatically be added prior to loading the language help-file).
+#
+# If a language has been requested by setting either $LANG or $LC_ALL in the
+# environment and the language-specific help-file does not exist we will fall
+# back to $file without-suffix.
+#
+# If the language help-file does not exist, an error is displayed instead.
+#
+f_show_help()
+{
+ local file="$1"
+ local lang="${LANG:-$LC_ALL}"
+
+ [ -f "$file.$lang" ] && file="$file.$lang"
+
+ #
+ # Use f_dialog_textbox 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_textbox; then
+ f_dialog_textbox "$file"
+ else
+ dialog --msgbox "$( cat "$file" 2>&1 )" 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"
+ f_dprintf "f_include: file=[%s]" "$file"
+ . "$file" || exit $?
+}
+
+# f_include_lang $file
+#
+# Include a language file. Automatically takes $LANG and $LC_ALL into
+# consideration 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 "f_include_lang: file=[%s] lang=[%s]" "$file" "$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 being 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 "f_usage: file=[%s] lang=[%s]" "$file" "$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_file $keyword [$var_to_set]
+#
+# Process all INDEX files known to bsdconfig and return the path to first file
+# containing a menu_selection line with a keyword portion matching $keyword.
+#
+# If $LANG or $LC_ALL (in order of preference, respectively) is set,
+# "INDEX.encoding" files will be searched first.
+#
+# If no file is found, error status is returned along with the NULL string.
+#
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+# 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_file_awk='
+# Variables that should be defined on the invocation line:
+# -v keyword="keyword"
+BEGIN { found = 0 }
+( $0 ~ "^menu_selection=\"" keyword "\\|" ) {
+ print FILENAME
+ found++
+ exit
+}
+END { exit ! found }
+'
+f_index_file()
+{
+ local __keyword="$1" __var_to_set="$2"
+ local __lang="${LANG:-$LC_ALL}"
+ local __indexes="$BSDCFG_LIBE${BSDCFG_LIBE:+/}*/INDEX"
+
+ f_dprintf "f_index_file: keyword=[%s] lang=[%s]" "$__keyword" "$__lang"
+
+ if [ "$__lang" ]; then
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes.$__lang
+ )"' && return $SUCCESS
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" \
+ $__indexes.$__lang && return $SUCCESS
+ fi
+ # No match, fall-thru to non-i18n sources
+ fi
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes )"' && return $SUCCESS
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" $__indexes &&
+ return $SUCCESS
+ fi
+
+ # No match? Fall-thru to `local' libexec sources (add-on modules)
+
+ [ "$BSDCFG_LOCAL_LIBE" ] || return $FAILURE
+ __indexes="$BSDCFG_LOCAL_LIBE/*/INDEX"
+ if [ "$__lang" ]; then
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes.$__lang
+ )"' && return $SUCCESS
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" \
+ $__indexes.$__lang && return $SUCCESS
+ fi
+ # No match, fall-thru to non-i18n sources
+ fi
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes )"'
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" $__indexes
+ fi
+}
+
+# f_index_menusel_keyword $indexfile $pgm [$var_to_set]
+#
+# Process $indexfile and return only the keyword portion of the menu_selection
+# line with a command portion matching $pgm.
+#
+# This function is for internationalization (i18n) mapping of the on-disk
+# scriptname ($pgm) into the localized language (given language-specific
+# $indexfile). If $LANG or $LC_ALL (in orderder of preference, respectively) is
+# set, ".encoding" will automatically be appended as a suffix to the provided
+# $indexfile pathname.
+#
+# If, within $indexfile, 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 $indexfile does not exist, error status is returned with NULL.
+#
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+# 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_keyword_awk='
+# Variables that should be defined on the invocation line:
+# -v pgm="program_name"
+#
+BEGIN {
+ prefix = "menu_selection=\""
+ plen = length(prefix)
+ found = 0
+}
+{
+ if (!match($0, "^" prefix ".*\\|.*\"")) next
+
+ keyword = command = substr($0, plen + 1, RLENGTH - plen - 1)
+ sub(/^.*\|/, "", command)
+ sub(/\|.*$/, "", keyword)
+
+ if ( command == pgm )
+ {
+ print keyword
+ found++
+ exit
+ }
+}
+END { exit ! found }
+'
+f_index_menusel_keyword()
+{
+ local __indexfile="$1" __pgm="$2" __var_to_set="$3"
+ local __lang="${LANG:-$LC_ALL}" __file="$__indexfile"
+
+ [ -f "$__indexfile.$__lang" ] && __file="$__indexfile.$__lang"
+ f_dprintf "f_index_menusel_keyword: index=[%s] pgm=[%s] lang=[%s]" \
+ "$__file" "$__pgm" "$__lang"
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$( awk \
+ -v pgm="$__pgm" "$f_index_menusel_keyword_awk" "$__file"
+ )"
+ else
+ awk -v pgm="$__pgm" "$f_index_menusel_keyword_awk" "$__file"
+ fi
+}
+
+# f_index_menusel_command $indexfile $keyword [$var_to_set]
+#
+# Process $indexfile and return only the command portion of the menu_selection
+# line with a keyword portion matching $keyword.
+#
+# This function is for mapping [possibly international] keywords into the
+# command to be executed. If $LANG or $LC_ALL (order of preference) is set,
+# ".encoding" will automatically be appended as a suffix to the provided
+# $indexfile pathname.
+#
+# If, within $indexfile, multiple $menu_selection values map to $keyword, only
+# the first one will be returned. If no mapping can be made, the NULL string is
+# returned.
+#
+# If $indexfile doesn't exist, error status is returned with NULL.
+#
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+# 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_command_awk='
+# Variables that should be defined on the invocation line:
+# -v key="keyword"
+#
+BEGIN {
+ prefix = "menu_selection=\""
+ plen = length(prefix)
+ found = 0
+}
+{
+ if (!match($0, "^" prefix ".*\\|.*\"")) next
+
+ keyword = command = substr($0, plen + 1, RLENGTH - plen - 1)
+ sub(/^.*\|/, "", command)
+ sub(/\|.*$/, "", keyword)
+
+ if ( keyword == key )
+ {
+ print command
+ found++
+ exit
+ }
+}
+END { exit ! found }
+'
+f_index_menusel_command()
+{
+ local __indexfile="$1" __keyword="$2" __var_to_set="$3" __command
+ local __lang="${LANG:-$LC_ALL}" __file="$__indexfile"
+
+ [ -f "$__indexfile.$__lang" ] && __file="$__indexfile.$__lang"
+ f_dprintf "f_index_menusel_command: index=[%s] key=[%s] lang=[%s]" \
+ "$__file" "$__keyword" "$__lang"
+
+ [ -f "$__file" ] || return $FAILURE
+ __command=$( awk -v key="$__keyword" \
+ "$f_index_menusel_command_awk" "$__file" ) || return $FAILURE
+
+ #
+ # If the command pathname is not fully qualified fix-up/force to be
+ # relative to the $indexfile directory.
+ #
+ case "$__command" in
+ /*) : already fully qualified ;;
+ *)
+ local __indexdir="${__indexfile%/*}"
+ [ "$__indexdir" != "$__indexfile" ] || __indexdir="."
+ __command="$__indexdir/$__command"
+ esac
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__command"
+ else
+ echo "$__command"
+ fi
+}
+
+# f_running_as_init
+#
+# Returns true if running as init(1).
+#
+f_running_as_init()
+{
+ #
+ # When a custom init(8) performs an exec(3) to invoke a shell script,
+ # PID 1 becomes sh(1) and $PPID is set to 1 in the executed script.
+ #
+ [ ${PPID:-0} -eq 1 ] # Return status
+}
+
+# f_mounted $local_directory
+# f_mounted -b $device
+#
+# Return success if a filesystem is mounted on a particular directory. If `-b'
+# is present, instead check that the block device (or a partition thereof) is
+# mounted.
+#
+f_mounted()
+{
+ local OPTIND OPTARG flag use_device=
+ while getopts b flag; do
+ case "$flag" in
+ b) use_device=1 ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+ if [ "$use_device" ]; then
+ local device="$1"
+ mount | grep -Eq \
+ "^$device([[:space:]]|p[0-9]|s[0-9]|\.nop|\.eli)"
+ else
+ [ -d "$dir" ] || return $FAILURE
+ mount | grep -Eq " on $dir \([^)]+\)$"
+ fi
+ # Return status is that of last grep(1)
+}
+
+# f_eval_catch [-de] [-k $var_to_set] $funcname $utility \
+# $format [$arguments ...]
+#
+# Silently evaluate a command in a sub-shell and test for error. If debugging
+# is enabled a copy of the command and its output is sent to debug (either
+# stdout or file depending on environment). If an error occurs, output of the
+# command is displayed in a dialog(1) msgbox using the [above] f_show_err()
+# function (unless optional `-d' flag is given, then no dialog).
+#
+# The $funcname argument is sent to debugging while the $utility argument is
+# used in the title of the dialog box. The command that is executed as well as
+# sent to debugging with $funcname is the product of the printf(1) syntax
+# produced by $format with optional $arguments.
+#
+# The following options are supported:
+#
+# -d Do not use dialog(1).
+# -e Produce error text from failed command on stderr.
+# -k var Save output from the command in var.
+#
+# Example 1:
+#
+# debug=1
+# f_eval_catch myfunc echo 'echo "%s"' "Hello, World!"
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: echo "Hello, World!"
+# DEBUG: myfunc: retval=0 <output below>
+# Hello, World!
+#
+# Example 2:
+#
+# debug=1
+# f_eval_catch -k contents myfunc cat 'cat "%s"' /some/file
+# # dialog(1) Error ``cat: /some/file: No such file or directory''
+# # contents=[cat: /some/file: No such file or directory]
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: cat "/some/file"
+# DEBUG: myfunc: retval=1 <output below>
+# cat: /some/file: No such file or directory
+#
+# Example 3:
+#
+# debug=1
+# echo 123 | f_eval_catch myfunc rev rev
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: rev
+# DEBUG: myfunc: retval=0 <output below>
+# 321
+#
+# Example 4:
+#
+# debug=1
+# f_eval_catch myfunc true true
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: true
+# DEBUG: myfunc: retval=0 <no output>
+#
+# Example 5:
+#
+# f_eval_catch -de myfunc ls 'ls "%s"' /some/dir
+# # Output on stderr ``ls: /some/dir: No such file or directory''
+#
+# Example 6:
+#
+# f_eval_catch -dek contents myfunc ls 'ls "%s"' /etc
+# # Output from `ls' sent to stderr and also saved in $contents
+#
+f_eval_catch()
+{
+ local __no_dialog= __show_err= __var_to_set=
+
+ #
+ # Process local function arguments
+ #
+ local OPTIND OPTARG __flag
+ while getopts "dek:" __flag > /dev/null; do
+ case "$__flag" in
+ d) __no_dialog=1 ;;
+ e) __show_err=1 ;;
+ k) __var_to_set="$OPTARG" ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ local __funcname="$1" __utility="$2"; shift 2
+ local __cmd __output __retval
+
+ __cmd=$( printf -- "$@" )
+ f_dprintf "%s: %s" "$__funcname" "$__cmd" # Log command *before* eval
+ __output=$( exec 2>&1; eval "$__cmd" )
+ __retval=$?
+ if [ "$__output" ]; then
+ [ "$__show_err" ] && echo "$__output" >&2
+ f_dprintf "%s: retval=%i <output below>\n%s" "$__funcname" \
+ $__retval "$__output"
+ else
+ f_dprintf "%s: retval=%i <no output>" "$__funcname" $__retval
+ fi
+
+ ! [ "$__no_dialog" -o "$nonInteractive" -o $__retval -eq $SUCCESS ] &&
+ msg_error="${msg_error:-Error}${__utility:+: $__utility}" \
+ f_show_err "%s" "$__output"
+ # NB: f_show_err will handle NULL output appropriately
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output"
+
+ return $__retval
+}
+
+# f_count $var_to_set arguments ...
+#
+# Sets $var_to_set to the number of arguments minus one (the effective number
+# of arguments following $var_to_set).
+#
+# Example:
+# f_count count dog house # count=[2]
+#
+f_count()
+{
+ setvar "$1" $(( $# - 1 ))
+}
+
+# f_count_ifs $var_to_set string ...
+#
+# Sets $var_to_set to the number of words (split by the internal field
+# separator, IFS) following $var_to_set.
+#
+# Example 1:
+#
+# string="word1 word2 word3"
+# f_count_ifs count "$string" # count=[3]
+# f_count_ifs count $string # count=[3]
+#
+# Example 2:
+#
+# IFS=. f_count_ifs count www.freebsd.org # count=[3]
+#
+# NB: Make sure to use double-quotes if you are using a custom value for IFS
+# and you don't want the current value to effect the result. See example 3.
+#
+# Example 3:
+#
+# string="a-b c-d"
+# IFS=- f_count_ifs count "$string" # count=[3]
+# IFS=- f_count_ifs count $string # count=[4]
+#
+f_count_ifs()
+{
+ local __var_to_set="$1"
+ shift 1
+ set -- $*
+ setvar "$__var_to_set" $#
+}
+
+############################################################ MAIN
+
+#
+# Trap signals so we can recover gracefully
+#
+trap 'f_interrupt' INT
+trap 'f_die' TERM PIPE XCPU XFSZ FPE TRAP ABRT SEGV
+trap '' ALRM PROF USR1 USR2 HUP VTALRM
+
+#
+# Clone terminal stdout/stderr so we can redirect to it from within sub-shells
+#
+eval exec $TERMINAL_STDOUT_PASSTHRU\>\&1
+eval exec $TERMINAL_STDERR_PASSTHRU\>\&2
+
+#
+# Self-initialize unless requested otherwise
+#
+f_dprintf "%s: DEBUG_SELF_INITIALIZE=[%s]" \
+ dialog.subr "$DEBUG_SELF_INITIALIZE"
+case "$DEBUG_SELF_INITIALIZE" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_debug_init
+esac
+
+#
+# Log our operating environment for debugging purposes
+#
+f_dprintf "UNAME_S=[%s] UNAME_P=[%s] UNAME_R=[%s]" \
+ "$UNAME_S" "$UNAME_P" "$UNAME_R"
+
+f_dprintf "%s: Successfully loaded." common.subr
+
+fi # ! $_COMMON_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/device.subr b/contrib/bsddialog/bsdconfig/share/device.subr
new file mode 100644
index 000000000000..97e878424703
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/device.subr
@@ -0,0 +1,1393 @@
+if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
+#
+# Copyright (c) 2012-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/geom.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+NDEVICES=0 # Set by f_device_register(), used by f_device_*()
+
+#
+# A "device" from legacy sysinstall's point of view (mostly)
+#
+# NB: Disk devices have their `private' property set to GEOM ident
+# NB: USB devices have their `private' property set to USB disk device name
+#
+f_struct_define DEVICE \
+ capacity \
+ desc \
+ devname \
+ enabled \
+ flags \
+ get \
+ init \
+ name \
+ private \
+ shutdown \
+ type \
+ volume
+
+# Network devices have their `private' property set to this
+f_struct_define DEVICE_INFO \
+ extras \
+ ipaddr \
+ ipv6addr \
+ netmask \
+ use_dhcp \
+ use_rtsol
+
+#
+# Device types for f_device_register(), f_device_find(), et al.
+#
+setvar DEVICE_TYPE_ANY "any" # Any
+setvar DEVICE_TYPE_NONE "NONE" # Unknown
+setvar DEVICE_TYPE_DISK "DISK" # GEOM `DISK'
+setvar DEVICE_TYPE_FLOPPY "FD" # GEOM `FD'
+setvar DEVICE_TYPE_FTP "FTP" # Dynamic network device
+setvar DEVICE_TYPE_NETWORK "NETWORK" # See f_device_get_all_network
+setvar DEVICE_TYPE_CDROM "CDROM" # GEOM `DISK'
+setvar DEVICE_TYPE_USB "USB" # GEOM `PART'
+setvar DEVICE_TYPE_DOS "DOS" # GEOM `DISK' `PART' or `LABEL'
+setvar DEVICE_TYPE_UFS "UFS" # GEOM `DISK' `PART' or `LABEL'
+setvar DEVICE_TYPE_NFS "NFS" # Dynamic network device
+setvar DEVICE_TYPE_HTTP_PROXY "HTTP_PROXY" # Dynamic network device
+setvar DEVICE_TYPE_HTTP "HTTP" # Dynamic network device
+
+# Network devices have the following flags available
+setvar IF_ETHERNET 1
+setvar IF_WIRELESS 2
+setvar IF_ACTIVE 4
+
+#
+# Default behavior is to call f_device_get_all() automatically when loaded.
+#
+: ${DEVICE_SELF_SCAN_ALL=1}
+
+#
+# Device Catalog variables
+#
+DEVICE_CATALOG_APPEND_ONLY= # Used by f_device_catalog_set()
+NCATALOG_DEVICES=0 # Used by f_device_catalog_*() and MAIN
+
+#
+# A ``catalog'' device is for mapping GEOM devices to media devices (for
+# example, determining if a $GEOM_CLASS_DISK geom is $DEVICE_TYPE_CDROM or
+# $DEVICE_TYPE_DISK) and also getting default descriptions for devices that
+# either lack a GEOM provided description or lack a presence in GEOM)
+#
+f_struct_define CATALOG_DEVICE \
+ desc \
+ name \
+ type
+
+############################################################ FUNCTIONS
+
+# f_device_register $var_to_set $name $desc $devname $type $enabled
+# $init_function $get_function $shutdown_function
+# $private $capacity
+#
+# Register a device. A `structure' (see struct.subr) is created and if
+# $var_to_set is non-NULL, upon success holds the name of the struct created.
+# The remaining positional arguments correspond to the properties of the
+# `DEVICE' structure-type to be assigned (defined above).
+#
+# If not already registered (based on $name and $type), a new device is created
+# and $NDEVICES is incremented.
+#
+f_device_register()
+{
+ local __var_to_set="$1" __name="$2" __desc="$3" __devname="$4"
+ local __type="$5" __enabled="$6" __init_func="$7" __get_func="$8"
+ local __shutdown_func="$9" __private="${10}" __capacity="${11}"
+
+ # Required parameter(s)
+ [ "$__name" ] || return $FAILURE
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "" || return $FAILURE
+ fi
+
+ local __device
+ if f_device_find -1 "$__name" "$__type" __device; then
+ f_struct_free "$__device"
+ f_struct_new DEVICE "$__device" || return $FAILURE
+ else
+ __device=device_$(( NDEVICES + 1 ))
+ f_struct_new DEVICE "$__device" || return $FAILURE
+ NDEVICES=$(( $NDEVICES + 1 ))
+ fi
+ $__device set name "$__name"
+ $__device set desc "$__desc"
+ $__device set devname "$__devname"
+ $__device set type "$__type"
+ $__device set enabled "$__enabled"
+ $__device set init "$__init_func"
+ $__device set get "$__get_func"
+ $__device set shutdown "$__shutdown_func"
+ $__device set private "$__private"
+ $__device set capacity "$__capacity"
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" "$__device"
+ return $SUCCESS
+}
+
+# f_device_reset
+#
+# Reset the registered device chain.
+#
+f_device_reset()
+{
+ local n=1
+ while [ $n -le $NDEVICES ]; do
+ f_device_shutdown device_$n
+
+ #
+ # XXX This potentially leaks $dev->private if it's being
+ # used to point to something dynamic, but you're not supposed
+ # to call this routine at such times that some open instance
+ # has its private member pointing somewhere anyway.
+ #
+ f_struct_free device_$n
+
+ n=$(( $n + 1 ))
+ done
+ NDEVICES=0
+}
+
+# f_device_reset_network
+#
+# Reset the registered network device chain.
+#
+f_device_reset_network()
+{
+ local n=1 device type private i
+ while [ $n -le $NDEVICES ]; do
+ device=device_$n
+ f_struct $device || continue
+ $device get type type
+ [ "$type" = "$DEVICE_TYPE_NETWORK" ] || continue
+
+ #
+ # Leave the device up (don't call shutdown routine)
+ #
+
+ # Network devices may have DEVICE_INFO private member
+ $device get private private
+ [ "$private" ] && f_struct_free "$private"
+
+ # Free the network device
+ f_struct_free $device
+
+ # Fill the gap we just created
+ i=$n
+ while [ $i -lt $NDEVICES ]; do
+ f_struct_copy device_$(( $i + 1 )) device_$i
+ done
+ f_struct_free device_$NDEVICES
+
+ # Finally decrement the number of devices
+ NDEVICES=$(( $NDEVICES - 1 ))
+
+ n=$(( $n + 1 ))
+ done
+}
+
+# f_device_get_all
+#
+# Get all device information for all devices.
+#
+f_device_get_all()
+{
+ local devname type desc capacity
+
+ f_dprintf "f_device_get_all: Probing devices..."
+ f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
+
+ # First go for the network interfaces
+ f_device_get_all_network
+
+ # Next, go for the GEOM devices we might want to use as media
+ local geom geoms geom_name
+ debug= f_geom_find "" $GEOM_CLASS_DEV geoms
+ for geom in $geoms; do
+ if ! f_device_probe_geom $geom; then
+ debug= $geom get name geom_name
+ f_dprintf "WARNING! Unable to classify %s as %s" \
+ "GEOM device $geom_name" "media source"
+ fi
+ done
+}
+
+# f_device_get_all_network
+#
+# Get all network device information for attached network devices.
+#
+f_device_get_all_network()
+{
+ local devname desc device flags
+ for devname in $( ifconfig -l ); do
+ # Eliminate network devices that don't make sense
+ case "$devname" in
+ lo*) continue ;;
+ esac
+
+ # Try and find its description
+ f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
+
+ f_dprintf "Found network device named %s" "$devname"
+ debug= f_device_register device $devname "$desc" \
+ "$devname" $DEVICE_TYPE_NETWORK 1 \
+ f_media_init_network "" f_media_shutdown_network "" -1
+
+ # Set flags based on media and status
+ flags=0
+ eval "$( ifconfig $devname 2> /dev/null | awk -v var=flags '
+ function _or(var, mask) {
+ printf "%s=$(( $%s | $%s ))\n", var, var, mask
+ }
+ BEGIN { S = "[[:space:]]+" }
+ {
+ if (!match($0, "^" S "(media|status):" S)) next
+ value = substr($0, RLENGTH + 1)
+ if ($1 == "media:") {
+ if (value ~ /Ethernet/) _or(var, "IF_ETHERNET")
+ if (value ~ /802\.11/) _or(var, "IF_WIRELESS")
+ } else if ($1 == "status:") {
+ if (value ~ /^active/) _or(var, "IF_ACTIVE")
+ }
+ }' )"
+ $device set flags $flags
+ done
+}
+
+# f_device_rescan
+#
+# Rescan all devices, after closing previous set - convenience function.
+#
+f_device_rescan()
+{
+ f_device_reset
+ f_geom_rescan
+ f_device_get_all
+}
+
+# f_device_rescan_network
+#
+# Rescan all network devices, after closing previous set - for convenience.
+#
+f_device_rescan_network()
+{
+ f_device_reset_network
+ f_device_get_all_network
+}
+
+# f_device_probe_geom $geom
+#
+# Probe a single GEOM device and if it can be classified as a media source,
+# register it using f_device_register() with known type-specific arguments.
+#
+f_device_probe_geom()
+{
+ local geom="$1"
+
+ f_struct "$geom" || return $FAILURE
+
+ # geom associated variables
+ local geom_name geom_consumer provider_ref geom_provider=
+ local provider_geom provider_config provider_class=
+ local provider_config_type catalog_struct catalog_type
+ local disk_ident
+
+ # gnop(8)/geli(8) associated variables (p for `parent device')
+ local p_devname p_geom p_consumer p_provider_ref p_provider
+ local p_provider_config p_provider_geom p_provider_class
+
+ # md(4) associated variables
+ local config config_type config_file magic=
+
+ # Temporarily disable debugging to keep debug output light
+ local old_debug="$debug" debug=
+
+ #
+ # Get the GEOM name (for use below in device registration)
+ #
+ $geom get name devname || continue
+
+ #
+ # Attempt to get the consumer, provider, provider config, and
+ # provider class for this geom (errors ignored).
+ #
+ # NB: Each GEOM in the `DEV' class should have one consumer.
+ # That consumer should have a reference to its provider.
+ #
+ $geom get consumer1 geom_consumer
+ f_struct "$geom_consumer" get provider_ref provider_ref &&
+ f_geom_find_by id "$provider_ref" provider geom_provider
+ if f_struct "$geom_provider"; then
+ $geom_provider get config provider_config
+ f_geom_parent $geom_provider provider_geom &&
+ f_geom_parent $provider_geom provider_class
+ fi
+
+ #
+ # Get values for device registration (errors ignored)
+ #
+ f_struct "$provider_class" get name type
+ f_struct "$geom_provider" get mediasize capacity
+ f_struct "$provider_config" get descr desc
+
+ #
+ # For gnop(8), geli(8), or combination thereof, change device type to
+ # that of the consumer
+ #
+ p_devname= p_geom= p_provider= p_provider_config=
+ case "$devname" in
+ *.nop.eli) p_devname="${devname%.nop.eli}" ;;
+ *.eli.nop) p_devname="${devname%.eli.nop}" ;;
+ *.eli) p_devname="${devname%.eli}" ;;
+ *.nop) p_devname="${devname%.nop}" ;;
+ esac
+ [ "$p_devname" ] && f_geom_find "$p_devname" $GEOM_CLASS_DEV p_geom
+ if [ "${p_geom:-$geom}" != "$geom" ]; then
+ f_struct "$p_geom" get consumer1 p_consumer
+ f_struct "$p_consumer" get provider_ref p_provider_ref &&
+ f_geom_find_by id "$p_provider_ref" provider p_provider
+ if f_struct "$p_provider"; then
+ $p_provider get config p_provider_config
+ f_geom_parent $p_provider p_provider_geom &&
+ f_geom_parent $p_provider_geom p_provider_class
+ fi
+ f_struct "$p_provider_class" get name type
+ fi
+
+ # Look up geom device in device catalog for default description
+ f_device_catalog_get \
+ $DEVICE_TYPE_ANY "${p_devname:-$devname}" catalog_struct
+ [ "$desc" ] || f_struct "catalog_device_$catalog_struct" get desc desc
+
+ # Use device catalog entry for potential re-classification(s)
+ f_struct "catalog_device_$catalog_struct" get type catalog_type
+
+ # Restore debugging for this next part (device registration)
+ debug="$old_debug"
+
+ #
+ # Register the device
+ #
+ local retval device
+ case "$type" in
+ $GEOM_CLASS_DISK)
+ # First attempt to classify by device catalog (see MAIN)
+ case "$catalog_type" in
+ $DEVICE_TYPE_CDROM)
+ f_dprintf "Found CDROM device for disk %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$capacity" &&
+ return $SUCCESS
+ ;;
+ esac
+
+ # Fall back to register label device as a disk and taste it
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_struct "$p_provider_config" get \
+ ident disk_ident ||
+ debug= f_struct "$provider_config" get \
+ ident disk_ident
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "$disk_ident" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems (errors ignored)
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS
+
+ return $retval
+ ;;
+ $GEOM_CLASS_FD)
+ f_dprintf "Found floppy device named %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_FLOPPY 1 \
+ f_media_init_floppy f_media_get_floppy \
+ f_media_shutdown_floppy "" "$capacity"
+ return $?
+ ;;
+ $GEOM_CLASS_LABEL)
+ : fall through to below section # reduces indentation level
+ ;;
+ $GEOM_CLASS_MD)
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ #
+ # Attempt to get file(1) magic to potentially classify as
+ # alternate media type. If unable to get magic, fall back to
+ # md(4) characteristics (such as vnode filename).
+ #
+ [ -r "/dev/$devname" ] &&
+ magic=$( file -bs "/dev/$devname" 2> /dev/null )
+ if [ ! "$magic" ]; then
+ # Fall back to md(4) characteristics
+ if f_struct "$p_provider_config"; then
+ config="$p_provider_config"
+ else
+ config="$provider_config"
+ fi
+ debug= f_struct "$config" get type config_type
+ debug= f_struct "$config" get file config_file
+
+ # Substitute magic for below based on type and file
+ case "$config_type=$config_file" in
+ vnode=*.iso) magic="ISO 9660" ;;
+ esac
+ fi
+ f_device_probe_disk_fs device \
+ "$devname" "$capacity" "$magic" &&
+ retval=$SUCCESS # Errors ignored
+
+ return $retval
+ ;;
+ $GEOM_CLASS_PART)
+ if f_struct "$p_provider_config"; then
+ config="$p_provider_config"
+ else
+ config="$provider_config"
+ fi
+ debug= f_struct "$config" get type provider_config_type
+ f_device_probe_geom_part device \
+ "$provider_config_type" "$devname" "$capacity"
+ retval=$?
+ device_type=$DEVICE_TYPE_NONE
+ [ $retval -eq $SUCCESS ] &&
+ debug= f_struct "$device" get type device_type
+
+ # Potentially re-classify as USB device
+ if [ "$device_type" = "$DEVICE_TYPE_UFS" -a \
+ "$catalog_type" = "$DEVICE_TYPE_USB" ]
+ then
+ f_dprintf "Found USB device for partition %s" \
+ "$devname"
+ debug= f_struct "$p_provider_geom" get \
+ name disk_name ||
+ debug= f_struct "$provider_geom" get \
+ name disk_name
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_USB 1 \
+ f_media_init_usb f_media_get_usb \
+ f_media_shutdown_usb "$disk_name" "$capacity"
+ retval=$?
+ fi
+
+ return $retval
+ ;;
+ $GEOM_CLASS_RAID)
+ # Use the provider geom name as the description
+ if [ ! "$desc" ]; then
+ f_struct "$p_provider_geom" get name desc ||
+ f_struct "$provider_geom" get name desc
+ fi
+
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "${desc:-GEOM RAID device}" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS # Errors ignored
+
+ return $retval
+ ;;
+ $GEOM_CLASS_ZFS_ZVOL)
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "${desc:-GEOM ZFS::ZVOL device}" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS # Errors ignored
+
+ return $retval
+ ;;
+ *)
+ return $FAILURE # Unknown GEOM class
+ esac
+
+ #
+ # Still here? Must be $GEOM_CLASS_LABEL
+ #
+
+ local label_geom label_devname label_devgeom= label_devconsumer
+ local label_devprovider= label_devprovider_ref label_devprovider_config
+ local label_gpart_type
+
+ if f_struct "$p_provider"; then
+ label_geom="$p_provider_geom"
+ else
+ label_geom="$provider_geom"
+ fi
+
+ case "$devname" in
+ gpt/*|gptid/*)
+ #
+ # Attempt to get the partition type by getting the `config'
+ # member of the provider for our device (which is named in the
+ # parent geom of our current provider).
+ #
+ debug= f_struct "$label_geom" get name label_devname &&
+ debug= f_geom_find "$label_devname" $GEOM_CLASS_DEV \
+ label_devgeom
+ debug= f_struct "$label_devgeom" get \
+ consumer1 label_devconsumer
+ debug= f_struct "$label_devconsumer" get \
+ provider_ref label_devprovider_ref &&
+ debug= f_geom_find_by id "$label_devprovider_ref" \
+ provider label_devprovider
+ debug= f_struct "$label_devprovider" get \
+ config label_devprovider_config
+ debug= f_struct "$label_devprovider_config" get \
+ type label_gpart_type
+
+ #
+ # Register device label based on partition type
+ #
+ f_device_probe_geom_part device \
+ "$label_gpart_type" "$devname" "$capacity"
+ return $?
+ ;;
+ iso9660/*)
+ f_dprintf "Found CDROM device labeled %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "ISO9660 file system" \
+ "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$capacity"
+ return $?
+ ;;
+ label/*)
+ # For generic labels, use provider geom name as real device
+ debug= f_struct "$label_geom" get name label_devname
+
+ # Look up label geom device in device catalog for default desc
+ debug= f_device_catalog_get \
+ $DEVICE_TYPE_ANY "$label_devname" catalog_struct
+ [ "$desc" ] || debug= f_struct \
+ "catalog_device_$catalog_struct" get desc desc
+
+ # Use device catalog entry for potential re-classification(s)
+ debug= f_struct "catalog_device_$catalog_struct" get \
+ type catalog_type
+
+ # First attempt to classify by device catalog (see MAIN)
+ case "$catalog_type" in
+ $DEVICE_TYPE_CDROM)
+ f_dprintf "Found CDROM device for disk %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$capacity" &&
+ return $SUCCESS
+ ;;
+ esac
+
+ # Fall back to register label device as a disk and taste it
+ f_dprintf "Found disk device labeled %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "GEOM LABEL device" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems (errors ignored)
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS
+
+ return $retval
+ ;;
+ msdosfs/*)
+ f_dprintf "Found DOS partition labeled %s" "$devname"
+ debug= f_device_register device "$devname" "DOS file system" \
+ "/dev/$devname" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos "" "$capacity"
+ return $?
+ ;;
+ ufs/*|ufsid/*)
+ f_dprintf "Found UFS partition labeled %s" "$devname"
+ debug= f_device_register device "$devname" "UFS file system" \
+ "/dev/$devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$capacity"
+ return $?
+ ;;
+ ext2fs/*|ntfs/*|reiserfs/*)
+ return $FAILURE # No media device handlers for these labels
+ ;;
+ esac
+
+ # Unable to classify GEOM label
+ return $FAILURE
+}
+
+# f_device_probe_geom_part $var_to_set $gpart_type $devname $capacity [$magic]
+#
+# Given a gpart(8) partition type and a device name, register the device if it
+# is a known partition type that we can handle. If $var_to_set is non-NULL,
+# upon success holds the DEVICE struct name of the registered device.
+#
+# Returns success if the device was successfully registered, failure otherwise.
+#
+f_device_probe_geom_part()
+{
+ local __var_to_set="$1" __gpart_type="$2" __devname="$3"
+ local __capacity="${4:--1}" __magic="$5"
+
+ #
+ # Register device based on partition type
+ # NB: !0 equates to `unused' bsdlabel
+ #
+ case "$__gpart_type" in
+ fat16|fat32)
+ f_dprintf "Found DOS partition named %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "DOS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos "" "$__capacity"
+ return $?
+ ;;
+ freebsd|!0) # Commonly used inappropriately, taste for FreeBSD
+ [ -r "/dev/$__devname" -a ! "$__magic" ] &&
+ __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
+ case "$__magic" in
+ *"Unix Fast File system"*)
+ f_dprintf "Found UFS partition named %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "UFS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$__capacity"
+ return $?
+ esac
+ return $FAILURE
+ ;;
+ freebsd-ufs)
+ f_dprintf "Found UFS partition named %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "UFS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$__capacity"
+ return $?
+ ;;
+ apple-*|linux-*|ms-*|netbsd-*|ntfs|vmware-*)
+ return $FAILURE # No device types for these
+ ;;
+ bios-*|ebr|efi|mbr|freebsd-boot|freebsd-swap)
+ return $FAILURE # Not a source for media
+ ;;
+ freebsd-nandfs|freebsd-vinum|freebsd-zfs)
+ return $FAILURE # Unsupported as media source
+ ;;
+ esac
+
+ return $FAILURE # Unknown partition type
+}
+
+# f_device_probe_disk_fs $var_to_set $devname [$capacity [$magic]]
+#
+# Given a device name, taste it and register the device if it is a so-called
+# ``dangerously dedicated'' file system written without a partition table.
+# Tasting is done using file(1) (specifically `file -bs') but if $magic is
+# present and non-NULL it is used instead. If $var_to_set is non-NULL, upon
+# success holds the DEVICE struct name of the registered device.
+#
+# Returns success if the device was successfully registered, failure otherwise.
+#
+f_device_probe_disk_fs()
+{
+ local __var_to_set="$1" __devname="$2" __capacity="${3:--1}"
+ local __magic="$4"
+
+ [ -r "/dev/${__devname#/dev/}" -a ! "$__magic" ] &&
+ __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
+
+ case "$__magic" in
+ *"ISO 9660"*)
+ f_dprintf "Found CDROM device for disk %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "ISO9660 file system" \
+ "/dev/$__devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$__capacity"
+ return $?
+ ;;
+ *"Unix Fast File system"*)
+ f_dprintf "Found UFS device for disk %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "UFS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$__capacity"
+ return $?
+ ;;
+ *"FAT (12 bit)"*|*"FAT (16 bit)"*|*"FAT (32 bit)"*)
+ f_dprintf "Found DOS device for disk %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "DOS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos "" "$__capacity"
+ return $?
+ ;;
+ esac
+
+ return $FAILURE # Unknown file system type
+}
+
+# f_device_catalog_get $type $name [$var_to_set]
+#
+# Fetch the struct name of the catalog device matching device $name. If $type
+# is either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
+# Returns success if a match was found, otherwise failure.
+#
+# If $var_to_set is missing or NULL, the struct name is printed to standard out
+# for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example, when called in a loop).
+#
+f_device_catalog_get()
+{
+ local __type="$1" __name="$2" __var_to_set="$3"
+ local __dname=
+
+ # Return failure if no $name
+ [ "$__name" ] || return $FAILURE
+
+ # Disable debugging to keep debug output light
+ local debug=
+
+ #
+ # Attempt to create an alternate-form of $__name that contains the
+ # first contiguous string of numbers replaced with `%d' for comparison
+ # against stored pattern names (see MAIN).
+ #
+ local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}"
+ if [ "$__left" != "$__name" ]; then
+ # Chop leading digits from right 'til we hit first non-digit
+ while :; do
+ case "$__right" in
+ [0-9]*) __right="${__right#[0-9]}" ;;
+ *) break
+ esac
+ done
+ __dname="${__left}%d$__right"
+ fi
+
+ [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
+ local __dev __dev_name __dev_type
+ for __dev in $DEVICE_CATALOG; do
+ catalog_device_$__dev get name __dev_name
+ [ "$__dev_name" = "$__name" -o "$__dev_name" = "$__dname" ] ||
+ continue
+ catalog_device_$__dev get type __dev_type
+ [ "${__type:-$__dev_type}" = "$__dev_type" ] || continue
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__dev
+ else
+ echo $__dev
+ fi
+ return $?
+ done
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return $FAILURE
+}
+
+# f_device_catalog_set $type $name $desc
+#
+# Store a description (desc) in-association with device $type and $name.
+# Returns success unless $name is NULL or missing. Use f_device_catalog_get()
+# routine with the same $name and optionally $type to retrieve catalog device
+# structure (see CATALOG_DEVICE struct definition in GLOBALS section).
+#
+f_device_catalog_set()
+{
+ local type="$1" name="$2" desc="$3"
+ local struct dev dev_type found=
+
+ [ "$name" ] || return $FAILURE
+
+ # Disable debugging to keep debug output light
+ local debug=
+
+ f_str2varname "$name" struct
+ if [ ! "$DEVICE_CATALOG_APPEND_ONLY" ]; then
+ for dev in $DEVICE_CATALOG; do
+ [ "$dev" = "$struct" ] || continue
+ found=1 break
+ done
+ fi
+ if [ "$found" ]; then
+ f_struct_free "catalog_device_$struct"
+ else
+ DEVICE_CATALOG="$DEVICE_CATALOG $struct"
+ fi
+ f_struct_new CATALOG_DEVICE "catalog_device_$struct" || return $FAILURE
+ catalog_device_$struct set type "$type"
+ catalog_device_$struct set name "$name"
+ catalog_device_$struct set desc "$desc"
+ return $SUCCESS
+}
+
+# f_device_desc $device_name $device_type [$var_to_set]
+#
+# Print a description for a device name (eg., `fxp0') given a specific device
+# type/class.
+#
+# If $var_to_set is missing or NULL, the device description is printed to
+# standard out for capturing in a sub-shell (which is less-recommended because
+# of performance degredation; for example, when called in a loop).
+#
+f_device_desc()
+{
+ local __name="$1" __type="$2" __var_to_set="$3"
+ local __devname __devunit __cp
+
+ # Check variables
+ [ "$__name" ] || return $SUCCESS
+ [ "$__type" = "$DEVICE_TYPE_ANY" ] && type=
+ [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; }
+
+ #
+ # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, otherwise fall
+ # through to further alternate methods.
+ #
+ if f_have sysctl; then
+ __devname="${__name%%[0-9]*}"
+ __devunit="${__name#$__devname}"
+ __devunit="${__devunit%%[!0-9]*}"
+ if [ "$__var_to_set" ]; then
+ if __cp=$(
+ sysctl -n "dev.$__devname.$__devunit.%desc" \
+ 2> /dev/null
+ ); then
+ setvar "$__var_to_set" "$__cp" &&
+ return $SUCCESS
+ fi
+ else
+ sysctl -n "dev.$__devname.$__devunit.%desc" \
+ 2> /dev/null && return $SUCCESS
+ fi
+ fi
+
+ # Look up device in catalog for default description
+ local __catalog_struct
+ debug= f_device_catalog_get "$__type" "$__name" __catalog_struct
+ debug= f_struct "catalog_device_$__catalog_struct" get \
+ desc "$__var_to_set" && return $SUCCESS
+
+ #
+ # Sensible fall-backs for specific types
+ #
+ case "$__type" in
+ $DEVICE_TYPE_CDROM) __cp="<unknown cdrom device type>" ;;
+ $DEVICE_TYPE_DISK) __cp="<unknown disk device type>" ;;
+ $DEVICE_TYPE_FLOPPY) __cp="<unknown floppy device type>" ;;
+ $DEVICE_TYPE_USB) __cp="<unknown USB storage device type>" ;;
+ $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>" ;;
+ *)
+ __cp="<unknown device type>"
+ esac
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__cp"
+ else
+ echo "$__cp"
+ fi
+
+ return $FAILURE
+}
+
+# f_device_is_ethernet $device
+#
+# Returns true if $device is a wired Ethernet network interface. Otherwise
+# returns false. Example wired interfaces include: fxp0 em0 bge0 rl0 etc.
+#
+f_device_is_ethernet()
+{
+ local dev="$1" type flags
+
+ # Make sure we have an actual device by that name
+ f_struct "$dev" || return $FAILURE
+
+ # Make sure that the device is a network device
+ $dev get type type
+ [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
+
+ # Make sure that the media flags indicate that it is Ethernet
+ $dev get flags flags
+ [ $(( ${flags:-0} & $IF_ETHERNET )) -eq $IF_ETHERNET ]
+}
+
+# f_device_is_wireless $device
+#
+# Returns true if $device is a Wireless network interface. Otherwise returns
+# false. Examples of wireless interfaces include: iwn0
+#
+f_device_is_wireless()
+{
+ local dev="$1" type flags
+
+ # Make sure we have an actual device by that name
+ f_struct "$dev" || return $FAILURE
+
+ # Make sure that the device is a network device
+ $dev get type type
+ [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
+
+ # Make sure that the media flags indicate that it is 802.11 wireless
+ $dev get flags flags
+ [ $(( ${flags:-0} & $IF_WIRELESS )) -eq $IF_WIRELESS ]
+}
+
+# f_device_is_active $device
+#
+# Returns true if $device is active. Otherwise returns false. Currently this
+# only works for network interfaces.
+#
+f_device_is_active()
+{
+ local dev="$1" type flags=0
+
+ # Make sure we have an actual device by that name
+ f_struct "$dev" || return $FAILURE
+
+ $dev get type type
+ case "$type" in
+ $DEVICE_TYPE_NETWORK)
+ # Make sure that the media flags indicate that it is active
+ $dev get flags flags
+ [ $(( ${flags:-0} & $IF_ACTIVE )) -eq $IF_ACTIVE ]
+ ;;
+ *)
+ return $FAILURE
+ esac
+}
+
+# f_device_find [-1] $name [$type [$var_to_set]]
+#
+# Find one or more registered devices by name, type, or both. Returns a space-
+# separated list of devices matching the search criterion.
+#
+# If `-1' option flag is given, only the first matching device is returned.
+#
+# If $var_to_set is missing or NULL, the device name(s) are printed to standard
+# out for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example, when called in a loop).
+#
+f_device_find()
+{
+ local OPTIND=1 OPTARG flag only_one=
+ while getopts 1 flag; do
+ case "$flag" in
+ 1) only_one=1 ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
+ local __n=1 __devname __devtype __found=
+ while [ $__n -le $NDEVICES ]; do
+ device_$__n get name __devname
+ device_$__n get type __devtype
+ if [ "$__name" = "$__devname" -o ! "$__name" ] &&
+ [ "$__type" = "$DEVICE_TYPE_ANY" -o \
+ "$__type" = "$__devtype" ]
+ then
+ __found="$__found device_$__n"
+ [ "$only_one" ] && break
+ fi
+ __n=$(( $__n + 1 ))
+ done
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "${__found# }"
+ else
+ echo $__found
+ fi
+ [ "$__found" ] # Return status
+}
+
+# f_device_init $device
+#
+# Initialize a device by evaluating its `init' function. The $device argument
+# is a DEVICE struct name.
+#
+f_device_init()
+{
+ local device="$1" init_func
+ f_struct "$device" || return $?
+ $device get init init_func
+ ${init_func:-:} "$device"
+}
+
+# f_device_get $device $file [$probe]
+#
+# Read $file by evaluating the device's `get' function. The file is commonly
+# produced on standard output (but it truly depends on the function called).
+# The $device argument is a DEVICE struct name.
+#
+f_device_get()
+{
+ local device="$1" file="$2" probe="$3" get_func
+ f_struct "$device" || return $?
+ $device get get get_func
+ ${get_func:-:} "$device" "$file" ${3+"$probe"}
+}
+
+# f_device_shutdown $device
+#
+# Shutdown a device by evaluating its `shutdown' function. The $device argument
+# is a DEVICE struct name.
+#
+f_device_shutdown()
+{
+ local device="$1" shutdown_func
+ f_struct "$device" || return $?
+ $device get shutdown shutdown_func
+ ${shutdown_func:-:} "$device"
+}
+
+# f_devices_sort_by $property $var_to_get [$var_to_set]
+#
+# Take list of devices from $var_to_get (separated by whitespace, newline
+# included) and sort them by $property (e.g., `name'). The sorted list of
+# DEVICE struct names is returned on standard output separated by whitespace
+# (newline to be specific) unless $var_to_set is present and non-NULL.
+#
+# 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_device_sort_by_awk='
+# Variables that should be defined on the invocation line:
+# -v prop="property"
+function _asorti(src, dest)
+{
+ k = nitems = 0
+ for (i in src) dest[++nitems] = i
+ for (i = 1; i <= nitems; k = i++) {
+ idx = dest[i]
+ while ((k > 0) && (dest[k] > idx)) {
+ dest[k+1] = dest[k]; k--
+ }
+ dest[k+1] = idx
+ }
+ return nitems
+}
+{
+ split($0, devs, FS)
+ for (d in devs) {
+ name = ENVIRON["_struct_value_" devs[d] "_" prop]
+ devices[name] = devs[d]
+ }
+}
+END {
+ nitems = _asorti(devices, devices_sorted)
+ for (i = 1; i <= nitems; i++) print devices[devices_sorted[i]]
+}
+'
+f_device_sort_by()
+{
+ local __property="${1:-name}" __var_to_get="$2" __var_to_set="$3"
+
+ f_isset "$__var_to_get" || return $FAILURE
+
+ local __dev
+ for __dev in $( f_getvar "$__var_to_get" ); do
+ export _struct_value_${__dev}_$__property
+ done
+
+ local __cp
+ setvar "${__var_to_set:-__cp}" "$(
+ f_getvar "$__var_to_get" |
+ awk -v prop="$__property" "$f_device_sort_by_awk"
+ )"
+ [ "$__var_to_set" ] || echo "$__cp"
+}
+
+# f_device_menu $title $prompt $hline $device_type [$helpfile]
+#
+# Display a menu listing all the devices of a certain type in the system.
+#
+f_device_menu()
+{
+ f_dialog_title "$1"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+
+ local prompt="$2" hline="$3" type="$4" helpfile="$5"
+
+ local devs
+ f_device_find "" "$type" devs || return $DIALOG_CANCEL
+
+ local name desc menu_list=
+ f_device_sort_by name devs devs
+ for dev in $devs; do
+ $dev get name name
+ $dev get desc desc
+ f_shell_escape "$name" name
+ f_shell_escape "$desc" desc
+ menu_list="$menu_list
+ '$name' '$desc'" # END-QUOTE
+ done
+ menu_list="${menu_list#$NL}"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local errexit=
+ case $- in *e*) errexit=1; esac
+ set +e
+
+ local mtag
+ while :; do
+ mtag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ ${helpfile:+ \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ } \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+
+ [ $retval -ne $DIALOG_HELP ] && break
+ # Otherwise, the Help button was pressed
+ f_show_help "$helpfile"
+ # ...then loop back to menu
+ done
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+
+ [ "$errexit" ] && set -e
+
+ if [ $retval -eq $DIALOG_OK ]; then
+ # Clean up the output of [X]dialog(1)
+ f_dialog_data_sanitize mtag
+
+ # Map the user's choice back to a struct name
+ local index device
+ index=$( eval f_dialog_menutag2index \"\$mtag\" $menu_list )
+ device=$( set -- $devs; eval echo \${$index} )
+
+ echo "$device" >&2
+ fi
+
+ return $retval
+}
+
+#
+# Short-hand
+#
+f_cdrom() { f_device_catalog_set $DEVICE_TYPE_CDROM "$1" "$2"; }
+f_disk() { f_device_catalog_set $DEVICE_TYPE_DISK "$1" "$2"; }
+f_floppy() { f_device_catalog_set $DEVICE_TYPE_FLOPPY "$1" "$2"; }
+f_usb() { f_device_catalog_set $DEVICE_TYPE_USB "$1" "$2"; }
+f_network() { f_device_catalog_set $DEVICE_TYPE_NETWORK "$1" "$2"; }
+
+############################################################ MAIN
+
+#
+# The below classifications allow us to re-group the GEOM devices from the
+# `DEV' GEOM class appropriately while providing fall-back descriptions both
+# for making the below code more maintainable and handling the rare case the
+# GEOM device lacks a description.
+#
+
+DEVICE_CATALOG_APPEND_ONLY=1 # Make initial loading faster
+
+# CDROM, Disk, Floppy, and USB devices/names
+f_cdrom "cd%d" "SCSI CDROM drive"
+f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive"
+f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type"
+f_disk "aacd%d" "Adaptec FSA RAID array"
+f_disk "ada%d" "ATA/SATA disk device"
+f_disk "amrd%d" "AMI MegaRAID drive"
+f_disk "da%d" "SCSI disk device"
+f_disk "idad%d" "Compaq RAID array"
+f_disk "ipsd%d" "IBM ServeRAID RAID array"
+f_disk "md%d" "md(4) disk device"
+f_disk "mfid%d" "LSI MegaRAID SAS array"
+f_disk "mlxd%d" "Mylex RAID disk"
+f_disk "twed%d" "3ware ATA RAID array"
+f_disk "vtbd%d" "VirtIO Block Device"
+f_floppy "fd%d" "Floppy Drive unit A"
+f_usb "da%da" "USB Mass Storage Device"
+
+# Network interfaces/names
+f_network "ae%d" "Attansic/Atheros L2 Fast Ethernet"
+f_network "age%d" "Attansic/Atheros L1 Gigabit Ethernet"
+f_network "alc%d" "Atheros AR8131/AR8132 PCIe Ethernet"
+f_network "ale%d" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
+f_network "an%d" "Aironet 4500/4800 802.11 wireless adapter"
+f_network "ath%d" "Atheros IEEE 802.11 wireless adapter"
+f_network "aue%d" "ADMtek USB Ethernet adapter"
+f_network "axe%d" "ASIX Electronics USB Ethernet adapter"
+f_network "bce%d" "Broadcom NetXtreme II Gigabit Ethernet card"
+f_network "bfe%d" "Broadcom BCM440x PCI Ethernet card"
+f_network "bge%d" "Broadcom BCM570x PCI Gigabit Ethernet card"
+f_network "bm%d" "Apple BMAC Built-in Ethernet"
+f_network "bwn%d" "Broadcom BCM43xx IEEE 802.11 wireless adapter"
+f_network "cas%d" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
+f_network "cc3i%d" "SDL HSSI sync serial PCI card"
+f_network "cue%d" "CATC USB Ethernet adapter"
+f_network "cxgb%d" "Chelsio T3 10Gb Ethernet card"
+f_network "dc%d" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
+f_network "de%d" "DEC DE435 PCI NIC or other DC21040-AA based card"
+f_network "disc%d" "Software discard network interface"
+f_network "ed%d" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
+f_network "el%d" "3Com 3C501 Ethernet card"
+f_network "em%d" "Intel(R) PRO/1000 Ethernet card"
+f_network "ep%d" "3Com 3C509 Ethernet card/3C589 PCMCIA"
+f_network "et%d" "Agere ET1310 based PCI Express Gigabit Ethernet card"
+f_network "ex%d" "Intel EtherExpress Pro/10 Ethernet card"
+f_network "fe%d" "Fujitsu MB86960A/MB86965A Ethernet card"
+f_network "fpa%d" "DEC DEFPA PCI FDDI card"
+f_network "fwe%d" "FireWire Ethernet emulation"
+f_network "fwip%d" "IP over FireWire"
+f_network "fxp%d" "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
+f_network "gem%d" "Apple GMAC or Sun ERI/GEM Ethernet adapter"
+f_network "hme%d" "Sun HME (Happy Meal Ethernet) Ethernet adapter"
+f_network "ie%d" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
+f_network "igb%d" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
+f_network "ipw%d" "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
+f_network "iwi%d" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
+f_network "iwn%d" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
+f_network "ix%d" "Intel Etherexpress Ethernet card"
+f_network "ixgbe%d" "Intel(R) PRO/10Gb Ethernet card"
+f_network "jme%d" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
+f_network "kue%d" "Kawasaki LSI USB Ethernet adapter"
+f_network "le%d" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
+f_network "lge%d" "Level 1 LXT1001 Gigabit Ethernet card"
+f_network "lnc%d" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
+f_network "lo%d" "Loop-back (local) network interface"
+f_network "lp%d" "Parallel Port IP (PLIP) peer connection"
+f_network "malo%d" "Marvell Libertas 88W8335 802.11 wireless adapter"
+f_network "msk%d" "Marvell/SysKonnect Yukon II Gigabit Ethernet"
+f_network "mxge%d" "Myricom Myri10GE 10Gb Ethernet card"
+f_network "nfe%d" "NVIDIA nForce MCP Ethernet"
+f_network "ng%d" "Vimage netgraph(4) bridged Ethernet device"
+f_network "nge%d" "NatSemi PCI Gigabit Ethernet card"
+f_network "nve%d" "NVIDIA nForce MCP Ethernet"
+f_network "pcn%d" "AMD Am79c79x PCI Ethernet card"
+f_network "plip%d" "Parallel Port IP (PLIP) peer connection"
+f_network "ral%d" "Ralink Technology IEEE 802.11 wireless adapter"
+f_network "ray%d" "Raytheon Raylink 802.11 wireless adapter"
+f_network "re%d" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
+f_network "rl%d" "RealTek 8129/8139 PCI Ethernet card"
+f_network "rue%d" "RealTek USB Ethernet card"
+f_network "rum%d" "Ralink Technology USB IEEE 802.11 wireless adapter"
+f_network "sf%d" "Adaptec AIC-6915 PCI Ethernet card"
+f_network "sge%d" "Silicon Integrated Systems SiS190/191 Ethernet"
+f_network "sis%d" "SiS 900/SiS 7016 PCI Ethernet card"
+f_network "sk%d" "SysKonnect PCI Gigabit Ethernet card"
+f_network "sn%d" "SMC/Megahertz Ethernet card"
+f_network "snc%d" "SONIC Ethernet card"
+f_network "sr%d" "SDL T1/E1 sync serial PCI card"
+f_network "ste%d" "Sundance ST201 PCI Ethernet card"
+f_network "stge%d" "Sundance/Tamarack TC9021 Gigabit Ethernet"
+f_network "ti%d" "Alteon Networks PCI Gigabit Ethernet card"
+f_network "tl%d" "Texas Instruments ThunderLAN PCI Ethernet card"
+f_network "tx%d" "SMC 9432TX Ethernet card"
+f_network "txp%d" "3Com 3cR990 Ethernet card"
+f_network "uath%d" "Atheros AR5005UG and AR5005UX USB wireless adapter"
+f_network "upgt%d" "Conexant/Intersil PrismGT USB wireless adapter"
+f_network "ural%d" "Ralink Technology RT2500USB 802.11 wireless adapter"
+f_network "urtw%d" "Realtek 8187L USB wireless adapter"
+f_network "vge%d" "VIA VT612x PCI Gigabit Ethernet card"
+f_network "vlan%d" "IEEE 802.1Q VLAN network interface"
+f_network "vr%d" "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
+f_network "vx%d" "3COM 3c590 / 3c595 Ethernet card"
+f_network "wb%d" "Winbond W89C840F PCI Ethernet card"
+f_network "wi%d" "Lucent WaveLAN/IEEE 802.11 wireless adapter"
+f_network "wpi%d" "Intel 3945ABG IEEE 802.11 wireless adapter"
+f_network "wx%d" "Intel Gigabit Ethernet (82452) card"
+f_network "xe%d" "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
+f_network "xl%d" "3COM 3c90x / 3c90xB PCI Ethernet card"
+f_network "zyd%d" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
+
+DEVICE_CATALOG_APPEND_ONLY= # Additional loading modifies existing devices
+
+f_count NCATALOG_DEVICES $DEVICE_CATALOG
+f_dprintf "%s: Initialized device catalog with %u names/descriptions." \
+ device.subr $NCATALOG_DEVICES
+
+#
+# Scan for the above devices unless requeted otherwise
+#
+f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL"
+case "$DEVICE_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_device_get_all
+esac
+
+f_dprintf "%s: Successfully loaded." device.subr
+
+fi # ! $_DEVICE_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/dialog.subr b/contrib/bsddialog/bsdconfig/share/dialog.subr
new file mode 100644
index 000000000000..5b5c8a32984e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/dialog.subr
@@ -0,0 +1,2339 @@
+if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1
+#
+# Copyright (c) 2006-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default file descriptor to link to stdout for dialog(1) passthru allowing
+# execution of dialog from within a sub-shell (so-long as its standard output
+# is explicitly redirected to this file descriptor).
+#
+: ${DIALOG_TERMINAL_PASSTHRU_FD:=${TERMINAL_STDOUT_PASSTHRU:-3}}
+
+############################################################ 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
+
+#
+# Exit codes for [X]dialog(1)
+#
+DIALOG_OK=${SUCCESS:-0}
+DIALOG_CANCEL=${FAILURE:-1}
+DIALOG_HELP=2
+DIALOG_EXTRA=3
+DIALOG_ITEM_HELP=4
+export DIALOG_ERROR=254 # sh(1) can't handle the default of `-1'
+DIALOG_ESC=255
+
+#
+# Default behavior is to call f_dialog_init() automatically when loaded.
+#
+: ${DIALOG_SELF_INITIALIZE=1}
+
+#
+# Default terminal size (used if/when running without a controlling terminal)
+#
+: ${DEFAULT_TERMINAL_SIZE:=24 80}
+
+#
+# Minimum width(s) for various dialog(1) implementations (sensible global
+# default(s) for all widgets of a given variant)
+#
+: ${DIALOG_MIN_WIDTH:=24}
+: ${XDIALOG_MIN_WIDTH:=35}
+
+#
+# When manually sizing Xdialog(1) widgets such as calendar and timebox, you'll
+# need to know the size of the embedded GUI objects because the height passed
+# to Xdialog(1) for these widgets has to be tall enough to accommodate them.
+#
+# These values are helpful when manually sizing with dialog(1) too, but in a
+# different way. dialog(1) does not make you accommodate the custom items in the
+# height (but does for width) -- a height of 3 will display three lines and a
+# full calendar, for example (whereas Xdialog will truncate the calendar if
+# given a height of 3). For dialog(1), use these values for making sure that
+# the height does not exceed max_height (obtained by f_dialog_max_size()).
+#
+DIALOG_CALENDAR_HEIGHT=15
+DIALOG_TIMEBOX_HEIGHT=6
+
+############################################################ GENERIC FUNCTIONS
+
+# f_dialog_data_sanitize $var_to_edit ...
+#
+# When using dialog(1) or Xdialog(1) sometimes unintended warnings or errors
+# are generated from underlying libraries. For example, if $LANG is set to an
+# invalid or unknown locale, the warnings from the Xdialog(1) libraries will
+# clutter the output. This function helps by providing a centralied function
+# that removes spurious warnings from the dialog(1) (or Xdialog(1)) response.
+#
+# Simply pass the name of one or more variables that need to be sanitized.
+# After execution, the variables will hold their newly-sanitized data.
+#
+f_dialog_data_sanitize()
+{
+ if [ "$#" -eq 0 ]; then
+ f_dprintf "%s: called with zero arguments" \
+ f_dialog_response_sanitize
+ return $FAILURE
+ fi
+
+ local __var_to_edit
+ for __var_to_edit in $*; do
+ # Skip warnings and trim leading/trailing whitespace
+ setvar $__var_to_edit "$( f_getvar $__var_to_edit | awk '
+ BEGIN { data = 0 }
+ {
+ if ( ! data )
+ {
+ if ( $0 ~ /^$/ ) next
+ if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next
+ data = 1
+ }
+ print
+ }
+ ' )"
+ done
+}
+
+# f_dialog_line_sanitize $var_to_edit ...
+#
+# When using dialog(1) or Xdialog(1) sometimes unintended warnings or errors
+# are generated from underlying libraries. For example, if $LANG is set to an
+# invalid or unknown locale, the warnings from the Xdialog(1) libraries will
+# clutter the output. This function helps by providing a centralied function
+# that removes spurious warnings from the dialog(1) (or Xdialog(1)) response.
+#
+# Simply pass the name of one or more variables that need to be sanitized.
+# After execution, the variables will hold their newly-sanitized data.
+#
+# This function, unlike f_dialog_data_sanitize(), also removes leading/trailing
+# whitespace from each line.
+#
+f_dialog_line_sanitize()
+{
+ if [ "$#" -eq 0 ]; then
+ f_dprintf "%s: called with zero arguments" \
+ f_dialog_response_sanitize
+ return $FAILURE
+ fi
+
+ local __var_to_edit
+ for __var_to_edit in $*; do
+ # Skip warnings and trim leading/trailing whitespace
+ setvar $__var_to_edit "$( f_getvar $__var_to_edit | awk '
+ BEGIN { data = 0 }
+ {
+ if ( ! data )
+ {
+ if ( $0 ~ /^$/ ) next
+ if ( $0 ~ /^Gdk-WARNING \*\*:/ ) next
+ data = 1
+ }
+ sub(/^[[:space:]]*/, "")
+ sub(/[[:space:]]*$/, "")
+ print
+ }
+ ' )"
+ done
+}
+
+############################################################ TITLE 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 [ "${1+set}" ]; 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 [ "${1+set}" ]; 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_max_size $var_height $var_width
+#
+# Get the maximum height and width for a dialog widget and store the values in
+# $var_height and $var_width (respectively).
+#
+f_dialog_max_size()
+{
+ local funcname=f_dialog_max_size
+ local __var_height="$1" __var_width="$2" __max_size
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+ if [ "$USE_XDIALOG" ]; then
+ __max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
+ else
+ if __max_size=$( $DIALOG --print-maxsize \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ then
+ f_dprintf "$funcname: %s --print-maxsize = [%s]" \
+ "$DIALOG" "$__max_size"
+ # usually "MaxSize: 24, 80"
+ __max_size="${__max_size#*: }"
+ f_replaceall "$__max_size" "," "" __max_size
+ else
+ f_eval_catch -dk __max_size $funcname stty \
+ 'stty size' || __max_size=
+ # usually "24 80"
+ fi
+ : ${__max_size:=$DEFAULT_TERMINAL_SIZE}
+ fi
+ if [ "$__var_height" ]; then
+ local __height="${__max_size%%[$IFS]*}"
+ #
+ # If we're not using Xdialog(1), we should assume that $DIALOG
+ # will render --backtitle behind the widget. In such a case, we
+ # should prevent a widget from obscuring the backtitle (unless
+ # $NO_BACKTITLE is set and non-NULL, allowing a trap-door).
+ #
+ if [ ! "$USE_XDIALOG" ] && [ ! "$NO_BACKTITLE" ]; then
+ #
+ # If use_shadow (in ~/.dialogrc) is OFF, we need to
+ # subtract 4, otherwise 5. However, don't check this
+ # every time, rely on an initialization variable set
+ # by f_dialog_init().
+ #
+ local __adjust=5
+ [ "$NO_SHADOW" ] && __adjust=4
+
+ # Don't adjust height if already too small (allowing
+ # obscured backtitle for small values of __height).
+ [ ${__height:-0} -gt 11 ] &&
+ __height=$(( $__height - $__adjust ))
+ fi
+ setvar "$__var_height" "$__height"
+ fi
+ [ "$__var_width" ] && setvar "$__var_width" "${__max_size##*[$IFS]}"
+}
+
+# f_dialog_size_constrain $var_height $var_width [$min_height [$min_width]]
+#
+# Modify $var_height to be no-less-than $min_height (if given; zero otherwise)
+# and no-greater-than terminal height (or screen height if $USE_XDIALOG is
+# set).
+#
+# Also modify $var_width to be no-less-than $XDIALOG_MIN_WIDTH (or
+# $XDIALOG_MIN_WIDTH if $_USE_XDIALOG is set) and no-greater-than terminal
+# or screen width. The use of $[X]DIALOG_MIN_WIDTH can be overridden by
+# passing $min_width.
+#
+# Return status is success unless one of the passed arguments is invalid
+# or all of the $var_* arguments are either NULL or missing.
+#
+f_dialog_size_constrain()
+{
+ local __var_height="$1" __var_width="$2"
+ local __min_height="$3" __min_width="$4"
+ local __retval=$SUCCESS
+
+ # Return failure unless at least one var_* argument is passed
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ #
+ # Print debug warnings if any given (non-NULL) argument are invalid
+ # NOTE: Don't change the name of $__{var,min,}{height,width}
+ #
+ local __height __width
+ local __arg __cp __fname=f_dialog_size_constrain
+ for __arg in height width; do
+ debug= f_getvar __var_$__arg __cp
+ [ "$__cp" ] || continue
+ if ! debug= f_getvar "$__cp" __$__arg; then
+ f_dprintf "%s: var_%s variable \`%s' not set" \
+ $__fname $__arg "$__cp"
+ __retval=$FAILURE
+ elif ! eval f_isinteger \$__$__arg; then
+ f_dprintf "%s: var_%s variable value not a number" \
+ $__fname $__arg
+ __retval=$FAILURE
+ fi
+ done
+ for __arg in height width; do
+ debug= f_getvar __min_$__arg __cp
+ [ "$__cp" ] || continue
+ f_isinteger "$__cp" && continue
+ f_dprintf "%s: min_%s value not a number" $__fname $__arg
+ __retval=$FAILURE
+ setvar __min_$__arg ""
+ done
+
+ # Obtain maximum height and width values
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __max_height_size_constain __max_width_size_constrain
+ f_dialog_max_size \
+ __max_height_size_constrain __max_width_size_constrain
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ if [ $__height -lt ${__min_height:-0} ]; then
+ setvar "$__var_height" $__min_height
+ elif [ $__height -gt $__max_height_size_constrain ]; then
+ setvar "$__var_height" $__max_height_size_constrain
+ fi
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ if [ "$USE_XDIALOG" ]; then
+ : ${__min_width:=${XDIALOG_MIN_WIDTH:-35}}
+ else
+ : ${__min_width:=${DIALOG_MIN_WIDTH:-24}}
+ fi
+ if [ $__width -lt $__min_width ]; then
+ setvar "$__var_width" $__min_width
+ elif [ $__width -gt $__max_width_size_constrain ]; then
+ setvar "$__var_width" $__max_width_size_constrain
+ fi
+ fi
+
+ if [ "$debug" ]; then
+ # Print final constrained values to debugging
+ [ "$__var_height" ] && f_quietly f_getvar "$__var_height"
+ [ "$__var_width" ] && f_quietly f_getvar "$__var_width"
+ fi
+
+ return $__retval # success if no debug warnings were printed
+}
+
+# f_dialog_menu_constrain $var_height $var_width $var_rows "$prompt" \
+# [$min_height [$min_width [$min_rows]]]
+#
+# Modify $var_height to be no-less-than $min_height (if given; zero otherwise)
+# and no-greater-than terminal height (or screen height if $USE_XDIALOG is
+# set).
+#
+# Also modify $var_width to be no-less-than $XDIALOG_MIN_WIDTH (or
+# $XDIALOG_MIN_WIDTH if $_USE_XDIALOG is set) and no-greater-than terminal
+# or screen width. The use of $[X]DIALOG_MIN_WIDTH can be overridden by
+# passing $min_width.
+#
+# Last, modify $var_rows to be no-less-than $min_rows (if specified; zero
+# otherwise) and no-greater-than (max_height - 8) where max_height is the
+# terminal height (or screen height if $USE_XDIALOG is set). If $prompt is NULL
+# or missing, dialog(1) allows $var_rows to be (max_height - 7), maximizing the
+# number of visible rows.
+#
+# Return status is success unless one of the passed arguments is invalid
+# or all of the $var_* arguments are either NULL or missing.
+#
+f_dialog_menu_constrain()
+{
+ local __var_height="$1" __var_width="$2" __var_rows="$3" __prompt="$4"
+ local __min_height="$5" __min_width="$6" __min_rows="$7"
+
+ # Return failure unless at least one var_* argument is passed
+ [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] ||
+ return $FAILURE
+
+ #
+ # Print debug warnings if any given (non-NULL) argument are invalid
+ # NOTE: Don't change the name of $__{var,min,}{height,width,rows}
+ #
+ local __height_menu_constrain __width_menu_constrain
+ local __rows_menu_constrain
+ local __arg __cp __fname=f_dialog_menu_constrain
+ for __arg in height width rows; do
+ debug= f_getvar __var_$__arg __cp
+ [ "$__cp" ] || continue
+ if ! debug= f_getvar "$__cp" __${__arg}_menu_constrain; then
+ f_dprintf "%s: var_%s variable \`%s' not set" \
+ $__fname $__arg "$__cp"
+ __retval=$FAILURE
+ elif ! eval f_isinteger \$__${__arg}_menu_constrain; then
+ f_dprintf "%s: var_%s variable value not a number" \
+ $__fname $__arg
+ __retval=$FAILURE
+ fi
+ done
+ for __arg in height width rows; do
+ debug= f_getvar __min_$__arg __cp
+ [ "$__cp" ] || continue
+ f_isinteger "$__cp" && continue
+ f_dprintf "%s: min_%s value not a number" $__fname $__arg
+ __retval=$FAILURE
+ setvar __min_$__arg ""
+ done
+
+ # Obtain maximum height and width values
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __max_height_menu_constrain __max_width_menu_constrain
+ f_dialog_max_size \
+ __max_height_menu_constrain __max_width_menu_constrain
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ if [ $__height_menu_constrain -lt ${__min_height:-0} ]; then
+ setvar "$__var_height" $__min_height
+ elif [ $__height_menu_constrain -gt \
+ $__max_height_menu_constrain ]
+ then
+ setvar "$__var_height" $__max_height_menu_constrain
+ fi
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ if [ "$USE_XDIALOG" ]; then
+ : ${__min_width:=${XDIALOG_MIN_WIDTH:-35}}
+ else
+ : ${__min_width:=${DIALOG_MIN_WIDTH:-24}}
+ fi
+ if [ $__width_menu_constrain -lt $__min_width ]; then
+ setvar "$__var_width" $__min_width
+ elif [ $__width_menu_constrain -gt \
+ $__max_width_menu_constrain ]
+ then
+ setvar "$__var_width" $__max_width_menu_constrain
+ fi
+ fi
+
+ # Adjust rows if desired
+ if [ "$__var_rows" ]; then
+ if [ "$USE_XDIALOG" ]; then
+ : ${__min_rows:=1}
+ else
+ : ${__min_rows:=0}
+ fi
+
+ local __max_rows_menu_constrain=$((
+ $__max_height_menu_constrain - 7
+ ))
+ # If prompt_len is zero (no prompt), bump the max-rows by 1
+ # Default assumption is (if no argument) that there's no prompt
+ [ ${__prompt_len:-0} -gt 0 ] || __max_rows_menu_constrain=$((
+ $__max_rows_menu_constrain + 1
+ ))
+
+ if [ $__rows_menu_constrain -lt $__min_rows ]; then
+ setvar "$__var_rows" $__min_rows
+ elif [ $__rows_menu_constrain -gt $__max_rows_menu_constrain ]
+ then
+ setvar "$__var_rows" $__max_rows_menu_constrain
+ fi
+ fi
+
+ if [ "$debug" ]; then
+ # Print final constrained values to debugging
+ [ "$__var_height" ] && f_quietly f_getvar "$__var_height"
+ [ "$__var_width" ] && f_quietly f_getvar "$__var_width"
+ [ "$__var_rows" ] && f_quietly f_getvar "$__var_rows"
+ fi
+
+ return $__retval # success if no debug warnings were printed
+}
+
+# f_dialog_infobox_size [-n] $var_height $var_width \
+# $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 two sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height and width. The second set of arguments are the
+# title, backtitle, prompt, and [optionally] hline. The optimal height and
+# width for the described widget (not exceeding the actual terminal height or
+# width) is stored in $var_height and $var_width (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height and
+# $var_width) are not constrained to minimum/maximum values.
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+f_dialog_infobox_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2"
+ local __title="$3" __btitle="$4" __prompt="$5" __hline="$6"
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ # Default height/width of zero for auto-sizing
+ local __height=0 __width=0 __n
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ #
+ # Set height based on number of rows in prompt
+ #
+ __n=$( echo -n "$__prompt" | f_number_of_lines )
+ __n=$(( $__n + 2 ))
+ [ $__n -gt $__height ] && __height=$__n
+
+ #
+ # 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
+
+ setvar "$__var_height" $__height
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ #
+ # Bump width for long titles
+ #
+ __n=$(( ${#__title} + 4 ))
+ [ $__n -gt $__width ] && __width=$__n
+
+ #
+ # If using Xdialog(1), bump width for long backtitles (which
+ # appear within the window).
+ #
+ if [ "$USE_XDIALOG" ]; then
+ __n=$(( ${#__btitle} + 4 ))
+ [ $__n -gt $__width ] && __width=$__n
+ fi
+
+ #
+ # Bump width for long prompts
+ #
+ __n=$( echo "$__prompt" | f_longest_line_length )
+ __n=$(( $__n + 4 )) # add width for border
+ [ $__n -gt $__width ] && __width=$__n
+
+ #
+ # Bump width for long hlines. Xdialog(1) supports `--hline' but
+ # it's currently not used (so don't do anything here if using
+ # Xdialog(1)).
+ #
+ if [ ! "$USE_XDIALOG" ]; then
+ __n=$(( ${#__hline} + 12 ))
+ [ $__n -gt $__width ] && __width=$__n
+ fi
+
+ # Bump width by 16.6% if using Xdialog(1)
+ [ "$USE_XDIALOG" ] && __width=$(( $__width + $__width / 6 ))
+
+ setvar "$__var_width" $__width
+ fi
+
+ # Constrain values to sensible minimums/maximums unless `-n' was passed
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] ||
+ f_dialog_size_constrain "$__var_height" "$__var_width"
+}
+
+# f_dialog_buttonbox_size [-n] $var_height $var_width \
+# $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 two sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height and width. The second set of arguments are the
+# title, backtitle, prompt, and [optionally] hline. The optimal height and
+# width for the described widget (not exceeding the actual terminal height or
+# width) is stored in $var_height and $var_width (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height and
+# $var_width) are not constrained to minimum/maximum values.
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+f_dialog_buttonbox_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2"
+ local __title="$3" __btitle="$4" __prompt="$5" __hline="$6"
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ # Calculate height/width of infobox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_bbox_size __width_bbox_size
+ f_dialog_infobox_size -n \
+ "${__var_height:+__height_bbox_size}" \
+ "${__var_width:+__width_bbox_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add height to accommodate the buttons
+ __height_bbox_size=$(( $__height_bbox_size + 2 ))
+
+ # Adjust for clipping with Xdialog(1) on Linux/GTK2
+ [ "$USE_XDIALOG" ] &&
+ __height_bbox_size=$(( $__height_bbox_size + 3 ))
+
+ setvar "$__var_height" $__height_bbox_size
+ fi
+
+ # No adjustemnts to width, just pass-thru the infobox width
+ if [ "$__var_width" ]; then
+ setvar "$__var_width" $__width_bbox_size
+ fi
+
+ # Constrain values to sensible minimums/maximums unless `-n' was passed
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] ||
+ f_dialog_size_constrain "$__var_height" "$__var_width"
+}
+
+# f_dialog_inputbox_size [-n] $var_height $var_width \
+# $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 two sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height and width. The second set of arguments are the
+# title, backtitle, prompt, and [optionally] hline. The optimal height and
+# width for the described widget (not exceeding the actual terminal height or
+# width) is stored in $var_height and $var_width (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height and
+# $var_width) are not constrained to minimum/maximum values.
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+f_dialog_inputbox_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2"
+ local __title="$3" __btitle="$4" __prompt="$5" __init="$6" __hline="$7"
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ # Calculate height/width of buttonbox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_ibox_size __width_ibox_size
+ f_dialog_buttonbox_size -n \
+ "${__var_height:+__height_ibox_size}" \
+ "${__var_width:+__width_ibox_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add height for input box (not needed for Xdialog(1))
+ [ ! "$USE_XDIALOG" ] &&
+ __height_ibox_size=$(( $__height_ibox_size + 3 ))
+
+ setvar "$__var_height" $__height_ibox_size
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ # Bump width for initial text (something neither dialog(1) nor
+ # Xdialog(1) do, but worth it!; add 16.6% if using Xdialog(1))
+ local __n=$(( ${#__init} + 7 ))
+ [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 ))
+ [ $__n -gt $__width_ibox_size ] && __width_ibox_size=$__n
+
+ setvar "$__var_width" $__width_ibox_size
+ fi
+
+ # Constrain values to sensible minimums/maximums unless `-n' was passed
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] ||
+ f_dialog_size_constrain "$__var_height" "$__var_width"
+}
+
+# f_xdialog_2inputsbox_size [-n] $var_height $var_width \
+# $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 two sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height and width. The second set of arguments are 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. The
+# optimal height and width for the described widget (not exceeding the actual
+# terminal height or width) is stored in $var_height and $var_width
+# (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height and
+# $var_width) are not constrained to minimum/maximum values.
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# Xdialog(1).
+#
+f_xdialog_2inputsbox_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2"
+ local __title="$3" __btitle="$4" __prompt="$5"
+ local __label1="$6" __init1="$7" __label2="$8" __init2="$9"
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ # Calculate height/width of inputbox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_2ibox_size __width_2ibox_size
+ f_dialog_inputbox_size -n \
+ "${__var_height:+__height_2ibox_size}" \
+ "${__var_width:+__width_2ibox_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline" "$__init1"
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add height for 1st label, 2nd label, and 2nd input box
+ __height_2ibox_size=$(( $__height_2ibox_size + 2 + 2 + 2 ))
+ setvar "$__var_height" $__height_2ibox_size
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ local __n
+
+ # Bump width for first label text (+16.6% since Xdialog(1))
+ __n=$(( ${#__label1} + 7 ))
+ __n=$(( $__n + $__n / 6 ))
+ [ $__n -gt $__width_2ibox_size ] && __width_2ibox_size=$__n
+
+ # Bump width for second label text (+16.6% since Xdialog(1))
+ __n=$(( ${#__label2} + 7 ))
+ __n=$(( $__n + $__n / 6 ))
+ [ $__n -gt $__width_2ibox_size ] && __width_2ibox_size=$__n
+
+ # Bump width for 2nd initial text (something neither dialog(1)
+ # nor Xdialog(1) do, but worth it!; +16.6% since Xdialog(1))
+ __n=$(( ${#__init2} + 7 ))
+ __n=$(( $__n + $__n / 6 ))
+ [ $__n -gt $__width_2ibox_size ] && __width_2ibox_size=$__n
+
+ setvar "$__var_width" $__width_2ibox_size
+ fi
+
+ # Constrain values to sensible minimums/maximums unless `-n' was passed
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] ||
+ f_dialog_size_constrain "$__var_height" "$__var_width"
+}
+
+# f_dialog_menu_size [-n] $var_height $var_width $var_rows \
+# $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 three sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height, width, and rows. The second set of arguments
+# are the title, backtitle, prompt, and hline. The [optional] third set of
+# arguments are the menu list itself (comprised of tag/item couplets). The
+# optimal height, width, and rows for the described widget (not exceeding the
+# actual terminal height or width) is stored in $var_height, $var_width, and
+# $var_rows (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height, $var_width,
+# and $var_rows) are not constrained to minimum/maximum values.
+#
+f_dialog_menu_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2" __var_rows="$3"
+ local __title="$4" __btitle="$5" __prompt="$6" __hline="$7"
+ shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] ||
+ return $FAILURE
+
+ # Calculate height/width of infobox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_menu_size __width_menu_size
+ f_dialog_infobox_size -n \
+ "${__var_height:+__height_menu_size}" \
+ "${__var_width:+__width_menu_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ #
+ # Always process the menu-item arguments to get the longest tag-length,
+ # longest item-length (both used to bump the width), and the number of
+ # rows (used to bump the height).
+ #
+ local __longest_tag=0 __longest_item=0 __rows=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=$(( $__rows + 1 ))
+ done
+
+ # Adjust rows early (for up-comning height calculation)
+ if [ "$__var_height" -o "$__var_rows" ]; then
+ # Add a row for visual aid if using Xdialog(1)
+ [ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 ))
+ fi
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add rows to height
+ if [ "$USE_XDIALOG" ]; then
+ __height_menu_size=$((
+ $__height_menu_size + $__rows + 7 ))
+ else
+ __height_menu_size=$((
+ $__height_menu_size + $__rows + 4 ))
+ fi
+ setvar "$__var_height" $__height_menu_size
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ # The sum total between the longest tag-length and the
+ # longest item-length should be used to bump menu width
+ local __n=$(( $__longest_tag + $__longest_item + 10 ))
+ [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6%
+ [ $__n -gt $__width_menu_size ] && __width_menu_size=$__n
+
+ setvar "$__var_width" $__width_menu_size
+ fi
+
+ # Store adjusted rows if desired
+ [ "$__var_rows" ] && setvar "$__var_rows" $__rows
+
+ # Constrain height, width, and rows to sensible minimum/maximum values
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] || f_dialog_menu_constrain \
+ "$__var_height" "$__var_width" "$__var_rows" "$__prompt"
+}
+
+# f_dialog_menu_with_help_size [-n] $var_height $var_width $var_rows \
+# $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 three sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height, width, and rows. The second set of arguments
+# are the title, backtitle, prompt, and hline. The [optional] third set of
+# arguments are the menu list itself (comprised of tag/item/help triplets). The
+# optimal height, width, and rows for the described widget (not exceeding the
+# actual terminal height or width) is stored in $var_height, $var_width, and
+# $var_rows (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height, $var_width,
+# and $var_rows) are not constrained to minimum/maximum values.
+#
+f_dialog_menu_with_help_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2" __var_rows="$3"
+ local __title="$4" __btitle="$5" __prompt="$6" __hline="$7"
+ shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] ||
+ return $FAILURE
+
+ # Calculate height/width of infobox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_menu_with_help_size __width_menu_with_help_size
+ f_dialog_infobox_size -n \
+ "${__var_height:+__height_menu_with_help_size}" \
+ "${__var_width:+__width_menu_with_help_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ #
+ # Always process the menu-item arguments to get the longest tag-length,
+ # longest item-length, longest help-length (help-length only considered
+ # if using Xdialog(1), as it places the help string in the widget) --
+ # all used to bump the width -- and the number of rows (used to bump
+ # the height).
+ #
+ local __longest_tag=0 __longest_item=0 __longest_help=0 __rows=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=$(( $__rows + 1 ))
+ done
+
+ # Adjust rows early (for up-coming height calculation)
+ if [ "$__var_height" -o "$__var_rows" ]; then
+ # Add a row for visual aid if using Xdialog(1)
+ [ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 ))
+ fi
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add rows to height
+ if [ "$USE_XDIALOG" ]; then
+ __height_menu_with_help_size=$((
+ $__height_menu_with_help_size + $__rows + 8 ))
+ else
+ __height_menu_with_help_size=$((
+ $__height_menu_with_help_size + $__rows + 4 ))
+ fi
+ setvar "$__var_height" $__height_menu_with_help_size
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ # The sum total between the longest tag-length and the
+ # longest item-length should be used to bump menu width
+ local __n=$(( $__longest_tag + $__longest_item + 10 ))
+ [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6%
+ [ $__n -gt $__width_menu_with_help_size ] &&
+ __width_menu_with_help_size=$__n
+
+ # Update width for help text if using Xdialog(1)
+ if [ "$USE_XDIALOG" ]; then
+ __n=$(( $__longest_help + 10 ))
+ __n=$(( $__n + $__n / 6 )) # plus 16.6%
+ [ $__n -gt $__width_menu_with_help_size ] &&
+ __width_menu_with_help_size=$__n
+ fi
+
+ setvar "$__var_width" $__width_menu_with_help_size
+ fi
+
+ # Store adjusted rows if desired
+ [ "$__var_rows" ] && setvar "$__var_rows" $__rows
+
+ # Constrain height, width, and rows to sensible minimum/maximum values
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] || f_dialog_menu_constrain \
+ "$__var_height" "$__var_width" "$__var_rows" "$__prompt"
+}
+
+# f_dialog_radiolist_size [-n] $var_height $var_width $var_rows \
+# $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 three sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height, width, and rows. The second set of arguments
+# are the title, backtitle, prompt, and hline. The [optional] third set of
+# arguments are the radio list itself (comprised of tag/item/status triplets).
+# The optimal height, width, and rows for the described widget (not exceeding
+# the actual terminal height or width) is stored in $var_height, $var_width,
+# and $var_rows (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height, $var_width,
+# and $var_rows) are not constrained to minimum/maximum values.
+#
+f_dialog_radiolist_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2" __var_rows="$3"
+ local __title="$4" __btitle="$5" __prompt="$6" __hline="$7"
+ shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] ||
+ return $FAILURE
+
+ # Calculate height/width of infobox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_rlist_size __width_rlist_size
+ f_dialog_infobox_size -n \
+ "${__var_height:+__height_rlist_size}" \
+ "${__var_width:+__width_rlist_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ #
+ # Always process the menu-item arguments to get the longest tag-length,
+ # longest item-length (both used to bump the width), and the number of
+ # rows (used to bump the height).
+ #
+ local __longest_tag=0 __longest_item=0 __rows_rlist_size=0
+ while [ $# -ge 3 ]; do
+ local __tag="$1" __item="$2"
+ shift 3 # tag/item/status
+ [ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag}
+ [ ${#__item} -gt $__longest_item ] && __longest_item=${#__item}
+ __rows_rlist_size=$(( $__rows_rlist_size + 1 ))
+ done
+
+ # Adjust rows early (for up-coming height calculation)
+ if [ "$__var_height" -o "$__var_rows" ]; then
+ # Add a row for visual aid if using Xdialog(1)
+ [ "$USE_XDIALOG" ] &&
+ __rows_rlist_size=$(( $__rows_rlist_size + 1 ))
+ fi
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add rows to height
+ if [ "$USE_XDIALOG" ]; then
+ __height_rlist_size=$((
+ $__height_rlist_size + $__rows_rlist_size + 7
+ ))
+ else
+ __height_rlist_size=$((
+ $__height_rlist_size + $__rows_rlist_size + 4
+ ))
+ fi
+ setvar "$__var_height" $__height_rlist_size
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ # Sum total between longest tag-length, longest item-length,
+ # and radio-button width should be used to bump menu width
+ local __n=$(( $__longest_tag + $__longest_item + 13 ))
+ [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6%
+ [ $__n -gt $__width_rlist_size ] && __width_rlist_size=$__n
+
+ setvar "$__var_width" $__width_rlist_size
+ fi
+
+ # Store adjusted rows if desired
+ [ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_size
+
+ # Constrain height, width, and rows to sensible minimum/maximum values
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] || f_dialog_menu_constrain \
+ "$__var_height" "$__var_width" "$__var_rows" "$__prompt"
+}
+
+# f_dialog_checklist_size [-n] $var_height $var_width $var_rows \
+# $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
+# `--checklist' boxes sensibly.
+#
+# This function helps solve this issue by taking three sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height, width, and rows. The second set of arguments
+# are the title, backtitle, prompt, and hline. The [optional] third set of
+# arguments are the check list itself (comprised of tag/item/status triplets).
+# The optimal height, width, and rows for the described widget (not exceeding
+# the actual terminal height or width) is stored in $var_height, $var_width,
+# and $var_rows (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height, $var_width,
+# and $var_rows) are not constrained to minimum/maximum values.
+#
+f_dialog_checklist_size()
+{
+ f_dialog_radiolist_size "$@"
+}
+
+# f_dialog_radiolist_with_help_size [-n] $var_height $var_width $var_rows \
+# $title $backtitle $prompt $hline \
+# $tag1 $item1 $status1 $help1 \
+# $tag2 $item2 $status2 $help2 ...
+#
+# 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 three sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height, width, and rows. The second set of arguments
+# are the title, backtitle, prompt, and hline. The [optional] third set of
+# arguments are the radio list itself (comprised of tag/item/status/help
+# quadruplets). The optimal height, width, and rows for the described widget
+# (not exceeding the actual terminal height or width) is stored in $var_height,
+# $var_width, and $var_rows (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height, $var_width,
+# and $var_rows) are not constrained to minimum/maximum values.
+#
+f_dialog_radiolist_with_help_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2" __var_rows="$3"
+ local __title="$4" __btitle="$5" __prompt="$6" __hline="$7"
+ shift 7 # var_height/var_width/var_rows/title/btitle/prompt/hline
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" -o "$__var_rows" ] ||
+ return $FAILURE
+
+ # Calculate height/width of infobox (adjusted/constrained below)
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_rlist_with_help_size __width_rlist_with_help_size
+ f_dialog_infobox_size -n \
+ "${__var_height:+__height_rlist_with_help_size}" \
+ "${__var_width:+__width_rlist_with_help_size}" \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ #
+ # Always process the menu-item arguments to get the longest tag-length,
+ # longest item-length, longest help-length (help-length only considered
+ # if using Xdialog(1), as it places the help string in the widget) --
+ # all used to bump the width -- and the number of rows (used to bump
+ # the height).
+ #
+ local __longest_tag=0 __longest_item=0 __longest_help=0
+ local __rows_rlist_with_help_size=0
+ while [ $# -ge 4 ]; do
+ local __tag="$1" __item="$2" __status="$3" __help="$4"
+ shift 4 # tag/item/status/help
+ [ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag}
+ [ ${#__item} -gt $__longest_item ] && __longest_item=${#__item}
+ [ ${#__help} -gt $__longest_help ] && __longest_help=${#__help}
+ __rows_rlist_with_help_size=$((
+ $__rows_rlist_with_help_size + 1
+ ))
+ done
+
+ # Adjust rows early (for up-coming height calculation)
+ if [ "$__var_height" -o "$__var_rows" ]; then
+ # Add a row for visual aid if using Xdialog(1)
+ [ "$USE_XDIALOG" ] &&
+ __rows_rlist_with_help_size=$((
+ $__rows_rlist_with_help_size + 1
+ ))
+ fi
+
+ # Adjust height if desired
+ if [ "$__var_height" ]; then
+ # Add rows to height
+ if [ "$USE_XDIALOG" ]; then
+ __height_rlist_with_help_size=$((
+ $__height_rlist_with_help_size +
+ $__rows_rlist_with_help_size + 7
+ ))
+ else
+ __height_rlist_with_help_size=$((
+ $__height_rlist_with_help_size +
+ $__rows_rlist_with_help_size + 4
+ ))
+ fi
+ setvar "$__var_height" $__height
+ fi
+
+ # Adjust width if desired
+ if [ "$__var_width" ]; then
+ # Sum total between longest tag-length, longest item-length,
+ # and radio-button width should be used to bump menu width
+ local __n=$(( $__longest_tag + $__longest_item + 13 ))
+ [ "$USE_XDIALOG" ] && __n=$(( $__n + $__n / 6 )) # plus 16.6%
+ [ $__n -gt $__width_rlist_with_help_size ] &&
+ __width_rlist_with_help_size=$__n
+
+ # Update width for help text if using Xdialog(1)
+ if [ "$USE_XDIALOG" ]; then
+ __n=$(( $__longest_help + 10 ))
+ __n=$(( $__n + $__n / 6 )) # plus 16.6%
+ [ $__n -gt $__width_rlist_with_help_size ] &&
+ __width_rlist_with_help_size=$__n
+ fi
+
+ setvar "$__var_width" $__width_rlist_with_help_size
+ fi
+
+ # Store adjusted rows if desired
+ [ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_with_help_size
+
+ # Constrain height, width, and rows to sensible minimum/maximum values
+ # Return success if no-constrain, else return status from constrain
+ [ ! "$__constrain" ] || f_dialog_menu_constrain \
+ "$__var_height" "$__var_width" "$__var_rows" "$__prompt"
+}
+
+# f_dialog_checklist_with_help_size [-n] $var_height $var_width $var_rows \
+# $title $backtitle $prompt $hline \
+# $tag1 $item1 $status1 $help1 \
+# $tag2 $item2 $status2 $help2 ...
+#
+# Not all versions of dialog(1) perform auto-sizing of the width and height of
+# `--checklist' boxes sensibly.
+#
+# This function helps solve this issue by taking three sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height, width, and rows. The second set of arguments
+# are the title, backtitle, prompt, and hline. The [optional] third set of
+# arguments are the check list itself (comprised of tag/item/status/help
+# quadruplets). The optimal height, width, and rows for the described widget
+# (not exceeding the actual terminal height or width) is stored in $var_height,
+# $var_width, and $var_rows (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height, $var_width,
+# and $var_rows) are not constrained to minimum/maximum values.
+#
+f_dialog_checklist_with_help_size()
+{
+ f_dialog_radiolist_with_help_size "$@"
+}
+
+# f_dialog_calendar_size [-n] $var_height $var_width \
+# $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 two sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height and width. The second set of arguments are the
+# title, backtitle, prompt, and [optionally] hline. The optimal height and
+# width for the described widget (not exceeding the actual terminal height or
+# width) is stored in $var_height and $var_width (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height and
+# $var_width) are not constrained to minimum/maximum values.
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+f_dialog_calendar_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2"
+ local __title="$3" __btitle="$4" __prompt="$5" __hline="$6"
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ #
+ # Obtain/Adjust minimum and maximum thresholds
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ #
+ local __max_height_cal_size __max_width_cal_size
+ f_dialog_max_size __max_height_cal_size __max_width_cal_size
+ __max_width_cal_size=$(( $__max_width_cal_size - 2 ))
+ # the calendar box will refuse to display if too wide
+ local __min_width
+ if [ "$USE_XDIALOG" ]; then
+ __min_width=55
+ else
+ __min_width=40
+ __max_height_cal_size=$((
+ $__max_height_cal_size - $DIALOG_CALENDAR_HEIGHT ))
+ # When using dialog(1), we can't predict whether the user has
+ # disabled shadow's in their `$HOME/.dialogrc' file, so we'll
+ # subtract one for the potential shadow around the widget
+ __max_height_cal_size=$(( $__max_height_cal_size - 1 ))
+ fi
+
+ # Calculate height if desired
+ if [ "$__var_height" ]; then
+ local __height
+ __height=$( echo "$__prompt" | f_number_of_lines )
+
+ if [ "$USE_XDIALOG" ]; then
+ # Add height to accommodate for embedded calendar widget
+ __height=$(( $__height + $DIALOG_CALENDAR_HEIGHT - 1 ))
+
+ # Also, bump height if backtitle is enabled
+ if [ "$__btitle" ]; then
+ local __n
+ __n=$( echo "$__btitle" | f_number_of_lines )
+ __height=$(( $__height + $__n + 2 ))
+ fi
+ else
+ [ "$__prompt" ] && __height=$(( $__height + 1 ))
+ fi
+
+ # Enforce maximum height, unless `-n' was passed
+ [ "$__constrain" -a $__height -gt $__max_height_cal_size ] &&
+ __height=$__max_height_cal_size
+
+ setvar "$__var_height" $__height
+ fi
+
+ # Calculate width if desired
+ if [ "$__var_width" ]; then
+ # NOTE: Function name appended to prevent __var_{height,width}
+ # values from becoming local (and thus preventing setvar
+ # from working).
+ local __width_cal_size
+ f_dialog_infobox_size -n "" __width_cal_size \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ # Enforce minimum/maximum width, unless `-n' was passed
+ if [ "$__constrain" ]; then
+ if [ $__width_cal_size -lt $__min_width ]; then
+ __width_cal_size=$__min_width
+ elif [ $__width_cal_size -gt $__max_width_cal_size ]
+ then
+ __width_cal_size=$__max_width_size
+ fi
+ fi
+
+ setvar "$__var_width" $__width_cal_size
+ fi
+
+ return $SUCCESS
+}
+
+# f_dialog_timebox_size [-n] $var_height $var_width \
+# $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 two sets of sequential
+# arguments. The first set of arguments are the variable names to use when
+# storing the calculated height and width. The second set of arguments are the
+# title, backtitle, prompt, and [optionally] hline. The optional height and
+# width for the described widget (not exceeding the actual terminal height or
+# width) is stored in $var_height and $var_width (respectively).
+#
+# If the first argument is `-n', the calculated sizes ($var_height and
+# $var_width) are not constrained to minimum/maximum values.
+#
+# Newline character sequences (``\n'') in $prompt are expanded as-is done by
+# dialog(1).
+#
+f_dialog_timebox_size()
+{
+ local __constrain=1
+ [ "$1" = "-n" ] && __constrain= && shift 1 # -n
+ local __var_height="$1" __var_width="$2"
+ local __title="$3" __btitle="$4" __prompt="$5" __hline="$6"
+
+ # Return unless at least one size aspect has been requested
+ [ "$__var_height" -o "$__var_width" ] || return $FAILURE
+
+ #
+ # Obtain/Adjust minimum and maximum thresholds
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ #
+ local __max_height_tbox_size __max_width_tbox_size
+ f_dialog_max_size __max_height_tbox_size __max_width_tbox_size
+ __max_width_tbox_size=$(( $__max_width_tbox_size - 2 ))
+ # the timebox widget refuses to display if too wide
+ local __min_width
+ if [ "$USE_XDIALOG" ]; then
+ __min_width=40
+ else
+ __min_width=20
+ __max_height_tbox_size=$(( \
+ $__max_height_tbox_size - $DIALOG_TIMEBOX_HEIGHT ))
+ # When using dialog(1), we can't predict whether the user has
+ # disabled shadow's in their `$HOME/.dialogrc' file, so we'll
+ # subtract one for the potential shadow around the widget
+ __max_height_tbox_size=$(( $__max_height_tbox_size - 1 ))
+ fi
+
+ # Calculate height if desired
+ if [ "$__var_height" -a "$USE_XDIALOG" ]; then
+ # When using Xdialog(1), the height seems to have
+ # no effect. All values provide the same results.
+ setvar "$__var_height" 0 # autosize
+ elif [ "$__var_height" ]; then
+ local __height
+ __height=$( echo "$__prompt" | f_number_of_lines )
+ __height=$(( $__height ${__prompt:++1} + 1 ))
+
+ # Enforce maximum height, unless `-n' was passed
+ [ "$__constrain" -a $__height -gt $__max_height_tbox_size ] &&
+ __height=$__max_height_tbox_size
+
+ setvar "$__var_height" $__height
+ fi
+
+ # Calculate width if desired
+ if [ "$__var_width" ]; then
+ # NOTE: Function name appended to prevent __var_{height,width}
+ # values from becoming local (and thus preventing setvar
+ # from working).
+ local __width_tbox_size
+ f_dialog_infobox_size -n "" __width_tbox_size \
+ "$__title" "$__btitle" "$__prompt" "$__hline"
+
+ # Enforce the minimum width for displaying the timebox
+ if [ "$__constrain" ]; then
+ if [ $__width_tbox_size -lt $__min_width ]; then
+ __width_tbox_size=$__min_width
+ elif [ $__width_tbox_size -ge $__max_width_tbox_size ]
+ then
+ __width_tbox_size=$__max_width_tbox_size
+ fi
+ fi
+
+ setvar "$__var_width" $__width_tbox_size
+ fi
+
+ return $SUCCESS
+}
+
+############################################################ CLEAR FUNCTIONS
+
+# f_dialog_clear
+#
+# Clears any/all previous dialog(1) displays.
+#
+f_dialog_clear()
+{
+ $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 f_dialog_clear) is called.
+#
+f_dialog_info()
+{
+ local info_text="$*" height width
+ f_dialog_infobox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$info_text"
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ ${USE_XDIALOG:+--ignore-eof} \
+ ${USE_XDIALOG:+--no-buttons} \
+ --infobox "$info_text" $height $width
+}
+
+# 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.
+#
+# To open an Xdialog(1) infobox that does not disappear until expeclitly dis-
+# missed, use the following:
+#
+# f_xdialog_info "$info_text" < /dev/tty &
+# pid=$!
+# # Perform some lengthy actions
+# kill $pid
+#
+# NB: Check $USE_XDIALOG if you need to support both dialog(1) and Xdialog(1).
+#
+f_xdialog_info()
+{
+ local info_text="$*" height width
+ f_dialog_infobox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$info_text"
+ exec $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --no-close --no-buttons \
+ --infobox "$info_text" $height $width \
+ -1 # timeout of -1 means abort when EOF on stdin
+}
+
+############################################################ PAUSE FUNCTIONS
+
+# f_dialog_pause $msg_text $duration [$hline]
+#
+# Display a message in a widget with a progress bar that runs backward for
+# $duration seconds.
+#
+f_dialog_pause()
+{
+ local pause_text="$1" duration="$2" hline="$3" height width
+ f_isinteger "$duration" || return $FAILURE
+ f_dialog_buttonbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$pause_text" "$hline"
+ if [ "$USE_XDIALOG" ]; then
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --ok-label "$msg_skip" \
+ --cancel-label "$msg_cancel" \
+ ${noCancel:+--no-cancel} \
+ --timeout "$duration" \
+ --yesno "$pause_text" \
+ $height $width
+ else
+ [ $duration -gt 0 ] && duration=$(( $duration - 1 ))
+ height=$(( $height + 3 )) # Add height for progress bar
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_skip" \
+ --cancel-label "$msg_cancel" \
+ ${noCancel:+--no-cancel} \
+ --pause "$pause_text" \
+ $height $width "$duration"
+ fi
+}
+
+# f_dialog_pause_no_cancel $msg_text $duration [$hline]
+#
+# Display a message in a widget with a progress bar that runs backward for
+# $duration seconds. No cancel button is provided. Always returns success.
+#
+f_dialog_pause_no_cancel()
+{
+ noCancel=1 f_dialog_pause "$@"
+ return $SUCCESS
+}
+
+############################################################ MSGBOX FUNCTIONS
+
+# f_dialog_msgbox $msg_text [$hline]
+#
+# 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()
+{
+ local msg_text="$1" hline="$2" height width
+ f_dialog_buttonbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_text" "$hline"
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --msgbox "$msg_text" $height $width
+}
+
+############################################################ TEXTBOX FUNCTIONS
+
+# f_dialog_textbox $file
+#
+# Display the contents of $file (or an error if $file does not exist, etc.) in
+# a dialog(1) textbox (which has a scrollable region for the text). The textbox
+# 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_textbox()
+{
+ local file="$1"
+ local contents height width retval
+
+ contents=$( cat "$file" 2>&1 )
+ retval=$?
+
+ f_dialog_buttonbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$contents"
+
+ if [ $retval -eq $SUCCESS ]; then
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --exit-label "$msg_ok" \
+ --no-cancel \
+ --textbox "$file" $height $width
+ else
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --ok-label "$msg_ok" \
+ --msgbox "$contents" $height $width
+ fi
+}
+
+############################################################ YESNO FUNCTIONS
+
+# f_dialog_yesno $msg_text [$hline]
+#
+# 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()
+{
+ local msg_text="$1" height width
+ local hline="${2-$hline_arrows_tab_enter}"
+
+ f_interactive || return 0 # If non-interactive, return YES all the time
+
+ f_dialog_buttonbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_text" "$hline"
+
+ if [ "$USE_XDIALOG" ]; then
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_yes" \
+ --cancel-label "$msg_no" \
+ --yesno "$msg_text" $height $width
+ else
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --yes-label "$msg_yes" \
+ --no-label "$msg_no" \
+ --yesno "$msg_text" $height $width
+ fi
+}
+
+# f_dialog_noyes $msg_text [$hline]
+#
+# 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()
+{
+ local msg_text="$1" height width
+ local hline="${2-$hline_arrows_tab_enter}"
+
+ f_interactive || return 1 # If non-interactive, return NO all the time
+
+ f_dialog_buttonbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$msg_text" "$hline"
+
+ if [ "$USE_XDIALOG" ]; then
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --default-no \
+ --ok-label "$msg_yes" \
+ --cancel-label "$msg_no" \
+ --yesno "$msg_text" $height $width
+ else
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --defaultno \
+ --yes-label "$msg_yes" \
+ --no-label "$msg_no" \
+ --yesno "$msg_text" $height $width
+ fi
+}
+
+############################################################ INPUT FUNCTIONS
+
+# f_dialog_inputstr_store [-s] $text
+#
+# Store some text from a dialog(1) inputbox to be retrieved later by
+# f_dialog_inputstr_fetch(). If the first argument is `-s', the text is
+# sanitized before being stored.
+#
+f_dialog_inputstr_store()
+{
+ local sanitize=
+ [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s
+ local text="$1"
+
+ # Sanitize the line before storing it if desired
+ [ "$sanitize" ] && f_dialog_line_sanitize text
+
+ setvar DIALOG_INPUTBOX_$$ "$text"
+}
+
+# f_dialog_inputstr_fetch [$var_to_set]
+#
+# Obtain the inputstr entered by the user from the most recently displayed
+# dialog(1) inputbox (previously stored with f_dialog_inputstr_store() above).
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+f_dialog_inputstr_fetch()
+{
+ local __var_to_set="$1" __cp
+
+ debug= f_getvar DIALOG_INPUTBOX_$$ "${__var_to_set:-__cp}" # get data
+ setvar DIALOG_INPUTBOX_$$ "" # scrub memory in case data was sensitive
+
+ # Return the line on standard-out if desired
+ [ "$__var_to_set" ] || echo "$__cp"
+
+ return $SUCCESS
+}
+
+# f_dialog_input $var_to_set $prompt [$init [$hline]]
+#
+# Prompt the user with a dialog(1) inputbox to enter some value. The inputbox
+# remains until the user presses ENTER or ESC, or otherwise ends the
+# editing session (by selecting `Cancel' for example).
+#
+# If the user presses ENTER, the exit status is zero (success), otherwise if
+# the user presses ESC the exit status is 255, or if the user chose Cancel, the
+# exit status is instead 1.
+#
+# NOTE: The hline should correspond to the type of data you want from the user.
+# NOTE: Should not be used to edit multiline values.
+#
+f_dialog_input()
+{
+ local __var_to_set="$1" __prompt="$2" __init="$3" __hline="$4"
+
+ # NOTE: Function name appended to prevent __var_{height,width} values
+ # from becoming local (and thus preventing setvar from working).
+ local __height_input __width_input
+ f_dialog_inputbox_size __height_input __width_input \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" \
+ "$__prompt" "$__init" "$__hline"
+
+ local __opterm="--"
+ [ "$USE_XDIALOG" ] && __opterm=
+
+ local __dialog_input
+ __dialog_input=$(
+ $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$__hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --inputbox "$__prompt" \
+ $__height_input $__width_input \
+ $__opterm "$__init" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local __retval=$?
+
+ # Remove warnings and leading/trailing whitespace from user input
+ f_dialog_line_sanitize __dialog_input
+
+ setvar "$__var_to_set" "$__dialog_input"
+ return $__retval
+}
+
+############################################################ MENU FUNCTIONS
+
+# f_dialog_menutag_store [-s] $text
+#
+# Store some text from a dialog(1) menu to be retrieved later by
+# f_dialog_menutag_fetch(). If the first argument is `-s', the text is
+# sanitized before being stored.
+#
+f_dialog_menutag_store()
+{
+ local sanitize=
+ [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s
+ local text="$1"
+
+ # Sanitize the menutag before storing it if desired
+ [ "$sanitize" ] && f_dialog_data_sanitize text
+
+ setvar DIALOG_MENU_$$ "$text"
+}
+
+# f_dialog_menutag_fetch [$var_to_set]
+#
+# Obtain the menutag chosen by the user from the most recently displayed
+# dialog(1) menu (previously stored with f_dialog_menutag_store() above). If
+# $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+f_dialog_menutag_fetch()
+{
+ local __var_to_set="$1" __cp
+
+ debug= f_getvar DIALOG_MENU_$$ "${__var_to_set:-__cp}" # get the data
+ setvar DIALOG_MENU_$$ "" # scrub memory in case data was sensitive
+
+ # Return the data on standard-out if desired
+ [ "$__var_to_set" ] || echo "$__cp"
+
+ return $SUCCESS
+}
+
+# f_dialog_menuitem_store [-s] $text
+#
+# Store the item from a dialog(1) menu (see f_dialog_menutag2item()) to be
+# retrieved later by f_dialog_menuitem_fetch(). If the first argument is `-s',
+# the text is sanitized before being stored.
+#
+f_dialog_menuitem_store()
+{
+ local sanitize=
+ [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s
+ local text="$1"
+
+ # Sanitize the menuitem before storing it if desired
+ [ "$sanitize" ] && f_dialog_data_sanitize text
+
+ setvar DIALOG_MENUITEM_$$ "$text"
+}
+
+# f_dialog_menuitem_fetch [$var_to_set]
+#
+# Obtain the menuitem chosen by the user from the most recently displayed
+# dialog(1) menu (previously stored with f_dialog_menuitem_store() above). If
+# $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+f_dialog_menuitem_fetch()
+{
+ local __var_to_set="$1" __cp
+
+ debug= f_getvar DIALOG_MENUITEM_$$ "${__var_to_set:-__cp}" # get data
+ setvar DIALOG_MENUITEM_$$ "" # scrub memory in case data was sensitive
+
+ # Return the data on standard-out if desired
+ [ "$__var_to_set" ] || echo "$__cp"
+
+ return $SUCCESS
+}
+
+# f_dialog_default_store [-s] $text
+#
+# Store some text to be used later as the --default-item argument to dialog(1)
+# (or Xdialog(1)) for --menu, --checklist, and --radiolist widgets. Retrieve
+# the text later with f_dialog_menutag_fetch(). If the first argument is `-s',
+# the text is sanitized before being stored.
+#
+f_dialog_default_store()
+{
+ local sanitize=
+ [ "$1" = "-s" ] && sanitize=1 && shift 1 # -s
+ local text="$1"
+
+ # Sanitize the defaulitem before storing it if desired
+ [ "$sanitize" ] && f_dialog_data_sanitize text
+
+ setvar DEFAULTITEM_$$ "$text"
+}
+
+# f_dialog_default_fetch [$var_to_set]
+#
+# Obtain text to be used with the --default-item argument of dialog(1) (or
+# Xdialog(1)) (previously stored with f_dialog_default_store() above). If
+# $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
+f_dialog_default_fetch()
+{
+ local __var_to_set="$1" __cp
+
+ debug= f_getvar DEFAULTITEM_$$ "${__var_to_set:-__cp}" # get the data
+ setvar DEFAULTITEM_$$ "" # scrub memory in case data was sensitive
+
+ # Return the data on standard-out if desired
+ [ "$__var_to_set" ] || echo "$__cp"
+
+ 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
+}
+
+# f_dialog_menutag2help $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 help associated with said tag (item 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_menutag2help()
+{
+ local tag="$1" tagn help
+ shift 1 # tag
+
+ while [ $# -gt 0 ]; do
+ tagn="$1"
+ help="$3"
+ shift 3 # tagn/item/help
+
+ if [ "$tag" = "$tagn" ]; then
+ echo "$help"
+ return $SUCCESS
+ fi
+ 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.
+#
+# Also reads ~/.dialogrc for the following information:
+#
+# NO_SHADOW Either NULL or Non-NULL. If use_shadow is OFF (case-
+# insensitive) in ~/.dialogrc this is set to "1" (otherwise
+# unset).
+#
+f_dialog_init()
+{
+ local funcname=f_dialog_init
+
+ DIALOG_SELF_INITIALIZE=
+ USE_DIALOG=1
+
+ #
+ # Clone terminal stdout so we can redirect to it from within sub-shells
+ #
+ eval exec $DIALOG_TERMINAL_PASSTHRU_FD\>\&1
+
+ #
+ # Add `-S' and `-X' to the list of standard arguments supported by all
+ #
+ case "$GETOPTS_STDARGS" in
+ *SX*) : good ;; # already present
+ *) GETOPTS_STDARGS="${GETOPTS_STDARGS}SX"
+ esac
+
+ #
+ # Process stored command-line arguments
+ #
+ # NB: Using backticks instead of $(...) for portability since Linux
+ # bash(1) balks at the right parentheses encountered in the case-
+ # statement (incorrectly interpreting it as the close of $(...)).
+ #
+ f_dprintf "f_dialog_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
+ "$ARGV" "$GETOPTS_STDARGS"
+ SECURE=`set -- $ARGV
+ OPTIND=1
+ while getopts \
+ "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \
+ flag > /dev/null; do
+ case "$flag" in
+ S) echo 1 ;;
+ esac
+ done
+ ` # END-BACKTICK
+ USE_XDIALOG=`set -- $ARGV
+ OPTIND=1
+ while getopts \
+ "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \
+ flag > /dev/null; do
+ case "$flag" in
+ S|X) echo 1 ;;
+ esac
+ done
+ ` # END-BACKTICK
+ f_dprintf "f_dialog_init: SECURE=[%s] USE_XDIALOG=[%s]" \
+ "$SECURE" "$USE_XDIALOG"
+
+ #
+ # Process `-X' command-line option
+ #
+ [ "$USE_XDIALOG" ] && DIALOG=Xdialog USE_DIALOG=
+
+ #
+ # Sanity check, or die gracefully
+ #
+ if ! f_have $DIALOG; then
+ unset USE_XDIALOG
+ local failed_dialog="$DIALOG"
+ DIALOG=dialog
+ f_die 1 "$msg_no_such_file_or_directory" "$pgm" "$failed_dialog"
+ fi
+
+ #
+ # Read ~/.dialogrc (unless using Xdialog(1)) for properties
+ #
+ if [ -f ~/.dialogrc -a ! "$USE_XDIALOG" ]; then
+ eval "$(
+ awk -v param=use_shadow -v expect=OFF \
+ -v set="NO_SHADOW=1" '
+ !/^[[:space:]]*(#|$)/ && \
+ tolower($1) ~ "^"param"(=|$)" && \
+ /[^#]*=/ {
+ sub(/^[^=]*=[[:space:]]*/, "")
+ if ( toupper($1) == expect ) print set";"
+ }' ~/.dialogrc
+ )"
+ 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 )
+ local 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
+ local maxsize
+ if ! f_eval_catch -dk maxsize $funcname "$DIALOG" \
+ 'LANG= LC_ALL= %s --print-maxsize' "$DIALOG"
+ then
+ # Xdialog(1) failed, fall back to dialog(1)
+ unset USE_XDIALOG
+
+ # Display the error message produced by Xdialog(1)
+ local height width
+ f_dialog_buttonbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$maxsize"
+ dialog \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --ok-label "$msg_ok" \
+ --msgbox "$maxsize" $height $width
+ exit $FAILURE
+ fi
+
+ XDIALOG_MAXSIZE=$(
+ set -- ${maxsize##*:}
+
+ height=${1%,}
+ width=$2
+
+ echo $height $width
+ )
+ 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
+ local _DIALOG_TITLE="$DIALOG_TITLE"
+ DIALOG_TITLE="$DIALOG_BACKTITLE"
+ DIALOG_BACKTITLE="$_DIALOG_TITLE"
+ fi
+
+ f_dprintf "f_dialog_init: dialog(1) API initialized."
+}
+
+############################################################ MAIN
+
+#
+# Self-initialize unless requested otherwise
+#
+f_dprintf "%s: DIALOG_SELF_INITIALIZE=[%s]" \
+ dialog.subr "$DIALOG_SELF_INITIALIZE"
+case "$DIALOG_SELF_INITIALIZE" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_dialog_init
+esac
+
+f_dprintf "%s: Successfully loaded." dialog.subr
+
+fi # ! $_DIALOG_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/geom.subr b/contrib/bsddialog/bsdconfig/share/geom.subr
new file mode 100644
index 000000000000..d6486c6d6543
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/geom.subr
@@ -0,0 +1,430 @@
+if [ ! "$_GEOM_SUBR" ]; then _GEOM_SUBR=1
+#
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." geom.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+############################################################ GLOBALS
+
+NGEOM_CLASSES=0 # Set by f_geom_get_all()/f_geom_reset()
+
+#
+# GEOM classes for use with f_geom_find()
+#
+# NB: Since $GEOM_CLASS_ANY is the NULL string, make sure you quote it whenever
+# you put arguments after it.
+#
+setvar GEOM_CLASS_ANY "any"
+setvar GEOM_CLASS_DEV "DEV"
+setvar GEOM_CLASS_DISK "DISK"
+setvar GEOM_CLASS_ELI "ELI"
+setvar GEOM_CLASS_FD "FD"
+setvar GEOM_CLASS_LABEL "LABEL"
+setvar GEOM_CLASS_MD "MD"
+setvar GEOM_CLASS_NOP "NOP"
+setvar GEOM_CLASS_PART "PART"
+setvar GEOM_CLASS_RAID "RAID"
+setvar GEOM_CLASS_SWAP "SWAP"
+setvar GEOM_CLASS_VFS "VFS"
+setvar GEOM_CLASS_ZFS_VDEV "ZFS::VDEV"
+setvar GEOM_CLASS_ZFS_ZVOL "ZFS::ZVOL"
+
+#
+# GEOM structure definitions
+#
+f_struct_define GEOM_CLASS \
+ id name ngeoms
+f_struct_define GEOM_GEOM \
+ id class_ref config name nconsumers nproviders rank
+ # Also consumerN where N is 1 through nconsumers
+ # Also providerN where N is 1 through nproviders
+f_struct_define GEOM_CONSUMER \
+ id geom_ref config mode provider_ref
+f_struct_define GEOM_PROVIDER \
+ id geom_ref config mode name mediasize
+
+# The config property of GEOM_GEOM struct is defined as this
+f_struct_define GEOM_GEOM_CONFIG \
+ entries first fwheads fwsectors last modified scheme state
+
+# The config property of GEOM_PROVIDER struct is defined as this
+f_struct_define GEOM_PROVIDER_CONFIG \
+ descr file fwheads fwsectors ident length type unit
+
+#
+# Default behavior is to call f_geom_get_all() automatically when loaded.
+#
+: ${GEOM_SELF_SCAN_ALL=1}
+
+############################################################ FUNCTIONS
+
+# f_geom_get_all
+#
+# Parse sysctl(8) `kern.geom.confxml' data into a series of structs. GEOM
+# classes are at the top of the hierarchy and are stored as numbered structs
+# from 1 to $NGEOM_CLASSES (set by this function) named `geom_class_C'. GEOM
+# objects within each class are stored as numbered structs from 1 to `ngeoms'
+# (a property of the GEOM class struct) named `geom_class_C_geom_N' (where C
+# is the class number and N is the geom number).
+#
+# Use the function f_geom_find() to get a list of geoms (execute without
+# arguments) or find specific geoms by class or name.
+#
+f_geom_get_all()
+{
+ eval "$( sysctl -n kern.geom.confxml | awk '
+ BEGIN {
+ struct_count["class"] = 0
+ struct_count["geom"] = 0
+ struct_count["consumer"] = 0
+ struct_count["provider"] = 0
+ }
+ ############################################### FUNCTIONS
+ function set_value(prop, value)
+ {
+ if (!struct_stack[cur_struct]) return
+ printf "%s set %s \"%s\"\n",
+ struct_stack[cur_struct], prop, value
+ }
+ function create(type, id)
+ {
+ if (struct = created[type "_" id])
+ print "f_struct_free", struct
+ else {
+ struct = struct_stack[cur_struct]
+ struct = struct ( struct ? "" : "geom" )
+ struct = struct "_" type "_" ++struct_count[type]
+ created[type "_" id] = struct
+ }
+ print "debug= f_struct_new GEOM_" toupper(type), struct
+ cur_struct++
+ struct_stack[cur_struct] = struct
+ type_stack[cur_struct] = type
+ set_value("id", id)
+ }
+ function create_config()
+ {
+ struct = struct_stack[cur_struct]
+ struct = struct ( struct ? "" : "geom" )
+ struct = struct "_config"
+ set_value("config", struct)
+ type = type_stack[cur_struct]
+ print "debug= f_struct_new GEOM_" toupper(type) "_CONFIG", \
+ struct
+ cur_struct++
+ struct_stack[cur_struct] = struct
+ type_stack[cur_struct] = type "_config"
+ }
+ function extract_attr(field, attr)
+ {
+ if (match(field, attr "=\"0x[[:xdigit:]]+\"")) {
+ len = length(attr)
+ return substr($2, len + 3, RLENGTH - len - 3)
+ }
+ }
+ function extract_data(type)
+ {
+ data = $0
+ sub("^[[:space:]]*<" type ">", "", data)
+ sub("</" type ">.*$", "", data)
+ return data
+ }
+ ############################################### OPENING PATTERNS
+ $1 == "<mesh>" { mesh = 1 }
+ $1 ~ /^<(class|geom)$/ && mesh {
+ prop = substr($1, 2)
+ if ((ref = extract_attr($2, "ref")) != "")
+ set_value(prop "_ref", ref)
+ else if ((id = extract_attr($2, "id")) != "")
+ create(prop, id)
+ }
+ $1 ~ /^<(consumer|provider)$/ && mesh {
+ prop = substr($1, 2)
+ if ((ref = extract_attr($2, "ref")) != "")
+ set_value(prop "_ref", ref)
+ else if ((id = extract_attr($2, "id")) != "") {
+ create(prop, id)
+ cur_struct--
+ propn = struct_count[prop]
+ set_value(prop propn, struct_stack[cur_struct+1])
+ cur_struct++
+ }
+ }
+ $1 == "<config>" && mesh { create_config() }
+ ############################################### PROPERTIES
+ $1 ~ /^<[[:alnum:]]+>/ {
+ prop = $1
+ sub(/^</, "", prop); sub(/>.*/, "", prop)
+ set_value(prop, extract_data(prop))
+ }
+ ############################################### CLOSING PATTERNS
+ $1 ~ "^</(consumer|provider|config)>$" { cur_struct-- }
+ $1 == "</geom>" {
+ set_value("nconsumers", struct_count["consumer"])
+ set_value("nproviders", struct_count["provider"])
+ cur_struct--
+ struct_count["consumer"] = 0
+ struct_count["provider"] = 0
+ }
+ $1 == "</class>" {
+ set_value("ngeoms", struct_count["geom"])
+ cur_struct--
+ struct_count["consumer"] = 0
+ struct_count["provider"] = 0
+ struct_count["geom"] = 0
+ }
+ $1 == "</mesh>" {
+ printf "NGEOM_CLASSES=%u\n", struct_count["class"]
+ delete struct_count
+ mesh = 0
+ }' )"
+}
+
+# f_geom_reset
+#
+# Reset the registered GEOM chain.
+#
+f_geom_reset()
+{
+ local classn=1 class ngeoms geomn geom
+ while [ $classn -le ${NGEOM_CLASSES:-0} ]; do
+ class=geom_class_$classn
+ $class get ngeoms ngeoms
+ geomn=1
+ while [ $geomn -le $ngeoms ]; do
+ f_struct_free ${class}_geom_$geomn
+ geomn=$(( $geomn + 1 ))
+ done
+ classn=$(( $classn + 1 ))
+ done
+ NGEOM_CLASSES=0
+}
+
+# f_geom_rescan
+#
+# Rescan all GEOMs - convenience function.
+#
+f_geom_rescan()
+{
+ f_geom_reset
+ f_geom_get_all
+}
+
+# f_geom_find $name [$type [$var_to_set]]
+#
+# Find one or more registered GEOMs by name, type, or both. Returns a space-
+# separated list of GEOMs matching the search criterion. The $type argument
+# should be the GEOM class (see $GEOM_CLASS_* variables in GLOBALS above).
+#
+# If $var_to_set is missing or NULL, the GEOM name(s) are printed to standard
+# out for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example, when called in a loop).
+#
+f_geom_find()
+{
+ local __name="$1" __type="${2:-$GEOM_CLASS_ANY}" __var_to_set="$3"
+ local __classn=1 __class __class_name __ngeoms
+ local __geomn __geom __geom_name __found=
+ while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
+ __class=geom_class_$__classn
+ $__class get name __class_name
+ if [ "$__type" != "$GEOM_CLASS_ANY" -a \
+ "$__type" != "$__class_name" ]
+ then
+ __classn=$(( $__classn + 1 ))
+ continue
+ fi
+
+ __geomn=1
+ $__class get ngeoms __ngeoms || __ngeoms=0
+ while [ $__geomn -le $__ngeoms ]; do
+ __geom=${__class}_geom_$__geomn
+ $__geom get name __geom_name
+ [ "$__name" = "$__geom_name" -o ! "$__name" ] &&
+ __found="$__found $__geom"
+ __geomn=$(( $__geomn + 1 ))
+ done
+ __classn=$(( $__classn + 1 ))
+ done
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "${__found# }"
+ else
+ echo $__found
+ fi
+ [ "$__found" ] # Return status
+}
+
+# f_geom_find_by $prop $find [$type [$var_to_set]]
+#
+# Find GEOM-related struct where $prop of the struct is equal to $find. Returns
+# NULL or the name of the first GEOM struct to match. The $type argument should
+# be one of the following:
+#
+# NULL Find any of the below
+# class Find GEOM_CLASS struct
+# geom Find GEOM_GEOM struct
+# consumer Find GEOM_CONSUMER struct
+# provider Find GEOM_PROVIDER struct
+#
+# The $prop argument can be any property of the given type of struct. Some
+# properties are common to all types (such as id) so the $type argument is
+# optional (allowing you to return any struct whose property matches $find).
+#
+# If $var_to_set is missing or NULL, the GEOM struct name is printed to
+# standard out for capturing in a sub-shell (which is less-recommended because
+# of performance degredation; for example when called in a loop).
+#
+f_geom_find_by()
+{
+ local __prop="$1" __find="$2" __type="$3" __var_to_set="$4"
+ local __classn=1 __class __ngeoms
+ local __geomn __geom __nitems
+ local __itype __itemn __item
+ local __value __found=
+
+ if [ ! "$__prop" ]; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return $FAILURE
+ fi
+
+ case "$__type" in
+ "") : OK ;;
+ class|GEOM_CLASS) __type=class ;;
+ geom|GEOM_GEOM) __type=geom ;;
+ consumer|GEOM_CONSUMER) __type=consumer ;;
+ provider|GEOM_PROVIDER) __type=provider ;;
+ *)
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return $FAILURE
+ esac
+
+ while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
+ __class=geom_class_$__classn
+
+ if [ "${__type:-class}" = "class" ]; then
+ $__class get "$__prop" __value || __value=
+ [ "$__value" = "$__find" ] && __found="$__class" break
+ [ "$__type" ] && __classn=$(( $__classn + 1 )) continue
+ fi
+
+ __geomn=1
+ $__class get ngeoms __ngeoms || __ngeoms=0
+ while [ $__geomn -le $__ngeoms ]; do
+ __geom=${__class}_geom_$__geomn
+
+ if [ "${__type:-geom}" = "geom" ]; then
+ $__geom get "$__prop" __value || __value=
+ [ "$__value" = "$__find" ] &&
+ __found="$__geom" break
+ [ "$__type" ] &&
+ __geomn=$(( $__geomn + 1 )) continue
+ fi
+
+ for __itype in ${__type:-consumer provider}; do
+ $__geom get n${__itype}s __nitems || continue
+ __itemn=1
+ while [ $__itemn -le $__nitems ]; do
+ __item=${__geom}_${__itype}_$__itemn
+
+ $__item get "$__prop" __value ||
+ __value=
+ [ "$__value" = "$__find" ] &&
+ __found="$__item" break
+ __itemn=$(( $__itemn + 1 ))
+ done
+ [ "$__found" ] && break
+ done
+ [ "$__found" ] && break
+ __geomn=$(( $__geomn + 1 ))
+ done
+ [ "$__found" ] && break
+ __classn=$(( $__classn + 1 ))
+ done
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__found"
+ else
+ [ "$__found" ] && echo "$__found"
+ fi
+ [ "$__found" ] # Return status
+}
+
+# f_geom_parent $geom|$consumer|$provider|$config [$var_to_set]
+#
+# Get the GEOM class associated with one of $geom, $consumer, $provider or
+# $config.
+#
+# If $var_to_set is missing or NULL, the GEOM class name is printed to standard
+# out for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example when called in a loop).
+#
+f_geom_parent()
+{
+ local __struct="$1" __var_to_set="$2"
+ # NB: Order of pattern matches below is important
+ case "$__struct" in
+ *_config*) __struct="${__struct%_config*}" ;;
+ *_consumer_*) __struct="${__struct%_consumer_[0-9]*}" ;;
+ *_provider_*) __struct="${__struct%_provider_[0-9]*}" ;;
+ *_geom_*) __struct="${__struct%_geom_[0-9]*}" ;;
+ *) __struct=
+ esac
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__struct"
+ else
+ echo "$__struct"
+ fi
+ f_struct "$__struct" # Return status
+}
+
+############################################################ MAIN
+
+#
+# Parse GEOM configuration unless requested otherwise
+#
+f_dprintf "%s: GEOM_SELF_SCAN_ALL=[%s]" geom.subr "$GEOM_SELF_SCAN_ALL"
+case "$GEOM_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*)
+ f_geom_get_all
+ if [ "$debug" ]; then
+ debug= f_geom_find "" "$GEOM_CLASS_ANY" geoms
+ f_count ngeoms $geoms
+ f_dprintf "%s: Initialized %u geom devices in %u classes." \
+ geom.subr "$ngeoms" "$NGEOM_CLASSES"
+ unset geoms ngeoms
+ fi
+esac
+
+f_dprintf "%s: Successfully loaded." geom.subr
+
+fi # ! $_GEOM_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/keymap.subr b/contrib/bsddialog/bsdconfig/share/keymap.subr
new file mode 100644
index 000000000000..ca6f3c8df841
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/keymap.subr
@@ -0,0 +1,266 @@
+if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1
+#
+# Copyright (c) 2013-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." keymap.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+############################################################ CONFIGURATION
+
+#
+# Defaults taken from usr.sbin/kbdmap/kbdmap.h
+#
+: ${DEFAULT_LANG:=en}
+case "$( sysctl -n kern.vty )" in
+vt) : ${DEFAULT_KEYMAP_DIR:=/usr/share/vt/keymaps} ;;
+*) : ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} ;;
+esac
+
+############################################################ GLOBALS
+
+KEYMAPS=
+NKEYMAPS=0
+
+# A "keymap" from kbdmap's point of view
+f_struct_define KEYMAP \
+ desc \
+ keym \
+ mark
+
+#
+# Default behavior is to call f_keymap_get_all() automatically when loaded.
+#
+: ${KEYMAP_SELF_SCAN_ALL=1}
+
+############################################################ FUNCTIONS
+
+# f_keymap_register $name $desc $keym $mark
+#
+# Register a keymap. A `structure' (see struct.subr) is created with the name
+# keymap_$name (so make sure $name contains only alpha-numeric characters or
+# the underscore, `_'). The remaining arguments after $name correspond to the
+# propertise of the `KEYMAP' structure-type (defined above).
+#
+# If not already registered, the keymap is then appended to the KEYMAPS
+# environment variable, a space-separated list of all registered keymaps.
+#
+f_keymap_register()
+{
+ local name="$1" desc="$2" keym="$3" mark="$4"
+
+ f_struct_new KEYMAP "keymap_$name" || return $FAILURE
+ keymap_$name set desc "$desc"
+ keymap_$name set keym "$keym"
+ keymap_$name set mark "$mark"
+
+ # Scan our global register to see if needs ammending
+ local k found=
+ for k in $KEYMAPS; do
+ [ "$k" = "$name" ] || continue
+ found=1 && break
+ done
+ [ "$found" ] || KEYMAPS="$KEYMAPS $name"
+
+ return $SUCCESS
+}
+
+# f_keymap_checkfile $keymap
+#
+# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap
+# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure.
+# If debugging is enabled, an appropriate debug error message is printed if
+# $keymap is not available.
+#
+f_keymap_checkfile()
+{
+ local keym="$1"
+
+ # Fixup keymap if it doesn't already contain at least one `/'
+ [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
+
+ # Short-cuts
+ [ -f "$keym" -a -r "$keym" ] && return $SUCCESS
+ f_debugging || return $FAILURE
+
+ # Print an appropriate debug error message
+ if [ ! -e "$keym" ]; then
+ f_dprintf "%s: No such file or directory" "$keym"
+ elif [ ! -f "$keym" ]; then
+ f_dprintf "%s: Not a file!" "$keym"
+ elif [ ! -r "$keym" ]; then
+ f_dprintf "%s: Permission denied" "$keym"
+ fi
+
+ return $FAILURE
+}
+
+# f_keymap_get_all
+#
+# Get all keymap information for kbdmap(5) entries both in the database and
+# loosely existing in $DEFAULT_KEYMAP_DIR.
+#
+f_keymap_get_all()
+{
+ local fname=f_keymap_get_all
+ local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
+ [ "$lang" = "C" ] && lang="$DEFAULT_LANG"
+
+ f_dprintf "%s: Looking for keymap files..." $fname
+ f_dialog_info "$msg_looking_for_keymap_files"
+ f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG"
+
+ eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
+ BEGIN {
+ # en_US.ISO8859-1 -> en_..\.ISO8859-1
+ dialect = lang
+ if (length(dialect) >= 6 &&
+ substr(dialect, 3, 1) == "_")
+ dialect = substr(dialect, 1, 3) ".." \
+ substr(dialect, 6)
+ printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
+
+ # en_US.ISO8859-1 -> en
+ lang_abk = lang
+ if (length(lang_abk) >= 3 &&
+ substr(lang_abk, 3, 1) == "_")
+ lang_abk = substr(lang_abk, 1, 2)
+ printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n",
+ lang_abk
+ }
+ function find_token(buffer, token)
+ {
+ if (split(buffer, tokens, /,/) == 0) return 0
+ found = 0
+ for (t in tokens)
+ if (token == tokens[t]) { found = 1; break }
+ return found
+ }
+ function add_keymap(desc,mark,keym)
+ {
+ marks[keym] = mark
+ name = keym
+ gsub(/[^[:alnum:]_]/, "_", name)
+ gsub(/'\''/, "'\''\\'\'\''", desc);
+ printf "f_keymap_checkfile %s && " \
+ "f_keymap_register %s '\'%s\'' %s %u\n",
+ keym, name, desc, keym, mark
+ }
+ !/^[[:space:]]*(#|$)/ {
+ sub(/^[[:space:]]*/, "", $0)
+ keym = $1
+ if (keym ~ /^(MENU|FONT)$/) next
+ lg = ($2 == "" ? lang_default : $2)
+
+ # Match the entry and store the type of match we made
+ # as the mark value (so that if we make a better match
+ # later on with a higher mark, it overwrites previous)
+
+ mark = marks[keym];
+ if (find_token(lg, lang))
+ add_keymap($3, 4, keym) # Best match
+ else if (mark <= 3 && find_token(lg, dialect))
+ add_keymap($3, 3, keym)
+ else if (mark <= 2 && find_token(lg, lang_abk))
+ add_keymap($3, 2, keym)
+ else if (mark <= 1 && find_token(lg, lang_default))
+ add_keymap($3, 1, keym)
+ else if (mark <= 0)
+ add_keymap($3, 0, keym)
+ }
+ ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
+
+
+ #
+ # Look for keymaps not in database
+ #
+ local direntry keym name
+ set +f # glob
+ for direntry in "$DEFAULT_KEYMAP_DIR"/*; do
+ [ "${direntry##*.}" = ".kbd" ] || continue
+ keym="${direntry##*/}"
+ f_str2varname "$keym" name
+ f_struct keymap_$name && continue
+ f_keymap_checkfile "$keym" &&
+ f_keymap_register $name "${keym%.*}" "$keym" 0
+ f_dprintf "%s: not in kbdmap(5) database" "$keym"
+ done
+
+ #
+ # Sort the items by their descriptions
+ #
+ f_dprintf "%s: Sorting keymap entries by description..." $fname
+ KEYMAPS=$(
+ for k in $KEYMAPS; do
+ echo -n "$k "
+ # NOTE: Translate '8x8' to '8x08' before sending to
+ # sort(1) so that things work out as we might expect.
+ debug= keymap_$k get desc | awk 'gsub(/8x8/,"8x08")||1'
+ done | sort -k2 | awk '{
+ printf "%s%s", (started ? " " : ""), $1; started = 1
+ }'
+ )
+
+ return $SUCCESS
+}
+
+# f_keymap_kbdcontrol $keymap
+#
+# Install keyboard map file from $keymap.
+#
+f_keymap_kbdcontrol()
+{
+ local keymap="$1"
+
+ [ "$keymap" ] || return $SUCCESS
+
+ # Fixup keymap if it doesn't already contain at least one `/'
+ [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
+
+ [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
+}
+
+############################################################ MAIN
+
+#
+# Scan for keymaps unless requeted otherwise
+#
+f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
+case "$KEYMAP_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_keymap_get_all
+esac
+
+f_count NKEYMAPS $KEYMAPS
+f_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS
+
+f_dprintf "%s: Successfully loaded." keymap.subr
+
+fi # ! $_KEYMAP_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/Makefile b/contrib/bsddialog/bsdconfig/share/media/Makefile
new file mode 100644
index 000000000000..e8ec319a0ae4
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/media
+FILES= any.subr cdrom.subr common.subr directory.subr dos.subr \
+ floppy.subr ftp.subr http.subr httpproxy.subr network.subr \
+ nfs.subr options.subr tcpip.subr ufs.subr usb.subr wlan.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/share/media/Makefile.depend b/contrib/bsddialog/bsdconfig/share/media/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/share/media/any.subr b/contrib/bsddialog/bsdconfig/share/media/any.subr
new file mode 100644
index 000000000000..516d2d2bd4ba
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/any.subr
@@ -0,0 +1,149 @@
+if [ ! "$_MEDIA_ANY_SUBR" ]; then _MEDIA_ANY_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/any.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/cdrom.subr
+f_include $BSDCFG_SHARE/media/directory.subr
+f_include $BSDCFG_SHARE/media/dos.subr
+f_include $BSDCFG_SHARE/media/floppy.subr
+f_include $BSDCFG_SHARE/media/ftp.subr
+f_include $BSDCFG_SHARE/media/http.subr
+f_include $BSDCFG_SHARE/media/httpproxy.subr
+f_include $BSDCFG_SHARE/media/nfs.subr
+f_include $BSDCFG_SHARE/media/options.subr
+f_include $BSDCFG_SHARE/media/ufs.subr
+f_include $BSDCFG_SHARE/media/usb.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+MEDIA_HELPFILE=$BSDCFG_LIBE/include/media.hlp
+
+############################################################ FUNCTIONS
+
+# f_media_get_type
+#
+# Prompt the user to select amongst the known media types (included above).
+#
+# If the user does not cancel or press Esc, invokes the f_media_set_* function
+# associated with the chosen media type. If after all that we have a struct
+# named `device_media' then success is returned, otherwise failure.
+#
+# NOTE: The f_media_set_* function should create the `device_media' struct.
+# See `struct.subr' and the above `media/*.subr' includes for more details.
+#
+f_media_get_type()
+{
+ f_dialog_title "$msg_choose_installation_media"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local prompt="$msg_choose_installation_media_description"
+ local menu_list="
+ '1 $msg_cd_dvd' '$msg_install_from_a_freebsd_cd_dvd'
+ '2 $msg_ftp' '$msg_install_from_an_ftp_server'
+ '3 $msg_http_proxy'
+ '$msg_install_from_an_ftp_server_thru_proxy'
+ '4 $msg_http_direct' '$msg_install_from_an_http_server'
+ '5 $msg_directory' '$msg_install_from_the_existing_filesystem'
+ '6 $msg_nfs' '$msg_install_over_nfs'
+ '7 $msg_dos' '$msg_install_from_a_dos_partition'
+ '8 $msg_ufs' '$msg_install_from_a_ufs_partition'
+ '9 $msg_floppy' '$msg_install_from_a_floppy_disk_set'
+ 'A $msg_usb' '$msg_install_from_a_usb_drive'
+ 'X $msg_options' '$msg_view_set_various_media_options'
+ " # END-QUOTE
+ local hline="$hline_choose_help_for_more_information_on_media_types"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local mtag
+ while :; do
+ mtag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize mtag
+ f_dprintf "retval=%s mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$MEDIA_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ return $FAILURE
+ fi
+
+ case "$mtag" in
+ ?" $msg_cd_dvd") f_media_set_cdrom ;;
+ ?" $msg_ftp") f_media_set_ftp ;;
+ ?" $msg_http_proxy") f_media_set_http_proxy ;;
+ ?" $msg_http_direct") f_media_set_http ;;
+ ?" $msg_directory") f_media_set_directory ;;
+ ?" $msg_dos") f_media_set_dos ;;
+ ?" $msg_nfs") f_media_set_nfs ;;
+ ?" $msg_ufs") f_media_set_ufs ;;
+ ?" $msg_floppy") f_media_set_floppy ;;
+ ?" $msg_usb") f_media_set_usb ;;
+ ?" $msg_options")
+ f_media_options_menu
+ continue
+ ;;
+ esac
+ break
+ done
+
+ f_struct device_media || return $FAILURE
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/any.subr
+
+fi # ! $_MEDIA_ANY_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/cdrom.subr b/contrib/bsddialog/bsdconfig/share/media/cdrom.subr
new file mode 100644
index 000000000000..bbbd638fec6e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/cdrom.subr
@@ -0,0 +1,217 @@
+if [ ! "$_MEDIA_CDROM_SUBR" ]; then _MEDIA_CDROM_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/cdrom.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+CDROM_MOUNTED=
+CDROM_PREVIOUSLY_MOUNTED=
+CDROM_INIT_QUIET=
+
+############################################################ FUNCTIONS
+
+# f_media_set_cdrom
+#
+# Return success if we both found and set the media type to be a CD.
+#
+f_media_set_cdrom()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_CDROM devs
+ f_count ndevs $devs
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_interactive && f_show_msg "$msg_no_cd_dvd_devices_found"
+ return $FAILURE
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
+ local title="$msg_choose_a_cd_dvd_type"
+ local prompt="$msg_please_select_a_cd_dvd_drive"
+ local hline=
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_CDROM \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
+
+ f_struct_copy "$dev" device_media
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_cdrom $device
+#
+# Initializes the CDROM media device. Returns success if able to mount the CD
+# device using mount_cd9660(8).
+#
+f_media_init_cdrom()
+{
+ local funcname=f_media_init_cdrom
+ local dev="$1" devname err
+
+ f_struct "$dev" get devname devname || return $FAILURE
+ f_dprintf "Init routine called for CDROM device. devname=[%s]" \
+ "$devname"
+
+ if [ "$CDROM_MOUNTED" ]; then
+ f_dprintf "CDROM device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
+ fi
+
+ if ! f_eval_catch -dk err $funcname mount_cd9660 \
+ 'mount_cd9660 "%s" "%s"' "$devname" "$MOUNTPOINT"
+ then
+ err="${err#mount_cd9660: }"; err="${err#$devname: }"
+ case "$err" in
+ "Device busy")
+ # Perhaps the CDROM drive is already mounted as /cdrom
+ if f_mounted /cdrom; then
+ CDROM_PREVIOUSLY_MOUNTED=1
+ MOUNTPOINT=/cdrom
+ err=
+ fi
+ ;;
+ esac
+ case "$err" in
+ "") : good ;; # no error
+ *)
+ [ "$CDROM_INIT_QUIET" ] ||
+ f_show_msg "$msg_error_mounting_device" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+ esac
+ fi
+ CDROM_MOUNTED=1
+
+ : xxx # /cdrom.inf has been deprecated since 9.0-R
+
+ # No other CDROM media validation at this time
+
+ return $SUCCESS
+}
+
+# f_media_get_cdrom $device $file [$probe_type]
+#
+# Returns data from $file on a mounted CDROM device. Similar to cat(1). If
+# $probe_type is present and non-NULL, returns success if $file exists. If
+# $probe_type is equal to $PROBE_SIZE, prints the size of $file in bytes to
+# standard-out.
+#
+f_media_get_cdrom()
+{
+ local dev="$1" file="$2" probe_type="$3"
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_cdrom: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
+}
+
+# f_media_shutdown_cdrom $device
+#
+# Shuts down the CDROM device. Return status should be ignored.
+#
+f_media_shutdown_cdrom()
+{
+ local funcname=f_media_shutdown_cdrom
+ local dev="$1" err
+
+ [ "$CDROM_MOUNTED" ] || return $FAILURE
+
+ if [ "$CDROM_PREVIOUSLY_MOUNTED" ]; then
+ CDROM_MOUNTED=
+ return $SUCCESS
+ fi
+
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_cdrom_dvd" \
+ "$MOUNTPOINT" "$err"
+ else
+ CDROM_MOUNTED=
+ fi
+}
+
+# f_media_eject_cdrom $device
+#
+# Eject the media from the CDROM device. Returns success.
+#
+f_media_eject_cdrom()
+{
+ local funcname=f_media_eject_cdrom
+ local dev="$1" name devname err
+
+ f_struct "$dev" || return $SUCCESS
+ $dev get name name || return $SUCCESS
+ $dev get devname devname || return $SUCCESS
+
+ # Don't eject labels
+ case "$name" in */*) return $SUCCESS; esac
+
+ f_dprintf "Ejecting CDROM/DVD at %s" "$devname"
+ if ! f_eval_catch -dk err $funcname cdcontrol \
+ 'cdcontrol -f "%s" eject' "$devname"
+ then
+ f_dprintf "Could not eject the CDROM/DVD from %s: %s" \
+ "$devname" "${err#cdcontrol: }"
+ fi
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/cdrom.subr
+
+fi # ! $_MEDIA_CDROM_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/common.subr b/contrib/bsddialog/bsdconfig/share/media/common.subr
new file mode 100644
index 000000000000..0bd420d58b38
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/common.subr
@@ -0,0 +1,155 @@
+if [ ! "$_MEDIA_COMMON_SUBR" ]; then _MEDIA_COMMON_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/common.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/media/any.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+############################################################ GLOBALS
+
+#
+# Where to mount media
+#
+MOUNTPOINT=/dist
+
+#
+# Media probe values to use for `f_media_get_TYPE media $file $PROBE' or
+# `f_device_get device_media $file $PROBE' (where $PROBE is one of the below
+# values).
+#
+PROBE_EXIST=1
+PROBE_SIZE=2
+
+############################################################ FUNCTIONS
+
+# f_media_open
+#
+# Returms success if able to initialize the media device.
+#
+f_media_open()
+{
+ f_dprintf "f_media_open: Verifying and initiliazing media device"
+ { # Verify and initialize device media if-defined
+ f_struct device_media &&
+ f_media_verify &&
+ f_device_init device_media
+ } || return $FAILURE
+}
+
+# f_media_close
+#
+# Shuts down the media device, see f_device_shutdown() from device.subr for
+# more details.
+#
+f_media_close()
+{
+ f_dprintf "f_media_close: Shutting down media device"
+ f_struct device_media &&
+ f_device_shutdown device_media
+ f_struct_free device_media
+}
+
+# f_media_verify
+#
+# Returns success if the media device is available, and if not, prompts the
+# user to select a media type. See f_media_get_type() from media/any.subr for
+# more details.
+#
+f_media_verify()
+{
+ f_dprintf "f_media_verify: Verifying media device"
+ f_struct device_media || f_media_get_type
+}
+
+# f_media_generic_get $base $file [$probe_type]
+#
+# A generic open which follows a well-known "path" of places to look. If
+# $probe_type is present and non-NULL, returns success if $file exists. If
+# $probe_type is equal to $PROBE_SIZE, prints the size of $file in bytes to
+# standard-out.
+#
+f_media_generic_get()
+{
+ local funcname=f_media_generic_get
+ local base="$1" file="$2" probe_type="$3"
+
+ local fname=f_media_generic_get
+ f_dprintf "%s: base=[%s] files=[%s] probe_type=%s" \
+ $fname "$base" "$file" "$probe_type"
+
+ local rel path
+ f_getvar $VAR_RELNAME rel
+ for path in \
+ "$base/$file" \
+ "$base/FreeBSD/$file" \
+ "$base/releases/$file" \
+ "$base/$rel/$file" \
+ ; do
+ if [ -f "$path" -a -r "$path" ]; then
+ f_dprintf "%s: file exists path=[%s]" $fname "$path"
+ if [ "$probe_type" = "$PROBE_SIZE" ]; then
+ local size
+ f_eval_catch -dk size $funcname stat \
+ 'stat -f %%z "%s"' "$path" || size=-1
+ f_isinteger "$size" || size=-1
+ echo $size
+ fi
+ [ "$probe_type" ] && return $SUCCESS
+ cat "$path"
+ return $?
+ fi
+ done
+
+ path="$base/releases/$rel/$file" # Final path to try
+ if [ -f "$path" -a -r "$path" ]; then
+ f_dprintf "%s: file exists path=[%s]" $fname "$path"
+ if [ "$probe_type" = "$PROBE_SIZE" ]; then
+ local size
+ f_eval_catch -dk size $funcname stat \
+ 'stat -f %%z "%s"' "$path" || size=-1
+ f_isinteger "$size" || size=-1
+ echo $size
+ fi
+ [ "$probe_type" ] && return $SUCCESS
+ elif [ "$probe_type" ]; then
+ [ "$probe_type" = "$PROBE_SIZE" ] && echo "-1"
+ return $FAILURE
+ fi
+ cat "$base/releases/$rel/$file" # Final path to try
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/common.subr
+
+fi # ! $_MEDIA_COMMON_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/directory.subr b/contrib/bsddialog/bsdconfig/share/media/directory.subr
new file mode 100644
index 000000000000..004cb74bb07e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/directory.subr
@@ -0,0 +1,151 @@
+if [ ! "$_MEDIA_DIRECTORY_SUBR" ]; then _MEDIA_DIRECTORY_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/directory.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+DIRECTORY_CHECKED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_directory
+#
+# Return success if we both found and set the media type to be a local
+# directory.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_DIRECTORY_PATH
+# Path to an existing directory containing the FreeBSD
+# distribution files.
+#
+f_media_set_directory()
+{
+ local path
+
+ f_media_close
+
+ f_variable_get_value $VAR_DIRECTORY_PATH \
+ "$msg_enter_a_fully_qualified_pathname_for_the_directory"
+ f_getvar $VAR_DIRECTORY_PATH path
+ [ "$path" ] || return $FAILURE
+
+ f_struct_new DEVICE device_directory
+ device_directory set name "$path"
+ device_directory set get f_media_get_directory
+ device_directory set init f_media_init_directory
+ device_directory set shutdown f_media_shutdown_directory
+ device_directory set private "$path"
+
+ f_struct_copy device_directory device_media
+ f_struct_free device_directory
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_directory $device
+#
+# Initializes the Directory media device. Returns success if the directory path
+# both exists and is a directory.
+#
+f_media_init_directory()
+{
+ local dev="$1" path
+
+ $dev get private path || return $FAILURE
+ f_dprintf "Init routine called for Directory device. path=[%s]" \
+ "$path"
+
+ # Track whether we've been through here before (for remote filesystems
+ # mounted in the directory path, not repeating these queries saves us
+ # valuable time for slow/uncooperative links).
+ if [ "$DIRECTORY_CHECKED" ]; then
+ f_dprintf "Directory device already checked."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$path" ]; then
+ f_show_msg "$msg_no_such_file_or_directory" \
+ "f_media_init_directory" "$path"
+ return $FAILURE
+ elif [ ! -d "$path" ]; then
+ f_show_msg "$msg_not_a_directory" \
+ "f_media_init_directory" "$path"
+ return $FAILURE
+ fi
+ DIRECTORY_CHECKED=1
+ return $SUCCESS
+}
+
+# f_media_get_directory $device $file [$probe_type]
+#
+# Returns data from $file in the existing/current filesystem. Similar to
+# cat(1). If $probe_type is present and non-NULL, returns success if $file
+# exists. If $probe_type is equal to $PROBE_SIZE, prints the size of $file in
+# bytes to standard-out.
+#
+f_media_get_directory()
+{
+ local dev="$1" file="$2" probe_type="$3" path
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_directory: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ $dev get private path
+ f_media_generic_get "$path" "$file" "$probe_type"
+}
+
+# f_media_shutdown_directory $device
+#
+# Shuts down the Directory device. Return status should be ignored.
+#
+f_media_shutdown_directory()
+{
+ DIRECTORY_CHECKED=
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/directory.subr
+
+fi # ! $_MEDIA_DIRECTORY_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/dos.subr b/contrib/bsddialog/bsdconfig/share/media/dos.subr
new file mode 100644
index 000000000000..df91aebcd814
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/dos.subr
@@ -0,0 +1,165 @@
+if [ ! "$_MEDIA_DOS_SUBR" ]; then _MEDIA_DOS_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/dos.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+DOS_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_dos
+#
+# Return success if we both found and set the media type to be a DOS partition.
+#
+f_media_set_dos()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_DOS devs
+ f_count ndevs $devs
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_show_msg "$msg_no_dos_primary_partitions_found"
+ return $FAILURE
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
+ local title="$msg_choose_a_dos_partition"
+ local prompt="$msg_please_select_dos_partition"
+ local hline=
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_DOS \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
+
+ f_struct_copy "$dev" device_media
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_dos $device
+#
+# Initializes the DOS media device. Returns success if able to mount the DOS
+# partition device using mount_msdosfs(8).
+#
+f_media_init_dos()
+{
+ local funcname=f_media_init_dos
+ local dev="$1" devname err
+
+ $dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for DOS device. devname=[%s]" \
+ "$devname"
+
+ if [ "$DOS_MOUNTED" ]; then
+ f_dprintf "DOS device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
+ fi
+
+ if ! f_eval_catch -dk err $funcname mount_msdosfs \
+ 'mount_msdosfs "%s" "%s"' "$devname" "$MOUNTPOINT"
+ then
+ err="${err#mount_msdosfs: }"; err="${err#$devname: }"
+ f_show_msg "$msg_error_mounting_device" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+ fi
+ DOS_MOUNTED=1
+ return $SUCCESS
+}
+
+# f_media_get_dos $device $file [$probe_type]
+#
+# Returns data from $file on a mounted DOS partition device. Similar to cat(1).
+# If $probe_type is present and non-NULL, returns success if $file exists. If
+# $probe_type is equal to $PROBE_SIZE, prints the size of $file in bytes to
+# standard-out.
+#
+f_media_get_dos()
+{
+ local dev="$1" file="$2" probe_type="$3"
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_dos: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
+}
+
+# f_media_shutdown_dos $device
+#
+# Shuts down the DOS partition device using umount(8). Return status should be
+# ignored.
+#
+f_media_shutdown_dos()
+{
+ local funcname=f_media_shutdown_dos
+ local dev="$1" err
+
+ [ "$DOS_MOUNTED" ] || return $FAILURE
+
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_dos_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ DOS_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/dos.subr
+
+fi # ! $_MEDIA_DOS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/floppy.subr b/contrib/bsddialog/bsdconfig/share/media/floppy.subr
new file mode 100644
index 000000000000..bf402e533d33
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/floppy.subr
@@ -0,0 +1,229 @@
+if [ ! "$_MEDIA_FLOPPY_SUBR" ]; then _MEDIA_FLOPPY_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/floppy.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+FLOPPY_MOUNTED=
+FLOPPY_DISTWANTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_floppy
+#
+# Return success if we both found and set the media type to be a floppy.
+#
+f_media_set_floppy()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_FLOPPY devs
+ f_count ndevs $devs
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_interactive && f_show_msg "$msg_no_floppy_devices_found"
+ return $FAILURE
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
+ local title="$msg_choose_a_floppy_drive"
+ local prompt="$msg_please_select_a_floppy_drive"
+ local hline=
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_FLOPPY \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
+
+ f_struct_copy "$dev" device_media
+ fi
+
+ f_struct device_media &&
+ device_media unset private
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_floppy $device
+#
+# Initializes the Floppy media device. Returns success if able to mount the
+# Floppy disk device using either mount_msdosfs(8) or mount(8) (tried in that
+# order).
+#
+f_media_init_floppy()
+{
+ local funcname=f_media_init_floppy
+ local dev="$1" devname err
+
+ $dev get devname devname || return $FAILURE
+ f_dprintf "Init floppy called for %s distribution. devname=[%s]" \
+ "${FLOPPY_DISTWANTED:-some}" "$devname"
+
+ if [ "$FLOPPY_MOUNTED" ]; then
+ f_dprintf "Floppy device already mounted."
+ return $SUCCESS
+ fi
+
+ local mp
+ $dev get private mp
+ if [ ! -e "${mp:=$MOUNTPOINT}" ] && ! f_quietly mkdir -p "$mp"; then
+ f_show_msg "$msg_unable_to_make_directory_mountpoint" \
+ "$mp" "$devname"
+ return $FAILURE
+ fi
+
+ if f_interactive; then
+ local desc
+ $dev get desc desc
+ if [ "$FLOPPY_DISTWANTED" ]; then
+ f_show_msg "$msg_please_insert_floppy_in_drive" "$desc"
+ else
+ f_show_msg "$msg_please_insert_floppy_containing" \
+ "$FLOPPY_DISTWANTED" "$desc"
+ fi
+ fi
+
+ if ! {
+ f_eval_catch -dk err $funcname mount_msdosfs \
+ 'mount_msdosfs -o ro -m 0777 -u 0 -g 0 "%s" "%s"' \
+ "$devname" "$mp" ||
+ f_eval_catch -dk err $funcname mount \
+ 'mount -o ro "%s" "%s"' "$devname" "$mp"
+ }; then
+ err="${err#mount: }"; err="${err#*: }"
+ local name
+ $dev get name name
+ f_show_msg "$msg_error_mounting_floppy_device" \
+ "$name" "$devname" "$mp" "$err"
+ return $FAILURE
+ fi
+ FLOPPY_MOUNTED=1
+ FLOPPY_DISTWANTED=
+ return $SUCCESS
+}
+
+# f_media_get_floppy $device $file [$probe_type]
+#
+# Returns data from $file on a mounted Floppy disk device. Similar to cat(1).
+# If $probe_type is present and non-NULL, limits retries to zero and returns
+# success if $file exists. If $probe_type is equal to $PROBE_SIZE, prints the
+# size of $file in bytes to standard-out.
+#
+f_media_get_floppy()
+{
+ local funcname=f_media_get_floppy
+ local dev="$1" file="$2" probe_type="$3"
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_floppy: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ #
+ # floppies don't use f_media_generic_get() because it's too expensive
+ # to speculatively open files on a floppy disk. Make user get it
+ # right or give up with floppies.
+ #
+ local mp
+ $dev get private mp
+ local fp="${mp:=$MOUNTPOINT}/$file"
+ if ! [ -f "$fp" -a -r "$fp" ]; then
+ local nretries=4
+ [ "$probe_type" = "$PROBE_SIZE" ] && echo "-1"
+ [ "$probe_type" ] && return $FAILURE
+ while ! [ -f "$fp" -a -r "$fp" ]; do
+ if [ $nretries -eq 0 ]; then
+ f_show_msg "$msg_failed_to_get_floppy_file" \
+ "$fp"
+ [ "$probe_type" = "$PROBE_SIZE" ] && echo "-1"
+ return $FAILURE
+ fi
+ FLOPPY_DISTWANTED="$fp"
+ f_media_shutdown_floppy "$dev"
+ f_media_init_floppy "$dev" || return $FAILURE
+ nretries=$(( $nretries - 1 ))
+ done
+ fi
+ #
+ # If we reach here, $file exists
+ #
+ if [ "$probe_type" = "$PROBE_SIZE" ]; then
+ local size
+ f_eval_catch -dk size $funcname stat 'stat -f %%z "%s"' "$fp"
+ f_isinteger "$size" || size=-1
+ echo "$size"
+ fi
+ [ "$probe_type" ] && return $SUCCESS
+ cat "$fp"
+}
+
+# f_media_shutdown_floppy $device
+#
+# Shuts down the Floppy disk device using umount(8). Return status should be
+# ignored.
+#
+f_media_shutdown_floppy()
+{
+ local funcname=f_media_shutdown_floppy
+ local dev="$1" err mp
+
+ [ "$FLOPPY_MOUNTED" ] || return $FAILURE
+
+ $dev get private mp
+ if f_eval_catch -d $funcname umount \
+ 'umount -f "%s"' "${mp:=$MOUNTPOINT}"
+ then
+ FLOPPY_MOUNTED=
+ if f_interactive && [ "$_systemState" != "fixit" ]; then
+ local desc
+ $dev get desc desc
+ f_show_msg "$msg_you_may_remove_the_floppy" "$desc"
+ fi
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/floppy.subr
+
+fi # ! $_MEDIA_FLOPPY_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/ftp.subr b/contrib/bsddialog/bsdconfig/share/media/ftp.subr
new file mode 100644
index 000000000000..1f6f216eb0a9
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/ftp.subr
@@ -0,0 +1,897 @@
+if [ ! "$_MEDIA_FTP_SUBR" ]; then _MEDIA_FTP_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/ftp.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+FTP_SKIP_RESOLV=
+
+URL_MAX=261261 # according to actual fetch(1) test-results
+
+FTP_DIRS="
+ .
+ releases/$UNAME_P
+ snapshots/$UNAME_P
+ pub/FreeBSD
+ pub/FreeBSD/releases/$UNAME_P
+ pub/FreeBSD/snapshots/$UNAME_P
+ pub/FreeBSD-Archive/old-releases/$UNAME_P
+" # END-QUOTE
+
+############################################################ FUNCTIONS
+
+# f_dialog_menu_media_ftp
+#
+# Prompt the user to select from a range of ``built-in'' FTP servers or specify
+# their own. If the user makes a choice and doesn't cancel or press Esc, stores
+# the user's choice in VAR_FTP_PATH (see variables.subr) and returns success.
+#
+f_dialog_menu_media_ftp()
+{
+ f_dialog_title "$msg_please_select_a_freebsd_ftp_distribution_site"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local prompt="$msg_please_select_the_site_closest_to_you_or_other"
+ local menu_list="
+ '$msg_main_site' 'ftp.freebsd.org'
+ 'URL' '$msg_specify_some_other_ftp_site'
+ 'IPv6 $msg_main_site' 'ftp.freebsd.org'
+ ' IPv6 $msg_france' 'ftp4.fr.freebsd.org'
+ ' IPv6 $msg_france #8' 'ftp8.fr.freebsd.org'
+ ' IPv6 $msg_ireland' 'ftp3.ie.freebsd.org'
+ ' IPv6 $msg_japan' 'ftp2.jp.freebsd.org'
+ ' IPv6 $msg_sweden' 'ftp4.se.freebsd.org'
+ ' IPv6 $msg_usa' 'ftp4.us.freebsd.org'
+ '$msg_primary' 'ftp1.freebsd.org'
+ ' $msg_primary #2' 'ftp2.freebsd.org'
+ ' $msg_primary #3' 'ftp3.freebsd.org'
+ ' $msg_primary #4' 'ftp4.freebsd.org'
+ ' $msg_primary #5' 'ftp5.freebsd.org'
+ ' $msg_primary #6' 'ftp6.freebsd.org'
+ ' $msg_primary #7' 'ftp7.freebsd.org'
+ ' $msg_primary #10' 'ftp10.freebsd.org'
+ ' $msg_primary #11' 'ftp11.freebsd.org'
+ ' $msg_primary #12' 'ftp12.freebsd.org'
+ ' $msg_primary #13' 'ftp13.freebsd.org'
+ ' $msg_primary #14' 'ftp14.freebsd.org'
+ '$msg_australia' 'ftp.au.freebsd.org'
+ ' $msg_australia #2' 'ftp2.au.freebsd.org'
+ ' $msg_australia #3' 'ftp3.au.freebsd.org'
+ '$msg_austria' 'ftp.at.freebsd.org'
+ '$msg_brazil' 'ftp2.br.freebsd.org'
+ ' $msg_brazil #3' 'ftp3.br.freebsd.org'
+ ' $msg_brazil #4' 'ftp4.br.freebsd.org'
+ '$msg_bulgaria' 'ftp.bg.freebsd.org'
+ '$msg_china' 'ftp.cn.freebsd.org'
+ '$msg_czech_republic' 'ftp.cz.freebsd.org'
+ '$msg_denmark' 'ftp.dk.freebsd.org'
+ '$msg_finland' 'ftp.fi.freebsd.org'
+ '$msg_france' 'ftp.fr.freebsd.org'
+ ' $msg_france #3' 'ftp3.fr.freebsd.org'
+ ' $msg_france #4' 'ftp4.fr.freebsd.org'
+ ' $msg_france #5' 'ftp5.fr.freebsd.org'
+ ' $msg_france #6' 'ftp6.fr.freebsd.org'
+ ' $msg_france #7' 'ftp7.fr.freebsd.org'
+ ' $msg_france #8' 'ftp8.fr.freebsd.org'
+ '$msg_germany' 'ftp.de.freebsd.org'
+ ' $msg_germany #2' 'ftp2.de.freebsd.org'
+ ' $msg_germany #4' 'ftp4.de.freebsd.org'
+ ' $msg_germany #5' 'ftp5.de.freebsd.org'
+ ' $msg_germany #7' 'ftp7.de.freebsd.org'
+ ' $msg_germany #8' 'ftp8.de.freebsd.org'
+ '$msg_greece' 'ftp.gr.freebsd.org'
+ ' $msg_greece #2' 'ftp2.gr.freebsd.org'
+ '$msg_ireland' 'ftp3.ie.freebsd.org'
+ '$msg_japan' 'ftp.jp.freebsd.org'
+ ' $msg_japan #2' 'ftp2.jp.freebsd.org'
+ ' $msg_japan #3' 'ftp3.jp.freebsd.org'
+ ' $msg_japan #4' 'ftp4.jp.freebsd.org'
+ ' $msg_japan #5' 'ftp5.jp.freebsd.org'
+ ' $msg_japan #6' 'ftp6.jp.freebsd.org'
+ ' $msg_japan #7' 'ftp7.jp.freebsd.org'
+ ' $msg_japan #8' 'ftp8.jp.freebsd.org'
+ ' $msg_japan #9' 'ftp9.jp.freebsd.org'
+ '$msg_korea' 'ftp.kr.freebsd.org'
+ ' $msg_korea #2' 'ftp2.kr.freebsd.org'
+ '$msg_latvia' 'ftp.lv.freebsd.org'
+ '$msg_netherlands' 'ftp.nl.freebsd.org'
+ ' $msg_netherlands #2' 'ftp2.nl.freebsd.org'
+ '$msg_new_zealand' 'ftp.nz.freebsd.org'
+ '$msg_norway' 'ftp.no.freebsd.org'
+ '$msg_poland' 'ftp.pl.freebsd.org'
+ '$msg_russia' 'ftp.ru.freebsd.org'
+ ' $msg_russia #2' 'ftp2.ru.freebsd.org'
+ ' $msg_russia #5' 'ftp5.ru.freebsd.org'
+ ' $msg_russia #6' 'ftp6.ru.freebsd.org'
+ '$msg_slovak_republic' 'ftp.sk.freebsd.org'
+ ' $msg_slovak_republic #2' 'ftp2.sk.freebsd.org'
+ '$msg_slovenia' 'ftp.si.freebsd.org'
+ '$msg_south_africa' 'ftp.za.freebsd.org'
+ ' $msg_south_africa #2' 'ftp2.za.freebsd.org'
+ ' $msg_south_africa #4' 'ftp4.za.freebsd.org'
+ '$msg_sweden' 'ftp.se.freebsd.org'
+ ' $msg_sweden #2' 'ftp2.se.freebsd.org'
+ ' $msg_sweden #4' 'ftp4.se.freebsd.org'
+ '$msg_switzerland' 'ftp.ch.freebsd.org'
+ '$msg_taiwan' 'ftp.tw.freebsd.org'
+ ' $msg_taiwan #2' 'ftp2.tw.freebsd.org'
+ ' $msg_taiwan #3' 'ftp3.tw.freebsd.org'
+ ' $msg_taiwan #4' 'ftp4.tw.freebsd.org'
+ ' $msg_taiwan #6' 'ftp6.tw.freebsd.org'
+ ' $msg_taiwan #11' 'ftp11.tw.freebsd.org'
+ '$msg_uk' 'ftp.uk.freebsd.org'
+ ' $msg_uk #2' 'ftp2.uk.freebsd.org'
+ ' $msg_uk #3' 'ftp3.uk.freebsd.org'
+ ' $msg_uk #4' 'ftp4.uk.freebsd.org'
+ ' $msg_uk #5' 'ftp5.uk.freebsd.org'
+ '$msg_ukraine' 'ftp.ua.freebsd.org'
+ '$msg_usa #1' 'ftp1.us.freebsd.org'
+ ' $msg_usa #2' 'ftp2.us.freebsd.org'
+ ' $msg_usa #3' 'ftp3.us.freebsd.org'
+ ' $msg_usa #4' 'ftp4.us.freebsd.org'
+ ' $msg_usa #5' 'ftp5.us.freebsd.org'
+ ' $msg_usa #6' 'ftp6.us.freebsd.org'
+ ' $msg_usa #8' 'ftp8.us.freebsd.org'
+ ' $msg_usa #10' 'ftp10.us.freebsd.org'
+ ' $msg_usa #11' 'ftp11.us.freebsd.org'
+ ' $msg_usa #13' 'ftp13.us.freebsd.org'
+ ' $msg_usa #14' 'ftp14.us.freebsd.org'
+ ' $msg_usa #15' 'ftp15.us.freebsd.org'
+ " # END-QUOTE
+ local hline="$msg_select_a_site_thats_close"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local mtag
+ mtag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $DIALOG_CANCEL
+ f_dialog_data_sanitize mtag
+
+ case "$mtag" in
+ URL) setvar $VAR_FTP_PATH "other" ;;
+ *)
+ local value
+ value=$( eval f_dialog_menutag2item \"\$mtag\" $menu_list )
+ setvar $VAR_FTP_PATH "ftp://$value"
+ esac
+
+ return $DIALOG_OK
+}
+
+# f_media_set_ftp
+#
+# Return success if we both found and set the media type to be an FTP server.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_FTP_PATH
+# Can be a URL (including "ftp://" protocol-prefix) or "other"
+# (user is prompted to enter FTP URL). If a URL, can optionally
+# contain directory prefix after hostname/port. Valid examples
+# include:
+# ftp://myhost
+# ftp://somename:21/pub/
+# ftp://192.168.2.3/pub/
+# ftp://[::1]:21/
+# The default port if not specified is 21.
+# VAR_NAMESERVER [Optional]
+# If set, overrides resolv.conf(5) and sets the nameserver that
+# is used to convert names into addresses (when a name converts
+# into multiple addresses, the first address to successfully
+# connect is used).
+#
+# Meanwhile, the following variables from variable.subr are set after
+# successful execution:
+#
+# VAR_FTP_HOST
+# The FTP host to connect to, parsed from VAR_FTP_PATH. In the
+# example case of IPv6 where VAR_FTP_PATH is "ftp://[::1]", this
+# variable will be set to "::1" (the outer brackets are removed).
+# VAR_FTP_PORT
+# The TCP port to connect to, parsed from VAR_FTP_PATH. Usually
+# 21 unless VAR_FTP_PATH was of one of the following forms:
+# ftp://hostname:OTHER_PORT
+# ftp://hostname:OTHER_PORT/*
+# ftp://ip:OTHER_PORT
+# ftp://ip:OTHER_PORT/*
+# ftp://[ip6]:OTHER_PORT
+# ftp://[ip6]:OTHER_PORT/*
+# VAR_FTP_DIR
+# If VAR_FTP_PATH contained a directory element (e.g.,
+# "ftp://localhost/pub") this variable contains only the
+# directory element (e.g., "/pub").
+#
+f_media_set_ftp()
+{
+ f_media_close
+
+ local url
+ f_getvar $VAR_FTP_PATH url
+
+ # If we've been through here before ...
+ if f_struct device_network && [ "${url#$msg_other}" ]; then
+ f_dialog_yesno "$msg_reuse_old_ftp_site_selection_values" ||
+ url=
+ fi
+
+ if [ ! "$url" ]; then
+ f_dialog_menu_media_ftp || return $FAILURE
+ f_getvar $VAR_FTP_PATH url
+ fi
+ [ "$url" ] || return $FAILURE
+
+ case "$url" in
+ other)
+ setvar $VAR_FTP_PATH "ftp://"
+ f_variable_get_value $VAR_FTP_PATH \
+ "$msg_please_specify_url_of_a_freebsd_distribution"
+ f_getvar $VAR_FTP_PATH url
+ if [ ! "${url#ftp://}" ]; then
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ if [ ${#url} -gt ${URL_MAX:-261261} ]; then
+ f_show_msg "$msg_length_of_specified_url_is_too_long" \
+ ${#url} ${URL_MAX:-261261}
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ case "$url" in
+ ftp://*) : valid URL ;;
+ *)
+ f_show_msg "$msg_sorry_invalid_url" "$url"
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ esac
+ esac
+ case "$url" in
+ ftp://*) : valid URL ;;
+ *)
+ f_show_msg "$msg_sorry_invalid_url" "$url"
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ esac
+
+ # Set the name of the FTP device to the URL
+ f_struct_new DEVICE device_ftp
+ device_ftp set name "$url"
+
+ if ! f_struct device_network ||
+ ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
+ then
+ f_struct device_network &&
+ f_device_shutdown device_network
+ if ! f_device_select_tcp; then
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ local dev if
+ f_getvar $VAR_NETWORK_DEVICE if
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_struct_copy "$dev" device_network
+ fi
+ if ! f_device_init device_network; then
+ f_dprintf "f_media_set_ftp: %s" "$msg_net_device_init_failed"
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+
+ local hostname="${url#*://}" port=21 dir=/
+ case "$hostname" in
+ #
+ # The order in-which the below individual cases appear is important!
+ #
+ "["*"]":*/*) # IPv6 address with port and directory
+ f_dprintf "Looks like an IPv6 addr with port/dir: %s" \
+ "$hostname"
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ "["*"]":*) # IPv6 address with port
+ f_dprintf "Looks like an IPv6 addr with port: %s" "$hostname"
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ "["*"]"/*) # IPv6 address with directory
+ f_dprintf "Looks like an IPv6 addr with dir: %s" "$hostname"
+ hostname="${hostname#\[}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%\]*}"
+ ;;
+ "["*"]") # IPv6 address
+ f_dprintf "Looks like an IPv6 addr: %s" "$hostname"
+ hostname="${hostname#\[}"
+ hostname="${hostname%\]}"
+ ;;
+ #
+ # ^^^ IPv6 above / DNS Name or IPv4 below vvv
+ #
+ *:*/*) # DNS name or IPv4 address with port and directory
+ f_dprintf "Looks like a %s with port/dir: %s" \
+ "DNS name or IPv4 addr" "$hostname"
+ port="${hostname#*:}"
+ port="${port%%[!0-9]*}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%:*}"
+ ;;
+ *:*) # DNS name or IPv4 address with port
+ f_dprintf "Looks like a DNS name or IPv4 addr with port: %s" \
+ "$hostname"
+ port="${hostname#*:}"
+ hostname="${hostname%%:*}"
+ ;;
+ */*) # DNS name or IPv4 address with directory
+ f_dprintf "Looks like a DNS name or IPv4 addr with dir: %s" \
+ "$hostname"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%/*}"
+ ;;
+ *) # DNS name or IPv4 address
+ f_dprintf "Looks like a DNS name or IPv4 addr: %s" "$hostname"
+ : leave hostname as-is
+ esac
+
+ f_dprintf "hostname = \`%s'" "$hostname"
+ f_dprintf "dir = \`%s'" "$dir"
+ f_dprintf "port \# = \`%d'" "$port"
+
+ local ns
+ f_getvar $VAR_NAMESERVER ns
+ [ "$ns" ] || f_resolv_conf_nameservers ns
+ if [ "$ns" -a ! "$FTP_SKIP_RESOLV" ] && ! {
+ f_validate_ipaddr "$hostname" ||
+ f_validate_ipaddr6 "$hostname"
+ }; then
+ f_show_info "$msg_looking_up_host" "$hostname"
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_set_ftp" "$hostname"
+ if ! f_quietly f_host_lookup "$hostname"; then
+ f_show_msg "$msg_cannot_resolve_hostname" "$hostname"
+ f_struct device_network &&
+ f_device_shutdown device_network
+ f_struct_free device_network
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ f_dprintf "Found DNS entry for %s successfully." "$hostname"
+ fi
+
+ setvar $VAR_FTP_HOST "$hostname"
+ setvar $VAR_FTP_PORT "$port"
+ setvar $VAR_FTP_DIR "$dir"
+
+ device_ftp set type $DEVICE_TYPE_FTP
+ device_ftp set init f_media_init_ftp
+ device_ftp set get f_media_get_ftp
+ device_ftp set shutdown f_media_shutdown_ftp
+ device_ftp set private device_network
+ f_struct_copy device_ftp device_media
+ f_struct_free device_ftp
+
+ return $SUCCESS
+}
+
+# f_media_set_ftp_active
+#
+# Wrapper to f_media_set_ftp to access FTP servers actively.
+#
+f_media_set_ftp_active()
+{
+ setvar $VAR_FTP_STATE "active"
+ f_media_set_ftp
+}
+
+# f_media_set_ftp_passive
+#
+# Wrapper to f_media_set_ftp to access FTP servers passively.
+#
+f_media_set_ftp_passive()
+{
+ setvar $VAR_FTP_STATE "passive"
+ f_media_set_ftp
+}
+
+# f_media_set_ftp_userpass
+#
+# Prompt the user to enter/confirm the username/password variables that will
+# be used to communicate with the FTP servers. Returns success if the user does
+# not cancel or press Esc to either username or password.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_FTP_USER
+# The username to send via ftp(1) when connecting to an FTP
+# server.
+# VAR_FTP_PASS
+# The password to send with the above username.
+#
+# Does not prompt for confirmation of values if VAR_NONINTERACTIVE is set (see
+# variable.subr for more information).
+#
+f_media_set_ftp_userpass()
+{
+ local user pass
+ f_variable_get_value $VAR_FTP_USER \
+ "$msg_please_enter_the_username_you_wish_to_login_as"
+ f_getvar $VAR_FTP_USER user
+ if [ "$user" ]; then
+ f_variable_get_value $VAR_FTP_PASS \
+ "$msg_please_enter_the_password_for_this_user"
+ f_getvar $VAR_FTP_PASS pass
+ else
+ pass=
+ fi
+ [ "$pass" ] # Return status
+}
+
+# f_device_network_up $device
+#
+# Brings up attached network device, if any - takes FTP device as arg.
+#
+f_device_network_up()
+{
+ local dev="$1" netDev
+ f_struct "$dev" || return $FAILURE
+ $dev get private netDev || return $SUCCESS # No net == happy net
+debug=1 f_dprintf "netDev=[$netDev]"
+ f_device_init $netDev
+}
+
+# f_device_network_down $device
+#
+# Brings down attached network device, if any - takes FTP device as arg.
+#
+f_device_network_down()
+{
+ local dev="$1" netDev
+ f_struct "$dev" || return $FAILURE
+ $dev get private netDev || return $SUCCESS
+ f_device_shutdown $netDev
+}
+
+# f_media_init_ftp $device
+#
+# Initializes the FTP media device. Returns success if both able to log into
+# the FTP server and confirm the existence of at least one known release path
+# using ftp(1).
+#
+# Variables from variable.subr used to initialize the connection are as follows
+# (all of which are configured by f_media_set_ftp above):
+#
+# VAR_FTP_PATH
+# The unparsed FTP URL representing the server to contact.
+# Usually "ftp://server" for example. Can contain TCP port number
+# and/or directory path (but should not contain username/password
+# info).
+# VAR_FTP_HOST
+# The FTP host to connect to. Can be an IPv4 address (e.g.,
+# 127.0.0.1), IPv6 address (e.g., ::1), or DNS hostname. Usually
+# set automatically in f_media_set_ftp() by parsing VAR_FTP_PATH.
+# VAR_FTP_PORT
+# The TCP port to connect to. Usually set automatically in
+# f_media_set_ftp() by parsing VAR_FTP_PATH.
+# VAR_FTP_DIR
+# The base FTP directory to use when downloading files from the
+# FTP server. Usually set automatically in f_media_set_ftp() by
+# parsing VAR_FTP_PATH.
+# VAR_FTP_USER [Optional]
+# If unset, defaults to using anonymous access.
+# VAR_FTP_PASS [Optional]
+# If unset, defaults to a sensible value.
+#
+# In addition, the following (managed either manually or by f_media_set_ftp_*):
+#
+# VAR_FTP_STATE
+# Sets FTPMODE for ftp(1) and can be one of:
+# active active mode FTP only
+# auto automatic determination of passive or active
+# (this is the default)
+# gate gate-ftp mode
+# passive passive mode FTP only
+# See ftp(1) for additional information.
+#
+# And last, but not least (managed automatically or manually):
+#
+# VAR_RELNAME
+# Defaults to being set to $(uname -r) but can be overridden.
+# This sets the name of a release to look for as part of a well
+# known set of paths to search for release data once connected
+# via FTP. If set to "__RELEASE" or "any" then the VAR_FTP_DIR is
+# taken as the absolute path to the release and no further
+# searching is done (see FTP_DIRS above in the GLOBALS section
+# for a list of well known paths that are used when searching for
+# a VAR_RELNAME sub-directory).
+#
+f_media_init_ftp()
+{
+ local dev="$1"
+ local url
+
+ $dev get name url
+ f_dprintf "Init routine called for FTP device. url=[%s]" "$url"
+
+ if [ "$FTP_INITIALIZED" ]; then
+ f_dprintf "FTP device already initialized."
+ return $SUCCESS
+ fi
+
+ # If we can't initialize the network, bag it!
+ f_device_network_up $dev || return $FAILURE
+
+ local cp
+ while :; do
+ f_getvar $VAR_FTP_PATH cp
+ if [ ! "$cp" ]; then
+ if ! f_media_set_ftp ||
+ ! f_getvar $VAR_FTP_PATH cp ||
+ [ ! "$cp" ]
+ then
+ f_show_msg "$msg_unable_to_get_proper_ftp_path"
+ f_device_network_down $dev
+ return $FAILURE
+ fi
+ fi
+
+ local ftp_host ftp_dir
+ if ! {
+ f_getvar $VAR_FTP_HOST ftp_host &&
+ f_getvar $VAR_FTP_DIR ftp_dir
+ }; then
+ f_show_msg "$msg_missing_ftp_host_or_directory"
+ f_device_network_down $dev
+ return $FAILURE
+ fi
+
+ local ftp_port
+ f_getvar $VAR_FTP_PORT ftp_port
+ local host="$ftp_host" port="${ftp_port:+:$ftp_port}"
+ case "$host" in *:*) host="[$host]"; esac
+
+ local user pass use_anon=
+ f_getvar $VAR_FTP_USER user
+ if [ ! "$user" ]; then
+ user="anonymous"
+ use_anon=1
+ fi
+ if ! f_getvar $VAR_FTP_PASS pass; then
+ f_getvar $VAR_HOSTNAME cp
+ if f_running_as_init; then
+ pass="installer@$cp"
+ else
+ local name="$( id -un 2> /dev/null )"
+ pass="${name:-ftp}@$cp"
+ fi
+ fi
+
+ f_show_info "$msg_logging_in_to_user_at_host" \
+ "$user" "$ftp_host"
+
+ local userpass=""
+ if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then
+ userpass="$user${pass:+:$( f_uriencode "$pass" )}"
+ userpass="$userpass${userpass:+@}"
+ fi
+
+ local mode rx
+ f_getvar $VAR_FTP_STATE mode
+
+ if [ "$ftp_dir" ]; then
+ if ! rx=$(
+ printf 'cd "%s"\npwd\n' "$ftp_dir" | eval \
+ FTPMODE=\"\$mode\" \
+ ${use_anon:+FTPANONPASS=\"\$pass\"} \
+ ftp -V ${use_anon:+-a} \
+ \"ftp://\$userpass\$host\$port\" \
+ 2>&1
+ ); then
+ f_show_msg "$msg_couldnt_open_ftp_connection" \
+ "$ftp_host" "$rx"
+ break # to failure
+ fi
+ if echo "$rx" | awk -v dir="/${ftp_dir#/}" '
+ BEGIN {
+ found = 0
+ if ( dir != "/" ) sub("/$", "", dir)
+ }
+ /^Remote directory: / {
+ sub(/^[^:]*:[[:space:]]*/, "")
+ if ($0 != dir) next
+ found = 1; exit
+ }
+ END { exit ! found }
+ '; then
+ setvar $VAR_FTP_DIR "$ftp_dir"
+ setvar $VAR_FTP_PATH \
+ "ftp://$ftp_host/${ftp_dir#/}"
+ else
+ f_show_msg \
+ "$msg_please_check_the_url_and_try_again" \
+ "ftp://$ftp_host/${ftp_dir#/}"
+ break # to failure
+ fi
+ fi
+
+ #
+ # Now that we've verified that the path we're given is ok,
+ # let's try to be a bit intelligent in locating the release we
+ # are looking for. First off, if the release is specified as
+ # "__RELEASE" or "any", then just assume that the current
+ # directory is the one we want and give up.
+ #
+ local rel
+ f_getvar $VAR_RELNAME rel
+ f_dprintf "f_media_init_ftp: rel=[%s]" "$rel"
+
+ case "$rel" in
+ __RELEASE|any)
+ FTP_INITIALIZED=YES
+ return $SUCCESS
+ ;;
+ *)
+ #
+ # Ok, since we have a release variable, let's walk
+ # through the list of directories looking for a release
+ # directory. First successful CWD wins.
+ #
+ if ! rx=$(
+ for dir in $FTP_DIRS; do
+ # Avoid confusing some servers
+ [ "$dir" = "." ] && continue
+ printf 'cd "/%s/%s"\npwd\n' \
+ "$dir" "$rel"
+ done | eval \
+ FTPMODE=\"\$mode\" \
+ ${use_anon:+FTPANONPASS=\"\$pass\"} \
+ ftp -V ${use_anon:+-a} \
+ \"ftp://\$userpass\$host\$port\" \
+ 2>&1
+ ); then
+ f_show_msg "$msg_couldnt_open_ftp_connection" \
+ "$ftp_host" "$rx"
+ break # to failure
+ fi
+
+ local fdir
+ if fdir=$( echo "$rx" | awk '
+ /^Remote directory: / {
+ sub(/^[^:]*:[[:space:]]*/, "")
+ if ($0 == "/") next
+ # Exit after the first dir
+ found++; print; exit
+ }
+ END { exit ! found }
+ ' ); then
+ setvar $VAR_FTP_DIR "$fdir"
+ setvar $VAR_FTP_PATH "ftp://$ftp_host$fdir"
+ FTP_INITIALIZED=YES
+ return $SUCCESS
+ else
+ f_yesno "$msg_cant_find_distribution" \
+ "$rel" "$ftp_host"
+ if [ $? -eq $DIALOG_OK ]; then
+ unset $VAR_FTP_PATH
+ f_media_set_ftp && continue
+ fi
+ fi
+ esac
+ break # to failure
+ done
+
+ unset FTP_INITIALIZED $VAR_FTP_PATH
+ f_device_network_down $dev
+ return $FAILURE
+}
+
+# f_media_get_ftp $device $file [$probe_type]
+#
+# Returns data from $file on an FTP server using ftp(1). Please note that
+# $device is unused but must be present (even if null). Information is instead
+# gathered from the environment. If $probe_type is present and non-NULL,
+# returns success if $file exists. If $probe_type is equal to $PROBE_SIZE,
+# prints the size of $file in bytes to standard-out.
+#
+# Variables from variable.subr used to configure the connection are as follows
+# (all of which are configured by f_media_set_ftp above):
+#
+# VAR_FTP_HOST
+# FTP host to connect to. Can be an IPv4 address, IPv6 address,
+# or DNS hostname of your choice.
+# VAR_FTP_PORT
+# TCP port to connect on; see f_media_set_ftp() above.
+# VAR_FTP_USER [Optional]
+# If unset, defaults to using anonymous access.
+# VAR_FTP_PASS [Optional]
+# If unset, defaults to a sensible value.
+#
+# In addition, the following (managed either manually or by f_media_set_ftp_*):
+#
+# VAR_FTP_STATE
+# Sets FTPMODE for ftp(1) and can be one of:
+# active active mode FTP only
+# auto automatic determination of passive or active
+# (this is the default)
+# gate gate-ftp mode
+# passive passive mode FTP only
+# See ftp(1) for additional information.
+#
+# See variable.subr for additional information.
+#
+# Example usage:
+# f_media_set_ftp
+# f_media_get_ftp media $file
+#
+f_media_get_ftp()
+{
+ local funcname=f_media_get_ftp
+ local dev="$1" file="$2" probe_type="$3" hosts=
+
+ f_dprintf "f_media_get_ftp: dev=[%s] file=[%s] probe_type=%s" \
+ "$dev" "$file" "$probe_type"
+
+ local ftp_host ftp_port
+ f_getvar $VAR_FTP_HOST ftp_host
+ f_getvar $VAR_FTP_PORT ftp_port
+
+ if [ ! "$FTP_INITIALIZED" ]; then
+ f_dprintf "No FTP connection open, can't get file %s" "$file"
+ return $FAILURE
+ fi
+
+ if ! {
+ f_validate_ipaddr "$ftp_host" ||
+ f_validate_ipaddr6 "$ftp_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_get_ftp" "$ftp_host"
+ f_host_lookup "$ftp_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$ftp_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$ftp_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_ftp_server %s:%s" \
+ "$ftp_host" "$ftp_port"
+ return $FAILURE
+ fi
+
+ local user pass use_anon=
+ f_getvar $VAR_FTP_USER user
+ if [ ! "$user" ]; then
+ user="anonymous"
+ use_anon=1
+ fi
+ if ! f_getvar $VAR_FTP_PASS pass; then
+ f_getvar $VAR_HOSTNAME cp
+ if f_running_as_init; then
+ pass="installer@$cp"
+ else
+ local name="$( id -un 2> /dev/null )"
+ pass="${name:-ftp}@$cp"
+ fi
+ fi
+
+ local userpass=""
+ if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then
+ userpass="$user${pass:+:$( f_uriencode "$pass" )}"
+ userpass="$userpass${userpass:+@}"
+ fi
+
+ local dir mode rx
+ f_getvar $VAR_FTP_DIR\#/ dir
+ f_getvar $VAR_FTP_STATE mode
+
+ local port="${ftp_port:+:$ftp_port}"
+ case "$host" in *:*) host="[$host]"; esac
+
+ f_dprintf "sending ftp request for: %s" "ftp://$host$port/$dir/$file"
+
+ if [ "$probe_type" ]; then
+ local url="ftp://$userpass$host$port/$dir/$file" size
+ [ "$use_anon" ] && url="ftp://$host$port/$dir/$file"
+ if ! f_eval_catch -dk size $funcname fetch \
+ 'fetch -s "%s"' "$url" || ! f_isinteger "$size"
+ then
+ f_dprintf "size request failed!"
+ [ "$probe_type" = "$PROBE_SIZE" ] && echo "-1"
+ return $FAILURE
+ fi
+ [ "$probe_type" = "$PROBE_SIZE" ] && echo "$size"
+ return $SUCCESS
+ fi
+
+ eval FTPMODE=\"\$mode\" ${use_anon:+FTPANONPASS=\"\$pass\"} \
+ ftp -V ${use_anon:+-a} -o - \
+ \"ftp://\$userpass\$host\$port/\$dir/\$file\" 2> /dev/null
+ local retval=$?
+
+ [ $retval -eq $SUCCESS ] || f_dprintf "request failed!"
+ return $retval
+}
+
+# f_media_shutdown_ftp $device
+#
+# Shuts down the FTP device. Return status should be ignored. Note that since
+# we don't maintain an open connection to the FTP server there's nothing to do.
+#
+f_media_shutdown_ftp()
+{
+ [ "$FTP_INITIALIZED" ] || return $SUCCESS
+
+ unset FTP_INITIALIZED
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/ftp.subr
+
+fi # ! $_MEDIA_FTP_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/http.subr b/contrib/bsddialog/bsdconfig/share/media/http.subr
new file mode 100644
index 000000000000..b928f7d6a78f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/http.subr
@@ -0,0 +1,688 @@
+if [ ! "$_MEDIA_HTTP_SUBR" ]; then _MEDIA_HTTP_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/http.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+HTTP_SKIP_RESOLV=
+
+URL_MAX=261261
+ # NOTE: This is according to actual fetch(1) test-results. We actually
+ # use nc(1) to retrieve files, but it's still a good idea to keep the
+ # URLs short enough that fetch(1) won't complain.
+
+HTTP_DIRS="
+ .
+ releases/$UNAME_P
+ snapshots/$UNAME_P
+ pub/FreeBSD
+ pub/FreeBSD/releases/$UNAME_P
+ pub/FreeBSD/snapshots/$UNAME_P
+ pub/FreeBSD-Archive/old-releases/$UNAME_P
+" # END-QUOTE
+
+############################################################ FUNCTIONS
+
+# f_dialog_menu_media_http
+#
+# Prompt the user to select from a range of ``built-in'' HTTP servers or
+# specify their own. If the user makes a choice and doesn't cancel or press
+# Esc, stores the user's choice in VAR_FTP_PATH (see variable.subr) and returns
+# success.
+#
+f_dialog_menu_media_http()
+{
+ f_dialog_title "$msg_please_select_a_freebsd_http_distribution_site"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local prompt="$msg_please_select_the_site_closest_to_you_or_other"
+ local menu_list="
+ 'dist $msg_main_site' 'ftp.freebsd.org'
+ 'pkg $msg_main_site' 'pkg.freebsd.org'
+ 'URL' '$msg_specify_some_other_http_site'
+ " # END-QUOTE
+ local hline="$msg_select_a_site_thats_close"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local mtag
+ mtag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $DIALOG_CANCEL
+ f_dialog_data_sanitize mtag
+
+ case "$mtag" in
+ URL) setvar $VAR_HTTP_PATH "other" ;;
+ *)
+ local value
+ value=$( eval f_dialog_menutag2item \"\$mtag\" $menu_list )
+ setvar $VAR_HTTP_PATH "http://$value"
+ esac
+
+ return $DIALOG_OK
+}
+
+# f_media_set_http
+#
+# Return success if we both found and set the media type to be an HTTP server.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_PATH
+# URL containing host and optionally a target path to the release
+# repository on the HTTP server. Valid examples include:
+# http://myhost
+# http://somename:80/pub/
+# http://192.168.2.3/pub/
+# http://[::1]:8000/
+# The default port if not specified is 80.
+# VAR_NAMESERVER [Optional]
+# If set, overrides resolv.conf(5) and sets the nameserver that
+# is used to convert names into addresses (when a name converts
+# into multiple addresses, the first address to successfully
+# connect is used).
+#
+# Meanwhile, the following variables from variable.subr are set after
+# successful execution:
+#
+# VAR_HTTP_HOST
+# The HTTP host to connect to, parsed from VAR_HTTP_PATH. In the
+# example case of IPv6 where VAR_HTTP_PATH is "http://[::1]" this
+# variable will be set to "::1" (the outer brackets are removed).
+# VAR_HTTP_PORT
+# The TCP port to connect to, parsed from VAR_HTTP_PATH. Usually
+# 80 unless VAR_HTTP_PATH was one of the following forms:
+# http://hostname:OTHER_PORT
+# http://hostname:OTHER_PORT/*
+# http://ip:OTHER_PORT
+# http://ip:OTHER_PORT/*
+# http://[ip6]:OTHER_PORT
+# http://[ip6]:OTHER_PORT/*
+# VAR_HTTP_DIR
+# If VAR_HTTP_PATH contained a directory element (e.g.,
+# "http://localhost/pub") this variable contains only the
+# directory element (e.g., "/pub").
+#
+f_media_set_http()
+{
+ f_media_close
+
+ local url
+ f_getvar $VAR_HTTP_PATH url
+
+ # If we've been through here before ...
+ if f_struct device_network && [ "${url#$msg_other}" ]; then
+ f_dialog_yesno "$msg_reuse_old_http_site_settings" || url=
+ fi
+
+ if [ ! "$url" ]; then
+ f_dialog_menu_media_http || return $FAILURE
+ f_getvar $VAR_HTTP_PATH url
+ fi
+ [ "$url" ] || return $FAILURE
+
+ case "$url" in
+ other)
+ setvar $VAR_HTTP_PATH "http://"
+ f_variable_get_value $VAR_HTTP_PATH \
+ "$msg_please_specify_url_of_freebsd_http_distribution"
+ f_getvar $VAR_HTTP_PATH url
+ if [ ! "${url#http://}" ]; then
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ fi
+ if [ ${#url} -gt ${URL_MAX:-261261} ]; then
+ f_show_msg "$msg_length_of_specified_url_is_too_long" \
+ ${#url} ${URL_MAX:-261261}
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ fi
+ case "$url" in
+ http://*) : valid URL ;;
+ *)
+ f_show_msg "$msg_sorry_invalid_url" "$url"
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ esac
+ esac
+ case "$url" in
+ http://*) : valid URL ;;
+ *)
+ f_show_msg "$msg_sorry_invalid_url" "$url"
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ esac
+
+ # Set the name of the HTTP device to the URL
+ f_struct_new DEVICE device_http
+ device_http set name "$url"
+
+ if ! f_struct device_network ||
+ ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
+ then
+ f_struct device_network &&
+ f_device_shutdown device_network
+ if ! f_device_select_tcp; then
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ fi
+ local dev if
+ f_getvar $VAR_NETWORK_DEVICE if
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_struct_copy "$dev" device_network
+ fi
+ if ! f_device_init device_network; then
+ f_dprintf "f_media_set_http: %s" "$msg_net_device_init_failed"
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ fi
+
+ local hostname="${url#*://}" port=80 dir=/
+ case "$hostname" in
+ #
+ # The order in-which the below individual cases appear is important!
+ #
+ "["*"]":*/*) # IPv6 address with port and directory
+ f_dprintf "Looks like an IPv6 addr with port/dir: %s" \
+ "$hostname"
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ "["*"]":*) # IPv6 address with port
+ f_dprintf "Looks like an IPv6 addr with port: %s" "$hostname"
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ "["*"]"/*) # IPv6 address with directory
+ f_dprintf "Looks like an IPv6 addr with dir: %s" "$hostname"
+ hostname="${hostname#\[}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%\]*}"
+ ;;
+ "["*"]") # IPv6 address
+ f_dprintf "Looks like an IPv6 addr: %s" "$hostname"
+ hostname="${hostname#\[}"
+ hostname="${hostname%\]}"
+ ;;
+ #
+ # ^^^ IPv6 above / DNS Name or IPv4 below vvv
+ #
+ *:*/*) # DNS name or IPv4 address with port and directory
+ f_dprintf "Looks like a %s with port/dir: %s" \
+ "DNS name or IPv4 addr" "$hostname"
+ port="${hostname#*:}"
+ port="${port%%[!0-9]*}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%:*}"
+ ;;
+ *:*) # DNS name or IPv4 address with port
+ f_dprintf "Looks like a DNS name or IPv4 addr with port: %s" \
+ "$hostname"
+ port="${hostname#*:}"
+ hostname="${hostname%%:*}"
+ ;;
+ */*) # DNS name or IPv4 address with directory
+ f_dprintf "Looks like a DNS name or IPv4 addr with dir: %s" \
+ "$hostname"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%/*}"
+ ;;
+ *) # DNS name or IPv4 address
+ f_dprintf "Looks like a DNS name or IPv4 addr: %s" "$hostname"
+ : leave hostname as-is
+ esac
+
+ f_dprintf "hostname = \`%s'" "$hostname"
+ f_dprintf "dir = \`%s'" "$dir"
+ f_dprintf "port \# = \`%d'" "$port"
+
+ local ns
+ f_getvar $VAR_NAMESERVER ns
+ [ "$ns" ] || f_resolv_conf_nameservers ns
+ if [ "$ns" -a ! "$HTTP_SKIP_RESOLV" ] && ! {
+ f_validate_ipaddr "$hostname" ||
+ f_validate_ipaddr6 "$hostname"
+ }; then
+ f_show_info "$msg_looking_up_host" "$hostname"
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_set_http" "$hostname"
+ if ! f_quietly f_host_lookup "$hostname"; then
+ f_show_msg "$msg_cannot_resolve_hostname" "$hostname"
+ f_struct device_network &&
+ f_device_shutdown device_network
+ f_struct_free device_network
+ unset $VAR_HTTP_PATH
+ return $FAILURE
+ fi
+ f_dprintf "Found DNS entry for %s successfully." "$hostname"
+ fi
+
+ setvar $VAR_HTTP_HOST "$hostname"
+ setvar $VAR_HTTP_PORT "$port"
+ setvar $VAR_HTTP_DIR "$dir"
+
+ device_http set type $DEVICE_TYPE_HTTP
+ device_http set init f_media_init_http
+ device_http set get f_media_get_http
+ device_http set shutdown f_media_shutdown_http
+ device_http set private device_network
+ f_struct_copy device_http device_media
+ f_struct_free device_http
+
+ return $SUCCESS
+}
+
+# f_http_check_access [$connect_only]
+#
+# Return success if able list a remote HTTP directory. If $connect_only is
+# present and non-null, then returns success if a connection can be made.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_HOST
+# The HTTP server host name, IPv4 address or IPv6 address.
+# Valid examples include:
+# myhost
+# 192.168.2.3
+# ::1
+# VAR_HTTP_PORT
+# The TCP port to connect to when communicating with the server.
+# VAR_HTTP_PATH
+# The HTTP path sent to the server. Unused if $connect_only is
+# present and non-NULL.
+#
+f_http_check_access()
+{
+ local connect_only="$1" hosts=
+
+ local http_host http_port
+ f_getvar $VAR_HTTP_HOST http_host
+ f_getvar $VAR_HTTP_PORT http_port
+
+ if ! {
+ f_validate_ipaddr "$http_host" ||
+ f_validate_ipaddr6 "$http_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_http_check_access" "$http_host"
+ f_host_lookup "$http_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ unset $VAR_HTTP_HOST
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$http_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$http_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_server http://%s:%s/" \
+ "$http_host" "$http_port"
+ unset $VAR_HTTP_HOST
+ return $FAILURE
+ fi
+ [ "$connect_only" ] && return $SUCCESS
+
+ local http_path
+ f_getvar $VAR_HTTP_PATH http_path
+ f_show_info "$msg_checking_access_to" "$http_path"
+
+ local rx
+ case "$http_path" in
+ http://*|/*) : valid request ;;
+ *) http_path="/$http_path" # full URI requests only
+ esac
+ if ! rx=$(
+ printf "GET %s/ HTTP/1.0\r\n\r\n" "${http_path%/}" |
+ nc -n "$host" "$http_port"
+ ); then
+ f_show_msg "$msg_couldnt_connect_to_server http://%s:%s/" \
+ "$http_host" "$http_port"
+ unset $VAR_HTTP_HOST
+ return $FAILURE
+ fi
+
+ local hdr
+ hdr=$( echo "$rx" | awk '/^\r$/{exit}{print}' )
+
+ local http_found=$FAILURE
+ if echo "$hdr" | awk '
+ BEGIN { found = 0 }
+ /^HTTP.... 200 / {
+ found = 1
+ exit
+ }
+ END { exit ! found }
+ '; then
+ http_found=$SUCCESS
+ fi
+
+ return $http_found
+}
+
+# f_media_init_http $device
+#
+# Initializes the HTTP media device. Returns success if able to confirm the
+# existence of at least one known HTTP server release path directly via HTTP
+# using f_http_check_access(), above.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_HOST
+# The HTTP server to connect to. Must be set. Also see
+# f_http_check_access() for additional variables.
+# VAR_RELNAME
+# Usually set to `uname -r' but can be overridden.
+# VAR_HTTP_PATH
+# The HTTP path sent to the server. Usually set by calling
+# f_media_set_http().
+#
+# Meanwhile, after successful execution, the following variables (also from
+# variable.subr) are set:
+#
+# VAR_HTTP_PATH
+# The [possibly] adjusted VAR_HTTP_PATH that was found to contain
+# a valid FreeBSD repository.
+#
+f_media_init_http()
+{
+ local dev="$1"
+ f_dprintf "Init routine called for HTTP device. dev=[%s]" "$dev"
+
+ if [ "$HTTP_INITIALIZED" ]; then
+ f_dprintf "HTTP device already initialized."
+ return $SUCCESS
+ fi
+
+ #
+ # First verify access
+ #
+ local connect_only=1
+ f_http_check_access $connect_only
+
+ local http_host
+ f_getvar $VAR_HTTP_HOST http_host
+ while [ ! "$http_host" ]; do
+ f_media_set_http || return $FAILURE
+ f_http_check_access $connect_only
+ f_getvar $VAR_HTTP_HOST http_host
+ done
+
+ local http_path http_found=$FAILURE
+ while :; do
+ #
+ # Now that we've verified that the path we're given is ok,
+ # let's try to be a bit intelligent in locating the release we
+ # are looking for. First off, if the release is specified as
+ # "__RELEASE" or "any", then just assume that the current
+ # directory is the one we want and give up.
+ #
+ local rel
+ f_getvar $VAR_RELNAME rel
+ f_dprintf "f_media_init_http: rel=[%s]" "$rel"
+
+ case "$rel" in
+ __RELEASE|any)
+ f_getvar $VAR_HTTP_DIR $VAR_HTTP_PATH
+ f_http_check_access
+ http_found=$?
+ ;;
+ *)
+ #
+ # Ok, since we have a release variable, let's walk
+ # through the list of directories looking for a release
+ # directory. First successful path wins.
+ #
+ local fdir hp
+ f_getvar $VAR_HTTP_PATH%/ hp
+ setvar $VAR_HTTP_PATH "$hp/$PKG_ABI/latest"
+ if [ "$PKG_ABI" ] && f_http_check_access; then
+ http_found=$SUCCESS
+ setvar $VAR_HTTP_PATH "$hp"
+ else
+ for fdir in $HTTP_DIRS; do
+ setvar $VAR_HTTP_PATH "$hp/$fdir/$rel"
+ if f_http_check_access; then
+ http_found=$SUCCESS
+ break
+ fi
+ done
+ fi
+ esac
+
+ [ $http_found -eq $SUCCESS ] && HTTP_INITIALIZED=YES break
+
+ f_getvar $VAR_HTTP_PATH http_path
+ f_show_msg "$msg_please_check_the_url_and_try_again" \
+ "$http_path"
+
+ unset HTTP_INITIALIZED $VAR_HTTP_PATH
+ f_media_set_http || break
+ done
+
+ return $http_found
+}
+
+# f_media_get_http $device $file [$probe_type]
+#
+# Returns data from $file on an HTTP server using nc(1). Please note that
+# $device is unused but must be present (even if null). Information is instead
+# gathered from the environment. If $probe_type is both present and non-NULL,
+# this function exits after receiving the HTTP header response from the server
+# (if the HTTP response code is 200, success is returned; otherwise failure).
+# If $probe_type is equal to $PROBE_SIZE, prints the content-length in bytes
+# from the response (or -1 if not found) to standard-out.
+#
+# The variables used to configure the connection are as follows (all of which
+# are configured by f_media_set_http above):
+#
+# VAR_HTTP_HOST
+# HTTP server which to connect. Can be an IPv4 address, IPv6
+# address, or DNS hostname of your choice.
+# VAR_HTTP_PORT
+# TCP port to connect on; see f_media_set_http above.
+# VAR_HTTP_PATH
+# Directory prefix to use when requesting $file. Default is `/'
+# unless f_media_init_http was able to use f_http_check_access
+# to validate one of the defaults in $HTTP_DIRS (see GLOBALS at
+# the top of this file); assuming VAR_RELNAME was not set to
+# either `__RELEASE' or `any' (indicating that the global set of
+# $HTTP_DIRS should be ignored).
+#
+# See variable.subr for additional information.
+#
+# Example usage:
+# f_media_set_http
+# f_media_get_http media $file
+#
+f_media_get_http()
+{
+ local dev="$1" file="$2" probe_type="$3" hosts=
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_http: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ local http_host http_port
+ f_getvar $VAR_HTTP_HOST http_host
+ f_getvar $VAR_HTTP_PORT http_port
+
+ if [ ! "$HTTP_INITIALIZED" ]; then
+ f_dprintf "No HTTP connection open, can't get file %s" "$file"
+ return $FAILURE
+ fi
+
+ if ! {
+ f_validate_ipaddr "$http_host" ||
+ f_validate_ipaddr6 "$http_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_get_http" "$http_host"
+ f_host_lookup "$http_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$http_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$http_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_server http://%s:%s/" \
+ "$http_host" "$http_port"
+ return $FAILURE
+ fi
+
+ local http_path
+ f_getvar $VAR_HTTP_PATH%/ http_path
+ case "$http_path" in
+ http://*|/*) : valid request ;;
+ *) http_path="/$http_path" # full URI requests only
+ esac
+
+ local url="$http_path/$file" rx
+ f_dprintf "sending http request for: %s" "$url"
+ f_dprintf "using nc to connect to: %s:%s" "$host" "$http_port"
+ printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$http_port" |
+ (
+ #
+ # scan the headers of the response
+ # this is extremely quick'n dirty
+ #
+
+ rv=0 length=-1
+ while read LINE; do
+ case "$LINE" in
+ HTTP*)
+ f_dprintf "received response: %s" "$LINE"
+ set -- $LINE; rv=$2
+ f_isinteger "$rv" || rv=0
+ ;;
+ "Content-Length: "*)
+ length="${LINE% }"
+ length="${length#Content-Length: }"
+ f_dprintf "received content-length: %s" \
+ "$length"
+ ;;
+ *)
+ [ "${LINE% }" ] || break # End of headers
+ esac
+ done
+
+ [ $rv -ge 500 ] && exit 5
+ [ $rv -eq 404 ] && exit 44
+ [ $rv -ge 400 ] && exit 4
+ [ $rv -ge 300 ] && exit 3
+ [ $rv -eq 200 ] || exit $FAILURE
+
+ if [ ! "$probe_type" ]; then
+ cat # output the rest ``as-is''
+ elif [ "$probe_type" = "$PROBE_SIZE" ]; then
+ f_isinteger "$length" || length=-1
+ echo "$length"
+ fi
+ exit 200
+ )
+ local retval=$?
+ [ $retval -eq 200 ] && return $SUCCESS
+ [ "$probe_type" ] && return $FAILURE
+
+ case "$retval" in
+ 5) f_show_msg "$msg_server_error_when_requesting_url" "$url" ;;
+ 44) f_show_msg "$msg_url_was_not_found" "$url" ;;
+ 4) f_show_msg "$msg_client_error" ;;
+ *) f_show_msg "$msg_error_when_requesting_url" "$url" ;;
+ esac 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ return $FAILURE
+}
+
+# f_media_shutdown_http $device
+#
+# Shuts down the HTTP device. Return status should be ignored. Note that since
+# we don't maintain an open connection to the HTTP server, nothing to do.
+#
+f_media_shutdown_http()
+{
+ [ "$HTTP_INITIALIZED" ] || return $SUCCESS
+
+ unset HTTP_INITIALIZED
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/http.subr
+
+fi # ! $_MEDIA_HTTP_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/httpproxy.subr b/contrib/bsddialog/bsdconfig/share/media/httpproxy.subr
new file mode 100644
index 000000000000..1ef516f76463
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/httpproxy.subr
@@ -0,0 +1,463 @@
+if [ ! "$_MEDIA_HTTPPROXY_SUBR" ]; then _MEDIA_HTTPPROXY_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/httpproxy.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/ftp.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_media_set_http_proxy
+#
+# Return success if we both found and set the media type to be an ftp server,
+# accessed via http proxy.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_PROXY
+# HTTP Proxy server to use. Valid examples include:
+# myhost
+# somename:3128
+# 192.168.2.3
+# [::1]:8080
+# The default port if not specified is 3128.
+#
+# Variables from variable.subr that are set after successful execution include
+# the following:
+#
+# VAR_HTTP_PROXY_HOST The host portion of VAR_HTTP_PROXY.
+# VAR_HTTP_PROXY_PORT The TCP port parsed from VAR_HTTP_PROXY.
+#
+# See also f_media_set_ftp() for additional variables.
+#
+f_media_set_http_proxy()
+{
+ FTP_SKIP_RESOLV=1 f_media_set_ftp || return $FAILURE
+
+ f_variable_get_value $VAR_HTTP_PROXY \
+ "$msg_please_enter_the_address_of_the_http_proxy"
+
+ local proxy
+ f_getvar $VAR_HTTP_PROXY proxy
+ [ "$proxy" ] || return $FAILURE
+
+ local hostname="$proxy" port=3128
+ case "$hostname" in
+ #
+ # The order in-which the below individual cases appear is important!
+ #
+ "["*"]":*) # IPv6 address with port
+ f_dprintf "Looks like an IPv6 addr with port: %s" "$hostname"
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ "["*"]") # IPv6 address
+ f_dprintf "Looks like an IPv6 addr: %s" "$hostname"
+ hostname="${hostname#\[}"
+ hostname="${hostname%\]}"
+ ;;
+ #
+ # ^^^ IPv6 above / DNS Name or IPv4 below vvv
+ #
+ *:*) # DNS name or IPv4 address with port
+ f_dprintf "Looks like a DNS name or IPv4 addr with port: %s" \
+ "$hostname"
+ port="${hostname#*:}"
+ hostname="${hostname%%:*}"
+ ;;
+ *) # DNS name or IPv4 address
+ f_dprintf "Looks like a DNS name or IPv4 addr: %s" "$hostname"
+ : leave hostname as-is
+ esac
+
+ setvar $VAR_HTTP_PROXY_HOST "$hostname"
+ setvar $VAR_HTTP_PROXY_PORT "$port"
+
+ if f_debugging; then
+ f_dprintf "VAR_FTP_PATH : %s" "$( f_getvar $VAR_FTP_PATH )"
+ f_dprintf "VAR_HTTP_PROXY_HOST, _PORT: %s:%s" \
+ "$( f_getvar $VAR_HTTP_PROXY_HOST )" \
+ "$( f_getvar $VAR_HTTP_PROXY_PORT )"
+ fi
+
+ # media device has been set by f_media_set_ftp(), overwrite partly:
+ device_media set type $DEVICE_TYPE_HTTP_PROXY
+ device_media set init f_media_init_http_proxy
+ device_media set get f_media_get_http_proxy
+ device_media unset shutdown
+
+ return $SUCCESS
+}
+
+# f_http_proxy_check_access [$connect_only]
+#
+# Return success if able list a remote FTP directory via HTTP proxy. If
+# $connect_only is present and non-null, then returns success if a connection
+# can be made. Variables from variable.subr that can be used to script user
+# input:
+#
+# VAR_HTTP_PROXY_HOST
+# The HTTP proxy server host name, IPv4 address or IPv6 address.
+# Valid examples include:
+# myhost
+# 192.168.2.3
+# ::1
+# VAR_HTTP_PROXY_PORT
+# The TCP port to connect to when communicating with the HTTP
+# proxy server.
+# VAR_HTTP_PROXY_PATH
+# The FTP URL sent to the HTTP proxy server. Unused if
+# $connect_only is present and non-NULL.
+#
+f_http_proxy_check_access()
+{
+ local connect_only="$1" hosts=
+
+ local proxy_host proxy_port
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ f_getvar $VAR_HTTP_PROXY_PORT proxy_port
+
+ if ! {
+ f_validate_ipaddr "$proxy_host" ||
+ f_validate_ipaddr6 "$proxy_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_http_proxy_check_access" "$proxy_host"
+ f_host_lookup "$proxy_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ unset $VAR_HTTP_PROXY_HOST
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$proxy_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$proxy_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \
+ "$proxy_host" "$proxy_port"
+ unset $VAR_HTTP_PROXY_HOST
+ return $FAILURE
+ fi
+ [ "$connect_only" ] && return $SUCCESS
+
+ #
+ # Some proxies fetch files with certain extensions in "ascii mode"
+ # instead of "binary mode" for FTP. The FTP server then translates all
+ # LF to CRLF.
+ #
+ # You can force Squid to use binary mode by appending ";type=i" to the
+ # URL, which is what sysinstall(8) has traditionally done.
+ #
+
+ local proxy_path
+ f_getvar $VAR_HTTP_PROXY_PATH proxy_path
+ f_show_info "$msg_checking_access_to" "$proxy_path"
+
+ local rx
+ if ! rx=$(
+ printf "GET %s/ HTTP/1.0\r\n\r\n" "${proxy_path%/}" |
+ nc -n "$host" "$proxy_port"
+ ); then
+ f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \
+ "$proxy_host" "$proxy_port"
+ unset $VAR_HTTP_PROXY_HOST
+ return $FAILURE
+ fi
+
+ local hdr
+ hdr=$( echo "$rx" | awk '/^\r$/{exit}{print}' )
+
+ local http_found=$FAILURE
+ if echo "$hdr" | awk '
+ BEGIN { found = 0 }
+ /^HTTP.... 200 / {
+ found = 1
+ exit
+ }
+ END { exit ! found }
+ '; then
+ http_found=$SUCCESS
+ fi
+
+ #
+ # Scan the headers of the response
+ # this is extremely quick'n dity
+ #
+
+ unset $VAR_HTTP_FTP_MODE
+ if echo "$hdr" | awk '
+ BEGIN { found = 0 }
+ {
+ if (!match($0, /^Server: /)) next
+ found = ( substr($0, 9, 5) ~ /[Ss]quid/ )
+ }
+ END { exit ! found }
+ '; then
+ setvar $VAR_HTTP_FTP_MODE ";type=i"
+ else
+ setvar $VAR_HTTP_FTP_MODE ""
+ fi
+
+ return $http_found
+}
+
+# f_media_init_http_proxy $device
+#
+# Initializes the HTTP Proxy media device. Returns success if able to confirm
+# the existence of at least one known FTP server release path via HTTP proxy
+# using f_http_proxy_check_access(), above.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_PROXY_HOST
+# The HTTP proxy server to connect to. Usually set by having
+# f_media_set_http_proxy() parse VAR_HTTP_PROXY. Must be set.
+# Also see f_http_proxy_check_access() for additional variables.
+# VAR_RELNAME
+# Usually set to `uname -r' but can be overridden.
+# VAR_FTP_PATH
+# The FTP URL to send to the HTTP proxy server. Usually set by
+# calling f_media_set_ftp().
+#
+# Meanwhile, after successful execution, the following variables (also from
+# variable.subr) are set:
+#
+# VAR_HTTP_PROXY_PATH
+# The [possibly] adjusted VAR_FTP_PATH that was found to contain
+# a valid FreeBSD repository.
+#
+f_media_init_http_proxy()
+{
+ local dev="$1"
+ f_dprintf "Init routine called for HTTP Proxy device. dev=[%s]" "$dev"
+
+ #
+ # First verify access
+ #
+ local connect_only=1
+ f_http_proxy_check_access $connect_only
+
+ local proxy_host
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ while [ ! "$proxy_host" ]; do
+ f_media_set_http_proxy || return $FAILURE
+ f_http_proxy_check_access $connect_only
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ done
+
+ local rel proxy_path http_found=$FAILURE
+ while :; do
+ #
+ # If the release is specified as "__RELEASE" or "any", then
+ # just assume that the path the user gave is ok.
+ #
+ f_getvar $VAR_RELNAME rel
+ f_dprintf "f_media_init_http_proxy: rel=[%s]" "$rel"
+
+ case "$rel" in
+ __RELEASE|any)
+ f_getvar $VAR_FTP_PATH $VAR_HTTP_PROXY_PATH
+ f_http_proxy_check_access
+ http_found=$?
+ ;;
+ *)
+ local fdir fp
+ f_getvar $VAR_FTP_PATH%/ fp
+ for fdir in $FTP_DIRS; do
+ setvar $VAR_HTTP_PROXY_PATH "$fp/$fdir/$rel"
+ if f_http_proxy_check_access; then
+ http_found=$SUCCESS
+ break
+ fi
+ done
+ esac
+
+ [ $http_found -eq $SUCCESS ] && break
+
+ f_getvar $VAR_HTTP_PROXY_PATH proxy_path
+ f_show_msg "$msg_please_check_the_url_and_try_again" \
+ "$proxy_path"
+
+ unset $VAR_HTTP_PROXY_PATH
+ f_media_set_http_proxy || break
+ done
+
+ return $http_found
+}
+
+# f_media_get_http_proxy $device $file [$probe_type]
+#
+# Returns data from $file on an FTP server via HTTP proxy using nc(1). Please
+# note that $device is unused but must be present (even if null). Information
+# is instead gathered from the environment. If $probe_type is both present and
+# non-NULL, this function exits after receiving the HTTP header response from
+# the proxy server (if the HTTP response code is 200, success is returned;
+# otherwise failure). If $probe_type is equal to $PROBE_SIZE, prints the
+# content-length in bytes from the response (or -1 if not found) to standard-
+# out.
+#
+# The variables used to configure the connection are as follows (all of which
+# are configured by f_media_set_http_proxy above):
+#
+# VAR_HTTP_PROXY_HOST
+# HTTP proxy host to connect. Can be an IPv4 address, IPv6
+# address, or DNS hostname of your choice.
+# VAR_HTTP_PROXY_PORT
+# TCP port to connect on; see f_media_set_http_proxy above.
+# VAR_HTTP_PROXY_PATH
+# URL (including "ftp://" protocol-prefix) of FTP directory to
+# use as a prefix when requesting $file via HTTP proxy.
+#
+# See variable.subr for additional information.
+#
+# Example usage:
+# f_media_set_http_proxy
+# f_media_get_http_proxy media $file
+#
+f_media_get_http_proxy()
+{
+ local dev="$1" file="$2" probe_type="$3" hosts=
+
+ f_dprintf "f_media_get_http_proxy: dev=[%s] file=[%s] probe_type=%s" \
+ "$dev" "$file" "$probe_type"
+
+ local proxy_host proxy_port
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ f_getvar $VAR_HTTP_PROXY_PORT proxy_port
+
+ if ! {
+ f_validate_ipaddr "$proxy_host" ||
+ f_validate_ipaddr6 "$proxy_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_get_http_proxy" "$proxy_host"
+ f_host_lookup "$proxy_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$proxy_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$proxy_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \
+ "$proxy_host" "$proxy_port"
+ return $FAILURE
+ fi
+
+ local proxy_path mode
+ f_getvar $VAR_HTTP_PROXY_PATH%/ proxy_path
+ f_getvar $VAR_HTTP_FTP_MODE mode
+ local url="$proxy_path/$file$mode" rx
+
+ f_dprintf "sending http request for: %s" "$url"
+ printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$proxy_port" |
+ (
+ #
+ # scan the headers of the response
+ # this is extremely quick'n dirty
+ #
+
+ rv=0 length=-1
+ while read LINE; do
+ case "$LINE" in
+ HTTP*)
+ f_dprintf "received response: %s" "$LINE"
+ set -- $LINE; rv=$2
+ f_isinteger "$rv" || rv=0
+ ;;
+ "Content-Length: "*)
+ length="${LINE% }"
+ length="${length#Content-Length: }"
+ f_dprintf "received content-length: %s" \
+ "$length"
+ ;;
+ *)
+ [ "${LINE% }" ] || break # End of headers
+ esac
+ done
+
+ [ $rv -ge 500 ] && exit 5
+ [ $rv -eq 404 ] && exit 44
+ [ $rv -ge 400 ] && exit 4
+ [ $rv -ge 300 ] && exit 3
+ [ $rv -eq 200 ] || exit $FAILURE
+
+ if [ ! "$probe_type" ]; then
+ cat # output the rest ``as-is''
+ elif [ "$probe_type" = "$PROBE_SIZE" ]; then
+ f_isinteger "$length" || length=-1
+ echo "$length"
+ fi
+ exit 200
+ )
+ local retval=$?
+ [ $retval -eq 200 ] && return $SUCCESS
+ [ "$probe_type" ] && return $FAILURE
+
+ case "$retval" in
+ 5) f_show_msg "$msg_server_error_when_requesting_url" "$url" ;;
+ 44) f_show_msg "$msg_url_was_not_found" "$url" ;;
+ 4) f_show_msg "$msg_client_error" ;;
+ *) f_show_msg "$msg_error_when_requesting_url" "$url" ;;
+ esac 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ return $FAILURE
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/httpproxy.subr
+
+fi # ! $_MEDIA_HTTPPROXY_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/network.subr b/contrib/bsddialog/bsdconfig/share/media/network.subr
new file mode 100644
index 000000000000..5a03d80e8163
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/network.subr
@@ -0,0 +1,182 @@
+if [ ! "$_MEDIA_NETWORK_SUBR" ]; then _MEDIA_NETWORK_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/network.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+NETWORK_INITIALIZED=
+
+############################################################ FUNCTIONS
+
+# f_media_init_network $device
+#
+# Initialize a network device (such as `fxp0', `em0', etc.). Returns success if
+# able to successfully initialize the device. If not running as init (basically
+# from the FreeBSD install media) then assume that the network has already been
+# initialized and returns success.
+#
+# The variables (from variable.subr) used to initialize the network are as
+# follows (all of which are configured either automatically or manually):
+#
+# VAR_IFCONFIG + device_name (e.g., `ifconfig_em0')
+# Automatically populated but can be overridden in a script. This
+# defines the ifconfig(8) properties specific to a chosen network
+# interface device. Optional if VAR_IPV6ADDR is set.
+# VAR_IPV6ADDR [Optional]
+# If not running as init (and setting up RTSOL connections for
+# the interface), then must be set manually. If set, used as the
+# IPv6 configuration for the given network interface device.
+# VAR_GATEWAY [Optional]
+# If not running as init (and setting up a static connection for
+# the interface) then must be set (usually via rc.conf(5), but
+# can be set manually to override). If unset, the user is warned
+# but not prevented from proceeding (as most connections need a
+# default route but not everyone).
+#
+f_media_init_network()
+{
+ local dev="$1"
+
+ f_dprintf "Init routine called for network device \`%s'." "$dev"
+ if [ "$NETWORK_INITIALIZED" ]; then
+ f_dprintf "Network already initialized."
+ return $SUCCESS
+ elif ! f_running_as_init; then
+ f_dprintf "Not running as init -- calling the deed done."
+ NETWORK_INITIALIZED=1
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$RESOLV_CONF" ]; then
+ if ! f_config_resolv; then
+ f_show_msg "$msg_cant_seem_to_write_out_resolv_conf" \
+ "$RESOLV_CONF"
+ return $FAILURE
+ fi
+ fi
+
+ local cp
+ if f_getvar $VAR_IFCONFIG$dev cp; then
+ #
+ # If this interface isn't a DHCP one, bring it up.
+ # If it is, then it's already up.
+ #
+ case "$cp" in
+ *DHCP*)
+ f_dprintf "A DHCP interface. Should already be up."
+ ;;
+ *)
+ f_dprintf "Not a DHCP interface."
+ if ! f_quietly ifconfig "$dev" $cp; then
+ f_show_msg "$msg_unable_to_configure_device" \
+ "$dev"
+ return $FAILURE
+ fi
+ local rp
+ f_getvar $VAR_GATEWAY rp
+ if [ ! "$rp" ]; then
+ f_show_msg "$msg_no_gateway_has_been_set"
+ else
+ #
+ # Explicitly flush all routes to get back to a
+ # known sane state. We don't need to check this
+ # exit code because if anything fails it will
+ # show up in the route add below.
+ #
+ f_quietly route -n flush
+ f_dprintf "Adding default route to %s." "$rp"
+ if ! f_quietly route -n add default "$rp"; then
+ f_show_msg \
+ "$msg_failed_to_add_default_route"
+ return $FAILURE
+ fi
+ fi
+ esac
+ elif ! { f_getvar $VAR_IPV6ADDR cp && [ "$cp" ]; }; then
+ f_show_msg "$msg_device_is_not_configured" "$dev"
+ return $FAILURE
+ fi
+
+ f_dprintf "Network initialized successfully."
+ NETWORK_INITIALIZED=1
+ return $SUCCESS
+}
+
+# f_media_shutdown_network $device
+#
+# Shuts down the configured network device (e.g., `fxp0', `em0', etc.) and
+# deletes the default route (if configured). Returns failure if the device
+# passed has not been configured. If not running as init (basically from the
+# FreeBSD install media) then does nothing and returns success.
+#
+f_media_shutdown_network()
+{
+ local dev="$1" cp
+
+ f_dprintf "Shutdown called for network device %s" "$dev"
+ if [ ! "$NETWORK_INITIALIZED" ]; then
+ f_dprintf "Network not initialized -- nothing to do."
+ return $SUCCESS
+ fi
+
+ unset NETWORK_INITIALIZED
+ unset $VAR_NETWORK_DEVICE
+
+ if ! f_running_as_init; then
+ f_dprintf "Not running as init -- calling the deed done."
+ return $SUCCESS
+ fi
+
+ f_getvar $VAR_IFCONFIG$dev cp || return $FAILURE
+ f_dprintf "ifconfig %s down" "$dev"
+ f_quietly ifconfig $dev down ||
+ f_show_msg "$msg_unable_to_down_the_interface_properly" "$dev"
+
+ if f_getvar $VAR_GATEWAY cp; then
+ f_dprintf "Deleting default route."
+ f_quietly route -n delete default
+ fi
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/network.subr
+
+fi # ! $_MEDIA_NETWORK_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/nfs.subr b/contrib/bsddialog/bsdconfig/share/media/nfs.subr
new file mode 100644
index 000000000000..d83661f46b69
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/nfs.subr
@@ -0,0 +1,258 @@
+if [ ! "$_MEDIA_NFS_SUBR" ]; then _MEDIA_NFS_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/nfs.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/media/network.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+NFS_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_nfs
+#
+# Return success if we both found and set the media type to be an NFS server.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_NFS_PATH
+# The NFS path specification (host:path) to use when mounting the
+# remote repository.
+# VAR_NAMESERVER [Optional]
+# Automatically populated from resolv.conf(5) but can be
+# overridden. If set, the host portion of VAR_NFS_PATH is
+# looked up using f_host_lookup() from `tcpip.subr'.
+#
+# Meanwhile, the following variables from variable.subr are set after
+# successful execution:
+#
+# VAR_NFS_HOST
+# The host portion of the NFS path specification, parsed from
+# VAR_NFS_PATH.
+#
+f_media_set_nfs()
+{
+ local nfs
+
+ f_media_close
+
+ f_variable_get_value $VAR_NFS_PATH \
+ "$msg_please_enter_the_full_nfs_file_specification"
+ f_getvar $VAR_NFS_PATH nfs
+ [ "$nfs" ] || return $FAILURE
+
+ case "$nfs" in
+ *:*) : valid NFS path ;;
+ *)
+ f_show_msg "$msg_invalid_nfs_path_specification"
+ return $FAILURE
+ esac
+
+ f_struct_new DEVICE device_nfs
+ device_nfs set name "$nfs"
+
+ if ! f_struct device_network ||
+ ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
+ then
+ f_struct device_network &&
+ f_device_shutdown device_network
+ f_device_select_tcp || return $FAILURE
+ local dev if
+ f_getvar $VAR_NETWORK_DEVICE if
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_struct_copy "$dev" device_network
+ fi
+ f_device_init device_network ||
+ f_dprintf "%s: $msg_net_device_init_failed\n" f_media_set_nfs
+
+ local hostname="${nfs%%:*}"
+ if f_isset $VAR_NAMESERVER && ! {
+ f_validate_ipaddr "$hostname" || f_validate_ipaddr6 "$hostname"
+ }; then
+ f_show_info "$msg_looking_up_host" "$hostname"
+ f_dprintf "%s Looking up hostname, %s, using host(1)" \
+ "f_media_set_nfs" "$hostname"
+ if ! f_quietly f_host_lookup "$hostname"; then
+ f_show_msg "$msg_cannot_resolve_hostname" "$hostname"
+ f_struct device_network &&
+ f_device_shutdown device_network
+ f_struct_free device_network
+ unset $VAR_NFS_PATH
+ return $FAILURE
+ fi
+ f_dprintf "Found DNS entry for %s successfully." "$hostname"
+ fi
+
+ setvar $VAR_NFS_HOST "$hostname"
+
+ device_nfs set type $DEVICE_TYPE_NFS
+ device_nfs set init f_media_init_nfs
+ device_nfs set get f_media_get_nfs
+ device_nfs set shutdown f_media_shutdown_nfs
+ device_nfs set private device_network # in name only (deref'd later)
+
+ f_struct_copy device_nfs device_media
+ f_struct_free device_nfs
+
+ return $SUCCESS
+}
+
+# f_media_init_nfs $device
+#
+# Initializes the NFS media device. Returns success if able to mount the NFS
+# device using mount_nfs(1).
+#
+# The variables (from variable.subr) used to initialize the NFS mount are as
+# follows (all of which are configured manually/optionally from the options
+# menu):
+#
+# VAR_NFS_TCP [Optional]
+# If non-NULL, adds the "tcp" option via `-o' to mount_nfs(8).
+# VAR_NFS_V3 [Optional]
+# If non-NULL, adds the "nfsv3" option via `-o' to mount_nfs(8).
+# VAR_NFS_SECURE [Optional]
+# If non-NULL, adds the "-P" flag to mount_nfs(8).
+# VAR_SLOW_ETHER [Optional]
+# If non-NULL, adjusts the read/write size to avoid timeouts.
+#
+f_media_init_nfs()
+{
+ local funcname=f_media_init_nfs
+ local dev="$1" name err
+
+ $dev get name name || return $FAILURE
+ f_dprintf "Init routine called for NFS device. name=[%s]" \
+ "$name"
+
+ if [ "$NFS_MOUNTED" ]; then
+ f_dprintf "NFS device already mounted."
+ return $SUCCESS
+ fi
+
+ if ! f_device_init device_network; then
+ f_dprintf "f_media_init_nfs: %s" "$msg_net_device_init_failed"
+ return $FAILURE
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
+ fi
+
+ local cp tcp="" use3="" secure="" readsize=4096 writesize=4096
+ f_getvar $VAR_NFS_TCP cp
+ [ "$cp" = "YES" ] && tcp=1
+ f_getvar $VAR_NFS_V3 cp
+ [ "$cp" = "YES" ] && use3=1
+ f_getvar $VAR_NFS_SECURE cp
+ [ "$cp" = "YES" ] && secure=1
+ f_getvar $VAR_SLOW_ETHER cp
+ [ "$cp" = "YES" ] && readsize=1024 writesize=1024
+
+ local options="rsize=$readsize,wsize=$writesize"
+ [ "$use3" ] && options="$options,nfsv3"
+ [ "$tcp" ] && options="$options,tcp"
+
+ if ! f_eval_catch -dk err $funcname mount_nfs \
+ 'mount_nfs %s -o "%s" "%s" "%s"' \
+ "${secure:+-P}" "$options" "$name" "$MOUNTPOINT"
+ then
+ err="${err#mount_nfs: }"
+ f_show_msg "$msg_error_mounting_device" \
+ "$name" "$MOUNTPOINT" "$err"
+ f_struct device_network &&
+ f_device_shutdown device_network
+ return $FAILURE
+ fi
+ NFS_MOUNTED=1
+
+ f_dprintf "Mounted NFS device %s onto %s" "$name" "$MOUNTPOINT"
+
+ return $SUCCESS
+}
+
+# f_media_get_nfs $device $file [$probe_type]
+#
+# Returns data from $file on a mounted NFS device. Similar to cat(1). If
+# $probe_type is present and non-NULL, returns success if $file exists. If
+# $probe_type is equal to $PROBE_SIZE, prints the size of $file in bytes to
+# standard-out.
+#
+f_media_get_nfs()
+{
+ local dev="$1" file="$2" probe_type="$3"
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_nfs: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
+}
+
+# f_media_shutdown_nfs $device
+#
+# Shuts down the NFS device using umount(8). Return status should be ignored.
+#
+f_media_shutdown_nfs()
+{
+ local funcname=f_media_shutdown_nfs
+ local dev="$1" err
+
+ [ "$NFS_MOUNTED" ] || return $FAILURE
+
+ f_dprintf "Unmounting NFS partition on %s" "$MOUNTPOINT"
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_nfs_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ NFS_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/nfs.subr
+
+fi # ! $_MEDIA_NFS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/options.subr b/contrib/bsddialog/bsdconfig/share/media/options.subr
new file mode 100644
index 000000000000..bc9568e65102
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/options.subr
@@ -0,0 +1,327 @@
+if [ ! "$_MEDIA_OPTIONS_SUBR" ]; then _MEDIA_OPTIONS_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/options.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/any.subr
+f_include $BSDCFG_SHARE/media/ftp.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+OPTIONS_HELPFILE=$BSDCFG_LIBE/include/options.hlp
+
+############################################################ FUNCTIONS
+
+# f_media_options_menu
+#
+# Prompt the user to confirm/edit various media settings. Returns success.
+#
+f_media_options_menu()
+{
+ f_dialog_title "$msg_options_editor"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local prompt=
+ local menu_list # Calculated below
+ local defaultitem=
+ local hline="$hline_arrows_tab_enter"
+
+ #
+ # A hack so that the dialogs below are always interactive in a script
+ #
+ local old_interactive=
+ if ! f_interactive; then
+ f_getvar $VAR_NONINTERACTIVE old_interactive
+ unset $VAR_NONINTERACTIVE
+ fi
+
+ local cp
+ while :; do
+ menu_list=
+
+ f_getvar $VAR_NFS_SECURE cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_secure' 'YES'
+ '$msg_nfs_server_talks_only_on_a_secure_port'"
+ else menu_list="$menu_list
+ ' $msg_nfs_secure' 'NO'
+ '$msg_nfs_server_talks_only_on_a_secure_port'"
+ fi
+
+ f_getvar $VAR_SLOW_ETHER cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_slow' 'YES'
+ '$msg_user_is_using_a_slow_pc_or_ethernet_card'"
+ else menu_list="$menu_list
+ ' $msg_nfs_slow' 'NO'
+ '$msg_user_is_using_a_slow_pc_or_ethernet_card'"
+ fi
+
+ f_getvar $VAR_NFS_TCP cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_tcp' 'YES' '$msg_use_tcp_protocol_for_nfs'"
+ else menu_list="$menu_list
+ ' $msg_nfs_tcp' 'NO' '$msg_use_tcp_protocol_for_nfs'"
+ fi
+
+ f_getvar $VAR_NFS_V3 cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_version_3' 'YES' '$msg_use_nfs_version_3'"
+ else menu_list="$menu_list
+ ' $msg_nfs_version_3' 'NO' '$msg_use_nfs_version_3'"
+ fi
+
+ f_getvar $VAR_DEBUG cp
+ if [ "$cp" ]; then menu_list="$menu_list
+ ' $msg_debugging' 'YES'
+ '$msg_emit_extra_debugging_output'"
+ else menu_list="$menu_list
+ ' $msg_debugging' 'NO'
+ '$msg_emit_extra_debugging_output'"
+ fi
+
+ f_getvar $VAR_NO_CONFIRM cp
+ if [ "$cp" ]; then menu_list="$menu_list
+ ' $msg_yes_to_all' 'YES'
+ '$msg_assume_yes_to_all_non_critical_dialogs'"
+ else menu_list="$menu_list
+ ' $msg_yes_to_all' 'NO'
+ '$msg_assume_yes_to_all_non_critical_dialogs'"
+ fi
+
+ f_getvar $VAR_TRY_DHCP cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_dhcp' 'YES'
+ '$msg_attempt_automatic_dhcp_configuration'"
+ else menu_list="$menu_list
+ ' $msg_dhcp' 'NO'
+ '$msg_attempt_automatic_dhcp_configuration'"
+ fi
+
+ f_getvar $VAR_TRY_RTSOL cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_ipv6' 'YES'
+ '$msg_attempt_ipv6_configuration_of_interfaces'"
+ else menu_list="$menu_list
+ ' $msg_ipv6' 'NO'
+ '$msg_attempt_ipv6_configuration_of_interfaces'"
+ fi
+
+ f_getvar $VAR_FTP_USER cp
+ menu_list="$menu_list
+ ' $msg_ftp_username' '$cp'
+ '$msg_username_and_password_to_use'"
+
+ f_getvar $VAR_EDITOR cp
+ menu_list="$menu_list
+ ' $msg_editor' '$cp' '$msg_which_text_editor_to_use'"
+
+ f_getvar $VAR_RELNAME cp
+ menu_list="$menu_list
+ ' $msg_release_name' '$cp'
+ '$msg_which_release_to_attempt_to_load'"
+
+ if f_struct device_media; then
+ device_media get type cp
+ case "$cp" in
+ $DEVICE_TYPE_UFS|$DEVICE_TYPE_DISK)
+ cp="$msg_file_system" ;;
+ $DEVICE_TYPE_DIRECTORY) cp="$msg_directory" ;;
+ $DEVICE_TYPE_FLOPPY) cp="$msg_floppy" ;;
+ $DEVICE_TYPE_FTP) cp="$msg_ftp" ;;
+ $DEVICE_TYPE_HTTP_PROXY) cp="$msg_http_proxy" ;;
+ $DEVICE_TYPE_HTTP) cp="$msg_http_direct" ;;
+ $DEVICE_TYPE_CDROM) cp="$msg_cdrom" ;;
+ $DEVICE_TYPE_USB) cp="$msg_usb" ;;
+ $DEVICE_TYPE_DOS) cp="$msg_dos" ;;
+ $DEVICE_TYPE_NFS) cp="$msg_nfs" ;;
+ *)
+ cp="<$msg_unknown>"
+ esac
+ else
+ cp="<$msg_not_yet_set>"
+ fi
+ menu_list="$menu_list
+ ' $msg_media_type' '$cp'
+ '$msg_the_current_installation_media_type'"
+
+ f_getvar $VAR_MEDIA_TIMEOUT cp
+ menu_list="$menu_list
+ ' $msg_media_timeout' '$cp'
+ '$msg_timeout_value_in_seconds_for_slow_media'"
+
+ f_getvar $VAR_PKG_TMPDIR cp
+ menu_list="$menu_list
+ ' $msg_package_temp' '$cp'
+ '$msg_directory_where_package_temporary_files_go'"
+
+ menu_list="$menu_list
+ ' $msg_rescan_devices' '<*>'
+ '$msg_rerun_bsdconfig_initial_device_probe'
+ ' $msg_use_defaults' '[${msg_reset}]'
+ '$msg_reset_all_values_to_startup_defaults'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_with_help_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local mtag
+ mtag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --item-help \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_done\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ --default-item \"\$defaultitem\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize mtag
+ defaultitem="$mtag"
+ f_dprintf "retval=%s mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$OPTIONS_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ break # to success
+ fi
+
+ case "$mtag" in
+ " $msg_nfs_secure")
+ f_getvar $VAR_NFS_SECURE cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_NFS_SECURE="NO"
+ else
+ export $VAR_NFS_SECURE="YES"
+ fi ;;
+ " $msg_nfs_slow")
+ f_getvar $VAR_SLOW_ETHER cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_SLOW_ETHER="NO"
+ else
+ export $VAR_SLOW_ETHER="YES"
+ fi ;;
+ " $msg_nfs_tcp")
+ f_getvar $VAR_NFS_TCP cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_NFS_TCP="NO"
+ else
+ export $VAR_NFS_TCP="YES"
+ fi ;;
+ " $msg_nfs_version_3")
+ f_getvar $VAR_NFS_V3 cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_NFS_V3="NO"
+ else
+ export $VAR_NFS_V3="YES"
+ fi ;;
+ " $msg_debugging")
+ if f_getvar $VAR_DEBUG cp && [ "$cp" ]; then
+ unset $VAR_DEBUG
+ else
+ export $VAR_DEBUG=1
+ fi ;;
+ " $msg_yes_to_all")
+ if f_getvar $VAR_NO_CONFIRM cp && [ "$cp" ]; then
+ unset $VAR_NO_CONFIRM
+ else
+ export $VAR_NO_CONFIRM=1
+ fi ;;
+ " $msg_dhcp")
+ f_getvar $VAR_TRY_DHCP cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_TRY_DHCP="NO"
+ else
+ export $VAR_TRY_DHCP="YES"
+ fi ;;
+ " $msg_ipv6")
+ f_getvar $VAR_TRY_RTSOL cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_TRY_RTSOL="NO"
+ else
+ export $VAR_TRY_RTSOL="YES"
+ fi ;;
+ " $msg_ftp_username")
+ f_media_set_ftp_userpass ;;
+ " $msg_editor")
+ f_variable_get_value $VAR_EDITOR \
+ "$msg_please_specify_the_name_of_the_text_editor"
+ ;;
+ " $msg_release_name")
+ f_variable_get_value $VAR_RELNAME \
+ "$msg_please_specify_the_release_you_wish_to_load"
+ ;;
+ " $msg_media_type")
+ f_media_get_type ;;
+ " $msg_media_timeout")
+ f_variable_get_value $VAR_MEDIA_TIMEOUT \
+ "$msg_please_specify_the_number_of_seconds_to_wait"
+ ;;
+ " $msg_package_temp")
+ f_variable_get_value $VAR_PKG_TMPDIR \
+ "$msg_please_specify_a_temporary_directory"
+ ;;
+ " $msg_rescan_devices")
+ f_device_rescan ;;
+ " $msg_use_defaults")
+ f_variable_set_defaults ;;
+ esac
+ done
+
+ # Restore old VAR_NONINTERACTIVE if needed.
+ [ "$old_interactive" ] &&
+ setvar $VAR_NONINTERACTIVE "$old_interactive"
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/options.subr
+
+fi # ! $_MEDIA_OPTIONS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/tcpip.subr b/contrib/bsddialog/bsdconfig/share/media/tcpip.subr
new file mode 100644
index 000000000000..d149bc6036d1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/tcpip.subr
@@ -0,0 +1,1713 @@
+if [ ! "$_MEDIA_TCPIP_SUBR" ]; then _MEDIA_TCPIP_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/tcpip.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+TCP_HELPFILE=$BSDCFG_LIBE/include/tcp.hlp
+NETWORK_DEVICE_HELPFILE=$BSDCFG_LIBE/include/network_device.hlp
+
+############################################################ GLOBALS
+
+#
+# Path to resolv.conf(5).
+#
+: ${RESOLV_CONF:="/etc/resolv.conf"}
+
+#
+# Path to nsswitch.conf(5).
+#
+: ${NSSWITCH_CONF:="/etc/nsswitch.conf"}
+
+#
+# Path to hosts(5)
+#
+: ${ETC_HOSTS:="/etc/hosts"}
+
+#
+# Structure of dhclient.leases(5) lease { ... } entry
+#
+f_struct_define DHCP_LEASE \
+ interface \
+ fixed_address \
+ filename \
+ server_name \
+ script \
+ medium \
+ host_name \
+ subnet_mask \
+ routers \
+ domain_name_servers \
+ domain_name \
+ broadcast_address \
+ dhcp_lease_time \
+ dhcp_message_type \
+ dhcp_server_identifier \
+ dhcp_renewal_time \
+ dhcp_rebinding_time \
+ renew \
+ rebind \
+ expire
+
+############################################################ FUNCTIONS
+
+# f_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.
+#
+# To call this function and display an appropriate error message to the user
+# based on the above error codes, use the following function defined in
+# dialog.subr:
+#
+# f_dialog_validate_hostname $hostname
+#
+f_validate_hostname()
+{
+ local fqhn="$1"
+
+ # Return error if the hostname exceeds 255 characters
+ [ ${#fqhn} -gt 255 ] && return 255
+
+ local IFS="." # Split on `dot'
+ for label in $fqhn; do
+ # Return error if the label exceeds 63 characters
+ [ ${#label} -gt 63 ] && return 63
+
+ # Return error if the label is null
+ [ "$label" ] || return 3
+
+ # Return error if label begins/ends with dash
+ case "$label" in -*|*-) return 2; esac
+
+ # Return error if the label contains any invalid chars
+ case "$label" in *[!0-9a-zA-Z-]*) return 1; esac
+ done
+
+ return $SUCCESS
+}
+
+# f_inet_atoi $ipv4_address [$var_to_set]
+#
+# Convert an IPv4 address or mask from dotted-quad notation (e.g., `127.0.0.1'
+# or `255.255.255.0') to a 32-bit unsigned integer for the purpose of network
+# and broadcast calculations. For example, one can validate that two addresses
+# are on the same network:
+#
+# f_inet_atoi 1.2.3.4 ip1num
+# f_inet_atoi 1.2.4.5 ip2num
+# f_inet_atoi 255.255.0.0 masknum
+# if [ $(( $ip1num & $masknum )) -eq \
+# $(( $ip2num & $masknum )) ]
+# then
+# : IP addresses are on same network
+# fi
+#
+# See f_validate_ipaddr() below for an additional example usage, on calculating
+# network and broadcast addresses.
+#
+# If $var_to_set is missing or NULL, the converted IP address is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_inet_atoi()
+{
+ local __addr="$1" __var_to_set="$2" __num=0
+ if f_validate_ipaddr "$__addr"; then
+ local IFS=.
+ set -- $__addr
+ __num=$(( ($1 << 24) + ($2 << 16) + ($3 << 8) + $4 ))
+ fi
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__num
+ else
+ echo $__num
+ fi
+}
+
+# f_validate_ipaddr $ipaddr [$netmask]
+#
+# 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 a netmask is provided, the IP address is checked further:
+#
+# 5 The IP address must not be the network or broadcast address.
+#
+f_validate_ipaddr()
+{
+ local ip="$1" mask="$2"
+
+ # Track number of octets for error checking
+ local noctets=0
+
+ local oldIFS="$IFS" IFS="." # Split on `dot'
+ for octet in $ip; do
+ # Return error if the octet is null
+ [ "$octet" ] || return 2
+
+ # Return error if not a whole integer
+ f_isinteger "$octet" || return 1
+
+ # Return error if not a positive integer
+ [ $octet -ge 0 ] || return 1
+
+ # Return error if the octet exceeds 255
+ [ $octet -gt 255 ] && return 3
+
+ noctets=$(( $noctets + 1 ))
+ done
+ IFS="$oldIFS"
+
+ [ $noctets -eq 4 ] || return 4
+
+ #
+ # The IP address must not be network or broadcast address.
+ #
+ if [ "$mask" ]; then
+ local ipnum masknum netnum bcastnum
+ local max_addr=4294967295 # 255.255.255.255
+
+ f_inet_atoi $ip ipnum
+ f_inet_atoi $mask masknum
+
+ netnum=$(( $ipnum & $masknum ))
+ bcastnum=$(( ($ipnum & $masknum)+$max_addr-$masknum ))
+
+ if [ "$masknum" ] &&
+ [ $ipnum -eq $netnum -o $ipnum -eq $bcastnum ]
+ then
+ return 5
+ fi
+ fi
+
+ return $SUCCESS
+}
+
+# f_validate_ipaddr6 $ipv6_addr
+#
+# Returns zero if the given argument (an IPv6 address) is of the proper format.
+#
+# The return status for invalid IP address is one of:
+# 1 One or more individual segments within the IP address
+# (separated by colons) contains one or more invalid characters.
+# Segments must contain only combinations of the characters 0-9,
+# A-F, or a-f.
+# 2 Too many/incorrect null segments. A single null segment is
+# allowed within the IP address (separated by colons) but not
+# allowed at the beginning or end (unless a double-null segment;
+# i.e., "::*" or "*::").
+# 3 One or more individual segments within the IP address
+# (separated by colons) exceeds the length of 4 hex-digits.
+# 4 The IP address entered has either too few (less than 3), too
+# many (more than 8), or not enough segments, separated by
+# colons.
+# 5* The IPv4 address at the end of the IPv6 address is invalid.
+# * When there is an error with the dotted-quad IPv4 address at the
+# end of the IPv6 address, the return value of 5 is OR'd with a
+# bit-shifted (<< 4) return of f_validate_ipaddr.
+#
+f_validate_ipaddr6()
+{
+ local ip="${1%\%*}" # removing the interface specification if-present
+
+ local IFS=":" # Split on `colon'
+ set -- $ip:
+
+ # Return error if too many or too few segments
+ # Using 9 as max in case of leading or trailing null spanner
+ [ $# -gt 9 -o $# -lt 3 ] && return 4
+
+ local h="[0-9A-Fa-f]"
+ local nulls=0 nsegments=$# contains_ipv4_segment=
+
+ while [ $# -gt 0 ]; do
+
+ segment="${1%:}"
+ shift
+
+ #
+ # Return error if this segment makes one null too-many. A
+ # single null segment is allowed anywhere in the middle as well
+ # as double null segments are allowed at the beginning or end
+ # (but not both).
+ #
+ if [ ! "$segment" ]; then
+ nulls=$(( $nulls + 1 ))
+ if [ $nulls -eq 3 ]; then
+ # Only valid syntax for 3 nulls is `::'
+ [ "$ip" = "::" ] || return 2
+ elif [ $nulls -eq 2 ]; then
+ # Only valid if begins/ends with `::'
+ case "$ip" in
+ ::*|*::) : fall thru ;;
+ *) return 2
+ esac
+ fi
+ continue
+ fi
+
+ #
+ # Return error if not a valid hexadecimal short
+ #
+ case "$segment" in
+ $h|$h$h|$h$h$h|$h$h$h$h)
+ : valid segment of 1-4 hexadecimal digits
+ ;;
+ *[!0-9A-Fa-f]*)
+ # Segment contains at least one invalid char
+
+ # Return error immediately if not last segment
+ [ $# -eq 0 ] || return 1
+
+ # Otherwise, check for legacy IPv4 notation
+ case "$segment" in
+ *[!0-9.]*)
+ # Segment contains at least one invalid
+ # character even for an IPv4 address
+ return 1
+ esac
+
+ # Return error if not enough segments
+ if [ $nulls -eq 0 ]; then
+ [ $nsegments -eq 7 ] || return 4
+ fi
+
+ contains_ipv4_segment=1
+
+ # Validate the IPv4 address
+ f_validate_ipaddr "$segment" ||
+ return $(( 5 | $? << 4 ))
+ ;;
+ *)
+ # Segment characters are all valid but too many
+ return 3
+ esac
+
+ done
+
+ if [ $nulls -eq 1 ]; then
+ # Single null segment cannot be at beginning/end
+ case "$ip" in
+ :*|*:) return 2
+ esac
+ fi
+
+ #
+ # A legacy IPv4 address can span the last two 16-bit segments,
+ # reducing the amount of maximum allowable segments by-one.
+ #
+ maxsegments=8
+ if [ "$contains_ipv4_segment" ]; then
+ maxsegments=7
+ fi
+
+ case $nulls in
+ # Return error if missing segments with no null spanner
+ 0) [ $nsegments -eq $maxsegments ] || return 4 ;;
+ # Return error if null spanner with too many segments
+ 1) [ $nsegments -le $maxsegments ] || return 4 ;;
+ # Return error if leading/trailing `::' with too many segments
+ 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || return 4 ;;
+ esac
+
+ return $SUCCESS
+}
+
+# f_validate_netmask $netmask
+#
+# Returns zero if the given argument (a subnet mask) is of the proper format.
+#
+# The return status for invalid netmask 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).
+#
+f_validate_netmask()
+{
+ local mask="$1"
+
+ # Track number of fields for error checking
+ local nfields=0
+
+ local IFS="." # Split on `dot'
+ for field in $mask; do
+ # Return error if the field is null
+ [ "$field" ] || return 2
+
+ # Return error if not a whole positive integer
+ f_isinteger "$field" || return 1
+
+ # Return error if the field exceeds 255
+ [ $field -gt 255 ] && return 3
+
+ # Return error if the field is an invalid integer
+ case "$field" in
+ 0|128|192|224|240|248|252|254|255) : ;;
+ *) return 5 ;;
+ esac
+
+ nfields=$(( $nfields + 1 ))
+ done
+
+ [ $nfields -eq 4 ] || return 4
+}
+
+# f_validate_gateway $gateway $ipaddr $netmask
+#
+# Validate an IPv4 default gateway (aka router) address for a given IP address
+# making sure the two are in the same network (able to ``talk'' to each other).
+# Returns success if $ipaddr and $gateway are in the same network given subnet
+# mask $netmask.
+#
+f_validate_gateway()
+{
+ local gateway="$1" ipaddr="$2" netmask="$3"
+ local gwnum ipnum masknum
+
+ f_validate_ipaddr "$gateway" "$netmask" || return $FAILURE
+
+ f_inet_atoi "$netmask" masknum
+ f_inet_atoi "$ipaddr" ipnum
+ f_inet_atoi "$gateway" gwnum
+
+ # Gateway must be within set of IPs reachable through interface
+ [ $(( $ipnum & $masknum )) -eq \
+ $(( $gwnum & $masknum )) ] # Return status
+}
+
+# f_dialog_validate_tcpip $hostname $gateway $nameserver $ipaddr $netmask
+#
+# Returns success if the arguments provided are valid for accessing a TCP/IP
+# network, otherwise returns failure.
+#
+f_dialog_validate_tcpip()
+{
+ local hostname="$1" gateway="$2" nameserver="$3"
+ local ipaddr="$4" netmask="$5"
+ local ipnum masknum
+
+ if [ ! "$hostname" ]; then
+ f_show_msg "$msg_must_specify_a_host_name_of_some_sort"
+ elif ! f_validate_hostname "$hostname"; then
+ f_show_msg "$msg_invalid_hostname_value"
+ elif [ "$netmask" ] && ! f_validate_netmask "$netmask"; then
+ f_show_msg "$msg_invalid_netmask_value"
+ elif [ "$nameserver" ] &&
+ ! f_validate_ipaddr "$nameserver" &&
+ ! f_validate_ipaddr6 "$nameserver"; then
+ f_show_msg "$msg_invalid_name_server_ip_address_specified"
+ elif [ "$ipaddr" ] && ! f_validate_ipaddr "$ipaddr" "$netmask"; then
+ f_show_msg "$msg_invalid_ipv4_address"
+ elif [ "$gateway" -a "$gateway" != "NO" ] &&
+ ! f_validate_gateway "$gateway" "$ipaddr" "$netmask"; then
+ f_show_msg "$msg_invalid_gateway_ipv4_address_specified"
+ else
+ return $DIALOG_OK
+ fi
+
+ return $DIALOG_CANCEL
+}
+
+# f_ifconfig_inet $interface [$var_to_set]
+#
+# Returns the IPv4 address associated with $interface. If $var_to_set is
+# missing or NULL, the IP address is printed to standard output for capturing
+# in a sub-shell (which is less-recommended because of performance degredation;
+# for example, when called in a loop).
+#
+# 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_ifconfig_inet_awk='
+BEGIN { found = 0 }
+( $1 == "inet" ) \
+{
+ print $2
+ found = 1
+ exit
+}
+END { exit ! found }
+'
+f_ifconfig_inet()
+{
+ local __interface="$1" __var_to_set="$2"
+ if [ "$__var_to_set" ]; then
+ local __ip
+ __ip=$( ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet_awk" )
+ setvar "$__var_to_set" "$__ip"
+ else
+ ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet_awk"
+ fi
+}
+
+# f_ifconfig_inet6 $interface [$var_to_set]
+#
+# Returns the IPv6 address associated with $interface. If $var_to_set is
+# missing or NULL, the IP address is printed to standard output for capturing
+# in a sub-shell (which is less-recommended because of performance degredation;
+# for example, when called in a loop).
+#
+# 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_ifconfig_inet6_awk='
+BEGIN { found = 0 }
+( $1 == "inet6" ) \
+{
+ print $2
+ found = 1
+ exit
+}
+END { exit ! found }
+'
+f_ifconfig_inet6()
+{
+ local __interface="$1" __var_to_set="$2"
+ if [ "$__var_to_set" ]; then
+ local __ip6
+ __ip6=$( ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet6_awk" )
+ setvar "$__var_to_set" "$__ip6"
+ else
+ ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet6_awk"
+ fi
+}
+
+# f_ifconfig_netmask $interface [$var_to_set]
+#
+# Returns the IPv4 subnet mask associated with $interface. If $var_to_set is
+# missing or NULL, the netmask is printed to standard output for capturing in a
+# sub-shell (which is less-recommended because of performance degredation; for
+# example, when called in a loop).
+#
+f_ifconfig_netmask()
+{
+ local __interface="$1" __var_to_set="$2" __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
+ f_sprintf __netmask "%s.%u" "$__netmask" "0x$__octet"
+ done
+ __netmask="${__netmask#.}"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__netmask"
+ else
+ echo $__netmask
+ fi
+}
+
+# f_route_get_default [$var_to_set]
+#
+# Returns the IP address of the currently active default router. If $var_to_set
+# is missing or NULL, the IP address is printed to standard output for
+# capturing in a sub-shell (which is less-recommended because of performance
+# degredation; for example, when called in a loop).
+#
+# 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_route_get_default_awk='
+BEGIN { found = 0 }
+( $1 == "gateway:" ) \
+{
+ print $2
+ found = 1
+ exit
+}
+END { exit ! found }
+'
+f_route_get_default()
+{
+ local __var_to_set="$1"
+ if [ "$__var_to_set" ]; then
+ local __ip
+ __ip=$( route -n get default 2> /dev/null |
+ awk "$f_route_get_default_awk" )
+ setvar "$__var_to_set" "$__ip"
+ else
+ route -n get default 2> /dev/null |
+ awk "$f_route_get_default_awk"
+ fi
+}
+
+# f_resolv_conf_nameservers [$var_to_set]
+#
+# Returns nameserver(s) configured in resolv.conf(5). If $var_to_set is missing
+# or NULL, the list of nameservers is printed to standard output for capturing
+# in a sub-shell (which is less-recommended because of performance degredation;
+# for example, when called in a loop).
+#
+# 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_resolv_conf_nameservers_awk='
+BEGIN { found = 0 }
+( $1 == "nameserver" ) \
+{
+ print $2
+ found = 1
+}
+END { exit ! found }
+'
+f_resolv_conf_nameservers()
+{
+ local __var_to_set="$1"
+ if [ "$__var_to_set" ]; then
+ local __ns
+ __ns=$( awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \
+ 2> /dev/null )
+ setvar "$__var_to_set" "$__ns"
+ else
+ awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \
+ 2> /dev/null
+ fi
+}
+
+# f_config_resolv
+#
+# Attempts to configure resolv.conf(5) and ilk. Returns success if able to
+# write the file(s), otherwise returns error status.
+#
+# Variables from variable.subr that are used in configuring resolv.conf(5) are
+# as follows (all of which can be configured automatically through functions
+# like f_dhcp_get_info() or manually):
+#
+# VAR_NAMESERVER
+# The nameserver to add in resolv.conf(5).
+# VAR_DOMAINNAME
+# The domain to configure in resolv.conf(5). Also used in the
+# configuration of hosts(5).
+# VAR_IPADDR
+# The IPv4 address to configure in hosts(5).
+# VAR_IPV6ADDR
+# The IPv6 address to configure in hosts(5).
+# VAR_HOSTNAME
+# The hostname to associate with the IPv4 and/or IPv6 address in
+# hosts(5).
+#
+f_config_resolv()
+{
+ local cp c6p dp hp
+
+ f_getvar $VAR_NAMESERVER cp
+ if [ "$cp" ]; then
+ case "$RESOLV_CONF" in
+ */*) f_quietly mkdir -p "${RESOLV_CONF%/*}" ;;
+ esac
+
+ # Attempt to create/truncate the file
+ ( :> "$RESOLV_CONF" ) 2> /dev/null || return $FAILURE
+
+ f_getvar $VAR_DOMAINNAME dp &&
+ printf "domain\t%s\n" "$dp" >> "$RESOLV_CONF"
+ printf "nameserver\t%s\n" "$cp" >> "$RESOLV_CONF"
+
+ f_dprintf "Wrote out %s" "$RESOLV_CONF"
+ fi
+
+ f_getvar $VAR_DOMAINNAME dp
+ f_getvar $VAR_IPADDR cp
+ f_getvar $VAR_IPV6ADDR c6p
+ f_getvar $VAR_HOSTNAME hp
+
+ # Attempt to create the file if it doesn't already exist
+ if [ ! -e "$ETC_HOSTS" ]; then
+ case "$ETC_HOSTS" in
+ */*) f_quietly mkdir -p "${ETC_HOSTS%/*}" ;;
+ esac
+
+ ( :> "$ETC_HOSTS" ) 2> /dev/null || return $FAILURE
+ fi
+
+ # Scan the file and add ourselves if not already configured
+ awk -v dn="$dp" -v ip4="$cp" -v ip6="$c6p" -v hn="$hp" '
+ BEGIN {
+ local4found = local6found = 0
+ hn4found = hn6found = h4found = h6found = 0
+ h = ( match(hn, /\./) ? substr(hn, 0, RSTART-1) : "" )
+ }
+ ($1 == "127.0.0.1") { local4found = 1 }
+ ($1 == "::1") { local6found = 1 }
+ {
+ for (n = 2; n <= NF; n++)
+ {
+ if ( $1 == ip4 ) {
+ if ( $n == h ) h4found = 1
+ if ( $n == hn ) hn4found = 1
+ if ( $n == hn "." ) hn4found = 1
+ }
+ if ( $1 == ip6 ) {
+ if ( $n == h ) h6found = 1
+ if ( $n == hn ) hn6found = 1
+ if ( $n == hn "." ) hn6found = 1
+ }
+ }
+ }
+ END {
+ hosts = FILENAME
+
+ if ( ! local6found )
+ printf "::1\t\t\tlocalhost%s\n",
+ ( dn ? " localhost." dn : "" ) >> hosts
+ if ( ! local4found )
+ printf "127.0.0.1\t\tlocalhost%s\n",
+ ( dn ? " localhost." dn : "" ) >> hosts
+
+ if ( ip6 && ! (h6found && hn6found))
+ {
+ printf "%s\t%s %s\n", ip6, hn, h >> hosts
+ printf "%s\t%s.\n", ip6, hn >> hosts
+ }
+ else if ( ip6 )
+ {
+ if ( ! h6found )
+ printf "%s\t%s.\n", ip6, h >> hosts
+ if ( ! hn6found )
+ printf "%s\t%s\n", ip6, hn >> hosts
+ }
+
+ if ( ip4 && ! (h4found && hn4found))
+ {
+ printf "%s\t\t%s %s\n", ip4, hn, h >> hosts
+ printf "%s\t\t%s.\n", ip4, hn >> hosts
+ }
+ else if ( ip4 )
+ {
+ if ( ! h4found )
+ printf "%s\t\t%s.\n", ip4, h >> hosts
+ if ( ! hn4found )
+ printf "%s\t\t%s\n", ip4, hn >> hosts
+ }
+ }
+ ' "$ETC_HOSTS" 2> /dev/null || return $FAILURE
+
+ f_dprintf "Wrote out %s" "$ETC_HOSTS"
+ return $SUCCESS
+}
+
+# f_dhcp_parse_leases $leasefile struct_name
+#
+# Parse $leasefile and store the information for the most recent lease in a
+# struct (see struct.subr for additional details) named `struct_name'. See
+# DHCP_LEASE struct definition in the GLOBALS section above.
+#
+f_dhcp_parse_leases()
+{
+ local leasefile="$1" struct_name="$2"
+
+ [ "$struct_name" ] || return $FAILURE
+
+ if [ ! -e "$leasefile" ]; then
+ f_dprintf "%s: No such file or directory" "$leasefile"
+ return $FAILURE
+ fi
+
+ f_struct "$struct_name" && f_struct_free "$struct_name"
+ f_struct_new DHCP_LEASE "$struct_name"
+
+ eval "$( awk -v struct="$struct_name" '
+ BEGIN {
+ lease_found = 0
+ keyword_list = " \
+ interface \
+ fixed-address \
+ filename \
+ server-name \
+ script \
+ medium \
+ "
+ split(keyword_list, keywords, FS)
+
+ time_list = "renew rebind expire"
+ split(time_list, times, FS)
+
+ option_list = " \
+ host-name \
+ subnet-mask \
+ routers \
+ domain-name-servers \
+ domain-name \
+ broadcast-address \
+ dhcp-lease-time \
+ dhcp-message-type \
+ dhcp-server-identifier \
+ dhcp-renewal-time \
+ dhcp-rebinding-time \
+ "
+ split(option_list, options, FS)
+ }
+ function set_value(prop,value)
+ {
+ lease_found = 1
+ gsub(/[^[:alnum:]_]/, "_", prop)
+ sub(/;$/, "", value)
+ sub(/^"/, "", value)
+ sub(/"$/, "", value)
+ sub(/,.*/, "", value)
+ printf "%s set %s \"%s\"\n", struct, prop, value
+ }
+ /^lease {$/, /^}$/ \
+ {
+ if ( $0 ~ /^lease {$/ ) next
+ if ( $0 ~ /^}$/ ) exit
+
+ for (k in keywords)
+ {
+ keyword = keywords[k]
+ if ( $1 == keyword )
+ {
+ set_value(keyword, $2)
+ next
+ }
+ }
+
+ for (t in times)
+ {
+ time = times[t]
+ if ( $1 == time )
+ {
+ set_value(time, $2 " " $3 " " $4)
+ next
+ }
+ }
+
+ if ( $1 != "option" ) next
+ for (o in options)
+ {
+ option = options[o]
+ if ( $2 == option )
+ {
+ set_value(option, $3)
+ next
+ }
+ }
+ }
+ EXIT {
+ if ( ! lease_found )
+ {
+ printf "f_struct_free \"%s\"\n", struct
+ print "return $FAILURE"
+ }
+ }
+ ' "$leasefile" )"
+}
+
+# f_dhcp_get_info $interface
+#
+# Parse the dhclient(8) lease database for $interface to obtain all the
+# necessary IPv4 details necessary to communicate on the network. The retrieved
+# information is stored in VAR_IPADDR, VAR_NETMASK, VAR_GATEWAY, and
+# VAR_NAMESERVER.
+#
+# If reading the lease database fails, values are obtained from ifconfig(8) and
+# route(8). If the DHCP lease did not provide a nameserver (or likewise, we
+# were unable to parse the lease database), fall-back to resolv.conf(5) for
+# obtaining the nameserver. Always returns success.
+#
+f_dhcp_get_info()
+{
+ local interface="$1" cp
+ local leasefile="/var/db/dhclient.leases.$interface"
+
+ # If it fails, do it the old-fashioned way
+ if f_dhcp_parse_leases "$leasefile" lease; then
+ lease get fixed_address $VAR_IPADDR
+ lease get subnet_mask $VAR_NETMASK
+ lease get routers cp
+ setvar $VAR_GATEWAY "${cp%%,*}"
+ lease get domain_name_servers cp
+ setvar $VAR_NAMESERVER "${cp%%,*}"
+ lease get host_name cp &&
+ setvar $VAR_HOSTNAME "$cp"
+ f_struct_free lease
+ else
+ # Bah, now we have to get the information from ifconfig
+ if f_debugging; then
+ f_dprintf "DHCP configured interface returns %s" \
+ "$( ifconfig "$interface" )"
+ fi
+ f_ifconfig_inet "$interface" $VAR_IPADDR
+ f_ifconfig_netmask "$interface" $VAR_NETMASK
+ f_route_get_default $VAR_GATEWAY
+ fi
+
+ # If we didn't get a name server value, hunt for it in resolv.conf
+ local ns
+ if [ -r "$RESOLV_CONF" ] && ! {
+ f_getvar $VAR_NAMESERVER ns || [ "$ns" ]
+ }; then
+ f_resolv_conf_nameservers cp &&
+ setvar $VAR_NAMESERVER ${cp%%[$IFS]*}
+ fi
+
+ return $SUCCESS
+}
+
+# f_rtsol_get_info $interface
+#
+# Returns the rtsol-provided IPv6 address associated with $interface. The
+# retrieved IP address is stored in VAR_IPV6ADDR. Always returns success.
+#
+f_rtsol_get_info()
+{
+ local interface="$1" cp
+ cp=$( ifconfig "$interface" 2> /dev/null | awk \
+ '
+ BEGIN { found = 0 }
+ ( $1 == "inet6" ) && ( $2 ~ /^fe80:/ ) \
+ {
+ print $2
+ found = 1
+ exit
+ }
+ END { exit ! found }
+ ' ) && setvar $VAR_IPV6ADDR "$cp"
+}
+
+# f_host_lookup $host [$var_to_set]
+#
+# Use host(1) to lookup (or reverse) an Internet number from (or to) a name.
+# Multiple answers are returned separated by a single space. If host(1) does
+# not exit cleanly, its full output is provided and the return status is 1.
+#
+# If nsswitch.conf(5) has been configured to query local access first for the
+# `hosts' database, we'll manually check hosts(5) first (preventing host(1)
+# from hanging in the event that DNS goes awry).
+#
+# If $var_to_set is missing or NULL, the list of IP addresses is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+# The variables from variable.subr used in looking up the host are as follows
+# (which are set manually):
+#
+# VAR_IPV6_ENABLE [Optional]
+# If set to "YES", enables the lookup of IPv6 addresses and IPv4
+# address. IPv6 addresses, if any, will come before IPv4. Note
+# that if nsswitch.conf(5) shows an affinity for "files" for the
+# "host" database and there is a valid entry in hosts(5) for
+# $host, this setting currently has no effect (an IPv4 address
+# can supersede an IPv6 address). By design, hosts(5) overrides
+# any preferential treatment. Otherwise, if this variable is not
+# set, IPv6 addresses will not be used (IPv4 addresses will
+# specifically be requested from DNS).
+#
+# 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_host_lookup_awk='
+BEGIN{ addrs = "" }
+!/^[[:space:]]*(#|$)/ \
+{
+ for (n=1; n++ < NF;) if ($n == name)
+ addrs = addrs (addrs ? " " : "") $1
+}
+END {
+ if (addrs) print addrs
+ exit !addrs
+}
+'
+f_host_lookup()
+{
+ local __host="$1" __var_to_set="$2"
+ f_dprintf "f_host_lookup: host=[%s]" "$__host"
+
+ # If we're configured to look at local files first, do that
+ if awk '/^hosts:/{exit !($2=="files")}' "$NSSWITCH_CONF"; then
+ if [ "$__var_to_set" ]; then
+ local __cp
+ if __cp=$( awk -v name="$__host" \
+ "$f_host_lookup_awk" "$ETC_HOSTS" )
+ then
+ setvar "$__var_to_set" "$__cp"
+ return $SUCCESS
+ fi
+ else
+ awk -v name="$__host" \
+ "$f_host_lookup_awk" "$ETC_HOSTS" &&
+ return $SUCCESS
+ fi
+ fi
+
+ #
+ # Fall back to host(1) -- which is further governed by nsswitch.conf(5)
+ #
+
+ local __output __ip6 __addrs=
+ f_getvar $VAR_IPV6_ENABLE __ip6
+
+ # If we have a TCP media type configured, check for an SRV record
+ local __srvtypes=
+ { f_quietly f_getvar $VAR_HTTP_PATH ||
+ f_quietly f_getvar $VAR_HTTP_PROXY_PATH
+ } && __srvtypes="$__srvtypes _http._tcp"
+ f_quietly f_getvar $VAR_FTP_PATH && __srvtypes="$__srvtypes _ftp._tcp"
+ f_quietly f_getvar $VAR_NFS_PATH &&
+ __srvtypes="$__srvtypes _nfs._tcp _nfs._udp"
+
+ # Calculate wait time as dividend of total time and host(1) invocations
+ local __host_runs __wait
+ f_count __host_runs $__srvtypes
+ if [ "$__ip6" = "YES" ]; then
+ __host_runs=$(( $__host_runs + 2 ))
+ else
+ __host_runs=$(( $__host_runs + 1 ))
+ fi
+ f_getvar $VAR_MEDIA_TIMEOUT __wait
+ [ "$__wait" ] && __wait="-W $(( $__wait / $__host_runs ))"
+
+ # Query SRV types first (1st host response taken as new host to query)
+ for __type in $__srvtypes; do
+ if __output=$(
+ host -t SRV $__wait -- "$__type.$__host" \
+ 2> /dev/null
+ ); then
+ __host=$( echo "$__output" |
+ awk '/ SRV /{print $NF;exit}' )
+ break
+ fi
+ done
+
+ # Try IPv6 first (if enabled)
+ if [ "$__ip6" = "YES" ]; then
+ if ! __output=$( host -t AAAA $__wait -- "$__host" 2>&1 ); then
+ # An error occurred, display in-full and return error
+ [ "$__var_to_set" ] &&
+ setvar "$__var_to_set" "$__output"
+ return $FAILURE
+ fi
+ # Add the IPv6 addresses and fall-through to collect IPv4 too
+ __addrs=$( echo "$__output" | awk '/ address /{print $NF}' )
+ fi
+
+ # Good ol' IPv4
+ if ! __output=$( host -t A $__wait -- "$__host" 2>&1 ); then
+ # An error occurred, display it in-full and return error
+ [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output"
+ return $FAILURE
+ fi
+
+ __addrs="$__addrs${__addrs:+ }$(
+ echo "$__output" | awk '/ address /{print $NF}' )"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__addrs"
+ else
+ echo $__addrs
+ fi
+}
+
+# f_device_dialog_tcp $device
+#
+# This is it - how to get TCP setup values. Prompt the user to edit/confirm the
+# interface, gateway, nameserver, and hostname settings -- all required for
+# general TCP/IP access.
+#
+# Variables from variable.subr that can be used to sript user input:
+#
+# VAR_NO_INET6
+# If set, prevents asking the user if they would like to use
+# rtsol(8) to check for an IPv6 router.
+# VAR_TRY_RTSOL
+# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the
+# user if they would like to try the IPv6 RouTer SOLicitation
+# utility (rtsol(8)) to get IPv6 information. Ignored if
+# VAR_NO_INET6 is set.
+# VAR_TRY_DHCP
+# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the
+# user if they would like to try to acquire IPv4 connection
+# settings from a DHCP server using dhclient(8).
+#
+# VAR_GATEWAY Default gateway to use.
+# VAR_IPADDR Interface address to assign.
+# VAR_NETMASK Interface subnet mask.
+# VAR_EXTRAS Extra interface options to ifconfig(8).
+# VAR_HOSTNAME Hostname to set.
+# VAR_DOMAINNAME Domain name to use.
+# VAR_NAMESERVER DNS nameserver to use when making lookups.
+# VAR_IPV6ADDR IPv6 interface address.
+#
+# In addition, the following variables are used in acquiring network settings
+# from the user:
+#
+# VAR_NONINTERACTIVE
+# If set (such as when running in a script), prevents asking the
+# user questions or displaying the usual prompts, etc.
+# VAR_NETINTERACTIVE
+# The one exception to VAR_NONINTERACTIVE is VAR_NETINTERACTIVE,
+# which if set will prompt the user to try RTSOL (unless
+# VAR_TRY_RTSOL has been set), try DHCP (unless VAR_TRY_DHCP has
+# been set), and display the network verification dialog. This
+# allows you to have a mostly non-interactive script that still
+# prompts for network setup/confirmation.
+#
+# After successful execution, the following variables are set:
+#
+# VAR_IFCONFIG + $device (e.g., `ifconfig_em0')
+# Defines the ifconfig(8) properties specific to $device.
+#
+f_device_dialog_tcp()
+{
+ local dev="$1" devname cp n
+ local use_dhcp="" use_rtsol=""
+ local _ipaddr _netmask _extras
+
+ [ "$dev" ] || return $DIALOG_CANCEL
+ f_struct "$dev" get name devname || return $DIALOG_CANCEL
+
+ # Initialize vars from previous device values
+ local private
+ $dev get private private
+ if [ "$private" ] && f_struct "$private"; then
+ $private get ipaddr _ipaddr
+ $private get netmask _netmask
+ $private get extras _extras
+ $private get use_dhcp use_dhcp
+ $private get use_rtsol use_rtsol
+ else # See if there are any defaults
+
+ #
+ # This is a hack so that the dialogs below are interactive in a
+ # script if we have requested interactive behavior.
+ #
+ local old_interactive=
+ if ! f_interactive && f_netinteractive; then
+ f_getvar $VAR_NONINTERACTIVE old_interactive
+ unset $VAR_NONINTERACTIVE
+ fi
+
+ #
+ # Try a RTSOL scan if such behavior is desired.
+ # If the variable was configured and is YES, do it.
+ # If it was configured to anything else, treat it as NO.
+ # Otherwise, ask the question interactively.
+ #
+ local try6
+ if ! f_isset $VAR_NO_INET6 && {
+ { f_getvar $VAR_TRY_RTSOL try6 && [ "$try6" = "YES" ]; } ||
+ {
+ # Only prompt the user when VAR_TRY_RTSOL is unset
+ ! f_isset $VAR_TRY_RTSOL &&
+ f_dialog_noyes "$msg_try_ipv6_configuration"
+ }
+ }; then
+ local i
+
+ f_quietly sysctl net.inet6.ip6.forwarding=0
+ f_quietly sysctl net.inet6.ip6.accept_rtadv=1
+ f_quietly ifconfig $devname up
+
+ i=$( sysctl -n net.inet6.ip6.dad_count )
+ sleep $(( $i + 1 ))
+
+ f_quietly mkdir -p /var/run
+ f_dialog_info "$msg_scanning_for_ra_servers"
+ if f_quietly rtsol $devname; then
+ i=$( sysctl -n net.inet6.ip6.dad_count )
+ sleep $(( $i + 1 ))
+ f_rtsol_get_info $devname
+ use_rtsol=1
+ else
+ use_rtsol=
+ fi
+ fi
+
+ #
+ # Try a DHCP scan if such behavior is desired.
+ # If the variable was configured and is YES, do it.
+ # If it was configured to anything else, treat it as NO.
+ # Otherwise, ask the question interactively.
+ #
+ local try4
+ if { f_getvar $VAR_TRY_DHCP try4 && [ "$try4" = "YES" ]; } || {
+ # Only prompt the user when VAR_TRY_DHCP is unset
+ ! f_isset $VAR_TRY_DHCP &&
+ f_dialog_noyes "$msg_try_dhcp_configuration"
+ }; then
+ f_quietly ifconfig $devname delete
+ f_quietly mkdir -p /var/db
+ f_quietly mkdir -p /var/run
+ f_quietly mkdir -p /tmp
+
+ local msg="$msg_scanning_for_dhcp_servers"
+ trap - SIGINT
+ ( # Execute in sub-shell to allow/catch Ctrl-C
+ trap 'exit $FAILURE' SIGINT
+ if [ "$USE_XDIALOG" ]; then
+ f_quietly dhclient $devname |
+ f_xdialog_info "$msg"
+ else
+ f_dialog_info "$msg"
+ f_quietly dhclient $devname
+ fi
+ )
+ local retval=$?
+ trap 'f_interrupt' SIGINT
+ if [ $retval -eq $SUCCESS ]; then
+ f_dhcp_get_info $devname
+ use_dhcp=1
+ else
+ use_dhcp=
+ fi
+ fi
+
+ # Restore old VAR_NONINTERACTIVE if needed.
+ [ "$old_interactive" ] &&
+ setvar $VAR_NONINTERACTIVE "$old_interactive"
+
+ # Special hack so it doesn't show up oddly in the menu
+ local gw
+ if f_getvar $VAR_GATEWAY gw && [ "$gw" = "NO" ]; then
+ setvar $VAR_GATEWAY ""
+ fi
+
+ # Get old IP address from variable space, if available
+ if [ ! "$_ipaddr" ]; then
+ if f_getvar $VAR_IPADDR cp; then
+ _ipaddr="$cp"
+ elif f_getvar ${devname}_$VAR_IPADDR cp; then
+ _ipaddr="$cp"
+ fi
+ fi
+
+ # Get old netmask from variable space, if available
+ if [ ! "$_netmask" ]; then
+ if f_getvar $VAR_NETMASK cp; then
+ _netmask="$cp"
+ elif f_getvar ${devname}_$VAR_NETMASK cp; then
+ _netmask="$cp"
+ fi
+ fi
+
+ # Get old extras string from variable space, if available
+ if [ ! "$_extras" ]; then
+ if f_getvar $VAR_EXTRAS cp; then
+ _extras="$cp"
+ elif f_getvar ${devname}_$VAR_EXTRAS cp; then
+ _extras="$cp"
+ fi
+ fi
+ fi
+
+ # Look up values already recorded with the system, or blank the string
+ # variables ready to accept some new data
+ local _hostname _gateway _nameserver
+ f_getvar $VAR_HOSTNAME _hostname
+ case "$_hostname" in
+ *.*) : do nothing ;; # Already fully-qualified
+ *)
+ f_getvar $VAR_DOMAINNAME cp
+ [ "$cp" ] && _hostname="$_hostname.$cp"
+ esac
+ f_getvar $VAR_GATEWAY _gateway
+ f_getvar $VAR_NAMESERVER _nameserver
+
+ # Re-check variables for initial inheritance before heading into dialog
+ [ "$_hostname" ] || _hostname="${HOSTNAME:-$( hostname )}"
+ [ "$_gateway" ] || f_route_get_default _gateway
+ [ ! "$_nameserver" ] &&
+ f_resolv_conf_nameservers cp && _nameserver=${cp%%[$IFS]*}
+ [ "$_ipaddr" ] || f_ifconfig_inet $devname _ipaddr
+ [ "$_netmask" ] || f_ifconfig_netmask $devname _netmask
+
+ # If non-interactive, jump over dialog section and into config section
+ if f_netinteractive || f_interactive || [ ! "$_hostname" ]
+ then
+ [ ! "$_hostname" ] && f_interactive &&
+ f_show_msg "$msg_hostname_variable_not_set"
+
+ local title=" $msg_network_configuration "
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+ local extras_help="$tcplayout_extras_help"
+
+ # Modify the help line for PLIP config
+ [ "${devname#plip}" != "$devname" ] &&
+ extras_help="$tcplayout_extras_help_for_plip"
+
+ f_getvar $VAR_IPV6ADDR cp && [ "$cp" ] &&
+ title="$title($msg_ipv6_ready) "
+
+ if [ ! "$USE_XDIALOG" ]; then
+ local prompt="$msg_dialog_mixedform_navigation_help"
+ # Calculate center position for displaying device label
+ local devlabel="$msg_configuration_for_interface"
+ devlabel="$devlabel $devname"
+ local width=54
+ local n=$(( $width/2 - (${#devlabel} + 4)/2 - 2 ))
+
+ while :; do
+ cp=$( $DIALOG \
+ --title "$title" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --item-help \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --help-button \
+ --help-label "$msg_help" \
+ --mixedform "$prompt" 16 $width 9 \
+ "$msg_host_name_including_domain:" 1 2 \
+ "$_hostname" 2 3 45 255 0 \
+ "$tcplayout_hostname_help" \
+ "$msg_ipv4_gateway:" 3 2 \
+ "$_gateway" 4 3 16 15 0 \
+ "$tcplayout_gateway_help" \
+ "$msg_name_server:" 3 31 \
+ "$_nameserver" 4 32 16 15 0 \
+ "$tcplayout_nameserver_help" \
+ "- $devlabel -" 5 $n "" 0 0 0 0 3 "" \
+ "$msg_ipv4_address:" 6 6 \
+ "$_ipaddr" 7 7 16 15 0 \
+ "$tcplayout_ipaddr_help" \
+ "$msg_netmask:" 6 31 \
+ "$_netmask" 7 32 16 15 0 \
+ "$tcplayout_netmask_help" \
+ "$msg_extra_options_to_ifconfig" 8 6 \
+ "$_extras" 9 7 41 2048 0 \
+ "$extras_help" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+
+ # --mixed-form always returns 0, we have to
+ # use the returned data to determine button
+ if [ ! "$cp" ]; then
+ # User either chose "Cancel", pressed
+ # ESC, or blanked every form field
+ return $DIALOG_CANCEL
+ else
+ n=$( echo "$cp" | f_number_of_lines )
+ [ $n -eq 1 ] && case "$cp" in HELP*)
+ # User chose "Help"
+ f_show_help "$TCP_HELPFILE"
+ continue
+ esac
+ fi
+
+ # Turn mixed-form results into env variables
+ eval "$( echo "$cp" | awk '
+ BEGIN {
+ n = 0
+ field[++n] = "_hostname"
+ field[++n] = "_gateway"
+ field[++n] = "_nameserver"
+ field[++n] = "_ipaddr"
+ field[++n] = "_netmask"
+ field[++n] = "_extras"
+ nfields = n
+ n = 0
+ }
+ {
+ gsub(/'\''/, "'\'\\\\\'\''")
+ sub(/[[:space:]]*$/, "")
+ value[field[++n]] = $0
+ }
+ END {
+ for ( n = 1; n <= nfields; n++ )
+ {
+ printf "%s='\''%s'\'';\n",
+ field[n],
+ value[field[n]]
+ }
+ }' )"
+
+ f_dialog_validate_tcpip \
+ "$_hostname" \
+ "$_gateway" \
+ "$_nameserver" \
+ "$_ipaddr" \
+ "$_netmask" \
+ && break
+ done
+ else
+ # Xdialog(1) does not support --mixed-form
+ # Create a persistent menu instead
+
+ f_dialog_title "$msg_network_configuration"
+ local prompt=
+
+ while :; do
+ cp=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --item-help \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --help "" \
+ --menu "$prompt" 21 60 8 \
+ "$msg_accept_continue" "" \
+ "$tcplayout_accept_cont_help" \
+ "$msg_host_name_including_domain:" \
+ "$_hostname" \
+ "$tcplayout_hostname_help" \
+ "$msg_ipv4_gateway:" "$_gateway" \
+ "$tcplayout_gateway_help" \
+ "$msg_name_server:" "$_nameserver" \
+ "$tcplayout_nameserver_help" \
+ "$msg_ipv4_address:" "$_ipaddr" \
+ "$tcplayout_ipaddr_help" \
+ "$msg_netmask:" "$_netmask" \
+ "$tcplayout_netmask_help" \
+ "$msg_extra_options_to_ifconfig" \
+ "$_extras" "$extras_help" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize cp
+ f_dprintf "retval=%u mtag=[%s]" $retval "$cp"
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$TCP_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ f_dialog_title_restore
+ return $DIALOG_CANCEL
+ fi
+
+ case "$cp" in
+ "$msg_accept_continue")
+ f_dialog_validate_tcpip \
+ "$_hostname" \
+ "$_gateway" \
+ "$_nameserver" \
+ "$_ipaddr" \
+ "$_netmask" \
+ && break ;;
+ "$msg_host_name_including_domain:")
+ f_dialog_input cp "$cp" "$_hostname" \
+ && _hostname="$cp" ;;
+ "$msg_ipv4_gateway:")
+ f_dialog_input cp "$cp" "$_gateway" \
+ && _gateway="$cp" ;;
+ "$msg_name_server:")
+ f_dialog_input cp "$cp" "$_nameserver" \
+ && _nameserver="$cp" ;;
+ "$msg_ipv4_address:")
+ f_dialog_input cp "$cp" "$_ipaddr" \
+ && _ipaddr="$cp" ;;
+ "$msg_netmask:")
+ f_dialog_input cp "$cp" "$_netmask" \
+ && _netmask="$cp" ;;
+ "$msg_extra_options_to_ifconfig")
+ f_dialog_input cp "$cp" "$_extras" \
+ && _extras="$cp" ;;
+ esac
+ done
+
+ f_dialog_title_restore
+
+ fi # XDIALOG
+
+ fi # interactive
+
+ # We actually need to inform the rest of bsdconfig about this
+ # data now if the user hasn't selected cancel.
+
+ if [ "$_hostname" ]; then
+ setvar $VAR_HOSTNAME "$_hostname"
+ f_quietly hostname "$_hostname"
+ case "$_hostname" in
+ *.*) setvar $VAR_DOMAINNAME "${_hostname#*.}" ;;
+ esac
+ fi
+ [ "$_gateway" ] && setvar $VAR_GATEWAY "$_gateway"
+ [ "$_nameserver" ] && setvar $VAR_NAMESERVER "$_nameserver"
+ [ "$_ipaddr" ] && setvar $VAR_IPADDR "$_ipaddr"
+ [ "$_netmask" ] && setvar $VAR_NETMASK "$_netmask"
+ [ "$_extras" ] && setvar $VAR_EXTRAS "$_extras"
+
+ f_dprintf "Creating struct DEVICE_INFO devinfo_%s" "$dev"
+ f_struct_new DEVICE_INFO devinfo_$dev
+ $dev set private devinfo_$dev
+
+ devinfo_$dev set ipaddr $_ipaddr
+ devinfo_$dev set netmask $_netmask
+ devinfo_$dev set extras $_extras
+ devinfo_$dev set use_rtsol $use_rtsol
+ devinfo_$dev set use_dhcp $use_dhcp
+
+ if [ "$use_dhcp" -o "$_ipaddr" ]; then
+ if [ "$use_dhcp" ]; then
+ cp="DHCP${extras:+ $extras}"
+ else
+ cp="inet $_ipaddr netmask $_netmask${extras:+ $extras}"
+ fi
+ setvar $VAR_IFCONFIG$devname "$cp"
+ fi
+ [ "$use_rtsol" ] &&
+ setvar $VAR_IPV6_ENABLE "YES"
+
+ [ "$use_dhcp" ] ||
+ f_config_resolv # XXX this will do it on the MFS copy
+
+ return $DIALOG_OK
+}
+
+# f_device_scan_tcp [$var_to_set]
+#
+# Scan for the first active/configured TCP/IP device. The name of the interface
+# is printed to stderr like other dialog(1)-based functions (stdout is reserved
+# for dialog(1) interaction) if $var_to_set is missing or NULL. Returns failure
+# if no active/configured interface
+#
+f_device_scan_tcp()
+{
+ local __var_to_set="$1" __iface
+ for __iface in $( ifconfig -l ); do
+ if ifconfig $__iface | awk '
+ BEGIN {
+ has_inet = has_inet6 = is_ethernet = 0
+ is_usable = 1
+ }
+ ( $1 == "status:" && $2 != "active" ) { is_usable = 0; exit }
+ ( $1 == "inet" ) {
+ if ($2 == "0.0.0.0") { is_usable = 0; exit }
+ has_inet++
+ }
+ ( $1 == "inet6") { has_inet6++ }
+ ( $1 == "media:" ) {
+ if ($2 != "Ethernet") { is_usable = 0; exit }
+ is_ethernet = 1
+ }
+ END {
+ if (!(is_ethernet && (has_inet || has_inet6)))
+ is_usable = 0
+ exit ! is_usable
+ }'; then
+ f_interactive &&
+ f_show_msg "$msg_using_interface" "$__iface"
+ f_dprintf "f_device_scan_tcp found %s" "$__iface"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__iface"
+ else
+ echo "$__iface" >&2
+ fi
+ return $SUCCESS
+ fi
+ done
+
+ return $FAILURE
+}
+
+# f_device_select_tcp
+#
+# Prompt the user to select network interface to use for TCP/IP access.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_NETWORK_DEVICE [Optional]
+# Either a comma-separated list of network interfaces to try when
+# setting up network access (e.g., "fxp0,em0") or "ANY" (case-
+# sensitive) to indicate that the first active and configured
+# interface is acceptable. If unset, the user is presented with a
+# menu of all available network interfaces.
+#
+# Returns success if a valid network interface has been selected.
+#
+f_device_select_tcp()
+{
+ local devs dev cnt if network_dev
+ f_getvar $VAR_NETWORK_DEVICE network_dev
+
+ f_dprintf "f_device_select_tcp: %s=[%s]" \
+ VAR_NETWORK_DEVICE "$network_dev"
+
+ if [ "$network_dev" ]; then
+ #
+ # This can be set to several types of values. If set to ANY,
+ # scan all network devices looking for a valid link, and go
+ # with the first device found. Can also be specified as a
+ # comma delimited list, with each network device tried in
+ # order. Can also be set to a single network device.
+ #
+ [ "$network_dev" = "ANY" ] && f_device_scan_tcp network_dev
+
+ while [ "$network_dev" ]; do
+ case "$network_dev" in
+ *,*) if="${network_dev%%,*}"
+ network_dev="${network_dev#*,}"
+ ;;
+ *) if="$network_dev"
+ network_dev=
+ esac
+
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_device_dialog_tcp $dev
+ if [ $? -eq $DIALOG_OK ]; then
+ setvar $VAR_NETWORK_DEVICE $if
+ return $DIALOG_OK
+ fi
+ done
+
+ f_interactive && f_show_msg "$msg_no_network_devices"
+ return $DIALOG_CANCEL
+
+ fi # $network_dev
+
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ f_count cnt $devs
+ dev="${devs%%[$IFS]*}"
+ $dev get name if
+
+ f_quietly f_getvar NETWORK_CONFIGURED # for debugging info
+ if ! f_running_as_init &&
+ ! [ "${NETWORK_CONFIGURED+set}" -a "$NETWORK_CONFIGURED" = "NO" ]
+ then
+ trap 'f_interrupt' SIGINT
+ if f_dialog_yesno "$msg_assume_network_is_already_configured"
+ then
+ setvar $VAR_NETWORK_DEVICE $if
+ return $DIALOG_OK
+ fi
+ fi
+
+ local retval=$SUCCESS
+ if [ ${cnt:=0} -eq 0 ]; then
+ f_show_msg "$msg_no_network_devices"
+ retval=$DIALOG_CANCEL
+ elif [ $cnt -eq 1 ]; then
+ f_device_dialog_tcp $dev
+ retval=$?
+ [ $retval -eq $DIALOG_OK ] && setvar $VAR_NETWORK_DEVICE $if
+ else
+ local title="$msg_network_interface_information_required"
+ local prompt="$msg_please_select_ethernet_device_to_configure"
+ local hline="$hline_arrows_tab_enter"
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_NETWORK \
+ "$NETWORK_DEVICE_HELPFILE" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $DIALOG_CANCEL
+
+ f_device_dialog_tcp $dev
+ retval=$?
+ if [ $retval -eq $DIALOG_OK ]; then
+ f_struct_copy "$dev" device_network
+ setvar $VAR_NETWORK_DEVICE device_network
+ else
+ f_struct_free device_network
+ fi
+ fi
+
+ return $retval
+}
+
+# f_dialog_menu_select_tcp
+#
+# Like f_dialog_select_tcp() above, but do it from a menu that doesn't care
+# about status. In other words, where f_dialog_select_tcp() will not display a
+# menu if scripted, this function will always display the menu of available
+# network interfaces.
+#
+f_dialog_menu_select_tcp()
+{
+ local private use_dhcp name
+ NETWORK_CONFIGURED=NO f_device_select_tcp
+ if f_struct device_network &&
+ device_network get private private &&
+ f_struct_copy "$private" di &&
+ di get use_dhcp use_dhcp &&
+ [ ! "$use_dhcp" ] &&
+ device_network get name name &&
+ f_yesno "$msg_would_you_like_to_bring_interface_up" "$name"
+ then
+ if ! f_device_init device_network; then
+ f_show_msg "$msg_initialization_of_device_failed" \
+ "$name"
+ fi
+ fi
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/tcpip.subr
+
+fi # ! $_MEDIA_TCPIP_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/ufs.subr b/contrib/bsddialog/bsdconfig/share/media/ufs.subr
new file mode 100644
index 000000000000..27e2f275b182
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/ufs.subr
@@ -0,0 +1,198 @@
+if [ ! "$_MEDIA_UFS_SUBR" ]; then _MEDIA_UFS_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/ufs.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+UFS_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_ufs
+#
+# Return success if we both found and set the media type to be a UFS partition.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_UFS_PATH
+# Path to a UFS character device node to be used with mount(8) in
+# mounting a UFS formatted partition. Valid examples include:
+# /dev/da0s1a
+# /dev/ad4s1e
+# However, other forms may be valid (see mount(8) for additional
+# information).
+#
+f_media_set_ufs()
+{
+ local ufs
+
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_UFS devs
+ f_count ndevs $devs
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_variable_get_value $VAR_UFS_PATH \
+ "$msg_enter_the_device_name_of_a_ufs_formatted_partition"
+ f_getvar $VAR_UFS_PATH ufs
+ [ "$ufs" ] || return $FAILURE
+
+ local fstype
+ fstype=$( df -nT $ufs 2> /dev/null |
+ awk '!/Type/{print $2;exit}' )
+
+ f_struct_new DEVICE device_ufs
+ device_ufs set name ${fstype:-ufs}
+ device_ufs set devname "$ufs"
+ device_ufs set get f_media_get_ufs
+ device_ufs set init f_media_init_ufs
+ device_ufs set shutdown f_media_shutdown_ufs
+ device_ufs unset private
+
+ f_struct_copy device_ufs device_media
+ f_struct_free device_ufs
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
+ local title="$msg_choose_a_ufs_partition"
+ local prompt="$msg_please_select_ufs_partition"
+ local hline=""
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_UFS \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
+
+ f_struct_copy "$dev" device_media
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_ufs $device
+#
+# Initializes the UFS media device. Returns success if able to mount the UFS
+# partition device using mount(1).
+#
+f_media_init_ufs()
+{
+ local funcname=f_media_init_ufs
+ local dev="$1" devname err
+
+ $dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for UFS device. devname=[%s]" \
+ "$devname"
+
+ if [ "$UFS_MOUNTED" ]; then
+ f_dprintf "UFS device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$devname" ]; then
+ f_show_msg "$msg_no_such_file_or_directory" \
+ "f_media_init_ufs" "$devname"
+ return $FAILURE
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
+ fi
+
+ if ! f_eval_catch -dk err $funcname mount \
+ 'mount "%s" "%s"' "$devname" "$MOUNTPOINT"
+ then
+ err="${err#mount: }"; err="${err#$devname : }"
+ f_show_msg "$msg_error_mounting_device" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+ fi
+ UFS_MOUNTED=1
+ return $SUCCESS
+}
+
+# f_media_get_ufs $device $file [$probe_type]
+#
+# Returns data from $file on a mounted UFS partition device. Similar to cat(1).
+# If $probe_type is present and non-NULL, returns success if $file exists. If
+# $probe_type is equal to $PROBE_SIZE, prints the size of $file in bytes to
+# standard-out.
+#
+f_media_get_ufs()
+{
+ local dev="$1" file="$2" probe_type="$3"
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_ufs: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
+}
+
+# f_media_shutdown_ufs $device
+#
+# Shuts down the UFS device using umount(8). Return status should be ignored.
+#
+f_media_shutdown_ufs()
+{
+ local funcname=f_media_shutdown_ufs
+ local dev="$1" err
+
+ [ "$UFS_MOUNTED" ] || return $FAILURE
+
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_ufs_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ UFS_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/ufs.subr
+
+fi # ! $_MEDIA_UFS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/usb.subr b/contrib/bsddialog/bsdconfig/share/media/usb.subr
new file mode 100644
index 000000000000..5ee9bc043800
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/usb.subr
@@ -0,0 +1,176 @@
+if [ ! "$_MEDIA_USB_SUBR" ]; then _MEDIA_USB_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/usb.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+USB_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_usb
+#
+# Attempt to use USB as the media type. Return success if we both found and set
+# the media type to be a USB drive.
+#
+f_media_set_usb()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_USB devs
+ f_count ndevs $devs
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_show_msg "$msg_no_usb_devices_found"
+ return $FAILURE
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
+ local title="$msg_choose_a_usb_drive"
+ local prompt="$msg_please_select_a_usb_drive"
+ local hline=
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_USB \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
+
+ f_struct_copy "$dev" device_media
+ fi
+
+ f_struct device_media &&
+ device_media unset private
+
+ if f_interactive; then
+ local name
+ f_struct device_media get name name
+ f_show_msg "$msg_using_usb_device" "$name"
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_usb $device
+#
+# Initializes the USB media device. Returns success if able to mount the USB
+# disk device using mount(8).
+#
+f_media_init_usb()
+{
+ local funcname=f_media_init_usb
+ local dev="$1" devname err
+
+ $dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for USB device. devname=[%s]" \
+ "$devname"
+
+ if [ "$USB_MOUNTED" ]; then
+ f_dprintf "USB device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
+ fi
+
+ if f_eval_catch -dk err $funcname mount \
+ 'mount "%s" "%s"' "$devname" "$MOUNTPOINT"
+ then
+ USB_MOUNTED=1
+ return $SUCCESS
+ fi
+
+ err="${err#mount: }"; err="${err#$devname: }"
+ f_show_msg "$msg_error_mounting_usb_drive" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+}
+
+# f_media_get_usb $device $file [$probe_type]
+#
+# Returns data from $file on a mounted USB disk device. Similar to cat(1). If
+# $probe_type is present and non-NULL, returns success if $file exists. If
+# $probe_type is equal to $PROBE_SIZE, prints the size of $file in bytes to
+# standard-out.
+#
+f_media_get_usb()
+{
+ local dev="$1" file="$2" probe_type="$3"
+ local name
+
+ $dev get name name
+ f_dprintf "f_media_get_usb: dev=[%s] file=[%s] probe_type=%s" \
+ "$name" "$file" "$probe_type"
+
+ f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
+}
+
+# f_media_shutdown_usb $device
+#
+# Shuts down the USB disk device using umount(8). Return status should be
+# ignored.
+#
+f_media_shutdown_usb()
+{
+ local funcname=f_media_shutdown_usb
+ local dev="$1" err
+
+ [ "$USB_MOUNTED" ] || return $FAILURE
+
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_ufs_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ USB_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/usb.subr
+
+fi # ! $_MEDIA_USB_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/media/wlan.subr b/contrib/bsddialog/bsdconfig/share/media/wlan.subr
new file mode 100644
index 000000000000..f25cddff94cd
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/media/wlan.subr
@@ -0,0 +1,1392 @@
+if [ ! "$_MEDIA_WLAN_SUBR" ]; then _MEDIA_WLAN_SUBR=1
+#
+# Copyright (c) 2013-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/wlan.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+NWIRELESS_CONFIGS=0
+NWSCAN_RESULTS=0
+
+#
+# Settings used while interacting with various dialog(1) menus
+#
+: ${DIALOG_MENU_WLAN_SCAN_DURATION:=5}
+: ${DIALOG_MENU_WLAN_SHOW_ALL=}
+: ${DIALOG_MENU_WLAN_SHOW_CONFIGURED=1}
+: ${DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS=1}
+
+#
+# Structure to contain the wpa_supplicant.conf(5) default overrides
+#
+f_struct_define WPA_DEFAULTS \
+ ap_scan \
+ ctrl_interface \
+ ctrl_interface_group \
+ eapol_version \
+ fast_reauth
+
+#
+# Structure of wpa_supplicant.conf(5) network={ ... } entry
+#
+f_struct_define WPA_NETWORK \
+ anonymous_identity \
+ auth_alg \
+ bssid \
+ ca_cert \
+ ca_cert2 \
+ client_cert \
+ client_cert2 \
+ dh_file \
+ dh_file2 \
+ eap \
+ eap_workaround \
+ eapol_flags \
+ eappsk \
+ engine \
+ engine_id \
+ frequency \
+ group \
+ identity \
+ key_id \
+ key_mgmt \
+ mixed_cell \
+ mode \
+ nai \
+ pac_file \
+ pairwise \
+ password \
+ pcsc \
+ phase1 \
+ phase2 \
+ pin \
+ priority \
+ private_key \
+ private_key2 \
+ private_key2_passwd \
+ private_key_passwd \
+ proto \
+ psk \
+ scan_ssid \
+ server_nai \
+ ssid \
+ subject_match \
+ subject_match2 \
+ wep_key0 \
+ wep_key1 \
+ wep_key2 \
+ wep_key3 \
+ wpa_ptk_rekey \
+ wep_tx_keyidx
+
+#
+# The following properties are ``Lists'' and as such should not be quoted.
+# Everything else should be quoted.
+#
+WPA_NETWORK_LIST_PROPERTIES="
+ auth_algo
+ eap
+ group
+ key_mgmt
+ pairwise
+ proto
+" # END-QUOTE
+
+#
+# Structure of wpa_cli(8) `scan_results' entry
+#
+f_struct_define WPA_SCAN_RESULT \
+ bssid \
+ flags \
+ freq \
+ siglev \
+ ssid
+
+#
+# Structure of a menu item in the wireless editor
+#
+f_struct_define WLAN_MENU_ITEM \
+ letter \
+ ssid \
+ nconfigs \
+ nfound \
+ help
+
+############################################################ FUNCTIONS
+
+# f_wpa_supplicant_init $file
+#
+# Initialize $file with basic contents of new wpa_supplicant.conf(5).
+#
+f_wpa_supplicant_init()
+{
+ local funcname=f_wpa_supplicant_init
+ local conf_file="$1" tmpfile
+
+ # Create a temporary file
+ f_eval_catch -k tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" ||
+ return $FAILURE
+
+ # Make it unreadable by anyone but ourselves
+ f_eval_catch $funcname chmod \
+ 'chmod 0600 "%s"' "$tmpfile" || return $FAILURE
+
+ # Make it owned by root/wheel
+ f_eval_catch $funcname chown \
+ 'chown 0:0 "%s"' "$tmpfile" || return $FAILURE
+
+ # Populate it
+ cat <<-EOF >> "$tmpfile"
+ ctrl_interface=/var/run/wpa_supplicant
+ eapol_version=2
+ ap_scan=1
+ fast_reauth=1
+ EOF
+ echo >> "$tmpfile"
+
+ # Move it into place
+ f_eval_catch $funcname mv 'mv "%s" "%s"' "$tmpfile" "$conf_file"
+}
+
+# f_wpa_supplicant_parse $file [struct_prefix [count_var]]
+#
+# Parse wpa_supplicant.conf(5) $file. Default overrides are stored in a struct
+# (see struct.subr for additional details) named `{struct_prefix}defaults'. See
+# WPA_DEFAULTS struct definition in the GLOBALS section above.
+#
+# In addition, for each one of the wireless networks we parse from $file,
+# create a struct named `struct_prefixN' where `N' is a number starting from 1
+# and ending in $count_var (zero means no networks). See WPA_NETWORK struct
+# definition in the GLOBALS section above.
+#
+# If a `blob-base64-*={ ... }' entry appears, a struct named
+# `{struct_prefix}blob_base64_*' is created and the `data' property holds the
+# base64 encoded binary data without whitespace.
+#
+# Custom `*={ ... }' definitions are also supported, but should be unique
+# (unlike the `network' definition). A struct named `{struct_prefix}*' is
+# created if at least one property is defined in the block.
+#
+f_wpa_supplicant_parse()
+{
+ local file="$1" struct_prefix="$2" count_var="$3"
+
+ [ "$count_var" ] && setvar "$count_var" 0
+
+ [ "$file" ] || file=$( f_sysrc_get wpa_supplicant_conf_file )
+ if [ ! -e "$file" ]; then
+ f_dprintf "%s: No such file or directory" "$file"
+ return $FAILURE
+ fi
+
+ local list_properties
+ f_replaceall "$WPA_NETWORK_LIST_PROPERTIES" "$NL" "" list_properties
+ eval "$( awk \
+ -v count_var="$count_var" \
+ -v struct_prefix="$struct_prefix" \
+ -v list_properties="$list_properties" '
+ BEGIN {
+ if (!count_var && !struct_prefix) exit
+ blob = count = custom_struct = network = 0
+ split(list_properties, lists, FS)
+ }
+ function set_value(struct, prop, value)
+ {
+ quoted = substr(value, 0, 1) == "\""
+ for (l in lists) if (list = prop == lists[l]) break
+ # Remove data after whitespace if unquoted and not a list
+ if (!quoted && !list) sub("[[:space:]].*", "", value)
+ # Otherwise if quoted and not a list, remove the quotes
+ # NB: wep_keyN needs to retain quoting if/when present
+ else if (quoted && !list && prop !~ /^wep_key[[:digit:]]+/) {
+ sub("^\"", "", value)
+ sub("\".*", "", value)
+ }
+ gsub(/'\''/, "'\''\\'\'\''", value) # Sanitize the value
+ if (!created[struct]) {
+ print "debug= f_struct_free", struct
+ print "debug= f_struct_new WPA_NETWORK", struct
+ created[struct] = 1
+ }
+ printf "debug= %s set %s '\'%s\''\n", struct, prop, value
+ }
+ {
+ if ($1 ~ /^network={/) {
+ empty = 1 # We do not increment count unless !empty
+ network = 1
+ next
+ } else if (match($1, "^blob-base64-[[:alnum:]_./-]+={")) {
+ blob = 1
+ blob_data = ""
+ struct = struct_prefix "blob_bas64_"
+ struct = struct substr($1, 13, RLENGTH - 14)
+ next
+ } else if (match($1, "^[[:alnum:]_./-]+={")) {
+ empty = 1
+ custom_struct = 1
+ struct = struct_prefix substr($1, 0, RLENGTH - 2)
+ gsub(/[^[:alnum:]_]/, "_", struct)
+ next
+ } else if ($1 ~ /^}/) {
+ if (blob) {
+ gsub("[[:space:]]", "", blob_data)
+ set_value(struct, "data", blob_data)
+ }
+ blob = custom_struct = network = 0
+ next
+ } else if (!match($0, /^[[:space:]]*[[:alnum:]_]+=/))
+ next
+
+ if (blob) {
+ blob_data = blob_data $0
+ next
+ } else if (network) {
+ if (empty) { count++; empty = 0 }
+ struct = struct_prefix count
+ } else if (!custom_struct)
+ struct = struct_prefix "defaults"
+
+ if (!struct_prefix) next
+
+ prop = substr($0, 0, RLENGTH - 1)
+ sub(/^[[:space:]]*/, "", prop)
+ value = substr($0, RSTART + RLENGTH)
+
+ set_value(struct, prop, value)
+ }
+ END { if (count_var) print count_var "=" count }' "$file" )"
+}
+
+# f_wpa_scan_results_parse [struct_prefix [count_var]]
+#
+# Parse the results of wpa_cli(8) `scan_results' into a series of structs (see
+# struct.subr for additional details) named `struct_prefixN' where `N' is a
+# number starting from 1 and ending in $count_var (zero means no results). See
+# WPA_SCAN_RESULT struct definition in the GLOBALS section above.
+#
+f_wpa_scan_results_parse()
+{
+ local struct_prefix="$1" count_var="$2"
+
+ [ "$count_var" ] && setvar "$count_var" 0
+
+ eval "$( wpa_cli scan_results 2> /dev/null | awk \
+ -v count_var="$count_var" \
+ -v struct_prefix="$struct_prefix" '
+ BEGIN {
+ if (!count_var && !struct_prefix) exit
+ count = 0
+ seg = "[[:xdigit:]][[:xdigit:]]"
+ bssid = seg":"seg":"seg":"seg":"seg":"seg
+ freq = siglev = flags = "[^[:space:]]+"
+ S = "[[:space:]]+"
+ line = bssid S freq S siglev S flags
+ line = "^[[:space:]]*" line "[[:space:]]*"
+ }
+ function set_value(struct, prop, value)
+ {
+ gsub(/'\''/, "'\''\\'\'\''", value) # Sanitize the value
+ if (!created[struct]) {
+ print "debug= f_struct_free", struct
+ print "debug= f_struct_new WPA_SCAN_RESULT", struct
+ created[struct] = 1
+ }
+ printf "debug= %s set %s '\'%s\''\n", struct, prop, value
+ }
+ {
+ if (!match($0, line)) next
+ ssid = substr($0, RLENGTH + 1)
+
+ count++
+ if (!struct_prefix) next
+
+ struct = struct_prefix count
+ set_value(struct, "ssid", ssid)
+ set_value(struct, "bssid", $1)
+ set_value(struct, "freq", $2)
+ set_value(struct, "siglev", $3)
+ set_value(struct, "flags", $4)
+ }
+ END { if (count_var) print count_var "=" count }' )"
+}
+
+# f_wpa_scan_match_network WPA_SCAN_RESULT WPA_NETWORK
+#
+# Compares a WPA_SCAN_RESULT struct to a WPA_NETWORK struct. If they appear to
+# be a match returns success, otherwise failure.
+#
+f_wpa_scan_match_network()
+{
+ local scan_struct="$1" wireless_struct="$2"
+ local cp debug=
+
+ f_struct "$scan_struct" || return $FAILURE
+ f_struct "$wireless_struct" || return $FAILURE
+
+ local scan_ssid scan_bssid
+ $scan_struct get ssid scan_ssid
+ $scan_struct get bssid scan_bssid
+ local wireless_ssid wireless_bssid
+ $wireless_struct get ssid wireless_ssid
+ $wireless_struct get bssid wireless_bssid
+
+ local id_matched=
+ if [ "$wireless_ssid" -a "$wireless_bssid" ]; then
+ # Must match both SSID and BSSID
+ [ "$scan_ssid" = "$wireless_ssid" -a \
+ "$scan_bssid" = "$wireless_bssid" ] && id_matched=1
+ elif [ "$wireless_ssid" ]; then
+ # Must match SSID only
+ [ "$scan_ssid" = "$wireless_ssid" ] && id_matched=1
+ elif [ "$wireless_bssid" ]; then
+ # Must match BSSID only
+ [ "$scan_bssid" = "$wireless_bssid" ] && id_matched=1
+ fi
+ [ "$id_matched" ] || return $FAILURE
+
+
+ #
+ # Get the scanned flags for the next few comparisons
+ #
+ local flags
+ $scan_struct get flags flags
+
+ #
+ # Compare configured key management against scanned network
+ #
+ if $wireless_struct get key_mgmt cp && [ "$cp" -a "$cp" != "NONE" ]
+ then
+ local mgmt mgmt_matched=
+ for mgmt in $cp; do
+ local mgmt2="$mgmt"
+ [ "$mgmt" != "${mgmt#WPA-}" ] &&
+ mgmt2="WPA2${mgmt#WPA}"
+ case "$flags" in
+ "$mgmt"|"$mgmt"-*|*-"$mgmt"|*-"$mgmt"-*)
+ mgmt_matched=1 break ;;
+ "$mgmt2"|"$mgmt2"-*|*-"$mgmt2"|*-"$mgmt2"-*)
+ mgmt_matched=1 break ;;
+ esac
+ done
+ [ "$mgmt_matched" ] || return $FAILURE
+ fi
+
+ local enc type flag
+
+ #
+ # Compare configured encryption against scanned network
+ #
+ for enc in psk:PSK eap:EAP \
+ wep_key0:WEP wep_key1:WEP wep_key2:WEP wep_key3:WEP
+ do
+ type=${enc%%:*}
+ flag=${enc#*:}
+ { debug= $wireless_struct get $type cp && [ "$cp" ]; } ||
+ continue
+ # Configured network requires encryption
+ case "$flags" in "[$flag]"|*"-$flag-"*)
+ break # Success; stop after first match
+ esac
+ return $FAILURE
+ done
+ cp="" # sensitive info
+
+ #
+ # Compare scanned network encryption against configuration
+ # NB: Scanned network flags indicates _one_ of PSK EAP or WEP
+ # NB: Otherwise, no encryption (so encryption won't match)
+ #
+ local enc_wanted=
+ for enc in -PSK-:psk -EAP-:eap; do
+ flag=${enc%%:*}
+ type=${enc#*:}
+ case "$flags" in *"$flag"*)
+ enc_wanted=1
+ { debug= $wireless_struct get $type cp &&
+ [ "$cp" ]; } || return $FAILURE
+ break # success
+ esac
+ done
+ case "$flags" in *"[WEP]"*)
+ enc_wanted=1
+ local wep_found=
+ for type in wep_key0 wep_key1 wep_key2 wep_key3; do
+ debug= $wireless_struct get $type cp && [ "$cp" ] &&
+ wep_found=1 break
+ done
+ [ "$wep_found" ] || return $FAILURE
+ esac
+ if [ ! "$enc_wanted" ]; then
+ # No match if the network specifies encryption
+ for type in psk eap wep_key0 wep_key1 wep_key2 wep_key3; do
+ debug= $wireless_struct get $type cp && [ "$cp" ] &&
+ return $FAILURE
+ done
+ fi
+ cp="" # sensitive info
+
+ return $SUCCESS
+}
+
+# f_wpa_scan_find_matches scans_prefix $scans_count \
+# wireless_prefix $wireless_count
+#
+# For each struct from `{scans_prefix}1' up to `{scans_prefix}$scans_count'
+# (see struct.subr for additional details) compare the wireless network info
+# (defined as struct WPA_SCAN_RESULT) to that of each configured wireless
+# stored in `{wireless_prefix}1' (defined as struct WPA_NETWORK) up to
+# `{wireless_prefix}$wireless_count'.
+#
+# If a scanned network is deemed to be a match to a configured wireless
+# network, a new `match' property is set on the WPA_NETWORK struct with a value
+# of `{scans_prefix}N' (where N represents the scanned network that matched).
+# At the same time, a new `matched' property is set on the WPA_SCAN_RESULT
+# struct with a value of 1, indicating that this network has been matched to a
+# stored [known] configuration and that it should not be displayed in menus.
+#
+# NB: If a matching entry is not correct, the user can optionally `Forget' the
+# network and that will cause the WPA_SCAN_RESULT to no longer match anything,
+# causing it to appear in the menus again.
+#
+# Return status should be ignored.
+#
+f_wpa_scan_find_matches()
+{
+ local scans_prefix="$1" scans_count="$2"
+ local wireless_prefix="$3" wireless_count="$4"
+ local matches
+
+ [ "$scans_count" -a "$wireless_count" ] || return $SUCCESS
+ f_isinteger "$scans_count" || return $FAILURE
+ f_isinteger "$wireless_count" || return $FAILURE
+
+ #
+ # Go through and eradicate any flags we set in a prior run, as things
+ # might have changed on us (either from the config side or scan side)
+ #
+ local w=1
+ while [ $w -le $wireless_count ]; do
+ f_struct "$wireless_prefix$w" set matches ""
+ w=$(( $w + 1 ))
+ done
+
+ #
+ # Find matches and set match data on structs
+ #
+ local s=1
+ while [ $s -le $scans_count ]; do
+ f_struct "$scans_prefix$s" set matched ""
+ w=1
+ while [ $w -le $wireless_count ]; do
+ if f_wpa_scan_match_network \
+ "$scans_prefix$s" "$wireless_prefix$w"
+ then
+ f_struct "$scans_prefix$s" set matched 1
+ debug= f_struct "$wireless_prefix$w" \
+ get matches matches
+ matches="$matches${matches:+ }$scans_prefix$s"
+ f_struct "$wireless_prefix$w" \
+ set matches "$matches"
+ break # to next scan result
+ fi
+ w=$(( $w + 1 ))
+ done
+ s=$(( $s + 1 ))
+ done
+}
+
+# f_dialog_menu_wlandev_edit $wlandev [$defaultitem]
+#
+# Display a list of wireless network devices (wlan*) associated with
+# $wlandev (e.g., `iwn0'). Allow the user to create and destroy wlan interfaces
+# while selecting ones to be cloned at startup (by setting `wlans_$wlandev').
+#
+f_dialog_menu_wlandev_edit()
+{
+ local funcname=f_dialog_menu_wlandev_edit
+ local wlandev="$1" defaultitem="$2"
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ [ "$wlandev" ] || return $FAILURE
+
+ f_sprintf prompt "$msg_select_wlan_interfaces_for" "wlandev"
+
+ #
+ # Initially mark wlan devices with a %parent of $wlandev
+ #
+ local dev devs if list_to_save=
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ for dev in $devs; do
+ f_struct "$dev" get name if || continue
+ case "$if" in wlan[0-9]*)
+ parent=$( sysctl -n net.wlan.${if#wlan}.%parent \
+ 2> /dev/null )
+ if [ "$parent" = "$if" ]; then
+ local _wlanmark_$if="X"
+ list_to_save="$list_to_save $if"
+ fi
+ esac
+ done
+ list_to_save="${list_to_save# }"
+
+ #
+ # Operate in a loop so we can create/destroy interfaces from here
+ #
+ while :; do
+ #
+ # Refresh list of wlan interfaces
+ #
+ local wlanlist=
+ f_device_rescan_network
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ for dev in $devs; do
+ f_struct "$dev" get name if || continue
+ case "$if" in wlan[0-9]*)
+ wlanlist="$wlanlist $if"
+ esac
+ done
+
+ #
+ # Build menu list of wlan devices
+ #
+ local menu_list="
+ '> $msg_save_exit' '$msg_return_to_previous_menu'
+ '> $msg_create_new' 'wlan'
+ '> $msg_destroy' '...'
+ " # END-QUOTE
+ local parent X
+ for if in $wlanlist; do
+ f_getvar _wlanmark_$if-" " X
+ menu_list="$menu_list '[$X] $if' '%parent: $parent'"
+ [ "$defaultitem" = "$if" ] && defaultitem="[$X] $if"
+ done
+
+ #
+ # Ask user to make a choice
+ #
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" \
+ $menu_list
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $FAILURE
+ f_dialog_data_sanitize menu_choice
+
+ case "$menu_choice" in
+ "> $msg_save_exit") # Save list to rc.conf(5) `wlans_$wlandev'
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set "wlans_%s" "%s"' \
+ "$wlandev" "$list_to_save" || continue
+ break # to success
+ ;;
+ "> $msg_create_new") # Create new wlan interface for wlandev
+ local wlan
+ f_eval_catch -k wlan $funcname ifconfig \
+ 'ifconfig wlan create wlandev "%s"' \
+ "$wlandev" || continue
+ local _wlanmark_$wlan="X"
+ list_to_save="$list_to_save${list_to_save:+ }$wlan"
+ ;;
+ "> $msg_destroy") # Display a menu to pick one item to destroy
+ [ "$wlanlist" ] || continue # Nothing to destroy
+
+ menu_list=
+ for if in $wlanlist; do
+ menu_list="$menu_list '$if' ''"
+ done
+ local msg="$msg_pick_an_interface_to_destroy"
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \"$btitle\" \"\$msg\" \"\" $menu_list
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --ok-label \"\$msg_destroy\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$msg\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || continue
+ f_dialog_data_sanitize menu_choice
+ f_eval_catch $funcname ifconfig \
+ 'ifconfig "%s" destroy' "$menu_choice"
+ ;;
+ "[ ] wlan"[0-9]*) # Unmarked; Mark
+ if="${menu_choice#??? }"
+ local _wlanmark_$if="X"
+ list_to_save="$list_to_save${list_to_save:+ }$if"
+ ;;
+ "[X] wlan"[0-9]*) # Marked; Unmark
+ menu_choice="${menu_choice#??? }"
+ local _wlanmark_$menu_choice=" "
+ local new_list_to_save=
+ for if in $list_to_save; do
+ [ "$if" = "$menu_choice" ] && continue
+ new_list_to_save="$new_list_to_save $if"
+ done
+ list_to_save="${new_list_to_save# }"
+ ;;
+ esac
+ done
+
+ return $SUCCESS
+}
+
+# f_dialog_scan_wireless
+#
+# Initiate a scan for wireless networks. If wpa_supplicant(8) is not running
+# but a wlan interface has been created, start an instance of wpa_supplicant(8)
+# with the first wlan(4) interface we find. After initiating the scan, displays
+# a message for 5 seconds (with option to dismiss). Returns failure if an error
+# occurs, otherwise success.
+#
+f_dialog_scan_wireless()
+{
+ local funcname=f_dialog_scan_wireless
+
+ #
+ # Try to communicate with a running wpa_supplicant(8)
+ #
+ if ! f_eval_catch -d $funcname wpa_cli 'wpa_cli ping'; then
+
+ # If there is indeed one running, bail!
+ if ps axo ucomm= | grep -qw wpa_supplicant; then
+ f_show_msg "$msg_failed_to_reach_wpa_supplicant" \
+ "$msg_wpa_cli_ping_failed"
+ return $FAILURE
+ fi
+
+ # Try and find a wlan device so we can start wpa_supplicant
+ local dev devs if wlan=
+ f_device_rescan_network
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ for dev in $devs; do
+ f_struct "$dev" get name if || continue
+ case "$if" in wlan[0-9]*)
+ wlan=$if
+ break
+ esac
+ done
+ if [ ! "$wlan" ]; then
+ # We can't start wpa_supplicant without wlan interface
+ # Tell the user they have to create one by navigating
+ # to a Wireless device to create a wlan interface. But
+ # let's go one step further and find an interface that
+ # we can provide in the prompt text.
+ local wlandev=
+ for if in $devs; do
+ case "$if" in wlan[0-9]*) next; esac
+ if f_device_is_wireless $if; then
+ wlandev=$if
+ break
+ fi
+ done
+ if [ "$wlandev" ]; then
+ f_show_msg "$msg_cant_start_wpa_supplicant" \
+ "$wlandev"
+ else
+ # Warn user, appears no wireless available
+ f_show_msg "$msg_warning_no_wireless_devices"
+ fi
+ return $FAILURE
+ fi
+
+ # NB: Before we can proceed to fire up wpa_supplicant(8), let's
+ # make sure there is a bare-bones wpa_supplicant.conf(5) for it
+ local conf_file
+ conf_file=$( f_sysrc_get wpa_supplicant_conf_file )
+ if [ ! -e "$conf_file" ]; then
+ f_wpa_supplicant_init "$conf_file" || return $FAILURE
+ f_eval_catch -d $funcname wpa_cli 'wpa_cli reconfigure'
+ fi
+
+ # Try and start wpa_supplicant(8)
+ f_eval_catch $funcname wpa_supplicant \
+ '/etc/rc.d/wpa_supplicant start "%s"' "$wlan" ||
+ return $FAILURE
+
+ # Try to reach this new wpa_supplicant(8)
+ if ! f_eval_catch -d $funcname wpa_cli 'wpa_cli ping'; then
+ f_show_msg "$msg_failed_to_reach_wpa_supplicant" \
+ "$msg_wpa_cli_ping_failed"
+ return $FAILURE
+ fi
+
+ fi # ! f_quietly wpa_cli ping
+
+ # If we reach hear, then it should be OK to scan the airwaves
+ f_eval_catch -d $funcname wpa_cli 'wpa_cli scan' || return $FAILURE
+
+ # Return immediately if a duration is: null or not a number >= 1
+ local duration="$DIALOG_MENU_WLAN_SCAN_DURATION"
+ f_isinteger "$duration" || return $SUCCESS
+ [ $duration -gt 0 ] || return $SUCCESS
+
+ # Display a message that times-out if not dismissed manually
+ local prompt
+ f_sprintf prompt "$msg_scanning_wireless_pausing" "$duration"
+ f_dialog_pause "$prompt" "$duration"
+}
+
+# f_dialog_wireless_edit $ssid
+#
+# Display a menu to allow the user to either create a new entry for the
+# wpa_supplicants.conf(5) file, or to edit values for an existing entry.
+#
+# If more than one wireless network is found to match $ssid, a sub-menu is
+# presented, allowing the user to select the desired network.
+#
+f_dialog_wireless_edit()
+{
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt1="$msg_select_the_configuration_you_would_like"
+ local prompt2 # Calculated below
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+ local ssid="$1" bssid="$2"
+
+ f_sprintf prompt2 "$msg_wireless_network_configuration_for" "$ssid"
+
+ #
+ # Find one or more configurations that match the SSID selection
+ #
+ local height1 width1 rows1 menu_list1=
+ local n=0 nmatches=0 tag wssid wbssid help matches=
+ while [ $n -lt $NWIRELESS_CONFIGS ]; do
+ n=$(( $n + 1 ))
+
+ debug= f_struct WIRELESS_$n get ssid wssid
+ [ "$ssid" = "$wssid" ] || continue
+ debug= f_struct WIRELESS_$n get bssid wbssid
+ [ "${bssid:-$wbssid}" = "$wbssid" ] || continue
+
+ nmatches=$(( $nmatches + 1 ))
+ [ $nmatches -le ${#DIALOG_MENU_TAGS} ] || break
+ f_substr -v tag "$DIALOG_MENU_TAGS" $nmatches 1
+
+ f_wireless_describe WIRELESS_$n help
+ menu_list1="$menu_list1
+ '$tag $wssid' '$wbssid' '$help'
+ " # END-QUOTE
+
+ matches="$matches WIRELESS_$n"
+ done
+ if [ $nmatches -eq 0 ]; then
+ f_show_msg "$msg_cannot_edit_wireless_ssid" "$ssid"
+ return $FAILURE
+ elif [ $nmatches -eq 1 ]; then
+ struct=${matches# }
+ else
+ eval f_dialog_menu_with_help_size height1 width1 rows1 \
+ \"\$title\" \"\$btitle\" \"\$prompt1\" \"\$hline\" \
+ $menu_list1
+ fi
+
+ #
+ # Operate in a loop; for the case of $nmatches > 1, we can cycle back
+ # to allow the user to make another choice after inspecting each one.
+ #
+ local menu_choice index struct defaultitem1=
+ while :; do
+ if [ $nmatches -gt 1 ]; then
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --item-help \
+ --default-item \"\$defaultitem1\" \
+ --menu \"\$prompt1\" \
+ $height1 $width1 $rows1 \
+ $menu_list1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $FAILURE
+ f_dialog_data_sanitize menu_choice
+ defaultitem1="$menu_choice"
+ index=$( eval f_dialog_menutag2index_with_help \
+ \"\$menu_choice\" $menu_list1 )
+ struct=$( set -- $matches; eval echo \${$index} )
+ fi
+
+ #
+ # Operate within another loop to allow editing multiple values
+ #
+ local menu_list2 height2 width2 rows2 member
+ while :; do
+ menu_list2="
+ '> $msg_save_exit'
+ '$msg_return_to_previous_menu'
+ " # END-QUOTE
+ n=0
+ for member in $_struct_typedef_WPA_NETWORK; do
+ [ "$member" = "ssid" ] && continue
+ debug= $struct get $member value || continue
+ n=$(( $n + 1 ))
+ [ $n -le ${#DIALOG_MENU_TAGS} ] || break
+ f_substr -v tag "$DIALOG_MENU_TAGS" $n 1
+ if [ ${#value} -gt 32 ]; then
+ f_snprintf value 29 "%s" "$value"
+ value="$value..."
+ fi
+ case "$member" in
+ password|pin|private_key_passwd|psk|wep_key*)
+ f_replaceall "$value" "?" "*" value ;;
+ esac
+ f_shell_escape "$value" value
+ menu_list2="$menu_list2
+ '$tag $member' '$value'
+ " # END-QUOTE
+ done
+ eval f_dialog_menu_size height2 width2 rows2 \
+ \"\$title\" \"\$btitle\" \"\$prompt2\" \
+ \"\$hline\" $menu_list2
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem2\" \
+ --menu \"\$prompt2\" \
+ $height2 $width2 $rows2 \
+ $menu_list2 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || break
+ f_dialog_data_sanitize menu_choice
+ defaultitem2="$menu_choice"
+
+ # XXXDT Unfinished
+ done
+ [ $nmatches -eq 1 ] && break
+ done
+
+ #
+ # XXXDT Unfinished
+ # This is where we display a menu that edits the entry
+ # And then we modify the wpa_supplicants.conf(5) config file
+ # XXXDT Unfinished
+ #
+
+ return $FAILURE # XXXDT Simulating DIALOG_CANCEL to mean ``no changes''
+}
+
+# f_wireless_describe WPA_NETWORK [$var_to_set]
+#
+# Provide a description of the WPA_NETWORK struct. If $var_to_set is missing or
+# NULL, the description is provided on standard output (which is less preferred
+# due to performance; e.g., if called in a loop).
+#
+f_wireless_describe()
+{
+ local __struct="$1" __var_to_set="$2" debug=
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ f_struct "$__struct" || return $FAILURE
+
+ #
+ # Basic description is `proto key_mgmt group eap'
+ #
+ local __member __cp __desc=
+ for __member in proto key_mgmt group eap; do
+ $__struct get $__member __cp && [ "$__cp" ] &&
+ __desc="$__desc${__desc:+ }$__cp"
+ done
+
+ local __check __kk
+
+ #
+ # Make sure we add WEP40/WEP140 even if omitted from the key_mgmt
+ # section of entry
+ #
+ local __wep_keyN __f_wireless_describe_first_char __length
+ for __wep_keyN in wep_key0 wep_key1 wep_key2 wep_key3; do
+ $__struct get $__wep_keyN __kk
+ [ "$__kk" ] || continue
+
+ # What type is it? ASCII or HEX?
+ __check=WEP
+ f_substr -v __f_wireless_describe_first_char "$__kk" 1 1
+ case "$__f_wireless_describe_first_char" in
+ \") # ASCII
+ __length=$(( ${#__kk} - 2 ))
+ if [ $__length -le 5 ]; then
+ __check=WEP40
+ elif [ $__length -le 13 ]; then
+ __check=WEP104
+ fi ;;
+ *) # HEX
+ __length=${#__kk}
+ if [ $__length -eq 10 ]; then
+ __check=WEP40
+ elif [ $__length -le 26 ]; then
+ __check=WEP104
+ fi
+ esac
+ __kk="" # sensitive info
+
+ case "$__desc" in
+ *"$__check"*) : already there ;;
+ *) __desc="$__desc${__desc:+ }$__check"
+ esac
+ done
+
+ #
+ # Make sure we display PSK even if omitted
+ # from the key_mgmt section of the entry
+ #
+ $__struct get psk __kk
+ if [ "$__kk" ]; then
+ __kk="" # sensitive info
+ __check=PSK
+ case "$__desc" in
+ *"$__check"*) : already there ;;
+ *) __desc="$__desc${__desc:+ }$__check"
+ esac
+ fi
+
+ #
+ # Produce results
+ #
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "${__desc:-NONE}"
+ else
+ echo "$__desc"
+ fi
+}
+
+# f_menu_wireless_configs
+#
+# Generates the tag/item/help triplets for wireless network menu (`--item-help'
+# required) from wpa_supplicant.conf(5) [WPA_NETWORK] structs.
+#
+f_menu_wireless_configs()
+{
+ [ "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" ] || return $SUCCESS
+
+ echo "' - $msg_configured_ssids -' ' - $msg_details -' ''"
+
+ local n=0 nunique=0 debug=
+ local ssid ussid matches nmatches nconfigs nfound help desc w
+ while [ $n -lt $NWIRELESS_CONFIGS ]; do
+ n=$(( $n + 1 ))
+
+ f_struct WIRELESS_$n get ssid ssid
+ [ ! "$DIALOG_MENU_WLAN_SHOW_ALL" -a ! "$ssid" ] && continue
+
+ local u=0 unique=1
+ while [ $u -lt $nunique ]; do
+ u=$(( $u + 1 ))
+ menuitem_$u get ssid ussid
+ [ "$ssid" != "$ussid" ] || unique= break
+ done
+ if [ "$unique" ]; then
+ nunique=$(( $nunique + 1 ))
+ u=$nunique
+
+ # Set SSID and initialize number of configs found (1)
+ f_struct_new WLAN_MENU_ITEM menuitem_$u
+ menuitem_$u set ssid "$ssid"
+ menuitem_$u set nconfigs 1
+
+ # Set number of wireless networks that match config
+ WIRELESS_$n get matches matches
+ f_count nmatches $matches
+ menuitem_$u set nfound $nmatches
+
+ # Set help to description of the wireless config
+ f_wireless_describe WIRELESS_$n desc
+ menuitem_$u set help "$desc"
+ else
+ # Increment number of configs found with this SSID
+ menuitem_$u get nconfigs nconfigs
+ nconfigs=$(( $nconfigs + 1 ))
+ menuitem_$u set nconfigs $nconfigs
+
+ # Add number of matched networks to existing count
+ WIRELESS_$n get matches matches
+ f_count nmatches $matches
+ menuitem_$u get nfound nfound
+ nfound=$(( $nfound + $nmatches ))
+ menuitem_$u set nfound $nfound
+
+ # Combine description with existing help
+ menuitem_$u get help help
+ f_wireless_describe WIRELESS_$n desc
+ for w in $desc; do
+ case "$help" in
+ "$w"|"$w "*|*" $w"|*" $w "*) : already there ;;
+ *) help="$help $w"
+ esac
+ done
+ menuitem_$u set help "${help# }"
+ fi
+ done
+
+ n=0
+ while [ $n -lt $nunique ]; do
+ n=$(( $n + 1 ))
+ menuitem_$n get ssid ssid
+
+ menuitem_$n get nconfigs nconfigs
+ desc="$nconfigs $msg_configured_lc"
+ [ $nconfigs -lt 10 ] && desc=" $desc"
+ menuitem_$n get nfound nfound
+ [ $nfound -gt 0 ] && desc="$desc $nfound $msg_found"
+
+ menuitem_$n get help help
+ echo "'[X] $ssid' '$desc' '$help'"
+ done | sort -bf | awk 'BEGIN { prefix = "" }
+ {
+ cur_prefix = toupper(substr($0, 6, 1))
+ if (cur_prefix != "'\''" && prefix != cur_prefix ) {
+ prefix = cur_prefix
+ printf "'\''%c%s\n", prefix, substr($0, 2)
+ } else
+ printf "'\'' %s\n", substr($0, 2)
+ }'
+}
+
+# f_menu_wpa_scan_results
+#
+# Generates the tag/item/help triplets for wireless network menu (`--item-help'
+# required) from wpa_cli(8) `scan_results' [WPA_SCAN_RESULT] structs.
+#
+f_menu_wpa_scan_results()
+{
+ [ "$DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS" ] || return $SUCCESS
+
+ if [ "$DIALOG_MENU_WLAN_SHOW_ALL" ]; then
+ echo "' - $msg_discovered_ssids -' ' - $msg_details -' ''"
+ else
+ echo "' - $msg_discovered_ssids -' '' ''"
+ fi
+
+ local n=0 nunique=0 debug=
+ local ssid ussid matched nfound help flags f
+ while [ $n -lt $NWSCAN_RESULTS ]; do
+ n=$(( $n + 1 ))
+
+ WSCANS_$n get ssid ssid
+ [ ! "$DIALOG_MENU_WLAN_SHOW_ALL" -a ! "$ssid" ] && continue
+
+ WSCANS_$n get matched matched
+ [ "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" -a "$matched" ] &&
+ continue
+
+ local u=0 unique=1
+ while [ $u -lt $nunique ]; do
+ u=$(( $u + 1 ))
+ menuitem_$u get ssid ussid
+ [ "$ssid" != "$ussid" ] || unique= break
+ done
+ if [ "$unique" ]; then
+ nunique=$(( $nunique + 1 ))
+ u=$nunique
+
+ # Set SSID and initialize number of networks found (1)
+ f_struct_new WLAN_MENU_ITEM menuitem_$u
+ menuitem_$u set ssid "$ssid"
+ menuitem_$u set nfound 1
+
+ # Set help to flags
+ WSCANS_$n get flags flags
+ f_replaceall "$flags" "[" " " flags
+ f_replaceall "$flags" "]" "" flags
+ flags="${flags# }"
+ case "$flags" in
+ "") flags="NONE" ;;
+ ESS) flags="NONE ESS" ;;
+ esac
+ menuitem_$u set help "$flags"
+ else
+ # Increment number of networks found with this SSID
+ menuitem_$u get nfound nfound
+ nfound=$(( $nfound + 1 ))
+ menuitem_$u set nfound $nfound
+
+ # Combine flags into existing help
+ WSCANS_$n get flags flags
+ f_replaceall "$flags" "[" " " flags
+ f_replaceall "$flags" "]" "" flags
+ local flags_ess=
+ case "$flags" in *" ESS")
+ flags_ess=1
+ flags="${flags% ESS}"
+ esac
+ local help_ess=
+ menuitem_$u get help help
+ case "$help" in *" ESS")
+ help_ess=1
+ help="${help% ESS}"
+ esac
+ for f in ${flags:-NONE}; do
+ case "$help" in
+ "$f"|"$f "*|*" $f"|*" $f "*) : already there ;;
+ *) help="$help $f"
+ esac
+ done
+ [ "$flags_ess" -a ! "$help_ess" ] && help="$help ESS"
+ menuitem_$u set help "${help# }"
+ fi
+ done
+
+ local desc n=0
+ while [ $n -lt $nunique ]; do
+ n=$(( $n + 1 ))
+ menuitem_$n get ssid ssid
+
+ desc=
+ if [ "$DIALOG_MENU_WLAN_SHOW_ALL" ]; then
+ menuitem_$n get nfound nfound
+ desc="$nfound $msg_found"
+ [ $nfound -lt 10 ] && desc=" $desc"
+ fi
+
+ menuitem_$n get help help
+ echo "'[ ] $ssid' '$desc' '$help'"
+ done | sort -bf | awk 'BEGIN { prefix = "" }
+ {
+ cur_prefix = toupper(substr($0, 6, 1))
+ if (cur_prefix != "'\''" && prefix != cur_prefix ) {
+ prefix = cur_prefix
+ printf "'\''%c%s\n", prefix, substr($0, 2)
+ } else
+ printf "'\'' %s\n", substr($0, 2)
+ }'
+}
+
+# f_dialog_menu_wireless_edit
+#
+# Display a list of wireless networks configured in wpa_supplicants.conf(5) and
+# (if wpa_supplicant(8) is running) also displays scan results for unconfigured
+# wireless networks.
+#
+f_dialog_menu_wireless_edit()
+{
+ local funcname=f_dialog_menu_wireless_edit
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt="$msg_wireless_networks_text"
+ local menu_list # Calculated below
+ local defaultitem= # Calculated below
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+
+ f_show_info "$msg_loading_wireless_menu"
+
+ local conf_file
+ conf_file=$( f_sysrc_get wpa_supplicant_conf_file )
+
+ #
+ # Operate in a loop so we can edit wpa_supplicant.conf(5) and rescan
+ # for new wireless networks from here.
+ #
+ local do_parse=1 remake_menu=1 item
+ while :; do
+ #
+ # If this is the first time here, parse wpa_supplicant.conf(5),
+ # scan the airwaves, and compare to find matches.
+ #
+ if [ "$do_parse" -a "$DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS" ]
+ then
+ f_dprintf "$funcname: Parsing wireless scan results"
+ f_dialog_scan_wireless &&
+ f_wpa_scan_results_parse WSCANS_ NWSCAN_RESULTS
+ f_dprintf "$funcname: Parsed %i scanned networks" \
+ $NWSCAN_RESULTS
+ fi
+ if [ "$do_parse" -a "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" ]
+ then
+ f_dprintf "$funcname: Parsing wpa_supplicants.conf(5)"
+ f_wpa_supplicant_parse "$conf_file" \
+ WIRELESS_ NWIRELESS_CONFIGS
+ f_dprintf "%s: Parsed %i wireless configurations" \
+ $funcname $NWIRELESS_CONFIGS
+ f_wpa_scan_find_matches WSCANS_ $NWSCAN_RESULTS \
+ WIRELESS_ $NWIRELESS_CONFIGS
+ fi
+ do_parse=
+
+ if [ "$remake_menu" ]; then
+ remake_menu=
+
+ #
+ # Add both items scanned from the airwaves and networks
+ # parsed from wpa_supplicants.conf(5). Latter items are
+ # marked, sorted, and added to top of list above the
+ # former (which are unmarked and sorted separately).
+ #
+ f_dprintf "$funcname: Building menu list..."
+ menu_list=$(
+ # Process wpa_supplicant.conf(5) structs
+ f_menu_wireless_configs
+ # Process wpa_cli(8) `scan_results' structs
+ f_menu_wpa_scan_results
+ )
+ f_dprintf "$funcname: menu list built."
+
+ #
+ # Add static top-level menu items
+ #
+ local XA=" " XC=" " XS=" "
+ [ "$DIALOG_MENU_WLAN_SHOW_ALL" ] && XA="X"
+ [ "$DIALOG_MENU_WLAN_SHOW_CONFIGURED" ] && XC="X"
+ [ "$DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS" ] && XS="X"
+ menu_list="
+ '> $msg_exit' '$msg_return_to_previous_menu'
+ ''
+ '> $msg_rescan_wireless' '*'
+ '$msg_rescan_wireless_help'
+ '> $msg_forget_all' '*'
+ '$msg_forget_all_help'
+ '> $msg_show_configured' '[$XC]'
+ '$msg_show_configured_help'
+ '> $msg_show_scan_results' '[$XS]'
+ '$msg_show_scan_results_help'
+ '> $msg_show_all' '[$XA]'
+ '$msg_show_all_help'
+ '> $msg_manually_connect' '...'
+ '$msg_manually_connect_help'
+ $menu_list" # END-QUOTE
+ fi
+
+ local height width rows
+ eval f_dialog_menu_with_help_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --item-help \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || break
+ f_dialog_data_sanitize menu_choice
+ defaultitem="$menu_choice"
+
+ case "$menu_choice" in
+ "> $msg_exit") break ;;
+ "> $msg_rescan_wireless") do_parse=1 remake_menu=1 ;;
+ "> $msg_forget_all")
+ if f_noyes "$msg_forget_all_confirm"; then
+ f_eval_catch $funcname rm \
+ 'rm -f "%s"' "$conf_file" || continue
+ f_wpa_supplicant_init "$conf_file" || continue
+ f_eval_catch -d $funcname wpa_cli \
+ 'wpa_cli reconfigure'
+ f_wpa_supplicant_parse "$conf_file" \
+ WIRELESS_ NWIRELESS_CONFIGS
+ f_wpa_scan_find_matches \
+ WSCANS_ $NWSCAN_RESULTS \
+ WIRELESS_ $NWIRELESS_CONFIGS
+ do_parse=1 remake_menu=1
+ fi ;;
+ "> $msg_show_configured")
+ item=$( eval f_dialog_menutag2item_with_help \
+ \"\$menu_choice\" $menu_list )
+ if [ "$item" = "[ ]" ]; then
+ DIALOG_MENU_WLAN_SHOW_CONFIGURED=1
+ else
+ DIALOG_MENU_WLAN_SHOW_CONFIGURED=
+ fi
+ remake_menu=1 ;;
+ "> $msg_show_scan_results")
+ item=$( eval f_dialog_menutag2item_with_help \
+ \"\$menu_choice\" $menu_list )
+ if [ "$item" = "[ ]" ]; then
+ DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS=1
+ else
+ DIALOG_MENU_WLAN_SHOW_SCAN_RESULTS=
+ fi
+ remake_menu=1 ;;
+ "> $msg_show_all")
+ item=$( eval f_dialog_menutag2item_with_help \
+ \"\$menu_choice\" $menu_list )
+ if [ "$item" = "[ ]" ]; then
+ DIALOG_MENU_WLAN_SHOW_ALL=1
+ else
+ DIALOG_MENU_WLAN_SHOW_ALL=
+ fi
+ remake_menu=1 ;;
+ "> $msg_manually_connect")
+ f_dialog_wireless_edit && remake_menu=1 ;;
+ ?"[X] "*)
+ ssid="${menu_choice#??X? }"
+ f_dialog_wireless_edit "$ssid" || continue
+ do_parse=1 remake_menu=1 ;;
+ "[ ] "*)
+ :
+ : XXXDT Unfinished
+ :
+ ;;
+ esac
+ done
+
+ #
+ # XXXDT Unfinished
+ #
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/wlan.subr
+
+fi # ! $_MEDIA_WLAN_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/mustberoot.subr b/contrib/bsddialog/bsdconfig/share/mustberoot.subr
new file mode 100644
index 000000000000..88ff81868d45
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/mustberoot.subr
@@ -0,0 +1,424 @@
+if [ ! "$_MUSTBEROOT_SUBR" ]; then _MUSTBEROOT_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." mustberoot.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+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 funcname=f_become_root_via_sudo
+ local prompt hline height width rows msg
+
+ [ "$( id -u )" = "0" ] && return $SUCCESS
+
+ f_have sudo || f_die 1 "$msg_must_be_root_to_execute" "$pgm"
+
+ #
+ # Ask the user if it's OK to become root via sudo(8) and give them
+ # the option to save this preference (by touch(1)ing a file in the
+ # user's $HOME directory).
+ #
+ local checkpath="${HOME%/}/.bsdconfig_uses_sudo"
+ if [ ! -e "$checkpath" ]; then
+ f_sprintf prompt "$msg_you_are_not_root_but" bsdconfig
+ f_sprintf msg "$msg_always_try_sudo_when_run_as" "$USER"
+ local menu_list="
+ 'X' '$msg_cancel_exit'
+ '1' '$msg'
+ '2' '$msg_try_sudo_only_this_once'
+ " # END-QUOTE
+ hline="$hline_arrows_tab_enter"
+
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local mtag
+ mtag=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || f_die
+ f_dialog_data_sanitize mtag
+
+ case "$mtag" in
+ X) # Cancel/Exit
+ f_die ;;
+ 1) # Always try sudo(8) when run as $user
+ f_eval_catch $funcname touch \
+ 'touch "%s"' "$checkpath" &&
+ f_show_msg "$msg_created_path" "$checkpath"
+ esac
+ else
+ #
+ # This user has created the path signing-off on sudo(8)-use
+ # but let's still give them a short/quick/unobtrusive reminder
+ #
+ f_dialog_info "$msg_becoming_root_via_sudo"
+ [ "$USE_XDIALOG" ] || sleep 0.6
+ fi
+
+ #
+ # 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.
+ #
+ prompt="$msg_please_enter_password"
+ hline="$hline_alnum_punc_tab_enter"
+ f_dialog_inputbox_size height width \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$prompt" \
+ "$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 "$prompt" \
+ $height $width \
+ 2>&1 > /dev/null
+ )
+ retval=$?
+
+ # Catch X11-related errors
+ if [ $retval -eq $DIALOG_ESC ]; then
+ f_die $retval "$password"
+ elif [ $retval -ne $DIALOG_OK ]; then
+ # User cancelled
+ exit $retval
+ fi
+ else
+ password=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$prompt" \
+ $height $width \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || exit $?
+ fi
+ debug= f_dialog_line_sanitize password
+
+ #
+ # 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
+ f_sprintf msg "$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)
+ f_dprintf "%s: Becoming root via sudo(8)..." mustberoot.subr
+ 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 height width
+
+ 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"
+ f_xdialog_2inputsbox_size height width \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$msg" \
+ "$field_username" "" \
+ "$field_password" ""
+ 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 $DIALOG_ESC ] && f_die $retval "$user_pass"
+
+ # Exit if the user cancelled.
+ [ $retval -eq $DIALOG_OK ] || 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_show_msg "$msg_no_username"
+ continue
+ fi
+ if [ ! "$SECURE_ALLOW_ROOT" ]; then
+ case "$user" in
+ root|toor)
+ nfailures=$(( $nfailures + 1 ))
+ f_show_msg "$msg_user_disallowed" "$user"
+ continue
+ esac
+ fi
+ if ! f_quietly id "$user"; then
+ nfailures=$(( $nfailures + 1 ))
+ if [ "$SECURE_DIVULGE_UNKNOWN_USER" ]; then
+ f_show_msg "$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
+ f_sprintf msg "$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
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." mustberoot.subr
+
+fi # ! $_MUSTBEROOT_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/packages/Makefile b/contrib/bsddialog/bsdconfig/share/packages/Makefile
new file mode 100644
index 000000000000..bc0e59ad63cd
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/packages/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/packages
+FILES= categories.subr index.subr musthavepkg.subr packages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/share/packages/Makefile.depend b/contrib/bsddialog/bsdconfig/share/packages/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/packages/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/share/packages/categories.subr b/contrib/bsddialog/bsdconfig/share/packages/categories.subr
new file mode 100644
index 000000000000..474c41d948ed
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/packages/categories.subr
@@ -0,0 +1,209 @@
+if [ ! "$_PACKAGES_CATEGORIES_SUBR" ]; then _PACKAGES_CATEGORIES_SUBR=1
+#
+# Copyright (c) 2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." packages/categories.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+CATEGORIES=
+NCATEGORIES=0
+
+############################################################ FUNCTIONS
+
+# f_category_desc_get $category [$var_to_set]
+#
+# Fetch the description of a given category. Returns success if a match was
+# found, otherwise failure.
+#
+# If $var_to_set is missing or NULL, the category description is printed to
+# standard out for capturing in a sub-shell (which is less-recommended because
+# of performance degredation; for example, when called in a loop).
+#
+f_category_desc_get()
+{
+ local __category="$1" __var_to_set="$2" __cat __varcat
+
+ # Return failure if $category
+ [ "$__category" ] || return $FAILURE
+
+ for __cat in $CATEGORIES; do
+ [ "$__cat" = "$__category" ] || continue
+ f_str2varname $__cat __varcat
+ f_getvar _category_$__varcat $__var_to_set
+ return $?
+ done
+ return $FAILURE
+}
+
+# f_category_desc_set $category $desc
+#
+# Store a description in-association with a category. $category should be
+# alphanumeric and can include the underscore [_] but should not contain
+# whitespace. Returns success unless $category is NULL or no arguments. Use the
+# f_category_desc_get() routine with the same $category to retrieve the stored
+# description.
+#
+f_category_desc_set()
+{
+ local category="$1" desc="$2"
+ local cat varcat found=
+ [ "$category" ] || return $FAILURE
+ for cat in $CATEGORIES; do
+ [ "$cat" = "$category" ] || continue
+ f_str2varname $cat varcat
+ f_isset _category_$varcat || continue
+ found=1 && break
+ done
+ if [ ! "$found" ]; then
+ CATEGORIES="$CATEGORIES $category"
+ fi
+ f_str2varname $category varcat
+ setvar "_category_$varcat" "$desc"
+ # Export the variable for awk(1) ENVIRON visibility
+ export "_category_$varcat"
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+#
+# Load descriptions for package categories. Note that we don't internationalize
+# category names because this would be confusing for people used to browsing
+# the FTP mirrors or are otherwise familiar with an interface that does not
+# provide internationalized names. The descriptions can be used to provide i18n
+# users a description of the non-i18n category name.
+#
+f_category() { f_category_desc_set "$1" "$2"; }
+f_category All "$msg_all_desc"
+f_category accessibility "$msg_accessibility_desc"
+f_category afterstep "$msg_afterstep_desc"
+f_category arabic "$msg_arabic_desc"
+f_category archivers "$msg_archivers_desc"
+f_category astro "$msg_astro_desc"
+f_category audio "$msg_audio_desc"
+f_category benchmarks "$msg_benchmarks_desc"
+f_category biology "$msg_biology_desc"
+f_category cad "$msg_cad_desc"
+f_category chinese "$msg_chinese_desc"
+f_category comms "$msg_comms_desc"
+f_category converters "$msg_converters_desc"
+f_category databases "$msg_databases_desc"
+f_category deskutils "$msg_deskutils_desc"
+f_category devel "$msg_devel_desc"
+f_category dns "$msg_dns_desc"
+f_category docs "$msg_docs_desc"
+f_category editors "$msg_editors_desc"
+f_category elisp "$msg_elisp_desc"
+f_category emulators "$msg_emulators_desc"
+f_category enlightenment "$msg_enlightenment_desc"
+f_category finance "$msg_finance_desc"
+f_category french "$msg_french_desc"
+f_category ftp "$msg_ftp_desc"
+f_category games "$msg_games_desc"
+f_category geography "$msg_geography_desc"
+f_category german "$msg_german_desc"
+f_category gnome "$msg_gnome_desc"
+f_category gnustep "$msg_gnustep_desc"
+f_category graphics "$msg_graphics_desc"
+f_category hamradio "$msg_hamradio_desc"
+f_category haskell "$msg_haskell_desc"
+f_category hebrew "$msg_hebrew_desc"
+f_category hungarian "$msg_hungarian_desc"
+f_category ipv6 "$msg_ipv6_desc"
+f_category irc "$msg_irc_desc"
+f_category japanese "$msg_japanese_desc"
+f_category java "$msg_java_desc"
+f_category kde "$msg_kde_desc"
+f_category kld "$msg_kld_desc"
+f_category korean "$msg_korean_desc"
+f_category lang "$msg_lang_desc"
+f_category linux "$msg_linux_desc"
+f_category lisp "$msg_lisp_desc"
+f_category mail "$msg_mail_desc"
+f_category math "$msg_math_desc"
+f_category mbone "$msg_mbone_desc"
+f_category misc "$msg_misc_desc"
+f_category multimedia "$msg_multimedia_desc"
+f_category net "$msg_net_desc"
+f_category net-im "$msg_net_im_desc"
+f_category net-mgmt "$msg_net_mgmt_desc"
+f_category net-p2p "$msg_net_p2p_desc"
+f_category news "$msg_news_desc"
+f_category palm "$msg_palm_desc"
+f_category parallel "$msg_parallel_desc"
+f_category pear "$msg_pear_desc"
+f_category perl5 "$msg_perl5_desc"
+f_category plan9 "$msg_plan9_desc"
+f_category polish "$msg_polish_desc"
+f_category ports-mgmt "$msg_ports_mgmt_desc"
+f_category portuguese "$msg_portuguese_desc"
+f_category print "$msg_print_desc"
+f_category python "$msg_python_desc"
+f_category ruby "$msg_ruby_desc"
+f_category rubygems "$msg_rubygems_desc"
+f_category russian "$msg_russian_desc"
+f_category scheme "$msg_scheme_desc"
+f_category science "$msg_science_desc"
+f_category security "$msg_security_desc"
+f_category shells "$msg_shells_desc"
+f_category spanish "$msg_spanish_desc"
+f_category sysutils "$msg_sysutils_desc"
+f_category tcl "$msg_tcl_desc"
+f_category textproc "$msg_textproc_desc"
+f_category tk "$msg_tk_desc"
+f_category ukrainian "$msg_ukrainian_desc"
+f_category vietnamese "$msg_vietnamese_desc"
+f_category windowmaker "$msg_windowmaker_desc"
+f_category www "$msg_www_desc"
+f_category x11 "$msg_x11_desc"
+f_category x11-clocks "$msg_x11_clocks_desc"
+f_category x11-drivers "$msg_x11_drivers_desc"
+f_category x11-fm "$msg_x11_fm_desc"
+f_category x11-fonts "$msg_x11_fonts_desc"
+f_category x11-servers "$msg_x11_servers_desc"
+f_category x11-themes "$msg_x11_themes_desc"
+f_category x11-toolkits "$msg_x11_toolkits_desc"
+f_category x11-wm "$msg_x11_wm_desc"
+f_category xfce "$msg_xfce_desc"
+f_category zope "$msg_zope_desc"
+
+f_count NCATEGORIES $CATEGORIES
+f_dprintf "%s: Initialized %u package category descriptions." \
+ packages/categories.subr $NCATEGORIES
+
+f_dprintf "%s: Successfully loaded." packages/categories.subr
+
+fi # ! $_PACKAGES_CATEGORIES_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/packages/index.subr b/contrib/bsddialog/bsdconfig/share/packages/index.subr
new file mode 100644
index 000000000000..95260da0de05
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/packages/index.subr
@@ -0,0 +1,416 @@
+if [ ! "$_PACKAGES_INDEX_SUBR" ]; then _PACKAGES_INDEX_SUBR=1
+#
+# Copyright (c) 2013-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." packages/index.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/packages/musthavepkg.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+PACKAGE_INDEX=
+_INDEX_INITTED=
+
+#
+# Default path to pkg(8) repo-packagesite.sqlite database
+#
+SQLITE_REPO="/var/db/pkg/repo-FreeBSD.sqlite"
+
+#
+# Default path to on-disk cache INDEX file
+#
+PACKAGES_INDEX_CACHEFILE="/var/run/bsdconfig/packages_INDEX.cache"
+
+############################################################ FUNCTIONS
+
+# f_index_initialize [$var_to_set]
+#
+# Read and initialize the global index. Returns success unless media cannot be
+# initialized for any reason (e.g. user cancels media selection dialog or an
+# error occurs). The index is sorted before being loaded into $var_to_set.
+#
+# NOTE: The index is processed with f_index_read() [below] after being loaded.
+#
+f_index_initialize()
+{
+ local __funcname=f_index_initialize
+ local __var_to_set="${1:-PACKAGE_INDEX}"
+
+ [ "$_INDEX_INITTED" ] && return $SUCCESS
+
+ # Got any media?
+ f_media_verify || return $FAILURE
+
+ # Make sure we have a usable pkg(8) with $PKG_ABI
+ f_musthavepkg_init
+
+ # Does it move when you kick it?
+ f_device_init device_media || return $FAILURE
+
+ f_show_info "$msg_attempting_to_update_repository_catalogue"
+
+ #
+ # Generate $PACKAGESITE variable for pkg(8) based on media type
+ #
+ local __type __data __site
+ device_media get type __type
+ device_media get private __data
+ case "$__type" in
+ $DEVICE_TYPE_DIRECTORY)
+ __site="file://$__data/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_FLOPPY)
+ __site="file://${__data:-$MOUNTPOINT}/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_FTP)
+ f_getvar $VAR_FTP_PATH __site
+ __site="$__site/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_HTTP)
+ f_getvar $VAR_HTTP_PATH __site
+ __site="$__site/$PKG_ABI/latest" ;;
+ $DEVICE_TYPE_HTTP_PROXY)
+ f_getvar $VAR_HTTP_PROXY_PATH __site
+ __site="$__site/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_CDROM)
+ __site="file://$MOUNTPOINT/packages/$PKG_ABI"
+ export REPOS_DIR="$MOUNTPOINT/packages/repos" ;;
+ *) # UFS, DISK, CDROM, USB, DOS, NFS, etc.
+ __site="file://$MOUNTPOINT/packages/$PKG_ABI"
+ esac
+
+ f_dprintf "PACKAGESITE=[%s]" "$__site"
+ if ! f_eval_catch $__funcname pkg \
+ 'PACKAGESITE="%s" pkg update' "$__site"
+ then
+ f_show_err "$msg_unable_to_update_pkg_from_selected_media"
+ f_device_shutdown device_media
+ return $FAILURE
+ fi
+
+ #
+ # Try to get contents from validated on-disk cache
+ #
+
+ #
+ # Calculate digest used to determine if the on-disk persistent cache
+ # INDEX (containing this digest on the first line) is valid and can be
+ # used to quickly populate the environment.
+ #
+ local __sqlite_digest
+ if ! __sqlite_digest=$( md5 < "$SQLITE_REPO" 2> /dev/null ); then
+ f_show_err "$msg_no_pkg_database_found"
+ f_device_shutdown device_media
+ return $FAILURE
+ fi
+
+ #
+ # Check to see if the persistent cache INDEX file exists
+ #
+ if [ -f "$PACKAGES_INDEX_CACHEFILE" ]; then
+ #
+ # Attempt to populate the environment with the (soon to be)
+ # validated on-disk cache. If validation fails, fall-back to
+ # generating a fresh cache.
+ #
+ if eval $__var_to_set='$(
+ ( # Get digest as the first word on first line
+ read digest rest_ignored
+
+ #
+ # If the stored digest matches the calculated-
+ # one populate the environment from the on-disk
+ # cache and provide success exit status.
+ #
+ if [ "$digest" = "$__sqlite_digest" ]; then
+ cat
+ exit $SUCCESS
+ else
+ # Otherwise, return the current value
+ eval echo \"\$__var_to_set\"
+ exit $FAILURE
+ fi
+ ) < "$PACKAGES_INDEX_CACHEFILE" 2> /dev/null
+ )'; then
+ if ! f_index_read "$__var_to_set"; then
+ f_show_err \
+ "$msg_io_or_format_error_on_index_file"
+ return $FAILURE
+ fi
+ _INDEX_INITTED=1
+ return $SUCCESS
+ fi
+ # Otherwise, fall-thru to create a fresh cache from scratch
+ fi
+
+ #
+ # If we reach this point, we need to generate the data from scratch
+ #
+
+ eval "$__var_to_set"='$( pkg rquery -I | (
+ exec 2<&1; dpv -ko /dev/stderr >&$TERMINAL_STDOUT_PASSTHRU \
+ -b "$DIALOG_BACKTITLE" \
+ -- "$msg_generating_index_from_pkg_database"
+ ) | sort )'
+
+ #
+ # Attempt to create the persistent on-disk cache
+ #
+
+ # Create a new temporary file to write to
+ local __tmpfile
+ if f_eval_catch -dk __tmpfile $__funcname mktemp \
+ 'mktemp -t "%s"' "$pgm"
+ then
+ # Write the temporary file contents
+ echo "$__sqlite_digest" > "$__tmpfile"
+ debug= f_getvar "$__var_to_set" >> "$__tmpfile"
+
+ # Finally, move the temporary file into place
+ case "$PACKAGES_INDEX_CACHEFILE" in
+ */*) f_eval_catch -d $__funcname mkdir \
+ 'mkdir -p "%s"' "${PACKAGES_INDEX_CACHEFILE%/*}"
+ esac
+ f_eval_catch -d $__funcname mv 'mv -f "%s" "%s"' \
+ "$__tmpfile" "$PACKAGES_INDEX_CACHEFILE"
+ fi
+
+ if ! f_index_read "$__var_to_set"; then
+ f_show_err "$msg_io_or_format_error_on_index_file"
+ return $FAILURE
+ fi
+
+ _INDEX_INITTED=1
+ return $SUCCESS
+}
+
+# f_index_read [$var_to_get]
+#
+# Process the INDEX file (contents contained in $var_to_get) and...
+#
+# 1. create a list ($CATEGORY_MENU_LIST) of categories with package counts
+# 2. For convenience, create $_npkgs holding the total number of all packages
+# 3. extract associative categories for each package into $_categories_$varpkg
+# 4. extract runtime dependencies for each package into $_rundeps_$varpkg
+# 5. extract a [sorted] list of categories into $PACKAGE_CATEGORIES
+# 6. create $_npkgs_$varcat holding the total number of packages in category
+#
+# NOTE: $varpkg is the product of f_str2varname $package varpkg
+# NOTE: $package is the name as it appears in the INDEX (no archive suffix)
+# NOTE: We only show categories for which there are at least one package.
+# NOTE: $varcat is the product of f_str2varname $category varcat
+#
+f_index_read()
+{
+ local var_to_get="${1:-PACKAGE_INDEX}"
+
+ # Export variables required by awk(1) below
+ export msg_no_description_provided
+ export msg_all msg_all_desc
+ export VALID_VARNAME_CHARS
+ export msg_packages
+
+ eval "$( debug= f_getvar "$var_to_get" | awk -F'|' '
+ function _asorti(src, dest)
+ {
+ k = nitems = 0
+
+ # Copy src indices to dest and calculate array length
+ for (i in src) dest[++nitems] = i
+
+ # Sort the array of indices (dest) using insertion sort method
+ for (i = 1; i <= nitems; k = i++)
+ {
+ idx = dest[i]
+ while ((k > 0) && (dest[k] > idx))
+ {
+ dest[k+1] = dest[k]
+ k--
+ }
+ dest[k+1] = idx
+ }
+
+ return nitems
+ }
+ function print_category(category, npkgs, desc)
+ {
+ cat = category
+ # Accent the category if the first page has been
+ # cached (also acting as a visitation indicator)
+ if ( ENVIRON["_index_page_" varcat "_1"] )
+ cat = cat "*"
+ printf "'\''%s'\'' '\''%s " packages "'\'' '\''%s'\''\n",
+ cat, npkgs, desc
+ }
+ BEGIN {
+ valid_chars = ENVIRON["VALID_VARNAME_CHARS"]
+ default_desc = ENVIRON["msg_no_description_provided"]
+ packages = ENVIRON["msg_packages"]
+ tpkgs = 0
+ prefix = ""
+ }
+ {
+ tpkgs++
+ varpkg = $1
+ gsub("[^" valid_chars "]", "_", varpkg)
+ print "_categories_" varpkg "=\"" $7 "\""
+ split($7, pkg_categories, /[[:space:]]+/)
+ for (pkg_category in pkg_categories)
+ categories[pkg_categories[pkg_category]]++
+ print "_rundeps_" varpkg "=\"" $9 "\""
+ }
+ END {
+ print "_npkgs=" tpkgs # For convenience, total package count
+
+ n = _asorti(categories, categories_sorted)
+
+ # Produce package counts for each category
+ for (i = 1; i <= n; i++)
+ {
+ cat = varcat = categories_sorted[i]
+ npkgs = categories[cat]
+ gsub("[^" valid_chars "]", "_", varcat)
+ print "_npkgs_" varcat "=\"" npkgs "\""
+ }
+
+ # Create menu list and generate list of categories at same time
+ print "CATEGORY_MENU_LIST=\""
+ print_category(ENVIRON["msg_all"], tpkgs,
+ ENVIRON["msg_all_desc"])
+ category_list = ""
+ for (i = 1; i <= n; i++)
+ {
+ cat = varcat = categories_sorted[i]
+ npkgs = categories[cat]
+ cur_prefix = tolower(substr(cat, 1, 1))
+ if ( prefix != cur_prefix )
+ prefix = cur_prefix
+ else
+ cat = " " cat
+ gsub("[^" valid_chars "]", "_", varcat)
+ desc = ENVIRON["_category_" varcat]
+ if ( ! desc ) desc = default_desc
+ print_category(cat, npkgs, desc)
+ category_list = category_list " " cat
+ }
+ print "\""
+
+ # Produce the list of categories (calculated in above block)
+ sub(/^ /, "", category_list)
+ print "PACKAGE_CATEGORIES=\"" category_list "\""
+
+ }' | ( exec 2<&1; dpv -ko /dev/stderr >&$TERMINAL_STDOUT_PASSTHRU \
+ -b "$DIALOG_BACKTITLE" -- "$msg_reading_package_index_data"
+ ) )" # End-Quote
+}
+
+# f_index_extract_pages $var_to_get $var_basename $pagesize [$category]
+#
+# Extracts the package INDEX ($PACKAGE_INDEX by default if/when $var_to_get is
+# NULL; but should not be missing) into a series of sequential variables
+# corresponding to "pages" containing up to $pagesize packages. The package
+# INDEX data must be contained in the variable $var_to_get. The extracted pages
+# are stored in variables ${var_basename}_# -- where "#" is a the page number.
+# If $category is set, only packages for that category are extracted.
+# Otherwise, if $category is "All", missing, or NULL, all packages are
+# extracted and no filtering is done.
+#
+f_index_extract_pages()
+{
+ local var_to_get="${1:-PACKAGE_INDEX}" var_basename="$2" pagesize="$3"
+ local category="$4" # Optional
+
+ eval "$(
+ debug= f_getvar "$var_to_get" | awk -F'|' \
+ -v cat="$category" \
+ -v pagesize="$pagesize" \
+ -v var_basename="$var_basename" \
+ -v i18n_all="$msg_all" '
+ BEGIN { n = page = 0 }
+ /'\''/{ gsub(/'\''/, "'\''\\'\'\''") }
+ {
+ if ( cat !~ "(^$|^" i18n_all "$)" && $7 !~ \
+ "(^|[[:space:]])" cat "([[:space:]]|$)" ) next
+ starting_new_page = (n++ == (pagesize * page))
+ if ( starting_new_page )
+ printf "%s%s", ( n > 1 ? "'\''\n" : "" ),
+ var_basename "_" ++page "='\''"
+ printf "%s%s", ( starting_new_page ? "" : "\n" ), $0
+ }
+ END { if ( n > 0 ) print "'\''" }'
+ )"
+}
+
+# f_index_search $var_to_get $name [$var_to_set]
+#
+# Search the package INDEX ($PACKAGE_INDEX by default if/when $var_to_get is
+# NULL; but should not be missing) for $name, returning the first match.
+# Matches are strict (not regular expressions) and must match the beginning
+# portion of the package name to be considered a match. If $var_to_set is
+# missing or NULL, output is sent to standard output. If a match is found,
+# returns success; otherwise failure.
+#
+f_index_search()
+{
+ local __var_to_get="${1:-PACKAGE_INDEX}" __pkg_basename="$2"
+ local __var_to_set="$3"
+
+ f_dprintf "f_index_search: Searching package data (in %s) for %s" \
+ "$__var_to_get" "$__pkg_basename"
+
+ local __pkg=
+ __pkg=$( debug= f_getvar "$__var_to_get" |
+ awk -F'|' -v basename="$__pkg_basename" '
+ BEGIN { n = length(basename) }
+ substr($1, 0, n) == basename { print $1; exit }
+ ' )
+ if [ ! "$__pkg" ]; then
+ f_dprintf "f_index_search: No packages matching %s found" \
+ "$__pkg_basename"
+ return $FAILURE
+ fi
+
+ f_dprintf "f_index_search: Found package %s" "$__pkg"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__pkg"
+ else
+ echo "$__pkg"
+ fi
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." packages/index.subr
+
+fi # ! $_PACKAGES_INDEX_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/packages/musthavepkg.subr b/contrib/bsddialog/bsdconfig/share/packages/musthavepkg.subr
new file mode 100644
index 000000000000..b336d26d9c2e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/packages/musthavepkg.subr
@@ -0,0 +1,91 @@
+if [ ! "$_PACKAGES_MUSTHAVEPKG_SUBR" ]; then _PACKAGES_MUSTHAVEPKG_SUBR=1
+#
+# Copyright (c) 2014-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." packages/musthavepkg.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+############################################################ FUNCTIONS
+
+# f_musthavepkg_init
+#
+# Validate pkg(8) is installed and set $PKG_ABI global if not already set.
+# Returns success unless pkg(8) is not installed and user refuses to install
+# it (upon prompt when running interactively).
+#
+f_musthavepkg_init()
+{
+ local funcname=f_musthavepkg_init
+ local pkg_abi_awk=' # BEGIN-AWK
+ $1 ~ /^ABI/ && $0 = $NF, sub(/^"/, "") && sub(/".*/, "") {
+ print; found = 1; exit
+ } END { exit ! found }
+ ' # END-AWK
+
+ if [ "$PKG_ABI" ]; then # Already set
+ f_dprintf "PKG_ABI=[%s]" "$PKG_ABI"
+ export PKG_ABI
+ f_quietly pkg -N -vv # return status (pkg(8) functional?)
+ return $?
+ fi
+
+ # Attempt to get PKG_ABI without prematurely bootstrapping pkg(8)
+ if f_eval_catch -k PKG_ABI $funcname pkg \
+ "pkg -N -vv | awk '%s'" "$pkg_abi_awk"
+ then
+ f_dprintf "PKG_ABI=[%s]" "$PKG_ABI"
+ export PKG_ABI
+ return $SUCCESS
+ fi
+
+ # pkg(8) not yet bootstrapped; ask for permission unless nonInteractive
+ f_dialog_yesno "$msg_pkg_not_yet_installed_install_now" ||
+ f_die 1 "$msg_must_have_pkg_to_execute" "$pgm"
+
+ f_mustberoot_init # Have to be root to install pkg(8)
+
+ # Bootstrap pkg(8)
+ f_dialog_info "$msg_bootstrapping_pkg"
+ f_eval_catch -k PKG_ABI $funcname pkg \
+ "ASSUME_ALWAYS_YES=1 pkg -vv | awk '%s'" "$pkg_abi_awk" ||
+ f_die 1 "$msg_must_have_pkg_to_execute" "$pgm"
+
+ f_dprintf "PKG_ABI=[%s]" "$PKG_ABI"
+ export PKG_ABI
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." packages/musthavepkg.subr
+
+fi # ! $_PACKAGES_MUSTHAVEPKG_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/packages/packages.subr b/contrib/bsddialog/bsdconfig/share/packages/packages.subr
new file mode 100644
index 000000000000..a22edd8bbb27
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/packages/packages.subr
@@ -0,0 +1,1194 @@
+if [ ! "$_PACKAGES_PACKAGES_SUBR" ]; then _PACKAGES_PACKAGES_SUBR=1
+#
+# Copyright (c) 2013-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/packages/categories.subr
+f_include $BSDCFG_SHARE/packages/index.subr
+f_include $BSDCFG_SHARE/packages/musthavepkg.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ CONFIGURATION
+
+#
+# How many packages to display (maximum) per dialog menubox.
+#
+: ${PACKAGE_MENU_PAGESIZE:=2000}
+
+############################################################ GLOBALS
+
+#
+# Package extensions to try
+#
+PACKAGE_EXTENSIONS=".txz .tbz .tbz2 .tgz"
+
+#
+# Variables used to track runtime states
+#
+PACKAGES_DETECTED= # Boolean (NULL/non-NULL); detected installed packages?
+PACKAGE_CATEGORIES= # List of package categories parsed from INDEX
+SELECTED_PACKAGES= # Packages selected by user in [X]dialog(1) interface
+
+#
+# Options
+#
+[ "${SHOW_DESC+set}" ] || SHOW_DESC=1
+
+############################################################ FUNCTIONS
+
+# eval f_package_accent_category_menu $var_to_set $CATEGORY_MENU_LIST
+#
+# Accent the CATEGORY_MENU_LIST produced by f_index_read() (see
+# packages/index.subr). Accented information includes adding an asterisk to the
+# category name if its index has been cached, adding the number of installed
+# packages for each category, and adding the number _selected_ packages for
+# each category.
+#
+# NOTE: The reason `eval' is recommended/shown for the syntax above is because
+# the $CATEGORY_MENU_LIST generated by f_index_read() is meant to be expanded
+# prior to execution (it contains a series of pre-quoted strings which act as
+# the interpolated command arguments).
+#
+f_package_accent_category_menu()
+{
+ local var_to_set="$1" category cat desc help varcat menu_buf n
+ shift 1 # var_to_set
+ while [ $# -gt 0 ]; do
+ category="${1%\*}" desc="${2%%; *}" help="$3"
+ shift 3 # cat/desc/help
+
+ cat="${category# }" # Trim lead space inserted by sort-method
+ f_str2varname "$cat" varcat
+
+ # Add number of installed packages for this category (if any)
+ n=0
+ case "$cat" in
+ "$msg_all") debug= f_getvar "_All_ninstalled" n ;;
+ *) debug= f_getvar "_${varcat}_ninstalled" n ;;
+ esac &&
+ [ $n -ge 1 ] && desc="$desc; $n $msg_installed_lc"
+
+ # Add number of selected packages for this category (if any)
+ n=0
+ case "$cat" in
+ "$msg_all") debug= f_getvar "_All_nselected" n ;;
+ *) debug= f_getvar "_${varcat}_nselected" n ;;
+ esac &&
+ [ $n -ge 1 ] && desc="$desc; $n $msg_selected"
+
+ # Re-Add asterisk to the category if its index has been cached
+ f_isset _index_page_${varcat}_1 && category="$category*"
+
+ # Update buffer with modified elements
+ menu_buf="$menu_buf
+ '$category' '$desc' '$help'" # End-Quote
+ done
+ setvar "$var_to_set" "$menu_buf" # return our buffer
+}
+
+# f_package_select $package ...
+#
+# Add $package to the list of tracked/selected packages. If $package is already
+# being tracked (already apears in $SELECTED_PACKAGES), this function amounts
+# to having no effect.
+#
+f_package_select()
+{
+ local package pkgsel
+ while [ $# -gt 0 ]; do
+ package="$1"
+ shift 1 # package
+ for pkgsel in $SELECTED_PACKAGES; do
+ [ "$package" = "$pkgsel" ] && return $SUCCESS
+ done
+ SELECTED_PACKAGES="$SELECTED_PACKAGES $package"
+ f_dprintf "Added %s to selection list" "$package"
+ done
+ SELECTED_PACKAGES="${SELECTED_PACKAGES# }" # Trim leading space
+}
+
+# f_package_deselect $package ...
+#
+# Remove $package from the list of tracked/selected packages. If $package is
+# not being tracked (doesn't appear in $SELECTED_PACKAGES), this function
+# amounts to having no effet.
+#
+f_package_deselect()
+{
+ local package pkgsel
+ while [ $# -gt 1 ]; do
+ local new_list=""
+ package="$1"
+ shift 1 # package
+ for pkgsel in $SELECTED_PACKAGES; do
+ [ "$pkgsel" = "$package" ] && continue
+ new_list="$new_list${new_list:+ }$pkgsel"
+ done
+ SELECTED_PACKAGES="$new_list"
+ f_dprintf "Removed %s from selection list" "$package"
+ done
+}
+
+# f_package_detect_installed
+#
+# Detect installed packages. Currently this uses pkg-query(8) for querying
+# entries and marks each entry as an installed/selected package.
+#
+f_package_detect_installed()
+{
+ local package varpkg
+ for package in $( pkg query "%n-%v" ); do
+ f_str2varname $package varpkg
+ export _mark_$varpkg=X # exported for awk(1) ENVIRON[]
+ f_package_select $package
+ done
+}
+
+# f_package_calculate_totals
+#
+# Calculate number of installed/selected packages for each category listed in
+# $PACKAGE_CATEGORIES (the number of installed packages for $category is stored
+# as $_${varcat}_ninstalled -- where $varcat is the product of `f_str2varname
+# $category varcat' -- and number selected packages as $_${varcat}_nselected).
+# Also calculates the total number of installed/selected packages stored as
+# $_All_ninstalled and $_All_nselected.
+#
+# Calculations are performed by checking "marks". A "mark" is stored as
+# $_mark_$varpkg -- where $varpkg is the product of `f_str2varname $package
+# varpkg'. A mark can be "X" for an installed package, `I' for a package that
+# is marked for installation, "R" for a package that is marked for re-install,
+# and "U" for a package that is marked for uninstallation. If a package mark is
+# NULL or a single space (e.g., " "), the package is considered to be NOT
+# selected (and therefore does not increment the counts calculated herein).
+#
+f_package_calculate_totals()
+{
+ local pkg varpkg mark cat varcat pkgcat n tselected=0 tinstalled=0
+ for cat in $PACKAGE_CATEGORIES; do
+ f_str2varname $cat varcat
+ setvar _${varcat}_ninstalled=0
+ setvar _${varcat}_nselected=0
+ done
+ for pkg in $SELECTED_PACKAGES; do
+ f_str2varname $pkg varpkg
+ mark=
+ f_getvar _mark_$varpkg mark
+ case "$mark" in
+ ""|" ") : ;;
+ X) tinstalled=$(( $tinstalled + 1 )) ;;
+ *) tselected=$(( $tselected + 1 ))
+ esac
+ f_getvar _categories_$varpkg pkgcat
+ for cat in $pkgcat; do
+ f_str2varname $cat varcat
+ case "$mark" in
+ ""|" ") : ;;
+ X) debug= f_getvar _${varcat}_ninstalled n
+ setvar _${varcat}_ninstalled $(( $n + 1 )) ;;
+ *) debug= f_getvar _${varcat}_nselected n
+ setvar _${varcat}_nselected $(( $n + 1 ))
+ esac
+ done
+ done
+ _All_nselected=$tselected
+ _All_ninstalled=$tinstalled
+}
+
+# f_package_calculate_rundeps
+#
+# Update package dependencies by first unmarking all dependencies and then
+# re-marking all dependencies of packages marked for either install ("I") or
+# re-install ("R").
+#
+f_package_calculate_rundeps()
+{
+ local pkg varpkg mark rundeps dep vardep
+
+ #
+ # First unmark all the existing run-dependencies
+ #
+ f_dprintf "Unselecting package run-dependencies..."
+ for pkg in $SELECTED_PACKAGES; do
+ f_str2varname $pkg varpkg
+ mark=
+ debug= f_getvar _mark_$varpkg mark
+ # Only unmark if it's marked as a Dependency
+ if [ "$mark" = "D" ]; then
+ f_dprintf "%s unselected" $pkg
+ unset _mark_$varpkg
+ f_package_deselect $pkg
+ fi
+ done
+
+ #
+ # Processes selected packages, adding dependencies
+ #
+ f_dprintf "Re-selecting package run-dependencies..."
+ for pkg in $SELECTED_PACKAGES; do
+ f_str2varname $pkg varpkg
+ mark=
+ debug= f_getvar _mark_$varpkg mark
+ # Skip pkg unless marked for [Re-]Install
+ [ "$mark" = "I" -o "$mark" = "R" ] || continue
+ f_getvar _rundeps_$varpkg rundeps
+ for dep in $rundeps; do
+ f_str2varname $dep vardep
+ mark=
+ debug= f_getvar _mark_$vardep mark
+ # Skip dep if already marked
+ [ "${mark:- }" = " " ] || continue
+ export _mark_$vardep="D"
+ f_package_select $dep
+ done
+ done
+
+ f_dprintf "Finished recalculating dependencies."
+}
+
+# f_package_menu_categories $var_to_set $defaultitem
+#
+# Dislay the menu of package categories, complete with package counts for each
+# category, accents, and other miscellany. If $defaultitem is non-NULL and
+# matches one of the existing menu-items, it will be pre-highlighted in the
+# menu dialog (HINT: Use f_dialog_menutag_fetch() to populate a local variable
+# that is passed as $defaultitem to highlight the user's last selection).
+#
+f_package_menu_categories()
+{
+ local var_to_get="$1" defaultitem="$2"
+ local prompt="$msg_please_select_a_category_to_display"
+ local menu_list="
+ '> $msg_review' '$msg_review_desc' '$msg_review_help'
+ " # End-Quote
+ local hline=
+
+ f_package_calculate_rundeps
+ # updates package mark variables and SELECTED_PACKAGES
+ f_package_calculate_totals
+ # creates _{varcat}_ninstalled and _{varcat}_nselected
+
+ local category_list
+ debug= f_getvar "$var_to_get" category_list || return $DIALOG_CANCEL
+
+ # Accent the category menu list with ninstalled/nselected
+ eval f_package_accent_category_menu category_list $category_list
+
+ # Add list of categories to menu list
+ menu_list="$menu_list $category_list"
+
+ local height width rows
+ eval f_dialog_menu_with_help_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --item-help \
+ --default-item \"\$defaultitem\" \
+ --ok-label \"$msg_select\" \
+ --cancel-label \"$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+# f_package_index_get_page $category $page [$var_to_set [$var_to_get]]
+#
+# Obtain a [potentially cached] page of the INDEX file for a given $category.
+# If $page is 1 and the cache has not yet been generated, the cache-generating
+# function f_index_extract_pages() (above) is called to generate all pages
+# (not just the requested page) in cache before returning the requested page.
+# If $page is not 1 and there is no cached page, failure status is returned.
+#
+f_package_index_get_page()
+{
+ local category="$1" page="$2" var_to_set="$3" var_to_get="$4" varcat
+ f_str2varname "$category" varcat
+ if ! debug= f_getvar "_index_page_${varcat}_$page" $var_to_set &&
+ [ "$page" = "1" ]
+ then
+ f_show_info "$msg_building_package_menus"
+ local pagesize="$PACKAGE_MENU_PAGESIZE"
+ f_index_extract_pages "${var_to_get:-PACKAGE_INDEX}" \
+ _index_page_${varcat} "$pagesize" "$category"
+ debug= f_getvar _index_page_${varcat}_$page $var_to_set
+
+ # Update category default-item because now we're cached
+ [ $page -eq 1 ] &&
+ category_defaultitem="${category_defaultitem%\*}*"
+ else
+ return $FAILURE
+ fi
+}
+
+# f_package_menu_select $category [$page [$defaultitem]]
+#
+# Display list of packages for $category, optionally $page N and with a default
+# item selected. If $page is omitted, the first page is displayed (but this
+# only matters if there are multiple pages; which is determined by the global
+# maximum $PACKAGE_MENU_PAGESIZE).
+#
+# On success, if the user doesn't press ESC or choose Cancel, use
+# f_dialog_menuitem_fetch() to populate a local variable with the item (not
+# tag) corresponding to the user's selection. The tag portion of the user's
+# selection is available through f_dialog_menutag_fetch().
+#
+f_package_menu_select()
+{
+ local category="$1" page="${2:-1}"
+ local prompt= # Calculated below
+ local menu_list # Calculated below
+ local defaultitem="$3"
+ local hline="$hline_arrows_tab_punc_enter"
+
+ f_isinteger "$page" || return $DIALOG_CANCEL
+
+ local varcat
+ f_str2varname "$category" varcat
+
+ # Get number of packages for this category
+ local npkgs=0
+ case "$category" in
+ "$msg_all"|"") npkgs="${_npkgs:-0}" ;;
+ *) f_getvar _npkgs_$varcat npkgs
+ esac
+
+ # Calculate number of pages
+ local npages=$(( ${npkgs:=0} / $PACKAGE_MENU_PAGESIZE ))
+
+ # Add a page to the pagecount if not evenly divisible
+ [ $(( $npages * $PACKAGE_MENU_PAGESIZE )) -lt $npkgs ] &&
+ npages=$(( $npages + 1 ))
+
+ # Print some debugging information
+ f_dprintf "f_package_menu_select: category=[%s] npkgs=%u npages=%u" \
+ "$category" "$npkgs" "$npages"
+
+ local add_prev="" add_next=""
+ local previous_page="$msg_previous_page" next_page="$msg_next_page"
+ if [ $page -gt 1 ]; then
+ add_prev=1
+ # Accent the `Previous Page' item with an asterisk
+ # if the page-before-previous is loaded/cached
+ f_isset _index_page_${varcat}_$(( $page - 1 )) &&
+ previous_page="$previous_page*"
+ fi
+ if [ $page -lt $npages ]; then
+ add_next=1
+ # Accent the `Next Page' item with an asterisk
+ # if the page-after-next is loaded/cached
+ f_isset _index_page_${varcat}_$(( $page + 1 )) &&
+ next_page="$next_page*"
+ fi
+
+ local index_page
+ f_package_index_get_page "$category" $page index_page
+
+ menu_list="
+ ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}}
+ ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}}
+ $(
+ export SHOW_DESC
+ export VALID_VARNAME_CHARS
+ echo "$index_page" | awk -F'|' -v view="port" '
+ BEGIN {
+ valid_chars = ENVIRON["VALID_VARNAME_CHARS"]
+ prefix = ""
+ }
+ {
+ cur_prefix = tolower(substr($1, 1, 1))
+ printf "'\''"
+ if ( prefix != cur_prefix )
+ prefix = cur_prefix
+ else
+ printf " "
+ package = $1
+ if ( view == "port" )
+ desc = $2
+ varpkg = package
+ gsub("[^" valid_chars "]", "_", varpkg)
+ mark = ENVIRON["_mark_" varpkg]
+ if ( ! mark ) mark = " "
+ printf "%s'\'' '\''[%c] %s'\''",
+ package, mark, desc
+ if ( ENVIRON["SHOW_DESC"] ) {
+ help = $4
+ gsub(/'\''/, "'\''\\'\'\''", help)
+ printf " '\''%s'\''", help
+ }
+ printf "\n"
+ }'
+ )
+ ${add_prev:+'> $previous_page' '' ${SHOW_DESC:+''}}
+ ${add_next:+'> $next_page' '' ${SHOW_DESC:+''}}
+ " # End-Quote
+
+ # Accept/Translate i18n "All" but other category names must
+ # match tree definitions from INDEX, ports, FTP, etc.
+ case "$category" in
+ "$msg_all"|"") f_category_desc_get "All" prompt ;;
+ *) f_category_desc_get "$category" prompt ;;
+ esac
+ f_sprintf prompt "%s $msg_page_of_npages" "$prompt" "$page" "$npages"
+
+ local mheight mwidth mrows
+ eval f_dialog_menu${SHOW_DESC:+_with_help}_size mheight mwidth mrows \
+ \"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \"\$hline\" $menu_list
+ local iheight iwidth
+ f_dialog_infobox_size iheight iwidth \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" \
+ "$msg_processing_selection"
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --keep-tite \
+ --ok-label \"$msg_select\" \
+ --cancel-label \"$msg_back\" \
+ ${SHOW_DESC:+--item-help} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $mheight $mwidth $mrows \
+ $menu_list \
+ --and-widget \
+ ${USE_XDIALOG:+--no-buttons} \
+ --infobox \"\$msg_processing_selection\" \
+ $iheight $iwidth \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ if [ $retval -eq $DIALOG_OK ]; then
+ local item
+ item=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \
+ \"\$menu_choice\" $menu_list )
+ f_dialog_menuitem_store "$item"
+ fi
+
+ return $retval
+}
+
+# f_package_menu_deselect $package
+#
+# Display a menu, asking the user what they would like to do with $package
+# with regard to "deselecting" an already installed package. Choices include
+# uninstall, re-install, or cancel (leave $package marked as installed).
+# Returns success if the user does not press ESC or choose Cnacel. Use the
+# f_dialog_menutag_fetch() function upon success to retrieve the user's choice.
+#
+f_package_menu_deselect()
+{
+ local package="$1"
+ local prompt # Calculated below
+ local menu_list="
+ 'X $msg_installed' '$msg_installed_desc'
+ 'R $msg_reinstall' '$msg_reinstall_desc'
+ 'U $msg_uninstall' '$msg_uninstall_desc'
+ " # End-Quote
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+
+ f_sprintf prompt "$msg_what_would_you_like_to_do_with" "$package"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"$msg_select\" \
+ --cancel-label \"$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+# f_package_review
+#
+# Display a review screen, showing selected packages and what they are marked
+# for, before proceeding (if the user does not press ESC or choose Cancel) to
+# operate on each selection. Returns error if no packages have been selected,
+# or the user has pressed ESC, or if they have chosen Cancel.
+#
+f_package_review()
+{
+ local funcname=f_package_review
+ local prompt # Calculated below
+ local menu_list # Calculated below
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+
+ f_dprintf "$funcname: SELECTED_PACKAGES=[%s]" "$SELECTED_PACKAGES"
+
+ f_sprintf prompt "$msg_reviewing_selected_packages" "$_All_nselected"
+
+ local package varpkg mark
+ for package in $SELECTED_PACKAGES; do
+ mark=
+ f_str2varname "$package" varpkg
+ f_getvar _mark_$varpkg mark
+ [ "$mark" -a ! "${mark#[IRUD]}" ] || continue
+ menu_list="$menu_list
+ '$mark' '$package'
+ " # End-Quote
+ done
+ if [ ! "$menu_list" ]; then
+ f_show_msg "$msg_no_packages_were_selected_for_extraction"
+ return $DIALOG_CANCEL # Might have selected this by accident
+ fi
+ menu_list=$( echo "$menu_list" | sort )
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Show the review menu (ignore menu choice)
+ eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_proceed\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2> /dev/null || return $?
+ # Return if the user pressed ESC or chose Cancel/No
+
+ #
+ # Process each of the selected packages:
+ # + First, process packages marked for Install.
+ # + Second, process packages marked for Re-install.
+ # + Finally, process packages marked for Uninstall.
+ #
+ for package in $SELECTED_PACKAGES; do
+ mark=
+ f_str2varname "$package" varpkg
+ debug= f_getvar _mark_$varpkg mark
+ [ "$mark" = "I" ] || continue
+ f_dprintf "$funcname: Installing %s package" "$package"
+ f_package_add "$package"
+ done
+ for package in $SELECTED_PACKAGES; do
+ mark=
+ f_str2varname "$package" varpkg
+ debug= f_getvar _mark_$varpkg mark
+ [ "$mark" = "R" ] || continue
+ f_dprintf "$funcname: Reinstalling %s package" "$package"
+ f_package_reinstall "$package"
+ done
+ for package in $SELECTED_PACKAGES; do
+ mark=
+ f_str2varname "$package" varpkg
+ debug= f_getvar _mark_$varpkg mark
+ [ "$mark" = "U" ] || continue
+ f_dprintf "$funcname: Uninstalling %s package" "$package"
+ f_package_delete "$package" || continue
+ f_package_deselect "$package"
+ done
+
+ return $DIALOG_OK
+}
+
+# f_package_config
+#
+# Allow the user to configure packages and install them. Initially, a list of
+# package categories is loaded/displayed. When the user selects a category,
+# the menus for that category are built (unlike sysinstall which built all
+# category menus up-front -- which also took forever, despite the fact that
+# few people visit more than a couple of categories each time).
+#
+f_package_config()
+{
+ # Did we get an INDEX?
+ f_index_initialize || return $FAILURE
+ # Creates following variables (indirectly via f_index_read())
+ # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
+ # PACKAGE_CATEGORIES _npkgs
+
+ f_show_info "$msg_building_package_main_menu"
+
+ # Detect installed packages (updates marks/SELECTED_PACKAGES)
+ f_package_detect_installed
+ export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
+
+ local retval category varcat defaultitem category_defaultitem=""
+ while :; do
+ # Display the list of package categories
+ f_package_menu_categories \
+ CATEGORY_MENU_LIST "$category_defaultitem"
+ retval=$?
+ f_dialog_menutag_fetch category
+ f_dprintf "retval=%u mtag=[%s]" $retval "$category"
+ category_defaultitem="$category"
+
+ [ $retval -eq $DIALOG_OK ] || break
+
+ # Maybe the user chose an action (like `Review')
+ case "$category" in
+ "> $msg_review")
+ f_package_review && break
+ continue ;;
+ "> "*)
+ continue
+ esac
+
+ # Anything else is a package category
+
+ category=${category# } # Trim leading space if present
+ category=${category%\*} # Trim trailing asterisk if present
+
+ f_str2varname "$category" varcat
+
+ local page package varpkg mark menu_choice
+ while :; do
+ # Display the list of packages for selected category
+ page=1 defaultitem=""
+ f_getvar _defaultitem_$varcat defaultitem
+ f_getvar _defaultpage_$varcat page
+ f_package_menu_select \
+ "$category" "${page:=1}" "$defaultitem"
+ retval=$?
+ f_dialog_menutag_fetch menu_choice
+ f_dprintf "retval=%u mtag=[%s]" $retval "$menu_choice"
+
+ # NOTE: When --and-widget is used only ESC will cause
+ # dialog(1) to return without going to the next widget.
+ # This is alright in our case as we can still detect
+ # the Cancel button because stdout will be NULL.
+ # Alternatively, Xdialog(1) will terminate with 1
+ # if/when Cancel is chosen on any widget.
+ if [ $retval -eq $DIALOG_ESC -o ! "$menu_choice" ]
+ then
+ break
+ elif [ $retval -eq $DIALOG_CANCEL ]; then
+ # Using X11, Xdialog(1) returned 1 for Cancel
+ f_show_msg "%s" "$menu_choice"
+ break
+ elif [ $retval -ne $DIALOG_OK ]; then
+ # X11-related error occurred using Xdialog(1)
+ f_show_msg "%s" "$menu_choice"
+ break
+ fi
+
+ defaultitem="$menu_choice"
+
+ # NOTE: f_package_menu_select() does not show the
+ # `Previous Page' or `Next Page' items unless needed
+ case "$menu_choice" in
+ "> $msg_previous_page"|"> $msg_previous_page*")
+ page=$(( $page - 1 ))
+ setvar _defaultpage_$varcat $page
+ # Update default-item to match accent that will
+ # be applied by f_package_menu_select(); if the
+ # page-before-prev is cached, add an asterisk.
+ if f_isset \
+ _index_page_${varcat}_$(( $page - 1 ))
+ then
+ defaultitem="${defaultitem%\*}*"
+ else
+ defaultitem="${defaultitem%\*}"
+ fi
+ setvar _defaultitem_$varcat "$defaultitem"
+ continue ;;
+ "> $msg_next_page"|"> $msg_next_page*")
+ page=$(( $page + 1 ))
+ setvar _defaultpage_$varcat $page
+ # Update default-item to match accent that will
+ # be applied by f_package_menu_select(); if the
+ # page-after-next is cached, add an asterisk.
+ if f_isset \
+ _index_page_${varcat}_$(( $page + 1 ))
+ then
+ defaultitem="${defaultitem%\*}*"
+ else
+ defaultitem="${defaultitem%\*}"
+ fi
+ setvar _defaultitem_$varcat "$defaultitem"
+ continue ;;
+ "> "*) # Unknown navigation/action item
+ setvar _defaultpage_$varcat $page
+ continue ;; # Do not treat as a package
+ *)
+ setvar _defaultitem_$varcat "$defaultitem"
+ esac
+
+ # Treat any other selection as a package
+ package="${menu_choice# }" # Trim leading space
+ f_str2varname $package varpkg
+ f_dialog_menuitem_fetch mark
+ mark="${mark#?}"
+ mark="${mark%%\] *}"
+ case "$mark" in
+ "I")
+ mark=" "
+ f_package_deselect $package
+ ;;
+ " "|"D")
+ mark="I"
+ f_package_select $package
+ ;;
+ "X"|"R"|"U")
+ f_package_menu_deselect $package || continue
+ f_dialog_menutag_fetch menu_choice
+ case "$menu_choice" in
+ "X $msg_installed")
+ f_package_deselect "$package"
+ mark="X"
+ ;;
+ "R $msg_reinstall")
+ f_package_select "$package"
+ mark="R"
+ ;;
+ "U $msg_uninstall")
+ f_package_select "$package"
+ mark="U"
+ ;;
+ esac
+ ;;
+ esac
+ export _mark_$varpkg="$mark"
+ # NOTE: exported for awk(1) ENVIRON[]
+ done
+ done
+}
+
+# f_package_add $package_name [$depended]
+#
+# Like f_package_extract(), but assumes current media device and chases deps.
+# Note that $package_name should not contain the archive suffix (e.g., `.tbz').
+# If $depended is present and non-NULL, the package is treated as a dependency
+# (in this function, dependencies are not handled any differently, but the
+# f_package_extract() function is passed this value and it displays a different
+# message when installing a dependency versus non-dependency).
+#
+f_package_add()
+{
+ local name="$1" depended="$2" status=$SUCCESS retval
+
+ local alert=f_show_msg no_confirm=
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
+ then
+ f_dprintf "packageAdd: %s" \
+ "$msg_no_package_name_passed_in_package_variable"
+ return $FAILURE
+ fi
+
+ { # Verify and initialize device media if-defined
+ f_media_verify &&
+ f_device_init device_media &&
+ f_index_initialize
+ } || return $FAILURE
+
+ # Now we have (indirectly via f_index_read()):
+ # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
+ # PACKAGE_CATEGORIES _npkgs
+
+ local varpkg
+ f_str2varname "$name" varpkg
+
+ # Just as-in the user-interface (opposed to scripted-use), only allow
+ # packages with at least one category to be recognized.
+ #
+ local pkgcat=
+ if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then
+ # $pkg may be a partial name, search the index (this is slow)
+ f_index_search PACKAGE_INDEX $name name
+ if [ ! "$name" ]; then
+ f_show_msg \
+ "$msg_sorry_package_was_not_found_in_the_index" \
+ "$name"
+ return $FAILURE
+ fi
+ f_str2varname "$name" varpkg
+ fi
+
+ # If invoked through the scripted interface, we likely have not yet
+ # detected the installed packages -- something we should do only once.
+ #
+ if [ ! "$PACKAGES_DETECTED" ]; then
+ f_dprintf "f_package_add: Detecting installed packages"
+ f_package_detect_installed
+ export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
+ fi
+ # Now we have: _mark_{varpkg}=X for all installed packages
+
+ #
+ # Since we're maintaining data structures for installed packages,
+ # short-circuit the package dependency checks if the package is already
+ # installed. This prevents wasted cycles, minor delays between package
+ # extractions, and worst-case an infinite loop with a certain faulty
+ # INDEX file.
+ #
+ local mark=
+ f_getvar _mark_$varpkg mark && [ "$mark" = "X" ] && return $SUCCESS
+
+ local dep vardep rundeps=
+ f_getvar _rundeps_$varpkg rundeps
+ for dep in $rundeps; do
+ f_str2varname "$dep" vardep
+
+ # Skip dependency if already installed
+ mark=
+ f_getvar _mark_$vardep mark && [ "$mark" = "X" ] && continue
+
+ # Just as-in the user-interface (opposed to scripted-use), only
+ # allow packages with at least one category to be recognized.
+ #
+ local depcat=
+ if ! f_getvar _categories_$vardep depcat || [ ! "$depcat" ]
+ then
+ $alert "$msg_required_package_not_found" "$dep"
+ [ "$no_confirm" ] && sleep 2
+ fi
+
+ f_package_add "$dep"
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ status=$(( $status | $retval ))
+
+ # XXX package could be on a future disc volume
+ # XXX (not supporting multiple disc volumes yet)
+
+ $alert "$msg_loading_of_dependent_package_failed" \
+ "$dep"
+ [ "$no_confirm" ] && sleep 2
+ fi
+ done
+ [ $status -eq $SUCCESS ] || return $status
+
+ #
+ # Done with the deps? Try to load the real m'coy.
+ #
+
+ f_package_extract device_media "$name" "$depended"
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ status=$(( $status | $retval ))
+ else
+ setvar _mark_$varpkg X
+ fi
+
+ return $status
+}
+
+# f_package_extract $device $name [$depended]
+#
+# Extract a package based on a namespec and media device. If $depended is
+# present and non-NULL, the notification displayed while installing the package
+# has "as a dependency" appended.
+#
+f_package_extract()
+{
+ local funcname=f_package_extract
+ local device="$1" name="$2" depended="$3"
+ local devname=
+
+ f_musthavepkg_init # Make sure we have a usable pkg(8) with $PKG_ABI
+
+ $device get name devname
+ f_dprintf "$funcname: device=[%s] name=[%s] depended=[%s]" \
+ "$devname" "$name" "$depended"
+
+ # Check to make sure it's not already there
+ local varpkg mark=
+ f_str2varname "$name" varpkg
+ f_getvar _mark_$varpkg mark
+ [ "$mark" = "X" ] && return $SUCCESS
+
+ if ! f_device_init $device; then
+ f_show_msg \
+ "$msg_unable_to_initialize_media_type_for_package_extract"
+ return $FAILURE
+ fi
+
+ # If necessary, initialize the ldconfig hints
+ [ -f "/var/run/ld-elf.so.hints" ] ||
+ f_quietly ldconfig /usr/lib /usr/lib/compat /usr/local/lib
+
+ # Make a couple paranoid locations for temp
+ # files to live if user specified none
+ local tmpdir
+ f_getvar $VAR_PKG_TMPDIR:-/var/tmp tmpdir
+ f_quietly mkdir -p -m 1777 "$tmpdir"
+
+ local path device_type
+ $device get type device_type
+ case "$name" in
+ */*) path="$name" ;;
+ *)
+ if [ "$device_type" = "$DEVICE_TYPE_HTTP" ]; then
+ path="$PKG_ABI/latest/All/$name"
+ else
+ path="packages/$PKG_ABI/All/$name"
+ fi
+ esac
+
+ # We have a path, call the device strategy routine to check the file
+ local pkg_ext found=
+ for pkg_ext in "" $PACKAGE_EXTENSIONS; do
+ if f_device_get $device "$path$pkg_ext" $PROBE_EXIST; then
+ path="$path$pkg_ext"
+ found=1
+ break
+ elif [ "$device_type" = "$DEVICE_TYPE_HTTP" ] &&
+ f_device_get $device \
+ "packages/$PKG_ABI/All/$name$pkg_ext" $PROBE_EXIST
+ then
+ # Mirroring physical media over HTTP
+ path="packages/$PKG_ABI/All/$name$pkg_ext"
+ found=1
+ break
+ fi
+ done
+ [ "$found" ] && f_dprintf "$funcname: found path=[%s] dev=[%s]" \
+ "$path" "$devname"
+
+ local alert=f_show_msg no_confirm=
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ if [ ! "$found" ]; then
+ f_dprintf "$funcname: No such %s file on %s device" \
+ "$path" "$devname"
+ $alert "$msg_unable_to_fetch_package_from_selected_media" \
+ "$name"
+ [ "$no_confirm" ] && sleep 2
+ return $FAILURE
+ fi
+
+ if [ "$depended" ]; then
+ f_show_info "$msg_adding_package_as_a_dependency_from_media" \
+ "$name" "$devname"
+ else
+ f_show_info "$msg_adding_package_from_media" "$name" "$devname"
+ fi
+
+ # Request the package be added via pkg-install(8)
+ if f_debugging; then
+ f_eval_catch $funcname pkg \
+ 'pkg -d install -${depended:+A}y "%s"' "$name"
+ else
+ f_eval_catch $funcname pkg \
+ 'pkg install -${depended:+A}y "%s"' "$name"
+ fi
+ if [ $? -ne $SUCCESS ]; then
+ $alert "$msg_pkg_install_apparently_did_not_like_the_package" \
+ "$name"
+ [ "$no_confirm" ] && sleep 2
+ else
+ f_show_info "$msg_package_was_added_successfully" "$name"
+ sleep 1
+ fi
+
+ return $SUCCESS
+}
+
+# f_package_delete $name
+#
+# Delete package by full $name (lacks archive suffix; e.g., `.tbz').
+#
+f_package_delete()
+{
+ local funcname=f_package_delete
+ local name="$1"
+
+ if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
+ then
+ f_dprintf "packageDelete: %s" \
+ "$msg_no_package_name_passed_in_package_variable"
+ return $FAILURE
+ fi
+
+ f_dprintf "$funcname: name=[%s]" "$name"
+
+ [ "$name" ] || return $FAILURE
+
+ { # Verify and initialize device media if-defined
+ f_media_verify &&
+ f_device_init device_media &&
+ f_index_initialize
+ } || return $FAILURE
+
+ # Now we have (indirectly via f_index_read()):
+ # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg}
+ # PACKAGE_CATEGORIES _npkgs
+
+ local varpkg
+ f_str2varname "$name" varpkg
+
+ # Just as-in the user-interface (opposed to scripted-use), only allow
+ # packages with at least one category to be recognized.
+ #
+ local pkgcat=
+ if ! f_getvar _categories_$varpkg pkgcat || [ ! "$pkgcat" ]; then
+ # $pkg may be a partial name, search the index (this is slow)
+ f_index_search PACKAGE_INDEX "$name" name
+ if [ ! "$name" ]; then
+ f_show_msg \
+ "$msg_sorry_package_was_not_found_in_the_index" \
+ "$name"
+ return $FAILURE
+ fi
+ f_str2varname "$name" varpkg
+ fi
+
+ # If invoked through the scripted interface, we likely have not yet
+ # detected the installed packages -- something we should do only once.
+ #
+ if [ ! "$PACKAGES_DETECTED" ]; then
+ f_dprintf "$funcname: Detecting installed packages"
+ f_package_detect_installed
+ export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
+ fi
+ # Now we have: _mark_{varpkg}=X for all installed packages
+
+ #
+ # Return failure if the package is not already installed.
+ #
+ local pkgmark=
+ f_getvar _mark_$varpkg pkgmark
+ if ! [ "$pkgmark" -a ! "${pkgmark#[XUR]}" ]; then
+ f_show_msg "$msg_package_not_installed_cannot_delete" "$name"
+ return $FAILURE
+ fi
+
+ #
+ # Check for dependencies
+ #
+ local pkgsel depc=0 udeps=
+ for pkgsel in $SELECTED_PACKAGES; do
+ local mark=
+ f_str2varname $pkgsel varpkg
+ debug= f_getvar _mark_$varpkg mark
+ [ "$mark" -a ! "${mark#[XUR]}" ] || continue
+ local dep rundeps=
+ debug= f_getvar _rundeps_$varpkg rundeps
+ for dep in $rundeps; do
+ if [ "$dep" = "$name" ]; then
+ # Maybe this package is marked for deletion too
+ if [ "$mark" = "U" ]; then
+ udeps="$udeps $pkgsel"
+ else
+ depc=$(( $depc + 1 ))
+ fi
+ break
+ fi
+ done
+ done
+ if [ $depc -gt 0 ]; then
+ local grammatical_s=
+ [ $depc -gt 1 ] && grammatical_s=s
+ f_show_msg \
+ "$msg_package_is_needed_by_other_installed_packages" \
+ "$name" "$depc" "$grammatical_s"
+ return $FAILURE
+ fi
+
+ #
+ # Chase dependencies that are marked for uninstallation
+ #
+ for pkgsel in $udeps; do
+ f_dprintf "$funcname: Uninstalling dependency %s (%s)" \
+ "$pkgsel" "marked for delete"
+ f_package_delete "$pkgsel"
+ done
+
+ #
+ # OK to perform the delete (no other packages depend on it)...
+ #
+ f_show_info "$msg_uninstalling_package_waiting_for_pkg_delete" "$name"
+ if f_debugging; then
+ f_eval_catch $funcname pkg 'pkg -d delete -y "%s"' "$name"
+ else
+ f_eval_catch $funcname pkg 'pkg delete -y "%s"' "$name"
+ fi
+ if [ $? -ne $SUCCESS ]; then
+ f_show_msg "$msg_pkg_delete_failed" "$name"
+ return $FAILURE
+ else
+ f_dprintf "$funcname: pkg-delete(8) of %s successful" "$name"
+ f_str2varname "$name" varpkg
+ setvar _mark_$varpkg ""
+ fi
+}
+
+# f_package_reinstall $name
+#
+# A simple wrapper to f_package_delete() + f_package_add()
+#
+f_package_reinstall()
+{
+ f_package_delete "$1" && f_package_add "$1"
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." packages/packages.subr
+
+fi # ! $_PACKAGES_PACKAGES_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/script.subr b/contrib/bsddialog/bsdconfig/share/script.subr
new file mode 100644
index 000000000000..b562e99b7303
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/script.subr
@@ -0,0 +1,219 @@
+if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1
+#
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." script.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/media/any.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/networking/services.subr
+f_include $BSDCFG_SHARE/packages/packages.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+############################################################ GLOBALS
+
+RESWORDS=
+
+############################################################ FUNCTIONS
+
+# f_resword_new $resword $function
+#
+# Create a new `reserved' word for scripting purposes. Reswords call pre-
+# defined functions but differ from those functions in the following ways:
+#
+# + Unless noError is set (must be non-NULL), if calling the resword
+# results in failure, the application will terminate prematurely.
+# + noError is unset after each/every resword is called.
+#
+# Reswords should not be used in bsdconfig itself (hence the name `reserved
+# word') but instead only in scripts loaded through f_script_load().
+#
+f_resword_new()
+{
+ local resword="$1" func="$2"
+ [ "$resword" ] || return $FAILURE
+ f_dprintf "script.subr: New resWord %s -> %s" "$resword" "$func"
+ eval $resword\(\){ f_dispatch $func $resword \"\$@\"\; }
+ RESWORDS="$RESWORDS${RESWORDS:+ }$resword"
+}
+
+# f_dispatch $func $resword
+#
+# Wrapper function used by `reserved words' (reswords) to call other functions.
+# If $noError is set and non-NULL, a failure result from $func is ignored,
+# otherwise the application is prematurely terminated using f_die().
+#
+# NOTE: $noError is unset after every call.
+#
+f_dispatch()
+{
+ local func="$1" resword="$2"
+ shift 2 # func resword
+ f_dprintf "f_dispatch: calling resword \`%s'" "$resword"
+ eval $func "$@"
+ local retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ local _ignore_this_error
+ f_getvar $VAR_NO_ERROR _ignore_this_error
+ [ "$_ignore_this_error" ] || f_die $retval \
+ "$msg_command_failed_rest_of_script_aborted" "$resword"
+ fi
+ unset $VAR_NO_ERROR
+}
+
+# f_script_load [$file]
+#
+# Load a script (usually filled with reswords). If $file is missing or NULL,
+# use one of the following instead (in order):
+#
+# $configFile (global)
+# install.cfg
+# /stand/install.fg
+# /tmp/install.cfg
+#
+# Unknown/unregistered reswords will generate sh(1) syntax errors but not cause
+# premature termination.
+#
+# Returns success if a script was loaded and itself returned success.
+#
+f_script_load()
+{
+ local funcname=f_script_load
+ local script="$1" config_file retval=$SUCCESS
+
+ f_dprintf "$funcname: script=[%s]" "$script"
+ if [ ! "$script" ]; then
+ f_getvar $VAR_CONFIG_FILE config_file
+ for script in \
+ $config_file \
+ install.cfg \
+ /stand/install.cfg \
+ /tmp/install.cfg \
+ ; do
+ [ -e "$script" ] && break
+ done
+ fi
+
+ local old_interactive=
+ f_getvar $VAR_NONINTERACTIVE old_interactive # save a copy
+
+ # Hint to others that we're running from a script, should they care
+ setvar $VAR_NONINTERACTIVE yes
+
+ if [ "$script" = "-" ]; then
+ f_dprintf "$funcname: Loading script from stdin"
+ eval "$( cat )"
+ retval=$?
+ else
+ f_dprintf "$funcname: Loading script \`%s'" "$script"
+ if [ ! -e "$script" ]; then
+ f_show_msg "$msg_unable_to_open" "$script"
+ return $FAILURE
+ fi
+ . "$script"
+ retval=$?
+ fi
+
+ [ "$old_interactive" ] &&
+ setvar $VAR_NONINTERACTIVE "$old_interactive"
+
+ return $retval
+}
+
+############################################################ MAIN
+
+#
+# Reserved words meant for scripting
+#
+
+# this file
+f_resword_new loadConfig f_script_load
+
+# device.subr
+f_resword_new deviceRescan f_device_rescan
+
+# media/common.subr
+f_resword_new mediaOpen f_media_open
+f_resword_new mediaClose f_media_close
+
+# media includes
+f_resword_new mediaGetType f_media_get_type # media/any.subr
+f_resword_new mediaSetCDROM f_media_set_cdrom # media/cdrom.subr
+f_resword_new mediaSetDOS f_media_set_dos # media/dos.subr
+f_resword_new mediaSetDirectory f_media_set_directory # media/directory.subr
+f_resword_new mediaSetFloppy f_media_set_floppy # media/floppy.subr
+f_resword_new mediaSetNFS f_media_set_nfs # media/nfs.subr
+f_resword_new mediaSetUFS f_media_set_ufs # media/ufs.subr
+f_resword_new mediaSetUSB f_media_set_usb # media/usb.subr
+f_resword_new optionsEditor f_media_options_menu # media/options.subr
+f_resword_new tcpMenuSelect f_dialog_menu_select_tcp # media/tcp.subr
+
+# media/ftp.subr
+f_resword_new mediaSetFTP f_media_set_ftp
+f_resword_new mediaSetFTPActive f_media_set_ftp_active
+f_resword_new mediaSetFTPPassive f_media_set_ftp_passive
+f_resword_new mediaSetFTPUserPass f_media_set_ftp_userpass
+
+# media/http.subr
+f_resword_new mediaSetHTTP f_media_set_http
+
+# media/httpproxy.subr
+f_resword_new mediaSetHTTPProxy f_media_set_http_proxy
+
+# networking/services.subr
+f_resword_new configPCNFSD f_config_pcnfsd
+
+# packages/packages.subr
+f_resword_new configPackages f_package_config
+f_resword_new packageAdd f_package_add
+f_resword_new packageDelete f_package_delete
+f_resword_new packageReinstall f_package_reinstall
+
+# usermgmt/group.subr
+f_resword_new addGroup f_group_add
+f_resword_new deleteGroup f_group_delete
+f_resword_new editGroup f_group_edit
+
+# usermgmt/user.subr
+f_resword_new addUser f_user_add
+f_resword_new deleteUser f_user_delete
+f_resword_new editUser f_user_edit
+
+# variable.subr
+f_resword_new installVarDefaults f_variable_set_defaults
+f_resword_new dumpVariables f_dump_variables
+
+f_dprintf "%s: Successfully loaded." script.subr
+
+fi # ! $_SCRIPT_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/strings.subr b/contrib/bsddialog/bsdconfig/share/strings.subr
new file mode 100644
index 000000000000..f33f4df566ad
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/strings.subr
@@ -0,0 +1,577 @@
+if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1
+#
+# Copyright (c) 2006-2016 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ GLOBALS
+
+#
+# A Literal newline (for use with f_replace_all(), or IFS, or whatever)
+#
+NL="
+" # END-QUOTE
+
+#
+# Valid characters that can appear in an sh(1) variable name
+#
+# Please note that the character ranges A-Z and a-z should be avoided because
+# these can include accent characters (which are not valid in a variable name).
+# For example, A-Z matches any character that sorts after A but before Z,
+# including A and Z. Although ASCII order would make more sense, that is not
+# how it works.
+#
+VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
+
+############################################################ FUNCTIONS
+
+# f_isinteger $arg
+#
+# Returns true if argument is a positive/negative whole integer.
+#
+f_isinteger()
+{
+ local arg="${1#-}"
+ [ "${arg:-x}" = "${arg%[!0-9]*}" ]
+}
+
+# f_substr [-v $var_to_set] $string $start [$length]
+#
+# Similar to awk(1)'s substr(), return length substring of string that begins
+# at start position counted from 1.
+#
+case "$BASH_VERSION" in
+*?*)
+ f_substr()
+ {
+ local __var_to_set=
+ case "$1" in
+ -v) __var_to_set="$2"; shift 2 ;;
+ -v?*) __var_to_set="${2#-v}"; shift 1 ;;
+ esac
+ local __tmp="$1" __start="${2:-1}" __len="$3"
+ [ "$__start" -gt 0 ] 2> /dev/null &&
+ __start=$(( $__start - 1 ))
+ if [ ! "$__var_to_set" ]; then
+ eval echo \"\${__tmp:\$__start${__len:+:\$__len}}\"
+ return $?
+ fi
+ if [ "$__len" ]; then
+ eval $__var_to_set=\"\${__tmp:\$__start:\$__len}\"
+ else
+ eval $__var_to_set=\"\${__tmp:\$__start}\"
+ fi
+ }
+ ;;
+*)
+ # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
+ f_substr()
+ {
+ local OPTIND=1 OPTARG __flag __var_to_set=
+ while getopts v: __flag; do
+ case "$__flag" in
+ v) __var_to_set="$OPTARG" ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ local __tmp="$1" __start="${2:-1}" __size="$3"
+ local __tbuf __tbuf_len __trim __trimq
+
+ if [ ! "$__tmp" ]; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return ${SUCCESS:-0}
+ fi
+ [ "$__start" -ge 1 ] 2> /dev/null || __start=1
+ if ! [ "${__size:-1}" -ge 1 ] 2> /dev/null; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return ${FAILURE:-1}
+ fi
+
+ __trim=$(( $__start - 1 ))
+ while [ $__trim -gt 0 ]; do
+ __tbuf="?"
+ __tbuf_len=1
+ while [ $__tbuf_len -lt $(( $__trim / $__tbuf_len )) ]
+ do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__trim / $__tbuf_len ))
+ __trim=$(( $__trim - $__tbuf_len * $__trimq ))
+ while [ $__trimq -gt 0 ]; do
+ __tmp="${__tmp#$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ done
+
+ local __tmp_size=${#__tmp}
+ local __mask __mask_len
+ __trim=$(( $__tmp_size - ${__size:-$__tmp_size} ))
+ while [ $__trim -gt 0 ]; do
+ __tbuf="?"
+ __tbuf_len=1
+ if [ $__trim -le $__size ]; then
+ while [ $__tbuf_len -lt $((
+ $__trim / $__tbuf_len
+ )) ]; do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__trim / $__tbuf_len ))
+ __trim=$(( $__trim - $__tbuf_len * $__trimq ))
+ while [ $__trimq -gt 0 ]; do
+ __tmp="${__tmp%$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ else
+ __mask="$__tmp"
+ while [ $__tbuf_len -lt $((
+ $__size / $__tbuf_len
+ )) ]; do
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ done
+ __trimq=$(( $__size / $__tbuf_len ))
+ if [ $__size -ne $((
+ $__trimq * $__tbuf_len
+ )) ]; then
+ __tbuf="$__tbuf?"
+ __tbuf_len=$(( $__tbuf_len + 1 ))
+ fi
+ __mask_len=$((
+ $__tmp_size - $__tbuf_len * $__trimq
+ ))
+ __trim=$((
+ $__tmp_size - $__mask_len - $__size
+ ))
+ while [ $__trimq -gt 0 ]; do
+ __mask="${__mask#$__tbuf}"
+ __trimq=$(( $__trimq - 1 ))
+ done
+ __tmp="${__tmp%"$__mask"}"
+ fi
+ done
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__tmp"
+ else
+ echo "$__tmp"
+ fi
+ }
+esac
+
+# f_sprintf $var_to_set $format [$arguments ...]
+#
+# Similar to sprintf(3), write a string into $var_to_set using printf(1) syntax
+# (`$format [$arguments ...]').
+#
+case "$BASH_VERSION" in
+3.1*|4.*)
+ f_sprintf()
+ {
+ local __var_to_set="$1" __tmp
+ shift 1 # var_to_set
+ printf -v __tmp "$@"
+ eval "$__var_to_set"=\"\${__tmp%\$NL}\"
+ }
+ ;;
+*)
+ # NB: On FreeBSD, sh(1) runs this faster than bash(1) runs the above
+ f_sprintf()
+ {
+ local __var_to_set="$1"
+ shift 1 # var_to_set
+ eval "$__var_to_set"=\$\( printf -- \"\$@\" \)
+ }
+esac
+
+# f_vsprintf $var_to_set $format $format_args
+#
+# Similar to vsprintf(3), write a string into $var_to_set using printf(1)
+# syntax (`$format $format_args').
+#
+f_vsprintf()
+{
+ eval f_sprintf \"\$1\" \"\$2\" $3
+}
+
+# f_snprintf $var_to_set $size $format [$arguments ...]
+#
+# Similar to snprintf(3), write at most $size number of bytes into $var_to_set
+# using printf(1) syntax (`$format [$arguments ...]').
+#
+f_snprintf()
+{
+ local __var_to_set="$1" __size="$2"
+ shift 2 # var_to_set size
+
+ local __f_snprintf_tmp
+ f_sprintf __f_snprintf_tmp "$@"
+ f_substr "$__var_to_set" "$__f_snprintf_tmp" 1 "$__size"
+}
+
+# f_vsnprintf $var_to_set $size $format $format_args
+#
+# Similar to vsnprintf(3), write at most $size number of bytes into $var_to_set
+# using printf(1) syntax (`$format $format_args'). The value of $var_to_set is
+# NULL unless at-least one byte is stored from the output.
+#
+# Example 1:
+#
+# limit=7 format="%s"
+# format_args="'abc 123'" # 3-spaces between abc and 123
+# f_vsnprintf foo $limit "$format" "$format_args" # foo=[abc 1]
+#
+# Example 2:
+#
+# limit=12 format="%s %s"
+# format_args=" 'doghouse' 'fox' "
+# # even more spaces added to illustrate escape-method
+# f_vsnprintf foo $limit "$format" "$format_args" # foo=[doghouse fox]
+#
+# Example 3:
+#
+# limit=13 format="%s %s"
+# f_shell_escape arg1 'aaa"aaa' # arg1=[aaa"aaa] (no change)
+# f_shell_escape arg2 "aaa'aaa" # arg2=[aaa'\''aaa] (escaped s-quote)
+# format_args="'$arg1' '$arg2'" # use single-quotes to surround args
+# f_vsnprintf foo $limit "$format" "$format_args" # foo=[aaa"aaa aaa'a]
+#
+# In all of the above examples, the call to f_vsnprintf() does not change. Only
+# the contents of $limit, $format, and $format_args changes in each example.
+#
+f_vsnprintf()
+{
+ eval f_snprintf \"\$1\" \"\$2\" \"\$3\" $4
+}
+
+# f_replaceall $string $find $replace [$var_to_set]
+#
+# Replace all occurrences of $find in $string with $replace. If $var_to_set is
+# either missing or NULL, the variable name is produced on standard out for
+# capturing in a sub-shell (which is less recommended due to performance
+# degradation).
+#
+# To replace newlines or a sequence containing the newline character, use $NL
+# as `\n' is not supported.
+#
+f_replaceall()
+{
+ local __left="" __right="$1"
+ local __find="$2" __replace="$3" __var_to_set="$4"
+ while :; do
+ case "$__right" in *$__find*)
+ __left="$__left${__right%%$__find*}$__replace"
+ __right="${__right#*$__find}"
+ continue
+ esac
+ break
+ done
+ __left="$__left${__right#*$__find}"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__left"
+ else
+ echo "$__left"
+ fi
+}
+
+# f_str2varname $string [$var_to_set]
+#
+# Convert a string into a suitable value to be used as a variable name
+# by converting unsuitable characters into the underscrore [_]. If $var_to_set
+# is either missing or NULL, the variable name is produced on standard out for
+# capturing in a sub-shell (which is less recommended due to performance
+# degradation).
+#
+f_str2varname()
+{
+ local __string="$1" __var_to_set="$2"
+ f_replaceall "$__string" "[!$VALID_VARNAME_CHARS]" "_" "$__var_to_set"
+}
+
+# f_shell_escape $string [$var_to_set]
+#
+# Escape $string for shell eval statement(s) by replacing all single-quotes
+# with a special sequence that creates a compound string when interpolated
+# by eval with surrounding single-quotes.
+#
+# For example:
+#
+# foo="abc'123"
+# f_shell_escape "$foo" bar # bar=[abc'\''123]
+# eval echo \'$bar\' # produces abc'123
+#
+# This is helpful when processing an argument list that has to retain its
+# escaped structure for later evaluations.
+#
+# WARNING: Surrounding single-quotes are not added; this is the responsibility
+# of the code passing the escaped values to eval (which also aids readability).
+#
+f_shell_escape()
+{
+ local __string="$1" __var_to_set="$2"
+ f_replaceall "$__string" "'" "'\\''" "$__var_to_set"
+}
+
+# f_shell_unescape $string [$var_to_set]
+#
+# The antithesis of f_shell_escape(), this function takes an escaped $string
+# and expands it.
+#
+# For example:
+#
+# foo="abc'123"
+# f_shell_escape "$foo" bar # bar=[abc'\''123]
+# f_shell_unescape "$bar" # produces abc'123
+#
+f_shell_unescape()
+{
+ local __string="$1" __var_to_set="$2"
+ f_replaceall "$__string" "'\\''" "'" "$__var_to_set"
+}
+
+# f_expand_number $string [$var_to_set]
+#
+# Unformat $string into a number, optionally to be stored in $var_to_set. This
+# function follows the SI power of two convention.
+#
+# The prefixes are:
+#
+# Prefix Description Multiplier
+# k kilo 1024
+# M mega 1048576
+# G giga 1073741824
+# T tera 1099511627776
+# P peta 1125899906842624
+# E exa 1152921504606846976
+#
+# NOTE: Prefixes are case-insensitive.
+#
+# Upon successful completion, success status is returned; otherwise the number
+# -1 is produced ($var_to_set set to -1 or if $var_to_set is NULL or missing)
+# on standard output. In the case of failure, the error status will be one of:
+#
+# Status Reason
+# 1 Given $string contains no digits
+# 2 An unrecognized prefix was given
+# 3 Result too large to calculate
+#
+f_expand_number()
+{
+ local __string="$1" __var_to_set="$2"
+ local __cp __num __bshift __maxinput
+
+ # Remove any leading non-digits
+ __string="${__string#${__string%%[0-9]*}}"
+
+ # Store the numbers (no trailing suffix)
+ __num="${__string%%[!0-9]*}"
+
+ # Produce `-1' if string didn't contain any digits
+ if [ ! "$__num" ]; then
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" -1
+ else
+ echo -1
+ fi
+ return 1 # 1 = "Given $string contains no digits"
+ fi
+
+ # Remove all the leading numbers from the string to get at the prefix
+ __string="${__string#"$__num"}"
+
+ #
+ # Test for invalid prefix (and determine bitshift length)
+ #
+ case "$__string" in
+ ""|[[:space:]]*) # Shortcut
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__num
+ else
+ echo $__num
+ fi
+ return $SUCCESS ;;
+ [Kk]*) __bshift=10 ;;
+ [Mm]*) __bshift=20 ;;
+ [Gg]*) __bshift=30 ;;
+ [Tt]*) __bshift=40 ;;
+ [Pp]*) __bshift=50 ;;
+ [Ee]*) __bshift=60 ;;
+ *)
+ # Unknown prefix
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" -1
+ else
+ echo -1
+ fi
+ return 2 # 2 = "An unrecognized prefix was given"
+ esac
+
+ # Determine if the wheels fall off
+ __maxinput=$(( 0x7fffffffffffffff >> $__bshift ))
+ if [ $__num -gt $__maxinput ]; then
+ # Input (before expanding) would exceed 64-bit signed int
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" -1
+ else
+ echo -1
+ fi
+ return 3 # 3 = "Result too large to calculate"
+ fi
+
+ # Shift the number out and produce it
+ __num=$(( $__num << $__bshift ))
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__num
+ else
+ echo $__num
+ fi
+}
+
+# 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_uriencode [$text]
+#
+# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric
+# characters are converted to `%XX' sequence where XX represents the hexa-
+# decimal ordinal of the non-alphanumeric character. If $text is missing, data
+# is instead read from standard input.
+#
+f_uriencode_awk='
+BEGIN {
+ output = ""
+ for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n)
+}
+{
+ sline = ""
+ slen = length($0)
+ for (n = 1; n <= slen; n++) {
+ char = substr($0, n, 1)
+ if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char]
+ sline = sline char
+ }
+ output = output ( output ? "%0a" : "" ) sline
+}
+END { print output }
+'
+f_uriencode()
+{
+ if [ $# -gt 0 ]; then
+ echo "$1" | awk "$f_uriencode_awk"
+ else
+ awk "$f_uriencode_awk"
+ fi
+}
+
+# f_uridecode [$text]
+#
+# Decode $text from a URI. Encoded characters are converted from their `%XX'
+# sequence into original unencoded ASCII sequences. If $text is missing, data
+# is instead read from standard input.
+#
+f_uridecode_awk='
+BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) }
+{
+ sline = ""
+ slen = length($0)
+ for (n = 1; n <= slen; n++)
+ {
+ seq = substr($0, n, 3)
+ if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) {
+ hex = substr(seq, 2, 2)
+ sline = sline chr[sprintf("%u", "0x"hex)]
+ n += 2
+ } else
+ sline = sline substr(seq, 1, 1)
+ }
+ print sline
+}
+'
+f_uridecode()
+{
+ if [ $# -gt 0 ]; then
+ echo "$1" | awk "$f_uridecode_awk"
+ else
+ awk "$f_uridecode_awk"
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." strings.subr
+
+fi # ! $_STRINGS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/struct.subr b/contrib/bsddialog/bsdconfig/share/struct.subr
new file mode 100644
index 000000000000..78c785fc2b51
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/struct.subr
@@ -0,0 +1,206 @@
+if [ ! "$_STRUCT_SUBR" ]; then _STRUCT_SUBR=1
+#
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ FUNCTIONS
+
+# f_struct_define $type $member_name1 ...
+#
+# Define a new `structure' type $type made up of the properties $member_name1
+# $member_name2 and so-on. Properties are not typed and can hold any type of
+# data (including names of other structs).
+#
+# Before creating instances of a struct (using f_struct_new $type $name) you
+# should use this function to define $type.
+#
+# Both $type and member names should consist only of alpha-numeric letters or
+# the underscore.
+#
+f_struct_define()
+{
+ local type="$1"
+ [ "$type" ] || return $FAILURE
+ shift
+ setvar "_struct_typedef_$type" "$*"
+}
+
+# f_struct_new $type $name
+#
+# Create a new `structure' named $name of type $type. There are two ways to
+# access properties of a struct, but they are not equal (each method has its
+# own unique benefits, discussed below).
+#
+# The primary method of accessing (both setting and getting) properties of any
+# struct is through the f_struct() function below.
+#
+# The secondary method of accessing data is by using $name as a function.
+#
+# Both access methods are cross-platform compatible with any version of sh(1).
+# Below is an example of the primary access method:
+#
+# f_struct_new MY_STRUCT_TYPE my_struct
+# f_struct my_struct set abc 123
+# f_struct my_struct get abc # prints 123 to stdout
+# f_struct my_struct get abc abc # sets local variable $abc to 123
+#
+# Alternatively, the secondary access method (details below):
+#
+# f_struct_new MY_STRUCT_TYPE my_struct
+# my_struct set abc 123
+# my_struct get abc # prints 123 to stdout
+# my_struct get abc abc # sets local variable $abc to 123
+#
+# The secondary form should only be used if/when:
+# + You are certain that the structure already exists
+# + You want a syntax error if/when the struct does not exist
+#
+# The primary benefit to the secondary form is syntax cleanliness and read-
+# ability. If you are unsure if a given struct exists (which would cause a
+# syntax error when using this form), you can use the primary access method to
+# first test for the existence of the struct. For example:
+#
+# if f_struct my_struct; then
+# my_struct get abc # only executed if my_struct exists
+# fi
+#
+# For more information, see the f_struct() function.
+#
+f_struct_new()
+{
+ local type="$1" name="$2"
+ f_dprintf "f_struct_new: type=[%s] name=[%s]" "$type" "$name"
+ [ "$name" ] || return $FAILURE
+ setvar "_struct_type_$name" "$type" || return $FAILURE
+ # OK to use bare $name at this point
+ eval $name\(\){ f_struct $name \"\$@\"\; }
+}
+
+# f_struct $name
+# f_struct $name get $property [$var_to_set]
+# f_struct $name set $property $new_value
+# f_struct $name unset $property
+#
+# Access routine for getting, setting, unsetting, and testing properties of
+# `structures'.
+#
+# If only given $name, returns success if struct $name has been created (using
+# the f_struct_new() function above).
+#
+# For getting properties of a struct (versus setting) there are two methods of
+# access. If $var_to_set is missing or NULL, the value of the property is
+# printed to standard output for capturing in a sub-shell (which is less-
+# recommended because of performance degredation; for example, when called in a
+# loop). Returns success unless the property is unset.
+#
+# For setting properties of a struct, sets the value of $property to $new_value
+# and returns success.
+#
+# For unsetting, the underlying environment variable associated with the given
+# $property is unset.
+#
+f_struct()
+{
+ local __name="$1" __action="$2" __property="$3"
+ case $# in
+ 0) return $FAILURE ;;
+ 1) f_have "$__name" ;;
+ *) case "$__action" in
+ get) local __var_to_set="$4"
+ f_getvar "_struct_value_${__name}_$__property" "$__var_to_set"
+ ;;
+ set) local new_value="$4"
+ setvar "_struct_value_${__name}_$__property" "$new_value" ;;
+ unset) unset "_struct_value_${__name}_$__property" ;;
+ esac
+ esac
+ # Return the status of the last command above
+}
+
+# f_struct_free $name
+#
+# Unset the collection of environment variables and accessor-function
+# associated with struct $name.
+#
+f_struct_free()
+{
+ local name="$1" type member members
+ f_getvar "_struct_type_$name" type
+ f_dprintf "f_struct_free: name=[%s] type=[%s]" "$name" "$type"
+ [ "$name" ] || return $FAILURE
+ f_getvar "_struct_typedef_$type" members
+ for member in $members; do
+ f_struct "$name" unset $member
+ done
+ unset -f "$name"
+ unset "_struct_type_$name"
+}
+
+# f_struct_copy $from_name $to_name
+#
+# Copy the properties of one struct to another. If struct $to_name does not
+# exist, it is created. If struct $from_name does not exist, nothing is done
+# and struct $to_name remains unmodified.
+#
+# Returns success unless struct $to_name did not exist and f_struct_new() was
+# unable to create it.
+#
+f_struct_copy()
+{
+ local from_name="$1" to_name="$2" type
+ f_dprintf "f_struct_copy: from_name=[%s] to_name=[%s]" \
+ "$from_name" "$to_name"
+ f_getvar "_struct_type_$from_name" type
+ f_struct "$to_name" ||
+ f_struct_new "$type" "$to_name" || return $FAILURE
+ f_struct "$from_name" || return $SUCCESS
+ f_dprintf "f_struct_copy: copying properties from %s to %s" \
+ "$from_name" "$to_name"
+ local property properties from_value n=0 k=0
+ f_getvar "_struct_typedef_$type" properties
+ for property in $properties; do
+ k=$(( $k + 1 ))
+ if f_struct "$from_name" get $property from_value; then
+ f_struct "$to_name" set $property "$from_value"
+ n=$(( $n + 1 ))
+ else
+ f_struct "$to_name" unset $property
+ fi
+ done
+ f_dprintf "f_struct_copy: copied %u of %u properties from %s to %s" \
+ "$n" "$k" "$from_name" "$to_name"
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." struct.subr
+
+fi # ! $_STRUCT_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/sysrc.subr b/contrib/bsddialog/bsdconfig/share/sysrc.subr
new file mode 100644
index 000000000000..11298f00f47a
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/sysrc.subr
@@ -0,0 +1,758 @@
+if [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1
+#
+# Copyright (c) 2006-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+if [ ! "$_SYSRC_JAILED" ]; then
+ f_dprintf "%s: loading includes..." sysrc.subr
+ f_include_lang $BSDCFG_LIBE/include/messages.subr
+fi
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames (inherit values from shell if available)
+#
+: ${RC_DEFAULTS:="/etc/defaults/rc.conf"}
+
+############################################################ GLOBALS
+
+#
+# Global exit status variables
+#
+SUCCESS=0
+FAILURE=1
+
+#
+# Valid characters that can appear in an sh(1) variable name
+#
+# Please note that the character ranges A-Z and a-z should be avoided because
+# these can include accent characters (which are not valid in a variable name).
+# For example, A-Z matches any character that sorts after A but before Z,
+# including A and Z. Although ASCII order would make more sense, that is not
+# how it works.
+#
+VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
+
+############################################################ 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.local)
+#
+# 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 IFS RC_CONFS RC_DEFAULTS
+
+ . "$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().
+ #
+ if [ "${RC_CONFS+set}" ]; then
+ rc_conf_files="$RC_CONFS"
+ _rc_confs_set=1
+ fi
+
+ source_rc_confs > /dev/null 2>&1
+
+ #
+ # If the query was for `rc_conf_files' AND after calling
+ # source_rc_confs the value 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 printf "'%s\\n'" '"${'"$1"'}"' 2> /dev/null
+ )
+}
+
+# f_sysrc_service_configs [-a|-p] $name [$var_to_set]
+#
+# Get a list of optional `rc.conf.d' entries sourced by system `rc.d' script
+# $name (see rc.subr(8) for additional information on `rc.conf.d'). If $name
+# exists in `/etc/rc.d' or $local_startup directories and is an rc(8) script
+# the result is a space separated list of `rc.conf.d' entries sourced by the
+# $name `rc.d' script. Otherwise, if $name exists as a binary `rc.d' script,
+# the result is ``/etc/rc.conf.d/$name /usr/local/etc/rc.conf.d/$name''. The
+# result is NULL if $name does not exist.
+#
+# If $var_to_set is missing or NULL, output is to standard out. Returns success
+# if $name was found, failure otherwise.
+#
+# If `-a' flag is given and $var_to_set is non-NULL, append result to value of
+# $var_to_set rather than overwriting current contents.
+#
+# If `-p' flag is given and $var_to_set is non-NULL, prepend result to value of
+# $var_to_set rather than overwriting current contents.
+#
+# NB: The `-a' and `-p' option flags are mutually exclusive.
+#
+f_sysrc_service_configs()
+{
+ local OPTIND=1 OPTARG __flag __append= __prepend=
+ local __local_startup __dir __spath __stype __names=
+
+ while getopts ap __flag; do
+ case "$__flag" in
+ a) __append=1 __prepend= ;;
+ p) __prepend=1 __append= ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ [ $# -gt 0 ] || return $FAILURE
+ local __sname="$1" __var_to_set="$2"
+
+ __local_startup=$( f_sysrc_get local_startup )
+ for __dir in /etc/rc.d $__local_startup; do
+ __spath="$__dir/$__sname"
+ [ -f "$__spath" -a -x "$__spath" ] || __spath= continue
+ break
+ done
+ [ "$__spath" ] || return $FAILURE
+
+ __stype=$( file -b "$__spath" 2> /dev/null )
+ case "$__stype" in
+ *"shell script"*)
+ __names=$( exec 9<&1 1>&- 2>&-
+ last_name=
+ print_name() {
+ local name="$1"
+ case "$name" in
+ ""|.|..|*/*|"$last_name") return ;;
+ esac
+ echo "$name" >&9
+ last_name="$name"
+ }
+ eval "$( awk '{
+ gsub(/load_rc_config /, "print_name ")
+ gsub(/run_rc_command /, ": ")
+ print
+ }' "$__spath" )"
+ ) ;;
+ *)
+ __names="$__sname"
+ esac
+
+ local __name __test_path __configs=
+ for __name in $__names; do
+ for __dir in /etc/rc.d $__local_startup; do
+ __test_path="${__dir%/rc.d}/rc.conf.d/$__name"
+ [ -d "$__test_path" ] ||
+ __configs="$__configs $__test_path" continue
+ for __test_path in "$__test_path"/*; do
+ [ -f "$__test_path" ] || continue
+ __configs="$__configs $__test_path"
+ done
+ done
+ done
+ __configs="${__configs# }"
+
+ if [ "$__var_to_set" ]; then
+ local __cur=
+ [ "$__append" -o "$__prepend" ] &&
+ f_getvar "$__var_to_set" __cur
+ [ "$__append" ] && __configs="$__cur{$__cur:+ }$__configs"
+ [ "$__prepend" ] && __configs="$__configs${__cur:+ }$__cur"
+ setvar "$__var_to_set" "$__configs"
+ else
+ echo "$__configs"
+ fi
+
+ return $SUCCESS
+}
+
+# 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 printf "'%s\\n'" '"${'"$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%%[!$VALID_VARNAME_CHARS]*}"
+ local regex="^[[:space:]]*$varname="
+ local rc_conf_files="$( f_sysrc_get rc_conf_files )"
+ local conf_files=
+ local file
+
+ # Check parameters
+ case "$varname" in
+ ""|[0-9]*) return $FAILURE
+ esac
+
+ #
+ # If RC_CONFS is defined, set $rc_conf_files to an explicit
+ # value, modifying the default behavior of source_rc_confs().
+ #
+ [ "${RC_CONFS+set}" ] && 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 funcname=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+set}" ]; then
+ file="${RC_CONFS%%[$IFS]*}"
+ else
+ file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' )
+ fi
+ fi
+
+ #
+ # If not found, append new value to first file and return.
+ #
+ if [ "$not_found" ]; then
+ # Add a newline if missing before appending to the file
+ [ ! -e "$file" ] || awk 'BEGIN { wc = 0 } NR == 1 {
+ (cmd = "wc -l " FILENAME) | getline
+ close(cmd)
+ wc = $1
+ } END { exit wc != NR }' "$file" ||
+ echo >> "$file" || return $?
+ 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
+ if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm"
+ then
+ echo "$tmpfile" >&2
+ return $FAILURE
+ fi
+
+ #
+ # 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
+ f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" ||
+ mode=0644
+ f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$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
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel"
+ f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile"
+
+ #
+ # Operate on the matching file, replacing only the last occurrence.
+ #
+ # Use awk to ensure LF at end of each line, else files without ending
+ # LF will trigger a bug in `tail -r' where last two lines are joined.
+ #
+ local new_contents retval
+ new_contents=$( awk 1 "$file" 2> /dev/null | tail -r )
+ 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 ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then
+ f_err "$msg_previous_syntax_errors\n" "$pgm" "$file"
+ rm -f "$tmpfile"
+ return $FAILURE
+ fi
+
+ #
+ # Finally, move the temporary file into place.
+ #
+ f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$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 funcname=f_sysrc_delete
+ local varname="$1"
+ local file
+
+ # Check arguments
+ [ "$varname" ] || return $FAILURE
+
+ #
+ # Operate on each of the specified files
+ #
+ local tmpfile
+ for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do
+ [ -e "$file" ] || continue
+
+ #
+ # Create a new temporary file to write to.
+ #
+ if ! f_eval_catch -dk tmpfile $funcname mktemp \
+ 'mktemp -t "%s"' "$pgm"
+ then
+ echo "$tmpfile" >&2
+ return $FAILURE
+ fi
+
+ #
+ # Fixup permissions and ownership (mktemp(1) defaults to 0600
+ # permissions) to instead match the destination file.
+ #
+ local mode owner
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$file" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel"
+ f_eval_catch -d $funcname chmod \
+ 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown \
+ 'chown "%s" "%s"' "$owner" "$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 ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$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.
+ #
+ f_eval_catch -de $funcname mv \
+ 'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE
+ done
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." sysrc.subr
+
+fi # ! $_SYSRC_SUBR
diff --git a/contrib/bsddialog/bsdconfig/share/variable.subr b/contrib/bsddialog/bsdconfig/share/variable.subr
new file mode 100644
index 000000000000..c453f674ee57
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/share/variable.subr
@@ -0,0 +1,315 @@
+if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_SUBR=1
+#
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." variable.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+############################################################ GLOBALS
+
+VARIABLES=
+
+#
+# Default behavior is to call f_variable_set_defaults() when loaded.
+#
+: ${VARIABLE_SELF_INITIALIZE=1}
+
+#
+# File to write when f_dump_variables() is called.
+#
+: ${VARIABLE_DUMPFILE:=/etc/bsdconfig.vars}
+
+############################################################ FUNCTIONS
+
+# f_variable_new $handle $variable
+#
+# Register a new variable named $variable with the given reference-handle
+# $handle. The environment variable $handle is set to $variable allowing you to
+# use the f_getvar() function (from common.subr) with $handle to get the value
+# of environment variable $variable. For example:
+#
+# f_variable_new VAR_ABC abc
+#
+# allows the later indirection:
+#
+# f_getvar $VAR_ABC
+#
+# to return the value of environment variable `abc'. Variables registered in
+# this manner are recorded in the $VARIABLES environment variable for later
+# allowing dynamic enumeration of so-called `registered/advertised' variables.
+#
+f_variable_new()
+{
+ local handle="$1" variable="$2"
+ [ "$handle" ] || return $FAILURE
+ f_dprintf "variable.subr: New variable %s -> %s" "$handle" "$variable"
+ setvar $handle $variable
+ VARIABLES="$VARIABLES${VARIABLES:+ }$handle"
+}
+
+# f_variable_get_value $var [ $fmt [ $opts ... ] ]
+#
+# Unless nonInteractive is set, prompt the user with a given value (pre-filled
+# with the value of $var) and give them the chance to change the value.
+#
+# Unlike f_getvar() (from common.subr) which can return a variable to the
+# caller on standard output, this function has no [meaningful] output.
+#
+# Returns success unless $var is either NULL or missing.
+#
+f_variable_get_value()
+{
+ local var="$1" cp
+
+ [ "$var" ] || return $FAILURE
+
+ if ! { f_getvar $var cp && ! f_interactive; }; then
+ shift 1 # var
+ f_dialog_input cp "$( printf "$@" )" "$cp" && setvar $var "$cp"
+ fi
+
+ return $SUCCESS
+}
+
+# f_variable_set_defaults
+#
+# Installs sensible defaults for registered/advertised variables.
+#
+f_variable_set_defaults()
+{
+ f_dprintf "f_variable_set_defaults: Initializing defaults..."
+
+ #
+ # Initialize various user-edittable values to their defaults
+ #
+ setvar $VAR_EDITOR "${EDITOR:-/usr/bin/ee}"
+ setvar $VAR_FTP_STATE "auto"
+ setvar $VAR_FTP_USER "ftp"
+ setvar $VAR_HOSTNAME "$( hostname )"
+ setvar $VAR_MEDIA_TIMEOUT "300"
+ setvar $VAR_NFS_SECURE "NO"
+ setvar $VAR_NFS_TCP "NO"
+ setvar $VAR_NFS_V3 "YES"
+ setvar $VAR_PKG_TMPDIR "/var/tmp"
+ setvar $VAR_RELNAME "$UNAME_R"
+
+ #
+ # Debugging
+ #
+ if f_debugging; then
+ local var
+ for var in \
+ $VAR_EDITOR \
+ $VAR_FTP_STATE \
+ $VAR_FTP_USER \
+ $VAR_HOSTNAME \
+ $VAR_MEDIA_TIMEOUT \
+ $VAR_NFS_SECURE \
+ $VAR_NFS_TCP \
+ $VAR_NFS_V3 \
+ $VAR_PKG_TMPDIR \
+ $VAR_RELNAME \
+ ; do
+ f_quietly f_getvar $var
+ done
+ fi
+
+ f_dprintf "f_variable_set_defaults: Defaults initialized."
+}
+
+# f_dump_variables
+#
+# Dump a list of registered/advertised variables and their respective values to
+# $VARIABLE_DUMPFILE. Returns success unless the file couldn't be written. If
+# an error occurs, it is displayed using f_dialog_msgbox() (from dialog.subr).
+#
+f_dump_variables()
+{
+ local err
+ if ! err=$(
+ ( for handle in $VARIABLES; do
+ f_getvar $handle var || continue
+ f_getvar $var value || continue
+ f_shell_escape "$value" value
+ printf "%s='%s'\n" "$var" "$value"
+ done > "$VARIABLE_DUMPFILE" ) 2>&1
+ ); then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+}
+
+# f_debugging
+#
+# Are we in debug mode? Returns success if extra DEBUG information has been
+# requested (by setting $debug to non-NULL), otherwise false.
+#
+f_debugging()
+{
+ local value
+ f_getvar $VAR_DEBUG value && [ "$value" ]
+}
+
+# f_interactive
+#
+# Are we running interactively? Return error if $nonInteractive is set and non-
+# NULL, otherwise return success.
+#
+f_interactive()
+{
+ local value
+ ! f_getvar $VAR_NONINTERACTIVE value || [ ! "$value" ]
+}
+
+# f_netinteractive
+#
+# Has the user specifically requested the network-portion of configuration and
+# setup to be performed interactively? Returns success if the user has asked
+# for the network configuration to be done interactively even if perhaps over-
+# all non-interactive mode has been requested (by setting nonInteractive).
+#
+# Returns success if $netInteractive is set and non-NULL.
+#
+f_netinteractive()
+{
+ local value
+ f_getvar $VAR_NETINTERACTIVE value && [ "$value" ]
+}
+
+# f_zfsinteractive
+#
+# Has the user specifically requested the ZFS-portion of configuration and
+# setup to be performed interactively? Returns success if the user has asked
+# for the ZFS configuration to be done interactively even if perhaps overall
+# non-interactive mode has been requested (by setting nonInteractive).
+#
+# Returns success if $zfsInteractive is set and non-NULL.
+#
+f_zfsinteractive()
+{
+ local value
+ f_getvar $VAR_ZFSINTERACTIVE value && [ "$value" ]
+}
+
+############################################################ MAIN
+
+#
+# Variables that can be tweaked from config files
+#
+# Handle Variable Name
+f_variable_new VAR_CONFIG_FILE configFile
+f_variable_new VAR_DEBUG debug
+f_variable_new VAR_DEBUG_FILE debugFile
+f_variable_new VAR_DIRECTORY_PATH _directoryPath
+f_variable_new VAR_DOMAINNAME domainname
+f_variable_new VAR_EDITOR editor
+f_variable_new VAR_EXTRAS ifconfig_
+f_variable_new VAR_FTP_DIR ftpDirectory
+f_variable_new VAR_FTP_HOST ftpHost
+f_variable_new VAR_FTP_PASS ftpPass
+f_variable_new VAR_FTP_PATH _ftpPath
+f_variable_new VAR_FTP_PORT ftpPort
+f_variable_new VAR_FTP_STATE ftpState
+f_variable_new VAR_FTP_USER ftpUser
+f_variable_new VAR_GATEWAY defaultrouter
+f_variable_new VAR_GROUP group
+f_variable_new VAR_GROUP_GID groupGid
+f_variable_new VAR_GROUP_MEMBERS groupMembers
+f_variable_new VAR_GROUP_PASSWORD groupPassword
+f_variable_new VAR_HOSTNAME hostname
+f_variable_new VAR_HTTP_DIR httpDirectory
+f_variable_new VAR_HTTP_FTP_MODE httpFtpMode
+f_variable_new VAR_HTTP_HOST httpHost
+f_variable_new VAR_HTTP_PATH _httpPath
+f_variable_new VAR_HTTP_PORT httpPort
+f_variable_new VAR_HTTP_PROXY httpProxy
+f_variable_new VAR_HTTP_PROXY_HOST httpProxyHost
+f_variable_new VAR_HTTP_PROXY_PATH _httpProxyPath
+f_variable_new VAR_HTTP_PROXY_PORT httpProxyPort
+f_variable_new VAR_IFCONFIG ifconfig_
+f_variable_new VAR_IPADDR ipaddr
+f_variable_new VAR_IPV6ADDR ipv6addr
+f_variable_new VAR_IPV6_ENABLE ipv6_activate_all_interfaces
+f_variable_new VAR_KEYMAP keymap
+f_variable_new VAR_MEDIA_TIMEOUT MEDIA_TIMEOUT
+f_variable_new VAR_MEDIA_TYPE mediaType
+f_variable_new VAR_NAMESERVER nameserver
+f_variable_new VAR_NETINTERACTIVE netInteractive
+f_variable_new VAR_NETMASK netmask
+f_variable_new VAR_NETWORK_DEVICE netDev
+f_variable_new VAR_NFS_HOST nfsHost
+f_variable_new VAR_NFS_PATH nfsPath
+f_variable_new VAR_NFS_SECURE nfs_reserved_port_only
+f_variable_new VAR_NFS_TCP nfs_use_tcp
+f_variable_new VAR_NFS_V3 nfs_use_v3
+f_variable_new VAR_NONINTERACTIVE nonInteractive
+f_variable_new VAR_NO_CONFIRM noConfirm
+f_variable_new VAR_NO_ERROR noError
+f_variable_new VAR_NO_INET6 noInet6
+f_variable_new VAR_PACKAGE package
+f_variable_new VAR_PKG_TMPDIR PKG_TMPDIR
+f_variable_new VAR_PORTS_PATH ports
+f_variable_new VAR_RELNAME releaseName
+f_variable_new VAR_SLOW_ETHER slowEthernetCard
+f_variable_new VAR_TRY_DHCP tryDHCP
+f_variable_new VAR_TRY_RTSOL tryRTSOL
+f_variable_new VAR_UFS_PATH ufs
+f_variable_new VAR_USER user
+f_variable_new VAR_USER_ACCOUNT_EXPIRE userAccountExpire
+f_variable_new VAR_USER_DOTFILES_CREATE userDotfilesCreate
+f_variable_new VAR_USER_GECOS userGecos
+f_variable_new VAR_USER_GID userGid
+f_variable_new VAR_USER_GROUPS userGroups
+f_variable_new VAR_USER_GROUP_DELETE userGroupDelete
+f_variable_new VAR_USER_HOME userHome
+f_variable_new VAR_USER_HOME_CREATE userHomeCreate
+f_variable_new VAR_USER_HOME_DELETE userHomeDelete
+f_variable_new VAR_USER_LOGIN_CLASS userLoginClass
+f_variable_new VAR_USER_PASSWORD userPassword
+f_variable_new VAR_USER_PASSWORD_EXPIRE userPasswordExpire
+f_variable_new VAR_USER_SHELL userShell
+f_variable_new VAR_USER_UID userUid
+f_variable_new VAR_ZFSINTERACTIVE zfsInteractive
+
+#
+# Self-initialize unless requested otherwise
+#
+f_dprintf "%s: VARIABLE_SELF_INITIALIZE=[%s]" \
+ variable.subr "$VARIABLE_SELF_INITIALIZE"
+case "$VARIABLE_SELF_INITIALIZE" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_variable_set_defaults
+esac
+
+f_dprintf "%s: Successfully loaded." variable.subr
+
+fi # ! $_VARIABLE_SUBR
diff --git a/contrib/bsddialog/bsdconfig/startup/INDEX b/contrib/bsddialog/bsdconfig/startup/INDEX
new file mode 100644
index 000000000000..afad3483313a
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/INDEX
@@ -0,0 +1,62 @@
+# 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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/startup/Makefile b/contrib/bsddialog/bsdconfig/startup/Makefile
new file mode 100644
index 000000000000..62a9e7141efc
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/140.startup
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= misc rcadd rcconf rcdelete rcedit rcvar startup
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/startup/Makefile.depend b/contrib/bsddialog/bsdconfig/startup/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/startup/USAGE b/contrib/bsddialog/bsdconfig/startup/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/startup/include/Makefile b/contrib/bsddialog/bsdconfig/startup/include/Makefile
new file mode 100644
index 000000000000..aab9842035cc
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/140.startup/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/startup/include/Makefile.depend b/contrib/bsddialog/bsdconfig/startup/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/startup/include/messages.subr b/contrib/bsddialog/bsdconfig/startup/include/messages.subr
new file mode 100644
index 000000000000..66b8bf6c731d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/include/messages.subr
@@ -0,0 +1,108 @@
+# Copyright (c) 2012-2013 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$
+
+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_delete_the_following="Are you sure you want to delete the following directives\nfrom the rc.conf(5) collection of system configuration files?"
+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_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_this_menu="Exit this menu"
+msg_info="Info"
+msg_lpd="lpd"
+msg_lpd_desc="This host has a printer and wants to run lpd."
+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_miscellaneous_startup_services="Miscellaneous Startup Services"
+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_show_configured="Show Configured"
+msg_show_configured_desc="Calculate rc.conf(5) locations (slowest)"
+msg_show_default_value="Show Default/Value"
+msg_show_default_value_desc="Show default/configured values (slow)"
+msg_show_value="Show Value"
+msg_show_value_desc="Show configured startup value (fast)"
+msg_startup="Startup"
+msg_startup_dirs="Startup dirs"
+msg_startup_dirs_desc="Set the list of dirs to look for startup scripts"
+msg_toggle_startup_services="Toggle Startup Services"
+msg_unknown_startup_menu_selection="Unknown startup menu selection"
+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 --git a/contrib/bsddialog/bsdconfig/startup/misc b/contrib/bsddialog/bsdconfig/startup/misc
new file mode 100755
index 000000000000..24638bfe7e2c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/misc
@@ -0,0 +1,369 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt="$msg_miscellaneous_menu_text"
+ local menu_list="
+ 'X $msg_exit' '$msg_exit_this_menu'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ # List of variables we'll need from rc.conf(5)
+ local var_list="
+ accounting_enable
+ local_startup
+ lpd_enable
+ named_enable
+ named_flags
+ nis_client_enable
+ nis_server_enable
+ nisdomainname
+ startup_dirs
+ " # END-QUOTE
+
+ # Add i386-specific variables if appropriate
+ if [ "$UNAME_P" = "i386" ]; then
+ var_list="$var_list
+ apm_enable
+ " # END-QUOTE
+ fi
+
+ # Obtain default-item (adjusted below for dynamic tags)
+ f_dialog_default_fetch defaultitem
+ local ditem="${defaultitem%%[$IFS]*}"
+
+ eval "$(
+ . "$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
+ :| awk \
+ -v uname_p="$UNAME_P" \
+ -v menu_tags="$DIALOG_MENU_TAGS" \
+ -v menu_fmt="'%s' '%s'\n" \
+ -v mtag_fmt="%c [%c] %s" \
+ -v separator="' ' ' -- '\n" \
+ -v ditem="$ditem" \
+ '
+ function mprint(tag,item)
+ {
+ printf menu_fmt, tag, item
+ }
+ END {
+ i = 1
+ defaultitem = ""
+
+ printf "menu_list=\"$menu_list\n"
+
+ if ( uname_p == "i386" )
+ {
+ #
+ # APM: Auto-power management services
+ # (typically laptops)
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( ENVIRON["apm_enable"] ~ \
+ /^[Yy][Ee][Ss]$/ ? "X" : " " )
+ subtag = ENVIRON["msg_apm"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_apm_desc"])
+ if (ditem == char) defaultitem = tag
+ }
+
+ printf separator
+
+ #
+ # Startup dirs: Set the list of dirs to look for
+ # startup scripts
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( length(ENVIRON["local_startup"]) > 0 \
+ ? "X" : " " )
+ subtag = ENVIRON["msg_startup_dirs"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_startup_dirs_desc"])
+ if (ditem == char) defaultitem = tag
+
+ #
+ # named: Run a local name server on this host
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( ENVIRON["named_enable"] ~ \
+ /^[Yy][Ee][Ss]$/ ? "X" : " " )
+ subtag = ENVIRON["msg_named"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_named_desc"])
+ if (ditem == char) defaultitem = tag
+
+ #
+ # named flags: Set default flags to named (if enabled)
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( length(ENVIRON["named_flags"]) > 0 \
+ ? "X" : " " )
+ subtag = ENVIRON["msg_named_flags"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_named_flags_desc"])
+ if (ditem == char) defaultitem = tag
+
+ #
+ # NIS client: This host wishes to be an NIS client.
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( ENVIRON["nis_client_enable"] ~ \
+ /^[Yy][Ee][Ss]$/ ? "X" : " " )
+ subtag = ENVIRON["msg_nis_client"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_nis_client_desc"])
+ if (ditem == char) defaultitem = tag
+
+ #
+ # NIS domainname: Set NIS domainname (if enabled)
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( length(ENVIRON["nisdomainname"]) > 0 && \
+ ENVIRON["nisdomainname"] != "NO" \
+ ? "X" : " " )
+ subtag = ENVIRON["msg_nis_domainname"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_nis_domainname_desc"])
+ if (ditem == char) defaultitem = tag
+
+ #
+ # NIS server: This host wishes to be an NIS server.
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( ENVIRON["nis_server_enable"] ~ \
+ /^[Yy][Ee][Ss]$/ ? "X" : " " )
+ subtag = ENVIRON["msg_nis_server"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_nis_server_desc"])
+ if (ditem == char) defaultitem = tag
+
+ printf separator
+
+ #
+ # Accounting: This host wishes to run process
+ # accounting.
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( ENVIRON["accounting_enable"] ~ \
+ /^[Yy][Ee][Ss]$/ ? "X" : " " )
+ subtag = ENVIRON["msg_accounting"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_accounting_desc"])
+ if (ditem == char) defaultitem = tag
+
+ #
+ # lpd: This host has a printer and wants to run lpd.
+ #
+ char = substr(menu_tags, i++, 1)
+ mark = ( ENVIRON["lpd_enable"] ~ \
+ /^[Yy][Ee][Ss]$/ ? "X" : " " )
+ subtag = ENVIRON["msg_lpd"]
+ tag = sprintf(mtag_fmt, char, mark, subtag)
+ mprint(tag, ENVIRON["msg_lpd_desc"])
+ if (ditem == char) defaultitem = tag
+
+ printf "\"\n"
+
+ if ( defaultitem )
+ printf "defaultitem=\"%s\"\n", defaultitem
+ }'
+ )"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+# 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 prompt="$1" _input="$2"
+
+ f_dialog_title "$msg_value_required"
+ f_dialog_input _input "$prompt" "$_input" "$hline_alnum_tab_enter"
+ local retval=$?
+ f_dialog_title_restore
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $retval
+
+ value="$_input"
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 || f_die
+ f_dialog_menutag_fetch mtag
+
+ case "$mtag" in
+ "X $msg_exit") break ;;
+ ?" [X] "*) toggled=1 reverse=NO ;;
+ *) toggled= reverse=YES
+ esac
+
+ case "$mtag" in
+ # Simple On/Off toggle bits
+ ?" ["?"] $msg_apm")
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set apm_enable "%s"' "$reverse" ;;
+ ?" ["?"] $msg_named")
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set named_enable "%s"' "$reverse" ;;
+ ?" ["?"] $msg_accounting")
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set accounting_enable "%s"' "$reverse" ;;
+ ?" ["?"] $msg_lpd")
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set lpd_enable "%s"' "$reverse" ;;
+ # Multi-variable On/Off toggle bits
+ ?" ["?"] $msg_nis_client")
+ if f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set nis_client_enable "%s"' "$reverse"
+ then
+ [ "$reverse" = "NO" ] || f_eval_catch -dk err "$0" \
+ f_sysrc_set 'f_sysrc_set rpcbind_enable YES'
+ fi ;;
+ ?" ["?"] $msg_nis_server")
+ if f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set nis_server_enable "%s"' "$reverse"
+ then
+ [ "$reverse" = "NO" ] || f_eval_catch -dk err "$0" \
+ f_sysrc_set 'f_sysrc_set rpcbind_enable YES'
+ fi ;;
+ # Checkboxes for non-boolean options
+ ?" ["?"] $msg_nis_domainname")
+ dialog_input_value "$msg_nis_domainname_desc" \
+ "$( f_sysrc_get nisdomainname )" || continue
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set nisdomainname "%s"' "$value" ;;
+ ?" ["?"] $msg_startup_dirs")
+ dialog_input_value "$msg_startup_dirs_desc" \
+ "$( f_sysrc_get local_startup )" || continue
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set local_startup "%s"' "$value" ;;
+ ?" ["?"] $msg_named_flags")
+ dialog_input_value "$msg_named_flags_desc" \
+ "$( f_sysrc_get named_flags )" || continue
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set named_flags "%s"' "$value" ;;
+ esac
+
+ [ $? -eq $DIALOG_OK ] || f_dialog_msgbox "$err\n"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/startup/rcadd b/contrib/bsddialog/bsdconfig/startup/rcadd
new file mode 100755
index 000000000000..7b536c2be9c5
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/rcadd
@@ -0,0 +1,149 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/startup/rcconf.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+[ "${SHOW_DESC+set}" ] || SHOW_DESC=1
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local menu_list="
+ '1' '$msg_add_from_list'
+ '2' '$msg_add_custom'
+ " # END-QUOTE
+ local hline="$hline_arrows_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 || f_die
+ f_dialog_menutag_fetch mtag
+
+ case "$mtag" in
+ 1) # Add From List
+ # Loop to allow adding multiple variables quickly
+ defaultitem=
+ while :; do
+ f_dialog_input_rclist "$defaultitem" || f_die
+ f_dialog_menutag_fetch mtag
+ defaultitem="$mtag"
+
+ [ "$mtag" = "X $msg_exit" ] && break
+
+ # Anything else is a directive
+
+ $BSDCFG_LIBE/$APP_DIR/rcedit ${USE_XDIALOG:+-X} \
+ "${mtag# }"
+ done
+ ;;
+ 2) # Add Custom
+ f_dialog_input_rcvar || continue
+ $BSDCFG_LIBE/$APP_DIR/rcedit ${USE_XDIALOG:+-X} "$rcvar"
+ ;;
+ esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/startup/rcconf b/contrib/bsddialog/bsdconfig/startup/rcconf
new file mode 100755
index 000000000000..6a6247b818e4
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/rcconf
@@ -0,0 +1,264 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+f_include $BSDCFG_SHARE/startup/rcconf.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ GLOBALS
+
+#
+# Global map/menu-list for the main menu
+#
+RCCONF_MAP=
+_RCCONF_MAP=
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+[ "${SHOW_DESC+set}" ] || 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 prompt=
+ local menu_list="
+ 'X $msg_exit' '$msg_exit_desc'
+ ${SHOW_DESC:+'$msg_exit_this_menu'}
+ '> $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
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ if [ ! "$_RCCONF_MAP" ]; then
+ # Genreate RCCONF_MAP of `var desc ...' per-line
+ f_dialog_info "$msg_creating_rcconf_map"
+ f_startup_rcconf_map RCCONF_MAP
+ export RCCONF_MAP
+ # Generate _${var}_desc variables from $RCCONF_MAP
+ f_startup_rcconf_map_expand RCCONF_MAP
+ 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"
+
+ menu_list="$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 # set noglob because descriptions in the $menu_list may contain
+ # `*' and get expanded by dialog(1) (doesn't affect Xdialog(1)).
+ # This prevents dialog(1) from expanding wildcards in help line.
+
+ local height width rows
+ eval f_dialog_menu${SHOW_DESC:+_with_help}_size \
+ height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --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} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_view_edit_startup_configuration"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+
+ if [ "$USE_XDIALOG" ]; then
+ case "$mtag" in
+ "> $msg_view_details")
+ f_dialog_input_view_details
+ continue
+ esac
+ elif [ $retval -eq $DIALOG_HELP ]; then
+ # The ``Help'' button (labeled "Details") was pressed
+ f_dialog_input_view_details
+ continue
+ fi
+
+ [ $retval -eq $DIALOG_OK ] || 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 --git a/contrib/bsddialog/bsdconfig/startup/rcdelete b/contrib/bsddialog/bsdconfig/startup/rcdelete
new file mode 100755
index 000000000000..ccc15ba3380f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/rcdelete
@@ -0,0 +1,414 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+f_include $BSDCFG_SHARE/startup/rcconf.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ GLOBALS
+
+#
+# Global map/menu-list for the main menu
+#
+RCCONF_MAP=
+RCCONF_MENU_LIST=
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+[ "${SHOW_DESC+set}" ] || 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_create_main
+#
+# Create the dialog(1) main menu. Separated from dialog_menu_main (used to
+# display the menu) to speed up execution (we only call this function when
+# initializing or changing the view details).
+#
+dialog_create_main()
+{
+ # 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=$(
+ . "$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"
+ }'
+ )
+}
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local 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
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ #
+ # [Re-]Accent the menu list before incorporating it
+ #
+ local rcconf_var details help menu_buf delete
+ eval set -- $RCCONF_MENU_LIST
+ while [ $# -gt 0 ]; do
+ rcconf_var="$1" details="$2" delete=
+ f_shell_escape "$details" details
+ if [ "$SHOW_DESC" ]; then
+ help="$3"
+ f_shell_escape "$help" help
+ shift 3 # rcconf_var/details/help
+ else
+ shift 2 # rcconf_var/details
+ fi
+
+ # Update mark
+ f_getvar _${rcconf_var# }_delete delete
+ if [ "$delete" ]; then
+ details="[X]${details#???}"
+ else
+ details="[ ]${details#???}"
+ fi
+
+ # Update buffer with modified elements
+ menu_buf="$menu_buf
+ '$rcconf_var' '$details' ${SHOW_DESC:+'$help'}" # End-Quote
+ done
+ menu_list="$menu_list $menu_buf"
+
+ set -f # set noglob because descriptions in the $menu_list may contain
+ # `*' and get expanded by dialog(1) (doesn't affect Xdialog(1)).
+ # This prevents dialog(1) from expanding wildcards in help line.
+
+ local height width rows
+ eval f_dialog_menu${SHOW_DESC:+_with_help}_size \
+ height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --keep-tite \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_details\" \
+ ${SHOW_DESC:+--item-help} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+# dialog_menu_confirm_delete $var1 [$var2 ...]
+#
+# Get the user's blessing to delete one or more variables. Returns success if
+# (and only-if) the user confirms (does not press ESC or Cancel/NO). Does NOT
+# return the user's menu-choice.
+#
+dialog_menu_confirm_delete()
+{
+ local prompt="$msg_are_you_sure_you_want_delete_the_following"
+ local menu_list # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ [ $# -ge 1 ] || return $DIALOG_CANCEL
+
+ # If asked to delete only one variable, simply ask and return
+ if [ $# -eq 1 ]; then
+ f_noyes "$msg_are_you_sure_you_want_to_delete" "$1"
+ return $?
+ fi
+ # Not reached unless requested to delete multiple variables
+
+ # Generate a menu to cleanly display the variables to be deleted
+ local var_list
+ 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
+ }'
+ )
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local defaultno="defaultno"
+ [ "$USE_XDIALOG" ] && defaultno="default-no"
+
+ eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --$defaultno \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2> /dev/null
+
+ # Menu choice ignored; status of above command returned
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_delete_startup_directives"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+# Genreate $RCCONF_MAP of `var desc ...' per-line (see share/rcconf.subr)
+f_dialog_info "$msg_creating_rcconf_map"
+f_startup_rcconf_map RCCONF_MAP
+
+# Generate _${var}_desc variables from $RCCONF_MAP
+f_startup_rcconf_map_expand RCCONF_MAP
+
+# Generate RCCONF_MENU_LIST from $RCCONF_MAP
+dialog_create_main
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+
+ if [ "$USE_XDIALOG" ]; then
+ case "$mtag" in "> $msg_view_details")
+ f_dialog_input_view_details && dialog_create_main
+ continue
+ esac
+ elif [ $retval -eq $DIALOG_HELP ]; then
+ # The ``Help'' button (labeled "Details") was pressed
+ f_dialog_input_view_details && dialog_create_main
+ continue
+ fi
+
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ case "$mtag" in
+ "X $msg_exit_cancel") break ;;
+ "> $msg_delete_selected")
+ delete_vars=
+ for var in $( f_startup_rcconf_list ); do
+ f_getvar _${var}_delete _delete
+ [ "$_delete" ] || continue
+ delete_vars="$delete_vars $var"
+ done
+ if dialog_menu_confirm_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
+ f_eval_catch "$0" f_sysrc_delete \
+ 'f_sysrc_delete "%s"' "$var" || break
+ done
+ dialog_create_main
+ fi
+ ;;
+ "> $msg_all")
+ for var in $( f_startup_rcconf_list ); do
+ setvar _${var}_delete 1
+ export _${var}_delete
+ done
+ ;;
+ "> $msg_none")
+ var_list=$( set | awk -F= "
+ /$STARTUP_RCCONF_REGEX/ {
+ if (\$1 ~ /^_[[:alpha:]_][[:alnum:]_]*_delete/)
+ print \$1
+ }"
+ )
+ [ "$var_list" ] && unset $var_list
+ ;;
+ *) # Anything else is a variable to edit
+ var="${mtag# }"
+
+ # Toggle the state-variable and loop back to menu
+ if f_isset _${var}_delete; then
+ unset _${var}_delete
+ else
+ setvar _${var}_delete 1
+ export _${var}_delete
+ fi
+ esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/startup/rcedit b/contrib/bsddialog/bsdconfig/startup/rcedit
new file mode 100755
index 000000000000..54061b54e0ad
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/rcedit
@@ -0,0 +1,72 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/startup/rcedit.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Edit the rc.conf(5) variable(s) passed as argument(s)
+#
+f_dialog_rcedit "$@"
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/startup/rcvar b/contrib/bsddialog/bsdconfig/startup/rcvar
new file mode 100755
index 000000000000..ddca9066e6e3
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/rcvar
@@ -0,0 +1,220 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+f_include $BSDCFG_SHARE/startup/rcvar.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ GLOBALS
+
+#
+# Global map/menu-list for the main menu
+#
+RCVAR_MAP=
+_RCVAR_MAP=
+
+#
+# Options
+#
+# Inherit SHOW_DESC value if set, otherwise default to 1
+[ "${SHOW_DESC+set}" ] || SHOW_DESC=1
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local menu_list="
+ 'X $msg_exit' '$msg_exit_this_menu'
+ ${SHOW_DESC:+'$msg_exit_this_menu'}
+ " # END-QUOTE
+ local hline="$hline_arrows_tab_enter"
+ local defaultitem= # Calculated below
+
+ if [ ! "$_RCVAR_MAP" ]; then
+ # Generate 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
+
+ menu_list="$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 # set noglob because descriptions in the $menu_list may
+ # contain `*' and get expanded by dialog(1). This prevents
+ # dialog(1) from expanding wildcards in the help line.
+
+ local height width rows
+ eval f_dialog_menu${SHOW_DESC:+_with_help}_size \
+ height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --keep-tite \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ ${SHOW_DESC:+--item-help} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+
+ if [ $retval -eq $DIALOG_OK ]; then
+ local item
+ item=$( eval f_dialog_menutag2item${SHOW_DESC:+_with_help} \
+ \"\$menu_choice\" $menu_list )
+ f_dialog_menuitem_store "$item"
+ fi
+
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_toggle_startup_services"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main || f_die
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && break
+
+ # Anything else is an rcvar to toggle
+
+ rcvar="${mtag# }"
+ f_dialog_menuitem_fetch value
+
+ # Determine the new [toggled] value to use
+ case "$value" in
+ "[X]"*) value="NO" ;;
+ *) value="YES"
+ esac
+
+ f_eval_catch "$0" f_sysrc_set 'f_sysrc_set "%s" "%s"' "$rcvar" "$value"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/startup/share/Makefile b/contrib/bsddialog/bsdconfig/startup/share/Makefile
new file mode 100644
index 000000000000..134914cb0880
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/share/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/startup
+FILES= rcconf.subr rcedit.subr rcvar.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/startup/share/Makefile.depend b/contrib/bsddialog/bsdconfig/startup/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/startup/share/rcconf.subr b/contrib/bsddialog/bsdconfig/startup/share/rcconf.subr
new file mode 100644
index 000000000000..80b6504994cc
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/share/rcconf.subr
@@ -0,0 +1,500 @@
+if [ ! "$_STARTUP_RCCONF_SUBR" ]; then _STARTUP_RCCONF_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." startup/rcconf.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" 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 [$var_to_set]
+#
+# 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
+#
+# If $var_to_set is missing or NULL, the map is printed to standard output for
+# capturing in a sub-shell (which is less-recommended because of performance
+# degredation; for example, when called in a loop).
+#
+f_startup_rcconf_map()
+{
+ local __funcname=f_startup_rcconf_map
+ local __var_to_set="$1"
+
+ # If the in-memory cached value is available, return it immediately
+ if [ "$_STARTUP_RCCONF_MAP" ]; then
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$STARTUP_RCCONF_MAP"
+ else
+ echo "$STARTUP_RCCONF_MAP"
+ fi
+ return $SUCCESS
+ fi
+
+ #
+ # Create the in-memory cache (potentially from validated on-disk cache)
+ #
+
+ #
+ # Calculate digest used to determine if the on-disk global persistent
+ # cache file (containing 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=$( exec 2> /dev/null; md5 < "$RC_DEFAULTS" )
+
+ #
+ # Check to see if the global persistent cache file exists
+ #
+ if [ -f "$STARTUP_RCCONF_MAP_CACHEFILE" ]; then
+ #
+ # Attempt to populate the in-memory cache with the (soon to 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 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"
+ )
+ local __retval=$?
+ export STARTUP_RCCONF_MAP # Make children faster (export cache)
+ if [ $__retval -eq $SUCCESS ]; then
+ export _STARTUP_RCCONF_MAP=1
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$STARTUP_RCCONF_MAP"
+ else
+ echo "$STARTUP_RCCONF_MAP"
+ fi
+ 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 persistent
+ # 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
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$STARTUP_RCCONF_MAP"
+ else
+ echo "$STARTUP_RCCONF_MAP"
+ fi
+
+ #
+ # Attempt to create the persistent global cache
+ #
+
+ # Create a new temporary file to write to
+ local __tmpfile
+ f_eval_catch -dk __tmpfile $__funcname mktemp \
+ 'mktemp -t "%s"' "$pgm" || 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_eval_catch -d $__funcname mkdir \
+ 'mkdir -p "%s"' "${STARTUP_RCCONF_MAP_CACHEFILE%/*}"
+ esac
+ f_eval_catch -d $__funcname mv \
+ 'mv "%s" "%s"' "$__tmpfile" "$STARTUP_RCCONF_MAP_CACHEFILE"
+}
+
+# f_startup_rcconf_map_expand $var_to_get
+#
+# Expands the map ($var_to_get) 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()
+{
+ local var_to_get="$1"
+ eval "$( debug= f_getvar "$var_to_get" | 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_DEFAULT_VALUE 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. Returns
+# success unless the user chose `Cancel' or pressed Escape.
+#
+f_dialog_input_view_details()
+{
+ local prompt=
+ local menu_list # calculated below
+ local defaultitem= # calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ # Calculate marks for checkboxes and radio buttons
+ local md=" "
+ if [ "$SHOW_DESC" ]; then
+ md="X"
+ fi
+ local m1=" " m2=" " m3=" "
+ if [ "$SHOW_VALUE" ]; then
+ m1="*"
+ defaultitem="1 ($m1) $msg_show_value"
+ elif [ "$SHOW_DEFAULT_VALUE" ]; then
+ m2="*"
+ defaultitem="2 ($m2) $msg_show_default_value"
+ elif [ "$SHOW_CONFIGURED" ]; then
+ m3="*"
+ defaultitem="3 ($m3) $msg_show_configured"
+ fi
+
+ # Create the menu list with the above-calculated marks
+ menu_list="
+ '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
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ f_dialog_title "$msg_choose_view_details"
+
+ local mtag
+ mtag=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize mtag
+
+ f_dialog_title_restore
+
+ [ $retval -eq $DIALOG_OK ] || return $DIALOG_CANCEL
+
+ 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 [$default]
+#
+# 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_fetch() should be used to get the user's
+# response). Optionally if present and non-null, highlight $default rcvar.
+#
+f_dialog_input_rclist()
+{
+ local prompt="$msg_please_select_an_rcconf_directive"
+ local menu_list="
+ 'X $msg_exit' '' ${SHOW_DESC:+'$msg_exit_this_menu'}
+ " # END-QUOTE
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ 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 # set noglob because descriptions in the $menu_list may contain
+ # `*' and get expanded by dialog(1) (doesn't affect Xdialog(1)).
+ # This prevents dialog(1) from expanding wildcards in help line.
+
+ local height width rows
+ eval f_dialog_menu${SHOW_DESC:+_with_help}_size \
+ height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --default-item \"\$defaultitem\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ ${SHOW_DESC:+--item-help} \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+# 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()
+{
+ #
+ # Loop until the user provides taint-free/valid input
+ #
+ local _input="$1"
+ while :; do
+
+ # Return if user either pressed ESC or chosen Cancel/No
+ f_dialog_input _input "$msg_please_enter_rcvar_name" \
+ "$_input" "$hline_alnum_tab_enter" || return $?
+
+ # 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->[%s]" "$rcvar"
+
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." startup/rcconf.subr
+
+fi # ! $_STARTUP_RCCONF_SUBR
diff --git a/contrib/bsddialog/bsdconfig/startup/share/rcedit.subr b/contrib/bsddialog/bsdconfig/startup/share/rcedit.subr
new file mode 100644
index 000000000000..1adca477ebf4
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/share/rcedit.subr
@@ -0,0 +1,90 @@
+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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." startup/rcedit.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" 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 funcname=f_dialog_rcedit
+ local msg var="$1" _input
+
+ f_sprintf msg "$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
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input _input "$msg" "$_input" \
+ "$hline_alnum_punc_tab_enter" || return $?
+
+ # Return if the value has not changed from current
+ local cur_val="$( f_sysrc_get "$var" )"
+ [ "$_input" = "$cur_val" ] && return $DIALOG_OK
+
+ f_dprintf "%s: [%s]->[%s]" "$var" "$cur_val" "$_input"
+
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set "%s" "%s"' "$var" "$_input"
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." startup/rcedit.subr
+
+fi # ! $_STARTUP_RCEDIT_SUBR
diff --git a/contrib/bsddialog/bsdconfig/startup/share/rcvar.subr b/contrib/bsddialog/bsdconfig/startup/share/rcvar.subr
new file mode 100644
index 000000000000..c1a6ff2443e2
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/share/rcvar.subr
@@ -0,0 +1,236 @@
+if [ ! "$_STARTUP_RCVAR_SUBR" ]; then _STARTUP_RCVAR_SUBR=1
+#
+# Copyright (c) 2006-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." startup/rcvar.subr
+f_include $BSDCFG_SHARE/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 [$var_to_set]
+#
+# 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
+#
+# If $var_to_set is missing or NULL, the map is printed to standard output for
+# capturing in a sub-shell (which is less-recommended because of performance
+# degredation; for example, when called in a loop).
+#
+f_startup_rcvar_map()
+{
+ local __funcname=f_startup_rcvar_map
+ local __var_to_set="$1"
+
+ # If the in-memory cached value is available, return it immediately
+ if [ "$_STARTUP_RCVAR_MAP" ]; then
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$STARTUP_RCVAR_MAP"
+ else
+ echo "$STARTUP_RCVAR_MAP"
+ fi
+ 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 $__file"
+ done
+ # ... and /usr/local/etc/rc.d scripts
+ __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
+ )"
+ __rc_script_list="${__rc_script_list# }" # Trim leading space
+
+ #
+ # 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 persistent 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" 2> /dev/null &&
+ cksum "$RC_DEFAULTS" $__rc_script_list 2> /dev/null | md5 )
+
+ #
+ # Check to see if the global persistent cache file exists
+ #
+ if [ -f "$STARTUP_RCVAR_MAP_CACHEFILE" ]; then
+ #
+ # Attempt to populate the in-memory cache with the (soon to be)
+ # validated on-disk cache. If validation fails, fall-back to
+ # the current value and return error.
+ #
+ STARTUP_RCVAR_MAP=$(
+ ( # Get digest as first word on 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 return success.
+ #
+ 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"
+ )
+ local __retval=$?
+ export STARTUP_RCVAR_MAP # Make children faster (export cache)
+ if [ $__retval -eq $SUCCESS ]; then
+ export _STARTUP_RCVAR_MAP=1
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$STARTUP_RCVAR_MAP"
+ else
+ echo "$STARTUP_RCVAR_MAP"
+ fi
+ 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 persistent
+ # cache file to speed up future executions).
+ #
+
+ STARTUP_RCVAR_MAP=$(
+ for script in $__rc_script_list; do
+ rcvar_list=$( $script rcvar 2> /dev/null | 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
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$STARTUP_RCVAR_MAP"
+ else
+ echo "$STARTUP_RCVAR_MAP"
+ fi
+
+ #
+ # Attempt to create/update the persistent global cache
+ #
+
+ # Create a new temporary file to write to
+ local __tmpfile
+ f_eval_catch -dk __tmpfile $__funcname mktemp \
+ 'mktemp -t "%s"' "$__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_eval_catch -d $__funcname mkdir \
+ 'mkdir -p "%s"' "${STARTUP_RCVAR_MAP_CACHEFILE%/*}"
+ esac
+ f_eval_catch -d $__funcname mv \
+ 'mv "%s" "%s"' "$__tmpfile" "$STARTUP_RCVAR_MAP_CACHEFILE"
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." startup/rcvar.subr
+
+fi # ! $_STARTUP_RCVAR_SUBR
diff --git a/contrib/bsddialog/bsdconfig/startup/startup b/contrib/bsddialog/bsdconfig/startup/startup
new file mode 100755
index 000000000000..17755d120852
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/startup/startup
@@ -0,0 +1,140 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local menu_list="
+ 'X' '$msg_exit'
+ '1' '$msg_toggle_startup_services'
+ '2' '$msg_view_edit_startup_configuration'
+ '3' '$msg_miscellaneous_startup_services'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_startup"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+while :; do
+ dialog_menu_main || f_die
+ f_dialog_menutag_fetch mtag
+
+ command=
+ case "$mtag" in
+ X) break ;;
+ 1) command=rcvar ;; # Toggle Startup Services
+ 2) command=rcconf ;; # View/Edit Startup Configuration
+ 3) command=misc ;; # Miscellaneous Startup Services
+ esac
+
+ if [ "$command" ]; then
+ $BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
+ else
+ f_die 1 "$msg_unknown_startup_menu_selection"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/timezone/INDEX b/contrib/bsddialog/bsdconfig/timezone/INDEX
new file mode 100644
index 000000000000..67fc50b0dcb6
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/timezone/Makefile b/contrib/bsddialog/bsdconfig/timezone/Makefile
new file mode 100644
index 000000000000..1569e7e49569
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/090.timezone
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= timezone
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/timezone/Makefile.depend b/contrib/bsddialog/bsdconfig/timezone/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/timezone/USAGE b/contrib/bsddialog/bsdconfig/timezone/USAGE
new file mode 100644
index 000000000000..6dbe96d3997d
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/USAGE
@@ -0,0 +1,46 @@
+# Copyright (c) 2011-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [-ehnrSsvX] [-C chroot_dir] [zinfo_file | zinfo_name]
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -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.
+ -h Print this usage statement and exit.
+ -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 --git a/contrib/bsddialog/bsdconfig/timezone/include/Makefile b/contrib/bsddialog/bsdconfig/timezone/include/Makefile
new file mode 100644
index 000000000000..8fc6dfc84535
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/090.timezone/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/timezone/include/Makefile.depend b/contrib/bsddialog/bsdconfig/timezone/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/timezone/include/messages.subr b/contrib/bsddialog/bsdconfig/timezone/include/messages.subr
new file mode 100644
index 000000000000..6a7f045cd4f2
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/include/messages.subr
@@ -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$
+
+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 --git a/contrib/bsddialog/bsdconfig/timezone/share/Makefile b/contrib/bsddialog/bsdconfig/timezone/share/Makefile
new file mode 100644
index 000000000000..166fb1020d29
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/timezone
+FILES= continents.subr countries.subr iso3166.subr menus.subr \
+ zones.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/timezone/share/Makefile.depend b/contrib/bsddialog/bsdconfig/timezone/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/timezone/share/continents.subr b/contrib/bsddialog/bsdconfig/timezone/share/continents.subr
new file mode 100644
index 000000000000..764f33fc6c50
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/continents.subr
@@ -0,0 +1,166 @@
+if [ ! "$_TIMEZONE_CONTINENTS_SUBR" ]; then _TIMEZONE_CONTINENTS_SUBR=1
+#
+# Copyright (c) 2011-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/continents.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" 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 [$var_to_set]
+#
+# 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.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_continent()
+{
+ f_getvar "continent_${1}_$2" $3
+}
+
+# f_find_continent $title [$var_to_set]
+#
+# Returns continent identifier given continent title.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_find_continent()
+{
+ local __cont __title
+ for __cont in $CONTINENTS; do
+ f_continent $__cont title __title
+ if [ "$1" = "$__title" ]; then
+ if [ "$2" ]; then
+ setvar "$2" $__cont
+ else
+ echo "$__cont"
+ fi
+ return $SUCCESS
+ fi
+ done
+ return $FAILURE
+}
+
+# f_OCEANP $cont [$var_to_set]
+#
+# Returns "1" if the first argument is an ocean, otherwise NULL.
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_OCEANP()
+{
+ case "$1" in
+ arctic|atlantic|indian|pacific)
+ if [ "$2" ]; then
+ setvar "$2" 1
+ else
+ echo 1
+ fi
+ ;;
+ *)
+ [ "$2" ] && setvar "$2" ""
+ esac
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/continents.subr
+
+fi # ! $_TIMEZONE_CONTINENTS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/timezone/share/countries.subr b/contrib/bsddialog/bsdconfig/timezone/share/countries.subr
new file mode 100644
index 000000000000..8958e877c3d8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/countries.subr
@@ -0,0 +1,105 @@
+if [ ! "$_TIMEZONE_COUNTRIES_SUBR" ]; then _TIMEZONE_COUNTRIES_SUBR=1
+#
+# Copyright (c) 2011-2015 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$
+#
+############################################################ FUNCTIONS
+
+# f_country $code $property [$var_to_set]
+#
+# 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)
+#
+# If $var_to_set is missing or NULL, the value of $var_to_get is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_country()
+{
+ f_getvar "country_${1}_$2" $3
+}
+
+# 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='
+function _asorti(src, dest)
+{
+ k = nitems = 0
+ for (i in src) dest[++nitems] = i
+ for (i = 1; i <= nitems; k = i++) {
+ idx = dest[i]
+ while ((k > 0) && (dest[k] > idx)) {
+ dest[k+1] = dest[k]; k--
+ }
+ dest[k+1] = idx
+ }
+ return nitems
+}
+BEGIN {
+ split(ENVIRON["COUNTRIES"], array, /[[:space:]]+/)
+ for (item in array)
+ {
+ tlc = array[item]
+ name = ENVIRON["country_" tlc "_name"]
+ countries[name] = tlc
+ }
+ n = _asorti(countries, sorted_countries)
+ for (i = 1; i <= n; i++)
+ print countries[sorted_countries[i]]
+ exit
+}
+'
+f_sort_countries()
+{
+ export COUNTRIES # for awk(1) ENVIRON[] visibility
+ COUNTRIES=$( awk "$f_sort_countries_awk" )
+ export COUNTRIES # Pedantic
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/countries.subr
+
+fi # ! $_TIMEZONE_COUNTRIES_SUBR
diff --git a/contrib/bsddialog/bsdconfig/timezone/share/iso3166.subr b/contrib/bsddialog/bsdconfig/timezone/share/iso3166.subr
new file mode 100644
index 000000000000..205d5f5046fd
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/iso3166.subr
@@ -0,0 +1,202 @@
+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 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/iso3166.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" 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" )
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/iso3166.subr
+
+fi # ! $_TIMEZONE_ISO3166_SUBR
diff --git a/contrib/bsddialog/bsdconfig/timezone/share/menus.subr b/contrib/bsddialog/bsdconfig/timezone/share/menus.subr
new file mode 100644
index 000000000000..ef3979be49a5
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/menus.subr
@@ -0,0 +1,225 @@
+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 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/menus.subr
+f_include $BSDCFG_SHARE/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" )
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/menus.subr
+
+fi # ! $_TIMEZONE_MENUS_SUBR
diff --git a/contrib/bsddialog/bsdconfig/timezone/share/zones.subr b/contrib/bsddialog/bsdconfig/timezone/share/zones.subr
new file mode 100644
index 000000000000..59a933013e57
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/share/zones.subr
@@ -0,0 +1,523 @@
+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 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." timezone/zones.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/timezone/continents.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
+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 funcname=f_install_zoneinfo_file
+ local zoneinfo_file="$1"
+ local copymode title msg height width
+
+ 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
+ f_sprintf msg "$msg_removing_file" "$_PATH_LOCALTIME"
+ elif [ "$copymode" ]; then
+ f_sprintf msg "$msg_copying_file" \
+ "$zoneinfo_file" "$_PATH_LOCALTIME"
+ else
+ f_sprintf msg "$msg_creating_symlink" \
+ "$_PATH_LOCALTIME" "$zoneinfo_file"
+ fi
+ if [ "$USEDIALOG" ]; then
+ f_dialog_title "$msg_info"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ printf "%s\n" "$msg"
+ fi
+ fi
+
+ [ "$REALLYDOIT" ] || return $SUCCESS
+
+ local catch_args="-de"
+ [ "$USEDIALOG" ] && catch_args=
+
+ if [ ! "$zoneinfo_file" ]; then
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_DB" || return $FAILURE
+
+ if [ "$VERBOSE" ]; then
+ f_sprintf msg "$msg_removed_file" "$_PATH_LOCALTIME"
+ if [ "$USEDIALOG" ]; then
+ f_dialog_title "$msg_done"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ printf "%s\n" "$msg"
+ fi
+ fi
+ return $SUCCESS
+ fi # ! zoneinfo_file
+
+ if [ "$copymode" ]; then
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname sh \
+ 'umask 222 && :> "%s"' "$_PATH_LOCALTIME" ||
+ return $FAILURE
+ f_eval_catch $catch_args $funcname sh \
+ 'cat "%s" > "%s"' \
+ "$zoneinfo_file" "$_PATH_LOCALTIME" || return $FAILURE
+ else
+ f_eval_catch $catch_args $funcname sh \
+ '( :< "%s" )' "$zoneinfo_file" || return $FAILURE
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname ln \
+ 'ln -s "%s" "%s"' \
+ "$zoneinfo_file" "$_PATH_LOCALTIME" || return $FAILURE
+ fi # copymode
+
+ if [ "$VERBOSE" ]; then
+ if [ "$copymode" ]; then
+ f_sprintf msg "$msg_copied_timezone_file" \
+ "$zoneinfo_file" "$_PATH_LOCALTIME"
+ else
+ f_sprintf msg "$msg_created_symlink" \
+ "$_PATH_LOCALTIME" "$zoneinfo_file"
+ fi
+ if [ "$USEDIALOG" ]; then
+ f_dialog_title "$msg_done"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ printf "%s\n" "$msg"
+ fi
+ fi
+
+ 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 true 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 # Calculated below
+ local height=5 width=72
+
+ f_sprintf prompt "$msg_look_reasonable" "$tm_zone"
+ 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 ""
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." timezone/zones.subr
+
+fi # ! $_TIMEZONE_ZONES_SUBR
diff --git a/contrib/bsddialog/bsdconfig/timezone/timezone b/contrib/bsddialog/bsdconfig/timezone/timezone
new file mode 100755
index 000000000000..a2914429846e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/timezone/timezone
@@ -0,0 +1,457 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/timezone/continents.subr
+f_include $BSDCFG_SHARE/timezone/countries.subr
+f_include $BSDCFG_SHARE/timezone/iso3166.subr
+f_include $BSDCFG_SHARE/timezone/menus.subr
+f_include $BSDCFG_SHARE/timezone/zones.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ CONFIGURATION
+
+#
+# Standard pathnames
+#
+_PATH_DB="/var/db/zoneinfo"
+_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+REALLYDOIT=1
+REINSTALL=
+USEDIALOG=1
+SKIPUTC= # See MAIN
+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 defaultitem= # Calculated below
+ local hline=
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $continent_menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $continent_menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ f_dialog_default_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+# Skip initial question regarding UTC v. Wall-Clock time if run in VM
+[ "$( sysctl -n kern.vm_guest 2> /dev/null )" = "none" ] || SKIPUTC=1
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts C:ehnrsv$GETOPTS_STDARGS 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_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"
+ f_eval_catch -dk zoneinfo "$0" cat 'cat "%s"' "$_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 $DIALOG_OK ]; 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"
+ f_sprintf msg "\n$msg_use_default_zone" "$default"
+ hline=
+ f_dialog_yesno "$msg" "$hline"
+ result=$?
+ f_dialog_title_restore
+
+ if [ $result -eq $DIALOG_OK ]; 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
+#
+defaultctry=
+defaultzone=
+NEED_CONTINENT=1
+NEED_COUNTRY=1
+while :; do
+ if [ "$NEED_CONTINENT" ]; then
+ dialog_menu_main # prompt the user to select a continent/ocean
+ retval=$?
+ f_dialog_menutag_fetch mtag
+
+ if [ $retval -ne $DIALOG_OK ]; then
+ [ "$TZ_OR_FAIL" ] && f_die
+ exit $SUCCESS
+ fi
+
+ NEED_CONTINENT=
+
+ continent=$( eval f_dialog_menutag2item \"\$mtag\" \
+ $continent_menu_list )
+ f_find_continent "$continent" cont
+ f_continent $cont title cont_title
+ f_continent $cont nitems nitems
+ f_OCEANP $cont isocean
+ 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
+ f_sprintf title "$msg_country_title" \
+ "$cont_title"
+ f_dialog_title "$title"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ prompt="$msg_select_country"
+ else
+ f_sprintf title "$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
+ #
+ f_continent $cont menu_list menu_list
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\" \
+ $menu_list
+
+ #
+ # Launch the country selection menu
+ #
+ tag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultctry\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize tag
+ defaultctry="$tag"
+
+ if [ $retval -ne $DIALOG_OK ]; then
+ NEED_CONTINENT=1
+ continue # back to main menu
+ fi
+ fi
+
+ # Get the country code from the user's selection
+ f_continent $cont tlc_$tag tlc
+
+ NEED_COUNTRY=
+ fi
+
+ #
+ # If the selection has only one zone (nzones == -1),
+ # just set it.
+ #
+ f_country $tlc nzones nzones
+ if [ $nzones -lt 0 ]; then
+ f_country $tlc cont real_cont
+ f_continent $real_cont name real_continent
+ f_country $tlc name name
+ f_country $tlc filename filename
+
+ if ! f_confirm_zone "$real_continent/$filename"; then
+ [ $nitems -eq 1 ] && NEED_CONTINENT=1
+ NEED_COUNTRY=1
+ continue
+ fi
+ else
+ f_country $tlc name name
+ f_sprintf title "$msg_country_time_zones" "$name"
+ f_dialog_title "$title"
+ title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ prompt="$msg_select_zone"
+ f_country $tlc menu_list menu_list
+ eval f_dialog_menu_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \"\" $menu_list
+
+ #
+ # Launch the zone selection menu
+ # NOTE: This is as deep as we go
+ #
+ n=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultzone\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize n
+ defaultzone="$n"
+
+ if [ $retval -ne $DIALOG_OK ]; then
+ [ $nitems -eq 1 ] && NEED_CONTINENT=1
+ NEED_COUNTRY=1
+ continue
+ fi
+
+ f_country $tlc cont_$n real_cont
+ f_continent $real_cont name real_continent
+ f_country $tlc name name
+ f_country $tlc filename_$n filename
+
+ f_confirm_zone "$real_continent/$filename" || continue
+ fi
+
+ [ $retval -eq $DIALOG_OK ] || 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 --git a/contrib/bsddialog/bsdconfig/ttys/INDEX b/contrib/bsddialog/bsdconfig/ttys/INDEX
new file mode 100644
index 000000000000..83ca0211bd80
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/INDEX
@@ -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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/ttys/Makefile b/contrib/bsddialog/bsdconfig/ttys/Makefile
new file mode 100644
index 000000000000..044fdcf8ca7b
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/150.ttys
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= ttys
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/ttys/Makefile.depend b/contrib/bsddialog/bsdconfig/ttys/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/ttys/USAGE b/contrib/bsddialog/bsdconfig/ttys/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/ttys/include/Makefile b/contrib/bsddialog/bsdconfig/ttys/include/Makefile
new file mode 100644
index 000000000000..45c72adf4f13
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/150.ttys/include
+FILES= messages.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/ttys/include/Makefile.depend b/contrib/bsddialog/bsdconfig/ttys/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/ttys/include/messages.subr b/contrib/bsddialog/bsdconfig/ttys/include/messages.subr
new file mode 100644
index 000000000000..296f75602f71
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/include/messages.subr
@@ -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$
+
+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 --git a/contrib/bsddialog/bsdconfig/ttys/ttys b/contrib/bsddialog/bsdconfig/ttys/ttys
new file mode 100755
index 000000000000..ed7ba756b785
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/ttys/ttys
@@ -0,0 +1,128 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="150.ttys"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ 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 h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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 --git a/contrib/bsddialog/bsdconfig/usermgmt/INDEX b/contrib/bsddialog/bsdconfig/usermgmt/INDEX
new file mode 100644
index 000000000000..6fc61eaa131f
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/INDEX
@@ -0,0 +1,64 @@
+# 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$
+
+#
+# Title that will be shown in 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 --git a/contrib/bsddialog/bsdconfig/usermgmt/Makefile b/contrib/bsddialog/bsdconfig/usermgmt/Makefile
new file mode 100644
index 000000000000..127c874fbaf6
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SUBDIR= include share
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= groupadd groupdel groupedit useradd userdel useredit usermgmt
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/Makefile.depend b/contrib/bsddialog/bsdconfig/usermgmt/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/USAGE b/contrib/bsddialog/bsdconfig/usermgmt/USAGE
new file mode 100644
index 000000000000..a06d8af24928
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/USAGE
@@ -0,0 +1,37 @@
+# Copyright (c) 2012-2013 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$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS]
+
+OPTIONS:
+ -d Provide lots of debugging info on standard-out when running.
+ -D file Send debugging info to file. If file begins with a plus-sign
+ debug info is sent to both standard-out and file (minus the
+ leading plus).
+ -h Print this 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 --git a/contrib/bsddialog/bsdconfig/usermgmt/groupadd b/contrib/bsddialog/bsdconfig/usermgmt/groupadd
new file mode 100755
index 000000000000..cba0f2bf7533
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/groupadd
@@ -0,0 +1,77 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_add $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Add a group
+#
+# NB: If given an argument on the command-line use it; otherwise fall-back to
+# environment variable $group (handle $VAR_GROUP).
+#
+f_group_add ${1:+"$1"}
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/groupdel b/contrib/bsddialog/bsdconfig/usermgmt/groupdel
new file mode 100755
index 000000000000..ea5548970c84
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/groupdel
@@ -0,0 +1,100 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_delete $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# If given a group name, operate on it and exit
+#
+if [ "$1" ]; then
+ f_group_delete "$1"
+ exit $SUCCESS
+fi
+
+#
+# Loop until the user Exits, Cancels or presses ESC
+#
+defaultitem=
+while :; do
+ f_dialog_menu_group_list "$defaultitem"
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ [ "$mtag" = "X $msg_exit" ] && break
+
+ # Anything else is a group name
+
+ f_group_delete "$mtag"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/groupedit b/contrib/bsddialog/bsdconfig/usermgmt/groupedit
new file mode 100755
index 000000000000..2338d5732270
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/groupedit
@@ -0,0 +1,100 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_edit_view $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# If given a group name, operate on it and exit
+#
+if [ "$1" ]; then
+ f_group_edit "$1"
+ exit $SUCCESS
+fi
+
+#
+# Present a list of groups and loop until user Exits, Cancels or presses ESC
+#
+defaultitem=
+while :; do
+ f_dialog_menu_group_list "$defaultitem"
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%s mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ [ "$mtag" = "X $msg_exit" ] && break
+
+ # Anything else is a group name
+
+ f_group_edit "$mtag"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/include/Makefile b/contrib/bsddialog/bsdconfig/usermgmt/include/Makefile
new file mode 100644
index 000000000000..48396540a331
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/include/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt/include
+FILES= messages.subr usermgmt.hlp
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/include/Makefile.depend b/contrib/bsddialog/bsdconfig/usermgmt/include/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/include/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/include/messages.subr b/contrib/bsddialog/bsdconfig/usermgmt/include/messages.subr
new file mode 100644
index 000000000000..f56b8443fbda
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/include/messages.subr
@@ -0,0 +1,119 @@
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+
+hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
+hline_alnum_space_tab_enter="Use alpha-numeric, SPACE, 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_does_not_expire="Account does not expire"
+msg_account_expire_manual_edit="Enter account expiration time. Format is one of:\n\n a) decimal for UNIX time since %s\n b) dd-mmm-yy[yy] for day, month, and 2- or 4-digit year\n c) +n[mhdwoy] for relative time from current date\n\nNOTE: Value of zero disables expiration."
+msg_account_expires_on="Account Expires on"
+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_groups_manually="Enter Groups 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_id="Group ID"
+msg_group_id_leave_empty_for_default="Group ID (Leave empty for default)"
+msg_group_is_empty="Group is empty."
+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_groups="Groups"
+msg_home_directory="Home Directory"
+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="%s: Login not found."
+msg_login_updated="Login Updated"
+msg_member_of_groups="Member of Groups"
+msg_n_a="N/A"
+msg_no="No"
+msg_no_group_specified="No group specified!"
+msg_no_user_specified="No user specified!"
+msg_number_of_seconds_since_epoch="Number of seconds since the Epoch\n(1 = %s)\nNULL or zero to disable:"
+msg_ok="OK"
+msg_password="Password"
+msg_password_does_not_expire="Password does not expire"
+msg_password_expire_manual_edit="Enter password expiration time. Format is one of:\n\n a) decimal for UNIX time since %s\n b) dd-mmm-yy[yy] for day, month, and 2- or 4-digit year\n c) +n[mhdwoy] for relative time from current date\n\nNOTE: Value of zero disables expiration."
+msg_password_expires_on="Password Expires on"
+msg_passwords_do_not_match="Passwords do not match."
+msg_please_enter_a_group_name="Please enter a group name!"
+msg_please_enter_a_user_name="Please enter a user name!"
+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_select_group_members_from_list="Select Group Members from a list"
+msg_select_groups_from_list="Select Groups from a list"
+msg_select_login_shell="Select Login Shell"
+msg_separated_by_commas="Separated by commas"
+msg_shell="Shell"
+msg_unknown_user_management_menu_selection="Unknown user management menu selection"
+msg_use_default_values_for_all_account_details="Use default values for all account details?"
+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 --git a/contrib/bsddialog/bsdconfig/usermgmt/include/usermgmt.hlp b/contrib/bsddialog/bsdconfig/usermgmt/include/usermgmt.hlp
new file mode 100644
index 000000000000..77be9bdeb5c6
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/include/usermgmt.hlp
@@ -0,0 +1,76 @@
+These screens allow you to add groups and users to your system.
+
+Many of the settings get reasonable defaults if you leave them blank.
+The first time you have entered the name of the new group or user, the
+system will show you what it would chose for most of these fields.
+You are free to change them, of course.
+
+
+User groups
+===========
+
+It's certainly almost generally a good idea to first create a new
+group for your users. Common names for such a group are "users", or
+even simply "other". Group names are used to control file access
+permissions for users that belong to the same group. Several group
+names are already used for system files.
+
+The numerical user or group IDs are often nothing you want to care for
+explicitly. If you don't fill in these fields, the system will choose
+reasonable defaults. However, these numbers (rather than the
+associated names) are what the operating system actually uses to
+distinguish users and groups -- hence they should normally be unique
+to each person or group, respectively.
+
+
+Users
+=====
+
+The user's login ID is a short (up to 15 characters) alphanumeric ID
+that the user must enter when logging into the system. It's often the
+initial letters of the user's name, and commonly used in lower case.
+It's also the local mail name for this user (though it's possible to
+also set up more descriptive mail alias names later).
+
+The user's login group determines which group access rights the user
+will initially get when logging in. If an additional list of groups is
+provided which the user will become a member of, (s)he will also be
+able to access files of those groups later without providing any
+additional password etc. Except for the "wheel" case mentioned below,
+the additional group membership list should normally not contain the
+login group again.
+
+The user's password can also be set here, and should be chosen with
+care - 6 or more characters, intermixing punctuation and numerics, and
+*not* a word from the dictionary or related to the username is a good
+password choice.
+
+Some of the system's groups have a special meaning. In particular,
+members of group "wheel" are the only people who are later allowed to
+become superuser using the command su(1). So if you're going to add a
+new user who should later perform administrative tasks, don't forget
+to add him to this group! (Well, ``he'' will most likely be yourself
+in the very first place. :)
+
+Also, members of group "operator" will by default get permissions for
+minor administrative operations, like performing system backups, or
+shutting down the system -- without first becoming superuser! So,
+take care when adding people to this group.
+
+The ``full name'' field serves as a comment only. It is also used by
+mail front ends to determine the real name of the user, hence you
+should actually fill in the first and last name of this user. By
+convention, this field can be divided into comma-separated subfields,
+where the office location, the work phone number, and the home phone
+number follow the full name of the user.
+
+The home directory is the directory in the filesystem where the user
+is being logged into, and where his personalized setup files (``dot
+files'', since they usually begin with a `.' and are not displayed by
+the ls(1) command by default) will be looked up. It is often created
+under /usr/home/ or /home/.
+
+Finally, the shell is the user's initial command interpreter. The
+default shell is /bin/sh, some users prefer the more historic
+/bin/csh. Other, often more user-friendly and comfortable shells can
+be found in the ports and packages collection.
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/share/Makefile b/contrib/bsddialog/bsdconfig/usermgmt/share/Makefile
new file mode 100644
index 000000000000..eba7c1cf0eb6
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/share/Makefile
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+FILESDIR= ${SHAREDIR}/bsdconfig/usermgmt
+FILES= group.subr group_input.subr user.subr user_input.subr
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/share/Makefile.depend b/contrib/bsddialog/bsdconfig/usermgmt/share/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/share/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/share/group.subr b/contrib/bsddialog/bsdconfig/usermgmt/share/group.subr
new file mode 100644
index 000000000000..e9c8b1637bc5
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/share/group.subr
@@ -0,0 +1,518 @@
+if [ ! "$_USERMGMT_GROUP_SUBR" ]; then _USERMGMT_GROUP_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/group.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${passwdtype:="yes"}
+
+############################################################ FUNCTIONS
+
+# f_group_add [$group]
+#
+# Add a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to enter the name
+# of a new group and (if $VAR_NO_CONFIRM is unset or NULL) prompt the user to
+# answer some questions about the new group. Variables that can be used to
+# script user input:
+#
+# VAR_GROUP [Optional if running interactively]
+# The group to add. Ignored if given non-NULL first-argument.
+# VAR_GROUP_GID [Optional]
+# Numerical group ID to use. If NULL or unset, the group ID is
+# automatically chosen.
+# VAR_GROUP_MEMBERS [Optional]
+# Comma separated list of users that are a member of this group.
+# VAR_GROUP_PASSWORD [Optional]
+# newgrp(1) password to set for the group. Default if NULL or
+# unset is to disable newgrp(1) password authentication.
+#
+# Returns success if the group was successfully added.
+#
+f_group_add()
+{
+ local funcname=f_group_add
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_GROUP input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as GID
+ # instead of name. Work-around is to also pass `-g GID' at the same
+ # time (the GID is ignored in this case, so any GID will do).
+ #
+ if [ "$input" ] && f_quietly pw groupshow -n "$input" -g 1337; then
+ f_show_err "$msg_group_already_used" "$input"
+ return $FAILURE
+ fi
+
+ local group_name="$input"
+ while f_interactive && [ ! "$group_name" ]; do
+ f_dialog_input_group_name group_name "$group_name" ||
+ return $SUCCESS
+ [ "$group_name" ] ||
+ f_show_err "$msg_please_enter_a_group_name"
+ done
+ if [ ! "$group_name" ]; then
+ f_show_err "$msg_no_group_specified"
+ return $FAILURE
+ fi
+
+ local group_password group_gid group_members
+ f_getvar $VAR_GROUP_PASSWORD group_password
+ f_getvar $VAR_GROUP_GID group_gid
+ f_getvar $VAR_GROUP_MEMBERS group_members
+
+ local group_password_disable=
+ f_interactive || [ "$group_password" ] || group_password_disable=1
+
+ if f_interactive && [ ! "$no_confirm" ]; then
+ f_dialog_noyes \
+ "$msg_use_default_values_for_all_account_details"
+ retval=$?
+ if [ $retval -eq $DIALOG_ESC ]; then
+ return $SUCCESS
+ elif [ $retval -ne $DIALOG_OK ]; then
+ #
+ # Ask series of questions to pre-fill the editor screen
+ #
+ # Defaults used in each dialog should allow the user to
+ # simply hit ENTER to proceed and cancelling a single
+ # dialog cause them to return to the previous menu.
+ #
+
+ if [ "$passwdtype" = "yes" ]; then
+ f_dialog_input_group_password group_password \
+ group_password_disable ||
+ return $FAILURE
+ fi
+ f_dialog_input_group_gid group_gid "$group_gid" ||
+ return $FAILURE
+ f_dialog_input_group_members group_members \
+ "$group_members" || return $FAILURE
+ fi
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_add $msg_group: $group_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_group_add "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Add/Exit
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \
+ \"\$group_$var\" _group_$var
+ done
+
+ local cmd="pw groupadd -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" ] &&
+ cmd="$cmd -M '$_group_members'"
+
+ # Execute the command (break on success)
+ if [ "$group_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" ]; then
+ echo "$group_password" |
+ f_eval_catch $funcname \
+ pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi && break
+ ;;
+ 1) # Group Name (prompt for new group name)
+ f_dialog_input_group_name input "$group_name" ||
+ continue
+ if f_quietly pw groupshow -n "$input" -g 1337; then
+ f_show_err "$msg_group_already_used" "$input"
+ continue
+ fi
+ group_name="$input"
+ title="$msg_add $msg_group: $group_name"
+ ;;
+ 2) # Password
+ f_dialog_input_group_password group_password \
+ group_password_disable
+ ;;
+ 3) # Group ID
+ f_dialog_input_group_gid group_gid "$group_gid"
+ ;;
+ 4) # Group Members
+ f_dialog_input_group_members group_members \
+ "$group_members"
+ ;;
+ esac
+ done
+ else
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ # Form the command
+ local cmd="pw groupadd -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" ] && cmd="$cmd -M '$_group_members'"
+
+ # Execute the command
+ local retval err
+ if [ "$group_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" ]; then
+ err=$( echo "$group_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_group_added"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_group_delete [$group]
+#
+# Delete a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to select a group
+# from a list of available groups. Variables that can be used to script user
+# input:
+#
+# VAR_GROUP [Optional if running interactively]
+# The group to delete. Ignored if given non-NULL first-argument.
+#
+# Returns success if the group was successfully deleted.
+#
+f_group_delete()
+{
+ local funcname=f_group_delete
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_GROUP input "$1"
+
+ local group_name group_password group_gid group_members
+ if [ "$input" ] && ! f_input_group "$input"; then
+ f_show_err "$msg_group_not_found" "$input"
+ return $FAILURE
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_delete $msg_group: $group_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_group_delete "$group_name" "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Delete/Exit
+ local _group_name
+ f_shell_escape "$group_name" _group_name
+ f_eval_catch $funcname pw 'pw groupdel "%s"' \
+ "$_group_name" && break
+ ;;
+ 1) # Group Name (select different group from list)
+ f_dialog_menu_group_list "$group_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_group "$mtag"; then
+ f_show_err "$msg_group_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_group "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ ;;
+ esac
+ done
+ else
+ local retval err _group_name
+ f_shell_escape "$group_name" _group_name
+ f_eval_catch -k err $funcname pw \
+ "pw groupdel '%s'" "$_group_name"
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_group_deleted"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_group_edit [$group]
+#
+# Modify a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to select a group
+# from a list of available groups. Variables that can be used to script user
+# input:
+#
+# VAR_GROUP [Optional if running interactively]
+# The group to modify. Ignored if given non-NULL first-argument.
+# VAR_GROUP_GID [Optional]
+# Numerical group ID to set. If NULL or unset, the group ID is
+# unchanged.
+# VAR_GROUP_MEMBERS [Optional]
+# Comma separated list of users that are a member of this group.
+# If set but NULL, group memberships are reset (no users will be
+# a member of this group). If unset, group membership is
+# unmodified.
+# VAR_GROUP_PASSWORD [Optional]
+# newgrp(1) password to set for the group. If unset, the password
+# is unmodified. If NULL, the newgrp(1) password is disabled.
+#
+# Returns success if the group was successfully modified.
+#
+f_group_edit()
+{
+ local funcname=f_group_edit
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_GROUP input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as GID
+ # instead of name. Work-around is to also pass `-g GID' at the same
+ # time (the GID is ignored in this case, so any GID will do).
+ #
+ if [ "$input" ] && ! f_quietly pw groupshow -n "$input" -g 1337; then
+ f_show_err "$msg_group_not_found" "$input"
+ return $FAILURE
+ fi
+
+ if f_interactive && [ ! "$input" ]; then
+ f_dialog_menu_group_list || return $SUCCESS
+ f_dialog_menutag_fetch input
+ [ "$input" = "X $msg_exit" ] && return $SUCCESS
+ elif [ ! "$input" ]; then
+ f_show_err "$msg_no_group_specified"
+ return $FAILURE
+ fi
+
+ local group_name group_password group_gid group_members
+ if ! f_input_group "$input"; then
+ f_show_err "$msg_group_not_found" "$input"
+ return $FAILURE
+ fi
+
+ f_isset $VAR_GROUP_GID && f_getvar $VAR_GROUP_GID group_gid
+ local null_members=
+ if f_isset $VAR_GROUP_MEMBERS; then
+ f_getvar $VAR_GROUP_MEMBERS group_members
+ [ "$group_members" ] || null_members=1
+ fi
+ local group_password_disable=
+ if f_isset $VAR_GROUP_PASSWORD; then
+ f_getvar $VAR_GROUP_PASSWORD group_password
+ [ "$group_password" ] || group_password_disable=1
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_edit_view $msg_group: $group_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_group_edit "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Save/Exit
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \
+ \"\$group_$var\" _group_$var
+ done
+
+ local cmd="pw groupmod -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" -o "$null_members" ] &&
+ cmd="$cmd -M '$_group_members'"
+
+ # Execute the command (break on success)
+ if [ "$group_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" ]; then
+ echo "$group_password" | f_eval_catch \
+ $funcname pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi && break
+ ;;
+ 1) # Group Name (select different group from list)
+ f_dialog_menu_group_list "$group_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_group "$mtag"; then
+ f_show_err "$msg_group_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_group "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ title="$msg_edit_view $msg_group: $group_name"
+ ;;
+ 2) # Password
+ f_dialog_input_group_password group_password \
+ group_password_disable
+ ;;
+ 3) # Group ID
+ f_dialog_input_group_gid group_gid "$group_gid"
+ ;;
+ 4) # Group Members
+ f_dialog_input_group_members group_members \
+ "$group_members" && [ ! "$group_members" ] &&
+ null_members=1
+ ;;
+ esac
+ done
+ else
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ # Form the command
+ local cmd="pw groupmod -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" -o "$null_members" ] &&
+ cmd="$cmd -M '$_group_members'"
+
+ # Execute the command
+ local retval err
+ if [ "$group_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" -o "$null_password" ]; then
+ err=$( echo "$group_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_group_updated"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/group.subr
+
+fi # ! $_USERMGMT_GROUP_SUBR
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/share/group_input.subr b/contrib/bsddialog/bsdconfig/usermgmt/share/group_input.subr
new file mode 100644
index 000000000000..2e8c08647adb
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/share/group_input.subr
@@ -0,0 +1,596 @@
+if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/group_input.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+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()
+{
+ local funcname=f_input_group
+ local group="$1"
+
+ f_dprintf "$funcname: Getting info for group \`%s'" "$group"
+ eval "$( pw groupshow "$group" 2> /dev/null | awk -F: '
+ function set_value(var, value) {
+ gsub(/'\''/, "'\''\\'\'\''", value)
+ printf "group_%s='\'%s\''\n", var, value
+ }
+ {
+ found = $1 != ""
+ set_value("name", $1)
+ set_value("password", "")
+ set_value("gid", $3)
+ set_value("members", $4)
+ exit
+ }
+ END { if (!found) print "false" }' )"
+}
+
+# f_dialog_menu_group_list [$default]
+#
+# Allows the user to select a group from a list. Optionally, if present and
+# non-NULL, initially highlight $default group.
+#
+f_dialog_menu_group_list()
+{
+ local prompt=
+ local menu_list="
+ 'X $msg_exit' ''
+ " # END-QUOTE
+ local defaultitem="$1"
+ local hline="$hline_alnum_punc_tab_enter"
+
+ # Add groups from group(5)
+ menu_list="$menu_list $( pw groupshow -a | awk -F: '
+ function mprint(tag, item) {
+ gsub(/'\''/, "'\''\\'\'\''", tag)
+ gsub(/'\''/, "'\''\\'\'\''", item)
+ printf "'\'%s\'\ \'%s\''\n", tag, item
+ }
+ !/^[[:space:]]*(#|$)/ { mprint($1, $1) }
+ ' )"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+# f_dialog_input_group_name $var_to_set [$group_name]
+#
+# Allows the user to enter a name for a new group. If the user does not cancel
+# or press ESC, the $var_to_set variable will hold the newly-configured value
+# upon return.
+#
+f_dialog_input_group_name()
+{
+ local __var_to_set="$1" __name="$2"
+
+ #
+ # Loop until the user provides taint-free/valid input
+ #
+ local __input="$__name"
+ while :; do
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_group" "$__input" \
+ "$hline_alnum_tab_enter" || return $?
+
+ # Check for no-change
+ if [ "$__input" = "$__name" ]; then
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+ fi
+
+ # Check for NULL entry
+ if [ ! "$__input" ]; then
+ f_show_msg "$msg_group_is_empty"
+ continue
+ fi
+
+ # Check for invalid entry
+ case "$__input" in [!a-zA-Z]*)
+ f_show_msg "$msg_group_must_start_with_letter"
+ continue
+ esac
+
+ # Check for duplicate entry
+ if f_quietly pw groupshow -n "$__input"; then
+ f_show_msg "$msg_group_already_used" "$__input"
+ continue
+ fi
+
+ setvar "$__var_to_set" "$__input"
+ break
+ done
+
+ return $DIALOG_OK
+}
+
+# f_dialog_input_group_password $var_to_set $dvar_to_set
+#
+# Prompt the user to enter a password (twice). If the user does not cancel or
+# press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the
+# user cancels or enters a NULL password (twice), they are given the choice to
+# disable password authentication for the given group, wherein $dvar_to_set has
+# a value of 1 to indicate password authentication should be disabled.
+#
+f_dialog_input_group_password()
+{
+ local __var_to_set="$1" __dvar_to_set="$2"
+ local __prompt1="$msg_group_password"
+ local __prompt2="$msg_reenter_group_password"
+ local __hline="$hline_alnum_punc_tab_enter"
+
+ local __height1 __width1
+ f_dialog_inputbox_size __height1 __width1 \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt1" \
+ "" \
+ "$__hline"
+
+ local __height2 __width2
+ f_dialog_inputbox_size __height2 __width2 \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt2" \
+ "" \
+ "$__hline"
+
+ #
+ # Loop until the user provides taint-free/valid input
+ #
+ local __retval __password1 __password2
+ while :; do
+ __password1=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$__hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$__prompt1" \
+ $__height1 $__width1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ debug= f_dialog_line_sanitize __password1
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
+
+ __password2=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$__hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$__prompt2" \
+ $__height2 $__width2 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ debug= f_dialog_line_sanitize __password2
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || 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"
+ __retval=$?
+ if [ $__retval -eq $DIALOG_ESC ]; then
+ return $__retval
+ elif [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__dvar_to_set" 1
+ else
+ continue # back to password prompt
+ fi
+ else
+ setvar "$__dvar_to_set" ""
+ fi
+
+ setvar "$__var_to_set" "$__password1"
+ break
+ done
+
+ return $DIALOG_OK
+}
+
+# f_dialog_input_group_gid $var_to_set [$group_gid]
+#
+# Allow the user to enter a new GID for a given group. If the user does not
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_group_gid()
+{
+ local __var_to_set="$1" __input="$2"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_group_id_leave_empty_for_default" \
+ "$__input" "$hline_num_tab_enter" || return $?
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_group_members $var_to_set [$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 $var_to_set variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_group_members()
+{
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_group_members:"
+ local __menu_list="
+ 'X' '$msg_continue'
+ '1' '$msg_select_group_members_from_list'
+ '2' '$msg_enter_group_members_manually'
+ " # END-QUOTE
+ local __defaultitem=
+ local __hline="$hline_num_arrows_tab_enter"
+
+ local __mheight __mwidth __mrows
+ eval f_dialog_menu_size __mheight __mwidth __mrows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__menu_list
+
+ local __menu_choice __retval
+ while :; do
+ __menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$__defaultitem\" \
+ --menu \"\$__prompt\" \
+ $__mheight $__mwidth $__mrows \
+ $__menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __menu_choice
+ __defaultitem="$__menu_choice"
+ f_dprintf "retval=%u menu_choice=[%s]" \
+ $__retval "$__menu_choice"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
+
+ local __group_members
+ case "$__menu_choice" in
+ X) # Exit
+ break ;;
+ 1) # Select Group Members from a list
+ local __check_list= # Calculated below
+ local __user_list __u __user __length=0
+ __user_list=$( pw usershow -a |
+ awk -F: '!/^[[:space:]]*(#|$)/{print $1}' )
+ while [ $__length -ne ${#__user_list} ]; do
+ __u="${__user_list%%$NL*}" # First line
+ f_shell_escape "$__u" __user
+
+ # Format of a checklist entry: tag item status
+ __check_list="$__check_list '$__user' ''"
+ case "$__input" in
+ "$__u"|"$__u",*|*,"$__u",*|*,"$__u")
+ __check_list="$__check_list on" ;;
+ *)
+ __check_list="$__check_list off"
+ esac
+
+ __length=${#__user_list}
+ __user_list="${__user_list#*$NL}" # Kill line
+ done
+
+ local __cheight __cwidth __crows
+ eval f_dialog_checklist_size \
+ __cheight __cwidth __crows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__check_list
+ __group_members=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --separate-output \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --checklist \"\$__prompt\" \
+ $__cheight $__cwidth $__crows \
+ $__check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || continue
+ # Return to previous menu if user either
+ # pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize __group_members
+
+ #
+ # Convert the newline separated list into a comma-
+ # separated one so that if the user switches over to
+ # manual editing, list reflects checklist selections
+ #
+ f_replaceall "$__group_members" "[$NL]" "," __input
+ ;;
+ 2) # Enter Group Members manually
+ local __prompt2="$msg_group_members"
+ __prompt2="$__prompt2 ($msg_separated_by_commas)"
+
+ f_dialog_input __group_members \
+ "$__prompt2" "$__input" \
+ "$hline_num_tab_enter" || continue
+ # Return to previous menu if user either
+ # pressed ESC or chose Cancel/No
+
+ __input="$__group_members"
+ ;;
+ esac
+ done
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_menu_group_add [$defaultitem]
+#
+# Present a menu detailing the properties of a group that is about to be added.
+# The user's menu choice is available using f_dialog_menutag_fetch(). Returns
+# success unless the user chose Cancel or pressed ESC. Data to display is taken
+# from environment variables group_name, group_gid, and group_members. If
+# $defaultitem is present and non-NULL, initially highlight the item in the
+# menu.
+#
+f_dialog_menu_group_add()
+{
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ menu_list="
+ 'X' '$msg_add/$msg_exit'
+ '1' '$msg_group: $_group_name'
+ '2' '$msg_password: -----'
+ '3' '$msg_group_id: $_group_gid'
+ '4' '$msg_group_members: $_group_members'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_group_delete $group [$defaultitem]
+#
+# Present a menu detailing the properties of a group that is about to be
+# deleted. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is populated automatically from the system accounting database for the given
+# $group argument. If $defaultitem is present and non-NULL, initially highlight
+# the item in the menu.
+#
+f_dialog_menu_group_delete()
+{
+ local prompt="$msg_delete_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$2"
+ local hline="$hline_arrows_tab_enter"
+
+ local group_name group_password group_gid group_members
+ f_input_group "$1"
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ menu_list="
+ 'X' '$msg_delete/$msg_exit'
+ '1' '$msg_group: $_group_name'
+ '-' '$msg_password: -----'
+ '-' '$msg_group_id: $_group_gid'
+ '-' '$msg_group_members: $_group_members'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_group_edit [$defaultitem]
+#
+# Present a menu detailing the properties of a group that is about to be
+# modified. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is taken from environment variables group_name, group_gid, and group_members.
+# If $defaultitem is present and non-NULL, initially highlight the item in the
+# menu.
+#
+f_dialog_menu_group_edit()
+{
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ menu_list="
+ 'X' '$msg_save/$msg_exit'
+ '1' '$msg_group: $_group_name'
+ '2' '$msg_password: -----'
+ '3' '$msg_group_id: $_group_gid'
+ '4' '$msg_group_members: $_group_members'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr
+
+fi # ! $_USERMGMT_GROUP_INPUT_SUBR
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/share/user.subr b/contrib/bsddialog/bsdconfig/usermgmt/share/user.subr
new file mode 100644
index 000000000000..27d9d665319e
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/share/user.subr
@@ -0,0 +1,1183 @@
+if [ ! "$_USERMGMT_USER_SUBR" ]; then _USERMGMT_USER_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/user.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+f_include $BSDCFG_SHARE/usermgmt/user_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${defaultclass:=""}
+: ${defaultshell:="/bin/sh"}
+: ${homeprefix:="/home"}
+: ${passwdtype:="yes"}
+: ${udotdir:="/usr/share/skel"}
+: ${uexpire:=""}
+ # Default account expire time. Format is similar to upwexpire variable.
+: ${ugecos:="User &"}
+: ${upwexpire:=""}
+ # The default password expiration time. Format of the date is either a
+ # UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where dd is
+ # the day, mmm is the month in either numeric or alphabetic format, and
+ # yy[yy] is either a two or four digit year. This variable also accepts
+ # a relative date in the form of n[mhdwoy] where n is a decimal, octal
+ # (leading 0) or hexadecimal (leading 0x) digit followed by the number
+ # of Minutes, Hours, Days, Weeks, Months or Years from the current date
+ # at which the expiration time is to be set.
+
+#
+# uexpire and upwexpire from adduser.conf(5) differ only slightly from what
+# pw(8) accepts as `date' argument(s); pw(8) requires a leading `+' for the
+# relative date syntax (n[mhdwoy]).
+#
+case "$uexpire" in *[mhdwoy])
+ f_isinteger "${uexpire%[mhdwoy]}" && uexpire="+$uexpire"
+esac
+case "$upwexpire" in *[mhdwoy])
+ f_isinteger "${upwexpire%[mhdwoy]}" && upwexpire="+$upwexpire"
+esac
+
+############################################################ FUNCTIONS
+
+# f_user_create_homedir $user
+#
+# Create home directory for $user.
+#
+f_user_create_homedir()
+{
+ local funcname=f_user_create_homedir
+ local user="$1"
+
+ [ "$user" ] || return $FAILURE
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ f_input_user "$user" || return $FAILURE
+
+ f_dprintf "Creating home directory \`%s' for user \`%s'" \
+ "$user_home_dir" "$user"
+
+ local _user_gid _user_home_dir _user_uid
+ f_shell_escape "$user_gid" _user_gid
+ f_shell_escape "$user_home_dir" _user_home_dir
+ f_shell_escape "$user_uid" _user_uid
+ f_eval_catch $funcname mkdir "mkdir -p '%s'" "$_user_home_dir" ||
+ return $FAILURE
+ f_eval_catch $funcname chown "chown '%i:%i' '%s'" \
+ "$_user_uid" "$_user_gid" "$_user_home_dir" || return $FAILURE
+}
+
+# f_user_copy_dotfiles $user
+#
+# Copy `skel' dot-files from $udotdir (global inherited from /etc/adduser.conf)
+# to the home-directory of $user. Attempts to create the home-directory first
+# if it doesn't exist.
+#
+f_user_copy_dotfiles()
+{
+ local funcname=f_user_copy_dotfiles
+ local user="$1"
+
+ [ "$udotdir" ] || return $FAILURE
+ [ "$user" ] || return $FAILURE
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ f_input_user "$user" || return $FAILURE
+
+ f_dprintf "Copying dot-files from \`%s' to \`%s'" \
+ "$udotdir" "$user_home_dir"
+
+ # Attempt to create the home directory if it doesn't exist
+ [ -d "$user_home_dir" ] ||
+ f_user_create_homedir "$user" || return $FAILURE
+
+ local _user_gid _user_home_dir _user_uid
+ f_shell_escape "$user_gid" _user_gid
+ f_shell_escape "$user_home_dir" _user_home_dir
+ f_shell_escape "$user_uid" _user_uid
+
+ local - # Localize `set' to this function
+ set +f # Enable glob pattern-matching for paths
+ cd "$udotdir" || return $FAILURE
+
+ local _file file retval
+ for file in dot.*; do
+ [ -e "$file" ] || continue # no-match
+
+ f_shell_escape "$file" "_file"
+ f_eval_catch $funcname cp "cp -n '%s' '%s'" \
+ "$_file" "$_user_home_dir/${_file#dot}"
+ retval=$?
+ [ $retval -eq $SUCCESS ] || break
+ f_eval_catch $funcname chown \
+ "chown -h '%i:%i' '%s'" \
+ "$_user_uid" "$_user_gid" \
+ "$_user_home_dir/${_file#dot}"
+ retval=$?
+ [ $retval -eq $SUCCESS ] || break
+ done
+
+ cd -
+ return $retval
+}
+
+# f_user_add [$user]
+#
+# Create a login account. If both $user (as a first argument) and $VAR_USER are
+# unset or NULL and we are running interactively, prompt the end-user to enter
+# the name of a new login account and (if $VAR_NO_CONFIRM is unset or NULL)
+# prompt the end-user to answer some questions about the new account. Variables
+# that can be used to script user input:
+#
+# VAR_USER [Optional if running interactively]
+# The login to add. Ignored if given non-NULL first-argument.
+# VAR_USER_ACCOUNT_EXPIRE [Optional]
+# The account expiration time. Format is similar to
+# VAR_USER_PASSWORD_EXPIRE variable below. Default is to never
+# expire the account.
+# VAR_USER_DOTFILES_CREATE [Optional]
+# If non-NULL, populate the user's home directory with the
+# template files found in $udotdir (`/usr/share/skel' default).
+# VAR_USER_GECOS [Optional]
+# Often the full name of the account holder. Default is NULL.
+# VAR_USER_GID [Optional]
+# Numerical primary-group ID to use. If NULL or unset, the group
+# ID is automatically chosen.
+# VAR_USER_GROUPS [Optional]
+# Comma-separated list of additional groups to which the user is
+# a member of. Default is NULL (no additional groups).
+# VAR_USER_HOME [Optional]
+# The home directory to set. If NULL or unset, the home directory
+# is automatically calculated.
+# VAR_USER_HOME_CREATE [Optional]
+# If non-NULL, create the user's home directory if it doesn't
+# already exist.
+# VAR_USER_LOGIN_CLASS [Optional]
+# Login class to use when creating the login. Default is NULL.
+# VAR_USER_PASSWORD [Optional]
+# Unencrypted password to use. If unset or NULL, password
+# authentication for the login is disabled.
+# VAR_USER_PASSWORD_EXPIRE [Optional]
+# The password expiration time. Format of the date is either a
+# UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where
+# dd is the day, mmm is the month in either numeric or alphabetic
+# format, and yy[yy] is either a two or four digit year. This
+# variable also accepts a relative date in the form of +n[mhdwoy]
+# where n is a decimal, octal (leading 0) or hexadecimal (leading
+# 0x) digit followed by the number of Minutes, Hours, Days,
+# Weeks, Months or Years from the current date at which the
+# expiration time is to be set. Default is to never expire the
+# account password.
+# VAR_USER_SHELL [Optional]
+# Path to login shell to use. Default is `/bin/sh'.
+# VAR_USER_UID [Optional]
+# Numerical user ID to use. If NULL or unset, the user ID is
+# automatically chosen.
+#
+# Returns success if the user account was successfully created.
+#
+f_user_add()
+{
+ local funcname=f_user_add
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_USER input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as UID
+ # instead of name. Work-around is to also pass `-u UID' at the same
+ # time (the UID is ignored in this case, so any UID will do).
+ #
+ if [ "$input" ] && f_quietly pw usershow -n "$input" -u 1337; then
+ f_show_err "$msg_login_already_used" "$input"
+ return $FAILURE
+ fi
+
+ local user_name="$input"
+ while f_interactive && [ ! "$user_name" ]; do
+ f_dialog_input_name user_name "$user_name" ||
+ return $SUCCESS
+ [ "$user_name" ] ||
+ f_show_err "$msg_please_enter_a_user_name"
+ done
+ if [ ! "$user_name" ]; then
+ f_show_err "$msg_no_user_specified"
+ return $FAILURE
+ fi
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_password user_password_expire user_shell
+ local user_uid user_dotfiles_create= user_home_create=
+ f_getvar $VAR_USER_ACCOUNT_EXPIRE-\$uexpire user_account_expire
+ f_getvar $VAR_USER_DOTFILES_CREATE:+\$msg_yes user_dotfiles_create
+ f_getvar $VAR_USER_GECOS-\$ugecos user_gecos
+ f_getvar $VAR_USER_GID user_gid
+ f_getvar $VAR_USER_GROUPS user_member_groups
+ f_getvar $VAR_USER_HOME:-\${homeprefix%/}/\$user_name \
+ user_home_dir
+ f_getvar $VAR_USER_HOME_CREATE:+\$msg_yes user_home_create
+ f_getvar $VAR_USER_LOGIN_CLASS-\$defaultclass user_class
+ f_getvar $VAR_USER_PASSWORD user_password
+ f_getvar $VAR_USER_PASSWORD_EXPIRE-\$upwexpire user_password_expire
+ f_getvar $VAR_USER_SHELL-\$defaultshell user_shell
+ f_getvar $VAR_USER_UID user_uid
+
+ # Create home-dir if no script-override and does not exist
+ f_isset $VAR_USER_HOME_CREATE || [ -d "$user_home_dir" ] ||
+ user_home_create="$msg_yes"
+ # Copy dotfiles if home-dir creation is desired, does not yet exist,
+ # and no script-override has been set
+ f_isset $VAR_USER_DOTFILES_CREATE ||
+ [ "$user_home_create" != "$msg_yes" ] ||
+ [ -d "$user_home_dir" ] || user_dotfiles_create="$msg_yes"
+ # Create home-dir if copying dotfiles but home-dir does not exist
+ [ "$user_dotfiles_create" -a ! -d "$user_home_dir" ] &&
+ user_home_create="$msg_yes"
+
+ # Set flags for meaningful NULL values if-provided
+ local no_account_expire= no_password_expire= null_gecos= null_members=
+ local user_password_disable=
+ f_isset $VAR_USER_ACCOUNT_EXPIRE &&
+ [ ! "$user_account_expire" ] && no_account_expire=1
+ f_isset $VAR_USER_GECOS &&
+ [ ! "$user_gecos" ] && null_gecos=1
+ f_isset $VAR_USER_GROUPS &&
+ [ ! "$user_member_groups" ] && null_members=1
+ f_isset $VAR_USER_PASSWORD &&
+ [ ! "$user_password" ] && user_password_disable=1
+ f_isset $VAR_USER_PASSWORD_EXPIRE &&
+ [ ! "$user_password_expire" ] && no_password_expire=1
+
+ if f_interactive && [ ! "$no_confirm" ]; then
+ f_dialog_noyes \
+ "$msg_use_default_values_for_all_account_details"
+ retval=$?
+ if [ $retval -eq $DIALOG_ESC ]; then
+ return $SUCCESS
+ elif [ $retval -ne $DIALOG_OK ]; then
+ #
+ # Ask series of questions to pre-fill the editor screen
+ #
+ # Defaults used in each dialog should allow the user to
+ # simply hit ENTER to proceed, because cancelling any
+ # single dialog will cause them to be returned to the
+ # previous menu.
+ #
+
+ f_dialog_input_gecos user_gecos "$user_gecos" ||
+ return $FAILURE
+ if [ "$passwdtype" = "yes" ]; then
+ f_dialog_input_password user_password \
+ user_password_disable ||
+ return $FAILURE
+ fi
+ f_dialog_input_uid user_uid "$user_uid" ||
+ return $FAILURE
+ f_dialog_input_gid user_gid "$user_gid" ||
+ return $FAILURE
+ f_dialog_input_member_groups user_member_groups \
+ "$user_member_groups" || return $FAILURE
+ f_dialog_input_class user_class "$user_class" ||
+ return $FAILURE
+ f_dialog_input_expire_password user_password_expire \
+ "$user_password_expire" || return $FAILURE
+ f_dialog_input_expire_account user_account_expire \
+ "$user_account_expire" || return $FAILURE
+ f_dialog_input_home_dir user_home_dir \
+ "$user_home_dir" || return $FAILURE
+ if [ ! -d "$user_home_dir" ]; then
+ f_dialog_input_home_create user_home_create ||
+ return $FAILURE
+ if [ "$user_home_create" = "$msg_yes" ]; then
+ f_dialog_input_dotfiles_create \
+ user_dotfiles_create ||
+ return $FAILURE
+ fi
+ fi
+ f_dialog_input_shell user_shell "$user_shell" ||
+ return $FAILURE
+ fi
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_add $msg_user: $user_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_user_add "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Add/Exit
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ local cmd="pw useradd -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o \
+ "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_home_dir" ] &&
+ cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_member_groups" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o \
+ "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ if [ "$user_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ echo "$user_password" | f_eval_catch \
+ $funcname pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi || continue
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ] && f_user_copy_dotfiles "$user_name"
+
+ break # to success
+ ;;
+ 1) # Login (prompt for new login name)
+ f_dialog_input_name input "$user_name" ||
+ continue
+ if f_quietly pw usershow -n "$input" -u 1337; then
+ f_show_err "$msg_login_already_used" "$input"
+ continue
+ fi
+ user_name="$input"
+ title="$msg_add $msg_user: $user_name"
+ user_home_dir="${homeprefix%/}/$user_name"
+ ;;
+ 2) # Full Name
+ f_dialog_input_gecos user_gecos "$user_gecos" &&
+ [ ! "$user_gecos" ] && null_gecos=1 ;;
+ 3) # Password
+ f_dialog_input_password \
+ user_password user_password_disable ;;
+ 4) # User ID
+ f_dialog_input_uid user_uid "$user_uid" ;;
+ 5) # Group ID
+ f_dialog_input_gid user_gid "$user_gid" ;;
+ 6) # Member of Groups
+ f_dialog_input_member_groups \
+ user_member_groups "$user_member_groups" &&
+ [ ! "$user_member_groups" ] &&
+ null_members=1 ;;
+ 7) # Login Class
+ f_dialog_input_class user_class "$user_class" &&
+ [ ! "$user_class" ] && null_class=1 ;;
+ 8) # Password Expires On
+ f_dialog_input_expire_password \
+ user_password_expire "$user_password_expire" &&
+ [ ! "$user_password_expire" ] &&
+ no_password_expire=1 ;;
+ 9) # Account Expires On
+ f_dialog_input_expire_account \
+ user_account_expire "$user_account_expire" &&
+ [ ! "$user_account_expire" ] &&
+ no_account_expire=1 ;;
+ A) # Home Directory
+ f_dialog_input_home_dir \
+ user_home_dir "$user_home_dir" ;;
+ B) # Shell
+ f_dialog_input_shell user_shell "$user_shell" ;;
+ C) # Create Home Directory?
+ if [ "${user_home_create:-$msg_no}" != "$msg_no" ]
+ then
+ user_home_create="$msg_no"
+ else
+ user_home_create="$msg_yes"
+ fi ;;
+ D) # Create Dotfiles?
+ if [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ]
+ then
+ user_dotfiles_create="$msg_no"
+ else
+ user_dotfiles_create="$msg_yes"
+ fi ;;
+ esac
+ done
+ else
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Form the command
+ local cmd="pw useradd -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_member_groups" -o "$null_members" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ local retval err
+ if [ "$user_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ err=$( echo "$user_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_copy_dotfiles "$user_name"
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_login_added"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_user_delete [$user]
+#
+# Delete a user. If both $user (as a first argument) and $VAR_USER are unset or
+# NULL and we are running interactively, prompt the end-user to select a user
+# account from a list of those available. Variables that can be used to script
+# user input:
+#
+# VAR_USER [Optional if running interactively]
+# The user to delete. Ignored if given non-NULL first-argument.
+#
+# Returns success if the user account was successfully deleted.
+#
+f_user_delete()
+{
+ local funcname=f_user_delete
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_USER input "$1"
+
+ if f_interactive && [ ! "$input" ]; then
+ f_dialog_menu_user_list || return $SUCCESS
+ f_dialog_menutag_fetch input
+ [ "$input" = "X $msg_exit" ] && return $SUCCESS
+ elif [ ! "$input" ]; then
+ f_show_err "$msg_no_user_specified"
+ return $FAILURE
+ fi
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ if [ "$input" ] && ! f_input_user "$input"; then
+ f_show_err "$msg_login_not_found" "$input"
+ return $FAILURE
+ fi
+
+ local user_group_delete= user_home_delete=
+ f_getvar $VAR_USER_GROUP_DELETE:-\$msg_no user_group_delete
+ f_getvar $VAR_USER_HOME_DELETE:-\$msg_no user_home_delete
+
+ # Attempt to translate user GID into a group name
+ local user_group
+ if user_group=$( pw groupshow -g "$user_gid" 2> /dev/null ); then
+ user_group="${user_group%%:*}"
+ # Default to delete the primary group if no script-override and
+ # exists with same name as the user (same logic used by pw(8))
+ f_isset $VAR_USER_GROUP_DELETE ||
+ [ "$user_group" != "$user_name" ] ||
+ user_group_delete="$msg_yes"
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_delete $msg_user: $user_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_user_delete "$user_name" "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Delete/Exit
+ f_shell_escape "$user_uid" _user_uid
+
+ # Save group information in case pw(8) deletes it
+ # and we wanted to keep it (to be restored below)
+ if [ "${user_group_delete:-$msg_no}" = "$msg_no" ]
+ then
+ local v vars="gid members name password"
+ for v in $vars; do local group_$var; done
+ f_input_group "$user_group"
+
+ # Remove user-to-delete from group members
+ # NB: Otherwise group restoration could fail
+ local name length=0 _members=
+ while [ $length -ne ${#group_members} ]; do
+ name="${group_members%%,*}"
+ [ "$name" != "$user_name" ] &&
+ _members="$_members,$name"
+ length=${#group_members}
+ group_members="${group_members#*,}"
+ done
+ group_members="${_members#,}"
+
+ # Create escaped variables for f_eval_catch()
+ for v in $vars; do
+ local _group_$v
+ eval f_shell_escape \
+ \"\$group_$v\" _group_$v
+ done
+ fi
+
+ # Delete the user (if asked to delete home directory
+ # display [X]dialog notification to show activity)
+ local cmd="pw userdel -u '$_user_uid'"
+ if [ "$user_home_delete" = "$msg_yes" -a \
+ "$USE_XDIALOG" ]
+ then
+ local err
+ err=$(
+ exec 9>&1
+ f_eval_catch -e $funcname pw \
+ "%s -r" "$cmd" \
+ >&$DIALOG_TERMINAL_PASSTHRU_FD 2>&9 |
+ f_xdialog_info \
+ "$msg_deleting_home_directory"
+ )
+ [ ! "$err" ]
+ elif [ "$user_home_delete" = "$msg_yes" ]; then
+ f_dialog_info "$msg_deleting_home_directory"
+ f_eval_catch $funcname pw '%s -r' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi || continue
+
+ #
+ # pw(8) may conditionally delete the primary group,
+ # which may not be what is desired.
+ #
+ # If we've been asked to delete the group and pw(8)
+ # chose not to, delete it. Otherwise, if we're told
+ # to NOT delete the group, we may need to restore it
+ # since pw(8) doesn't have a flag to tell `userdel'
+ # to not delete the group.
+ #
+ # NB: If primary group and user have different names
+ # the group may not have been deleted (again, see PR
+ # 169471 and SVN r263114 for details).
+ #
+ if [ "${user_group_delete:-$msg_no}" != "$msg_no" ]
+ then
+ f_quietly pw groupshow -g "$user_gid" &&
+ f_eval_catch $funcname pw \
+ "pw groupdel -g '%s'" "$_user_gid"
+ elif ! f_quietly pw groupshow -g "$group_gid" &&
+ [ "$group_name" -a "$group_gid" ]
+ then
+ # Group deleted by pw(8), so restore it
+ local cmd="pw groupadd -n '$_group_name'"
+ cmd="$cmd -g '$_group_gid'"
+ cmd="$cmd -M '$_group_members'"
+
+ # Get the group password (pw(8) groupshow does
+ # NOT provide this (even if running privileged)
+ local group_password_enc
+ group_password_enc=$( getent group | awk -F: '
+ !/^[[:space:]]*(#|$)/ && \
+ $1 == ENVIRON["group_name"] && \
+ $3 == ENVIRON["group_gid"] && \
+ $4 == ENVIRON["group_members"] \
+ { print $2; exit }
+ ' )
+ if [ "$group_password_enc" ]; then
+ echo "$group_password_enc" |
+ f_eval_catch $funcname \
+ pw '%s -H 0' "$cmd"
+ else
+ f_eval_catch $funcname \
+ pw '%s -h -' "$cmd"
+ fi
+ fi
+
+ break # to success
+ ;;
+ 1) # Login (select different login from list)
+ f_dialog_menu_user_list "$user_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_user "$mtag"; then
+ f_show_err "$msg_login_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_user "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ title="$msg_delete $msg_user: $user_name"
+ ;;
+ C) # Delete Primary Group?
+ if [ "${user_group_delete:-$msg_no}" != "$msg_no" ]
+ then
+ user_group_delete="$msg_no"
+ else
+ user_group_delete="$msg_yes"
+ fi ;;
+ D) # Delete Home Directory?
+ if [ "${user_home_delete:-$msg_no}" != "$msg_no" ]
+ then
+ user_home_delete="$msg_no"
+ else
+ user_home_delete="$msg_yes"
+ fi ;;
+ esac
+ done
+ else
+ f_shell_escape "$user_uid" _user_uid
+
+ # Save group information in case pw(8) deletes it
+ # and we wanted to keep it (to be restored below)
+ if [ "${user_group_delete:-$msg_no}" = "$msg_no" ]; then
+ local v vars="gid members name password"
+ for v in $vars; do local group_$v; done
+ f_input_group "$user_group"
+
+ # Remove user we're about to delete from group members
+ # NB: Otherwise group restoration could fail
+ local name length=0 _members=
+ while [ $length -ne ${#group_members} ]; do
+ name="${group_members%%,*}"
+ [ "$name" != "$user_name" ] &&
+ _members="$_members,$name"
+ length=${#group_members}
+ group_members="${group_members#*,}"
+ done
+ group_members="${_members#,}"
+
+ # Create escaped variables for later f_eval_catch()
+ for v in $vars; do
+ local _group_$v
+ eval f_shell_escape \"\$group_$v\" _group_$v
+ done
+ fi
+
+ # Delete the user (if asked to delete home directory
+ # display [X]dialog notification to show activity)
+ local err cmd="pw userdel -u '$_user_uid'"
+ if [ "$user_home_delete" = "$msg_yes" -a "$USE_XDIALOG" ]; then
+ err=$(
+ exec 9>&1
+ f_eval_catch -de $funcname pw \
+ '%s -r' "$cmd" 2>&9 | f_xdialog_info \
+ "$msg_deleting_home_directory"
+ )
+ [ ! "$err" ]
+ elif [ "$user_home_delete" = "$msg_yes" ]; then
+ f_dialog_info "$msg_deleting_home_directory"
+ f_eval_catch -k err $funcname pw '%s -r' "$cmd"
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ local retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+
+ #
+ # pw(8) may conditionally delete the primary group, which may
+ # not be what is desired.
+ #
+ # If we've been asked to delete the group and pw(8) chose not
+ # to, delete it. Otherwise, if we're told to NOT delete the
+ # group, we may need to restore it since pw(8) doesn't have a
+ # flag to tell `userdel' to not delete the group.
+ #
+ # NB: If primary group and user have different names the group
+ # may not have been deleted (again, see PR 169471 and SVN
+ # r263114 for details).
+ #
+ if [ "${user_group_delete:-$msg_no}" != "$msg_no" ]
+ then
+ f_quietly pw groupshow -g "$user_gid" &&
+ f_eval_catch $funcname pw \
+ "pw groupdel -g '%s'" "$_user_gid"
+ elif ! f_quietly pw groupshow -g "$group_gid" &&
+ [ "$group_name" -a "$group_gid" ]
+ then
+ # Group deleted by pw(8), so restore it
+ local cmd="pw groupadd -n '$_group_name'"
+ cmd="$cmd -g '$_group_gid'"
+ cmd="$cmd -M '$_group_members'"
+ local group_password_enc
+ group_password_enc=$( getent group | awk -F: '
+ !/^[[:space:]]*(#|$)/ && \
+ $1 == ENVIRON["group_name"] && \
+ $3 == ENVIRON["group_gid"] && \
+ $4 == ENVIRON["group_members"] \
+ { print $2; exit }
+ ' )
+ if [ "$group_password_enc" ]; then
+ echo "$group_password_enc" |
+ f_eval_catch $funcname \
+ pw '%s -H 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ fi
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_login_deleted"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_user_edit [$user]
+#
+# Modify a login account. If both $user (as a first argument) and $VAR_USER are
+# unset or NULL and we are running interactively, prompt the end-user to select
+# a login account from a list of those available. Variables that can be used to
+# script user input:
+#
+# VAR_USER [Optional if running interactively]
+# The login to modify. Ignored if given non-NULL first-argument.
+# VAR_USER_ACCOUNT_EXPIRE [Optional]
+# The account expiration time. Format is similar to
+# VAR_USER_PASSWORD_EXPIRE variable below. If unset, account
+# expiry is unchanged. If set but NULL, account expiration is
+# disabled (same as setting a value of `0').
+# VAR_USER_DOTFILES_CREATE [Optional]
+# If non-NULL, re-populate the user's home directory with the
+# template files found in $udotdir (`/usr/share/skel' default).
+# VAR_USER_GECOS [Optional]
+# Often the full name of the account holder. If unset, the GECOS
+# field is unmodified. If set but NULL, the field is blanked.
+# VAR_USER_GID [Optional]
+# Numerical primary-group ID to set. If NULL or unset, the group
+# ID is unchanged.
+# VAR_USER_GROUPS [Optional]
+# Comma-separated list of additional groups to which the user is
+# a member of. If set but NULL, group memberships are reset (this
+# login will not be a member of any additional groups besides the
+# primary group). If unset, group membership is unmodified.
+# VAR_USER_HOME [Optional]
+# The home directory to set. If NULL or unset, the home directory
+# is unchanged.
+# VAR_USER_HOME_CREATE [Optional]
+# If non-NULL, create the user's home directory if it doesn't
+# already exist.
+# VAR_USER_LOGIN_CLASS [Optional]
+# Login class to set. If unset, the login class is unchanged. If
+# set but NULL, the field is blanked.
+# VAR_USER_PASSWORD [Optional]
+# Unencrypted password to set. If unset, the login password is
+# unmodified. If set but NULL, password authentication for the
+# login is disabled.
+# VAR_USER_PASSWORD_EXPIRE [Optional]
+# The password expiration time. Format of the date is either a
+# UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where
+# dd is the day, mmm is the month in either numeric or alphabetic
+# format, and yy[yy] is either a two or four digit year. This
+# variable also accepts a relative date in the form of +n[mhdwoy]
+# where n is a decimal, octal (leading 0) or hexadecimal (leading
+# 0x) digit followed by the number of Minutes, Hours, Days,
+# Weeks, Months or Years from the current date at which the
+# expiration time is to be set. If unset, password expiry is
+# unchanged. If set but NULL, password expiration is disabled
+# (same as setting a value of `0').
+# VAR_USER_SHELL [Optional]
+# Path to login shell to set. If NULL or unset, the shell is
+# unchanged.
+# VAR_USER_UID [Optional]
+# Numerical user ID to set. If NULL or unset, the user ID is
+# unchanged.
+#
+# Returns success if the user account was successfully modified.
+#
+f_user_edit()
+{
+ local funcname=f_user_edit
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_USER input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as UID
+ # instead of name. Work-around is to also pass `-u UID' at the same
+ # time (the UID is ignored in this case, so any UID will do).
+ #
+ if [ "$input" ] && ! f_quietly pw usershow -n "$input" -u 1337; then
+ f_show_err "$msg_login_not_found" "$input"
+ return $FAILURE
+ fi
+
+ if f_interactive && [ ! "$input" ]; then
+ f_dialog_menu_user_list || return $SUCCESS
+ f_dialog_menutag_fetch input
+ [ "$input" = "X $msg_exit" ] && return $SUCCESS
+ elif [ ! "$input" ]; then
+ f_show_err "$msg_no_user_specified"
+ return $FAILURE
+ fi
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ if ! f_input_user "$input"; then
+ f_show_err "$msg_login_not_found" "$input"
+ return $FAILURE
+ fi
+
+ #
+ # Override values probed by f_input_user() with desired values
+ #
+ f_isset $VAR_USER_GID && f_getvar $VAR_USER_GID user_gid
+ f_isset $VAR_USER_HOME && f_getvar $VAR_USER_HOME user_home_dir
+ f_isset $VAR_USER_SHELL && f_getvar $VAR_USER_SHELL user_shell
+ f_isset $VAR_USER_UID && f_getvar $VAR_USER_UID user_uid
+ local user_dotfiles_create= user_home_create=
+ f_getvar $VAR_USER_DOTFILES_CREATE:+\$msg_yes user_dotfiles_create
+ f_getvar $VAR_USER_HOME_CREATE:+\$msg_yes user_home_create
+ local no_account_expire=
+ if f_isset $VAR_USER_ACCOUNT_EXPIRE; then
+ f_getvar $VAR_USER_ACCOUNT_EXPIRE user_account_expire
+ [ "$user_account_expire" ] || no_account_expire=1
+ fi
+ local null_gecos=
+ if f_isset $VAR_USER_GECOS; then
+ f_getvar $VAR_USER_GECOS user_gecos
+ [ "$user_gecos" ] || null_gecos=1
+ fi
+ local null_members=
+ if f_isset $VAR_USER_GROUPS; then
+ f_getvar $VAR_USER_GROUPS user_member_groups
+ [ "$user_member_groups" ] || null_members=1
+ fi
+ local null_class=
+ if f_isset $VAR_USER_LOGIN_CLASS; then
+ f_getvar $VAR_USER_LOGIN_CLASS user_class
+ [ "$user_class" ] || null_class=1
+ fi
+ local user_password_disable=
+ if f_isset $VAR_USER_PASSWORD; then
+ f_getvar $VAR_USER_PASSWORD user_password
+ [ "$user_password" ] || user_password_disable=1
+ fi
+ local no_password_expire=
+ if f_isset $VAR_USER_PASSWORD_EXPIRE; then
+ f_getvar $VAR_USER_PASSWORD_EXPIRE user_password_expire
+ [ "$user_password_expire" ] || no_password_expire=1
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_edit_view $msg_user: $user_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_user_edit "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Save/Exit
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ local cmd="pw usermod -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o \
+ "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_home_dir" ] &&
+ cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_member_groups" -o "$null_members" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o \
+ "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ if [ "$user_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ echo "$user_password" | f_eval_catch \
+ $funcname pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi || continue
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ] && f_user_copy_dotfiles "$user_name"
+
+ break # to success
+ ;;
+ 1) # Login (select different login from list)
+ f_dialog_menu_user_list "$user_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_user "$mtag"; then
+ f_show_err "$msg_login_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_user "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ title="$msg_edit_view $msg_user: $user_name"
+ ;;
+ 2) # Full Name
+ f_dialog_input_gecos user_gecos "$user_gecos" &&
+ [ ! "$user_gecos" ] && null_gecos=1 ;;
+ 3) # Password
+ f_dialog_input_password \
+ user_password user_password_disable ;;
+ 4) # User ID
+ f_dialog_input_uid user_uid "$user_uid" ;;
+ 5) # Group ID
+ f_dialog_input_gid user_gid "$user_gid" ;;
+ 6) # Member of Groups
+ f_dialog_input_member_groups \
+ user_member_groups "$user_member_groups" &&
+ [ ! "$user_member_groups" ] &&
+ null_members=1 ;;
+ 7) # Login Class
+ f_dialog_input_class user_class "$user_class" &&
+ [ ! "$user_class" ] && null_class=1 ;;
+ 8) # Password Expires On
+ f_dialog_input_expire_password \
+ user_password_expire "$user_password_expire" &&
+ [ ! "$user_password_expire" ] &&
+ no_password_expire=1 ;;
+ 9) # Account Expires On
+ f_dialog_input_expire_account \
+ user_account_expire "$user_account_expire" &&
+ [ ! "$user_account_expire" ] &&
+ no_account_expire=1 ;;
+ A) # Home Directory
+ f_dialog_input_home_dir \
+ user_home_dir "$user_home_dir" ;;
+ B) # Shell
+ f_dialog_input_shell user_shell "$user_shell" ;;
+ C) # Create Home Directory?
+ if [ "${user_home_create:-$msg_no}" != "$msg_no" ]
+ then
+ user_home_create="$msg_no"
+ else
+ user_home_create="$msg_yes"
+ fi ;;
+ D) # Create Dotfiles?
+ if [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ]
+ then
+ user_dotfiles_create="$msg_no"
+ else
+ user_dotfiles_create="$msg_yes"
+ fi ;;
+ esac
+ done
+ else
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Form the command
+ local cmd="pw usermod -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_member_groups" -o "$null_members" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ local retval err
+ if [ "$user_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ err=$( echo "$user_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_copy_dotfiles "$user_name"
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_login_updated"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/user.subr
+
+fi # ! $_USERMGMT_USER_SUBR
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/share/user_input.subr b/contrib/bsddialog/bsdconfig/usermgmt/share/user_input.subr
new file mode 100644
index 000000000000..4f2342ab4b23
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/share/user_input.subr
@@ -0,0 +1,1341 @@
+if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/user_input.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+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 $var_to_set $user
+#
+# Get a list of additional groups $user is a member of in group(5).
+#
+f_get_member_groups()
+{
+ f_replaceall "$( pw groupshow -a | awk -F: -v user="$2" '{
+ if (!split($4, users, /,/)) next
+ for (u in users) if (users[u] == user) { print $1; next }
+ }' )" "[$NL]" "," "$1"
+}
+
+# f_input_user $user
+#
+# Given $user name or id, create the environment variables user_name, user_uid,
+# user_gid, user_class, user_password_expire, user_account_expire, user_gecos,
+# user_home_dir, user_shell, and user_member_groups (and user_password is reset
+# to NULL).
+#
+f_input_user()
+{
+ local funcname=f_input_user
+ local user="$1"
+
+ f_dprintf "$funcname: Getting info for user \`%s'" "$user"
+ eval "$( pw usershow "$user" 2> /dev/null | awk -F: '
+ function set_value(var, value) {
+ gsub(/'\''/, "'\''\\'\'\''", value)
+ printf "user_%s='\'%s\''\n", var, value
+ }
+ {
+ found = $1 != ""
+ set_value("name", $1 )
+ set_value("password", "" )
+ set_value("uid", $3 )
+ set_value("gid", $4 )
+ set_value("class", $5 )
+ set_value("password_expire", $6 )
+ set_value("account_expire", $7 )
+ set_value("gecos", $8 )
+ set_value("home_dir", $9 )
+ set_value("shell", $10)
+ exit
+ }
+ END { if (!found) print "false" }' )"
+ local retval=$?
+
+ f_dprintf "$funcname: Getting group memberships for user \`%s'" "$user"
+ f_get_member_groups user_member_groups "$user"
+
+ return $retval
+}
+
+# f_dialog_menu_user_list [$default]
+#
+# Allows the user to select a login from a list. Optionally, if present and
+# non-NULL, initially highlight $default user.
+#
+f_dialog_menu_user_list()
+{
+ local prompt=
+ local menu_list="
+ 'X $msg_exit' ''
+ " # END-QUOTE
+ local defaultitem="$1"
+ local hline="$hline_alnum_punc_tab_enter"
+
+ # Add users from passwd(5)
+ menu_list="$menu_list $( pw usershow -a | awk -F: '
+ function mprint(tag, item) {
+ gsub(/'\''/, "'\''\\'\'\''", tag)
+ gsub(/'\''/, "'\''\\'\'\''", item)
+ printf "'\'%s\'\ \'%s\''\n", tag, item
+ }
+ !/^[[:space:]]*(#|$)/ { mprint($1, $8) }
+ ' )"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$menu_choice"
+ return $retval
+}
+
+# f_dialog_input_member_groups $var_to_set [$member_groups]
+#
+# Allows the user to edit group memberships for a given user. If the user does
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_member_groups()
+{
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_member_of_groups"
+ local __menu_list="
+ 'X' '$msg_continue'
+ '1' '$msg_select_groups_from_list'
+ '2' '$msg_enter_groups_manually'
+ " # END-QUOTE
+ local __defaultitem=
+ local __hline="$hline_alnum_space_tab_enter"
+
+ local __mheight __mwidth __mrows
+ eval f_dialog_menu_size __mheight __mwidth __mrows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__menu_list
+
+ local __menu_choice __retval
+ while :; do
+ __menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$__defaultitem\" \
+ --menu \"\$__prompt\" \
+ $__mheight $__mwidth $__mrows \
+ $__menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __menu_choice
+ __defaultitem="$__menu_choice"
+ f_dprintf "retval=%u menu_choice=[%s]" \
+ $__retval "$__menu_choice"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
+
+ local __member_groups
+ case "$__menu_choice" in
+ X) # Exit
+ break ;;
+ 1) # Select Groups from a list
+ local __check_list= # Calculated below
+ local __group_list __g __grp __length=0
+ __group_list=$( pw groupshow -a |
+ awk -F: '!/^[[:space:]]*(#|$)/{print $1}' )
+ while [ $__length -ne ${#__group_list} ]; do
+ __g="${__group_list%%$NL*}" # First line
+ f_shell_escape "$__g" __grp
+
+ # Format of a checklist entry: tag item status
+ # NB: Setting both tag/item to group name below
+ __check_list="$__check_list '$__grp' '$__grp'"
+ case "$__input" in
+ "$__g"|"$__g",*|*,"$__g",*|*,"$__g")
+ __check_list="$__check_list on" ;;
+ *)
+ __check_list="$__check_list off"
+ esac
+
+ __length=${#__group_list}
+ __group_list="${__group_list#*$NL}" # Kill line
+ done
+
+ local __cheight __cwidth __crows
+
+ eval f_dialog_checklist_size \
+ __cheight __cwidth __crows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__check_list
+ __member_groups=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --separate-output \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --checklist \"\$__prompt\" \
+ $__cheight $__cwidth $__crows \
+ $__check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || continue
+ # Return to previous menu if user either
+ # pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize __member_groups
+
+ #
+ # Convert the newline separated list into a comma-
+ # separated one so that if the user switches over to
+ # manual editing, list reflects checklist selections
+ #
+ f_replaceall "$__member_groups" "[$NL]" "," __input
+ ;;
+ 2) # Enter Groups manually
+ local __prompt2="$msg_groups"
+ __prompt2="$__prompt2 ($msg_separated_by_commas)"
+
+ f_dialog_input __member_groups \
+ "$__prompt2" "$__input" \
+ "$hline_num_tab_enter" || continue
+ # Return to previous menu if user either
+ # pressed ESC or chose Cancel/No
+
+ #
+ # Validate each of the groups the user has entered
+ #
+ local __all_groups_valid=1 __grp __grp_list
+ f_replaceall "$__member_groups" "," " " __grp_list
+ for __grp in $__grp_list; do
+ if ! f_quietly pw groupshow -n "$__grp"; then
+ f_show_msg "$msg_group_not_found" \
+ "$__grp"
+ __all_groups_valid=
+ break
+ fi
+ done
+ [ "$__all_groups_valid" ] || continue
+
+ __input="$__member_groups"
+ ;;
+ esac
+ done
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_name $var_to_set [$name]
+#
+# Allows the user to enter a new username for a given user. If the user does
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_name()
+{
+ local __var_to_set="$1" __name="$2"
+
+ #
+ # Loop until the user provides taint-free/valid input
+ #
+ local __input="$__name"
+ while :; do
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_login" "$__input" \
+ "$hline_alnum_tab_enter" || return $?
+
+ # Check for no-change
+ if [ "$__input" = "$__name" ]; then
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+ fi
+
+ # Check for NULL entry
+ if [ ! "$__input" ]; then
+ f_show_msg "$msg_login_is_empty"
+ continue
+ fi
+
+ # Check for invalid entry
+ case "$__input" in [!a-zA-Z]*)
+ f_show_msg "$msg_login_must_start_with_letter"
+ continue
+ esac
+
+ # Check for duplicate entry
+ if f_quietly pw usershow -n "$__input"; then
+ f_show_msg "$msg_login_already_used" "$__input"
+ continue
+ fi
+
+ setvar "$__var_to_set" "$__input"
+ break
+ done
+
+ return $DIALOG_OK
+}
+
+# f_dialog_input_password $var_to_set $dvar_to_set
+#
+# Prompt the user to enter a password (twice). If the user does not cancel or
+# press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the
+# user cancels or enters a NULL password (twice), they are given the choice to
+# disable password authentication for the given login, wherein $dvar_to_set has
+# a value of 1 to indicate password authentication should be disabled.
+#
+f_dialog_input_password()
+{
+ local __var_to_set="$1" __dvar_to_set="$2"
+ local __prompt1="$msg_password"
+ local __prompt2="$msg_reenter_password"
+ local __hline="$hline_alnum_punc_tab_enter"
+
+ local __height1 __width1
+ f_dialog_inputbox_size __height1 __width1 \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt1" \
+ "" \
+ "$__hline"
+ local __height2 __width2
+ f_dialog_inputbox_size __height2 __width2 \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt2" \
+ "" \
+ "$__hline"
+
+ #
+ # Loop until the user provides taint-free/valid input
+ #
+ local __retval __password1 __password2
+ while :; do
+ __password1=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$__hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$__prompt1" \
+ $__height1 $__width1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Return if user either pressed ESC or chose Cancel/No
+ debug= f_dialog_line_sanitize __password1
+
+ __password2=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$__hline" \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --insecure \
+ --passwordbox "$__prompt2" \
+ $__height2 $__width2 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Return if user either pressed ESC or chose Cancel/No
+ debug= f_dialog_line_sanitize __password2
+
+ # 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"
+ __retval=$?
+ if [ $__retval -eq $DIALOG_ESC ]; then
+ return $__retval
+ elif [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__dvar_to_set" 1
+ else
+ continue # back to password prompt
+ fi
+ else
+ setvar "$__dvar_to_set" ""
+ fi
+
+ setvar "$__var_to_set" "$__password1"
+ break
+ done
+
+ return $DIALOG_OK
+}
+
+# f_dialog_input_gecos $var_to_set [$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 $var_to_set variable will hold the
+# newly-configured value upon return.
+#
+f_dialog_input_gecos()
+{
+ local __var_to_set="$1" __input="$2"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_full_name" "$__input" \
+ "$hline_alnum_punc_tab_enter" || return $?
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_uid $var_to_set [$uid]
+#
+# Allow the user to enter a new UID for a given user. If the user does not
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_uid()
+{
+ local __var_to_set="$1" __input="$2"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_user_id_leave_empty_for_default" \
+ "$__input" "$hline_num_tab_enter" || return $?
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_gid $var_to_set [$gid]
+#
+# Allow the user to enter a new primary GID for a given user. If the user does
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_gid()
+{
+ local __var_to_set="$1" __input="$2"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_group_id_leave_empty_for_default" \
+ "$__input" "$hline_num_tab_enter" || return $?
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_class $var_to_set [$class]
+#
+# Allow the user to enter a new login class for a given user. If the user does
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_class()
+{
+ local __var_to_set="$1" __input="$2"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_login_class" "$__input" \
+ "$hline_alnum_tab_enter" || return $?
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_expire_password $var_to_set [$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 $var_to_set variable will hold the newly-configured value
+# upon return.
+#
+f_dialog_input_expire_password()
+{
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_password_expires_on"
+ local __menu_list="
+ '1' '$msg_password_does_not_expire'
+ '2' '$msg_edit_date_time_with_a_calendar'
+ '3' '$msg_enter_value_manually'
+ " # END-QUOTE
+ local __defaultitem= # Calculated below
+ local __hline="$hline_num_arrows_tab_enter"
+
+ local __mheight __mwidth __mrows
+ eval f_dialog_menu_size __mheight __mwidth __mrows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__menu_list
+ local __cheight __cwidth
+ f_dialog_calendar_size __cheight __cwidth \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt" \
+ "$__hline"
+ local __theight __twidth
+ f_dialog_timebox_size __theight __twidth \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt" \
+ "$__hline"
+
+ #
+ # Loop until the user provides taint-free/cancellation-free input
+ #
+ local __retval __date_type
+ while :; do
+ __date_type=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --default-item \"\$__defaultitem\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$__prompt\" \
+ $__mheight $__mwidth $__mrows \
+ $__menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __date_type
+ __defaultitem="$__date_type"
+ f_dprintf "retval=%u date_type=[%s]" $__retval "$__date_type"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || 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 __seconds="$__input"
+ { f_isinteger "$__seconds" && [ $__seconds -gt 0 ]; } ||
+ __seconds=
+ __input_date=$( date -j -f "%s" -- "$__seconds" \
+ "+%d %m %Y" 2> /dev/null )
+ __ret_date=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --calendar \"\$__prompt\" \
+ $__cheight $__cwidth \
+ $__input_date \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __ret_date
+ f_dprintf "retval=%u ret_date=[%s]" \
+ $__retval "$__ret_date"
+
+ # Return to menu if either ESC or Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || continue
+
+ __input_time=
+ [ "$__seconds" ] && __input_time=$( date -j \
+ -f %s -- "$__input" "+%H %M %S" 2> /dev/null )
+ __ret_time=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --timebox \"\$__prompt\" \
+ $__theight $__twidth \
+ $__input_time \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __ret_time
+ f_dprintf "retval=%u ret_time=[%s]" \
+ $__retval "$__ret_time"
+
+ # Return to menu if either ESC or Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || continue
+
+ __input=$( date -j -f "%d/%m/%Y %T" -- \
+ "$__ret_date $__ret_time" +%s 2> /dev/null )
+ f_dprintf "input=[%s]" "$__input"
+ break ;;
+
+ 3) # Enter value manually
+ local __msg __new_input
+ f_sprintf __msg "$msg_password_expire_manual_edit" \
+ "$( date -r 0 "+%c %Z" )"
+
+ # Return to menu if either ESC or Cancel/No
+ f_dialog_input __new_input \
+ "$__msg" "$__input" "$__hline" || continue
+
+ __input="$__new_input"
+ f_dprintf "input=[%s]" "$__input"
+ break ;;
+
+ esac
+
+ done # Loop forever
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_expire_account $var_to_set [$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 $var_to_set variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_expire_account()
+{
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_account_expires_on"
+ local __menu_list="
+ '1' '$msg_account_does_not_expire'
+ '2' '$msg_edit_date_time_with_a_calendar'
+ '3' '$msg_enter_value_manually'
+ " # END-QUOTE
+ local __defaultitem= # Calculated below
+ local __hline="$hline_num_arrows_tab_enter"
+
+ local __mheight __mwidth __mrows
+ eval f_dialog_menu_size __mheight __mwidth __mrows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__menu_list
+ local __cheight __cwidth
+ f_dialog_calendar_size __cheight __cwidth \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt" \
+ "$__hline"
+ local __theight __twidth
+ f_dialog_timebox_size __theight __twidth \
+ "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" \
+ "$__prompt" \
+ "$__hline"
+
+ #
+ # Loop until the user provides taint-free/cancellation-free input
+ #
+ local __retval __date_type
+ while :; do
+ __date_type=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --default-item \"\$__defaultitem\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$__prompt\" \
+ $__mheight $__mwidth $__mrows \
+ $__menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __date_type
+ __defaultitem="$__date_type"
+ f_dprintf "retval=%u date_type=[%s]" $__retval "$__date_type"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || 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 __seconds="$__input"
+ { f_isinteger "$__seconds" && [ $__seconds -gt 0 ]; } ||
+ __seconds=
+ __input_date=$( date -j -f "%s" -- "$__seconds" \
+ "+%d %m %Y" 2> /dev/null )
+ __ret_date=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --calendar \"\$__prompt\" \
+ $__cheight $__cwidth \
+ $__input_date \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __ret_date
+ f_dprintf "retval=%u ret_date=[%s]" \
+ $__retval "$__ret_date"
+
+ # Return to menu if either ESC or Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || continue
+
+ __input_time=
+ [ "$__seconds" ] && __input_time=$( date -j \
+ -f %s -- "$__input" "+%H %M %S" 2> /dev/null )
+ __ret_time=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --timebox \"\$__prompt\" \
+ $__theight $__twidth \
+ $__input_time \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ __retval=$?
+ f_dialog_data_sanitize __ret_time
+ f_dprintf "retval=%u ret_time=[%s]" \
+ $__retval "$__ret_time"
+
+ # Return to menu if either ESC or Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || continue
+
+ __input=$( date -j -f "%d/%m/%Y %T" -- \
+ "$ret_date $ret_time" +%s 2> /dev/null )
+ f_dprintf "input=[%s]" "$__input"
+ break ;;
+
+ 3) # Enter value manually
+ local __msg __new_input
+ f_sprintf __msg "$msg_account_expire_manual_edit" \
+ "$( date -r 0 "+%c %Z" )"
+
+ # Return to menu if either ESC or Cancel/No
+ f_dialog_input __new_input \
+ "$__msg" "$__input" "$__hline" || continue
+
+ __input="$__new_input"
+ f_dprintf "input=[%s]" "$__input"
+ break ;;
+
+ esac
+
+ done # Loop forever
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_home_dir $var_to_set [$home_dir]
+#
+# Allow the user to enter a new home directory for a given login. If the user
+# does not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
+#
+f_dialog_input_home_dir()
+{
+ local __var_to_set="$1" __input="$2"
+
+ # Return if user has either pressed ESC or chosen Cancel/No
+ f_dialog_input __input "$msg_home_directory" "$__input" \
+ "$hline_alnum_punc_tab_enter" || return $?
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_input_home_create $var_to_set
+#
+# Prompt the user to confirm creation of a given login's home directory. If the
+# user does not cancel (by choosing "No") or press ESC, the $var_to_set
+# 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 __var_to_set="$1"
+
+ f_dialog_yesno "$msg_create_home_directory"
+ local __retval=$?
+
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
+ else
+ setvar "$__var_to_set" "$msg_no"
+ fi
+
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_group_delete $var_to_set [$group]
+#
+# Prompt the user to confirm deletion of a given login's primary group. If the
+# user does not cancel (by choosing "No") or press ESC, the $var_to_set
+# 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 __var_to_set="$1" __group="$2"
+
+ if f_isinteger "$__group"; then
+ if [ $__group -lt 1000 ]; then
+ f_dialog_noyes "$msg_delete_primary_group"
+ else
+ f_dialog_yesno "$msg_delete_primary_group"
+ fi
+ elif [ "$__group" ]; then
+ local __gid=0
+ __gid=$( pw groupshow "$__group" | 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
+ local __retval=$?
+
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
+ else
+ setvar "$__var_to_set" "$msg_no"
+ fi
+
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_home_delete $var_to_set
+#
+# Prompt the user to confirm deletion of a given login's home directory. If the
+# user does not cancel (by choosing "No") or press ESC, the $var_to_set
+# 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 __var_to_set="$1"
+
+ f_dialog_yesno "$msg_delete_home_directory"
+ local __retval=$?
+
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
+ else
+ setvar "$__var_to_set" "$msg_no"
+ fi
+
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_dotfiles_create $var_to_set
+#
+# Prompt the user to confirm population of a given login's home directory with
+# sample dotfiles. If the user does not cancel (by choosing "No") or press ESC,
+# the $var_to_set 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 __var_to_set="$1"
+
+ f_dialog_yesno "$msg_create_dotfiles"
+ local __retval=$?
+
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
+ else
+ setvar "$__var_to_set" "$msg_no"
+ fi
+
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+}
+
+# f_dialog_input_shell $var_to_set [$shell]
+#
+# Allow the user to select a new shell for a given login. If the user does not
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
+# value upon return.
+#
+f_dialog_input_shell()
+{
+ local __funcname=f_dialog_input_shell
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_select_login_shell"
+ local __radio_list= # Calculated below
+ local __defaultitem="$2"
+ local __hline="$hline_arrows_space_tab_enter"
+
+ #
+ # Generate the radiolist of shells
+ #
+ local __shell_list __s __shell __length=0
+ f_eval_catch -k __shell_list $__funcname awk "awk '%s' \"%s\"" \
+ '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" || return $FAILURE
+ while [ $__length -ne ${#__shell_list} ]; do
+ __s="${__shell_list%%$NL*}" # First line
+ f_shell_escape "$__s" __shell
+
+ # Format of a radiolist entry: tag item status
+ if [ "$__s" = "$__input" ]; then
+ __radio_list="$__radio_list '$__shell' '' 'on'"
+ else
+ __radio_list="$__radio_list '$__shell' '' 'off'"
+ fi
+
+ __length=${#__shell_list}
+ __shell_list="${__shell_list#*$NL}" # Kill line
+ done
+
+ local __height __width __rows
+ eval f_dialog_radiolist_size __height __width __rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__radio_list
+
+ __input=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$__defaultitem\" \
+ --radiolist \"\$__prompt\" \
+ $__height $__width $__rows \
+ $__radio_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Return if user either pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize __input
+
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
+
+# f_dialog_menu_user_add [$defaultitem]
+#
+# Present a menu detailing the properties of a login that is about to be added.
+# The user's menu choice is available using f_dialog_menutag_fetch(). Returns
+# success unless the user chose Cancel or pressed ESC. Data to display is taken
+# from environment variables user_account_expire, user_class,
+# user_dotfiles_create, user_gecos, user_gid, user_home_create, user_home_dir,
+# user_member_groups, user_name, user_password_expire, user_shell, and
+# user_uid. If $defaultitem is present and non-NULL, initially highlight the
+# item in the menu.
+#
+f_dialog_menu_user_add()
+{
+ local funcname=f_dialog_menu_user_add
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Attempt to convert numeric UNIX time to calendar date/time
+ local user_account_expires_on=
+ if f_isinteger "$user_account_expire"; then
+ [ "$user_account_expire" -ne 0 ] && user_account_expires_on=$(
+ date -r "$user_account_expire" "+%F %T %Z"
+ )
+ else
+ user_account_expires_on="$user_account_expire"
+ fi
+ local user_password_expires_on=
+ if f_isinteger "$user_password_expire"; then
+ [ $user_password_expire -ne 0 ] && user_password_expires_on=$(
+ date -r "$user_password_expire" "+%F %T %Z"
+ )
+ else
+ user_password_expires_on="$user_password_expire"
+ fi
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in account_expires_on class dotfiles_create gecos gid \
+ home_create home_dir member_groups name password_expires_on \
+ shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Attempt to translate a numeric GID into `number (name)'
+ if f_isinteger "$_user_gid"; then
+ local _user_group
+ _user_group=$( pw groupshow -g "$_user_gid" 2> /dev/null ) &&
+ _user_group="${_user_group%%:*}" &&
+ f_shell_escape "$_user_gid ($_user_group)" _user_gid
+ fi
+
+ menu_list="
+ 'X' '$msg_add/$msg_exit'
+ '1' '$msg_login: $_user_name'
+ '2' '$msg_full_name: $_user_gecos'
+ '3' '$msg_password: -----'
+ '4' '$msg_user_id: $_user_uid'
+ '5' '$msg_group_id: $_user_gid'
+ '6' '$msg_member_of_groups: $_user_member_groups'
+ '7' '$msg_login_class: $_user_class'
+ '8' '$msg_password_expires_on: $_user_password_expires_on'
+ '9' '$msg_account_expires_on: $_user_account_expires_on'
+ 'A' '$msg_home_directory: $_user_home_dir'
+ 'B' '$msg_shell: $_user_shell'
+ " # END-QUOTE
+ case "$user_home_dir" in
+ /|/nonexistent|/var/empty) menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ '-' '$msg_create_dotfiles: $msg_n_a'
+ " # END-QUOTE
+ ;;
+ *) if [ -d "$user_home_dir" ]; then menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ 'C' '$msg_create_home_directory: ${_user_home_create:-$msg_no}'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ fi
+ esac
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --keep-tite \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_user_delete $user [$defaultitem]
+#
+# Present a menu detailing the properties of a login that is about to be
+# deleted. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is populated automatically from the system accounting database for the given
+# $user argument with the exception of two environment variables:
+# user_group_delete and user_home_delete. If $defaultitem is present and non-
+# NULL, initially highlight the item in the menu.
+#
+f_dialog_menu_user_delete()
+{
+ local prompt="$msg_delete_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$2"
+ local hline="$hline_arrows_tab_enter"
+
+ local user_name user_password user_uid user_gid user_class
+ local user_password_expire user_account_expire user_gecos
+ local user_home_dir user_shell user_member_groups
+ f_input_user "$1"
+
+ # Attempt to convert numeric UNIX time to calendar date/time
+ local user_account_expires_on=
+ if f_isinteger "$user_account_expire"; then
+ [ "$user_account_expire" -ne 0 ] && user_account_expires_on=$(
+ date -r "$user_account_expire" "+%F %T %Z"
+ )
+ else
+ user_account_expires_on="$user_account_expire"
+ fi
+ local user_password_expires_on=
+ if f_isinteger "$user_password_expire"; then
+ [ $user_password_expire -ne 0 ] && user_password_expires_on=$(
+ date -r "$user_password_expire" "+%F %T %Z"
+ )
+ else
+ user_password_expires_on="$user_password_expire"
+ fi
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in account_expires_on class gecos gid group_delete \
+ home_delete home_dir member_groups name password_expires_on \
+ shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Attempt to translate a numeric GID into `number (name)'
+ if f_isinteger "$_user_gid"; then
+ local _user_group
+ _user_group=$( pw groupshow -g "$_user_gid" 2> /dev/null ) &&
+ _user_group="${_user_group%%:*}" &&
+ f_shell_escape "$_user_gid ($_user_group)" _user_gid
+ fi
+
+ menu_list="
+ 'X' '$msg_delete/$msg_exit'
+ '1' '$msg_login: $_user_name'
+ '-' '$msg_full_name: $_user_gecos'
+ '-' '$msg_password: -----'
+ '-' '$msg_user_id: $_user_uid'
+ '-' '$msg_group_id: $_user_gid'
+ '-' '$msg_group_members: $_user_member_groups'
+ '-' '$msg_login_class: $_user_class'
+ '-' '$msg_password_expires_on: $_user_password_expires_on'
+ '-' '$msg_account_expires_on: $_user_account_expires_on'
+ '-' '$msg_home_directory: $_user_home_dir'
+ '-' '$msg_shell: $_user_shell'
+ " # END-QUOTE
+ if f_quietly pw groupshow -g "$user_gid"; then menu_list="$menu_list
+ 'C' '$msg_delete_primary_group: ${_user_group_delete:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ '-' '$msg_delete_primary_group: $msg_n_a'
+ " # END-QUOTE
+ fi
+ case "$user_home_dir" in
+ /|/nonexistent|/var/empty) menu_list="$menu_list
+ '-' '$msg_delete_home_directory: $msg_n_a'
+ " # END-QUOTE
+ ;;
+ *) if [ -d "$user_home_dir" ]; then menu_list="$menu_list
+ 'D' '$msg_delete_home_directory: ${_user_home_delete:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ '-' '$msg_delete_home_directory: $msg_n_a'
+ " # END-QUOTE
+ fi
+ esac
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --keep-tite \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_user_edit [$defaultitem]
+#
+# Present a menu detailing the properties of a login that is about to be
+# modified. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is taken from environment variables user_account_expire, user_class,
+# user_dotfiles_create, user_gecos, user_gid, user_home_create, user_home_dir,
+# user_member_groups, user_name, user_password_expire, user_shell, and
+# user_uid. If $defaultitem is present and non-NULL, initially highlight the
+# item in the menu.
+#
+f_dialog_menu_user_edit()
+{
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Attempt to convert numeric UNIX time to calendar date/time
+ local user_account_expires_on=
+ if f_isinteger "$user_account_expire"; then
+ [ "$user_account_expire" -ne 0 ] && user_account_expires_on=$(
+ date -r "$user_account_expire" "+%F %T %Z"
+ )
+ else
+ user_account_expires_on="$user_account_expire"
+ fi
+ local user_password_expires_on=
+ if f_isinteger "$user_password_expire"; then
+ [ $user_password_expire -ne 0 ] && user_password_expires_on=$(
+ date -r "$user_password_expire" "+%F %T %Z"
+ )
+ else
+ user_password_expires_on="$user_password_expire"
+ fi
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in account_expires_on class dotfiles_create gecos gid \
+ home_create home_dir member_groups name password_expires_on \
+ shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Attempt to translate a numeric GID into `number (name)'
+ if f_isinteger "$_user_gid"; then
+ local _user_group
+ _user_group=$( pw groupshow -g "$_user_gid" 2> /dev/null ) &&
+ _user_group="${_user_group%%:*}" &&
+ f_shell_escape "$_user_gid ($_user_group)" _user_gid
+ fi
+
+ menu_list="
+ 'X' '$msg_save/$msg_exit'
+ '1' '$msg_login: $_user_name'
+ '2' '$msg_full_name: $_user_gecos'
+ '3' '$msg_password: -----'
+ '4' '$msg_user_id: $_user_uid'
+ '5' '$msg_group_id: $_user_gid'
+ '6' '$msg_member_of_groups: $_user_member_groups'
+ '7' '$msg_login_class: $_user_class'
+ '8' '$msg_password_expires_on: $_user_password_expires_on'
+ '9' '$msg_account_expires_on: $_user_account_expires_on'
+ 'A' '$msg_home_directory: $_user_home_dir'
+ 'B' '$msg_shell: $_user_shell'
+ " # END-QUOTE
+ case "$user_home_dir" in
+ /|/nonexistent|/var/empty) menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ '-' '$msg_create_dotfiles: $msg_n_a'
+ " # END-QUOTE
+ ;;
+ *) if [ -d "$user_home_dir" ]; then menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ 'C' '$msg_create_home_directory: ${_user_home_create:-$msg_no}'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ fi
+ esac
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --keep-tite \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/user_input.subr
+
+fi # ! $_USERMGMT_USER_INPUT_SUBR
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/useradd b/contrib/bsddialog/bsdconfig/usermgmt/useradd
new file mode 100755
index 000000000000..d372be4694b8
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/useradd
@@ -0,0 +1,77 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_add $msg_user"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Add a user
+#
+# NB: If given an argument on the command-line use it; otherwise fall-back to
+# environment variable $user (handle $VAR_USER).
+#
+f_user_add ${1:+"$1"}
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/userdel b/contrib/bsddialog/bsdconfig/usermgmt/userdel
new file mode 100755
index 000000000000..9425c7bb4244
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/userdel
@@ -0,0 +1,100 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
+f_include $BSDCFG_SHARE/usermgmt/user_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_delete $msg_login"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# If given a user name, operate on it and exit
+#
+if [ "$1" ]; then
+ f_user_delete "$1"
+ exit $SUCCESS
+fi
+
+#
+# Loop until the user Exits, Cancels or presses ESC
+#
+defaultitem=
+while :; do
+ f_dialog_menu_user_list "$defaultitem"
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ [ "$mtag" = "X $msg_exit" ] && break
+
+ # Anything else is a userid
+
+ f_user_delete "$mtag"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/useredit b/contrib/bsddialog/bsdconfig/usermgmt/useredit
new file mode 100755
index 000000000000..612f3a653d76
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/useredit
@@ -0,0 +1,100 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
+f_include $BSDCFG_SHARE/usermgmt/user_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+f_dialog_title "$msg_edit_view $msg_login"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# If given a user name, operate on it and exit
+#
+if [ "$1" ]; then
+ f_user_edit "$1"
+ exit $SUCCESS
+fi
+
+#
+# Present a list of users and loop until user Exits, Cancels or presses ESC
+#
+defaultitem=
+while :; do
+ f_dialog_menu_user_list "$defaultitem"
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ [ "$mtag" = "X $msg_exit" ] && break
+
+ # Anything else is a userid
+
+ f_user_edit "$mtag"
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdconfig/usermgmt/usermgmt b/contrib/bsddialog/bsdconfig/usermgmt/usermgmt
new file mode 100755
index 000000000000..79fbc955133c
--- /dev/null
+++ b/contrib/bsddialog/bsdconfig/usermgmt/usermgmt
@@ -0,0 +1,168 @@
+#!/bin/sh
+#-
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2013 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+USERMGMT_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/usermgmt.hlp
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local prompt=
+ local 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
+ local defaultitem= # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ # When using Xdialog(1) we need to bump the width for the buttons
+ [ "$USE_XDIALOG" ] && width=40
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+#
+# Process command-line arguments
+#
+while getopts h$GETOPTS_STDARGS flag; do
+ case "$flag" in
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+#
+# Initialize
+#
+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=$?
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq $DIALOG_HELP ]; then
+ f_show_help "$USERMGMT_HELPFILE"
+ continue
+ elif [ $retval -ne $DIALOG_OK ]; then
+ f_die
+ fi
+
+ command=
+ case "$mtag" in
+ X) break ;;
+ 1) command=useradd ;; # Add User
+ 2) command=useredit ;; # Edit/View User
+ 3) command=userdel ;; # Delete User
+ 4) command=groupadd ;; # Add Group
+ 5) command=groupedit ;; # Edit/View Group
+ 6) command=groupdel ;; # Delete Group
+ esac
+
+ if [ "$command" ]; then
+ $BSDCFG_LIBE/$APP_DIR/$command ${USE_XDIALOG:+-X}
+ else
+ f_die 1 "$msg_unknown_user_management_menu_selection"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsddialog.1 b/contrib/bsddialog/bsddialog.1
new file mode 100644
index 000000000000..7e1238f38e52
--- /dev/null
+++ b/contrib/bsddialog/bsddialog.1
@@ -0,0 +1,42 @@
+.Dd $Mdocdate$
+.Dt PROGNAME section
+.Os
+.Sh NAME
+.Nm progname
+.Nd one line about what it does
+.\" .Sh LIBRARY
+.\" For sections 2, 3, and 9 only.
+.\" Not used in OpenBSD.
+.Sh SYNOPSIS
+.Nm progname
+.Op Fl options
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility processes files ...
+.\" .Sh CONTEXT
+.\" For section 9 functions only.
+.\" .Sh IMPLEMENTATION NOTES
+.\" Not used in OpenBSD.
+.\" .Sh RETURN VALUES
+.\" For sections 2, 3, and 9 function return values only.
+.\" .Sh ENVIRONMENT
+.\" For sections 1, 6, 7, and 8 only.
+.\" .Sh FILES
+.\" .Sh EXIT STATUS
+.\" For sections 1, 6, and 8 only.
+.\" .Sh EXAMPLES
+.\" .Sh DIAGNOSTICS
+.\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only.
+.\" .Sh ERRORS
+.\" For sections 2, 3, 4, and 9 errno settings only.
+.\" .Sh SEE ALSO
+.\" .Xr foobar 1
+.\" .Sh STANDARDS
+.\" .Sh HISTORY
+.\" .Sh AUTHORS
+.\" .Sh CAVEATS
+.\" .Sh BUGS
+.\" .Sh SECURITY CONSIDERATIONS
+.\" Not used in OpenBSD.
diff --git a/contrib/bsddialog/bsddialog.c b/contrib/bsddialog/bsddialog.c
index 249f1d3c4f3a..7b9b6488fe2d 100644
--- a/contrib/bsddialog/bsddialog.c
+++ b/contrib/bsddialog/bsddialog.c
@@ -37,11 +37,11 @@
#include <bsddialog.h>
#include <bsddialog_theme.h>
-#define BSDDIALOG_VERSION "0.1 devel"
+#define BSDDIALOG_VERSION "0.0.1"
enum OPTS {
/* Common options */
- ASCII_LINES,
+ ASCII_LINES = '?' + 1,
ASPECT_RATIO,
BACKTITLE,
BEGIN_X,
@@ -49,9 +49,7 @@ enum OPTS {
CANCEL_LABEL,
CLEAR,
COLORS,
- /*COLUMN_SEPARATOR,*/
CR_WRAP,
- /*CREATE_RC,*/
DATE_FORMAT,
DEFAULTNO,
DEFAULT_BUTTON,
@@ -67,22 +65,16 @@ enum OPTS {
HFILE,
HLINE,
IGNORE,
- /*INPUT_FD,*/
- /*INSECURE,*/
+ INSECURE,
ITEM_HELP,
ITEM_PREFIX,
- /*KEEP_TITE,*/
- /*KEEP_WINDOW,*/
- /*LAST_KEY,*/
- /*MAX_INPUT,*/
+ MAX_INPUT,
NO_CANCEL,
NOCANCEL,
NO_COLLAPSE,
NO_ITEMS,
- /*NO_KILL,*/
NO_LABEL,
NO_LINES,
- /*NO_MOUSE,*/
NO_NL_EXPAND,
NO_OK,
NOOK,
@@ -95,39 +87,27 @@ enum OPTS {
PRINT_SIZE,
PRINT_VERSION,
QUOTED,
- /*SCROLLBAR,*/
SEPARATE_OUTPUT,
- /*SEPARATE_WIDGET,*/
SEPARATOR,
SHADOW,
SINGLE_QUOTED,
- /*SIZE_ERR,*/
SLEEP,
STDERR,
STDOUT,
- /*TAB_CORRECT,*/
- /*TAB_LEN,*/
THEME,
TIME_FORMAT,
- /*TIMEOUT,*/
TITLE,
- /*TRACE,*/
TRIM,
VERSION,
- /*VISIT_ITEMS,*/
YES_LABEL,
/* Widgets */
BUILDLIST,
- CALENDAR,
CHECKLIST,
- DSELECT,
- EDITBOX,
+ DATEBOX,
FORM,
- FSELECT,
GAUGE,
INFOBOX,
INPUTBOX,
- INPUTMENU,
MENU,
MIXEDFORM,
MIXEDGAUGE,
@@ -135,13 +115,8 @@ enum OPTS {
PASSWORDBOX,
PASSWORDFORM,
PAUSE,
- PRGBOX,
- PROGRAMBOX,
- PROGRESSBOX,
RADIOLIST,
RANGEBOX,
- TAILBOX,
- TAILBOXBG,
TEXTBOX,
TIMEBOX,
TREEVIEW,
@@ -157,24 +132,22 @@ static bool item_always_quote_flag;
static char *item_output_sep_flag;
/* Time and calendar options */
static char *date_fmt_flag, *time_fmt_flag;
+/* Forms */
+static int max_input_form_flag;
/* General flags and options */
static int output_fd_flag;
void usage(void);
/* widgets */
#define BUILDER_ARGS struct bsddialog_conf conf, char* text, int rows, \
- int cols, int argc, char **argv
+ int cols, int argc, char **argv, char *errbuf
int buildlist_builder(BUILDER_ARGS);
-int calendar_builder(BUILDER_ARGS);
int checklist_builder(BUILDER_ARGS);
-int dselect_builder(BUILDER_ARGS);
-int editbox_builder(BUILDER_ARGS);
+int datebox_builder(BUILDER_ARGS);
int form_builder(BUILDER_ARGS);
-int fselect_builder(BUILDER_ARGS);
int gauge_builder(BUILDER_ARGS);
int infobox_builder(BUILDER_ARGS);
int inputbox_builder(BUILDER_ARGS);
-int inputmenu_builder(BUILDER_ARGS);
int menu_builder(BUILDER_ARGS);
int mixedform_builder(BUILDER_ARGS);
int mixedgauge_builder(BUILDER_ARGS);
@@ -182,13 +155,8 @@ int msgbox_builder(BUILDER_ARGS);
int passwordbox_builder(BUILDER_ARGS);
int passwordform_builder(BUILDER_ARGS);
int pause_builder(BUILDER_ARGS);
-int prgbox_builder(BUILDER_ARGS);
-int programbox_builder(BUILDER_ARGS);
-int progressbox_builder(BUILDER_ARGS);
int radiolist_builder(BUILDER_ARGS);
int rangebox_builder(BUILDER_ARGS);
-int tailbox_builder(BUILDER_ARGS);
-int tailboxbg_builder(BUILDER_ARGS);
int textbox_builder(BUILDER_ARGS);
int timebox_builder(BUILDER_ARGS);
int treeview_builder(BUILDER_ARGS);
@@ -197,28 +165,85 @@ int yesno_builder(BUILDER_ARGS);
void usage(void)
{
- printf("usage: bsddialog --help\n"\
- " bsddialog --version\n"\
- " bsddialog [--<common-opts>] --<widget> <text> "\
+ printf("usage: bsddialog --help\n"
+ " bsddialog --version\n"
+ " bsddialog [--<common-opts>] --<widget> <text> "
"<height> <width> [--<widget-opts>]\n");
+ printf("\n");
+ printf("Common Options:\n");
+ printf("--ascii-lines, --aspect <ratio>, --backtitle <backtitle>, "
+ "--begin-x <x>, --begin-y <y>, --cancel-label <string>, "
+ "-clear, --colors, --date-format <format>, "
+ "--default-button <label>, --defaultno, --default-item <name>,"
+ "--exit-label <label>, --extra-button, --extra-label <label>,"
+ "--hfile <filename>, --help-button, --help-label <label>, "
+ "--help-status, --help-tags, --hline string, --ignore, "
+ "--insecure, --item-help, --max-input <size>, --no-cancel, "
+ "--nocancel, --no-label <label>, --no-items, --no-lines, "
+ "--no-ok, --nook, --no-shadow, --no-tags, --ok-label <label>, "
+ "--output-fd <fd>, --output-separator <sep>, --print-version, "
+ "--print-size, --quoted, --print-maxsize, --shadow, "
+ "--single-quoted, --separator <sep>, --separate-output, "
+ "--sleep <secs>, --stderr, --stdout, "
+ "--theme <blackwhite|bsddialog|dialog>, "
+ "--time-format <format>, --title <title>, "
+ "--yes-label <string>.\n");
+ printf("\n");
+ printf("Widgets:\n");
+ printf("--buildlist <text> <rows> <cols> <menurows> [<name> <desc> "
+ "<on|off> ...]\n"
+ "--checklist <text> <rows> <cols> <menurows> [<name> <desc> "
+ "<on|off> ...]\n"
+ "--datebox <text> <rows> <cols> [<yy> <mm> <dd>]\n"
+ "--form <text> <rows> <cols> <formrows> [<label> <ylabel> "
+ "<xlabel> <init> <yfield> <xfield> <fieldlen> <maxvalue> "
+ "...]\n"
+ "--gauge <text> <rows> <cols> [<perc\\n> [<text> ...] XXX "
+ "...] EOF\n"
+ "--infobox <text> <rows> <cols>\n"
+ "--inputbox <text> <rows> <cols> [init]\n"
+ "--menu <text> <rows> <cols> <menurows> [<name> <desc> ...]\n"
+ "--mixedform <text> <rows> <cols> <formrows> [<label> <ylabel> "
+ "<xlabe> <init> <yfield> <xfield> <fieldlen> <maxvalue> "
+ "<0|1|2> ...]\n"
+ "--mixedgauge <text> <rows> <cols> <mainperc> [<label> "
+ "<01234567|-perc> ...]\n"
+ "--msgbox <text> <rows> <cols>\n"
+ "--passwordbox <text> <rows> <cols> [init]\n"
+ "--passwordform <text> <rows> <cols> <formrows> [<label> "
+ "<ylabel> <xlabe> <init> <yfield> <xfield> <fieldlen> "
+ "<maxvalue> ...]\n"
+ "--pause <text> <rows> <cols> <secs>\n"
+ "--radiolist <text> <rows> <cols> <menurows> [<name> <desc> "
+ "<on|off> ...]\n"
+ "--rangebox <text> <rows> <cols> <min> <max> <default>\n"
+ "--textbox <file> <rows> <cols>\n"
+ "--timebox <text> <rows> <cols> [<hh> <mm> <ss>]\n"
+ "--treeview <text> <rows> <cols> <menurows> [<depth> <name> "
+ "<desc> <on|off> ...]\n"
+ "--yesno <text> <rows> <cols>\n");
+
+
}
int main(int argc, char *argv[argc])
{
- char *text, *backtitle_flag, *theme_flag;
+ char *text, *backtitle_flag, errorbuilder[1024];
int input, rows, cols, output, getH, getW;
int (*widgetbuilder)(BUILDER_ARGS) = NULL;
bool ignore_flag, print_maxsize_flag;
struct winsize ws;
struct bsddialog_conf conf;
+ enum bsddialog_default_theme theme_flag;
bsddialog_initconf(&conf);
backtitle_flag = NULL;
- theme_flag = NULL;
+ theme_flag = -1;
output_fd_flag = STDERR_FILENO;
print_maxsize_flag = false;
ignore_flag = false;
+ errorbuilder[0] = '\0';
item_output_sepnl_flag = item_singlequote_flag = false;
item_prefix_flag = item_bottomdesc_flag = false;
@@ -227,114 +252,91 @@ int main(int argc, char *argv[argc])
item_output_sep_flag = NULL;
date_fmt_flag = time_fmt_flag = NULL;
+
+ max_input_form_flag = 0;
/* options descriptor */
struct option longopts[] = {
/* common options */
- { "ascii-lines", no_argument, NULL, ASCII_LINES },
- { "aspect", required_argument, NULL, ASPECT_RATIO },
- { "backtitle_flag", required_argument, NULL, BACKTITLE },
- { "begin-x", required_argument, NULL, BEGIN_X },
- { "begin-y", required_argument, NULL, BEGIN_Y },
- { "cancel-label", required_argument, NULL, CANCEL_LABEL },
- { "clear", no_argument, NULL, CLEAR },
- { "colors", no_argument, NULL, COLORS },
- /*{ "column-separator", required_argument, NULL, COLUMN_SEPARATOR },*/
- { "cr-wrap", no_argument, NULL, CR_WRAP },
- /*{ "create-rc", required_argument, NULL, CREATE_RC },*/
- { "date-format", required_argument, NULL, DATE_FORMAT },
- { "defaultno", no_argument, NULL, DEFAULTNO },
- { "default-button", required_argument, NULL, DEFAULT_BUTTON },
- { "default-item", required_argument, NULL, DEFAULT_ITEM },
- { "exit-label", required_argument, NULL, EXIT_LABEL },
- { "extra-button", no_argument, NULL, EXTRA_BUTTON },
- { "extra-label", required_argument, NULL, EXTRA_LABEL },
- { "help", no_argument, NULL, HELP },
- { "help-button", no_argument, NULL, HELP_BUTTON },
- { "help-label", required_argument, NULL, HELP_LABEL },
- { "help-status", no_argument, NULL, HELP_STATUS },
- { "help-tags", no_argument, NULL, HELP_TAGS },
- { "hfile", required_argument, NULL, HFILE },
- { "hline", required_argument, NULL, HLINE },
- { "ignore", no_argument, NULL, IGNORE },
- /*{ "input-fd", required_argument, NULL, INPUT_FD },*/
- /*{ "insecure", no_argument, NULL, INSECURE },*/
- { "item-help", no_argument, NULL, ITEM_HELP },
- /*{ "keep-tite", no_argument, NULL, KEEP_TITE },*/
- /*{ "keep-window", no_argument, NULL, KEEP_WINDOW },*/
- /*{ "last-key", no_argument, NULL, LAST_KEY },*/
- /*{ "max-input", required_argument, NULL, MAX_INPUT },*/
- { "no-cancel", no_argument, NULL, NO_CANCEL },
- { "nocancel", no_argument, NULL, NOCANCEL },
- { "no-collapse", no_argument, NULL, NO_COLLAPSE },
- { "no-items", no_argument, NULL, NO_ITEMS },
- /*{ "no-kill", no_argument, NULL, NO_KILL },*/
- { "no-label", required_argument, NULL, NO_LABEL },
- { "no-lines", no_argument, NULL, NO_LINES },
- /*{ "no-mouse", no_argument, NULL, NO_MOUSE },*/
- { "no-nl-expand", no_argument, NULL, NO_NL_EXPAND },
- { "no-ok", no_argument, NULL, NO_OK },
- { "nook ", no_argument, NULL, NOOK },
- { "no-tags", no_argument, NULL, NO_TAGS },
- { "no-shadow", no_argument, NULL, NO_SHADOW },
- { "ok-label", required_argument, NULL, OK_LABEL },
- { "output-fd", required_argument, NULL, OUTPUT_FD },
- { "separator", required_argument, NULL, SEPARATOR },
- { "output-separator", required_argument, NULL, OUTPUT_SEPARATOR },
- { "print-maxsize", no_argument, NULL, PRINT_MAXSIZE },
- { "print-size", no_argument, NULL, PRINT_SIZE },
- { "print-version", no_argument, NULL, PRINT_VERSION },
- { "quoted", no_argument, NULL, QUOTED },
- /*{ "scrollbar", no_argument, NULL, SCROLLBAR},*/
- { "separate-output", no_argument, NULL, SEPARATE_OUTPUT },
- /*{ "separate-widget", required_argument, NULL, SEPARATE_WIDGET },*/
- { "shadow", no_argument, NULL, SHADOW },
- { "single-quoted", no_argument, NULL, SINGLE_QUOTED },
- /*{ "size-err", no_argument, NULL, SIZE_ERR },*/
- { "sleep", required_argument, NULL, SLEEP },
- { "stderr", no_argument, NULL, STDERR },
- { "stdout", no_argument, NULL, STDOUT },
- /*{ "tab-correct", no_argument, NULL, TAB_CORRECT },*/
- /*{ "tab-len", required_argument, NULL, TAB_LEN },*/
- { "theme_flag", required_argument, NULL, THEME },
- { "time-format", required_argument, NULL, TIME_FORMAT },
- /*{ "timeout", required_argument, NULL, TIMEOUT },*/
- { "title", required_argument, NULL, TITLE },
- /*{ "trace", required_argument, NULL, TRACE },*/
- { "trim", no_argument, NULL, TRIM },
- { "version", no_argument, NULL, VERSION },
- /*{ "visit-items", no_argument, NULL, VISIT_ITEMS },*/
- { "yes-label", required_argument, NULL, YES_LABEL },
+ {"ascii-lines", no_argument, NULL, ASCII_LINES },
+ {"aspect", required_argument, NULL, ASPECT_RATIO },
+ {"backtitle", required_argument, NULL, BACKTITLE },
+ {"begin-x", required_argument, NULL, BEGIN_X },
+ {"begin-y", required_argument, NULL, BEGIN_Y },
+ {"cancel-label", required_argument, NULL, CANCEL_LABEL },
+ {"clear", no_argument, NULL, CLEAR },
+ {"colors", no_argument, NULL, COLORS },
+ {"cr-wrap", no_argument, NULL, CR_WRAP },
+ {"date-format", required_argument, NULL, DATE_FORMAT },
+ {"defaultno", no_argument, NULL, DEFAULTNO },
+ {"default-button", required_argument, NULL, DEFAULT_BUTTON },
+ {"default-item", required_argument, NULL, DEFAULT_ITEM },
+ {"exit-label", required_argument, NULL, EXIT_LABEL },
+ {"extra-button", no_argument, NULL, EXTRA_BUTTON },
+ {"extra-label", required_argument, NULL, EXTRA_LABEL },
+ {"help", no_argument, NULL, HELP },
+ {"help-button", no_argument, NULL, HELP_BUTTON },
+ {"help-label", required_argument, NULL, HELP_LABEL },
+ {"help-status", no_argument, NULL, HELP_STATUS },
+ {"help-tags", no_argument, NULL, HELP_TAGS },
+ {"hfile", required_argument, NULL, HFILE },
+ {"hline", required_argument, NULL, HLINE },
+ {"ignore", no_argument, NULL, IGNORE },
+ {"insecure", no_argument, NULL, INSECURE },
+ {"item-help", no_argument, NULL, ITEM_HELP },
+ {"max-input", required_argument, NULL, MAX_INPUT },
+ {"no-cancel", no_argument, NULL, NO_CANCEL },
+ {"nocancel", no_argument, NULL, NOCANCEL },
+ {"no-collapse", no_argument, NULL, NO_COLLAPSE },
+ {"no-items", no_argument, NULL, NO_ITEMS },
+ {"no-label", required_argument, NULL, NO_LABEL },
+ {"no-lines", no_argument, NULL, NO_LINES },
+ {"no-nl-expand", no_argument, NULL, NO_NL_EXPAND },
+ {"no-ok", no_argument, NULL, NO_OK },
+ {"nook ", no_argument, NULL, NOOK },
+ {"no-tags", no_argument, NULL, NO_TAGS },
+ {"no-shadow", no_argument, NULL, NO_SHADOW },
+ {"ok-label", required_argument, NULL, OK_LABEL },
+ {"output-fd", required_argument, NULL, OUTPUT_FD },
+ {"separator", required_argument, NULL, SEPARATOR },
+ {"output-separator",required_argument, NULL, OUTPUT_SEPARATOR },
+ {"print-maxsize", no_argument, NULL, PRINT_MAXSIZE },
+ {"print-size", no_argument, NULL, PRINT_SIZE },
+ {"print-version", no_argument, NULL, PRINT_VERSION },
+ {"quoted", no_argument, NULL, QUOTED },
+ {"separate-output", no_argument, NULL, SEPARATE_OUTPUT },
+ {"shadow", no_argument, NULL, SHADOW },
+ {"single-quoted", no_argument, NULL, SINGLE_QUOTED },
+ {"sleep", required_argument, NULL, SLEEP },
+ {"stderr", no_argument, NULL, STDERR },
+ {"stdout", no_argument, NULL, STDOUT },
+ {"theme_flag", required_argument, NULL, THEME },
+ {"time-format", required_argument, NULL, TIME_FORMAT },
+ {"title", required_argument, NULL, TITLE },
+ {"trim", no_argument, NULL, TRIM },
+ {"version", no_argument, NULL, VERSION },
+ {"yes-label", required_argument, NULL, YES_LABEL },
/* Widgets */
- { "buildlist", no_argument, NULL, BUILDLIST },
- { "calendar", no_argument, NULL, CALENDAR },
- { "checklist", no_argument, NULL, CHECKLIST },
- { "dselect", no_argument, NULL, DSELECT },
- { "editbox", no_argument, NULL, EDITBOX },
- { "form", no_argument, NULL, FORM },
- { "fselect", no_argument, NULL, FSELECT },
- { "gauge", no_argument, NULL, GAUGE },
- { "infobox", no_argument, NULL, INFOBOX },
- { "inputbox", no_argument, NULL, INPUTBOX },
- { "inputmenu", no_argument, NULL, INPUTMENU },
- { "menu", no_argument, NULL, MENU },
- { "mixedform", no_argument, NULL, MIXEDFORM },
- { "mixedgauge", no_argument, NULL, MIXEDGAUGE },
- { "msgbox", no_argument, NULL, MSGBOX },
- { "passwordbox", no_argument, NULL, PASSWORDBOX },
- { "passwordform", no_argument, NULL, PASSWORDFORM },
- { "pause", no_argument, NULL, PAUSE },
- { "prgbox", no_argument, NULL, PRGBOX },
- { "programbox", no_argument, NULL, PROGRAMBOX },
- { "progressbox", no_argument, NULL, PROGRESSBOX },
- { "radiolist", no_argument, NULL, RADIOLIST },
- { "rangebox", no_argument, NULL, RANGEBOX },
- { "tailbox", no_argument, NULL, TAILBOX },
- { "tailboxbg", no_argument, NULL, TAILBOXBG },
- { "textbox", no_argument, NULL, TEXTBOX },
- { "timebox", no_argument, NULL, TIMEBOX },
- { "treeview", no_argument, NULL, TREEVIEW },
- { "yesno", no_argument, NULL, YESNO },
+ {"buildlist", no_argument, NULL, BUILDLIST },
+ {"checklist", no_argument, NULL, CHECKLIST },
+ {"datebox", no_argument, NULL, DATEBOX },
+ {"form", no_argument, NULL, FORM },
+ {"gauge", no_argument, NULL, GAUGE },
+ {"infobox", no_argument, NULL, INFOBOX },
+ {"inputbox", no_argument, NULL, INPUTBOX },
+ {"menu", no_argument, NULL, MENU },
+ {"mixedform", no_argument, NULL, MIXEDFORM },
+ {"mixedgauge", no_argument, NULL, MIXEDGAUGE },
+ {"msgbox", no_argument, NULL, MSGBOX },
+ {"passwordbox", no_argument, NULL, PASSWORDBOX },
+ {"passwordform", no_argument, NULL, PASSWORDFORM },
+ {"pause", no_argument, NULL, PAUSE },
+ {"radiolist", no_argument, NULL, RADIOLIST },
+ {"rangebox", no_argument, NULL, RANGEBOX },
+ {"textbox", no_argument, NULL, TEXTBOX },
+ {"timebox", no_argument, NULL, TIMEBOX },
+ {"treeview", no_argument, NULL, TREEVIEW },
+ {"yesno", no_argument, NULL, YESNO },
/* END */
{ NULL, 0, NULL, 0 }
};
@@ -406,8 +408,6 @@ int main(int argc, char *argv[argc])
break;
case HELP:
usage();
- printf("\n");
- printf("See \'man 1 bsddialog\' for more information.\n");
return (BSDDIALOG_YESOK);
case HELP_BUTTON:
conf.button.help_button = true;
@@ -430,11 +430,17 @@ int main(int argc, char *argv[argc])
case IGNORE:
ignore_flag = true;
break;
+ case INSECURE:
+ conf.form.securech = '*';
+ break;
case ITEM_HELP:
item_bottomdesc_flag = true;
break;
+ case MAX_INPUT:
+ max_input_form_flag = atoi(optarg);
+ break;
case NO_ITEMS:
- conf.menu.no_items = true;
+ conf.menu.no_desc = true;
break;
case ITEM_PREFIX:
item_prefix_flag = true;
@@ -460,7 +466,7 @@ int main(int argc, char *argv[argc])
conf.button.no_ok = true;
break;
case NO_TAGS:
- conf.menu.no_tags = true;
+ conf.menu.no_name = true;
break;
case NO_SHADOW:
conf.shadow = false;
@@ -507,7 +513,17 @@ int main(int argc, char *argv[argc])
output_fd_flag = STDOUT_FILENO;
break;
case THEME:
- theme_flag = optarg;
+ if (strcmp(optarg, "bsddialog") == 0)
+ theme_flag = BSDDIALOG_THEME_BSDDIALOG;
+ else if (strcmp(optarg, "blackwhite") == 0)
+ theme_flag = BSDDIALOG_THEME_BLACKWHITE;
+ else if (strcmp(optarg, "dialog") == 0)
+ theme_flag = BSDDIALOG_THEME_DIALOG;
+ else {
+ printf("Unknown theme, possible values: ");
+ printf("blackwhite, bsddialog, dialog");
+ return (BSDDIALOG_ERROR);
+ }
break;
case TIME_FORMAT:
time_fmt_flag = optarg;
@@ -519,7 +535,8 @@ int main(int argc, char *argv[argc])
conf.text.trim = true;
break;
case VERSION:
- printf("bsddialog version %s\n", BSDDIALOG_VERSION);
+ printf("bsddialog %s (libbsddialog %s).\n",
+ BSDDIALOG_VERSION, LIBBSDDIALOG_VERSION);
return (BSDDIALOG_YESOK);
case YES_LABEL:
conf.button.yes_label = optarg;
@@ -528,24 +545,15 @@ int main(int argc, char *argv[argc])
case BUILDLIST:
widgetbuilder = buildlist_builder;
break;
- case CALENDAR:
- widgetbuilder = calendar_builder;
- break;
case CHECKLIST:
widgetbuilder = checklist_builder;
break;
- case DSELECT:
- widgetbuilder = dselect_builder;
- break;
- case EDITBOX:
- widgetbuilder = editbox_builder;
+ case DATEBOX:
+ widgetbuilder = datebox_builder;
break;
case FORM:
widgetbuilder = form_builder;
break;
- case FSELECT:
- widgetbuilder = fselect_builder;
- break;
case GAUGE:
widgetbuilder = gauge_builder;
break;
@@ -555,9 +563,6 @@ int main(int argc, char *argv[argc])
case INPUTBOX:
widgetbuilder = inputbox_builder;
break;
- case INPUTMENU:
- widgetbuilder = inputmenu_builder;
- break;
case MENU:
widgetbuilder = menu_builder;
break;
@@ -579,27 +584,12 @@ int main(int argc, char *argv[argc])
case PASSWORDFORM:
widgetbuilder = passwordform_builder;
break;
- case PRGBOX:
- widgetbuilder = prgbox_builder;
- break;
- case PROGRAMBOX:
- widgetbuilder = programbox_builder;
- break;
- case PROGRESSBOX:
- widgetbuilder = progressbox_builder;
- break;
case RADIOLIST:
widgetbuilder = radiolist_builder;
break;
case RANGEBOX:
widgetbuilder = rangebox_builder;
break;
- case TAILBOX:
- widgetbuilder = tailbox_builder;
- break;
- case TAILBOXBG:
- widgetbuilder = tailboxbg_builder;
- break;
case TEXTBOX:
widgetbuilder = textbox_builder;
break;
@@ -614,10 +604,10 @@ int main(int argc, char *argv[argc])
break;
/* Error */
default:
- if (ignore_flag == false) {
- usage();
- return (BSDDIALOG_ERROR);
- }
+ if (ignore_flag == true)
+ break;
+ usage();
+ return (BSDDIALOG_ERROR);
}
}
argc -= optind;
@@ -640,40 +630,28 @@ int main(int argc, char *argv[argc])
argc -= 3;
argv += 3;
+ /* bsddialog terminal mode */
if(bsddialog_init() != 0) {
printf("Error: %s\n", bsddialog_geterror());
return (BSDDIALOG_ERROR);
}
- if (theme_flag != NULL) {
- if (strcmp(theme_flag, "bsddialog") == 0)
- bsddialog_set_default_theme(BSDDIALOG_THEME_BSDDIALOG);
- else if (strcmp(theme_flag, "blackwhite") == 0)
- bsddialog_set_default_theme(BSDDIALOG_THEME_BLACKWHITE);
- else if (strcmp(theme_flag, "dialog") == 0)
- bsddialog_set_default_theme(BSDDIALOG_THEME_DIALOG);
- else if (strcmp(theme_flag, "magenta") == 0)
- bsddialog_set_default_theme(BSDDIALOG_THEME_MAGENTA);
- else
- bsddialog_set_default_theme(BSDDIALOG_THEME_DIALOG);
- }
+ if (theme_flag >= 0)
+ bsddialog_set_default_theme(theme_flag);
if (backtitle_flag != NULL)
- bsddialog_backtitle(conf, backtitle_flag);
+ bsddialog_backtitle(&conf, backtitle_flag);
output = BSDDIALOG_YESOK;
if (widgetbuilder != NULL)
- output = widgetbuilder(conf, text, rows, cols, argc, argv);
+ output = widgetbuilder(conf, text, rows, cols, argc, argv,
+ errorbuilder);
bsddialog_end();
-
- if (conf.get_height != NULL && conf.get_width != NULL &&
- output != BSDDIALOG_ERROR)
- dprintf(output_fd_flag, "Widget size: (%d - %d)\n",
- *conf.get_height, *conf.get_width);
+ /* end bsddialog terminal mode */
/* debug & devel */
- printf("[Debug] Exit status: %d ", output);
+ /*printf("[Debug] Exit status: %d ", output);
switch (output) {
case BSDDIALOG_ERROR: printf("ERROR"); break;
case BSDDIALOG_YESOK: printf("YESOK"); break;
@@ -684,162 +662,56 @@ int main(int argc, char *argv[argc])
case BSDDIALOG_ESC: printf("ESC"); break;
default: printf("Unknow status! Bug!"); break;
}
- printf("\n");
-
- if (output == BSDDIALOG_ERROR)
- printf("Error: %s\n", bsddialog_geterror());
-
- return (output);
-}
-
-int calendar_builder(BUILDER_ARGS)
-{
- int output;
- unsigned int yy, mm, dd;
- time_t cal;
- struct tm *localtm;
- char stringdate[1024];
-
- time(&cal);
- localtm = localtime(&cal);
- yy = localtm->tm_year + 1900;
- mm = localtm->tm_mon;
- dd = localtm->tm_mday;
-
- /* --calendar text h w [year month day] */
- if (argc == 3) {
- yy = atoi(argv[0]) + 1900;
- yy = yy > 9999 ? 9999 : yy;
- mm = atoi(argv[1]);
- mm = mm > 12 ? 12 : mm;
- dd = atoi(argv[2]);
- dd = dd > 31 ? 31 : dd;
- }
-
- output = bsddialog_calendar(conf, text, rows, cols, &yy, &mm, &dd);
- if (output != BSDDIALOG_YESOK)
- return (output);
-
- if (date_fmt_flag == NULL) {
- dprintf(output_fd_flag, "%u/%u/%u", yy, mm, dd);
- }
- else {
- time(&cal);
- localtm = localtime(&cal);
- localtm->tm_year = yy - 1900;
- localtm->tm_mon = mm;
- localtm->tm_mday = dd;
- strftime(stringdate, 1024, date_fmt_flag, localtm);
- dprintf(output_fd_flag, "%s", stringdate);
- }
-
- return (output);
-}
-
-int dselect_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_dselect(conf, text, rows, cols);
+ printf("\n");*/
- return (output);
-}
-
-int editbox_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_editbox(conf, text, rows, cols);
-
- return (output);
-}
-
-int form_builder(BUILDER_ARGS)
-{
- int output, formheight;
-
- if (argc < 1 || (((argc-1) % 8) != 0) ) {
- usage();
- return (BSDDIALOG_ERROR);
+ if (output == BSDDIALOG_ERROR) {
+ if (errorbuilder[0] != '\0')
+ printf("Error: %s\n", errorbuilder);
+ else
+ printf("Error: %s\n", bsddialog_geterror());
}
- formheight = atoi(argv[0]);
-
- output = bsddialog_form(conf, text, rows, cols, formheight, argc-1,
- argv + 1);
+ if (conf.get_height != NULL && conf.get_width != NULL)
+ dprintf(output_fd_flag, "Widget size: (%d - %d)\n",
+ *conf.get_height, *conf.get_width);
return (output);
}
-int fselect_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_fselect(conf, text, rows, cols);
-
- return (output);
-}
+/* Widgets */
int gauge_builder(BUILDER_ARGS)
{
- int output /* always BSDDIALOG_YESOK */, perc;
+ int output, perc;
- perc = argc > 0 ? atoi (argv[0]) : 0;
- perc = perc < 0 ? 0 : perc;
- perc = perc > 100 ? 100 : perc;
+ if (argc > 0) {
+ perc = argc > 0 ? atoi (argv[0]) : 0;
+ perc = perc < 0 ? 0 : perc;
+ perc = perc > 100 ? 100 : perc;
+ }
+ else
+ perc = 0;
- output = bsddialog_gauge(conf, text, rows, cols, perc);
+ output = bsddialog_gauge(&conf, text, rows, cols, perc);
return (output);
}
int infobox_builder(BUILDER_ARGS)
{
- int output; /* always BSDDIALOG_YESOK */
-
- output = bsddialog_infobox(conf, text, rows, cols);
-
- return (output);
-}
-
-int inputbox_builder(BUILDER_ARGS)
-{
int output;
- output = bsddialog_inputbox(conf, text, rows, cols);
-
- return (output);
-}
-
-int inputmenu_builder(BUILDER_ARGS)
-{
-
- return (BSDDIALOG_ERROR);
-}
-
-int mixedform_builder(BUILDER_ARGS)
-{
- int output, formheight;
-
- if (argc < 1 || (((argc-1) % 9) != 0) ) {
- usage();
- return (BSDDIALOG_ERROR);
- }
-
- formheight = atoi(argv[0]);
-
- output = bsddialog_mixedform(conf, text, rows, cols, formheight, argc-1,
- argv + 1);
+ output = bsddialog_infobox(&conf, text, rows, cols);
return (output);
}
int mixedgauge_builder(BUILDER_ARGS)
{
- int output /* always BSDDIALOG_YESOK */, perc;
+ int output, perc;
if (argc < 1 || (((argc-1) % 2) != 0) ) {
- usage();
+ strcpy(errbuf, "bad --mixedgauge arguments\n");
return (BSDDIALOG_ERROR);
}
@@ -847,7 +719,7 @@ int mixedgauge_builder(BUILDER_ARGS)
perc = perc < 0 ? 0 : perc;
perc = perc > 100 ? 100 : perc;
- output = bsddialog_mixedgauge(conf, text, rows, cols, perc,
+ output = bsddialog_mixedgauge(&conf, text, rows, cols, perc,
argc-1, argv + 1);
return (output);
@@ -857,33 +729,7 @@ int msgbox_builder(BUILDER_ARGS)
{
int output;
- output = bsddialog_msgbox(conf, text, rows, cols);
-
- return (output);
-}
-
-int passwordbox_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_passwordbox(conf, text, rows, cols);
-
- return (output);
-}
-
-int passwordform_builder(BUILDER_ARGS)
-{
- int output, formheight;
-
- if (argc < 1 || (((argc-1) % 8) != 0) ) {
- usage();
- return (BSDDIALOG_ERROR);
- }
-
- formheight = atoi(argv[0]);
-
- output = bsddialog_passwordform(conf, text, rows, cols, formheight,
- argc-1, argv + 1);
+ output = bsddialog_msgbox(&conf, text, rows, cols);
return (output);
}
@@ -893,45 +739,12 @@ int pause_builder(BUILDER_ARGS)
int output, sec;
if (argc < 1) {
- usage();
+ strcpy(errbuf, "not <seconds> argument for --pause\n");
return (BSDDIALOG_ERROR);
}
sec = atoi(argv[0]);
- output = bsddialog_pause(conf, text, rows, cols, sec);
-
- return (output);
-}
-
-int prgbox_builder(BUILDER_ARGS)
-{
- int output;
-
- if (argc < 1) {
- usage();
- return (BSDDIALOG_ERROR);
- }
-
- output = bsddialog_prgbox(conf, strlen(text) == 0 ? NULL : text, rows,
- cols, argv[0]);
-
- return (output);
-}
-
-int programbox_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_programbox(conf, strlen(text) == 0 ? NULL : text, rows, cols);
-
- return (output);
-}
-
-int progressbox_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_progressbox(conf, strlen(text) == 0 ? NULL : text, rows, cols);
+ output = bsddialog_pause(&conf, text, rows, cols, sec);
return (output);
}
@@ -940,8 +753,11 @@ int rangebox_builder(BUILDER_ARGS)
{
int output, min, max, value;
- if (argc < 2)
+ if (argc < 2) {
+ strcpy(errbuf, "usage --rangebox <text> <rows> <cols> <min> "
+ "<max> [<init>]\n");
return (BSDDIALOG_ERROR);
+ }
min = atoi(argv[0]);
max = atoi(argv[1]);
@@ -954,38 +770,71 @@ int rangebox_builder(BUILDER_ARGS)
else
value = min;
- output = bsddialog_rangebox(conf, text, rows, cols, min, max, &value);
+ output = bsddialog_rangebox(&conf, text, rows, cols, min, max, &value);
dprintf(output_fd_flag, "%d", value);
return (output);
}
-int tailbox_builder(BUILDER_ARGS)
+int textbox_builder(BUILDER_ARGS)
{
int output;
- output = bsddialog_tailbox(conf, text, rows, cols);
+ output = bsddialog_textbox(&conf, text, rows, cols);
return (output);
}
-int tailboxbg_builder(BUILDER_ARGS)
+int yesno_builder(BUILDER_ARGS)
{
int output;
- output = bsddialog_tailboxbg(conf, text, rows, cols);
+ output = bsddialog_yesno(&conf, text, rows, cols);
- return output;
+ return (output);
}
-int textbox_builder(BUILDER_ARGS)
+/* DATE and TIME */
+int datebox_builder(BUILDER_ARGS)
{
int output;
+ unsigned int yy, mm, dd;
+ time_t cal;
+ struct tm *localtm;
+ char stringdate[1024];
+
+ time(&cal);
+ localtm = localtime(&cal);
+ yy = localtm->tm_year + 1900;
+ mm = localtm->tm_mon + 1;
+ dd = localtm->tm_mday;
+
+ /* --calendar text h w [year month day] */
+ if (argc == 3) {
+ yy = atoi(argv[0]);
+ mm = atoi(argv[1]);
+ dd = atoi(argv[2]);
+ }
+
+ output = bsddialog_datebox(&conf, text, rows, cols, &yy, &mm, &dd);
+ if (output != BSDDIALOG_YESOK)
+ return (output);
- output = bsddialog_textbox(conf, text, rows, cols);
+ if (date_fmt_flag == NULL) {
+ dprintf(output_fd_flag, "%u/%u/%u", yy, mm, dd);
+ }
+ else {
+ time(&cal);
+ localtm = localtime(&cal);
+ localtm->tm_year = yy - 1900;
+ localtm->tm_mon = mm;
+ localtm->tm_mday = dd;
+ strftime(stringdate, 1024, date_fmt_flag, localtm);
+ dprintf(output_fd_flag, "%s", stringdate);
+ }
- return output;
+ return (output);
}
int timebox_builder(BUILDER_ARGS)
@@ -1005,16 +854,13 @@ int timebox_builder(BUILDER_ARGS)
/* --timebox text h w [hour minute second] */
if (argc == 3) {
hh = atoi(argv[0]);
- hh = hh > 23 ? 23 : hh;
mm = atoi(argv[1]);
- mm = mm > 60 ? 60 : mm;
ss = atoi(argv[2]);
- ss = ss > 60 ? 60 : ss;
}
- output = bsddialog_timebox(conf, text, rows, cols, &hh, &mm, &ss);
+ output = bsddialog_timebox(&conf, text, rows, cols, &hh, &mm, &ss);
if (output != BSDDIALOG_YESOK)
- return output;
+ return (output);
if (time_fmt_flag == NULL) {
dprintf(output_fd_flag, "%u:%u:%u", hh, mm, ss);
@@ -1032,20 +878,11 @@ int timebox_builder(BUILDER_ARGS)
return (output);
}
-int yesno_builder(BUILDER_ARGS)
-{
- int output;
-
- output = bsddialog_yesno(conf, text, rows, cols);
-
- return output;
-}
-
/* MENU */
static int
-get_menu_items(int argc, char **argv, bool setprefix, bool setdepth,
- bool setname, bool setdesc, bool setstatus, bool sethelp, int *nitems,
- struct bsddialog_menuitem *items)
+get_menu_items(char *errbuf, int argc, char **argv, bool setprefix,
+ bool setdepth, bool setname, bool setdesc, bool setstatus, bool sethelp,
+ int *nitems, struct bsddialog_menuitem *items)
{
int i, j, sizeitem;
@@ -1057,7 +894,7 @@ get_menu_items(int argc, char **argv, bool setprefix, bool setdepth,
if (setstatus) sizeitem++;
if (sethelp) sizeitem++;
if ((argc % sizeitem) != 0) {
- printf("Error: Menu/Checklist/Treeview/Radiolist bad #args\n");
+ strcpy(errbuf, "bad number of arguments for this menu\n");
return (BSDDIALOG_ERROR);
}
@@ -1079,7 +916,7 @@ get_menu_items(int argc, char **argv, bool setprefix, bool setdepth,
}
static void
-print_selected_items(struct bsddialog_conf conf, int output, int nitems,
+print_menu_items(struct bsddialog_conf *conf, int output, int nitems,
struct bsddialog_menuitem *items, int focusitem)
{
int i;
@@ -1138,126 +975,306 @@ print_selected_items(struct bsddialog_conf conf, int output, int nitems,
int buildlist_builder(BUILDER_ARGS)
{
int output, menurows, nitems, focusitem;
- struct bsddialog_menuitem items[100];
+ struct bsddialog_menuitem items[1024];
if (argc < 1) {
- usage();
+ strcpy(errbuf, "<menurows> not provided");
return (BSDDIALOG_ERROR);
}
menurows = atoi(argv[0]);
- output = get_menu_items(argc-1, argv+1, item_prefix_flag, false, true,
- true, true, item_bottomdesc_flag, &nitems, items);
+ output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
+ true, true, true, item_bottomdesc_flag, &nitems, items);
if (output != 0)
return (output);
- output = bsddialog_buildlist(conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_buildlist(&conf, text, rows, cols, menurows, nitems,
items, &focusitem);
if (output == BSDDIALOG_ERROR)
return (BSDDIALOG_ERROR);
- print_selected_items(conf, output, nitems, items, focusitem);
+ print_menu_items(&conf, output, nitems, items, focusitem);
- return output;
+ return (output);
}
int checklist_builder(BUILDER_ARGS)
{
int output, menurows, nitems, focusitem;
- struct bsddialog_menuitem items[100];
+ struct bsddialog_menuitem items[1024];
if (argc < 1) {
- usage();
+ strcpy(errbuf, "<menurows> not provided");
return (BSDDIALOG_ERROR);
}
menurows = atoi(argv[0]);
- output = get_menu_items(argc-1, argv+1, item_prefix_flag, false, true,
- true, true, item_bottomdesc_flag, &nitems, items);
+ output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
+ true, true, true, item_bottomdesc_flag, &nitems, items);
if (output != 0)
- return output;
+ return (output);
- output = bsddialog_checklist(conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_checklist(&conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_selected_items(conf, output, nitems, items, focusitem);
+ print_menu_items(&conf, output, nitems, items, focusitem);
- return output;
+ return (output);
}
int menu_builder(BUILDER_ARGS)
{
int output, menurows, nitems, focusitem;
- struct bsddialog_menuitem items[100];
+ struct bsddialog_menuitem items[1024];
if (argc < 1) {
- usage();
+ strcpy(errbuf, "<menurows> not provided");
return (BSDDIALOG_ERROR);
}
menurows = atoi(argv[0]);
- output = get_menu_items(argc-1, argv+1, item_prefix_flag, false, true,
- true, false, item_bottomdesc_flag, &nitems, items);
+ output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
+ true, true, false, item_bottomdesc_flag, &nitems, items);
if (output != 0)
- return output;
+ return (output);
- output = bsddialog_menu(conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_menu(&conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_selected_items(conf, output, nitems, items, focusitem);
+ print_menu_items(&conf, output, nitems, items, focusitem);
- return output;
+ return (output);
}
int radiolist_builder(BUILDER_ARGS)
{
int output, menurows, nitems, focusitem;
- struct bsddialog_menuitem items[100];
+ struct bsddialog_menuitem items[1024];
if (argc < 1) {
- usage();
+ strcpy(errbuf, "<menurows> not provided");
return (BSDDIALOG_ERROR);
}
menurows = atoi(argv[0]);
- output = get_menu_items(argc-1, argv+1, item_prefix_flag, false, true,
- true, true, item_bottomdesc_flag, &nitems, items);
+ output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, false,
+ true, true, true, item_bottomdesc_flag, &nitems, items);
if (output != 0)
- return output;
+ return (output);
- output = bsddialog_radiolist(conf, text, rows, cols, menurows, nitems,
+ output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_selected_items(conf, output, nitems, items, focusitem);
+ print_menu_items(&conf, output, nitems, items, focusitem);
- return output;
+ return (output);
}
int treeview_builder(BUILDER_ARGS)
{
int output, menurows, nitems, focusitem;
- struct bsddialog_menuitem items[100];
+ struct bsddialog_menuitem items[1024];
if (argc < 1) {
- usage();
+ strcpy(errbuf, "<menurows> not provided");
return (BSDDIALOG_ERROR);
}
menurows = atoi(argv[0]);
- output = get_menu_items(argc-1, argv+1, item_prefix_flag, true, true,
- true, true, item_bottomdesc_flag, &nitems, items);
+ output = get_menu_items(errbuf, argc-1, argv+1, item_prefix_flag, true,
+ true, true, true, item_bottomdesc_flag, &nitems, items);
if (output != 0)
- return output;
+ return (output);
- output = bsddialog_treeview(conf, text, rows, cols, menurows, nitems,
+ conf.menu.no_name = true;
+ conf.menu.align_left = true;
+
+ output = bsddialog_radiolist(&conf, text, rows, cols, menurows, nitems,
items, &focusitem);
- print_selected_items(conf, output, nitems, items, focusitem);
+ print_menu_items(&conf, output, nitems, items, focusitem);
+
+ return (output);
+}
+
+/* FORM */
+static void
+print_form_items(struct bsddialog_conf *conf, int output, int nitems,
+ struct bsddialog_formitem *items)
+{
+ int i;
+
+ if (output == BSDDIALOG_ERROR)
+ return;
+
+ for (i=0; i < nitems; i++) {
+ dprintf(output_fd_flag, "%s\n", items[i].value);
+ free(items[i].value);
+ }
+}
+
+int form_builder(BUILDER_ARGS)
+{
+ int i, output, formheight, nitems, fieldlen, valuelen;
+ struct bsddialog_formitem items[1024];
+ unsigned int flags = 0;
+
+ if (argc < 1 || (((argc-1) % 8) != 0) ) {
+ strcpy(errbuf, "bad number of arguments for this form\n");
+ return (BSDDIALOG_ERROR);
+ }
+
+ formheight = atoi(argv[0]);
+
+ argc--;
+ argv++;
+
+ nitems = argc / 8;
+ for (i=0; i<nitems; i++) {
+ items[i].label = argv[8*i];
+ items[i].ylabel = atoi(argv[8*i+1]);
+ items[i].xlabel = atoi(argv[8*i+2]);
+ items[i].init = argv[8*i+3];
+ items[i].yfield = atoi(argv[8*i+4]);
+ items[i].xfield = atoi(argv[8*i+5]);
+
+ fieldlen = atoi(argv[8*i+6]);
+ items[i].fieldlen = abs(fieldlen);
+
+ valuelen = atoi(argv[8*i+7]);
+ items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
+
+ flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
+ items[i].flags = flags;
+ }
+
+ output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
+ items);
+ print_form_items(&conf, output, nitems, items);
- return output;
+ return (output);
+}
+
+int inputbox_builder(BUILDER_ARGS)
+{
+ int output;
+ struct bsddialog_formitem item;
+
+ item.label = "";
+ item.ylabel = 0;
+ item.xlabel = 0;
+ item.init = argc > 0 ? argv[0] : "";
+ item.yfield = 1;
+ item.xfield = 1;
+ item.fieldlen = cols > 4 ? cols-4 : 25;
+ item.maxvaluelen = max_input_form_flag > 0 ? max_input_form_flag : 2048;
+ item.flags = 0;
+
+ output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
+ print_form_items(&conf, output, 1, &item);
+
+ return (output);
+}
+
+int mixedform_builder(BUILDER_ARGS)
+{
+ int i, output, formheight, nitems;
+ struct bsddialog_formitem items[1024];
+
+ if (argc < 1 || (((argc-1) % 9) != 0) ) {
+ strcpy(errbuf, "bad number of arguments for this form\n");
+ return (BSDDIALOG_ERROR);
+ }
+
+ formheight = atoi(argv[0]);
+
+ argc--;
+ argv++;
+
+ nitems = argc / 9;
+ for (i=0; i<nitems; i++) {
+ items[i].label = argv[9*i];
+ items[i].ylabel = atoi(argv[9*i+1]);
+ items[i].xlabel = atoi(argv[9*i+2]);
+ items[i].init = argv[9*i+3];
+ items[i].yfield = atoi(argv[9*i+4]);
+ items[i].xfield = atoi(argv[9*i+5]);
+ items[i].fieldlen = atoi(argv[9*i+6]);
+ items[i].maxvaluelen = atoi(argv[9*i+7]);
+ items[i].flags = atoi(argv[9*i+8]);
+ }
+
+ output = bsddialog_form(&conf, text, rows, cols, formheight, nitems,
+ items);
+ print_form_items(&conf, output, nitems, items);
+
+ return (output);
+}
+
+int passwordbox_builder(BUILDER_ARGS)
+{
+ int output;
+ struct bsddialog_formitem item;
+
+ item.label = "";
+ item.ylabel = 0;
+ item.xlabel = 0;
+ item.init = argc > 0 ? argv[0] : "";
+ item.yfield = 1;
+ item.xfield = 1;
+ item.fieldlen = cols > 4 ? cols-4 : 25;
+ item.maxvaluelen = max_input_form_flag > 0 ? max_input_form_flag : 2048;
+ item.flags = BSDDIALOG_FIELDHIDDEN;
+
+ output = bsddialog_form(&conf, text, rows, cols, 1, 1, &item);
+ print_form_items(&conf, output, 1, &item);
+
+ return (output);
+}
+
+int passwordform_builder(BUILDER_ARGS)
+{
+ int i, output, formheight, nitems, fieldlen, valuelen;
+ struct bsddialog_formitem items[1024];
+ unsigned int flags = BSDDIALOG_FIELDHIDDEN;
+
+ if (argc < 1 || (((argc-1) % 8) != 0) ) {
+ strcpy(errbuf, "bad number of arguments for this form\n");
+ return (BSDDIALOG_ERROR);
+ }
+
+ formheight = atoi(argv[0]);
+
+ argc--;
+ argv++;
+
+ nitems = argc / 8;
+ for (i=0; i<nitems; i++) {
+ items[i].label = argv[8*i];
+ items[i].ylabel = atoi(argv[8*i+1]);
+ items[i].xlabel = atoi(argv[8*i+2]);
+ items[i].init = argv[8*i+3];
+ items[i].yfield = atoi(argv[8*i+4]);
+ items[i].xfield = atoi(argv[8*i+5]);
+
+ fieldlen = atoi(argv[8*i+6]);
+ items[i].fieldlen = abs(fieldlen);
+
+ valuelen = atoi(argv[8*i+7]);
+ items[i].maxvaluelen = valuelen == 0 ? abs(fieldlen) : valuelen;
+
+ flags |= (fieldlen < 0 ? BSDDIALOG_FIELDREADONLY : 0);
+ items[i].flags = flags;
+ }
+
+ output = bsddialog_form(&conf, text, rows, cols, formheight,
+ nitems, items);
+ print_form_items(&conf, output, nitems, items);
+
+ return (output);
}
diff --git a/contrib/bsddialog/bsdinstall/Makefile b/contrib/bsddialog/bsdinstall/Makefile
new file mode 100644
index 000000000000..88cb691d8dda
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+SUBDIR= distextract distfetch partedit scripts
+SUBDIR_PARALLEL=
+SCRIPTS= bsdinstall
+MAN= bsdinstall.8
+PACKAGE= bsdinstall
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdinstall/Makefile.depend b/contrib/bsddialog/bsdinstall/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdinstall/Makefile.inc b/contrib/bsddialog/bsdinstall/Makefile.inc
new file mode 100644
index 000000000000..dc4e35b73799
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/Makefile.inc
@@ -0,0 +1 @@
+PACKAGE=bsdinstall
diff --git a/contrib/bsddialog/bsdinstall/README.txt b/contrib/bsddialog/bsdinstall/README.txt
new file mode 100644
index 000000000000..fadac7318dc2
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/README.txt
@@ -0,0 +1,20 @@
+bsdinstall testing
+
+% git clone https://gitlab.com/alfix/bsddialog.git
+% cd bsddialog
+% make
+% cd bsdinstall
+
+You may need to be root to run scripts/utilities:
+
+Script tested:
+
+ - time
+ - docinstall
+ - hardening
+ - hostname
+ - mirrorselect
+
+Utilities (Library) tested:
+
+ - partedit (sade(8)), in progress
diff --git a/contrib/bsddialog/bsdinstall/bsdinstall b/contrib/bsddialog/bsdinstall/bsdinstall
new file mode 100755
index 000000000000..1ca03f5c9593
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/bsdinstall
@@ -0,0 +1,90 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 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$
+#
+############################################################ INCLUDES
+
+# Delay processing of debug flags as the parent until MAIN. export'd to disable
+# re-processing of flags (all children log to the parent's log file).
+#
+export DEBUG_SELF_INITIALIZE=
+export DEBUG_INITIALIZE_FILE=
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ GLOBALS
+
+: ${TMPDIR:="/tmp"}; export TMPDIR
+
+: ${BSDINSTALL_TMPETC="${TMPDIR}/bsdinstall_etc"}; export BSDINSTALL_TMPETC
+: ${BSDINSTALL_TMPBOOT="${TMPDIR}/bsdinstall_boot"}; export BSDINSTALL_TMPBOOT
+: ${PATH_FSTAB="$BSDINSTALL_TMPETC/fstab"}; export PATH_FSTAB
+: ${BSDINSTALL_DISTDIR="/usr/freebsd-dist"}; export BSDINSTALL_DISTDIR
+: ${BSDINSTALL_CHROOT="/mnt"}; export BSDINSTALL_CHROOT
+
+export debugFile="${debugFile-${BSDINSTALL_LOG-${TMPDIR}/bsdinstall_log}}"
+
+############################################################ MAIN
+
+#
+# Process command-line arguments
+#
+while getopts $GETOPTS_STDARGS ignored; do
+ : just skipping known flags
+done
+shift $(( $OPTIND - 1 ))
+
+# What are we here to do?
+VERB="${1:-auto}"; shift
+
+[ -d "$BSDINSTALL_TMPETC" ] || mkdir -p "$BSDINSTALL_TMPETC"
+[ -d "$BSDINSTALL_TMPBOOT" ] || mkdir -p "$BSDINSTALL_TMPBOOT"
+
+# Only enable debugging if debugFile is non-NULL and can be initialized
+f_quietly f_debug_init
+f_isset debugFile || debug=
+
+f_dprintf "Running installation step: %s %s" "$VERB" "$*"
+if [ "$debug" ]; then
+ case "$debugFile" in
+ # If NULL, send errors to the bit-bucket
+ "") exec "/usr/libexec/bsdinstall/$VERB" "$@" 2> /dev/null ;;
+ # If begins with `+', send errors to both terminal and file (no `+')
+ +*) exec "/usr/libexec/bsdinstall/$VERB" "$@" \
+ 2>&1 >&$TERMINAL_STDOUT_PASSTHRU | tee "${debugFile#+}" ;;
+ # Otherwise, just send errors to the file specified
+ *) exec "/usr/libexec/bsdinstall/$VERB" "$@" 2>> "$debugFile"
+ esac
+else
+ exec "/usr/libexec/bsdinstall/$VERB" "$@" 2> /dev/null
+fi
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/bsdinstall.8 b/contrib/bsddialog/bsdinstall/bsdinstall.8
new file mode 100644
index 000000000000..ee23fb4cecc4
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/bsdinstall.8
@@ -0,0 +1,639 @@
+.\"-
+.\" Copyright (c) 2011-2013 Nathan Whitehorn <nwhitehorn@FreeBSD.org> All rights reserved.
+.\" Copyright (c) 2018 Roberto Fernandez Cueto <roberfern@gmail.com>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 26, 2021
+.Dt BSDINSTALL 8
+.Os
+.Sh NAME
+.Nm bsdinstall
+.Nd system installer
+.Sh SYNOPSIS
+.Nm
+.Op Ar options
+.Op Ar target
+.Op Ar ...
+.Sh DESCRIPTION
+.Nm
+is used for installation of new systems, both for system setup from
+installation media, e.g., CD-ROMs, and for use on live systems to prepare
+VM images and jails.
+.Pp
+Much like
+.Xr make 1 , Nm
+takes a target and possible parameters of the target as arguments.
+If invoked with no arguments, it will invoke the
+.Cm auto
+target, which provides a standard interactive installation, invoking the
+others in sequence.
+To perform a scripted installation,
+these subtargets can be invoked separately by an installation script.
+.Sh OPTIONS
+.Nm
+supports the following options, global to all targets:
+.Bl -tag -width indent+
+.It Fl D Ar file
+Provide a path for the installation log file
+.Pq overrides Ev BSDINSTALL_LOG .
+See
+.Sx ENVIRONMENT VARIABLES
+for more information on
+.Ev BSDINSTALL_LOG .
+.El
+.Sh TARGETS
+Most of the following targets are only useful for scripting the installer.
+For interactive use, most users will be interested only in the
+.Cm auto ,
+.Cm jail ,
+and
+.Cm script
+targets.
+.Bl -tag -width ".Cm jail Ar destination"
+.It Cm auto
+Run the standard interactive installation, including disk partitioning.
+.It Cm jail Ar destination
+Sets up a new chroot system at
+.Pa destination ,
+suitable for use with
+.Xr jail 8 .
+Behavior is generally similar to
+.Cm auto ,
+except that disk partitioning and network setup are skipped and a kernel is
+not installed into the new system.
+.It Cm script Ar script
+Runs the installation script at
+.Pa script .
+See
+.Sx SCRIPTING
+for more information on this target.
+.It Cm keymap
+If the current controlling TTY is a
+.Xr syscons 4
+or
+.Xr vt 4
+console, asks the user to set the current keymap, and saves the result to the
+new system's
+.Pa rc.conf .
+.It Cm hostname
+Prompts the user for a host name for the new system and saves the result to the
+new system's
+.Pa rc.conf .
+If
+.Ev BSDINSTALL_CONFIGCURRENT
+is set, also sets the host name of the current system.
+.It Cm netconfig
+Interactively configures network interfaces (first invoking
+.Cm wlanconfig
+on wireless interfaces), saving the result to the new system's
+.Pa rc.conf
+and
+.Pa resolv.conf .
+If
+.Ev BSDINSTALL_CONFIGCURRENT
+is set, also configures the network interfaces of the current system to match.
+.It Cm autopart
+Provides the installer's interactive guided disk partitioner for single-disk
+installations.
+Defaults to UFS.
+.It Cm bootconfig
+Detects an appropriate partition and installs UEFI boot loader files.
+.It Cm zfsboot
+Provides a ZFS-only automatic interactive disk partitioner.
+Creates a single
+.Ic zpool
+with separate datasets for
+.Pa /tmp ,
+.Pa /usr ,
+.Pa /usr/home ,
+.Pa /usr/ports ,
+.Pa /usr/src ,
+and
+.Pa /var .
+Optionally can set up
+.Xr geli 8
+to encrypt the disk.
+.It Cm partedit
+Provides the installer's interactive manual disk partitioner with an interface
+identical to
+.Xr sade 8 .
+Supports multiple disks as well as UFS, ZFS, and FAT file systems.
+ZFS is set up with one pool and dataset per partition.
+.It Cm scriptedpart Ar parameters
+Sets up disks like
+.Cm autopart
+and
+.Cm partedit ,
+but non-interactively according to the disk setup specified in
+.Ar parameters .
+Each disk setup is specified by a three-part argument:
+.Pp
+.Ar disk
+.Op Ar scheme
+.Op Ar {partitions}
+.Pp
+Multiple disk setups are separated by semicolons.
+The
+.Ar disk
+argument specifies the disk on which to operate (which will be erased),
+or the special value
+.Em DEFAULT ,
+which will result in either a selection window (as in
+.Cm autopart )
+for the destination disk or, if there is only one possible disk, will
+automatically select it.
+The
+.Ar scheme
+argument specifies the
+.Xr gpart 8
+partition scheme to apply to the disk.
+If
+.Ar scheme
+is unspecified,
+.Cm scriptedpart
+will apply the default bootable scheme on your platform.
+The
+.Ar partitions
+argument is also optional and specifies how to partition
+.Ar disk .
+It consists of a comma-separated list of partitions to create enclosed in
+curly braces.
+Each partition declaration takes the form
+.Pp
+.Ar size
+.Ar type
+.Op Ar mount point
+.Pp
+.Ar size
+specifies the partition size to create in bytes (K, M, and G suffixes
+can be appended to specify kilobytes, megabytes, and gigabytes respectively),
+while the
+.Em auto
+keyword causes the partition to take all the remaining space on the disk.
+The
+.Ar type
+option chooses the
+.Xr gpart 8
+filesystem type, e.g., freebsd-ufs, freebsd-zfs, or freebsd-swap.
+The optional
+.Ar mount point
+argument sets where the created partition is to be mounted in the installed
+system.
+As an example, a typical invocation looks like:
+.Pp
+bsdinstall scriptedpart ada0 { 20G freebsd-ufs /, 4G freebsd-swap, 20G freebsd-ufs /var, auto freebsd-ufs /usr }
+.Pp
+Note that the list of partitions should
+.Em not
+include boot partitions (e.g. EFI system partitions), which will be created automatically on whatever disk includes /.
+.Pp
+A shorter invocation to use the default partitioning (as
+.Cm autopart
+would have used) on the same disk:
+.Pp
+bsdinstall scriptedpart ada0
+.Pp
+or, even shorter:
+.Pp
+bsdinstall scriptedpart DEFAULT
+.It Cm mount
+Mounts the file systems previously configured by
+.Cm autopart ,
+.Cm partedit ,
+or
+.Cm scriptedpart
+under
+.Ev BSDINSTALL_CHROOT .
+.It Cm distfetch
+Fetches the distributions in
+.Ev DISTRIBUTIONS
+to
+.Ev BSDINSTALL_DISTDIR
+from
+.Ev BSDINSTALL_DISTSITE .
+.It Cm checksum
+Verifies the checksums of the distributions listed in
+.Ev DISTRIBUTIONS
+against the distribution manifest.
+.It Cm distextract
+Extracts the distributions listed in
+.Ev DISTRIBUTIONS
+into
+.Ev BSDINSTALL_CHROOT .
+.It Cm rootpass
+Interactively invokes
+.Xr passwd 1
+in the new system to set the root user's password.
+.It Cm adduser
+Interactively invokes
+.Xr adduser 8
+in the new system.
+.It Cm time
+Interactively sets the time, date, and time zone of the new system.
+.It Cm services
+Queries the user for the system daemons to begin at system startup,
+writing the result into the new system's
+.Pa rc.conf .
+.It Cm entropy
+Reads a small amount of data from
+.Pa /dev/random
+and stores it in a file in the new system's root directory.
+.It Cm config
+Installs the configuration files destined for the new system, e.g.,
+.Xr rc.conf 5
+fragments generated by
+.Cm netconfig ,
+etc.) onto the new system.
+.El
+.Sh ENVIRONMENT VARIABLES
+The following environment variables control various aspects of the installation
+process.
+Many are used internally during installation and have reasonable default values
+for most installation scenarios.
+Others are set by various interactive user prompts, and can be usefully
+overridden when making scripted or customized installers.
+.Bl -tag -width ".Ev BSDINSTALL_DISTSITE"
+.It Ev TMPDIR
+The directory to use for temporary files.
+Default:
+.Dq Pa /tmp
+.It Ev DISTRIBUTIONS
+The set of distributions to install, e.g., "base.txz kernel.txz ports.txz".
+Default: unset
+.It Ev PARTITIONS
+The partitioning of the disk onto which the system is being installed.
+See
+.Cm scriptedpart
+of
+the
+.Sx TARGETS
+section for format details. If this variable is unset, the installer will
+use the default partitioning as in
+.Cm autopart .
+Default: unset
+.It Ev BSDINSTALL_DISTDIR
+The directory in which the distribution files can be found (or to which they
+should be downloaded).
+Default:
+.Dq Pa /usr/freebsd-dist
+.It Ev BSDINSTALL_DISTSITE
+URL from which the distribution files should be downloaded if they are not
+already present in the directory defined by
+.Ev BSDINSTALL_DISTDIR .
+This should be a full path to the files, including architecture and release
+names.
+Most targets, e.g.,
+.Cm auto
+and
+.Cm jail ,
+that prompt for a
+.Fx
+mirror will skip that step if this variable is already defined in the
+environment.
+Example:
+.Pa ftp://ftp.freebsd.org/pub/FreeBSD/releases/powerpc/powerpc64/9.1-RELEASE
+.It Ev BSDINSTALL_CHROOT
+The directory into which the distribution files should be unpacked and the
+directory at which the root file system of the new system should be mounted.
+Default:
+.Dq Pa /mnt
+.It Ev BSDINSTALL_LOG
+Path to a log file for the installation.
+Default:
+.Dq Pa $TMPDIR/bsdinstall_log
+.It Ev BSDINSTALL_TMPETC
+Directory where files destined for the new system's
+.Pa /etc
+will be stored until the
+.Cm config
+target is executed.
+If this directory does not already exist, it will be created.
+Default:
+.Dq Pa $TMPDIR/bsdinstall_etc
+.It Ev BSDINSTALL_TMPBOOT
+Directory where files destined for the new system's
+.Pa /boot
+will be stored until the
+.Cm config
+target is executed.
+If this directory does not already exist, it will be created.
+Default:
+.Dq Pa $TMPDIR/bsdinstall_boot
+.It Ev ZFSBOOT_POOL_NAME
+Name for the pool containing the base system.
+Default:
+.Dq zroot
+.It Ev ZFSBOOT_POOL_CREATE_OPTIONS
+Options to be used when creating the base system's pool.
+Each option must be followed by the -O flag to be taken into consideration
+or the pool will not be created due to errors using the command
+.Cm zpool .
+Default:
+.Dq Li "-O compress=lz4 -O atime=off"
+.It Ev ZFSBOOT_BEROOT_NAME
+Name for the boot environment parent dataset.
+This is a non-mountable dataset meant to be a parent dataset where different
+boot environment are going to be created.
+Default:
+.Dq ROOT
+.It Ev ZFSBOOT_BOOTFS_NAME
+Name for the primary boot environment, which will be the default boot
+environment for the system.
+Default:
+.Dq default
+.It Ev ZFSBOOT_VDEV_TYPE
+The type of pool to be created for the base system.
+This variable can take one of this values: stripe (No redundancy),
+mirror (n-Way mirroring), raid10 (RAID 1+0 - n x 2-Way Mirrors),
+raidz1 (RAID-Z1 - Single Redundancy RAID), raidz2 (RAID-Z2 - Double Redundancy RAID)
+or raidz3 (RAID-Z3 Triple Redundancy RAID).
+Default:
+.Dq stripe
+.It Ev ZFSBOOT_FORCE_4K_SECTORS
+Indicates either the pool will use 4K or 512 sectors.
+If this variable is not empty, 4K sectors will be used.
+Default:
+.Dq 1
+.It Ev ZFSBOOT_GELI_ENCRYPTION
+If this variable is not empty, it will use
+.Xr geli 8
+to encrypt the root pool, enabling automatically the
+.Ev ZFSBOOT_BOOT_POOL
+variable.
+Default:
+.Dq ""
+.It Ev ZFSBOOT_GELI_KEY_FILE
+Path to the
+.Xr geli 8
+keyfile used to encrypt the pool where the base system is stored.
+Default:
+.Dq Pa /boot/encryption.key
+.It Ev ZFSBOOT_BOOT_POOL
+If set a separated boot pool will be created for the kernel of the
+system and
+.Xr loader 8 .
+Default: unset
+.It Ev ZFSBOOT_BOOT_POOL_CREATE_OPTIONS
+Options to use when creating the boot pool, when enabled (See
+.Ev ZFSBOOT_BOOT_POOL ).
+Default: unset
+.It Ev ZFSBOOT_BOOT_POOL_NAME
+Name for the optional boot pool when it is enabled, (See
+.Ev ZFSBOOT_BOOT_POOL ).
+Default:
+.Dq bootpool
+.It Ev ZFSBOOT_BOOT_POOL_SIZE
+Size of the boot pool when it is enabled (See
+.Ev ZFSBOOT_BOOT_POOL ).
+Default:
+.Dq 2g
+.It Ev ZFSBOOT_DISKS
+Disks to be used for the base system, including the boot pool.
+This variable must only be used on a scripted installation.
+See
+.Sx SCRIPTING
+for more information.
+Default: unset
+.It Ev ZFSBOOT_SWAP_SIZE
+Size of the swap partition on each block device.
+This variable will be passed to
+.Xr gpart 8 ;
+which supports SI unit suffixes.
+Default:
+.Dq 2g
+.It Ev ZFSBOOT_SWAP_ENCRYPTION
+If set, enables the encryption of the swap partition using
+.Xr geli 8 .
+Default: ""
+.It Ev ZFSBOOT_SWAP_MIRROR
+If set, enables a swap mirroring using
+.Xr gmirror 8 .
+Default:
+unset
+.It Ev ZFSBOOT_DATASETS
+ZFS datasets to be created on the root zpool, it requires the
+following datasets:
+.Pa /tmp ,
+.Pa /var/tmp ,
+.Pa /$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME .
+See
+.Sx ZFS DATASETS
+for more information about who to write this variable and to
+take a look into the default value of it.
+.It Ev ZFSBOOT_CONFIRM_LAYOUT
+If set and the installation is interactive, allow the user to confirm
+the layout before continuing with the installation.
+Default:
+.Dq 1
+.El
+.Sh SCRIPTING
+.Nm
+supports unattended, or minimally-attended, installations using scripting.
+This can be used with either modified physical installation media or with
+.Xr diskless 8
+installations over the network; information on preparing such media can be
+found in
+.Sx BUILDING AUTOMATIC INSTALL MEDIA
+.Pp
+Scripted installations follow an essentially identical path to interactive
+installations, though with some minor feature differences (for example,
+scripted installations do not support fetching of remote distribution files
+since scripted installations normally install the same files and the distributions
+can be added directly to the installation media).
+.Nm
+scripts consist of two parts: a
+.Em preamble
+and a
+.Em setup script .
+The preamble sets up the options for the installation (how to partition the
+disk[s], which distributions to install, etc.) and the optional second part is
+a shell script run under
+.Xr chroot 8
+in the newly installed system before
+.Nm
+exits.
+The two parts are separated by the usual script header (#!), which also sets
+the interpreter for the setup script.
+.Pp
+A typical bsdinstall script, using the default filesystem layout and the UFS
+filesystem, looks like this:
+.Bd -literal -offset indent
+PARTITIONS=DEFAULT
+DISTRIBUTIONS="kernel.txz base.txz"
+
+#!/bin/sh
+sysrc ifconfig_DEFAULT=DHCP
+sysrc sshd_enable=YES
+pkg install puppet
+.Ed
+.Pp
+For a scripted installation involving a ZFS pool spanning multiple disks,
+the script instead looks like this:
+.Bd -literal -offset indent
+DISTRIBUTIONS="kernel.txz base.txz"
+export ZFSBOOT_VDEV_TYPE=stripe
+export ZFSBOOT_DISKS="ada0 ada1"
+export nonInteractive="YES"
+
+#!/bin/sh
+echo "ifconfig_DEFAULT=DHCP" >> /etc/rc.conf
+echo "sshd_enable=YES" >> /etc/rc.conf
+pkg install puppet
+.Ed
+.Pp
+On
+.Fx
+release media, such a script placed at
+.Pa /etc/installerconfig
+will be run at boot time and the system will be rebooted automatically after
+the installation has completed.
+This can be used for unattended network installation of new systems; see
+.Xr diskless 8
+for details.
+.Ss PREAMBLE
+The preamble consists of installer settings.
+These control global installation parameters (see
+.Sx ENVIRONMENT VARIABLES )
+as well as disk partitioning.
+The preamble is interpreted as a
+.Xr sh 1
+script run at the very beginning of the install.
+If more complicated behavior than setting these variables is desired,
+arbitrary commands can be run here to extend the installer.
+In addition to the variables in
+.Sx ENVIRONMENT VARIABLES ,
+in particular
+.Ev DISTRIBUTIONS ,
+the preamble can contain a variable
+.Ev PARTITIONS
+which is passed to the
+.Cm scriptedpart
+target to control disk setup.
+.Pp
+Alternatively,
+to use
+.Cm zfsboot
+instead of
+.Cm partedit ,
+the preamble can contain the variable
+.Ev ZFSBOOT_DATASETS
+instead of
+.Ev PARTITIONS
+(see below).
+If using .Cm zfsboot, the variables
+.Ev ZFSBOOT_DISKS
+and
+.Ev ZFSBOOT_VDEV_TYPE
+must be set to create the pool of disks for the base system.
+Usually, for a mirrored booting disk, this two variables looks like this:
+.Bd -literal -offset indent
+ZFSBOOT_DISKS="ada0 ada1"
+ZFSBOOT_VDEV_TYPE=mirror
+.Ed
+.Pp
+Remember to export all the variables for the
+.Cm zfsboot
+command, otherwise installation will fail.
+.Ss SETUP SCRIPT
+Following the preamble is an optional shell script, beginning with a #!
+declaration.
+This script will be run at the end of the installation process inside a
+.Xr chroot 8
+environment in the newly installed system and can be used to set up
+configuration files, install packages, etc.
+Note that newly configured system services, e.g., networking have not
+been started in the installed system at this time and only installation
+host services are available.
+.Ss ZFS DATASETS
+If using
+.Cm zfsboot
+in an installation script, the
+.Cm zfsboot
+partitioning tool takes the
+.Ev ZFSBOOT_DATASETS
+variable to create the ZFS datasets on the base system.
+This variable definition can become large if the pool contains many datasets.
+The default value of the
+.Ev ZFSBOOT_DATASETS
+is:
+.Bd -literal -offset indent
+# DATASET OPTIONS (comma or space separated; or both)
+
+# Boot Environment [BE] root and default boot dataset
+/$ZFSBOOT_BEROOT_NAME mountpoint=none
+/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME mountpoint=/
+
+# Compress /tmp, allow exec but not setuid
+/tmp mountpoint=/tmp,exec=on,setuid=off
+
+# Do not mount /usr so that 'base' files go to the BEROOT
+/usr mountpoint=/usr,canmount=off
+
+# Home directories separated so they are common to all BEs
+/usr/home # NB: /home is a symlink to /usr/home
+
+# Ports tree
+/usr/ports setuid=off
+
+# Source tree (compressed)
+/usr/src
+
+# Create /var and friends
+/var mountpoint=/var,canmount=off
+/var/audit exec=off,setuid=off
+/var/crash exec=off,setuid=off
+/var/log exec=off,setuid=off
+/var/mail atime=on
+/var/tmp setuid=off
+.Ed
+.Pp
+The first column is the name of the dataset to be created as part of the
+.Ev ZFSBOOT_POOL_NAME
+pool and the remainder of each line contains the options to be set on each dataset.
+If multiple options are given, they can be separated by either commas or whitespace;
+everything following a pound/hash character is ignored as a comment.
+.Ss BUILDING AUTOMATIC INSTALL MEDIA
+If building automatic install media, use tar to extract a release ISO:
+.Dl mkdir release-media
+.Dl tar xvf -C release-media FreeBSD-13.0-RELEASE-amd64-disc1.iso
+.Pp
+Then place a script as above in
+.Pa etc/installerconfig
+.Pp
+This directory can then be used directly as an NFS root for
+.Xr diskless 8
+installations or it can be rebuilt into an ISO image using the release scripts in
+.Pa /usr/src/release .
+For example, on amd64:
+.Dl sh /usr/src/release/amd64/mkisoimages.sh -b '13_0_RELEASE_AMD64_CD' output.iso release-media
+.Sh HISTORY
+This version of
+.Nm
+first appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.An Nathan Whitehorn Aq Mt nwhitehorn@FreeBSD.org
+.An Devin Teske Aq Mt dteske@FreeBSD.org
+.An Allan Jude Aq Mt allanjude@FreeBSD.org
diff --git a/contrib/bsddialog/bsdinstall/distextract/Makefile b/contrib/bsddialog/bsdinstall/distextract/Makefile
new file mode 100644
index 000000000000..2b7180e28ea0
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/distextract/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+BINDIR= ${LIBEXECDIR}/bsdinstall
+PROG= distextract
+LIBADD= archive dpv dialog m
+
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdinstall/distextract/Makefile.depend b/contrib/bsddialog/bsdinstall/distextract/Makefile.depend
new file mode 100644
index 000000000000..78020ffb2489
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/distextract/Makefile.depend
@@ -0,0 +1,30 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ gnu/lib/libdialog \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libarchive \
+ lib/libbz2 \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libdpv \
+ lib/libexpat \
+ lib/libfigpar \
+ lib/liblzma \
+ lib/libthr \
+ lib/libutil \
+ lib/libz \
+ lib/msun \
+ lib/ncurses/ncursesw \
+ secure/lib/libcrypto \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdinstall/distextract/distextract.c b/contrib/bsddialog/bsdinstall/distextract/distextract.c
new file mode 100644
index 000000000000..8ad6c7b2c64b
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/distextract/distextract.c
@@ -0,0 +1,334 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * Copyright (c) 2014 Devin Teske <dteske@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <archive.h>
+#include <ctype.h>
+#include <dialog.h>
+#include <dpv.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Data to process */
+static char *distdir = NULL;
+static struct archive *archive = NULL;
+static struct dpv_file_node *dists = NULL;
+
+/* Function prototypes */
+static void sig_int(int sig);
+static int count_files(const char *file);
+static int extract_files(struct dpv_file_node *file, int out);
+
+#define _errx(...) (end_dialog(), errx(__VA_ARGS__))
+
+int
+main(void)
+{
+ char *chrootdir;
+ char *distributions;
+ int retval;
+ size_t config_size = sizeof(struct dpv_config);
+ size_t file_node_size = sizeof(struct dpv_file_node);
+ size_t span;
+ struct dpv_config *config;
+ struct dpv_file_node *dist = dists;
+ static char backtitle[] = "FreeBSD Installer";
+ static char title[] = "Archive Extraction";
+ static char aprompt[] = "\n Overall Progress:";
+ static char pprompt[] = "Extracting distribution files...\n";
+ struct sigaction act;
+ char error[PATH_MAX + 512];
+
+ if ((distributions = getenv("DISTRIBUTIONS")) == NULL)
+ errx(EXIT_FAILURE, "DISTRIBUTIONS variable is not set");
+ if ((distdir = getenv("BSDINSTALL_DISTDIR")) == NULL)
+ distdir = __DECONST(char *, "");
+
+ /* Initialize dialog(3) */
+ init_dialog(stdin, stdout);
+ dialog_vars.backtitle = backtitle;
+ dlg_put_backtitle();
+
+ dialog_msgbox("",
+ "Checking distribution archives.\nPlease wait...", 4, 35, FALSE);
+
+ /*
+ * Parse $DISTRIBUTIONS into dpv(3) linked-list
+ */
+ while (*distributions != '\0') {
+ span = strcspn(distributions, "\t\n\v\f\r ");
+ if (span < 1) { /* currently on whitespace */
+ distributions++;
+ continue;
+ }
+
+ /* Allocate a new struct for the distribution */
+ if (dist == NULL) {
+ if ((dist = calloc(1, file_node_size)) == NULL)
+ _errx(EXIT_FAILURE, "Out of memory!");
+ dists = dist;
+ } else {
+ dist->next = calloc(1, file_node_size);
+ if (dist->next == NULL)
+ _errx(EXIT_FAILURE, "Out of memory!");
+ dist = dist->next;
+ }
+
+ /* Set path */
+ if ((dist->path = malloc(span + 1)) == NULL)
+ _errx(EXIT_FAILURE, "Out of memory!");
+ snprintf(dist->path, span + 1, "%s", distributions);
+ dist->path[span] = '\0';
+
+ /* Set display name */
+ dist->name = strrchr(dist->path, '/');
+ if (dist->name == NULL)
+ dist->name = dist->path;
+
+ /* Set initial length in files (-1 == error) */
+ dist->length = count_files(dist->path);
+ if (dist->length < 0) {
+ end_dialog();
+ return (EXIT_FAILURE);
+ }
+
+ distributions += span;
+ }
+
+ /* Optionally chdir(2) into $BSDINSTALL_CHROOT */
+ chrootdir = getenv("BSDINSTALL_CHROOT");
+ if (chrootdir != NULL && chdir(chrootdir) != 0) {
+ snprintf(error, sizeof(error),
+ "Could not change to directory %s: %s\n",
+ chrootdir, strerror(errno));
+ dialog_msgbox("Error", error, 0, 0, TRUE);
+ end_dialog();
+ return (EXIT_FAILURE);
+ }
+
+ /* Set cleanup routine for Ctrl-C action */
+ act.sa_handler = sig_int;
+ sigaction(SIGINT, &act, 0);
+
+ /*
+ * Hand off to dpv(3)
+ */
+ if ((config = calloc(1, config_size)) == NULL)
+ _errx(EXIT_FAILURE, "Out of memory!");
+ config->backtitle = backtitle;
+ config->title = title;
+ config->pprompt = pprompt;
+ config->aprompt = aprompt;
+ config->options |= DPV_WIDE_MODE;
+ config->label_size = -1;
+ config->action = extract_files;
+ config->status_solo =
+ "%10lli files read @ %'9.1f files/sec.";
+ config->status_many =
+ "%10lli files read @ %'9.1f files/sec. [%i/%i busy/wait]";
+ end_dialog();
+ retval = dpv(config, dists);
+
+ dpv_free();
+ while ((dist = dists) != NULL) {
+ dists = dist->next;
+ if (dist->path != NULL)
+ free(dist->path);
+ free(dist);
+ }
+
+ return (retval);
+}
+
+static void
+sig_int(int sig __unused)
+{
+ dpv_interrupt = TRUE;
+}
+
+/*
+ * Returns number of files in archive file. Parses $BSDINSTALL_DISTDIR/MANIFEST
+ * if it exists, otherwise uses archive(3) to read the archive file.
+ */
+static int
+count_files(const char *file)
+{
+ static FILE *manifest = NULL;
+ char *p;
+ int file_count;
+ int retval;
+ size_t span;
+ struct archive_entry *entry;
+ char line[512];
+ char path[PATH_MAX];
+ char errormsg[PATH_MAX + 512];
+
+ if (manifest == NULL) {
+ snprintf(path, sizeof(path), "%s/MANIFEST", distdir);
+ manifest = fopen(path, "r");
+ }
+
+ if (manifest != NULL) {
+ rewind(manifest);
+ while (fgets(line, sizeof(line), manifest) != NULL) {
+ p = &line[0];
+ span = strcspn(p, "\t") ;
+ if (span < 1 || strncmp(p, file, span) != 0)
+ continue;
+
+ /*
+ * We're at the right manifest line. The file count is
+ * in the third element
+ */
+ span = strcspn(p += span + (*p != '\0' ? 1 : 0), "\t");
+ span = strcspn(p += span + (*p != '\0' ? 1 : 0), "\t");
+ if (span > 0) {
+ file_count = (int)strtol(p, (char **)NULL, 10);
+ if (file_count == 0 && errno == EINVAL)
+ continue;
+ return (file_count);
+ }
+ }
+ }
+
+ /*
+ * Either no manifest, or manifest didn't mention this archive.
+ * Use archive(3) to read the archive, counting files within.
+ */
+ if ((archive = archive_read_new()) == NULL) {
+ snprintf(errormsg, sizeof(errormsg),
+ "Error: %s\n", archive_error_string(NULL));
+ dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE);
+ return (-1);
+ }
+ archive_read_support_format_all(archive);
+ archive_read_support_filter_all(archive);
+ snprintf(path, sizeof(path), "%s/%s", distdir, file);
+ retval = archive_read_open_filename(archive, path, 4096);
+ if (retval != ARCHIVE_OK) {
+ snprintf(errormsg, sizeof(errormsg),
+ "Error while extracting %s: %s\n", file,
+ archive_error_string(archive));
+ dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE);
+ archive = NULL;
+ return (-1);
+ }
+
+ file_count = 0;
+ while (archive_read_next_header(archive, &entry) == ARCHIVE_OK)
+ file_count++;
+ archive_read_free(archive);
+ archive = NULL;
+
+ return (file_count);
+}
+
+static int
+extract_files(struct dpv_file_node *file, int out __unused)
+{
+ int retval;
+ struct archive_entry *entry;
+ char path[PATH_MAX];
+ char errormsg[PATH_MAX + 512];
+
+ /* Open the archive if necessary */
+ if (archive == NULL) {
+ if ((archive = archive_read_new()) == NULL) {
+ snprintf(errormsg, sizeof(errormsg),
+ "Error: %s\n", archive_error_string(NULL));
+ dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE);
+ dpv_abort = 1;
+ return (-1);
+ }
+ archive_read_support_format_all(archive);
+ archive_read_support_filter_all(archive);
+ snprintf(path, sizeof(path), "%s/%s", distdir, file->path);
+ retval = archive_read_open_filename(archive, path, 4096);
+ if (retval != 0) {
+ snprintf(errormsg, sizeof(errormsg),
+ "Error opening %s: %s\n", file->name,
+ archive_error_string(archive));
+ dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE);
+ file->status = DPV_STATUS_FAILED;
+ dpv_abort = 1;
+ return (-1);
+ }
+ }
+
+ /* Read the next archive header */
+ retval = archive_read_next_header(archive, &entry);
+
+ /* If that went well, perform the extraction */
+ if (retval == ARCHIVE_OK)
+ retval = archive_read_extract(archive, entry,
+ ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_OWNER |
+ ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL |
+ ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_FFLAGS);
+
+ /* Test for either EOF or error */
+ if (retval == ARCHIVE_EOF) {
+ archive_read_free(archive);
+ archive = NULL;
+ file->status = DPV_STATUS_DONE;
+ return (100);
+ } else if (retval != ARCHIVE_OK &&
+ !(retval == ARCHIVE_WARN &&
+ strcmp(archive_error_string(archive), "Can't restore time") == 0)) {
+ /*
+ * Print any warning/error messages except inability to set
+ * ctime/mtime, which is not fatal, or even interesting,
+ * for our purposes. Would be nice if this were a libarchive
+ * option.
+ */
+ snprintf(errormsg, sizeof(errormsg),
+ "Error while extracting %s: %s\n", file->name,
+ archive_error_string(archive));
+ dialog_msgbox("Extract Error", errormsg, 0, 0, TRUE);
+ file->status = DPV_STATUS_FAILED;
+ dpv_abort = 1;
+ return (-1);
+ }
+
+ dpv_overall_read++;
+ file->read++;
+
+ /* Calculate [overall] percentage of completion (if possible) */
+ if (file->length >= 0)
+ return (file->read * 100 / file->length);
+ else
+ return (-1);
+}
diff --git a/contrib/bsddialog/bsdinstall/distfetch/Makefile b/contrib/bsddialog/bsdinstall/distfetch/Makefile
new file mode 100644
index 000000000000..70ecb381d485
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/distfetch/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+BINDIR= ${LIBEXECDIR}/bsdinstall
+PROG= distfetch
+LIBADD= fetch dialog m
+
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdinstall/distfetch/Makefile.depend b/contrib/bsddialog/bsdinstall/distfetch/Makefile.depend
new file mode 100644
index 000000000000..c1195d955ced
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/distfetch/Makefile.depend
@@ -0,0 +1,23 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ gnu/lib/libdialog \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libfetch \
+ lib/msun \
+ lib/ncurses/ncursesw \
+ secure/lib/libcrypto \
+ secure/lib/libssl \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdinstall/distfetch/distfetch.c b/contrib/bsddialog/bsdinstall/distfetch/distfetch.c
new file mode 100644
index 000000000000..5f262343720e
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/distfetch/distfetch.c
@@ -0,0 +1,225 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * Copyright (c) 2014 Devin Teske <dteske@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <ctype.h>
+#include <err.h>
+#include <dialog.h>
+#include <errno.h>
+#include <fetch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static int fetch_files(int nfiles, char **urls);
+
+int
+main(void)
+{
+ char *diststring;
+ char **urls;
+ int i;
+ int ndists = 0;
+ int nfetched;
+ char error[PATH_MAX + 512];
+
+ if (getenv("DISTRIBUTIONS") == NULL)
+ errx(EXIT_FAILURE, "DISTRIBUTIONS variable is not set");
+
+ diststring = strdup(getenv("DISTRIBUTIONS"));
+ for (i = 0; diststring[i] != 0; i++)
+ if (isspace(diststring[i]) && !isspace(diststring[i+1]))
+ ndists++;
+ ndists++; /* Last one */
+
+ urls = calloc(ndists, sizeof(const char *));
+ if (urls == NULL) {
+ free(diststring);
+ errx(EXIT_FAILURE, "Out of memory!");
+ }
+
+ init_dialog(stdin, stdout);
+ dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer");
+ dlg_put_backtitle();
+
+ for (i = 0; i < ndists; i++) {
+ urls[i] = malloc(PATH_MAX);
+ snprintf(urls[i], PATH_MAX, "%s/%s",
+ getenv("BSDINSTALL_DISTSITE"), strsep(&diststring, " \t"));
+ }
+
+ if (chdir(getenv("BSDINSTALL_DISTDIR")) != 0) {
+ snprintf(error, sizeof(error),
+ "Could not change to directory %s: %s\n",
+ getenv("BSDINSTALL_DISTDIR"), strerror(errno));
+ dialog_msgbox("Error", error, 0, 0, TRUE);
+ end_dialog();
+ return (EXIT_FAILURE);
+ }
+
+ nfetched = fetch_files(ndists, urls);
+
+ end_dialog();
+
+ free(diststring);
+ for (i = 0; i < ndists; i++)
+ free(urls[i]);
+ free(urls);
+
+ return ((nfetched == ndists) ? EXIT_SUCCESS : EXIT_FAILURE);
+}
+
+static int
+fetch_files(int nfiles, char **urls)
+{
+ FILE *fetch_out;
+ FILE *file_out;
+ const char **items;
+ int i;
+ int last_progress;
+ int nsuccess = 0; /* Number of files successfully downloaded */
+ int progress = 0;
+ size_t chunk;
+ off_t current_bytes;
+ off_t fsize;
+ off_t total_bytes;
+ char status[8];
+ struct url_stat ustat;
+ char errormsg[PATH_MAX + 512];
+ uint8_t block[4096];
+
+ /* Make the transfer list for dialog */
+ items = calloc(sizeof(char *), nfiles * 2);
+ if (items == NULL)
+ errx(EXIT_FAILURE, "Out of memory!");
+
+ for (i = 0; i < nfiles; i++) {
+ items[i*2] = strrchr(urls[i], '/');
+ if (items[i*2] != NULL)
+ items[i*2]++;
+ else
+ items[i*2] = urls[i];
+ items[i*2 + 1] = "Pending";
+ }
+
+ dialog_msgbox("", "Connecting to server.\nPlease wait...", 0, 0, FALSE);
+
+ /* Try to stat all the files */
+ total_bytes = 0;
+ for (i = 0; i < nfiles; i++) {
+ if (fetchStatURL(urls[i], &ustat, "") == 0 && ustat.size > 0)
+ total_bytes += ustat.size;
+ }
+
+ current_bytes = 0;
+ for (i = 0; i < nfiles; i++) {
+ last_progress = progress;
+ if (total_bytes == 0)
+ progress = (i*100)/nfiles;
+
+ fetchLastErrCode = 0;
+ fetch_out = fetchXGetURL(urls[i], &ustat, "");
+ if (fetch_out == NULL) {
+ snprintf(errormsg, sizeof(errormsg),
+ "Error while fetching %s: %s\n", urls[i],
+ fetchLastErrString);
+ items[i*2 + 1] = "Failed";
+ dialog_msgbox("Fetch Error", errormsg, 0, 0,
+ TRUE);
+ continue;
+ }
+
+ items[i*2 + 1] = "In Progress";
+ fsize = 0;
+ file_out = fopen(items[i*2], "w+");
+ if (file_out == NULL) {
+ snprintf(errormsg, sizeof(errormsg),
+ "Error while fetching %s: %s\n",
+ urls[i], strerror(errno));
+ items[i*2 + 1] = "Failed";
+ dialog_msgbox("Fetch Error", errormsg, 0, 0,
+ TRUE);
+ fclose(fetch_out);
+ continue;
+ }
+
+ while ((chunk = fread(block, 1, sizeof(block), fetch_out))
+ > 0) {
+ if (fwrite(block, 1, chunk, file_out) < chunk)
+ break;
+
+ current_bytes += chunk;
+ fsize += chunk;
+
+ if (total_bytes > 0) {
+ last_progress = progress;
+ progress = (current_bytes*100)/total_bytes;
+ }
+
+ if (ustat.size > 0) {
+ snprintf(status, sizeof(status), "-%jd",
+ (fsize*100)/ustat.size);
+ items[i*2 + 1] = status;
+ }
+
+ if (progress > last_progress)
+ dialog_mixedgauge("Fetching Distribution",
+ "Fetching distribution files...", 0, 0,
+ progress, nfiles,
+ __DECONST(char **, items));
+ }
+
+ if (ustat.size > 0 && fsize < ustat.size) {
+ if (fetchLastErrCode == 0)
+ snprintf(errormsg, sizeof(errormsg),
+ "Error while fetching %s: %s\n",
+ urls[i], strerror(errno));
+ else
+ snprintf(errormsg, sizeof(errormsg),
+ "Error while fetching %s: %s\n",
+ urls[i], fetchLastErrString);
+ items[i*2 + 1] = "Failed";
+ dialog_msgbox("Fetch Error", errormsg, 0, 0,
+ TRUE);
+ } else {
+ items[i*2 + 1] = "Done";
+ nsuccess++;
+ }
+
+ fclose(fetch_out);
+ fclose(file_out);
+ }
+
+ free(items);
+ return (nsuccess);
+}
diff --git a/contrib/bsddialog/bsdinstall/partedit/Makefile b/contrib/bsddialog/bsdinstall/partedit/Makefile
new file mode 100644
index 000000000000..e63840cbb9dc
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/Makefile
@@ -0,0 +1,52 @@
+# Any copyright is dedicated to the Public Domain, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>
+#
+# Written by Alfonso Sabato Siciliano
+
+OUTPUT= sade
+# arch: partedit_powerpc.c partedit_efi.c partedit_generic.c diskeditor.c
+SOURCES= diskmenu.c gpart_ops.c part_wizard.c partedit_x86.c partedit.c \
+ scripted.c
+OBJECTS= ${SOURCES:.c=.o}
+#LIBPATH= ${.CURDIR}../../../lib
+LIBPATH= ../../lib
+LIBBSDDIALOG= ${LIBPATH}/libbsddialog.so
+
+CFLAGS= -Wall -I${LIBPATH}
+LDFLAGS= -Wl,-rpath=${LIBPATH} -L${LIBPATH} -lbsddialog -lgeom -lncursesw -lutil -ldialog -lm
+
+BINDIR= /usr/local/bin
+MAN= ${OUTPUT}.1
+GZIP= gzip -cn
+MANDIR= /usr/local/share/man/man1
+
+INSTALL= install
+RM= rm -f
+
+all : ${OUTPUT}
+
+${OUTPUT}: ${LIBBSDDIALOG} ${OBJECTS}
+ ${CC} ${LDFLAGS} ${OBJECTS} -o ${.PREFIX}
+
+${LIBBSDDIALOG}:
+.if defined(PORTNCURSES)
+ make -C ${LIBPATH} -DPORTNCURSES
+.else
+ make -C ${LIBPATH}
+.endif
+
+.c.o:
+ ${CC} ${CFLAGS} -c ${.IMPSRC} -o ${.TARGET}
+
+install:
+ ${INSTALL} -s -m 555 ${OUTPUT} ${BINDIR}
+ ${GZIP} ${MAN} > ${MAN}.gz
+ ${INSTALL} -m 444 ${MAN}.gz ${MANDIR}
+
+unistall:
+ ${RM} ${BINDIR}/${OUTPUT}
+ ${RM} ${MANDIR}/${MAN}.gz
+
+clean:
+ make -C ${LIBPATH} clean
+ ${RM} ${OUTPUT} *.o *~ *.core ${MAN}.gz
diff --git a/contrib/bsddialog/bsdinstall/partedit/Makefile.depend b/contrib/bsddialog/bsdinstall/partedit/Makefile.depend
new file mode 100644
index 000000000000..2c3bc47c6d42
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/Makefile.depend
@@ -0,0 +1,24 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+ gnu/lib/csu \
+ gnu/lib/libdialog \
+ include \
+ include/xlocale \
+ lib/${CSU_DIR} \
+ lib/libc \
+ lib/libcompiler_rt \
+ lib/libexpat \
+ lib/libgeom \
+ lib/libsbuf \
+ lib/libutil \
+ lib/msun \
+ lib/ncurses/ncursesw \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdinstall/partedit/Makefile_ORIG b/contrib/bsddialog/bsdinstall/partedit/Makefile_ORIG
new file mode 100644
index 000000000000..a250302a1962
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/Makefile_ORIG
@@ -0,0 +1,26 @@
+# $FreeBSD$
+
+BINDIR= ${LIBEXECDIR}/bsdinstall
+PROG= partedit
+LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \
+ ${BINDIR}/partedit ${BINDIR}/scriptedpart
+SYMLINKS= ../libexec/bsdinstall/partedit /usr/sbin/sade
+LIBADD+= geom ncursesw util dialog m
+
+PARTEDIT_ARCH= ${MACHINE}
+.if ${MACHINE} == "i386" || ${MACHINE} == "amd64"
+PARTEDIT_ARCH= x86
+.elif ${MACHINE} == "arm64" || ${MACHINE} == "riscv"
+PARTEDIT_ARCH= efi
+.endif
+.if !exists(partedit_${PARTEDIT_ARCH}.c)
+PARTEDIT_ARCH= generic
+.endif
+
+SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
+ part_wizard.c scripted.c
+
+WARNS?= 3
+MAN= sade.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdinstall/partedit/diskeditor.c b/contrib/bsddialog/bsdinstall/partedit/diskeditor.c
new file mode 100644
index 000000000000..1679def32a19
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/diskeditor.c
@@ -0,0 +1,292 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <libutil.h>
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#include "diskeditor.h"
+
+static void
+print_partedit_item(WINDOW *partitions, struct partedit_item *items,
+ int item, int nscroll, int selected)
+{
+ chtype attr = A_NORMAL;
+ char sizetext[16];
+ int y = item - nscroll + 1;
+
+ wattrset(partitions, selected ? item_selected_attr : item_attr);
+ wmove(partitions, y, MARGIN + items[item].indentation*2);
+ dlg_print_text(partitions, items[item].name, 10, &attr);
+ wmove(partitions, y, 17);
+ wattrset(partitions, item_attr);
+
+ humanize_number(sizetext, 7, items[item].size, "B", HN_AUTOSCALE,
+ HN_DECIMAL);
+ dlg_print_text(partitions, sizetext, 8, &attr);
+ wmove(partitions, y, 25);
+ dlg_print_text(partitions, items[item].type, 15, &attr);
+ wmove(partitions, y, 40);
+ if (items[item].mountpoint != NULL)
+ dlg_print_text(partitions, items[item].mountpoint, 8, &attr);
+}
+
+int
+diskeditor_show(const char *title, const char *cprompt,
+ struct partedit_item *items, int nitems, int *selected, int *nscroll)
+{
+ WINDOW *dialog, *partitions;
+ char *prompt;
+ const char *buttons[] =
+ { "Create", "Delete", "Modify", "Revert", "Auto", "Finish", NULL };
+ const char *help_text[] = {
+ "Add a new partition", "Delete selected partition or partitions",
+ "Change partition type or mountpoint",
+ "Revert changes to disk setup", "Use guided partitioning tool",
+ "Exit partitioner (will ask whether to save changes)", NULL };
+ int x, y;
+ int i;
+ int height, width, min_width;
+ int partlist_height, partlist_width;
+ int cur_scroll = 0;
+ int key, fkey;
+ int cur_button = 5, cur_part = 0;
+ int result = DLG_EXIT_UNKNOWN;
+
+ static DLG_KEYS_BINDING binding[] = {
+ ENTERKEY_BINDINGS,
+ DLG_KEYS_DATA( DLGK_ENTER, ' ' ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
+ DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ),
+ DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
+ DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
+ DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_LEFT ),
+
+ SCROLLKEY_BINDINGS,
+ END_KEYS_BINDING
+ };
+
+ static DLG_KEYS_BINDING binding2[] = {
+ INPUTSTR_BINDINGS,
+ ENTERKEY_BINDINGS,
+ DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ),
+ DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ),
+ DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_PREVIOUS ),
+ DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ),
+ DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ),
+ DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE ),
+ END_KEYS_BINDING
+ };
+
+ /*
+ * Set up editor window.
+ */
+ prompt = dlg_strclone(cprompt);
+
+ min_width = 50;
+ height = width = 0;
+ partlist_height = 10;
+ dlg_tab_correct_str(prompt);
+ dlg_button_layout(buttons, &min_width);
+ dlg_auto_size(title, prompt, &height, &width, 2, min_width);
+ height += partlist_height;
+ partlist_width = width - 2*MARGIN;
+ dlg_print_size(height, width);
+ dlg_ctl_size(height, width);
+
+ x = dlg_box_x_ordinate(width);
+ y = dlg_box_y_ordinate(height);
+
+ dialog = dlg_new_window(height, width, y, x);
+ dlg_register_window(dialog, "diskeditorbox", binding);
+ dlg_register_buttons(dialog, "diskeditorbox", buttons);
+
+ dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr);
+ dlg_draw_bottom_box(dialog);
+ dlg_draw_title(dialog, title);
+ wattrset(dialog, dialog_attr);
+
+ /* Partition list sub-window */
+ partitions = dlg_sub_window(dialog, partlist_height, partlist_width,
+ y + 3, x + 1);
+ dlg_register_window(partitions, "partlist", binding2);
+ dlg_register_buttons(partitions, "partlist", buttons);
+ wattrset(partitions, menubox_attr);
+
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ dlg_print_autowrap(dialog, prompt, height, width);
+
+ if (selected != NULL)
+ cur_part = *selected;
+ if (nscroll != NULL)
+ cur_scroll = *nscroll;
+ if (cur_part - cur_scroll >= partlist_height - 2 ||
+ cur_part - cur_scroll < 0)
+ cur_scroll = cur_part;
+
+repaint:
+ dlg_draw_box(dialog, 3, 1, partlist_height, partlist_width,
+ menubox_border_attr, menubox_attr);
+ for (i = cur_scroll; i < MIN(cur_scroll + partlist_height - 2, nitems);
+ i++)
+ print_partedit_item(partitions, items, i, cur_scroll,
+ i == cur_part);
+ if (nitems > partlist_height - 2)
+ dlg_draw_arrows(partitions, cur_scroll > 0,
+ nitems > cur_scroll + partlist_height - 2,
+ partlist_width - 5, 0, partlist_height - 1);
+ wrefresh(partitions);
+
+ while (result == DLG_EXIT_UNKNOWN) {
+ key = dlg_mouse_wgetch(dialog, &fkey);
+ if ((i = dlg_char_to_button(key, buttons)) >= 0) {
+ cur_button = i;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ break;
+ }
+
+ if (!fkey)
+ continue;
+
+ switch (key) {
+ case DLGK_FIELD_NEXT:
+ cur_button = dlg_next_button(buttons, cur_button);
+ if (cur_button < 0)
+ cur_button = 0;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ break;
+ case DLGK_FIELD_PREV:
+ cur_button = dlg_prev_button(buttons, cur_button);
+ if (cur_button < 0)
+ cur_button = 0;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0, buttons,
+ cur_button, FALSE, width);
+ break;
+ case DLGK_ITEM_NEXT:
+ if (cur_part == nitems - 1)
+ break; /* End of list */
+
+ /* Deselect old item */
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 0);
+ /* Select new item */
+ cur_part++;
+ if (cur_part - cur_scroll >= partlist_height - 2) {
+ cur_scroll = cur_part;
+ goto repaint;
+ }
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 1);
+ wrefresh(partitions);
+ break;
+ case DLGK_ITEM_PREV:
+ if (cur_part == 0)
+ break; /* Start of list */
+
+ /* Deselect old item */
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 0);
+ /* Select new item */
+ cur_part--;
+ if (cur_part - cur_scroll < 0) {
+ cur_scroll = cur_part;
+ goto repaint;
+ }
+ print_partedit_item(partitions, items, cur_part,
+ cur_scroll, 1);
+ wrefresh(partitions);
+ break;
+ case DLGK_PAGE_NEXT:
+ cur_scroll += (partlist_height - 2);
+ if (cur_scroll + partlist_height - 2 >= nitems)
+ cur_scroll = nitems - (partlist_height - 2);
+ if (cur_scroll < 0)
+ cur_scroll = 0;
+ if (cur_part < cur_scroll)
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_PAGE_PREV:
+ cur_scroll -= (partlist_height - 2);
+ if (cur_scroll < 0)
+ cur_scroll = 0;
+ if (cur_part >= cur_scroll + partlist_height - 2)
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_PAGE_FIRST:
+ cur_scroll = 0;
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_PAGE_LAST:
+ cur_scroll = nitems - (partlist_height - 2);
+ if (cur_scroll < 0)
+ cur_scroll = 0;
+ cur_part = cur_scroll;
+ goto repaint;
+ case DLGK_ENTER:
+ goto done;
+ default:
+ if (is_DLGK_MOUSE(key)) {
+ cur_button = key - M_EVENT;
+ dlg_item_help(help_text[cur_button]);
+ dlg_draw_buttons(dialog, height - 2*MARGIN, 0,
+ buttons, cur_button, FALSE, width);
+ goto done;
+ }
+ break;
+ }
+ }
+
+done:
+ if (selected != NULL)
+ *selected = cur_part;
+ if (nscroll != NULL)
+ *nscroll = cur_scroll;
+
+ dlg_del_window(partitions);
+ dlg_del_window(dialog);
+ dlg_mouse_free_regions();
+
+ return (cur_button);
+}
+
diff --git a/contrib/bsddialog/lib/editorbox.c b/contrib/bsddialog/bsdinstall/partedit/diskeditor.h
index b0f57908aa0e..186dc3146ced 100644
--- a/contrib/bsddialog/lib/editorbox.c
+++ b/contrib/bsddialog/bsdinstall/partedit/diskeditor.h
@@ -1,7 +1,8 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2021 Alfonso Sabato Siciliano
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,23 +24,26 @@
* LIABILITY, OR TORT (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$
*/
-#ifdef PORTNCURSES
-#include <ncurses/curses.h>
-#else
-#include <curses.h>
-#endif
+#ifndef _PARTEDIT_DISKEDITOR_H
+#define _PARTEDIT_DISKEDITOR_H
-#include "bsddialog.h"
-#include "lib_util.h"
+#include <inttypes.h>
-/* "Editor": editbox */
+struct partedit_item {
+ int indentation;
+ const char *name;
+ intmax_t size;
+ const char *type;
+ char *mountpoint;
-int bsddialog_editbox(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
- text = "Editbox unimplemented";
- bsddialog_msgbox(conf, text, rows, cols);
- RETURN_ERROR(text);
-}
+ void *cookie;
+};
+int diskeditor_show(const char *title, const char *prompt,
+ struct partedit_item *items, int nitems, int *selected, int *scroll);
+
+#endif
diff --git a/contrib/bsddialog/bsdinstall/partedit/diskmenu.c b/contrib/bsddialog/bsdinstall/partedit/diskmenu.c
new file mode 100644
index 000000000000..fe8ecb92b264
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/diskmenu.c
@@ -0,0 +1,99 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Alfonso Sabato Siciliano
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <bsddialog.h>
+#include <stdio.h>
+#include <libutil.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "diskmenu.h"
+
+int
+diskmenu_show(const char *title, const char *text, struct partedit_item *items,
+ int nitems, int *selected)
+{
+ int i, output;
+ struct bsddialog_conf conf;
+ struct bsddialog_menuitem *bsditems;
+ char desc[1024], *mp, size[16];
+
+ bsditems = malloc(nitems * sizeof(struct bsddialog_menuitem));
+ if (bsditems == NULL)
+ return BSDDIALOG_ERROR;
+ for (i=0; i<nitems; i++) {
+ bsditems[i].prefix = "";
+ bsditems[i].depth = items[i].indentation;
+ bsditems[i].name = __DECONST(char *, items[i].name);
+ humanize_number(size, 7, items[i].size, "B",
+ HN_AUTOSCALE, HN_DECIMAL);
+ mp = items[i].mountpoint != NULL ? items[i].mountpoint : "";
+ snprintf(desc, 1024, "%s %-15s %-10s",
+ size, items[i].type, mp);
+ bsditems[i].desc = strdup(desc);
+ bsditems[i].bottomdesc = "";
+ bsditems[i].on = false;
+ }
+
+ bsddialog_initconf(&conf);
+ conf.title = __DECONST(char *, title);
+ conf.menu.align_left = true;
+ /*
+ * libbsddialog does not provides bottom description for buttons.
+ * "Add a new partition", "Delete selected partition or partitions",
+ * "Change partition type or mountpoint",
+ * "Revert changes to disk setup", "Use guided partitioning tool",
+ * "Exit partitioner (will ask whether to save changes)",
+ */
+ conf.button.ok_label = "Create";
+ conf.button.extra_button = true;
+ conf.button.extra_label = "Delete";
+ conf.button.no_label = "Modify";
+ conf.button.help_button = true;
+ conf.button.help_label = "Revert";
+ conf.button.generic1_label = "Auto";
+ conf.button.generic2_label = "Finish";
+ conf.button.default_label = "Finish";
+
+ if (bsddialog_init() == BSDDIALOG_ERROR)
+ return BSDDIALOG_ERROR;
+
+ output = bsddialog_menu(&conf, __DECONST(char *, text), 20, 0, 10,
+ nitems, bsditems, NULL);
+ bsddialog_end();
+
+ for (i=0; i<nitems; i++){
+ if (bsditems[i].on == true) {
+ *selected = i;
+ break;
+ }
+ }
+
+ free(bsditems);
+
+ return output;
+}
diff --git a/contrib/bsddialog/lib/filebox.c b/contrib/bsddialog/bsdinstall/partedit/diskmenu.h
index b951f4e0d0f0..37b4b3b70c0e 100644
--- a/contrib/bsddialog/lib/filebox.c
+++ b/contrib/bsddialog/bsdinstall/partedit/diskmenu.h
@@ -1,7 +1,8 @@
/*-
- * SPDX-License-Identifier: BSD-2-Clause
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
- * Copyright (c) 2021 Alfonso Sabato Siciliano
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,30 +24,35 @@
* LIABILITY, OR TORT (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$
*/
-#ifdef PORTNCURSES
-#include <ncurses/curses.h>
-#else
-#include <curses.h>
-#endif
+#ifndef _PARTEDIT_DISKEDITOR_H
+#define _PARTEDIT_DISKEDITOR_H
+
+#include <inttypes.h>
-#include "bsddialog.h"
-#include "lib_util.h"
-/* "File": dselect - fselect */
+#define BUTTONCREATE BSDDIALOG_YESOK
+#define BUTTONDELETE BSDDIALOG_EXTRA
+#define BUTTONMODIFY BSDDIALOG_NOCANCEL
+#define BUTTONREVERT BSDDIALOG_HELP
+#define BUTTONAUTO BSDDIALOG_GENERIC1
+#define BUTTONFINISH BSDDIALOG_GENERIC2
-int bsddialog_dselect(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
- text = "Dselect unimplemented";
- bsddialog_msgbox(conf, text, rows, cols);
- RETURN_ERROR(text);
-}
-int bsddialog_fselect(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
- text = "Fselect unimplemented";
- bsddialog_msgbox(conf, text, rows, cols);
- RETURN_ERROR(text);
-}
+struct partedit_item {
+ int indentation;
+ const char *name;
+ intmax_t size;
+ const char *type;
+ char *mountpoint;
+ void *cookie;
+};
+
+int diskmenu_show(const char *title, const char *text,
+ struct partedit_item *items, int nitems, int *selected);
+
+#endif
diff --git a/contrib/bsddialog/bsdinstall/partedit/gpart_ops.c b/contrib/bsddialog/bsdinstall/partedit/gpart_ops.c
new file mode 100644
index 000000000000..b49ff1c9fd42
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/gpart_ops.c
@@ -0,0 +1,1460 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libutil.h>
+#include <inttypes.h>
+
+#include <libgeom.h>
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#include "partedit.h"
+
+#define GPART_FLAGS "x" /* Do not commit changes by default */
+
+static void
+gpart_show_error(const char *title, const char *explanation, const char *errstr)
+{
+ char *errmsg;
+ char message[512];
+ int error;
+
+ if (explanation == NULL)
+ explanation = "";
+
+ error = strtol(errstr, &errmsg, 0);
+ if (errmsg != errstr) {
+ while (errmsg[0] == ' ')
+ errmsg++;
+ if (errmsg[0] != '\0')
+ sprintf(message, "%s%s. %s", explanation,
+ strerror(error), errmsg);
+ else
+ sprintf(message, "%s%s", explanation, strerror(error));
+ } else {
+ sprintf(message, "%s%s", explanation, errmsg);
+ }
+
+ dialog_msgbox(title, message, 0, 0, TRUE);
+}
+
+static int
+scheme_supports_labels(const char *scheme)
+{
+ if (strcmp(scheme, "APM") == 0)
+ return (1);
+ if (strcmp(scheme, "GPT") == 0)
+ return (1);
+
+ return (0);
+}
+
+static void
+newfs_command(const char *fstype, char *command, int use_default)
+{
+ if (strcmp(fstype, "freebsd-ufs") == 0) {
+ int i;
+ DIALOG_LISTITEM items[] = {
+ {"UFS1", "UFS Version 1",
+ "Use version 1 of the UFS file system instead "
+ "of version 2 (not recommended)", 0 },
+ {"SU", "Softupdates",
+ "Enable softupdates (default)", 1 },
+ {"SUJ", "Softupdates journaling",
+ "Enable file system journaling (default - "
+ "turn off for SSDs)", 1 },
+ {"TRIM", "Enable SSD TRIM support",
+ "Enable TRIM support, useful on solid-state drives",
+ 0 },
+ };
+
+ if (!use_default) {
+ int choice;
+ choice = dlg_checklist("UFS Options", "", 0, 0, 0,
+ nitems(items), items, NULL,
+ FLAG_CHECK, &i);
+ if (choice == 1) /* Cancel */
+ return;
+ }
+
+ strcpy(command, "newfs ");
+ for (i = 0; i < (int)nitems(items); i++) {
+ if (items[i].state == 0)
+ continue;
+ if (strcmp(items[i].name, "UFS1") == 0)
+ strcat(command, "-O1 ");
+ else if (strcmp(items[i].name, "SU") == 0)
+ strcat(command, "-U ");
+ else if (strcmp(items[i].name, "SUJ") == 0)
+ strcat(command, "-j ");
+ else if (strcmp(items[i].name, "TRIM") == 0)
+ strcat(command, "-t ");
+ }
+ } else if (strcmp(fstype, "freebsd-zfs") == 0) {
+ int i;
+ DIALOG_LISTITEM items[] = {
+ {"fletcher4", "checksum algorithm: fletcher4",
+ "Use fletcher4 for data integrity checking. "
+ "(default)", 1 },
+ {"fletcher2", "checksum algorithm: fletcher2",
+ "Use fletcher2 for data integrity checking. "
+ "(not recommended)", 0 },
+ {"sha256", "checksum algorithm: sha256",
+ "Use sha256 for data integrity checking. "
+ "(not recommended)", 0 },
+ {"atime", "Update atimes for files",
+ "Disable atime update", 0 },
+ };
+
+ if (!use_default) {
+ int choice;
+ choice = dlg_checklist("ZFS Options", "", 0, 0, 0,
+ nitems(items), items, NULL,
+ FLAG_CHECK, &i);
+ if (choice == 1) /* Cancel */
+ return;
+ }
+
+ strcpy(command, "zpool create -f -m none ");
+ if (getenv("BSDINSTALL_TMPBOOT") != NULL) {
+ char zfsboot_path[MAXPATHLEN];
+ snprintf(zfsboot_path, sizeof(zfsboot_path), "%s/zfs",
+ getenv("BSDINSTALL_TMPBOOT"));
+ mkdir(zfsboot_path, S_IRWXU | S_IRGRP | S_IXGRP |
+ S_IROTH | S_IXOTH);
+ sprintf(command, "%s -o cachefile=%s/zpool.cache ",
+ command, zfsboot_path);
+ }
+ for (i = 0; i < (int)nitems(items); i++) {
+ if (items[i].state == 0)
+ continue;
+ if (strcmp(items[i].name, "fletcher4") == 0)
+ strcat(command, "-O checksum=fletcher4 ");
+ else if (strcmp(items[i].name, "fletcher2") == 0)
+ strcat(command, "-O checksum=fletcher2 ");
+ else if (strcmp(items[i].name, "sha256") == 0)
+ strcat(command, "-O checksum=sha256 ");
+ else if (strcmp(items[i].name, "atime") == 0)
+ strcat(command, "-O atime=off ");
+ }
+ } else if (strcmp(fstype, "fat32") == 0 || strcmp(fstype, "efi") == 0 ||
+ strcmp(fstype, "ms-basic-data") == 0) {
+ int i;
+ DIALOG_LISTITEM items[] = {
+ {"FAT32", "FAT Type 32",
+ "Create a FAT32 filesystem (default)", 1 },
+ {"FAT16", "FAT Type 16",
+ "Create a FAT16 filesystem", 0 },
+ {"FAT12", "FAT Type 12",
+ "Create a FAT12 filesystem", 0 },
+ };
+
+ if (!use_default) {
+ int choice;
+ choice = dlg_checklist("FAT Options", "", 0, 0, 0,
+ nitems(items), items, NULL,
+ FLAG_RADIO, &i);
+ if (choice == 1) /* Cancel */
+ return;
+ }
+
+ strcpy(command, "newfs_msdos ");
+ for (i = 0; i < (int)nitems(items); i++) {
+ if (items[i].state == 0)
+ continue;
+ if (strcmp(items[i].name, "FAT32") == 0)
+ strcat(command, "-F 32 -c 1");
+ else if (strcmp(items[i].name, "FAT16") == 0)
+ strcat(command, "-F 16 ");
+ else if (strcmp(items[i].name, "FAT12") == 0)
+ strcat(command, "-F 12 ");
+ }
+ } else {
+ if (!use_default)
+ dialog_msgbox("Error", "No configurable options exist "
+ "for this filesystem.", 0, 0, TRUE);
+ command[0] = '\0';
+ }
+}
+
+const char *
+choose_part_type(const char *def_scheme)
+{
+ int cancel, choice;
+ const char *scheme = NULL;
+
+ DIALOG_LISTITEM items[] = {
+ {"APM", "Apple Partition Map",
+ "Bootable on PowerPC Apple Hardware", 0 },
+ {"BSD", "BSD Labels",
+ "Bootable on most x86 systems", 0 },
+ {"GPT", "GUID Partition Table",
+ "Bootable on most x86 systems and EFI aware ARM64", 0 },
+ {"MBR", "DOS Partitions",
+ "Bootable on most x86 systems", 0 },
+ };
+
+parttypemenu:
+ dialog_vars.default_item = __DECONST(char *, def_scheme);
+ cancel = dlg_menu("Partition Scheme",
+ "Select a partition scheme for this volume:", 0, 0, 0,
+ nitems(items), items, &choice, NULL);
+ dialog_vars.default_item = NULL;
+
+ if (cancel)
+ return NULL;
+
+ if (!is_scheme_bootable(items[choice].name)) {
+ char message[512];
+ sprintf(message, "This partition scheme (%s) is not "
+ "bootable on this platform. Are you sure you want "
+ "to proceed?", items[choice].name);
+ dialog_vars.defaultno = TRUE;
+ cancel = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.defaultno = FALSE;
+ if (cancel) /* cancel */
+ goto parttypemenu;
+ }
+
+ scheme = items[choice].name;
+
+ return scheme;
+}
+
+int
+gpart_partition(const char *lg_name, const char *scheme)
+{
+ int cancel;
+ struct gctl_req *r;
+ const char *errstr;
+
+schememenu:
+ if (scheme == NULL) {
+ scheme = choose_part_type(default_scheme());
+
+ if (scheme == NULL)
+ return (-1);
+
+ if (!is_scheme_bootable(scheme)) {
+ char message[512];
+ sprintf(message, "This partition scheme (%s) is not "
+ "bootable on this platform. Are you sure you want "
+ "to proceed?", scheme);
+ dialog_vars.defaultno = TRUE;
+ cancel = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.defaultno = FALSE;
+ if (cancel) { /* cancel */
+ /* Reset scheme so user can choose another */
+ scheme = NULL;
+ goto schememenu;
+ }
+ }
+ }
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, lg_name);
+ gctl_ro_param(r, "flags", -1, GPART_FLAGS);
+ gctl_ro_param(r, "scheme", -1, scheme);
+ gctl_ro_param(r, "verb", -1, "create");
+
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0') {
+ gpart_show_error("Error", NULL, errstr);
+ gctl_free(r);
+ scheme = NULL;
+ goto schememenu;
+ }
+ gctl_free(r);
+
+ if (bootcode_path(scheme) != NULL)
+ get_part_metadata(lg_name, 1)->bootcode = 1;
+ return (0);
+}
+
+static void
+gpart_activate(struct gprovider *pp)
+{
+ struct gconfig *gc;
+ struct gctl_req *r;
+ const char *errstr, *scheme;
+ const char *attribute = NULL;
+ intmax_t idx;
+
+ /*
+ * Some partition schemes need this partition to be marked 'active'
+ * for it to be bootable.
+ */
+ LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ break;
+ }
+ }
+
+ if (strcmp(scheme, "MBR") == 0 || strcmp(scheme, "EBR") == 0)
+ attribute = "active";
+ else
+ return;
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "index") == 0) {
+ idx = atoi(gc->lg_val);
+ break;
+ }
+ }
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name);
+ gctl_ro_param(r, "verb", -1, "set");
+ gctl_ro_param(r, "attrib", -1, attribute);
+ gctl_ro_param(r, "index", sizeof(idx), &idx);
+
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0')
+ gpart_show_error("Error", "Error marking partition active:",
+ errstr);
+ gctl_free(r);
+}
+
+void
+gpart_set_root(const char *lg_name, const char *attribute)
+{
+ struct gctl_req *r;
+ const char *errstr;
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, lg_name);
+ gctl_ro_param(r, "flags", -1, "C");
+ gctl_ro_param(r, "verb", -1, "set");
+ gctl_ro_param(r, "attrib", -1, attribute);
+
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0')
+ gpart_show_error("Error", "Error setting parameter on disk:",
+ errstr);
+ gctl_free(r);
+}
+
+static void
+gpart_bootcode(struct ggeom *gp)
+{
+ const char *bootcode;
+ struct gconfig *gc;
+ struct gctl_req *r;
+ const char *errstr, *scheme;
+ uint8_t *boot;
+ size_t bootsize, bytes;
+ int bootfd;
+
+ /*
+ * Write default bootcode to the newly partitioned disk, if that
+ * applies on this platform.
+ */
+ LIST_FOREACH(gc, &gp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ break;
+ }
+ }
+
+ bootcode = bootcode_path(scheme);
+ if (bootcode == NULL)
+ return;
+
+ bootfd = open(bootcode, O_RDONLY);
+ if (bootfd < 0) {
+ dialog_msgbox("Bootcode Error", strerror(errno), 0, 0,
+ TRUE);
+ return;
+ }
+
+ bootsize = lseek(bootfd, 0, SEEK_END);
+ boot = malloc(bootsize);
+ lseek(bootfd, 0, SEEK_SET);
+ bytes = 0;
+ while (bytes < bootsize)
+ bytes += read(bootfd, boot + bytes, bootsize - bytes);
+ close(bootfd);
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, gp->lg_name);
+ gctl_ro_param(r, "verb", -1, "bootcode");
+ gctl_ro_param(r, "bootcode", bootsize, boot);
+
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0')
+ gpart_show_error("Bootcode Error", NULL, errstr);
+ gctl_free(r);
+ free(boot);
+}
+
+static void
+gpart_partcode(struct gprovider *pp, const char *fstype)
+{
+ struct gconfig *gc;
+ const char *scheme;
+ const char *indexstr;
+ char message[255], command[255];
+
+ LIST_FOREACH(gc, &pp->lg_geom->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ break;
+ }
+ }
+
+ /* Make sure this partition scheme needs partcode on this platform */
+ if (partcode_path(scheme, fstype) == NULL)
+ return;
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "index") == 0) {
+ indexstr = gc->lg_val;
+ break;
+ }
+ }
+
+ /* Shell out to gpart for partcode for now */
+ sprintf(command, "gpart bootcode -p %s -i %s %s",
+ partcode_path(scheme, fstype), indexstr, pp->lg_geom->lg_name);
+ if (system(command) != 0) {
+ sprintf(message, "Error installing partcode on partition %s",
+ pp->lg_name);
+ dialog_msgbox("Error", message, 0, 0, TRUE);
+ }
+}
+
+void
+gpart_destroy(struct ggeom *lg_geom)
+{
+ struct gctl_req *r;
+ struct gprovider *pp;
+ const char *errstr;
+ int force = 1;
+
+ /* Delete all child metadata */
+ LIST_FOREACH(pp, &lg_geom->lg_provider, lg_provider)
+ gpart_delete(pp);
+
+ /* Revert any local changes to get this geom into a pristine state */
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, lg_geom->lg_name);
+ gctl_ro_param(r, "verb", -1, "undo");
+ gctl_issue(r); /* Ignore errors -- these are non-fatal */
+ gctl_free(r);
+
+ /* Now destroy the geom itself */
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, lg_geom->lg_name);
+ gctl_ro_param(r, "flags", -1, GPART_FLAGS);
+ gctl_ro_param(r, "force", sizeof(force), &force);
+ gctl_ro_param(r, "verb", -1, "destroy");
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0') {
+ /*
+ * Check if we reverted away the existence of the geom
+ * altogether. Show all other errors to the user.
+ */
+ if (strtol(errstr, NULL, 0) != EINVAL)
+ gpart_show_error("Error", NULL, errstr);
+ }
+ gctl_free(r);
+
+ /* And any metadata associated with the partition scheme itself */
+ delete_part_metadata(lg_geom->lg_name);
+}
+
+void
+gpart_edit(struct gprovider *pp)
+{
+ struct gctl_req *r;
+ struct gconfig *gc;
+ struct gconsumer *cp;
+ struct ggeom *geom;
+ const char *errstr, *oldtype, *scheme;
+ struct partition_metadata *md;
+ char sizestr[32];
+ char newfs[255];
+ intmax_t idx;
+ int hadlabel, choice, junk, nitems;
+ unsigned i;
+
+ DIALOG_FORMITEM items[] = {
+ {0, "Type:", 5, 0, 0, FALSE, "", 11, 0, 12, 15, 0,
+ FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
+ "freebsd-swap)", FALSE},
+ {0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 0, 0,
+ FALSE, "Partition size. Append K, M, G for kilobytes, "
+ "megabytes or gigabytes.", FALSE},
+ {0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0,
+ FALSE, "Path at which to mount this partition (leave blank "
+ "for swap, set to / for root filesystem)", FALSE},
+ {0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE,
+ "Partition name. Not all partition schemes support this.",
+ FALSE},
+ };
+
+ /*
+ * Find the PART geom we are manipulating. This may be a consumer of
+ * this provider, or its parent. Check the consumer case first.
+ */
+ geom = NULL;
+ LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
+ if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) {
+ /* Check for zombie geoms, treating them as blank */
+ scheme = NULL;
+ LIST_FOREACH(gc, &cp->lg_geom->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ break;
+ }
+ }
+ if (scheme == NULL || strcmp(scheme, "(none)") == 0) {
+ gpart_partition(cp->lg_geom->lg_name, NULL);
+ return;
+ }
+
+ /* If this is a nested partition, edit as usual */
+ if (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0)
+ break;
+
+ /* Destroy the geom and all sub-partitions */
+ gpart_destroy(cp->lg_geom);
+
+ /* Now re-partition and return */
+ gpart_partition(cp->lg_geom->lg_name, NULL);
+ return;
+ }
+
+ if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0)
+ geom = pp->lg_geom;
+
+ if (geom == NULL) {
+ /* Disk not partitioned, so partition it */
+ gpart_partition(pp->lg_name, NULL);
+ return;
+ }
+
+ LIST_FOREACH(gc, &geom->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ break;
+ }
+ }
+
+ nitems = scheme_supports_labels(scheme) ? 4 : 3;
+
+ /* Edit editable parameters of a partition */
+ hadlabel = 0;
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "type") == 0) {
+ oldtype = gc->lg_val;
+ items[0].text = gc->lg_val;
+ }
+ if (strcmp(gc->lg_name, "label") == 0 && gc->lg_val != NULL) {
+ hadlabel = 1;
+ items[3].text = gc->lg_val;
+ }
+ if (strcmp(gc->lg_name, "index") == 0)
+ idx = atoi(gc->lg_val);
+ }
+
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->name != NULL && strcmp(md->name, pp->lg_name) == 0) {
+ if (md->fstab != NULL)
+ items[2].text = md->fstab->fs_file;
+ break;
+ }
+ }
+
+ humanize_number(sizestr, 7, pp->lg_mediasize, "B", HN_AUTOSCALE,
+ HN_NOSPACE | HN_DECIMAL);
+ items[1].text = sizestr;
+
+editpart:
+ choice = dlg_form("Edit Partition", "", 0, 0, 0, nitems, items, &junk);
+
+ if (choice) /* Cancel pressed */
+ goto endedit;
+
+ /* If this is the root partition, check that this fs is bootable */
+ if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
+ items[0].text)) {
+ char message[512];
+ sprintf(message, "This file system (%s) is not bootable "
+ "on this system. Are you sure you want to proceed?",
+ items[0].text);
+ dialog_vars.defaultno = TRUE;
+ choice = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.defaultno = FALSE;
+ if (choice == 1) /* cancel */
+ goto editpart;
+ }
+
+ /* Check if the label has a / in it */
+ if (strchr(items[3].text, '/') != NULL) {
+ dialog_msgbox("Error", "Label contains a /, which is not an "
+ "allowed character.", 0, 0, TRUE);
+ goto editpart;
+ }
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, geom->lg_name);
+ gctl_ro_param(r, "flags", -1, GPART_FLAGS);
+ gctl_ro_param(r, "verb", -1, "modify");
+ gctl_ro_param(r, "index", sizeof(idx), &idx);
+ if (hadlabel || items[3].text[0] != '\0')
+ gctl_ro_param(r, "label", -1, items[3].text);
+ gctl_ro_param(r, "type", -1, items[0].text);
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0') {
+ gpart_show_error("Error", NULL, errstr);
+ gctl_free(r);
+ goto editpart;
+ }
+ gctl_free(r);
+
+ newfs_command(items[0].text, newfs, 1);
+ set_default_part_metadata(pp->lg_name, scheme, items[0].text,
+ items[2].text, (strcmp(oldtype, items[0].text) != 0) ?
+ newfs : NULL);
+
+endedit:
+ if (strcmp(oldtype, items[0].text) != 0 && cp != NULL)
+ gpart_destroy(cp->lg_geom);
+ if (strcmp(oldtype, items[0].text) != 0 && strcmp(items[0].text,
+ "freebsd") == 0)
+ gpart_partition(pp->lg_name, "BSD");
+
+ for (i = 0; i < nitems(items); i++)
+ if (items[i].text_free)
+ free(items[i].text);
+}
+
+void
+set_default_part_metadata(const char *name, const char *scheme,
+ const char *type, const char *mountpoint, const char *newfs)
+{
+ struct partition_metadata *md;
+ char *zpool_name = NULL;
+ const char *default_bootmount = NULL;
+ int i;
+
+ /* Set part metadata */
+ md = get_part_metadata(name, 1);
+
+ if (newfs) {
+ if (md->newfs != NULL) {
+ free(md->newfs);
+ md->newfs = NULL;
+ }
+
+ if (newfs != NULL && newfs[0] != '\0') {
+ md->newfs = malloc(strlen(newfs) + strlen(" /dev/") +
+ strlen(mountpoint) + 5 + strlen(name) + 1);
+ if (strcmp("freebsd-zfs", type) == 0) {
+ zpool_name = strdup((strlen(mountpoint) == 1) ?
+ "root" : &mountpoint[1]);
+ for (i = 0; zpool_name[i] != 0; i++)
+ if (!isalnum(zpool_name[i]))
+ zpool_name[i] = '_';
+ sprintf(md->newfs, "%s %s /dev/%s", newfs,
+ zpool_name, name);
+ } else {
+ sprintf(md->newfs, "%s /dev/%s", newfs, name);
+ }
+ }
+ }
+
+ if (strcmp(type, "freebsd-swap") == 0)
+ mountpoint = "none";
+ if (strcmp(type, bootpart_type(scheme, &default_bootmount)) == 0) {
+ if (default_bootmount == NULL)
+ md->bootcode = 1;
+ else if (mountpoint == NULL || strlen(mountpoint) == 0)
+ mountpoint = default_bootmount;
+ }
+
+ if (mountpoint == NULL || mountpoint[0] == '\0') {
+ if (md->fstab != NULL) {
+ free(md->fstab->fs_spec);
+ free(md->fstab->fs_file);
+ free(md->fstab->fs_vfstype);
+ free(md->fstab->fs_mntops);
+ free(md->fstab->fs_type);
+ free(md->fstab);
+ md->fstab = NULL;
+ }
+ } else {
+ if (md->fstab == NULL) {
+ md->fstab = malloc(sizeof(struct fstab));
+ } else {
+ free(md->fstab->fs_spec);
+ free(md->fstab->fs_file);
+ free(md->fstab->fs_vfstype);
+ free(md->fstab->fs_mntops);
+ free(md->fstab->fs_type);
+ }
+ if (strcmp("freebsd-zfs", type) == 0) {
+ md->fstab->fs_spec = strdup(zpool_name);
+ } else {
+ md->fstab->fs_spec = malloc(strlen(name) +
+ strlen("/dev/") + 1);
+ sprintf(md->fstab->fs_spec, "/dev/%s", name);
+ }
+ md->fstab->fs_file = strdup(mountpoint);
+ /* Get VFS from text after freebsd-, if possible */
+ if (strncmp("freebsd-", type, 8) == 0)
+ md->fstab->fs_vfstype = strdup(&type[8]);
+ else if (strcmp("fat32", type) == 0 || strcmp("efi", type) == 0
+ || strcmp("ms-basic-data", type) == 0)
+ md->fstab->fs_vfstype = strdup("msdosfs");
+ else
+ md->fstab->fs_vfstype = strdup(type); /* Guess */
+ if (strcmp(type, "freebsd-swap") == 0) {
+ md->fstab->fs_type = strdup(FSTAB_SW);
+ md->fstab->fs_freq = 0;
+ md->fstab->fs_passno = 0;
+ } else if (strcmp(type, "freebsd-zfs") == 0) {
+ md->fstab->fs_type = strdup(FSTAB_RW);
+ md->fstab->fs_freq = 0;
+ md->fstab->fs_passno = 0;
+ } else {
+ md->fstab->fs_type = strdup(FSTAB_RW);
+ if (strcmp(mountpoint, "/") == 0) {
+ md->fstab->fs_freq = 1;
+ md->fstab->fs_passno = 1;
+ } else {
+ md->fstab->fs_freq = 2;
+ md->fstab->fs_passno = 2;
+ }
+ }
+ md->fstab->fs_mntops = strdup(md->fstab->fs_type);
+ }
+
+ if (zpool_name != NULL)
+ free(zpool_name);
+}
+
+static
+int part_compare(const void *xa, const void *xb)
+{
+ struct gprovider **a = (struct gprovider **)xa;
+ struct gprovider **b = (struct gprovider **)xb;
+ intmax_t astart, bstart;
+ struct gconfig *gc;
+
+ astart = bstart = 0;
+ LIST_FOREACH(gc, &(*a)->lg_config, lg_config)
+ if (strcmp(gc->lg_name, "start") == 0) {
+ astart = strtoimax(gc->lg_val, NULL, 0);
+ break;
+ }
+ LIST_FOREACH(gc, &(*b)->lg_config, lg_config)
+ if (strcmp(gc->lg_name, "start") == 0) {
+ bstart = strtoimax(gc->lg_val, NULL, 0);
+ break;
+ }
+
+ if (astart < bstart)
+ return -1;
+ else if (astart > bstart)
+ return 1;
+ else
+ return 0;
+}
+
+intmax_t
+gpart_max_free(struct ggeom *geom, intmax_t *npartstart)
+{
+ struct gconfig *gc;
+ struct gprovider *pp, **providers;
+ intmax_t sectorsize, stripesize, offset;
+ intmax_t lastend;
+ intmax_t start, end;
+ intmax_t maxsize, maxstart;
+ intmax_t partstart, partend;
+ int i, nparts;
+
+ /* Now get the maximum free size and free start */
+ start = end = 0;
+ LIST_FOREACH(gc, &geom->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "first") == 0)
+ start = strtoimax(gc->lg_val, NULL, 0);
+ if (strcmp(gc->lg_name, "last") == 0)
+ end = strtoimax(gc->lg_val, NULL, 0);
+ }
+
+ i = nparts = 0;
+ LIST_FOREACH(pp, &geom->lg_provider, lg_provider)
+ nparts++;
+ providers = calloc(nparts, sizeof(providers[0]));
+ LIST_FOREACH(pp, &geom->lg_provider, lg_provider)
+ providers[i++] = pp;
+ qsort(providers, nparts, sizeof(providers[0]), part_compare);
+
+ lastend = start - 1;
+ maxsize = 0;
+ for (i = 0; i < nparts; i++) {
+ pp = providers[i];
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "start") == 0)
+ partstart = strtoimax(gc->lg_val, NULL, 0);
+ if (strcmp(gc->lg_name, "end") == 0)
+ partend = strtoimax(gc->lg_val, NULL, 0);
+ }
+
+ if (partstart - lastend > maxsize) {
+ maxsize = partstart - lastend - 1;
+ maxstart = lastend + 1;
+ }
+
+ lastend = partend;
+ }
+
+ if (end - lastend > maxsize) {
+ maxsize = end - lastend;
+ maxstart = lastend + 1;
+ }
+
+ pp = LIST_FIRST(&geom->lg_consumer)->lg_provider;
+
+ /*
+ * Round the start and size of the largest available space up to
+ * the nearest multiple of the adjusted stripe size.
+ *
+ * The adjusted stripe size is the least common multiple of the
+ * actual stripe size, or the sector size if no stripe size was
+ * reported, and 4096. The reason for this is that contemporary
+ * disks often have 4096-byte physical sectors but report 512
+ * bytes instead for compatibility with older / broken operating
+ * systems and BIOSes. For the same reasons, virtualized storage
+ * may also report a 512-byte stripe size, or none at all.
+ */
+ sectorsize = pp->lg_sectorsize;
+ if ((stripesize = pp->lg_stripesize) == 0)
+ stripesize = sectorsize;
+ while (stripesize % 4096 != 0)
+ stripesize *= 2;
+ if ((offset = maxstart * sectorsize % stripesize) != 0) {
+ offset = (stripesize - offset) / sectorsize;
+ maxstart += offset;
+ maxsize -= offset;
+ }
+
+ if (npartstart != NULL)
+ *npartstart = maxstart;
+
+ return (maxsize);
+}
+
+static size_t
+add_boot_partition(struct ggeom *geom, struct gprovider *pp,
+ const char *scheme, int interactive)
+{
+ struct gconfig *gc;
+ struct gprovider *ppi;
+ int choice;
+
+ /* Check for existing freebsd-boot partition */
+ LIST_FOREACH(ppi, &geom->lg_provider, lg_provider) {
+ struct partition_metadata *md;
+ const char *bootmount = NULL;
+
+ LIST_FOREACH(gc, &ppi->lg_config, lg_config)
+ if (strcmp(gc->lg_name, "type") == 0)
+ break;
+ if (gc == NULL)
+ continue;
+ if (strcmp(gc->lg_val, bootpart_type(scheme, &bootmount)) != 0)
+ continue;
+
+ /*
+ * If the boot partition is not mountable and needs partcode,
+ * but doesn't have it, it doesn't satisfy our requirements.
+ */
+ md = get_part_metadata(ppi->lg_name, 0);
+ if (bootmount == NULL && (md == NULL || !md->bootcode))
+ continue;
+
+ /* If it is mountable, but mounted somewhere else, remount */
+ if (bootmount != NULL && md != NULL && md->fstab != NULL
+ && strlen(md->fstab->fs_file) > 0
+ && strcmp(md->fstab->fs_file, bootmount) != 0)
+ continue;
+
+ /* If it is mountable, but mountpoint is not set, mount it */
+ if (bootmount != NULL && md == NULL)
+ set_default_part_metadata(ppi->lg_name, scheme,
+ gc->lg_val, bootmount, NULL);
+
+ /* Looks good at this point, no added data needed */
+ return (0);
+ }
+
+ if (interactive)
+ choice = dialog_yesno("Boot Partition",
+ "This partition scheme requires a boot partition "
+ "for the disk to be bootable. Would you like to "
+ "make one now?", 0, 0);
+ else
+ choice = 0;
+
+ if (choice == 0) { /* yes */
+ struct partition_metadata *md;
+ const char *bootmount = NULL;
+ char *bootpartname = NULL;
+ char sizestr[7];
+
+ humanize_number(sizestr, 7,
+ bootpart_size(scheme), "B", HN_AUTOSCALE,
+ HN_NOSPACE | HN_DECIMAL);
+
+ gpart_create(pp, bootpart_type(scheme, &bootmount),
+ sizestr, bootmount, &bootpartname, 0);
+
+ if (bootpartname == NULL) /* Error reported to user already */
+ return 0;
+
+ /* If the part is not mountable, make sure newfs isn't set */
+ if (bootmount == NULL) {
+ md = get_part_metadata(bootpartname, 0);
+ if (md != NULL && md->newfs != NULL) {
+ free(md->newfs);
+ md->newfs = NULL;
+ }
+ }
+
+ free(bootpartname);
+
+ return (bootpart_size(scheme));
+ }
+
+ return (0);
+}
+
+void
+gpart_create(struct gprovider *pp, const char *default_type,
+ const char *default_size, const char *default_mountpoint,
+ char **partname, int interactive)
+{
+ struct gctl_req *r;
+ struct gconfig *gc;
+ struct gconsumer *cp;
+ struct ggeom *geom;
+ const char *errstr, *scheme;
+ char sizestr[32], startstr[32], output[64], *newpartname;
+ char newfs[255], options_fstype[64];
+ intmax_t maxsize, size, sector, firstfree, stripe;
+ uint64_t bytes;
+ int nitems, choice, junk;
+ unsigned i;
+
+ DIALOG_FORMITEM items[] = {
+ {0, "Type:", 5, 0, 0, FALSE, "freebsd-ufs", 11, 0, 12, 15, 0,
+ FALSE, "Filesystem type (e.g. freebsd-ufs, freebsd-zfs, "
+ "freebsd-swap)", FALSE},
+ {0, "Size:", 5, 1, 0, FALSE, "", 11, 1, 12, 15, 0,
+ FALSE, "Partition size. Append K, M, G for kilobytes, "
+ "megabytes or gigabytes.", FALSE},
+ {0, "Mountpoint:", 11, 2, 0, FALSE, "", 11, 2, 12, 15, 0,
+ FALSE, "Path at which to mount partition (blank for "
+ "swap, / for root filesystem)", FALSE},
+ {0, "Label:", 7, 3, 0, FALSE, "", 11, 3, 12, 15, 0, FALSE,
+ "Partition name. Not all partition schemes support this.",
+ FALSE},
+ };
+
+ if (partname != NULL)
+ *partname = NULL;
+
+ /* Record sector and stripe sizes */
+ sector = pp->lg_sectorsize;
+ stripe = pp->lg_stripesize;
+
+ /*
+ * Find the PART geom we are manipulating. This may be a consumer of
+ * this provider, or its parent. Check the consumer case first.
+ */
+ geom = NULL;
+ LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
+ if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) {
+ geom = cp->lg_geom;
+ break;
+ }
+
+ if (geom == NULL && strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0)
+ geom = pp->lg_geom;
+
+ /* Now get the partition scheme */
+ scheme = NULL;
+ if (geom != NULL) {
+ LIST_FOREACH(gc, &geom->lg_config, lg_config)
+ if (strcmp(gc->lg_name, "scheme") == 0)
+ scheme = gc->lg_val;
+ }
+
+ if (geom == NULL || scheme == NULL || strcmp(scheme, "(none)") == 0) {
+ if (gpart_partition(pp->lg_name, NULL) == 0)
+ dialog_msgbox("",
+ "The partition table has been successfully created."
+ " Please press Create again to create partitions.",
+ 0, 0, TRUE);
+
+ return;
+ }
+
+ /*
+ * If we still don't have a geom, either the user has
+ * canceled partitioning or there has been an error which has already
+ * been displayed, so bail.
+ */
+ if (geom == NULL)
+ return;
+
+ maxsize = size = gpart_max_free(geom, &firstfree);
+ if (size <= 0) {
+ dialog_msgbox("Error", "No free space left on device.", 0, 0,
+ TRUE);
+ return;
+ }
+
+ humanize_number(sizestr, 7, size*sector, "B", HN_AUTOSCALE,
+ HN_NOSPACE | HN_DECIMAL);
+ items[1].text = sizestr;
+
+ /* Special-case the MBR default type for nested partitions */
+ if (strcmp(scheme, "MBR") == 0) {
+ items[0].text = "freebsd";
+ items[0].help = "Filesystem type (e.g. freebsd, fat32)";
+ }
+
+ nitems = scheme_supports_labels(scheme) ? 4 : 3;
+
+ if (default_type != NULL)
+ items[0].text = (char *)default_type;
+ if (default_size != NULL)
+ items[1].text = (char *)default_size;
+ if (default_mountpoint != NULL)
+ items[2].text = (char *)default_mountpoint;
+
+ /* Default options */
+ strncpy(options_fstype, items[0].text,
+ sizeof(options_fstype));
+ newfs_command(options_fstype, newfs, 1);
+addpartform:
+ if (interactive) {
+ dialog_vars.extra_label = "Options";
+ dialog_vars.extra_button = TRUE;
+ choice = dlg_form("Add Partition", "", 0, 0, 0, nitems,
+ items, &junk);
+ dialog_vars.extra_button = FALSE;
+ switch (choice) {
+ case 0: /* OK */
+ break;
+ case 1: /* Cancel */
+ return;
+ case 3: /* Options */
+ strncpy(options_fstype, items[0].text,
+ sizeof(options_fstype));
+ newfs_command(options_fstype, newfs, 0);
+ goto addpartform;
+ }
+ }
+
+ /*
+ * If the user changed the fs type after specifying options, undo
+ * their choices in favor of the new filesystem's defaults.
+ */
+ if (strcmp(options_fstype, items[0].text) != 0) {
+ strncpy(options_fstype, items[0].text, sizeof(options_fstype));
+ newfs_command(options_fstype, newfs, 1);
+ }
+
+ size = maxsize;
+ if (strlen(items[1].text) > 0) {
+ if (expand_number(items[1].text, &bytes) != 0) {
+ char error[512];
+
+ sprintf(error, "Invalid size: %s\n", strerror(errno));
+ dialog_msgbox("Error", error, 0, 0, TRUE);
+ goto addpartform;
+ }
+ size = MIN((intmax_t)(bytes/sector), maxsize);
+ }
+
+ /* Check if the label has a / in it */
+ if (strchr(items[3].text, '/') != NULL) {
+ dialog_msgbox("Error", "Label contains a /, which is not an "
+ "allowed character.", 0, 0, TRUE);
+ goto addpartform;
+ }
+
+ /* Warn if no mountpoint set */
+ if (strcmp(items[0].text, "freebsd-ufs") == 0 &&
+ items[2].text[0] != '/') {
+ choice = 0;
+ if (interactive) {
+ dialog_vars.defaultno = TRUE;
+ choice = dialog_yesno("Warning",
+ "This partition does not have a valid mountpoint "
+ "(for the partition from which you intend to boot the "
+ "operating system, the mountpoint should be /). Are you "
+ "sure you want to continue?"
+ , 0, 0);
+ dialog_vars.defaultno = FALSE;
+ }
+ if (choice == 1) /* cancel */
+ goto addpartform;
+ }
+
+ /*
+ * Error if this scheme needs nested partitions, this is one, and
+ * a mountpoint was set.
+ */
+ if (strcmp(items[0].text, "freebsd") == 0 &&
+ strlen(items[2].text) > 0) {
+ dialog_msgbox("Error", "Partitions of type \"freebsd\" are "
+ "nested BSD-type partition schemes and cannot have "
+ "mountpoints. After creating one, select it and press "
+ "Create again to add the actual file systems.", 0, 0, TRUE);
+ goto addpartform;
+ }
+
+ /* If this is the root partition, check that this scheme is bootable */
+ if (strcmp(items[2].text, "/") == 0 && !is_scheme_bootable(scheme)) {
+ char message[512];
+ sprintf(message, "This partition scheme (%s) is not bootable "
+ "on this platform. Are you sure you want to proceed?",
+ scheme);
+ dialog_vars.defaultno = TRUE;
+ choice = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.defaultno = FALSE;
+ if (choice == 1) /* cancel */
+ goto addpartform;
+ }
+
+ /* If this is the root partition, check that this fs is bootable */
+ if (strcmp(items[2].text, "/") == 0 && !is_fs_bootable(scheme,
+ items[0].text)) {
+ char message[512];
+ sprintf(message, "This file system (%s) is not bootable "
+ "on this system. Are you sure you want to proceed?",
+ items[0].text);
+ dialog_vars.defaultno = TRUE;
+ choice = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.defaultno = FALSE;
+ if (choice == 1) /* cancel */
+ goto addpartform;
+ }
+
+ /*
+ * If this is the root partition, and we need a boot partition, ask
+ * the user to add one.
+ */
+
+ if ((strcmp(items[0].text, "freebsd") == 0 ||
+ strcmp(items[2].text, "/") == 0) && bootpart_size(scheme) > 0) {
+ size_t bytes = add_boot_partition(geom, pp, scheme,
+ interactive);
+
+ /* Now adjust the part we are really adding forward */
+ if (bytes > 0) {
+ firstfree += bytes / sector;
+ size -= (bytes + stripe)/sector;
+ if (stripe > 0 && (firstfree*sector % stripe) != 0)
+ firstfree += (stripe - ((firstfree*sector) %
+ stripe)) / sector;
+ }
+ }
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, geom->lg_name);
+ gctl_ro_param(r, "flags", -1, GPART_FLAGS);
+ gctl_ro_param(r, "verb", -1, "add");
+
+ gctl_ro_param(r, "type", -1, items[0].text);
+ snprintf(sizestr, sizeof(sizestr), "%jd", size);
+ gctl_ro_param(r, "size", -1, sizestr);
+ snprintf(startstr, sizeof(startstr), "%jd", firstfree);
+ gctl_ro_param(r, "start", -1, startstr);
+ if (items[3].text[0] != '\0')
+ gctl_ro_param(r, "label", -1, items[3].text);
+ gctl_rw_param(r, "output", sizeof(output), output);
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0') {
+ gpart_show_error("Error", NULL, errstr);
+ gctl_free(r);
+ goto addpartform;
+ }
+ newpartname = strtok(output, " ");
+ gctl_free(r);
+
+ /*
+ * Try to destroy any geom that gpart picked up already here from
+ * dirty blocks.
+ */
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, newpartname);
+ gctl_ro_param(r, "flags", -1, GPART_FLAGS);
+ junk = 1;
+ gctl_ro_param(r, "force", sizeof(junk), &junk);
+ gctl_ro_param(r, "verb", -1, "destroy");
+ gctl_issue(r); /* Error usually expected and non-fatal */
+ gctl_free(r);
+
+
+ if (strcmp(items[0].text, "freebsd") == 0)
+ gpart_partition(newpartname, "BSD");
+ else
+ set_default_part_metadata(newpartname, scheme,
+ items[0].text, items[2].text, newfs);
+
+ for (i = 0; i < nitems(items); i++)
+ if (items[i].text_free)
+ free(items[i].text);
+
+ if (partname != NULL)
+ *partname = strdup(newpartname);
+}
+
+void
+gpart_delete(struct gprovider *pp)
+{
+ struct gconfig *gc;
+ struct ggeom *geom;
+ struct gconsumer *cp;
+ struct gctl_req *r;
+ const char *errstr;
+ intmax_t idx;
+ int is_partition;
+
+ /* Is it a partition? */
+ is_partition = (strcmp(pp->lg_geom->lg_class->lg_name, "PART") == 0);
+
+ /* Find out if this is the root of a gpart geom */
+ geom = NULL;
+ LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
+ if (strcmp(cp->lg_geom->lg_class->lg_name, "PART") == 0) {
+ geom = cp->lg_geom;
+ break;
+ }
+
+ /* If so, destroy all children */
+ if (geom != NULL) {
+ gpart_destroy(geom);
+
+ /* If this is a partition, revert it, so it can be deleted */
+ if (is_partition) {
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, geom->lg_name);
+ gctl_ro_param(r, "verb", -1, "undo");
+ gctl_issue(r); /* Ignore non-fatal errors */
+ gctl_free(r);
+ }
+ }
+
+ /*
+ * If this is not a partition, see if that is a problem, complain if
+ * necessary, and return always, since we need not do anything further,
+ * error or no.
+ */
+ if (!is_partition) {
+ if (geom == NULL)
+ dialog_msgbox("Error",
+ "Only partitions can be deleted.", 0, 0, TRUE);
+ return;
+ }
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, pp->lg_geom->lg_class->lg_name);
+ gctl_ro_param(r, "arg0", -1, pp->lg_geom->lg_name);
+ gctl_ro_param(r, "flags", -1, GPART_FLAGS);
+ gctl_ro_param(r, "verb", -1, "delete");
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "index") == 0) {
+ idx = atoi(gc->lg_val);
+ gctl_ro_param(r, "index", sizeof(idx), &idx);
+ break;
+ }
+ }
+
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0') {
+ gpart_show_error("Error", NULL, errstr);
+ gctl_free(r);
+ return;
+ }
+
+ gctl_free(r);
+
+ delete_part_metadata(pp->lg_name);
+}
+
+void
+gpart_revert_all(struct gmesh *mesh)
+{
+ struct gclass *classp;
+ struct gconfig *gc;
+ struct ggeom *gp;
+ struct gctl_req *r;
+ const char *modified;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+ }
+
+ if (strcmp(classp->lg_name, "PART") != 0) {
+ dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
+ return;
+ }
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ modified = "true"; /* XXX: If we don't know (kernel too old),
+ * assume there are modifications. */
+ LIST_FOREACH(gc, &gp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "modified") == 0) {
+ modified = gc->lg_val;
+ break;
+ }
+ }
+
+ if (strcmp(modified, "false") == 0)
+ continue;
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, gp->lg_name);
+ gctl_ro_param(r, "verb", -1, "undo");
+
+ gctl_issue(r);
+ gctl_free(r);
+ }
+}
+
+void
+gpart_commit(struct gmesh *mesh)
+{
+ struct partition_metadata *md;
+ struct gclass *classp;
+ struct ggeom *gp;
+ struct gconfig *gc;
+ struct gconsumer *cp;
+ struct gprovider *pp;
+ struct gctl_req *r;
+ const char *errstr;
+ const char *modified;
+ const char *rootfs;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+ }
+
+ /* Figure out what filesystem / uses */
+ rootfs = "ufs"; /* Assume ufs if nothing else present */
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0) {
+ rootfs = md->fstab->fs_vfstype;
+ break;
+ }
+ }
+
+ if (strcmp(classp->lg_name, "PART") != 0) {
+ dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
+ return;
+ }
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ modified = "true"; /* XXX: If we don't know (kernel too old),
+ * assume there are modifications. */
+ LIST_FOREACH(gc, &gp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "modified") == 0) {
+ modified = gc->lg_val;
+ break;
+ }
+ }
+
+ if (strcmp(modified, "false") == 0)
+ continue;
+
+ /* Add bootcode if necessary, before the commit */
+ md = get_part_metadata(gp->lg_name, 0);
+ if (md != NULL && md->bootcode)
+ gpart_bootcode(gp);
+
+ /* Now install partcode on its partitions, if necessary */
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
+ md = get_part_metadata(pp->lg_name, 0);
+ if (md == NULL || !md->bootcode)
+ continue;
+
+ /* Mark this partition active if that's required */
+ gpart_activate(pp);
+
+ /* Check if the partition has sub-partitions */
+ LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
+ if (strcmp(cp->lg_geom->lg_class->lg_name,
+ "PART") == 0)
+ break;
+
+ if (cp == NULL) /* No sub-partitions */
+ gpart_partcode(pp, rootfs);
+ }
+
+ r = gctl_get_handle();
+ gctl_ro_param(r, "class", -1, "PART");
+ gctl_ro_param(r, "arg0", -1, gp->lg_name);
+ gctl_ro_param(r, "verb", -1, "commit");
+
+ errstr = gctl_issue(r);
+ if (errstr != NULL && errstr[0] != '\0')
+ gpart_show_error("Error", NULL, errstr);
+ gctl_free(r);
+ }
+}
+
diff --git a/contrib/bsddialog/bsdinstall/partedit/part_wizard.c b/contrib/bsddialog/bsdinstall/partedit/part_wizard.c
new file mode 100644
index 000000000000..52c5d7f649cc
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/part_wizard.c
@@ -0,0 +1,366 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/param.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <string.h>
+
+#include <libgeom.h>
+#include <dialog.h>
+#include <dlg_keys.h>
+
+#include "partedit.h"
+
+#define MIN_FREE_SPACE (1024*1024*1024) /* 1 GB */
+#define SWAP_SIZE(available) MIN(available/20, 4*1024*1024*1024LL)
+
+static char *wizard_partition(struct gmesh *mesh, const char *disk);
+
+int
+part_wizard(const char *fsreq)
+{
+ char *disk, *schemeroot;
+ const char *fstype;
+ struct gmesh mesh;
+ int error;
+
+ if (fsreq != NULL)
+ fstype = fsreq;
+ else
+ fstype = "ufs";
+
+startwizard:
+ error = geom_gettree(&mesh);
+
+ dlg_put_backtitle();
+ error = geom_gettree(&mesh);
+ disk = boot_disk_select(&mesh);
+ if (disk == NULL)
+ return (1);
+
+ dlg_clear();
+ dlg_put_backtitle();
+ schemeroot = wizard_partition(&mesh, disk);
+ free(disk);
+ if (schemeroot == NULL)
+ return (1);
+
+ geom_deletetree(&mesh);
+ dlg_clear();
+ dlg_put_backtitle();
+ error = geom_gettree(&mesh);
+
+ error = wizard_makeparts(&mesh, schemeroot, fstype, 1);
+ if (error)
+ goto startwizard;
+ free(schemeroot);
+
+ geom_deletetree(&mesh);
+
+ return (0);
+}
+
+char *
+boot_disk_select(struct gmesh *mesh)
+{
+ struct gclass *classp;
+ struct gconfig *gc;
+ struct ggeom *gp;
+ struct gprovider *pp;
+ DIALOG_LISTITEM *disks = NULL;
+ const char *type, *desc;
+ char diskdesc[512];
+ char *chosen;
+ int i, err, selected, n = 0;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, "DISK") != 0 &&
+ strcmp(classp->lg_name, "RAID") != 0 &&
+ strcmp(classp->lg_name, "MD") != 0)
+ continue;
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ if (LIST_EMPTY(&gp->lg_provider))
+ continue;
+
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
+ desc = type = NULL;
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "type") == 0)
+ type = gc->lg_val;
+ if (strcmp(gc->lg_name, "descr") == 0)
+ desc = gc->lg_val;
+ }
+
+ /* Skip swap-backed md and WORM devices */
+ if (strcmp(classp->lg_name, "MD") == 0 &&
+ type != NULL && strcmp(type, "swap") == 0)
+ continue;
+ if (strncmp(pp->lg_name, "cd", 2) == 0)
+ continue;
+
+ disks = realloc(disks, (++n)*sizeof(disks[0]));
+ disks[n-1].name = pp->lg_name;
+ humanize_number(diskdesc, 7, pp->lg_mediasize,
+ "B", HN_AUTOSCALE, HN_DECIMAL);
+ if (strncmp(pp->lg_name, "ad", 2) == 0)
+ strcat(diskdesc, " ATA Hard Disk");
+ else if (strncmp(pp->lg_name, "md", 2) == 0)
+ strcat(diskdesc, " Memory Disk");
+ else
+ strcat(diskdesc, " Disk");
+
+ if (desc != NULL)
+ snprintf(diskdesc, sizeof(diskdesc),
+ "%s <%s>", diskdesc, desc);
+
+ disks[n-1].text = strdup(diskdesc);
+ disks[n-1].help = NULL;
+ disks[n-1].state = 0;
+ }
+ }
+ }
+
+ if (n > 1) {
+ err = dlg_menu("Partitioning",
+ "Select the disk on which to install FreeBSD.", 0, 0, 0,
+ n, disks, &selected, NULL);
+
+ chosen = (err == 0) ? strdup(disks[selected].name) : NULL;
+ } else if (n == 1) {
+ chosen = strdup(disks[0].name);
+ } else {
+ chosen = NULL;
+ }
+
+ for (i = 0; i < n; i++)
+ free(disks[i].text);
+
+ return (chosen);
+}
+
+static struct gprovider *
+provider_for_name(struct gmesh *mesh, const char *name)
+{
+ struct gclass *classp;
+ struct gprovider *pp = NULL;
+ struct ggeom *gp;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ if (LIST_EMPTY(&gp->lg_provider))
+ continue;
+
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider)
+ if (strcmp(pp->lg_name, name) == 0)
+ break;
+
+ if (pp != NULL) break;
+ }
+
+ if (pp != NULL) break;
+ }
+
+ return (pp);
+}
+
+static char *
+wizard_partition(struct gmesh *mesh, const char *disk)
+{
+ struct gclass *classp;
+ struct ggeom *gpart = NULL;
+ struct gconfig *gc;
+ char *retval = NULL;
+ const char *scheme = NULL;
+ char message[512];
+ int choice;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class)
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+
+ if (classp != NULL) {
+ LIST_FOREACH(gpart, &classp->lg_geom, lg_geom)
+ if (strcmp(gpart->lg_name, disk) == 0)
+ break;
+ }
+
+ if (gpart != NULL) {
+ LIST_FOREACH(gc, &gpart->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ break;
+ }
+ }
+ }
+
+ /* Treat uncommitted scheme deletions as no scheme */
+ if (scheme != NULL && strcmp(scheme, "(none)") == 0)
+ scheme = NULL;
+
+query:
+ dialog_vars.yes_label = "Entire Disk";
+ dialog_vars.no_label = "Partition";
+ if (gpart != NULL)
+ dialog_vars.defaultno = TRUE;
+
+ snprintf(message, sizeof(message), "Would you like to use this entire "
+ "disk (%s) for FreeBSD or partition it to share it with other "
+ "operating systems? Using the entire disk will erase any data "
+ "currently stored there.", disk);
+ choice = dialog_yesno("Partition", message, 0, 0);
+
+ dialog_vars.yes_label = NULL;
+ dialog_vars.no_label = NULL;
+ dialog_vars.defaultno = FALSE;
+
+ if (choice == 1 && scheme != NULL && !is_scheme_bootable(scheme)) {
+ char warning[512];
+ int subchoice;
+
+ sprintf(warning, "The existing partition scheme on this "
+ "disk (%s) is not bootable on this platform. To install "
+ "FreeBSD, it must be repartitioned. This will destroy all "
+ "data on the disk. Are you sure you want to proceed?",
+ scheme);
+ subchoice = dialog_yesno("Non-bootable Disk", warning, 0, 0);
+ if (subchoice != 0)
+ goto query;
+
+ gpart_destroy(gpart);
+ scheme = choose_part_type(default_scheme());
+ if (scheme == NULL)
+ return NULL;
+ gpart_partition(disk, scheme);
+ }
+
+ if (scheme == NULL || choice == 0) {
+ if (gpart != NULL && scheme != NULL) {
+ /* Erase partitioned disk */
+ choice = dialog_yesno("Confirmation", "This will erase "
+ "the disk. Are you sure you want to proceed?", 0, 0);
+ if (choice != 0)
+ goto query;
+
+ gpart_destroy(gpart);
+ }
+
+ scheme = choose_part_type(default_scheme());
+ if (scheme == NULL)
+ return NULL;
+ gpart_partition(disk, scheme);
+ }
+
+ if (strcmp(scheme, "MBR") == 0) {
+ struct gmesh submesh;
+ geom_gettree(&submesh);
+ gpart_create(provider_for_name(&submesh, disk),
+ "freebsd", NULL, NULL, &retval,
+ choice /* Non-interactive for "Entire Disk" */);
+ geom_deletetree(&submesh);
+ } else {
+ retval = strdup(disk);
+ }
+
+ return (retval);
+}
+
+int
+wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype,
+ int interactive)
+{
+ struct gclass *classp;
+ struct ggeom *gp;
+ struct gprovider *pp;
+ char *fsnames[] = {"freebsd-ufs", "freebsd-zfs"};
+ char *fsname;
+ struct gmesh submesh;
+ char swapsizestr[10], rootsizestr[10];
+ intmax_t swapsize, available;
+ int retval;
+
+ if (strcmp(fstype, "zfs") == 0) {
+ fsname = fsnames[1];
+ } else {
+ /* default to UFS */
+ fsname = fsnames[0];
+ }
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class)
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
+ if (strcmp(gp->lg_name, disk) == 0)
+ break;
+
+ pp = provider_for_name(mesh, disk);
+
+ available = gpart_max_free(gp, NULL)*pp->lg_sectorsize;
+ if (interactive && available < MIN_FREE_SPACE) {
+ char availablestr[10], neededstr[10], message[512];
+ humanize_number(availablestr, 7, available, "B", HN_AUTOSCALE,
+ HN_DECIMAL);
+ humanize_number(neededstr, 7, MIN_FREE_SPACE, "B", HN_AUTOSCALE,
+ HN_DECIMAL);
+ sprintf(message, "There is not enough free space on %s to "
+ "install FreeBSD (%s free, %s required). Would you like "
+ "to choose another disk or to open the partition editor?",
+ disk, availablestr, neededstr);
+
+ dialog_vars.yes_label = "Another Disk";
+ dialog_vars.no_label = "Editor";
+ retval = dialog_yesno("Warning", message, 0, 0);
+ dialog_vars.yes_label = NULL;
+ dialog_vars.no_label = NULL;
+
+ return (!retval); /* Editor -> return 0 */
+ }
+
+ swapsize = SWAP_SIZE(available);
+ humanize_number(swapsizestr, 7, swapsize, "B", HN_AUTOSCALE,
+ HN_NOSPACE | HN_DECIMAL);
+ humanize_number(rootsizestr, 7, available - swapsize - 1024*1024,
+ "B", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
+
+ geom_gettree(&submesh);
+ pp = provider_for_name(&submesh, disk);
+ gpart_create(pp, fsname, rootsizestr, "/", NULL, 0);
+ geom_deletetree(&submesh);
+
+ geom_gettree(&submesh);
+ pp = provider_for_name(&submesh, disk);
+ gpart_create(pp, "freebsd-swap", swapsizestr, NULL, NULL, 0);
+ geom_deletetree(&submesh);
+
+ return (0);
+}
diff --git a/contrib/bsddialog/bsdinstall/partedit/partedit.c b/contrib/bsddialog/bsdinstall/partedit/partedit.c
new file mode 100644
index 000000000000..df7e573d42c2
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/partedit.c
@@ -0,0 +1,606 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/param.h>
+
+#include <dialog.h>
+#include <dlg_keys.h>
+#include <err.h>
+#include <errno.h>
+#include <fstab.h>
+#include <inttypes.h>
+#include <libgeom.h>
+#include <libutil.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include "diskmenu.h"
+#include "partedit.h"
+
+struct pmetadata_head part_metadata;
+static int sade_mode = 0;
+
+static int apply_changes(struct gmesh *mesh);
+static void apply_workaround(struct gmesh *mesh);
+static struct partedit_item *read_geom_mesh(struct gmesh *mesh, int *nitems);
+static void add_geom_children(struct ggeom *gp, int recurse,
+ struct partedit_item **items, int *nitems);
+static void init_fstab_metadata(void);
+static void get_mount_points(struct partedit_item *items, int nitems);
+static int validate_setup(void);
+
+static void
+sigint_handler(int sig)
+{
+ struct gmesh mesh;
+
+ /* Revert all changes and exit dialog-mode cleanly on SIGINT */
+ geom_gettree(&mesh);
+ gpart_revert_all(&mesh);
+ geom_deletetree(&mesh);
+
+ end_dialog();
+
+ exit(1);
+}
+
+int
+main(int argc, const char **argv)
+{
+ struct partition_metadata *md;
+ const char *progname, *prompt;
+ struct partedit_item *items = NULL;
+ struct gmesh mesh;
+ int i, op, nitems;
+ int error;
+
+ progname = getprogname();
+ if (strcmp(progname, "sade") == 0)
+ sade_mode = 1;
+
+ TAILQ_INIT(&part_metadata);
+
+ init_fstab_metadata();
+
+ init_dialog(stdin, stdout);
+ if (!sade_mode)
+ dialog_vars.backtitle = __DECONST(char *, "FreeBSD Installer");
+ dialog_vars.item_help = TRUE;
+ i = 0;
+
+ /* Revert changes on SIGINT */
+ signal(SIGINT, sigint_handler);
+
+ if (strcmp(progname, "autopart") == 0) { /* Guided */
+ prompt = "Please review the disk setup. When complete, press "
+ "the Finish button.";
+ /* Experimental ZFS autopartition support */
+ if (argc > 1 && strcmp(argv[1], "zfs") == 0) {
+ part_wizard("zfs");
+ } else {
+ part_wizard("ufs");
+ }
+ } else if (strcmp(progname, "scriptedpart") == 0) {
+ error = scripted_editor(argc, argv);
+ prompt = NULL;
+ if (error != 0) {
+ end_dialog();
+ return (error);
+ }
+ } else {
+ prompt = "Create partitions for FreeBSD. No changes will be "
+ "made until you select Finish.";
+ }
+
+ /* Show the part editor either immediately, or to confirm wizard */
+ while (prompt != NULL) {
+ dlg_clear();
+ dlg_put_backtitle();
+
+ error = geom_gettree(&mesh);
+ if (error == 0)
+ items = read_geom_mesh(&mesh, &nitems);
+ if (error || items == NULL) {
+ dialog_msgbox("Error", "No disks found. If you need to "
+ "install a kernel driver, choose Shell at the "
+ "installation menu.", 0, 0, TRUE);
+ break;
+ }
+
+ get_mount_points(items, nitems);
+
+ if (i >= nitems)
+ i = nitems - 1;
+ end_dialog();op = diskmenu_show("Partition Editor", prompt,
+ items, nitems, &i);init_dialog(stdin, stdout);
+
+ switch (op) {
+ case 0: /* Create */
+ gpart_create((struct gprovider *)(items[i].cookie),
+ NULL, NULL, NULL, NULL, 1);
+ break;
+ case 1: /* Delete */
+ gpart_delete((struct gprovider *)(items[i].cookie));
+ break;
+ case 2: /* Modify */
+ gpart_edit((struct gprovider *)(items[i].cookie));
+ break;
+ case 3: /* Revert */
+ gpart_revert_all(&mesh);
+ while ((md = TAILQ_FIRST(&part_metadata)) != NULL) {
+ if (md->fstab != NULL) {
+ free(md->fstab->fs_spec);
+ free(md->fstab->fs_file);
+ free(md->fstab->fs_vfstype);
+ free(md->fstab->fs_mntops);
+ free(md->fstab->fs_type);
+ free(md->fstab);
+ }
+ if (md->newfs != NULL)
+ free(md->newfs);
+ free(md->name);
+
+ TAILQ_REMOVE(&part_metadata, md, metadata);
+ free(md);
+ }
+ init_fstab_metadata();
+ break;
+ case 4: /* Auto */
+ part_wizard("ufs");
+ break;
+ }
+
+ error = 0;
+ if (op == 5) { /* Finished */
+ dialog_vars.ok_label = __DECONST(char *, "Commit");
+ dialog_vars.extra_label =
+ __DECONST(char *, "Revert & Exit");
+ dialog_vars.extra_button = TRUE;
+ dialog_vars.cancel_label = __DECONST(char *, "Back");
+ op = dialog_yesno("Confirmation", "Your changes will "
+ "now be written to disk. If you have chosen to "
+ "overwrite existing data, it will be PERMANENTLY "
+ "ERASED. Are you sure you want to commit your "
+ "changes?", 0, 0);
+ dialog_vars.ok_label = NULL;
+ dialog_vars.extra_button = FALSE;
+ dialog_vars.cancel_label = NULL;
+
+ if (op == 0 && validate_setup()) { /* Save */
+ error = apply_changes(&mesh);
+ if (!error)
+ apply_workaround(&mesh);
+ break;
+ } else if (op == 3) { /* Quit */
+ gpart_revert_all(&mesh);
+ error = -1;
+ break;
+ }
+ }
+
+ geom_deletetree(&mesh);
+ free(items);
+ }
+
+ if (prompt == NULL) {
+ error = geom_gettree(&mesh);
+ if (validate_setup()) {
+ error = apply_changes(&mesh);
+ } else {
+ gpart_revert_all(&mesh);
+ error = -1;
+ }
+ }
+
+ geom_deletetree(&mesh);
+ free(items);
+ end_dialog();
+
+ return (error);
+}
+
+struct partition_metadata *
+get_part_metadata(const char *name, int create)
+{
+ struct partition_metadata *md;
+
+ TAILQ_FOREACH(md, &part_metadata, metadata)
+ if (md->name != NULL && strcmp(md->name, name) == 0)
+ break;
+
+ if (md == NULL && create) {
+ md = calloc(1, sizeof(*md));
+ md->name = strdup(name);
+ TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
+ }
+
+ return (md);
+}
+
+void
+delete_part_metadata(const char *name)
+{
+ struct partition_metadata *md;
+
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->name != NULL && strcmp(md->name, name) == 0) {
+ if (md->fstab != NULL) {
+ free(md->fstab->fs_spec);
+ free(md->fstab->fs_file);
+ free(md->fstab->fs_vfstype);
+ free(md->fstab->fs_mntops);
+ free(md->fstab->fs_type);
+ free(md->fstab);
+ }
+ if (md->newfs != NULL)
+ free(md->newfs);
+ free(md->name);
+
+ TAILQ_REMOVE(&part_metadata, md, metadata);
+ free(md);
+ break;
+ }
+ }
+}
+
+static int
+validate_setup(void)
+{
+ struct partition_metadata *md, *root = NULL;
+ int cancel;
+
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->fstab != NULL && strcmp(md->fstab->fs_file, "/") == 0)
+ root = md;
+
+ /* XXX: Check for duplicate mountpoints */
+ }
+
+ if (root == NULL) {
+ dialog_msgbox("Error", "No root partition was found. "
+ "The root FreeBSD partition must have a mountpoint of '/'.",
+ 0, 0, TRUE);
+ return (FALSE);
+ }
+
+ /*
+ * Check for root partitions that we aren't formatting, which is
+ * usually a mistake
+ */
+ if (root->newfs == NULL && !sade_mode) {
+ dialog_vars.defaultno = TRUE;
+ cancel = dialog_yesno("Warning", "The chosen root partition "
+ "has a preexisting filesystem. If it contains an existing "
+ "FreeBSD system, please update it with freebsd-update "
+ "instead of installing a new system on it. The partition "
+ "can also be erased by pressing \"No\" and then deleting "
+ "and recreating it. Are you sure you want to proceed?",
+ 0, 0);
+ dialog_vars.defaultno = FALSE;
+ if (cancel)
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+static int
+mountpoint_sorter(const void *xa, const void *xb)
+{
+ struct partition_metadata *a = *(struct partition_metadata **)xa;
+ struct partition_metadata *b = *(struct partition_metadata **)xb;
+
+ if (a->fstab == NULL && b->fstab == NULL)
+ return 0;
+ if (a->fstab == NULL)
+ return 1;
+ if (b->fstab == NULL)
+ return -1;
+
+ return strcmp(a->fstab->fs_file, b->fstab->fs_file);
+}
+
+static int
+apply_changes(struct gmesh *mesh)
+{
+ struct partition_metadata *md;
+ char message[512];
+ int i, nitems, error;
+ const char **items;
+ const char *fstab_path;
+ FILE *fstab;
+
+ nitems = 1; /* Partition table changes */
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->newfs != NULL)
+ nitems++;
+ }
+ items = calloc(nitems * 2, sizeof(const char *));
+ items[0] = "Writing partition tables";
+ items[1] = "7"; /* In progress */
+ i = 1;
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->newfs != NULL) {
+ char *item;
+ item = malloc(255);
+ sprintf(item, "Initializing %s", md->name);
+ items[i*2] = item;
+ items[i*2 + 1] = "Pending";
+ i++;
+ }
+ }
+
+ i = 0;
+ dialog_mixedgauge("Initializing",
+ "Initializing file systems. Please wait.", 0, 0, i*100/nitems,
+ nitems, __DECONST(char **, items));
+ gpart_commit(mesh);
+ items[i*2 + 1] = "3";
+ i++;
+
+ if (getenv("BSDINSTALL_LOG") == NULL)
+ setenv("BSDINSTALL_LOG", "/dev/null", 1);
+
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->newfs != NULL) {
+ items[i*2 + 1] = "7"; /* In progress */
+ dialog_mixedgauge("Initializing",
+ "Initializing file systems. Please wait.", 0, 0,
+ i*100/nitems, nitems, __DECONST(char **, items));
+ sprintf(message, "(echo %s; %s) >>%s 2>>%s",
+ md->newfs, md->newfs, getenv("BSDINSTALL_LOG"),
+ getenv("BSDINSTALL_LOG"));
+ error = system(message);
+ items[i*2 + 1] = (error == 0) ? "3" : "1";
+ i++;
+ }
+ }
+ dialog_mixedgauge("Initializing",
+ "Initializing file systems. Please wait.", 0, 0,
+ i*100/nitems, nitems, __DECONST(char **, items));
+
+ for (i = 1; i < nitems; i++)
+ free(__DECONST(char *, items[i*2]));
+ free(items);
+
+ /* Sort filesystems for fstab so that mountpoints are ordered */
+ {
+ struct partition_metadata **tobesorted;
+ struct partition_metadata *tmp;
+ int nparts = 0;
+ TAILQ_FOREACH(md, &part_metadata, metadata)
+ nparts++;
+ tobesorted = malloc(sizeof(struct partition_metadata *)*nparts);
+ nparts = 0;
+ TAILQ_FOREACH_SAFE(md, &part_metadata, metadata, tmp) {
+ tobesorted[nparts++] = md;
+ TAILQ_REMOVE(&part_metadata, md, metadata);
+ }
+ qsort(tobesorted, nparts, sizeof(tobesorted[0]),
+ mountpoint_sorter);
+
+ /* Now re-add everything */
+ while (nparts-- > 0)
+ TAILQ_INSERT_HEAD(&part_metadata,
+ tobesorted[nparts], metadata);
+ free(tobesorted);
+ }
+
+ if (getenv("PATH_FSTAB") != NULL)
+ fstab_path = getenv("PATH_FSTAB");
+ else
+ fstab_path = "/etc/fstab";
+ fstab = fopen(fstab_path, "w+");
+ if (fstab == NULL) {
+ sprintf(message, "Cannot open fstab file %s for writing (%s)\n",
+ getenv("PATH_FSTAB"), strerror(errno));
+ dialog_msgbox("Error", message, 0, 0, TRUE);
+ return (-1);
+ }
+ fprintf(fstab, "# Device\tMountpoint\tFStype\tOptions\tDump\tPass#\n");
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->fstab != NULL)
+ fprintf(fstab, "%s\t%s\t\t%s\t%s\t%d\t%d\n",
+ md->fstab->fs_spec, md->fstab->fs_file,
+ md->fstab->fs_vfstype, md->fstab->fs_mntops,
+ md->fstab->fs_freq, md->fstab->fs_passno);
+ }
+ fclose(fstab);
+
+ return (0);
+}
+
+static void
+apply_workaround(struct gmesh *mesh)
+{
+ struct gclass *classp;
+ struct ggeom *gp;
+ struct gconfig *gc;
+ const char *scheme = NULL, *modified = NULL;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+ }
+
+ if (strcmp(classp->lg_name, "PART") != 0) {
+ dialog_msgbox("Error", "gpart not found!", 0, 0, TRUE);
+ return;
+ }
+
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ LIST_FOREACH(gc, &gp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0) {
+ scheme = gc->lg_val;
+ } else if (strcmp(gc->lg_name, "modified") == 0) {
+ modified = gc->lg_val;
+ }
+ }
+
+ if (scheme && strcmp(scheme, "GPT") == 0 &&
+ modified && strcmp(modified, "true") == 0) {
+ if (getenv("WORKAROUND_LENOVO"))
+ gpart_set_root(gp->lg_name, "lenovofix");
+ if (getenv("WORKAROUND_GPTACTIVE"))
+ gpart_set_root(gp->lg_name, "active");
+ }
+ }
+}
+
+static struct partedit_item *
+read_geom_mesh(struct gmesh *mesh, int *nitems)
+{
+ struct gclass *classp;
+ struct ggeom *gp;
+ struct partedit_item *items;
+
+ *nitems = 0;
+ items = NULL;
+
+ /*
+ * Build the device table. First add all disks (and CDs).
+ */
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ if (strcmp(classp->lg_name, "DISK") != 0 &&
+ strcmp(classp->lg_name, "MD") != 0)
+ continue;
+
+ /* Now recurse into all children */
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom)
+ add_geom_children(gp, 0, &items, nitems);
+ }
+
+ return (items);
+}
+
+static void
+add_geom_children(struct ggeom *gp, int recurse, struct partedit_item **items,
+ int *nitems)
+{
+ struct gconsumer *cp;
+ struct gprovider *pp;
+ struct gconfig *gc;
+
+ if (strcmp(gp->lg_class->lg_name, "PART") == 0 &&
+ !LIST_EMPTY(&gp->lg_config)) {
+ LIST_FOREACH(gc, &gp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "scheme") == 0)
+ (*items)[*nitems-1].type = gc->lg_val;
+ }
+ }
+
+ if (LIST_EMPTY(&gp->lg_provider))
+ return;
+
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
+ if (strcmp(gp->lg_class->lg_name, "LABEL") == 0)
+ continue;
+
+ /* Skip WORM media */
+ if (strncmp(pp->lg_name, "cd", 2) == 0)
+ continue;
+
+ *items = realloc(*items,
+ (*nitems+1)*sizeof(struct partedit_item));
+ (*items)[*nitems].indentation = recurse;
+ (*items)[*nitems].name = pp->lg_name;
+ (*items)[*nitems].size = pp->lg_mediasize;
+ (*items)[*nitems].mountpoint = NULL;
+ (*items)[*nitems].type = "";
+ (*items)[*nitems].cookie = pp;
+
+ LIST_FOREACH(gc, &pp->lg_config, lg_config) {
+ if (strcmp(gc->lg_name, "type") == 0)
+ (*items)[*nitems].type = gc->lg_val;
+ }
+
+ /* Skip swap-backed MD devices */
+ if (strcmp(gp->lg_class->lg_name, "MD") == 0 &&
+ strcmp((*items)[*nitems].type, "swap") == 0)
+ continue;
+
+ (*nitems)++;
+
+ LIST_FOREACH(cp, &pp->lg_consumers, lg_consumers)
+ add_geom_children(cp->lg_geom, recurse+1, items,
+ nitems);
+
+ /* Only use first provider for acd */
+ if (strcmp(gp->lg_class->lg_name, "ACD") == 0)
+ break;
+ }
+}
+
+static void
+init_fstab_metadata(void)
+{
+ struct fstab *fstab;
+ struct partition_metadata *md;
+
+ setfsent();
+ while ((fstab = getfsent()) != NULL) {
+ md = calloc(1, sizeof(struct partition_metadata));
+
+ md->name = NULL;
+ if (strncmp(fstab->fs_spec, "/dev/", 5) == 0)
+ md->name = strdup(&fstab->fs_spec[5]);
+
+ md->fstab = malloc(sizeof(struct fstab));
+ md->fstab->fs_spec = strdup(fstab->fs_spec);
+ md->fstab->fs_file = strdup(fstab->fs_file);
+ md->fstab->fs_vfstype = strdup(fstab->fs_vfstype);
+ md->fstab->fs_mntops = strdup(fstab->fs_mntops);
+ md->fstab->fs_type = strdup(fstab->fs_type);
+ md->fstab->fs_freq = fstab->fs_freq;
+ md->fstab->fs_passno = fstab->fs_passno;
+
+ md->newfs = NULL;
+
+ TAILQ_INSERT_TAIL(&part_metadata, md, metadata);
+ }
+}
+
+static void
+get_mount_points(struct partedit_item *items, int nitems)
+{
+ struct partition_metadata *md;
+ int i;
+
+ for (i = 0; i < nitems; i++) {
+ TAILQ_FOREACH(md, &part_metadata, metadata) {
+ if (md->name != NULL && md->fstab != NULL &&
+ strcmp(md->name, items[i].name) == 0) {
+ items[i].mountpoint = md->fstab->fs_file;
+ break;
+ }
+ }
+ }
+}
diff --git a/contrib/bsddialog/bsdinstall/partedit/partedit.h b/contrib/bsddialog/bsdinstall/partedit/partedit.h
new file mode 100644
index 000000000000..5c0405922d21
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/partedit.h
@@ -0,0 +1,108 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#ifndef _PARTEDIT_PARTEDIT_H
+#define _PARTEDIT_PARTEDIT_H
+
+#include <sys/queue.h>
+#include <inttypes.h>
+#include <fstab.h>
+
+struct gprovider;
+struct gmesh;
+struct ggeom;
+
+TAILQ_HEAD(pmetadata_head, partition_metadata);
+extern struct pmetadata_head part_metadata;
+
+struct partition_metadata {
+ char *name; /* name of this partition, as in GEOM */
+
+ struct fstab *fstab; /* fstab data for this partition */
+ char *newfs; /* shell command to initialize partition */
+
+ int bootcode;
+
+ TAILQ_ENTRY(partition_metadata) metadata;
+};
+
+struct partition_metadata *get_part_metadata(const char *name, int create);
+void delete_part_metadata(const char *name);
+
+int part_wizard(const char *fstype);
+int scripted_editor(int argc, const char **argv);
+char *boot_disk_select(struct gmesh *mesh);
+int wizard_makeparts(struct gmesh *mesh, const char *disk, const char *fstype,
+ int interactive);
+
+/* gpart operations */
+void gpart_delete(struct gprovider *pp);
+void gpart_destroy(struct ggeom *lg_geom);
+void gpart_edit(struct gprovider *pp);
+void gpart_create(struct gprovider *pp, const char *default_type,
+ const char *default_size, const char *default_mountpoint,
+ char **output, int interactive);
+intmax_t gpart_max_free(struct ggeom *gp, intmax_t *start);
+void gpart_revert(struct gprovider *pp);
+void gpart_revert_all(struct gmesh *mesh);
+void gpart_commit(struct gmesh *mesh);
+int gpart_partition(const char *lg_name, const char *scheme);
+void set_default_part_metadata(const char *name, const char *scheme,
+ const char *type, const char *mountpoint, const char *newfs);
+void gpart_set_root(const char *lg_name, const char *attribute);
+const char *choose_part_type(const char *def_scheme);
+
+/* machine-dependent bootability checks */
+const char *default_scheme(void); /* Default partition scheme */
+int is_scheme_bootable(const char *scheme); /* Non-zero if scheme boots */
+int is_fs_bootable(const char *scheme, const char *fs); /* Ditto if FS boots */
+
+/* Size of boot partition in bytes. Zero if no boot partition */
+size_t bootpart_size(const char *scheme);
+
+/*
+ * Type and mountpoint of boot partition for given scheme. If boot partition
+ * should not be mounted, set mountpoint to NULL or leave it unchanged.
+ * Note that mountpoint non-NULL implies partcode_path() will be ignored.
+ * Do *NOT* set both!
+ */
+const char *bootpart_type(const char *scheme, const char **mountpoint);
+
+/* Path to bootcode that goes in the scheme (e.g. disk MBR). NULL if none */
+const char *bootcode_path(const char *scheme);
+
+/*
+ * Path to boot blocks to be dd'ed into the partition suggested by bootpart_*
+ * for the given scheme and root filesystem type. If the boot partition should
+ * be mounted rather than dd'ed to, return NULL here.
+ */
+const char *partcode_path(const char *scheme, const char *fs_type);
+
+#endif
diff --git a/contrib/bsddialog/bsdinstall/partedit/partedit_efi.c b/contrib/bsddialog/bsdinstall/partedit/partedit_efi.c
new file mode 100644
index 000000000000..074475e07152
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/partedit_efi.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 Cavium Inc.
+ * All rights reserved.
+ *
+ * Developed by Semihalf.
+ * Based on work by Nathan Whitehorn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/types.h>
+#include <string.h>
+
+#include "partedit.h"
+
+/*
+ * partedit implementation for platforms on which the installer only offers
+ * UEFI-based boot. Currently, this includes arm64 and RISC-V.
+ */
+
+/* EFI partition size in bytes */
+#define EFI_BOOTPART_SIZE (260 * 1024 * 1024)
+
+const char *
+default_scheme(void)
+{
+
+ return ("GPT");
+}
+
+int
+is_scheme_bootable(const char *part_type)
+{
+
+ if (strcmp(part_type, "GPT") == 0)
+ return (1);
+
+ return (0);
+}
+
+int
+is_fs_bootable(const char *part_type, const char *fs)
+{
+
+ if (strcmp(fs, "freebsd-ufs") == 0)
+ return (1);
+
+ return (0);
+}
+
+size_t
+bootpart_size(const char *scheme)
+{
+
+ /* We only support GPT with EFI */
+ if (strcmp(scheme, "GPT") != 0)
+ return (0);
+
+ return (EFI_BOOTPART_SIZE);
+}
+
+const char *
+bootpart_type(const char *scheme, const char **mountpoint)
+{
+
+ /* Only EFI is supported as boot partition */
+ *mountpoint = "/boot/efi";
+ return ("efi");
+}
+
+const char *
+bootcode_path(const char *part_type)
+{
+
+ return (NULL);
+}
+
+const char *
+partcode_path(const char *part_type, const char *fs_type)
+{
+
+ /* No boot partition data. */
+ return (NULL);
+}
+
diff --git a/contrib/bsddialog/bsdinstall/partedit/partedit_generic.c b/contrib/bsddialog/bsdinstall/partedit/partedit_generic.c
new file mode 100644
index 000000000000..e25784592a9b
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/partedit_generic.c
@@ -0,0 +1,81 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <string.h>
+
+#include "partedit.h"
+
+const char *
+default_scheme(void) {
+ /*
+ * Our loader can parse GPT, so pick that as the default for lack of
+ * a better idea.
+ */
+
+ return ("GPT");
+}
+
+int
+is_scheme_bootable(const char *part_type) {
+ /*
+ * We don't know anything about this platform, so don't irritate the
+ * user by claiming the chosen partition scheme isn't bootable.
+ */
+
+ return (1);
+}
+
+int
+is_fs_bootable(const char *part_type, const char *fs) {
+ return (1);
+}
+
+/* No clue => no boot partition, bootcode, or partcode */
+
+size_t
+bootpart_size(const char *part_type) {
+ return (0);
+}
+
+const char *
+bootpart_type(const char *scheme, const char **mountpoint) {
+ return ("freebsd-boot");
+}
+
+const char *
+bootcode_path(const char *part_type) {
+ return (NULL);
+}
+
+const char *
+partcode_path(const char *part_type, const char *fs_type) {
+ return (NULL);
+}
+
diff --git a/contrib/bsddialog/bsdinstall/partedit/partedit_powerpc.c b/contrib/bsddialog/bsdinstall/partedit/partedit_powerpc.c
new file mode 100644
index 000000000000..5a3041df5b0c
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/partedit_powerpc.c
@@ -0,0 +1,147 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#include "partedit.h"
+
+static char platform[255] = "";
+
+const char *
+default_scheme(void) {
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname("hw.platform", platform, &platlen, NULL, -1);
+
+ if (strcmp(platform, "powermac") == 0)
+ return ("APM");
+ if (strcmp(platform, "chrp") == 0 || strcmp(platform, "ps3") == 0 ||
+ strcmp(platform, "mpc85xx") == 0)
+ return ("MBR");
+
+ /* Pick GPT as a generic default */
+ return ("GPT");
+}
+
+int
+is_scheme_bootable(const char *part_type) {
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname("hw.platform", platform, &platlen, NULL, -1);
+
+ if (strcmp(platform, "powermac") == 0 && strcmp(part_type, "APM") == 0)
+ return (1);
+ if (strcmp(platform, "powernv") == 0 && strcmp(part_type, "GPT") == 0)
+ return (1);
+ if ((strcmp(platform, "chrp") == 0 || strcmp(platform, "ps3") == 0) &&
+ (strcmp(part_type, "MBR") == 0 || strcmp(part_type, "BSD") == 0 ||
+ strcmp(part_type, "GPT") == 0))
+ return (1);
+ if (strcmp(platform, "mpc85xx") == 0 && strcmp(part_type, "MBR") == 0)
+ return (1);
+
+ return (0);
+}
+
+int
+is_fs_bootable(const char *part_type, const char *fs)
+{
+ if (strcmp(fs, "freebsd-ufs") == 0)
+ return (1);
+
+ return (0);
+}
+
+size_t
+bootpart_size(const char *part_type)
+{
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname("hw.platform", platform, &platlen, NULL, -1);
+
+ if (strcmp(part_type, "APM") == 0)
+ return (800*1024);
+ if (strcmp(part_type, "BSD") == 0) /* Nothing for nested */
+ return (0);
+ if (strcmp(platform, "chrp") == 0)
+ return (800*1024);
+ if (strcmp(platform, "ps3") == 0 || strcmp(platform, "powernv") == 0)
+ return (512*1024*1024);
+ if (strcmp(platform, "mpc85xx") == 0)
+ return (16*1024*1024);
+ return (0);
+}
+
+const char *
+bootpart_type(const char *scheme, const char **mountpoint)
+{
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname("hw.platform", platform, &platlen, NULL, -1);
+
+ if (strcmp(platform, "chrp") == 0)
+ return ("prep-boot");
+ if (strcmp(platform, "powermac") == 0)
+ return ("apple-boot");
+ if (strcmp(platform, "powernv") == 0 || strcmp(platform, "ps3") == 0) {
+ *mountpoint = "/boot";
+ if (strcmp(scheme, "GPT") == 0)
+ return ("ms-basic-data");
+ else if (strcmp(scheme, "MBR") == 0)
+ return ("fat32");
+ }
+ if (strcmp(platform, "mpc85xx") == 0) {
+ *mountpoint = "/boot/uboot";
+ return ("fat16");
+ }
+
+ return ("freebsd-boot");
+}
+
+const char *
+bootcode_path(const char *part_type) {
+ return (NULL);
+}
+
+const char *
+partcode_path(const char *part_type, const char *fs_type) {
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname("hw.platform", platform, &platlen, NULL, -1);
+
+ if (strcmp(part_type, "APM") == 0)
+ return ("/boot/boot1.hfs");
+ if (strcmp(platform, "chrp") == 0)
+ return ("/boot/boot1.elf");
+ return (NULL);
+}
+
diff --git a/contrib/bsddialog/bsdinstall/partedit/partedit_x86.c b/contrib/bsddialog/bsdinstall/partedit/partedit_x86.c
new file mode 100644
index 000000000000..6983188ba34f
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/partedit_x86.c
@@ -0,0 +1,155 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2011 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+#include "partedit.h"
+
+/* EFI partition size in bytes */
+#define EFI_BOOTPART_SIZE (260 * 1024 * 1024)
+
+static const char *
+x86_bootmethod(void)
+{
+ static char fw[255] = "";
+ size_t len = sizeof(fw);
+ int error;
+
+ if (strlen(fw) == 0) {
+ error = sysctlbyname("machdep.bootmethod", fw, &len, NULL, -1);
+ if (error != 0)
+ return ("BIOS");
+ }
+
+ return (fw);
+}
+
+const char *
+default_scheme(void)
+{
+ if (strcmp(x86_bootmethod(), "UEFI") == 0)
+ return ("GPT");
+ else
+ return ("MBR");
+}
+
+int
+is_scheme_bootable(const char *part_type)
+{
+
+ if (strcmp(part_type, "GPT") == 0)
+ return (1);
+ if (strcmp(x86_bootmethod(), "BIOS") == 0) {
+ if (strcmp(part_type, "BSD") == 0)
+ return (1);
+ if (strcmp(part_type, "MBR") == 0)
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+is_fs_bootable(const char *part_type, const char *fs)
+{
+
+ if (strcmp(fs, "freebsd-ufs") == 0)
+ return (1);
+
+ if (strcmp(fs, "freebsd-zfs") == 0 &&
+ strcmp(part_type, "GPT") == 0 &&
+ strcmp(x86_bootmethod(), "BIOS") == 0)
+ return (1);
+
+ return (0);
+}
+
+size_t
+bootpart_size(const char *scheme)
+{
+
+ /* No partcode except for GPT */
+ if (strcmp(scheme, "GPT") != 0)
+ return (0);
+
+ if (strcmp(x86_bootmethod(), "BIOS") == 0)
+ return (512*1024);
+ else
+ return (EFI_BOOTPART_SIZE);
+
+ return (0);
+}
+
+const char *
+bootpart_type(const char *scheme, const char **mountpoint)
+{
+
+ if (strcmp(x86_bootmethod(), "UEFI") == 0) {
+ *mountpoint = "/boot/efi";
+ return ("efi");
+ }
+
+ return ("freebsd-boot");
+}
+
+const char *
+bootcode_path(const char *part_type)
+{
+
+ if (strcmp(x86_bootmethod(), "UEFI") == 0)
+ return (NULL);
+
+ if (strcmp(part_type, "GPT") == 0)
+ return ("/boot/pmbr");
+ if (strcmp(part_type, "MBR") == 0)
+ return ("/boot/mbr");
+ if (strcmp(part_type, "BSD") == 0)
+ return ("/boot/boot");
+
+ return (NULL);
+}
+
+const char *
+partcode_path(const char *part_type, const char *fs_type)
+{
+
+ if (strcmp(part_type, "GPT") == 0 && strcmp(x86_bootmethod(), "UEFI") != 0) {
+ if (strcmp(fs_type, "zfs") == 0)
+ return ("/boot/gptzfsboot");
+ else
+ return ("/boot/gptboot");
+ }
+
+ /* No partcode except for non-UEFI GPT */
+ return (NULL);
+}
+
diff --git a/contrib/bsddialog/bsdinstall/partedit/sade.8 b/contrib/bsddialog/bsdinstall/partedit/sade.8
new file mode 100644
index 000000000000..f80f8c5fb7d0
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/sade.8
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1997
+.\" Jordan Hubbard <jkh@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 Jordan Hubbard AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL Jordan Hubbard OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (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$
+.\"
+.Dd December 30, 2012
+.Dt SADE 8
+.Os
+.Sh NAME
+.Nm sade
+.Nd sysadmins disk editor
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+The
+.Nm
+utility is used for various disk administration tasks on
+.Fx
+systems.
+.Pp
+It is generally invoked without arguments for the default
+behavior, where the main menu is presented.
+.Sh NOTES
+The
+.Nm
+utility aims to provide a handy tool for disk management
+tasks on an already installed system.
+The goal is to provide the same text interface for disk management in
+.Xr bsdinstall 8
+in the post-installation environment.
+.Sh SEE ALSO
+.Xr bsdinstall 8 ,
+.Xr gpart 8
+.Sh HISTORY
+A program called
+.Nm
+first appeared in
+.Fx 6.3
+as a utility encapsulating features from the
+.Xr sysinstall 8
+installer.
+It was replaced in
+.Fx 10.0
+with the equivalent part of
+.Xr bsdinstall 8 .
+.Sh AUTHORS
+.An Nathan Whitehorn Aq Mt nwhitehorn@FreeBSD.org
+.Sh BUGS
+The utility misses a lot of nice features, such as tools for
+manipulating
+.Xr gmirror 8 .
+These will be added later.
diff --git a/contrib/bsddialog/bsdinstall/partedit/scripted.c b/contrib/bsddialog/bsdinstall/partedit/scripted.c
new file mode 100644
index 000000000000..956855eb6e54
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/partedit/scripted.c
@@ -0,0 +1,218 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2013 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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$
+ */
+
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <libgeom.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "partedit.h"
+
+static struct gprovider *
+provider_for_name(struct gmesh *mesh, const char *name)
+{
+ struct gclass *classp;
+ struct gprovider *pp = NULL;
+ struct ggeom *gp;
+
+ LIST_FOREACH(classp, &mesh->lg_class, lg_class) {
+ LIST_FOREACH(gp, &classp->lg_geom, lg_geom) {
+ if (LIST_EMPTY(&gp->lg_provider))
+ continue;
+
+ LIST_FOREACH(pp, &gp->lg_provider, lg_provider)
+ if (strcmp(pp->lg_name, name) == 0)
+ break;
+
+ if (pp != NULL) break;
+ }
+
+ if (pp != NULL) break;
+ }
+
+ return (pp);
+}
+
+static int
+part_config(char *disk, const char *scheme, char *config)
+{
+ char *partition, *ap, *size = NULL, *type = NULL, *mount = NULL;
+ struct gclass *classp;
+ struct gmesh mesh;
+ struct ggeom *gpart = NULL;
+ int error;
+
+ if (scheme == NULL)
+ scheme = default_scheme();
+
+ error = geom_gettree(&mesh);
+ if (provider_for_name(&mesh, disk) == NULL) {
+ fprintf(stderr, "GEOM provider %s not found\n", disk);
+ geom_deletetree(&mesh);
+ return (-1);
+ }
+
+ /* Remove any existing partitioning and create new scheme */
+ LIST_FOREACH(classp, &mesh.lg_class, lg_class)
+ if (strcmp(classp->lg_name, "PART") == 0)
+ break;
+ if (classp != NULL) {
+ LIST_FOREACH(gpart, &classp->lg_geom, lg_geom)
+ if (strcmp(gpart->lg_name, disk) == 0)
+ break;
+ }
+ if (gpart != NULL)
+ gpart_destroy(gpart);
+ gpart_partition(disk, scheme);
+
+ if (strcmp(scheme, "MBR") == 0) {
+ struct gmesh submesh;
+ geom_gettree(&submesh);
+ gpart_create(provider_for_name(&submesh, disk),
+ "freebsd", NULL, NULL, &disk, 0);
+ geom_deletetree(&submesh);
+ } else {
+ disk= strdup(disk);
+ }
+
+ geom_deletetree(&mesh);
+ error = geom_gettree(&mesh);
+
+ /* Create partitions */
+ if (config == NULL) {
+ wizard_makeparts(&mesh, disk, "ufs", 0);
+ goto finished;
+ }
+
+ while ((partition = strsep(&config, ",")) != NULL) {
+ while ((ap = strsep(&partition, " \t\n")) != NULL) {
+ if (*ap == '\0')
+ continue;
+ if (size == NULL)
+ size = ap;
+ else if (type == NULL)
+ type = ap;
+ else if (mount == NULL)
+ mount = ap;
+ }
+ if (size == NULL)
+ continue;
+ if (strcmp(size, "auto") == 0)
+ size = NULL;
+ gpart_create(provider_for_name(&mesh, disk), type, size, mount,
+ NULL, 0);
+ geom_deletetree(&mesh);
+ error = geom_gettree(&mesh);
+ size = type = mount = NULL;
+ }
+
+finished:
+ geom_deletetree(&mesh);
+ free(disk);
+
+ return (0);
+}
+
+static
+int parse_disk_config(char *input)
+{
+ char *ap;
+ char *disk = NULL, *scheme = NULL, *partconfig = NULL;
+
+ while (input != NULL && *input != 0) {
+ if (isspace(*input)) {
+ input++;
+ continue;
+ }
+
+ switch(*input) {
+ case '{':
+ input++;
+ partconfig = strchr(input, '}');
+ if (partconfig == NULL) {
+ fprintf(stderr, "Malformed partition setup "
+ "string: %s\n", input);
+ return (1);
+ }
+ *partconfig = '\0';
+ ap = partconfig+1;
+ partconfig = input;
+ input = ap;
+ break;
+ default:
+ if (disk == NULL)
+ disk = strsep(&input, " \t\n");
+ else if (scheme == NULL)
+ scheme = strsep(&input, " \t\n");
+ else {
+ fprintf(stderr, "Unknown directive: %s\n",
+ strsep(&input, " \t\n"));
+ return (1);
+ }
+ }
+ } while (input != NULL && *input != 0);
+
+ if (disk == NULL || strcmp(disk, "DEFAULT") == 0) {
+ struct gmesh mesh;
+ geom_gettree(&mesh);
+ disk = boot_disk_select(&mesh);
+ geom_deletetree(&mesh);
+ }
+
+ return (part_config(disk, scheme, partconfig));
+}
+
+int
+scripted_editor(int argc, const char **argv)
+{
+ char *token;
+ int i, error = 0, len = 0;
+
+ for (i = 1; i < argc; i++)
+ len += strlen(argv[i]) + 1;
+ char inputbuf[len], *input = inputbuf;
+ strcpy(input, argv[1]);
+ for (i = 2; i < argc; i++) {
+ strcat(input, " ");
+ strcat(input, argv[i]);
+ }
+
+ while ((token = strsep(&input, ";")) != NULL) {
+ error = parse_disk_config(token);
+ if (error != 0)
+ return (error);
+ }
+
+ return (0);
+}
+
diff --git a/contrib/bsddialog/bsdinstall/scripts/Makefile b/contrib/bsddialog/bsdinstall/scripts/Makefile
new file mode 100644
index 000000000000..147f49609921
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SCRIPTS= auto adduser bootconfig checksum config docsinstall entropy \
+ fetchmissingdists hardening hostname jail keymap mirrorselect mount \
+ netconfig netconfig_ipv4 netconfig_ipv6 rootpass script services time \
+ umount wlanconfig zfsboot
+BINDIR= ${LIBEXECDIR}/bsdinstall
+
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/contrib/bsddialog/bsdinstall/scripts/Makefile.depend b/contrib/bsddialog/bsdinstall/scripts/Makefile.depend
new file mode 100644
index 000000000000..f80275d86ab1
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/Makefile.depend
@@ -0,0 +1,11 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif
diff --git a/contrib/bsddialog/bsdinstall/scripts/adduser b/contrib/bsddialog/bsdinstall/scripts/adduser
new file mode 100755
index 000000000000..456f76b04319
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/adduser
@@ -0,0 +1,34 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+clear
+echo "FreeBSD Installer"
+echo "========================"
+echo "Add Users"
+echo
+chroot $BSDINSTALL_CHROOT adduser 2>&1
diff --git a/contrib/bsddialog/bsdinstall/scripts/auto b/contrib/bsddialog/bsdinstall/scripts/auto
new file mode 100755
index 000000000000..9f8946880f61
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/auto
@@ -0,0 +1,444 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2018 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_include $BSDCFG_SHARE/dialog.subr
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+hline_arrows_tab_space_enter="Press arrows, TAB, SPACE or ENTER"
+msg_abort="Abort"
+msg_an_installation_step_has_been_aborted="An installation step has been aborted. Would you like\nto restart the installation or exit the installer?"
+msg_auto_ufs="Auto (UFS)"
+msg_auto_ufs_desc="Guided UFS Disk Setup"
+msg_auto_ufs_help="Menu options help choose which disk to setup using UFS and standard partitions"
+msg_auto_zfs="Auto (ZFS)"
+msg_auto_zfs_desc="Guided Root-on-ZFS"
+msg_auto_zfs_help="To use ZFS with less than 8GB RAM, see https://wiki.freebsd.org/ZFSTuningGuide"
+msg_exit="Exit"
+msg_freebsd_installer="FreeBSD Installer"
+msg_gpt_active_fix="Your hardware is known to have issues booting in CSM/Legacy/BIOS mode from GPT partitions that are not set active. Would you like the installer to apply this workaround for you?"
+msg_lenovo_fix="Your model of Lenovo is known to have a BIOS bug that prevents it booting from GPT partitions without UEFI. Would you like the installer to apply a workaround for you?"
+msg_manual="Manual"
+msg_manual_desc="Manual Disk Setup (experts)"
+msg_manual_help="Create customized partitions from menu options"
+msg_no="NO"
+msg_restart="Restart"
+msg_shell="Shell"
+msg_shell_desc="Open a shell and partition by hand"
+msg_shell_help="Create customized partitions using command-line utilities"
+msg_yes="YES"
+
+############################################################ FUNCTIONS
+
+# error [$msg]
+#
+# Display generic error message when a script fails. An optional message
+# argument can preceed the generic message. User is given the choice of
+# restarting the installer or exiting.
+#
+error()
+{
+ local title="$msg_abort"
+ local btitle="$msg_freebsd_installer"
+ local prompt="${1:+$1\n\n}$msg_an_installation_step_has_been_aborted"
+ local hline="$hline_arrows_tab_space_enter"
+
+ [ -f "$PATH_FSTAB" ] && bsdinstall umount
+
+ local height width
+ f_dialog_buttonbox_size height width \
+ "$title" "$btitle" "$prompt" "$hline"
+
+ if $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --no-label "$msg_exit" \
+ --yes-label "$msg_restart" \
+ --yesno "$prompt" $height $width
+ then
+ exec $0
+ # NOTREACHED
+ fi
+ exit 1
+}
+
+# dialog_workaround
+#
+# Ask the user if they wish to apply a workaround
+#
+dialog_workaround()
+{
+ local passed_msg="$1"
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height=8 width=50 prefix=" "
+ local plen=${#prefix} list= line=
+ local max_width=$(( $width - 3 - $plen ))
+
+ local yes no defaultno extra_args format
+ if [ "$USE_XDIALOG" ]; then
+ yes=ok no=cancel defaultno=default-no
+ extra_args="--wrap --left"
+ format="$passed_msg"
+ else
+ yes=yes no=no defaultno=defaultno
+ extra_args="--cr-wrap"
+ format="$passed_msg"
+ fi
+
+ # Add height for Xdialog(1)
+ [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 ))
+
+ prompt=$( printf "$format" )
+ f_dprintf "%s: Workaround prompt" "$0"
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --$yes-label "$msg_yes" \
+ --$no-label "$msg_no" \
+ $extra_args \
+ --yesno "$prompt" $height $width
+}
+
+############################################################ MAIN
+
+f_dprintf "Began Installation at %s" "$( date )"
+
+rm -rf $BSDINSTALL_TMPETC
+mkdir $BSDINSTALL_TMPETC
+
+trap true SIGINT # This section is optional
+bsdinstall keymap
+
+trap error SIGINT # Catch cntrl-C here
+bsdinstall hostname || error "Set hostname failed"
+
+export DISTRIBUTIONS="base.txz kernel.txz"
+if [ -f $BSDINSTALL_DISTDIR/MANIFEST ]; then
+ DISTMENU=`awk -F'\t' '!/^(kernel\.txz|base\.txz)/{print $1,$5,$6}' $BSDINSTALL_DISTDIR/MANIFEST`
+ DISTMENU="$(echo ${DISTMENU} | sed -E 's/\.txz//g')"
+
+ if [ -n "$DISTMENU" ]; then
+ exec 3>&1
+ EXTRA_DISTS=$( eval dialog \
+ --backtitle \"FreeBSD Installer\" \
+ --title \"Distribution Select\" --nocancel --separate-output \
+ --checklist \"Choose optional system components to install:\" \
+ 0 0 0 $DISTMENU \
+ 2>&1 1>&3 )
+ for dist in $EXTRA_DISTS; do
+ export DISTRIBUTIONS="$DISTRIBUTIONS $dist.txz"
+ done
+ fi
+fi
+
+FETCH_DISTRIBUTIONS=""
+for dist in $DISTRIBUTIONS; do
+ if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
+ FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
+ fi
+done
+
+if [ -n "$FETCH_DISTRIBUTIONS" -a -n "$BSDINSTALL_CONFIGCURRENT" ]; then
+ dialog --backtitle "FreeBSD Installer" --title "Network Installation" --msgbox "Some installation files were not found on the boot volume. The next few screens will allow you to configure networking so that they can be downloaded from the Internet." 0 0
+ bsdinstall netconfig || error
+ NETCONFIG_DONE=yes
+fi
+
+rm -f $PATH_FSTAB
+touch $PATH_FSTAB
+
+#
+# Try to detect known broken platforms and apply their workarounds
+#
+
+if f_interactive; then
+ sys_maker=$( kenv -q smbios.system.maker )
+ f_dprintf "smbios.system.maker=[%s]" "$sys_maker"
+ sys_model=$( kenv -q smbios.system.product )
+ f_dprintf "smbios.system.product=[%s]" "$sys_model"
+ sys_version=$( kenv -q smbios.system.version )
+ f_dprintf "smbios.system.version=[%s]" "$sys_version"
+ sys_mb_maker=$( kenv -q smbios.planar.maker )
+ f_dprintf "smbios.planar.maker=[%s]" "$sys_mb_maker"
+ sys_mb_product=$( kenv -q smbios.planar.product )
+ f_dprintf "smbios.planar.product=[%s]" "$sys_mb_product"
+
+ #
+ # Laptop Models
+ #
+ case "$sys_maker" in
+ "LENOVO")
+ case "$sys_version" in
+ "ThinkPad X220"|"ThinkPad T420"|"ThinkPad T520"|"ThinkPad W520"|"ThinkPad X1")
+ dialog_workaround "$msg_lenovo_fix"
+ retval=$?
+ f_dprintf "lenovofix_prompt=[%s]" "$retval"
+ if [ $retval -eq $DIALOG_OK ]; then
+ export ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix"
+ export WORKAROUND_LENOVO=1
+ fi
+ ;;
+ esac
+ ;;
+ "Dell Inc.")
+ case "$sys_model" in
+ "Latitude E6330"|"Latitude E7440"|"Latitude E7240"|"Precision Tower 5810")
+ dialog_workaround "$msg_gpt_active_fix"
+ retval=$?
+ f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
+ if [ $retval -eq $DIALOG_OK ]; then
+ export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
+ export WORKAROUND_GPTACTIVE=1
+ fi
+ ;;
+ esac
+ ;;
+ "Hewlett-Packard")
+ case "$sys_model" in
+ "HP ProBook 4330s")
+ dialog_workaround "$msg_gpt_active_fix"
+ retval=$?
+ f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
+ if [ $retval -eq $DIALOG_OK ]; then
+ export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
+ export WORKAROUND_GPTACTIVE=1
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ #
+ # Motherboard Models
+ #
+ case "$sys_mb_maker" in
+ "Intel Corporation")
+ case "$sys_mb_product" in
+ "DP965LT"|"D510MO")
+ dialog_workaround "$msg_gpt_active_fix"
+ retval=$?
+ f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
+ if [ $retval -eq $DIALOG_OK ]; then
+ export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
+ export WORKAROUND_GPTACTIVE=1
+ fi
+ ;;
+ esac
+ ;;
+ "Acer")
+ case "$sys_mb_product" in
+ "Veriton M6630G")
+ dialog_workaround "$msg_gpt_active_fix"
+ retval=$?
+ f_dprintf "gpt_active_fix_prompt=[%s]" "$retval"
+ if [ $retval -eq $DIALOG_OK ]; then
+ export ZFSBOOT_PARTITION_SCHEME="GPT + Active"
+ export WORKAROUND_GPTACTIVE=1
+ fi
+ ;;
+ esac
+ ;;
+ esac
+fi
+
+PMODES="
+ '$msg_auto_ufs' '$msg_auto_ufs_desc' '$msg_auto_ufs_help'
+ '$msg_manual' '$msg_manual_desc' '$msg_manual_help'
+ '$msg_shell' '$msg_shell_desc' '$msg_shell_help'
+" # END-QUOTE
+
+CURARCH=$( uname -m )
+case $CURARCH in
+ amd64|arm64|i386|riscv) # Booting ZFS Supported
+ PMODES="
+ '$msg_auto_zfs' '$msg_auto_zfs_desc' '$msg_auto_zfs_help'
+ $PMODES
+ " # END-QUOTE
+ ;;
+ *) # Booting ZFS Unsupported
+ ;;
+esac
+
+exec 3>&1
+PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \
+ --title "Partitioning" \
+ --item-help \
+ --menu "How would you like to partition your disk?" \
+ 0 0 0 2>&1 1>&3` || exit 1
+exec 3>&-
+
+case "$PARTMODE" in
+"$msg_auto_zfs") # ZFS
+ bsdinstall zfsboot || error "ZFS setup failed"
+ bsdinstall mount || error "Failed to mount filesystem"
+ ;;
+"$msg_auto_ufs") # Guided UFS
+ bsdinstall autopart || error "Partitioning error"
+ bsdinstall mount || error "Failed to mount filesystem"
+ ;;
+"$msg_shell") # Shell
+ clear
+ echo "Use this shell to set up partitions for the new system. When finished, mount the system at $BSDINSTALL_CHROOT and place an fstab file for the new system at $PATH_FSTAB. Then type 'exit'. You can also enter the partition editor at any time by entering 'bsdinstall partedit'."
+ sh 2>&1
+ ;;
+"$msg_manual") # Manual
+ if f_isset debugFile; then
+ # Give partedit the path to our logfile so it can append
+ BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error "Partitioning error"
+ else
+ bsdinstall partedit || error "Partitioning error"
+ fi
+ bsdinstall mount || error "Failed to mount filesystem"
+ ;;
+*)
+ error "Unknown partitioning mode"
+ ;;
+esac
+
+if [ -n "$FETCH_DISTRIBUTIONS" ]; then
+ exec 3>&1
+ export BSDINSTALL_DISTDIR=$(`dirname $0`/fetchmissingdists 2>&1 1>&3)
+ FETCH_RESULT=$?
+ exec 3>&-
+
+ [ $FETCH_RESULT -ne 0 ] && error "Could not fetch remote distributions"
+fi
+bsdinstall checksum || error "Distribution checksum failed"
+bsdinstall distextract || error "Distribution extract failed"
+
+# Set up boot loader
+bsdinstall bootconfig || error "Failed to configure bootloader"
+
+bsdinstall rootpass || error "Could not set root password"
+
+trap true SIGINT # This section is optional
+if [ "$NETCONFIG_DONE" != yes ]; then
+ bsdinstall netconfig # Don't check for errors -- the user may cancel
+fi
+bsdinstall time
+bsdinstall services
+bsdinstall hardening
+
+dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \
+ "Would you like to add users to the installed system now?" 0 0 && \
+ bsdinstall adduser
+
+finalconfig() {
+ exec 3>&1
+ REVISIT=$(dialog --backtitle "FreeBSD Installer" \
+ --title "Final Configuration" --no-cancel --menu \
+ "Setup of your FreeBSD system is nearly complete. You can now modify your configuration choices. After this screen, you will have an opportunity to make more complex changes using a shell." 0 0 0 \
+ "Exit" "Apply configuration and exit installer" \
+ "Add User" "Add a user to the system" \
+ "Root Password" "Change root password" \
+ "Hostname" "Set system hostname" \
+ "Network" "Networking configuration" \
+ "Services" "Set daemons to run on startup" \
+ "System Hardening" "Set security options" \
+ "Time Zone" "Set system timezone" \
+ "Handbook" "Install FreeBSD Handbook (requires network)" 2>&1 1>&3)
+ exec 3>&-
+
+ case "$REVISIT" in
+ "Add User")
+ bsdinstall adduser
+ finalconfig
+ ;;
+ "Root Password")
+ bsdinstall rootpass
+ finalconfig
+ ;;
+ "Hostname")
+ bsdinstall hostname
+ finalconfig
+ ;;
+ "Network")
+ bsdinstall netconfig
+ finalconfig
+ ;;
+ "Services")
+ bsdinstall services
+ finalconfig
+ ;;
+ "System Hardening")
+ bsdinstall hardening
+ finalconfig
+ ;;
+ "Time Zone")
+ bsdinstall time
+ finalconfig
+ ;;
+ "Handbook")
+ bsdinstall docsinstall
+ finalconfig
+ ;;
+ esac
+}
+
+# Allow user to change his mind
+finalconfig
+
+trap error SIGINT # SIGINT is bad again
+bsdinstall config || error "Failed to save config"
+
+if [ ! -z "$BSDINSTALL_FETCHDEST" ]; then
+ rm -rf "$BSDINSTALL_FETCHDEST"
+fi
+
+dialog --backtitle "FreeBSD Installer" --title "Manual Configuration" \
+ --default-button no --yesno \
+ "The installation is now finished. Before exiting the installer, would you like to open a shell in the new system to make any final manual modifications?" 0 0
+if [ $? -eq 0 ]; then
+ clear
+ echo This shell is operating in a chroot in the new system. \
+ When finished making configuration changes, type \"exit\".
+ chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1
+fi
+
+bsdinstall entropy
+bsdinstall umount
+
+f_dprintf "Installation Completed at %s" "$( date )"
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/bootconfig b/contrib/bsddialog/bsdinstall/scripts/bootconfig
new file mode 100755
index 000000000000..c5218b10a271
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/bootconfig
@@ -0,0 +1,97 @@
+#!/bin/sh
+#-
+# Copyright (c) 2018 Rebecca Cran
+# Copyright (c) 2017 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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_BOOTLABEL="FreeBSD"
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+: ${TMPDIR:="/tmp"}
+
+die() {
+ echo $*
+ exit 1
+}
+
+if [ `uname -m` == powerpc ]; then
+ platform=`sysctl -n hw.platform`
+ if [ "$platform" == ps3 -o "$platform" == powernv ]; then
+ rootpart=$(awk '{ if($2 == "/") printf("%s:%s\n", $3, $1); }' $PATH_FSTAB)
+ kboot_conf=$BSDINSTALL_CHROOT/boot/etc/kboot.conf
+ mkdir -p $BSDINSTALL_CHROOT/boot/etc/
+ echo default=$FREEBSD_BOOTLABEL > $kboot_conf
+ echo $FREEBSD_BOOTLABEL=\'/kernel/kernel kernelname=/boot/kernel/kernel vfs.root.mountfrom=${rootpart}\' >> $kboot_conf
+ fi
+fi
+
+# Update the ESP (EFI System Partition) with the new bootloader if we have an ESP
+if [ -n "$(awk '{if ($2=="/boot/efi") printf("%s\n",$1);}' $PATH_FSTAB)" ]; then
+ case $(uname -m) in
+ arm64) ARCHBOOTNAME=aa64 ;;
+ amd64) ARCHBOOTNAME=x64 ;;
+ riscv) ARCHBOOTNAME=riscv64 ;;
+ # arm) ARCHBOOTNAME=arm ;; # No other support for arm install
+ # i386) ARCHBOOTNAME=ia32 ;; # no support for this in i386 kernels, rare machines
+ *) die "Unsupported arch $(uname -m) for UEFI install"
+ esac
+ BOOTDIR="/efi/boot"
+ BOOTNAME="${BOOTDIR}/boot${ARCHBOOTNAME}.efi"
+ FREEBSD_BOOTDIR="/efi/freebsd"
+ FREEBSD_BOOTNAME="${FREEBSD_BOOTDIR}/loader.efi"
+ mntpt="$BSDINSTALL_CHROOT/boot/efi"
+
+ f_dprintf "Installing loader.efi onto ESP"
+ mkdir -p "${mntpt}/${FREEBSD_BOOTDIR}" "${mntpt}/${BOOTDIR}"
+ cp "$BSDINSTALL_CHROOT/boot/loader.efi" "${mntpt}/${FREEBSD_BOOTNAME}"
+
+ #
+ # The following shouldn't be necessary. UEFI defines a way to
+ # specifically select what to boot (which we do via
+ # efibootmgr). However, virtual environments often times lack
+ # support for the NV variables efibootmgr sets. In addition,
+ # some UEFI implementations have features that interfere with
+ # the setting of these variables. To combat that, we install the
+ # default removable media boot file as a fallback if it doesn't
+ # exist. We don't install it all the time since that can
+ # interfere with other installations on the drive (like rEFInd).
+ #
+ if [ ! -f "${mntpt}/${BOOTNAME}" ]; then
+ cp "$BSDINSTALL_CHROOT/boot/loader.efi" "${mntpt}/${BOOTNAME}"
+ fi
+
+ if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+ f_dprintf "Creating UEFI boot entry"
+ efibootmgr --create --activate --label "$FREEBSD_BOOTLABEL" --loader "${mntpt}/${FREEBSD_BOOTNAME}" > /dev/null
+ fi
+
+ f_dprintf "Finished configuring ESP"
+fi
+
+# Add boot0cfg for MBR BIOS booting?
diff --git a/contrib/bsddialog/bsdinstall/scripts/checksum b/contrib/bsddialog/bsdinstall/scripts/checksum
new file mode 100755
index 000000000000..ff404d7f587b
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/checksum
@@ -0,0 +1,79 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+test -f $BSDINSTALL_DISTDIR/MANIFEST || exit 0
+
+percentage=0
+for dist in $DISTRIBUTIONS; do
+ distname=$(basename $dist .txz)
+ eval "status_$distname=7"
+
+ items=""
+ for i in $DISTRIBUTIONS; do
+ items="$items $i `eval echo \\\${status_$(basename $i .txz):-Pending}`"
+ done
+ dialog --backtitle "FreeBSD Installer" --title "Checksum Verification" \
+ --mixedgauge "Verifying checksums of selected distributions." \
+ 0 0 $percentage $items
+
+ CK=`sha256 -q $BSDINSTALL_DISTDIR/$dist`
+ awk -v checksum=$CK -v dist=$dist -v found=0 '{
+ if (dist == $1) {
+ found = 1
+ if (checksum == $2)
+ exit(0)
+ else
+ exit(2)
+ }
+ } END {if (!found) exit(1);}' $BSDINSTALL_DISTDIR/MANIFEST
+
+ CK_VALID=$?
+ if [ $CK_VALID -le 1 ]; then
+ if [ $CK_VALID -eq 0 ]; then
+ eval "status_$distname=2"
+ else
+ eval "status_$distname=6"
+ fi
+ percentage=$(echo $percentage + 100/`echo $DISTRIBUTIONS | wc -w` | bc)
+ else
+ eval "status_$distname=1"
+ case $(/bin/freebsd-version -u) in
+ *-ALPHA*|*-CURRENT|*-STABLE|*-PRERELEASE)
+ dialog --backtitle "FreeBSD Installer" --title "Error" \
+ --msgbox "The checksum for $dist does not match. It may have become corrupted, or it may be from a newer version of FreeBSD. Please check for a newer snapshot." 0 0
+ ;;
+ *)
+ dialog --backtitle "FreeBSD Installer" --title "Error" \
+ --msgbox "The checksum for $dist does not match. It may have become corrupted, and should be redownloaded." 0 0
+ ;;
+ esac
+ exit 1
+ fi
+done
+
+exit 0
diff --git a/contrib/bsddialog/bsdinstall/scripts/config b/contrib/bsddialog/bsdinstall/scripts/config
new file mode 100755
index 000000000000..a909c3faee63
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/config
@@ -0,0 +1,63 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2015 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$
+#
+############################################################ MAIN
+
+cat $BSDINSTALL_TMPETC/rc.conf.* >> $BSDINSTALL_TMPETC/rc.conf
+rm $BSDINSTALL_TMPETC/rc.conf.*
+
+cat $BSDINSTALL_CHROOT/etc/sysctl.conf $BSDINSTALL_TMPETC/sysctl.conf.* >> $BSDINSTALL_TMPETC/sysctl.conf
+rm $BSDINSTALL_TMPETC/sysctl.conf.*
+
+if [ -f $BSDINSTALL_TMPETC/ttys.hardening ]; then
+ cat $BSDINSTALL_TMPETC/ttys.hardening > $BSDINSTALL_TMPETC/ttys
+ rm $BSDINSTALL_TMPETC/ttys.hardening
+fi
+
+cp $BSDINSTALL_TMPETC/* $BSDINSTALL_CHROOT/etc
+
+cat $BSDINSTALL_TMPBOOT/loader.conf.* >> $BSDINSTALL_TMPBOOT/loader.conf
+rm $BSDINSTALL_TMPBOOT/loader.conf.*
+# The 'cryptodev_load' line is a workaround for arm64, which does not
+# automatically load cryptodev.ko with zfs.ko.
+df -t zfs $BSDINSTALL_CHROOT > /dev/null && echo "cryptodev_load=\"YES\"" >> $BSDINSTALL_TMPBOOT/loader.conf
+df -t zfs $BSDINSTALL_CHROOT > /dev/null && echo "zfs_load=\"YES\"" >> $BSDINSTALL_TMPBOOT/loader.conf
+
+cp $BSDINSTALL_TMPBOOT/* $BSDINSTALL_CHROOT/boot
+
+[ "${debugFile#+}" ] && cp "${debugFile#+}" $BSDINSTALL_CHROOT/var/log/
+
+# Set up other things from installed config
+chroot $BSDINSTALL_CHROOT /usr/bin/newaliases > /dev/null 2>&1
+
+exit 0
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/docsinstall b/contrib/bsddialog/bsdinstall/scripts/docsinstall
new file mode 100755
index 000000000000..ea6fcf49b029
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/docsinstall
@@ -0,0 +1,167 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Marc Fonvieille
+# Copyright (c) 2013-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/packages/packages.subr
+
+############################################################ CONFIGURATION
+
+#
+# List of languages to display (descriptions pulled from $msg_{lang}doc_desc)
+#
+: ${DOCSINSTALL_LANGS:=\
+ bn da de el en es fr hu it ja ko mn nl pl pt ru tr zh_cn zh_tw \
+}
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER"
+msg_bndoc_desc="Bengali Documentation"
+msg_cancel="Cancel"
+msg_dadoc_desc="Danish Documentation"
+msg_dedoc_desc="German Documentation"
+msg_docsinstall_menu_text="This menu allows you to install the whole documentation set from\nthe FreeBSD Documentation Project: Handbook, FAQ, and articles.\n\nPlease select the language versions you wish to install. At\nminimum, you should install the English version, the original\nversion of the documentation."
+msg_eldoc_desc="Greek Documentation"
+msg_endoc_desc="English Documentation (recommended)"
+msg_esdoc_desc="Spanish Documentation"
+msg_frdoc_desc="French Documentation"
+msg_freebsd_documentation_installation="FreeBSD Documentation Installation"
+msg_freebsd_installer="FreeBSD Installer"
+msg_hudoc_desc="Hungarian Documentation"
+msg_itdoc_desc="Italian Documentation"
+msg_jadoc_desc="Japanese Documentation"
+msg_kodoc_desc="Korean Documentation"
+msg_mndoc_desc="Mongolian Documentation"
+msg_nldoc_desc="Dutch Documentation"
+msg_ok="OK"
+msg_pldoc_desc="Polish Documentation"
+msg_ptdoc_desc="Portuguese Documentation"
+msg_rudoc_desc="Russian Documentation"
+msg_trdoc_desc="Turkish Documentation"
+msg_zh_cndoc_desc="Simplified Chinese Documentation"
+msg_zh_twdoc_desc="Traditional Chinese Documentation"
+
+############################################################ 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_docsinstall_menu_text"
+ local check_list= # Calculated below
+ local hline="$hline_arrows_space_tab_enter"
+
+ local lang desc upper status
+ for lang in $DOCSINSTALL_LANGS; do
+ # Fetch the i18n description to display
+ f_getvar msg_${lang}doc_desc desc
+ f_shell_escape "$desc" desc
+
+ # Get default status for each language
+ upper=$( echo "$lang" | awk '{print toupper($0)}' )
+ case "$lang" in
+ en) f_getvar DIST_DOC_$upper:-on status ;;
+ *) f_getvar DIST_DOC_$upper:-off status
+ esac
+
+ check_list="$check_list
+ '$lang' '$desc' '$status'
+ " # END-QUOTE
+ done
+
+ local height width rows
+ eval f_dialog_checklist_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $check_list
+ local selected
+ #selected=$( eval $DIALOG \
+ selected=$( eval ../../bsddialog \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --separate-output \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --checklist \"\$prompt\" \
+ $height $width $rows \
+ $check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$selected"
+ return $retval
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_freebsd_documentation_installation"
+f_dialog_backtitle "$msg_freebsd_installer"
+f_mustberoot_init
+
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch selected
+
+# Let pkg_add be able to use name servers
+f_quietly cp -f $BSDINSTALL_TMPETC/resolv.conf $BSDINSTALL_CHROOT/etc/
+
+#
+# Install each of the selected packages
+#
+docsets=""
+for lang in $selected; do
+ docsets="$docsets $lang-freebsd-doc"
+done
+
+ASSUME_ALWAYS_YES=YES chroot $BSDINSTALL_CHROOT pkg install $docsets
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/entropy b/contrib/bsddialog/bsdinstall/scripts/entropy
new file mode 100755
index 000000000000..d3938f12cb33
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/entropy
@@ -0,0 +1,34 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 Dag-Erling Smørgrav
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+umask 077
+for i in /entropy /boot/entropy; do
+ i="$BSDINSTALL_CHROOT/$i"
+ dd if=/dev/random of="$i" bs=4096 count=1
+ chown 0:0 "$i"
+done
diff --git a/contrib/bsddialog/bsdinstall/scripts/fetchmissingdists b/contrib/bsddialog/bsdinstall/scripts/fetchmissingdists
new file mode 100644
index 000000000000..768217e2fb8c
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/fetchmissingdists
@@ -0,0 +1,132 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2018 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$
+#
+
+error()
+{
+ dialog --backtitle "FreeBSD Installer" --title "Error" --msgbox $1 0 0
+ exit 1
+}
+
+FETCH_DISTRIBUTIONS=""
+LOCAL_DISTRIBUTIONS=""
+for dist in $DISTRIBUTIONS; do
+ if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
+ FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
+ else
+ LOCAL_DISTRIBUTIONS="$LOCAL_DISTRIBUTIONS $dist"
+ fi
+done
+LOCAL_DISTRIBUTIONS=`echo $LOCAL_DISTRIBUTIONS` # Trim white space
+FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS` # Trim white space
+
+if [ -z "$FETCH_DISTRIBUTIONS" ]; then
+ echo $BSDINSTALL_DISTDIR >&2
+ exit 0
+fi
+
+ALL_DISTRIBUTIONS="$DISTRIBUTIONS"
+WANT_DEBUG=
+
+# Download to a directory in the new system as scratch space
+BSDINSTALL_FETCHDEST="$BSDINSTALL_CHROOT/usr/freebsd-dist"
+mkdir -p "$BSDINSTALL_FETCHDEST" || error "Could not create directory $BSDINSTALL_FETCHDEST"
+
+if [ -z "$BSDINSTALL_DISTSITE" ]; then
+ exec 3>&1
+ BSDINSTALL_DISTSITE=$(`dirname $0`/mirrorselect 2>&1 1>&3)
+ MIRROR_BUTTON=$?
+ exec 3>&-
+ test $MIRROR_BUTTON -eq 0 || error "No mirror selected"
+ export BSDINSTALL_DISTSITE
+fi
+
+BSDINSTALL_DISTDIR_ORIG="$BSDINSTALL_DISTDIR"
+export BSDINSTALL_DISTDIR="$BSDINSTALL_FETCHDEST"
+export FTP_PASSIVE_MODE=YES
+
+if [ -f "$BSDINSTALL_DISTDIR_ORIG/MANIFEST" ]; then
+ cp "$BSDINSTALL_DISTDIR_ORIG/MANIFEST" "$BSDINSTALL_DISTDIR/MANIFEST"
+ VERIFY_MANIFEST_SIG=0
+else
+ FETCH_DISTRIBUTIONS="MANIFEST $FETCH_DISTRIBUTIONS"
+ VERIFY_MANIFEST_SIG=1
+
+ # XXX actually verify signature on manifest
+ dialog --backtitle "FreeBSD Installer" --title "Warning" --msgbox "Manifest not found on local disk and will be fetched from an unverified source. This is a potential security risk. If you do not wish to proceed, press control-C now." 0 0
+fi
+
+if [ ! -z "$LOCAL_DISTRIBUTIONS" ]; then
+ # Copy local stuff first
+ env DISTRIBUTIONS="$LOCAL_DISTRIBUTIONS" \
+ BSDINSTALL_DISTSITE="file://$BSDINSTALL_DISTDIR" \
+ bsdinstall distfetch || \
+ error "Failed to fetch distribution from local media"
+fi
+
+export DISTRIBUTIONS="$FETCH_DISTRIBUTIONS"
+
+# Iterate through the distribution list and set a flag if debugging
+# distributions have been selected.
+for _DISTRIBUTION in $DISTRIBUTIONS; do
+ case $_DISTRIBUTION in
+ *-dbg.*)
+ [ -e $BSDINSTALL_DISTDIR/$_DISTRIBUTION ] \
+ && continue
+ WANT_DEBUG=1
+ DEBUG_LIST="\n$DEBUG_LIST\n$_DISTRIBUTION"
+ ;;
+ *)
+ ;;
+ esac
+done
+
+# Fetch the distributions.
+bsdinstall distfetch
+rc=$?
+
+if [ $rc -ne 0 ]; then
+ # If unable to fetch the remote distributions, recommend
+ # deselecting the debugging distributions, and retrying the
+ # installation, since failure to fetch *-dbg.txz should not
+ # be considered a fatal installation error.
+ msg="Failed to fetch remote distribution"
+ if [ ! -z "$WANT_DEBUG" ]; then
+ # Trim leading and trailing newlines.
+ DEBUG_LIST="${DEBUG_LIST%%\n}"
+ DEBUG_LIST="${DEBUG_LIST##\n}"
+ msg="$msg\n\nPlease deselect the following distributions"
+ msg="$msg and retry the installation:"
+ msg="$msg\n$DEBUG_LIST"
+ fi
+ error "$msg"
+fi
+
+echo $BSDINSTALL_DISTDIR >&2
+
diff --git a/contrib/bsddialog/bsdinstall/scripts/hardening b/contrib/bsddialog/bsdinstall/scripts/hardening
new file mode 100755
index 000000000000..952b56180ee2
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/hardening
@@ -0,0 +1,91 @@
+#!/bin/sh
+#-
+# Copyright (c) 2016 Bartek Rutkowski
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+: ${DIALOG_OK=0}
+
+echo -n > $BSDINSTALL_TMPETC/rc.conf.hardening
+echo -n > $BSDINSTALL_TMPETC/sysctl.conf.hardening
+echo -n > $BSDINSTALL_TMPBOOT/loader.conf.hardening
+
+exec 3>&1
+FEATURES=$( ../../bsddialog --backtitle "FreeBSD Installer" \
+ --title "System Hardening" --nocancel --separate-output \
+ --checklist "Choose system security hardening options:" \
+ 0 0 0 \
+ "0 hide_uids" "Hide processes running as other users" ${hide_uids:-off} \
+ "1 hide_gids" "Hide processes running as other groups" ${hide_gids:-off} \
+ "2 hide_jail" "Hide processes running in jails" ${hide_jail:-off} \
+ "3 read_msgbuf" "Disable reading kernel message buffer for unprivileged users" ${read_msgbuf:-off} \
+ "4 proc_debug" "Disable process debugging facilities for unprivileged users" ${proc_debug:-off} \
+ "5 random_pid" "Randomize the PID of newly created processes" ${random_pid:-off} \
+ "6 clear_tmp" "Clean the /tmp filesystem on system startup" ${clear_tmp:-off} \
+ "7 disable_syslogd" "Disable opening Syslogd network socket (disables remote logging)" ${disable_syslogd:-off} \
+ "8 disable_sendmail" "Disable Sendmail service" ${disable_sendmail:-off} \
+ "9 secure_console" "Enable console password prompt" ${secure_console:-off} \
+ "10 disable_ddtrace" "Disallow DTrace destructive-mode" ${disable_ddtrace:-off} \
+2>&1 1>&3 )
+exec 3>&-
+
+for feature in $FEATURES; do
+ case "$feature" in
+ hide_uids)
+ echo security.bsd.see_other_uids=0 >> $BSDINSTALL_TMPETC/sysctl.conf.hardening
+ ;;
+ hide_gids)
+ echo security.bsd.see_other_gids=0 >> $BSDINSTALL_TMPETC/sysctl.conf.hardening
+ ;;
+ hide_jail)
+ echo security.bsd.see_jail_proc=0 >> $BSDINSTALL_TMPETC/sysctl.conf.hardening
+ ;;
+ read_msgbuf)
+ echo security.bsd.unprivileged_read_msgbuf=0 >> $BSDINSTALL_TMPETC/sysctl.conf.hardening
+ ;;
+ proc_debug)
+ echo security.bsd.unprivileged_proc_debug=0 >> $BSDINSTALL_TMPETC/sysctl.conf.hardening
+ ;;
+ random_pid)
+ echo kern.randompid=1 >> $BSDINSTALL_TMPETC/sysctl.conf.hardening
+ ;;
+ clear_tmp)
+ echo 'clear_tmp_enable="YES"' >> $BSDINSTALL_TMPETC/rc.conf.hardening
+ ;;
+ disable_syslogd)
+ echo 'syslogd_flags="-ss"' >> $BSDINSTALL_TMPETC/rc.conf.hardening
+ ;;
+ disable_sendmail)
+ echo 'sendmail_enable="NONE"' >> $BSDINSTALL_TMPETC/rc.conf.hardening
+ ;;
+ secure_console)
+ sed "s/unknown off secure/unknown off insecure/g" $BSDINSTALL_CHROOT/etc/ttys > $BSDINSTALL_TMPETC/ttys.hardening
+ ;;
+ disable_ddtrace)
+ echo 'security.bsd.allow_destructive_dtrace=0' >> $BSDINSTALL_TMPBOOT/loader.conf.hardening
+ ;;
+ esac
+done
+
diff --git a/contrib/bsddialog/bsdinstall/scripts/hostname b/contrib/bsddialog/bsdinstall/scripts/hostname
new file mode 100755
index 000000000000..23620ab91571
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/hostname
@@ -0,0 +1,126 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2015-2018 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading_includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default value
+#
+: ${HOSTNAME=$( hostname )}
+
+#
+# Default file to store hostname entry in
+#
+: ${HOSTNAMEFILE:=$BSDINSTALL_TMPETC/rc.conf.hostname}
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+msg_freebsd_installer="FreeBSD Installer"
+msg_ok="OK"
+msg_please_choose_a_hostname="Please choose a hostname for this machine.\n\nIf you are running on a managed network, please ask\nyour network administrator for an appropriate name."
+msg_set_hostname="Set Hostname"
+
+#
+# Command strings for various tasks
+#
+ECHO_OVERWRITE='echo "%s" > "%s"'
+SET_HOSTNAME='hostname -s "%s"'
+
+############################################################ FUNCTIONS
+
+# dialog_hostname
+#
+# Display input box (without cancel button) for user to enter desired hostname.
+#
+dialog_hostname()
+{
+ local prompt="$msg_please_choose_a_hostname"
+ local hline=
+ local value="$*"
+
+ local height width
+ f_dialog_inputbox_size height width \
+ "$DIALOG_TITLE" "$DIALOG_BACKTITLE" "$prompt" "$value" "$hline"
+
+ #$DIALOG \
+ ../../bsddialog \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --no-cancel \
+ --inputbox "$prompt" \
+ $height $width "$value" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_set_hostname"
+f_dialog_backtitle "$msg_freebsd_installer"
+
+#
+# Get user input
+#
+HOSTNAME=$( dialog_hostname "$HOSTNAME" )
+[ $? -eq $DIALOG_CANCEL ] && exit 1
+
+#
+# Store the user's choice
+#
+f_eval_catch "$pgm" echo "$ECHO_OVERWRITE" \
+ 'hostname=\"$HOSTNAME\"' "$HOSTNAMEFILE"
+retval=$?
+
+#
+# Activate entry if configured
+#
+if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+ f_eval_catch "$pgm" hostname "$SET_HOSTNAME" "$HOSTNAME"
+ retval=$?
+fi
+
+exit $retval
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/jail b/contrib/bsddialog/bsdinstall/scripts/jail
new file mode 100755
index 000000000000..d3a84f872fb6
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/jail
@@ -0,0 +1,159 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ MAIN
+
+f_dprintf "Began Installation at %s" "$( date )"
+export BSDINSTALL_CHROOT=$1
+
+error() {
+ local msg
+ if [ -n "$1" ]; then
+ msg="$1\n\n"
+ fi
+ dialog --backtitle "FreeBSD Installer" --title "Abort" \
+ --no-label "Exit" --yes-label "Restart" --yesno \
+ "${msg}An installation step has been aborted. Would you like to restart the installation or exit the installer?" 0 0
+ if [ $? -ne 0 ]; then
+ exit
+ else
+ exec $0 $BSDINSTALL_CHROOT
+ fi
+}
+
+rm -rf $BSDINSTALL_TMPETC
+mkdir $BSDINSTALL_TMPETC
+mkdir -p $1 || error "mkdir failed for $1"
+
+if [ -n "$SCRIPT" ]
+then
+ split -a 2 -p '^#!.*' "$SCRIPT" $TMPDIR/bsdinstall-installscript-
+ . $TMPDIR/bsdinstall-installscript-aa
+fi
+
+test ! -d $BSDINSTALL_DISTDIR && mkdir -p $BSDINSTALL_DISTDIR
+
+if [ ! -f $BSDINSTALL_DISTDIR/MANIFEST -a -z "$BSDINSTALL_DISTSITE" ]; then
+ exec 3>&1
+ BSDINSTALL_DISTSITE=$(`dirname $0`/mirrorselect 2>&1 1>&3)
+ MIRROR_BUTTON=$?
+ exec 3>&-
+ test $MIRROR_BUTTON -eq 0 || error "No mirror selected"
+ export BSDINSTALL_DISTSITE
+ fetch -o $BSDINSTALL_DISTDIR/MANIFEST $BSDINSTALL_DISTSITE/MANIFEST || error "Could not download $BSDINSTALL_DISTSITE/MANIFEST"
+fi
+
+: ${DISTRIBUTIONS="base.txz"}; export DISTRIBUTIONS
+if [ -f $BSDINSTALL_DISTDIR/MANIFEST ]; then
+ DISTMENU=`cut -f 4,5,6 $BSDINSTALL_DISTDIR/MANIFEST | grep -v -e ^kernel -e ^base`
+
+ if [ ! "$nonInteractive" == "YES" ]
+ then
+ exec 3>&1
+ EXTRA_DISTS=$(echo $DISTMENU | xargs dialog \
+ --backtitle "FreeBSD Installer" \
+ --title "Distribution Select" --nocancel --separate-output \
+ --checklist "Choose optional system components to install:" \
+ 0 0 0 \
+ 2>&1 1>&3)
+ for dist in $EXTRA_DISTS; do
+ export DISTRIBUTIONS="$DISTRIBUTIONS $dist.txz"
+ done
+ fi
+fi
+
+FETCH_DISTRIBUTIONS=""
+for dist in $DISTRIBUTIONS; do
+ if [ ! -f $BSDINSTALL_DISTDIR/$dist ]; then
+ FETCH_DISTRIBUTIONS="$FETCH_DISTRIBUTIONS $dist"
+ fi
+done
+FETCH_DISTRIBUTIONS=`echo $FETCH_DISTRIBUTIONS` # Trim white space
+
+if [ -n "$FETCH_DISTRIBUTIONS" -a -z "$BSDINSTALL_DISTSITE" ]; then
+ exec 3>&1
+ BSDINSTALL_DISTSITE=$(`dirname $0`/mirrorselect 2>&1 1>&3)
+ MIRROR_BUTTON=$?
+ exec 3>&-
+ test $MIRROR_BUTTON -eq 0 || error "No mirror selected"
+ export BSDINSTALL_DISTSITE
+fi
+
+if [ ! -z "$FETCH_DISTRIBUTIONS" ]; then
+ bsdinstall distfetch || error "Failed to fetch distribution"
+fi
+
+bsdinstall checksum || error "Distribution checksum failed"
+bsdinstall distextract || error "Distribution extract failed"
+
+if [ ! "$nonInteractive" == "YES" ]
+then
+ bsdinstall rootpass || error "Could not set root password"
+fi
+
+trap true SIGINT # This section is optional
+
+if [ ! "$nonInteractive" == "YES" ]
+then
+bsdinstall services
+
+ dialog --backtitle "FreeBSD Installer" --title "Add User Accounts" --yesno \
+ "Would you like to add users to the installed system now?" 0 0 && \
+ bsdinstall adduser
+fi
+
+trap error SIGINT # SIGINT is bad again
+bsdinstall config || error "Failed to save config"
+cp /etc/resolv.conf $1/etc
+cp /etc/localtime $1/etc
+cp /var/db/zoneinfo $1/var/db
+
+# Run post-install script
+if [ -f $TMPDIR/bsdinstall-installscript-ab ]; then
+ cp $TMPDIR/bsdinstall-installscript-ab $BSDINSTALL_CHROOT/tmp/installscript
+ chmod a+x $BSDINSTALL_CHROOT/tmp/installscript
+ mount -t devfs devfs "$BSDINSTALL_CHROOT/dev"
+ chroot $BSDINSTALL_CHROOT /tmp/installscript $@ 2>&1
+ umount "$BSDINSTALL_CHROOT/dev"
+ rm $BSDINSTALL_CHROOT/tmp/installscript
+fi
+
+bsdinstall entropy
+
+f_dprintf "Installation Completed at %s" "$(date)"
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/keymap b/contrib/bsddialog/bsdinstall/scripts/keymap
new file mode 100755
index 000000000000..739d0223c4f4
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/keymap
@@ -0,0 +1,233 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/keymap.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default file to store keymap selection in
+#
+: ${KEYMAPFILE:=$BSDINSTALL_TMPETC/rc.conf.keymap}
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_continue_with_keymap="Continue with %s keymap"
+msg_default="default"
+msg_error="Error"
+msg_freebsd_installer="FreeBSD Installer"
+msg_keymap_menu_text="The system console driver for FreeBSD defaults to standard \"US\"\nkeyboard map. Other keymaps can be chosen below."
+msg_keymap_selection="Keymap Selection"
+msg_ok="OK"
+msg_select="Select"
+msg_test_keymap="Test %s keymap"
+msg_test_the_currently_selected_keymap="Test the currently selected keymap"
+msg_test_the_keymap_by_typing="Test the keymap by typing letters, numbers, and symbols. Characters\nshould match labels on the keyboard keys. Press Enter to stop testing."
+
+############################################################ FUNCTIONS
+
+# dialog_keymap_test $keymap
+#
+# Activate $keymap and display an input box (without cancel button) for the
+# user to test keyboard input and return. Always returns success.
+#
+dialog_keymap_test()
+{
+ local keym="$1"
+ local title= # Calculated below
+ local btitle= # Calculated below
+ local prompt="$msg_test_the_keymap_by_typing"
+ local hline=
+
+ # Attempt to activate the keymap
+ if [ "$keym" ]; then
+ local err
+ err=$( f_keymap_kbdcontrol "$keym" 2>&1 > /dev/null )
+ if [ "$err" ]; then
+ f_dialog_title "$msg_error"
+ f_dialog_msgbox "$err"
+ f_dialog_title_restore
+ return $FAILURE
+ fi
+ fi
+
+ f_dialog_title "$( printf "$msg_test_keymap" "${keym:-$msg_default}" )"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+
+ local height width
+ f_dialog_inputbox_size height width \
+ "$title" "$btitle" "$prompt" "" "$hline"
+
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --no-cancel \
+ --inputbox "$prompt" \
+ $height $width \
+ 2>/dev/null >&$DIALOG_TERMINAL_PASSTHRU_FD
+
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_keymap_selection"
+f_dialog_backtitle "$msg_freebsd_installer"
+
+#
+# Die immediately if we can't dump the current keyboard map
+#
+#error=$( kbdcontrol -d 2>&1 > /dev/null ) || f_die $FAILURE "%s" "$error"
+
+# Capture Ctrl-C for clean-up
+trap 'rm -f $KEYMAPFILE; exit $FAILURE' SIGINT
+
+# Get a value from rc.conf(5) as initial value (if not being scripted)
+f_getvar $VAR_KEYMAP keymap
+if [ ! "$keymap" ]; then
+ keymap=$( f_sysrc_get keymap )
+ case "$keymap" in [Nn][Oo]) keymap="";; esac
+fi
+
+#
+# Loop until the user has finalized their selection (by clicking the
+# [relabeled] Cancel button).
+#
+width=67 first_pass=1 back_from_testing=
+[ "$USE_XDIALOG" ] && width=70
+prompt="$msg_keymap_menu_text"
+hline="$hline_arrows_tab_enter"
+while :; do
+ #
+ # Re/Build list of keymaps
+ #
+ cont_msg=$( printf "$msg_continue_with_keymap" \
+ "${keymap:-$msg_default}" )
+ test_msg=$( printf "$msg_test_keymap" "${keymap:-$msg_default}" )
+ menu_list="
+ '>>> $cont_msg' '' '$msg_continue_with_current_keymap'
+ '->- $test_msg' '' '$msg_test_the_currently_selected_keymap'
+ " # END-QUOTE
+ if [ "$first_pass" ]; then
+ defaultitem=
+ first_pass=
+ else
+ defaultitem="->- $test_msg"
+ fi
+ for k in $KEYMAPS; do
+ keymap_$k get keym keym
+ keymap_$k get desc desc
+ radio=" "
+ if [ "$keym" = "$keymap" ]; then
+ radio="*"
+ if [ "$back_from_testing" ]; then
+ defaultitem="(*) $desc"
+ back_from_testing=
+ fi
+ fi
+ f_shell_escape "$desc" desc
+ menu_list="$menu_list
+ '($radio) $desc' '' '$keym: $desc'
+ " # END-QUOTE
+ done
+ back_from_testing=
+
+ #
+ # Display keymap configuration menu
+ #
+ eval f_dialog_menu_with_help_size height \"\" rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --keep-tite \
+ --item-help \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || {
+ f_quietly rm -f "$KEYMAPFILE"
+ exit $FAILURE # Exit with an error so bsdinstall restarts
+ }
+ f_dialog_data_sanitize menu_choice
+
+ case "$menu_choice" in
+ ">>> "*) # Continue with keymap
+ break ;;
+ "->-"*) # Test keymap
+ dialog_keymap_test "$keymap"
+ back_from_testing=1
+ continue ;;
+ esac
+
+ # Turn the user's choice into a number
+ n=$( eval f_dialog_menutag2index_with_help \
+ \"\$menu_choice\" $menu_list )
+
+ # Turn that number ithe name of the keymap struct
+ k=$( set -- $KEYMAPS; eval echo \"\${$(( $n - 2))}\" )
+
+ # Get actual keymap setting while we update $keymap and $KEYMAPFILE
+ keymap_$k get keym keymap
+ echo "keymap=\"$keymap\"" > "$KEYMAPFILE"
+done
+
+f_quietly f_keymap_kbdcontrol "$keymap"
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/mirrorselect b/contrib/bsddialog/bsdinstall/scripts/mirrorselect
new file mode 100755
index 000000000000..67ef5f2c02a6
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/mirrorselect
@@ -0,0 +1,179 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+: ${DIALOG_OK=0}
+: ${DIALOG_CANCEL=1}
+: ${DIALOG_HELP=2}
+: ${DIALOG_EXTRA=3}
+: ${DIALOG_ITEM_HELP=4}
+: ${DIALOG_ESC=255}
+
+exec 3>&1
+MIRROR=`../../bsddialog --backtitle "FreeBSD Installer" \
+ --title "Mirror Selection" --extra-button --extra-label "Other" \
+ --menu "Please select the site closest to you or \"other\" if you'd like to specify a different choice. Also note that not every site listed here carries more than the base distribution kits. Only Primary sites are guaranteed to carry the full range of possible distributions. Select a site that's close!" \
+ 0 0 0 \
+ ftp://ftp.freebsd.org "Main Site"\
+ ftp://ftp.freebsd.org "IPv6 Main Site"\
+ ftp://ftp3.ie.freebsd.org "IPv6 Ireland"\
+ ftp://ftp2.jp.freebsd.org "IPv6 Japan"\
+ ftp://ftp4.se.freebsd.org "IPv6 Sweden"\
+ ftp://ftp4.us.freebsd.org "IPv6 USA"\
+ ftp://ftp1.freebsd.org "Primary"\
+ ftp://ftp2.freebsd.org "Primary #2"\
+ ftp://ftp3.freebsd.org "Primary #3"\
+ ftp://ftp4.freebsd.org "Primary #4"\
+ ftp://ftp5.freebsd.org "Primary #5"\
+ ftp://ftp6.freebsd.org "Primary #6"\
+ ftp://ftp7.freebsd.org "Primary #7"\
+ ftp://ftp10.freebsd.org "Primary #10"\
+ ftp://ftp11.freebsd.org "Primary #11"\
+ ftp://ftp12.freebsd.org "Primary #12"\
+ ftp://ftp13.freebsd.org "Primary #13"\
+ ftp://ftp14.freebsd.org "Primary #14"\
+ ftp://ftp.au.freebsd.org "Australia"\
+ ftp://ftp2.au.freebsd.org "Australia #2"\
+ ftp://ftp3.au.freebsd.org "Australia #3"\
+ ftp://ftp.at.freebsd.org "Austria"\
+ ftp://ftp2.br.freebsd.org "Brazil #2"\
+ ftp://ftp3.br.freebsd.org "Brazil #3"\
+ ftp://ftp4.br.freebsd.org "Brazil #4"\
+ ftp://ftp.bg.freebsd.org "Bulgaria"\
+ ftp://ftp.cn.freebsd.org "China"\
+ ftp://ftp.cz.freebsd.org "Czech Republic"\
+ ftp://ftp.dk.freebsd.org "Denmark"\
+ ftp://ftp.fi.freebsd.org "Finland"\
+ ftp://ftp.fr.freebsd.org "France"\
+ ftp://ftp3.fr.freebsd.org "France #3"\
+ ftp://ftp4.fr.freebsd.org "IPv6 France #4"\
+ ftp://ftp5.fr.freebsd.org "France #5"\
+ ftp://ftp6.fr.freebsd.org "France #6"\
+ ftp://ftp7.fr.freebsd.org "France #7"\
+ ftp://ftp8.fr.freebsd.org "IPv6 France #8"\
+ ftp://ftp.de.freebsd.org "Germany"\
+ ftp://ftp2.de.freebsd.org "Germany #2"\
+ ftp://ftp4.de.freebsd.org "Germany #4"\
+ ftp://ftp5.de.freebsd.org "Germany #5"\
+ ftp://ftp7.de.freebsd.org "Germany #7"\
+ ftp://ftp8.de.freebsd.org "Germany #8"\
+ ftp://ftp.gr.freebsd.org "Greece"\
+ ftp://ftp2.gr.freebsd.org "Greece #2"\
+ ftp://ftp3.ie.freebsd.org "Ireland #3"\
+ ftp://ftp.jp.freebsd.org "Japan"\
+ ftp://ftp2.jp.freebsd.org "Japan #2"\
+ ftp://ftp3.jp.freebsd.org "Japan #3"\
+ ftp://ftp4.jp.freebsd.org "Japan #4"\
+ ftp://ftp5.jp.freebsd.org "Japan #5"\
+ ftp://ftp6.jp.freebsd.org "Japan #6"\
+ ftp://ftp7.jp.freebsd.org "Japan #7"\
+ ftp://ftp8.jp.freebsd.org "Japan #8"\
+ ftp://ftp9.jp.freebsd.org "Japan #9"\
+ ftp://ftp.kr.freebsd.org "Korea"\
+ ftp://ftp2.kr.freebsd.org "Korea #2"\
+ ftp://ftp.lv.freebsd.org "Latvia"\
+ ftp://ftp.nl.freebsd.org "Netherlands"\
+ ftp://ftp2.nl.freebsd.org "Netherlands #2"\
+ ftp://ftp.nz.freebsd.org "New Zealand"\
+ ftp://ftp.no.freebsd.org "Norway"\
+ ftp://ftp.pl.freebsd.org "Poland"\
+ ftp://ftp.ru.freebsd.org "Russia"\
+ ftp://ftp2.ru.freebsd.org "Russia #2"\
+ ftp://ftp5.ru.freebsd.org "Russia #5"\
+ ftp://ftp6.ru.freebsd.org "Russia #6"\
+ ftp://ftp.sk.freebsd.org "Slovak Republic"\
+ ftp://ftp2.sk.freebsd.org "Slovak Republic #2"\
+ ftp://ftp.si.freebsd.org "Slovenia"\
+ ftp://ftp.za.freebsd.org "South Africa"\
+ ftp://ftp2.za.freebsd.org "South Africa #2"\
+ ftp://ftp4.za.freebsd.org "South Africa #4"\
+ ftp://ftp.se.freebsd.org "Sweden"\
+ ftp://ftp4.se.freebsd.org "Sweden #4"\
+ ftp://ftp.ch.freebsd.org "Switzerland"\
+ ftp://ftp.tw.freebsd.org "Taiwan"\
+ ftp://ftp2.tw.freebsd.org "Taiwan #2"\
+ ftp://ftp3.tw.freebsd.org "Taiwan #3"\
+ ftp://ftp4.tw.freebsd.org "Taiwan #4"\
+ ftp://ftp6.tw.freebsd.org "Taiwan #6"\
+ ftp://ftp11.tw.freebsd.org "Taiwan #11"\
+ ftp://ftp.uk.freebsd.org "UK"\
+ ftp://ftp2.uk.freebsd.org "UK #2"\
+ ftp://ftp3.uk.freebsd.org "UK #3"\
+ ftp://ftp4.uk.freebsd.org "UK #4"\
+ ftp://ftp5.uk.freebsd.org "UK #5"\
+ ftp://ftp.ua.freebsd.org "Ukraine"\
+ ftp://ftp1.us.freebsd.org "USA #1"\
+ ftp://ftp2.us.freebsd.org "USA #2"\
+ ftp://ftp3.us.freebsd.org "USA #3"\
+ ftp://ftp4.us.freebsd.org "USA #4"\
+ ftp://ftp5.us.freebsd.org "USA #5"\
+ ftp://ftp6.us.freebsd.org "USA #6"\
+ ftp://ftp8.us.freebsd.org "USA #8"\
+ ftp://ftp10.us.freebsd.org "USA #10"\
+ ftp://ftp11.us.freebsd.org "USA #11"\
+ ftp://ftp13.us.freebsd.org "USA #13"\
+ ftp://ftp14.us.freebsd.org "USA #14"\
+ ftp://ftp15.us.freebsd.org "USA #15"\
+ 2>&1 1>&3`
+MIRROR_BUTTON=$?
+exec 3>&-
+
+_UNAME_R=`uname -r`
+_UNAME_R=${_UNAME_R%-p*}
+
+case ${_UNAME_R} in
+ *-ALPHA*|*-CURRENT|*-STABLE|*-PRERELEASE)
+ RELDIR="snapshots"
+ ;;
+ *)
+ RELDIR="releases"
+ ;;
+esac
+
+BSDINSTALL_DISTSITE="$MIRROR/pub/FreeBSD/${RELDIR}/`uname -m`/`uname -p`/${_UNAME_R}"
+
+case $MIRROR_BUTTON in
+$DIALOG_CANCEL)
+ exit 1
+ ;;
+$DIALOG_OK)
+ ;;
+$DIALOG_EXTRA)
+ exec 3>&1
+ BSDINSTALL_DISTSITE=`../../bsddialog --backtitle "FreeBSD Installer" \
+ --title "Mirror Selection" \
+ --inputbox "Please enter the URL to an alternate FreeBSD mirror:" \
+ 0 30 "$BSDINSTALL_DISTSITE" 2>&1 1>&3`
+ #0 0 "$BSDINSTALL_DISTSITE" 2>&1 1>&3` known bug: inputbox cols autosize
+ MIRROR_BUTTON=$?
+ exec 3>&-
+ test $MIRROR_BUTTON -eq 0 || exec $0 $@
+ ;;
+esac
+
+export BSDINSTALL_DISTSITE
+echo $BSDINSTALL_DISTSITE >&2
diff --git a/contrib/bsddialog/bsdinstall/scripts/mount b/contrib/bsddialog/bsdinstall/scripts/mount
new file mode 100755
index 000000000000..c7bc1aa5387d
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/mount
@@ -0,0 +1,55 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+TMP_FSTAB=${TMPDIR:-"/tmp"}/bsdinstall-tmp-fstab
+
+cat $PATH_FSTAB | awk -v BSDINSTALL_CHROOT=$BSDINSTALL_CHROOT '{
+ if ($2 ~ "^/.*") {
+ fsname = $2;
+ if (fsname == "/")
+ fsname = ""
+ printf("%s\t%s%s\t%s\t%s\t%s\t%s\n", $1, BSDINSTALL_CHROOT,
+ fsname, $3, $4, $5, $6);
+ }
+}' > $TMP_FSTAB
+
+FILESYSTEMS=`cat $TMP_FSTAB | awk '/^[^#].*/ {if ($2 ~ "^/.*") printf("%s\n", $2);}' | sort -t /`
+
+for i in $FILESYSTEMS; do
+ mkdir -p $i 2>/dev/null
+ MNTERROR=`mount -F $TMP_FSTAB $i 2>&1`
+ if [ $? -ne 0 ]; then
+ dialog --backtitle "FreeBSD Installer" --title "Error" \
+ --msgbox "Error mounting partition $i:\n$MNTERROR" 0 0
+ exit 1
+ fi
+done
+
+# User might want a shell and require devfs, so mount it
+mkdir $BSDINSTALL_CHROOT/dev 2>/dev/null
+mount -t devfs devfs $BSDINSTALL_CHROOT/dev
diff --git a/contrib/bsddialog/bsdinstall/scripts/netconfig b/contrib/bsddialog/bsdinstall/scripts/netconfig
new file mode 100755
index 000000000000..f9913c324228
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/netconfig
@@ -0,0 +1,217 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+# Copyright (c) 2011 The FreeBSD Foundation
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+INTERFACES=""
+DIALOG_TAGS=""
+
+: ${DIALOG_OK=0}
+: ${DIALOG_CANCEL=1}
+: ${DIALOG_HELP=2}
+: ${DIALOG_EXTRA=3}
+: ${DIALOG_ITEM_HELP=4}
+: ${DIALOG_ESC=255}
+
+for IF in `ifconfig -l`; do
+ test "$IF" = "lo0" && continue
+ (ifconfig -g wlan | egrep -wq $IF) && continue
+ INTERFACES="$INTERFACES $IF"
+done
+
+INTERFACES="$INTERFACES $(sysctl -in net.wlan.devices)"
+is_wireless_if() {
+ for IF in $(sysctl -in net.wlan.devices); do
+ if [ $IF = $1 ]; then
+ return 0
+ fi
+ done
+ return 1
+}
+
+for IF in $INTERFACES; do
+ DESC=`sysctl -n dev.$(echo $IF | sed -E 's/([[:alpha:]]*)([[:digit:]]*)/\1.\2/g').%desc`
+ DIALOG_TAGS="$DIALOG_TAGS $IF \"$DESC\""
+done
+
+if [ -z "$INTERFACES" ]; then
+ dialog --backtitle 'FreeBSD Installer' \
+ --title 'Network Configuration Error' \
+ --msgbox 'No network interfaces present to configure.' 0 0
+ exit 1
+fi
+
+exec 3>&1
+INTERFACE=`echo $DIALOG_TAGS | xargs dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --menu 'Please select a network interface to configure:' 0 0 0 2>&1 1>&3`
+if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
+exec 3>&-
+
+: > $BSDINSTALL_TMPETC/._rc.conf.net
+
+IFCONFIG_PREFIX=""
+if is_wireless_if $INTERFACE; then
+ NEXT_WLAN_IFACE=wlan0 # XXX
+ echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+ IFCONFIG_PREFIX="WPA "
+ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ ifconfig $NEXT_WLAN_IFACE create wlandev $INTERFACE
+ ifconfig $NEXT_WLAN_IFACE up
+ fi
+ bsdinstall wlanconfig $NEXT_WLAN_IFACE || exec $0
+ INTERFACE="$NEXT_WLAN_IFACE"
+fi
+
+IPV6_AVAIL=0
+IPV4_AVAIL=0
+sysctl -N kern.features.inet6 > /dev/null 2>&1
+case $? in
+0) IPV6_AVAIL=1 ;;
+esac
+sysctl -N kern.features.inet > /dev/null 2>&1
+case $? in
+0) IPV4_AVAIL=1 ;;
+esac
+
+if [ ${IPV4_AVAIL} -eq 1 ]; then
+ dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --yesno 'Would you like to configure IPv4 for this interface?' 0 0
+ if [ $? -eq $DIALOG_OK ]; then
+ bsdinstall netconfig_ipv4 ${INTERFACE} "${IFCONFIG_PREFIX}" || \
+ exec $0
+ else
+ IPV4_AVAIL=0
+ fi
+fi
+# In case wlanconfig left an option and we do not support IPv4 we need to write
+# it out on its own. We cannot write it out with IPv6 as that suffix.
+if [ ${IPV4_AVAIL} -eq 0 -a -n ${IFCONFIG_PREFIX} ]; then
+ echo ifconfig_${INTERFACE}=\"${IFCONFIG_PREFIX}\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+fi
+if [ ${IPV6_AVAIL} -eq 1 ]; then
+ dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --yesno 'Would you like to configure IPv6 for this interface?' 0 0
+ if [ $? -eq $DIALOG_OK ]; then
+ bsdinstall netconfig_ipv6 ${INTERFACE} || exec $0
+ else
+ IPV6_AVAIL=0
+ fi
+fi
+
+SEARCH=""
+IP4_1=""
+IP4_2=""
+IP6_1=""
+IP6_2=""
+while read key value; do
+ case "${key}" in
+ search) SEARCH="${value}" ;;
+ nameserver) # is more trick as we have to distinguish v4 and v6
+ case "${value}" in
+ [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)
+ if [ -z "${IP4_1}" ] ; then
+ IP4_1="${value}"
+ elif [ -z "${IP4_2}" ]; then
+ IP4_2="${value}"
+ fi
+ ;;
+ [0-9A-Fa-f:]*:*)
+ if [ -z "${IP6_1}" ] ; then
+ IP6_1="${value}"
+ elif [ -z "${IP6_2}" ]; then
+ IP6_2="${value}"
+ fi
+ ;;
+ esac
+ ;;
+ # ignore others
+ esac
+done < ${BSDINSTALL_TMPETC}/resolv.conf
+
+RESOLV=""
+if [ ${IPV6_AVAIL} -eq 1 -a ${IPV4_AVAIL} -eq 1 ]; then
+ RESOLV="
+ 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0
+ 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2
+ 'IPv6 DNS #1' 2 0 \"${IP6_1}\" 2 16 50 0 0
+ 'IPv6 DNS #2' 3 0 \"${IP6_2}\" 3 16 50 0 0
+ 'IPv4 DNS #1' 4 0 \"${IP4_1}\" 4 16 16 0 0
+ 'IPv4 DNS #2' 5 0 \"${IP4_2}\" 5 16 16 0 0"
+elif [ ${IPV6_AVAIL} -eq 1 ]; then
+ RESOLV="
+ 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0
+ 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2
+ 'IPv6 DNS #1' 2 0 \"${IP6_1}\" 2 16 50 0 0
+ 'IPv6 DNS #2' 3 0 \"${IP6_2}\" 3 16 50 0 0"
+elif [ ${IPV4_AVAIL} -eq 1 ]; then
+ RESOLV="
+ 'Search' 1 0 \"${SEARCH}\" 1 16 50 0 0
+ 'Nameserver' 2 0 \"Nameserver\" 2 16 50 0 2
+ 'IPv4 DNS #1' 2 0 \"${IP4_1}\" 2 16 16 0 0
+ 'IPv4 DNS #2' 3 0 \"${IP4_2}\" 3 16 16 0 0"
+else
+ exit 0
+fi
+
+exec 3>&1
+RESOLV=$(echo "${RESOLV}" | xargs dialog --backtitle 'FreeBSD Installer' \
+ --title 'Network Configuration' \
+ --mixedform 'Resolver Configuration' 0 0 0 \
+2>&1 1>&3)
+if [ $? -eq $DIALOG_CANCEL ]; then exec $0; fi
+exec 3>&-
+
+echo ${RESOLV} | tr ' ' '\n' | \
+awk '
+BEGIN {
+ search=-1;
+}
+{
+ if (/^[[:space:]]+$/) {
+ next;
+ }
+ if (/^Nameserver$/) {
+ printf "\n";
+ search=0;
+ next;
+ }
+ if (search == -1) {
+ printf "search ";
+ search=1;
+ }
+ if (search > 0) {
+ printf "%s%s", (search > 1) ? " " : "", $1;
+ search++;
+ next;
+ }
+ printf "nameserver %s\n", $1;
+}' > ${BSDINSTALL_TMPETC}/resolv.conf
+
+mv $BSDINSTALL_TMPETC/._rc.conf.net $BSDINSTALL_TMPETC/rc.conf.net
diff --git a/contrib/bsddialog/bsdinstall/scripts/netconfig_ipv4 b/contrib/bsddialog/bsdinstall/scripts/netconfig_ipv4
new file mode 100755
index 000000000000..2acd9029d150
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/netconfig_ipv4
@@ -0,0 +1,103 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+
+############################################################ MAIN
+
+INTERFACE=$1
+IFCONFIG_PREFIX="$2"
+test -z "$IFCONFIG_PREFIX" || IFCONFIG_PREFIX="$2 "
+case "${INTERFACE}" in
+"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --msgbox 'No interface specified for IPv4 configuration.' 0 0
+ exit 1
+ ;;
+esac
+
+dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --yesno 'Would you like to use DHCP to configure this interface?' 0 0
+if [ $? -eq $DIALOG_OK ]; then
+ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ ifconfig $INTERFACE up
+ dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0
+ err=$( pkill -F /var/run/dhclient/dhclient.${INTERFACE}.pid; dhclient $INTERFACE 2>&1 )
+ if [ $? -ne 0 ]; then
+ f_dprintf "%s" "$err"
+ dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0
+ exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}"
+ fi
+ fi
+ echo ifconfig_$INTERFACE=\"${IFCONFIG_PREFIX}DHCP\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+ exit 0
+fi
+
+IP_ADDRESS=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $2); }'`
+NETMASK=`ifconfig $INTERFACE inet | awk '/inet/ {printf("%s\n", $4); }'`
+ROUTER=`netstat -rn -f inet | awk '/default/ {printf("%s\n", $2);}'`
+
+exec 3>&1
+IF_CONFIG=$(dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' --form 'Static Network Interface Configuration' 0 0 0 \
+ 'IP Address' 1 0 "$IP_ADDRESS" 1 20 16 0 \
+ 'Subnet Mask' 2 0 "$NETMASK" 2 20 16 0 \
+ 'Default Router' 3 0 "$ROUTER" 3 20 16 0 \
+2>&1 1>&3)
+if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
+exec 3>&-
+
+echo $INTERFACE $IF_CONFIG |
+ awk -v prefix="$IFCONFIG_PREFIX" '{
+ printf("ifconfig_%s=\"%s\inet %s netmask %s\"\n", $1, prefix, $2, $3);
+ printf("defaultrouter=\"%s\"\n", $4);
+ }' >> $BSDINSTALL_TMPETC/._rc.conf.net
+retval=$?
+
+if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+ . $BSDINSTALL_TMPETC/._rc.conf.net
+ if [ -n "$2" ]; then
+ ifconfig $INTERFACE `eval echo \\\$ifconfig_$INTERFACE | sed "s|$2||"`
+ else
+ ifconfig $INTERFACE `eval echo \\\$ifconfig_$INTERFACE`
+ fi
+ if [ "$defaultrouter" ]; then
+ route delete -inet default
+ route add -inet default $defaultrouter
+ retval=$?
+ fi
+fi
+
+exit $retval
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/netconfig_ipv6 b/contrib/bsddialog/bsdinstall/scripts/netconfig_ipv6
new file mode 100755
index 000000000000..abc53906f4ad
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/netconfig_ipv6
@@ -0,0 +1,160 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2011 The FreeBSD Foundation
+# Copyright (c) 2013-2015 Devin Teske
+# All rights reserved.
+#
+# Portions of this software were developed by Bjoern Zeeb
+# under sponsorship from the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+
+############################################################ MAIN
+
+#
+# TODO:
+# - Add DHCPv6 support once FreeBSD ships with it.
+#
+
+INTERFACE=$1
+case "${INTERFACE}" in
+"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --msgbox 'No interface specified for IPv6 configuration.' 0 0
+ exit 1
+ ;;
+esac
+
+AGAIN=""
+while : ; do
+ MSG="Would you like to try stateless address autoconfiguration (SLAAC)${AGAIN}?"
+ dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
+ --yesno "${MSG}" 0 0
+ if [ $? -eq $DIALOG_OK ]; then
+ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
+ dialog --backtitle 'FreeBSD Installer' \
+ --infobox "Sending Router Solicitation ..." 0 0
+ ifconfig ${INTERFACE} inet6 -ifdisabled accept_rtadv up
+ err=$( rtsol -F $INTERFACE 2>&1 )
+ if [ $? -ne 0 ]; then
+ f_dprintf "%s" "$err"
+ dialog --backtitle 'FreeBSD Installer' --msgbox "SLAAC failed." 0 0
+ AGAIN=" again"
+ continue
+ fi
+ fi
+ echo ifconfig_${INTERFACE}_ipv6=\"inet6 accept_rtadv\" >> $BSDINSTALL_TMPETC/._rc.conf.net
+ exit 0
+ else
+ break
+ fi
+done
+
+ROUTER6=`netstat -Wrn -f inet6 | awk '/default/ {printf("%s\n", $2);}'`
+ADDRS=`ifconfig ${INTERFACE} inet6 | \
+awk -v dfr="${ROUTER6}" '
+BEGIN {
+ n=0;
+}
+{
+ if (/inet6/) {
+ if (match($2, "^fe80:")) { next; };
+ # For the moment ignore all but the first address; it might confuse the user.
+ if (n > 0) { next; };
+ n++;
+ printf "\"IPv6 Address\" %d 0 \"%s/%s\" %d 16 50 0 0 ", n, $2, $4, n;
+ }
+}
+END {
+ if (n == 0) {
+ n++;
+ printf "\"IPv6 Address\" %d 0 \"\" %d 16 50 0 0 ", n, n;
+ }
+ n++;
+ # Nasty trick adding a (hidden, same y) read-only field as a marker
+ # to separate interface address(es) from the default router.
+ printf "\"Default Router\" %d 0 \"%s\" %d 16 50 0 2 ", n, "DefaultRouter", n;
+ printf "\"Default Router\" %d 0 \"%s\" %d 16 50 0 0 ", n, dfr, n;
+}'`
+
+exec 3>&1
+IF_CONFIG=$(echo ${ADDRS} | xargs dialog --backtitle 'FreeBSD Installer' \
+ --title 'Network Configuration' \
+ --mixedform 'Static IPv6 Network Interface Configuration' 0 0 0 \
+2>&1 1>&3)
+if [ $? -eq $DIALOG_CANCEL ]; then exit 1; fi
+exec 3>&-
+
+echo ${IF_CONFIG} | tr ' ' '\n' | \
+awk -v iface="${INTERFACE}" '
+BEGIN {
+ dfr=0;
+ count=0;
+}
+{
+ if (/^[[:space:]]+$/) {
+ next;
+ }
+ if (/DefaultRouter/) {
+ dfr=1;
+ next;
+ }
+ if (dfr == 1) {
+ printf("ipv6_defaultrouter=\"%s\"\n", $1);
+ next;
+ }
+ if (count > 0) {
+ # Ignore all but the first IP address for now.
+ next;
+ }
+ count++;
+ if (!match($1, "/")) {
+ sub("$", "/64", $1);
+ }
+ printf("ifconfig_%s_ipv6=\"inet6 %s\"\n", iface, $1);
+}' >> $BSDINSTALL_TMPETC/._rc.conf.net
+retval=$?
+
+if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+ . $BSDINSTALL_TMPETC/._rc.conf.net
+ ifconfig ${INTERFACE} `eval echo \\\$ifconfig_${INTERFACE}_ipv6`
+ if [ "$ipv6_defaultrouter" ]; then
+ route delete -inet6 default
+ route add -inet6 default ${ipv6_defaultrouter}
+ retval=$?
+ fi
+fi
+
+exit $retval
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/rootpass b/contrib/bsddialog/bsdinstall/scripts/rootpass
new file mode 100755
index 000000000000..7764a51b62fb
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/rootpass
@@ -0,0 +1,37 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+clear
+echo "FreeBSD Installer"
+echo "========================"
+echo
+
+echo "Please select a password for the system management account (root):"
+echo "Typed characters will not be visible."
+
+chroot $BSDINSTALL_CHROOT passwd root 2>&1
diff --git a/contrib/bsddialog/bsdinstall/scripts/script b/contrib/bsddialog/bsdinstall/scripts/script
new file mode 100755
index 000000000000..8d9dd5205132
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/script
@@ -0,0 +1,182 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 Nathan Whitehorn
+# Copyright (c) 2013-2015 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+############################################################ CONFIGURATION
+
+# VARIABLES:
+# PARTITIONS
+# DISTRIBUTIONS
+# BSDINSTALL_DISTDIR
+
+#
+# Default name of the ZFS boot-pool
+#
+: ${ZFSBOOT_POOL_NAME:=zroot}
+
+############################################################ GLOBALS
+
+: ${TMPDIR:="/tmp"}
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+msg_installation_error="Installation Error!"
+
+############################################################ FUNCTIONS
+
+error()
+{
+ local file
+ f_getvar "$VAR_DEBUG_FILE#+" file
+ if [ "$file" ]; then
+ f_dialog_title "$msg_installation_error"
+ f_dialog_textbox "$file"
+ # No need to restore title, pining for the fjords
+ fi
+
+ [ -f "$PATH_FSTAB" ] || exit
+ if [ "$ZFSBOOT_DISKS" ]; then
+ zpool export $ZFSBOOT_POOL_NAME
+ else
+ bsdinstall umount
+ fi
+
+ exit 1
+}
+
+############################################################ MAIN
+
+set -e
+trap error EXIT
+
+SCRIPT="$1"
+shift
+
+f_dprintf "Began Installation at %s" "$( date )"
+rm -rf $BSDINSTALL_TMPETC
+mkdir $BSDINSTALL_TMPETC
+
+split -a 2 -p '^#!.*' "$SCRIPT" $TMPDIR/bsdinstall-installscript-
+
+. $TMPDIR/bsdinstall-installscript-aa
+: ${DISTRIBUTIONS="kernel.txz base.txz"}; export DISTRIBUTIONS
+export BSDINSTALL_DISTDIR
+
+# Re-initialize a new log if preamble changed BSDINSTALL_LOG
+if [ "$BSDINSTALL_LOG" != "${debugFile#+}" ]; then
+ export debugFile="$BSDINSTALL_LOG"
+ f_quietly f_debug_init
+ # NB: Being scripted, let debug go to terminal for invalid debugFile
+ f_dprintf "Began Installation at %s" "$( date )"
+fi
+
+# Make partitions
+rm -f $PATH_FSTAB
+touch $PATH_FSTAB
+if [ "$ZFSBOOT_DISKS" ]; then
+ bsdinstall zfsboot
+else
+ bsdinstall scriptedpart "$PARTITIONS"
+fi
+bsdinstall mount
+
+# Fetch missing distribution files, if any
+exec 3>&1
+export BSDINSTALL_DISTDIR=$(`dirname $0`/fetchmissingdists 2>&1 1>&3)
+FETCH_RESULT=$?
+exec 3>&-
+
+[ $FETCH_RESULT -ne 0 ] && error "Could not fetch remote distributions"
+
+# Unpack distributions
+bsdinstall checksum
+if [ -t 0 ]; then
+ # If install is a tty, use distextract as normal
+ bsdinstall distextract
+else
+ # Otherwise, we need to use tar (see https://reviews.freebsd.org/D10736)
+ for set in $DISTRIBUTIONS; do
+ f_dprintf "Extracting $BSDINSTALL_DISTDIR/$set"
+ # XXX: The below fails if any mountpoints are FAT, due to
+ # inability to set ctime/mtime on the root of FAT partitions,
+ # which is needed to support e.g. EFI system partitions. tar has
+ # no option to ignore this (distextract ignores them internally
+ # through a hack), and returns 1 on any warning or error,
+ # effectively turning all warnings into fatal errors.
+ #
+ # Work around this in an extremely lame way for the specific
+ # case of EFI system partitions only. This *ONLY WORKS* if
+ # /boot/efi is empty and does not handle analagous problems on
+ # other systems (ARM, PPC64).
+ tar -xf "$BSDINSTALL_DISTDIR/$set" -C $BSDINSTALL_CHROOT --exclude boot/efi
+ mkdir -p $BSDINSTALL_CHROOT/boot/efi
+ done
+fi
+
+# Configure bootloader if needed
+bsdinstall bootconfig
+
+# Finalize install
+bsdinstall config
+
+# Make sure networking is functional, if we can arrange that
+if [ ! -f $BSDINSTALL_CHROOT/etc/resolv.conf -a -f /etc/resolv.conf ]; then
+ cp /etc/resolv.conf $BSDINSTALL_CHROOT/etc/resolv.conf
+fi
+
+# Run post-install script
+if [ -f $TMPDIR/bsdinstall-installscript-ab ]; then
+ cp $TMPDIR/bsdinstall-installscript-ab $BSDINSTALL_CHROOT/tmp/installscript
+ chmod a+x $BSDINSTALL_CHROOT/tmp/installscript
+ chroot $BSDINSTALL_CHROOT /tmp/installscript $@ 2>&1
+ rm $BSDINSTALL_CHROOT/tmp/installscript
+fi
+
+bsdinstall entropy
+if [ "$ZFSBOOT_DISKS" ]; then
+ zpool export $ZFSBOOT_POOL_NAME
+fi
+bsdinstall umount
+
+f_dprintf "Installation Completed at %s" "$( date )"
+
+trap - EXIT
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/services b/contrib/bsddialog/bsdinstall/scripts/services
new file mode 100755
index 000000000000..c59628b2a88c
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/services
@@ -0,0 +1,70 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+: ${DIALOG_OK=0}
+
+if [ -f $BSDINSTALL_TMPETC/rc.conf.services ]; then
+ eval $( sed -e s/YES/on/i -e s/NO/off/i \
+ $BSDINSTALL_TMPETC/rc.conf.services )
+else
+ # Default service states. Everything is off if not enabled.
+ sshd_enable="on"
+fi
+
+echo -n > $BSDINSTALL_TMPETC/rc.conf.services
+
+exec 3>&1
+DAEMONS=$( dialog --backtitle "FreeBSD Installer" \
+ --title "System Configuration" --nocancel --separate-output \
+ --checklist "Choose the services you would like to be started at boot:" \
+ 0 0 0 \
+ local_unbound "Local caching validating resolver" ${local_unbound:-off} \
+ sshd "Secure shell daemon" ${sshd_enable:-off} \
+ moused "PS/2 mouse pointer on console" ${moused_enable:-off} \
+ ntpdate "Synchronize system and network time at bootime" \
+ ${ntpdate_enable:-off} \
+ ntpd "Synchronize system and network time" ${ntpd_enable:-off} \
+ powerd "Adjust CPU frequency dynamically if supported" \
+ ${powerd_enable:-off} \
+ dumpdev "Enable kernel crash dumps to /var/crash" ${dumpdev:-on} \
+2>&1 1>&3 )
+exec 3>&-
+
+havedump=
+for daemon in $DAEMONS; do
+ [ "$daemon" = "dumpdev" ] && havedump=1 continue
+ echo ${daemon}_enable=\"YES\" >> $BSDINSTALL_TMPETC/rc.conf.services
+done
+
+echo '# Set dumpdev to "AUTO" to enable crash dumps, "NO"' \
+ 'to disable' >> $BSDINSTALL_TMPETC/rc.conf.services
+if [ "$havedump" ]; then
+ echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services
+else
+ echo dumpdev=\"NO\" >> $BSDINSTALL_TMPETC/rc.conf.services
+fi
diff --git a/contrib/bsddialog/bsdinstall/scripts/time b/contrib/bsddialog/bsdinstall/scripts/time
new file mode 100755
index 000000000000..0e6b32adc6b1
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/time
@@ -0,0 +1,67 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+# Select timezone
+chroot $BSDINSTALL_CHROOT tzsetup
+
+# Switch to target timezone
+saved_TZ="$TZ"
+TZ="${BSDINSTALL_CHROOT}/etc/localtime"
+export TZ
+
+# Set date
+exec 3>&1
+DATE=$(../../bsddialog --backtitle 'FreeBSD Installer' \
+ --title 'Time & Date' \
+ --ok-label 'Set Date' \
+ --cancel-label 'Skip' \
+ --defaultno \
+ --date-format '%Y%m%d%H%M.%S' \
+ --datebox '' 0 40 \
+2>&1 1>&3) && date $DATE
+exec 3>&-
+
+# Set time
+exec 3>&1
+TIME=$(../../bsddialog --backtitle 'FreeBSD Installer' \
+ --title 'Time & Date' \
+ --ok-label 'Set Time' \
+ --cancel-label 'Skip' \
+ --defaultno \
+ --time-format '%H%M.%S' \
+ --timebox '' 0 40 \
+2>&1 1>&3) && date $TIME
+exec 3>&-
+
+# Switch back
+if [ -n "$saved_TZ" ]; then
+ TZ="$saved_TZ"
+else
+ unset TZ
+fi
+unset saved_TZ
diff --git a/contrib/bsddialog/bsdinstall/scripts/umount b/contrib/bsddialog/bsdinstall/scripts/umount
new file mode 100755
index 000000000000..3c33eff7e105
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/umount
@@ -0,0 +1,44 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (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$
+
+TMP_FSTAB=${TMPDIR:-"/tmp"}/bsdinstall-tmp-fstab
+
+cat $PATH_FSTAB | awk -v BSDINSTALL_CHROOT=$BSDINSTALL_CHROOT '{
+ if ($2 ~ "^/.*") {
+ fsname = $2;
+ if (fsname == "/")
+ fsname = ""
+ printf("%s\t%s%s\t%s\t%s\t%s\t%s\n", $1, BSDINSTALL_CHROOT,
+ fsname, $3, $4, $5, $6);
+ }
+}' > $TMP_FSTAB
+
+umount $BSDINSTALL_CHROOT/dev 2>/dev/null
+if [ -n "$TMP_FSTAB" ]; then
+ umount -F $TMP_FSTAB -a 2>/dev/null
+fi
diff --git a/contrib/bsddialog/bsdinstall/scripts/wlanconfig b/contrib/bsddialog/bsdinstall/scripts/wlanconfig
new file mode 100755
index 000000000000..c2234831be9d
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/wlanconfig
@@ -0,0 +1,365 @@
+#!/bin/sh
+#-
+# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013-2020 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_include $BSDCFG_SHARE/dialog.subr
+f_dialog_backtitle "FreeBSD Installer"
+
+############################################################ FUNCTIONS
+
+country_set()
+{
+ local error_str iface_up ifconfig_args=
+
+ #
+ # Setup what was selected
+ # NB: Do not change order of arguments (or regdomain will be ignored)
+ #
+ [ "$2" ] && ifconfig_args="$ifconfig_args country $2"
+ [ "$1" ] && ifconfig_args="$ifconfig_args regdomain $1"
+ [ "$ifconfig_args" ] || return $SUCCESS # Nothing to do
+ ifconfig_args="${ifconfig_args# }"
+
+ # Regdomain/country cannot be applied while interface is running
+ iface_up=$( ifconfig -lu | grep -w "$WLAN_IFACE" )
+ [ "$iface_up" ] && ifconfig "$WLAN_IFACE" down
+ f_eval_catch -dk error_str wlanconfig ifconfig "ifconfig %s %s" \
+ "$WLAN_IFACE" "$ifconfig_args"
+ error_str="${error_str#ifconfig: }"
+ # Restart wpa_supplicant(8) (should not fail).
+ [ "$iface_up" ] && f_eval_catch -d wlanconfig wpa_supplicant \
+ 'wpa_supplicant -B -i "%s" -c "%s/wpa_supplicant.conf"' \
+ "$WLAN_IFACE" "$BSDINSTALL_TMPETC"
+ if [ "$error_str" ]; then
+ $DIALOG --title "$msg_error" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --yes-label Change \
+ --no-label Ignore \
+ --yesno \
+ "Error while applying chosen settings ($error_str)" \
+ 0 0 || return $SUCCESS # Skip
+ return $FAILURE # Restart
+ else
+ cat > "$BSDINSTALL_TMPETC/rc.conf.net.wlan" <<-EOF
+ create_args_$WLAN_IFACE="$ifconfig_args"
+ EOF
+ fi
+
+ return $SUCCESS
+}
+
+dialog_country_select()
+{
+ local input regdomains countries regdomain country prompt
+ local no_default="<not selected>"
+ local default_regdomain="${1:-$no_default}"
+ local default_country="${2:-$no_default}"
+
+ #
+ # Parse available countries/regdomains
+ #
+ input=$( ifconfig "$WLAN_IFACE" list countries | sed -e 's/DEBUG//gi' )
+ regdomains=$( echo "$input" | awk '
+ sub(/.*domains:/, ""), /[^[:alnum:][[:space:]]/ {
+ n = split($0, domains)
+ for (i = 1; i <= n; i++)
+ printf "'\''%s'\'' '\'\''", domains[i]
+ }
+ ' | sort )
+ countries=$( echo "$input" | awk '
+ sub(/Country codes:/, ""), sub(/Regulatory.*/, "") {
+ while (match($0, /[[:upper:]][[:upper:][:digit:]] /)) {
+ country = substr($0, RSTART)
+ sub(/ [[:upper:]][[:upper:][:digit:]].*/, "",
+ country)
+ code = substr(country, 1, 2)
+ desc = substr(country, 4)
+ sub(/[[:space:]]*$/, "", desc)
+ printf "'\''%s'\'' '\''%s'\''\n", code, desc
+ $0 = substr($0, RSTART + RLENGTH)
+ }
+ }
+ ' | sort )
+
+ f_dialog_title "Regdomain selection"
+ prompt="Select your regdomain."
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \"\" $regdomains
+ regdomain=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --cancel-label \"\$msg_skip\" \
+ --default-item \"\$default_regdomain\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $regdomains \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ f_dialog_data_sanitize regdomain
+
+ f_dialog_title "Country selection"
+ prompt="Select your country."
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \"\" $countries
+ country=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --cancel-label \"\$msg_skip\" \
+ --default-item \"\$default_country\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $countries \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ f_dialog_data_sanitize country
+
+ country_set "$regdomain" "$country"
+}
+
+############################################################ MAIN
+
+: > "$BSDINSTALL_TMPETC/wpa_supplicant.conf"
+chmod 0600 "$BSDINSTALL_TMPETC/wpa_supplicant.conf"
+
+cat >> "$BSDINSTALL_TMPETC/wpa_supplicant.conf" <<EOF
+ctrl_interface=/var/run/wpa_supplicant
+eapol_version=2
+ap_scan=1
+fast_reauth=1
+
+EOF
+
+#
+# Try to reach wpa_supplicant. If it isn't running and we can modify the
+# existing system, start it. Otherwise, fail.
+#
+if ! f_eval_catch -d wlanconfig wpa_cli "wpa_cli ping"; then
+ if [ ! "$BSDINSTALL_CONFIGCURRENT" ]; then
+ f_show_err "Wireless cannot be configured without %s" \
+ "making changes to the local system!"
+ exit 1
+ fi
+ f_eval_catch wlanconfig wpa_supplicant \
+ 'wpa_supplicant -B -i "%s" -c "%s/wpa_supplicant.conf"' \
+ "$1" "$BSDINSTALL_TMPETC" || exit 1
+
+ # See if we succeeded
+ f_eval_catch wlanconfig wpa_cli "wpa_cli ping" || exit 1
+fi
+
+#
+# There is no way to check country/regdomain without (possible)
+# interface state modification
+#
+if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+ # Get current country/regdomain for selected interface
+ WLAN_IFACE=$( wpa_cli ifname | tail -n 1 )
+ INPUT=$( ifconfig "$WLAN_IFACE" list regdomain | head -n 1 )
+ DEF_REGDOMAIN=$( echo "$INPUT" | cut -w -f 2 )
+ DEF_COUNTRY=$( echo "$INPUT" | cut -w -f 4 )
+ [ "$DEF_REGDOMAIN" = 0 ] && DEF_REGDOMAIN="<not selected>"
+ [ "$DEF_COUNTRY" = 0 ] && DEF_COUNTRY="<not selected>"
+ f_dialog_title "Regdomain/country"
+ if f_yesno "Change regdomain/country ($DEF_REGDOMAIN/$DEF_COUNTRY)?"
+ then
+ while ! dialog_country_select "$DEF_REGDOMAIN" "$DEF_COUNTRY"
+ do :; done
+ fi
+fi
+
+while :; do
+ SCANSSID=0
+ f_eval_catch -d wlanconfig wpa_cli "wpa_cli scan"
+ f_dialog_title "Scanning"
+ f_dialog_pause "Waiting 5 seconds to scan for wireless networks..." 5 ||
+ exit 1
+
+ f_eval_catch -dk SCAN_RESULTS wlanconfig wpa_cli "wpa_cli scan_results"
+ NETWORKS=$( echo "$SCAN_RESULTS" | awk -F '\t' '
+ /..:..:..:..:..:../ && $5 { printf "\"%s\"\t\"%s\"\n", $5, $4 }
+ ' | sort | uniq )
+
+ if [ ! "$NETWORKS" ]; then
+ f_dialog_title "$msg_error"
+ f_yesno "No wireless networks were found. Rescan?" && continue
+ exit 1
+ fi
+
+ f_dialog_title "Network Selection"
+ prompt="Select a wireless network to connect to."
+ f_dialog_menu_size height width rows "$DIALOG_TITLE" \
+ "$DIALOG_BACKTITLE" "$prompt" "" $menu_list
+ NETWORK=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --extra-button \
+ --extra-label \"Rescan\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $NETWORKS \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ f_dialog_data_sanitize NETWORK
+ case $retval in
+ $DIALOG_OK) break ;;
+ $DIALOG_CANCEL)
+ # Ask if the user wants to select network manually
+ f_dialog_title "Network Selection"
+ f_yesno "Do you want to select the network manually?" || exit 1
+ f_dialog_input NETWORK "Enter SSID" || exit 1
+ prompt="Select encryption type"
+ menu_list="
+ '1 WPA/WPA2 PSK' ''
+ '2 WPA/WPA2 EAP' ''
+ '3 WEP' ''
+ '0 None' ''
+ " # END-QUOTE
+ eval f_dialog_menu_size height width rows \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \"\$prompt\" \"\" $menu_list
+ ENCRYPTION=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || exit 1
+ SCANSSID=1
+ break
+ ;;
+ $DIALOG_EXTRA) # Rescan
+ ;;
+ esac
+done
+
+[ "$ENCRYPTION" ] || ENCRYPTION=$( echo "$NETWORKS" |
+ awk -F '\t' "/^\"$NETWORK\"\t/ { print \$2 }" )
+
+if echo "$ENCRYPTION" | grep -q PSK; then
+ PASS=$( $DIALOG \
+ --title "WPA Setup" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --insecure \
+ --mixedform "" \
+ 0 0 0 \
+ "SSID" 1 0 "$NETWORK" 1 12 0 0 2 \
+ "Password" 2 0 "" 2 12 15 63 1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || exec "$0" "$@"
+ awk 'sub(/^\\/,"")||1' \
+ >> "$BSDINSTALL_TMPETC/wpa_supplicant.conf" <<-EOF
+ network={
+ \ ssid="$NETWORK"
+ \ scan_ssid=$SCANSSID
+ \ psk="$PASS"
+ \ priority=5
+ }
+ EOF
+elif echo "$ENCRYPTION" | grep -q EAP; then
+ USERPASS=$( $DIALOG \
+ --title "WPA-Enterprise Setup" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --insecure \
+ --mixedform "" \
+ 0 0 0 \
+ "SSID" 1 0 "$NETWORK" 1 12 0 0 2 \
+ "Username" 2 0 "" 2 12 25 63 0 \
+ "Password" 3 0 "" 3 12 25 63 1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || exec "$0" "$@"
+ awk 'sub(/^\\/,"")||1' \
+ >> "$BSDINSTALL_TMPETC/wpa_supplicant.conf" <<-EOF
+ network={
+ \ ssid="$NETWORK"
+ \ scan_ssid=$SCANSSID
+ \ key_mgmt=WPA-EAP$(
+ echo "$USERPASS" | awk '
+ NR == 1 { printf "\n\tidentity=\"%s\"", $1 }
+ NR == 2 { printf "\n\tpassword=\"%s\"", $1 }
+ ' )
+ \ priority=5
+ }
+ EOF
+elif echo "$ENCRYPTION" | grep -q WEP; then
+ WEPKEY=$( $DIALOG \
+ --title "WEP Setup" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --insecure \
+ --mixedform "" \
+ 0 0 0 \
+ "SSID" 1 0 "$NETWORK" 1 12 0 0 2 \
+ "WEP Key 0" 2 0 "" 2 12 15 0 1 \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || exec "$0" "$@"
+ awk 'sub(/^\\/,"")||1' \
+ >> "$BSDINSTALL_TMPETC/wpa_supplicant.conf" <<-EOF
+ network={
+ \ ssid="$NETWORK"
+ \ scan_ssid=$SCANSSID
+ \ key_mgmt=NONE
+ \ wep_key0="$WEPKEY"
+ \ wep_tx_keyidx=0
+ \ priority=5
+ }
+ EOF
+else # Open
+ awk 'sub(/^\\/,"")||1' \
+ >> "$BSDINSTALL_TMPETC/wpa_supplicant.conf" <<-EOF
+ network={
+ \ ssid="$NETWORK"
+ \ scan_ssid=$SCANSSID
+ \ key_mgmt=NONE
+ \ priority=5
+ }
+ EOF
+fi
+
+# Connect to any open networks policy
+cat >> "$BSDINSTALL_TMPETC/wpa_supplicant.conf" <<EOF
+network={
+ priority=0
+ key_mgmt=NONE
+}
+EOF
+
+# Bring up new network
+[ "$BSDINSTALL_CONFIGCURRENT" ] &&
+ f_eval_catch -d wlanconfig wpa_cli "wpa_cli reconfigure"
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/bsdinstall/scripts/zfsboot b/contrib/bsddialog/bsdinstall/scripts/zfsboot
new file mode 100755
index 000000000000..45c8b001c393
--- /dev/null
+++ b/contrib/bsddialog/bsdinstall/scripts/zfsboot
@@ -0,0 +1,1814 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013-2016 Allan Jude
+# Copyright (c) 2013-2018 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$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/password/password.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default name of the boot-pool
+#
+: ${ZFSBOOT_POOL_NAME:=zroot}
+
+#
+# Default pool size is optional
+#
+: ${ZFSBOOT_POOL_SIZE=}
+
+#
+# Default options to use when creating zroot pool
+#
+: ${ZFSBOOT_POOL_CREATE_OPTIONS:=-O compress=lz4 -O atime=off}
+
+#
+# Default name for the boot environment parent dataset
+#
+: ${ZFSBOOT_BEROOT_NAME:=ROOT}
+
+#
+# Default name for the primary boot environment
+#
+: ${ZFSBOOT_BOOTFS_NAME:=default}
+
+#
+# Default Virtual Device (vdev) type to create
+#
+: ${ZFSBOOT_VDEV_TYPE:=stripe}
+
+#
+# Should we use sysctl(8) vfs.zfs.min_auto_ashift=12 to force 4K sectors?
+#
+: ${ZFSBOOT_FORCE_4K_SECTORS:=1}
+
+#
+# Should we use geli(8) to encrypt the drives?
+# NB: Automatically enables ZFSBOOT_BOOT_POOL
+#
+: ${ZFSBOOT_GELI_ENCRYPTION=}
+
+#
+# Default path to the geli(8) keyfile used in drive encryption
+#
+: ${ZFSBOOT_GELI_KEY_FILE:=/boot/encryption.key}
+
+#
+# Create a separate boot pool?
+# NB: Automatically set when using geli(8) or MBR
+#
+: ${ZFSBOOT_BOOT_POOL=}
+
+#
+# Options to use when creating separate boot pool (if any)
+#
+: ${ZFSBOOT_BOOT_POOL_CREATE_OPTIONS:=}
+
+#
+# Default name for boot pool when enabled (e.g., geli(8) or MBR)
+#
+: ${ZFSBOOT_BOOT_POOL_NAME:=bootpool}
+
+#
+# Default size for boot pool when enabled (e.g., geli(8) or MBR)
+#
+: ${ZFSBOOT_BOOT_POOL_SIZE:=2g}
+
+#
+# Default disks to use (always empty unless being scripted)
+#
+: ${ZFSBOOT_DISKS:=}
+
+#
+# Default partitioning scheme to use on disks
+#
+: ${ZFSBOOT_PARTITION_SCHEME:=}
+
+#
+# Default boot type to use on disks
+#
+: ${ZFSBOOT_BOOT_TYPE:=}
+
+#
+# How much swap to put on each block device in the boot zpool
+# NOTE: Value passed to gpart(8); which supports SI unit suffixes.
+#
+: ${ZFSBOOT_SWAP_SIZE:=2g}
+
+#
+# Should we use geli(8) to encrypt the swap?
+#
+: ${ZFSBOOT_SWAP_ENCRYPTION=}
+
+#
+# Should we use gmirror(8) to mirror the swap?
+#
+: ${ZFSBOOT_SWAP_MIRROR=}
+
+#
+# Default ZFS datasets for root zpool
+#
+# NOTE: Requires /tmp, /var/tmp, /$ZFSBOOT_BOOTFS_NAME/$ZFSBOOT_BOOTFS_NAME
+# NOTE: Anything after pound/hash character [#] is ignored as a comment.
+#
+f_isset ZFSBOOT_DATASETS || ZFSBOOT_DATASETS="
+ # DATASET OPTIONS (comma or space separated; or both)
+
+ # Boot Environment [BE] root and default boot dataset
+ /$ZFSBOOT_BEROOT_NAME mountpoint=none
+ /$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME mountpoint=/
+
+ # Compress /tmp, allow exec but not setuid
+ /tmp mountpoint=/tmp,exec=on,setuid=off
+
+ # Don't mount /usr so that 'base' files go to the BEROOT
+ /usr mountpoint=/usr,canmount=off
+
+ # Home directories separated so they are common to all BEs
+ /usr/home # NB: /home is a symlink to /usr/home
+
+ # Ports tree
+ /usr/ports setuid=off
+
+ # Source tree (compressed)
+ /usr/src
+
+ # Create /var and friends
+ /var mountpoint=/var,canmount=off
+ /var/audit exec=off,setuid=off
+ /var/crash exec=off,setuid=off
+ /var/log exec=off,setuid=off
+ /var/mail atime=on
+ /var/tmp setuid=off
+" # END-QUOTE
+
+#
+# If interactive and the user has not explicitly chosen a vdev type or disks,
+# make the user confirm scripted/default choices when proceeding to install.
+#
+: ${ZFSBOOT_CONFIRM_LAYOUT:=1}
+
+############################################################ GLOBALS
+
+#
+# Format of a line in printf(1) syntax to add to fstab(5)
+#
+FSTAB_FMT="%s\t\t%s\t%s\t%s\t\t%s\t%s\n"
+
+#
+# Command strings for various tasks
+#
+COPY='cp "%s" "%s"'
+CHMOD_MODE='chmod %s "%s"'
+DD_WITH_OPTIONS='dd if="%s" of="%s" %s'
+ECHO_APPEND='echo "%s" >> "%s"'
+ECHO_OVERWRITE='echo "%s" > "%s"'
+GELI_ATTACH='geli attach -j - -k "%s" "%s"'
+GELI_ATTACH_NOKEY='geli attach -j - "%s"'
+GELI_DETACH_F='geli detach -f "%s"'
+GELI_PASSWORD_INIT='geli init -b -B "%s" -e %s -J - -K "%s" -l 256 -s 4096 "%s"'
+GELI_PASSWORD_GELIBOOT_INIT='geli init -bg -e %s -J - -l 256 -s 4096 "%s"'
+GPART_ADD_ALIGN='gpart add %s -t %s "%s"'
+GPART_ADD_ALIGN_INDEX='gpart add %s -i %s -t %s "%s"'
+GPART_ADD_ALIGN_INDEX_WITH_SIZE='gpart add %s -i %s -t %s -s %s "%s"'
+GPART_ADD_ALIGN_LABEL='gpart add %s -l %s -t %s "%s"'
+GPART_ADD_ALIGN_LABEL_WITH_SIZE='gpart add %s -l %s -t %s -s %s "%s"'
+GPART_BOOTCODE='gpart bootcode -b "%s" "%s"'
+GPART_BOOTCODE_PART='gpart bootcode -b "%s" -p "%s" -i %s "%s"'
+GPART_BOOTCODE_PARTONLY='gpart bootcode -p "%s" -i %s "%s"'
+GPART_CREATE='gpart create -s %s "%s"'
+GPART_DESTROY_F='gpart destroy -F "%s"'
+GPART_SET_ACTIVE='gpart set -a active -i %s "%s"'
+GPART_SET_LENOVOFIX='gpart set -a lenovofix "%s"'
+GPART_SET_PMBR_ACTIVE='gpart set -a active "%s"'
+GRAID_DELETE='graid delete "%s"'
+KLDLOAD='kldload %s'
+LN_SF='ln -sf "%s" "%s"'
+MKDIR_P='mkdir -p "%s"'
+MOUNT_TYPE='mount -t %s "%s" "%s"'
+NEWFS_ESP='newfs_msdos "%s"'
+PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\""
+PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"'
+SHELL_TRUNCATE=':> "%s"'
+SWAP_GMIRROR_LABEL='gmirror label swap %s'
+SYSCTL_ZFS_MIN_ASHIFT_12='sysctl vfs.zfs.min_auto_ashift=12'
+UMOUNT='umount "%s"'
+ZFS_CREATE_WITH_OPTIONS='zfs create %s "%s"'
+ZFS_MOUNT='zfs mount "%s"'
+ZFS_SET='zfs set "%s" "%s"'
+ZFS_UNMOUNT='zfs unmount "%s"'
+ZPOOL_CREATE_WITH_OPTIONS='zpool create %s "%s" %s %s'
+ZPOOL_DESTROY='zpool destroy "%s"'
+ZPOOL_EXPORT='zpool export "%s"'
+ZPOOL_EXPORT_F='zpool export -f "%s"'
+ZPOOL_IMPORT_WITH_OPTIONS='zpool import %s "%s"'
+ZPOOL_LABELCLEAR_F='zpool labelclear -f "%s"'
+ZPOOL_SET='zpool set %s "%s"'
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER"
+hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_an_unknown_error_occurred="An unknown error occurred"
+msg_back="Back"
+msg_cancel="Cancel"
+msg_change_selection="Change Selection"
+msg_configure_options="Configure Options:"
+msg_detailed_disk_info="gpart(8) show %s:\n%s\n\ncamcontrol(8) inquiry %s:\n%s\n\n\ncamcontrol(8) identify %s:\n%s\n"
+msg_disk_info="Disk Info"
+msg_disk_info_help="Get detailed information on disk device(s)"
+msg_disk_plural="disks"
+msg_disk_singular="disk"
+msg_encrypt_disks="Encrypt Disks?"
+msg_encrypt_disks_help="Use geli(8) to encrypt all data partitions"
+msg_error="Error"
+msg_force_4k_sectors="Force 4K Sectors?"
+msg_force_4k_sectors_help="Align partitions to 4K sector boundries and set vfs.zfs.min_auto_ashift=12"
+msg_freebsd_installer="FreeBSD Installer"
+msg_geli_password="Enter a strong passphrase, used to protect your encryption keys. You will be required to enter this passphrase each time the system is booted"
+msg_geli_setup="Initializing encryption on selected disks,\n this will take several seconds per disk"
+msg_install="Install"
+msg_install_desc="Proceed with Installation"
+msg_install_help="Create ZFS boot pool with displayed options"
+msg_invalid_boot_pool_size="Invalid boot pool size \`%s'"
+msg_invalid_disk_argument="Invalid disk argument \`%s'"
+msg_invalid_index_argument="Invalid index argument \`%s'"
+msg_invalid_pool_size="Invalid pool size \`%s'"
+msg_invalid_swap_size="Invalid swap size \`%s'"
+msg_invalid_virtual_device_type="Invalid Virtual Device type \`%s'"
+msg_last_chance_are_you_sure="Last Chance! Are you sure you want to destroy\nthe current contents of the following disks:\n\n %s"
+msg_last_chance_are_you_sure_color='\\ZrLast Chance!\\ZR Are you \\Z1sure\\Zn you want to \\Zr\\Z1destroy\\Zn\nthe current contents of the following disks:\n\n %s'
+msg_mirror_desc="Mirror - n-Way Mirroring"
+msg_mirror_help="[2+ Disks] Mirroring provides the best performance, but the least storage"
+msg_missing_disk_arguments="missing disk arguments"
+msg_missing_one_or_more_scripted_disks="Missing one or more scripted disks!"
+msg_no="NO"
+msg_no_disks_present_to_configure="No disk(s) present to configure"
+msg_no_disks_selected="No disks selected."
+msg_not_enough_disks_selected="Not enough disks selected. (%u < %u minimum)"
+msg_null_disk_argument="NULL disk argument"
+msg_null_index_argument="NULL index argument"
+msg_null_poolname="NULL poolname"
+msg_odd_disk_selected="An even number of disks must be selected to create a RAID 1+0. (%u selected)"
+msg_ok="OK"
+msg_partition_scheme="Partition Scheme"
+msg_partition_scheme_help="Select partitioning scheme. GPT is recommended."
+msg_please_enter_a_name_for_your_zpool="Please enter a name for your zpool:"
+msg_please_enter_amount_of_swap_space="Please enter amount of swap space (SI-Unit suffixes\nrecommended; e.g., \`2g' for 2 Gigabytes):"
+msg_please_select_one_or_more_disks="Please select one or more disks to create a zpool:"
+msg_pool_name="Pool Name"
+msg_pool_name_cannot_be_empty="Pool name cannot be empty."
+msg_pool_name_help="Customize the name of the zpool to be created (Required)"
+msg_pool_type_disks="Pool Type/Disks:"
+msg_pool_type_disks_help="Choose type of ZFS Virtual Device and disks to use (Required)"
+msg_processing_selection="Processing selection..."
+msg_raid10_desc="RAID 1+0 - n x 2-Way Mirrors"
+msg_raid10_help="[4+ Disks] Striped Mirrors provides the best performance, but the least storage"
+msg_raidz1_desc="RAID-Z1 - Single Redundant RAID"
+msg_raidz1_help="[3+ Disks] Withstand failure of 1 disk. Recommended for: 3, 5 or 9 disks"
+msg_raidz2_desc="RAID-Z2 - Double Redundant RAID"
+msg_raidz2_help="[4+ Disks] Withstand failure of 2 disks. Recommended for: 4, 6 or 10 disks"
+msg_raidz3_desc="RAID-Z3 - Triple Redundant RAID"
+msg_raidz3_help="[5+ Disks] Withstand failure of 3 disks. Recommended for: 5, 7 or 11 disks"
+msg_rescan_devices="Rescan Devices"
+msg_rescan_devices_help="Scan for device changes"
+msg_select="Select"
+msg_select_a_disk_device="Select a disk device"
+msg_select_virtual_device_type="Select Virtual Device type:"
+msg_stripe_desc="Stripe - No Redundancy"
+msg_stripe_help="[1+ Disks] Striping provides maximum storage but no redundancy"
+msg_swap_encrypt="Encrypt Swap?"
+msg_swap_encrypt_help="Encrypt swap partitions with temporary keys, discarded on reboot"
+msg_swap_invalid="The selected swap size (%s) is invalid. Enter a number optionally followed by units. Example: 2G"
+msg_swap_mirror="Mirror Swap?"
+msg_swap_mirror_help="Mirror swap partitions for redundancy, breaks crash dumps"
+msg_swap_size="Swap Size"
+msg_swap_size_help="Customize how much swap space is allocated to each selected disk"
+msg_swap_toosmall="The selected swap size (%s) is to small. Please enter a value greater than 100MB or enter 0 for no swap"
+msg_these_disks_are_too_small="These disks are smaller than the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 100%% or more of each of the following selected disks:\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of disks."
+msg_unable_to_get_disk_capacity="Unable to get disk capacity of \`%s'"
+msg_unsupported_partition_scheme="%s is an unsupported partition scheme"
+msg_user_cancelled="User Cancelled."
+msg_yes="YES"
+msg_zfs_configuration="ZFS Configuration"
+
+############################################################ 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_configure_options"
+ local force4k="$msg_no"
+ local usegeli="$msg_no"
+ local swapgeli="$msg_no"
+ local swapmirror="$msg_no"
+ [ "$ZFSBOOT_FORCE_4K_SECTORS" ] && force4k="$msg_yes"
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] && usegeli="$msg_yes"
+ [ "$ZFSBOOT_SWAP_ENCRYPTION" ] && swapgeli="$msg_yes"
+ [ "$ZFSBOOT_SWAP_MIRROR" ] && swapmirror="$msg_yes"
+ local disks n disks_grammar
+ f_count n $ZFSBOOT_DISKS
+ { [ $n -eq 1 ] && disks_grammar=$msg_disk_singular; } ||
+ disks_grammar=$msg_disk_plural # grammar
+ local menu_list="
+ '>>> $msg_install' '$msg_install_desc'
+ '$msg_install_help'
+ 'T $msg_pool_type_disks'
+ '$ZFSBOOT_VDEV_TYPE: $n $disks_grammar'
+ '$msg_pool_type_disks_help'
+ '- $msg_rescan_devices' '*'
+ '$msg_rescan_devices_help'
+ '- $msg_disk_info' '*'
+ '$msg_disk_info_help'
+ 'N $msg_pool_name' '$ZFSBOOT_POOL_NAME'
+ '$msg_pool_name_help'
+ '4 $msg_force_4k_sectors'
+ '$force4k'
+ '$msg_force_4k_sectors_help'
+ 'E $msg_encrypt_disks' '$usegeli'
+ '$msg_encrypt_disks_help'
+ 'P $msg_partition_scheme'
+ '$ZFSBOOT_PARTITION_SCHEME ($ZFSBOOT_BOOT_TYPE)'
+ '$msg_partition_scheme_help'
+ 'S $msg_swap_size' '$ZFSBOOT_SWAP_SIZE'
+ '$msg_swap_size_help'
+ 'M $msg_swap_mirror' '$swapmirror'
+ '$msg_swap_mirror_help'
+ 'W $msg_swap_encrypt' '$swapgeli'
+ '$msg_swap_encrypt_help'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_with_help_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --item-help \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+# dialog_last_chance $disks ...
+#
+# Display a list of the disks that the user is about to destroy. The default
+# action is to return error status unless the user explicitly (non-default)
+# selects "Yes" from the noyes dialog.
+#
+dialog_last_chance()
+{
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height=8 width=50 prefix=" "
+ local plen=${#prefix} list= line=
+ local max_width=$(( $width - 3 - $plen ))
+
+ local yes no defaultno extra_args format
+ if [ "$USE_XDIALOG" ]; then
+ yes=ok no=cancel defaultno=default-no
+ extra_args="--wrap --left"
+ format="$msg_last_chance_are_you_sure"
+ else
+ yes=yes no=no defaultno=defaultno
+ extra_args="--colors --cr-wrap"
+ format="$msg_last_chance_are_you_sure_color"
+ fi
+
+ local disk line_width
+ for disk in $*; do
+ if [ "$line" ]; then
+ line_width=${#line}
+ else
+ line_width=$plen
+ fi
+ line_width=$(( $line_width + 1 + ${#disk} ))
+ # Add newline before disk if it would exceed max_width
+ if [ $line_width -gt $max_width ]; then
+ list="$list$line\n"
+ line="$prefix"
+ height=$(( $height + 1 ))
+ fi
+ # Add the disk to the list
+ line="$line $disk"
+ done
+ # Append the left-overs
+ if [ "${line#$prefix}" ]; then
+ list="$list$line"
+ height=$(( $height + 1 ))
+ fi
+
+ # Add height for Xdialog(1)
+ [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 ))
+
+ prompt=$( printf "$format" "$list" )
+ f_dprintf "%s: Last Chance!" "$0"
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --$defaultno \
+ --$yes-label "$msg_yes" \
+ --$no-label "$msg_no" \
+ $extra_args \
+ --yesno "$prompt" $height $width
+}
+
+# dialog_menu_layout
+#
+# Configure Virtual Device type and disks to use for the ZFS boot pool. User
+# must select enough disks to satisfy the chosen vdev type.
+#
+dialog_menu_layout()
+{
+ local funcname=dialog_menu_layout
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local vdev_prompt="$msg_select_virtual_device_type"
+ local disk_prompt="$msg_please_select_one_or_more_disks"
+ local vdev_menu_list="
+ 'stripe' '$msg_stripe_desc' '$msg_stripe_help'
+ 'mirror' '$msg_mirror_desc' '$msg_mirror_help'
+ 'raid10' '$msg_raid10_desc' '$msg_raid10_help'
+ 'raidz1' '$msg_raidz1_desc' '$msg_raidz1_help'
+ 'raidz2' '$msg_raidz2_desc' '$msg_raidz2_help'
+ 'raidz3' '$msg_raidz3_desc' '$msg_raidz3_help'
+ " # END-QUOTE
+ local disk_check_list= # Calculated below
+ local vdev_hline="$hline_arrows_tab_enter"
+ local disk_hline="$hline_arrows_space_tab_enter"
+
+ # Warn the user if vdev type is not valid
+ case "$ZFSBOOT_VDEV_TYPE" in
+ stripe|mirror|raid10|raidz1|raidz2|raidz3) : known good ;;
+ *)
+ f_dprintf "%s: Invalid virtual device type \`%s'" \
+ $funcname "$ZFSBOOT_VDEV_TYPE"
+ f_show_err "$msg_invalid_virtual_device_type" \
+ "$ZFSBOOT_VDEV_TYPE"
+ f_interactive || return $FAILURE
+ esac
+
+ # Calculate size of vdev menu once only
+ local vheight vwidth vrows
+ eval f_dialog_menu_with_help_size vheight vwidth vrows \
+ \"\$title\" \"\$btitle\" \"\$vdev_prompt\" \"\$vdev_hline\" \
+ $vdev_menu_list
+
+ # Get a list of probed disk devices
+ local disks=
+ debug= f_device_find "" $DEVICE_TYPE_DISK disks
+
+ # Prune out mounted md(4) devices that may be part of the boot process
+ local disk name new_list=
+ for disk in $disks; do
+ debug= $disk get name name
+ case "$name" in
+ md[0-9]*) f_mounted -b "/dev/$name" && continue ;;
+ esac
+ new_list="$new_list $disk"
+ done
+ disks="${new_list# }"
+
+ # Debugging
+ if [ "$debug" ]; then
+ local disk_names=
+ for disk in $disks; do
+ debug= $disk get name name
+ disk_names="$disk_names $name"
+ done
+ f_dprintf "$funcname: disks=[%s]" "${disk_names# }"
+ fi
+
+ if [ ! "$disks" ]; then
+ f_dprintf "No disk(s) present to configure"
+ f_show_err "$msg_no_disks_present_to_configure"
+ return $FAILURE
+ fi
+
+ # Lets sort the disks array to be more user friendly
+ f_device_sort_by name disks disks
+
+ #
+ # Operate in a loop so we can (if interactive) repeat if not enough
+ # disks are selected to satisfy the chosen vdev type or user wants to
+ # back-up to the previous menu.
+ #
+ local vardisk ndisks onoff selections vdev_choice breakout device
+ local valid_disks all_valid want_disks desc height width rows
+ while :; do
+ #
+ # Confirm the vdev type that was selected
+ #
+ if f_interactive && [ "$ZFSBOOT_CONFIRM_LAYOUT" ]; then
+ vdev_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$vdev_hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --item-help \
+ --default-item \"\$ZFSBOOT_VDEV_TYPE\" \
+ --menu \"\$vdev_prompt\" \
+ $vheight $vwidth $vrows \
+ $vdev_menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Exit if user pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize vdev_choice
+
+ ZFSBOOT_VDEV_TYPE="$vdev_choice"
+ f_dprintf "$funcname: ZFSBOOT_VDEV_TYPE=[%s]" \
+ "$ZFSBOOT_VDEV_TYPE"
+ fi
+
+ # Determine the number of disks needed for this vdev type
+ want_disks=0
+ case "$ZFSBOOT_VDEV_TYPE" in
+ stripe) want_disks=1 ;;
+ mirror) want_disks=2 ;;
+ raid10) want_disks=4 ;;
+ raidz1) want_disks=3 ;;
+ raidz2) want_disks=4 ;;
+ raidz3) want_disks=5 ;;
+ esac
+
+ #
+ # Warn the user if any scripted disks are invalid
+ #
+ valid_disks= all_valid=${ZFSBOOT_DISKS:+1} # optimism
+ for disk in $ZFSBOOT_DISKS; do
+ if debug= f_device_find -1 \
+ $disk $DEVICE_TYPE_DISK device
+ then
+ valid_disks="$valid_disks $disk"
+ continue
+ fi
+ f_dprintf "$funcname: \`%s' is not a real disk" "$disk"
+ all_valid=
+ done
+ if [ ! "$all_valid" ]; then
+ if [ "$ZFSBOOT_DISKS" ]; then
+ f_show_err \
+ "$msg_missing_one_or_more_scripted_disks"
+ else
+ f_dprintf "No disks selected."
+ f_interactive ||
+ f_show_err "$msg_no_disks_selected"
+ fi
+ f_interactive || return $FAILURE
+ fi
+ ZFSBOOT_DISKS="${valid_disks# }"
+
+ #
+ # Short-circuit if we're running non-interactively
+ #
+ if ! f_interactive || [ ! "$ZFSBOOT_CONFIRM_LAYOUT" ]; then
+ f_count ndisks $ZFSBOOT_DISKS
+ [ $ndisks -ge $want_disks ] && break # to success
+
+ # Not enough disks selected
+ f_dprintf "$funcname: %s: %s (%u < %u minimum)" \
+ "$ZFSBOOT_VDEV_TYPE" \
+ "Not enough disks selected." \
+ $ndisks $want_disks
+ f_interactive || return $FAILURE
+ msg_yes="$msg_change_selection" msg_no="$msg_cancel" \
+ f_yesno "%s: $msg_not_enough_disks_selected" \
+ "$ZFSBOOT_VDEV_TYPE" $ndisks $want_disks ||
+ return $FAILURE
+ fi
+
+ #
+ # Confirm the disks that were selected
+ # Loop until the user cancels or selects enough disks
+ #
+ breakout=
+ while :; do
+ # Loop over list of available disks, resetting state
+ for disk in $disks; do
+ f_isset _${disk}_status && _${disk}_status=
+ done
+
+ # Loop over list of selected disks and create temporary
+ # locals to map statuses onto up-to-date list of disks
+ for disk in $ZFSBOOT_DISKS; do
+ debug= f_device_find -1 \
+ $disk $DEVICE_TYPE_DISK disk
+ f_isset _${disk}_status ||
+ local _${disk}_status
+ _${disk}_status=on
+ done
+
+ # Create the checklist menu of discovered disk devices
+ disk_check_list=
+ for disk in $disks; do
+ desc=
+ $disk get name name
+ $disk get desc desc
+ f_shell_escape "$desc" desc
+ f_getvar _${disk}_status:-off onoff
+ disk_check_list="$disk_check_list
+ $name '$desc' $onoff"
+ done
+
+ eval f_dialog_checklist_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \
+ \"\$hline\" $disk_check_list
+
+ selections=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --separate-output \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_back\" \
+ --checklist \"\$prompt\" \
+ $height $width $rows \
+ $disk_check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || break
+ # Loop if user pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize selections
+
+ ZFSBOOT_DISKS="$selections"
+ f_dprintf "$funcname: ZFSBOOT_DISKS=[%s]" \
+ "$ZFSBOOT_DISKS"
+
+ f_count ndisks $ZFSBOOT_DISKS
+
+ if [ "$ZFSBOOT_VDEV_TYPE" == "raid10" ] &&
+ [ $(( $ndisks % 2 )) -ne 0 ]; then
+ f_dprintf "$funcname: %s: %s (%u %% 2 = %u)" \
+ "$ZFSBOOT_VDEV_TYPE" \
+ "Number of disks not even:" \
+ $ndisks $(( $ndisks % 2 ))
+ msg_yes="$msg_change_selection" \
+ msg_no="$msg_cancel" \
+ f_yesno "%s: $msg_odd_disk_selected" \
+ "$ZFSBOOT_VDEV_TYPE" $ndisks ||
+ break
+ continue
+ fi
+
+ [ $ndisks -ge $want_disks ] &&
+ breakout=break && break
+
+ # Not enough disks selected
+ f_dprintf "$funcname: %s: %s (%u < %u minimum)" \
+ "$ZFSBOOT_VDEV_TYPE" \
+ "Not enough disks selected." \
+ $ndisks $want_disks
+ msg_yes="$msg_change_selection" msg_no="$msg_cancel" \
+ f_yesno "%s: $msg_not_enough_disks_selected" \
+ "$ZFSBOOT_VDEV_TYPE" $ndisks $want_disks ||
+ break
+ done
+ [ "$breakout" = "break" ] && break
+ [ "$ZFSBOOT_CONFIRM_LAYOUT" ] || return $FAILURE
+ done
+
+ return $DIALOG_OK
+}
+
+# zfs_create_diskpart $disk $index
+#
+# For each block device to be used in the zpool, rather than just create the
+# zpool with the raw block devices (e.g., da0, da1, etc.) we create partitions
+# so we can have some real swap. This also provides wiggle room incase your
+# replacement drivers do not have the exact same sector counts.
+#
+# NOTE: $swapsize and $bootsize should be defined by the calling function.
+# NOTE: Sets $bootpart and $targetpart for the calling function.
+#
+zfs_create_diskpart()
+{
+ local funcname=zfs_create_diskpart
+ local disk="$1" index="$2"
+
+ # Check arguments
+ if [ ! "$disk" ]; then
+ f_dprintf "$funcname: NULL disk argument"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_null_disk_argument"
+ return $FAILURE
+ fi
+ if [ "${disk#*[$IFS]}" != "$disk" ]; then
+ f_dprintf "$funcname: Invalid disk argument \`%s'" "$disk"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_invalid_disk_argument" "$disk"
+ return $FAILURE
+ fi
+ if [ ! "$index" ]; then
+ f_dprintf "$funcname: NULL index argument"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_null_index_argument"
+ return $FAILURE
+ fi
+ if ! f_isinteger "$index"; then
+ f_dprintf "$funcname: Invalid index argument \`%s'" "$index"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_invalid_index_argument" "$index"
+ return $FAILURE
+ fi
+ f_dprintf "$funcname: disk=[%s] index=[%s]" "$disk" "$index"
+
+ # Check for unknown partition scheme before proceeding further
+ case "$ZFSBOOT_PARTITION_SCHEME" in
+ ""|MBR|GPT*) : known good ;;
+ *)
+ f_dprintf "$funcname: %s is an unsupported partition scheme" \
+ "$ZFSBOOT_PARTITION_SCHEME"
+ msg_error="$msg_error: $funcname" f_show_err \
+ "$msg_unsupported_partition_scheme" \
+ "$ZFSBOOT_PARTITION_SCHEME"
+ return $FAILURE
+ esac
+
+ #
+ # Destroy whatever partition layout is currently on disk.
+ # NOTE: `-F' required to destroy if partitions still exist.
+ # NOTE: Failure is ok here, blank disk will have nothing to destroy.
+ #
+ f_dprintf "$funcname: Exporting ZFS pools..."
+ zpool list -Ho name | while read z_name; do
+ f_eval_catch -d $funcname zpool "$ZPOOL_EXPORT_F" $z_name
+ done
+ f_dprintf "$funcname: Detaching all GELI providers..."
+ geli status | tail -n +2 | while read g_name g_status g_component; do
+ f_eval_catch -d $funcname geli "$GELI_DETACH_F" $g_name
+ done
+ f_dprintf "$funcname: Destroying all data/layouts on \`%s'..." "$disk"
+ f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk
+ f_eval_catch -d $funcname graid "$GRAID_DELETE" $disk
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" /dev/$disk
+
+ # Make doubly-sure backup GPT is destroyed
+ f_eval_catch -d $funcname gpart "$GPART_CREATE" gpt $disk
+ f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk
+
+ #
+ # Lay down the desired type of partition scheme
+ #
+ local setsize mbrindex align_small align_big
+ #
+ # If user has requested 4 K alignment, add these params to the
+ # gpart add calls. With GPT, we align large partitions to 1 M for
+ # improved performance on SSDs. MBR does not always play well with gaps
+ # between partitions, so all alignment is only 4k for that case.
+ # With MBR, we align the BSD partition that contains the MBR, otherwise
+ # the system fails to boot.
+ #
+ if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then
+ align_small="-a 4k"
+ align_big="-a 1m"
+ fi
+
+ case "$ZFSBOOT_PARTITION_SCHEME" in
+ ""|GPT*) f_dprintf "$funcname: Creating GPT layout..."
+ #
+ # 1. Create GPT layout using labels
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" gpt $disk ||
+ return $FAILURE
+
+ #
+ # Apply workarounds if requested by the user
+ #
+ if [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Lenovo Fix" ]; then
+ f_eval_catch $funcname gpart "$GPART_SET_LENOVOFIX" \
+ $disk || return $FAILURE
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then
+ f_eval_catch $funcname gpart "$GPART_SET_PMBR_ACTIVE" \
+ $disk || return $FAILURE
+ fi
+
+ #
+ # 2. Add small freebsd-boot and/or efi partition
+ #
+ if [ "$ZFSBOOT_BOOT_TYPE" = "UEFI" -o \
+ "$ZFSBOOT_BOOT_TYPE" = "BIOS+UEFI" ]
+ then
+ f_eval_catch -k justaddedpart $funcname gpart \
+ "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_small" efiboot$index efi 260M \
+ $disk || return $FAILURE
+
+ # We'll configure the ESP in bootconfig
+ if [ -z "$efibootpart" ]; then
+ efibootpart="/dev/$(echo $justaddedpart | cut -f 1 -d ' ')"
+ f_dprintf "$funcname: configuring ESP at [%s]" \
+ "${efibootpart}"
+
+ f_eval_catch $funcname newfs_msdos "$NEWFS_ESP"\
+ "$efibootpart" \
+ || return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ $efibootpart /boot/efi msdosfs \
+ rw 2 2 "$BSDINSTALL_TMPETC/fstab" \
+ || return $FAILURE
+ fi
+ fi
+
+ if [ "$ZFSBOOT_BOOT_TYPE" = "BIOS" -o \
+ "$ZFSBOOT_BOOT_TYPE" = "BIOS+UEFI" ]
+ then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_small" gptboot$index \
+ freebsd-boot 512k $disk || return $FAILURE
+ if [ "$ZFSBOOT_BOOT_TYPE" = "BIOS" ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_BOOTCODE_PART" \
+ /boot/pmbr /boot/gptzfsboot 1 \
+ $disk || return $FAILURE
+ else
+ f_eval_catch $funcname gpart \
+ "$GPART_BOOTCODE_PART" \
+ /boot/pmbr /boot/gptzfsboot 2 \
+ $disk || return $FAILURE
+ fi
+ fi
+
+ # NB: zpool will use the `zfs#' GPT labels
+ if [ "$ZFSBOOT_BOOT_TYPE" = "BIOS+UEFI" ]; then
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ bootpart=p3 swappart=p4 targetpart=p4
+ [ ${swapsize:-0} -gt 0 ] && targetpart=p5
+ else
+ # Bootpart unused
+ bootpart=p3 swappart=p3 targetpart=p3
+ [ ${swapsize:-0} -gt 0 ] && targetpart=p4
+ fi
+ else
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ bootpart=p2 swappart=p3 targetpart=p3
+ [ ${swapsize:-0} -gt 0 ] && targetpart=p4
+ else
+ # Bootpart unused
+ bootpart=p2 swappart=p2 targetpart=p2
+ [ ${swapsize:-0} -gt 0 ] && targetpart=p3
+ fi
+ fi
+
+ #
+ # Prepare boot pool if enabled (e.g., for geli(8))
+ #
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_big" boot$index freebsd-zfs \
+ ${bootsize}b $disk || return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Pedantically detach targetpart for later
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$targetpart
+ fi
+ fi
+
+ #
+ # 3. Add freebsd-swap partition labeled `swap#'
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_big" swap$index freebsd-swap \
+ ${swapsize}b $disk || return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$swappart
+ fi
+
+ #
+ # 4. Add freebsd-zfs partition labeled `zfs#' for zroot
+ #
+ if [ "$ZFSBOOT_POOL_SIZE" ]; then
+ f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_LABEL_WITH_SIZE" \
+ "$align_big" zfs$index freebsd-zfs $ZFSBOOT_POOL_SIZE $disk ||
+ return $FAILURE
+ else
+ f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_LABEL" \
+ "$align_big" zfs$index freebsd-zfs $disk ||
+ return $FAILURE
+ fi
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$targetpart
+ ;;
+
+ MBR) f_dprintf "$funcname: Creating MBR layout..."
+ #
+ # Enable boot pool if encryption is desired
+ #
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] && ZFSBOOT_BOOT_POOL=1
+ #
+ # 1. Create MBR layout (no labels)
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" mbr $disk ||
+ return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \
+ $disk || return $FAILURE
+
+ #
+ # 2. Add freebsd slice with all available space
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD_ALIGN" \
+ "$align_small" freebsd $disk || return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/${disk}s1
+ # Pedantically nuke any old scheme
+ f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" ${disk}s1
+
+ #
+ # 3. Write BSD scheme to the freebsd slice
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 ||
+ return $FAILURE
+
+ # NB: zpool will use s1a (no labels)
+ bootpart=s1a swappart=s1b targetpart=s1d mbrindex=4
+
+ #
+ # Always prepare a boot pool on MBR
+ # Do not align this partition, there must not be a gap
+ #
+ ZFSBOOT_BOOT_POOL=1
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_INDEX_WITH_SIZE" \
+ "" 1 freebsd-zfs ${bootsize}b ${disk}s1 ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Pedantically detach targetpart for later
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$targetpart
+ fi
+
+ #
+ # 4. Add freebsd-swap partition
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_ALIGN_INDEX_WITH_SIZE" \
+ "$align_small" 2 freebsd-swap \
+ ${swapsize}b ${disk}s1 || return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/${disk}s1b
+ fi
+
+ #
+ # 5. Add freebsd-zfs partition for zroot
+ #
+ if [ "$ZFSBOOT_POOL_SIZE" ]; then
+ f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_INDEX_WITH_SIZE" \
+ "$align_small" $mbrindex freebsd-zfs $ZFSBOOT_POOL_SIZE ${disk}s1 || return $FAILURE
+ else
+ f_eval_catch $funcname gpart "$GPART_ADD_ALIGN_INDEX" \
+ "$align_small" $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE
+ fi
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$targetpart # Pedantic
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/${disk}s1 count=1 ||
+ return $FAILURE
+ ;;
+
+ esac # $ZFSBOOT_PARTITION_SCHEME
+
+ # Update fstab(5)
+ local swapsize
+ f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize
+ if [ "$isswapmirror" ]; then
+ # This is not the first disk in the mirror, do nothing
+ elif [ ${swapsize:-0} -eq 0 ]; then
+ # If swap is 0 sized, don't add it to fstab
+ elif [ "$ZFSBOOT_SWAP_ENCRYPTION" -a "$ZFSBOOT_SWAP_MIRROR" ]; then
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ /dev/mirror/swap.eli none swap sw 0 0 \
+ $BSDINSTALL_TMPETC/fstab || return $FAILURE
+ isswapmirror=1
+ elif [ "$ZFSBOOT_SWAP_MIRROR" ]; then
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ /dev/mirror/swap none swap sw 0 0 \
+ $BSDINSTALL_TMPETC/fstab || return $FAILURE
+ isswapmirror=1
+ elif [ "$ZFSBOOT_SWAP_ENCRYPTION" ]; then
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ /dev/$disk${swappart}.eli none swap sw 0 0 \
+ $BSDINSTALL_TMPETC/fstab || return $FAILURE
+ else
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ /dev/$disk$swappart none swap sw 0 0 \
+ $BSDINSTALL_TMPETC/fstab || return $FAILURE
+ fi
+
+ return $SUCCESS
+}
+
+# zfs_create_boot $poolname $vdev_type $disks ...
+#
+# Creates boot pool and dataset layout. Returns error if something goes wrong.
+# Errors are printed to stderr for collection and display.
+#
+zfs_create_boot()
+{
+ local funcname=zfs_create_boot
+ local zroot_name="$1"
+ local zroot_vdevtype="$2"
+ local zroot_vdevs= # Calculated below
+ local swap_devs= # Calculated below
+ local boot_vdevs= # Used for geli(8) and/or MBR layouts
+ shift 2 # poolname vdev_type
+ local disks="$*" disk
+ local isswapmirror
+ local bootpart targetpart swappart # Set by zfs_create_diskpart() below
+ local create_options
+ local efibootpart
+
+ #
+ # Pedantic checks; should never be seen
+ #
+ if [ ! "$zroot_name" ]; then
+ f_dprintf "$funcname: NULL poolname"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_null_poolname"
+ return $FAILURE
+ fi
+ if [ $# -lt 1 ]; then
+ f_dprintf "$funcname: missing disk arguments"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_missing_disk_arguments"
+ return $FAILURE
+ fi
+ f_dprintf "$funcname: poolname=[%s] vdev_type=[%s]" \
+ "$zroot_name" "$zroot_vdevtype"
+
+ #
+ # Initialize fstab(5)
+ #
+ f_dprintf "$funcname: Initializing temporary fstab(5) file..."
+ f_eval_catch $funcname sh "$SHELL_TRUNCATE" $BSDINSTALL_TMPETC/fstab ||
+ return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ "# Device" Mountpoint FStype Options Dump "Pass#" \
+ $BSDINSTALL_TMPETC/fstab || return $FAILURE
+
+ #
+ # Expand SI units in desired sizes
+ #
+ f_dprintf "$funcname: Expanding supplied size values..."
+ local swapsize bootsize poolsize
+ if ! f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize; then
+ f_dprintf "$funcname: Invalid swap size \`%s'" \
+ "$ZFSBOOT_SWAP_SIZE"
+ f_show_err "$msg_invalid_swap_size" "$ZFSBOOT_SWAP_SIZE"
+ return $FAILURE
+ fi
+ if ! f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize; then
+ f_dprintf "$funcname: Invalid boot pool size \`%s'" \
+ "$ZFSBOOT_BOOT_POOL_SIZE"
+ f_show_err "$msg_invalid_boot_pool_size" \
+ "$ZFSBOOT_BOOT_POOL_SIZE"
+ return $FAILURE
+ fi
+ if [ "$ZFSBOOT_POOL_SIZE" ]; then
+ if ! f_expand_number "$ZFSBOOT_POOL_SIZE" poolsize; then
+ f_dprintf "$funcname: Invalid pool size \`%s'" \
+ "$ZFSBOOT_POOL_SIZE"
+ f_show_err "$msg_invalid_pool_size" \
+ "$ZFSBOOT_POOL_SIZE"
+ fi
+ f_dprintf "$funcname: ZFSBOOT_POOL_SIZE=[%s] poolsize=[%s]" \
+ "$ZFSBOOT_POOL_SIZE" "$poolsize"
+ fi
+ f_dprintf "$funcname: ZFSBOOT_SWAP_SIZE=[%s] swapsize=[%s]" \
+ "$ZFSBOOT_SWAP_SIZE" "$swapsize"
+ f_dprintf "$funcname: ZFSBOOT_BOOT_POOL_SIZE=[%s] bootsize=[%s]" \
+ "$ZFSBOOT_BOOT_POOL_SIZE" "$bootsize"
+
+ #
+ # Destroy the pool in-case this is our second time 'round (case of
+ # failure and installer presented ``Retry'' option to come back).
+ #
+ # NB: If we don't destroy the pool, later gpart(8) destroy commands
+ # that try to clear existing partitions (see zfs_create_diskpart())
+ # will fail with a `Device Busy' error, leading to `GEOM exists'.
+ #
+ f_eval_catch -d $funcname zpool "$ZPOOL_DESTROY" "$zroot_name"
+
+ #
+ # Prepare the disks and build pool device list(s)
+ #
+ f_dprintf "$funcname: Preparing disk partitions for ZFS pool..."
+
+ # Force 4K sectors using vfs.zfs.min_auto_ashift=12
+ if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then
+ f_dprintf "$funcname: With 4K sectors..."
+ f_eval_catch $funcname sysctl "$SYSCTL_ZFS_MIN_ASHIFT_12" \
+ || return $FAILURE
+ sysctl kern.geom.part.mbr.enforce_chs=0
+ fi
+ local n=0
+ for disk in $disks; do
+ zfs_create_diskpart $disk $n || return $FAILURE
+ # Now $bootpart, $targetpart, and $swappart are set (suffix
+ # for $disk)
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ boot_vdevs="$boot_vdevs $disk$bootpart"
+ fi
+ zroot_vdevs="$zroot_vdevs $disk$targetpart"
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ zroot_vdevs="$zroot_vdevs.eli"
+ fi
+
+ n=$(( $n + 1 ))
+ done # disks
+
+ #
+ # If we need/want a boot pool, create it
+ #
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ local bootpool_vdevtype= # Calculated below
+ local bootpool_options= # Calculated below
+ local bootpool_name="$ZFSBOOT_BOOT_POOL_NAME"
+ local bootpool="$BSDINSTALL_CHROOT/$bootpool_name"
+ local zroot_key="${ZFSBOOT_GELI_KEY_FILE#/}"
+
+ f_dprintf "$funcname: Setting up boot pool..."
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] &&
+ f_dprintf "$funcname: For encrypted root disk..."
+
+ # Create parent directory for boot pool
+ f_eval_catch -d $funcname umount "$UMOUNT" "$BSDINSTALL_CHROOT"
+ f_eval_catch $funcname mount "$MOUNT_TYPE" tmpfs none \
+ $BSDINSTALL_CHROOT || return $FAILURE
+
+ # Create mirror across the boot partition on all disks
+ local nvdevs
+ f_count nvdevs $boot_vdevs
+ [ $nvdevs -gt 1 ] && bootpool_vdevtype=mirror
+
+ create_options="$ZFSBOOT_BOOT_POOL_CREATE_OPTIONS"
+ bootpool_options="-o altroot=$BSDINSTALL_CHROOT"
+ bootpool_options="$bootpool_options $create_options"
+ bootpool_options="$bootpool_options -m \"/$bootpool_name\" -f"
+ f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \
+ "$bootpool_options" "$bootpool_name" \
+ "$bootpool_vdevtype" "$boot_vdevs" ||
+ return $FAILURE
+
+ f_eval_catch $funcname mkdir "$MKDIR_P" "$bootpool/boot" ||
+ return $FAILURE
+
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Generate an encryption key using random(4)
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /dev/random "$bootpool/$zroot_key" \
+ "bs=4096 count=1" || return $FAILURE
+ f_eval_catch $funcname chmod "$CHMOD_MODE" \
+ go-wrx "$bootpool/$zroot_key" ||
+ return $FAILURE
+ fi
+
+ fi
+
+ #
+ # Create the geli(8) GEOMS
+ #
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ #
+ # Load the AES-NI kernel module to accelerate encryption
+ #
+ f_eval_catch -d $funcname kldload "$KLDLOAD" "aesni"
+ # Prompt user for password (twice)
+ if ! msg_enter_new_password="$msg_geli_password" \
+ f_dialog_input_password
+ then
+ f_dprintf "$funcname: User cancelled"
+ f_show_err "$msg_user_cancelled"
+ return $FAILURE
+ fi
+
+ # Initialize geli(8) on each of the target partitions
+ for disk in $disks; do
+ f_dialog_info "$msg_geli_setup" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ if ! echo "$pw_password" | f_eval_catch \
+ $funcname geli "$GELI_PASSWORD_INIT" \
+ "$bootpool/boot/$disk$targetpart.eli" \
+ AES-XTS "$bootpool/$zroot_key" \
+ $disk$targetpart
+ then
+ f_interactive || f_die
+ unset pw_password # Sensitive info
+ return $FAILURE
+ fi
+ if ! echo "$pw_password" | f_eval_catch \
+ $funcname geli "$GELI_ATTACH" \
+ "$bootpool/$zroot_key" $disk$targetpart
+ then
+ f_interactive || f_die
+ unset pw_password # Sensitive info
+ return $FAILURE
+ fi
+ else
+ # With no bootpool, there is no place to store
+ # the key files, use only a password
+ if ! echo "$pw_password" | f_eval_catch \
+ $funcname geli \
+ "$GELI_PASSWORD_GELIBOOT_INIT" \
+ AES-XTS $disk$targetpart
+ then
+ f_interactive || f_die
+ unset pw_password # Sensitive info
+ return $FAILURE
+ fi
+ if ! echo "$pw_password" | f_eval_catch \
+ $funcname geli "$GELI_ATTACH_NOKEY" \
+ $disk$targetpart
+ then
+ f_interactive || f_die
+ unset pw_password # Sensitive info
+ return $FAILURE
+ fi
+ fi
+ done
+ unset pw_password # Sensitive info
+ fi
+
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ # Clean up
+ f_eval_catch $funcname zfs "$ZFS_UNMOUNT" "$bootpool_name" ||
+ return $FAILURE
+ # tmpfs
+ f_eval_catch -d $funcname umount "$UMOUNT" "$BSDINSTALL_CHROOT"
+ fi
+
+ #
+ # Create the gmirror(8) GEOMS for swap
+ #
+ if [ ${swapsize:-0} -gt 0 -a "$ZFSBOOT_SWAP_MIRROR" ]; then
+ for disk in $disks; do
+ swap_devs="$swap_devs $disk$swappart"
+ done
+ f_eval_catch $funcname gmirror "$SWAP_GMIRROR_LABEL" \
+ "$swap_devs" || return $FAILURE
+ fi
+
+ #
+ # Create the ZFS root pool with desired type and disk devices
+ #
+ f_dprintf "$funcname: Creating root pool..."
+ create_options="$ZFSBOOT_POOL_CREATE_OPTIONS"
+ if [ "$zroot_vdevtype" == "raid10" ]; then
+ raid10_vdevs=""
+ for vdev in $zroot_vdevs; do
+ f_count nvdev $raid10_vdevs
+ if [ $(( $nvdev % 3 )) -eq 0 ]; then
+ raid10_vdevs="$raid10_vdevs mirror"
+ fi
+ raid10_vdevs="$raid10_vdevs $vdev"
+ done
+ f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \
+ "-o altroot=$BSDINSTALL_CHROOT $create_options -m none -f" \
+ "$zroot_name" "" "$raid10_vdevs" || return $FAILURE
+ else
+ f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \
+ "-o altroot=$BSDINSTALL_CHROOT $create_options -m none -f" \
+ "$zroot_name" "$zroot_vdevtype" "$zroot_vdevs" ||
+ return $FAILURE
+ fi
+
+ #
+ # Create ZFS dataset layout within the new root pool
+ #
+ f_dprintf "$funcname: Creating ZFS datasets..."
+ echo "$ZFSBOOT_DATASETS" | while read dataset options; do
+ # Skip blank lines and comments
+ case "$dataset" in "#"*|"") continue; esac
+ # Remove potential inline comments in options
+ options="${options%%#*}"
+ # Replace tabs with spaces
+ f_replaceall "$options" " " " " options
+ # Reduce contiguous runs of space to one single space
+ oldoptions=
+ while [ "$oldoptions" != "$options" ]; do
+ oldoptions="$options"
+ f_replaceall "$options" " " " " options
+ done
+ # Replace both commas and spaces with ` -o '
+ f_replaceall "$options" "[ ,]" " -o " options
+ # Create the dataset with desired options
+ f_eval_catch $funcname zfs "$ZFS_CREATE_WITH_OPTIONS" \
+ "${options:+-o $options}" "$zroot_name$dataset" ||
+ return $FAILURE
+ done
+
+ #
+ # Set a mountpoint for the root of the pool so newly created datasets
+ # have a mountpoint to inherit
+ #
+ f_dprintf "$funcname: Setting mountpoint for root of the pool..."
+ f_eval_catch $funcname zfs "$ZFS_SET" \
+ "mountpoint=/$zroot_name" "$zroot_name" || return $FAILURE
+
+ # Touch up permissions on the tmp directories
+ f_dprintf "$funcname: Modifying directory permissions..."
+ local dir
+ for dir in /tmp /var/tmp; do
+ f_eval_catch $funcname mkdir "$MKDIR_P" \
+ $BSDINSTALL_CHROOT$dir || return $FAILURE
+ f_eval_catch $funcname chmod "$CHMOD_MODE" 1777 \
+ $BSDINSTALL_CHROOT$dir || return $FAILURE
+ done
+
+ # Set bootfs property
+ local zroot_bootfs="$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME"
+ f_dprintf "$funcname: Setting bootfs property..."
+ f_eval_catch $funcname zpool "$ZPOOL_SET" \
+ "bootfs=\"$zroot_name/$zroot_bootfs\"" "$zroot_name" ||
+ return $FAILURE
+
+ # MBR boot loader touch-up
+ if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then
+ # Export the pool(s)
+ f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..."
+ f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$zroot_name" ||
+ return $FAILURE
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \
+ "$bootpool_name" || return $FAILURE
+ fi
+
+ f_dprintf "$funcname: Updating MBR boot loader on disks..."
+ # Stick the ZFS boot loader in the "convenient hole" after
+ # the ZFS internal metadata
+ for disk in $disks; do
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/$disk$bootpart \
+ "skip=1 seek=1024" || return $FAILURE
+ done
+
+ # Re-import the ZFS pool(s)
+ f_dprintf "$funcname: Re-importing ZFS pool(s)..."
+ f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \
+ "-o altroot=\"$BSDINSTALL_CHROOT\"" \
+ "$zroot_name" || return $FAILURE
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ # Import the bootpool, but do not mount it yet
+ f_eval_catch $funcname zpool \
+ "$ZPOOL_IMPORT_WITH_OPTIONS" \
+ "-o altroot=\"$BSDINSTALL_CHROOT\" -N" \
+ "$bootpool_name" || return $FAILURE
+ fi
+ fi
+
+ # Remount bootpool and create symlink(s)
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch $funcname zfs "$ZFS_MOUNT" "$bootpool_name" ||
+ return $FAILURE
+ f_dprintf "$funcname: Creating /boot symlink for boot pool..."
+ f_eval_catch $funcname ln "$LN_SF" "$bootpool_name/boot" \
+ $BSDINSTALL_CHROOT/boot || return $FAILURE
+ fi
+
+ # zpool.cache is required to mount more than one pool at boot time
+ f_dprintf "$funcname: Configuring zpool.cache for zroot..."
+ f_eval_catch $funcname mkdir "$MKDIR_P" $BSDINSTALL_CHROOT/boot/zfs ||
+ return $FAILURE
+ f_eval_catch $funcname zpool "$ZPOOL_SET" \
+ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \
+ "$zroot_name" || return $FAILURE
+
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ vfs.root.mountfrom \
+ "\"zfs:$zroot_name/$zroot_bootfs\"" \
+ $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE
+ fi
+ #
+ # Set canmount=noauto so that the default Boot Environment (BE) does
+ # not get mounted if a different BE is selected from the beastie menu
+ #
+ f_dprintf "$funcname: Set canmount=noauto for the root of the pool..."
+ f_eval_catch $funcname zfs "$ZFS_SET" "canmount=noauto" \
+ "$zroot_name/$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME"
+
+ # Last, but not least... required lines for rc.conf(5)/loader.conf(5)
+ # NOTE: We later concatenate these into their destination
+ f_dprintf "%s: Configuring rc.conf(5)/loader.conf(5) additions..." \
+ "$funcname"
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_enable=\"YES\"' \
+ $BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE
+ f_eval_catch $funcname echo "$ECHO_APPEND" \
+ 'kern.geom.label.disk_ident.enable=\"0\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE
+ f_eval_catch $funcname echo "$ECHO_APPEND" \
+ 'kern.geom.label.gptid.enable=\"0\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE
+
+ if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then
+ f_eval_catch $funcname echo "$ECHO_APPEND" \
+ 'vfs.zfs.min_auto_ashift=12' \
+ $BSDINSTALL_TMPETC/sysctl.conf.zfs || return $FAILURE
+ fi
+
+ if [ "$ZFSBOOT_SWAP_MIRROR" ]; then
+ f_eval_catch $funcname echo "$ECHO_APPEND" \
+ 'geom_mirror_load=\"YES\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.gmirror ||
+ return $FAILURE
+ fi
+
+ # We're all done unless we should go on to do encryption
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS
+
+ #
+ # Configure geli(8)-based encryption
+ #
+ f_dprintf "$funcname: Configuring disk encryption..."
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'aesni_load=\"YES\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'geom_eli_load=\"YES\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE
+
+ # We're all done unless we should go on for boot pool
+ [ "$ZFSBOOT_BOOT_POOL" ] || return $SUCCESS
+
+ for disk in $disks; do
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ geli_%s_keyfile0_load "$disk$targetpart YES" \
+ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart ||
+ return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ geli_%s_keyfile0_type \
+ "$disk$targetpart $disk$targetpart:geli_keyfile0" \
+ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart ||
+ return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ geli_%s_keyfile0_name \
+ "$disk$targetpart \"$ZFSBOOT_GELI_KEY_FILE\"" \
+ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart ||
+ return $FAILURE
+ done
+
+ # Set cachefile for boot pool so it auto-imports at system start
+ f_dprintf "$funcname: Configuring zpool.cache for boot pool..."
+ f_eval_catch $funcname zpool "$ZPOOL_SET" \
+ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \
+ "$bootpool_name" || return $FAILURE
+
+ # Some additional geli(8) requirements for loader.conf(5)
+ for option in \
+ 'zpool_cache_load=\"YES\"' \
+ 'zpool_cache_type=\"/boot/zfs/zpool.cache\"' \
+ 'zpool_cache_name=\"/boot/zfs/zpool.cache\"' \
+ 'geom_eli_passphrase_prompt=\"YES\"' \
+ ; do
+ f_eval_catch $funcname echo "$ECHO_APPEND" "$option" \
+ $BSDINSTALL_TMPBOOT/loader.conf.zfs ||
+ return $FAILURE
+ done
+ return $SUCCESS
+}
+
+# dialog_menu_diskinfo
+#
+# Prompt the user to select a disk and then provide detailed info on it.
+#
+dialog_menu_diskinfo()
+{
+ local device disk
+
+ #
+ # Break from loop when user cancels disk selection
+ #
+ while :; do
+ device=$( msg_cancel="$msg_back" f_device_menu \
+ "$DIALOG_TITLE" "$msg_select_a_disk_device" "" \
+ $DEVICE_TYPE_DISK 2>&1 ) || break
+ $device get name disk
+
+ # Show gpart(8) `show' and camcontrol(8) `inquiry' data
+ f_show_msg "$msg_detailed_disk_info" \
+ "$disk" "$( gpart show $disk 2> /dev/null )" \
+ "$disk" "$( camcontrol inquiry $disk 2> /dev/null )" \
+ "$disk" "$( camcontrol identify $disk 2> /dev/null )"
+ done
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_zfs_configuration"
+f_dialog_backtitle "$msg_freebsd_installer"
+
+# User may have specifically requested ZFS-related operations be interactive
+! f_interactive && f_zfsinteractive && unset $VAR_NONINTERACTIVE
+
+#
+# Debugging
+#
+f_dprintf "BSDINSTALL_CHROOT=[%s]" "$BSDINSTALL_CHROOT"
+f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC"
+f_dprintf "FSTAB_FMT=[%s]" "$FSTAB_FMT"
+
+#
+# Determine default boot type
+#
+case $(uname -m) in
+arm64|riscv)
+ # We support only UEFI boot for arm64 and riscv.
+ : ${ZFSBOOT_BOOT_TYPE:=UEFI}
+ : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
+ ;;
+*)
+ # If the system was booted with UEFI, set the default boot type to UEFI
+ bootmethod=$( sysctl -n machdep.bootmethod )
+ f_dprintf "machdep.bootmethod=[%s]" "$bootmethod"
+ if [ "$bootmethod" = "UEFI" ]; then
+ : ${ZFSBOOT_BOOT_TYPE:=BIOS+UEFI}
+ : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
+ else
+ : ${ZFSBOOT_BOOT_TYPE:=BIOS}
+ : ${ZFSBOOT_PARTITION_SCHEME:=GPT}
+ fi
+ ;;
+esac
+
+#
+# Loop over the main menu until we've accomplished what we came here to do
+#
+while :; do
+ if ! f_interactive; then
+ retval=$DIALOG_OK
+ mtag=">>> $msg_install"
+ else
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ fi
+
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ case "$mtag" in
+ ">>> $msg_install")
+ #
+ # First, validate the user's selections
+ #
+
+ # Make sure they gave us a name for the pool
+ if [ ! "$ZFSBOOT_POOL_NAME" ]; then
+ f_dprintf "Pool name cannot be empty."
+ f_show_err "$msg_pool_name_cannot_be_empty"
+ continue
+ fi
+
+ # Validate vdev type against number of disks selected/scripted
+ # (also validates that ZFSBOOT_DISKS are real [probed] disks)
+ # NB: dialog_menu_layout supports running non-interactively
+ dialog_menu_layout || continue
+
+ # Make sure each disk will have room for ZFS
+ if f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize &&
+ f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize &&
+ f_expand_number "1g" zpoolmin
+ then
+ minsize=$swapsize teeny_disks=
+ if [ "$ZFSBOOT_POOL_SIZE" ]; then
+ f_expand_number "$ZFSBOOT_POOL_SIZE" poolsize
+ minsize=$(( $minsize + $poolsize ))
+ fi
+ [ "$ZFSBOOT_BOOT_POOL" ] &&
+ minsize=$(( $minsize + $bootsize ))
+ for disk in $ZFSBOOT_DISKS; do
+ debug= f_device_find -1 \
+ $disk $DEVICE_TYPE_DISK device
+ $device get capacity disksize || continue
+ [ ${disksize:-0} -ge 0 ] || disksize=0
+ [ $disksize -lt $minsize ] &&
+ teeny_disks="$teeny_disks $disk"
+ done
+ if [ "$teeny_disks" ]; then
+ f_dprintf "swapsize=[%s] bootsize[%s] %s" \
+ "$ZFSBOOT_SWAP_SIZE" \
+ "$ZFSBOOT_BOOT_POOL_SIZE" \
+ "minsize=[$minsize]"
+ f_dprintf "These disks are too small: %s" \
+ "$teeny_disks"
+ f_show_err "$msg_these_disks_are_too_small" \
+ "$ZFSBOOT_SWAP_SIZE" \
+ "$ZFSBOOT_BOOT_POOL_SIZE" \
+ "$teeny_disks"
+ continue
+ fi
+ fi
+
+ #
+ # Last Chance!
+ #
+ if f_interactive; then
+ dialog_last_chance $ZFSBOOT_DISKS || continue
+ fi
+
+ #
+ # Let's do this
+ #
+
+ vdev_type="$ZFSBOOT_VDEV_TYPE"
+
+ # Blank the vdev type for the default layout
+ [ "$vdev_type" = "stripe" ] && vdev_type=
+
+ zfs_create_boot "$ZFSBOOT_POOL_NAME" \
+ "$vdev_type" $ZFSBOOT_DISKS || continue
+
+ # To be reused by bootconfig
+ echo "$ZFSBOOT_DISKS" > ${TMPDIR:-"/tmp"}/bsdinstall-zfsboot
+
+ break # to success
+ ;;
+ ?" $msg_pool_type_disks")
+ ZFSBOOT_CONFIRM_LAYOUT=1
+ dialog_menu_layout
+ # User has poked settings, disable later confirmation
+ ZFSBOOT_CONFIRM_LAYOUT=
+ ;;
+ "- $msg_rescan_devices") f_device_rescan ;;
+ "- $msg_disk_info") dialog_menu_diskinfo ;;
+ ?" $msg_pool_name")
+ # Prompt the user to input/change the name for the new pool
+ f_dialog_input input \
+ "$msg_please_enter_a_name_for_your_zpool" \
+ "$ZFSBOOT_POOL_NAME" &&
+ ZFSBOOT_POOL_NAME="$input"
+ ;;
+ ?" $msg_force_4k_sectors")
+ # Toggle the variable referenced both by the menu and later
+ if [ "$ZFSBOOT_FORCE_4K_SECTORS" ]; then
+ ZFSBOOT_FORCE_4K_SECTORS=
+ else
+ ZFSBOOT_FORCE_4K_SECTORS=1
+ fi
+ ;;
+ ?" $msg_encrypt_disks")
+ # Toggle the variable referenced both by the menu and later
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ ZFSBOOT_GELI_ENCRYPTION=
+ else
+ ZFSBOOT_FORCE_4K_SECTORS=1
+ ZFSBOOT_GELI_ENCRYPTION=1
+ fi
+ ;;
+ ?" $msg_partition_scheme")
+ # Toggle between GPT (BIOS), GPT (UEFI) and MBR
+ if [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" -a \
+ "$ZFSBOOT_BOOT_TYPE" = "BIOS" ]
+ then
+ ZFSBOOT_PARTITION_SCHEME="GPT"
+ ZFSBOOT_BOOT_TYPE="UEFI"
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" -a \
+ "$ZFSBOOT_BOOT_TYPE" = "UEFI" ]
+ then
+ ZFSBOOT_PARTITION_SCHEME="GPT"
+ ZFSBOOT_BOOT_TYPE="BIOS+UEFI"
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT" ]; then
+ ZFSBOOT_PARTITION_SCHEME="MBR"
+ ZFSBOOT_BOOT_TYPE="BIOS"
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then
+ ZFSBOOT_PARTITION_SCHEME="GPT + Active"
+ ZFSBOOT_BOOT_TYPE="BIOS"
+ elif [ "$ZFSBOOT_PARTITION_SCHEME" = "GPT + Active" ]; then
+ ZFSBOOT_PARTITION_SCHEME="GPT + Lenovo Fix"
+ ZFSBOOT_BOOT_TYPE="BIOS"
+ else
+ ZFSBOOT_PARTITION_SCHEME="GPT"
+ ZFSBOOT_BOOT_TYPE="BIOS"
+ fi
+ ;;
+ ?" $msg_swap_size")
+ # Prompt the user to input/change the swap size for each disk
+ while :; do
+ f_dialog_input input \
+ "$msg_please_enter_amount_of_swap_space" \
+ "$ZFSBOOT_SWAP_SIZE" &&
+ ZFSBOOT_SWAP_SIZE="${input:-0}"
+ if f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize
+ then
+ if [ $swapsize -ne 0 -a $swapsize -lt 104857600 ]; then
+ f_show_err "$msg_swap_toosmall" \
+ "$ZFSBOOT_SWAP_SIZE"
+ continue;
+ else
+ break;
+ fi
+ else
+ f_show_err "$msg_swap_invalid" \
+ "$ZFSBOOT_SWAP_SIZE"
+ continue;
+ fi
+ done
+ ;;
+ ?" $msg_swap_mirror")
+ # Toggle the variable referenced both by the menu and later
+ if [ "$ZFSBOOT_SWAP_MIRROR" ]; then
+ ZFSBOOT_SWAP_MIRROR=
+ else
+ ZFSBOOT_SWAP_MIRROR=1
+ fi
+ ;;
+ ?" $msg_swap_encrypt")
+ # Toggle the variable referenced both by the menu and later
+ if [ "$ZFSBOOT_SWAP_ENCRYPTION" ]; then
+ ZFSBOOT_SWAP_ENCRYPTION=
+ else
+ ZFSBOOT_SWAP_ENCRYPTION=1
+ fi
+ ;;
+ esac
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/contrib/bsddialog/library_examples/buildlist.c b/contrib/bsddialog/examples_library/buildlist.c
index f5d991bcb2e6..37c1e342ace5 100644
--- a/contrib/bsddialog/library_examples/buildlist.c
+++ b/contrib/bsddialog/examples_library/buildlist.c
@@ -31,7 +31,7 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_buildlist(conf, "Example", 15, 30, 5, 5, items, NULL);
+ output = bsddialog_buildlist(&conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
diff --git a/contrib/bsddialog/library_examples/checklist.c b/contrib/bsddialog/examples_library/checklist.c
index 104c2285a6e1..d1c4a4db3597 100644
--- a/contrib/bsddialog/library_examples/checklist.c
+++ b/contrib/bsddialog/examples_library/checklist.c
@@ -31,7 +31,7 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_checklist(conf, "Example", 15, 30, 5, 5, items, NULL);
+ output = bsddialog_checklist(&conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
diff --git a/contrib/bsddialog/library_examples/compile b/contrib/bsddialog/examples_library/compile
index 3215dceb72b6..4427568a7f0f 100755
--- a/contrib/bsddialog/library_examples/compile
+++ b/contrib/bsddialog/examples_library/compile
@@ -2,7 +2,7 @@
libpath=../lib
examples="buildlist menu treeview checklist radiolist mixedlist theme \
- infobox yesno msgbox ports"
+ infobox yesno msgbox datebox form timebox sade rangebox pause"
for e in $examples
do
diff --git a/contrib/bsddialog/examples_library/datebox.c b/contrib/bsddialog/examples_library/datebox.c
new file mode 100644
index 000000000000..b74146b15f26
--- /dev/null
+++ b/contrib/bsddialog/examples_library/datebox.c
@@ -0,0 +1,59 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2021 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <bsddialog.h>
+
+int main()
+{
+ int output;
+ unsigned int yy, mm, dd;
+ struct bsddialog_conf conf;
+ time_t cal;
+ struct tm *localtm;
+
+ time(&cal);
+ localtm = localtime(&cal);
+ yy = localtm->tm_year + 1900;
+ mm = localtm->tm_mon + 1;
+ dd = localtm->tm_mday;
+
+ bsddialog_initconf(&conf);
+ conf.title = "datebox";
+ conf.hline = "Press TAB and arrows";
+
+ if (bsddialog_init() < 0)
+ return -1;
+
+ output = bsddialog_datebox(&conf, "Example", 10, 50, &yy, &mm, &dd);
+
+ bsddialog_end();
+
+ switch (output) {
+ case BSDDIALOG_YESOK:
+ printf("Date: %u/%u/%u", yy, mm, dd);
+ break;
+ case BSDDIALOG_ESC:
+ printf("ESC\n");
+ break;
+ case BSDDIALOG_NOCANCEL:
+ printf("Cancel");
+ break;
+ case BSDDIALOG_ERROR:
+ printf("Error: %s", bsddialog_geterror());
+ break;
+ }
+ printf("\n");
+
+ return output;
+}
diff --git a/contrib/bsddialog/examples_library/form.c b/contrib/bsddialog/examples_library/form.c
new file mode 100644
index 000000000000..efb997f31d36
--- /dev/null
+++ b/contrib/bsddialog/examples_library/form.c
@@ -0,0 +1,51 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2021 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <bsddialog.h>
+
+#define H BSDDIALOG_FIELDHIDDEN
+#define RO BSDDIALOG_FIELDREADONLY
+
+int main()
+{
+ int i, output;
+ struct bsddialog_conf conf;
+ struct bsddialog_formitem items[3] = {
+ {"Input:", 1, 1, "value", 1, 11, 30, 50, NULL, 0, "desc 1"},
+ {"Input:", 2, 1, "read only", 2, 11, 30, 50, NULL, RO, "desc 2"},
+ {"Password:", 3, 1, "", 3, 11, 30, 50, NULL, H, "desc 3"}
+ };
+
+ bsddialog_initconf(&conf);
+ conf.title = "form";
+ conf.form.securech = '*';
+
+ if (bsddialog_init() < 0)
+ return -1;
+
+ output = bsddialog_form(&conf, "Example", 10, 50, 3, 3, items);
+
+ bsddialog_end();
+
+ if (output == BSDDIALOG_ERROR)
+ printf("Error: %s", bsddialog_geterror());
+
+ for (i=0; i<3; i++) {
+ printf("%s \"%s\"\n", items[i].label, items[i].value);
+ free(items[i].value);
+ }
+
+ return output;
+}
diff --git a/contrib/bsddialog/library_examples/infobox.c b/contrib/bsddialog/examples_library/infobox.c
index 8def8a482920..74f34bba91e1 100644
--- a/contrib/bsddialog/library_examples/infobox.c
+++ b/contrib/bsddialog/examples_library/infobox.c
@@ -24,7 +24,7 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_infobox(conf, "Example", 7, 20);
+ output = bsddialog_infobox(&conf, "Example", 7, 20);
bsddialog_end();
diff --git a/contrib/bsddialog/library_examples/menu.c b/contrib/bsddialog/examples_library/menu.c
index 04306e8317f4..59999dabd1e5 100644
--- a/contrib/bsddialog/library_examples/menu.c
+++ b/contrib/bsddialog/examples_library/menu.c
@@ -31,7 +31,7 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_menu(conf, "Example", 15, 30, 5, 5, items, NULL);
+ output = bsddialog_menu(&conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
diff --git a/contrib/bsddialog/library_examples/mixedlist.c b/contrib/bsddialog/examples_library/mixedlist.c
index 8b918b707869..2a4e9102164c 100644
--- a/contrib/bsddialog/library_examples/mixedlist.c
+++ b/contrib/bsddialog/examples_library/mixedlist.c
@@ -13,7 +13,6 @@
#include <bsddialog.h>
-/* Actually this is an example for mixedmenu to reproduce dialog4ports(1) */
int main()
{
int i, j, output;
@@ -48,12 +47,12 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_mixedlist(conf, "dialog4ports", 20, 30, 11, 3, group,
+ output = bsddialog_mixedlist(&conf, "dialog4ports", 20, 30, 11, 3, group,
NULL,NULL);
bsddialog_end();
- printf("Mixedlist (dialog4ports):\n");
+ printf("Mixedlist:\n");
for (i=0; i<3; i++) {
for (j=0; j<group[i].nitems; j++) {
item = group[i].items[j];
diff --git a/contrib/bsddialog/library_examples/msgbox.c b/contrib/bsddialog/examples_library/msgbox.c
index 93ac5201425e..92943d563b78 100644
--- a/contrib/bsddialog/library_examples/msgbox.c
+++ b/contrib/bsddialog/examples_library/msgbox.c
@@ -27,7 +27,7 @@ int main()
printf("Error: %s\n", bsddialog_geterror());
return -1;
}
- input = bsddialog_msgbox(conf, "Example", 7, 20);
+ input = bsddialog_msgbox(&conf, "Example", 7, 20);
bsddialog_end();
/* User Input */
diff --git a/contrib/bsddialog/examples_library/pause.c b/contrib/bsddialog/examples_library/pause.c
new file mode 100644
index 000000000000..fa38120d989e
--- /dev/null
+++ b/contrib/bsddialog/examples_library/pause.c
@@ -0,0 +1,50 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2021 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <bsddialog.h>
+
+int main()
+{
+ int output;
+ struct bsddialog_conf conf;
+
+ bsddialog_initconf(&conf);
+ conf.title = "pause";
+
+ if (bsddialog_init() < 0)
+ return -1;
+
+ output = bsddialog_pause(&conf, "Example", 8, 50, 10);
+
+ bsddialog_end();
+
+ switch (output) {
+ case BSDDIALOG_YESOK:
+ printf("OK\n");
+ break;
+ case BSDDIALOG_ESC:
+ printf("ESC\n");
+ break;
+ case BSDDIALOG_NOCANCEL:
+ printf("Cancel\n");
+ break;
+ case BSDDIALOG_ERROR:
+ printf("Error: %s\n", bsddialog_geterror());
+ break;
+ case BSDDIALOG_TIMEOUT:
+ printf("Timeout\n");
+ break;
+ }
+
+ return output;
+}
diff --git a/contrib/bsddialog/library_examples/radiolist.c b/contrib/bsddialog/examples_library/radiolist.c
index 39570d4b6602..d4c93c3d406f 100644
--- a/contrib/bsddialog/library_examples/radiolist.c
+++ b/contrib/bsddialog/examples_library/radiolist.c
@@ -31,7 +31,7 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_radiolist(conf, "Example", 15, 30, 5, 5, items, NULL);
+ output = bsddialog_radiolist(&conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
diff --git a/contrib/bsddialog/examples_library/rangebox.c b/contrib/bsddialog/examples_library/rangebox.c
new file mode 100644
index 000000000000..624bd4e438e8
--- /dev/null
+++ b/contrib/bsddialog/examples_library/rangebox.c
@@ -0,0 +1,35 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2021 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <bsddialog.h>
+
+int main()
+{
+ int value, output;
+ struct bsddialog_conf conf;
+
+ bsddialog_initconf(&conf);
+ conf.title = "rangebox";
+
+ if (bsddialog_init() < 0)
+ return -1;
+
+ value = 5;
+ output = bsddialog_rangebox(&conf, "Example", 8, 50, 0, 10, &value);
+
+ bsddialog_end();
+
+ printf("Value: %d", value);
+
+ return output;
+}
diff --git a/contrib/bsddialog/examples_library/sade.c b/contrib/bsddialog/examples_library/sade.c
new file mode 100644
index 000000000000..95bfadc36df1
--- /dev/null
+++ b/contrib/bsddialog/examples_library/sade.c
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2021 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <bsddialog.h>
+
+/* Figure 15 - https://docs.freebsd.org/en/books/handbook/bsdinstall/ */
+int main()
+{
+ int i, output;
+ struct bsddialog_conf conf;
+ struct bsddialog_menuitem items[5] = {
+ {"", false, 0, "ada0", "16 GB GPT", ""},
+ {"", false, 1, "ada0p1", "512 KB freebsd-boot", ""},
+ {"", false, 1, "ada0p2", "15 GB freebsd-ufs", ""},
+ {"", false, 1, "ada0p3", "819 MB freebsd-swap none", ""},
+ {"", false, 0, "ada1", "16 GB", ""}
+ };
+
+ bsddialog_initconf(&conf);
+ conf.title = "Partition Editor";
+ char *text = "Please review the disk setup. When complete, press the "\
+ "Finish button";
+
+ conf.menu.align_left = true;
+
+ conf.button.ok_label = "Create";
+
+ conf.button.extra_button = true;
+ conf.button.extra_label = "Delete";
+
+ conf.button.no_label = "Cancel";
+
+ conf.button.help_button = true;
+ conf.button.help_label = "Revert";
+
+ conf.button.generic1_label = "Auto";
+ conf.button.generic2_label = "Finish";
+
+ conf.button.default_label= "Finish";
+
+ if (bsddialog_init() < 0)
+ return -1;
+
+ output = bsddialog_menu(&conf, text, 20, 0, 10, 5, items, NULL);
+
+ bsddialog_end();
+
+ printf("Menu:\n");
+ for (i=0; i<5; i++)
+ printf(" [%c] %s\n", items[i].on ? 'X' : ' ', items[i].name);
+
+
+ return output;
+}
diff --git a/contrib/bsddialog/library_examples/theme.c b/contrib/bsddialog/examples_library/theme.c
index 56ed4459cacb..74bc91b59fe6 100644
--- a/contrib/bsddialog/library_examples/theme.c
+++ b/contrib/bsddialog/examples_library/theme.c
@@ -34,9 +34,9 @@ int main()
return BSDDIALOG_ERROR;
while (true) {
- bsddialog_backtitle(conf, "Theme Example");
+ bsddialog_backtitle(&conf, "Theme Example");
- output = bsddialog_menu(conf, "Choose theme", 15, 40, 5, 5, items, NULL);
+ output = bsddialog_menu(&conf, "Choose theme", 15, 40, 5, 5, items, NULL);
if (output != BSDDIALOG_YESOK || items[4].on)
break;
diff --git a/contrib/bsddialog/examples_library/timebox.c b/contrib/bsddialog/examples_library/timebox.c
new file mode 100644
index 000000000000..ff7a7c254468
--- /dev/null
+++ b/contrib/bsddialog/examples_library/timebox.c
@@ -0,0 +1,58 @@
+/*-
+ * SPDX-License-Identifier: CC0-1.0
+ *
+ * Written in 2021 by Alfonso Sabato Siciliano.
+ * To the extent possible under law, the author has dedicated all copyright
+ * and related and neighboring rights to this software to the public domain
+ * worldwide. This software is distributed without any warranty, see:
+ * <http://creativecommons.org/publicdomain/zero/1.0/>.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <bsddialog.h>
+
+int main()
+{
+ int output;
+ unsigned int hh, mm, ss;
+ struct bsddialog_conf conf;
+ time_t clock;
+ struct tm *localtm;
+
+ time(&clock);
+ localtm = localtime(&clock);
+ hh = localtm->tm_hour;
+ mm = localtm->tm_min;
+ ss = localtm->tm_sec;
+
+ bsddialog_initconf(&conf);
+ conf.title = "timebox";
+ conf.hline = "Press TAB and arrows";
+
+ if (bsddialog_init() < 0)
+ return -1;
+
+ output = bsddialog_timebox(&conf, "Example", 10, 50, &hh, &mm, &ss);
+
+ bsddialog_end();
+
+ switch (output) {
+ case BSDDIALOG_YESOK:
+ printf("Time: [%u:%u:%u]\n", hh, mm, ss);
+ break;
+ case BSDDIALOG_ESC:
+ printf("ESC\n");
+ break;
+ case BSDDIALOG_NOCANCEL:
+ printf("Cancel\n");
+ break;
+ case BSDDIALOG_ERROR:
+ printf("Error: %s\n", bsddialog_geterror());
+ break;
+ }
+
+ return output;
+}
diff --git a/contrib/bsddialog/library_examples/treeview.c b/contrib/bsddialog/examples_library/treeview.c
index d4c7afb4a1d0..628f24ffb287 100644
--- a/contrib/bsddialog/library_examples/treeview.c
+++ b/contrib/bsddialog/examples_library/treeview.c
@@ -27,11 +27,13 @@ int main()
bsddialog_initconf(&conf);
conf.title = "radiolist";
+ conf.menu.no_tags = true;
+ conf.menu.align_left = true;
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_treeview(conf, "Example", 15, 30, 5, 5, items, NULL);
+ output = bsddialog_radiolist(&conf, "Example", 15, 30, 5, 5, items, NULL);
bsddialog_end();
diff --git a/contrib/bsddialog/library_examples/yesno.c b/contrib/bsddialog/examples_library/yesno.c
index 035b65c69a12..783fcf57cbb6 100644
--- a/contrib/bsddialog/library_examples/yesno.c
+++ b/contrib/bsddialog/examples_library/yesno.c
@@ -24,7 +24,7 @@ int main()
if (bsddialog_init() < 0)
return -1;
- output = bsddialog_yesno(conf, "Example", 7, 25);
+ output = bsddialog_yesno(&conf, "Example", 7, 25);
bsddialog_end();
diff --git a/contrib/bsddialog/examples_utility/buildlist.sh b/contrib/bsddialog/examples_utility/buildlist.sh
new file mode 100755
index 000000000000..cefeea8f3c51
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/buildlist.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title buildlist --buildlist "Hello World!" 15 40 5 \
+ "Tag 1" "DESC 1 xyz" off \
+ "Tag 2" "DESC 2 xyz" off \
+ "Tag 3" "DESC 3 xyz" on \
+ "Tag 4" "DESC 4 xyz" off \
+ "Tag 5" "DESC 5 xyz" off \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/checklist.sh b/contrib/bsddialog/examples_utility/checklist.sh
new file mode 100755
index 000000000000..5f9a17cb64b1
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/checklist.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title checklist --checklist "Hello World!" 15 30 5 \
+ "Tag 1" "DESC 1 xyz" on \
+ "Tag 2" "DESC 2 xyz" off \
+ "Tag 3" "DESC 3 xyz" on \
+ "Tag 4" "DESC 4 xyz" off \
+ "Tag 5" "DESC 5 xyz" on \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/form.sh b/contrib/bsddialog/examples_utility/form.sh
new file mode 100755
index 000000000000..5d6b6ee1b606
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/form.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title " form " --form "Hello World!" 12 40 5 \
+ Label1: 1 1 Value1 1 9 18 25 \
+ Label2: 2 1 Value2 2 9 18 25 \
+ Label3: 3 1 Value3 3 9 18 25 \
+ Label4: 4 1 Value4 4 9 18 25 \
+ Label5: 5 1 Value5 5 9 18 25 \
+ 2>out.txt ; cat out.txt ; rm out.txt
+
+
diff --git a/contrib/bsddialog/utility_examples/gauge_example.sh b/contrib/bsddialog/examples_utility/gauge.sh
index b17f20274c79..82d15655efe2 100755
--- a/contrib/bsddialog/utility_examples/gauge_example.sh
+++ b/contrib/bsddialog/examples_utility/gauge.sh
@@ -1,4 +1,12 @@
#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
input="A B C D E F G"
total=`echo $input | awk '{print split($0, a)}'`
diff --git a/contrib/bsddialog/examples_utility/infobox.sh b/contrib/bsddialog/examples_utility/infobox.sh
new file mode 100755
index 000000000000..468ecff826fd
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/infobox.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+
+./bsddialog --sleep 3 --title infobox --infobox "Hello World!\n3 seconds" 6 20
diff --git a/contrib/bsddialog/examples_utility/inputbox.sh b/contrib/bsddialog/examples_utility/inputbox.sh
new file mode 100755
index 000000000000..27073468a478
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/inputbox.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title " inputbox " --inputbox "Hello World!" 12 40 init \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/menu.sh b/contrib/bsddialog/examples_utility/menu.sh
new file mode 100755
index 000000000000..66c9f54beb4c
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/menu.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title menu --menu "Hello World!" 15 30 5 \
+ "Tag 1" "DESC 1 xyz" \
+ "Tag 2" "DESC 2 xyz" \
+ "Tag 3" "DESC 3 xyz" \
+ "Tag 4" "DESC 4 xyz" \
+ "Tag 5" "DESC 5 xyz" \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/mixedform.sh b/contrib/bsddialog/examples_utility/mixedform.sh
new file mode 100755
index 000000000000..6677c20781ad
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/mixedform.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --insecure --title " mixedform " --mixedform "Hello World!" 12 40 5 \
+ Label: 1 1 Entry 1 11 18 25 0 \
+ Label: 2 1 Read-Only 2 11 18 25 2 \
+ Password: 3 1 Value2 3 11 18 25 1 \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/mixedgauge.sh b/contrib/bsddialog/examples_utility/mixedgauge.sh
new file mode 100755
index 000000000000..940972aeb174
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/mixedgauge.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+
+input="A B C D E F G H"
+total=`echo $input | awk '{print split($0, a)}'`
+curr=1
+for i in $input
+do
+ perc="$(expr $(expr $curr "*" 100 ) "/" $total )"
+ curr=`expr $curr + 1`
+ ./bsddialog --title " mixedgauge " --mixedgauge "Example" 20 38 $perc \
+ "Hidden!" 8 \
+ "Label 1" 0 \
+ "Label 2" 1 \
+ "Label 3" 2 \
+ "Label 4" 3 \
+ "Label 5" 4 \
+ "Label 6" 5 \
+ "Label 7" 6 \
+ "Label 8" 7 \
+ "Label 9" 9 \
+ "Label X" -- -$perc
+ sleep 1
+done
+
diff --git a/contrib/bsddialog/examples_utility/msgbox.sh b/contrib/bsddialog/examples_utility/msgbox.sh
new file mode 100755
index 000000000000..49cb626f4055
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/msgbox.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title msgbox --msgbox "Hello World!" 6 20
diff --git a/contrib/bsddialog/examples_utility/passwordbox.sh b/contrib/bsddialog/examples_utility/passwordbox.sh
new file mode 100755
index 000000000000..5c6a91e0f057
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/passwordbox.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --insecure --title " password " --passwordbox "Hello World!" 12 40 \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/passwordform.sh b/contrib/bsddialog/examples_utility/passwordform.sh
new file mode 100755
index 000000000000..5cfe0b0fa0a1
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/passwordform.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --insecure --title " passwordform " --passwordform "Example" 12 40 5 \
+ Password1: 1 1 Value1 1 12 18 25 \
+ Password2: 2 1 Value2 2 12 18 25 \
+ Password3: 3 1 Value3 3 12 18 25 \
+ Password4: 4 1 Value4 4 12 18 25 \
+ Password5: 5 1 Value5 5 12 18 25 \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/radiolist.sh b/contrib/bsddialog/examples_utility/radiolist.sh
new file mode 100755
index 000000000000..c1c7724eb09d
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/radiolist.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title radiolist --radiolist "Hello World!" 15 30 5 \
+ "Tag 1" "DESC 1 xyz" off \
+ "Tag 2" "DESC 2 xyz" off \
+ "Tag 3" "DESC 3 xyz" on \
+ "Tag 4" "DESC 4 xyz" off \
+ "Tag 5" "DESC 5 xyz" off \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/treeview.sh b/contrib/bsddialog/examples_utility/treeview.sh
new file mode 100755
index 000000000000..5286de673a1d
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/treeview.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title treeview --treeview "Hello World!" 15 40 5 \
+ 0 "Tag 1" "DESC 1 xyz" off \
+ 1 "Tag 2" "DESC 2 xyz" off \
+ 2 "Tag 3" "DESC 3 xyz" on \
+ 1 "Tag 4" "DESC 4 xyz" off \
+ 1 "Tag 5" "DESC 5 xyz" off \
+ 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/examples_utility/yesno.sh b/contrib/bsddialog/examples_utility/yesno.sh
new file mode 100755
index 000000000000..7d1d33530606
--- /dev/null
+++ b/contrib/bsddialog/examples_utility/yesno.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+#-
+# SPDX-License-Identifier: CC0-1.0
+#
+# Written in 2021 by Alfonso Sabato Siciliano.
+# To the extent possible under law, the author has dedicated all copyright
+# and related and neighboring rights to this software to the public domain
+# worldwide. This software is distributed without any warranty, see:
+# <http://creativecommons.org/publicdomain/zero/1.0/>.
+
+./bsddialog --title yesno --yesno "Hello World!" 6 25
diff --git a/contrib/bsddialog/lib/GNUMakefile b/contrib/bsddialog/lib/GNUMakefile
index 26dbdce9d4a0..045b58828a07 100644
--- a/contrib/bsddialog/lib/GNUMakefile
+++ b/contrib/bsddialog/lib/GNUMakefile
@@ -1,15 +1,14 @@
# PUBLIC DOMAIN - NO WARRANTY, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>
#
-# Written by Alfonso Sabato Siciliano
+# Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.1
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h
-SOURCES = barbox.c editorbox.c formbox.c lib_util.c menubox.c textbox.c \
- timebox.c commandbox.c filebox.c infobox.c libbsddialog.c messagebox.c \
- theme.c
+SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
+ messagebox.c textbox.c theme.c timebox.c
OBJECTS = $(SOURCES:.c=.o)
CFLAGS = -g -Wall -Werror -fpic
LDFLAGS = -lform -lncurses -ltinfo
diff --git a/contrib/bsddialog/lib/Makefile b/contrib/bsddialog/lib/Makefile
index 74b6bc174a38..99dfea4d77e0 100644
--- a/contrib/bsddialog/lib/Makefile
+++ b/contrib/bsddialog/lib/Makefile
@@ -1,15 +1,14 @@
# Any copyright is dedicated to the Public Domain, see:
# <http://creativecommons.org/publicdomain/zero/1.0/>
#
-# Written by Alfonso Sabato Siciliano
+# Written in 2021 by Alfonso Sabato Siciliano
VERSION = 0.1
LIBRARY = bsddialog
LIBRARY_SO = lib${LIBRARY:=.so}
HEADERS = bsddialog.h bsddialog_theme.h
-SOURCES = barbox.c editorbox.c formbox.c lib_util.c menubox.c textbox.c \
- timebox.c commandbox.c filebox.c infobox.c libbsddialog.c messagebox.c \
- theme.c
+SOURCES = barbox.c formbox.c infobox.c libbsddialog.c lib_util.c menubox.c \
+ messagebox.c textbox.c theme.c timebox.c
OBJECTS= ${SOURCES:.c=.o}
FBSDFLAGS= -O2 -pipe -std=gnu99 -Wno-format-zero-length \
-fstack-protector-strong -Qunused-arguments
diff --git a/contrib/bsddialog/lib/barbox.c b/contrib/bsddialog/lib/barbox.c
index bb341605d6f5..b0d5c0febcf8 100644
--- a/contrib/bsddialog/lib/barbox.c
+++ b/contrib/bsddialog/lib/barbox.c
@@ -25,6 +25,9 @@
* SUCH DAMAGE.
*/
+#include <sys/param.h>
+
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -38,12 +41,18 @@
#include "lib_util.h"
#include "bsddialog_theme.h"
+#define BARMARGIN 3
+#define MINBARWIDTH 10
+#define MINWIDTH (VBORDERS + MINBARWIDTH + BARMARGIN * 2)
+#define MINHEIGHT 7 /* without text */
+
/* "Bar": gauge - mixedgauge - rangebox - pause */
extern struct bsddialog_theme t;
static void
-draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, int label)
+draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel,
+ int label)
{
char labelstr[128];
int i, blue_x, color;
@@ -52,7 +61,7 @@ draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, int
wmove(win, y, x);
for (i = 0; i < size; i++) {
- color = (i <= blue_x) ? t.currbarcolor : t.barcolor;
+ color = (i <= blue_x) ? t.bar.f_color : t.bar.color;
wattron(win, color);
waddch(win, ' ');
wattroff(win, color);
@@ -64,34 +73,106 @@ draw_perc_bar(WINDOW *win, int y, int x, int size, int perc, bool withlabel, int
sprintf(labelstr, "%3d%%", perc);
wmove(win, y, x + size/2 - 2);
for (i=0; i < (int) strlen(labelstr); i++) {
- color = ( (blue_x + 1) <= (size/2 - (int) strlen(labelstr)/2 + i) ) ?
- t.barcolor : t.currbarcolor;
+ color = (blue_x + 1 <= size/2 - (int)strlen(labelstr)/2 + i ) ?
+ t.bar.color : t.bar.f_color;
wattron(win, color);
waddch(win, labelstr[i]);
wattroff(win, color);
}
}
-int bsddialog_gauge(struct bsddialog_conf conf, char* text, int rows, int cols, int perc)
+static int
+bar_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
+ char *text, struct buttons *bs)
{
- WINDOW *widget, *bar, *shadow;
- char input[2048];
- int i, y, x;
- bool mainloop = true;
+ int maxword, maxline, nlines, buttonswidth;
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- false) <0)
- return -1;
+ if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
+ return BSDDIALOG_ERROR;
- bar = new_boxed_window(conf, y+rows -4, x+3, 3, cols-6, RAISED);
+ buttonswidth = 0;
+ if (bs != NULL) { /* gauge has not buttons */
+ buttonswidth= bs->nbuttons * bs->sizebutton;
+ if (bs->nbuttons > 0)
+ buttonswidth += (bs->nbuttons-1) * t.button.space;
+ }
- wrefresh(widget);
- wrefresh(bar);
+ if (cols == BSDDIALOG_AUTOSIZE) {
+ *w = VBORDERS;
+ /* buttons size */
+ *w += buttonswidth;
+ /* bar size */
+ *w = MAX(*w, MINWIDTH);
+ /* text size*/
+ *w = MAX((int)(maxline + VBORDERS + t.text.hmargin * 2), *w);
+ /* avoid terminal overflow */
+ *w = MIN(*w, widget_max_width(conf));
+ }
- while (mainloop) {
- draw_perc_bar(bar, 1, 1, cols-8, perc, false, -1 /*unused*/);
+ if (rows == BSDDIALOG_AUTOSIZE) {
+ *h = MINHEIGHT;
+ if (maxword > 0)
+ *h += 1;
+ /* avoid terminal overflow */
+ *h = MIN(*h, widget_max_height(conf));
+ }
+
+ return (0);
+}
+static int
+bar_checksize(char *text, int rows, int cols, struct buttons *bs)
+{
+ int minheight, minwidth;
+
+ minwidth = 0;
+ if (bs != NULL) { /* gauge has not buttons */
+ minwidth = bs->nbuttons * bs->sizebutton;
+ if (bs->nbuttons > 0)
+ minwidth += (bs->nbuttons-1) * t.button.space;
+ }
+ minwidth = MAX(minwidth + VBORDERS, MINBARWIDTH);
+
+ if (cols< minwidth)
+ RETURN_ERROR("Few cols for this widget");
+
+ minheight = MINHEIGHT + ((text != NULL && strlen(text) > 0) ? 1 : 0);
+ if (rows < minheight)
+ RETURN_ERROR("Few rows for this mixedgauge");
+
+ return 0;
+}
+
+int
+bsddialog_gauge(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int perc)
+{
+ WINDOW *widget, *textpad, *bar, *shadow;
+ char input[2048], ntext[2048], *pntext;
+ int y, x, h, w, htextpad;
+ bool mainloop;
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_autosize(conf, rows, cols, &h, &w, text, NULL) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_checksize(text, h, w, NULL) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, false) != 0)
+ return BSDDIALOG_ERROR;
+
+ bar = new_boxed_window(conf, y+h-4, x+3, 3, w-6, RAISED);
+
+ mainloop = true;
+ while (mainloop) {
wrefresh(widget);
+ prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-4,
+ x+w-1-t.text.hmargin);
+ draw_perc_bar(bar, 1, 1, w-8, perc, false, -1 /*unused*/);
wrefresh(bar);
while (true) {
@@ -106,9 +187,10 @@ int bsddialog_gauge(struct bsddialog_conf conf, char* text, int rows, int cols,
scanf("%d", &perc);
perc = perc < 0 ? 0 : perc;
perc = perc > 100 ? 100 : perc;
- i = 2;
- wmove(widget, 1, 1);
- wclrtoeol(widget);
+ htextpad = 1;
+ wclear(textpad);
+ pntext = &ntext[0];
+ ntext[0] = '\0';
while (true) {
scanf("%s", input);
if (strcmp(input,"EOF") == 0) {
@@ -117,24 +199,28 @@ int bsddialog_gauge(struct bsddialog_conf conf, char* text, int rows, int cols,
}
if (strcmp(input,"XXX") == 0)
break;
- //print_text(conf, widget, 1, 1, cols-2, input);
- mvwaddstr(widget, 1, i, input);
- i = i + strlen(input) + 1;
- wrefresh(widget);
+ pntext[0] = ' ';
+ pntext++;
+ strcpy(pntext, input);
+ pntext += strlen(input);
}
+ print_textpad(conf, textpad, &htextpad, w-2-t.text.hmargin*2,
+ ntext);
}
delwin(bar);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return BSDDIALOG_YESOK;
}
-int bsddialog_mixedgauge(struct bsddialog_conf conf, char* text, int rows, int cols,
- unsigned int perc, int argc, char **argv)
+int
+bsddialog_mixedgauge(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int mainperc, unsigned int nminbars, char **minibars)
{
- WINDOW *widget, *bar, *shadow;
- int i, miniperc, y, x;
+ WINDOW *widget, *textpad, *bar, *shadow;
+ int i, output, miniperc, y, x, h, w, max_minbarlen;
+ int maxword, maxline, nlines, htextpad, ypad;
char states[11][16] = {
"[ Succeeded ]",
"[ Failed ]",
@@ -146,97 +232,156 @@ int bsddialog_mixedgauge(struct bsddialog_conf conf, char* text, int rows, int c
"[ In Progress ]",
"!!! BLANK !!!",
"[ N/A ]",
- "[ UNKNOWN ]",};
+ "[ UNKNOWN ]",
+ };
+
+ if (nminbars % 2 !=0)
+ RETURN_ERROR("Mixedgauge wants a pair name/perc");
- if (new_widget(conf, &widget, &y, &x, NULL, &rows, &cols, &shadow,
- false) <0)
- return -1;
+ max_minbarlen = 0;
+ for (i=0; i < (int)(nminbars/2); i++)
+ max_minbarlen = MAX(max_minbarlen, (int) strlen(minibars[i*2]));
+ max_minbarlen += 3 + 16 /* seps + [...] or mainbar */;
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+
+ /* mixedgauge autosize */
+ if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (cols == BSDDIALOG_AUTOSIZE) {
+ w = max_minbarlen + HBORDERS;
+ w = MAX(max_minbarlen, maxline + 4);
+ w = MIN(w, widget_max_width(conf) - 1);
+ }
+ if (rows == BSDDIALOG_AUTOSIZE) {
+ h = 5; /* borders + mainbar */
+ h += nminbars/2;
+ h += (strlen(text) > 0 ? 3 : 0);
+ h = MIN(h, widget_max_height(conf) -1);
+ }
- bar = new_boxed_window(conf, y+rows -4, x+3, 3, cols-6, RAISED);
+ /* mixedgauge checksize */
+ if (w < max_minbarlen + 2)
+ RETURN_ERROR("Few cols for this mixedgauge");
+ if (h < 5 + (int)nminbars/2 + (strlen(text) > 0 ? 1 : 0))
+ RETURN_ERROR("Few rows for this mixedgauge");
+
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ output = new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w,
+ RAISED, &textpad, &htextpad, text, false);
+ if (output == BSDDIALOG_ERROR)
+ return output;
/* mini bars */
- for (i=0; i < (argc/2); i++) {
- miniperc = atol(argv[i*2 + 1]);
+ for (i=0; i < (int)nminbars/2; i++) {
+ miniperc = atol(minibars[i*2 + 1]);
if (miniperc == 8)
continue;
- mvwaddstr(widget, i+1, 2, argv[i*2]);
+ mvwaddstr(widget, i+1, 2, minibars[i*2]);
if (miniperc > 9)
- mvwaddstr(widget, i+1, cols-2-15, states[10]);
+ mvwaddstr(widget, i+1, w-2-15, states[10]);
else if (miniperc >= 0 && miniperc <= 9)
- mvwaddstr(widget, i+1, cols-2-15, states[miniperc]);
+ mvwaddstr(widget, i+1, w-2-15, states[miniperc]);
else { //miniperc < 0
miniperc = abs(miniperc);
- mvwaddstr(widget, i+1, cols-2-15, "[ ]");
- draw_perc_bar(widget, i+1, 1+cols-2-15, 13, miniperc,
+ mvwaddstr(widget, i+1, w-2-15, "[ ]");
+ draw_perc_bar(widget, i+1, 1+w-2-15, 13, miniperc,
false, -1 /*unused*/);
}
}
- print_text(conf, widget, rows-6, 2, cols-2, text);
-
+ wrefresh(widget);
+ ypad = y + h - 5 - htextpad;
+ ypad = ypad < y+(int)nminbars/2 ? y+nminbars/2 : ypad;
+ prefresh(textpad, 0, 0, ypad, x+2, y+h-4, x+w-2);
+
/* main bar */
- draw_perc_bar(bar, 1, 1, cols-8, perc, false, -1 /*unused*/);
+ bar = new_boxed_window(conf, y+h -4, x+3, 3, w-6, RAISED);
+
+ draw_perc_bar(bar, 1, 1, w-8, mainperc, false, -1 /*unused*/);
- wattron(bar, t.barcolor);
+ wattron(bar, t.bar.color);
mvwaddstr(bar, 0, 2, "Overall Progress");
- wattroff(bar, t.barcolor);
+ wattroff(bar, t.bar.color);
- wrefresh(widget);
wrefresh(bar);
- getch();
+ /* getch(); port ncurses shows nothing */
delwin(bar);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return BSDDIALOG_YESOK;
}
int
-bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols, int min,
- int max, int *value)
+bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ int min, int max, int *value)
{
- WINDOW *widget, *bar, *shadow;
- int y, x;
+ WINDOW *widget, *textpad, *bar, *shadow;
+ int i, y, x, h, w, htextpad;
bool loop, buttupdate, barupdate;
- int input, currvalue, output, sizebar;
+ int input, currvalue, output, sizebar, bigchange, positions;
float perc;
- int positions = max - min + 1;
struct buttons bs;
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
+ if (value == NULL)
+ RETURN_ERROR("*value cannot be NULL");
+
+ if (min >= max)
+ RETURN_ERROR("min >= max");
- bar = new_boxed_window(conf, y + rows - 6, x +7, 3, cols-14, RAISED);
+ currvalue = *value;
+ positions = max - min + 1;
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
- if (value == NULL)
- RETURN_ERROR("*value == NULL");
-
- currvalue = *value;
- sizebar = cols - 16;
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_checksize(text, h, w, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
+ x+w-1-t.text.hmargin);
+
+ sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
+ bigchange = MAX(1, sizebar/10);
+
+ bar = new_boxed_window(conf, y + h - 6, x + 1 + BARMARGIN, 3,
+ sizebar + 2, RAISED);
+
loop = buttupdate = barupdate = true;
while(loop) {
+ if (buttupdate) {
+ draw_buttons(widget, h-2, w, bs, true);
+ wrefresh(widget);
+ buttupdate = false;
+ }
if (barupdate) {
- perc = ((float)(currvalue - min)*100) / ((float)positions-1);
+ perc = ((float)(currvalue - min)*100) / (positions-1);
draw_perc_bar(bar, 1, 1, sizebar, perc, true, currvalue);
barupdate = false;
wrefresh(bar);
}
- if (buttupdate) {
- draw_buttons(widget, rows-2, cols, bs, true);
- wrefresh(widget);
- buttupdate = false;
- }
-
input = getch();
switch(input) {
- case 10: // Enter
- output = bs.value[bs.curr]; // values -> outputs
+ case KEY_ENTER:
+ case 10: /* Enter */
+ output = bs.value[bs.curr];
*value = currvalue;
loop = false;
break;
@@ -244,7 +389,7 @@ bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols, i
output = BSDDIALOG_ESC;
loop = false;
break;
- case '\t': // TAB
+ case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
@@ -260,6 +405,26 @@ bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols, i
buttupdate = true;
}
break;
+ case KEY_HOME:
+ currvalue = max;
+ barupdate = true;
+ break;
+ case KEY_END:
+ currvalue = min;
+ barupdate = true;
+ break;
+ case KEY_NPAGE:
+ currvalue -= bigchange;
+ if (currvalue < min)
+ currvalue = min;
+ barupdate = true;
+ break;
+ case KEY_PPAGE:
+ currvalue += bigchange;
+ if (currvalue > max)
+ currvalue = max;
+ barupdate = true;
+ break;
case KEY_UP:
if (currvalue < max) {
currvalue++;
@@ -272,58 +437,132 @@ bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols, i
barupdate = true;
}
break;
+ case KEY_F(1):
+ if (conf->hfile == NULL)
+ break;
+ if (f1help(conf) != 0)
+ return BSDDIALOG_ERROR;
+ /* No break! the terminal size can change */
+ case KEY_RESIZE:
+ hide_widget(y, x, h, w,conf->shadow);
+
+ /*
+ * Unnecessary, but, when the columns decrease the
+ * following "refresh" seem not work
+ */
+ refresh();
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_checksize(text, h, w, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ wclear(shadow);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
+ wresize(shadow, h, w);
+
+ wclear(widget);
+ mvwin(widget, y, x);
+ wresize(widget, h, w);
+
+ htextpad = 1;
+ wclear(textpad);
+ wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
+
+ sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
+ bigchange = MAX(1, sizebar/10);
+ wclear(bar);
+ mvwin(bar, y + h - 6, x + 1 + BARMARGIN);
+ wresize(bar, 3, sizebar + 2);
+
+ if(update_widget_withtextpad(conf, shadow, widget, h, w,
+ RAISED, textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
+ x+w-1-t.text.hmargin);
+
+ draw_borders(conf, bar, 3, sizebar + 2, RAISED);
+
+ barupdate = true;
+ buttupdate = true;
+ break;
+ default:
+ for (i = 0; i < (int) bs.nbuttons; i++)
+ if (tolower(input) == tolower((bs.label[i])[0])) {
+ output = bs.value[i];
+ loop = false;
+ }
}
}
delwin(bar);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
-int bsddialog_pause(struct bsddialog_conf conf, char* text, int rows, int cols, int sec)
+int
+bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int sec)
{
- WINDOW *widget, *bar, *shadow;
- int output, y, x;
+ WINDOW *widget, *textpad, *bar, *shadow;
+ int i, output, y, x, h, w, htextpad;
bool loop, buttupdate, barupdate;
- int input, currvalue, sizebar;
+ int input, tout, sizebar;
float perc;
struct buttons bs;
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
-
- bar = new_boxed_window(conf, y + rows - 6, x +7, 3, cols-14, RAISED);
-
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
- currvalue = sec;
- sizebar = cols-16;
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_checksize(text, h, w, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
+ x+w-1-t.text.hmargin);
+
+ sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
+ bar = new_boxed_window(conf, y + h - 6, x + 1 + BARMARGIN, 3,
+ sizebar + 2, RAISED);
+
+ tout = sec;
nodelay(stdscr, TRUE);
timeout(1000);
- //wtimeout(buttwin, 2);
loop = buttupdate = barupdate = true;
while(loop) {
if (barupdate) {
- perc = ((float)(currvalue*100)) / ((float)sec);
- draw_perc_bar(bar, 1, 1, sizebar, perc, true, currvalue);
+ perc = (float)tout * 100 / sec;
+ draw_perc_bar(bar, 1, 1, sizebar, perc, true, tout);
barupdate = false;
wrefresh(bar);
}
if (buttupdate) {
- draw_buttons(widget, rows-2, cols, bs, true);
+ draw_buttons(widget, h-2, w, bs, true);
wrefresh(widget);
buttupdate = false;
}
input = getch();
- if(input < 0) {
- currvalue--;
- if (currvalue < 0) {
- output = BSDDIALOG_ERROR;
+ if(input < 0) { /* timeout */
+ tout--;
+ if (tout < 0) {
+ output = BSDDIALOG_TIMEOUT;
break;
}
else {
@@ -332,15 +571,16 @@ int bsddialog_pause(struct bsddialog_conf conf, char* text, int rows, int cols,
}
}
switch(input) {
- case 10: // Enter
- output = bs.value[bs.curr]; // values -> outputs
+ case KEY_ENTER:
+ case 10: /* Enter */
+ output = bs.value[bs.curr];
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
- case '\t': // TAB
+ case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
@@ -356,14 +596,72 @@ int bsddialog_pause(struct bsddialog_conf conf, char* text, int rows, int cols,
buttupdate = true;
}
break;
+ case KEY_F(1):
+ if (conf->hfile == NULL)
+ break;
+ if (f1help(conf) != 0)
+ return BSDDIALOG_ERROR;
+ /* No break! the terminal size can change */
+ case KEY_RESIZE:
+ hide_widget(y, x, h, w,conf->shadow);
+
+ /*
+ * Unnecessary, but, when the columns decrease the
+ * following "refresh" seem not work
+ */
+ refresh();
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_autosize(conf, rows, cols, &h, &w, text, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (bar_checksize(text, h, w, &bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ wclear(shadow);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
+ wresize(shadow, h, w);
+
+ wclear(widget);
+ mvwin(widget, y, x);
+ wresize(widget, h, w);
+
+ htextpad = 1;
+ wclear(textpad);
+ wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
+
+ sizebar = w - HBORDERS - 2 - BARMARGIN * 2;
+ wclear(bar);
+ mvwin(bar, y + h - 6, x + 1 + BARMARGIN);
+ wresize(bar, 3, sizebar + 2);
+
+ if(update_widget_withtextpad(conf, shadow, widget, h, w,
+ RAISED, textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ prefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-7,
+ x+w-1-t.text.hmargin);
+
+ draw_borders(conf, bar, 3, sizebar + 2, RAISED);
+
+ barupdate = true;
+ buttupdate = true;
+ break;
+ default:
+ for (i = 0; i < (int) bs.nbuttons; i++)
+ if (tolower(input) == tolower((bs.label[i])[0])) {
+ output = bs.value[i];
+ loop = false;
+ }
}
}
nodelay(stdscr, FALSE);
delwin(bar);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
-
diff --git a/contrib/bsddialog/lib/bsddialog.3 b/contrib/bsddialog/lib/bsddialog.3
new file mode 100644
index 000000000000..7e1238f38e52
--- /dev/null
+++ b/contrib/bsddialog/lib/bsddialog.3
@@ -0,0 +1,42 @@
+.Dd $Mdocdate$
+.Dt PROGNAME section
+.Os
+.Sh NAME
+.Nm progname
+.Nd one line about what it does
+.\" .Sh LIBRARY
+.\" For sections 2, 3, and 9 only.
+.\" Not used in OpenBSD.
+.Sh SYNOPSIS
+.Nm progname
+.Op Fl options
+.Ar
+.Sh DESCRIPTION
+The
+.Nm
+utility processes files ...
+.\" .Sh CONTEXT
+.\" For section 9 functions only.
+.\" .Sh IMPLEMENTATION NOTES
+.\" Not used in OpenBSD.
+.\" .Sh RETURN VALUES
+.\" For sections 2, 3, and 9 function return values only.
+.\" .Sh ENVIRONMENT
+.\" For sections 1, 6, 7, and 8 only.
+.\" .Sh FILES
+.\" .Sh EXIT STATUS
+.\" For sections 1, 6, and 8 only.
+.\" .Sh EXAMPLES
+.\" .Sh DIAGNOSTICS
+.\" For sections 1, 4, 6, 7, 8, and 9 printf/stderr messages only.
+.\" .Sh ERRORS
+.\" For sections 2, 3, 4, and 9 errno settings only.
+.\" .Sh SEE ALSO
+.\" .Xr foobar 1
+.\" .Sh STANDARDS
+.\" .Sh HISTORY
+.\" .Sh AUTHORS
+.\" .Sh CAVEATS
+.\" .Sh BUGS
+.\" .Sh SECURITY CONSIDERATIONS
+.\" Not used in OpenBSD.
diff --git a/contrib/bsddialog/lib/bsddialog.h b/contrib/bsddialog/lib/bsddialog.h
index e6c2cc67f581..de6dc100b8c3 100644
--- a/contrib/bsddialog/lib/bsddialog.h
+++ b/contrib/bsddialog/lib/bsddialog.h
@@ -25,11 +25,13 @@
* SUCH DAMAGE.
*/
-#ifndef _BSDDIALOG_H_
-#define _BSDDIALOG_H_
+#ifndef _LIBBSDDIALOG_H_
+#define _LIBBSDDIALOG_H_
#include <stdbool.h>
+#define LIBBSDDIALOG_VERSION "0.1-devel"
+
/* Exit status */
#define BSDDIALOG_ERROR -1
#define BSDDIALOG_YESOK 0
@@ -37,7 +39,10 @@
#define BSDDIALOG_HELP 2
#define BSDDIALOG_EXTRA 3
#define BSDDIALOG_ITEM_HELP 4
-#define BSDDIALOG_ESC 5
+#define BSDDIALOG_TIMEOUT 5
+#define BSDDIALOG_ESC 6
+#define BSDDIALOG_GENERIC1 7
+#define BSDDIALOG_GENERIC2 8
/* size and position */
#define BSDDIALOG_FULLSCREEN -1
@@ -45,55 +50,40 @@
#define BSDDIALOG_CENTER -1
struct bsddialog_conf {
- /* conf.* */
bool ascii_lines;
- int aspect_ratio;
- int x;
- int y;
+ int aspect_ratio;
+ int x;
+ int y;
bool clear;
- int *get_height;
- int *get_width;
+ int *get_height;
+ int *get_width;
char *hfile;
char *hline;
- /*int input_fd;*/
- /*bool keep_tite;*/
- /*bool keep_window;*/
- /*bool last_key;*/
- /*int max_input;*/
- /*bool no_kill;*/
bool no_lines;
- /*bool no_mouse; useful?*/
- /*bool scrollbar; useful?*/
- /*char *separate_witget;*/
bool shadow;
- /*bool size_err;*/
- int sleep;
- /*int timeout;*/
+ int sleep;
char *title;
- /* conf.text.* */
+
struct {
bool colors;
+ /* following members could be deleted in the future */
bool cr_wrap;
bool no_collapse;
bool no_nl_expand;
- /*bool tab_correct; textbox?*/
- /*int tab_len; textbox?*/
bool trim;
} text;
- /* conf.form.* */
- /*struct {
- bool insecure;
- } form;*/
- /* conf.menu.* */
+
struct {
bool align_left;
- char *colums_separator;
- char *default_item; /*delete, add int *focus to API?*/
- bool no_items;
- bool no_tags;
- /*bool visit_items;*/
+ char *default_item;
+ bool no_desc;
+ bool no_name;
} menu;
- /* conf.button.* */
+
+ struct {
+ int securech;
+ } form;
+
struct {
char *cancel_label;
bool defaultno;
@@ -101,6 +91,8 @@ struct bsddialog_conf {
char *exit_label;
bool extra_button;
char *extra_label;
+ char *generic1_label;
+ char *generic2_label;
bool help_button;
char *help_label;
bool no_cancel;
@@ -113,8 +105,8 @@ struct bsddialog_conf {
struct bsddialog_menuitem {
char *prefix;
- bool on;
- int depth;
+ bool on;
+ int depth;
char *name;
char *desc;
char *bottomdesc;
@@ -132,126 +124,97 @@ struct bsddialog_menugroup {
struct bsddialog_menuitem *items;
};
+struct bsddialog_formitem {
+ char *label;
+ unsigned int ylabel;
+ unsigned int xlabel;
+
+ char *init;
+ unsigned int yfield;
+ unsigned int xfield;
+ unsigned int fieldlen;
+ unsigned int maxvaluelen;
+ char *value; /* allocated memory */
+#define BSDDIALOG_FIELDHIDDEN 0x1
+#define BSDDIALOG_FIELDREADONLY 0x2
+ unsigned int flags;
+
+ char *bottomdesc; /* unimplemented for now */
+};
+
int bsddialog_init(void);
int bsddialog_end(void);
-int bsddialog_backtitle(struct bsddialog_conf conf, char *backtitle);
+int bsddialog_backtitle(struct bsddialog_conf *conf, char *backtitle);
const char *bsddialog_geterror(void);
+void bsddialog_initconf(struct bsddialog_conf *conf);
+/* funcs for tzsetup(8), they will be deleted */
int bsddialog_terminalheight(void);
int bsddialog_terminalwidth(void);
-void bsddialog_initconf(struct bsddialog_conf *conf);
/* widgets */
int
-bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_buildlist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
-bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int cols,
- unsigned int *yy, unsigned int *mm, unsigned int *dd);
-
-int
-bsddialog_checklist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_checklist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
-bsddialog_dselect(struct bsddialog_conf conf, char* text, int rows, int cols);
-
-int
-bsddialog_editbox(struct bsddialog_conf conf, char* text, int rows, int cols);
-
-int bsddialog_form(struct bsddialog_conf conf, char* text, int rows, int cols,
- int formheight, int argc, char **argv);
-
-int
-bsddialog_fselect(struct bsddialog_conf conf, char* text, int rows, int cols);
-
-int
-bsddialog_gauge(struct bsddialog_conf conf, char* text, int rows, int cols,
- int perc);
+bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int *yy, unsigned int *mm, unsigned int *dd);
int
-bsddialog_infobox(struct bsddialog_conf conf, char* text, int rows, int cols);
+bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int formheight, unsigned int nitems,
+ struct bsddialog_formitem *items);
int
-bsddialog_inputbox(struct bsddialog_conf conf, char* text, int rows, int cols);
+bsddialog_gauge(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int perc);
int
-bsddialog_inputmenu(struct bsddialog_conf conf, char* text, int rows, int cols);
+bsddialog_infobox(struct bsddialog_conf *conf, char* text, int rows, int cols);
int
-bsddialog_menu(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_menu(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
-bsddialog_mixedform(struct bsddialog_conf conf, char* text, int rows, int cols,
- int formheight, int argc, char **argv);
+bsddialog_mixedgauge(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int mainperc, unsigned int nminbars, char **minibars);
int
-bsddialog_mixedgauge(struct bsddialog_conf conf, char* text, int rows, int cols,
- unsigned int perc, int argc, char **argv);
-
-int
-bsddialog_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int ngroups, struct bsddialog_menugroup *groups,
int *focuslist, int *focusitem);
int
-bsddialog_msgbox(struct bsddialog_conf conf, char* text, int rows, int cols);
-
-int
-bsddialog_passwordbox(struct bsddialog_conf conf, char* text, int rows,
- int cols);
-
-int
-bsddialog_passwordform(struct bsddialog_conf conf, char* text, int rows,
- int cols, int formheight, int argc, char **argv);
-
-int
-bsddialog_pause(struct bsddialog_conf conf, char* text, int rows, int cols,
- int sec);
-
-int
-bsddialog_prgbox(struct bsddialog_conf conf, char* text, int rows, int cols,
- char *command);
+bsddialog_msgbox(struct bsddialog_conf *conf, char* text, int rows, int cols);
int
-bsddialog_programbox(struct bsddialog_conf conf, char* text, int rows,
- int cols);
+bsddialog_pause(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int sec);
int
-bsddialog_progressbox(struct bsddialog_conf conf, char* text, int rows,
- int cols);
-
-int
-bsddialog_radiolist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_radiolist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem);
int
-bsddialog_rangebox(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_rangebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
int min, int max, int *value);
int
-bsddialog_tailbox(struct bsddialog_conf conf, char* text, int rows, int cols);
-
-int
-bsddialog_tailboxbg(struct bsddialog_conf conf, char* text, int rows, int cols);
-
-int
-bsddialog_textbox(struct bsddialog_conf conf, char* text, int rows, int cols);
+bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols);
int
-bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int *hh, unsigned int *mm, unsigned int *ss);
-int
-bsddialog_treeview(struct bsddialog_conf conf, char* text, int rows, int cols,
- unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
- int *focusitem);
-
-int bsddialog_yesno(struct bsddialog_conf conf, char* text, int rows, int cols);
+int bsddialog_yesno(struct bsddialog_conf *conf, char* text, int rows, int cols);
#endif
diff --git a/contrib/bsddialog/lib/bsddialog_theme.h b/contrib/bsddialog/lib/bsddialog_theme.h
index b39b8840bce8..de44b456576a 100644
--- a/contrib/bsddialog/lib/bsddialog_theme.h
+++ b/contrib/bsddialog/lib/bsddialog_theme.h
@@ -39,45 +39,63 @@ enum bsddialog_color {
BSDDIALOG_WHITE,
};
+/* f_ for focus/selected/active/current element */
struct bsddialog_theme {
- int shadowcolor;
- unsigned int shadowrows;
- unsigned int shadowcols;
+ struct {
+ int color;
+ } terminal;
- int backgroundcolor;
- bool surroundtitle;
- int titlecolor;
- int lineraisecolor;
- int linelowercolor;
- int widgetcolor;
+ struct {
+ int color;
+ unsigned int h;
+ unsigned int w;
+ } shadow;
- unsigned int texthmargin;
+ struct {
+ int color;
+ bool delimtitle;
+ int titlecolor;
+ int lineraisecolor;
+ int linelowercolor;
+ int bottomtitlecolor;
+ } widget;
- int curritemcolor;
- int itemcolor;
- int currtagcolor;
- int tagcolor;
- int namesepcolor;
- int descsepcolor;
+ struct {
+ unsigned int hmargin;
+ } text;
- int currfieldcolor;
- int fieldcolor;
- int fieldreadonlycolor;
+ struct {
+ int arrowcolor;
+ int f_namecolor;
+ int namecolor;
+ int f_desccolor;
+ int desccolor;
+ int namesepcolor;
+ int descsepcolor;
+ } menu;
- int currbarcolor;
- int barcolor;
+ struct {
+ int f_fieldcolor;
+ int fieldcolor;
+ int readonlycolor;
+ } form;
- unsigned int buttonspace;
- int buttleftch;
- int buttrightchar;
- int currbuttdelimcolor;
- int buttdelimcolor;
- int currbuttoncolor;
- int buttoncolor;
- int currshortkeycolor;
- int shortkeycolor;
+ struct {
+ int f_color;
+ int color;
+ } bar;
- int bottomtitlecolor;
+ struct {
+ unsigned int space;
+ int leftch;
+ int rightch;
+ int delimcolor;
+ int f_delimcolor;
+ int color;
+ int f_color;
+ int shortcutcolor;
+ int f_shortcutcolor;
+ } button;
};
enum bsddialog_default_theme {
@@ -85,11 +103,12 @@ enum bsddialog_default_theme {
BSDDIALOG_THEME_BSDDIALOG,
BSDDIALOG_THEME_DEFAULT,
BSDDIALOG_THEME_DIALOG,
- BSDDIALOG_THEME_MAGENTA,
};
-int bsddialog_color(enum bsddialog_color background, enum bsddialog_color foreground);
-struct bsddialog_theme bsddialog_get_theme();
+int
+bsddialog_color(enum bsddialog_color background,
+ enum bsddialog_color foreground);
+struct bsddialog_theme bsddialog_get_theme(void);
void bsddialog_set_theme(struct bsddialog_theme theme);
int bsddialog_set_default_theme(enum bsddialog_default_theme theme);
diff --git a/contrib/bsddialog/lib/commandbox.c b/contrib/bsddialog/lib/commandbox.c
deleted file mode 100644
index e5d65166e230..000000000000
--- a/contrib/bsddialog/lib/commandbox.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * Copyright (c) 2021 Alfonso Sabato Siciliano
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <unistd.h>
-
-#ifdef PORTNCURSES
-#include <ncurses/curses.h>
-#else
-#include <curses.h>
-#endif
-
-#include "bsddialog.h"
-#include "lib_util.h"
-#include "bsddialog_theme.h"
-
-/* "Command": prgbox - programbox - progressbox */
-
-#define MAXINPUT 2048 /* in bsddialoh.h? in bsddialog.c get/set static maxinput? */
-
-extern struct bsddialog_theme t;
-
-static int
-command_handler(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey)
-{
- bool loop, update;
- int i, input;
- int output;
-
- loop = update = true;
- while(loop) {
- if (update) {
- draw_buttons(window, y, cols, bs, shortkey);
- update = false;
- }
- wrefresh(window);
- input = getch();
- switch (input) {
- case 10: /* Enter */
- output = bs.value[bs.curr];
- loop = false;
- break;
- case 27: /* Esc */
- output = BSDDIALOG_ESC;
- loop = false;
- break;
- case '\t': /* TAB */
- bs.curr = (bs.curr + 1) % bs.nbuttons;
- update = true;
- break;
- case KEY_LEFT:
- if (bs.curr > 0) {
- bs.curr--;
- update = true;
- }
- break;
- case KEY_RIGHT:
- if (bs.curr < (int) bs.nbuttons - 1) {
- bs.curr++;
- update = true;
- }
- break;
- default:
- if (shortkey) {
- for (i = 0; i < (int) bs.nbuttons; i++)
- if (input == (bs.label[i])[0]) {
- output = bs.value[i];
- loop = false;
- }
- }
- }
- }
-
- return output;
-}
-
-int
-bsddialog_prgbox(struct bsddialog_conf conf, char* text, int rows, int cols, char *command)
-{
- char line[MAXINPUT];
- WINDOW *widget, *pad, *shadow;
- int i, y, x, padrows, padcols, ys, ye, xs, xe;
- int output;
- int pipefd[2];
- struct buttons bs;
-
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
-
- get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
- NULL, BUTTONLABEL(help_label));
-
- if (text != NULL && conf.no_lines == false) {
- print_text(conf, widget, 1, 1, cols-2, text);
- mvwhline(widget, 2, 2, conf.ascii_lines ? '-' : ACS_HLINE, cols -4);
- wrefresh(widget);
- }
-
- padrows = text == NULL ? rows - 4 : rows - 6;
- padcols = cols - 2;
- ys = text == NULL ? y + 1 : y + 3;
- xs = x + 1;
- ye = ys + padrows;
- xe = xs + padcols;
-
- pad = newpad(padrows, padcols);
- wbkgd(pad, t.widgetcolor);
-
- pipe(pipefd);
- if (fork() == 0)
- {
- close(pipefd[0]); // close reading
-
- dup2(pipefd[1], 1); // send stdout to the pipe
- dup2(pipefd[1], 2); // send stderr to the pipe
-
- close(pipefd[1]); // this descriptor is no longer needed
-
- //const char *ls="/bin/ls";
- execl(command, command, NULL);
- return 0;
- }
- else
- {
- close(pipefd[1]); // close write
-
- i = 0;
- while (read(pipefd[0], line, MAXINPUT) != 0) {
- mvwaddstr(pad, i, 0, line);
- prefresh(pad, 0, 0, ys, xs, ye, xe);
- i++;
- }
- }
-
- output = command_handler(widget, rows-2, cols, bs, true);
-
- return output;
-}
-
-int bsddialog_programbox(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
- char line[MAXINPUT];
- WINDOW *widget, *pad, *shadow;
- int i, y, x, padrows, padcols, ys, ye, xs, xe, output;
- struct buttons bs;
-
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
-
- get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
- BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
-
- if (text != NULL && conf.no_lines == false) {
- mvwhline(widget, 2, 2, conf.ascii_lines ? '-' : ACS_HLINE, cols -4);
- wrefresh(widget);
- }
-
- padrows = text == NULL ? rows - 4 : rows - 6;
- padcols = cols - 2;
- ys = text == NULL ? y + 1 : y + 3;
- xs = x + 1;
- ye = ys + padrows;
- xe = xs + padcols;
-
- pad = newpad(padrows, padcols);
-
- i = 0;
- //while (fgets(line, MAXINPUT, stdin) != NULL) {
- while(getstr(line) != ERR){
- mvwaddstr(pad, i, 0, line);
- prefresh(pad, 0, 0, ys, xs, ye, xe);
- i++;
- }
-
- output = command_handler(widget, rows-2, cols, bs, true);
-
- return output;
-}
-
-int bsddialog_progressbox(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
- text = "Progressbox unimplemented";
- bsddialog_msgbox(conf, text, rows, cols);
- RETURN_ERROR(text);
-}
-
diff --git a/contrib/bsddialog/lib/formbox.c b/contrib/bsddialog/lib/formbox.c
index f636db7990dd..70e7d9498b90 100644
--- a/contrib/bsddialog/lib/formbox.c
+++ b/contrib/bsddialog/lib/formbox.c
@@ -25,13 +25,15 @@
* SUCH DAMAGE.
*/
+#include <sys/param.h>
+
+#include <ctype.h>
#include <stdlib.h>
+#include <string.h>
#ifdef PORTNCURSES
-#include <ncurses/curses.h>
#include <ncurses/form.h>
#else
-#include <curses.h>
#include <form.h>
#endif
@@ -39,82 +41,111 @@
#include "lib_util.h"
#include "bsddialog_theme.h"
+#define REDRAWFORM 14021986 /* magic number */
+#define ISFIELDHIDDEN(item) (item.flags & BSDDIALOG_FIELDHIDDEN)
+#define ISFIELDREADONLY(item) (item.flags & BSDDIALOG_FIELDREADONLY)
+
/* "Form": inputbox - passwordbox - form - passwordform - mixedform */
extern struct bsddialog_theme t;
-int bsddialog_inputmenu(struct bsddialog_conf conf, char* text, int rows, int cols)
+/* util struct for private buffer and view options */
+struct myfield {
+ int len;
+ char *buf;
+ int pos;
+ int size;
+ bool secure;
+ int securech;
+};
+#define GETMYFIELD(field) ((struct myfield*)field_userptr(field))
+#define GETMYFIELD2(form) ((struct myfield*)field_userptr(current_field(form)))
+
+static void insertch(struct myfield *mf, int ch)
{
- text = "Inputbox unimplemented";
- bsddialog_msgbox(conf, text, rows, cols);
- RETURN_ERROR(text);
+ int i;
+
+ if (mf->len == mf->size)
+ return;
+
+ for (i=mf->len-1; i>=mf->pos; i--) {
+ mf->buf[i+1] = mf->buf[i];
+ }
+
+ mf->buf[mf->pos] = ch;
+ mf->pos += 1;
+ mf->len += 1;
+ mf->buf[mf->len] = '\0';
}
-#define ITEMHIDDEN 0x1
-#define ISITEMHIDDEN(item) (item.itemflags & 0x1)
-#define ITEMREADONLY 0x2
-#define ISITEMREADONLY(item) (item.itemflags & 0x2)
-struct formitem {
- char *label;
- unsigned int ylabel;
- unsigned int xlabel;
- char *item;
- unsigned int yitem;
- unsigned int xitem;
- int itemlen;
- unsigned int inputlen;
- unsigned int itemflags;
-};
+static void shiftleft(struct myfield *mf)
+{
+ int i, last;
+
+ for (i=mf->pos; i<mf->len; i++) {
+ mf->buf[i] = mf->buf[i+1];
+ }
+
+ last = mf->len > 0 ? mf->len -1 : 0;
+ mf->buf[last] = '\0';
+ mf->len = last;
+}
static int
-mixedform_handler(WINDOW *widget, int y, int cols, struct buttons bs,
- bool shortkey, WINDOW *entry, FORM *form, FIELD **field, int nitems
- /*struct formitem *items*/)
+form_handler(struct bsddialog_conf *conf, WINDOW *widget, int y, int cols,
+ struct buttons bs, WINDOW *formwin, FORM *form, FIELD **cfield, int nitems,
+ struct bsddialog_formitem *items)
{
- bool loop, buttupdate, inentry = true;
- int input, output;
+ bool loop, buttupdate, informwin = true;
+ int i, input, output;
+ struct myfield *mf;
curs_set(2);
pos_form_cursor(form);
loop = buttupdate = true;
bs.curr = -1;
+ form_driver(form, REQ_END_LINE);
+ form_driver(form, REQ_END_LINE);
+ mf = GETMYFIELD2(form);
+ mf->pos = mf->len;
while(loop) {
if (buttupdate) {
- draw_buttons(widget, y, cols, bs, shortkey);
+ draw_buttons(widget, y, cols, bs, !informwin);
wrefresh(widget);
buttupdate = false;
}
- wrefresh(entry);
+ wrefresh(formwin);
input = getch();
switch(input) {
- case 10: // Enter
- if (inentry)
+ case KEY_ENTER:
+ case 10: /* Enter */
+ if (informwin)
break;
- output = bs.value[bs.curr]; // values -> buttvalues
- form_driver(form, REQ_NEXT_FIELD);
- form_driver(form, REQ_PREV_FIELD);
- /* add a struct for forms */
- /*for (i=0; i<nitems; i++) {
- bufp = field_buffer(field[i], 0);
- dprintf(fd, "\n+%s", bufp);
- bufp = field_buffer(field[i], 1);
- dprintf(fd, "-%s+", bufp);
- }*/
+ output = bs.value[bs.curr];
+ if (output == BSDDIALOG_YESOK) {
+ form_driver(form, REQ_NEXT_FIELD);
+ form_driver(form, REQ_PREV_FIELD);
+ for (i=0; i<nitems; i++) {
+ mf = GETMYFIELD(cfield[i]);
+ items[i].value = strdup(mf->buf);
+ }
+ }
loop = false;
break;
case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
- case '\t': // TAB
- if (inentry) {
+ case '\t': /* TAB */
+ if (informwin) {
bs.curr = 0;
- inentry = false;
+ informwin = false;
curs_set(0);
} else {
bs.curr++;
- inentry = bs.curr >= (int) bs.nbuttons ? true : false;
- if (inentry) {
+ informwin = bs.curr >= (int) bs.nbuttons ?
+ true : false;
+ if (informwin) {
curs_set(2);
pos_form_cursor(form);
}
@@ -122,8 +153,11 @@ mixedform_handler(WINDOW *widget, int y, int cols, struct buttons bs,
buttupdate = true;
break;
case KEY_LEFT:
- if (inentry) {
+ if (informwin) {
form_driver(form, REQ_PREV_CHAR);
+ mf = GETMYFIELD2(form);
+ if (mf->pos > 0)
+ mf->pos -= 1;
} else {
if (bs.curr > 0) {
bs.curr--;
@@ -132,7 +166,11 @@ mixedform_handler(WINDOW *widget, int y, int cols, struct buttons bs,
}
break;
case KEY_RIGHT:
- if (inentry) {
+ if (informwin) {
+ mf = GETMYFIELD2(form);
+ if (mf->pos >= mf->len)
+ break;
+ mf->pos += 1;
form_driver(form, REQ_NEXT_CHAR);
} else {
if (bs.curr < (int) bs.nbuttons - 1) {
@@ -144,32 +182,73 @@ mixedform_handler(WINDOW *widget, int y, int cols, struct buttons bs,
case KEY_UP:
if (nitems < 2)
break;
- set_field_fore(current_field(form), t.fieldcolor);
- set_field_back(current_field(form), t.fieldcolor);
+ set_field_fore(current_field(form), t.form.fieldcolor);
+ set_field_back(current_field(form), t.form.fieldcolor);
form_driver(form, REQ_PREV_FIELD);
form_driver(form, REQ_END_LINE);
- set_field_fore(current_field(form), t.currfieldcolor);
- set_field_back(current_field(form), t.currfieldcolor);
+ mf = GETMYFIELD2(form);
+ mf->pos = mf->len;
+ set_field_fore(current_field(form), t.form.f_fieldcolor);
+ set_field_back(current_field(form), t.form.f_fieldcolor);
break;
case KEY_DOWN:
if (nitems < 2)
break;
- set_field_fore(current_field(form), t.fieldcolor);
- set_field_back(current_field(form), t.fieldcolor);
+ set_field_fore(current_field(form), t.form.fieldcolor);
+ set_field_back(current_field(form), t.form.fieldcolor);
form_driver(form, REQ_NEXT_FIELD);
form_driver(form, REQ_END_LINE);
- set_field_fore(current_field(form), t.currfieldcolor);
- set_field_back(current_field(form), t.currfieldcolor);
+ mf = GETMYFIELD2(form);
+ mf->pos = mf->len;
+ set_field_fore(current_field(form), t.form.f_fieldcolor);
+ set_field_back(current_field(form), t.form.f_fieldcolor);
break;
case KEY_BACKSPACE:
+ case 127: /* Backspace */
+ mf = GETMYFIELD2(form);
+ if (mf->pos <= 0)
+ break;
form_driver(form, REQ_DEL_PREV);
+ mf = GETMYFIELD2(form);
+ mf->pos -= 1;
+ shiftleft(mf);
break;
case KEY_DC:
form_driver(form, REQ_DEL_CHAR);
+ mf = GETMYFIELD2(form);
+ if (mf->len-1 >= mf->pos)
+ shiftleft(mf);
+ break;
+ case KEY_F(1):
+ if (conf->hfile == NULL)
+ break;
+ if (f1help(conf) != 0)
+ return BSDDIALOG_ERROR;
+ /* No Break */
+ case KEY_RESIZE:
+ output = REDRAWFORM;
+ loop = false;
break;
default:
- if (inentry) {
- form_driver(form, input);
+ /*
+ * user input, add unicode chars to "public" buffer
+ */
+ if (informwin) {
+ mf = GETMYFIELD2(form);
+ if (mf->secure)
+ form_driver(form, mf->securech);
+ else
+ form_driver(form, input);
+ insertch(mf, input);
+ }
+ else {
+ for (i = 0; i < (int) bs.nbuttons; i++) {
+ if (tolower(input) ==
+ tolower((bs.label[i])[0])) {
+ output = bs.value[i];
+ loop = false;
+ }
+ }
}
break;
}
@@ -180,217 +259,214 @@ mixedform_handler(WINDOW *widget, int y, int cols, struct buttons bs,
return output;
}
-static int
-do_mixedform(struct bsddialog_conf conf, char* text, int rows, int cols,
- int formheight, int nitems, struct formitem *items)
+static void
+form_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
+ char *text, int linelen, unsigned int *formheight, int nitems,
+ struct buttons bs)
{
- WINDOW *widget, *entry, *shadow;
- int i, output, color, y, x;
- FIELD **field;
- FORM *form;
- struct buttons bs;
-
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
-
- entry = new_boxed_window(conf, y + rows - 3 - formheight -2, x +1,
- formheight+2, cols-2, LOWERED);
+ int textrow, menusize;
+
+ textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
+
+ if (cols == BSDDIALOG_AUTOSIZE) {
+ *w = VBORDERS;
+ /* buttons size */
+ *w += bs.nbuttons * bs.sizebutton;
+ *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
+ /* line size */
+ *w = MAX(*w, linelen + 3);
+ /*
+ * avoid terminal overflow,
+ * -1 fix false negative with big menu over the terminal and
+ * autosize, for example "portconfig /usr/ports/www/apache24/".
+ */
+ *w = MIN(*w, widget_max_width(conf)-1);
+ }
- get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
- BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
+ if (rows == BSDDIALOG_AUTOSIZE) {
+ *h = HBORDERS + 2 /* buttons */ + textrow;
- field = calloc(nitems + 1, sizeof(FIELD*));
- for (i=0; i < nitems; i++) {
- field[i] = new_field(1, items[i].itemlen, items[i].yitem-1, items[i].xitem-1, 0, 1);
- field_opts_off(field[i], O_STATIC);
- set_max_field(field[i], items[i].inputlen);
- set_field_buffer(field[i], 0, items[i].item);
- set_field_buffer(field[i], 1, items[i].item);
- field_opts_off(field[i], O_AUTOSKIP);
- field_opts_off(field[i], O_BLANK);
- //field_opts_off(field[i], O_BS_OVERLOAD);
-
- if (ISITEMHIDDEN(items[i]))
- field_opts_off(field[i], O_PUBLIC);
-
- if (ISITEMREADONLY(items[i])) {
- field_opts_off(field[i], O_EDIT);
- field_opts_off(field[i], O_ACTIVE);
- color = t.fieldreadonlycolor;
- } else {
- color = i == 0 ? t.currfieldcolor : t.fieldcolor;
+ if (*formheight == 0) {
+ *h += nitems + 2;
+ *h = MIN(*h, widget_max_height(conf));
+ menusize = MIN(nitems + 2, *h - (HBORDERS + 2 + textrow));
+ menusize -=2;
+ *formheight = menusize < 0 ? 0 : menusize;
}
- set_field_fore(field[i], color);
- set_field_back(field[i], color);
- }
- field[i] = NULL;
+ else /* h autosize with a fixed formheight */
+ *h = *h + *formheight + 2;
- if (nitems == 1) {// inputbox or passwordbox
- set_field_fore(field[0], t.widgetcolor);
- set_field_back(field[0], t.widgetcolor);
+ /* avoid terminal overflow */
+ *h = MIN(*h, widget_max_height(conf));
}
+ else {
+ if (*formheight == 0)
+ *formheight = MIN(rows-6-textrow, nitems);
+ }
+}
- form = new_form(field);
- set_form_win(form, entry);
- set_form_sub(form, derwin(entry, nitems, cols-4, 1, 1));
- post_form(form);
+static int
+form_checksize(int rows, int cols, char *text, int formheight, int nitems,
+ struct buttons bs)
+{
+ int mincols, textrow, formrows;
- for (i=0; i < nitems; i++)
- mvwaddstr(entry, items[i].ylabel, items[i].xlabel, items[i].label);
+ mincols = VBORDERS;
+ /* buttons */
+ mincols += bs.nbuttons * bs.sizebutton;
+ mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
+ /* line, comment to permet some cols hidden */
+ /* mincols = MAX(mincols, linelen); */
- wrefresh(entry);
+ if (cols < mincols)
+ RETURN_ERROR("Few cols, width < size buttons or "\
+ "labels + forms");
- output = mixedform_handler(widget, rows-2, cols, bs, true, entry, form,
- field, nitems /*,items*/);
+ textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
- unpost_form(form);
- free_form(form);
- for (i=0; i < nitems; i++)
- free_field(field[i]);
- free(field);
+ if (nitems > 0 && formheight == 0)
+ RETURN_ERROR("fields > 0 but formheight == 0, probably "\
+ "terminal too small");
- delwin(entry);
- end_widget(conf, widget, rows, cols, shadow);
+ formrows = nitems > 0 ? 3 : 0;
+ if (rows < 2 + 2 + formrows + textrow)
+ RETURN_ERROR("Few lines for this menus");
- return output;
+ return 0;
}
-int bsddialog_inputbox(struct bsddialog_conf conf, char* text, int rows, int cols)
+int
+bsddialog_form(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int formheight, unsigned int nitems,
+ struct bsddialog_formitem *items)
{
- int output;
- struct formitem item;
-
- item.label = "";
- item.ylabel = 0;
- item.xlabel = 0;
- item.item = ""; // TODO add argv
- item.yitem = 1;
- item.xitem = 1;
- item.itemlen = cols-4;
- item.inputlen = 2048; // todo conf.sizeinput
- item.itemflags = 0;
-
- output = do_mixedform(conf, text, rows, cols, 1, 1, &item);
-
- return output;
-}
+ WINDOW *widget, *formwin, *textpad, *shadow;
+ int i, output, color, y, x, h, w, htextpad;
+ FIELD **cfield;
+ FORM *form;
+ struct buttons bs;
+ struct myfield *myfields;
+ unsigned long maxline;
+
+ /* disable form scrolling like dialog */
+ if (formheight < nitems)
+ formheight = nitems;
+
+ maxline = 0;
+ myfields = malloc(nitems * sizeof(struct myfield));
+ cfield = calloc(nitems + 1, sizeof(FIELD*));
+ for (i=0; i < (int)nitems; i++) {
+ cfield[i] = new_field(1, items[i].fieldlen, items[i].yfield-1,
+ items[i].xfield-1, 0, 0);
+ field_opts_off(cfield[i], O_STATIC);
+ set_max_field(cfield[i], items[i].maxvaluelen);
+ set_field_buffer(cfield[i], 0, items[i].init);
+
+ myfields[i].pos = strlen(items[i].init);
+ myfields[i].len = strlen(items[i].init);
+ myfields[i].size = items[i].maxvaluelen;
+ myfields[i].buf = malloc(myfields[i].size);
+ memset(myfields[i].buf, 0, myfields[i].size);
+ strcpy(myfields[i].buf, items[i].init);
+ set_field_userptr(cfield[i], &myfields[i]);
+
+ field_opts_off(cfield[i], O_AUTOSKIP);
+ field_opts_off(cfield[i], O_BLANK);
+ /* field_opts_off(field[i], O_BS_OVERLOAD); */
+
+ if (ISFIELDHIDDEN(items[i])) {
+ /* field_opts_off(field[i], O_PUBLIC); old hidden */
+ myfields[i].secure = true;
+ myfields[i].securech = ' ';
+ if (conf->form.securech != '\0')
+ myfields[i].securech = conf->form.securech;
+ }
+ else myfields[i].secure = false;
-int bsddialog_passwordbox(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
- int output;
- struct formitem item;
+ if (ISFIELDREADONLY(items[i])) {
+ field_opts_off(cfield[i], O_EDIT);
+ field_opts_off(cfield[i], O_ACTIVE);
+ color = t.form.readonlycolor;
+ } else {
+ color = i == 0 ? t.form.f_fieldcolor : t.form.fieldcolor;
+ }
+ set_field_fore(cfield[i], color);
+ set_field_back(cfield[i], color);
- item.label = "";
- item.ylabel = 0;
- item.xlabel = 0;
- item.item = ""; // TODO add argv
- item.yitem = 1;
- item.xitem = 1;
- item.itemlen = cols-4;
- item.inputlen = 2048; // todo conf.sizeinput
- item.itemflags = ITEMHIDDEN;
+ maxline = MAX(maxline, items[i].xlabel + strlen(items[i].label));
+ maxline = MAX(maxline, items[i].xfield + items[i].fieldlen);
+ }
+ cfield[i] = NULL;
- output = do_mixedform(conf, text, rows, cols, 1, 1, &item);
+ /* disable focus with 1 item (inputbox or passwordbox) */
+ if (formheight == 1 && nitems == 1 && strlen(items[0].label) == 0 &&
+ items[0].xfield == 1 ) {
+ set_field_fore(cfield[0], t.widget.color);
+ set_field_back(cfield[0], t.widget.color);
+ }
+
+ get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
+ BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
- return output;
-}
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ form_autosize(conf, rows, cols, &h, &w, text, maxline, &formheight,
+ nitems, bs);
+ if (form_checksize(h, w, text, formheight, nitems, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin,
+ y + h - formheight, x + 1 + w - t.text.hmargin);
+
+ formwin = new_boxed_window(conf, y + h - 3 - formheight -2, x +1,
+ formheight+2, w-2, LOWERED);
+
+ form = new_form(cfield);
+ set_form_win(form, formwin);
+ /* should be formheight */
+ set_form_sub(form, derwin(formwin, nitems, w-4, 1, 1));
+ post_form(form);
-int
-bsddialog_mixedform(struct bsddialog_conf conf, char* text, int rows, int cols,
- int formheight, int argc, char **argv)
-{
- int i, output, nitems;
- struct formitem items[128];
-
- if ((argc % 9) != 0)
- return (-1);
-
- nitems = argc / 9;
- for (i=0; i<nitems; i++) {
- items[i].label = argv[9*i];
- items[i].ylabel = atoi(argv[9*i+1]);
- items[i].xlabel = atoi(argv[9*i+2]);
- items[i].item = argv[9*i+3];
- items[i].yitem = atoi(argv[9*i+4]);
- items[i].xitem = atoi(argv[9*i+5]);
- items[i].itemlen = atoi(argv[9*i+6]);
- items[i].inputlen = atoi(argv[9*i+7]);
- items[i].itemflags = atoi(argv[9*i+8]);
- }
+ for (i=0; i < (int)nitems; i++)
+ mvwaddstr(formwin, items[i].ylabel, items[i].xlabel, items[i].label);
- output = do_mixedform(conf, text, rows, cols, formheight, nitems, items);
+ wrefresh(formwin);
- return output;
-}
+ do {
+ output = form_handler(conf, widget, h-2, w, bs, formwin, form,
+ cfield, nitems, items);
-int
-bsddialog_form(struct bsddialog_conf conf, char* text, int rows, int cols,
- int formheight, int argc, char **argv)
-{
- int i, output, nitems, itemlen, inputlen;
- unsigned int flags = 0;
- struct formitem items[128];
-
- if ((argc % 8) != 0)
- return (-1);
-
- nitems = argc / 8;
- for (i=0; i<nitems; i++) {
- items[i].label = argv[8*i];
- items[i].ylabel = atoi(argv[8*i+1]);
- items[i].xlabel = atoi(argv[8*i+2]);
- items[i].item = argv[8*i+3];
- items[i].yitem = atoi(argv[8*i+4]);
- items[i].xitem = atoi(argv[8*i+5]);
-
- itemlen = atoi(argv[8*i+6]);
- items[i].itemlen = abs(itemlen);
-
- inputlen = atoi(argv[8*i+7]);
- items[i].inputlen = inputlen == 0 ? abs(itemlen) : inputlen;
-
- flags = flags | (itemlen < 0 ? ITEMREADONLY : 0);
- items[i].itemflags = flags;
- }
+ if(update_widget_withtextpad(conf, shadow, widget, h, w,
+ RAISED, textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ draw_buttons(widget, h-2, w, bs, true);
+ wrefresh(widget);
- output = do_mixedform(conf, text, rows, cols, formheight, nitems, items);
+ prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin,
+ y + h - formheight, x + 1 + w - t.text.hmargin);
- return output;
-}
+ draw_borders(conf, formwin, formheight+2, w-2, LOWERED);
+ /* wrefresh(formwin); */
+ } while (output == REDRAWFORM);
-int
-bsddialog_passwordform(struct bsddialog_conf conf, char* text, int rows, int cols,
- int formheight, int argc, char **argv)
-{
- int i, output, nitems, itemlen, inputlen;
- unsigned int flags = ITEMHIDDEN;
- struct formitem items[128];
-
- if ((argc % 8) != 0)
- return (-1);
-
- nitems = argc / 8;
- for (i=0; i<nitems; i++) {
- items[i].label = argv[8*i];
- items[i].ylabel = atoi(argv[8*i+1]);
- items[i].xlabel = atoi(argv[8*i+2]);
- items[i].item = argv[8*i+3];
- items[i].yitem = atoi(argv[8*i+4]);
- items[i].xitem = atoi(argv[8*i+5]);
-
- itemlen = atoi(argv[8*i+6]);
- items[i].itemlen = abs(itemlen);
-
- inputlen = atoi(argv[8*i+7]);
- items[i].inputlen = inputlen == 0 ? abs(itemlen) : inputlen;
-
- flags = flags | (itemlen < 0 ? ITEMREADONLY : 0);
- items[i].itemflags = flags;
+ unpost_form(form);
+ free_form(form);
+ for (i=0; i < (int)nitems; i++) {
+ free_field(cfield[i]);
+ free(myfields[i].buf);
}
+ free(cfield);
+ free(myfields);
- output = do_mixedform(conf, text, rows, cols, formheight, nitems, items);
+ delwin(formwin);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
-
diff --git a/contrib/bsddialog/lib/infobox.c b/contrib/bsddialog/lib/infobox.c
index 0d3eca86a258..304e68a62107 100644
--- a/contrib/bsddialog/lib/infobox.c
+++ b/contrib/bsddialog/lib/infobox.c
@@ -44,7 +44,7 @@
extern struct bsddialog_theme t;
static int
-infobox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
+infobox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
char *text)
{
int maxword, maxline, nlines;
@@ -54,7 +54,7 @@ infobox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
if (cols == BSDDIALOG_AUTOSIZE) {
/* text size */
- *w = maxline + VBORDERS + t.texthmargin * 2;
+ *w = maxline + VBORDERS + t.text.hmargin * 2;
/* avoid terminal overflow */
*w = MIN(*w, widget_max_width(conf));
}
@@ -74,7 +74,7 @@ infobox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
static int infobox_checksize(int rows, int cols)
{
- if (cols < HBORDERS + 1 + (int) t.texthmargin * 2)
+ if (cols < HBORDERS + 1 + (int) t.text.hmargin * 2)
RETURN_ERROR("Few cols, infobox needs at least width 3 + text "\
"margins");
@@ -85,7 +85,7 @@ static int infobox_checksize(int rows, int cols)
}
int
-bsddialog_infobox(struct bsddialog_conf conf, char* text, int rows, int cols)
+bsddialog_infobox(struct bsddialog_conf *conf, char* text, int rows, int cols)
{
WINDOW *shadow, *widget, *textpad;
int y, x, h, w, htextpad;
@@ -103,7 +103,7 @@ bsddialog_infobox(struct bsddialog_conf conf, char* text, int rows, int cols)
&textpad, &htextpad, text, false) != 0)
return BSDDIALOG_ERROR;
- pnoutrefresh(textpad, 0, 0, y+1, x+1+t.texthmargin, y+h-2, x+w-t.texthmargin);
+ pnoutrefresh(textpad, 0, 0, y+1, x+1+t.text.hmargin, y+h-2, x+w-t.text.hmargin);
doupdate();
diff --git a/contrib/bsddialog/lib/lib_util.c b/contrib/bsddialog/lib/lib_util.c
index a1cdac1169c4..0751a666de92 100644
--- a/contrib/bsddialog/lib/lib_util.c
+++ b/contrib/bsddialog/lib/lib_util.c
@@ -65,9 +65,9 @@ int hide_widget(int y, int x, int h, int w, bool withshadow)
WINDOW *clear;
/* no check: y, x, h and w are checked by the builders */
- if ((clear = newwin(h, w, y + t.shadowrows, x + t.shadowcols)) == NULL)
+ if ((clear = newwin(h, w, y + t.shadow.h, x + t.shadow.w)) == NULL)
RETURN_ERROR("Cannot hide the widget");
- wbkgd(clear, t.backgroundcolor);
+ wbkgd(clear, t.terminal.color);
if (withshadow)
wrefresh(clear);
@@ -81,23 +81,23 @@ int hide_widget(int y, int x, int h, int w, bool withshadow)
}
/* F1 help */
-int f1help(struct bsddialog_conf conf)
+int f1help(struct bsddialog_conf *conf)
{
- char *file = conf.hfile;
- char *title = conf.title;
+ char *file = conf->hfile;
+ char *title = conf->title;
int output;
- conf.hfile = NULL;
- conf.clear = true;
- conf.y = BSDDIALOG_CENTER;
- conf.x = BSDDIALOG_CENTER;
- conf.title = "HELP";
- conf.sleep = 0;
+ conf->hfile = NULL;
+ conf->clear = true;
+ conf->y = BSDDIALOG_CENTER;
+ conf->x = BSDDIALOG_CENTER;
+ conf->title = "HELP";
+ conf->sleep = 0;
output = bsddialog_textbox(conf, file, BSDDIALOG_AUTOSIZE,
BSDDIALOG_AUTOSIZE);
- conf.hfile = file;
- conf.title = title;
+ conf->hfile = file;
+ conf->title = title;
return output;
}
@@ -110,24 +110,24 @@ draw_button(WINDOW *window, int y, int x, int size, char *text, bool selected,
int i, color_arrows, color_shortkey, color_button;
if (selected) {
- color_arrows = t.currbuttdelimcolor;
- color_shortkey = t.currshortkeycolor;
- color_button = t.currbuttoncolor;
+ color_arrows = t.button.f_delimcolor;
+ color_shortkey = t.button.f_shortcutcolor;
+ color_button = t.button.f_color;
} else {
- color_arrows = t.buttdelimcolor;
- color_shortkey = t.shortkeycolor;
- color_button = t.buttoncolor;
+ color_arrows = t.button.delimcolor;
+ color_shortkey = t.button.shortcutcolor;
+ color_button = t.button.color;
}
wattron(window, color_arrows);
- mvwaddch(window, y, x, t.buttleftch);
+ mvwaddch(window, y, x, t.button.leftch);
wattroff(window, color_arrows);
wattron(window, color_button);
for(i = 1; i < size - 1; i++)
waddch(window, ' ');
wattroff(window, color_button);
wattron(window, color_arrows);
- mvwaddch(window, y, x + i, t.buttrightchar);
+ mvwaddch(window, y, x + i, t.button.rightch);
wattroff(window, color_arrows);
x = x + 1 + ((size - 2 - strlen(text))/2);
@@ -147,18 +147,18 @@ draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey)
{
int i, x, start_x;
- start_x = bs.sizebutton * bs.nbuttons + (bs.nbuttons - 1) * t.buttonspace;
+ start_x = bs.sizebutton * bs.nbuttons + (bs.nbuttons - 1) * t.button.space;
start_x = cols/2 - start_x/2;
for (i = 0; i < (int) bs.nbuttons; i++) {
- x = i * (bs.sizebutton + t.buttonspace);
+ x = i * (bs.sizebutton + t.button.space);
draw_button(window, y, start_x + x, bs.sizebutton, bs.label[i],
i == bs.curr, shortkey);
}
}
void
-get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
+get_buttons(struct bsddialog_conf *conf, struct buttons *bs, char *yesoklabel,
char *extralabel, char *nocancellabel, char *helplabel)
{
int i;
@@ -171,41 +171,53 @@ get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
bs->curr = 0;
bs->sizebutton = 0;
- if (yesoklabel != NULL && conf.button.no_ok == false) {
+ if (yesoklabel != NULL && conf->button.no_ok == false) {
bs->label[0] = yesoklabel;
bs->value[0] = BSDDIALOG_YESOK;
bs->nbuttons += 1;
}
- if (extralabel != NULL && conf.button.extra_button) {
+ if (extralabel != NULL && conf->button.extra_button) {
bs->label[bs->nbuttons] = extralabel;
bs->value[bs->nbuttons] = BSDDIALOG_EXTRA;
bs->nbuttons += 1;
}
- if (nocancellabel != NULL && conf.button.no_cancel == false) {
+ if (nocancellabel != NULL && conf->button.no_cancel == false) {
bs->label[bs->nbuttons] = nocancellabel;
bs->value[bs->nbuttons] = BSDDIALOG_NOCANCEL;
- if (conf.button.defaultno)
+ if (conf->button.defaultno)
bs->curr = bs->nbuttons;
bs->nbuttons += 1;
}
- if (helplabel != NULL && conf.button.help_button) {
+ if (helplabel != NULL && conf->button.help_button) {
bs->label[bs->nbuttons] = helplabel;
bs->value[bs->nbuttons] = BSDDIALOG_HELP;
bs->nbuttons += 1;
}
+ if (conf->button.generic1_label != NULL) {
+ bs->label[bs->nbuttons] = conf->button.generic1_label;
+ bs->value[bs->nbuttons] = BSDDIALOG_GENERIC1;
+ bs->nbuttons += 1;
+ }
+
+ if (conf->button.generic2_label != NULL) {
+ bs->label[bs->nbuttons] = conf->button.generic2_label;
+ bs->value[bs->nbuttons] = BSDDIALOG_GENERIC2;
+ bs->nbuttons += 1;
+ }
+
if (bs->nbuttons == 0) {
bs->label[0] = DEFAULT_BUTTON_LABEL;
bs->value[0] = DEFAULT_BUTTON_VALUE;
bs->nbuttons = 1;
}
- if (conf.button.default_label != NULL) {
+ if (conf->button.default_label != NULL) {
for (i=0; i<(int)bs->nbuttons; i++) {
- if (strcmp(conf.button.default_label, bs->label[i]) == 0)
+ if (strcmp(conf->button.default_label, bs->label[i]) == 0)
bs->curr = i;
}
}
@@ -217,39 +229,29 @@ get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
}
/* Text */
+static bool is_ncurses_attr(char *text)
+{
-// old text, to delete in the future
-enum token { TEXT, WS, END };
+ if (strnlen(text, 3) < 3)
+ return false;
+
+ if (text[0] != '\\' || text[1] != 'Z')
+ return false;
+
+ return (strchr("nbBrRuU01234567", text[2]) == NULL ? false : true);
+}
static bool check_set_ncurses_attr(WINDOW *win, char *text)
{
- bool isattr;
- int colors[8] = {
- COLOR_BLACK,
- COLOR_RED,
- COLOR_GREEN,
- COLOR_YELLOW,
- COLOR_BLUE,
- COLOR_MAGENTA,
- COLOR_CYAN,
- COLOR_WHITE
- };
-
- if (text[0] == '\0' || text[0] != '\\')
- return false;
- if (text[1] == '\0' || text[1] != 'Z')
- return false;
- if (text[2] == '\0')
+
+ if (is_ncurses_attr(text) == false)
return false;
- if ((text[2] - 48) >= 0 && (text[2] - 48) < 8) {
- // tocheck: import BSD_COLOR
- // tofix color background
- wattron(win, COLOR_PAIR(colors[text[2] - 48] * 8 + COLOR_WHITE + 1));
+ if ((text[2] - '0') >= 0 && (text[2] - '0') < 8) {
+ wattron(win, bsddialog_color( text[2] - '0', COLOR_WHITE) );
return true;
}
- isattr = true;
switch (text[2]) {
case 'n':
wattrset(win, A_NORMAL);
@@ -272,143 +274,9 @@ static bool check_set_ncurses_attr(WINDOW *win, char *text)
case 'U':
wattroff(win, A_UNDERLINE);
break;
- default:
- isattr = false;
}
- return isattr;
-}
-
-static bool isws(int ch)
-{
-
- return (ch == ' ' || ch == '\t' || ch == '\n');
-}
-
-static int
-next_token(char *text, char *valuestr)
-{
- int i, j;
- enum token tok;
-
- i = j = 0;
-
- if (text[0] == '\0')
- return END;
-
- while (text[i] != '\0') {
- if (isws(text[i])) {
- if (i == 0) {
- valuestr[0] = text[i];
- valuestr[1] = '\0';
- tok = WS;
- }
- break;
- }
-
- valuestr[j] = text[i];
- j++;
- valuestr[j] = '\0';
- i++;
- tok = TEXT;
- }
-
- return tok;
-}
-
-static void
-print_string(WINDOW *win, int *y, int *x, int minx, int maxx, char *str, bool color)
-{
- int i, j, len, reallen;
-
- if(strlen(str) == 0)
- return;
-
- len = reallen = strlen(str);
- if (color) {
- i=0;
- while (i < len) {
- if (check_set_ncurses_attr(win, str+i))
- reallen -= 3;
- i++;
- }
- }
-
- i = 0;
- while (i < len) {
- if (*x + reallen > maxx) {
- *y = (*x != minx ? *y+1 : *y);
- *x = minx;
- }
- j = *x;
- while (j < maxx && i < len) {
- if (color && check_set_ncurses_attr(win, str+i)) {
- i += 3;
- } else {
- mvwaddch(win, *y, j, str[i]);
- i++;
- reallen--;
- j++;
- *x = j;
- }
- }
- }
-}
-
-void
-print_text(struct bsddialog_conf conf, WINDOW *pad, int starty, int minx, int maxx,
- char *text)
-{
- char *valuestr;
- int x, y;
- bool loop;
- enum token tok;
-
- valuestr = malloc(strlen(text) + 1);
-
- x = minx;
- y = starty;
- loop = true;
- while (loop) {
- tok = next_token(text, valuestr);
- switch (tok) {
- case END:
- loop = false;
- break;
- case WS:
- text += strlen(valuestr);
- print_string(pad, &y, &x, minx, maxx, valuestr, false /*useless*/);
- break;
- case TEXT:
- text += strlen(valuestr);
- print_string(pad, &y, &x, minx, maxx, valuestr, conf.text.colors);
- break;
- }
- }
-
- free(valuestr);
-}
-
-// new text funcs
-
-static bool is_ncurses_attr(char *text)
-{
- bool isattr;
-
- if (strnlen(text, 3) < 3)
- return false;
-
- if (text[0] != '\\' || text[1] != 'Z')
- return false;
-
- if ((text[2] - '0') >= 0 && (text[2] - '0') < 8)
- return true;
-
- isattr = text[2] == 'n' || text[2] == 'b' || text[2] == 'B' ||
- text[2] == 'r' || text[2] == 'R' || text[2] == 'u' ||
- text[2] == 'U';
-
- return isattr;
+ return true;
}
static void
@@ -454,7 +322,7 @@ print_str(WINDOW *win, int *rows, int *y, int *x, int cols, char *str, bool colo
}
}
-static void prepare_text(struct bsddialog_conf conf, char *text, char *buf)
+static void prepare_text(struct bsddialog_conf *conf, char *text, char *buf)
{
int i, j;
@@ -468,7 +336,7 @@ static void prepare_text(struct bsddialog_conf conf, char *text, char *buf)
i++;
break;
case 'n':
- if (conf.text.no_nl_expand) {
+ if (conf->text.no_nl_expand) {
j++;
buf[j] = 'n';
} else
@@ -476,7 +344,7 @@ static void prepare_text(struct bsddialog_conf conf, char *text, char *buf)
i++;
break;
case 't':
- if (conf.text.no_collapse) {
+ if (conf->text.no_collapse) {
j++;
buf[j] = 't';
} else
@@ -486,23 +354,23 @@ static void prepare_text(struct bsddialog_conf conf, char *text, char *buf)
}
break;
case '\n':
- buf[j] = conf.text.cr_wrap ? ' ' : '\n';
+ buf[j] = conf->text.cr_wrap ? ' ' : '\n';
break;
case '\t':
- buf[j] = conf.text.no_collapse ? '\t' : ' ';
+ buf[j] = conf->text.no_collapse ? '\t' : ' ';
break;
default:
buf[j] = text[i];
}
i++;
- j += (buf[j] == ' ' && conf.text.trim && j > 0 && buf[j-1] == ' ') ?
+ j += (buf[j] == ' ' && conf->text.trim && j > 0 && buf[j-1] == ' ') ?
0 : 1;
}
buf[j] = '\0';
}
int
-get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
+get_text_properties(struct bsddialog_conf *conf, char *text, int *maxword,
int *maxline, int *nlines)
{
char *buf;
@@ -524,7 +392,7 @@ get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
wordlen = 0;
continue;
}
- if (conf.text.colors && is_ncurses_attr(buf + i))
+ if (conf->text.colors && is_ncurses_attr(buf + i))
i += 3;
else
wordlen++;
@@ -541,7 +409,7 @@ get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
linelen = 0;
break;
default:
- if (conf.text.colors && is_ncurses_attr(buf + i))
+ if (conf->text.colors && is_ncurses_attr(buf + i))
i += 3;
else
linelen++;
@@ -555,8 +423,9 @@ get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
return 0;
}
-static int
-print_textpad(struct bsddialog_conf conf, WINDOW *pad, int *rows, int cols, char *text)
+int
+print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols,
+ char *text)
{
char *buf, *string;
int i, j, x, y;
@@ -580,7 +449,7 @@ print_textpad(struct bsddialog_conf conf, WINDOW *pad, int *rows, int cols, char
string[j] == '\t' || string[j] == ' ') {
if (j != 0) {
string[j] = '\0';
- print_str(pad, rows, &y, &x, cols, string, conf.text.colors);
+ print_str(pad, rows, &y, &x, cols, string, conf->text.colors);
}
}
@@ -633,15 +502,15 @@ print_textpad(struct bsddialog_conf conf, WINDOW *pad, int *rows, int cols, char
* max y, that is from 0 to LINES - 1 - t.shadowrows,
* could not be max height but avoids problems with checksize
*/
-int widget_max_height(struct bsddialog_conf conf)
+int widget_max_height(struct bsddialog_conf *conf)
{
int maxheight;
- if ((maxheight = conf.shadow ? LINES - 1 - t.shadowrows : LINES - 1) <= 0)
+ if ((maxheight = conf->shadow ? LINES - 1 - t.shadow.h : LINES - 1) <= 0)
RETURN_ERROR("Terminal too small, LINES - shadow <= 0");
- if (conf.y > 0)
- if ((maxheight -= conf.y) <=0)
+ if (conf->y > 0)
+ if ((maxheight -= conf->y) <=0)
RETURN_ERROR("Terminal too small, LINES - shadow - y <= 0");
return maxheight;
@@ -651,21 +520,21 @@ int widget_max_height(struct bsddialog_conf conf)
* max x, that is from 0 to COLS - 1 - t.shadowcols,
* * could not be max height but avoids problems with checksize
*/
-int widget_max_width(struct bsddialog_conf conf)
+int widget_max_width(struct bsddialog_conf *conf)
{
int maxwidth;
- if ((maxwidth = conf.shadow ? COLS - 1 - t.shadowcols : COLS - 1) <= 0)
+ if ((maxwidth = conf->shadow ? COLS - 1 - t.shadow.w : COLS - 1) <= 0)
RETURN_ERROR("Terminal too small, COLS - shadow <= 0");
- if (conf.x > 0)
- if ((maxwidth -= conf.x) <=0)
+ if (conf->x > 0)
+ if ((maxwidth -= conf->x) <=0)
RETURN_ERROR("Terminal too small, COLS - shadow - x <= 0");
return maxwidth;
}
int
-set_widget_size(struct bsddialog_conf conf, int rows, int cols, int *h, int *w)
+set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w)
{
int maxheight, maxwidth;
@@ -700,33 +569,33 @@ set_widget_size(struct bsddialog_conf conf, int rows, int cols, int *h, int *w)
}
int
-set_widget_position(struct bsddialog_conf conf, int *y, int *x, int h, int w)
+set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w)
{
- if (conf.y == BSDDIALOG_CENTER)
+ if (conf->y == BSDDIALOG_CENTER)
*y = LINES/2 - h/2;
- else if (conf.y < BSDDIALOG_CENTER)
+ else if (conf->y < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin y (less than -1)");
- else if (conf.y >= LINES)
+ else if (conf->y >= LINES)
RETURN_ERROR("Begin Y under the terminal");
else
- *y = conf.y;
+ *y = conf->y;
- if ((*y + h + (conf.shadow ? (int) t.shadowrows : 0)) > LINES)
+ if ((*y + h + (conf->shadow ? (int) t.shadow.h : 0)) > LINES)
RETURN_ERROR("The lower of the box under the terminal "\
"(begin Y + height (+ shadow) > terminal lines)");
- if (conf.x == BSDDIALOG_CENTER)
+ if (conf->x == BSDDIALOG_CENTER)
*x = COLS/2 - w/2;
- else if (conf.x < BSDDIALOG_CENTER)
+ else if (conf->x < BSDDIALOG_CENTER)
RETURN_ERROR("Negative begin x (less than -1)");
- else if (conf.x >= COLS)
+ else if (conf->x >= COLS)
RETURN_ERROR("Begin X over the right of the terminal");
else
- *x = conf.x;
+ *x = conf->x;
- if ((*x + w + (conf.shadow ? (int) t.shadowcols : 0)) > COLS)
+ if ((*x + w + (conf->shadow ? (int) t.shadow.w : 0)) > COLS)
RETURN_ERROR("The right of the box over the terminal "\
"(begin X + width (+ shadow) > terminal cols)");
@@ -735,7 +604,7 @@ set_widget_position(struct bsddialog_conf conf, int *y, int *x, int h, int w)
/* Widgets builders */
void
-draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
+draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols,
enum elevation elev)
{
int leftcolor, rightcolor;
@@ -751,14 +620,14 @@ draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
ltee = ACS_LTEE;
rtee = ACS_RTEE;
- if (conf.no_lines == false) {
- if (conf.ascii_lines) {
+ if (conf->no_lines == false) {
+ if (conf->ascii_lines) {
ls = rs = '|';
ts = bs = '-';
tl = tr = bl = br = ltee = rtee = '+';
}
- leftcolor = elev == RAISED ? t.lineraisecolor : t.linelowercolor;
- rightcolor = elev == RAISED ? t.linelowercolor : t.lineraisecolor;
+ leftcolor = elev == RAISED ? t.widget.lineraisecolor : t.widget.linelowercolor;
+ rightcolor = elev == RAISED ? t.widget.linelowercolor : t.widget.lineraisecolor;
wattron(win, leftcolor);
wborder(win, ls, rs, ts, bs, tl, tr, bl, br);
wattroff(win, leftcolor);
@@ -773,7 +642,7 @@ draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
}
WINDOW *
-new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
+new_boxed_window(struct bsddialog_conf *conf, int y, int x, int rows, int cols,
enum elevation elev)
{
WINDOW *win;
@@ -783,7 +652,7 @@ new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
return NULL;
}
- wbkgd(win, t.widgetcolor);
+ wbkgd(win, t.widget.color);
draw_borders(conf, win, rows, cols, elev);
@@ -795,17 +664,17 @@ new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
* to check at the end.
*/
static int
-draw_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
+draw_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *shadow,
WINDOW *widget, int h, int w, enum elevation elev,
WINDOW *textpad, int *htextpad, char *text, bool buttons)
{
int ts, ltee, rtee;
int colorsurroundtitle;
- ts = conf.ascii_lines ? '-' : ACS_HLINE;
- ltee = conf.ascii_lines ? '+' : ACS_LTEE;
- rtee = conf.ascii_lines ? '+' : ACS_RTEE;
- colorsurroundtitle = elev == RAISED ? t.lineraisecolor : t.linelowercolor;
+ ts = conf->ascii_lines ? '-' : ACS_HLINE;
+ ltee = conf->ascii_lines ? '+' : ACS_LTEE;
+ rtee = conf->ascii_lines ? '+' : ACS_RTEE;
+ colorsurroundtitle = elev == RAISED ? t.widget.lineraisecolor : t.widget.linelowercolor;
if (shadow != NULL)
wnoutrefresh(shadow);
@@ -813,43 +682,43 @@ draw_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
// move / resize now or the caller?
draw_borders(conf, widget, h, w, elev);
- if (conf.title != NULL) {
- if (t.surroundtitle && conf.no_lines == false) {
+ if (conf->title != NULL) {
+ if (t.widget.delimtitle && conf->no_lines == false) {
wattron(widget, colorsurroundtitle);
- mvwaddch(widget, 0, w/2 - strlen(conf.title)/2 - 1, rtee);
+ mvwaddch(widget, 0, w/2 - strlen(conf->title)/2 - 1, rtee);
wattroff(widget, colorsurroundtitle);
}
- wattron(widget, t.titlecolor);
- mvwaddstr(widget, 0, w/2 - strlen(conf.title)/2, conf.title);
- wattroff(widget, t.titlecolor);
- if (t.surroundtitle && conf.no_lines == false) {
+ wattron(widget, t.widget.titlecolor);
+ mvwaddstr(widget, 0, w/2 - strlen(conf->title)/2, conf->title);
+ wattroff(widget, t.widget.titlecolor);
+ if (t.widget.delimtitle && conf->no_lines == false) {
wattron(widget, colorsurroundtitle);
waddch(widget, ltee);
wattroff(widget, colorsurroundtitle);
}
}
- if (conf.hline != NULL) {
- wattron(widget, t.bottomtitlecolor);
- wmove(widget, h - 1, w/2 - strlen(conf.hline)/2 - 1);
+ if (conf->hline != NULL) {
+ wattron(widget, t.widget.bottomtitlecolor);
+ wmove(widget, h - 1, w/2 - strlen(conf->hline)/2 - 1);
waddch(widget, '[');
- waddstr(widget, conf.hline);
+ waddstr(widget, conf->hline);
waddch(widget, ']');
- wattroff(widget, t.bottomtitlecolor);
+ wattroff(widget, t.widget.bottomtitlecolor);
}
- if (textpad == NULL && text != NULL) /* no pad, text null for textbox */
- print_text(conf, widget, 1, 2, w-3, text);
+ //if (textpad == NULL && text != NULL) /* no pad, text null for textbox */
+ // print_text(conf, widget, 1, 2, w-3, text);
- if (buttons && conf.no_lines == false) {
- wattron(widget, t.lineraisecolor);
+ if (buttons && conf->no_lines == false) {
+ wattron(widget, t.widget.lineraisecolor);
mvwaddch(widget, h-3, 0, ltee);
mvwhline(widget, h-3, 1, ts, w-2);
- wattroff(widget, t.lineraisecolor);
+ wattroff(widget, t.widget.lineraisecolor);
- wattron(widget, t.linelowercolor);
+ wattron(widget, t.widget.linelowercolor);
mvwaddch(widget, h-3, w-1, rtee);
- wattroff(widget, t.linelowercolor);
+ wattroff(widget, t.widget.linelowercolor);
}
wnoutrefresh(widget);
@@ -859,7 +728,7 @@ draw_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
if (text != NULL) /* programbox etc */
if (print_textpad(conf, textpad, htextpad,
- w - HBORDERS - t.texthmargin * 2, text) !=0)
+ w - HBORDERS - t.text.hmargin * 2, text) !=0)
return BSDDIALOG_ERROR;
return 0;
@@ -870,7 +739,7 @@ draw_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
* to check at the end.
*/
int
-update_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
+update_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *shadow,
WINDOW *widget, int h, int w, enum elevation elev,
WINDOW *textpad, int *htextpad, char *text, bool buttons)
{
@@ -889,21 +758,21 @@ update_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
* to check at the end.
*/
int
-new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
+new_widget_withtextpad(struct bsddialog_conf *conf, WINDOW **shadow,
WINDOW **widget, int y, int x, int h, int w, enum elevation elev,
WINDOW **textpad, int *htextpad, char *text, bool buttons)
{
int error;
- if (conf.shadow) {
- *shadow = newwin(h, w, y + t.shadowrows, x + t.shadowcols);
+ if (conf->shadow) {
+ *shadow = newwin(h, w, y + t.shadow.h, x + t.shadow.w);
if (*shadow == NULL)
RETURN_ERROR("Cannot build shadow");
- wbkgd(*shadow, t.shadowcolor);
+ wbkgd(*shadow, t.shadow.color);
}
if ((*widget = new_boxed_window(conf, y, x, h, w, elev)) == NULL) {
- if (conf.shadow)
+ if (conf->shadow)
delwin(*shadow);
return BSDDIALOG_ERROR;
}
@@ -916,14 +785,14 @@ new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
if (text != NULL) { /* programbox etc */
*htextpad = 1;
- *textpad = newpad(*htextpad, w - HBORDERS - t.texthmargin * 2);
+ *textpad = newpad(*htextpad, w - HBORDERS - t.text.hmargin * 2);
if (*textpad == NULL) {
delwin(*textpad);
- if (conf.shadow)
+ if (conf->shadow)
delwin(*shadow);
RETURN_ERROR("Cannot build the pad window for text");
}
- wbkgd(*textpad, t.widgetcolor);
+ wbkgd(*textpad, t.widget.color);
}
error = draw_widget_withtextpad(conf, *shadow, *widget, h, w, elev,
@@ -932,65 +801,30 @@ new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
return error;
}
-int
-new_widget(struct bsddialog_conf conf, WINDOW **widget, int *y, int *x,
- char *text, int *h, int *w, WINDOW **shadow, bool buttons)
-{
-
- // to delete (each widget has to check its x,y,h,w)
- if (*h <= 0)
- ; /* todo */
-
- if (*w <= 0)
- ; /* todo */
-
- *y = (conf.y < 0) ? (LINES/2 - *h/2) : conf.y;
- *x = (conf.x < 0) ? (COLS/2 - *w/2) : conf.x;
-
- if (new_widget_withtextpad(conf, shadow, widget, *y, *x, *h, *w, RAISED,
- NULL, NULL, text, buttons) != 0)
- return BSDDIALOG_ERROR;
-
- if (conf.shadow)
- wrefresh(*shadow);
-
- wrefresh(*widget);
-
- return 0;
-}
-
void
-end_widget_withtextpad(struct bsddialog_conf conf, WINDOW *window, int h, int w,
+end_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *window, int h, int w,
WINDOW *textpad, WINDOW *shadow)
{
int y, x;
getbegyx(window, y, x); /* for clear, add y & x to args? */
- if (conf.sleep > 0)
- sleep(conf.sleep);
+ if (conf->sleep > 0)
+ sleep(conf->sleep);
if (textpad != NULL)
delwin(textpad);
delwin(window);
- if (conf.shadow)
+ if (conf->shadow)
delwin(shadow);
- if (conf.clear)
+ if (conf->clear)
hide_widget(y, x, h, w, shadow != NULL);
- if (conf.get_height != NULL)
- *conf.get_height = h;
- if (conf.get_width != NULL)
- *conf.get_width = w;
-}
-
-void
-end_widget(struct bsddialog_conf conf, WINDOW *window, int h, int w,
- WINDOW *shadow)
-{
-
- end_widget_withtextpad(conf, window, h, w, NULL, shadow);
+ if (conf->get_height != NULL)
+ *conf->get_height = h;
+ if (conf->get_width != NULL)
+ *conf->get_width = w;
}
diff --git a/contrib/bsddialog/lib/lib_util.h b/contrib/bsddialog/lib/lib_util.h
index b6fe1dd86b59..b3598e900e9e 100644
--- a/contrib/bsddialog/lib/lib_util.h
+++ b/contrib/bsddialog/lib/lib_util.h
@@ -29,7 +29,7 @@
#define _LIBBSDDIALOG_UTIL_H_
/*
- * Utils to implement widgets - Internal library API
+ * Utils to implement widgets - Internal library API - Dafult values
*/
#define HBORDERS 2
@@ -39,7 +39,7 @@
#define KEY_CTRL(x) ((x) & 0x1f)
/* Set default aspect ratio to 9 */
-#define GET_ASPECT_RATIO(conf) (conf.aspect_ratio > 0 ? conf.aspect_ratio : 9)
+#define GET_ASPECT_RATIO(conf) (conf->aspect_ratio > 0 ? conf->aspect_ratio : 9)
/* debug */
#define BSDDIALOG_DEBUG(y,x,fmt, ...) do { \
@@ -64,9 +64,9 @@ void set_error_string(char *string);
#define LABEL_no_label "No"
#define LABEL_ok_label "OK"
#define LABEL_yes_label "Yes"
-#define BUTTONLABEL(l) (conf.button.l != NULL ? conf.button.l : LABEL_ ##l)
+#define BUTTONLABEL(l) (conf->button.l != NULL ? conf->button.l : LABEL_ ##l)
-#define MAXBUTTONS 4 /* yes|ok - extra - no|cancel - help */
+#define MAXBUTTONS 6 /* yes|ok + extra + no|cancel + help + 2 generics */
struct buttons {
unsigned int nbuttons;
char *label[MAXBUTTONS];
@@ -76,7 +76,7 @@ struct buttons {
};
void
-get_buttons(struct bsddialog_conf conf, struct buttons *bs, char *yesoklabel,
+get_buttons(struct bsddialog_conf *conf, struct buttons *bs, char *yesoklabel,
char *extralabel, char *nocancellabel, char *helplabel);
void
@@ -87,60 +87,52 @@ void
draw_buttons(WINDOW *window, int y, int cols, struct buttons bs, bool shortkey);
/* help window with F1 key */
-int f1help(struct bsddialog_conf conf);
+int f1help(struct bsddialog_conf *conf);
/* cleaner */
int hide_widget(int y, int x, int h, int w, bool withshadow);
/* (auto) size and (auto) position */
int
-get_text_properties(struct bsddialog_conf conf, char *text, int *maxword,
+get_text_properties(struct bsddialog_conf *conf, char *text, int *maxword,
int *maxline, int *nlines);
-int widget_max_height(struct bsddialog_conf conf);
-int widget_max_width(struct bsddialog_conf conf);
+int widget_max_height(struct bsddialog_conf *conf);
+int widget_max_width(struct bsddialog_conf *conf);
int
-set_widget_size(struct bsddialog_conf conf, int rows, int cols, int *h, int *w);
+set_widget_size(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w);
int
-set_widget_position(struct bsddialog_conf conf, int *y, int *x, int h, int w);
+set_widget_position(struct bsddialog_conf *conf, int *y, int *x, int h, int w);
/* widget builders */
-void
-print_text(struct bsddialog_conf conf, WINDOW *pad, int starty, int minx,
- int maxx, char *text);
+int
+print_textpad(struct bsddialog_conf *conf, WINDOW *pad, int *rows, int cols,
+ char *text);
enum elevation { RAISED, LOWERED };
void
-draw_borders(struct bsddialog_conf conf, WINDOW *win, int rows, int cols,
+draw_borders(struct bsddialog_conf *conf, WINDOW *win, int rows, int cols,
enum elevation elev);
WINDOW *
-new_boxed_window(struct bsddialog_conf conf, int y, int x, int rows, int cols,
+new_boxed_window(struct bsddialog_conf *conf, int y, int x, int rows, int cols,
enum elevation elev);
int
-new_widget_withtextpad(struct bsddialog_conf conf, WINDOW **shadow,
+new_widget_withtextpad(struct bsddialog_conf *conf, WINDOW **shadow,
WINDOW **widget, int y, int x, int h, int w, enum elevation elev,
WINDOW **textpad, int *htextpad, char *text, bool buttons);
int
-update_widget_withtextpad(struct bsddialog_conf conf, WINDOW *shadow,
+update_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *shadow,
WINDOW *widget, int h, int w, enum elevation elev, WINDOW *textpad,
int *htextpad, char *text, bool buttons);
void
-end_widget_withtextpad(struct bsddialog_conf conf, WINDOW *window, int h, int w,
+end_widget_withtextpad(struct bsddialog_conf *conf, WINDOW *window, int h, int w,
WINDOW *textpad, WINDOW *shadow);
-int
-new_widget(struct bsddialog_conf conf, WINDOW **widget, int *y, int *x,
- char *text, int *h, int *w, WINDOW **shadow, bool buttons);
-
-void
-end_widget(struct bsddialog_conf conf, WINDOW *window, int h, int w,
- WINDOW *shadow);
-
#endif
diff --git a/contrib/bsddialog/lib/libbsddialog.c b/contrib/bsddialog/lib/libbsddialog.c
index a5866f39bea9..bcc811a02e45 100644
--- a/contrib/bsddialog/lib/libbsddialog.c
+++ b/contrib/bsddialog/lib/libbsddialog.c
@@ -46,14 +46,11 @@
* Widgets implementation:
* infobox.c infobox
* messgebox.c msgbox - yesno
- * menubox.c buildlist - checklist - menu - mixedlist - radiolist - treeview
+ * menubox.c buildlist - checklist - menu - mixedlist - radiolist
* formbox.c inputbox - passwordbox - form - passwordform - mixedform
- * editorbox.c editbox
* barbox.c gauge - mixedgauge - rangebox - pause
+ * textbox.c textbox
* timebox.c timebox - calendar
- * commandbox.c prgbox - programbox - progressbox
- * tailbox.c tailbox - tailboxbg - textbox
- * filebox.c dselect - fselect
*/
extern struct bsddialog_theme t;
@@ -103,12 +100,12 @@ int bsddialog_end(void)
return 0;
}
-int bsddialog_backtitle(struct bsddialog_conf conf, char *backtitle)
+int bsddialog_backtitle(struct bsddialog_conf *conf, char *backtitle)
{
mvaddstr(0, 1, backtitle);
- if (conf.no_lines != true)
- mvhline(1, 1, conf.ascii_lines ? '-' : ACS_HLINE, COLS-2);
+ if (conf->no_lines != true)
+ mvhline(1, 1, conf->ascii_lines ? '-' : ACS_HLINE, COLS-2);
refresh();
diff --git a/contrib/bsddialog/lib/menubox.c b/contrib/bsddialog/lib/menubox.c
index 523e41fdeb1b..72038d4b0246 100644
--- a/contrib/bsddialog/lib/menubox.c
+++ b/contrib/bsddialog/lib/menubox.c
@@ -40,7 +40,7 @@
#include "lib_util.h"
#include "bsddialog_theme.h"
-/* "Menu": checklist - menu - mixedlist - radiolist - treeview - buildlist */
+/* "Menu": checklist - menu - mixedlist - radiolist - buildlist */
#define DEPTHSPACE 4
#define MIN_HEIGHT VBORDERS + 6 /* 2 buttons 1 text 3 menu */
@@ -123,7 +123,7 @@ getfirst(int ngroups, struct bsddialog_menugroup *groups, int *abs, int *group,
}
static void
-getfirst_with_default(struct bsddialog_conf conf, int ngroups,
+getfirst_with_default(struct bsddialog_conf *conf, int ngroups,
struct bsddialog_menugroup *groups, int *abs, int *group, int *rel)
{
int i, j, a;
@@ -142,8 +142,8 @@ getfirst_with_default(struct bsddialog_conf conf, int ngroups,
}
for (j = 0; j < (int) groups[i].nitems; j++) {
item = &groups[i].items[j];
- if (conf.menu.default_item != NULL && item->name != NULL) {
- if (strcmp(item->name, conf.menu.default_item) == 0) {
+ if (conf->menu.default_item != NULL && item->name != NULL) {
+ if (strcmp(item->name, conf->menu.default_item) == 0) {
*abs = a;
*group = i;
*rel = j;
@@ -288,31 +288,31 @@ getmode(enum menumode mode, struct bsddialog_menugroup group)
}
static void
-drawitem(struct bsddialog_conf conf, WINDOW *pad, int y,
+drawitem(struct bsddialog_conf *conf, WINDOW *pad, int y,
struct bsddialog_menuitem item, enum menumode mode, struct lineposition pos,
bool curr)
{
int color, colorname, linech;
- color = curr ? t.curritemcolor : t.itemcolor;
- colorname = curr ? t.currtagcolor : t.tagcolor;
+ color = curr ? t.menu.f_desccolor : t.menu.desccolor;
+ colorname = curr ? t.menu.f_namecolor : t.menu.namecolor;
if (mode == SEPARATORMODE) {
- if (conf.no_lines == false) {
- wattron(pad, t.itemcolor);
- linech = conf.ascii_lines ? '-' : ACS_HLINE;
+ if (conf->no_lines == false) {
+ wattron(pad, t.menu.desccolor);
+ linech = conf->ascii_lines ? '-' : ACS_HLINE;
mvwhline(pad, y, 0, linech, pos.line);
- wattroff(pad, t.itemcolor);
+ wattroff(pad, t.menu.desccolor);
}
wmove(pad, y, pos.line/2 - (strlen(item.name)+strlen(item.desc))/2);
- wattron(pad, t.namesepcolor);
+ wattron(pad, t.menu.namesepcolor);
waddstr(pad, item.name);
- wattroff(pad, t.namesepcolor);
+ wattroff(pad, t.menu.namesepcolor);
if (strlen(item.name) > 0 && strlen(item.desc) > 0)
waddch(pad, ' ');
- wattron(pad, t.descsepcolor);
+ wattron(pad, t.menu.descsepcolor);
waddstr(pad, item.desc);
- wattroff(pad, t.descsepcolor);
+ wattroff(pad, t.menu.descsepcolor);
return;
}
@@ -330,18 +330,18 @@ drawitem(struct bsddialog_conf conf, WINDOW *pad, int y,
wattroff(pad, color);
/* name */
- if (mode != BUILDLISTMODE && conf.menu.no_tags == false) {
+ if (mode != BUILDLISTMODE && conf->menu.no_name == false) {
wattron(pad, colorname);
mvwaddstr(pad, y, pos.xname + item.depth * DEPTHSPACE, item.name);
wattroff(pad, colorname);
}
/* description */
- if (conf.menu.no_items == false) {
- if ((mode == BUILDLISTMODE || conf.menu.no_tags) && curr == false)
- color = item.on ? t.tagcolor : t.itemcolor;
+ if (conf->menu.no_desc == false) {
+ if ((mode == BUILDLISTMODE || conf->menu.no_name) && curr == false)
+ color = item.on ? t.menu.namecolor : t.menu.desccolor;
wattron(pad, color);
- if (conf.menu.no_tags)
+ if (conf->menu.no_name)
mvwaddstr(pad, y, pos.xname + item.depth * DEPTHSPACE, item.desc);
else
mvwaddstr(pad, y, pos.xdesc, item.desc);
@@ -359,7 +359,7 @@ drawitem(struct bsddialog_conf conf, WINDOW *pad, int y,
}
static void
-menu_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
+menu_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
char *text, int linelen, unsigned int *menurows, int nitems,
struct buttons bs)
{
@@ -371,7 +371,7 @@ menu_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
*w = VBORDERS;
/* buttons size */
*w += bs.nbuttons * bs.sizebutton;
- *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
+ *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
/* line size */
*w = MAX(*w, linelen + 6);
/*
@@ -413,7 +413,7 @@ menu_checksize(int rows, int cols, char *text, int menurows, int nitems,
mincols = VBORDERS;
/* buttons */
mincols += bs.nbuttons * bs.sizebutton;
- mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
+ mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
/* line, comment to permet some cols hidden */
/* mincols = MAX(mincols, linelen); */
@@ -436,23 +436,22 @@ menu_checksize(int rows, int cols, char *text, int menurows, int nitems,
/* the caller has to call prefresh(menupad, ymenupad, 0, ys, xs, ye, xe); */
static void
-update_menuwin(struct bsddialog_conf conf, WINDOW *menuwin, int h, int w,
+update_menuwin(struct bsddialog_conf *conf, WINDOW *menuwin, int h, int w,
int totnitems, unsigned int menurows, int ymenupad)
{
if (totnitems > (int) menurows) {
draw_borders(conf, menuwin, h, w, LOWERED);
- if (ymenupad > 0) {
- wattron(menuwin, t.lineraisecolor);
- mvwprintw(menuwin, 0, 2, "^^");
- wattroff(menuwin, t.lineraisecolor);
- }
- if ((int) (ymenupad + menurows) < totnitems) {
- wattron(menuwin, t.linelowercolor);
- mvwprintw(menuwin, h-1, 2, "vv");
- wattroff(menuwin, t.linelowercolor);
- }
+ wattron(menuwin, t.menu.arrowcolor);
+
+ if (ymenupad > 0)
+ mvwprintw(menuwin, 0, 2, "^^^");
+
+ if ((int) (ymenupad + menurows) < totnitems)
+ mvwprintw(menuwin, h-1, 2, "vvv");
+
+ wattroff(menuwin, t.menu.arrowcolor);
mvwprintw(menuwin, h-1, w-10, "%3d%%",
100 * (ymenupad + menurows) / totnitems);
@@ -460,7 +459,7 @@ update_menuwin(struct bsddialog_conf conf, WINDOW *menuwin, int h, int w,
}
static int
-do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
+do_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, enum menumode mode, int ngroups,
struct bsddialog_menugroup *groups, int *focuslist, int *focusitem)
{
@@ -503,8 +502,8 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
pos.maxdesc = MAX(pos.maxdesc, strlen(item->desc));
}
}
- pos.maxname = conf.menu.no_tags ? 0 : pos.maxname;
- pos.maxdesc = conf.menu.no_items ? 0 : pos.maxdesc;
+ pos.maxname = conf->menu.no_name ? 0 : pos.maxname;
+ pos.maxdesc = conf->menu.no_desc ? 0 : pos.maxdesc;
pos.maxdepth *= DEPTHSPACE;
pos.xselector = pos.maxprefix + (pos.maxprefix != 0 ? 1 : 0);
@@ -530,14 +529,14 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
&textpad, &htextpad, text, true) != 0)
return BSDDIALOG_ERROR;
- prefresh(textpad, 0, 0, y + 1, x + 1 + t.texthmargin,
- y + h - menurows, x + 1 + w - t.texthmargin);
+ prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin,
+ y + h - menurows, x + 1 + w - t.text.hmargin);
menuwin = new_boxed_window(conf, y + h - 5 - menurows, x + 2,
menurows+2, w-4, LOWERED);
menupad = newpad(totnitems, pos.line);
- wbkgd(menupad, t.widgetcolor);
+ wbkgd(menupad, t.widget.color);
getfirst_with_default(conf, ngroups, groups, &abs, &g, &rel);
ymenupad = 0;
@@ -553,7 +552,7 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
ys = y + h - 5 - menurows + 1;
ye = y + h - 5 ;
- if (conf.menu.align_left || (int)pos.line > w - 6) {
+ if (conf->menu.align_left || (int)pos.line > w - 6) {
xs = x + 3;
xe = xs + w - 7;
}
@@ -608,15 +607,15 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
wrefresh(widget);
}
break;
- case KEY_CTRL('E'): /* add conf.menu.extrahelpkey ? */
+ case KEY_CTRL('E'): /* add conf->menu.extrahelpkey ? */
case KEY_F(1):
- if (conf.hfile == NULL)
+ if (conf->hfile == NULL)
break;
if (f1help(conf) != 0)
return BSDDIALOG_ERROR;
/* No break! the terminal size can change */
case KEY_RESIZE:
- hide_widget(y, x, h, w,conf.shadow);
+ hide_widget(y, x, h, w,conf->shadow);
/*
* Unnecessary, but, when the columns decrease the
@@ -635,7 +634,7 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
return BSDDIALOG_ERROR;
wclear(shadow);
- mvwin(shadow, y + t.shadowrows, x + t.shadowcols);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
wresize(shadow, h, w);
wclear(widget);
@@ -644,7 +643,7 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
htextpad = 1;
wclear(textpad);
- wresize(textpad, 1, w - HBORDERS - t.texthmargin * 2);
+ wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
if(update_widget_withtextpad(conf, shadow, widget, h, w,
RAISED, textpad, &htextpad, text, true) != 0)
@@ -653,8 +652,8 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
draw_buttons(widget, h-2, w, bs, true);
wrefresh(widget);
- prefresh(textpad, 0, 0, y + 1, x + 1 + t.texthmargin,
- y + h - menurows, x + 1 + w - t.texthmargin);
+ prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin,
+ y + h - menurows, x + 1 + w - t.text.hmargin);
wclear(menuwin);
mvwin(menuwin, y + h - 5 - menurows, x + 2);
@@ -665,7 +664,7 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
ys = y + h - 5 - menurows + 1;
ye = y + h - 5 ;
- if (conf.menu.align_left || (int)pos.line > w - 6) {
+ if (conf->menu.align_left || (int)pos.line > w - 6) {
xs = x + 3;
xe = xs + w - 7;
}
@@ -687,7 +686,6 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
output = bs.value[i];
loop = false;
}
-
}
if (abs < 0)
@@ -743,16 +741,14 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
else if (currmode == CHECKLISTMODE)
item->on = !item->on;
else { /* RADIOLISTMODE */
- if (item->on == true)
- break;
for (i=0; i < (int) groups[g].nitems; i++)
- if (groups[g].items[i].on == true) {
+ if (groups[g].items[i].on == true && i != rel) {
groups[g].items[i].on = false;
drawitem(conf, menupad,
abs - rel + i, groups[g].items[i],
currmode, pos, false);
}
- item->on = true;
+ item->on = !item->on;
}
drawitem(conf, menupad, abs, *item, currmode, pos, true);
prefresh(menupad, ymenupad, 0, ys, xs, ye, xe);
@@ -775,7 +771,7 @@ do_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
* API
*/
-int bsddialog_mixedlist(struct bsddialog_conf conf, char* text, int rows, int cols,
+int bsddialog_mixedlist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int ngroups, struct bsddialog_menugroup *groups,
int *focuslist, int *focusitem)
{
@@ -788,7 +784,7 @@ int bsddialog_mixedlist(struct bsddialog_conf conf, char* text, int rows, int co
}
int
-bsddialog_checklist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_checklist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem)
{
@@ -803,7 +799,7 @@ bsddialog_checklist(struct bsddialog_conf conf, char* text, int rows, int cols,
}
int
-bsddialog_menu(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_menu(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem)
{
@@ -818,7 +814,7 @@ bsddialog_menu(struct bsddialog_conf conf, char* text, int rows, int cols,
}
int
-bsddialog_radiolist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_radiolist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem)
{
@@ -832,31 +828,57 @@ bsddialog_radiolist(struct bsddialog_conf conf, char* text, int rows, int cols,
return output;
}
-int
-bsddialog_treeview(struct bsddialog_conf conf, char* text, int rows, int cols,
- unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
- int *focusitem)
+/* todo */
+static int buildlist_autosize(int rows, int cols)
{
- int output;
- struct bsddialog_menugroup group = {
- BSDDIALOG_RADIOLIST /* unused */, nitems, items};
- conf.menu.no_tags = true;
- conf.menu.align_left = true;
+ if (cols == BSDDIALOG_AUTOSIZE)
+ RETURN_ERROR("Unimplemented cols autosize for buildlist");
- output = do_mixedlist(conf, text, rows, cols, menurows, RADIOLISTMODE,
- 1, &group, NULL, focusitem);
+ if (rows == BSDDIALOG_AUTOSIZE)
+ RETURN_ERROR("Unimplemented rows autosize for buildlist");
- return output;
+ return 0;
+}
+
+/* to improve */
+static int
+buildlist_checksize(int rows, int cols, char *text, int menurows, int nitems,
+ struct buttons bs)
+{
+ int mincols, textrow, menusize;
+
+ mincols = VBORDERS;
+ /* buttons */
+ mincols += bs.nbuttons * bs.sizebutton;
+ mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
+ /* line, comment to permet some cols hidden */
+ /* mincols = MAX(mincols, linelen); */
+
+ if (cols < mincols)
+ RETURN_ERROR("Few cols, width < size buttons or "\
+ "name+descripion of the items");
+
+ textrow = text != NULL && strlen(text) > 0 ? 1 : 0;
+
+ if (nitems > 0 && menurows == 0)
+ RETURN_ERROR("items > 0 but menurows == 0, probably terminal "\
+ "too small");
+
+ menusize = nitems > 0 ? 3 : 0;
+ if (rows < 2 + 2 + menusize + textrow)
+ RETURN_ERROR("Few lines for this menus");
+
+ return 0;
}
int
-bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
+bsddialog_buildlist(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int menurows, int nitems, struct bsddialog_menuitem *items,
int *focusitem)
{
- WINDOW *widget, *leftwin, *leftpad, *rightwin, *rightpad, *shadow;
- int output, i, x, y, input;
+ WINDOW *widget, *textpad, *leftwin, *leftpad, *rightwin, *rightpad, *shadow;
+ int output, i, x, y, h, w, htextpad, input;
bool loop, buttupdate, padsupdate, startleft;
int nlefts, nrights, leftwinx, rightwinx, winsy, padscols, curr;
enum side {LEFT, RIGHT} currV;
@@ -871,36 +893,48 @@ bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
startleft = true;
}
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
+ get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
+ BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (buildlist_autosize(rows, cols) != 0)
+ return BSDDIALOG_ERROR;
+ if (buildlist_checksize(h, w, text, menurows, nitems, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
- winsy = y + rows - 5 - menurows;
+ prefresh(textpad, 0, 0, y + 1, x + 1 + t.text.hmargin,
+ y + h - menurows, x + 1 + w - t.text.hmargin);
+
+ winsy = y + h - 5 - menurows;
leftwinx = x+2;
- leftwin = new_boxed_window(conf, winsy, leftwinx, menurows+2, (cols-5)/2,
+ leftwin = new_boxed_window(conf, winsy, leftwinx, menurows+2, (w-5)/2,
LOWERED);
- rightwinx = x + cols - 2 -(cols-5)/2;
+ rightwinx = x + w - 2 -(w-5)/2;
rightwin = new_boxed_window(conf, winsy, rightwinx, menurows+2,
- (cols-5)/2, LOWERED);
+ (w-5)/2, LOWERED);
wrefresh(leftwin);
wrefresh(rightwin);
- padscols = (cols-5)/2 - 2;
+ padscols = (w-5)/2 - 2;
leftpad = newpad(nitems, pos.line);
rightpad = newpad(nitems, pos.line);
- wbkgd(leftpad, t.widgetcolor);
- wbkgd(rightpad, t.widgetcolor);
-
- get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
- BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
+ wbkgd(leftpad, t.widget.color);
+ wbkgd(rightpad, t.widget.color);
currH = 0;
currV = startleft ? LEFT : RIGHT;
loop = buttupdate = padsupdate = true;
while(loop) {
if (buttupdate) {
- draw_buttons(widget, rows-2, cols, bs, true);
+ draw_buttons(widget, h-2, w, bs, true);
wrefresh(widget);
buttupdate = false;
}
@@ -934,15 +968,16 @@ bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
input = getch();
switch(input) {
- case 10: // Enter
- output = bs.value[bs.curr]; // -> buttvalues[selbutton]
+ case KEY_ENTER:
+ case 10: /* Enter */
+ output = bs.value[bs.curr];
loop = false;
break;
- case 27: // Esc
+ case 27: /* Esc */
output = BSDDIALOG_ERROR;
loop = false;
break;
- case '\t': // TAB
+ case '\t': /* TAB */
bs.curr = (bs.curr + 1) % bs.nbuttons;
buttupdate = true;
break;
@@ -977,7 +1012,7 @@ bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
currH = (currH < nrights-1)? currH +1 : currH;
padsupdate = true;
break;
- case ' ': // Space
+ case ' ': /* Space */
items[curr].on = ! items[curr].on;
if (currV == LEFT) {
if (nlefts > 1)
@@ -1009,7 +1044,7 @@ bsddialog_buildlist(struct bsddialog_conf conf, char* text, int rows, int cols,
delwin(leftwin);
delwin(rightpad);
delwin(rightwin);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
diff --git a/contrib/bsddialog/lib/messagebox.c b/contrib/bsddialog/lib/messagebox.c
index 2920986b48a8..0f04eed11473 100644
--- a/contrib/bsddialog/lib/messagebox.c
+++ b/contrib/bsddialog/lib/messagebox.c
@@ -53,7 +53,7 @@
extern struct bsddialog_theme t;
static int
-message_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
+message_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
char *text, struct buttons bs)
{
int maxword, maxline, nlines, line;
@@ -65,10 +65,10 @@ message_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
*w = VBORDERS;
/* buttons size */
*w += bs.nbuttons * bs.sizebutton;
- *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
+ *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
/* text size */
- line = MIN(maxline + VBORDERS + t.texthmargin * 2, AUTO_WIDTH);
- line = MAX(line, (int) (maxword + VBORDERS + t.texthmargin * 2));
+ line = MIN(maxline + VBORDERS + t.text.hmargin * 2, AUTO_WIDTH);
+ line = MAX(line, (int) (maxword + VBORDERS + t.text.hmargin * 2));
*w = MAX(*w, line);
/* avoid terminal overflow */
*w = MIN(*w, widget_max_width(conf));
@@ -92,7 +92,7 @@ static int message_checksize(int rows, int cols, struct buttons bs)
mincols = VBORDERS;
mincols += bs.nbuttons * bs.sizebutton;
- mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.buttonspace : 0;
+ mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
if (cols < mincols)
RETURN_ERROR("Few cols, Msgbox and Yesno need at least width "\
@@ -126,7 +126,7 @@ textupdate(WINDOW *widget, int y, int x, int h, int w, WINDOW *textpad,
}
static int
-do_widget(struct bsddialog_conf conf, char *text, int rows, int cols,
+do_widget(struct bsddialog_conf *conf, char *text, int rows, int cols,
struct buttons bs, bool shortkey)
{
WINDOW *widget, *textpad, *shadow;
@@ -167,13 +167,13 @@ do_widget(struct bsddialog_conf conf, char *text, int rows, int cols,
buttonsupdate(widget, h, w, bs, shortkey);
break;
case KEY_F(1):
- if (conf.hfile == NULL)
+ if (conf->hfile == NULL)
break;
if (f1help(conf) != 0)
return BSDDIALOG_ERROR;
/* No break! the terminal size can change */
case KEY_RESIZE:
- hide_widget(y, x, h, w,conf.shadow);
+ hide_widget(y, x, h, w,conf->shadow);
/*
* Unnecessary, but, when the columns decrease the
@@ -191,7 +191,7 @@ do_widget(struct bsddialog_conf conf, char *text, int rows, int cols,
return BSDDIALOG_ERROR;
wclear(shadow);
- mvwin(shadow, y + t.shadowrows, x + t.shadowcols);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
wresize(shadow, h, w);
wclear(widget);
@@ -200,11 +200,11 @@ do_widget(struct bsddialog_conf conf, char *text, int rows, int cols,
htextpad = 1;
wclear(textpad);
- wresize(textpad, 1, w - HBORDERS - t.texthmargin * 2);
+ wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
if(update_widget_withtextpad(conf, shadow, widget, h, w,
RAISED, textpad, &htextpad, text, true) != 0)
- return BSDDIALOG_ERROR;
+ return BSDDIALOG_ERROR;
buttonsupdate(widget, h, w, bs, shortkey);
textupdate(widget, y, x, h, w, textpad, htextpad, textrow);
@@ -256,7 +256,7 @@ do_widget(struct bsddialog_conf conf, char *text, int rows, int cols,
/* API */
int
-bsddialog_msgbox(struct bsddialog_conf conf, char* text, int rows, int cols)
+bsddialog_msgbox(struct bsddialog_conf *conf, char* text, int rows, int cols)
{
struct buttons bs;
@@ -267,7 +267,7 @@ bsddialog_msgbox(struct bsddialog_conf conf, char* text, int rows, int cols)
}
int
-bsddialog_yesno(struct bsddialog_conf conf, char* text, int rows, int cols)
+bsddialog_yesno(struct bsddialog_conf *conf, char* text, int rows, int cols)
{
struct buttons bs;
diff --git a/contrib/bsddialog/lib/textbox.c b/contrib/bsddialog/lib/textbox.c
index 2874aa5832b9..481256fefc8a 100644
--- a/contrib/bsddialog/lib/textbox.c
+++ b/contrib/bsddialog/lib/textbox.c
@@ -40,16 +40,14 @@
#include "lib_util.h"
#include "bsddialog_theme.h"
-/* "Text": tailbox - tailboxbg - textbox */
+/* "Text": textbox */
#define BUTTON_TEXTBOX "HELP"
extern struct bsddialog_theme t;
-enum textmode { TAILMODE, TAILBGMODE, TEXTMODE};
-
static void
-textbox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
+textbox_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h, int *w,
int hpad, int wpad)
{
@@ -70,7 +68,7 @@ textbox_autosize(struct bsddialog_conf conf, int rows, int cols, int *h, int *w,
}
}
-static int textbox_checksize(int rows, int cols, int hpad, int wpad)
+static int textbox_checksize(int rows, int cols, int hpad)
{
int mincols;
@@ -85,8 +83,8 @@ static int textbox_checksize(int rows, int cols, int hpad, int wpad)
return 0;
}
-static int
-do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows, int cols)
+int
+bsddialog_textbox(struct bsddialog_conf *conf, char* file, int rows, int cols)
{
WINDOW *widget, *pad, *shadow;
int i, input, y, x, h, w, hpad, wpad, ypad, xpad, ys, ye, xs, xe, printrows;
@@ -95,26 +93,13 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
bool loop;
int output;
- if (mode == TAILMODE || mode == TAILBGMODE) {
- bsddialog_msgbox(conf, "Tailbox and Tailboxbg unimplemented", rows, cols);
- RETURN_ERROR("Tailbox and Tailboxbg unimplemented");
- }
-
- if ((fp = fopen(path, "r")) == NULL)
+ if ((fp = fopen(file, "r")) == NULL)
RETURN_ERROR("Cannot open file");
- /*if (mode == TAILMODE) {
- fseek (fp, 0, SEEK_END);
- i = nlines = 0;
- while (i < hpad) {
- line = ;
- }
- for (i=hpad-1; i--; i>=0) {
- }
- }*/
+
hpad = 1;
wpad = 1;
pad = newpad(hpad, wpad);
- wbkgd(pad, t.widgetcolor);
+ wbkgd(pad, t.widget.color);
i = 0;
while(fgets(buf, BUFSIZ, fp) != NULL) {
if ((int) strlen(buf) > wpad) {
@@ -133,7 +118,7 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad);
- if (textbox_checksize(h, w, hpad, wpad) != 0)
+ if (textbox_checksize(h, w, hpad) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
@@ -142,9 +127,9 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
NULL, NULL, NULL, true) != 0)
return BSDDIALOG_ERROR;
- exitbutt = conf.button.exit_label == NULL ? BUTTON_TEXTBOX : conf.button.exit_label;
+ exitbutt = conf->button.exit_label == NULL ? BUTTON_TEXTBOX : conf->button.exit_label;
draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2, strlen(exitbutt)+2,
- exitbutt, true, true);
+ exitbutt, true, false);
wrefresh(widget);
@@ -202,13 +187,13 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
ypad = ypad + printrows <= hpad -1 ? ypad + 1 : ypad;
break;
case KEY_F(1):
- if (conf.hfile == NULL)
+ if (conf->hfile == NULL)
break;
if (f1help(conf) != 0)
return BSDDIALOG_ERROR;
/* No break! the terminal size can change */
case KEY_RESIZE:
- hide_widget(y, x, h, w,conf.shadow);
+ hide_widget(y, x, h, w,conf->shadow);
/*
* Unnecessary, but, when the columns decrease the
@@ -219,13 +204,13 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
if (set_widget_size(conf, rows, cols, &h, &w) != 0)
return BSDDIALOG_ERROR;
textbox_autosize(conf, rows, cols, &h, &w, hpad, wpad);
- if (textbox_checksize(h, w, hpad, wpad) != 0)
+ if (textbox_checksize(h, w, hpad) != 0)
return BSDDIALOG_ERROR;
if (set_widget_position(conf, &y, &x, h, w) != 0)
return BSDDIALOG_ERROR;
wclear(shadow);
- mvwin(shadow, y + t.shadowrows, x + t.shadowcols);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
wresize(shadow, h, w);
wclear(widget);
@@ -244,7 +229,7 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
return BSDDIALOG_ERROR;
draw_button(widget, h-2, (w-2)/2 - strlen(exitbutt)/2,
- strlen(exitbutt)+2, exitbutt, true, true);
+ strlen(exitbutt)+2, exitbutt, true, false);
wrefresh(widget); /* for button */
@@ -258,23 +243,3 @@ do_textbox(enum textmode mode, struct bsddialog_conf conf, char* path, int rows,
return output;
}
-
-int bsddialog_tailbox(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
-
- return (do_textbox(TAILMODE, conf, text, rows, cols));
-}
-
-int bsddialog_tailboxbg(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
-
- return (do_textbox(TAILBGMODE, conf, text, rows, cols));
-}
-
-
-int bsddialog_textbox(struct bsddialog_conf conf, char* text, int rows, int cols)
-{
-
- return (do_textbox(TEXTMODE, conf, text, rows, cols));
-}
-
diff --git a/contrib/bsddialog/lib/theme.c b/contrib/bsddialog/lib/theme.c
index 7c27a85af74f..f204729ab4c1 100644
--- a/contrib/bsddialog/lib/theme.c
+++ b/contrib/bsddialog/lib/theme.c
@@ -42,213 +42,172 @@ struct bsddialog_theme t;
static struct bsddialog_theme bsddialogtheme = {
#define bgwidget COLOR_WHITE
#define bgcurr COLOR_YELLOW
- .shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadowrows = 1,
- .shadowcols = 2,
-
- .backgroundcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
- .surroundtitle = true,
- .titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget),
- .lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .widgetcolor = GET_COLOR(COLOR_BLACK, bgwidget),
-
- .texthmargin = 1,
-
- .curritemcolor = GET_COLOR(COLOR_WHITE, bgcurr),
- .itemcolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .currtagcolor = GET_COLOR(COLOR_BLACK, bgcurr),
- .tagcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
- .namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
- .descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
-
- .currfieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
- .fieldreadonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE),
-
- .currbarcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
- .barcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
-
- .buttonspace = 3,
- .buttleftch = '[',
- .buttrightchar = ']',
- .currbuttdelimcolor = GET_COLOR(COLOR_WHITE, bgcurr),
- .buttdelimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
- .currbuttoncolor = GET_COLOR(COLOR_WHITE, bgcurr) | A_UNDERLINE,
- .buttoncolor = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE,
- .currshortkeycolor = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE,
- .shortkeycolor = GET_COLOR(COLOR_YELLOW, bgwidget) | A_UNDERLINE,
-
- .bottomtitlecolor= GET_COLOR(COLOR_BLACK, bgwidget)
+ .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
+ .shadow.h = 1,
+ .shadow.w = 2,
+
+ .terminal.color = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
+ .widget.delimtitle = true,
+ .widget.titlecolor = GET_COLOR(COLOR_YELLOW, bgwidget),
+ .widget.lineraisecolor = GET_COLOR(COLOR_BLACK, bgwidget),
+ .widget.linelowercolor = GET_COLOR(COLOR_BLACK, bgwidget),
+ .widget.color = GET_COLOR(COLOR_BLACK, bgwidget),
+ .widget.bottomtitlecolor = GET_COLOR(COLOR_BLACK, bgwidget),
+
+ .text.hmargin = 1,
+
+ .menu.arrowcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
+ .menu.f_desccolor = GET_COLOR(COLOR_WHITE, bgcurr),
+ .menu.desccolor = GET_COLOR(COLOR_BLACK, bgwidget),
+ .menu.f_namecolor = GET_COLOR(COLOR_BLACK, bgcurr),
+ .menu.namecolor = GET_COLOR(COLOR_YELLOW, bgwidget),
+ .menu.namesepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
+ .menu.descsepcolor = GET_COLOR(COLOR_YELLOW, bgwidget),
+
+ .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
+ .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN),
+ .form.readonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE),
+
+ .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE),
+ .bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE),
+
+ .button.space = 3,
+ .button.leftch = '[',
+ .button.rightch = ']',
+ .button.f_delimcolor = GET_COLOR(COLOR_WHITE, bgcurr),
+ .button.delimcolor = GET_COLOR(COLOR_BLACK, bgwidget),
+ .button.f_color = GET_COLOR(COLOR_WHITE, bgcurr) | A_UNDERLINE,
+ .button.color = GET_COLOR(COLOR_BLACK, bgwidget) | A_UNDERLINE,
+ .button.f_shortcutcolor = GET_COLOR(COLOR_BLACK, bgcurr) | A_UNDERLINE,
+ .button.shortcutcolor = GET_COLOR(COLOR_YELLOW, bgwidget) | A_UNDERLINE
};
static struct bsddialog_theme blackwhite = {
#define bk COLOR_BLACK
#define fg COLOR_WHITE
- .shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadowrows = 1,
- .shadowcols = 2,
-
- .backgroundcolor = GET_COLOR(fg, bk),
- .surroundtitle = true,
- .titlecolor = GET_COLOR(fg, bk),
- .lineraisecolor = GET_COLOR(fg, bk),
- .linelowercolor = GET_COLOR(fg, bk),
- .widgetcolor = GET_COLOR(fg, bk),
-
- .texthmargin = 1,
-
- .curritemcolor = GET_COLOR(fg, bk) | A_REVERSE,
- .itemcolor = GET_COLOR(fg, bk),
- .currtagcolor = GET_COLOR(fg, bk) | A_REVERSE,
- .tagcolor = GET_COLOR(fg, bk),
- .namesepcolor = GET_COLOR(fg, bk),
- .descsepcolor = GET_COLOR(fg, bk),
-
- .currfieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
- .fieldcolor = GET_COLOR(fg, bk),
- .fieldreadonlycolor = GET_COLOR(fg, bk),
-
- .currbarcolor = GET_COLOR(fg, bk) | A_REVERSE,
- .barcolor = GET_COLOR(fg, bk),
-
- .buttonspace = 3,
- .buttleftch = '[',
- .buttrightchar = ']',
- .currbuttdelimcolor = GET_COLOR(fg, bk),
- .buttdelimcolor = GET_COLOR(fg, bk),
- .currbuttoncolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
- .buttoncolor = GET_COLOR(fg, bk) | A_UNDERLINE,
- .currshortkeycolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
- .shortkeycolor = GET_COLOR(fg, bk) | A_UNDERLINE,
-
- .bottomtitlecolor= GET_COLOR(fg, bk)
+ .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
+ .shadow.h = 1,
+ .shadow.w = 2,
+
+ .terminal.color = GET_COLOR(fg, bk),
+ .widget.delimtitle = true,
+ .widget.titlecolor = GET_COLOR(fg, bk),
+ .widget.lineraisecolor = GET_COLOR(fg, bk),
+ .widget.linelowercolor = GET_COLOR(fg, bk),
+ .widget.color = GET_COLOR(fg, bk),
+ .widget.bottomtitlecolor = GET_COLOR(fg, bk),
+
+ .text.hmargin = 1,
+
+ .menu.arrowcolor = GET_COLOR(fg, bk),
+ .menu.f_desccolor = GET_COLOR(fg, bk) | A_REVERSE,
+ .menu.desccolor = GET_COLOR(fg, bk),
+ .menu.f_namecolor = GET_COLOR(fg, bk) | A_REVERSE,
+ .menu.namecolor = GET_COLOR(fg, bk),
+ .menu.namesepcolor = GET_COLOR(fg, bk),
+ .menu.descsepcolor = GET_COLOR(fg, bk),
+
+ .form.f_fieldcolor = GET_COLOR(fg, bk) | A_REVERSE,
+ .form.fieldcolor = GET_COLOR(fg, bk),
+ .form.readonlycolor = GET_COLOR(fg, bk),
+
+ .bar.f_color = GET_COLOR(fg, bk) | A_REVERSE,
+ .bar.color = GET_COLOR(fg, bk),
+
+ .button.space = 3,
+ .button.leftch = '[',
+ .button.rightch = ']',
+ .button.f_delimcolor = GET_COLOR(fg, bk),
+ .button.delimcolor = GET_COLOR(fg, bk),
+ .button.f_color = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
+ .button.color = GET_COLOR(fg, bk) | A_UNDERLINE,
+ .button.f_shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE | A_REVERSE,
+ .button.shortcutcolor = GET_COLOR(fg, bk) | A_UNDERLINE
};
static struct bsddialog_theme dialogtheme = {
- .shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadowrows = 1,
- .shadowcols = 2,
-
- .backgroundcolor = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD,
- .surroundtitle = false,
- .titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
- .lineraisecolor = GET_COLOR(COLOR_WHITE, COLOR_WHITE) | A_BOLD,
- .linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
- .widgetcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
-
- .texthmargin = 1,
-
- .curritemcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .itemcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
- .currtagcolor = GET_COLOR(COLOR_YELLOW,COLOR_BLUE) | A_BOLD,
- .tagcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
- .namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
- .descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
-
- .currfieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
- .fieldreadonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE)| A_BOLD,
-
- .currbarcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .barcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
-
- .buttonspace = 3,
- .buttleftch = '<',
- .buttrightchar = '>',
- .currbuttdelimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .buttdelimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
- .currbuttoncolor = GET_COLOR(COLOR_YELLOW, COLOR_BLUE) | A_BOLD,
- .buttoncolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
- .currshortkeycolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .shortkeycolor = GET_COLOR(COLOR_RED, COLOR_WHITE) | A_BOLD,
-
- .bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD
-};
-
-static struct bsddialog_theme magentatheme = {
- .shadowcolor = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
- .shadowrows = 1,
- .shadowcols = 2,
-
- .backgroundcolor = GET_COLOR(COLOR_WHITE, COLOR_MAGENTA) | A_BOLD,
- .surroundtitle = true,
- .titlecolor = GET_COLOR(COLOR_RED, COLOR_CYAN),
- .lineraisecolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
- .linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
- .widgetcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
-
- .texthmargin = 1,
-
- .curritemcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .itemcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN) | A_BOLD,
- .currtagcolor = GET_COLOR(COLOR_YELLOW,COLOR_BLUE) | A_BOLD,
- .tagcolor = GET_COLOR(COLOR_BLUE, COLOR_CYAN) | A_BOLD,
- .namesepcolor = GET_COLOR(COLOR_RED, COLOR_CYAN) | A_BOLD,
- .descsepcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN) | A_BOLD,
-
- .currfieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
- .fieldreadonlycolor = GET_COLOR(COLOR_CYAN,COLOR_WHITE)| A_BOLD,
-
- .currbarcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
- .barcolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
-
- .buttonspace = 3,
- .buttleftch = '<',
- .buttrightchar = '>',
- .currbuttdelimcolor = GET_COLOR(COLOR_WHITE, COLOR_RED) | A_BOLD,
- .buttdelimcolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
- .currbuttoncolor = GET_COLOR(COLOR_WHITE, COLOR_RED),
- .buttoncolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
- .currshortkeycolor = GET_COLOR(COLOR_WHITE, COLOR_RED) | A_BOLD,
- .shortkeycolor = GET_COLOR(COLOR_BLACK, COLOR_CYAN),
-
- .bottomtitlecolor= GET_COLOR(COLOR_BLACK, COLOR_CYAN) | A_BOLD
+ .shadow.color = GET_COLOR(COLOR_BLACK, COLOR_BLACK),
+ .shadow.h = 1,
+ .shadow.w = 2,
+
+ .terminal.color = GET_COLOR(COLOR_CYAN, COLOR_BLUE) | A_BOLD,
+ .widget.delimtitle = false,
+ .widget.titlecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
+ .widget.lineraisecolor = GET_COLOR(COLOR_WHITE, COLOR_WHITE) | A_BOLD,
+ .widget.linelowercolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
+ .widget.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .widget.bottomtitlecolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
+
+ .text.hmargin = 1,
+
+ .menu.arrowcolor = GET_COLOR(COLOR_GREEN, COLOR_WHITE),
+ .menu.f_desccolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
+ .menu.desccolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE) | A_BOLD,
+ .menu.f_namecolor = GET_COLOR(COLOR_YELLOW,COLOR_BLUE) | A_BOLD,
+ .menu.namecolor = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
+ .menu.namesepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+ .menu.descsepcolor = GET_COLOR(COLOR_RED, COLOR_WHITE),
+
+ .form.f_fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
+ .form.fieldcolor = GET_COLOR(COLOR_WHITE, COLOR_CYAN) | A_BOLD,
+ .form.readonlycolor = GET_COLOR(COLOR_CYAN, COLOR_WHITE)| A_BOLD,
+
+ .bar.f_color = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
+ .bar.color = GET_COLOR(COLOR_BLUE, COLOR_WHITE) | A_BOLD,
+
+ .button.space = 3,
+ .button.leftch = '<',
+ .button.rightch = '>',
+ .button.f_delimcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
+ .button.delimcolor = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .button.f_color = GET_COLOR(COLOR_YELLOW, COLOR_BLUE) | A_BOLD,
+ .button.color = GET_COLOR(COLOR_BLACK, COLOR_WHITE),
+ .button.f_shortcutcolor = GET_COLOR(COLOR_WHITE, COLOR_BLUE) | A_BOLD,
+ .button.shortcutcolor = GET_COLOR(COLOR_RED, COLOR_WHITE) | A_BOLD
};
void bsddialog_set_theme(struct bsddialog_theme newtheme)
{
- t.shadowcolor = newtheme.shadowcolor;
- t.shadowrows = newtheme.shadowrows;
- t.shadowcols = newtheme.shadowcols;
-
- t.backgroundcolor = newtheme.backgroundcolor;
- t.surroundtitle = newtheme.surroundtitle;
- t.titlecolor = newtheme.titlecolor;
- t.lineraisecolor = newtheme.lineraisecolor;
- t.linelowercolor = newtheme.linelowercolor;
- t.widgetcolor = newtheme.widgetcolor;
-
- t.texthmargin = newtheme.texthmargin;
-
- t.curritemcolor = newtheme.curritemcolor;
- t.itemcolor = newtheme.itemcolor;
- t.currtagcolor = newtheme.currtagcolor;
- t.tagcolor = newtheme.tagcolor;
- t.namesepcolor = newtheme.namesepcolor;
- t.descsepcolor = newtheme.descsepcolor;
-
- t.currfieldcolor = newtheme.currfieldcolor;
- t.fieldcolor = newtheme.fieldcolor;
- t.fieldreadonlycolor = newtheme.fieldreadonlycolor;
-
- t.currbarcolor = newtheme.currbarcolor;
- t.barcolor = newtheme.barcolor;
-
- t.buttonspace = newtheme.buttonspace;
- t.buttleftch = newtheme.buttleftch;
- t.buttrightchar = newtheme.buttrightchar;
- t.currbuttdelimcolor = newtheme.currbuttdelimcolor;
- t.buttdelimcolor = newtheme.buttdelimcolor;
- t.currbuttoncolor = newtheme.currbuttoncolor;
- t.buttoncolor = newtheme.buttoncolor;
- t.currshortkeycolor = newtheme.currshortkeycolor;
- t.shortkeycolor = newtheme.shortkeycolor;
-
- t.bottomtitlecolor = newtheme.bottomtitlecolor;
-
- bkgd(t.backgroundcolor);
+ t.shadow.color = newtheme.shadow.color;
+ t.shadow.h = newtheme.shadow.h;
+ t.shadow.w = newtheme.shadow.w;
+
+ t.terminal.color = newtheme.terminal.color;
+ t.widget.delimtitle = newtheme.widget.delimtitle;
+ t.widget.titlecolor = newtheme.widget.titlecolor;
+ t.widget.lineraisecolor = newtheme.widget.lineraisecolor;
+ t.widget.linelowercolor = newtheme.widget.linelowercolor;
+ t.widget.color = newtheme.widget.color;
+ t.widget.bottomtitlecolor = newtheme.widget.bottomtitlecolor;
+
+ t.text.hmargin = newtheme.text.hmargin;
+
+ t.menu.arrowcolor = newtheme.menu.arrowcolor;
+ t.menu.f_desccolor = newtheme.menu.f_desccolor;
+ t.menu.desccolor = newtheme.menu.desccolor;
+ t.menu.f_namecolor = newtheme.menu.f_namecolor;
+ t.menu.namecolor = newtheme.menu.namecolor;
+ t.menu.namesepcolor = newtheme.menu.namesepcolor;
+ t.menu.descsepcolor = newtheme.menu.descsepcolor;
+
+ t.form.f_fieldcolor = newtheme.form.f_fieldcolor;
+ t.form.fieldcolor = newtheme.form.fieldcolor;
+ t.form.readonlycolor = newtheme.form.readonlycolor;
+
+ t.bar.f_color = newtheme.bar.f_color;
+ t.bar.color = newtheme.bar.color;
+
+ t.button.space = newtheme.button.space;
+ t.button.leftch = newtheme.button.leftch;
+ t.button.rightch = newtheme.button.rightch;
+ t.button.f_delimcolor = newtheme.button.f_delimcolor;
+ t.button.delimcolor = newtheme.button.delimcolor;
+ t.button.f_color = newtheme.button.f_color;
+ t.button.color = newtheme.button.color;
+ t.button.f_shortcutcolor = newtheme.button.f_shortcutcolor;
+ t.button.shortcutcolor = newtheme.button.shortcutcolor;
+
+ bkgd(t.terminal.color);
refresh();
}
@@ -264,8 +223,6 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
bsddialog_set_theme(blackwhite);
else if (newtheme == BSDDIALOG_THEME_DIALOG)
bsddialog_set_theme(dialogtheme);
- else if (newtheme == BSDDIALOG_THEME_MAGENTA)
- bsddialog_set_theme(magentatheme);
else
RETURN_ERROR("Unknow default theme");
@@ -273,7 +230,8 @@ int bsddialog_set_default_theme(enum bsddialog_default_theme newtheme)
}
int
-bsddialog_color(enum bsddialog_color background, enum bsddialog_color foreground)
+bsddialog_color(enum bsddialog_color background,
+ enum bsddialog_color foreground)
{
return GET_COLOR(background, foreground);
diff --git a/contrib/bsddialog/lib/timebox.c b/contrib/bsddialog/lib/timebox.c
index f7abfd8c0f31..4b1b8ee989a6 100644
--- a/contrib/bsddialog/lib/timebox.c
+++ b/contrib/bsddialog/lib/timebox.c
@@ -25,59 +25,146 @@
* SUCH DAMAGE.
*/
+#include <sys/param.h>
+
#ifdef PORTNCURSES
#include <ncurses/curses.h>
#else
#include <curses.h>
#endif
+#include <ctype.h>
+#include <string.h>
+
#include "bsddialog.h"
#include "lib_util.h"
+#include "bsddialog_theme.h"
-/* "Time": timebox - calendar */
+#define MINWDATE 25 /* 23 wins + 2 VBORDERS */
+#define MINWTIME 16 /*14 wins + 2 VBORDERS */
+#define MINHEIGHT 8 /* 2 for text */
-int bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols,
- unsigned int *hh, unsigned int *mm, unsigned int *ss)
+/* "Time": timebox - datebox */
+
+extern struct bsddialog_theme t;
+
+static int
+datetime_autosize(struct bsddialog_conf *conf, int rows, int cols, int *h,
+ int *w, int minw, char *text, struct buttons bs)
{
- WINDOW *widget, *shadow;
- int i, input, output, y, x, sel;
- struct buttons bs;
- bool loop, buttupdate;
+ int maxword, maxline, nlines, line;
- if (hh == NULL || mm == NULL || ss == NULL)
- RETURN_ERROR("hh or mm or ss == NULL");
+ if (get_text_properties(conf, text, &maxword, &maxline, &nlines) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (cols == BSDDIALOG_AUTOSIZE) {
+ *w = VBORDERS;
+ /* buttons size */
+ *w += bs.nbuttons * bs.sizebutton;
+ *w += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
+ /* text size */
+ line = maxline + VBORDERS + t.text.hmargin * 2;
+ line = MAX(line, (int) (maxword + VBORDERS + t.text.hmargin * 2));
+ *w = MAX(*w, line);
+ /* date windows */
+ *w = MAX(*w, minw);
+ /* avoid terminal overflow */
+ *w = MIN(*w, widget_max_width(conf) -1);
+ }
+
+ if (rows == BSDDIALOG_AUTOSIZE) {
+ *h = MINHEIGHT;
+ if (maxword > 0)
+ *h += MAX(nlines, (*w / GET_ASPECT_RATIO(conf)));
+ /* avoid terminal overflow */
+ *h = MIN(*h, widget_max_height(conf) -1);
+ }
+
+ return 0;
+}
+
+static int
+datetime_checksize(int rows, int cols, char *text, int minw, struct buttons bs)
+{
+ int mincols;
+
+ mincols = VBORDERS;
+ mincols += bs.nbuttons * bs.sizebutton;
+ mincols += bs.nbuttons > 0 ? (bs.nbuttons-1) * t.button.space : 0;
+ mincols = MAX(minw, mincols);
+
+ if (cols < mincols)
+ RETURN_ERROR("Few cols for this timebox/datebox");
+
+ if (rows < MINHEIGHT + (strlen(text) > 0 ? 1 : 0))
+ RETURN_ERROR("Few rows for this timebox/datebox");
+ return 0;
+}
+
+int bsddialog_timebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
+ unsigned int *hh, unsigned int *mm, unsigned int *ss)
+{
+ WINDOW *widget, *textpad, *shadow;
+ int i, input, output, y, x, h, w, sel, htextpad;
+ struct buttons bs;
+ bool loop;
struct myclockstruct {
unsigned int max;
- unsigned int curr;
+ unsigned int value;
WINDOW *win;
- } c[3] = { {23, *hh, NULL}, {59, *mm, NULL}, {59, *ss, NULL} };
+ };
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
+ if (hh == NULL || mm == NULL || ss == NULL)
+ RETURN_ERROR("hh / mm / ss cannot be NULL");
+
+ struct myclockstruct c[3] = {
+ {23, *hh, NULL},
+ {59, *mm, NULL},
+ {59, *ss, NULL}
+ };
- c[0].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 7, 3, 4, LOWERED);
- mvwaddch(widget, rows - 5, cols/2 - 3, ':');
- c[1].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 2, 3, 4, LOWERED);
- mvwaddch(widget, rows - 5, cols/2 + 2, ':');
- c[2].win = new_boxed_window(conf, y + rows - 6, x + cols/2 + 3, 3, 4, LOWERED);
+ for (i = 0 ; i < 3; i++) {
+ if (c[i].value > c[i].max)
+ c[i].value = c[i].max;
+ }
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
- sel=0;
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_checksize(h, w, text, MINWTIME, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ draw_buttons(widget, h-2, w, bs, true);
+
+ wrefresh(widget);
+
+ prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
+
+ c[0].win = new_boxed_window(conf, y + h - 6, x + w/2 - 7, 3, 4, LOWERED);
+ mvwaddch(widget, h - 5, w/2 - 3, ':');
+ c[1].win = new_boxed_window(conf, y + h - 6, x + w/2 - 2, 3, 4, LOWERED);
+ mvwaddch(widget, h - 5, w/2 + 2, ':');
+ c[2].win = new_boxed_window(conf, y + h - 6, x + w/2 + 3, 3, 4, LOWERED);
+
+ wrefresh(widget);
+
+ sel = 0;
curs_set(2);
- loop = buttupdate = true;
+ loop = true;
while(loop) {
- if (buttupdate) {
- draw_buttons(widget, rows-2, cols, bs, true);
- wrefresh(widget);
- buttupdate = false;
- }
-
for (i=0; i<3; i++) {
- mvwprintw(c[i].win, 1, 1, "%2d", c[i].curr);
+ mvwprintw(c[i].win, 1, 1, "%2d", c[i].value);
wrefresh(c[i].win);
}
wmove(c[sel].win, 1, 2);
@@ -85,12 +172,13 @@ int bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols
input = getch();
switch(input) {
+ case KEY_ENTER:
case 10: /* Enter */
output = bs.value[bs.curr];
if (output == BSDDIALOG_YESOK) {
- *hh = c[0].curr - 1900;
- *mm = c[1].curr;
- *ss = c[2].curr;
+ *hh = c[0].value;
+ *mm = c[1].value;
+ *ss = c[2].value;
}
loop = false;
break;
@@ -104,21 +192,98 @@ int bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
- buttupdate = true;
+ draw_buttons(widget, h-2, w, bs, true);
+ wrefresh(widget);
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
- buttupdate = true;
+ draw_buttons(widget, h-2, w, bs, true);
+ wrefresh(widget);
}
break;
case KEY_UP:
- c[sel].curr = c[sel].curr < c[sel].max ? c[sel].curr + 1 : 0;
+ c[sel].value = c[sel].value < c[sel].max ? c[sel].value + 1 : 0;
break;
case KEY_DOWN:
- c[sel].curr = c[sel].curr > 0 ? c[sel].curr - 1 : c[sel].max;
+ c[sel].value = c[sel].value > 0 ? c[sel].value - 1 : c[sel].max;
+ break;
+ case KEY_F(1):
+ if (conf->hfile == NULL)
+ break;
+ curs_set(0);
+ if (f1help(conf) != 0)
+ return BSDDIALOG_ERROR;
+ curs_set(2);
+ /* No break! the terminal size can change */
+ case KEY_RESIZE:
+ hide_widget(y, x, h, w,conf->shadow);
+
+ /*
+ * Unnecessary, but, when the columns decrease the
+ * following "refresh" seem not work
+ */
+ refresh();
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_autosize(conf, rows, cols, &h, &w, MINWTIME, text, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_checksize(h, w, text, MINWTIME, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ wclear(shadow);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
+ wresize(shadow, h, w);
+
+ wclear(widget);
+ mvwin(widget, y, x);
+ wresize(widget, h, w);
+
+ htextpad = 1;
+ wclear(textpad);
+ wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
+
+ if(update_widget_withtextpad(conf, shadow, widget, h, w,
+ RAISED, textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ mvwaddch(widget, h - 5, w/2 - 3, ':');
+ mvwaddch(widget, h - 5, w/2 + 2, ':');
+
+ draw_buttons(widget, h-2, w, bs, true);
+
+ wrefresh(widget);
+
+ prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
+
+ wclear(c[0].win);
+ mvwin(c[0].win, y + h - 6, x + w/2 - 7);
+ draw_borders(conf, c[0].win, 3, 4, LOWERED);
+ wrefresh(c[0].win);
+
+ wclear(c[1].win);
+ mvwin(c[1].win, y + h - 6, x + w/2 - 2);
+ draw_borders(conf, c[1].win, 3, 4, LOWERED);
+ wrefresh(c[1].win);
+
+ wclear(c[2].win);
+ mvwin(c[2].win, y + h - 6, x + w/2 + 3);
+ draw_borders(conf, c[2].win, 3, 4, LOWERED);
+ wrefresh(c[2].win);
+
+ /* Important to avoid grey lines expanding screen */
+ refresh();
break;
+ default:
+ for (i = 0; i < (int) bs.nbuttons; i++)
+ if (tolower(input) == tolower((bs.label[i])[0])) {
+ output = bs.value[i];
+ loop = false;
+ }
}
}
@@ -126,66 +291,97 @@ int bsddialog_timebox(struct bsddialog_conf conf, char* text, int rows, int cols
for (i=0; i<3; i++)
delwin(c[i].win);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
-int bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int cols,
+int
+bsddialog_datebox(struct bsddialog_conf *conf, char* text, int rows, int cols,
unsigned int *yy, unsigned int *mm, unsigned int *dd)
{
- WINDOW *widget, *shadow;
- int i, input, output, y, x, sel;
+ WINDOW *widget, *textpad, *shadow;
+ int i, input, output, y, x, h, w, sel, htextpad;
struct buttons bs;
- bool loop, buttupdate;
-
- if (yy == NULL || mm == NULL || dd == NULL)
- RETURN_ERROR("yy or mm or dd == NULL");
-
+ bool loop;
struct calendar {
- unsigned int max;
- unsigned int curr;
+ int max;
+ int value;
WINDOW *win;
unsigned int x;
- } c[3] = {{9999, *yy, NULL, 4 }, {12, *mm, NULL, 9 }, {31, *dd, NULL, 2 }};
+ };
struct month {
char *name;
unsigned int days;
- } m[12] = {
- { "January", 30 }, { "February", 30 }, { "March", 30 },
- { "April", 30 }, { "May", 30 }, { "June", 30 },
- { "July", 30 }, { "August", 30 }, { "September", 30 },
- { "October", 30 }, { "November", 30 }, { "December", 30 }
};
- if (new_widget(conf, &widget, &y, &x, text, &rows, &cols, &shadow,
- true) <0)
- return -1;
+ if (yy == NULL || mm == NULL || dd == NULL)
+ RETURN_ERROR("yy / mm / dd cannot be NULL");
+
+ struct calendar c[3] = {
+ {9999, *yy, NULL, 4 },
+ {12, *mm, NULL, 9 },
+ {31, *dd, NULL, 2 }
+ };
+
+ struct month m[12] = {
+ { "January", 31 }, { "February", 28 }, { "March", 31 },
+ { "April", 30 }, { "May", 31 }, { "June", 30 },
+ { "July", 31 }, { "August", 31 }, { "September", 30 },
+ { "October", 31 }, { "November", 30 }, { "December", 31 }
+ };
- c[0].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 12, 3, 6, LOWERED);
- mvwaddch(widget, rows - 5, cols/2 - 6, '/');
- c[1].win = new_boxed_window(conf, y + rows - 6, x + cols/2 - 5, 3, 11, LOWERED);
- mvwaddch(widget, rows - 5, cols/2 + 6, '/');
- c[2].win = new_boxed_window(conf, y + rows - 6, x + cols/2 + 7, 3, 4, LOWERED);
+#define ISLEAF(year) ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
- wrefresh(widget);
+ for (i = 0 ; i < 3; i++) {
+ if (c[i].value > c[i].max)
+ c[i].value = c[i].max;
+ if (c[i].value < 1)
+ c[i].value = 1;
+ }
+ c[2].max = m[c[1].value -1].days;
+ if (c[1].value == 2 && ISLEAF(c[0].value))
+ c[2].max = 29;
+ if (c[2].value > c[2].max)
+ c[2].value = c[2].max;
get_buttons(conf, &bs, BUTTONLABEL(ok_label), BUTTONLABEL(extra_label),
BUTTONLABEL(cancel_label), BUTTONLABEL(help_label));
- sel=2;
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_checksize(h, w, text, MINWDATE, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ if (new_widget_withtextpad(conf, &shadow, &widget, y, x, h, w, RAISED,
+ &textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ draw_buttons(widget, h-2, w, bs, true);
+
+ wrefresh(widget);
+
+ prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
+
+ c[0].win = new_boxed_window(conf, y + h - 6, x + w/2 - 11, 3, 6, LOWERED);
+ mvwaddch(widget, h - 5, w/2 - 5, '/');
+ c[1].win = new_boxed_window(conf, y + h - 6, x + w/2 - 4, 3, 11, LOWERED);
+ mvwaddch(widget, h - 5, w/2 + 7, '/');
+ c[2].win = new_boxed_window(conf, y + h - 6, x + w/2 + 8, 3, 4, LOWERED);
+
+ wrefresh(widget);
+
+ sel = 2;
curs_set(2);
- loop = buttupdate = true;
+ loop = true;
while(loop) {
- if (buttupdate) {
- draw_buttons(widget, rows-2, cols, bs, true);
- wrefresh(widget);
- buttupdate = false;
- }
-
- mvwprintw(c[0].win, 1, 1, "%4d", c[0].curr);
- mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].curr-1].name);
- mvwprintw(c[2].win, 1, 1, "%2d", c[2].curr);
+ mvwprintw(c[0].win, 1, 1, "%4d", c[0].value);
+ mvwprintw(c[1].win, 1, 1, "%9s", m[c[1].value-1].name);
+ mvwprintw(c[2].win, 1, 1, "%2d", c[2].value);
for (i=0; i<3; i++) {
wrefresh(c[i].win);
}
@@ -194,40 +390,134 @@ int bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int col
input = getch();
switch(input) {
- case 10: // Enter
- output = bs.value[bs.curr]; // values -> outputs
+ case KEY_ENTER:
+ case 10: /* Enter */
+ output = bs.value[bs.curr];
if (output == BSDDIALOG_YESOK) {
- *yy = c[0].curr - 1900;
- *mm = c[1].curr;
- *dd = c[2].curr;
+ *yy = c[0].value;
+ *mm = c[1].value;
+ *dd = c[2].value;
}
loop = false;
break;
- case 27: // Esc
+ case 27: /* Esc */
output = BSDDIALOG_ESC;
loop = false;
break;
- case '\t': // TAB
+ case '\t': /* TAB */
sel = (sel + 1) % 3;
break;
case KEY_LEFT:
if (bs.curr > 0) {
bs.curr--;
- buttupdate = true;
+ draw_buttons(widget, h-2, w, bs, true);
+ wrefresh(widget);
}
break;
case KEY_RIGHT:
if (bs.curr < (int) bs.nbuttons - 1) {
bs.curr++;
- buttupdate = true;
+ draw_buttons(widget, h-2, w, bs, true);
+ wrefresh(widget);
}
break;
case KEY_UP:
- c[sel].curr = c[sel].curr < c[sel].max ? c[sel].curr + 1 : 1;
+ c[sel].value = c[sel].value > 1 ? c[sel].value - 1 : c[sel].max ;
+ /* if mount change */
+ c[2].max = m[c[1].value -1].days;
+ /* if year change */
+ if (c[1].value == 2 && ISLEAF(c[0].value))
+ c[2].max = 29;
+ /* set new day */
+ if (c[2].value > c[2].max)
+ c[2].value = c[2].max;
break;
case KEY_DOWN:
- c[sel].curr = c[sel].curr > 1 ? c[sel].curr - 1 : c[sel].max;
+ c[sel].value = c[sel].value < c[sel].max ? c[sel].value + 1 : 1;
+ /* if mount change */
+ c[2].max = m[c[1].value -1].days;
+ /* if year change */
+ if (c[1].value == 2 && ISLEAF(c[0].value))
+ c[2].max = 29;
+ /* set new day */
+ if (c[2].value > c[2].max)
+ c[2].value = c[2].max;
+ break;
+ case KEY_F(1):
+ if (conf->hfile == NULL)
+ break;
+ curs_set(0);
+ if (f1help(conf) != 0)
+ return BSDDIALOG_ERROR;
+ curs_set(2);
+ /* No break! the terminal size can change */
+ case KEY_RESIZE:
+ hide_widget(y, x, h, w,conf->shadow);
+
+ /*
+ * Unnecessary, but, when the columns decrease the
+ * following "refresh" seem not work
+ */
+ refresh();
+
+ if (set_widget_size(conf, rows, cols, &h, &w) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_autosize(conf, rows, cols, &h, &w, MINWDATE, text, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (datetime_checksize(h, w, text, MINWDATE, bs) != 0)
+ return BSDDIALOG_ERROR;
+ if (set_widget_position(conf, &y, &x, h, w) != 0)
+ return BSDDIALOG_ERROR;
+
+ wclear(shadow);
+ mvwin(shadow, y + t.shadow.h, x + t.shadow.w);
+ wresize(shadow, h, w);
+
+ wclear(widget);
+ mvwin(widget, y, x);
+ wresize(widget, h, w);
+
+ htextpad = 1;
+ wclear(textpad);
+ wresize(textpad, 1, w - HBORDERS - t.text.hmargin * 2);
+
+ if(update_widget_withtextpad(conf, shadow, widget, h, w,
+ RAISED, textpad, &htextpad, text, true) != 0)
+ return BSDDIALOG_ERROR;
+
+ mvwaddch(widget, h - 5, w/2 - 5, '/');
+ mvwaddch(widget, h - 5, w/2 + 7, '/');
+
+ draw_buttons(widget, h-2, w, bs, true);
+
+ wrefresh(widget);
+
+ prefresh(textpad, 0, 0, y+1, x+2, y+h-7, x+w-2);
+
+ wclear(c[0].win);
+ mvwin(c[0].win, y + h - 6, x + w/2 - 11);
+ draw_borders(conf, c[0].win, 3, 6, LOWERED);
+ wrefresh(c[0].win);
+
+ wclear(c[1].win);
+ mvwin(c[1].win, y + h - 6, x + w/2 - 4);
+ draw_borders(conf, c[1].win, 3, 11, LOWERED);
+ wrefresh(c[1].win);
+
+ wclear(c[2].win);
+ mvwin(c[2].win, y + h - 6, x + w/2 + 8);
+ draw_borders(conf, c[2].win, 3, 4, LOWERED);
+ wrefresh(c[2].win);
+
+ /* Important to avoid grey lines expanding screen */
+ refresh();
break;
+ default:
+ for (i = 0; i < (int) bs.nbuttons; i++)
+ if (tolower(input) == tolower((bs.label[i])[0])) {
+ output = bs.value[i];
+ loop = false;
+ }
}
}
@@ -235,7 +525,7 @@ int bsddialog_calendar(struct bsddialog_conf conf, char* text, int rows, int col
for (i=0; i<3; i++)
delwin(c[i].win);
- end_widget(conf, widget, rows, cols, shadow);
+ end_widget_withtextpad(conf, widget, h, w, textpad, shadow);
return output;
}
diff --git a/contrib/bsddialog/library_examples/ports.c b/contrib/bsddialog/library_examples/ports.c
deleted file mode 100644
index 1a5c514490e7..000000000000
--- a/contrib/bsddialog/library_examples/ports.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*-
- * SPDX-License-Identifier: CC0-1.0
- *
- * Written in 2021 by Alfonso Sabato Siciliano.
- * To the extent possible under law, the author has dedicated all copyright
- * and related and neighboring rights to this software to the public domain
- * worldwide. This software is distributed without any warranty, see:
- * <http://creativecommons.org/publicdomain/zero/1.0/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <bsddialog.h>
-
-/* Actually this is an example for mixedmenu to reproduce dialog4ports(1) */
-int main()
-{
- int i, j, output;
- struct bsddialog_conf conf;
- struct bsddialog_menuitem item;
-
- struct bsddialog_menuitem check1[5] = {
- { "+", true, 0, "CSCOPE", "cscope support", "" },
- { "+", true, 0, "DEFAULT_VIMRC", "Install bundled vimrc as default setting", "" },
- { "", false, 0, "MAKE_JOBS", "Enable parallel build", "" },
- { "", true, 0, "NLS", "Native Language Support", "" },
- { "+", false, 0, "XTERM_SAVE", "Restore xterm screen after exit", "" }
- };
- struct bsddialog_menuitem sep1[1] = {
- { "", true, 0, "Optional language bindings", "", "" }
- };
- struct bsddialog_menuitem check2[6] = {
- { "", false, 0, "LUA", "Lua scripting language support", "" },
- { "+", true, 0, "PERL", "Perl scripting language support", "" },
- { "", true, 0, "PYTHON", "Python bindings or support", "" },
- { "+", true, 0, "RUBY", "Ruby bindings or support", "" },
- { "", false, 0, "SCHEME", "MzScheme (Racket) bindings", "" },
- { "", false, 0, "TCL", "Tcl scripting language support", "" }
- };
- struct bsddialog_menuitem sep2[1] = {
- { "", true, 0, "CTAGS", "", "" }
- };
- struct bsddialog_menuitem radio1[3] = {
- { "+", false, 0, "CTAGS_BASE", "Use system ctags", "" },
- { "", true, 0, "CTAGS_EXUBERANT", "Use exctags instead of ctags", "" },
- { "", false, 0, "CTAGS_UNIVERSAL", "Use uctags instead of ctags", "" }
- };
- struct bsddialog_menuitem sep3[1] = {
- { "", true, 0, "User interface", "", "" }
- };
- struct bsddialog_menuitem radio2[7] = {
- { "", false, 0, "ATHENA", "Athena GUI toolkit", "" },
- { "", false, 0, "CONSOLE","Console/terminal mode", "" },
- { "", false, 0, "GNOME", "GNOME desktop environment support", "" },
- { "", false, 0, "GTK2", "GTK+ 2 GUI toolkit support", "" },
- { "", true, 0, "GTK3", "GTK+ 3 GUI toolkit support", "" },
- { "", false, 0, "MOTIF", "Motif widget library support", "" },
- { "", false, 0, "X11", "X11 (graphics) support", "" }
- };
-
- struct bsddialog_menugroup group[7] = {
- { BSDDIALOG_CHECKLIST, 5, check1 },
- { BSDDIALOG_SEPARATOR, 1, sep1 },
- { BSDDIALOG_CHECKLIST, 6, check2 },
- { BSDDIALOG_SEPARATOR, 1, sep2 },
- { BSDDIALOG_RADIOLIST, 3, radio1 },
- { BSDDIALOG_SEPARATOR, 1, sep3 },
- { BSDDIALOG_RADIOLIST, 7, radio2 },
- };
-
- bsddialog_initconf(&conf);
- conf.title = "vim-8.2.2569";
-
- if (bsddialog_init() < 0)
- return -1;
-
- output = bsddialog_mixedlist(conf, "", 0, 0, 0, 7, group, NULL,NULL);
-
- bsddialog_end();
-
- printf("Options:\n");
- for (i=0; i<7; i++) {
- for (j=0; j<group[i].nitems; j++) {
- item = group[i].items[j];
- if (group[i].type == BSDDIALOG_SEPARATOR)
- printf("----- %s -----\n", item.name);
- else if (group[i].type == BSDDIALOG_RADIOLIST)
- printf(" (%c) %s\n", item.on ? '*' : ' ', item.name);
- else /* BSDDIALOG_PORTCHECKLIST */
- printf(" [%c] %s\n", item.on ? 'X' : ' ', item.name);
- }
- }
-
-
- return output;
-}
diff --git a/contrib/bsddialog/utility_examples/info_example.sh b/contrib/bsddialog/utility_examples/info_example.sh
deleted file mode 100755
index a57afa5fad88..000000000000
--- a/contrib/bsddialog/utility_examples/info_example.sh
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-./bsddialog --sleep 5 --title infobox --infobox "Hello World!\n5 seconds" 6 20 \ No newline at end of file
diff --git a/contrib/bsddialog/utility_examples/menu_example.sh b/contrib/bsddialog/utility_examples/menu_example.sh
deleted file mode 100755
index dc41279a6b71..000000000000
--- a/contrib/bsddialog/utility_examples/menu_example.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/sh
-
-./bsddialog --title menu --menu "Hello World!" 15 30 5 \
- "Tag 1" "DESC 1 xyz" \
- "Tag 2" "DESC 2 xyz" \
- "Tag 3" "DESC 3 xyz" \
- "Tag 4" "DESC 4 xyz" \
- "Tag 5" "DESC 5 xyz" \
- 2>out.txt ; cat out.txt ; rm out.txt
-
-./bsddialog --title checklist --checklist "Hello World!" 15 30 5 \
- "Tag 1" "DESC 1 xyz" on \
- "Tag 2" "DESC 2 xyz" off \
- "Tag 3" "DESC 3 xyz" on \
- "Tag 4" "DESC 4 xyz" off \
- "Tag 5" "DESC 5 xyz" on \
- 2>out.txt ; cat out.txt ; rm out.txt
-
-./bsddialog --title radiolist --radiolist "Hello World!" 15 30 5 \
- "Tag 1" "DESC 1 xyz" off \
- "Tag 2" "DESC 2 xyz" off \
- "Tag 3" "DESC 3 xyz" on \
- "Tag 4" "DESC 4 xyz" off \
- "Tag 5" "DESC 5 xyz" off \
- 2>out.txt ; cat out.txt ; rm out.txt
-
-./bsddialog --title buildlist --buildlist "Hello World!" 15 40 5 \
- "Tag 1" "DESC 1 xyz" off \
- "Tag 2" "DESC 2 xyz" off \
- "Tag 3" "DESC 3 xyz" on \
- "Tag 4" "DESC 4 xyz" off \
- "Tag 5" "DESC 5 xyz" off \
- 2>out.txt ; cat out.txt ; rm out.txt
-
-./bsddialog --title treeview --treeview "Hello World!" 15 40 5 \
- 0 "Tag 1" "DESC 1 xyz" off \
- 1 "Tag 2" "DESC 2 xyz" off \
- 2 "Tag 3" "DESC 3 xyz" on \
- 1 "Tag 4" "DESC 4 xyz" off \
- 1 "Tag 5" "DESC 5 xyz" off \
- 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/utility_examples/message_example.sh b/contrib/bsddialog/utility_examples/message_example.sh
deleted file mode 100755
index ac9dcc6e48b6..000000000000
--- a/contrib/bsddialog/utility_examples/message_example.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-./bsddialog --title msgbox --msgbox "Hello World!" 6 20
-
-./bsddialog --title yesno --yesno "Hello World!" 6 25 \ No newline at end of file
diff --git a/contrib/bsddialog/utility_examples/mixedform_example.sh b/contrib/bsddialog/utility_examples/mixedform_example.sh
deleted file mode 100755
index 079805996dad..000000000000
--- a/contrib/bsddialog/utility_examples/mixedform_example.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-
-./bsddialog --title mixedform --mixedform "Hello World!" 12 40 5 \
- Label: 1 1 Entry 1 11 18 25 0 \
- Label: 2 1 Read-Only 2 11 18 25 2 \
- Password: 3 1 Value2 3 11 18 25 1 \
- Password: 4 1 Value4 4 11 18 25 3 \
- Label5: 5 1 Value5 5 11 18 25 4 \
- 2>out.txt ; cat out.txt ; rm out.txt
-
-./bsddialog --backtitle "BSD-2-Clause Licese" --title " form " --form "Hello World!" 12 40 5 \
- Label1: 1 1 Value1 1 9 18 25 \
- Label2: 2 1 Value2 2 9 18 25 \
- Label3: 3 1 Value3 3 9 18 25 \
- Label4: 4 1 Value4 4 9 18 25 \
- Label5: 5 1 Value5 5 9 18 25 \
- 2>out.txt ; cat out.txt ; rm out.txt
-
-./bsddialog --title passwordform --passwordform "Hello World!" 12 40 5 \
- Password1: 1 1 Value1 1 12 18 25 \
- Password2: 2 1 Value2 2 12 18 25 \
- Password3: 3 1 Value3 3 12 18 25 \
- Password4: 4 1 Value4 4 12 18 25 \
- Password5: 5 1 Value5 5 12 18 25 \
- 2>out.txt ; cat out.txt ; rm out.txt
diff --git a/contrib/bsddialog/utility_examples/mixedgauge_example.sh b/contrib/bsddialog/utility_examples/mixedgauge_example.sh
deleted file mode 100755
index 900639f9ee84..000000000000
--- a/contrib/bsddialog/utility_examples/mixedgauge_example.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh
-
-input="A B C D E F G H"
-total=`echo $input | awk '{print split($0, a)}'`
-curr=1
-for i in $input
-do
- perc="$(expr $(expr $curr "*" 100 ) "/" $total )"
- curr=`expr $curr + 1`
- ./bsddialog --title " mixedgauge " --mixedgauge "Hello World! Press <ENTER>" 20 35 $perc \
- "Hidden!" 8 \
- "Label 1" 0 \
- "Label 2" 1 \
- "Label 3" 2 \
- "Label 4" 3 \
- "Label 5" 4 \
- "Label 6" 5 \
- "Label 7" 6 \
- "Label 8" 7 \
- "Label 9" 9 \
- "Label X" -- -$perc
- #sleep 1
-done
-