From f7ffc174b6b148d1dada94608a0fc47142888530 Mon Sep 17 00:00:00 2001 From: dteske Date: Sun, 7 Jul 2013 19:13:34 +0000 Subject: [PATCH] MFC bsdconfig(8) and sysrc(8) from HEAD. (shazam!) git-svn-id: svn://svn.freebsd.org/base/stable/9@252995 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- usr.sbin/Makefile | 2 + usr.sbin/bsdconfig/Makefile | 32 + usr.sbin/bsdconfig/USAGE | 47 + usr.sbin/bsdconfig/bsdconfig | 429 ++++ usr.sbin/bsdconfig/bsdconfig.8 | 243 ++ usr.sbin/bsdconfig/console/INDEX | 63 + usr.sbin/bsdconfig/console/Makefile | 16 + usr.sbin/bsdconfig/console/USAGE | 37 + usr.sbin/bsdconfig/console/console | 146 ++ usr.sbin/bsdconfig/console/font | 191 ++ usr.sbin/bsdconfig/console/include/Makefile | 11 + .../bsdconfig/console/include/messages.subr | 270 +++ usr.sbin/bsdconfig/console/keymap | 333 +++ usr.sbin/bsdconfig/console/repeat | 142 ++ usr.sbin/bsdconfig/console/saver | 193 ++ usr.sbin/bsdconfig/console/screenmap | 154 ++ usr.sbin/bsdconfig/console/ttys | 204 ++ usr.sbin/bsdconfig/diskmgmt/INDEX | 57 + usr.sbin/bsdconfig/diskmgmt/Makefile | 16 + usr.sbin/bsdconfig/diskmgmt/USAGE | 37 + usr.sbin/bsdconfig/diskmgmt/diskmgmt | 85 + usr.sbin/bsdconfig/diskmgmt/include/Makefile | 11 + .../bsdconfig/diskmgmt/include/messages.subr | 27 + usr.sbin/bsdconfig/docsinstall/INDEX | 57 + usr.sbin/bsdconfig/docsinstall/Makefile | 16 + usr.sbin/bsdconfig/docsinstall/USAGE | 37 + usr.sbin/bsdconfig/docsinstall/docsinstall | 97 + .../bsdconfig/docsinstall/include/Makefile | 11 + .../docsinstall/include/messages.subr | 28 + usr.sbin/bsdconfig/dot/INDEX | 57 + usr.sbin/bsdconfig/dot/Makefile | 16 + usr.sbin/bsdconfig/dot/USAGE | 143 ++ usr.sbin/bsdconfig/dot/dot | 683 ++++++ usr.sbin/bsdconfig/dot/include/Makefile | 11 + usr.sbin/bsdconfig/dot/include/messages.subr | 30 + usr.sbin/bsdconfig/examples/Makefile | 11 + .../bsdconfig/examples/browse_packages.sh | 26 + usr.sbin/bsdconfig/examples/bsdconfigrc | 42 + usr.sbin/bsdconfig/include/Makefile | 12 + usr.sbin/bsdconfig/include/bsdconfig.hlp | 12 + usr.sbin/bsdconfig/include/media.hlp | 54 + usr.sbin/bsdconfig/include/messages.subr | 427 ++++ usr.sbin/bsdconfig/include/network_device.hlp | 58 + usr.sbin/bsdconfig/include/options.hlp | 115 + usr.sbin/bsdconfig/include/tcp.hlp | 33 + usr.sbin/bsdconfig/include/usage.hlp | 64 + usr.sbin/bsdconfig/mouse/INDEX | 62 + usr.sbin/bsdconfig/mouse/Makefile | 16 + usr.sbin/bsdconfig/mouse/USAGE | 37 + usr.sbin/bsdconfig/mouse/disable | 93 + usr.sbin/bsdconfig/mouse/enable | 118 + usr.sbin/bsdconfig/mouse/flags | 95 + usr.sbin/bsdconfig/mouse/include/Makefile | 11 + .../bsdconfig/mouse/include/messages.subr | 93 + usr.sbin/bsdconfig/mouse/mouse | 144 ++ usr.sbin/bsdconfig/mouse/port | 153 ++ usr.sbin/bsdconfig/mouse/type | 169 ++ usr.sbin/bsdconfig/networking/INDEX | 61 + usr.sbin/bsdconfig/networking/Makefile | 16 + usr.sbin/bsdconfig/networking/USAGE | 37 + usr.sbin/bsdconfig/networking/defaultrouter | 73 + usr.sbin/bsdconfig/networking/devices | 158 ++ usr.sbin/bsdconfig/networking/hostname | 76 + .../bsdconfig/networking/include/Makefile | 11 + .../networking/include/messages.subr | 105 + usr.sbin/bsdconfig/networking/nameservers | 76 + usr.sbin/bsdconfig/networking/networking | 151 ++ usr.sbin/bsdconfig/networking/share/Makefile | 12 + .../bsdconfig/networking/share/common.subr | 58 + .../bsdconfig/networking/share/device.subr | 393 +++ .../bsdconfig/networking/share/hostname.subr | 160 ++ .../bsdconfig/networking/share/ipaddr.subr | 218 ++ .../bsdconfig/networking/share/media.subr | 244 ++ .../bsdconfig/networking/share/netmask.subr | 135 ++ .../bsdconfig/networking/share/resolv.subr | 481 ++++ .../bsdconfig/networking/share/routing.subr | 133 + .../bsdconfig/networking/share/services.subr | 54 + usr.sbin/bsdconfig/packages/INDEX | 56 + usr.sbin/bsdconfig/packages/Makefile | 16 + usr.sbin/bsdconfig/packages/USAGE | 37 + usr.sbin/bsdconfig/packages/include/Makefile | 11 + .../bsdconfig/packages/include/messages.subr | 27 + usr.sbin/bsdconfig/packages/packages | 80 + usr.sbin/bsdconfig/password/INDEX | 57 + usr.sbin/bsdconfig/password/Makefile | 16 + usr.sbin/bsdconfig/password/USAGE | 37 + usr.sbin/bsdconfig/password/include/Makefile | 11 + .../bsdconfig/password/include/messages.subr | 35 + usr.sbin/bsdconfig/password/password | 85 + usr.sbin/bsdconfig/password/share/Makefile | 11 + .../bsdconfig/password/share/password.subr | 124 + usr.sbin/bsdconfig/security/INDEX | 58 + usr.sbin/bsdconfig/security/Makefile | 16 + usr.sbin/bsdconfig/security/USAGE | 37 + usr.sbin/bsdconfig/security/include/Makefile | 11 + .../bsdconfig/security/include/messages.subr | 50 + .../security/include/securelevel.hlp | 40 + usr.sbin/bsdconfig/security/kern_securelevel | 169 ++ usr.sbin/bsdconfig/security/security | 177 ++ usr.sbin/bsdconfig/share/Makefile | 14 + usr.sbin/bsdconfig/share/common.subr | 753 ++++++ usr.sbin/bsdconfig/share/device.subr | 800 ++++++ usr.sbin/bsdconfig/share/dialog.subr | 2145 +++++++++++++++++ usr.sbin/bsdconfig/share/media/Makefile | 13 + usr.sbin/bsdconfig/share/media/any.subr | 150 ++ usr.sbin/bsdconfig/share/media/cdrom.subr | 210 ++ usr.sbin/bsdconfig/share/media/common.subr | 129 + usr.sbin/bsdconfig/share/media/directory.subr | 148 ++ usr.sbin/bsdconfig/share/media/dos.subr | 164 ++ usr.sbin/bsdconfig/share/media/floppy.subr | 216 ++ usr.sbin/bsdconfig/share/media/ftp.subr | 938 +++++++ usr.sbin/bsdconfig/share/media/http.subr | 635 +++++ usr.sbin/bsdconfig/share/media/httpproxy.subr | 452 ++++ usr.sbin/bsdconfig/share/media/network.subr | 182 ++ usr.sbin/bsdconfig/share/media/nfs.subr | 250 ++ usr.sbin/bsdconfig/share/media/options.subr | 328 +++ usr.sbin/bsdconfig/share/media/tcpip.subr | 1685 +++++++++++++ usr.sbin/bsdconfig/share/media/ufs.subr | 193 ++ usr.sbin/bsdconfig/share/media/usb.subr | 174 ++ usr.sbin/bsdconfig/share/mustberoot.subr | 425 ++++ usr.sbin/bsdconfig/share/packages/Makefile | 11 + .../bsdconfig/share/packages/categories.subr | 207 ++ usr.sbin/bsdconfig/share/packages/index.subr | 287 +++ .../bsdconfig/share/packages/packages.subr | 1202 +++++++++ usr.sbin/bsdconfig/share/script.subr | 207 ++ usr.sbin/bsdconfig/share/strings.subr | 326 +++ usr.sbin/bsdconfig/share/struct.subr | 206 ++ usr.sbin/bsdconfig/share/sysrc.subr | 633 +++++ usr.sbin/bsdconfig/share/variable.subr | 279 +++ usr.sbin/bsdconfig/startup/INDEX | 62 + usr.sbin/bsdconfig/startup/Makefile | 16 + usr.sbin/bsdconfig/startup/USAGE | 37 + usr.sbin/bsdconfig/startup/include/Makefile | 11 + .../bsdconfig/startup/include/messages.subr | 112 + usr.sbin/bsdconfig/startup/misc | 439 ++++ usr.sbin/bsdconfig/startup/rcadd | 149 ++ usr.sbin/bsdconfig/startup/rcconf | 264 ++ usr.sbin/bsdconfig/startup/rcdelete | 415 ++++ usr.sbin/bsdconfig/startup/rcedit | 72 + usr.sbin/bsdconfig/startup/rcvar | 220 ++ usr.sbin/bsdconfig/startup/share/Makefile | 11 + usr.sbin/bsdconfig/startup/share/rcconf.subr | 496 ++++ usr.sbin/bsdconfig/startup/share/rcedit.subr | 87 + usr.sbin/bsdconfig/startup/share/rcvar.subr | 232 ++ usr.sbin/bsdconfig/startup/startup | 140 ++ usr.sbin/bsdconfig/timezone/INDEX | 57 + usr.sbin/bsdconfig/timezone/Makefile | 16 + usr.sbin/bsdconfig/timezone/USAGE | 46 + usr.sbin/bsdconfig/timezone/include/Makefile | 11 + .../bsdconfig/timezone/include/messages.subr | 78 + usr.sbin/bsdconfig/timezone/share/Makefile | 12 + .../bsdconfig/timezone/share/continents.subr | 143 ++ .../bsdconfig/timezone/share/countries.subr | 80 + .../bsdconfig/timezone/share/iso3166.subr | 202 ++ usr.sbin/bsdconfig/timezone/share/menus.subr | 225 ++ usr.sbin/bsdconfig/timezone/share/zones.subr | 597 +++++ usr.sbin/bsdconfig/timezone/timezone | 455 ++++ usr.sbin/bsdconfig/ttys/INDEX | 57 + usr.sbin/bsdconfig/ttys/Makefile | 16 + usr.sbin/bsdconfig/ttys/USAGE | 37 + usr.sbin/bsdconfig/ttys/include/Makefile | 11 + usr.sbin/bsdconfig/ttys/include/messages.subr | 31 + usr.sbin/bsdconfig/ttys/ttys | 128 + usr.sbin/bsdconfig/usermgmt/INDEX | 64 + usr.sbin/bsdconfig/usermgmt/Makefile | 17 + usr.sbin/bsdconfig/usermgmt/USAGE | 37 + usr.sbin/bsdconfig/usermgmt/groupadd | 64 + usr.sbin/bsdconfig/usermgmt/groupdel | 92 + usr.sbin/bsdconfig/usermgmt/groupedit | 92 + usr.sbin/bsdconfig/usermgmt/groupinput | 307 +++ usr.sbin/bsdconfig/usermgmt/include/Makefile | 11 + .../bsdconfig/usermgmt/include/messages.subr | 114 + .../bsdconfig/usermgmt/include/usermgmt.hlp | 76 + usr.sbin/bsdconfig/usermgmt/share/Makefile | 11 + .../bsdconfig/usermgmt/share/group_input.subr | 409 ++++ .../bsdconfig/usermgmt/share/user_input.subr | 1025 ++++++++ usr.sbin/bsdconfig/usermgmt/useradd | 64 + usr.sbin/bsdconfig/usermgmt/userdel | 92 + usr.sbin/bsdconfig/usermgmt/useredit | 92 + usr.sbin/bsdconfig/usermgmt/userinput | 529 ++++ usr.sbin/bsdconfig/usermgmt/usermgmt | 169 ++ usr.sbin/sysrc/Makefile | 11 + usr.sbin/sysrc/sysrc | 611 +++++ usr.sbin/sysrc/sysrc.8 | 297 +++ 184 files changed, 32101 insertions(+) create mode 100644 usr.sbin/bsdconfig/Makefile create mode 100644 usr.sbin/bsdconfig/USAGE create mode 100755 usr.sbin/bsdconfig/bsdconfig create mode 100644 usr.sbin/bsdconfig/bsdconfig.8 create mode 100644 usr.sbin/bsdconfig/console/INDEX create mode 100644 usr.sbin/bsdconfig/console/Makefile create mode 100644 usr.sbin/bsdconfig/console/USAGE create mode 100755 usr.sbin/bsdconfig/console/console create mode 100755 usr.sbin/bsdconfig/console/font create mode 100644 usr.sbin/bsdconfig/console/include/Makefile create mode 100644 usr.sbin/bsdconfig/console/include/messages.subr create mode 100755 usr.sbin/bsdconfig/console/keymap create mode 100755 usr.sbin/bsdconfig/console/repeat create mode 100755 usr.sbin/bsdconfig/console/saver create mode 100755 usr.sbin/bsdconfig/console/screenmap create mode 100755 usr.sbin/bsdconfig/console/ttys create mode 100644 usr.sbin/bsdconfig/diskmgmt/INDEX create mode 100644 usr.sbin/bsdconfig/diskmgmt/Makefile create mode 100644 usr.sbin/bsdconfig/diskmgmt/USAGE create mode 100755 usr.sbin/bsdconfig/diskmgmt/diskmgmt create mode 100644 usr.sbin/bsdconfig/diskmgmt/include/Makefile create mode 100644 usr.sbin/bsdconfig/diskmgmt/include/messages.subr create mode 100644 usr.sbin/bsdconfig/docsinstall/INDEX create mode 100644 usr.sbin/bsdconfig/docsinstall/Makefile create mode 100644 usr.sbin/bsdconfig/docsinstall/USAGE create mode 100755 usr.sbin/bsdconfig/docsinstall/docsinstall create mode 100644 usr.sbin/bsdconfig/docsinstall/include/Makefile create mode 100644 usr.sbin/bsdconfig/docsinstall/include/messages.subr create mode 100644 usr.sbin/bsdconfig/dot/INDEX create mode 100644 usr.sbin/bsdconfig/dot/Makefile create mode 100644 usr.sbin/bsdconfig/dot/USAGE create mode 100755 usr.sbin/bsdconfig/dot/dot create mode 100644 usr.sbin/bsdconfig/dot/include/Makefile create mode 100644 usr.sbin/bsdconfig/dot/include/messages.subr create mode 100644 usr.sbin/bsdconfig/examples/Makefile create mode 100755 usr.sbin/bsdconfig/examples/browse_packages.sh create mode 100644 usr.sbin/bsdconfig/examples/bsdconfigrc create mode 100644 usr.sbin/bsdconfig/include/Makefile create mode 100644 usr.sbin/bsdconfig/include/bsdconfig.hlp create mode 100644 usr.sbin/bsdconfig/include/media.hlp create mode 100644 usr.sbin/bsdconfig/include/messages.subr create mode 100644 usr.sbin/bsdconfig/include/network_device.hlp create mode 100644 usr.sbin/bsdconfig/include/options.hlp create mode 100644 usr.sbin/bsdconfig/include/tcp.hlp create mode 100644 usr.sbin/bsdconfig/include/usage.hlp create mode 100644 usr.sbin/bsdconfig/mouse/INDEX create mode 100644 usr.sbin/bsdconfig/mouse/Makefile create mode 100644 usr.sbin/bsdconfig/mouse/USAGE create mode 100755 usr.sbin/bsdconfig/mouse/disable create mode 100755 usr.sbin/bsdconfig/mouse/enable create mode 100755 usr.sbin/bsdconfig/mouse/flags create mode 100644 usr.sbin/bsdconfig/mouse/include/Makefile create mode 100644 usr.sbin/bsdconfig/mouse/include/messages.subr create mode 100755 usr.sbin/bsdconfig/mouse/mouse create mode 100755 usr.sbin/bsdconfig/mouse/port create mode 100755 usr.sbin/bsdconfig/mouse/type create mode 100644 usr.sbin/bsdconfig/networking/INDEX create mode 100644 usr.sbin/bsdconfig/networking/Makefile create mode 100644 usr.sbin/bsdconfig/networking/USAGE create mode 100755 usr.sbin/bsdconfig/networking/defaultrouter create mode 100755 usr.sbin/bsdconfig/networking/devices create mode 100755 usr.sbin/bsdconfig/networking/hostname create mode 100644 usr.sbin/bsdconfig/networking/include/Makefile create mode 100644 usr.sbin/bsdconfig/networking/include/messages.subr create mode 100755 usr.sbin/bsdconfig/networking/nameservers create mode 100755 usr.sbin/bsdconfig/networking/networking create mode 100644 usr.sbin/bsdconfig/networking/share/Makefile create mode 100644 usr.sbin/bsdconfig/networking/share/common.subr create mode 100644 usr.sbin/bsdconfig/networking/share/device.subr create mode 100644 usr.sbin/bsdconfig/networking/share/hostname.subr create mode 100644 usr.sbin/bsdconfig/networking/share/ipaddr.subr create mode 100644 usr.sbin/bsdconfig/networking/share/media.subr create mode 100644 usr.sbin/bsdconfig/networking/share/netmask.subr create mode 100644 usr.sbin/bsdconfig/networking/share/resolv.subr create mode 100644 usr.sbin/bsdconfig/networking/share/routing.subr create mode 100644 usr.sbin/bsdconfig/networking/share/services.subr create mode 100644 usr.sbin/bsdconfig/packages/INDEX create mode 100644 usr.sbin/bsdconfig/packages/Makefile create mode 100644 usr.sbin/bsdconfig/packages/USAGE create mode 100644 usr.sbin/bsdconfig/packages/include/Makefile create mode 100755 usr.sbin/bsdconfig/packages/include/messages.subr create mode 100755 usr.sbin/bsdconfig/packages/packages create mode 100644 usr.sbin/bsdconfig/password/INDEX create mode 100644 usr.sbin/bsdconfig/password/Makefile create mode 100644 usr.sbin/bsdconfig/password/USAGE create mode 100644 usr.sbin/bsdconfig/password/include/Makefile create mode 100644 usr.sbin/bsdconfig/password/include/messages.subr create mode 100755 usr.sbin/bsdconfig/password/password create mode 100644 usr.sbin/bsdconfig/password/share/Makefile create mode 100644 usr.sbin/bsdconfig/password/share/password.subr create mode 100644 usr.sbin/bsdconfig/security/INDEX create mode 100644 usr.sbin/bsdconfig/security/Makefile create mode 100644 usr.sbin/bsdconfig/security/USAGE create mode 100644 usr.sbin/bsdconfig/security/include/Makefile create mode 100644 usr.sbin/bsdconfig/security/include/messages.subr create mode 100644 usr.sbin/bsdconfig/security/include/securelevel.hlp create mode 100755 usr.sbin/bsdconfig/security/kern_securelevel create mode 100755 usr.sbin/bsdconfig/security/security create mode 100644 usr.sbin/bsdconfig/share/Makefile create mode 100644 usr.sbin/bsdconfig/share/common.subr create mode 100644 usr.sbin/bsdconfig/share/device.subr create mode 100644 usr.sbin/bsdconfig/share/dialog.subr create mode 100644 usr.sbin/bsdconfig/share/media/Makefile create mode 100644 usr.sbin/bsdconfig/share/media/any.subr create mode 100644 usr.sbin/bsdconfig/share/media/cdrom.subr create mode 100644 usr.sbin/bsdconfig/share/media/common.subr create mode 100644 usr.sbin/bsdconfig/share/media/directory.subr create mode 100644 usr.sbin/bsdconfig/share/media/dos.subr create mode 100644 usr.sbin/bsdconfig/share/media/floppy.subr create mode 100644 usr.sbin/bsdconfig/share/media/ftp.subr create mode 100644 usr.sbin/bsdconfig/share/media/http.subr create mode 100644 usr.sbin/bsdconfig/share/media/httpproxy.subr create mode 100644 usr.sbin/bsdconfig/share/media/network.subr create mode 100644 usr.sbin/bsdconfig/share/media/nfs.subr create mode 100644 usr.sbin/bsdconfig/share/media/options.subr create mode 100644 usr.sbin/bsdconfig/share/media/tcpip.subr create mode 100644 usr.sbin/bsdconfig/share/media/ufs.subr create mode 100644 usr.sbin/bsdconfig/share/media/usb.subr create mode 100644 usr.sbin/bsdconfig/share/mustberoot.subr create mode 100644 usr.sbin/bsdconfig/share/packages/Makefile create mode 100755 usr.sbin/bsdconfig/share/packages/categories.subr create mode 100755 usr.sbin/bsdconfig/share/packages/index.subr create mode 100755 usr.sbin/bsdconfig/share/packages/packages.subr create mode 100644 usr.sbin/bsdconfig/share/script.subr create mode 100644 usr.sbin/bsdconfig/share/strings.subr create mode 100644 usr.sbin/bsdconfig/share/struct.subr create mode 100644 usr.sbin/bsdconfig/share/sysrc.subr create mode 100644 usr.sbin/bsdconfig/share/variable.subr create mode 100644 usr.sbin/bsdconfig/startup/INDEX create mode 100644 usr.sbin/bsdconfig/startup/Makefile create mode 100644 usr.sbin/bsdconfig/startup/USAGE create mode 100644 usr.sbin/bsdconfig/startup/include/Makefile create mode 100644 usr.sbin/bsdconfig/startup/include/messages.subr create mode 100755 usr.sbin/bsdconfig/startup/misc create mode 100755 usr.sbin/bsdconfig/startup/rcadd create mode 100755 usr.sbin/bsdconfig/startup/rcconf create mode 100755 usr.sbin/bsdconfig/startup/rcdelete create mode 100755 usr.sbin/bsdconfig/startup/rcedit create mode 100755 usr.sbin/bsdconfig/startup/rcvar create mode 100644 usr.sbin/bsdconfig/startup/share/Makefile create mode 100644 usr.sbin/bsdconfig/startup/share/rcconf.subr create mode 100644 usr.sbin/bsdconfig/startup/share/rcedit.subr create mode 100644 usr.sbin/bsdconfig/startup/share/rcvar.subr create mode 100755 usr.sbin/bsdconfig/startup/startup create mode 100644 usr.sbin/bsdconfig/timezone/INDEX create mode 100644 usr.sbin/bsdconfig/timezone/Makefile create mode 100644 usr.sbin/bsdconfig/timezone/USAGE create mode 100644 usr.sbin/bsdconfig/timezone/include/Makefile create mode 100644 usr.sbin/bsdconfig/timezone/include/messages.subr create mode 100644 usr.sbin/bsdconfig/timezone/share/Makefile create mode 100644 usr.sbin/bsdconfig/timezone/share/continents.subr create mode 100644 usr.sbin/bsdconfig/timezone/share/countries.subr create mode 100644 usr.sbin/bsdconfig/timezone/share/iso3166.subr create mode 100644 usr.sbin/bsdconfig/timezone/share/menus.subr create mode 100644 usr.sbin/bsdconfig/timezone/share/zones.subr create mode 100755 usr.sbin/bsdconfig/timezone/timezone create mode 100644 usr.sbin/bsdconfig/ttys/INDEX create mode 100644 usr.sbin/bsdconfig/ttys/Makefile create mode 100644 usr.sbin/bsdconfig/ttys/USAGE create mode 100644 usr.sbin/bsdconfig/ttys/include/Makefile create mode 100644 usr.sbin/bsdconfig/ttys/include/messages.subr create mode 100755 usr.sbin/bsdconfig/ttys/ttys create mode 100644 usr.sbin/bsdconfig/usermgmt/INDEX create mode 100644 usr.sbin/bsdconfig/usermgmt/Makefile create mode 100644 usr.sbin/bsdconfig/usermgmt/USAGE create mode 100755 usr.sbin/bsdconfig/usermgmt/groupadd create mode 100755 usr.sbin/bsdconfig/usermgmt/groupdel create mode 100755 usr.sbin/bsdconfig/usermgmt/groupedit create mode 100755 usr.sbin/bsdconfig/usermgmt/groupinput create mode 100644 usr.sbin/bsdconfig/usermgmt/include/Makefile create mode 100644 usr.sbin/bsdconfig/usermgmt/include/messages.subr create mode 100644 usr.sbin/bsdconfig/usermgmt/include/usermgmt.hlp create mode 100644 usr.sbin/bsdconfig/usermgmt/share/Makefile create mode 100644 usr.sbin/bsdconfig/usermgmt/share/group_input.subr create mode 100644 usr.sbin/bsdconfig/usermgmt/share/user_input.subr create mode 100755 usr.sbin/bsdconfig/usermgmt/useradd create mode 100755 usr.sbin/bsdconfig/usermgmt/userdel create mode 100755 usr.sbin/bsdconfig/usermgmt/useredit create mode 100755 usr.sbin/bsdconfig/usermgmt/userinput create mode 100755 usr.sbin/bsdconfig/usermgmt/usermgmt create mode 100644 usr.sbin/sysrc/Makefile create mode 100644 usr.sbin/sysrc/sysrc create mode 100644 usr.sbin/sysrc/sysrc.8 diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index a628b8b2a..228e17989 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -7,6 +7,7 @@ SUBDIR= adduser \ arp \ bootparamd \ burncd \ + bsdconfig \ bsdinstall \ cdcontrol \ chkgrp \ @@ -80,6 +81,7 @@ SUBDIR= adduser \ snapinfo \ spray \ syslogd \ + sysrc \ tcpdchk \ tcpdmatch \ tcpdrop \ diff --git a/usr.sbin/bsdconfig/Makefile b/usr.sbin/bsdconfig/Makefile new file mode 100644 index 000000000..13cc1c7d6 --- /dev/null +++ b/usr.sbin/bsdconfig/Makefile @@ -0,0 +1,32 @@ +# $FreeBSD$ + +SUBDIR= console \ + diskmgmt \ + docsinstall \ + dot \ + examples \ + include \ + mouse \ + networking \ + packages \ + password \ + security \ + share \ + startup \ + timezone \ + ttys \ + usermgmt + +FILESDIR= ${LIBEXECDIR}/bsdconfig +FILES= USAGE + +SCRIPTS= bsdconfig + +MAN= bsdconfig.8 + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + mkdir -p ${DESTDIR}${SCRIPTSDIR} + mkdir -p ${DESTDIR}${MANDIR}8 + +.include diff --git a/usr.sbin/bsdconfig/USAGE b/usr.sbin/bsdconfig/USAGE new file mode 100644 index 000000000..6b70bd645 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/bsdconfig b/usr.sbin/bsdconfig/bsdconfig new file mode 100755 index 000000000..b23e083bc --- /dev/null +++ b/usr.sbin/bsdconfig/bsdconfig @@ -0,0 +1,429 @@ +#!/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 + +# 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 )) # Accomodate leading tab character + x=$(( $x + 3 + $longest_cmd )) # Preload end of next column + while [ $x -lt $max_width ]; do + ncols=$(( $ncols + 1 )) + x=$(( $x + 3 + $longest_cmd )) + done + f_dprintf "ncols=[%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" + + # Never reached +} + +# 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 + + tag=$( f_substr "$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 + + tag=$( f_substr "$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 0 ] && 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] indexfile=[%s] cmd=[%s]" \ + "$pgm" "$indexfile" "$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 + 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 + # Not reached + 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 + # Not reached + fi + + shift + exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1 + # Not reached +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 2 ]; then + # The Help button was pressed + f_show_help "$BSDCONFIG_HELPFILE" + continue + elif [ $retval -ne 0 ]; 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/usr.sbin/bsdconfig/bsdconfig.8 b/usr.sbin/bsdconfig/bsdconfig.8 new file mode 100644 index 000000000..b99cac248 --- /dev/null +++ b/usr.sbin/bsdconfig/bsdconfig.8 @@ -0,0 +1,243 @@ +.\" 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 Jun 5, 2013 +.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, 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. +.It Cm syscons_font +Shortcut to the Font menu under console. +.It Cm syscons_keymap +Shortcut to the Keymap menu under console. +.It Cm syscons_repeat +Shortcut to the Repeat menu under console. +.It Cm syscons_saver +Shortcut to the Saver menu under console. +.It Cm syscons_screenmap +Shortcut to the Screenmap menu under console. +.It Cm syscons_ttys +Shortcut to the Ttys menu under console. +.It Cm timezone +Set the regional timezone of the local machine. +.It Cm 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. +.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 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/usr.sbin/bsdconfig/console/INDEX b/usr.sbin/bsdconfig/console/INDEX new file mode 100644 index 000000000..18763fdbf --- /dev/null +++ b/usr.sbin/bsdconfig/console/INDEX @@ -0,0 +1,63 @@ +# 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="Console" + +# +# A short descriptive line shown at the bottom of the bsdconfig menu. keep it +# short because any line longer than the terminal width will be truncated. +# +menu_help="Customize system console behavior" + +# +# Two-part variable that defines an action to take when `keyword' is passed on +# a bsdconfig command line. Variable takes the form "keyword|command" and +# multiple occurrences of the variable (with different `keyword's, or different +# `keyword's AND `command's) are allowed. If `command' begins with a '/' then +# the full path to the program is needed. If `command' begins with anything +# else it is a path relative to the directory this INDEX file is in. `keyword' +# can be i18n'ed but `command' is the name of a script. +# +menu_selection="console|console" +menu_selection="syscons_font|font" +menu_selection="syscons_keymap|keymap" +menu_selection="syscons_repeat|repeat" +menu_selection="syscons_saver|saver" +menu_selection="syscons_screenmap|screenmap" +menu_selection="syscons_ttys|ttys" + +# +# ------------ Items below this line do NOT need i18n translation ------------ +# +# Name of the program to be run when this menu choice is selected. If it begins +# with a '/' then the full path to the program is needed. If it begins with +# anything else it is a path relative to the directory this INDEX file is in. +# +menu_program="console" diff --git a/usr.sbin/bsdconfig/console/Makefile b/usr.sbin/bsdconfig/console/Makefile new file mode 100644 index 000000000..aa6c6f181 --- /dev/null +++ b/usr.sbin/bsdconfig/console/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/080.console +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= console font keymap repeat saver screenmap ttys + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/console/USAGE b/usr.sbin/bsdconfig/console/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/console/console b/usr.sbin/bsdconfig/console/console new file mode 100755 index 000000000..ce3d01450 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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/usr.sbin/bsdconfig/console/font b/usr.sbin/bsdconfig/console/font new file mode 100755 index 000000000..1ffa696f2 --- /dev/null +++ b/usr.sbin/bsdconfig/console/font @@ -0,0 +1,191 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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_sysrc_set font8x8 "$f8" || f_die +f_sysrc_set font8x14 "$f14" || f_die +f_sysrc_set font8x16 "$f16" || f_die + +if [ "$mc_start" ]; then + f_sysrc_set mousechar_start "$mc_start" || f_die +else + f_sysrc_delete mousechar_start || f_die +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/console/include/Makefile b/usr.sbin/bsdconfig/console/include/Makefile new file mode 100644 index 000000000..e9157515c --- /dev/null +++ b/usr.sbin/bsdconfig/console/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/080.console/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/console/include/messages.subr b/usr.sbin/bsdconfig/console/include/messages.subr new file mode 100644 index 000000000..11e3022f3 --- /dev/null +++ b/usr.sbin/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_screenmap="Choose an alternate screenmap" +msg_choose_alternate_screen_font="Choose an alternate screen font" +msg_choose_console_terminal_type="Choose console terminal type" +msg_configure_screen_saver="Configure the screen saver" +msg_console_menu_text="The system console driver for FreeBSD has a number of configuration\noptions which may be set according to your preference.\n\nWhen you are done setting configuration options, select Cancel." +msg_croatian_iso="Croation ISO" +msg_croatian_iso_desc="Croation ISO keymap" +msg_czech_iso_accent="Czech ISO (accent)" +msg_czech_iso_accent_desc="Czech ISO keymap (accent keys)" +msg_daemon="Daemon" +msg_daemon_desc="\"BSD Daemon\" animated screen saver (text)" +msg_danish_cp865="Danish CP865" +msg_danish_cp865_desc="Danish Code Page 865 keymap" +msg_danish_iso="Danish ISO" +msg_danish_iso_desc="Danish ISO keymap" +msg_default="Default" +msg_default_desc="Use default keyboard repeat rate" +msg_dragon="Dragon" +msg_dragon_desc="Dragon screensaver (graphics)" +msg_enter_timeout_period="Enter time-out period in seconds for screen saver" +msg_estonian_cp850="Estonian CP850" +msg_estonian_cp850_desc="Estonian Code Page 850 keymap" +msg_estonian_iso="Estonian ISO" +msg_estonian_iso_desc="Estonian ISO keymap" +msg_estonian_iso_15="Estonian ISO 15" +msg_estonian_iso_15_desc="Estonian ISO 8859-15 keymap" +msg_exit="Exit" +msg_exit_this_menu="Exit this menu" +msg_fade="Fade" +msg_fade_desc="Fade out effect screen saver" +msg_fast="Fast" +msg_fast_desc="Fast keyboard repeat rate" +msg_finnish_cp850="Finnish CP850" +msg_finnish_cp850_desc="Finnish Code Page 850 keymap" +msg_finnish_iso="Finnish ISO" +msg_finnish_iso_desc="Finnish ISO keymap" +msg_fire="Fire" +msg_fire_desc="Flames effect screen saver" +msg_font="Font" +msg_font_menu_text="Most PC hardware defaults to displaying characters in the\nIBM 437 character set. However, in the Unix world, this\ncharacter set is very rarely used. Most Western European\ncountries, for example, prefer ISO 8859-1.\nAmerican users won't notice the difference since the bottom half\nof all these charactersets is ANSI anyway. However, they might\nwant to load a font anyway to use the 30- or 50-line displays.\nIf your hardware is capable of downloading a new display font,\nyou can select the appropriate font below." +msg_french_iso="French ISO" +msg_french_iso_accent="French ISO (accent)" +msg_french_iso_accent_desc="French ISO keymap (accent keys)" +msg_french_iso_desc="French ISO keymap" +msg_french_iso_macbook="French ISO/Macbook" +msg_french_iso_macbook_desc="French ISO keymap on macbook" +msg_green="Green" +msg_green_desc="\"Green\" power saving mode (if supported by monitor)" +msg_german_cp850="German CP850" +msg_german_cp850_desc="German Code Page 850 keymap" +msg_german_iso="German ISO" +msg_german_iso_desc="German ISO keymap" +msg_greek_101="Greek 101" +msg_greek_101_desc="Greek ISO keymap (101 keys)" +msg_greek_104="Greek 104" +msg_greek_104_desc="Greek ISO keymap (104 keys)" +msg_greek_elot="Greek ELOT" +msg_greek_elot_desc="Greek ISO keymap (ELOT 1000)" +msg_hungarian_101="Hungarian 101" +msg_hungarian_101_desc="Hungarian ISO keymap (101 key)" +msg_hungarian_102="Hungarian 102" +msg_hungarian_102_desc="Hungarian ISO keymap (102 key)" +msg_ibm_437="IBM 437" +msg_ibm_437_desc="English and others, VGA default" +msg_ibm_437_vga_default="IBM437 (VGA default)" +msg_ibm_850="IBM 850" +msg_ibm_850_desc="Western Europe, IBM encoding" +msg_ibm_865="IBM 865" +msg_ibm_865_desc="Norwegian, IBM encoding" +msg_ibm_866="IBM 866" +msg_ibm_866_desc="Russian, IBM encoding (use with KOI8-R screenmap)" +msg_ibm_866u="IBM 866u" +msg_ibm_866u_desc="Ukrainian, IBM encoding (use with KOI8-U screenmap)" +msg_ibm_1251="IBM 1251" +msg_ibm_1251_desc="Cyrillic, MS Windows encoding" +msg_icelandic="Icelandic" +msg_icelandic_accent="Icelandic (accent)" +msg_icelandic_accent_desc="Icelandic ISO keymap (accent keys)" +msg_icelandic_desc="Icelandic ISO keymap" +msg_iso_8859_1="ISO 8859-1" +msg_iso_8859_1_desc="Western Europe, ISO encoding" +msg_iso_8859_1_to_ibm437="ISO 8859-1 to IBM437" +msg_iso_8859_1_to_ibm437_desc="W-Europe ISO 8859-1 to IBM 437 screenmap" +msg_iso_8859_2="ISO 8859-2" +msg_iso_8859_2_desc="Eastern Europe, ISO encoding" +msg_iso_8859_4="ISO 8859-4" +msg_iso_8859_4_desc="Baltic, ISO encoding" +msg_iso_8859_7="ISO 8859-7" +msg_iso_8859_7_desc="Greek, ISO encoding" +msg_iso_8859_7_to_ibm437="ISO 8859-7 to IBM437" +msg_iso_8859_7_to_ibm437_desc="Greek ISO 8859-1 to IBM 437 screenmap" +msg_iso_8859_8="ISO 8859-8" +msg_iso_8859_8_desc="Hebrew, ISO encoding" +msg_iso_8859_15="ISO 8859-15" +msg_iso_8859_15_desc="Europe, ISO encoding" +msg_italian="Italian" +msg_italian_desc="Italian ISO keymap" +msg_japanese_106="Japanese 106" +msg_japanese_106_desc="Japanese 106 keymap" +msg_keymap="Keymap" +msg_keymap_menu_text="The system console driver for FreeBSD defaults to a standard\n\"US\" keyboard map. Users may wish to choose one of the\nother keymaps below." +msg_koi8_r="KOI8-R" +msg_koi8_u="KOI8-U" +msg_koi8_r_to_ibm866="KOI8-R to IBM866" +msg_koi8_r_to_ibm866_desc="Russian KOI8-R to IBM 866 screenmap" +msg_koi8_u_to_ibm866u="KOI8-U to IBM866u" +msg_koi8_u_to_ibm866u_desc="Ukrainian KOI8-U to IBM 866u screenmap" +msg_latin_american="Latin American" +msg_latin_american_accent="Latin American (accent)" +msg_latin_american_accent_desc="Latin American ISO keymap (accent keys)" +msg_latin_american_desc="Latin American ISO keymap" +msg_logo="Logo" +msg_logo_desc="FreeBSD \"logo\" animated screen saver (graphics)" +msg_none="None" +msg_none_saver_desc="Disable the screensaver" +msg_none_screenmap_desc="No screenmap, don'\''t touch font" +msg_none_ttys_desc="Don'\''t touch anything" +msg_normal="Normal" +msg_normal_desc="\"Normal\" keyboard repeat rate" +msg_norway_iso="Norway ISO" +msg_norway_iso_desc="Norwegian ISO keymap" +msg_ok="OK" +msg_polish_iso="Polish ISO" +msg_polish_iso_desc="Polish ISO keymap" +msg_portuguese="Portuguese" +msg_portuguese_accent="Portuguese (accent)" +msg_portuguese_accent_desc="Portuguese ISO keymap (accent keys)" +msg_portuguese_desc="Portuguese ISO keymap" +msg_rain="Rain" +msg_rain_desc="Rain drops screen saver" +msg_repeat="Repeat" +msg_repeat_menu_text="This menu allows you to set the speed at which keys repeat\nwhen held down." +msg_russia_koi8_r="Russia KOI8-R" +msg_russia_koi8_r_desc="Russia KOI8-R keymap" +msg_saver="Saver" +msg_saver_menu_text="By default, the console driver will not attempt to do anything\nspecial with your screen when it's idle. If you expect to leave your\nmonitor switched on and idle for long periods of time then you should\nprobably enable one of these screen savers to prevent burn-in." +msg_screenmap="Screenmap" +msg_screenmap_menu_text="Unless you load a specific font, most PC hardware defaults to\ndisplaying characters in the IBM 437 character set. However,\nin the Unix world, this character set is very rarely used. Most\nWestern European countries, for example, prefer ISO 8859-1.\nAmerican users won't notice the difference since the bottom half\nof all these character sets is ANSI anyway.\nIf your hardware is capable of downloading a new display font,\nyou should probably choose that option. However, for hardware\nwhere this is not possible (e.g. monochrome adapters), a screen\nmap will give you the best approximation that your hardware can\ndisplay at all." +msg_set_repeat_rate="Set the rate at which keys repeat" +msg_slovak="Slovak" +msg_slovak_desc="Slovak ISO keymap" +msg_slovenian="Slovenian" +msg_slovenian_desc="Slovenian ISO keymap" +msg_slow="Slow" +msg_slow_desc="Slow keyboard repeat rate" +msg_snake="Snake" +msg_snake_desc="Draw a FreeBSD \"snake\" on your screen" +msg_spanish="Spanish" +msg_spanish_accent="Spanish (accent)" +msg_spanish_accent_desc="Spanish ISO keymap (accent keys)" +msg_spanish_desc="Spanish ISO keymap" +msg_star="Star" +msg_star_desc="A \"twinkling stars\" effect" +msg_swedish_cp850="Swedish CP850" +msg_swedish_cp850_desc="Swedish Code Page 850 keymap" +msg_swedish_iso="Swedish ISO" +msg_swedish_iso_desc="Swedish ISO keymap" +msg_swiss="SWISS" +msg_swiss_desc="English, better resolution" +msg_swiss_french_cp850="Swiss French CP850" +msg_swiss_french_cp850_desc="Swiss French Code Page 850 keymap" +msg_swiss_french_iso="Swiss French ISO" +msg_swiss_french_iso_accent="Swiss French ISO (accent)" +msg_swiss_french_iso_accent_desc="Swiss French ISO keymap (accent keys)" +msg_swiss_french_iso_desc="Swiss French ISO keymap" +msg_swiss_german_cp850="Swiss German CP850" +msg_swiss_german_cp850_desc="Swiss German Code Page 850 keymap" +msg_swiss_german_iso="Swiss German ISO" +msg_swiss_german_iso_accent="Swiss German ISO (accent)" +msg_swiss_german_iso_accent_desc="Swiss German ISO keymap (accent keys)" +msg_swiss_german_iso_desc="Swiss German ISO keymap" +msg_system_console_configuration="System Console Configuration" +msg_system_console_font="System Console Font" +msg_system_console_keymap="System Console Keymap" +msg_system_console_keyboard_repeat_rate="System Console Keyboard Repeat Rate" +msg_system_console_screen_saver="System Console Screen Saver" +msg_system_console_screenmap="System Console Screenmap" +msg_system_console_terminal_type="System Console Terminal Type" +msg_timeout="Timeout" +msg_timeout_desc="Set the screen saver timeout interval" +msg_ttys="Ttys" +msg_ttys_menu_text="For various console encodings, a corresponding terminal type\nmust be chosen in /etc/ttys.\n\nWARNING: For compatibility reasons, only entries starting with\nttyv and terminal types starting with cons[0-9] can be changed\nvia this menu." +msg_uk_cp850="UK CP850" +msg_uk_cp850_desc="UK Code Page 850 keymap" +msg_uk_iso="UK ISO" +msg_uk_iso_desc="UK ISO keymap" +msg_ukrainian_koi8_u="Ukranian KOI8-U" +msg_ukrainian_koi8_u_desc="Ukranian KOI8-U keymap" +msg_ukrainian_koi8_u_koi8_r="Ukranian KOI8-U+KOI8-R" +msg_ukrainian_koi8_u_koi8_r_desc="Ukranian KOI8-U+KOI8-R keymap (alter)" +msg_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/usr.sbin/bsdconfig/console/keymap b/usr.sbin/bsdconfig/console/keymap new file mode 100755 index 000000000..99072b539 --- /dev/null +++ b/usr.sbin/bsdconfig/console/keymap @@ -0,0 +1,333 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# List of keymap names +# +KEYMAP_NAMES=" + belgian brazil_cp850 brazil_iso + brazil_iso_accent bulgarian_bds bulgarian_phonetic + central_european_iso croatian_iso czech_iso_accent + danish_cp865 danish_iso estonian_cp850 + estonian_iso estonian_iso_15 finnish_cp850 + finnish_iso french_iso french_iso_accent + french_iso_macbook german_cp850 german_iso + greek_101 greek_104 greek_elot + hungarian_101 hungarian_102 icelandic + icelandic_accent italian japanese_106 + latin_american latin_american_accent norway_iso + polish_iso portuguese portuguese_accent + russia_koi8_r slovak slovenian + spanish spanish_accent swedish_cp850 + swedish_iso swiss_french_cp850 swiss_french_iso + swiss_french_iso_accent swiss_german_cp850 swiss_german_iso + swiss_german_iso_accent uk_cp850 uk_iso + ukrainian_koi8_u ukrainian_koi8_u_koi8_r usa_capslock_ctrl + usa_dvorak usa_dvorak_left usa_dvorak_right + usa_emacs usa_iso usa_unix +" # END-QUOTE + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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.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 + if [ "$( eval echo \"\$msg_$name\" )" = "$mtag" ]; then + keymap_name="$name" + break + fi + 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) keymap_to_set="us.pc-ctrl" ;; + 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_sysrc_set keymap "$keymap_to_set" || f_die + break + else + f_die 1 "$msg_unknown_keymap" + fi +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/console/repeat b/usr.sbin/bsdconfig/console/repeat new file mode 100755 index 000000000..54134c636 --- /dev/null +++ b/usr.sbin/bsdconfig/console/repeat @@ -0,0 +1,142 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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_sysrc_set keyrate "$repeat_rate_to_set" || f_die + break +else + f_die 1 "$msg_unknown_repeat_rate" +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/console/saver b/usr.sbin/bsdconfig/console/saver new file mode 100755 index 000000000..00d9e940c --- /dev/null +++ b/usr.sbin/bsdconfig/console/saver @@ -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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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_sysrc_set blanktime "$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_sysrc_set saver "$saver_to_set" || f_die + break +else + f_die 1 "$msg_unknown_saver" +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/console/screenmap b/usr.sbin/bsdconfig/console/screenmap new file mode 100755 index 000000000..f9bbcd81a --- /dev/null +++ b/usr.sbin/bsdconfig/console/screenmap @@ -0,0 +1,154 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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_sysrc_set scrnmap "$scrnmap_to_set" || f_die + break +else + f_die 1 "$msg_unknown_screenmap_selection" +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/console/ttys b/usr.sbin/bsdconfig/console/ttys new file mode 100755 index 000000000..c0f3ee8fa --- /dev/null +++ b/usr.sbin/bsdconfig/console/ttys @@ -0,0 +1,204 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ 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 $SUCCESS ]; 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 consterm="$1" err + + # + # Create new temporary file to write our ttys(5) update with new types. + # + local tmpfile="$( mktemp -t "pgm" )" + [ "$tmpfile" ] || return $FAILURE + + # + # Fixup permissions and ownership (mktemp(1) creates the temporary file + # with 0600 permissions -- change the permissions and ownership to + # match ttys(5) before we write it out and mv(1) it into place). + # + local mode="$( stat -f '%#Lp' "$ETC_TTYS" 2> /dev/null )" + local owner="$( stat -f '%u:%g' "$ETC_TTYS" 2> /dev/null )" + f_quietly chmod "${mode:-0644}" "$tmpfile" + f_quietly chown "${owner:-root:wheel}" "$tmpfile" + + # + # Operate on ttys(5), replacing only the types of `ttyv*' and + # `cons[0-9]' terminals with the new type. + # + 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 + if ! err=$( mv -f "$tmpfile" "$ETC_TTYS" 2>&1 ); then + f_dialog_msgbox "$err" + return $FAILURE + fi + + 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/usr.sbin/bsdconfig/diskmgmt/INDEX b/usr.sbin/bsdconfig/diskmgmt/INDEX new file mode 100644 index 000000000..e04bb79da --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/diskmgmt/Makefile b/usr.sbin/bsdconfig/diskmgmt/Makefile new file mode 100644 index 000000000..894c62c17 --- /dev/null +++ b/usr.sbin/bsdconfig/diskmgmt/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/050.diskmgmt +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= diskmgmt + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/diskmgmt/USAGE b/usr.sbin/bsdconfig/diskmgmt/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/diskmgmt/diskmgmt b/usr.sbin/bsdconfig/diskmgmt/diskmgmt new file mode 100755 index 000000000..8c3435df9 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# If X11 is requested, which terminal and what options should we use? +# +X11TERM=xterm +X11TERM_OPTS= + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/diskmgmt/include/Makefile b/usr.sbin/bsdconfig/diskmgmt/include/Makefile new file mode 100644 index 000000000..9c94c0e15 --- /dev/null +++ b/usr.sbin/bsdconfig/diskmgmt/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/050.diskmgmt/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/diskmgmt/include/messages.subr b/usr.sbin/bsdconfig/diskmgmt/include/messages.subr new file mode 100644 index 000000000..f0b563f97 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/docsinstall/INDEX b/usr.sbin/bsdconfig/docsinstall/INDEX new file mode 100644 index 000000000..6308f30ce --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/docsinstall/Makefile b/usr.sbin/bsdconfig/docsinstall/Makefile new file mode 100644 index 000000000..de03d7d97 --- /dev/null +++ b/usr.sbin/bsdconfig/docsinstall/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/020.docsinstall +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= docsinstall + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/docsinstall/USAGE b/usr.sbin/bsdconfig/docsinstall/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/docsinstall/docsinstall b/usr.sbin/bsdconfig/docsinstall/docsinstall new file mode 100755 index 000000000..5e3a0d308 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# If X11 is requested, which terminal and what options should we use? +# +X11TERM=xterm +X11TERM_OPTS= + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/docsinstall/include/Makefile b/usr.sbin/bsdconfig/docsinstall/include/Makefile new file mode 100644 index 000000000..9f75f7d21 --- /dev/null +++ b/usr.sbin/bsdconfig/docsinstall/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/020.docsinstall/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/docsinstall/include/messages.subr b/usr.sbin/bsdconfig/docsinstall/include/messages.subr new file mode 100644 index 000000000..4c55f0fc0 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/dot/INDEX b/usr.sbin/bsdconfig/dot/INDEX new file mode 100644 index 000000000..fa641e01f --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/dot/Makefile b/usr.sbin/bsdconfig/dot/Makefile new file mode 100644 index 000000000..5a87282c7 --- /dev/null +++ b/usr.sbin/bsdconfig/dot/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/dot +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= dot + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/dot/USAGE b/usr.sbin/bsdconfig/dot/USAGE new file mode 100644 index 000000000..5bc38cc57 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/dot/dot b/usr.sbin/bsdconfig/dot/dot new file mode 100755 index 000000000..e13a269ae --- /dev/null +++ b/usr.sbin/bsdconfig/dot/dot @@ -0,0 +1,683 @@ +#!/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 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="dot" +f_include_lang $BSDCFG_LIBE/include/messages.subr +f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ 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 1 "$msg_directory_not_found" "$BSDCFG_LIB" + +# +# Get a list of menu programs +# +menu_program_list= +for file in [0-9][0-9][0-9].*/INDEX; do + menu_program_list="$menu_program_list $( + tail -r "$file" | awk -v item="${file%%/*}" ' + /^[[:space:]]*menu_program="/ { + sub(/^.*="/, "") + sub(/"$/, "") + if ( ! $0 ) next + if ( $0 !~ "^/" ) sub(/^/, item "/") + print; exit + }' + )" +done + +# +# Get a list of submenu programs +# +submenu_program_list= +for menu_program in $menu_program_list; do + case "$menu_program" in + [0-9][0-9][0-9].*/*) : fall-through ;; + *) continue # No sub-menus we can process + esac + + submenu_program_list="$submenu_program_list $( + awk -v menu_program="$menu_program" \ + -v item="${menu_program%%/*}" \ + ' + /^menu_selection="/ { + sub(/.*\|/, "") + sub(/"$/, "") + if ( ! $0 ) next + if ( $0 !~ "^/" ) + sub(/^/, item "/") + if ( $0 == menu_program ) next + print + } + ' "${menu_program%%/*}/INDEX" + )" +done + +# +# Get a list of command-line programs +# +cmd_program_list= +for file in */INDEX; do + cmd_program_list="$cmd_program_list $( + awk -v item="${file%%/*}" ' + /^menu_selection="/ { + sub(/.*\|/, "") + sub(/"$/, "") + + if ( ! $0 ) next + + if ( $0 !~ "^/" ) + sub(/^/, item "/") + + print + } + ' $file + )" +done + +# +# [Optionally] Calculate list of include files +# +if [ "$SHOW_INCLUDES" ]; then + 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 \ + ; 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 + +# +# Add script.subr to includes if it exists +# +[ -f $BSDCFG_SHARE/script.subr ] && + include_file_list="$include_file_list script.subr" + +# +# 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, // 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" +if [ "$SHOW_INCLUDES" ]; then + printf '\t\tsubgraph "cluster_includes" {\n' + printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_includes" + printf '\t\t\tlabel = "%s";\n' "$msg_includes" + + for include_file in $include_file_list; do + echo $include_file + done | awk -v bgcolor="$bgcolor_bsdconfig" ' + BEGIN { created = 0 } + function end_subgraph() { printf "\t\t\t};\n" } + ( $0 !~ "/" ) { + if ( ! created ) + { + printf "\t\t\tsubgraph \"%s\" {\n", + "cluster_bsdconfig_includes" + printf "\t\t\t\tbgcolor = \"%s\";\n", bgcolor + printf "\t\t\t\tlabel = \"bsdconfig\";\n" + created++ + } + printf "\t\t\t\t\"%s\";\n", $1 + } + END { created && end_subgraph() }' + + for include_file in $include_file_list; do + echo $include_file + done | awk ' + BEGIN { created = 0 } + function end_subgraph() { printf "\t\t\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 "\t\t\tsubgraph \"cluster_%s_includes\" {\n", + include_dir + printf "\t\t\t\tbgcolor = \"white\";\n" + printf "\t\t\t\tlabel = \"%s\";\n", include_dir + created++ + } + + printf "\t\t\t\t\"%s\";\n", $1 + } + END { created && end_subgraph() }' + + printf '\t\t};\n' +fi +end_nodelist +for INDEX in */INDEX; do + menu_title= + menu_help= + f_include_lang "$INDEX" + + item="${INDEX%%/*}" + printf '\tsubgraph "cluster_%s" {\n' "$item" + + case "$item" in + [0-9][0-9][0-9].*) bgcolor="$bgcolor_menuitem" ;; + *) bgcolor="$bgcolor_shortcuts" + esac + printf '\t\tbgcolor = "%s";\n' "$bgcolor" + if [ "$menu_title" ]; then + printf '\t\tlabel = "%s\\n\\"%s\\"";\n' "$item" "$menu_title" + else + printf '\t\tlabel = "%s";\n' "$item" + fi + printf '\t\ttooltip = "%s";\n' "${menu_help:-$item}" + + program_list=$( + for program in \ + $menu_program_list \ + $submenu_program_list \ + $cmd_program_list \ + ; do + echo "$program" + done | sort -u + ) + for program in $program_list; do + case "$program" in "$item"/*) + print_node "$program" "label = \"${program#*/}\"" + esac + done + + if [ "$SHOW_INCLUDES" ]; then + item_include_list= + [ -d "$item/include" ] && + item_include_list=$( find "$item/include" -type f ) + item_include_list=$( + for item_include in $item_include_list; do + for include_file in $include_file_list; do + [ "$item_include" = "$include_file" ] || + continue + echo "$item_include"; break + done + done + ) + if [ "$item_include_list" ]; then + printf '\t\tsubgraph "cluster_%s_includes" {\n' "$item" + printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_includes" + printf '\t\t\tlabel = "%s";\n' "$msg_includes" + fi + for item_include in $item_include_list; do + printf '\t\t\t"%s";\n' "$item_include" + done + [ "$item_include_list" ] && printf '\t\t};\n' + fi + + if [ "$SHOW_CMDLINE" ]; then + printf '\t\tsubgraph "cluster_%s_shortcuts" {\n' "$item" + printf '\t\t\tbgcolor = "%s";\n' "$bgcolor_shortcuts" + printf '\t\t\tlabel = "%s";\n' "$msg_shortcuts" + awk '/^menu_selection="/ { + sub(/^.*="/, "") + sub(/\|.*/, "") + printf "\t\t\t\"bsdconfig %s\";\n", $0 + }' "$INDEX" + printf '\t\t};\n' + fi + + end_nodelist +done + +printf '\n};\n' + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/dot/include/Makefile b/usr.sbin/bsdconfig/dot/include/Makefile new file mode 100644 index 000000000..9bbdea074 --- /dev/null +++ b/usr.sbin/bsdconfig/dot/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/dot/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/dot/include/messages.subr b/usr.sbin/bsdconfig/dot/include/messages.subr new file mode 100644 index 000000000..527f30885 --- /dev/null +++ b/usr.sbin/bsdconfig/dot/include/messages.subr @@ -0,0 +1,30 @@ +# Copyright (c) 2012 Devin Teske +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +msg_graph_label_with_command="bsdconfig(8)\\\ndot(1) output generated by \`\`%s''" +msg_graph_label_with_command_and_date="bsdconfig(8)\\\ndot(1) output generated by \`\`%s'' on\\\n%s" +msg_includes="Includes" +msg_shortcuts="Shortcuts" diff --git a/usr.sbin/bsdconfig/examples/Makefile b/usr.sbin/bsdconfig/examples/Makefile new file mode 100644 index 000000000..78711d29b --- /dev/null +++ b/usr.sbin/bsdconfig/examples/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/examples/bsdconfig +FILES= browse_packages.sh bsdconfigrc + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/examples/browse_packages.sh b/usr.sbin/bsdconfig/examples/browse_packages.sh new file mode 100755 index 000000000..6396f4677 --- /dev/null +++ b/usr.sbin/bsdconfig/examples/browse_packages.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# $FreeBSD$ +# +# This sample downloads the package INDEX file from FTP to /tmp (if it doesn't +# already exist) and then displays the package configuration/management screen +# using the local INDEX file (results in faster browsing of packages from-start +# since the INDEX can be loaded from local media). +# +# NOTE: Packages cannot be installed unless staged to /tmp/packages/All +# +. /usr/share/bsdconfig/script.subr +nonInteractive=1 +TMPDIR=/tmp +if [ ! -e "$TMPDIR/packages/INDEX" ]; then + [ -d "$TMPDIR/packages" ] || mkdir -p "$TMPDIR/packages" || exit 1 + _ftpPath=ftp://ftp.freebsd.org + # For older releases, use ftp://ftp-archive.freebsd.org + mediaSetFTP + mediaOpen + f_show_info "Downloading packages/INDEX from %s" "$_ftpPath" + f_device_get media packages/INDEX > $TMPDIR/packages/INDEX + mediaClose +fi +_directoryPath=$TMPDIR +mediaSetDirectory +configPackages diff --git a/usr.sbin/bsdconfig/examples/bsdconfigrc b/usr.sbin/bsdconfig/examples/bsdconfigrc new file mode 100644 index 000000000..2e3155fda --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/include/Makefile b/usr.sbin/bsdconfig/include/Makefile new file mode 100644 index 000000000..ee21cec56 --- /dev/null +++ b/usr.sbin/bsdconfig/include/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/include +FILES= bsdconfig.hlp media.hlp messages.subr network_device.hlp \ + options.hlp tcp.hlp usage.hlp + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/include/bsdconfig.hlp b/usr.sbin/bsdconfig/include/bsdconfig.hlp new file mode 100644 index 000000000..b6eeaf3c4 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/include/media.hlp b/usr.sbin/bsdconfig/include/media.hlp new file mode 100644 index 000000000..6fd609473 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/include/messages.subr b/usr.sbin/bsdconfig/include/messages.subr new file mode 100644 index 000000000..1dc8f954a --- /dev/null +++ b/usr.sbin/bsdconfig/include/messages.subr @@ -0,0 +1,427 @@ +# 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$ + +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_arabic_desc="Ported software for Arab countries." +msg_archivers_desc="Utilities for archiving and unarchiving data." +msg_argentina="Argentina" +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_fetch_file_from_selected_media="Attempting to fetch %s file 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_brazil="Brazil" +msg_building_package_menus="Building package menu(s)..." +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_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_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_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_created_path="Created %s" +msg_croatia="Croatia" +msg_czech_republic="Czech Republic" +msg_databases_desc="Database software." +msg_debugging="Debugging" +msg_denmark="Denmark" +msg_deskutils_desc="Various Desktop utilities." +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 / 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_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_file_system="File System" +msg_finance_desc="Monetary, financial and related applications." +msg_finland="Finland" +msg_floppy="Floppy" +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_games_desc="Various games and sundry amusements." +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_hungary="Hungary" +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_lc="installed" +msg_installed_desc="Leave package as-is, 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 %s 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_italy="Italy" +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_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_located_index_now_reading_package_data_from_it="Located INDEX, now reading package data from it..." +msg_logging_in_to_user_at_host="Logging in to %s@%s.." +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_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_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_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_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_pkg_delete_failed="Warning: pkg_delete of %s failed.\n Run with debugging for details." +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_read_successfully_waiting_for_pkg_add="Package %s read successfully - waiting for pkg_add(1)" +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_pkg_add_apparently_did_not_like_the_package="pkg_add(1) apparently did not like the %s package." +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:///\nWhere 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:///" +msg_poland="Poland" +msg_polish_desc="Ported software for the Polish market." +msg_ports_mgmt_desc="Utilities for managing ports and packages." +msg_portugal="Portugal" +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_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_devices="Re-scan Devices" +msg_reset="RESET!" +msg_reset_all_values_to_startup_defaults="Reset all values to startup defaults" +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_romania="Romania" +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_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_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_singapore="Singapore" +msg_slovak_republic="Slovak Republic" +msg_slovenia="Slovenia" +msg_snapshots_server_japan="Snapshots Server Japan" +msg_snapshots_server_sweden="Snapshots Server Sweden" +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_turkey="Turkey" +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_uninstall="Uninstall" +msg_uninstall_desc="Mark this package for deletion" +msg_uninstalling_package_waiting_for_pkg_delete="Uninstalling %s package - waiting for pkg_delete(1)" +msg_unknown="unknown" +msg_unknown_user="Unknown user: %s" +msg_url_was_not_found="%s was not found, maybe 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_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_windowmaker_desc="Ports to support the WindowMaker window manager." +msg_would_you_like_to_bring_interface_up="Would you like to bring the %s interface up right now?" +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 utilties." +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/usr.sbin/bsdconfig/include/network_device.hlp b/usr.sbin/bsdconfig/include/network_device.hlp new file mode 100644 index 000000000..affa86a91 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/include/options.hlp b/usr.sbin/bsdconfig/include/options.hlp new file mode 100644 index 000000000..f47df27a6 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/include/tcp.hlp b/usr.sbin/bsdconfig/include/tcp.hlp new file mode 100644 index 000000000..6d0ba10f6 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/include/usage.hlp b/usr.sbin/bsdconfig/include/usage.hlp new file mode 100644 index 000000000..4412da7dd --- /dev/null +++ b/usr.sbin/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 to +switch between screens, where `F' 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/usr.sbin/bsdconfig/mouse/INDEX b/usr.sbin/bsdconfig/mouse/INDEX new file mode 100644 index 000000000..4a33a7929 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/mouse/Makefile b/usr.sbin/bsdconfig/mouse/Makefile new file mode 100644 index 000000000..3b68cad57 --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/110.mouse +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= disable enable flags mouse port type + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/mouse/USAGE b/usr.sbin/bsdconfig/mouse/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/mouse/disable b/usr.sbin/bsdconfig/mouse/disable new file mode 100755 index 000000000..6807abdcd --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/disable @@ -0,0 +1,93 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# Location of moused(8) pidfile +# +MOUSED_PIDFILE=/var/run/moused.pid + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 +# +[ -r "$MOUSED_PIDFILE" ] && + f_quietly kill "$( cat "$MOUSED_PIDFILE" )" +f_sysrc_set moused_enable "NO" || f_die +f_sysrc_set moused_type "NO" || f_die +f_sysrc_delete moused_port || f_die +f_sysrc_delete moused_flags || f_die + +# +# Message box +# +f_dialog_title "$msg_message" +f_dialog_msgbox "$msg_mouse_daemon_is_disabled" "$hline_press_enter_or_space" + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/mouse/enable b/usr.sbin/bsdconfig/mouse/enable new file mode 100755 index 000000000..695eac08d --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/enable @@ -0,0 +1,118 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# Location of moused(8) pidfile +# +MOUSED_PIDFILE=/var/run/moused.pid + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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" +[ -r "$MOUSED_PIDFILE" ] && + f_quietly kill "$( cat "$MOUSED_PIDFILE" 2> /dev/null )" +f_quietly vidcontrol -m on +f_quietly moused -t "$type" -p "$port" $flags + +# +# Confirm with the user that the mouse is working +# +f_dialog_title "$msg_user_confirmation_requested" +f_dialog_yesno "$msg_now_move_the_mouse" +retval=$? +f_dialog_title_restore + +# +# Stop the mouse daemon +# +f_quietly vidcontrol -m off +if [ $retval -eq $SUCCESS ]; then + f_sysrc_set moused_enable "YES" || f_die + ln -fs /dev/sysmouse /dev/mouse || f_die # backwards compat +else + [ -r "$MOUSED_PIDFILE" ] && + f_quietly kill "$( cat "$MOUSED_PIDFILE" )" + f_sysrc_set moused_enable "NO" || f_die +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/mouse/flags b/usr.sbin/bsdconfig/mouse/flags new file mode 100755 index 000000000..de2ca7633 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# Location of moused(8) pidfile +# +MOUSED_PIDFILE=/var/run/moused.pid + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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_sysrc_set moused_flags "$flags" || f_die + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/mouse/include/Makefile b/usr.sbin/bsdconfig/mouse/include/Makefile new file mode 100644 index 000000000..ed0b24dad --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/110.mouse/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/mouse/include/messages.subr b/usr.sbin/bsdconfig/mouse/include/messages.subr new file mode 100644 index 000000000..74d998081 --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/include/messages.subr @@ -0,0 +1,93 @@ +# 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_busmouse="BusMouse" +msg_busmouse_desc="Logitech, ATI or MS bus mouse (/dev/mse0)" +msg_cancel="Cancel" +msg_com1="COM1" +msg_com1_desc="Serial mouse on COM1 (/dev/cuau0)" +msg_com2="COM2" +msg_com2_desc="Serial mouse on COM2 (/dev/cuau1)" +msg_com3="COM3" +msg_com3_desc="Serial mouse on COM3 (/dev/cuau2)" +msg_com4="COM4" +msg_com4_desc="Serial mouse on COM4 (/dev/cuau3)" +msg_disable="Disable" +msg_disable_the_mouse_daemon="Disable the mouse daemon" +msg_enable="Enable" +msg_exit="Exit" +msg_exit_this_menu="Exit this menu" +msg_flags="Flags" +msg_glidepoint="GlidePoint" +msg_glidepoint_desc="ALPS GlidePoint pad (serial)" +msg_hitachi="Hitachi" +msg_hitachi_desc="Hitachi tablet (serial)" +msg_intellimouse="IntelliMouse" +msg_intellimouse_desc="Microsoft IntelliMouse (serial)" +msg_logitech="Logitech" +msg_logitech_desc="Logitech protocol (old models) (serial)" +msg_menu_text="You can cut and paste text in the text console by running the mouse\ndaemon. Specify a port and a protocol type of your mouse and enable\nthe mouse daemon. If you don't want this feature, select 6 to disable\nthe daemon.\nOnce you've enabled the mouse daemon, you can specify \"/dev/sysmouse\"\nas your mouse device and \"SysMouse\" or \"MouseSystems\" as mouse\nprotocol when running the X configuration utility (see Configuration\nmenu)." +msg_message="Message" +msg_microsoft="Microsoft" +msg_microsoft_desc="Microsoft protocol (serial)" +msg_mm_series="MM Series" +msg_mm_series_desc="MM Series protocol (serial)" +msg_mouseman="MouseMan" +msg_mouseman_desc="Logitech MouseMan/TrackMan models (serial)" +msg_mousesystems="MouseSystems" +msg_mousesystems_desc="MouseSystems protocol (serial)" +msg_mouse_daemon_is_disabled="The mouse daemon is disabled." +msg_mouse_disable="Mouse Disable" +msg_mouse_enable="Mouse Enable" +msg_mouse_flags="Mouse Flags" +msg_now_move_the_mouse="Now move the mouse and see if it works.\n(Note that buttons don't have any effect for now.)\n\n Is the mouse cursor moving?\n" +msg_ok="OK" +msg_please_configure_your_mouse="Please configure your mouse" +msg_please_select_protocol_and_port_first="Please select a mouse protocol and a port first." +msg_please_specify_the_mouse_daemon_flags="Please specify the mouse daemon flags. If you would like to\nemulate 3 buttons, use -3 here.\n " +msg_port="Port" +msg_port_menu_text="The built-in pointing device of laptop/notebook computers is usually\na PS/2 style device." +msg_protocol_menu_text="If your mouse is attached to the PS/2 mouse port or the bus mouse port,\nyou should always choose \"Auto\", regardless of the model and the brand\nof the mouse. All other protocol types are for serial mice and should\nnot be used with the PS/2 port mouse or the bus mouse. If you have\na serial mouse and are not sure about its protocol, you should also try\n\"Auto\". It may not work for the serial mouse if the mouse does not\nsupport the PnP standard. But, it won't hurt. Many 2-button serial mice\nare compatible with \"Microsoft\" or \"MouseMan\". 3-button serial mice\nmay be compatible with \"MouseSystems\" or \"MouseMan\". If the serial\nmouse has a wheel, it may be compatible with \"IntelliMouse\"." +msg_ps2="PS/2" +msg_ps2_desc="PS/2 style mouse (/dev/psm0)" +msg_select_a_protocol_type_for_your_mouse="Select a protocol type for your mouse" +msg_select_mouse_port="Select mouse port" +msg_select_mouse_protocol_type="Select mouse protocol type" +msg_select_your_mouse_port_from_the_following_menu="Select your mouse port from the following menu" +msg_set_additional_flags="Set additional flags" +msg_test_and_run_the_mouse_daemon="Test and run the mouse daemon" +msg_thinkingmouse="ThinkingMouse" +msg_thinkingmouse_desc="Kensington ThinkingMouse (serial)" +msg_trying_to_start_the_mouse_daemon="Trying to start the mouse daemon..." +msg_type="Type" +msg_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/usr.sbin/bsdconfig/mouse/mouse b/usr.sbin/bsdconfig/mouse/mouse new file mode 100755 index 000000000..bafed0415 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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/usr.sbin/bsdconfig/mouse/port b/usr.sbin/bsdconfig/mouse/port new file mode 100755 index 000000000..41dd481b6 --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/port @@ -0,0 +1,153 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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' + '6 $msg_busmouse' '$msg_busmouse_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" ;; + /dev/mse0) defaultitem="6 $msg_busmouse" ;; + 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" ;; +"6 $msg_busmouse") # Logitech, ATI or MS bus mouse (/dev/mse0) + moused_port_to_set="/dev/mse0" ;; +esac + +if [ "$moused_port_to_set" ]; then + f_sysrc_set moused_port "$moused_port_to_set" || f_die +else + f_die 1 "$msg_unknown_mouse_port_selection" +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/mouse/type b/usr.sbin/bsdconfig/mouse/type new file mode 100755 index 000000000..30d202292 --- /dev/null +++ b/usr.sbin/bsdconfig/mouse/type @@ -0,0 +1,169 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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_sysrc_set moused_type "$moused_type_to_set" || f_die +else + f_die 1 "$msg_unknown_mouse_protocol_selection" +fi + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/networking/INDEX b/usr.sbin/bsdconfig/networking/INDEX new file mode 100644 index 000000000..852712480 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/INDEX @@ -0,0 +1,61 @@ +# 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="Networking Management" + +# +# A short descriptive line shown at the bottom of the bsdconfig menu. keep it +# short because any line longer than the terminal width will be truncated. +# +menu_help="Setup Networking interfaces, services, etc." + +# +# Two-part variable that defines an action to take when `keyword' is passed on +# a bsdconfig command line. Variable takes the form "keyword|command" and +# multiple occurrences of the variable (with different `keyword's, or different +# `keyword's AND `command's) are allowed. If `command' begins with a '/' then +# the full path to the program is needed. If `command' begins with anything +# else it is a path relative to the directory this INDEX file is in. `keyword' +# can be i18n'ed but `command' is the name of a script. +# +menu_selection="networking|networking" +menu_selection="defaultrouter|defaultrouter" +menu_selection="hostname|hostname" +menu_selection="nameservers|nameservers" +menu_selection="netdev|devices" + +# +# ------------ Items below this line do NOT need i18n translation ------------ +# +# Name of the program to be run when this menu choice is selected. If it begins +# with a '/' then the full path to the program is needed. If it begins with +# anything else it is a path relative to the directory this INDEX file is in. +# +menu_program="networking" diff --git a/usr.sbin/bsdconfig/networking/Makefile b/usr.sbin/bsdconfig/networking/Makefile new file mode 100644 index 000000000..4b7d5283d --- /dev/null +++ b/usr.sbin/bsdconfig/networking/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include share + +FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= defaultrouter devices hostname nameservers networking + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/networking/USAGE b/usr.sbin/bsdconfig/networking/USAGE new file mode 100644 index 000000000..872094666 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/networking/defaultrouter b/usr.sbin/bsdconfig/networking/defaultrouter new file mode 100755 index 000000000..4719e45fc --- /dev/null +++ b/usr.sbin/bsdconfig/networking/defaultrouter @@ -0,0 +1,73 @@ +#!/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 + +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/networking/devices b/usr.sbin/bsdconfig/networking/devices new file mode 100755 index 000000000..00a50c515 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/devices @@ -0,0 +1,158 @@ +#!/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 + +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line options +# +while getopts 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" ] || _ipaddr=$( f_ifconfig_inet $interface ) + [ "$_netmask" ] || _netmask=$( f_ifconfig_netmask $interface ) + + # Get the extra options (this always comes from rc.conf(5)) + _options=$( f_ifconfig_options $interface ) + + # Block on user-configuration of the probed settings + f_dialog_menu_netdev_edit \ + "$interface" "$_ipaddr" "$_netmask" "$_options" $dhcp + + # Return to root menu if above returns success + [ $? -eq $SUCCESS ] && break +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/networking/hostname b/usr.sbin/bsdconfig/networking/hostname new file mode 100755 index 000000000..23cf804db --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/networking/include/Makefile b/usr.sbin/bsdconfig/networking/include/Makefile new file mode 100644 index 000000000..c93d4866f --- /dev/null +++ b/usr.sbin/bsdconfig/networking/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/networking/include/messages.subr b/usr.sbin/bsdconfig/networking/include/messages.subr new file mode 100644 index 000000000..ad5461ca6 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/include/messages.subr @@ -0,0 +1,105 @@ +# 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_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_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_ipv4_mask_field_contains_invalid_chars="ERROR! One or more individual fields within the subnet mask\n(separated by dots) contains one or more invalid characters.\n\nInvalid Subnet Mask: %s" +msg_ipv4_mask_field_exceeds_max_value="ERROR! One or more individual fields within the subnet mask\n(separated by dots) exceeds the maximum of 255.\n\nInvalid Subnet Mask: %s" +msg_ipv4_mask_field_invalid_value="ERROR! One or more individual fields within the subnet mask\n(separated by dots) contains one or more invalid integers.\nFields must be one of 0/128/192/224/240/248/252/254/255.\n\nInvalid Subnet Mask: %s" +msg_ipv4_mask_field_is_null="ERROR! One or more individual fields within the subnet mask\n(separated by dots) are null and/or missing.\n\nInvalid Subnet Mask: %s" +msg_ipv4_mask_field_missing_or_extra="ERROR! The subnet mask entered has either too few or too many\nfields.\n\nInvalid Subnet Mask: %s" +msg_netmask="netmask" +msg_network_configuration="%s Network Configuration:\nChoose Save/Exit when finished or Cancel." +msg_network_interfaces="Network Interfaces" +msg_network_management="Network Management" +msg_networking_devices="Networking Devices" +msg_nfs_mounts_may_cause_hang="WARNING! Changing this setting while NFS directories are\nmounted may cause the system to hang. 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" +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/usr.sbin/bsdconfig/networking/nameservers b/usr.sbin/bsdconfig/networking/nameservers new file mode 100755 index 000000000..108c56781 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/networking/networking b/usr.sbin/bsdconfig/networking/networking new file mode 100755 index 000000000..b320e5d77 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/networking @@ -0,0 +1,151 @@ +#!/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 + +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local prompt= + local menu_list=" + 'X' '$msg_exit' + '1' '$msg_hostname_domain' + '2' '$msg_network_interfaces' + '3' '$msg_default_router' + '4' '$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=defaultrouter ;; # Default Router/Gateway + 4) 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/usr.sbin/bsdconfig/networking/share/Makefile b/usr.sbin/bsdconfig/networking/share/Makefile new file mode 100644 index 000000000..cf1119ddb --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/bsdconfig/networking +FILES= common.subr device.subr hostname.subr ipaddr.subr media.subr \ + netmask.subr resolv.subr routing.subr services.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/networking/share/common.subr b/usr.sbin/bsdconfig/networking/share/common.subr new file mode 100644 index 000000000..152d1aceb --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr new file mode 100644 index 000000000..a0ca5cc31 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/device.subr @@ -0,0 +1,393 @@ +if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_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/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/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/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 defaultitem="${1%\*}" # Tim 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 d='[[:digit:]]+:' + local iflist="`echo "$(ifconfig -l):" | sed -E -e " + # Convert all spaces to colons + y/ /:/ + + # Prune unsavory interfaces + s/lo$d//g + s/ppp$d//g + s/sl$d//g + s/faith$d//g + + # Convert all colons back into spaces + y/:/ / + "`" + + # + # Optionally kick interfaces in the head to get them to accurately + # track the carrier status in realtime (required on FreeBSD). + # + if [ "$DIALOG_MENU_NETDEV_KICK_INTERFACES" ]; then + DIALOG_MENU_NETDEV_KICK_INTERFACES= + + local ifn + for ifn in $iflist; do + f_quietly ifconfig $ifn up + done + + if [ "$DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK" ]; then + # interfaces need time to update carrier status + sleep $DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK + fi + fi + + # + # Mark any "active" interfaces with an asterisk (*) + # to the right of the device name. + # + interfaces=$( + for ifn in $iflist; do + active=$( ifconfig $ifn | awk \ + ' + ( $1 == "status:" ) \ + { + if ( $2 == "active" ) { print 1; exit } + } + ' ) + printf "'%s%s' '%s'\n" \ + $ifn "${active:+*}" "$( f_device_desc $ifn )" + done + ) + if [ ! "$interfaces" ]; then + f_show_msg "$msg_no_network_interfaces" + return $FAILURE + fi + + # + # Maybe the default item was marked as active + # + if [ "$defaultitem" ]; then + ifconfig "$defaultitem" 2> /dev/null | awk \ + '( $1 == "status:" && $2 != "active" ) { exit 0 }' || + defaultitem="$defaultitem*" + fi + + local hline="$hline_arrows_tab_enter" + + # + # Ask user to select an interface + # + local prompt="$msg_select_network_interface" + local height width rows + eval f_dialog_menu_size height width rows \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$prompt\" \ + \"\$hline\" \ + $interfaces + 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 \ + $interfaces \ + 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 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" + prompt=$( printf "$msg_network_configuration" "$interface" ) + + # + # Loop forever until the user has finished configuring the different + # components of the network interface. + # + # To apply the settings, we need to know each of the following: + # - IP Address + # - Network subnet mask + # - Additional ifconfig(8) options + # + # It is only when we have all of the above values that we can make the + # changes effective because all three options must be specified at-once + # to ifconfig(8). + # + local defaultitem= + while :; do + local dhcp_status="$msg_disabled" + [ "$dhcp" ] && dhcp_status="$msg_enabled" + + # + # Display configuration-edit menu + # + menu_list=" + 'X $msg_save_exit' '$msg_return_to_previous_menu' + '2 $msg_dhcp' '$dhcp_status' + '3 $msg_ipaddr4' '$ipaddr' + '4 $msg_netmask' '$netmask' + '5 $msg_options' '$options' + " + 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 2 ]; then + # The Help button was pressed + f_show_help "$TCP_HELPFILE" + continue + elif [ $retval -ne $SUCCESS ]; then + # "Cancel" was chosen (-1) or ESC was pressed (255) + 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 ;; + 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="$( printf "$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 + msg=$( printf "$msg_scanning_for_dhcp" "$interface" ) + if [ "$USE_XDIALOG" ]; then + ( + f_quietly ifconfig $interface delete + f_quietly dhclient $interface + ) | + f_xdialog_info "$msg" + else + f_dialog_info "$msg" + f_quietly ifconfig $interface delete + f_quietly dhclient $interface + fi + ) + retval=$? + trap 'interrupt' SIGINT + if [ $retval -eq $SUCCESS ]; then + dhcp=1 + ipaddr=$( f_ifconfig_inet $interface ) + netmask=$( f_ifconfig_netmask $interface ) + options= + + # Fixup search/domain in resolv.conf(5) + hostname=$( f_sysrc_get \ + 'hostname:-$(hostname)' ) + f_dialog_resolv_conf_update "$hostname" + fi + fi + ;; + 3\ *) f_dialog_input_ipaddr "$interface" "$ipaddr" + [ $? -eq $SUCCESS ] && dhcp= ;; + 4\ *) f_dialog_input_netmask "$interface" "$netmask" + [ $? -eq $SUCCESS -a "$_netmask" ] && dhcp= ;; + 5\ *) f_dialog_menu_media_options "$interface" "$options" + [ $? -eq $SUCCESS ] && dhcp= ;; + esac + done + + # + # Save only if the user changed at least one feature of the interface + # + if [ "$ipaddr" != "$ipaddr_orig" -o \ + "$netmask" != "$netmask_orig" -o \ + "$options" != "$options_orig" -o \ + "$dhcp" != "$dhcp_orig" ] + then + f_show_info "$msg_saving_network_interface" "$interface" + + local value= + if [ "$dhcp" ]; then + f_sysrc_delete defaultrouter + value=DHCP + else + value="inet $ipaddr netmask $netmask" + value="$value${options:+ }$options" + fi + + f_sysrc_set ifconfig_$interface "$value" + fi + + # + # Re/Apply the settings if desired + # + if [ ! "$dhcp" ]; then + if f_yesno "$msg_bring_interface_up" "$interface" + then + f_show_info "$msg_bring_interface_up" "$interface" + + local dr="$( f_sysrc_get defaultrouter )" err + if [ "$dr" = "NO" -o ! "$dr" ]; then + dr=$( f_route_get_default ) + [ "$dr" ] && f_sysrc_set defaultrouter "$dr" + fi + # + # Make a backup of resolv.conf(5) before using + # ifconfig(8) and then restore it afterward. This + # allows preservation of nameservers acquired via + # DHCP on FreeBSD-8.x (normally lost as ifconfig(8) + # usage causes dhclient(8) to exit which scrubs + # resolv.conf(5) by-default upon termination). + # + f_quietly cp -fp "$RESOLV_CONF" "$RESOLV_CONF.$$" + err=$( ifconfig $interface inet $ipaddr \ + netmask $netmask $options 2>&1 ) + if [ $? -eq $SUCCESS ]; then + if [ "$dr" -a "$dr" != "NO" ]; then + err=$( route add default "$dr" 2>&1 ) + [ $? -eq $SUCCESS ] || \ + dialog_msgbox "$err" + fi + else + dialog_msgbox "$err" + fi + if cmp -s "$RESOLV_CONF" "$RESOLV_CONF.$$"; then + f_quietly rm -f "$RESOLV_CONF.$$" + else + f_quietly mv -f "$RESOLV_CONF.$$" "$RESOLV_CONF" + fi + fi + fi + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." networking/device.subr + +fi # ! $_NETWORKING_DEVICE_SUBR diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr new file mode 100644 index 000000000..05f03154c --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/hostname.subr @@ -0,0 +1,160 @@ +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 +# http://tools.ietf.org/html/rfc952 +# +# RFC 1123 - Requirements for Internet Hosts - Application and Support +# http://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 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_sysrc_set hostname "$hostname" + fi + + # + # Update resolv.conf(5) search/domain directives + # + f_dialog_resolv_conf_update "$hostname" + + # + # Only ask to apply setting if the current hostname is different than + # the stored configuration (in rc.conf(5)). + # + if [ "$( hostname )" != "$( f_sysrc_get hostname )" ]; then + [ ! "$USE_XDIALOG" ] && 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 $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." networking/hostname.subr + +fi # ! $_NETWORKING_HOSTNAME_SUBR diff --git a/usr.sbin/bsdconfig/networking/share/ipaddr.subr b/usr.sbin/bsdconfig/networking/share/ipaddr.subr new file mode 100644 index 000000000..9c51f592a --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/ipaddr.subr @@ -0,0 +1,218 @@ +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="$( printf "$msg_current_ipaddr" \ + "$interface" "$_ipaddr" )" + f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" || + return $FAILURE + fi + + local msg="$( printf "$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 $FAILURE + + # Return success if NULL value was entered + [ "$_input" ] || return $SUCCESS + + # Take only the first "word" of the user's input + _ipaddr="$_input" + _ipaddr="${_ipaddr%%[$IFS]*}" + + # Taint-check the user's input + f_dialog_validate_ipaddr "${_ipaddr%%/*}" && break + done + + # + # Support the syntax: IP_ADDRESS/NBITS + # + local _netmask="" + case "$_ipaddr" in + */*) + local nbits="${_ipaddr#*/}" n=0 + _ipaddr="${_ipaddr%%/*}" + + # + # Taint-check $nbits to be (a) a positive whole-integer, + # and (b) to be less than or equal to 32. Otherwise, set + # $n so that the below loop never executes. + # + ( f_isinteger "$nbits" && [ $nbits -ge 0 -a $nbits -le 32 ] ) \ + || n=4 + + while [ $n -lt 4 ]; do + _netmask="$_netmask${_netmask:+.}$(( + (65280 >> ($nbits - 8 * $n) & 255) + * ((8*$n) < $nbits & $nbits <= (8*($n+1))) + + 255 * ($nbits > (8*($n+1))) + ))" + n=$(( $n + 1 )) + done + ;; + esac + + ipaddr="$_ipaddr" + [ "$_netmask" ] && netmask="$_netmask" + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." networking/ipaddr.subr + +fi # ! $_NETWORKING_IPADDR_SUBR diff --git a/usr.sbin/bsdconfig/networking/share/media.subr b/usr.sbin/bsdconfig/networking/share/media.subr new file mode 100644 index 000000000..c6efa57a9 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/media.subr @@ -0,0 +1,244 @@ +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="$( printf "$msg_current_options" \ + "$interface" "$options" )" + f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" || + return $FAILURE + fi + + local msg="$( printf "$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 $SUCCESS ] && options="$_options" + + return $retval +} + +# f_dialog_menu_media_options $interface +# +# Display a menu of additional media options for the given network interface. +# +f_dialog_menu_media_options() +{ + local interface="$1" _options="$2" + # + # Not all network interfaces support additional media options, but + # when available we should prompt the user to select from a list + # of available options (or none, as is the first/default option). + # + + # + # Return with-error when there are NFS-mounts currently active. If the + # media options are changed while NFS-exported directories are mounted, + # the system may hang (if any NFS mounts are using that interface). + # + if f_nfs_mounted && ! f_jailed; then + local setting="$( printf "$msg_current_options" \ + "$interface" "$_options" )" + f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" || + return $FAILURE + fi + + # + # Build list of additional media options + # + local opt_none="$msg_no_options" + local opt_cust="$msg_custom" + local supported_media="$( + f_ifconfig_media $interface | \ + ( index=1 + + echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'" + echo "'$opt_none'" + index=$(( $index + 1 )) + + echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'" + echo "'$opt_cust'" + index=$(( $index + 1 )) + + while read media_options; do + [ $index -lt ${#DIALOG_MENU_TAGS} ] || break + echo "'$( f_substr "$DIALOG_MENU_TAGS" $index 1 )'" + echo "'$media_options'" + index=$(( $index + 1 )) + done + ) + )" + + local msg + if [ "$USE_XDIALOG" ]; then + msg=$( printf "$xmsg_supported_media_options" \ + "$interface" "$interface" ) + else + msg=$( printf "$msg_supported_media_options" \ + "$interface" "$interface" ) + fi + + local hline="$hline_arrows_tab_enter" + + 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 $SUCCESS ]; 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/usr.sbin/bsdconfig/networking/share/netmask.subr b/usr.sbin/bsdconfig/networking/share/netmask.subr new file mode 100644 index 000000000..845bf7e0c --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/netmask.subr @@ -0,0 +1,135 @@ +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="$( printf "$msg_current_subnet" \ + "$interface" "$_netmask" )" + f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" || + return $FAILURE + fi + + # + # Loop until the user provides taint-free input. + # + local msg="$( printf "$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 $FAILURE + + # Return success if NULL value was entered + [ "$_input" ] || return $SUCCESS + + # Take only the first "word" of the user's input + _netmask="$_input" + _netmask="${_netmask%%[$IFS]*}" + + # Taint-check the user's input + f_dialog_validate_netmask "$_netmask" && break + done + + netmask="$_netmask" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." networking/netmask.subr + +fi # ! $_NETWORKING_NETMASK_SUBR diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr new file mode 100644 index 000000000..ac281fc9b --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/resolv.subr @@ -0,0 +1,481 @@ +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 hostname="$1" + + # + # Extrapolate the desired domain search parameter for resolv.conf(5) + # + local search ndots domain="${hostname#*.}" + if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then + search="" + ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) ) + while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do + search="$search${search:+ }$domain" + domain="${domain#*.}" + ndots=$(( $ndots - 1 )) + done + domain="${hostname#*.}" + else + search="$domain" + fi + + # + # Save domain/search information only if different from resolv.conf(5) + # + if [ "$domain" != "$( f_resolv_conf_domain )" -o \ + "$search" != "$( f_resolv_conf_search )" ] + then + f_dialog_info "Saving new domain/search settings" \ + "to resolv.conf(5)..." + + # + # Create a new temporary file to write our resolv.conf(5) + # update with our new `domain' and `search' directives. + # + local tmpfile="$( mktemp -t "$pgm" )" + [ "$tmpfile" ] || return $FAILURE + + # + # Fixup permissions and ownership (mktemp(1) creates the + # temporary file with 0600 permissions -- change the + # permissions and ownership to match resolv.conf(5) before + # we write it out and mv(1) it into place). + # + local mode="$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )" + local owner="$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )" + f_quietly chmod "${mode:-0644}" "$tmpfile" + f_quietly chown "${owner:-root:wheel}" "$tmpfile" + + # + # Operate on resolv.conf(5), replacing only the last + # occurrences of `domain' and `search' directives (or add + # them to the top if not found), in strict-adherence to the + # following entry in resolver(5): + # + # The domain and search keywords are mutually exclusive. + # If more than one instance of these keywords is present, + # the last instance will override. + # + # NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the + # environment, all sub-domains will be added to the `search' + # directive, not just the FQDN. + # + local domain="${hostname#*.}" new_contents + [ "$domain" = "$hostname" ] && domain= + new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null ) + new_contents=$( echo "$new_contents" | awk \ + -v domain="$domain" \ + -v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \ + -v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \ + "$f_dialog_resolv_conf_update_awk" ) + + # + # Write the temporary file contents and move the temporary + # file into place. + # + echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE + f_quietly mv "$tmpfile" "$RESOLV_CONF" + + fi +} + +# f_dialog_input_nameserver [ $n $nameserver ] +# +# Allows the user to edit a given nameserver. The first argument is the +# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one +# if editing the first nameserver instance, two if editing the second, three if +# the third, ad nauseum. If this argument is zero, null, or missing, the value +# entered by the user (if non-null) will be added to resolv.conf(5) as a new +# `nameserver' entry. The second argument is the IPv4 address of the nameserver +# to be edited -- this will be displayed as the initial value during the edit. +# +# Taint-checking is performed when editing an existing entry (when the second +# argument is one or higher) in that the first argument must match the current +# value of the Nth `nameserver' instance in resolv.conf(5) else an error is +# generated discarding any/all changes. +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_dialog_input_nameserver_edit_awk=' +# Variables that should be defined on the invocation line: +# -v nsindex="1+" +# -v old_value="..." +# -v new_value="..." +# +BEGIN { + if ( nsindex < 1 ) exit 1 + found = n = 0 +} +{ + if ( found ) { print; next } + + if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) { + if ( ++n == nsindex ) { + if ( $2 != old_value ) exit 2 + if ( new_value != "" ) printf "%s%s\n", \ + substr($0, 0, RLENGTH), new_value + found = 1 + } + else print + } + else print +} +END { if ( ! found ) exit 3 } +' +f_dialog_input_nameserver() +{ + local index="${1:-0}" old_ns="$2" new_ns + local ns="$old_ns" + + # + # Perform sanity checks + # + f_isinteger "$index" || return $FAILURE + [ $index -ge 0 ] || return $FAILURE + + local msg + if [ $index -gt 0 ]; then + if [ "$USE_XDIALOG" ]; then + msg="$xmsg_please_enter_nameserver_existing" + else + msg="$msg_please_enter_nameserver_existing" + fi + else + msg="$msg_please_enter_nameserver" + fi + + # + # 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 $SUCCESS + elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then + if [ "$new_ns" ]; then + msg="$msg_saving_nameserver_existing" + else + msg="$msg_removing_nameserver" + fi + f_dialog_info "$msg" + + # + # Create a new temporary file to write our new resolv.conf(5) + # + local tmpfile="$( mktemp -t "$pgm" )" + [ "$tmpfile" ] || return $FAILURE + + # + # Quietly fixup permissions and ownership + # + local mode owner + mode=$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null ) + owner=$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null ) + f_quietly chmod "${mode:-0644}" "$tmpfile" + f_quietly chown "${owner:-root:wheel}" "$tmpfile" + + # + # Operate on resolv.conf(5) + # + local new_contents + new_contents=$( awk -v nsindex="$index" \ + -v old_value="$old_ns" \ + -v new_value="$new_ns" \ + "$f_dialog_input_nameserver_edit_awk" \ + "$RESOLV_CONF" ) + + # + # Produce an appropriate error message if necessary. + # + local retval=$? + case $retval in + 1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex" ;; + 2) f_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 $FAILURE + f_quietly mv "$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 )" + menu_list=$( + index=1 + + echo "'X $msg_exit' '$opt_exit'" + index=$(( $index + 1 )) + + echo "'A $msg_add' '$opt_add'" + index=$(( $index + 1 )) + + for ns in $nameservers; do + [ $index -lt ${#DIALOG_MENU_TAGS} ] || break + tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 ) + echo "'$tag nameserver' '$ns'" + index=$(( $index + 1 )) + done + ) + + # + # Display configuration-edit menu + # + 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 $SUCCESS ]; 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/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr new file mode 100644 index 000000000..3af9f36df --- /dev/null +++ b/usr.sbin/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/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() +{ + # + # Get the defaultrouter. When this is not configured, the default is + # "NO", however we don't ever want to present this default to the user + # in the following dialog. If the current value is "NO", then try to + # obtain the value from the running system using route(8). + # + # NOTE: Our `f_route_get_default' function will return NULL if the + # system does not have an active default router set (which is what we + # want). + # + local defaultrouter="$( f_sysrc_get 'defaultrouter:-NO' )" + local defaultrouter_orig="$defaultrouter" # for change-tracking + case "$defaultrouter" in + [Nn][Oo]) + defaultrouter=$( f_route_get_default ) + ;; + esac + + # + # Return with-error when there are NFS-mounts currently active. If the + # default router/gateway is changed while NFS-exported directories are + # mounted, the system will hang. + # + if f_nfs_mounted && ! f_jailed; then + local setting="$( printf "$msg_current_default_router" \ + "$defaultrouter" )" + f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" || + return $FAILURE + 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 $SUCCESS + [ $retval -eq $SUCCESS ] || return $retval + + # Taint-check the user's input + f_dialog_validate_ipaddr "$defaultrouter" && break + done + + # + # Save only if the user changed the default router/gateway. + # + if [ "$defaultrouter" != "$defaultrouter_orig" ]; then + f_dialog_info "$msg_saving_default_router" + + # Save the default router/gateway + f_sysrc_set defaultrouter "$defaultrouter" + fi + + # + # Only ask to apply setting if the current defaultrouter is different + # than the stored configuration (in rc.conf(5)). + # + if [ "$( f_route_get_default )" != "$defaultrouter" ]; then + f_dialog_clear + f_yesno "$msg_activate_default_router" \ + "$( f_route_get_default )" "$defaultrouter" + if [ $? -eq $SUCCESS ]; then + local err + + # Apply the default router/gateway + f_quietly route delete default + err=$( route add default "$defaultrouter" 2>&1 ) + if [ $? -ne $SUCCESS ]; then + f_dialog_msgbox "$err" + return $FAILURE + fi + fi + fi +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." networking/routing.subr + +fi # ! $_NETWORKING_ROUTING_SUBR diff --git a/usr.sbin/bsdconfig/networking/share/services.subr b/usr.sbin/bsdconfig/networking/share/services.subr new file mode 100644 index 000000000..b0cf95be6 --- /dev/null +++ b/usr.sbin/bsdconfig/networking/share/services.subr @@ -0,0 +1,54 @@ +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() +{ + f_package_add "pcnfsd" || return $? + f_sysrc_set mountd_flags "-n" + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." networking/services.subr + +fi # ! $_NETWORKING_SERVICES_SUBR diff --git a/usr.sbin/bsdconfig/packages/INDEX b/usr.sbin/bsdconfig/packages/INDEX new file mode 100644 index 000000000..80434779f --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/packages/Makefile b/usr.sbin/bsdconfig/packages/Makefile new file mode 100644 index 000000000..fd96757ff --- /dev/null +++ b/usr.sbin/bsdconfig/packages/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/030.packages +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= packages + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/packages/USAGE b/usr.sbin/bsdconfig/packages/USAGE new file mode 100644 index 000000000..5f99b3826 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/packages/include/Makefile b/usr.sbin/bsdconfig/packages/include/Makefile new file mode 100644 index 000000000..ed2a1f3ef --- /dev/null +++ b/usr.sbin/bsdconfig/packages/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/030.packages/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/packages/include/messages.subr b/usr.sbin/bsdconfig/packages/include/messages.subr new file mode 100755 index 000000000..8e945acc8 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/packages/packages b/usr.sbin/bsdconfig/packages/packages new file mode 100755 index 000000000..5b01c3e96 --- /dev/null +++ b/usr.sbin/bsdconfig/packages/packages @@ -0,0 +1,80 @@ +#!/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/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 +# +f_package_config + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/password/INDEX b/usr.sbin/bsdconfig/password/INDEX new file mode 100644 index 000000000..10f23db67 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/password/Makefile b/usr.sbin/bsdconfig/password/Makefile new file mode 100644 index 000000000..7330c318e --- /dev/null +++ b/usr.sbin/bsdconfig/password/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include share + +FILESDIR= ${LIBEXECDIR}/bsdconfig/040.password +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= password + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/password/USAGE b/usr.sbin/bsdconfig/password/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/password/include/Makefile b/usr.sbin/bsdconfig/password/include/Makefile new file mode 100644 index 000000000..27ad607ed --- /dev/null +++ b/usr.sbin/bsdconfig/password/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/040.password/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/password/include/messages.subr b/usr.sbin/bsdconfig/password/include/messages.subr new file mode 100644 index 000000000..655160de0 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/password/password b/usr.sbin/bsdconfig/password/password new file mode 100755 index 000000000..662a536af --- /dev/null +++ b/usr.sbin/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" + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# Default login of system manager +# +USER_ROOT=root + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 + err=$( echo "$pw_password" | pw usermod $USER_ROOT -h 0 2>&1 ) || + f_die $? "%s" "$err" + f_show_msg "$msg_password_changed" +fi + +return $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/password/share/Makefile b/usr.sbin/bsdconfig/password/share/Makefile new file mode 100644 index 000000000..ceba51074 --- /dev/null +++ b/usr.sbin/bsdconfig/password/share/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/bsdconfig/password +FILES= password.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/password/share/password.subr b/usr.sbin/bsdconfig/password/share/password.subr new file mode 100644 index 000000000..05db7f1d8 --- /dev/null +++ b/usr.sbin/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 $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." password/password.subr + +fi # ! $_PASSWORD_PASSWORD_SUBR diff --git a/usr.sbin/bsdconfig/security/INDEX b/usr.sbin/bsdconfig/security/INDEX new file mode 100644 index 000000000..9e7718690 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/security/Makefile b/usr.sbin/bsdconfig/security/Makefile new file mode 100644 index 000000000..c23097395 --- /dev/null +++ b/usr.sbin/bsdconfig/security/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/130.security +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= kern_securelevel security + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/security/USAGE b/usr.sbin/bsdconfig/security/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/security/include/Makefile b/usr.sbin/bsdconfig/security/include/Makefile new file mode 100644 index 000000000..a94c127d8 --- /dev/null +++ b/usr.sbin/bsdconfig/security/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/130.security/include +FILES= messages.subr securelevel.hlp + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/security/include/messages.subr b/usr.sbin/bsdconfig/security/include/messages.subr new file mode 100644 index 000000000..f6df66751 --- /dev/null +++ b/usr.sbin/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 affect only following a system reboot." +msg_network_secure="Network Secure" +msg_network_secure_mode="Network secure mode" +msg_nfs_port="NFS port" +msg_nfs_port_desc="Require that the NFS clients use reserved ports" +msg_ok="OK" +msg_secure="Secure" +msg_secure_mode="Secure mode" +msg_securelevel="Securelevel" +msg_securelevel_desc="Configure securelevels for the system" +msg_securelevels_menu_text="This menu allows you to select the securelevel your system runs with.\nWhen operating at a securelevel, certain root privileges are disabled,\nwhich may increase resistance to exploits and protect system integrity.\nIn secure mode system flags may not be overridden by the root user,\naccess to direct kernel memory is limited, and kernel modules may not\nbe changed. In highly secure mode, mounted file systems may not be\nmodified on-disk, tampering with the system clock is prohibited. In\nnetwork secure mode configuration changes to firewalling are prohibited.\n " +msg_securelevels_menu_title="Securelevel Configuration Menu" +msg_system_security_options_menu="System Security Options Menu" +msg_unknown_kern_securelevel_selection="Unknown kern.securelevel selection" +msg_unknown_security_menu_selection="Unknown security menu selection" diff --git a/usr.sbin/bsdconfig/security/include/securelevel.hlp b/usr.sbin/bsdconfig/security/include/securelevel.hlp new file mode 100644 index 000000000..27eb1ec23 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/security/kern_securelevel b/usr.sbin/bsdconfig/security/kern_securelevel new file mode 100755 index 000000000..fd1c91c98 --- /dev/null +++ b/usr.sbin/bsdconfig/security/kern_securelevel @@ -0,0 +1,169 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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 2 ]; then + # The Help button was pressed + f_show_help "$SECURELEVEL_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + f_die + fi + + break +done + +case "$mtag" in +"$msg_disabled") + f_sysrc_set kern_securelevel_enable "NO" + ;; +"$msg_secure") + f_sysrc_set kern_securelevel_enable "YES" + f_sysrc_set kern_securelevel "1" + ;; +"$msg_highly_secure") + f_sysrc_set kern_securelevel_enable "YES" + f_sysrc_set kern_securelevel "2" + ;; +"$msg_network_secure") + f_sysrc_set kern_securelevel_enable "YES" + f_sysrc_set kern_securelevel "3" + ;; +*) + f_die 1 "$msg_unknown_kern_securelevel_selection" +esac + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/security/security b/usr.sbin/bsdconfig/security/security new file mode 100755 index 000000000..ca19a26aa --- /dev/null +++ b/usr.sbin/bsdconfig/security/security @@ -0,0 +1,177 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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 0 ] && 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_sysrc_set nfs_reserved_port_only "NO" ;; + "3 [ ] $msg_nfs_port") # Same; Toggle value + f_sysrc_set nfs_reserved_port_only "YES" ;; + *) + f_die 1 "$msg_unknown_security_menu_selection" + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/share/Makefile b/usr.sbin/bsdconfig/share/Makefile new file mode 100644 index 000000000..3392e2ac5 --- /dev/null +++ b/usr.sbin/bsdconfig/share/Makefile @@ -0,0 +1,14 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= media packages + +FILESDIR= ${SHAREDIR}/bsdconfig +FILES= common.subr device.subr dialog.subr mustberoot.subr \ + script.subr strings.subr struct.subr sysrc.subr variable.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr new file mode 100644 index 000000000..6c0400ab1 --- /dev/null +++ b/usr.sbin/bsdconfig/share/common.subr @@ -0,0 +1,753 @@ +if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1 +# +# 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$ +# +############################################################ 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_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} + +# +# 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 $fmt [ $opts ... ] +# +# 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 + 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 persistant if set + # + [ "$debug" ] && export debug + [ "$debugFile" ] && export debugFile + + # + # Truncate the debug file upon. Note that we will trim a leading plus + # (`+') from the value of debugFile to support persistant 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" ]; then + if ( umask 022 && :> "$_debug_file" ); then + f_dprintf "Successfully initialized debugFile \`%s'" \ + "$_debug_file" + [ "${debug+set}" ] || + debug=1 # turn debugging on if not set + else + unset debugFile + f_dprintf "Unable to initialize debugFile \`%s'" \ + "$_debug_file" + fi + fi +} + +# f_err $fmt [ $opts ... ] +# +# Print a message to stderr (fd=2). +# +f_err() +{ + printf "$@" >&${TERMINAL_STDERR_PASSTHRU:-2} +} + +# f_quietly $command [ $arguments ... ] +# +# Run a command quietly (quell any output to stdout or stderr) +# +f_quietly() +{ + "$@" > /dev/null 2>&1 +} + +# f_have $anything ... +# +# A wrapper to the `type' built-in. Returns true if argument is a valid shell +# built-in, keyword, or externally-tracked binary, otherwise false. +# +f_have() +{ + f_quietly type "$@" +} + +# f_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_set:-value}=\"\${$__var_to_get}\" + eval [ \"\${$__var_to_get+set}\" ] + local __retval=$? + 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 [ $fmt [ $opts ... ]]] +# +# Abruptly terminate due to an error optionally displaying a message in a +# dialog box using printf(1) syntax. +# +f_die() +{ + local status=$FAILURE + + # If there is at least one argument, take it as the status + if [ $# -gt 0 ]; then + status=$1 + shift 1 # status + fi + + # If there are still arguments left, pass them to f_show_msg + [ $# -gt 0 ] && f_show_msg "$@" + + # Optionally call f_clean_up() function if it exists + f_have f_clean_up && f_clean_up + + exit $status +} + +# f_interrupt +# +# Interrupt handler. +# +f_interrupt() +{ + exec 2>&1 # fix sh(1) bug where stderr gets lost within async-trap + f_die +} + +# f_show_info $fmt [ $opts ... ] +# +# 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 $fmt [ $opts ... ] +# +# Display a message in a dialog box using printf(1) syntax. +# +f_show_msg() +{ + local msg + msg=$( printf "$@" ) + + # + # Use f_dialog_msgbox from dialog.subr if possible, otherwise fall + # back to dialog(1) (without options, making it obvious when using + # un-aided system dialog). + # + if f_have f_dialog_msgbox; then + f_dialog_msgbox "$msg" + else + dialog --msgbox "$msg" 0 0 + fi +} + + +# f_yesno $fmt [ $opts ... ] +# +# 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 $fmt [ $opts ... ] +# +# 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 bering printed to the screen. +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_usage_awk=' +BEGIN { found = 0 } +{ + if ( !found && $0 ~ /^[[:space:]]*($|#)/ ) next + found = 1 + print +} +' +f_usage() +{ + local file="$1" + local lang="${LANG:-$LC_ALL}" + + f_dprintf "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 +# +# 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. +# +# 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" + local lang="${LANG:-$LC_ALL}" + + f_dprintf "f_index_file: keyword=[%s] lang=[%s]" "$keyword" "$lang" + + if [ "$lang" ]; then + awk -v keyword="$keyword" "$f_index_file_awk" \ + $BSDCFG_LIBE${BSDCFG_LIBE:+/}*/INDEX.$lang && return + # No match, fall-thru to non-i18n sources + fi + awk -v keyword="$keyword" "$f_index_file_awk" \ + $BSDCFG_LIBE${BSDCFG_LIBE:+/}*/INDEX && return + + # No match? Fall-thru to `local' libexec sources (add-on modules) + + [ "$BSDCFG_LOCAL_LIBE" ] || return $FAILURE + if [ "$lang" ]; then + awk -v keyword="$keyword" "$f_index_file_awk" \ + $BSDCFG_LOCAL_LIBE/*/INDEX.$lang && return + # No match, fall-thru to non-i18n sources + fi + awk -v keyword="$keyword" "$f_index_file_awk" \ + $BSDCFG_LOCAL_LIBE/*/INDEX +} + +# f_index_menusel_keyword $indexfile $pgm +# +# 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. +# +# 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" + local lang="${LANG:-$LC_ALL}" + + f_dprintf "f_index_menusel_keyword: index=[%s] pgm=[%s] lang=[%s]" \ + "$indexfile" "$pgm" "$lang" + + if [ -f "$indexfile.$lang" ]; then + awk -v pgm="$pgm" \ + "$f_index_menusel_keyword_awk" \ + "$indexfile.$lang" + elif [ -f "$indexfile" ]; then + awk -v pgm="$pgm" \ + "$f_index_menusel_keyword_awk" \ + "$indexfile" + fi +} + +# f_index_menusel_command $indexfile $keyword +# +# 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. +# +# 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" command + local lang="${LANG:-$LC_ALL}" + + f_dprintf "f_index_menusel_command: index=[%s] key=[%s] lang=[%s]" \ + "$indexfile" "$keyword" "$lang" + + if [ -f "$indexfile.$lang" ]; then + command=$( awk -v key="$keyword" \ + "$f_index_menusel_command_awk" \ + "$indexfile.$lang" ) || return $FAILURE + elif [ -f "$indexfile" ]; then + command=$( awk -v key="$keyword" \ + "$f_index_menusel_command_awk" \ + "$indexfile" ) || return $FAILURE + else + return $FAILURE + fi + + # + # 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 + + echo "$command" +} + +# 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 +# +# Return success if a filesystem is mounted on a particular directory. +# +f_mounted() +{ + local dir="$1" + [ -d "$dir" ] || return $FAILURE + mount | grep -Eq " on $dir \([^)]+\)$" +} + +############################################################ MAIN + +# +# Trap signals so we can recover gracefully +# +trap 'f_interrupt' SIGINT +trap 'f_die' SIGTERM SIGPIPE SIGXCPU SIGXFSZ \ + SIGFPE SIGTRAP SIGABRT SIGSEGV +trap '' SIGALRM SIGPROF SIGUSR1 SIGUSR2 SIGHUP SIGVTALRM + +# +# 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/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr new file mode 100644 index 000000000..bbd3a104f --- /dev/null +++ b/usr.sbin/bsdconfig/share/device.subr @@ -0,0 +1,800 @@ +if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_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..." device.subr +f_include $BSDCFG_SHARE/dialog.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 + +DEVICES= +DEVICE_NAMES= + +# A "device" from sysinstall's point of view +f_struct_define DEVICE \ + name \ + desc \ + devname \ + type \ + enabled \ + init \ + get \ + shutdown \ + flags \ + private \ + volume + +# Network devices have their `private' property set to this +f_struct_define DEVICE_INFO \ + use_rtsol use_dhcp ipaddr ipv6addr netmask extras + +setvar DEVICE_TYPE_NONE 1 +setvar DEVICE_TYPE_DISK 2 +setvar DEVICE_TYPE_FLOPPY 3 +setvar DEVICE_TYPE_FTP 4 +setvar DEVICE_TYPE_NETWORK 5 +setvar DEVICE_TYPE_CDROM 6 +setvar DEVICE_TYPE_USB 7 +setvar DEVICE_TYPE_DOS 8 +setvar DEVICE_TYPE_UFS 9 +setvar DEVICE_TYPE_NFS 10 +setvar DEVICE_TYPE_ANY 11 +setvar DEVICE_TYPE_HTTP_PROXY 12 +setvar DEVICE_TYPE_HTTP 13 + +# +# Default behavior is to call f_device_get_all() automatically when loaded. +# +: ${DEVICE_SELF_SCAN_ALL=1} + +############################################################ FUNCTIONS + +# f_device_try $name [$i [$var_path]] +# +# Test a particular device. If $i is given, then $name is expected to contain a +# single "%d" where $i will be inserted using printf. If $var_path is given, +# it is used as a variable name to provide the caller the device pathname. +# +# Returns success if the device path exists and is a cdev. +# +f_device_try() +{ + local name="$1" i="$2" var_path="$3" unit + if [ "$i" ]; then + unit=$( printf "$name" "$i" ) + else + unit="$name" + fi + case "$unit" in + /dev/*) : good ;; # already qualified + *) unit="/dev/$unit" ;; + esac + [ "$var_path" ] && setvar "$var_path" "$unit" + f_dprintf "f_device_try: making sure %s is a device node" "$unit" + if [ -c "$unit" ]; then + f_dprintf "f_device_try: %s is a cdev [good]" "$unit" + return $SUCCESS + else + f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit" + return $FAILURE + fi +} + +# f_device_register $name $desc $devname $type $enabled $init_function \ +# $get_function $shutdown_function $private +# +# Register a device. A `structure' (see struct.subr) is created with the name +# device_$name (so make sure $name contains only alpha-numeric characters or +# the underscore, `_'). The remaining arguments after $name correspond to the +# properties of the `DEVICE' structure-type (defined above). +# +# If not already registered, the device is then appended to the DEVICES +# environment variable, a space-separated list of all registered devices. +# +f_device_register() +{ + local name="$1" desc="$2" devname="$3" type="$4" enabled="$5" + local init_func="$6" get_func="$7" shutdown_func="$8" private="$9" + + f_struct_new DEVICE "device_$name" || return $FAILURE + device_$name set name "$name" + device_$name set desc "$desc" + device_$name set devname "$devname" + device_$name set type "$type" + device_$name set enabled "$enabled" + device_$name set init "$init_func" + device_$name set get "$get_func" + device_$name set shutdown "$shutdown_func" + device_$name set private "$private" + + # Scan our global register to see if it needs ammending + local dev found= + for dev in $DEVICES; do + [ "$dev" = "$name" ] || continue + found=1 && break + done + [ "$found" ] || DEVICES="$DEVICES $name" + + return $SUCCESS +} + +# f_device_reset +# +# Reset the registered device chain. +# +f_device_reset() +{ + local dev + for dev in $DEVICES; do + f_device_shutdown $dev + + # + # 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. XXX + # + f_struct_free device_$dev + done + DEVICES= +} + +# f_device_get_all +# +# Get all device information for devices we have attached. +# +f_device_get_all() +{ + local devname desc + + 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 + 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 a network device named %s" "$devname" + f_device_register $devname \ + "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \ + f_media_init_network "" f_media_shutdown_network "" + done + + # Next, try to find all the types of devices one might use + # as a media source for content + # + + local dev desc type max n=0 + for dev in $DEVICE_NAMES; do + n=$(( $n + 1 )) + # Get the desc, type, and max (with debugging disabled) + # NOTE: Bypassing f_device_name_get() for efficiency + debug= f_getvar _device_desc$n desc + debug= f_getvar _device_type$n type + debug= f_getvar _device_max$n max + + local k=0 + while [ $k -lt ${max:-0} ]; do + i=$k k=$(( $k + 1 )) + devname="" + case "$type" in + $DEVICE_TYPE_CDROM) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" \ + "$devname" + ;; + $DEVICE_TYPE_FLOPPY) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_FLOPPY 1 \ + f_media_init_floppy \ + f_media_get_floppy \ + f_media_shutdown_floppy "" + f_dprintf "Found a floppy device for %s" \ + "$devname" + ;; + $DEVICE_TYPE_USB) + f_device_try "$dev" "$i" devname || continue + f_device_register "${devname##*/}" "$desc" \ + "$devname" $DEVICE_TYPE_USB 1 \ + f_media_init_usb f_media_get_usb \ + f_media_shutdown_usb "" + f_dprintf "Found a USB disk for %s" "$devname" + ;; + esac + done + done + + # Register ISO9660 providers as CDROM devices + for devname in /dev/iso9660/*; do + f_device_try "$devname" || continue + f_device_register "${devname##*/}" "ISO9660 file system" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" "$devname" + done + + # Scan for mdconfig(8)-created md(4) devices + local filename + for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do + f_device_try "$devname" || continue + + # See if the md(4) device is a vnode type backed by a file + filename=$( sysctl kern.geom.conftxt | + awk -v devname="${devname##*/}" \ + ' + ( $2 == "MD" ) && \ + ( $3 == devname ) && \ + ( $(NF-2) == "vnode" ) && \ + ( $(NF-1) == "file" ) \ + { + print $NF + } + ' ) + case "$filename" in + *.iso) # Register the device as an ISO9660 provider + f_device_register "${devname##*/}" \ + "md(4) vnode file system" \ + "$devname" $DEVICE_TYPE_CDROM 1 \ + f_media_init_cdrom f_media_get_cdrom \ + f_media_shutdown_cdrom "" + f_dprintf "Found a CDROM device for %s" "$devname" + ;; + esac + done + + # Finally go get the disks and look for partitions to register + local diskname slices index type rest slice part + for diskname in $( sysctl -n kern.disks ); do + + case "$diskname" in + cd*) + # XXX + # Due to unknown reasons, kern.disks returns SCSI + # CDROM as a valid disk. This will prevent bsdconfig + # from presenting SCSI CDROMs as available disks in + # various menus. Why GEOM treats SCSI CDROM as a disk + # is beyond me and that should be investigated. + # For temporary workaround, ignore SCSI CDROM device. + # + continue ;; + esac + + # Try to create a list of partitions and their types, + # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06"). + if ! slices=$( fdisk -p "$diskname" 2> /dev/null | + awk '( $1 == "p" ) { print $2","$3 }' ) + then + f_dprintf "Unable to open disk %s" "$diskname" + continue + fi + + f_device_register "$diskname" "" \ + "/dev/$diskname" $DEVICE_TYPE_DISK 0 + f_dprintf "Found a disk device named %s" "$diskname" + + # Look for existing partitions to register + for slice in $slices; do + index="${slice%%,*}" type="${slice#*,}" + slice=${diskname}s$index + case "$type" in + 0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef) + # DOS partitions to add as "DOS media devices" + f_device_register "$slice" "" \ + "/dev/$slice" $DEVICE_TYPE_DOS 1 \ + f_media_init_dos f_media_get_dos \ + f_media_shutdown_dos "" + f_dprintf "Found a DOS partition %s" "$slice" + ;; + 0xa5) # FreeBSD partition + for part in $( + bsdlabel -r $slice 2> /dev/null | + awk -v slice="$slice" ' + ( $1 ~ /[abdefgh]:/ ) { + printf "%s%s\n", + slice, + substr($1,1,1) + }' + ); do + f_quietly dumpfs -m /dev/$part || + continue + f_device_register \ + "$part" "" "/dev/$part" \ + $DEVICE_TYPE_UFS 1 \ + f_media_init_ufs \ + f_media_get_ufs \ + f_media_shutdown_ufs "" + f_dprintf "Found a UFS partition %s" \ + "$part" + done # parts + ;; + esac + done # slices + + done # disks +} + +# f_device_name_get $type $name type|desc|max [$var_to_set] +# +# Fetch the device type (type), description (desc), or maximum number of +# devices to scan for (max) associated with device $name and $type. 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 device 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_name_get() +{ + local __type="$1" __name="$2" __prop="$3" __var_to_set="$4" + local __dev __devtype __n=0 + + # Return failure if no $name or $prop is an unknown property + [ "$__name" ] || return $FAILURE + case "$__prop" in type|desc|max) : good ;; + *) return $FAILURE; esac + + [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type= + for __dev in $DEVICE_NAMES; do + __n=$(( $__n + 1 )) + [ "$__dev" = "$__name" ] || continue + f_getvar _device_type$__n __devtype + [ "${__type:-$__devtype}" = "$__devtype" ] || continue + f_getvar _device_$__prop$__n $__var_to_set + return $? + done + return $FAILURE +} + +# f_device_name_set $type $name $desc [$max] +# +# Store a description (desc) and [optionally] maximum number of devices to scan +# for (max) in-association with device $type and $name. Returns success unless +# $name is NULL or missing. Use the f_device_name_get() routine with the same +# $name and optionally $type to retrieve one of type, desc, or max properties. +# +f_device_name_set() +{ + local type="$1" name="$2" desc="$3" max="$4" + local dev devtype n=0 found= + [ "$name" ] || return $FAILURE + for dev in $DEVICE_NAMES; do + n=$(( $n + 1 )) + [ "$dev" = "$name" ] || continue + if f_getvar _device_type$n devtype; then + # Allow multiple entries with same name but diff type + [ "$devtype" = "$type" ] || continue + fi + found=1 && break + done + if [ ! "$found" ]; then + DEVICE_NAMES="$DEVICE_NAMES $name" + n=$(( $n + 1 )) + fi + setvar _device_type$n "$type" + setvar _device_desc$n "$desc" + [ "${4+set}" ] && setvar _device_max$n "$max" + 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 below static list. + # + 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 + + local __dev __devtype __n=0 + for __dev in $DEVICE_NAMES; do + __n=$(( $__n + 1 )) + debug= f_getvar _device_type$__n __devtype + [ "${__type:-$__devtype}" = "$__devtype" ] || continue + if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then + __devname=$( f_substr "$__name" 0 ${#__dev} ) + [ "$__devname" = "$__dev" ] || continue + else + __devname="${__name%%[0-9]*}" + __devunit="${__name#$__devname}" + __devunit="${__devunit%%[!0-9]*}" + __devname=$( printf "$__dev" $__devunit ) + [ "$__devname" = "$__name" ] || continue + fi + debug= f_getvar _device_desc$__n $__var_to_set + return $? + done + + # + # Sensible fall-backs for specific types + # + case "$__type" in + $DEVICE_TYPE_CDROM) __cp="" ;; + $DEVICE_TYPE_DISK) __cp="" ;; + $DEVICE_TYPE_FLOPPY) __cp="" ;; + $DEVICE_TYPE_USB) __cp="" ;; + $DEVICE_TYPE_NETWORK) __cp="" ;; + *) + __cp="" + esac + + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$__cp" + else + echo "$__cp" + fi + + return $FAILURE +} + +# f_device_rescan +# +# Rescan all devices, after closing previous set - convenience function. +# +f_device_rescan() +{ + f_device_reset + f_device_get_all +} + +# f_device_find $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 $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 __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3" + local __dev __devname __devtype __found= + for __dev in $DEVICES; do + device_$__dev get name __devname + device_$__dev get type __devtype + if [ "$__name" = "$__devname" -o ! "$__name" ] && + [ "$__type" = "$DEVICE_TYPE_ANY" -o \ + "$__type" = "$__devtype" ] + then + __found="$__found $__dev" + fi + done + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "${__found# }" + else + echo $__found + fi + [ "$__found" ] # Return status +} + +# f_device_init $name +# +# Initialize a device by evaluating its `init' function. +# +f_device_init() +{ + local name="$1" init_func + device_$name get init init_func || return + ${init_func:-:} $name +} + +# f_device_get $name $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). +# +f_device_get() +{ + local name="$1" file="$2" probe="$3" get_func + device_$name get get get_func || return + ${get_func:-:} $name "$file" ${3+"$probe"} +} + +# f_device_shutdown $name +# +# Shutdown a device by evaluating its `shutdown' function. +# +f_device_shutdown() +{ + local name="$1" shutdown_func + device_$name get shutdown shutdown_func || return + ${shutdown_func:-:} $name +} + +# 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 dev devtype devs= + for dev in $DEVICES; do + device_$dev get type devtype || continue + [ "$devtype" = "$type" ] || continue + devs="$devs $dev" + done + [ "$devs" ] || return $FAILURE + + local desc menu_list= + for dev in $devs; do + device_$dev get desc desc + f_shell_escape "$desc" desc + menu_list="$menu_list '$dev' '$desc'" + done + + 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\" \ + --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 2 ] && 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 0 ]; then + # Clean up the output of [X]dialog(1) and return it + f_dialog_data_sanitize mtag + echo "$mtag" >&2 + fi + + return $retval +} + +# +# Short-hand +# +f_cdrom() { f_device_name_set $DEVICE_TYPE_CDROM "$1" "$2" "$3"; } +f_disk() { f_device_name_set $DEVICE_TYPE_DISK "$1" "$2" "$3"; } +f_floppy() { f_device_name_set $DEVICE_TYPE_FLOPPY "$1" "$2" "$3"; } +f_serial() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3"; } +f_usb() { f_device_name_set $DEVICE_TYPE_USB "$1" "$2" "$3"; } +f_network() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2"; } + +############################################################ MAIN + +# CDROM, Disk, Floppy, Serial, and USB devices/names +f_cdrom "cd%d" "SCSI CDROM drive" 4 +f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive" 4 +f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type" 4 +f_disk "aacd%d" "Adaptec FSA RAID array" 4 +f_disk "ada%d" "ATA/SATA disk device" 16 +f_disk "amrd%d" "AMI MegaRAID drive" 4 +f_disk "da%d" "SCSI disk device" 16 +f_disk "idad%d" "Compaq RAID array" 4 +f_disk "ipsd%d" "IBM ServeRAID RAID array" 4 +f_disk "mfid%d" "LSI MegaRAID SAS array" 4 +f_disk "mlxd%d" "Mylex RAID disk" 4 +f_disk "twed%d" "3ware ATA RAID array" 4 +f_floppy "fd%d" "Floppy Drive unit A" 4 +f_serial "cuau%d" "%s on device %s (COM%d)" 16 +f_usb "da%da" "USB Mass Storage Device" 16 + +# Network interfaces/names +f_network "ae" "Attansic/Atheros L2 Fast Ethernet" +f_network "age" "Attansic/Atheros L1 Gigabit Ethernet" +f_network "alc" "Atheros AR8131/AR8132 PCIe Ethernet" +f_network "ale" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet" +f_network "an" "Aironet 4500/4800 802.11 wireless adapter" +f_network "ath" "Atheros IEEE 802.11 wireless adapter" +f_network "aue" "ADMtek USB Ethernet adapter" +f_network "axe" "ASIX Electronics USB Ethernet adapter" +f_network "bce" "Broadcom NetXtreme II Gigabit Ethernet card" +f_network "bfe" "Broadcom BCM440x PCI Ethernet card" +f_network "bge" "Broadcom BCM570x PCI Gigabit Ethernet card" +f_network "bm" "Apple BMAC Built-in Ethernet" +f_network "bwn" "Broadcom BCM43xx IEEE 802.11 wireless adapter" +f_network "cas" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet" +f_network "cc3i" "SDL HSSI sync serial PCI card" +f_network "cue" "CATC USB Ethernet adapter" +f_network "cxgb" "Chelsio T3 10Gb Ethernet card" +f_network "dc" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card" +f_network "de" "DEC DE435 PCI NIC or other DC21040-AA based card" +f_network "disc" "Software discard network interface" +f_network "ed" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA" +f_network "el" "3Com 3C501 Ethernet card" +f_network "em" "Intel(R) PRO/1000 Ethernet card" +f_network "en" "Efficient Networks ATM PCI card" +f_network "ep" "3Com 3C509 Ethernet card/3C589 PCMCIA" +f_network "et" "Agere ET1310 based PCI Express Gigabit Ethernet card" +f_network "ex" "Intel EtherExpress Pro/10 Ethernet card" +f_network "fe" "Fujitsu MB86960A/MB86965A Ethernet card" +f_network "fpa" "DEC DEFPA PCI FDDI card" +f_network "fwe" "FireWire Ethernet emulation" +f_network "fwip" "IP over FireWire" +f_network "fxp" "Intel EtherExpress Pro/100B PCI Fast Ethernet card" +f_network "gem" "Apple GMAC or Sun ERI/GEM Ethernet adapter" +f_network "hme" "Sun HME (Happy Meal Ethernet) Ethernet adapter" +f_network "ie" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210" +f_network "igb" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card" +f_network "ipw" "Intel PRO/Wireless 2100 IEEE 802.11 adapter" +f_network "iwi" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter" +f_network "iwn" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter" +f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card" +f_network "ixgb" "Intel(R) PRO/10Gb Ethernet card" +f_network "ix" "Intel Etherexpress Ethernet card" + # Maintain sequential order of above(3): ixgbe ixgb ix +f_network "jme" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet" +f_network "kue" "Kawasaki LSI USB Ethernet adapter" +f_network "le" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter" +f_network "lge" "Level 1 LXT1001 Gigabit Ethernet card" +f_network "lnc" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet" +f_network "lo" "Loop-back (local) network interface" +f_network "lp" "Parallel Port IP (PLIP) peer connection" +f_network "malo" "Marvell Libertas 88W8335 802.11 wireless adapter" +f_network "msk" "Marvell/SysKonnect Yukon II Gigabit Ethernet" +f_network "mxge" "Myricom Myri10GE 10Gb Ethernet card" +f_network "nfe" "NVIDIA nForce MCP Ethernet" +f_network "nge" "NatSemi PCI Gigabit Ethernet card" +f_network "ng" "Vimage netgraph(4) bridged Ethernet device" + # Maintain sequential order of above(2): nge ng +f_network "nve" "NVIDIA nForce MCP Ethernet" +f_network "nxge" "Neterion Xframe 10GbE Server/Storage adapter" +f_network "pcn" "AMD Am79c79x PCI Ethernet card" +f_network "plip" "Parallel Port IP (PLIP) peer connection" +f_network "ral" "Ralink Technology IEEE 802.11 wireless adapter" +f_network "ray" "Raytheon Raylink 802.11 wireless adapter" +f_network "re" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter" +f_network "rl" "RealTek 8129/8139 PCI Ethernet card" +f_network "rue" "RealTek USB Ethernet card" +f_network "rum" "Ralink Technology USB IEEE 802.11 wireless adapter" +f_network "sf" "Adaptec AIC-6915 PCI Ethernet card" +f_network "sge" "Silicon Integrated Systems SiS190/191 Ethernet" +f_network "sis" "SiS 900/SiS 7016 PCI Ethernet card" +f_network "sk" "SysKonnect PCI Gigabit Ethernet card" +f_network "snc" "SONIC Ethernet card" +f_network "sn" "SMC/Megahertz Ethernet card" + # Maintain sequential order of above(2): snc sn +f_network "sr" "SDL T1/E1 sync serial PCI card" +f_network "ste" "Sundance ST201 PCI Ethernet card" +f_network "stge" "Sundance/Tamarack TC9021 Gigabit Ethernet" +f_network "ti" "Alteon Networks PCI Gigabit Ethernet card" +f_network "tl" "Texas Instruments ThunderLAN PCI Ethernet card" +f_network "txp" "3Com 3cR990 Ethernet card" +f_network "tx" "SMC 9432TX Ethernet card" + # Maintain sequential order of above(2): txp tx +f_network "uath" "Atheros AR5005UG and AR5005UX USB wireless adapter" +f_network "upgt" "Conexant/Intersil PrismGT USB wireless adapter" +f_network "ural" "Ralink Technology RT2500USB 802.11 wireless adapter" +f_network "urtw" "Realtek 8187L USB wireless adapter" +f_network "vge" "VIA VT612x PCI Gigabit Ethernet card" +f_network "vlan" "IEEE 802.1Q VLAN network interface" +f_network "vr" "VIA VT3043/VT86C100A Rhine PCI Ethernet card" +f_network "vx" "3COM 3c590 / 3c595 Ethernet card" +f_network "wb" "Winbond W89C840F PCI Ethernet card" +f_network "wi" "Lucent WaveLAN/IEEE 802.11 wireless adapter" +f_network "wpi" "Intel 3945ABG IEEE 802.11 wireless adapter" +f_network "wx" "Intel Gigabit Ethernet (82452) card" +f_network "xe" "Xircom/Intel EtherExpress Pro100/16 Ethernet card" +f_network "xl" "3COM 3c90x / 3c90xB PCI Ethernet card" +f_network "zyd" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter" + +f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \ + "$( set -- $DEVICE_NAMES; echo $# )" + +# +# 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/usr.sbin/bsdconfig/share/dialog.subr b/usr.sbin/bsdconfig/share/dialog.subr new file mode 100644 index 000000000..cbf80fce9 --- /dev/null +++ b/usr.sbin/bsdconfig/share/dialog.subr @@ -0,0 +1,2145 @@ +if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_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..." 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 + +# +# 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 accomodate them. +# +# These values are helpful when manually sizing with dialog(1) too, but in a +# different way. dialog(1) does not make you accomodate 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 __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 + __max_size=$( stty size 2> /dev/null ) # usually "24 80" + : ${__max_size:=$DEFAULT_TERMINAL_SIZE} + fi + [ "$__var_height" ] && setvar "$__var_height" "${__max_size%%[$IFS]*}" + [ "$__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 + f_quietly f_getvar "$__var_height" + 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 __width __rows + 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; 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 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 -lt ${__min_height:-0} ]; then + setvar "$__var_height" $__min_height + elif [ $__height -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 -lt $__min_width ]; then + setvar "$__var_width" $__min_width + elif [ $__width -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=$(( $__max_height_menu_constrain - 8 )) + # 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=$(( $__max_rows + 1 )) + + if [ $__rows -lt $__min_rows ]; then + setvar "$__var_rows" $__min_rows + elif [ $__rows -gt $__max_rows ]; then + setvar "$__var_rows" $__max_rows + fi + fi + + if [ "$debug" ]; then + # Print final constrained values to debuggin + f_quietly f_getvar "$__var_height" + f_quietly f_getvar "$__var_width" + 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} + 10 )) + [ $__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 accomodate 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=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=$(( $__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_rlist_size=$(( + $__height_rlist_size + $__rows + 7 )) + else + __height_rlist_size=$(( + $__height_rlist_size + $__rows + 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 + + # 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 __rows=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=$(( $__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_rlist_with_help_size=$(( + $__height_rlist_with_help_size + $__rows + 7 )) + else + __height_rlist_with_help_size=$(( + $__height_rlist_with_help_size + $__rows + 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 + + # 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 accomodate 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. +# +f_xdialog_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" \ + --no-close --no-buttons \ + --infobox "$info_text" $height $width \ + -1 # timeout of -1 means abort when EOF on stdin +} + +############################################################ 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 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 +} + +############################################################ INIT FUNCTIONS + +# f_dialog_init +# +# Initialize (or re-initialize) the dialog module after setting/changing any +# of the following environment variables: +# +# USE_XDIALOG Either NULL or Non-NULL. If given a value will indicate +# that Xdialog(1) should be used instead of dialog(1). +# +# SECURE Either NULL or Non-NULL. If given a value will indicate +# that (while running as root) sudo(8) authentication is +# required to proceed. +# +f_dialog_init() +{ + DIALOG_SELF_INITIALIZE= + + # + # 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 + # + f_dprintf "f_dialog_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \ + "$ARGV" "$GETOPTS_STDARGS" + SECURE=$( set -- $ARGV + while getopts \ + "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \ + flag > /dev/null; do + case "$flag" in + S) echo 1 ;; + esac + done + ) + USE_XDIALOG=$( set -- $ARGV + while getopts \ + "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" \ + flag > /dev/null; do + case "$flag" in + S|X) echo 1 ;; + esac + done + ) + f_dprintf "f_dialog_init: SECURE=[%s] USE_XDIALOG=[%s]" \ + "$SECURE" "$USE_XDIALOG" + + # + # Process `-X' command-line option + # + [ "$USE_XDIALOG" ] && DIALOG=Xdialog + + # + # 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 + + # + # 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 ! maxsize=$( LANG= LC_ALL= $DIALOG --print-maxsize 2>&1 ) + 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/usr.sbin/bsdconfig/share/media/Makefile b/usr.sbin/bsdconfig/share/media/Makefile new file mode 100644 index 000000000..643674921 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +NO_OBJ= + +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 + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/share/media/any.subr b/usr.sbin/bsdconfig/share/media/any.subr new file mode 100644 index 000000000..367571338 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/any.subr @@ -0,0 +1,150 @@ +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 2 ]; then + # The Help button was pressed + f_show_help "$MEDIA_HELPFILE" + continue + elif [ $retval -ne 0 ]; 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/usr.sbin/bsdconfig/share/media/cdrom.subr b/usr.sbin/bsdconfig/share/media/cdrom.subr new file mode 100644 index 000000000..8ed3e960e --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/cdrom.subr @@ -0,0 +1,210 @@ +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 + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_interactive && f_show_msg "$msg_no_cd_dvd_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_cd_dvd_type" + local prompt="$msg_please_select_a_cd_dvd_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_CDROM \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_CDROM devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs 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 dev="$1" devname err + + device_$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" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount_cd9660 "$devname" "$MOUNTPOINT" 2>&1 ) + 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_only] +# +# Returns data from $file on a mounted CDROM device. Similar to cat(1). If +# $probe_only is present and non-NULL, returns success if $file exists. +# +f_media_get_cdrom() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_cdrom: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" "$probe_only" +} + +# f_media_shutdown_cdrom $device +# +# Shuts down the CDROM device and ejects the media using f_media_eject_cdrom(), +# below. Return status should be ignored. +# +f_media_shutdown_cdrom() +{ + local dev="$1" err + + [ "$CDROM_MOUNTED" ] || return + + if [ "$CDROM_PREVIOUSLY_MOUNTED" ]; then + CDROM_MOUNTED= + return $SUCCESS + fi + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); 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 "$dev" +} + +# f_media_eject_cdrom $device +# +# Eject the media from the CDROM device. Returns success. +# +f_media_eject_cdrom() +{ + local dev="$1" devname err + device_$dev get name devname || return $SUCCESS + case "$devname" in /dev/iso9660/*) return $SUCCESS; esac + f_dprintf "Ejecting CDROM/DVD at %s" "$devname" + if ! err=$( cdcontrol -f "$devname" eject 2>&1 ); 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/usr.sbin/bsdconfig/share/media/common.subr b/usr.sbin/bsdconfig/share/media/common.subr new file mode 100644 index 000000000..32ad53259 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/common.subr @@ -0,0 +1,129 @@ +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 + +############################################################ 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 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 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_only] +# +# A generic open which follows a well-known "path" of places to look. If +# $probe_only is present and non-NULL, returns success if $file exists. +# +f_media_generic_get() +{ + local base="$1" file="$2" probe_only="$3" + + local fname=f_media_generic_get + f_dprintf "%s: base=[%s] files=[%s] probe_only=%s" \ + $fname "$base" "$file" "$probe_only" + + 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" + [ "$probe_only" ] && 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" + [ "$probe_only" ] && return $SUCCESS + elif [ "$probe_only" ]; then + 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/usr.sbin/bsdconfig/share/media/directory.subr b/usr.sbin/bsdconfig/share/media/directory.subr new file mode 100644 index 000000000..3efa991a9 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/directory.subr @@ -0,0 +1,148 @@ +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 + + device_$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_only] +# +# Returns data from $file in the existing/current filesystem. Similar to +# cat(1). If $probe_only is present and non-NULL, returns success if $file +# exists. +# +f_media_get_directory() +{ + local dev="$1" file="$2" probe_only="$3" path + + f_dprintf "f_media_get_directory: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + device_$dev get private path + f_media_generic_get "$path" "$file" "$probe_only" +} + +# 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/usr.sbin/bsdconfig/share/media/dos.subr b/usr.sbin/bsdconfig/share/media/dos.subr new file mode 100644 index 000000000..068ef5986 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/dos.subr @@ -0,0 +1,164 @@ +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 + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_show_msg "$msg_no_dos_primary_partitions_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_dos_partition" + local prompt="$msg_please_select_dos_partition" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_DOS \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_DOS devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs 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 dev="$1" devname err + + device_$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" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount_msdosfs "$devname" "$MOUNTPOINT" 2>&1 ) + 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_only] +# +# Returns data from $file on a mounted DOS partition device. Similar to cat(1). +# If $probe_only is present and non-NULL, returns success if $file exists. +# +f_media_get_dos() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_dos: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" "$probe_only" +} + +# f_media_shutdown_dos $device +# +# Shuts down the DOS partition device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_dos() +{ + local dev="$1" err + + [ "$DOS_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); 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/usr.sbin/bsdconfig/share/media/floppy.subr b/usr.sbin/bsdconfig/share/media/floppy.subr new file mode 100644 index 000000000..ac059377e --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/floppy.subr @@ -0,0 +1,216 @@ +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 + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_interactive && f_show_msg "$msg_no_floppy_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_floppy_drive" + local prompt="$msg_please_select_a_floppy_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_FLOPPY \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_FLOPPY devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs 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 dev="$1" devname err + + device_$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 + device_$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 + device_$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_quietly mount_msdosfs -o ro -m 0777 -u 0 -g 0 "$devname" "$mp" || + err=$( mount -o ro "$devname" "$mp" 2>&1 ) + }; then + err="${err#mount: }"; err="${err#*: }" + local name + device_$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_only] +# +# Returns data from $file on a mounted Floppy disk device. Similar to cat(1). +# If $probe_only is present and non-null, limits retries to zero. +# +f_media_get_floppy() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_floppy: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + # + # 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 + device_$dev get private mp + local fp="${mp:=$MOUNTPOINT}/$file" + if ! [ -f "$fp" -a -r "$fp" ]; then + local nretries=4 + [ "$probe_only" ] && return $FAILURE + while ! [ -f "$fp" -a -r "$fp" ]; do + if [ $nretries -eq 0 ]; then + f_show_msg "$msg_failed_to_get_floppy_file" \ + "$fp" + return $FAILURE + fi + FLOPPY_DISTWANTED="$fp" + f_media_shutdown_floppy "$dev" + f_media_init_floppy "$dev" || return $FAILURE + nretries=$(( $nretries - 1 )) + done + elif [ "$probe_only" ]; then + return $SUCCESS + fi + 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 dev="$1" err mp + + [ "$FLOPPY_MOUNTED" ] || return + + device_$dev get private mp + if ! err=$( umount -f "${mp:=$MOUNTPOINT}" 2>&1 ); then + err="${err#umount: }"; err="${err#*:}" + f_dprintf "Umount of floppy on %s failed: %s" "$mp" "$err" + else + FLOPPY_MOUNTED= + if f_interactive && [ "$_systemState" != "fixit" ]; then + local desc + device_$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/usr.sbin/bsdconfig/share/media/ftp.subr b/usr.sbin/bsdconfig/share/media/ftp.subr new file mode 100644 index 000000000..ac46a27e2 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/ftp.subr @@ -0,0 +1,938 @@ +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' + '$msg_snapshots_server_japan' + 'snapshots.jp.freebsd.org' + '$msg_snapshots_server_sweden' + 'snapshots.se.freebsd.org' + 'IPv6 $msg_main_site' 'ftp.freebsd.org' + ' IPv6 $msg_ireland' 'ftp3.ie.freebsd.org' + ' IPv6 $msg_israel' 'ftp.il.freebsd.org' + ' IPv6 $msg_japan' 'ftp2.jp.freebsd.org' + ' IPv6 $msg_usa' 'ftp4.us.freebsd.org' + ' IPv6 $msg_turkey' 'ftp2.tr.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 #8' 'ftp8.freebsd.org' + ' $msg_primary #9' 'ftp9.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_argentina' 'ftp.ar.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_austria #2' 'ftp2.at.freebsd.org' + '$msg_brazil' 'ftp.br.freebsd.org' + ' $msg_brazil #2' 'ftp2.br.freebsd.org' + ' $msg_brazil #3' 'ftp3.br.freebsd.org' + ' $msg_brazil #4' 'ftp4.br.freebsd.org' + ' $msg_brazil #5' 'ftp5.br.freebsd.org' + ' $msg_brazil #6' 'ftp6.br.freebsd.org' + ' $msg_brazil #7' 'ftp7.br.freebsd.org' + '$msg_canada' 'ftp.ca.freebsd.org' + '$msg_china' 'ftp.cn.freebsd.org' + ' $msg_china #2' 'ftp2.cn.freebsd.org' + '$msg_croatia' 'ftp.hr.freebsd.org' + '$msg_czech_republic' 'ftp.cz.freebsd.org' + '$msg_denmark' 'ftp.dk.freebsd.org' + ' $msg_denmark #2' 'ftp2.dk.freebsd.org' + '$msg_estonia' 'ftp.ee.freebsd.org' + '$msg_finland' 'ftp.fi.freebsd.org' + '$msg_france' 'ftp.fr.freebsd.org' + ' $msg_france #2' 'ftp2.fr.freebsd.org' + ' $msg_france #3' 'ftp3.fr.freebsd.org' + ' $msg_france #5' 'ftp5.fr.freebsd.org' + ' $msg_france #6' 'ftp6.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 #3' 'ftp3.de.freebsd.org' + ' $msg_germany #4' 'ftp4.de.freebsd.org' + ' $msg_germany #5' 'ftp5.de.freebsd.org' + ' $msg_germany #6' 'ftp6.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_hungary' 'ftp.hu.freebsd.org' + '$msg_iceland' 'ftp.is.freebsd.org' + '$msg_ireland' 'ftp.ie.freebsd.org' + ' $msg_ireland #2' 'ftp2.ie.freebsd.org' + ' $msg_ireland #3' 'ftp3.ie.freebsd.org' + '$msg_israel' 'ftp.il.freebsd.org' + '$msg_italy' 'ftp.it.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_lithuania' 'ftp.lt.freebsd.org' + '$msg_netherlands' 'ftp.nl.freebsd.org' + ' $msg_netherlands #2' 'ftp2.nl.freebsd.org' + '$msg_norway' 'ftp.no.freebsd.org' + ' $msg_norway #3' 'ftp3.no.freebsd.org' + '$msg_poland' 'ftp.pl.freebsd.org' + ' $msg_poland #2' 'ftp2.pl.freebsd.org' + ' $msg_poland #5' 'ftp5.pl.freebsd.org' + '$msg_portugal' 'ftp.pt.freebsd.org' + ' $msg_portugal #2' 'ftp2.pt.freebsd.org' + ' $msg_portugal #4' 'ftp4.pt.freebsd.org' + '$msg_romania' 'ftp.ro.freebsd.org' + '$msg_russia' 'ftp.ru.freebsd.org' + ' $msg_russia #2' 'ftp2.ru.freebsd.org' + ' $msg_russia #3' 'ftp3.ru.freebsd.org' + ' $msg_russia #4' 'ftp4.ru.freebsd.org' + '$msg_singapore' 'ftp.sg.freebsd.org' + '$msg_slovak_republic' 'ftp.sk.freebsd.org' + '$msg_slovenia' 'ftp.si.freebsd.org' + ' $msg_slovenia #2' 'ftp2.si.freebsd.org' + '$msg_south_africa' 'ftp.za.freebsd.org' + ' $msg_south_africa #2' 'ftp2.za.freebsd.org' + ' $msg_south_africa #3' 'ftp3.za.freebsd.org' + ' $msg_south_africa #4' 'ftp4.za.freebsd.org' + '$msg_spain' 'ftp.es.freebsd.org' + ' $msg_spain #2' 'ftp2.es.freebsd.org' + ' $msg_spain #3' 'ftp3.es.freebsd.org' + '$msg_sweden' 'ftp.se.freebsd.org' + ' $msg_sweden #2' 'ftp2.se.freebsd.org' + ' $msg_sweden #3' 'ftp3.se.freebsd.org' + ' $msg_sweden #4' 'ftp4.se.freebsd.org' + ' $msg_sweden #5' 'ftp5.se.freebsd.org' + '$msg_switzerland' 'ftp.ch.freebsd.org' + ' $msg_switzerland #2' 'ftp2.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_turkey' 'ftp.tr.freebsd.org' + ' $msg_turkey #2' 'ftp2.tr.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_uk #6' 'ftp6.uk.freebsd.org' + '$msg_ukraine' 'ftp.ua.freebsd.org' + ' $msg_ukraine #2' 'ftp2.ua.freebsd.org' + ' $msg_ukraine #5' 'ftp5.ua.freebsd.org' + ' $msg_ukraine #6' 'ftp6.ua.freebsd.org' + ' $msg_ukraine #7' 'ftp7.ua.freebsd.org' + ' $msg_ukraine #8' 'ftp8.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 #7' 'ftp7.us.freebsd.org' + ' $msg_usa #8' 'ftp8.us.freebsd.org' + ' $msg_usa #9' 'ftp9.us.freebsd.org' + ' $msg_usa #10' 'ftp10.us.freebsd.org' + ' $msg_usa #11' 'ftp11.us.freebsd.org' + ' $msg_usa #12' 'ftp12.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 $FAILURE + 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 $SUCCESS +} + +# 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 network + if ! f_device_select_tcp; then + unset $VAR_FTP_PATH + return $FAILURE + fi + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + if ! f_device_init 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 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 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 device_$dev || return $FAILURE + device_$dev get private netDev || return $SUCCESS # No net == happy net + 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 device_$dev || return $FAILURE + device_$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 + device_$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 ' + BEGIN { found = 0 } + /^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 $SUCCESS ]; 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_only] +# +# 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_only is present and non-NULL, +# returns success if $file exists. +# +# 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 dev="$1" file="$2" probe_only="$3" hosts= + + f_dprintf "f_media_get_ftp: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + 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_only" ]; then + local url="ftp://$userpass$host$port/$dir/$file" + [ "$use_anon" ] && url="ftp://$host$port/$dir/$file" + if ! size=$( fetch -s "$url" 2>&1 ) || ! f_isinteger "$size" + then + f_dprintf "request failed! size response=[%s]" "$size" + return $FAILURE + fi + 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/usr.sbin/bsdconfig/share/media/http.subr b/usr.sbin/bsdconfig/share/media/http.subr new file mode 100644 index 000000000..a904d013b --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/http.subr @@ -0,0 +1,635 @@ +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=" + '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 $FAILURE + 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 $SUCCESS +} + +# 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 network + if ! f_device_select_tcp; then + unset $VAR_HTTP_PATH + return $FAILURE + fi + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + if ! f_device_init 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 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 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 + 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" + + # + # 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) + setvar $VAR_HTTP_PATH "$VAR_HTTP_DIR" + 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 + 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 + esac + + [ $http_found -eq $SUCCESS ] && break + + f_getvar $VAR_HTTP_PATH http_path + f_show_msg "$msg_please_check_the_url_and_try_again" \ + "$http_path" + + unset $VAR_HTTP_PATH + f_media_set_http || break + done + + return $http_found +} + +# f_media_get_http $device $file [$probe_only] +# +# 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_only 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). +# +# 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_only="$3" hosts= + + f_dprintf "f_media_get_http: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + 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_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 + local url="/$http_path/$file" rx + + f_dprintf "sending http request for: %s" "$url" + 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 + while read LINE; do + case "$LINE" in + HTTP*) + f_dprintf "received response: %s" "$LINE" + set -- $LINE; rv=$2 + f_isinteger "$rv" || rv=0 + ;; + *) + [ "${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_only" ]; then + cat # output the rest ``as-is'' + fi + exit 200 + ) + local retval=$? + [ $retval -eq 200 ] && return $SUCCESS + [ "$probe_only" ] && 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 + return $FAILURE +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/http.subr + +fi # ! $_MEDIA_HTTP_SUBR diff --git a/usr.sbin/bsdconfig/share/media/httpproxy.subr b/usr.sbin/bsdconfig/share/media/httpproxy.subr new file mode 100644 index 000000000..817cf0db5 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/httpproxy.subr @@ -0,0 +1,452 @@ +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_only] +# +# 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_only 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). +# +# 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_only="$3" hosts= + + f_dprintf "f_media_get_http_proxy: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + 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 + while read LINE; do + case "$LINE" in + HTTP*) + f_dprintf "received response: %s" "$LINE" + set -- $LINE; rv=$2 + f_isinteger "$rv" || rv=0 + ;; + *) + [ "${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_only" ]; then + cat # output the rest ``as-is'' + fi + exit 200 + ) + local retval=$? + [ $retval -eq 200 ] && return $SUCCESS + [ "$probe_only" ] && 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 + return $FAILURE +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/httpproxy.subr + +fi # ! $_MEDIA_HTTPPROXY_SUBR diff --git a/usr.sbin/bsdconfig/share/media/network.subr b/usr.sbin/bsdconfig/share/media/network.subr new file mode 100644 index 000000000..6e1720034 --- /dev/null +++ b/usr.sbin/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 manaully): +# +# 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/usr.sbin/bsdconfig/share/media/nfs.subr b/usr.sbin/bsdconfig/share/media/nfs.subr new file mode 100644 index 000000000..93089cb7c --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/nfs.subr @@ -0,0 +1,250 @@ +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 network + f_device_select_tcp || return $FAILURE + local dev + f_getvar $VAR_NETWORK_DEVICE dev + f_struct_copy "device_$dev" device_network + fi + f_device_init 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 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 dev="$1" name err + + device_$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 network; then + f_dprintf "f_media_init_nfs: %s" "$msg_net_device_init_failed" + return $FAILURE + fi + + if [ ! -e "$MOUNTPOINT" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + 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 ! err=$( mount_nfs \ + ${secure:+-P} -o "$options" "$name" "$MOUNTPOINT" 2>&1 ) + then + err="${err#mount_nfs: }" + f_show_msg "$msg_error_mounting_device" \ + "$name" "$MOUNTPOINT" "$err" + f_struct device_network && + f_device_shutdown 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_only] +# +# Returns data from $file on a mounted NFS device. Similar to cat(1). If +# $probe_only is present and non-NULL, returns success if $file exists. +# +f_media_get_nfs() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_nfs: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" "$probe_only" +} + +# f_media_shutdown_nfs $device +# +# Shuts down the NFS device using umount(8). Return status should be ignored. +# +f_media_shutdown_nfs() +{ + local dev="$1" err + + [ "$NFS_MOUNTED" ] || return + + f_dprintf "Unmounting NFS partition on %s" "$MOUNTPOINT" + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); 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/usr.sbin/bsdconfig/share/media/options.subr b/usr.sbin/bsdconfig/share/media/options.subr new file mode 100644 index 000000000..3f71a96a8 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/options.subr @@ -0,0 +1,328 @@ +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 2 ]; then + # The Help button was pressed + f_show_help "$OPTIONS_HELPFILE" + continue + elif [ $retval -ne 0 ]; 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/usr.sbin/bsdconfig/share/media/tcpip.subr b/usr.sbin/bsdconfig/share/media/tcpip.subr new file mode 100644 index 000000000..6b4791edc --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/tcpip.subr @@ -0,0 +1,1685 @@ +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/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. +# +# f_dialog_validate_hostname $hostname +# +# If the hostname is determined to be invalid, the appropriate error will be +# displayed using the f_show_msg function. +# +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 + __num=$( IFS=.; set -- $__addr; \ + echo $(( ($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" + local 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 $SUCCESS + fi + + return $FAILURE +} + +# 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 + __netmask="$__netmask.$( printf "%u" "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="" __wait="" + f_getvar $VAR_MEDIA_TIMEOUT __wait + [ "$__wait" ] && __wait="-W $(( $__wait / 2 ))" + f_getvar $VAR_IPV6_ENABLE __ip6 + 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 + __addrs=$( echo "$__output" | awk '/ address /{print $NF}' ) + fi + 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 successfull 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" cp n + local use_dhcp="" use_rtsol="" + local _ipaddr _netmask _extras + + [ "$dev" ] || return $FAILURE + + # Initialize vars from previous device values + local private + device_$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 $dev 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 $dev; then + i=$( sysctl -n net.inet6.ip6.dad_count ) + sleep $(( $i + 1 )) + f_rtsol_get_info $dev + 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 $dev 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 $dev | + f_xdialog_info "$msg" + else + f_dialog_info "$msg" + f_quietly dhclient $dev + fi + ) + local retval=$? + trap 'f_interrupt' SIGINT + if [ $retval -eq $SUCCESS ]; then + f_dhcp_get_info $dev + 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 ${dev}_$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 ${dev}_$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 ${dev}_$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 $dev _ipaddr + [ "$_netmask" ] || f_ifconfig_netmask $dev _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 + [ "${dev#plip}" != "$dev" ] && + 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 $dev" + 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 $FAILURE + 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 2 ]; then + # The Help button was pressed + f_show_help "$TCP_HELPFILE" + continue + elif [ $retval -ne 0 ]; then + # User chose "Cancel" or pressed ESC + f_dialog_title_restore + return $FAILURE + 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 + device_$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$dev "$cp" + fi + [ "$use_rtsol" ] && + setvar $VAR_IPV6_ENABLE "YES" + + [ "$use_dhcp" ] || + f_config_resolv # XXX this will do it on the MFS copy + + return $SUCCESS +} + +# 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 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 + *,*) dev="${network_dev%%,*}" + network_dev="${network_dev#*,}" + ;; + *) dev="$network_dev" + network_dev= + esac + + f_device_find "$dev" $DEVICE_TYPE_NETWORK devs + cnt=$( set -- $devs; echo $# ) + + if [ ${cnt:=0} -gt 0 ]; then + dev="${devs%%[$IFS]*}" + f_device_dialog_tcp $dev + if [ $? -eq $SUCCESS ]; then + setvar $VAR_NETWORK_DEVICE $dev + return $SUCCESS + fi + fi + done + + f_interactive && f_show_msg "$msg_no_network_devices" + return $FAILURE + + fi # $network_dev + + f_device_find "" $DEVICE_TYPE_NETWORK devs + cnt=$( set -- $devs; echo $# ) + dev="${devs%%[$IFS]*}" + + 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 $dev + return $SUCCESS + fi + fi + + local retval=$SUCCESS + if [ ${cnt:=0} -eq 0 ]; then + f_show_msg "$msg_no_network_devices" + retval=$FAILURE + elif [ $cnt -eq 1 ]; then + f_device_dialog_tcp $dev + retval=$? + [ $retval -eq $SUCCESS ] && setvar $VAR_NETWORK_DEVICE $dev + 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 ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_NETWORK devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_device_dialog_tcp $dev + retval=$? + if [ $retval -eq $SUCCESS ]; then + f_struct_copy device_$dev device_network + setvar $VAR_NETWORK_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 network; then + f_show_msg "$msg_initialization_of_device_failed" \ + "$name" + fi + fi + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." media/tcpip.subr + +fi # ! $_MEDIA_TCPIP_SUBR diff --git a/usr.sbin/bsdconfig/share/media/ufs.subr b/usr.sbin/bsdconfig/share/media/ufs.subr new file mode 100644 index 000000000..63094c1a6 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/ufs.subr @@ -0,0 +1,193 @@ +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 + ndevs=$( set -- $devs; echo $# ) + + 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 -gt 1 ]; then + local title="$msg_choose_a_ufs_partition" + local prompt="$msg_please_select_ufs_partition" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_UFS \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs 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 dev="$1" devname err + + device_$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" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if ! err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ) + 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_only] +# +# Returns data from $file on a mounted UFS partition device. Similar to cat(1). +# If $probe_only is present and non-NULL, returns success if $file exists. +# +f_media_get_ufs() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_ufs: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" "$probe_only" +} + +# f_media_shutdown_ufs $device +# +# Shuts down the UFS device using umount(8). Return status should be ignored. +# +f_media_shutdown_ufs() +{ + local dev="$1" err + + [ "$UFS_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); 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/usr.sbin/bsdconfig/share/media/usb.subr b/usr.sbin/bsdconfig/share/media/usb.subr new file mode 100644 index 000000000..aa47b2008 --- /dev/null +++ b/usr.sbin/bsdconfig/share/media/usb.subr @@ -0,0 +1,174 @@ +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 + ndevs=$( set -- $devs; echo $# ) + + if [ ${ndevs:=0} -eq 0 ]; then + f_show_msg "$msg_no_usb_devices_found" + return $FAILURE + elif [ $ndevs -gt 1 ]; then + local title="$msg_choose_a_usb_drive" + local prompt="$msg_please_select_a_usb_drive" + local hline="" + + local dev retval + dev=$( f_device_menu \ + "$title" "$prompt" "$hline" $DEVICE_TYPE_USB \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) + retval=$? + [ "$dev" ] || return $FAILURE + + f_device_find "$dev" $DEVICE_TYPE_USB devs + [ "$devs" ] || return $FAILURE + dev="${devs%%[$IFS]*}" + + f_struct_copy device_$dev device_media + [ $retval -eq $SUCCESS ] || return $FAILURE + else + f_struct_copy device_$devs 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 dev="$1" devname err + + device_$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" ] && + ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 ) + then + f_dialog_msgbox "$err" + return $FAILURE + fi + + if err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ); 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_only] +# +# Returns data from $file on a mounted USB disk device. Similar to cat(1). +# If $probe_only is present and non-NULL, returns success if $file exists. +# +f_media_get_usb() +{ + local dev="$1" file="$2" probe_only="$3" + + f_dprintf "f_media_get_usb: dev=[%s] file=[%s] probe_only=%s" \ + "$dev" "$file" "$probe_only" + + f_media_generic_get "$MOUNTPOINT" "$file" "$probe_only" +} + +# f_media_shutdown_usb $device +# +# Shuts down the USB disk device using umount(8). Return status should be +# ignored. +# +f_media_shutdown_usb() +{ + local dev="$1" err + + [ "$USB_MOUNTED" ] || return + + if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); 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/usr.sbin/bsdconfig/share/mustberoot.subr b/usr.sbin/bsdconfig/share/mustberoot.subr new file mode 100644 index 000000000..765487dc4 --- /dev/null +++ b/usr.sbin/bsdconfig/share/mustberoot.subr @@ -0,0 +1,425 @@ +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 + +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 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 + prompt=$( printf "$msg_you_are_not_root_but" bsdconfig ) + msg=$( printf "$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 + local err + if ! err=$( touch "$checkpath" 2>&1 ); then + f_dialog_msgbox "$err" + else + f_show_msg "$msg_created_path" "$checkpath" + fi + 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 255 ]; then + f_die $retval "$password" + elif [ $retval -ne 0 ]; 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 + msg=$( printf "$msg_nfailed_attempts" "$nfailures" ) + logger -p auth.notice -t sudo " " \ + "$USER : $msg" \ + "; TTY=$(tty)" \ + "; PWD=$PWD" \ + "; USER=root" \ + "; COMMAND=$0" + f_die 1 "sudo: $msg" + fi + fi + + # Use xauth(1) to grant root the ability to use this X11/SSH session + if [ "$USE_XDIALOG" -a "$SSH_CONNECTION" -a "$DISPLAY" ]; then + f_have xauth || f_die 1 \ + "$msg_no_such_file_or_directory" "$pgm" "xauth" + local HOSTNAME displaynum + HOSTNAME=$(hostname) + displaynum="${DISPLAY#*:}" + xauth -f ~/.Xauthority extract - $HOSTNAME/unix:$displaynum \ + $HOSTNAME:$displaynum | sudo sh -c 'xauth -ivf \ + ~root/.Xauthority merge - > /dev/null 2>&1' + fi + + # Re-execute ourselves with sudo(8) + 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 255 ] && f_die $retval "$user_pass" + + # Exit if the user cancelled. + [ $retval -eq $SUCCESS ] || exit $retval + + # + # Make sure the user exists and is non-root + # + local user password + user="${user_pass%%/*}" + password="${user_pass#*/}" + unset user_pass # scrub memory + if [ ! "$user" ]; then + nfailures=$(( $nfailures + 1 )) + f_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 < /dev/null < diff --git a/usr.sbin/bsdconfig/share/packages/categories.subr b/usr.sbin/bsdconfig/share/packages/categories.subr new file mode 100755 index 000000000..dd2fa8f44 --- /dev/null +++ b/usr.sbin/bsdconfig/share/packages/categories.subr @@ -0,0 +1,207 @@ +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= + +############################################################ 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_dprintf "%s: Initialized %u package category descriptions." \ + packages/categories.subr "$( set -- $CATEGORIES; echo $# )" + +f_dprintf "%s: Successfully loaded." packages/categories.subr + +fi # ! $_PACKAGES_CATEGORIES_SUBR diff --git a/usr.sbin/bsdconfig/share/packages/index.subr b/usr.sbin/bsdconfig/share/packages/index.subr new file mode 100755 index 000000000..863249c21 --- /dev/null +++ b/usr.sbin/bsdconfig/share/packages/index.subr @@ -0,0 +1,287 @@ +if [ ! "$_PACKAGES_INDEX_SUBR" ]; then _PACKAGES_INDEX_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/index.subr +f_include $BSDCFG_SHARE/device.subr +f_include $BSDCFG_SHARE/media/common.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= + +############################################################ FUNCTIONS + +# f_index_initialize $path [$var_to_set] +# +# Read and initialize the global index. $path is to be relative to the chosen +# media (not necessarily the filesystem; e.g. FTP) -- this is usually going to +# be `packages/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 __path="$1" __var_to_set="${2:-PACKAGE_INDEX}" + + [ "$_INDEX_INITTED" ] && return $SUCCESS + [ "$__path" ] || return $FAILURE + + # Got any media? + f_media_verify || return $FAILURE + + # Does it move when you kick it? + f_device_init media || return $FAILURE + + f_show_info "$msg_attempting_to_fetch_file_from_selected_media" \ + "$__path" + eval "$__var_to_set"='$( f_device_get media "$__path" )' + if [ $? -ne $SUCCESS ]; then + f_show_msg "$msg_unable_to_get_file_from_selected_media" \ + "$__path" + f_device_shutdown media + return $FAILURE + fi + eval "$__var_to_set"='$( debug= f_getvar "$__var_to_set" | sort )' + + f_show_info "$msg_located_index_now_reading_package_data_from_it" + if ! f_index_read "$__var_to_set"; then + f_show_msg "$msg_io_or_format_error_on_index_file" "$__path" + 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) + { + # Copy src indices to dest and calculate array length + nitems = 0; 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 "\"" + + }' )" # 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/usr.sbin/bsdconfig/share/packages/packages.subr b/usr.sbin/bsdconfig/share/packages/packages.subr new file mode 100755 index 000000000..75d524495 --- /dev/null +++ b/usr.sbin/bsdconfig/share/packages/packages.subr @@ -0,0 +1,1202 @@ +if [ ! "$_PACKAGES_PACKAGES_SUBR" ]; then _PACKAGES_PACKAGES_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..." "$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/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=".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 + 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 teh 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 searches /var/db/pkg for directory +# entries and marks each entry as an installed/selected package. +# +f_package_detect_installed() +{ + local installed package varpkg + # + # XXX KLUDGE ALERT! This makes evil assumptions about how XXX + # packages register themselves and should *really* be done with + # `pkg_info -e ' except that this is too slow for an + # item check routine.. :-( + # + # NOTE: When transitioning to pkgng, make a single fork to `pkg' to + # produce a list of all installed packages and parse _that_ + # + installed=$( find -s /var/db/pkg -mindepth 1 -maxdepth 1 -type d | + sed -e 's:/var/db/pkg/::' ) + for package in $installed; 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 peformed 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 $FAILURE + + # 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 $FAILURE + + 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 + prompt="$prompt $( printf "$msg_page_of_npages" \ + "$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 $SUCCESS ]; 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" + + prompt=$( printf "$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 prompt # Calculated below + local menu_list # Calculated below + local hline="$hline_alnum_arrows_punc_tab_enter" + + local fname=f_package_review + f_dprintf "%s: SELECTED_PACKAGES=[%s]" $fname "$SELECTED_PACKAGES" + + prompt=$( printf "$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 $FAILURE # They 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 "%s: Installing %s package" $fname "$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 "%s: Reinstalling %s package" $fname "$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 "%s: Uninstalling %s package" $fname "$package" + f_package_delete "$package" || continue + f_package_deselect "$package" + done + + return $SUCCESS +} + +# 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 packages/INDEX || return $FAILURE + # Creates following variables (indirectly via f_index_read()) + # CATEGORY_MENU_LIST _categories_{varpkg} _rundeps_{varpkg} + # PACKAGE_CATEGORIES _npkgs + + # 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 $SUCCESS ] || 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 255 -o ! "$menu_choice" ]; then + # User pressed ESC or chose Cancel + break + elif [ $retval -eq 1 ]; then + # Using X11, Xdialog(1) returned 1 for Cancel + f_show_msg "%s" "$menu_choice" + break + elif [ $retval -ne $SUCCESS ]; 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 media && + f_index_initialize packages/INDEX + } || 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 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 device="$1" name="$2" depended="$3" + + local fname=f_package_extract + f_dprintf "%s: device=[%s] name=[%s] depended=[%s]" \ + $fname "$device" "$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 + case "$name" in + */*) path="$name" ;; + *) + case "$name" in + *-*|*_*) path="packages/All/$name" ;; + *) path="packages/Latest/$name" + esac + esac + + # We have a path, call the device strategy routine to get the file + local pkg_ext probe_only=1 found= + for pkg_ext in "" $PACKAGE_EXTENSIONS; do + if f_device_get $device "$path$pkg_ext" $probe_only; then + path="$path$pkg_ext" + f_dprintf "%s: found path=[%s] dev=[%s]" \ + $fname "$path" "$device" + found=1 + break + fi + done + + 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 "%s: No such %s file on %s device" \ + $fname "$path" "$device" + $alert "$msg_unable_to_fetch_package_from_selected_media" \ + "$name" + [ "$no_confirm" ] && sleep 2 + return $FAILURE + fi + + local devname= + f_struct device_$device get name devname + 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 + + # Get package data and pipe into pkg_add(1) while providing feedback + { + if ! f_device_get $device "$path"; then + $alert "$msg_io_error_while_reading_in_the_package" \ + "$name" \ + >&$DIALOG_TERMINAL_PASSTHRU_FD 2> /dev/null + [ "$no_confirm" ] && sleep 2 + else + f_show_info \ + "$msg_package_read_successfully_waiting_for_pkg_add" \ + "$name" >&$DIALOG_TERMINAL_PASSTHRU_FD 2> /dev/null + fi + } | { + if f_debugging; then + /usr/sbin/pkg_add -v - + else + f_quietly /usr/sbin/pkg_add - + fi + } + if [ $? -ne $SUCCESS ]; then + $alert "$msg_pkg_add_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 name="$1" + local fname=f_package_delete + + 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 "%s: name=[%s]" $fname "$name" + + [ "$name" ] || return $FAILURE + + { # Verify and initialize device media if-defined + f_media_verify && + f_device_init media && + f_index_initialize packages/INDEX + } || 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 "%s: Detecting installed packages" $fname + 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 "%s: Uninstalling dependecy %s (marked for delete)" \ + $fname "$pkgsel" + 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 + pkg_delete -v "$name" + else + f_quietly pkg_delete "$name" + fi + if [ $? -ne $SUCCESS ]; then + f_show_msg "$msg_pkg_delete_failed" "$name" + return $FAILURE + else + f_dprintf "%s: pkg_delete(1) of %s successful" $fname "$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/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr new file mode 100644 index 000000000..a22741993 --- /dev/null +++ b/usr.sbin/bsdconfig/share/script.subr @@ -0,0 +1,207 @@ +if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_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..." 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/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: +# +# + Reswords do not take arguments but instead get all their data from +# the environment variable namespace. +# + 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:-$1}" + 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 +# 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 script="$1" config_file retval=$SUCCESS + + f_dprintf "f_script_load: 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 "f_script_load: Loading script from stdin" + eval "$( cat )" + retval=$? + else + f_dprintf "f_script_load: 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 + +# 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/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr new file mode 100644 index 000000000..0a77048c2 --- /dev/null +++ b/usr.sbin/bsdconfig/share/strings.subr @@ -0,0 +1,326 @@ +if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_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$ +# +############################################################ GLOBALS + +# +# 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_substr "$string" $start [ $length ] +# +# Simple wrapper to awk(1)'s `substr' function. +# +f_substr() +{ + local string="$1" start="${2:-0}" len="${3:-0}" + echo "$string" | awk "{ print substr(\$0, $start, $len) }" +} + +# f_snprintf $var_to_set $size $format ... +# +# Similar to snprintf(3), write at most $size number of bytes into $var_to_set +# using printf(1) syntax (`$format ...'). The value of $var_to_set is NULL +# unless at-least one byte is stored from the output. +# +f_snprintf() +{ + local __var_to_set="$1" __size="$2" + shift 2 # var_to_set/size + eval "$__var_to_set"=\$\( printf \"\$@\" \| awk -v max=\"\$__size\" \'' + { + len = length($0) + max -= len + print substr($0,0,(max > 0 ? len : max + len)) + if ( max < 0 ) exit + max-- + }'\' \) +} + +# 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' 'foxhound' " +# # 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_longest_line_length +# +# Simple wrapper to an awk(1) script to print the length of the longest line of +# input (read from stdin). Supports the newline escape-sequence `\n' for +# splitting a single line into multiple lines. +# +f_longest_line_length_awk=' +BEGIN { longest = 0 } +{ + if (split($0, lines, /\\n/) > 1) + { + for (n in lines) + { + len = length(lines[n]) + longest = ( len > longest ? len : longest ) + } + } + else + { + len = length($0) + longest = ( len > longest ? len : longest ) + } +} +END { print longest } +' +f_longest_line_length() +{ + awk "$f_longest_line_length_awk" +} + +# f_number_of_lines +# +# Simple wrapper to an awk(1) script to print the number of lines read from +# stdin. Supports newline escape-sequence `\n' for splitting a single line into +# multiple lines. +# +f_number_of_lines_awk=' +BEGIN { num_lines = 0 } +{ + num_lines += split(" "$0, unused, /\\n/) +} +END { print num_lines } +' +f_number_of_lines() +{ + awk "$f_number_of_lines_awk" +} + +# f_isinteger $arg +# +# Returns true if argument is a positive/negative whole integer. +# +f_isinteger() +{ + local arg="$1" + + # Prevent division-by-zero + [ "$arg" = "0" ] && return $SUCCESS + + # Attempt to perform arithmetic divison (an operation which will exit + # with error unless arg is a valid positive/negative whole integer). + # + ( : $((0/$arg)) ) > /dev/null 2>&1 +} + +# 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 +} + +# 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). +# +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" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." strings.subr + +fi # ! $_STRINGS_SUBR diff --git a/usr.sbin/bsdconfig/share/struct.subr b/usr.sbin/bsdconfig/share/struct.subr new file mode 100644 index 000000000..fc4f7114e --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/share/sysrc.subr b/usr.sbin/bsdconfig/share/sysrc.subr new file mode 100644 index 000000000..66a4cf34e --- /dev/null +++ b/usr.sbin/bsdconfig/share/sysrc.subr @@ -0,0 +1,633 @@ +if [ ! "$_SYSRC_SUBR" ]; then _SYSRC_SUBR=1 +# +# Copyright (c) 2006-2012 Devin Teske +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING 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). +# +# 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 echo '"${'"$1"'}"' 2> /dev/null + ) +} + +# f_sysrc_get_default $varname +# +# Get a system configuration default setting from the default rc.conf(5) file +# (or whatever RC_DEFAULTS points at). +# +f_sysrc_get_default() +{ + # Sanity check + [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ] || return $FAILURE + + # Taint-check variable name + case "$1" in + [0-9]*) + # Don't expand possible positional parameters + return $FAILURE ;; + *) + [ "$1" ] || return $FAILURE + esac + + ( # Execute within sub-shell to protect parent environment + + # + # Clear the environment of all variables, preventing the + # expansion of normals such as `PS1', `TERM', etc. + # + f_clean_env --except RC_DEFAULTS + + . "$RC_DEFAULTS" > /dev/null 2>&1 + + unset RC_DEFAULTS + # no longer needed + + # + # This must be the last functional line for both the sub-shell + # and the function to preserve the return status from formats + # such as "${varname?}" and "${varname:?}" (see "Parameter + # Expansion" in sh(1) for more information). + # + eval echo '"${'"$1"'}"' 2> /dev/null + ) +} + +# f_sysrc_find $varname +# +# Find which file holds the effective last-assignment to a given variable +# within the rc.conf(5) file(s). +# +# If the variable is found in any of the rc.conf(5) files, the function prints +# the filename it was found in and then returns success. Otherwise output is +# NULL and the function returns with error status. +# +f_sysrc_find() +{ + local varname="${1%%[!$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 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 last file and return. + # + if [ "$not_found" ]; then + echo "$varname=\"$new_value\"" >> "$file" + return $? + fi + + # + # Perform sanity checks. + # + if [ ! -w "$file" ]; then + f_err "$msg_cannot_create_permission_denied\n" \ + "$pgm" "$file" + return $FAILURE + fi + + # + # Create a new temporary file to write to. + # + local tmpfile="$( mktemp -t "$pgm" )" + [ "$tmpfile" ] || return $FAILURE + + # + # Fixup permissions (else we're in for a surprise, as mktemp(1) creates + # the temporary file with 0600 permissions, and if we simply mv(1) the + # temporary file over the destination, the destination will inherit the + # permissions from the temporary file). + # + local mode + mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) + f_quietly chmod "${mode:-0644}" "$tmpfile" + + # + # Fixup ownership. The destination file _is_ writable (we tested + # earlier above). However, this will fail if we don't have sufficient + # permissions (so we throw stderr into the bit-bucket). + # + local owner + owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) + f_quietly chown "${owner:-root:wheel}" "$tmpfile" + + # + # Operate on the matching file, replacing only the last occurrence. + # + local new_contents retval + new_contents=$( tail -r $file 2> /dev/null ) + new_contents=$( echo "$new_contents" | awk -v varname="$varname" \ + -v new_value="$new_value" "$f_sysrc_set_awk" ) + retval=$? + + # + # Write the temporary file contents. + # + echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE + if [ $retval -ne $SUCCESS ]; then + echo "$varname=\"$new_value\"" >> "$tmpfile" + fi + + # + # Taint-check our results. + # + if ! /bin/sh -n "$tmpfile"; then + f_err "$msg_previous_syntax_errors\n" "$pgm" "$file" + rm -f "$tmpfile" + return $FAILURE + fi + + # + # Finally, move the temporary file into place. + # + mv "$tmpfile" "$file" +} + +# f_sysrc_delete $varname +# +# Remove a setting from the system configuration files (edits files in-place). +# Deletes all assignments to the given variable in all config files. If the +# `-f file' option is passed, the removal is restricted to only those files +# specified, otherwise the system collection of rc_conf_files is used. +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_sysrc_delete_awk=' +# Variables that should be defined on the invocation line: +# -v varname="varname" +# +BEGIN { + regex = "^[[:space:]]*"varname"=" + found = 0 +} +{ + if ( $0 ~ regex ) + found = 1 + else + print +} +END { exit ! found } +' +f_sysrc_delete() +{ + local varname="$1" + local file + + # Check arguments + [ "$varname" ] || return $FAILURE + + # + # Operate on each of the specified files + # + for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do + [ -e "$file" ] || continue + + # + # Create a new temporary file to write to. + # + local tmpfile="$( mktemp -t "$pgm" )" + [ "$tmpfile" ] || return $FAILURE + + # + # Fixup permissions and ownership (mktemp(1) defaults to 0600 + # permissions) to instead match the destination file. + # + local mode owner + mode=$( stat -f '%#Lp' "$file" 2> /dev/null ) + owner=$( stat -f '%u:%g' "$file" 2> /dev/null ) + f_quietly chmod "${mode:-0644}" "$tmpfile" + f_quietly chown "${owner:-root:wheel}" "$tmpfile" + + # + # Operate on the file, removing all occurrences, saving the + # output in our temporary file. + # + awk -v varname="$varname" "$f_sysrc_delete_awk" "$file" \ + > "$tmpfile" + if [ $? -ne $SUCCESS ]; then + # The file didn't contain any assignments + rm -f "$tmpfile" + continue + fi + + # + # Taint-check our results. + # + if ! /bin/sh -n "$tmpfile"; then + f_err "$msg_previous_syntax_errors\n" \ + "$pgm" "$file" + rm -f "$tmpfile" + return $FAILURE + fi + + # + # Perform sanity checks + # + if [ ! -w "$file" ]; then + f_err "$msg_permission_denied\n" "$pgm" "$file" + rm -f "$tmpfile" + return $FAILURE + fi + + # + # Finally, move the temporary file into place. + # + mv "$tmpfile" "$file" + done +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." sysrc.subr + +fi # ! $_SYSRC_SUBR diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr new file mode 100644 index 000000000..86523d6b3 --- /dev/null +++ b/usr.sbin/bsdconfig/share/variable.subr @@ -0,0 +1,279 @@ +if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_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..." 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" ] +} + +############################################################ 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_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_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 + +# +# 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/usr.sbin/bsdconfig/startup/INDEX b/usr.sbin/bsdconfig/startup/INDEX new file mode 100644 index 000000000..afad34833 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/startup/Makefile b/usr.sbin/bsdconfig/startup/Makefile new file mode 100644 index 000000000..0bba51014 --- /dev/null +++ b/usr.sbin/bsdconfig/startup/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include share + +FILESDIR= ${LIBEXECDIR}/bsdconfig/140.startup +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= misc rcadd rcconf rcdelete rcedit rcvar startup + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/startup/USAGE b/usr.sbin/bsdconfig/startup/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/startup/include/Makefile b/usr.sbin/bsdconfig/startup/include/Makefile new file mode 100644 index 000000000..163431432 --- /dev/null +++ b/usr.sbin/bsdconfig/startup/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/140.startup/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/startup/include/messages.subr b/usr.sbin/bsdconfig/startup/include/messages.subr new file mode 100644 index 000000000..87bde269a --- /dev/null +++ b/usr.sbin/bsdconfig/startup/include/messages.subr @@ -0,0 +1,112 @@ +# 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_to_delete="Are you sure you want to delete the \`%s' directive\nfrom the rc.conf(5) collection of system configuration files?" +msg_are_you_sure_you_want_delete_the_following="Are you sure you want to delete the following directives\nfrom the rc.conf(5) collection of system configuration files?" +msg_cancel="Cancel" +msg_choose_view_details="Choose View Details" +msg_creating_menu_list="Creating menu list...\nThis may take a while." +msg_creating_rcconf_map="Creating rc.conf(5) map...\nThis may take a while." +msg_creating_rcvar_map="Creating rcvar map...\nThis may take a while." +msg_default_value="Default: %s" +msg_delete="Delete" +msg_delete_desc="Delete directive(s)" +msg_delete_help="Select one or more directives from a list to delete" +msg_delete_selected="Delete Selected" +msg_delete_selected_desc="Delete selected directive(s)" +msg_delete_selected_help="Delete each of the selected rc.conf(5) configuration directives" +msg_delete_startup_directives="Delete Startup Directive(s)" +msg_deleting_selected_directives="Deleting selected directive(s)..." +msg_desc="Description" +msg_desc_desc="Toggle display of system description" +msg_details="Details" +msg_exit="Exit" +msg_exit_cancel="Exit/Cancel" +msg_exit_cancel_desc="Return to previous menu" +msg_exit_cancel_help="Return to the previous menu (selected items are untouched)" +msg_exit_desc="Return to previous menu" +msg_exit_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_startup_services="Miscellaneous Startup Services" +msg_miscellaneous_menu_text="This menu allows you to configure various aspects of your system's\nstartup configuration. Use [SPACE] or [ENTER] to select items, and\n[TAB] to move to the buttons. Select Exit to leave this menu." +msg_named="named" +msg_named_desc="Run a local name server on this host" +msg_named_flags="named flags" +msg_named_flags_desc="Set default flags to named (if enabled)" +msg_nis_client="NIS client" +msg_nis_client_desc="This host wishes to be an NIS client." +msg_nis_domainname="NIS domainname" +msg_nis_domainname_desc="Set NIS domainname (if enabled)" +msg_nis_server="NIS Server" +msg_nis_server_desc="This host wishes to be an NIS server." +msg_none="None" +msg_none_desc="Un-Select all directives" +msg_none_help="Un-Select all rc.conf(5) configuration directives" +msg_ok="OK" +msg_please_enter_a_new_value="Please enter a new value for \`%s' (Default: %s):" +msg_please_enter_rcvar_name="Please enter rc.conf(5) variable name:" +msg_please_select_an_rcconf_directive="Please select an rc.conf(5) directive:" +msg_rcvar_contains_invalid_chars="ERROR! rc.conf(5) variable name contains invalid characters.\n Name may only consist of letters [a-zA-Z], numbers [0-9],\n or underscore [_] and must not start with a number." +msg_rcvar_must_start_with="ERROR! rc.conf(5) variable name must start with\n a letter [a-zA-Z] or underscore [_]." +msg_reset="Reset" +msg_reset_desc="Reset to default view settings" +msg_sco="SCO" +msg_sco_desc="This host wants to be able to run IBCS2 binaries." +msg_show_configured="Show Configured" +msg_show_configured_desc="Calculate rc.conf(5) locations (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_svr4="SVR4" +msg_svr4_desc="This host wants to be able to run SVR4 binaries." +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/usr.sbin/bsdconfig/startup/misc b/usr.sbin/bsdconfig/startup/misc new file mode 100755 index 000000000..edfc1acbe --- /dev/null +++ b/usr.sbin/bsdconfig/startup/misc @@ -0,0 +1,439 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ GLOBALS + +# +# Operating environment +# +UNAME_P=$( uname -p ) # Processor Architecture (i.e. i386) + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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 + ibcs2_enable + svr4_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 + export msg_sco msg_sco_desc + export msg_svr4 msg_svr4_desc + :| awk \ + -v uname_p="$UNAME_P" \ + -v menu_tags="$DIALOG_MENU_TAGS" \ + -v menu_fmt="'%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 + + if ( uname_p == "i386" ) + { + # + # SCO: This host wants to be able to run IBCS2 + # binaries. + # + char = substr(menu_tags, i++, 1) + mark = ( ENVIRON["ibcs2_enable"] ~ \ + /^[Yy][Ee][Ss]$/ ? "X" : " " ) + subtag = ENVIRON["msg_sco"] + tag = sprintf(mtag_fmt, char, mark, subtag) + mprint(tag, ENVIRON["msg_sco_desc"]) + if (ditem == char) defaultitem = tag + + # + # SVR4: This host wants to be able to run SVR4 + # binaries. + # + char = substr(menu_tags, i++, 1) + mark = ( ENVIRON["svr4_enable"] ~ \ + /^[Yy][Ee][Ss]$/ ? "X" : " " ) + subtag = ENVIRON["msg_svr4"] + tag = sprintf(mtag_fmt, char, mark, subtag) + mprint(tag, ENVIRON["msg_svr4_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 $SUCCESS ] || return $retval + + value="$_input" + return $SUCCESS +} + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 ;; + *) toggled= + esac + + case "$mtag" in + # Simple On/Off toggle bits + ?" ["?"] $msg_apm") + if [ "$toggled" ]; then + err=$( f_sysrc_set apm_enable NO 2>&1 ) + else + err=$( f_sysrc_set apm_enable YES 2>&1 ) + fi + ;; + ?" ["?"] $msg_named") + if [ "$toggled" ]; then + err=$( f_sysrc_set named_enable NO 2>&1 ) + else + err=$( f_sysrc_set named_enable YES 2>&1 ) + fi + ;; + ?" ["?"] $msg_accounting") + if [ "$toggled" ]; then + err=$( f_sysrc_set accounting_enable NO 2>&1 ) + else + err=$( f_sysrc_set accounting_enable YES 2>&1 ) + fi + ;; + ?" ["?"] $msg_lpd") + if [ "$toggled" ]; then + err=$( f_sysrc_set lpd_enable NO 2>&1 ) + else + err=$( f_sysrc_set lpd_enable YES 2>&1 ) + fi + ;; + ?" ["?"] $msg_sco") + if [ "$toggled" ]; then + err=$( f_sysrc_set ibcs2_enable NO 2>&1 ) + else + err=$( f_sysrc_set ibcs2_enable YES 2>&1 ) + fi + ;; + ?" ["?"] $msg_svr4") + if [ "$toggled" ]; then + err=$( f_sysrc_set svr4_enable NO 2>&1 ) + else + err=$( f_sysrc_set svr4_enable YES 2>&1 ) + fi + ;; + # Multi-variable On/Off toggle bits + ?" ["?"] $msg_nis_client") + if [ "$toggled" ]; then + err=$( f_sysrc_set nis_client_enable NO 2>&1 ) + else + err=$( f_sysrc_set nis_client_enable YES 2>&1 ) \ + && err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) + fi + ;; + ?" ["?"] $msg_nis_server") + if [ "$toggled" ]; then + err=$( f_sysrc_set nis_server_enable NO 2>&1 ) + else + err=$( f_sysrc_set nis_server_enable YES 2>&1 ) \ + && err=$( f_sysrc_set rpcbind_enable YES 2>&1 ) + fi + ;; + # Checkboxes for non-boolean options + ?" ["?"] $msg_nis_domainname") + dialog_input_value "$msg_nis_domainname_desc" \ + "$( f_sysrc_get nisdomainname )" || continue + err=$( f_sysrc_set nisdomainname "$value" 2>&1 ) + ;; + ?" ["?"] $msg_startup_dirs") + dialog_input_value "$msg_startup_dirs_desc" \ + "$( f_sysrc_get local_startup )" || continue + err=$( f_sysrc_set local_startup "$value" 2>&1 ) + ;; + ?" ["?"] $msg_named_flags") + dialog_input_value "$msg_named_flags_desc" \ + "$( f_sysrc_get named_flags )" || continue + err=$( f_sysrc_set named_flags "$value" 2>&1 ) + ;; + esac + + [ $? -eq $SUCCESS ] || f_dialog_msgbox "$err\n" +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/startup/rcadd b/usr.sbin/bsdconfig/startup/rcadd new file mode 100755 index 000000000..9fd3bdda7 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ GLOBALS + +# +# Options +# +# Inherit SHOW_DESC value if set, otherwise default to 1 +[ "${SHOW_DESC+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/usr.sbin/bsdconfig/startup/rcconf b/usr.sbin/bsdconfig/startup/rcconf new file mode 100755 index 000000000..d064224d3 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ GLOBALS + +# +# Global map/menu-list for the main menu +# +RCCONF_MAP= +_RCCONF_MAP= + +# +# 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 0 ] && 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 2 ]; then + # The ``Help'' button (labeled "Details") was pressed + f_dialog_input_view_details + continue + fi + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + "X $msg_exit") break ;; + "> $msg_add_new") $BSDCFG_LIBE/$APP_DIR/rcadd ${USE_XDIALOG:+-X} ;; + "> $msg_delete") + # rcdelete has a similar interface that can inherit the below: + export SHOW_VALUE SHOW_DESC SHOW_DEFAULT_VALUE SHOW_CONFIGURED + $BSDCFG_LIBE/$APP_DIR/rcdelete ${USE_XDIALOG:+-X} + ;; + *) # Anything else is a variable to edit + $BSDCFG_LIBE/$APP_DIR/rcedit ${USE_XDIALOG:+-X} "${mtag# }" + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/startup/rcdelete b/usr.sbin/bsdconfig/startup/rcdelete new file mode 100755 index 000000000..b6eeba481 --- /dev/null +++ b/usr.sbin/bsdconfig/startup/rcdelete @@ -0,0 +1,415 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ 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 0 ] && 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 $FAILURE + + # 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 2 ]; then + # The ``Help'' button (labeled "Details") was pressed + f_dialog_input_view_details && dialog_create_main + continue + fi + + [ $retval -eq 0 ] || f_die + + case "$mtag" in + "X $msg_exit_cancel") break ;; + "> $msg_delete_selected") + delete_vars= + for var in $( f_startup_rcconf_list ); do + [ "$( eval echo \$_${var}_delete )" ] || continue + delete_vars="$delete_vars${delete_vars:+ }$var" + done + 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 + if ! err=$( f_sysrc_delete $var 2>&1 ); then + f_dialog_msgbox "$err\n" + break + fi + 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/usr.sbin/bsdconfig/startup/rcedit b/usr.sbin/bsdconfig/startup/rcedit new file mode 100755 index 000000000..de7f32100 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/startup/rcvar b/usr.sbin/bsdconfig/startup/rcvar new file mode 100755 index 000000000..7d29bfcd5 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ GLOBALS + +# +# Global map/menu-list for the main menu +# +RCVAR_MAP= +_RCVAR_MAP= + +# +# 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 $SUCCESS ]; 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 + + err=$( f_sysrc_set "$rcvar" "$value" 2>&1 ) || f_dialog_msgbox "$err" +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/startup/share/Makefile b/usr.sbin/bsdconfig/startup/share/Makefile new file mode 100644 index 000000000..01c7d032a --- /dev/null +++ b/usr.sbin/bsdconfig/startup/share/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/bsdconfig/startup +FILES= rcconf.subr rcedit.subr rcvar.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/startup/share/rcconf.subr b/usr.sbin/bsdconfig/startup/share/rcconf.subr new file mode 100644 index 000000000..4c3e0d676 --- /dev/null +++ b/usr.sbin/bsdconfig/startup/share/rcconf.subr @@ -0,0 +1,496 @@ +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 __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 persistant + # 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=$( md5 < "$RC_DEFAULTS" ) + + # + # Check to see if the global persistant cache file exists + # + if [ -f "$STARTUP_RCCONF_MAP_CACHEFILE" ]; then + # + # Attempt to populate the in-memory cache with the (soon to be) + # validated on-disk cache. If validation fails, fall-back to + # the current value and provide error exit status. + # + STARTUP_RCCONF_MAP=$( + ( # Get digest as the first word on the first line + read digest rest_ignored + + # + # If the stored digest matches the calculated- + # one populate the in-memory cache from the on- + # disk cache and provide success exit status. + # + if [ "$digest" = "$__rc_defaults_digest" ] + then + cat + exit $SUCCESS + else + # Otherwise, return the current value + echo "$STARTUP_RCCONF_MAP" + exit $FAILURE + fi + ) < "$STARTUP_RCCONF_MAP_CACHEFILE" + ) + 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 persistant + # cache file to speed up future executions). + # + + STARTUP_RCCONF_MAP=$( + f_clean_env --except \ + PATH \ + RC_DEFAULTS \ + STARTUP_RCCONF_REGEX \ + f_sysrc_desc_awk + . "$RC_DEFAULTS" + + # Unset variables we don't want reported + unset source_rc_confs_defined + + for var in $( set | awk -F= " + function test_print(var) + { + if ( var == \"OPTIND\" ) return + if ( var == \"PATH\" ) return + if ( var == \"RC_DEFAULTS\" ) return + if ( var == \"STARTUP_RCCONF_REGEX\" ) return + if ( var == \"f_sysrc_desc_awk\" ) return + print var + } + /$STARTUP_RCCONF_REGEX/ { test_print(\$1) } + " ); do + echo $var "$( f_sysrc_desc $var )" + done + ) + export STARTUP_RCCONF_MAP + export _STARTUP_RCCONF_MAP=1 + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$STARTUP_RCCONF_MAP" + else + echo "$STARTUP_RCCONF_MAP" + fi + + # + # Attempt to create the persistant global cache + # + + # Create a new temporary file to write to + local __tmpfile="$( mktemp -t "$pgm" )" + [ "$__tmpfile" ] || return $FAILURE + + # Write the temporary file contents + echo "$__rc_defaults_digest" > "$__tmpfile" + echo "$STARTUP_RCCONF_MAP" >> "$__tmpfile" + + # Finally, move the temporary file into place + case "$STARTUP_RCCONF_MAP_CACHEFILE" in + */*) f_quietly mkdir -p "${STARTUP_RCCONF_MAP_CACHEFILE%/*}" + esac + mv "$__tmpfile" "$STARTUP_RCCONF_MAP_CACHEFILE" +} + +# f_startup_rcconf_map_expand $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 "$( 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 0 ] || return $FAILURE + + 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 $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." startup/rcconf.subr + +fi # ! $_STARTUP_RCCONF_SUBR diff --git a/usr.sbin/bsdconfig/startup/share/rcedit.subr b/usr.sbin/bsdconfig/startup/share/rcedit.subr new file mode 100644 index 000000000..64ee1ccf0 --- /dev/null +++ b/usr.sbin/bsdconfig/startup/share/rcedit.subr @@ -0,0 +1,87 @@ +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/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 msg var="$1" _input + + msg=$( printf "$msg_please_enter_a_new_value" \ + "$var" "$( f_sysrc_get_default "$var" )" ) + + shift 1 # var + if [ "$1" ]; then + [ "$1" = "--" ] && shift 1 # -- + _input="$1" + else + _input=$( f_sysrc_get "$var" ) + fi + + # 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 $SUCCESS + + f_dprintf "%s: [%s]->[%s]" "$var" "$cur_val" "$_input" + + err=$( f_sysrc_set "$var" "$_input" 2>&1 ) || f_dialog_msgbox "$err" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." startup/rcedit.subr + +fi # ! $_STARTUP_RCEDIT_SUBR diff --git a/usr.sbin/bsdconfig/startup/share/rcvar.subr b/usr.sbin/bsdconfig/startup/share/rcvar.subr new file mode 100644 index 000000000..098689531 --- /dev/null +++ b/usr.sbin/bsdconfig/startup/share/rcvar.subr @@ -0,0 +1,232 @@ +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 __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 persistant cache file (containg this digest on the + # first line) is valid and can be used to quickly populate the cache + # value for immediate return. + # + local __rc_script_list_digest + __rc_script_list_digest=$( cd "$ETC_RC_D" && + cksum "$RC_DEFAULTS" $__rc_script_list | md5 ) + + # + # Check to see if the global persistant cache file exists + # + if [ -f "$STARTUP_RCVAR_MAP_CACHEFILE" ]; then + # + # Attempt to populate the in-memory cache with the (soon to be) + # 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 persistant + # cache file to speed up future executions). + # + + STARTUP_RCVAR_MAP=$( + for script in $__rc_script_list; do + rcvar_list=$( $script rcvar | awk -F= \ + -v script="$script" ' + /^'"$STARTUP_RCVAR_REGEX"'/ { + if ( $2 ~ /^"[Yy][Ee][Ss]"$/ ) + print $1 ",YES" + else + print $1 ",NO" + }' ) + for entry in $rcvar_list; do + rcvar="${entry%%,*}" + rcvar_default=$( f_sysrc_get_default "$rcvar" ) + [ "$rcvar_default" ] || + rcvar_default="${entry#*,}" + rcvar_desc=$( f_sysrc_desc "$rcvar" ) + echo $rcvar ${rcvar_default:-NO} \ + $script "$rcvar_desc" + done + done | sort -u + ) + export STARTUP_RCVAR_MAP + export _STARTUP_RCVAR_MAP=1 + if [ "$__var_to_set" ]; then + setvar "$__var_to_set" "$STARTUP_RCVAR_MAP" + else + echo "$STARTUP_RCVAR_MAP" + fi + + # + # Attempt to create/update the persistant global cache + # + + # Create a new temporary file to write to + local __tmpfile="$( mktemp -t "$pgm" )" + [ "$__tmpfile" ] || return $FAILURE + + # Write the temporary file contents + echo "$__rc_script_list_digest" > "$__tmpfile" + echo "$STARTUP_RCVAR_MAP" >> "$__tmpfile" + + # Finally, move the temporary file into place + case "$STARTUP_RCVAR_MAP_CACHEFILE" in + */*) f_quietly mkdir -p "${STARTUP_RCVAR_MAP_CACHEFILE%/*}" + esac + mv "$__tmpfile" "$STARTUP_RCVAR_MAP_CACHEFILE" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." startup/rcvar.subr + +fi # ! $_STARTUP_RCVAR_SUBR diff --git a/usr.sbin/bsdconfig/startup/startup b/usr.sbin/bsdconfig/startup/startup new file mode 100755 index 000000000..6b02cb413 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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/usr.sbin/bsdconfig/timezone/INDEX b/usr.sbin/bsdconfig/timezone/INDEX new file mode 100644 index 000000000..67fc50b0d --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/timezone/Makefile b/usr.sbin/bsdconfig/timezone/Makefile new file mode 100644 index 000000000..b4ef0cbd0 --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include share + +FILESDIR= ${LIBEXECDIR}/bsdconfig/090.timezone +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= timezone + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/timezone/USAGE b/usr.sbin/bsdconfig/timezone/USAGE new file mode 100644 index 000000000..6dbe96d39 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/timezone/include/Makefile b/usr.sbin/bsdconfig/timezone/include/Makefile new file mode 100644 index 000000000..887536eec --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/090.timezone/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/timezone/include/messages.subr b/usr.sbin/bsdconfig/timezone/include/messages.subr new file mode 100644 index 000000000..6a7f045cd --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/timezone/share/Makefile b/usr.sbin/bsdconfig/timezone/share/Makefile new file mode 100644 index 000000000..1b7b80c3a --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/share/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/bsdconfig/timezone +FILES= continents.subr countries.subr iso3166.subr menus.subr \ + zones.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/timezone/share/continents.subr b/usr.sbin/bsdconfig/timezone/share/continents.subr new file mode 100644 index 000000000..02c407177 --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/share/continents.subr @@ -0,0 +1,143 @@ +if [ ! "$_TIMEZONE_CONTINENTS_SUBR" ]; then _TIMEZONE_CONTINENTS_SUBR=1 +# +# Copyright (c) 2011-2012 Devin Teske +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING 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 +# +# Returns a single property of a given continent. Available properties are: +# +# name Directory name of continent/ocean as it appears in +# _PATH_ZONEINFO. +# title Menu text of this continent/ocean to be displayed in the +# continent-selection menu. +# nitems Number of submenu items associated with this +# continent/ocean. +# tlc_N 2-character country code of the Nth submenu item associated +# with this continent displayed in the country-selection menu +# (which appears after continent selection). +# menu_list Menu-list of regions for this continent. +# +f_continent() +{ + local cont="$1" property="$2" + eval echo \"\${continent_${cont}_$property}\" +} + +# f_find_continent $title +# +# Returns continent identifier given continent title. +# +f_find_continent() +{ + local cont + for cont in $CONTINENTS; do + if [ "$1" = "$( f_continent $cont title )" ]; then + echo "$cont" + return $SUCCESS + fi + done + return $FAILURE +} + +# f_OCEANP $cont +# +# Returns "1" if the first argument is an ocean, otherwise NULL. +# +f_OCEANP() +{ + case "$1" in + arctic|atlantic|indian|pacific) + echo 1 + esac +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." timezone/continents.subr + +fi # ! $_TIMEZONE_CONTINENTS_SUBR diff --git a/usr.sbin/bsdconfig/timezone/share/countries.subr b/usr.sbin/bsdconfig/timezone/share/countries.subr new file mode 100644 index 000000000..ff05766ba --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/share/countries.subr @@ -0,0 +1,80 @@ +if [ ! "$_TIMEZONE_COUNTRIES_SUBR" ]; then _TIMEZONE_COUNTRIES_SUBR=1 +# +# Copyright (c) 2011-2012 Devin Teske +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ + +# f_country $code $property +# +# Returns a single property of a given country. Available properties are: +# +# name Name of the country as read from _PATH_ISO3166. +# nzones Number of zones within the country (-1 if country has +# only a single zone). +# filename The filename portion of the TZ field (after the `/') as +# read from _PATH_ZONETAB. +# cont The principal continent in which the country lies (appears +# before the `/' in the TZ field of _PATH_ZONETAB). +# filename_N Like filename, but for the Nth zone when the country has +# multiple zones (nzones > 0). +# cont_N Like cont, but for the Nth zone when the country has +# multiple zones (nzones > 0). +# descr_N Like name, but for the Nth zone when the country has +# multiple zones (nzones > 0) +# +f_country() +{ + local code="$1" property="$2" + eval echo \"\${country_${code}_$property}\" +} + +# f_sort_countries +# +# Sorts alphabetically the 2-character country codes listed in $COUNTRIES based +# on the name of each country. +# +# This function is a two-parter. Below is the awk(1) portion of the function, +# afterward is the sh(1) function which utilizes the below awk script. +# +f_sort_countries_awk=' +{ + split($0, array, /[[:space:]]+/) + for (item in array) + { + tlc = array[item] + print ENVIRON["country_" tlc "_name"] " " tlc + } +} +' +f_sort_countries() +{ + COUNTRIES=$( echo "$COUNTRIES" | awk "$f_sort_countries_awk" | + sort | awk '{print $NF}' ) + export COUNTRIES +} + +f_dprintf "%s: Successfully loaded." timezone/countries.subr + +fi # ! $_TIMEZONE_COUNTRIES_SUBR diff --git a/usr.sbin/bsdconfig/timezone/share/iso3166.subr b/usr.sbin/bsdconfig/timezone/share/iso3166.subr new file mode 100644 index 000000000..205d5f504 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/timezone/share/menus.subr b/usr.sbin/bsdconfig/timezone/share/menus.subr new file mode 100644 index 000000000..2028bf3f9 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/timezone/share/zones.subr b/usr.sbin/bsdconfig/timezone/share/zones.subr new file mode 100644 index 000000000..b356323ec --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/share/zones.subr @@ -0,0 +1,597 @@ +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/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 zoneinfo_file="$1" + local copymode title msg err 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 + msg=$( printf "$msg_removing_file" "$_PATH_LOCALTIME" ) + elif [ "$copymode" ]; then + msg=$( printf "$msg_copying_file" \ + "$zoneinfo_file" "$_PATH_LOCALTIME" ) + else + msg=$( printf "$msg_creating_symlink" \ + "$_PATH_LOCALTIME" "$zoneinfo_file" ) + fi + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_info" + f_dialog_msgbox "$msg" + f_dialog_title_restore + else + printf "%s\n" "$msg" + fi + fi + + [ "$REALLYDOIT" ] || return $SUCCESS + + if [ ! "$zoneinfo_file" ]; then + err=$( rm -f "$_PATH_LOCALTIME" 2>&1 ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + err=$( rm -f "$_PATH_DB" 2>&1 ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + if [ "$VERBOSE" ]; then + msg=$( printf "$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 + + err=$( rm -f "$_PATH_LOCALTIME" 2>&1 ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + err=$( umask 222 && : 2>&1 > "$_PATH_LOCALTIME" ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + err=$( cat "$zoneinfo_file" 2>&1 > "$_PATH_LOCALTIME" ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + else # ! copymode + + err=$( ( :< "$zoneinfo_file" ) 2>&1 ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + err=$( rm -f "$_PATH_LOCALTIME" 2>&1 ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + err=$( ln -s "$zoneinfo_file" "$_PATH_LOCALTIME" 2>&1 ) + if [ "$err" ]; then + if [ "$USEDIALOG" ]; then + f_dialog_title "$msg_error" + f_dialog_msgbox "$err" + f_dialog_title_restore + else + f_err "%s\n" "$err" + fi + return $FAILURE + fi + + fi # copymode + + if [ "$VERBOSE" ]; then + if [ "$copymode" ]; then + msg=$( printf "$msg_copied_timezone_file" \ + "$zoneinfo_file" "$_PATH_LOCALTIME" ) + else + msg=$( printf "$msg_created_symlink" \ + "$_PATH_LOCALTIME" "$zoneinfo_file" ) + fi + if [ "$USEDIALOG" ]; then + 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="$( printf "$msg_look_reasonable" "$tm_zone" )" + local height=5 width=72 + + if [ "$USE_XDIALOG" ]; then + height=$(( $height + 4 )) + $DIALOG \ + --title "$title" \ + --backtitle "$btitle" \ + --ok-label "$msg_yes" \ + --cancel-label "$msg_no" \ + --yesno "$prompt" $height $width + else + $DIALOG \ + --title "$title" \ + --backtitle "$btitle" \ + --yes-label "$msg_yes" \ + --no-label "$msg_no" \ + --yesno "$prompt" $height $width + fi +} + +# f_set_zone_utc +# +# Resets to the UTC timezone. +# +f_set_zone_utc() +{ + f_confirm_zone "" || return $FAILURE + f_install_zoneinfo_file "" +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." timezone/zones.subr + +fi # ! $_TIMEZONE_ZONES_SUBR diff --git a/usr.sbin/bsdconfig/timezone/timezone b/usr.sbin/bsdconfig/timezone/timezone new file mode 100755 index 000000000..709c8a81a --- /dev/null +++ b/usr.sbin/bsdconfig/timezone/timezone @@ -0,0 +1,455 @@ +#!/bin/sh +#- +# 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$ +# +############################################################ 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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# Standard pathnames +# +_PATH_DB="/var/db/zoneinfo" +_PATH_WALL_CMOS_CLOCK="/etc/wall_cmos_clock" + +############################################################ GLOBALS + +# +# Options +# +REALLYDOIT=1 +REINSTALL= +USEDIALOG=1 +SKIPUTC= +VERBOSE= +TZ_OR_FAIL= +CHROOTENV= + +# +# Dummy vars (populated dynamically) +# +COUNTRIES= # list of 2-character country codes created by f_read_iso3166_table + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local title="$DIALOG_TITLE" + local btitle="$DIALOG_BACKTITLE" + local prompt="$msg_select_region" + local 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 + +# 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" + zoneinfo=$( cat "$_PATH_DB" ) || + f_die 1 "$msg_error_reading" "$_PATH_DB" + [ "$zoneinfo" ] || + f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB" + f_install_zoneinfo "$zoneinfo" + exit $? +fi + +# +# If the arguments on the command-line do not specify a file, +# then interpret it as a zoneinfo name +# +if [ $# -ge 1 ]; then + zoneinfo="$1" + + if [ ! -f "$zoneinfo" ]; then + USEDIALOG= + f_install_zoneinfo "$zoneinfo" + exit $? + fi + + # FALLTHROUGH +fi + +# +# Process the UTC option +# +if [ "$_PATH_WALL_CMOS_CLOCK" -a ! "$SKIPUTC" ]; then + f_dialog_title "$msg_select_local_or_utc" + title="$DIALOG_TITLE" + btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + msg="$msg_is_machine_clock_utc" + + if [ "$USE_XDIALOG" ]; then + defaultno="default-no" + height=10 width=77 + else + defaultno="defaultno" + height=7 width=73 + fi + + if [ "$USE_XDIALOG" ]; then + $DIALOG \ + --title "$title" \ + --backtitle "$btitle" \ + --$defaultno \ + --ok-label "$msg_yes" \ + --cancel-label "$msg_no" \ + --yesno "$msg" $height $width + result=$? + else + $DIALOG \ + --title "$title" \ + --backtitle "$btitle" \ + --$defaultno \ + --yes-label "$msg_yes" \ + --no-label "$msg_no" \ + --yesno "$msg" $height $width + result=$? + fi + + if [ $result -eq 0 ]; then + # User chose YES + [ "$REALLYDOIT" ] && + f_quietly rm -f "$_PATH_WALL_CMOS_CLOCK" + else + # User chose NO, pressed ESC (or Ctrl-C), or closed box + [ "$REALLYDOIT" ] && + ( umask 222 && :> "$_PATH_WALL_CMOS_CLOCK" ) + fi +fi + +# +# Process optional default zone argument +# +if [ $# -ge 1 ]; then + default="$1" + + f_dialog_title "$msg_default_zone_provided" + msg=$( printf "\n$msg_use_default_zone" "$default" ) + hline= + f_dialog_yesno "$msg" "$hline" + result=$? + f_dialog_title_restore + + if [ $result -eq 0 ]; then + # User chose YES + f_install_zoneinfo_file "$default" + result=$? + [ ! "$USE_XDIALOG" ] && f_dialog_clear + exit $result + fi + + [ ! "$USE_XDIALOG" ] && f_dialog_clear +fi + +# +# Override the user-supplied umask +# +umask 022 + +# +# Read databases and perform initialization +# +f_read_iso3166_table # creates $COUNTRIES and $country_*_name +f_read_zones # creates $country_*_{descr,cont,filename} +f_sort_countries # sorts the countries listed for each continent +f_make_menus # creates $continent_menu_list and $continent_*_menu_list + +# +# Launch application main menu +# +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 0 ]; then + [ "$TZ_OR_FAIL" ] && f_die + exit $SUCCESS + fi + + NEED_CONTINENT= + + continent=$( eval f_dialog_menutag2item \"\$mtag\" \ + $continent_menu_list ) + cont=$( f_find_continent "$continent" ) + cont_title=$( f_continent $cont title ) + nitems=$( f_continent $cont nitems ) + isocean=$( f_OCEANP $cont ) + fi + + if [ "$NEED_COUNTRY" ]; then + if [ "$cont_title" = "$continent_utc_title" ]; then + if f_set_zone_utc; then + break + else + NEED_CONTINENT=1 + continue + fi + fi + + # + # Short cut -- if there's only one country, don't post a menu. + # + if [ $nitems -eq 1 ]; then + tag=1 + else + # + # It's amazing how much good grammar really matters... + # + if [ ! "$isocean" ]; then + title=$( printf "$msg_country_title" \ + "$cont_title" ) + f_dialog_title "$title" + title="$DIALOG_TITLE" + btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + prompt="$msg_select_country" + else + title=$( printf "$msg_island_and_group_title" \ + "$cont_title" ) + f_dialog_title "$title" + title="$DIALOG_TITLE" + btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + prompt="$msg_select_island_or_group" + fi + + # + # Calculate size of menu + # + menu_list=$( f_continent $cont menu_list ) + 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 0 ]; then + NEED_CONTINENT=1 + continue # back to main menu + fi + fi + + # Get the country code from the user's selection + tlc=$( f_continent $cont tlc_$tag ) + + NEED_COUNTRY= + fi + + # + # If the selection has only one zone (nzones == -1), + # just set it. + # + nzones=$( f_country $tlc nzones ) + if [ $nzones -lt 0 ]; then + real_cont=$( f_country $tlc cont ) + real_continent=$( f_continent $real_cont name ) + name=$( f_country $tlc name ) + filename=$( f_country $tlc filename ) + + if ! f_confirm_zone "$real_continent/$filename"; then + [ $nitems -eq 1 ] && NEED_CONTINENT=1 + NEED_COUNTRY=1 + continue + fi + else + title=$( printf "$msg_country_time_zones" \ + "$( f_country $tlc name )" ) + f_dialog_title "$title" + title="$DIALOG_TITLE" + btitle="$DIALOG_BACKTITLE" + f_dialog_title_restore + prompt="$msg_select_zone" + menu_list=$( f_country $tlc menu_list ) + 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 0 ]; then + [ $nitems -eq 1 ] && NEED_CONTINENT=1 + NEED_COUNTRY=1 + continue + fi + + real_cont=$( f_country $tlc cont_$n ) + real_continent=$( f_continent $real_cont name ) + name=$( f_country $tlc name ) + filename=$( f_country $tlc filename_$n ) + + f_confirm_zone "$real_continent/$filename" || continue + fi + + [ $retval -eq 0 ] || continue # back to main menu + + if ! f_install_zoneinfo "$real_continent/$filename"; then + [ $nzones -lt 0 ] && NEED_COUNTRY=1 + else + break + fi +done + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/ttys/INDEX b/usr.sbin/bsdconfig/ttys/INDEX new file mode 100644 index 000000000..83ca0211b --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/ttys/Makefile b/usr.sbin/bsdconfig/ttys/Makefile new file mode 100644 index 000000000..b77bc249b --- /dev/null +++ b/usr.sbin/bsdconfig/ttys/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include + +FILESDIR= ${LIBEXECDIR}/bsdconfig/150.ttys +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= ttys + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/ttys/USAGE b/usr.sbin/bsdconfig/ttys/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/ttys/include/Makefile b/usr.sbin/bsdconfig/ttys/include/Makefile new file mode 100644 index 000000000..9333abecd --- /dev/null +++ b/usr.sbin/bsdconfig/ttys/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/150.ttys/include +FILES= messages.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/ttys/include/messages.subr b/usr.sbin/bsdconfig/ttys/include/messages.subr new file mode 100644 index 000000000..296f75602 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/ttys/ttys b/usr.sbin/bsdconfig/ttys/ttys new file mode 100755 index 000000000..999ce7619 --- /dev/null +++ b/usr.sbin/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# +# Default text-editor to use +# +: ${EDITOR:=ee} + + +# +# If X11 is requested, which terminal and what options should we use? +# +X11TERM=xterm +X11TERM_OPTS= + +# +# Location of ttys(5) +# +ETC_TTYS=/etc/ttys + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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/usr.sbin/bsdconfig/usermgmt/INDEX b/usr.sbin/bsdconfig/usermgmt/INDEX new file mode 100644 index 000000000..6fc61eaa1 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/usermgmt/Makefile b/usr.sbin/bsdconfig/usermgmt/Makefile new file mode 100644 index 000000000..910d38062 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +NO_OBJ= + +SUBDIR= include share + +FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt +FILES= INDEX USAGE + +SCRIPTSDIR= ${FILESDIR} +SCRIPTS= groupadd groupdel groupedit groupinput \ + useradd userdel useredit userinput usermgmt + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/usermgmt/USAGE b/usr.sbin/bsdconfig/usermgmt/USAGE new file mode 100644 index 000000000..a06d8af24 --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/usermgmt/groupadd b/usr.sbin/bsdconfig/usermgmt/groupadd new file mode 100755 index 000000000..6f806a65a --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupadd @@ -0,0 +1,64 @@ +#!/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 + +BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt" + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts h$GETOPTS_STDARGS flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Chain-load to groupinput to centralize code and minimize duplication +# +$BSDCFG_LIBE/$APP_DIR/groupinput ${USE_XDIALOG:+-X} mode="Add" + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/groupdel b/usr.sbin/bsdconfig/usermgmt/groupdel new file mode 100755 index 000000000..30762168e --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupdel @@ -0,0 +1,92 @@ +#!/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 +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 + +# +# 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 0 ] || f_die + + [ "$mtag" = "X $msg_exit" ] && break + + # Anything else is a group name + + $BSDCFG_LIBE/$APP_DIR/groupinput \ + ${USE_XDIALOG:+-X} mode="Delete" group="$mtag" +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/groupedit b/usr.sbin/bsdconfig/usermgmt/groupedit new file mode 100755 index 000000000..1f1c744d6 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupedit @@ -0,0 +1,92 @@ +#!/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 +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 + +# +# 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=%s mtag=[%s]" $retval "$mtag" + defaultitem="$mtag" + + [ $retval -eq 0 ] || f_die + + [ "$mtag" = "X $msg_exit" ] && break + + # Anything else is a group name + + $BSDCFG_LIBE/$APP_DIR/groupinput \ + ${USE_XDIALOG:+-X} mode="Edit/View" group="$mtag" +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/groupinput b/usr.sbin/bsdconfig/usermgmt/groupinput new file mode 100755 index 000000000..6fff40fa3 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/groupinput @@ -0,0 +1,307 @@ +#!/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 +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# set some reasonable defaults if /etc/adduser.conf does not exist. +[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf +: ${passwdtype:="yes"} + +############################################################ FUNCTIONS + +# save_changes +# +# Save any/all settings (actions performed depend on $mode value). +# +save_changes() +{ + local err retval=$SUCCESS + + case "$mode" in + Delete) + err=$( pw groupdel "$group_name" 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_error $err\n" + return $retval + fi + f_show_msg "$msg_group_deleted" + ;; + Add) + local cmd="pw groupadd -n '$group_name'" + [ "$group_gid" ] && cmd="$cmd -g '$group_gid'" + [ "$group_members" != "$cur_group_members" ] && + cmd="$cmd -M '$group_members'" + if [ "$pw_group_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$group_password" ]; then + cmd="echo \"\$group_password\" | $cmd -h 0" + fi + f_dprintf "cmd=%s" "$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_error $err\n" + return $retval + fi + f_show_msg "$msg_group_added" + ;; + Edit/View) + local cmd="pw groupmod -n '$group_name'" + [ "$group_gid" ] && cmd="$cmd -g '$group_gid'" + [ "$group_members" != "$cur_group_members" ] && + cmd="$cmd -M '$group_members'" + if [ "$pw_group_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$group_password" ]; then + cmd="echo \"\$group_password\" | $cmd -h 0" + fi + f_dprintf "cmd=%s" "$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_error $err\n" + return $retval + fi + f_show_msg "$msg_group_updated" + ;; + esac + + save_flag= + return $SUCCESS +} + +# dialog_title_update $mode +# +# Set the title based on the given $mode. +# +dialog_title_update() +{ + local mode="$1" + case "$mode" in + Add) f_dialog_title "$msg_add $msg_group" ;; + Edit/View) f_dialog_title "$msg_edit_view $msg_group: $group" ;; + Delete) f_dialog_title "$msg_delete $msg_group: $group" ;; + esac +} + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while [ $# -gt 0 ]; do + key="${1%%=*}" + value="${1#*=}" + f_dprintf "key=[%s] value=[%s]" "$key" "$value" + case "$key" in + mode) mode="$value" ;; + group) group="$value" ;; + esac + shift +done +f_dprintf "mode=[%s] group=[%s]" "$mode" "$group" + +# +# Initialize +# +dialog_title_update "$mode" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init +menu_text= +save_flag= +hline="$hline_arrows_tab_enter" + +if [ "$mode" = "Add" ]; then + f_dialog_input_group_name || exit 0 + + f_dialog_noyes "$msg_use_default_values_for_all_account_details" + retval=$? + + if [ $retval -eq 255 ]; then # User pressed ESC + exit $SUCCESS + elif [ $retval -ne $SUCCESS ]; then + # + # Ask a series of questions to pre-fill the editor screen. + # + # The defaults used in each dialog should allow the user to + # simply hit ENTER to proceed, because cancelling a single + # dialog will cause them to be returned to the main groupmenu. + # + + [ "$passwdtype" = "yes" ] && + { f_dialog_input_group_password || exit 0; } + f_dialog_input_group_gid || exit 0 + f_dialog_input_group_members || exit 0 + fi +fi + +if [ "$mode" = "Edit/View" -o "$mode" = "Delete" ]; then + f_input_group "$group" || f_die 1 "$msg_group_not_found" +fi + +cur_group_name="$group_name" +cur_group_password="$group_password" +cur_group_gid="$group_gid" +cur_group_members="$group_members" + +[ "$mode" = "Delete" ] && save_flag=1 + +# +# Loop until the user decides to Exit, Cancel, or presses ESC +# +while :; do + dialog_title_update "$mode" + + menu_text= + menu_exit="$msg_exit" + if [ "$save_flag" ]; then + if [ "$mode" = "Delete" ]; then + menu_exit="$msg_delete/$msg_exit" + menu_text="$msg_delete_exit_or_cancel" + else + menu_exit="$msg_save/$msg_exit" + menu_text="$msg_save_exit_or_cancel" + fi + fi + + case "$mode" in + Delete) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_group: $group_name' + '-' '$msg_password: -----' + '-' '$msg_group_id: $group_gid' + '-' '$msg_group_members: $group_members' + " # END-QUOTE + ;; + *) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_group: $group_name' + '2' '$msg_password: -----' + '3' '$msg_group_id: $group_gid' + '4' '$msg_group_members: $group_members' + " # END-QUOTE + esac + + eval f_dialog_menu_size height width rows \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$menu_text\" \ + \"\$hline\" \ + $menu_items + + f_dialog_default_fetch defaultitem + mtag=$( eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --default-item \"\$defaultitem\" \ + --menu \"\$menu_text\" \ + $height $width $rows \ + $menu_items \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + retval=$? + f_dialog_data_sanitize mtag + f_dialog_default_store "$mtag" + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" + + # Exit if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || f_die + + case "$mtag" in + X) # Exit + if [ "$save_flag" ]; then + save_changes || continue + fi + break + ;; + 1) # Group Name + case "$mode" in + Add) f_dialog_input_group_name "$group_name" ;; + Edit/View|Delete) + f_dialog_menu_group_list "$group_name" + retval=$? + f_dialog_menutag_fetch mtag + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" + + # Loop if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || continue + + [ "$mtag" = "X $msg_exit" ] && continue + + group="$mtag" + f_input_group "$group" || f_die 1 "$msg_group_not_found" + cur_group_name="$group_name" + cur_group_password="$group_password" + cur_group_gid="$group_gid" + cur_group_members="$group_members" + [ "$mode" != "Delete" ] && save_flag= + esac + ;; + 2) # Password + f_dialog_input_group_password + ;; + 3) # GID + f_dialog_input_group_gid "$group_gid" + ;; + 4) # Users in Group + f_dialog_input_group_members "$group_members" + ;; + esac + +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/include/Makefile b/usr.sbin/bsdconfig/usermgmt/include/Makefile new file mode 100644 index 000000000..25d2a07ae --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/include/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt/include +FILES= messages.subr usermgmt.hlp + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/usermgmt/include/messages.subr b/usr.sbin/bsdconfig/usermgmt/include/messages.subr new file mode 100644 index 000000000..71cc51d92 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/include/messages.subr @@ -0,0 +1,114 @@ +# 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$ + +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_expires_in_how_many_days="Account expires in how many days?" +msg_account_expires_on="Account Expires on" +msg_account_does_not_expire="Account does not expire" +msg_add="Add" +msg_add_group="Add Group" +msg_add_login="Add Login" +msg_cancel="Cancel" +msg_continue="Continue" +msg_create_dotfiles="Create Dotfiles" +msg_create_home_directory="Create Home Directory" +msg_delete="Delete" +msg_delete_exit_or_cancel="Choose Delete/Exit when finished or Cancel." +msg_delete_group="Delete Group" +msg_delete_home_directory="Delete Home Directory" +msg_delete_login="Delete Login" +msg_delete_primary_group="Delete Primary Group" +msg_deleting_home_directory="Deleting home directory..." +msg_disable_password_auth_for_account="Disable password authentication for this account?" +msg_disable_password_auth_for_group="Disable password authentication for this group?" +msg_edit_date_time_with_a_calendar="Edit date/time with a calendar" +msg_edit_group="Edit/View Group" +msg_edit_login="Edit/View Login" +msg_edit_view="Edit/View" +msg_enter_group_members_manually="Enter Group Members manually" +msg_enter_number_of_days_into_the_future="Enter number of days into the future" +msg_enter_value_manually="Edit value manually" +msg_error="ERROR!" +msg_exit="Exit" +msg_full_name="Full Name" +msg_group="Group" +msg_group_added="Group Added" +msg_group_already_used="%s: Group is already used." +msg_group_deleted="Group Deleted" +msg_group_is_empty="Group is empty." +msg_group_id="Group ID" +msg_group_id_leave_empty_for_default="Group ID (Leave empty for default)" +msg_group_members="Group Members" +msg_group_must_start_with_letter="Group must start with a letter." +msg_group_not_found="%s: Group not found." +msg_group_password="Group Password" +msg_group_passwords_do_not_match="Group Passwords do not match." +msg_group_updated="Group Updated" +msg_home_directory="Home Directory" +msg_invalid_number_of_days="Invalid number of days." +msg_invalid_number_of_seconds="Invalid number of seconds." +msg_login="Login" +msg_login_added="Login Added" +msg_login_already_used="%s: Login is already used." +msg_login_class="Login Class" +msg_login_deleted="Login Deleted" +msg_login_is_empty="Login is empty." +msg_login_management="Login/Group Management" +msg_login_must_start_with_letter="Login must start with a letter." +msg_login_not_found="Login not found." +msg_login_updated="Login Updated" +msg_member_of_groups="Member of Groups" +msg_n_a="N/A" +msg_number_of_seconds_since_epoch="Number of seconds since the Epoch\n(1 = %s)\nNULL or zero to disable:" +msg_no="No" +msg_ok="OK" +msg_password="Password" +msg_password_expires_in_how_many_days="Password expires in how many days?" +msg_password_expires_on="Password Expires on" +msg_passwords_do_not_match="Passwords do not match." +msg_password_does_not_expire="Password does not expire" +msg_reenter_group_password="Re-enter Group Password" +msg_reenter_password="Re-enter Password" +msg_save="Save" +msg_save_exit_or_cancel="Choose Save/Exit when finished or Cancel." +msg_separated_by_commas="Separated by commas" +msg_select_group_members_from_list="Select Group Members from a list" +msg_select_login_shell="Select Login Shell" +msg_shell="Shell" +msg_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/usr.sbin/bsdconfig/usermgmt/include/usermgmt.hlp b/usr.sbin/bsdconfig/usermgmt/include/usermgmt.hlp new file mode 100644 index 000000000..77be9bdeb --- /dev/null +++ b/usr.sbin/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/usr.sbin/bsdconfig/usermgmt/share/Makefile b/usr.sbin/bsdconfig/usermgmt/share/Makefile new file mode 100644 index 000000000..d6b9e3a57 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/share/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/bsdconfig/usermgmt +FILES= group_input.subr user_input.subr + +beforeinstall: + mkdir -p ${DESTDIR}${FILESDIR} + +.include diff --git a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr new file mode 100644 index 000000000..93d981acd --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr @@ -0,0 +1,409 @@ +if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1 +# +# 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..." 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() +{ + eval $( pw groupshow "$1" | awk -F: ' + { + printf "group_name='\'%s\''\n", $1 + printf "group_password=\n" + printf "group_gid='\'%s\''\n", $3 + printf "group_members='\'%s\''\n", $4 + exit + }' ) +} + +# f_dialog_menu_group_list [$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: ' + !/^[[:space:]]*(#|$)/ { + printf "'\'%s\'\ \'%s\''\n", $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 [$group_name] +# +# Allows the user to enter a new groupname for a given group. If the user does +# not cancel or press ESC, the $group_name variable will hold the +# newly-configured value upon return. +# +# If $cur_group_name is defined, the user can enter that and by-pass error- +# checking (allowing the user to "revert" to an old value without, for example, +# being told that the groupname already exists). +# +f_dialog_input_group_name() +{ + # + # Loop until the user provides taint-free/valid input + # + local _name="$1" _input="$1" + 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 + [ "$_input" = "$_name" ] && return $SUCCESS + + # Check for reversion + if [ "$_input" = "$cur_group_name" ]; then + group_name="$cur_group_name" + return $SUCCESS + fi + + # Check for NULL entry + if [ ! "$_input" ]; then + f_show_msg "$msg_group_is_empty" + continue + fi + + # Check for invalid entry + if ! echo "$_input" | grep -q "^[[:alpha:]]"; then + f_show_msg "$msg_group_must_start_with_letter" + continue + fi + + # Check for duplicate entry + if f_quietly pw groupshow -n "$_input"; then + f_show_msg "$msg_group_already_used" "$_input" + continue + fi + + group_name="$_input" + break + done + save_flag=1 + + f_dprintf "group_name: [%s]->[%s]" "$cur_group_name" "$group_name" + + return $SUCCESS +} + +# f_dialog_input_group_password +# +# Prompt the user to enter a password (twice). +# +f_dialog_input_group_password() +{ + local 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 $SUCCESS ] || 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 $SUCCESS ] || return $retval + + # Check for password mismatch + if [ "$_password1" != "$_password2" ]; then + f_show_msg "$msg_group_passwords_do_not_match" + continue + fi + + # Check for NULL entry + if [ ! "$_password1" ]; then + f_dialog_yesno "$msg_disable_password_auth_for_group" + local retval=$? + if [ $retval -eq 255 ]; then # ESC was pressed + return $retval + elif [ $retval -eq $SUCCESS ]; then + pw_group_password_disable=1 + else + continue # back to password prompt + fi + else + pw_group_password_disable= + fi + + group_password="$_password1" + break + done + save_flag=1 + + f_dprintf "group_password: [%s]->[%s]" \ + "$cur_group_password" "$group_password" + + return $SUCCESS +} + +# f_dialog_input_group_gid [$group_gid] +# +# Allow the user to enter a new GID for a given group. If the user does not +# cancel or press ESC, the $group_gid variable will hold the newly-configured +# value upon return. +# +f_dialog_input_group_gid() +{ + local _input="$1" + + # 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 + + group_gid="$_input" + save_flag=1 + + f_dprintf "group_gid: [%s]->[%s]" "$cur_group_gid" "$group_gid" + + return $SUCCESS +} + +# f_dialog_input_group_members [$group_members] +# +# Allow the user to modify a list of members for a given group. If the user +# does not cancel or press ESC, the $group_members variable will hold the +# newly-configured value upon return. +# +f_dialog_input_group_members() +{ + local _input="$1" + 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 $SUCCESS ] || return $retval + + local _group_members + case "$menu_choice" in + X) # Exit + break ;; + 1) # Select Group Members from a list + local user check_list= + for user in $( pw usershow -a | + awk -F: '!/^[[:space:]]*(#|$)/{print $1}' + ); do + # Format of a checklist entry: tag item status + if echo "$_input" | grep -q "\<$user\>"; then + check_list="$check_list $user '' on" + else + check_list="$check_list $user '' off" + fi + 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 + _group_members=$( echo "$_group_members" | + tr '\n' ' ' | + sed -e 's/[[:space:]]\{1,\}/,/g;s/^,//;s/,$//' + ) + + _input="$_group_members" + ;; + 2) # Enter Group Members manually + local p="$msg_group_members ($msg_separated_by_commas)" + + f_dialog_input _group_members "$p" "$_input" \ + "$hline_num_tab_enter" || continue + # Return to previous menu if user either + # pressed ESC or chose Cancel/No + + _input="$_group_members" + ;; + esac + done + + group_members="$_input" + save_flag=1 + f_dprintf "group_members: [%s]->[%s]" \ + "$cur_group_members" "$group_members" + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr + +fi # ! $_USERMGMT_GROUP_INPUT_SUBR diff --git a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr new file mode 100644 index 000000000..21bfbd375 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr @@ -0,0 +1,1025 @@ +if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1 +# +# 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..." 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 $user +# +# Get a list of additional groups $user is a member of in group(5). +# +f_get_member_groups() +{ + echo $( pw groupshow -a | awk -F: "/[:,]$1(,|\$)/{print \$1}" ) +} + +# f_input_user $user +# +# Given $user name or id, create the environment variables pw_name, pw_uid, +# pw_gid, pw_class, pw_password_expire, pw_account_expire, pw_gecos, +# pw_home_dir, pw_shell, and pw_member_groups (and pw_password is reset to +# NULL). +# +f_input_user() +{ + local user="$1" + eval $( pw usershow "$user" | awk -F: ' + { + printf "pw_name='\'%s\''\n", $1 + printf "pw_password=\n" + printf "pw_uid='\'%s\''\n", $3 + printf "pw_gid='\'%s\''\n", $4 + printf "pw_class='\'%s\''\n", $5 + printf "pw_password_expire='\'%s\''\n", $6 + printf "pw_account_expire='\'%s\''\n", $7 + printf "pw_gecos='\'%s\''\n", $8 + printf "pw_home_dir='\'%s\''\n", $9 + printf "pw_shell='\'%s\''\n", $10 + }' ) + pw_member_groups=$( f_get_member_groups "$user" ) +} + +# f_dialog_menu_user_list [$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: ' + !/^[[:space:]]*(#|$)/ { + printf "'\'%s\'\ \'%s\''\n", $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 [$member_groups] +# +# Allows the user to edit group memberships for a given user. If the user does +# not cancel or press ESC, the $pw_member_groups variable will hold the newly- +# configured value upon return. +# +f_dialog_input_member_groups() +{ + local _member_groups="$1" + local prompt="$msg_member_of_groups" + local check_list= # Calculated below + local hline="$hline_alnum_space_tab_enter" + local group + + # + # Generate the checklist menu + # + for group in $( + pw groupshow -a | awk -F: '!/^[[:space:]]*(#|$)/{print $1}' + ); do + # Format of a checklist menu entry is "tag item status" + # (setting both tag and item to the group name below). + if echo "$_member_groups" | grep -q "\<$group\>"; then + check_list="$check_list $group $group on" + else + check_list="$check_list $group $group off" + fi + done + + # + # Loop until the user provides taint-free/valid input + # + local height width rows + while :; do + eval f_dialog_checklist_size height width rows \ + \"\$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\" \ + $height $width $rows \ + $check_list \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) || return $? + # Return if user either pressed ESC or chose Cancel/No + f_dialog_data_sanitize _member_groups + + # + # Validate each of the groups the user has entered + # + local all_groups_valid=1 + for group in $_member_groups; do + if ! f_quietly pw groupshow -n "$group"; then + f_show_msg "$msg_group_not_found" "$group" + all_groups_valid= + break + fi + done + [ "$all_groups_valid" ] || continue + + pw_member_groups="$_member_groups" + break + done + save_flag=1 + + f_dprintf "pw_member_groups: [%s]->[%s]" \ + "$cur_pw_member_groups" "$pw_member_groups" + + return $SUCCESS +} + +# f_dialog_input_name [$name] +# +# Allows the user to enter a new username for a given user. If the user does +# not cancel or press ESC, the $pw_name variable will hold the newly-configured +# value upon return. +# +# If $cur_pw_name is defined, the user can enter that and by-pass error- +# checking (allowing the user to "revert" to an old value without, for example, +# being told that the username already exists). +# +f_dialog_input_name() +{ + # + # Loop until the user provides taint-free/valid input + # + local _name="$1" _input="$1" + 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 + [ "$_input" = "$_name" ] && return $SUCCESS + + # Check for reversion + if [ "$_input" = "$cur_pw_name" ]; then + pw_name="$cur_pw_name" + return $SUCCESS + fi + + # Check for NULL entry + if [ ! "$_input" ]; then + f_show_msg "$msg_login_is_empty" + continue + fi + + # Check for invalid entry + if ! echo "$_input" | grep -q "^[[:alpha:]]"; then + f_show_msg "$msg_login_must_start_with_letter" + continue + fi + + # Check for duplicate entry + if f_quietly pw usershow -n "$_input"; then + f_show_msg "$msg_login_already_used" "$_input" + continue + fi + + pw_name="$_input" + break + done + save_flag=1 + + f_dprintf "pw_name: [%s]->[%s]" "$cur_pw_name" "$pw_name" + + return $SUCCESS +} + +# f_dialog_input_password +# +# Prompt the user to enter a password (twice). +# +f_dialog_input_password() +{ + 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 _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" + local retval=$? + if [ $retval -eq 255 ]; then # ESC was pressed + return $retval + elif [ $retval -eq $SUCCESS ]; then + pw_password_disable=1 + else + continue # back to password prompt + fi + else + pw_password_disable= + fi + + pw_password="$_password1" + break + done + save_flag=1 + + f_dprintf "pw_password: [%s]->[%s]" "$cur_pw_password" "$pw_password" + + return $SUCCESS +} + +# f_dialog_input_gecos [$gecos] +# +# Allow the user to enter new GECOS information for a given user. This +# information is commonly used to store the ``Full Name'' of the user. If the +# user does not cancel or press ESC, the $pw_gecos variable will hold the +# newly-configured value upon return. +# +f_dialog_input_gecos() +{ + local _input="$1" + + # 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 + + pw_gecos="$_input" + save_flag=1 + + f_dprintf "pw_gecos: [%s]->[%s]" "$cur_pw_gecos" "$pw_gecos" + + return $SUCCESS +} + +# f_dialog_input_uid [$uid] +# +# Allow the user to enter a new UID for a given user. If the user does not +# cancel or press ESC, the $pw_uid variable will hold the newly-configured +# value upon return. +# +f_dialog_input_uid() +{ + local _input="$1" + + # 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 + + pw_uid="$_input" + save_flag=1 + + f_dprintf "pw_uid: [%s]->[%s]" "$cur_pw_uid" "$pw_uid" + + return $SUCCESS +} + +# f_dialog_input_gid [$gid] +# +# Allow the user to enter a new primary GID for a given user. If the user does +# not cancel or press ESC, the $pw_gid variable will hold the newly-configured +# value upon return. +# +f_dialog_input_gid() +{ + local _input="$1" + + # 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 + + pw_gid="$_input" + save_flag=1 + + f_dprintf "pw_gid: [%s]->[%s]" "$cur_pw_gid" "$pw_gid" + + return $SUCCESS +} + +# f_dialog_input_class [$class] +# +# Allow the user to enter a new login class for a given user. If the user does +# not cancel or press ESC, the $pw_class variable will hold the newly- +# configured value upon return. +# +f_dialog_input_class() +{ + local _input="$1" + + # Return if user has either pressed ESC or chosen Cancel/No + f_dialog_input _input "$msg_login_class" "$_input" \ + "$hline_alnum_tab_enter" || return + + pw_class="$_input" + save_flag=1 + + f_dprintf "pw_class: [%s]->[%s]" "$cur_pw_class" "$pw_class" + + return $SUCCESS +} + +# f_dialog_input_expire_password [$seconds] +# +# Allow the user to enter a date/time (in number-of-seconds since the `epoch') +# for when a given user's password must be changed. If the user does not cancel +# or press ESC, the $pw_password_expire variable will hold the newly- +# configured value upon return. +# +f_dialog_input_expire_password() +{ + 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_number_of_days_into_the_future' + '4' '$msg_enter_value_manually' + " # END-QUOTE + local hline="$hline_num_arrows_tab_enter" + local retval _input="$1" + + 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 date_type defaultitem= + 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 $SUCCESS ] || return $retval + + case "$date_type" in + 1) # Password does not expire + _input="" + break ;; + + 2) # Edit date/time with a calendar + local _input_date _input_time ret_date ret_time + + local secs="$_input" + { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= + _input_date=$( date -j -f "%s" -- "$secs" \ + "+%d %m %Y" 2> /dev/null ) + 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 $SUCCESS ] || continue + + _input_time= + [ "$secs" ] && _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 $SUCCESS ] || 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 number of days into the future + local ret_days seconds="$( date +%s )" + + f_isinteger "$_input" || _input=0 + [ $_input -gt 0 -a $_input -gt $seconds ] && + ret_days=$(( ( $_input - $seconds ) / 86400 )) + f_isinteger "$ret_days" && + ret_days=$(( $ret_days + 1 )) + + # Return to menu if either ESC or Cancel/No + f_dialog_input ret_days \ + "$msg_password_expires_in_how_many_days" \ + "$ret_days" "$hline" || continue + + # Taint-check the user's input + if ! f_isinteger "$ret_days"; then + f_show_msg "$msg_invalid_number_of_days" + continue + fi + + f_dprintf "ret_days=[%s]" "$ret_days" + case "$ret_days" in + [-+]*) _input=$( date -v${ret_days}d +%s ) ;; + 0) _input=$( date +%s ) ;; + *) _input=$( date -v+${ret_days}d +%s ) ;; + esac + f_dprintf "_input=[%s]" "$_input" + break ;; + + 4) # Enter value manually + local msg ret_secs + msg=$( printf "$msg_number_of_seconds_since_epoch" \ + "$( date -r 1 "+%c %Z" )" ) + + # Return to menu if either ESC or Cancel/No + f_dialog_input ret_secs \ + "$msg" "$_input" "$hline" || continue + + _input="$ret_secs" + + # Taint-check the user's input + if ! f_isinteger "${_input:-0}"; then + f_show_msg "$msg_invalid_number_of_seconds" + continue + fi + + f_dprintf "_input=[%s]" "$_input" + break ;; + + esac + + done # Loop forever + + pw_password_expire="$_input" + save_flag=1 + + f_dprintf "pw_password_expire: [%s]->[%s]" \ + "$cur_pw_password_expire" "$pw_password_expire" + + return $SUCCESS +} + +# f_dialog_input_expire_account [$seconds] +# +# Allow the user to enter a date/time (in number-of-seconds since the `epoch') +# for when a given user's account should become expired. If the user does not +# cancel or press ESC, the $pw_account_expire variable will hold the newly- +# configured value upon return. +# +f_dialog_input_expire_account() +{ + 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_number_of_days_into_the_future' + '4' '$msg_enter_value_manually' + " # END-QUOTE + local hline="$hline_num_arrows_tab_enter" + local retval _input="$1" + + 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 date_type defaultitem= + 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 $SUCCESS ] || return $retval + + case "$date_type" in + 1) # Account does not expire + _input="" + break ;; + + 2) # Edit date/time with a calendar + local _input_date _input_time ret_date ret_time + + local secs="$_input" + { f_isinteger "$secs" && [ $secs -gt 0 ]; } || secs= + _input_date=$( date -j -f "%s" -- "$secs" \ + "+%d %m %Y" 2> /dev/null ) + 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 $SUCCESS ] || continue + + _input_time= + [ "$secs" ] && _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 $SUCCESS ] || 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 number of days into the future + local ret_days seconds="$( date +%s )" + + f_isinteger "$_input" || _input=0 + [ $_input -gt 0 -a $_input -gt $seconds ] && + ret_days=$(( ( $_input - $seconds ) / 86400 )) + f_isinteger "$ret_days" && + ret_days=$(( $ret_days + 1 )) + + # Return to menu if either ESC or Cancel/No + f_dialog_input ret_days \ + "$msg_account_expires_in_how_many_days" \ + "$ret_days" "$hline" || continue + + # Taint-check the user's input + if ! f_isinteger "$ret_days"; then + f_show_msg "$msg_invalid_number_of_days" + continue + fi + + f_dprintf "ret_days=[%s]" "$ret_days" + case "$ret_days" in + [-+]*) _input=$( date -v${ret_days}d +%s ) ;; + 0) _input=$( date +%s ) ;; + *) _input=$( date -v+${ret_days}d +%s ) ;; + esac + f_dprintf "_input=[%s]" "$_input" + break ;; + + 4) # Enter value manually + local msg ret_secs + msg=$( printf "$msg_number_of_seconds_since_epoch" \ + "$( date -r 1 "+%c %Z" )" ) + + # Return to menu if either ESC or Cancel/No + f_dialog_input ret_secs "$msg" \ + "$_input" "$hline" || continue + + _input="$ret_secs" + + # Taint-check the user's input + if ! f_isinteger "${_input:-0}"; then + f_show_msg "$msg_invalid_number_of_seconds" + continue + fi + + f_dprintf "_input=[%s]" "$_input" + break ;; + + esac + + done # Loop forever + + pw_account_expire="$_input" + save_flag=1 + + f_dprintf "pw_account_expire: [%s]->[%s]" \ + "$cur_pw_account_expire" "$pw_account_expire" + + return $SUCCESS +} + +# f_dialog_input_home_dir [$home_dir] +# +# Allow the user to enter a new home directory for a given user. If the user +# does not cancel or press ESC, the $pw_home_dir variable will hold the newly- +# configured value upon return. +# +f_dialog_input_home_dir() +{ + local _input="$1" + + # 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 + + pw_home_dir="$_input" + save_flag=1 + + f_dprintf "pw_home_dir: [%s]->[%s]" "$cur_pw_home_dir" "$pw_home_dir" + + return $SUCCESS +} + +# f_dialog_input_home_create +# +# Prompt the user to confirm creation of a given user's home directory. If the +# user does not cancel (by choosing "No") or press ESC, the $pw_home_create +# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return +# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. +# +f_dialog_input_home_create() +{ + local retval + + f_dialog_yesno "$msg_create_home_directory" + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_home_create="$msg_yes" + else + pw_home_create="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_home_create: [%s]->[%s]" \ + "$cur_pw_home_create" "$pw_home_create" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_group_delete +# +# Prompt the user to confirm deletion of a given user's primary group. If the +# user does not cancel (by choosing "No") or press ESC, the $pw_group_delete +# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return +# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. +# +f_dialog_input_group_delete() +{ + local retval + + if f_isinteger "$pw_gid"; then + if [ $pw_gid -lt 1000 ]; then + f_dialog_noyes "$msg_delete_primary_group" + else + f_dialog_yesno "$msg_delete_primary_group" + fi + elif [ "$pw_gid" ]; then + local gid=0 + gid=$( pw groupshow "$pw_gid" | awk -F: '{print $3}' ) + if f_isinteger "$gid" && [ $gid -lt 1000 ]; then + f_dialog_noyes "$msg_delete_primary_group" + else + f_dialog_yesno "$msg_delete_primary_group" + fi + else + f_dialog_yesno "$msg_delete_primary_group" + fi + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_group_delete="$msg_yes" + else + pw_group_delete="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_group_delete: [%s]->[%s]" \ + "$cur_pw_group_delete" "$pw_group_delete" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_home_delete +# +# Prompt the user to confirm deletion of a given user's home directory. If the +# user does not cancel (by choosing "No") or press ESC, the $pw_home_delete +# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return +# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible. +# +f_dialog_input_home_delete() +{ + local retval + + f_dialog_yesno "$msg_delete_home_directory" + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_home_delete="$msg_yes" + else + pw_home_delete="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_home_delete: [%s]->[%s]" \ + "$cur_pw_home_delete" "$pw_home_delete" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_dotfiles_create +# +# Prompt the user to confirm population of a given user's home directory with +# sample dotfiles. If the user does not cancel (by choosing "No") or press ESC, +# the $pw_dotfiles_create variable will hold $msg_yes upon return, otherwise +# $msg_no. Use these return variables ($msg_yes and $msg_no) for comparison to +# be i18n-compatible. +# +f_dialog_input_dotfiles_create() +{ + local retval + + f_dialog_yesno "$msg_create_dotfiles" + retval=$? + + if [ $retval -eq $SUCCESS ]; then + pw_dotfiles_create="$msg_yes" + else + pw_dotfiles_create="$msg_no" + fi + save_flag=1 + + f_dprintf "pw_dotfiles_create: [%s]->[%s]" \ + "$cur_pw_dotfiles_create" "$pw_dotfiles_create" + + [ $retval -ne 255 ] # return failure if user pressed ESC +} + +# f_dialog_input_shell [$shell] +# +# Allow the user to select a new login shell for a given user. If the user does +# not cancel or press ESC, the $pw_home_dir variable will hold the newly- +# configured value upon return. +# +# +f_dialog_input_shell() +{ + local _input="$1" + local prompt="$msg_select_login_shell" + local radio_list= # Calculated below + local hline="$hline_arrows_space_tab_enter" + + # + # Generate the radiolist of shells + # + local shell + for shell in $( awk '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" ); do + # Format of a radiolist menu entry is "tag item status" + if [ "$shell" = "$_input" ]; then + radio_list="$radio_list '$shell' '' 'on'" + else + radio_list="$radio_list '$shell' '' 'off'" + fi + 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\" \ + --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 + + pw_shell="$_input" + save_flag=1 + + f_dprintf "pw_shell: [%s]->[%s]" "$cur_pw_shell" "$pw_shell" + + return $SUCCESS +} + +############################################################ MAIN + +f_dprintf "%s: Successfully loaded." usermgmt/user_input.subr + +fi # ! $_USERMGMT_USER_INPUT_SUBR diff --git a/usr.sbin/bsdconfig/usermgmt/useradd b/usr.sbin/bsdconfig/usermgmt/useradd new file mode 100755 index 000000000..b8cac27ba --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/useradd @@ -0,0 +1,64 @@ +#!/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 + +BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt" + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts h$GETOPTS_STDARGS flag; do + case "$flag" in + h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;; + esac +done +shift $(( $OPTIND - 1 )) + +# +# Chain-load to userinput to centralize code and minimize duplication +# +$BSDCFG_LIBE/$APP_DIR/userinput ${USE_XDIALOG:+-X} mode="Add" + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/userdel b/usr.sbin/bsdconfig/usermgmt/userdel new file mode 100755 index 000000000..f26649798 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/userdel @@ -0,0 +1,92 @@ +#!/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 +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 + +# +# 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 0 ] || f_die + + [ "$mtag" = "X $msg_exit" ] && break + + # Anything else is a userid + + $BSDCFG_LIBE/$APP_DIR/userinput \ + ${USE_XDIALOG:+-X} mode="Delete" user="$mtag" +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/useredit b/usr.sbin/bsdconfig/usermgmt/useredit new file mode 100755 index 000000000..64b7b8e2f --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/useredit @@ -0,0 +1,92 @@ +#!/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 +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while getopts 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 + +# +# 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 0 ] || f_die + + [ "$mtag" = "X $msg_exit" ] && break + + # Anything else is a userid + + $BSDCFG_LIBE/$APP_DIR/userinput \ + ${USE_XDIALOG:+-X} mode="Edit/View" user="$mtag" +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/userinput b/usr.sbin/bsdconfig/usermgmt/userinput new file mode 100755 index 000000000..196262b22 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/userinput @@ -0,0 +1,529 @@ +#!/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 +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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ CONFIGURATION + +# set some reasonable defaults if /etc/adduser.conf does not exist. +[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf +: ${passwdtype:="yes"} +: ${homeprefix:="/home"} +: ${defaultshell:="/bin/sh"} +: ${udotdir:="/usr/share/skel"} + +############################################################ FUNCTIONS + +# copy_dotfiles +# +# Copy `skel' dot-files to a new home directory. +# +copy_dotfiles() +{ + ( # Operate within sub-shell to protect CWD/glob of parent + cd "$udotdir" || exit $? + set +f # glob + for file in dot.*; do + cp -n "$file" "$pw_home_dir/${file#dot}" || exit $? + done + ) +} + +# save_changes +# +# Save any/all settings (actions performed depend on $mode value). +# +save_changes() +{ + local err retval=$SUCCESS + + case "$mode" in + Delete) + err=$( pw userdel -u "$pw_uid" 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_error $err\n" + return $retval + fi + f_show_msg "$msg_login_deleted" + + if [ "$pw_group_delete" = "$msg_yes" ] && + f_quietly pw groupshow -g "$pw_gid" + then + err=$( pw groupdel -g "$pw_gid" 2>&1 ) || + f_dialog_msgbox "$msg_warning $err\n" + fi + + if [ "$pw_home_delete" = "$msg_yes" ]; then + f_dialog_info "$msg_deleting_home_directory" + err=$( rm -Rf "$pw_home_dir" 2>&1 ) || + f_dialog_msgbox "$msg_warning $err\n" + fi + ;; + Add) + local cmd="pw useradd -n '$pw_name'" + [ "$pw_member_groups" ] && cmd="$cmd -G '$pw_member_groups'" + [ "$pw_class" ] && cmd="$cmd -L '$pw_class'" + [ "$pw_gecos" ] && cmd="$cmd -c '$pw_gecos'" + [ "$pw_home_dir" ] && cmd="$cmd -d '$pw_home_dir'" + [ "$pw_account_expire" ] && cmd="$cmd -e '$pw_account_expire'" + [ "$pw_gid" ] && cmd="$cmd -g '$pw_gid'" + [ "$pw_password_expire" ] && cmd="$cmd -p '$pw_password_expire'" + [ "$pw_shell" ] && cmd="$cmd -s '$pw_shell'" + [ "$pw_uid" ] && cmd="$cmd -u '$pw_uid'" + if [ "$pw_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$pw_password" ]; then + cmd="echo \"\$pw_password\" | $cmd -h 0" + fi + f_dprintf "cmd=%s" "$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_error $err\n" + return $retval + fi + f_show_msg "$msg_login_added" + + if [ "$pw_home_create" = "$msg_yes" ]; then + err=$( mkdir -p "$pw_home_dir" 2>&1 ) + if [ $? -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_warning $err\n" + elif [ -e "$pw_home_dir" ]; then + err=$( chown -R "$pw_uid:$pw_gid" \ + "$pw_home_dir" 2>&1 ) + [ $? -eq $SUCCESS ] || + f_dialog_msgbox "$msg_warning $err\n" + fi + fi + + if [ "$pw_dotfiles_create" = "$msg_yes" ]; then + err=$( copy_dotfiles 2>&1 ) || + f_dialog_msgbox "$msg_warning $err\n" + fi + + user="$pw_name" + f_quietly pw usershow -n "$pw_name" && + mode="Edit/View" # Change mode + ;; + Edit/View) + local cmd="pw usermod -n '$pw_name'" + [ "$pw_member_groups" ] && cmd="$cmd -G '$pw_member_groups'" + [ "$pw_class" ] && cmd="$cmd -L '$pw_class'" + [ "$pw_gecos" ] && cmd="$cmd -c '$pw_gecos'" + [ "$pw_home_dir" ] && cmd="$cmd -d '$pw_home_dir'" + [ "$pw_account_expire" ] && cmd="$cmd -e '$pw_account_expire'" + [ "$pw_gid" ] && cmd="$cmd -g '$pw_gid'" + [ "$pw_password_expire" ] && cmd="$cmd -p '$pw_password_expire'" + [ "$pw_shell" ] && cmd="$cmd -s '$pw_shell'" + [ "$pw_uid" ] && cmd="$cmd -u '$pw_uid'" + if [ "$pw_password_disable" ]; then + cmd="$cmd -h -" + elif [ "$pw_password" ]; then + cmd="echo \"\$pw_password\" | $cmd -h 0" + fi + f_dprintf "cmd=%s" "$cmd" + err=$( eval $cmd 2>&1 ) + retval=$? + if [ $retval -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_error $err\n" + return $retval + fi + f_show_msg "$msg_login_updated" + + if [ "$pw_home_create" = "$msg_yes" ]; then + err=$( mkdir -p "$pw_home_dir" ) + if [ $? -ne $SUCCESS ]; then + f_dialog_msgbox "$msg_warning $err\n" + elif [ -e "$pw_home_dir" ]; then + err=$( chown -R "$pw_uid:$pw_gid" \ + "$pw_home_dir" 2>&1 ) + [ $? -eq $SUCCESS ] || + f_dialog_msgbox "$msg_warning $err\n" + fi + fi + + if [ "$pw_dotfiles_create" = "$msg_yes" ]; then + err=$( copy_dotfiles 2>&1 ) || + f_dialog_msgbox "$msg_warning $err\n" + fi + ;; + esac + + save_flag= + return $SUCCESS +} + +# dialog_title_update $mode +# +# Set the title based on the given $mode. +# +dialog_title_update() +{ + local mode="$1" + case "$mode" in + Add) f_dialog_title "$msg_add $msg_user" ;; + Edit/View) f_dialog_title "$msg_edit_view $msg_user: $user" ;; + Delete) f_dialog_title "$msg_delete $msg_user: $user" ;; + esac +} + +############################################################ MAIN + +# Incorporate rc-file if it exists +[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc" + +# +# Process command-line arguments +# +while [ $# -gt 0 ]; do + key="${1%%=*}" + value="${1#*=}" + f_dprintf "key=[%s] value=[%s]" "$key" "$value" + case "$key" in + mode) mode="$value" ;; + user) user="$value" ;; + esac + shift +done +f_dprintf "mode=[%s] user=[%s]" "$mode" "$user" + +# +# Initialize +# +dialog_title_update "$mode" +f_dialog_backtitle "${ipgm:+bsdconfig }$pgm" +f_mustberoot_init +menu_text= +save_flag= +hline="$hline_arrows_tab_enter" + +if [ "$mode" = "Add" ]; then + f_dialog_input_name || exit 0 + + # + # Set some sensible defaults for account attributes + # + pw_gecos="${pw_gecos-$pw_name}" + pw_home_dir="${pw_home_dir:-$homeprefix/$pw_name}" + if [ -d "$pw_home_dir" ]; then + pw_home_create="${pw_home_create:-$msg_no}" + pw_dotfiles_create="${pw_dotfiles_create:-$msg_no}" + else + pw_home_create="${pw_home_create:-$msg_yes}" + pw_dotfiles_create="${pw_dotfiles_create:-$msg_yes}" + fi + pw_shell="${pw_shell:-$defaultshell}" + + f_dialog_noyes "$msg_use_default_values_for_all_account_details" + retval=$? + + if [ $retval -eq 255 ]; then # User pressed ESC + exit $SUCCESS + elif [ $retval -ne $SUCCESS ]; then + # + # Ask a series of questions to pre-fill the editor screen. + # + # The defaults used in each dialog should allow the user to + # simply hit ENTER to proceed, because cancelling a single + # dialog will cause them to be returned to the main usermenu. + # + + f_dialog_input_gecos "$pw_gecos" || exit 0 + [ "$passwdtype" = "yes" ] && + { f_dialog_input_password || exit 0; } + f_dialog_input_uid || exit 0 + f_dialog_input_gid || exit 0 + f_dialog_input_member_groups || exit 0 + f_dialog_input_class || exit 0 + f_dialog_input_expire_password || exit 0 + f_dialog_input_expire_account || exit 0 + f_dialog_input_home_dir "$pw_home_dir" || exit 0 + if [ ! -d "$pw_home_dir" ]; then + f_dialog_input_home_create || exit 0 + [ "$pw_home_create" = "$msg_yes" ] && + { f_dialog_input_dotfiles_create || exit 0; } + fi + f_dialog_input_shell "$pw_shell" || exit 0 + fi +fi + +if [ "$mode" = "Edit/View" -o "$mode" = "Delete" ]; then + f_input_user "$user" || f_die 1 "$msg_login_not_found" +fi + +if [ "$mode" = "Edit/View" ]; then + [ -d "$pw_home_dir" ] || pw_home_create="$msg_no" + pw_dotfiles_create="$msg_no" +fi + +if [ "$mode" = "Delete" ]; then + f_dialog_input_group_delete || exit 0 + pw_home_delete="$msg_no" + [ -d "$pw_home_dir" ] && + { f_dialog_input_home_delete || exit 0; } +fi + +cur_pw_name="$pw_name" +cur_pw_password="$pw_password" +cur_pw_uid="$pw_uid" +cur_pw_gid="$pw_gid" +cur_pw_member_groups="$pw_member_groups" +cur_pw_class="$pw_class" +cur_pw_password_expire="$pw_password_expire" +cur_pw_account_expire="$pw_account_expire" +cur_pw_gecos="$pw_gecos" +cur_pw_home_dir="$pw_home_dir" +cur_pw_shell="$pw_shell" +cur_pw_group_delete="$pw_group_delete" +cur_pw_home_create="$pw_home_create" +cur_pw_home_delete="$pw_home_delete" +cur_pw_dotfiles_create="$pw_dotfiles_create" + +[ "$mode" = "Delete" ] && save_flag=1 + +# +# Loop until the user decides to Exit, Cancel, or presses ESC +# +while :; do + dialog_title_update "$mode" + + menu_text= + menu_exit="$msg_exit" + if [ "$save_flag" ]; then + if [ "$mode" = "Delete" ]; then + menu_exit="$msg_delete/$msg_exit" + menu_text="$msg_delete_exit_or_cancel" + else + menu_exit="$msg_save/$msg_exit" + menu_text="$msg_save_exit_or_cancel" + fi + fi + + pw_password_expires_on="$pw_password_expire" + f_isinteger "$pw_password_expire" && [ $pw_password_expire -ne 0 ] && + pw_password_expires_on=$( + date -r "$pw_password_expire" "+%F %T %Z" + ) + pw_account_expires_on="$pw_account_expire" + f_isinteger "$pw_account_expire" && [ "$pw_account_expire" -ne 0 ] && + pw_account_expires_on=$( + date -r "$pw_account_expire" "+%F %T %Z" + ) + + case "$mode" in + Delete) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_login: $pw_name' + '-' '$msg_full_name: $pw_gecos' + '-' '$msg_password: -----' + '-' '$msg_user_id: $pw_uid' + '-' '$msg_group_id: $pw_gid' + '-' '$msg_member_of_groups: $pw_member_groups' + '-' '$msg_login_class: $pw_class' + '-' '$msg_password_expires_on: $pw_password_expires_on' + '-' '$msg_account_expires_on: $pw_account_expires_on' + '-' '$msg_home_directory: $pw_home_dir' + '-' '$msg_shell: $pw_shell' + " # END-QUOTE + ;; + *) + menu_items=" + 'X' '$menu_exit' + '1' '$msg_login: $pw_name' + '2' '$msg_full_name: $pw_gecos' + '3' '$msg_password: -----' + '4' '$msg_user_id: $pw_uid' + '5' '$msg_group_id: $pw_gid' + '6' '$msg_member_of_groups: $pw_member_groups' + '7' '$msg_login_class: $pw_class' + '8' '$msg_password_expires_on: $pw_password_expires_on' + '9' '$msg_account_expires_on: $pw_account_expires_on' + 'A' '$msg_home_directory: $pw_home_dir' + 'B' '$msg_shell: $pw_shell' + " # END-QUOTE + esac + + case "$mode" in + Add|Edit/View) + if [ -d "$pw_home_dir" ]; then menu_items="$menu_items + '-' '$msg_create_home_directory: $msg_n_a' + 'D' '$msg_create_dotfiles: $pw_dotfiles_create' + "; else menu_items="$menu_items + 'C' '$msg_create_home_directory: $pw_home_create' + 'D' '$msg_create_dotfiles: $pw_dotfiles_create' + "; fi + ;; + Delete) + if [ -d "$pw_home_dir" ]; then menu_items="$menu_items + 'C' '$msg_delete_primary_group: $pw_group_delete' + 'D' '$msg_delete_home_directory: $pw_home_delete' + "; else menu_items="$menu_items + 'C' '$msg_delete_primary_group: $pw_group_delete' + '-' '$msg_delete_home_directory: $msg_n_a' + "; fi + ;; + esac + + eval f_dialog_menu_size height width rows \ + \"\$DIALOG_TITLE\" \ + \"\$DIALOG_BACKTITLE\" \ + \"\$menu_text\" \ + \"\$hline\" \ + $menu_items + + f_dialog_default_fetch defaultitem + mtag=$( eval $DIALOG \ + --title \"\$DIALOG_TITLE\" \ + --backtitle \"\$DIALOG_BACKTITLE\" \ + --hline \"\$hline\" \ + --ok-label \"\$msg_ok\" \ + --cancel-label \"\$msg_cancel\" \ + --default-item \"\$defaultitem\" \ + --menu \"\$menu_text\" \ + $height $width $rows \ + $menu_items \ + 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD + ) + retval=$? + f_dialog_data_sanitize mtag + f_dialog_default_store "$mtag" + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" + + # Exit if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || f_die + + case "$mtag" in + X) # Exit + if [ "$save_flag" ]; then + save_changes || continue + fi + break + ;; + 1) # Login + case "$mode" in + Add) f_dialog_input_name "$pw_name" ;; + Edit/View|Delete) + f_dialog_menu_user_list "$pw_name" + retval=$? + f_dialog_menutag_fetch mtag + f_dprintf "retval=%u mtag=[%s]" $retval "$mtag" + + # Loop if user has either pressed ESC or chosen Cancel/No + [ $retval -eq $SUCCESS ] || continue + + [ "$mtag" = "X $msg_exit" ] && continue + + user="$mtag" + f_input_user "$user" || f_die 1 "$msg_login_not_found" + cur_pw_name="$pw_name" + cur_pw_password="$pw_password" + cur_pw_uid="$pw_uid" + cur_pw_gid="$pw_gid" + cur_pw_member_groups="$pw_member_groups" + cur_pw_class="$pw_class" + cur_pw_password_expire="$pw_password_expire" + cur_pw_account_expire="$pw_account_expire" + cur_pw_gecos="$pw_gecos" + cur_pw_home_dir="$pw_home_dir" + cur_pw_shell="$pw_shell" + cur_pw_group_delete="$pw_group_delete" + cur_pw_home_create="$pw_home_create" + cur_pw_home_delete="$pw_home_delete" + cur_pw_dotfiles_create="$pw_dotfiles_create" + [ "$mode" != "Delete" ] && save_flag= + esac + ;; + 2) # Full Name + f_dialog_input_gecos "$pw_gecos" ;; + 3) # Password + f_dialog_input_password ;; + 4) # UID + f_dialog_input_uid "$pw_uid" ;; + 5) # Default Group + f_dialog_input_gid "$pw_gid" ;; + 6) # Member of Groups + f_dialog_input_member_groups "$pw_member_groups" ;; + 7) # Login Class + f_dialog_input_class "$pw_class" ;; + 8) # Password Expire on + f_dialog_input_expire_password "$pw_password_expire" ;; + 9) # Account Expire on + f_dialog_input_expire_account "$pw_account_expire" ;; + A) # Home Directory + f_dialog_input_home_dir "$pw_home_dir" ;; + B) # Shell + f_dialog_input_shell "$pw_shell" ;; + esac + + case "$mode" in + Delete) + case "$mtag" in + C) # Delete Primary Group + f_dialog_input_group_delete ;; + D) # Delete Home Directory + f_dialog_input_home_delete ;; + esac + ;; + Add|Edit/View) + case "$mtag" in + C) # Create Home Directory + f_dialog_input_home_create + [ "$pw_home_create" = "$msg_no" ] && + pw_dotfiles_create="$msg_no" + ;; + D) # Create Dotfiles + f_dialog_input_dotfiles_create + [ "$pw_dotfiles_create" = "$msg_yes" ] && + pw_home_create="$msg_yes" + ;; + esac + ;; + esac +done + +exit $SUCCESS + +################################################################################ +# END +################################################################################ diff --git a/usr.sbin/bsdconfig/usermgmt/usermgmt b/usr.sbin/bsdconfig/usermgmt/usermgmt new file mode 100755 index 000000000..0a4c160b3 --- /dev/null +++ b/usr.sbin/bsdconfig/usermgmt/usermgmt @@ -0,0 +1,169 @@ +#!/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 + +ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ) +[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm" + +############################################################ FUNCTIONS + +# dialog_menu_main +# +# Display the dialog(1)-based application main menu. +# +dialog_menu_main() +{ + local 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 0 ] && 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 2 ]; then + # The Help button was pressed + f_show_help "$USERMGMT_HELPFILE" + continue + elif [ $retval -ne $SUCCESS ]; 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/usr.sbin/sysrc/Makefile b/usr.sbin/sysrc/Makefile new file mode 100644 index 000000000..ca3dc56bc --- /dev/null +++ b/usr.sbin/sysrc/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +SCRIPTS= sysrc + +MAN= sysrc.8 + +beforeinstall: + mkdir -p ${DESTDIR}${SCRIPTSDIR} + mkdir -p ${DESTDIR}${MANDIR}8 + +.include diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc new file mode 100644 index 000000000..7e1ddcb79 --- /dev/null +++ b/usr.sbin/sysrc/sysrc @@ -0,0 +1,611 @@ +#!/bin/sh +#- +# Copyright (c) 2010-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" +[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1 +[ "$_SYSRC_SUBR" ] || f_include $BSDCFG_SHARE/sysrc.subr + +############################################################ GLOBALS + +# +# Options +# +DELETE= +DESCRIBE= +IGNORE_UNKNOWNS= +JAIL= +QUIET= +ROOTDIR= +SHOW_ALL= +SHOW_EQUALS= +SHOW_FILE= +SHOW_NAME=1 +SHOW_VALUE=1 +SYSRC_VERBOSE= + +############################################################ FUNCTIONS + +# die [ $fmt [ $opts ... ]] +# +# Optionally print a message to stderr before exiting with failure status. +# +die() +{ + local fmt="$1" + [ $# -gt 0 ] && shift 1 + [ "$fmt" ] && f_err "$fmt\n" "$@" + + exit $FAILURE +} + +# usage +# +# Prints a short syntax statement and exits. +# +usage() +{ + f_err "Usage: %s [OPTIONS] name[=value] ...\n" "$pgm" + f_err "Try \`%s --help' for more information.\n" "$pgm" + die +} + +# help +# +# Prints a full syntax statement and exits. +# +help() +{ + local optfmt="\t%-11s%s\n" + local envfmt="\t%-17s%s\n" + + f_err "Usage: %s [OPTIONS] name[=value] ...\n" "$pgm" + + f_err "OPTIONS:\n" + f_err "$optfmt" "-a" \ + "Dump a list of all non-default configuration variables." + f_err "$optfmt" "-A" \ + "Dump a list of all configuration variables (incl. defaults)." + f_err "$optfmt" "-d" \ + "Print a description of the given variable." + f_err "$optfmt" "-D" \ + "Show default value(s) only (this is the same as setting" + f_err "$optfmt" "" \ + "RC_CONFS to NULL or passing \`-f' with a NULL file-argument)." + f_err "$optfmt" "-e" \ + "Print query results as \`var=value' (useful for producing" + f_err "$optfmt" "" \ + "output to be fed back in). Ignored if \`-n' is specified." + f_err "$optfmt" "-f file" \ + "Operate on the specified file(s) instead of rc_conf_files." + f_err "$optfmt" "" \ + "Can be specified multiple times for additional files." + f_err "$optfmt" "-F" \ + "Show only the last rc.conf(5) file each directive is in." + f_err "$optfmt" "-h" \ + "Print a short usage statement to stderr and exit." + f_err "$optfmt" "--help" \ + "Print this message to stderr and exit." + f_err "$optfmt" "-i" \ + "Ignore unknown variables." + f_err "$optfmt" "-j jail" \ + "The jid or name of the jail to operate within (overrides" + f_err "$optfmt" "" \ + "\`-R dir'; requires jexec(8))." + f_err "$optfmt" "-n" \ + "Show only variable values, not their names." + f_err "$optfmt" "-N" \ + "Show only variable names, not their values." + f_err "$optfmt" "-q" \ + "Quiet. Ignore previous \`-v' and/or SYSRC_VERBOSE." + f_err "$optfmt" "-R dir" \ + "Operate within the root directory \`dir' rather than \`/'." + f_err "$optfmt" "-v" \ + "Verbose. Print the pathname of the specific rc.conf(5)" + f_err "$optfmt" "" \ + "file where the directive was found." + f_err "$optfmt" "-x" \ + "Remove variable(s) from specified file(s)." + f_err "\n" + + f_err "ENVIRONMENT:\n" + f_err "$envfmt" "RC_CONFS" \ + "Override default rc_conf_files (even if set to NULL)." + f_err "$envfmt" "RC_DEFAULTS" \ + "Location of \`/etc/defaults/rc.conf' file." + f_err "$envfmt" "SYSRC_VERBOSE" \ + "Default verbosity. Set to non-NULL to enable." + + die +} + +# jail_depend +# +# Dump dependencies such as language-file variables and include files to stdout +# to be piped-into sh(1) running via jexec(8)/chroot(8). As a security measure, +# this prevents existing language files and library files from being loaded in +# the jail. This also relaxes the requirement to have these files in every jail +# before sysrc can be used on said jail. +# +jail_depend() +{ + # + # Indicate that we are jailed + # + echo export _SYSRC_JAILED=1 + + # + # Print i18n language variables (their current values are sanitized + # and re-printed for interpretation so that the i18n language files + # do not need to exist within the jail). + # + local var val + for var in \ + msg_cannot_create_permission_denied \ + msg_permission_denied \ + msg_previous_syntax_errors \ + ; do + val=$( eval echo \"\$$var\" | + awk '{ gsub(/'\''/, "'\''\\'\'\''"); print }' ) + echo $var="'$val'" + done + + # + # Print include dependencies + # + cat $BSDCFG_SHARE/common.subr + cat $BSDCFG_SHARE/sysrc.subr +} + +############################################################ MAIN SOURCE + +# +# Perform sanity checks +# +[ $# -gt 0 ] || usage + +# +# Check for `--help' command-line option +# +( # Operate in sub-shell to protect $@ in parent + while [ $# -gt 0 ]; do + case "$1" in + --help) exit 1;; + -[fRj]) # These flags take an argument + shift 1;; + esac + shift 1 + done + exit 0 +) || help + +# +# Process command-line flags +# +while getopts aAdDef:Fhij:nNqR:vxX flag; do + case "$flag" in + a) SHOW_ALL=${SHOW_ALL:-1};; + A) SHOW_ALL=2;; + d) DESCRIBE=1;; + D) RC_CONFS=;; + e) SHOW_EQUALS=1;; + f) RC_CONFS="$RC_CONFS${RC_CONFS:+ }$OPTARG";; + F) SHOW_FILE=1;; + h) usage;; + i) IGNORE_UNKNOWNS=1;; + j) [ "$OPTARG" ] || die \ + "%s: Missing or null argument to \`-j' flag" "$pgm" + JAIL="$OPTARG";; + n) SHOW_NAME=;; + N) SHOW_VALUE=;; + q) QUIET=1 SYSRC_VERBOSE=;; + R) [ "$OPTARG" ] || die \ + "%s: Missing or null argument to \`-R' flag" "$pgm" + ROOTDIR="$OPTARG";; + v) SYSRC_VERBOSE=1 QUIET=;; + x) DELETE=${DELETE:-1};; + X) DELETE=2;; + \?) usage;; + esac +done +shift $(( $OPTIND - 1 )) + +# +# [More] Sanity checks (e.g., "sysrc --") +# +[ $# -eq 0 -a ! "$SHOW_ALL" ] && usage + +# +# Taint-check all rc.conf(5) files +# +errmsg="$pgm: Exiting due to previous syntax errors" +if [ "${RC_CONFS+set}" ]; then + ( for i in $RC_CONFS; do + [ -e "$i" ] || continue + /bin/sh -n "$i" || exit $FAILURE + done + exit $SUCCESS + ) || die "$errmsg" +else + /bin/sh -n "$RC_DEFAULTS" || die "$errmsg" + ( . "$RC_DEFAULTS" + for i in $rc_conf_files; do + [ -e "$i" ] || continue + /bin/sh -n "$i" || exit $FAILURE + done + exit $SUCCESS + ) || die "$errmsg" +fi + +# +# Process `-x' (and secret `-X') command-line options +# +errmsg="$pgm: \`-x' option incompatible with \`-a'/\`-A' options" +errmsg="$errmsg (use \`-X' to override)" +if [ "$DELETE" -a "$SHOW_ALL" ]; then + [ "$DELETE" = "2" ] || die "$errmsg" +fi + +# +# Process `-e', `-n', and `-N' command-line options +# +SEP=': ' +[ "$SHOW_EQUALS" ] && SEP='="' +[ "$SHOW_NAME" ] || SHOW_EQUALS= +[ "$SYSRC_VERBOSE" = "0" ] && SYSRC_VERBOSE= +if [ ! "$SHOW_VALUE" ]; then + SHOW_NAME=1 + SHOW_EQUALS= +fi + +# +# Process `-j jail' and `-R dir' command-line options +# +if [ "$JAIL" -o "$ROOTDIR" ]; then + # + # Reconstruct the arguments that we want to carry-over + # + args=" + ${SYSRC_VERBOSE:+-v} + ${QUIET:+-q} + $( [ "$DELETE" = "1" ] && echo \ -x ) + $( [ "$DELETE" = "2" ] && echo \ -X ) + $( [ "$SHOW_ALL" = "1" ] && echo \ -a ) + $( [ "$SHOW_ALL" = "2" ] && echo \ -A ) + ${DESCRIBE:+-d} + ${SHOW_EQUALS:+-e} + ${IGNORE_UNKNOWNS:+-i} + $( [ "$SHOW_NAME" ] || echo \ -n ) + $( [ "$SHOW_VALUE" ] || echo \ -N ) + $( [ "$SHOW_FILE" ] && echo \ -F ) + " + if [ "${RC_CONFS+set}" ]; then + args="$args -f '$RC_CONFS'" + fi + for arg in "$@"; do + args="$args '$arg'" + done + + # + # If both are supplied, `-j jail' supercedes `-R dir' + # + if [ "$JAIL" ]; then + # + # Re-execute ourselves with sh(1) via jexec(8) + # + ( echo set -- $args + jail_depend + cat $0 + ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ + /usr/sbin/jexec "$JAIL" /bin/sh + exit $? + elif [ "$ROOTDIR" ]; then + # + # Make sure that the root directory specified is not to any + # running jails. + # + # NOTE: To maintain backward compatibility with older jails on + # older systems, we will not perform this check if either the + # jls(1) or jexec(8) utilities are missing. + # + if f_have jexec && f_have jls; then + jid="`jls jid path | \ + ( + while read JID JROOT; do + [ "$JROOT" = "$ROOTDIR" ] || continue + echo $JID + done + )`" + + # + # If multiple running jails match the specified root + # directory, exit with error. + # + if [ "$jid" -a "${jid%[$IFS]*}" != "$jid" ]; then + die "%s: %s: %s" "$pgm" "$ROOTDIR" \ + "$( echo "Multiple jails claim this" \ + "directory as their root." \ + "(use \`-j jail' instead)" )" + fi + + # + # If only a single running jail matches the specified + # root directory, implicitly use `-j jail'. + # + if [ "$jid" ]; then + # + # Re-execute outselves with sh(1) via jexec(8) + # + ( echo set -- $args + jail_depend + cat $0 + ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ + /usr/sbin/jexec "$jid" /bin/sh + exit $? + fi + + # Otherwise, fall through and allow chroot(8) + fi + + # + # Re-execute ourselves with sh(1) via chroot(8) + # + ( echo set -- $args + jail_depend + cat $0 + ) | env - RC_DEFAULTS="$RC_DEFAULTS" \ + /usr/sbin/chroot "$ROOTDIR" /bin/sh + exit $? + fi +fi + +# +# Process `-a' or `-A' command-line options +# +if [ "$SHOW_ALL" ]; then + # + # Get a list of variables that are currently set in the rc.conf(5) + # files (included `/etc/defaults/rc.conf') by performing a call to + # source_rc_confs() in a clean environment. + # + ( # Operate in a sub-shell to protect the parent environment + # + # Set which variables we want to preserve in the environment. + # Append the pipe-character (|) to the list of internal field + # separation (IFS) characters, allowing us to use the below + # list both as an extended grep (-E) pattern and argument list + # (required to first get f_clean_env() to preserve these in the + # environment and then later to prune them from the list of + # variables produced by set(1)). + # + IFS="$IFS|" + EXCEPT="IFS|EXCEPT|PATH|RC_DEFAULTS|OPTIND|DESCRIBE|SEP" + EXCEPT="$EXCEPT|DELETE|SHOW_ALL|SHOW_EQUALS|SHOW_NAME" + EXCEPT="$EXCEPT|SHOW_VALUE|SHOW_FILE|SYSRC_VERBOSE|RC_CONFS" + EXCEPT="$EXCEPT|pgm|SUCCESS|FAILURE" + EXCEPT="$EXCEPT|f_sysrc_desc_awk|f_sysrc_delete_awk" + + # + # Clean the environment (except for our required variables) + # and then source the required files. + # + f_clean_env --except $EXCEPT + if [ -f "$RC_DEFAULTS" -a -r "$RC_DEFAULTS" ]; then + . "$RC_DEFAULTS" + + # + # If passed `-a' (rather than `-A'), re-purge the + # environment, removing the rc.conf(5) defaults. + # + [ "$SHOW_ALL" = "1" ] \ + && f_clean_env --except rc_conf_files $EXCEPT + + # + # If `-f file' was passed, set $rc_conf_files to an + # explicit value, modifying the default behavior of + # source_rc_confs(). + # + [ "${RC_CONFS+set}" ] && rc_conf_files="$RC_CONFS" + + source_rc_confs + + # + # If passed `-a' (rather than `-A'), remove + # `rc_conf_files' unless it was defined somewhere + # other than rc.conf(5) defaults. + # + [ "$SHOW_ALL" = "1" -a \ + "$( f_sysrc_find rc_conf_files )" = "$RC_DEFAULTS" \ + ] \ + && unset rc_conf_files + fi + + for NAME in $( set | + awk -F= '/^[[:alpha:]_][[:alnum:]_]*=/ {print $1}' | + grep -Ev "^($EXCEPT)$" + ); do + # + # If enabled, describe rather than expand value + # + if [ "$DESCRIBE" ]; then + echo "$NAME: $( f_sysrc_desc "$NAME" )" + continue + fi + + # + # If `-F' is passed, find it and move on + # + if [ "$SHOW_FILE" ]; then + [ "$SHOW_NAME" ] && echo -n "$NAME: " + f_sysrc_find "$NAME" + continue + fi + + # + # If `-X' is passed, delete the variables + # + if [ "$DELETE" = "2" ]; then + f_sysrc_delete "$NAME" + continue + fi + + [ "$SYSRC_VERBOSE" ] && \ + echo -n "$( f_sysrc_find "$NAME" ): " + + # + # If `-N' is passed, simplify the output + # + if [ ! "$SHOW_VALUE" ]; then + echo "$NAME" + continue + fi + + echo "${SHOW_NAME:+$NAME$SEP}$( + f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}" + + done + ) + + # + # Ignore the remainder of positional arguments. + # + exit $SUCCESS +fi + +# +# Process command-line arguments +# +while [ $# -gt 0 ]; do + NAME="${1%%=*}" + + [ "$DESCRIBE" ] && \ + echo "$NAME: $( f_sysrc_desc "$NAME" )" + + case "$1" in + *=*) + # + # Like sysctl(8), if both `-d' AND "name=value" is passed, + # first describe, then attempt to set + # + + if [ "$SYSRC_VERBOSE" ]; then + file=$( f_sysrc_find "$NAME" ) + [ "$file" = "$RC_DEFAULTS" -o ! "$file" ] && \ + file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' ) + echo -n "$file: " + fi + + # + # If `-x' or `-X' is passed, delete the variable and ignore the + # desire to set some value + # + if [ "$DELETE" ]; then + f_sysrc_delete "$NAME" + shift 1 + continue + fi + + # + # If `-N' is passed, simplify the output + # + if [ ! "$SHOW_VALUE" ]; then + echo "$NAME" + f_sysrc_set "$NAME" "${1#*}" + else + if [ "$SHOW_FILE" ]; then + before=$( f_sysrc_find "$NAME" ) + else + before=$( f_sysrc_get "$NAME" ) + fi + if f_sysrc_set "$NAME" "${1#*=}"; then + if [ "$SHOW_FILE" ]; then + after=$( f_sysrc_find "$NAME" ) + echo -n "${SHOW_NAME:+$NAME$SEP}" + echo -n "$before${SHOW_EQUALS:+\"}" + echo " -> $after" + else + after=$( f_sysrc_get "$NAME" ) + echo -n "${SHOW_NAME:+$NAME$SEP}" + echo "$before -> $after" + fi + fi + fi + ;; + *) + if ! IGNORED="$( f_sysrc_get "$NAME?" )"; then + [ "$IGNORE_UNKNOWNS" ] \ + || echo "$pgm: unknown variable '$NAME'" + shift 1 + continue + fi + + # + # Like sysctl(8), when `-d' is passed, + # desribe it rather than expanding it + # + + if [ "$DESCRIBE" ]; then + shift 1 + continue + fi + + # + # If `-x' or `-X' is passed, delete the variable + # + if [ "$DELETE" ]; then + f_sysrc_delete "$NAME" + shift 1 + continue + fi + + # + # If `-F' is passed, find it and move on + # + if [ "$SHOW_FILE" ]; then + [ "$SHOW_NAME" ] && echo -n "$NAME: " + f_sysrc_find "$NAME" + shift 1 + continue + fi + + [ "$SYSRC_VERBOSE" ] && \ + echo -n "$( f_sysrc_find "$NAME" ): " + + # + # If `-N' is passed, simplify the output + # + if [ ! "$SHOW_VALUE" ]; then + echo "$NAME" + else + echo "${SHOW_NAME:+$NAME$SEP}$( + f_sysrc_get "$NAME" )${SHOW_EQUALS:+\"}" + fi + esac + shift 1 +done diff --git a/usr.sbin/sysrc/sysrc.8 b/usr.sbin/sysrc/sysrc.8 new file mode 100644 index 000000000..b5671a0a5 --- /dev/null +++ b/usr.sbin/sysrc/sysrc.8 @@ -0,0 +1,297 @@ +.\" 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$ +.\" +.Dd Jul 5, 2013 +.Dt SYSRC 8 +.Os +.Sh NAME +.Nm sysrc +.Nd safely edit system rc files +.Sh SYNOPSIS +.Nm +.Op Fl dDeFhinNqvx +.Op Fl f Ar file +.Op Fl j Ar jail | Fl R Ar dir +.Ar name Ns Op = Ns Ar value +.Ar ... +.Nm +.Op Fl dDeFhinNqvx +.Op Fl f Ar file +.Op Fl j Ar jail | Fl R Ar dir +.Fl a | A +.Sh DESCRIPTION +The +.Nm +utility retrieves +.Xr rc.conf 5 +variables from the collection of system rc files and allows processes with +appropriate privilege to change values in a safe and effective manner. +.Pp +The following options are available: +.Bl -tag -width indent+ +.It Fl a +Dump a list of all non-default configuration variables. +.It Fl A +Dump a list of all configuration variables +.Pq incl. defaults . +.It Fl d +Print a description of the given variable. +.It Fl D +Show default value(s) only (this is the same as setting RC_CONFS to NULL or +passing `-f' with a NULL file-argument). +.It Fl e +Print query results as +.Ql var=value +.Pq useful for producing output to be fed back in . +Ignored if +.Fl n +is specified. +.It Fl f Ar file +Operate on the specified file(s) instead of the files obtained by reading the +.Sq rc_conf_files +entry in the +.Ev RC_DEFAULTS +file. +This option can be specified multiple times for additional files. +.It Fl F +Show only the last +.Xr rc.conf 5 +file each directive is in. +.It Fl h +Print a short usage message to stderr and exit. +.It Fl -help +Print a full usage statement to stderr and exit. +.It Fl i +Ignore unknown variables. +.It Fl j Ar jail +The +.Ar jid +or name of the +.Ar jail +to operate within +.Pq overrides So Fl R Ar dir Sc ; requires Xr jexec 8 . +.It Fl n +Show only variable values, not their names. +.It Fl N +Show only variable names, not their values. +.It Fl q +Quiet. +Ignore previous occurrences of +.Fl v +flag. +.It Fl R Ar dir +Operate within the root directory +.Pq Sq Ar dir +rather than +.Pq Sq / . +.It Fl v +Verbose. +Print the pathname of the specific +.Xr rc.conf 5 +file where the directive was found. +.It Fl x +Remove variable(s) from specified file(s). +.El +.Pp +This utility works similar to +.Xr sysctl 8 . +It shares the `-e' and `-n' options +.Pq detailed above +and also has the same +.Ql name[=value] +syntax for querying/setting configuration options. +.Pp +However, while +.Xr sysctl 8 +serves to query/modify MIBs in the entrant kernel, +.Nm +instead works on values in the system +.Xr rc.conf 5 +configuration files. +.Pp +The list of system configuration files is configured in the file +.Ql /etc/defaults/rc.conf +within the variable +.Ql rc_conf_files , +which by-default contains a space-separated list of pathnames. +On all FreeBSD +systems, this defaults to the value "/etc/rc.conf /etc/rc.conf.local". +Each +pathname is sourced in-order upon startup. +It is in the same fashion that +.Nm +sources the configuration files before returning the value of the given +variable. +.Pp +When supplied a variable name, +.Nm +will return the value of the variable. +If the variable does not appear in any +of the configured +.Ql rc_conf_files , +an error is printed and error status is returned. +.Pp +When changing values of a given variable, it does not matter if the variable +appears in any of the +.Ql rc_conf_files +or not. +If the variable does not appear in any of the files, it is appended to +the end of the first pathname in the +.Ql rc_conf_files +variable. +Otherwise, +.Nm +will replace only the last-occurrence in the last-file found to contain the +variable. +This gets the value to take effect next boot without heavily +modifying these integral files (yet taking care not to allow the file to +grow unwieldy should +.Nm +be called repeatedly). +.Sh ENVIRONMENT +The following environment variables are referenced by +.Nm : +.Bl -tag -width ".Ev RC_DEFAULTS" +.It Ev RC_CONFS +Override default +.Ql rc_conf_files +.Pq even if set to NULL . +.It Ev RC_DEFAULTS +Location of +.Ql /etc/defaults/rc.conf +file. +.El +.Sh DEPENDENCIES +The following standard commands are required by +.Nm : +.Pp +.Xr awk 1 , +.Xr cat 1 , +.Xr chmod 1 , +.Xr env 1 , +.Xr grep 1 , +.Xr jls 1 , +.Xr mktemp 1 , +.Xr mv 1 , +.Xr rm 1 , +.Xr sh 1 , +.Xr stat 1 , +.Xr tail 1 , +.Xr chown 8 +and +.Xr jexec 8 . +.Sh FILES +.Bl -tag -width ".Pa /etc/defaults/rc.conf" -compact +.It Pa /etc/defaults/rc.conf +.It Pa /etc/rc.conf +.It Pa /etc/rc.conf.local +.El +.Sh EXAMPLES +Below are some simple examples of how +.Nm +can be used to query certain values from the +.Xr rc.conf 5 +collection of system configuration files: +.Pp +.Nm +sshd_enable +.Dl returns the value of $sshd_enable, usually YES or NO . +.Pp +.Nm +defaultrouter +.Dl returns IP address of default router Pq if configured . +.Pp +Working on other files, such as +.Xr crontab 5 : +.Pp +.Nm +-f /etc/crontab MAILTO +.Dl returns the value of the MAILTO setting Pq if configured . +.Pp +In addition to the above syntax, +.Nm +also supports inline +.Xr sh 1 +PARAMETER expansion for changing the way values are reported, shown below: +.Pp +.Nm +\&'hostname%%.*' +.Dl returns $hostname up to (but not including) first `.' . +.Pp +.Nm +\&'network_interfaces%%[$IFS]*' +.Dl returns first word of $network_interfaces . +.Pp +.Nm +\&'ntpdate_flags##*[$IFS]' +.Dl returns last word of $ntpdate_flags (time server address) . +.Pp +.Nm +usbd_flags-"default" +.Dl returns $usbd_flags or "default" if unset or NULL . +.Pp +.Nm +cloned_interfaces+"alternate" +.Dl returns "alternate" if $cloned_interfaces is set . +.Pp +.Nm +\&'#kern_securelevel' +.Dl returns length in characters of $kern_securelevel . +.Pp +.Nm +\&'hostname?' +.Dl returns NULL and error status 2 if $hostname is unset Pq or if set, returns the value of $hostname with no error status . +.Pp +.Nm +\&'hostname:?' +.Dl returns NULL and error status 2 if $hostname is unset or NULL Pq or if set and non-NULL, returns value without error status . +.Sh LIMITATIONS +The +.Nm +utility presently does not support the +.Ql rc.conf.d +collection of system configuration files +.Pq which requires a service name to be known during execution . +.Pp +This will be corrected by a future enhancement. +.Sh SEE ALSO +.Xr jls 1 , +.Xr rc.conf 5 , +.Xr jail 8 , +.Xr jexec 8 , +.Xr rc 8 , +.Xr sysctl 8 +.Sh HISTORY +A +.Nm +utility first appeared in +.Fx 9.2 . +.Sh AUTHORS +.An Devin Teske Aq dteske@FreeBSD.org +.Sh THANKS TO +Brandon Gooch, Garrett Cooper, Julian Elischer, Pawel Jakub Dawidek, +Cyrille Lefevre, Ross West, Stefan Esser, Marco Steinbach, and Jilles Tjoelker +for suggestions and help. -- 2.45.0