summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/IPXrouted/IPXrouted.8224
-rw-r--r--usr.sbin/IPXrouted/Makefile11
-rw-r--r--usr.sbin/IPXrouted/Makefile.depend19
-rw-r--r--usr.sbin/IPXrouted/af.c294
-rw-r--r--usr.sbin/IPXrouted/af.h77
-rw-r--r--usr.sbin/IPXrouted/defs.h108
-rw-r--r--usr.sbin/IPXrouted/if.c151
-rw-r--r--usr.sbin/IPXrouted/input.c304
-rw-r--r--usr.sbin/IPXrouted/interface.h95
-rw-r--r--usr.sbin/IPXrouted/main.c401
-rw-r--r--usr.sbin/IPXrouted/output.c231
-rw-r--r--usr.sbin/IPXrouted/protocol.h92
-rw-r--r--usr.sbin/IPXrouted/sap.h108
-rw-r--r--usr.sbin/IPXrouted/sap_input.c215
-rw-r--r--usr.sbin/IPXrouted/sap_output.c198
-rw-r--r--usr.sbin/IPXrouted/sap_tables.c321
-rw-r--r--usr.sbin/IPXrouted/startup.c278
-rw-r--r--usr.sbin/IPXrouted/table.h115
-rw-r--r--usr.sbin/IPXrouted/tables.c419
-rw-r--r--usr.sbin/IPXrouted/timer.c239
-rw-r--r--usr.sbin/IPXrouted/trace.c520
-rw-r--r--usr.sbin/IPXrouted/trace.h138
-rw-r--r--usr.sbin/Makefile22
-rw-r--r--usr.sbin/acpi/acpidump/acpi.c1
-rw-r--r--usr.sbin/amd/include/newvers.sh9
-rw-r--r--usr.sbin/arp/arp.46
-rw-r--r--usr.sbin/arp/arp.c27
-rw-r--r--usr.sbin/bhyve/Makefile39
-rw-r--r--usr.sbin/bhyve/acpi.c369
-rw-r--r--usr.sbin/bhyve/acpi.h21
-rw-r--r--usr.sbin/bhyve/atkbdc.c85
-rw-r--r--usr.sbin/bhyve/bhyve.8306
-rw-r--r--usr.sbin/bhyve/bhyverun.c350
-rw-r--r--usr.sbin/bhyve/bhyverun.h5
-rw-r--r--usr.sbin/bhyve/block_if.c7
-rw-r--r--usr.sbin/bhyve/consport.c12
-rw-r--r--usr.sbin/bhyve/dbgport.c3
-rw-r--r--usr.sbin/bhyve/inout.c54
-rw-r--r--usr.sbin/bhyve/inout.h14
-rw-r--r--usr.sbin/bhyve/ioapic.c310
-rw-r--r--usr.sbin/bhyve/ioapic.h17
-rw-r--r--usr.sbin/bhyve/mevent.c12
-rw-r--r--usr.sbin/bhyve/mevent.h3
-rw-r--r--usr.sbin/bhyve/mptbl.c274
-rw-r--r--usr.sbin/bhyve/mptbl.h2
-rw-r--r--usr.sbin/bhyve/pci_ahci.c104
-rw-r--r--usr.sbin/bhyve/pci_emul.c713
-rw-r--r--usr.sbin/bhyve/pci_emul.h47
-rw-r--r--usr.sbin/bhyve/pci_hostbridge.c16
-rw-r--r--usr.sbin/bhyve/pci_lpc.c366
-rw-r--r--usr.sbin/bhyve/pci_lpc.h (renamed from usr.sbin/bhyve/elcr.c)63
-rw-r--r--usr.sbin/bhyve/pci_passthru.c106
-rw-r--r--usr.sbin/bhyve/pci_uart.c549
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c80
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c25
-rw-r--r--usr.sbin/bhyve/pci_virtio_rnd.c188
-rw-r--r--usr.sbin/bhyve/pit_8254.c272
-rw-r--r--usr.sbin/bhyve/pm.c291
-rw-r--r--usr.sbin/bhyve/pmtmr.c13
-rw-r--r--usr.sbin/bhyve/post.c2
-rw-r--r--usr.sbin/bhyve/rtc.c25
-rw-r--r--usr.sbin/bhyve/smbiostbl.c832
-rw-r--r--usr.sbin/bhyve/smbiostbl.h (renamed from usr.sbin/bhyve/atpic.c)47
-rw-r--r--usr.sbin/bhyve/spinup_ap.c19
-rw-r--r--usr.sbin/bhyve/uart_emul.c622
-rw-r--r--usr.sbin/bhyve/uart_emul.h (renamed from usr.sbin/bhyve/pit_8254.h)28
-rw-r--r--usr.sbin/bhyve/virtio.c15
-rw-r--r--usr.sbin/bhyve/virtio.h20
-rw-r--r--usr.sbin/bhyve/xmsr.c17
-rw-r--r--usr.sbin/bhyve/xmsr.h1
-rw-r--r--usr.sbin/bhyvectl/Makefile2
-rw-r--r--usr.sbin/bhyvectl/bhyvectl.c33
-rw-r--r--usr.sbin/bhyveload/bhyveload.837
-rw-r--r--usr.sbin/bhyveload/bhyveload.c171
-rw-r--r--usr.sbin/binmiscctl/Makefile10
-rw-r--r--usr.sbin/binmiscctl/binmiscctl.8196
-rw-r--r--usr.sbin/binmiscctl/binmiscctl.c508
-rw-r--r--usr.sbin/bluetooth/bthidd/kbd.c2
-rw-r--r--usr.sbin/bluetooth/btpand/btpand.81
-rw-r--r--usr.sbin/bootparamd/bootparamd/main.c2
-rw-r--r--usr.sbin/bootparamd/callbootd/Makefile2
-rw-r--r--usr.sbin/bootparamd/callbootd/callbootd.c2
-rw-r--r--usr.sbin/bsdconfig/Makefile1
-rwxr-xr-xusr.sbin/bsdconfig/bsdconfig10
-rwxr-xr-xusr.sbin/bsdconfig/console/console4
-rwxr-xr-xusr.sbin/bsdconfig/console/font16
-rw-r--r--usr.sbin/bsdconfig/console/include/messages.subr20
-rwxr-xr-xusr.sbin/bsdconfig/console/keymap13
-rwxr-xr-xusr.sbin/bsdconfig/console/repeat7
-rwxr-xr-xusr.sbin/bsdconfig/console/saver10
-rwxr-xr-xusr.sbin/bsdconfig/console/screenmap7
-rwxr-xr-xusr.sbin/bsdconfig/console/ttys25
-rwxr-xr-xusr.sbin/bsdconfig/diskmgmt/diskmgmt4
-rwxr-xr-xusr.sbin/bsdconfig/docsinstall/docsinstall4
-rwxr-xr-xusr.sbin/bsdconfig/dot/dot8
-rwxr-xr-xusr.sbin/bsdconfig/examples/browse_packages_ftp.sh2
-rwxr-xr-xusr.sbin/bsdconfig/examples/browse_packages_http.sh2
-rw-r--r--usr.sbin/bsdconfig/include/messages.subr22
-rw-r--r--usr.sbin/bsdconfig/includes/INDEX56
-rw-r--r--usr.sbin/bsdconfig/includes/Makefile16
-rw-r--r--usr.sbin/bsdconfig/includes/USAGE71
-rw-r--r--usr.sbin/bsdconfig/includes/include/Makefile11
-rw-r--r--usr.sbin/bsdconfig/includes/include/messages.subr28
-rwxr-xr-xusr.sbin/bsdconfig/includes/includes203
-rwxr-xr-xusr.sbin/bsdconfig/mouse/disable20
-rwxr-xr-xusr.sbin/bsdconfig/mouse/enable34
-rwxr-xr-xusr.sbin/bsdconfig/mouse/flags6
-rw-r--r--usr.sbin/bsdconfig/mouse/include/messages.subr8
-rwxr-xr-xusr.sbin/bsdconfig/mouse/mouse4
-rwxr-xr-xusr.sbin/bsdconfig/mouse/port7
-rwxr-xr-xusr.sbin/bsdconfig/mouse/type7
-rwxr-xr-xusr.sbin/bsdconfig/networking/defaultrouter7
-rwxr-xr-xusr.sbin/bsdconfig/networking/devices14
-rwxr-xr-xusr.sbin/bsdconfig/networking/hostname4
-rw-r--r--usr.sbin/bsdconfig/networking/include/messages.subr8
-rwxr-xr-xusr.sbin/bsdconfig/networking/nameservers4
-rwxr-xr-xusr.sbin/bsdconfig/networking/networking4
-rw-r--r--usr.sbin/bsdconfig/networking/share/device.subr126
-rw-r--r--usr.sbin/bsdconfig/networking/share/hostname.subr4
-rw-r--r--usr.sbin/bsdconfig/networking/share/ipaddr.subr7
-rw-r--r--usr.sbin/bsdconfig/networking/share/media.subr21
-rw-r--r--usr.sbin/bsdconfig/networking/share/netmask.subr8
-rw-r--r--usr.sbin/bsdconfig/networking/share/resolv.subr58
-rw-r--r--usr.sbin/bsdconfig/networking/share/routing.subr32
-rw-r--r--usr.sbin/bsdconfig/networking/share/services.subr3
-rwxr-xr-xusr.sbin/bsdconfig/packages/packages6
-rwxr-xr-xusr.sbin/bsdconfig/password/password8
-rwxr-xr-xusr.sbin/bsdconfig/security/kern_securelevel25
-rwxr-xr-xusr.sbin/bsdconfig/security/security10
-rw-r--r--usr.sbin/bsdconfig/share/Makefile5
-rw-r--r--usr.sbin/bsdconfig/share/common.subr394
-rw-r--r--usr.sbin/bsdconfig/share/device.subr1513
-rw-r--r--usr.sbin/bsdconfig/share/dialog.subr111
-rw-r--r--usr.sbin/bsdconfig/share/geom.subr430
-rw-r--r--usr.sbin/bsdconfig/share/keymap.subr263
-rw-r--r--usr.sbin/bsdconfig/share/media/cdrom.subr69
-rw-r--r--usr.sbin/bsdconfig/share/media/common.subr27
-rw-r--r--usr.sbin/bsdconfig/share/media/directory.subr8
-rw-r--r--usr.sbin/bsdconfig/share/media/dos.subr47
-rw-r--r--usr.sbin/bsdconfig/share/media/floppy.subr61
-rw-r--r--usr.sbin/bsdconfig/share/media/ftp.subr35
-rw-r--r--usr.sbin/bsdconfig/share/media/http.subr74
-rw-r--r--usr.sbin/bsdconfig/share/media/nfs.subr42
-rw-r--r--usr.sbin/bsdconfig/share/media/tcpip.subr141
-rw-r--r--usr.sbin/bsdconfig/share/media/ufs.subr41
-rw-r--r--usr.sbin/bsdconfig/share/media/usb.subr48
-rw-r--r--usr.sbin/bsdconfig/share/mustberoot.subr17
-rwxr-xr-xusr.sbin/bsdconfig/share/packages/categories.subr4
-rwxr-xr-xusr.sbin/bsdconfig/share/packages/index.subr222
-rwxr-xr-xusr.sbin/bsdconfig/share/packages/packages.subr125
-rw-r--r--usr.sbin/bsdconfig/share/script.subr36
-rw-r--r--usr.sbin/bsdconfig/share/strings.subr158
-rw-r--r--usr.sbin/bsdconfig/share/struct.subr2
-rw-r--r--usr.sbin/bsdconfig/share/sysrc.subr55
-rw-r--r--usr.sbin/bsdconfig/share/variable.subr42
-rw-r--r--usr.sbin/bsdconfig/startup/include/messages.subr4
-rwxr-xr-xusr.sbin/bsdconfig/startup/misc101
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcadd4
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcconf4
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcdelete15
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcedit4
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcvar6
-rw-r--r--usr.sbin/bsdconfig/startup/share/rcconf.subr20
-rw-r--r--usr.sbin/bsdconfig/startup/share/rcedit.subr9
-rw-r--r--usr.sbin/bsdconfig/startup/share/rcvar.subr18
-rwxr-xr-xusr.sbin/bsdconfig/startup/startup4
-rw-r--r--usr.sbin/bsdconfig/timezone/share/menus.subr4
-rw-r--r--usr.sbin/bsdconfig/timezone/share/zones.subr156
-rwxr-xr-xusr.sbin/bsdconfig/timezone/timezone23
-rwxr-xr-xusr.sbin/bsdconfig/ttys/ttys4
-rw-r--r--usr.sbin/bsdconfig/usermgmt/Makefile3
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/groupadd23
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/groupdel20
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/groupedit22
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/groupinput305
-rw-r--r--usr.sbin/bsdconfig/usermgmt/include/messages.subr27
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/Makefile2
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/group.subr518
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/group_input.subr487
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/user.subr1184
-rw-r--r--usr.sbin/bsdconfig/usermgmt/share/user_input.subr1345
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/useradd23
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/userdel20
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/useredit22
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/userinput529
-rwxr-xr-xusr.sbin/bsdconfig/usermgmt/usermgmt4
-rwxr-xr-xusr.sbin/bsdinstall/bsdinstall57
-rw-r--r--usr.sbin/bsdinstall/bsdinstall.851
-rw-r--r--usr.sbin/bsdinstall/distextract/Makefile16
-rw-r--r--usr.sbin/bsdinstall/distfetch/Makefile16
-rw-r--r--usr.sbin/bsdinstall/partedit/Makefile14
-rw-r--r--usr.sbin/bsdinstall/partedit/gpart_ops.c9
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit.h9
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit_generic.c5
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit_pc98.c5
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit_powerpc.c5
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit_sparc64.c5
-rw-r--r--usr.sbin/bsdinstall/partedit/partedit_x86.c64
-rw-r--r--usr.sbin/bsdinstall/scripts/Makefile8
-rwxr-xr-xusr.sbin/bsdinstall/scripts/auto63
-rwxr-xr-xusr.sbin/bsdinstall/scripts/config15
-rwxr-xr-x[-rw-r--r--]usr.sbin/bsdinstall/scripts/docsinstall170
-rwxr-xr-xusr.sbin/bsdinstall/scripts/entropy29
-rwxr-xr-xusr.sbin/bsdinstall/scripts/jail17
-rwxr-xr-xusr.sbin/bsdinstall/scripts/keymap214
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig12
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig_ipv421
-rwxr-xr-xusr.sbin/bsdinstall/scripts/netconfig_ipv624
-rwxr-xr-xusr.sbin/bsdinstall/scripts/script62
-rwxr-xr-xusr.sbin/bsdinstall/scripts/services24
-rwxr-xr-xusr.sbin/bsdinstall/scripts/wlanconfig46
-rwxr-xr-xusr.sbin/bsdinstall/scripts/zfsboot1458
-rw-r--r--usr.sbin/bsnmpd/modules/Makefile5
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_hast/BEGEMOT-HAST-MIB.txt54
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_hast/hast_snmp.c30
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_hast/hast_tree.def5
-rw-r--r--usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.163
-rw-r--r--usr.sbin/btxld/btxld.c2
-rw-r--r--usr.sbin/config/config.87
-rw-r--r--usr.sbin/config/config.h7
-rw-r--r--usr.sbin/config/configvers.h2
-rw-r--r--usr.sbin/config/lang.l13
-rw-r--r--usr.sbin/config/main.c12
-rw-r--r--usr.sbin/config/mkmakefile.c345
-rwxr-xr-xusr.sbin/crashinfo/crashinfo.sh10
-rw-r--r--usr.sbin/cron/cron/cron.c27
-rw-r--r--usr.sbin/crunch/examples/Makefile2
-rw-r--r--usr.sbin/ctladm/ctladm.814
-rw-r--r--usr.sbin/ctladm/ctladm.c64
-rw-r--r--usr.sbin/ctld/ctl.conf.577
-rw-r--r--usr.sbin/ctld/ctld.c727
-rw-r--r--usr.sbin/ctld/ctld.h88
-rw-r--r--usr.sbin/ctld/discovery.c9
-rw-r--r--usr.sbin/ctld/kernel.c72
-rw-r--r--usr.sbin/ctld/keys.c2
-rw-r--r--usr.sbin/ctld/login.c54
-rw-r--r--usr.sbin/ctld/parse.y320
-rw-r--r--usr.sbin/ctld/pdu.c32
-rw-r--r--usr.sbin/ctld/token.l4
-rw-r--r--usr.sbin/ctm/ctm_dequeue/Makefile2
-rw-r--r--usr.sbin/ctm/ctm_smail/Makefile2
-rw-r--r--usr.sbin/ctm/mkCTM/Makefile2
-rw-r--r--usr.sbin/daemon/daemon.c2
-rw-r--r--usr.sbin/edquota/edquota.c2
-rw-r--r--usr.sbin/eeprom/ofw_options.c2
-rw-r--r--usr.sbin/etcupdate/Makefile6
-rw-r--r--usr.sbin/etcupdate/etcupdate.895
-rwxr-xr-xusr.sbin/etcupdate/etcupdate.sh180
-rw-r--r--usr.sbin/etcupdate/tests/Makefile17
-rw-r--r--usr.sbin/etcupdate/tests/always_test.sh630
-rw-r--r--usr.sbin/etcupdate/tests/conflicts_test.sh294
-rw-r--r--usr.sbin/etcupdate/tests/fbsdid_test.sh394
-rw-r--r--usr.sbin/etcupdate/tests/ignore_test.sh276
-rw-r--r--usr.sbin/etcupdate/tests/preworld_test.sh252
-rw-r--r--usr.sbin/etcupdate/tests/tests_test.sh1021
-rw-r--r--usr.sbin/etcupdate/tests/tzsetup_test.sh239
-rw-r--r--usr.sbin/fifolog/fifolog_reader/Makefile2
-rw-r--r--usr.sbin/fifolog/fifolog_writer/Makefile2
-rw-r--r--usr.sbin/freebsd-update/freebsd-update.sh50
-rw-r--r--usr.sbin/gpioctl/gpioctl.84
-rw-r--r--usr.sbin/ifmcstat/ifmcstat.81
-rw-r--r--usr.sbin/ifmcstat/ifmcstat.c4
-rw-r--r--usr.sbin/iostat/iostat.c12
-rw-r--r--usr.sbin/iscsid/discovery.c2
-rw-r--r--usr.sbin/iscsid/iscsid.c78
-rw-r--r--usr.sbin/iscsid/iscsid.h10
-rw-r--r--usr.sbin/iscsid/keys.c2
-rw-r--r--usr.sbin/iscsid/login.c5
-rw-r--r--usr.sbin/iscsid/pdu.c30
-rw-r--r--usr.sbin/isfctl/Makefile7
-rw-r--r--usr.sbin/isfctl/Makefile.depend18
-rw-r--r--usr.sbin/isfctl/isfctl.889
-rw-r--r--usr.sbin/isfctl/isfctl.c115
-rw-r--r--usr.sbin/jail/command.c33
-rw-r--r--usr.sbin/jail/config.c1
-rw-r--r--usr.sbin/jail/jail.825
-rw-r--r--usr.sbin/jail/jail.c2
-rw-r--r--usr.sbin/jail/jail.conf.57
-rw-r--r--usr.sbin/jail/jailp.h1
-rw-r--r--usr.sbin/kldxref/kldxref.c2
-rw-r--r--usr.sbin/lpr/filters.ru/koi2855/Makefile2
-rw-r--r--usr.sbin/lpr/filters.ru/koi2alt/Makefile2
-rw-r--r--usr.sbin/lpr/filters/Makefile2
-rw-r--r--usr.sbin/lpr/lpr/printcap.51
-rw-r--r--usr.sbin/makefs/cd9660/iso9660_rrip.c5
-rw-r--r--usr.sbin/makefs/cd9660/iso9660_rrip.h2
-rw-r--r--usr.sbin/makefs/ffs.c7
-rw-r--r--usr.sbin/makefs/mtree.c11
-rwxr-xr-xusr.sbin/mergemaster/mergemaster.sh13
-rw-r--r--usr.sbin/mfiutil/Makefile5
-rw-r--r--usr.sbin/mfiutil/mfi_evt.c18
-rw-r--r--usr.sbin/mfiutil/mfi_properties.c171
-rw-r--r--usr.sbin/mfiutil/mfi_show.c4
-rw-r--r--usr.sbin/mfiutil/mfiutil.815
-rw-r--r--usr.sbin/mfiutil/mfiutil.c4
-rw-r--r--usr.sbin/mount_smbfs/Makefile5
-rw-r--r--usr.sbin/mptable/mptable.c460
-rw-r--r--usr.sbin/mtest/mtest.84
-rw-r--r--usr.sbin/mtree/Makefile7
-rw-r--r--usr.sbin/ndiscvt/ndisgen.sh2
-rw-r--r--usr.sbin/ndp/ndp.c68
-rw-r--r--usr.sbin/newsyslog/Makefile6
-rw-r--r--usr.sbin/newsyslog/newsyslog.c3
-rw-r--r--usr.sbin/newsyslog/tests/Makefile7
-rw-r--r--usr.sbin/newsyslog/tests/legacy_test.sh444
-rw-r--r--usr.sbin/nmtree/Makefile15
-rw-r--r--usr.sbin/nmtree/mtree.5 (renamed from usr.sbin/mtree/mtree.5)7
-rw-r--r--usr.sbin/ntp/ntp-keygen/Makefile2
-rw-r--r--usr.sbin/ntp/ntpd/Makefile2
-rw-r--r--usr.sbin/ntp/ntpdate/Makefile2
-rw-r--r--usr.sbin/ntp/ntpdc/Makefile2
-rw-r--r--usr.sbin/ntp/ntpq/Makefile2
-rw-r--r--usr.sbin/ntp/ntptime/Makefile2
-rw-r--r--usr.sbin/ntp/sntp/Makefile2
-rw-r--r--usr.sbin/pciconf/cap.c8
-rw-r--r--usr.sbin/pciconf/pciconf.880
-rw-r--r--usr.sbin/pciconf/pciconf.c172
-rw-r--r--usr.sbin/pkg/Makefile10
-rw-r--r--usr.sbin/pkg/config.c363
-rw-r--r--usr.sbin/pkg/config.h10
-rw-r--r--usr.sbin/pkg/dns_utils.c90
-rw-r--r--usr.sbin/pkg/dns_utils.h1
-rw-r--r--usr.sbin/pkg/pkg.7281
-rw-r--r--usr.sbin/pkg/pkg.c756
-rw-r--r--usr.sbin/pkg_install/Makefile20
-rw-r--r--usr.sbin/pkg_install/Makefile.inc17
-rw-r--r--usr.sbin/pkg_install/README10
-rw-r--r--usr.sbin/pkg_install/add/Makefile14
-rw-r--r--usr.sbin/pkg_install/add/Makefile.depend24
-rw-r--r--usr.sbin/pkg_install/add/add.h48
-rw-r--r--usr.sbin/pkg_install/add/extract.c288
-rw-r--r--usr.sbin/pkg_install/add/futil.c98
-rw-r--r--usr.sbin/pkg_install/add/main.c376
-rw-r--r--usr.sbin/pkg_install/add/perform.c709
-rw-r--r--usr.sbin/pkg_install/add/pkg_add.1612
-rw-r--r--usr.sbin/pkg_install/create/Makefile14
-rw-r--r--usr.sbin/pkg_install/create/Makefile.depend21
-rw-r--r--usr.sbin/pkg_install/create/create.h58
-rw-r--r--usr.sbin/pkg_install/create/main.c268
-rw-r--r--usr.sbin/pkg_install/create/perform.c607
-rw-r--r--usr.sbin/pkg_install/create/pkg_create.1670
-rw-r--r--usr.sbin/pkg_install/create/pl.c281
-rw-r--r--usr.sbin/pkg_install/delete/Makefile13
-rw-r--r--usr.sbin/pkg_install/delete/Makefile.depend21
-rw-r--r--usr.sbin/pkg_install/delete/delete.h35
-rw-r--r--usr.sbin/pkg_install/delete/main.c180
-rw-r--r--usr.sbin/pkg_install/delete/perform.c425
-rw-r--r--usr.sbin/pkg_install/delete/pkg_delete.1297
-rw-r--r--usr.sbin/pkg_install/info/Makefile13
-rw-r--r--usr.sbin/pkg_install/info/Makefile.depend24
-rw-r--r--usr.sbin/pkg_install/info/info.h84
-rw-r--r--usr.sbin/pkg_install/info/main.c295
-rw-r--r--usr.sbin/pkg_install/info/perform.c476
-rw-r--r--usr.sbin/pkg_install/info/pkg_info.1302
-rw-r--r--usr.sbin/pkg_install/info/show.c404
-rw-r--r--usr.sbin/pkg_install/lib/Makefile11
-rw-r--r--usr.sbin/pkg_install/lib/Makefile.depend17
-rw-r--r--usr.sbin/pkg_install/lib/deps.c241
-rw-r--r--usr.sbin/pkg_install/lib/exec.c110
-rw-r--r--usr.sbin/pkg_install/lib/file.c436
-rw-r--r--usr.sbin/pkg_install/lib/global.c32
-rw-r--r--usr.sbin/pkg_install/lib/lib.h243
-rw-r--r--usr.sbin/pkg_install/lib/match.c603
-rw-r--r--usr.sbin/pkg_install/lib/msg.c76
-rw-r--r--usr.sbin/pkg_install/lib/pen.c186
-rw-r--r--usr.sbin/pkg_install/lib/pkgwrap.c89
-rw-r--r--usr.sbin/pkg_install/lib/plist.c596
-rw-r--r--usr.sbin/pkg_install/lib/str.c129
-rw-r--r--usr.sbin/pkg_install/lib/url.c177
-rw-r--r--usr.sbin/pkg_install/lib/version.c328
-rwxr-xr-xusr.sbin/pkg_install/tkpkg152
-rw-r--r--usr.sbin/pkg_install/updating/Makefile13
-rw-r--r--usr.sbin/pkg_install/updating/Makefile.depend24
-rw-r--r--usr.sbin/pkg_install/updating/main.c284
-rw-r--r--usr.sbin/pkg_install/updating/pathnames.h17
-rw-r--r--usr.sbin/pkg_install/updating/pkg_updating.197
-rw-r--r--usr.sbin/pkg_install/version/Makefile16
-rw-r--r--usr.sbin/pkg_install/version/Makefile.depend24
-rw-r--r--usr.sbin/pkg_install/version/main.c138
-rw-r--r--usr.sbin/pkg_install/version/perform.c434
-rw-r--r--usr.sbin/pkg_install/version/pkg_version.1263
-rwxr-xr-xusr.sbin/pkg_install/version/test-pkg_version.sh94
-rw-r--r--usr.sbin/pkg_install/version/version.h43
-rw-r--r--usr.sbin/pmcstat/Makefile3
-rw-r--r--usr.sbin/pmcstat/pmcpl_annotate_cg.c127
-rw-r--r--usr.sbin/pmcstat/pmcpl_annotate_cg.h (renamed from usr.sbin/pkg_install/lib/pkgng.c)45
-rw-r--r--usr.sbin/pmcstat/pmcstat.c12
-rw-r--r--usr.sbin/pmcstat/pmcstat.h1
-rw-r--r--usr.sbin/pmcstat/pmcstat_log.c6
-rw-r--r--usr.sbin/portsnap/make_index/Makefile2
-rw-r--r--usr.sbin/portsnap/phttpget/Makefile2
-rw-r--r--usr.sbin/portsnap/portsnap/portsnap.814
-rw-r--r--usr.sbin/portsnap/portsnap/portsnap.sh17
-rw-r--r--usr.sbin/powerd/powerd.c1
-rw-r--r--usr.sbin/ppp/chat.c5
-rw-r--r--usr.sbin/ppp/mppe.c2
-rw-r--r--usr.sbin/ppp/ppp.813
-rw-r--r--usr.sbin/ppp/route.c19
-rw-r--r--usr.sbin/pw/pw.h1
-rw-r--r--usr.sbin/pw/pw_conf.c35
-rw-r--r--usr.sbin/pw/pw_group.c19
-rw-r--r--usr.sbin/pw/pw_user.c44
-rw-r--r--usr.sbin/pwd_mkdb/pwd_mkdb.88
-rw-r--r--usr.sbin/route6d/route6d.c26
-rw-r--r--usr.sbin/rpc.lockd/kern.c7
-rw-r--r--usr.sbin/rpc.lockd/lock_proc.c186
-rw-r--r--usr.sbin/rpc.lockd/lockd.c10
-rw-r--r--usr.sbin/rpc.lockd/rpc.lockd.86
-rw-r--r--usr.sbin/rpc.statd/rpc.statd.86
-rw-r--r--usr.sbin/rpc.ypupdated/Makefile2
-rw-r--r--usr.sbin/rpcbind/check_bound.c53
-rw-r--r--usr.sbin/rpcbind/pmap_svc.c53
-rw-r--r--usr.sbin/rpcbind/rpcb_stat.c53
-rw-r--r--usr.sbin/rpcbind/rpcb_svc.c53
-rw-r--r--usr.sbin/rpcbind/rpcb_svc_4.c53
-rw-r--r--usr.sbin/rpcbind/rpcb_svc_com.c53
-rw-r--r--usr.sbin/rpcbind/rpcbind.84
-rw-r--r--usr.sbin/rpcbind/rpcbind.c72
-rw-r--r--usr.sbin/rpcbind/rpcbind.h56
-rw-r--r--usr.sbin/rpcbind/security.c16
-rw-r--r--usr.sbin/rpcbind/warmstart.c53
-rw-r--r--usr.sbin/rwhod/rwhod.c4
-rw-r--r--usr.sbin/sa/Makefile6
-rw-r--r--usr.sbin/sa/tests/Makefile33
-rw-r--r--usr.sbin/sa/tests/legacy_test.sh78
-rwxr-xr-xusr.sbin/sa/tests/prime.sh37
-rw-r--r--usr.sbin/sa/tests/v1-amd64-sav.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v1-amd64-sav.out5
-rw-r--r--usr.sbin/sa/tests/v1-amd64-u.out28
-rw-r--r--usr.sbin/sa/tests/v1-amd64-usr.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v1-amd64-usr.out1
-rw-r--r--usr.sbin/sa/tests/v1-i386-sav.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v1-i386-sav.out5
-rw-r--r--usr.sbin/sa/tests/v1-i386-u.out28
-rw-r--r--usr.sbin/sa/tests/v1-i386-usr.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v1-i386-usr.out1
-rw-r--r--usr.sbin/sa/tests/v1-sparc64-sav.inbin0 -> 16384 bytes
-rw-r--r--usr.sbin/sa/tests/v1-sparc64-sav.out5
-rw-r--r--usr.sbin/sa/tests/v1-sparc64-u.out28
-rw-r--r--usr.sbin/sa/tests/v1-sparc64-usr.inbin0 -> 16384 bytes
-rw-r--r--usr.sbin/sa/tests/v1-sparc64-usr.out1
-rw-r--r--usr.sbin/sa/tests/v2-amd64-sav.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v2-amd64-u.out28
-rw-r--r--usr.sbin/sa/tests/v2-amd64-usr.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v2-i386-sav.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v2-i386-u.out28
-rw-r--r--usr.sbin/sa/tests/v2-i386-usr.inbin0 -> 8192 bytes
-rw-r--r--usr.sbin/sa/tests/v2-sparc64-sav.inbin0 -> 16384 bytes
-rw-r--r--usr.sbin/sa/tests/v2-sparc64-u.out36
-rw-r--r--usr.sbin/sa/tests/v2-sparc64-usr.inbin0 -> 16384 bytes
-rwxr-xr-xusr.sbin/service/service.sh2
-rw-r--r--usr.sbin/services_mkdb/extern.h2
-rw-r--r--usr.sbin/services_mkdb/services_mkdb.812
-rw-r--r--usr.sbin/services_mkdb/services_mkdb.c17
-rw-r--r--usr.sbin/syslogd/syslogd.c23
-rw-r--r--usr.sbin/sysrc/sysrc107
-rw-r--r--usr.sbin/sysrc/sysrc.825
-rw-r--r--usr.sbin/tcpdump/tcpdump/Makefile9
-rw-r--r--usr.sbin/tests/Makefile10
-rw-r--r--usr.sbin/tzsetup/Makefile14
-rw-r--r--usr.sbin/usbdump/usbdump.c20
-rw-r--r--usr.sbin/utx/Makefile3
-rw-r--r--usr.sbin/utx/utx.813
-rw-r--r--usr.sbin/utx/utx.c8
-rw-r--r--usr.sbin/watchdogd/watchdogd.812
-rw-r--r--usr.sbin/wlandebug/wlandebug.86
-rw-r--r--usr.sbin/wpa/ndis_events/ndis_events.82
-rw-r--r--usr.sbin/ypbind/yp_ping.c52
-rw-r--r--usr.sbin/ypset/ypset.c5
469 files changed, 22935 insertions, 23721 deletions
diff --git a/usr.sbin/IPXrouted/IPXrouted.8 b/usr.sbin/IPXrouted/IPXrouted.8
deleted file mode 100644
index f5d0e13..0000000
--- a/usr.sbin/IPXrouted/IPXrouted.8
+++ /dev/null
@@ -1,224 +0,0 @@
-.\" Copyright (c) 1986, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Copyright (c) 1995 John Hay. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd October 11, 1995
-.Dt IPXROUTED 8
-.Os
-.Sh NAME
-.Nm IPXrouted
-.Nd IPX Routing Information Protocol daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl N
-.Op Fl q
-.Op Fl s
-.Op Fl S
-.Op Fl t
-.Op Ar logfile
-.Sh DESCRIPTION
-The
-.Nm
-utility is invoked at boot time to manage the
-.Tn IPX
-routing tables.
-The
-.Tn IPX
-routing daemon uses the Novell
-.Tn IPX
-Routing Information Protocol in maintaining up to date kernel routing
-table entries.
-.Pp
-Available options:
-.Bl -tag -width logfile
-.It Fl N
-Do not reply on GetNearestServer
-.Tn SAP
-request.
-.It Fl q
-Do not supply routing information (opposite of
-.Fl s
-option below).
-.It Fl s
-Forces
-.Nm
-to supply routing information whether it is acting as an internetwork
-router or not.
-.It Fl S
-Do not supply Service Advertising Protocol
-.Pq Tn SAP
-information.
-The default is to supply
-.Tn SAP
-information.
-.It Fl t
-All packets sent or received are
-printed on the standard output.
-In addition,
-.Nm
-will not divorce itself from the controlling terminal
-so that interrupts from the keyboard will kill the process.
-.It Ar logfile
-Name of file in which
-.Nm Ns 's
-actions should be logged.
-This log contains information
-about any changes to the routing tables and a history of
-recent messages sent and received which are related to
-the changed route.
-.El
-.Pp
-In normal operation
-.Nm
-listens
-for routing information packets.
-If the host is connected to
-multiple
-.Tn IPX
-networks, it periodically supplies copies
-of its routing tables to any directly connected hosts
-and networks.
-.Pp
-When
-.Nm
-is started, it uses the
-.Dv SIOCGIFCONF
-.Xr ioctl 2
-to find those
-directly connected interfaces configured into the
-system and marked
-.Dq up
-(the software loopback interface is ignored).
-If multiple interfaces
-are present, it is assumed the host will forward packets
-between networks.
-The
-.Nm
-utility then transmits a
-.Em request
-packet on each interface (using a broadcast packet if
-the interface supports it) and enters a loop, listening
-for
-.Em request
-and
-.Em response
-packets from other hosts.
-.Pp
-When a
-.Em request
-packet is received,
-.Nm
-formulates a reply based on the information maintained in its
-internal tables.
-The
-.Em response
-packet generated contains a list of known routes, each marked
-with a
-.Dq hop count
-metric (a count of 16, or greater, is
-considered
-.Dq infinite ) .
-The metric associated with each
-route returned provides a metric
-.Em relative to the sender .
-.Pp
-.Em Response
-packets received by
-.Nm
-are used to update the routing tables if one of the following
-conditions is satisfied:
-.Bl -bullet
-.It
-No routing table entry exists for the destination network
-or host, and the metric indicates the destination is
-.Dq reachable
-(i.e., the hop count is not infinite).
-.It
-The source host of the packet is the same as the router in the
-existing routing table entry.
-That is, updated information is
-being received from the very internetwork router through which
-packets for the destination are being routed.
-.It
-The existing entry in the routing table has not been updated for
-some time (defined to be 90 seconds) and the route is at least
-as cost effective as the current route.
-.It
-The new route describes a shorter route to the destination than
-the one currently stored in the routing tables; the metric of
-the new route is compared against the one stored in the table
-to decide this.
-.El
-.Pp
-When an update is applied,
-.Nm
-records the change in its internal tables and generates a
-.Em response
-packet to all directly connected hosts and networks.
-The
-.Xr routed 8
-utility waits a short period
-of time (no more than 30 seconds) before modifying the kernel's
-routing tables to allow possible unstable situations to settle.
-.Pp
-In addition to processing incoming packets,
-.Nm
-also periodically checks the routing table entries.
-If an entry has not been updated for 3 minutes, the entry's metric
-is set to infinity and marked for deletion.
-Deletions are delayed
-an additional 60 seconds to ensure the invalidation is propagated
-to other routers.
-.Pp
-Hosts acting as internetwork routers gratuitously supply their
-routing tables every 30 seconds to all directly connected hosts
-and networks.
-.Pp
-If
-.Nm
-receives a
-.Dv SIGINFO
-signal the current contents of the
-.Tn RIP
-and
-.Tn SAP
-tables are appended to the file
-.Pa /var/log/ipxrouted.dmp .
-.Sh SEE ALSO
-.Xr ipx 3
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 2.2 .
diff --git a/usr.sbin/IPXrouted/Makefile b/usr.sbin/IPXrouted/Makefile
deleted file mode 100644
index 44605ac..0000000
--- a/usr.sbin/IPXrouted/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
-PROG= IPXrouted
-MAN= IPXrouted.8
-SRCS= af.c if.c input.c main.c output.c startup.c tables.c timer.c trace.c
-SRCS+= sap_input.c sap_tables.c sap_output.c
-
-WARNS?= 2
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/IPXrouted/Makefile.depend b/usr.sbin/IPXrouted/Makefile.depend
deleted file mode 100644
index 26cf195..0000000
--- a/usr.sbin/IPXrouted/Makefile.depend
+++ /dev/null
@@ -1,19 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/arpa \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/IPXrouted/af.c b/usr.sbin/IPXrouted/af.c
deleted file mode 100644
index ea61762..0000000
--- a/usr.sbin/IPXrouted/af.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)af.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-#include "defs.h"
-
-/*
- * Address family support routines
- */
-af_hash_t null_hash;
-af_netmatch_t null_netmatch;
-af_output_t null_output;
-af_portmatch_t null_portmatch;
-af_portcheck_t null_portcheck;
-af_checkhost_t null_checkhost;
-af_ishost_t null_ishost;
-af_canon_t null_canon;
-
-void ipxnet_hash(struct sockaddr_ipx *, struct afhash *);
-int ipxnet_netmatch(struct sockaddr_ipx *, struct sockaddr_ipx *);
-void ipxnet_output(int, int, struct sockaddr_ipx *, int);
-int ipxnet_portmatch(struct sockaddr_ipx *);
-int ipxnet_checkhost(struct sockaddr_ipx *);
-int ipxnet_ishost(struct sockaddr_ipx *);
-void ipxnet_canon(struct sockaddr_ipx *);
-
-#define NIL \
- { null_hash, null_netmatch, null_output, \
- null_portmatch, null_portcheck, null_checkhost, \
- null_ishost, null_canon }
-#define IPXNET \
- { (af_hash_t *)ipxnet_hash, \
- (af_netmatch_t *)ipxnet_netmatch, \
- (af_output_t *)ipxnet_output, \
- (af_portmatch_t *)ipxnet_portmatch, \
- (af_portcheck_t *)ipxnet_portmatch, \
- (af_checkhost_t *)ipxnet_checkhost, \
- (af_ishost_t *)ipxnet_ishost, \
- (af_canon_t *)ipxnet_canon }
-
-struct afswitch afswitch[AF_MAX] =
- { NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL,
- NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL,
- NIL, NIL, NIL, IPXNET, NIL, NIL };
-
-struct sockaddr_ipx ipxnet_default = { sizeof(struct sockaddr_ipx), AF_IPX };
-
-union ipx_net ipx_anynet;
-union ipx_net ipx_zeronet;
-
-void
-ipxnet_hash(sipx, hp)
- register struct sockaddr_ipx *sipx;
- struct afhash *hp;
-{
- long hash;
-#if 0
- u_short *s = sipx->sipx_addr.x_host.s_host;
-#endif
- u_char *c;
-
- c = sipx->sipx_addr.x_net.c_net;
-
-#define IMVAL 33
- hash = 0;
- hash = hash * IMVAL + *c++;
- hash = hash * IMVAL + *c++;
- hash = hash * IMVAL + *c++;
- hash = hash * IMVAL + *c++;
-#undef IMVAL
-
- hp->afh_nethash = hash;
- hp->afh_nethash ^= (hash >> 8);
- hp->afh_nethash ^= (hash >> 16);
- hp->afh_nethash ^= (hash >> 24);
-
-#if 0
- hash = 0;
- hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
- hp->afh_hosthash = hash;
-#endif
-}
-
-int
-ipxnet_netmatch(sxn1, sxn2)
- struct sockaddr_ipx *sxn1, *sxn2;
-{
- return (ipx_neteq(sxn1->sipx_addr, sxn2->sipx_addr));
-}
-
-/*
- * Verify the message is from the right port.
- */
-int
-ipxnet_portmatch(sipx)
- register struct sockaddr_ipx *sipx;
-{
-
- return (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP );
-}
-
-
-/*
- * ipx output routine.
- */
-#ifdef DEBUG
-int do_output = 0;
-#endif
-void
-ipxnet_output(s, flags, sipx, size)
- int s;
- int flags;
- struct sockaddr_ipx *sipx;
- int size;
-{
- struct sockaddr_ipx dst;
-
- dst = *sipx;
- sipx = &dst;
- if (sipx->sipx_addr.x_port == 0)
- sipx->sipx_addr.x_port = htons(IPXPORT_RIP);
-#ifdef DEBUG
- if(do_output || ntohs(msg->rip_cmd) == RIPCMD_REQUEST)
-#endif
- /*
- * Kludge to allow us to get routes out to machines that
- * don't know their addresses yet; send to that address on
- * ALL connected nets
- */
- if (ipx_neteqnn(sipx->sipx_addr.x_net, ipx_zeronet)) {
- extern struct interface *ifnet;
- register struct interface *ifp;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- sipx->sipx_addr.x_net =
- satoipx_addr(ifp->int_addr).x_net;
- (void) sendto(s, msg, size, flags,
- (struct sockaddr *)sipx, sizeof (*sipx));
- }
- return;
- }
-
- (void) sendto(s, msg, size, flags,
- (struct sockaddr *)sipx, sizeof (*sipx));
-}
-
-/*
- * Return 1 if we want this route.
- * We use this to disallow route net G entries for one for multiple
- * point to point links.
- */
-int
-ipxnet_checkhost(sipx)
- struct sockaddr_ipx *sipx;
-{
- register struct interface *ifp = if_ifwithnet((struct sockaddr *)sipx);
- /*
- * We want this route if there is no more than one
- * point to point interface with this network.
- */
- if (ifp == 0 || (ifp->int_flags & IFF_POINTOPOINT)==0) return (1);
- return (ifp->int_sq.n == ifp->int_sq.p);
-}
-
-/*
- * Return 1 if the address is
- * for a host, 0 for a network.
- */
-int
-ipxnet_ishost(sipx)
-struct sockaddr_ipx *sipx;
-{
- register u_short *s = sipx->sipx_addr.x_host.s_host;
-
- if ((s[0]==0x0000) && (s[1]==0x0000) && (s[2]==0x0000))
- return (0);
- if ((s[0]==0xffff) && (s[1]==0xffff) && (s[2]==0xffff))
- return (0);
-
- return (1);
-}
-
-void
-ipxnet_canon(sipx)
- struct sockaddr_ipx *sipx;
-{
-
- sipx->sipx_addr.x_port = 0;
-}
-
-void
-null_hash(addr, hp)
- struct sockaddr *addr;
- struct afhash *hp;
-{
-
- hp->afh_nethash = hp->afh_hosthash = 0;
-}
-
-int
-null_netmatch(a1, a2)
- struct sockaddr *a1, *a2;
-{
-
- return (0);
-}
-
-void
-null_output(s, f, a1, n)
- int s;
- int f;
- struct sockaddr *a1;
- int n;
-{
-
- ;
-}
-
-int
-null_portmatch(a1)
- struct sockaddr *a1;
-{
-
- return (0);
-}
-
-int
-null_portcheck(a1)
- struct sockaddr *a1;
-{
-
- return (0);
-}
-
-int
-null_ishost(a1)
- struct sockaddr *a1;
-{
-
- return (0);
-}
-
-int
-null_checkhost(a1)
- struct sockaddr *a1;
-{
-
- return (0);
-}
-
-void
-null_canon(a1)
- struct sockaddr *a1;
-{
-
- ;
-}
-
diff --git a/usr.sbin/IPXrouted/af.h b/usr.sbin/IPXrouted/af.h
deleted file mode 100644
index 576a6c7..0000000
--- a/usr.sbin/IPXrouted/af.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)af.h 5.1 (Berkeley) 6/4/85 (routed/af.h)
- *
- * @(#)af.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-/*
- * Routing table management daemon.
- */
-
-/*
- * Structure returned by af_hash routines.
- */
-struct afhash {
- u_int afh_hosthash; /* host based hash */
- u_int afh_nethash; /* network based hash */
-};
-
-/*
- * Per address family routines.
- */
-typedef void af_hash_t(struct sockaddr *, struct afhash *);
-typedef int af_netmatch_t(struct sockaddr *, struct sockaddr *);
-typedef void af_output_t(int, int, struct sockaddr *, int);
-typedef int af_portmatch_t(struct sockaddr *);
-typedef int af_portcheck_t(struct sockaddr *);
-typedef int af_checkhost_t(struct sockaddr *);
-typedef int af_ishost_t(struct sockaddr *);
-typedef void af_canon_t(struct sockaddr *);
-
-struct afswitch {
- af_hash_t *af_hash; /* returns keys based on address */
- af_netmatch_t *af_netmatch; /* verifies net # matching */
- af_output_t *af_output; /* interprets address for sending */
- af_portmatch_t *af_portmatch; /* packet from some other router? */
- af_portcheck_t *af_portcheck; /* packet from privileged peer? */
- af_checkhost_t *af_checkhost; /* tells if address for host or net */
- af_ishost_t *af_ishost; /* tells if address is valid */
- af_canon_t *af_canon; /* canonicalize address for compares */
-};
-
-struct afswitch afswitch[AF_MAX]; /* table proper */
diff --git a/usr.sbin/IPXrouted/defs.h b/usr.sbin/IPXrouted/defs.h
deleted file mode 100644
index c2b28a7..0000000
--- a/usr.sbin/IPXrouted/defs.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)defs.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <arpa/inet.h>
-#include <net/route.h>
-#include <netipx/ipx.h>
-#if defined(vax) || defined(pdp11)
-#define xnnet(x) ((u_long) (x)->rip_dst[1] << 16 | (u_long) (x)->rip_dst[0] )
-#else
-#define xnnet(x) ((u_long) (x)->rip_dst[0] << 16 | (u_long) (x)->rip_dst[1] )
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-
-#include "protocol.h"
-#include "sap.h"
-#include "table.h"
-#include "trace.h"
-#include "interface.h"
-#include "af.h"
-
-
-/*
- * When we find any interfaces marked down we rescan the
- * kernel every CHECK_INTERVAL seconds to see if they've
- * come up.
- */
-#define CHECK_INTERVAL (5*60)
-
-#define equal(a1, a2) \
- (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0)
-#define min(a,b) ((a)>(b)?(b):(a))
-#define max(a,b) ((a)<(b)?(b):(a))
-
-extern int ripsock; /* Socket to listen on */
-extern int sapsock; /* Socket to listen on */
-extern int kmem;
-extern int supplier; /* process should supply updates */
-extern int dosap; /* SAP is enabled */
-extern int dognreply; /* enable GET_NEAREST response */
-extern int install; /* if 1 call kernel */
-extern int lookforinterfaces; /* if 1 probe kernel for new up ifs */
-extern int performnlist; /* if 1 check if /kernel has changed */
-extern int externalinterfaces; /* # of remote and local interfaces */
-extern int timeval; /* local idea of time */
-extern int noteremoterequests; /* squawk on requests from non-local nets */
-extern int r; /* Routing socket to install updates with */
-extern int gateway;
-extern struct sockaddr_ipx ipx_netmask; /* Used in installing routes */
-
-extern char packet[MAXRXPACKETSIZE+1];
-extern struct rip *msg;
-
-extern char **argv0;
-
-#define ADD 1
-#define DELETE 2
-#define CHANGE 3
-
-void sndmsg(struct sockaddr *, int, struct interface *, int);
-void supply(struct sockaddr *, int, struct interface *, int);
-void addrouteforif(struct interface *);
-void ifinit(void);
-void toall(void (*f)(struct sockaddr *, int, struct interface *, int),
- struct rt_entry *, int);
-void rip_input(struct sockaddr *, int);
-
diff --git a/usr.sbin/IPXrouted/if.c b/usr.sbin/IPXrouted/if.c
deleted file mode 100644
index 2c6e664..0000000
--- a/usr.sbin/IPXrouted/if.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * static char sccsid[] = "@(#)if.c 5.1 (Berkeley) 6/4/85"; (routed/if.c)
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * Routing Table Management Daemon
- */
-#include "defs.h"
-
-extern struct interface *ifnet;
-
-/*
- * Find the interface with address addr.
- */
-struct interface *
-if_ifwithaddr(addr)
- struct sockaddr *addr;
-{
- register struct interface *ifp;
-
-#define same(a1, a2) \
- (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 10) == 0)
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_flags & IFF_REMOTE)
- continue;
- if (ifp->int_addr.sa_family != addr->sa_family)
- continue;
- if (same(&ifp->int_addr, addr))
- break;
- if ((ifp->int_flags & IFF_BROADCAST) &&
- same(&ifp->int_broadaddr, addr))
- break;
- }
- return (ifp);
-}
-
-/*
- * Find the point-to-point interface with destination address addr.
- */
-struct interface *
-if_ifwithdstaddr(addr)
- struct sockaddr *addr;
-{
- register struct interface *ifp;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if ((ifp->int_flags & IFF_POINTOPOINT) == 0)
- continue;
- if (same(&ifp->int_dstaddr, addr))
- break;
- }
- return (ifp);
-}
-
-/*
- * Find the interface on the network
- * of the specified address.
- */
-struct interface *
-if_ifwithnet(addr)
- register struct sockaddr *addr;
-{
- register struct interface *ifp;
- register int af = addr->sa_family;
- register int (*netmatch)();
-
- if (af >= AF_MAX)
- return (0);
- netmatch = afswitch[af].af_netmatch;
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_flags & IFF_REMOTE)
- continue;
- if (af != ifp->int_addr.sa_family)
- continue;
- if ((*netmatch)(addr, &ifp->int_addr))
- break;
- }
- return (ifp);
-}
-
-/*
- * Find an interface from which the specified address
- * should have come from. Used for figuring out which
- * interface a packet came in on -- for tracing.
- */
-struct interface *
-if_iflookup(addr)
- struct sockaddr *addr;
-{
- register struct interface *ifp, *maybe;
- register int af = addr->sa_family;
- register int (*netmatch)();
-
- if (af >= AF_MAX)
- return (0);
- maybe = 0;
- netmatch = afswitch[af].af_netmatch;
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_addr.sa_family != af)
- continue;
- if (same(&ifp->int_addr, addr))
- break;
- if ((ifp->int_flags & IFF_BROADCAST) &&
- same(&ifp->int_broadaddr, addr))
- break;
- if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr))
- maybe = ifp;
- }
- if (ifp == 0)
- ifp = maybe;
- return (ifp);
-}
diff --git a/usr.sbin/IPXrouted/input.c b/usr.sbin/IPXrouted/input.c
deleted file mode 100644
index 651a8ae..0000000
--- a/usr.sbin/IPXrouted/input.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * IPX Routing Table Management Daemon
- */
-#include "defs.h"
-
-struct sockaddr *
-ipx_nettosa(net)
-union ipx_net net;
-{
- static struct sockaddr_ipx sxn;
-
- bzero(&sxn, sizeof (struct sockaddr_ipx));
- sxn.sipx_family = AF_IPX;
- sxn.sipx_len = sizeof (sxn);
- sxn.sipx_addr.x_net = net;
- return( (struct sockaddr *)&sxn);
-
-}
-
-/*
- * Process a newly received packet.
- */
-void
-rip_input(from, size)
- struct sockaddr *from;
- int size;
-{
- int newsize;
- int rtchanged = 0;
- struct rt_entry *rt;
- struct netinfo *n;
- struct interface *ifp = 0;
- struct afswitch *afp;
- struct sockaddr_ipx *ipxp;
-
- ifp = if_ifwithnet(from);
- ipxp = (struct sockaddr_ipx *)from;
- if (ifp == 0) {
- if(ftrace) {
- fprintf(ftrace, "Received bogus packet from %s\n",
- ipxdp_ntoa(&ipxp->sipx_addr));
- }
- return;
- }
-
- TRACE_INPUT(ifp, from, size);
- if (from->sa_family >= AF_MAX)
- return;
- afp = &afswitch[from->sa_family];
-
- size -= sizeof (u_short) /* command */;
- n = msg->rip_nets;
-
- switch (ntohs(msg->rip_cmd)) {
-
- case RIPCMD_REQUEST:
- if (ipx_hosteq(satoipx_addr(ifp->int_addr), ipxp->sipx_addr))
- return;
- newsize = 0;
- while (size > 0) {
- if (size < sizeof (struct netinfo))
- break;
- size -= sizeof (struct netinfo);
-
- /*
- * A single entry with rip_dst == DSTNETS_ALL and
- * metric ``infinity'' means ``all routes''.
- *
- * XXX According to the IPX RIP spec the metric
- * and tick fields can be anything. So maybe we
- * should not check the metric???
- */
- if (ipx_neteqnn(n->rip_dst, ipx_anynet) &&
- ntohs(n->rip_metric) == HOPCNT_INFINITY &&
- size == 0) {
- supply(from, 0, ifp, 0);
- return;
- }
- /*
- * request for specific nets
- */
- rt = rtlookup(ipx_nettosa(n->rip_dst));
- if (ftrace) {
- fprintf(ftrace,
- "specific request for %s",
- ipxdp_nettoa(n->rip_dst));
- fprintf(ftrace,
- " yields route %lx\n",
- (u_long)rt);
- }
- /*
- * XXX We break out on the first net that isn't
- * found. The specs is a bit vague here. I'm not
- * sure what we should do.
- */
- if (rt == 0)
- return;
- /* XXX
- * According to the spec we should not include
- * information about networks for which the number
- * of hops is 16.
- */
- if (rt->rt_metric == (HOPCNT_INFINITY-1))
- return;
- n->rip_metric = htons( rt == 0 ? HOPCNT_INFINITY :
- min(rt->rt_metric+1, HOPCNT_INFINITY));
- n->rip_ticks = htons(rt->rt_ticks+1);
-
- /*
- * We use split horizon with a twist. If the requested
- * net is the directly connected net we supply an
- * answer. This is so that the host can learn about
- * the routers on its net.
- */
- {
- register struct rt_entry *trt = rt;
-
- while (trt) {
- if ((trt->rt_ifp == ifp) &&
- !ipx_neteqnn(n->rip_dst,
- satoipx_addr(ifp->int_addr).x_net))
- return;
- trt = trt->rt_clone;
- }
- n++;
- newsize += sizeof (struct netinfo);
- }
- }
- if (newsize > 0) {
- msg->rip_cmd = htons(RIPCMD_RESPONSE);
- newsize += sizeof (u_short);
- /* should check for if with dstaddr(from) first */
- (*afp->af_output)(ripsock, 0, from, newsize);
- TRACE_OUTPUT(ifp, from, newsize);
- if (ftrace) {
- /* XXX This should not happen anymore. */
- if(ifp == 0)
- fprintf(ftrace, "--- ifp = 0\n");
- else
- fprintf(ftrace,
- "request arrived on interface %s\n",
- ifp->int_name);
- }
- }
- return;
-
- case RIPCMD_RESPONSE:
- /* verify message came from a router */
- if ((*afp->af_portmatch)(from) == 0)
- return;
- (*afp->af_canon)(from);
- /* are we talking to ourselves? */
- if ((ifp = if_ifwithaddr(from)) != 0) {
- rt = rtfind(from);
- if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) {
- addrouteforif(ifp);
- rtchanged = 1;
- } else
- rt->rt_timer = 0;
- return;
- }
- /* Update timer for interface on which the packet arrived.
- * If from other end of a point-to-point link that isn't
- * in the routing tables, (re-)add the route.
- */
- if ((rt = rtfind(from)) && (rt->rt_state & RTS_INTERFACE)) {
- if(ftrace) fprintf(ftrace, "Got route\n");
- rt->rt_timer = 0;
- } else if ((ifp = if_ifwithdstaddr(from)) != 0) {
- if(ftrace) fprintf(ftrace, "Got partner\n");
- addrouteforif(ifp);
- rtchanged = 1;
- }
- for (; size > 0; size -= sizeof (struct netinfo), n++) {
- struct sockaddr *sa;
- if (size < sizeof (struct netinfo))
- break;
- if ((unsigned) ntohs(n->rip_metric) > HOPCNT_INFINITY)
- continue;
- rt = rtfind(sa = ipx_nettosa(n->rip_dst));
- if (rt == 0) {
- if (ntohs(n->rip_metric) == HOPCNT_INFINITY)
- continue;
- rtadd(sa, from, ntohs(n->rip_metric),
- ntohs(n->rip_ticks), 0);
- rtchanged = 1;
- continue;
- }
-
- /*
- * A clone is a different route to the same net
- * with exactly the same cost (ticks and metric).
- * They must all be recorded because those interfaces
- * must be handled in the same way as the first route
- * to that net. ie When using the split horizon
- * algorithm we must look at these interfaces also.
- *
- * Update if from gateway and different,
- * from anywhere and less ticks or
- * if same ticks and shorter,
- * or getting stale and equivalent.
- */
- if (!equal(from, &rt->rt_router) &&
- ntohs(n->rip_ticks) == rt->rt_ticks &&
- ntohs(n->rip_metric) == rt->rt_metric &&
- ntohs(n->rip_metric) != HOPCNT_INFINITY) {
- register struct rt_entry *trt = rt->rt_clone;
-
- while (trt) {
- if (equal(from, &trt->rt_router)) {
- trt->rt_timer = 0;
- break;
- }
- trt = trt->rt_clone;
- }
- if (trt == NULL) {
- rtadd_clone(rt, sa, from,
- ntohs(n->rip_metric),
- ntohs(n->rip_ticks), 0);
- }
- continue;
- }
- if ((equal(from, &rt->rt_router) &&
- ((ntohs(n->rip_ticks) != rt->rt_ticks) ||
- (ntohs(n->rip_metric) != rt->rt_metric))) ||
- (ntohs(n->rip_ticks) < rt->rt_ticks) ||
- ((ntohs(n->rip_ticks) == rt->rt_ticks) &&
- (ntohs(n->rip_metric) < rt->rt_metric)) ||
- (rt->rt_timer > (EXPIRE_TIME*2/3) &&
- rt->rt_metric == ntohs(n->rip_metric) &&
- ntohs(n->rip_metric) != HOPCNT_INFINITY)) {
- rtchange(rt, from, ntohs(n->rip_metric),
- ntohs(n->rip_ticks));
- if (ntohs(n->rip_metric) == HOPCNT_INFINITY)
- rt->rt_timer = EXPIRE_TIME;
- else
- rt->rt_timer = 0;
- rtchanged = 1;
- } else if (equal(from, &rt->rt_router) &&
- (ntohs(n->rip_ticks) == rt->rt_ticks) &&
- (ntohs(n->rip_metric) == rt->rt_metric) &&
- (ntohs(n->rip_metric) != HOPCNT_INFINITY)) {
- rt->rt_timer = 0;
- }
- }
- if (rtchanged) {
- register struct rthash *rh;
- register struct rt_entry *rt;
-
- toall(supply, NULL, 1);
- for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
- for (rt = rh->rt_forw;
- rt != (struct rt_entry *)rh;
- rt = rt->rt_forw)
- rt->rt_state &= ~RTS_CHANGED;
- }
-
- return;
- }
-}
diff --git a/usr.sbin/IPXrouted/interface.h b/usr.sbin/IPXrouted/interface.h
deleted file mode 100644
index ed7b988..0000000
--- a/usr.sbin/IPXrouted/interface.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)interface.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-/*
- * Routing table management daemon.
- */
-
-/*
- * An ``interface'' is similar to an ifnet structure,
- * except it doesn't contain q'ing info, and it also
- * handles ``logical'' interfaces (remote gateways
- * that we want to keep polling even if they go down).
- * The list of interfaces which we maintain is used
- * in supplying the gratuitous routing table updates.
- * We list only one address for each interface, the AF_IPX one.
- */
-struct interface {
- struct interface *int_next;
- struct sockaddr int_addr; /* address on this host */
- union {
- struct sockaddr intu_broadaddr;
- struct sockaddr intu_dstaddr;
- } int_intu;
-#define int_broadaddr int_intu.intu_broadaddr /* broadcast address */
-#define int_dstaddr int_intu.intu_dstaddr /* other end of p-to-p link */
- int int_metric; /* init's routing entry */
- int int_flags; /* see below */
- struct ifdebug int_input, int_output; /* packet tracing stuff */
- int int_ipackets; /* input packets received */
- int int_opackets; /* output packets sent */
- char *int_name; /* from kernel if structure */
- u_short int_transitions; /* times gone up-down */
-
- /* XXX IPX Specific entry */
- struct sameq {
- struct sameq *n; /* q of other pt-to-pt links */
- struct sameq *p; /* with same net # */
- } int_sq;
-};
-
-/*
- * 0x1 to 0x10 are reused from the kernel's ifnet definitions,
- * the others agree with the RTS_ flags defined elsewhere.
- */
-#define IFF_UP 0x1 /* interface is up */
-#define IFF_BROADCAST 0x2 /* broadcast address valid */
-#define IFF_DEBUG 0x4 /* turn on debugging */
-#define IFF_ROUTE 0x8 /* routing entry installed */
-#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */
-
-#define IFF_PASSIVE 0x200000 /* can't tell if up/down */
-#define IFF_INTERFACE 0x400000 /* hardware interface */
-#define IFF_REMOTE 0x800000 /* interface isn't on this machine */
-
-struct interface *if_ifwithaddr(struct sockaddr *);
-struct interface *if_ifwithdstaddr(struct sockaddr *);
-struct interface *if_ifwithnet(struct sockaddr *);
-struct interface *if_iflookup(struct sockaddr *);
-
diff --git a/usr.sbin/IPXrouted/main.c b/usr.sbin/IPXrouted/main.c
deleted file mode 100644
index 773410a..0000000
--- a/usr.sbin/IPXrouted/main.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1985, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static const char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * IPX Routing Information Protocol Daemon
- */
-#include "defs.h"
-#include <sys/time.h>
-
-#include <net/if.h>
-
-#include <errno.h>
-#include <nlist.h>
-#include <signal.h>
-#include <paths.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#define SAP_PKT 0
-#define RIP_PKT 1
-
-struct sockaddr_ipx addr; /* Daemon's Address */
-int ripsock; /* RIP Socket to listen on */
-int sapsock; /* SAP Socket to listen on */
-int kmem;
-int install; /* if 1 call kernel */
-int lookforinterfaces; /* if 1 probe kernel for new up interfaces */
-int performnlist; /* if 1 check if /kernel has changed */
-int externalinterfaces; /* # of remote and local interfaces */
-int timeval; /* local idea of time */
-int noteremoterequests; /* squawk on requests from non-local nets */
-int r; /* Routing socket to install updates with */
-struct sockaddr_ipx ipx_netmask; /* Used in installing routes */
-
-char packet[MAXRXPACKETSIZE+1];
-
-char **argv0;
-
-int supplier = -1; /* process should supply updates */
-int dosap = 1; /* By default do SAP services. */
-int dobcast = 1; /* A RIP/SAP broadcast is needed. */
-time_t lastbcast; /* Time of last RIP/SAP broadcast */
-
-struct rip *msg = (struct rip *) &packet[sizeof (struct ipx)];
-struct sap_packet *sap_msg =
- (struct sap_packet *) &packet[sizeof (struct ipx)];
-void hup(), fkexit(), timer();
-void process(int fd, int pkt_type);
-int getsocket(int type, int proto, struct sockaddr_ipx *sipx);
-void getinfo();
-void catchtimer();
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int nfds;
- fd_set fdvar;
- time_t ttime;
- struct itimerval tval;
-
- argv0 = argv;
- argv++, argc--;
- while (argc > 0 && **argv == '-') {
- if (strcmp(*argv, "-s") == 0) {
- supplier = 1;
- argv++, argc--;
- continue;
- }
- if (strcmp(*argv, "-q") == 0) {
- supplier = 0;
- argv++, argc--;
- continue;
- }
- if (strcmp(*argv, "-R") == 0) {
- noteremoterequests++;
- argv++, argc--;
- continue;
- }
- if (strcmp(*argv, "-S") == 0) {
- dosap = 0;
- argv++, argc--;
- continue;
- }
- if (strcmp(*argv, "-t") == 0) {
- tracepackets++;
- argv++, argc--;
- ftrace = stderr;
- tracing = 1;
- continue;
- }
- if (strcmp(*argv, "-g") == 0) {
- gateway = 1;
- argv++, argc--;
- continue;
- }
- if (strcmp(*argv, "-l") == 0) {
- gateway = -1;
- argv++, argc--;
- continue;
- }
- if (strcmp(*argv, "-N") == 0) {
- dognreply = 0;
- argv++, argc--;
- continue;
- }
- fprintf(stderr,
- "usage: ipxrouted [ -s ] [ -q ] [ -t ] [ -g ] [ -l ] [ -N ]\n");
- exit(1);
- }
-
-
-#ifndef DEBUG
- if (!tracepackets)
- daemon(0, 0);
-#endif
- openlog("IPXrouted", LOG_PID, LOG_DAEMON);
-
- addr.sipx_family = AF_IPX;
- addr.sipx_len = sizeof(addr);
- addr.sipx_port = htons(IPXPORT_RIP);
- ipx_anynet.s_net[0] = ipx_anynet.s_net[1] = -1;
- ipx_netmask.sipx_addr.x_net = ipx_anynet;
- ipx_netmask.sipx_len = 6;
- ipx_netmask.sipx_family = AF_IPX;
- r = socket(AF_ROUTE, SOCK_RAW, 0);
- /* later, get smart about lookingforinterfaces */
- if (r)
- shutdown(r, SHUT_RD); /* for now, don't want reponses */
- else {
- fprintf(stderr, "IPXrouted: no routing socket\n");
- exit(1);
- }
- ripsock = getsocket(SOCK_DGRAM, 0, &addr);
- if (ripsock < 0)
- exit(1);
-
- if (dosap) {
- addr.sipx_port = htons(IPXPORT_SAP);
- sapsock = getsocket(SOCK_DGRAM, 0, &addr);
- if (sapsock < 0)
- exit(1);
- } else
- sapsock = -1;
-
- /*
- * Any extra argument is considered
- * a tracing log file.
- */
- if (argc > 0)
- traceon(*argv);
- /*
- * Collect an initial view of the world by
- * snooping in the kernel. Then, send a request packet on all
- * directly connected networks to find out what
- * everyone else thinks.
- */
- rtinit();
- sapinit();
- ifinit();
- if (supplier < 0)
- supplier = 0;
- /* request the state of the world */
- msg->rip_cmd = htons(RIPCMD_REQUEST);
- msg->rip_nets[0].rip_dst = ipx_anynet;
- msg->rip_nets[0].rip_metric = htons(HOPCNT_INFINITY);
- msg->rip_nets[0].rip_ticks = htons(-1);
- toall(sndmsg, NULL, 0);
-
- if (dosap) {
- sap_msg->sap_cmd = htons(SAP_REQ);
- sap_msg->sap[0].ServType = htons(SAP_WILDCARD);
- toall(sapsndmsg, NULL, 0);
- }
-
- signal(SIGALRM, catchtimer);
- signal(SIGHUP, hup);
- signal(SIGINT, hup);
- signal(SIGEMT, fkexit);
- signal(SIGINFO, getinfo);
-
- tval.it_interval.tv_sec = TIMER_RATE;
- tval.it_interval.tv_usec = 0;
- tval.it_value.tv_sec = TIMER_RATE;
- tval.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &tval, NULL);
-
- nfds = 1 + max(sapsock, ripsock);
-
- for (;;) {
- if (dobcast) {
- dobcast = 0;
- lastbcast = time(NULL);
- timer();
- }
-
- FD_ZERO(&fdvar);
- if (dosap) {
- FD_SET(sapsock, &fdvar);
- }
- FD_SET(ripsock, &fdvar);
-
- if(select(nfds, &fdvar, (fd_set *)NULL, (fd_set *)NULL,
- (struct timeval *)NULL) < 0) {
- if(errno == EINTR)
- continue;
- perror("during select");
- exit(1);
- }
-
- if(FD_ISSET(ripsock, &fdvar))
- process(ripsock, RIP_PKT);
-
- if(dosap && FD_ISSET(sapsock, &fdvar))
- process(sapsock, SAP_PKT);
-
- ttime = time(NULL);
- if (ttime > (lastbcast + TIMER_RATE + (TIMER_RATE * 2 / 3))) {
- dobcast = 1;
- syslog(LOG_ERR, "Missed alarm");
- }
- }
-}
-
-void
-process(fd, pkt_type)
- int fd;
- int pkt_type;
-{
- struct sockaddr from;
- int cc, omask;
- socklen_t fromlen = sizeof (from);
- struct ipx *ipxdp = (struct ipx *)packet;
-
- cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen);
- if (cc <= 0) {
- if (cc < 0 && errno != EINTR)
- syslog(LOG_ERR, "recvfrom: %m");
- return;
- }
- if (tracepackets > 1 && ftrace) {
- fprintf(ftrace,"rcv %d bytes on %s ",
- cc, ipxdp_ntoa(&ipxdp->ipx_dna));
- fprintf(ftrace," from %s\n", ipxdp_ntoa(&ipxdp->ipx_sna));
- }
-
- if (noteremoterequests &&
- !ipx_neteqnn(ipxdp->ipx_sna.x_net, ipx_zeronet) &&
- !ipx_neteq(ipxdp->ipx_sna, ipxdp->ipx_dna))
- {
- syslog(LOG_ERR,
- "net of interface (%s) != net on ether (%s)!\n",
- ipxdp_nettoa(ipxdp->ipx_dna.x_net),
- ipxdp_nettoa(ipxdp->ipx_sna.x_net));
- }
-
- /* We get the IPX header in front of the RIF packet*/
- cc -= sizeof (struct ipx);
-#define mask(s) (1<<((s)-1))
- omask = sigblock(mask(SIGALRM));
- switch(pkt_type) {
- case SAP_PKT: sap_input(&from, cc);
- break;
- case RIP_PKT: rip_input(&from, cc);
- break;
- }
- sigsetmask(omask);
-}
-
-int
-getsocket(type, proto, sipx)
- int type, proto;
- struct sockaddr_ipx *sipx;
-{
- int domain = sipx->sipx_family;
- int retry, s, on = 1;
-
- retry = 1;
- while ((s = socket(domain, type, proto)) < 0 && retry) {
- syslog(LOG_ERR, "socket: %m");
- sleep(5 * retry);
- retry <<= 1;
- }
- if (retry == 0)
- return (-1);
- while (bind(s, (struct sockaddr *)sipx, sizeof (*sipx)) < 0 && retry) {
- syslog(LOG_ERR, "bind: %m");
- sleep(5 * retry);
- retry <<= 1;
- }
- if (retry == 0)
- return (-1);
- if (domain==AF_IPX) {
- struct ipx ipxdp;
- if (setsockopt(s, 0, SO_HEADERS_ON_INPUT, &on, sizeof(on))) {
- syslog(LOG_ERR, "setsockopt SEE HEADERS: %m");
- exit(1);
- }
- if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_RIP)
- ipxdp.ipx_pt = IPXPROTO_RI;
- else if (ntohs(sipx->sipx_addr.x_port) == IPXPORT_SAP)
-#ifdef IPXPROTO_SAP
- ipxdp.ipx_pt = IPXPROTO_SAP;
-#else
- ipxdp.ipx_pt = IPXPROTO_PXP;
-#endif
- else {
- syslog(LOG_ERR, "port should be either RIP or SAP");
- exit(1);
- }
- if (setsockopt(s, 0, SO_DEFAULT_HEADERS, &ipxdp, sizeof(ipxdp))) {
- syslog(LOG_ERR, "setsockopt SET HEADER: %m");
- exit(1);
- }
- }
- if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
- syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
- exit(1);
- }
- return (s);
-}
-
-/*
- * Fork and exit on EMT-- for profiling.
- */
-void
-fkexit()
-{
- if (fork() == 0)
- exit(0);
-}
-
-void
-catchtimer()
-{
- dobcast = 1;
-}
-
-void
-getinfo()
-{
- FILE *fh;
-
- fh = fopen("/var/log/ipxrouted.dmp", "a");
- if(fh == NULL)
- return;
-
- dumpriptable(fh);
- dumpsaptable(fh, sap_head);
-
- fclose(fh);
-}
-
diff --git a/usr.sbin/IPXrouted/output.c b/usr.sbin/IPXrouted/output.c
deleted file mode 100644
index 78922c9..0000000
--- a/usr.sbin/IPXrouted/output.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)output.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * Routing Table Management Daemon
- */
-#include <unistd.h>
-#include "defs.h"
-
-/*
- * Apply the function "f" to all non-passive
- * interfaces. If the interface supports the
- * use of broadcasting use it, otherwise address
- * the output to the known router.
- */
-void
-toall(f, except, changesonly)
- void (*f)(struct sockaddr *, int, struct interface *, int);
- struct rt_entry *except;
- int changesonly;
-{
- register struct interface *ifp;
- register struct sockaddr *dst;
- register int flags;
- register struct rt_entry *trt;
- int onlist;
- extern struct interface *ifnet;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_flags & IFF_PASSIVE)
- continue;
-
- /*
- * Don't send it on interfaces in the except list.
- */
- onlist = 0;
- trt = except;
- while(trt) {
- if (ifp == trt->rt_ifp) {
- onlist = 1;
- break;
- }
- trt = trt->rt_clone;
- }
- if (onlist)
- continue;
-
- dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr :
- ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr :
- &ifp->int_addr;
- flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
- (*f)(dst, flags, ifp, changesonly);
- }
-}
-
-/*
- * Output a preformed packet.
- */
-void
-sndmsg(dst, flags, ifp, changesonly)
- struct sockaddr *dst;
- int flags;
- struct interface *ifp;
- int changesonly;
-{
-
- (*afswitch[dst->sa_family].af_output)
- (ripsock, flags, dst, sizeof (struct rip));
- TRACE_OUTPUT(ifp, dst, sizeof (struct rip));
-}
-
-/*
- * Supply dst with the contents of the routing tables.
- * If this won't fit in one packet, chop it up into several.
- *
- * This must be done using the split horizon algorithm.
- * 1. Don't send routing info to the interface from where it was received.
- * 2. Don't publish an interface to itself.
- * 3. If a route is received from more than one interface and the cost is
- * the same, don't publish it on either interface. I am calling this
- * clones.
- */
-void
-supply(dst, flags, ifp, changesonly)
- struct sockaddr *dst;
- int flags;
- struct interface *ifp;
- int changesonly;
-{
- register struct rt_entry *rt;
- register struct rt_entry *crt; /* Clone route */
- register struct rthash *rh;
- register struct netinfo *nn;
- register struct netinfo *n = msg->rip_nets;
- struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst;
- af_output_t *output = afswitch[dst->sa_family].af_output;
- int size, metric, ticks;
- union ipx_net net;
- int delay = 0;
-
- if (sipx->sipx_port == 0)
- sipx->sipx_port = htons(IPXPORT_RIP);
-
- msg->rip_cmd = ntohs(RIPCMD_RESPONSE);
- for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
- for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
- size = (char *)n - (char *)msg;
- if (size >= ((MAXRIPNETS * sizeof (struct netinfo)) +
- sizeof (msg->rip_cmd))) {
- (*output)(ripsock, flags, dst, size);
- TRACE_OUTPUT(ifp, dst, size);
- n = msg->rip_nets;
- delay++;
- if(delay == 2) {
- usleep(50000);
- delay = 0;
- }
- }
-
- if (changesonly && !(rt->rt_state & RTS_CHANGED))
- continue;
-
- /*
- * This should do rule one and two of the split horizon
- * algorithm.
- */
- if (rt->rt_ifp == ifp)
- continue;
-
- /*
- * Rule 3.
- * Look if we have clones (different routes to the same
- * place with exactly the same cost).
- *
- * We should not publish on any of the clone interfaces.
- */
- crt = rt->rt_clone;
- while (crt) {
- if (crt->rt_ifp == ifp)
- goto next;
- crt = crt->rt_clone;
- }
-
- sipx = (struct sockaddr_ipx *)&rt->rt_dst;
- if ((rt->rt_flags & (RTF_HOST|RTF_GATEWAY)) == RTF_HOST)
- sipx = (struct sockaddr_ipx *)&rt->rt_router;
- if (rt->rt_metric == HOPCNT_INFINITY)
- metric = HOPCNT_INFINITY;
- else {
- metric = rt->rt_metric + 1;
- /*
- * We don't advertize routes with more than 15 hops.
- */
- if (metric >= HOPCNT_INFINITY)
- continue;
- }
- /* XXX One day we should cater for slow interfaces also. */
- ticks = rt->rt_ticks + 1;
- net = sipx->sipx_addr.x_net;
-
- /*
- * Make sure that we don't put out a two net entries
- * for a pt to pt link (one for the G route, one for the if)
- * This is a kludge, and won't work if there are lots of nets.
- */
- for (nn = msg->rip_nets; nn < n; nn++) {
- if (ipx_neteqnn(net, nn->rip_dst)) {
- if (ticks < ntohs(nn->rip_ticks)) {
- nn->rip_metric = htons(metric);
- nn->rip_ticks = htons(ticks);
- } else if ((ticks == ntohs(nn->rip_ticks)) &&
- (metric < ntohs(nn->rip_metric))) {
- nn->rip_metric = htons(metric);
- nn->rip_ticks = htons(ticks);
- }
- goto next;
- }
- }
- n->rip_dst = net;
- n->rip_metric = htons(metric);
- n->rip_ticks = htons(ticks);
- n++;
- next:;
- }
- if (n != msg->rip_nets) {
- size = (char *)n - (char *)msg;
- (*output)(ripsock, flags, dst, size);
- TRACE_OUTPUT(ifp, dst, size);
- }
-}
diff --git a/usr.sbin/IPXrouted/protocol.h b/usr.sbin/IPXrouted/protocol.h
deleted file mode 100644
index 7fae536..0000000
--- a/usr.sbin/IPXrouted/protocol.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)protocol.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-/*
- * IPX Routing Information Protocol
- *
- */
-
-struct netinfo {
- union ipx_net rip_dst; /* destination net */
- u_short rip_metric; /* cost of route */
- u_short rip_ticks; /* cost of route */
-};
-
-struct rip {
- u_short rip_cmd; /* request/response */
- struct netinfo rip_nets[1]; /* variable length */
-};
-
-/*
- * Packet types.
- */
-#define RIPCMD_REQUEST 1 /* want info */
-#define RIPCMD_RESPONSE 2 /* responding to request */
-
-#define RIPCMD_MAX 3
-#ifdef RIPCMDS
-char *ripcmds[RIPCMD_MAX] =
- { "#0", "REQUEST", "RESPONSE" };
-#endif
-
-#define HOPCNT_INFINITY 16 /* per IPX */
-#define DSTNETS_ALL 0xffffffff /* per IPX */
-#define MAXRXPACKETSIZE 1500 /* max rx broadcast size */
-#define MAXRIPNETS 50 /* max nets in tx packet */
-
-extern union ipx_net ipx_anynet;
-extern union ipx_net ipx_zeronet;
-
-/*
- * Timer values used in managing the routing table.
- * Every update forces an entry's timer to be reset. After
- * EXPIRE_TIME without updates, the entry is marked invalid,
- * but held onto until GARBAGE_TIME so that others may
- * see it "be deleted".
- */
-#define TIMER_RATE 30 /* alarm clocks every 30 seconds */
-
-#define SUPPLY_INTERVAL 30 /* time to supply tables */
-#define RIP_INTERVAL 60 /* time to supply rip tables */
-
-#define EXPIRE_TIME 180 /* time to mark entry invalid */
-#define GARBAGE_TIME 240 /* time to garbage collect */
diff --git a/usr.sbin/IPXrouted/sap.h b/usr.sbin/IPXrouted/sap.h
deleted file mode 100644
index b4e9dcb..0000000
--- a/usr.sbin/IPXrouted/sap.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by John Hay.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-#ifndef _SAP_H_
-#define _SAP_H_
-
-#define SAP_REQ 1
-#define SAP_RESP 2
-#define SAP_REQ_NEAR 3
-#define SAP_RESP_NEAR 4
-
-#define SAPCMD_MAX 5
-#ifdef SAPCMDS
-char *sapcmds[SAPCMD_MAX] =
- { "#0", "REQUEST", "RESPONSE", "REQ NEAREST", "RESP NEAREST"};
-#endif
-
-#define MAXSAPENTRIES 7
-#define SAP_WILDCARD 0xFFFF
-#define SERVNAMELEN 48
-typedef struct sap_info {
- u_short ServType;
- char ServName[SERVNAMELEN];
- struct ipx_addr ipx;
- u_short hops;
- }sap_info;
-
-typedef struct sap_packet {
- u_short sap_cmd;
- sap_info sap[0]; /* Variable length. */
- }sap_packet;
-
-typedef struct sap_entry {
- struct sap_entry *forw;
- struct sap_entry *back;
- struct sap_entry *clone;
- struct interface *ifp;
- struct sap_info sap;
- struct sockaddr source;
- int hash;
- int state;
- int timer;
- }sap_entry;
-
-#define SAPHASHSIZ 256 /* Should be a power of 2 */
-#define SAPHASHMASK (SAPHASHSIZ-1)
-typedef struct sap_hash {
- struct sap_entry *forw;
- struct sap_entry *back;
- }sap_hash;
-
-extern sap_hash sap_head[SAPHASHSIZ];
-
-extern struct sap_packet *sap_msg;
-
-void sapinit(void);
-void sap_input(struct sockaddr *from, int size);
-void sapsndmsg(struct sockaddr *dst, int flags, struct interface *ifp,
- int changesonly);
-void sap_supply_toall(int changesonly);
-void sap_supply(struct sockaddr *dst,
- int flags,
- struct interface *ifp,
- int ServType,
- int changesonly);
-
-struct sap_entry *sap_lookup(u_short ServType, char *ServName);
-struct sap_entry *sap_nearestserver(ushort ServType, struct interface *ifp);
-void sap_add(struct sap_info *si, struct sockaddr *from);
-void sap_change(struct sap_entry *sap,
- struct sap_info *si,
- struct sockaddr *from);
-void sap_add_clone(struct sap_entry *sap,
- struct sap_info *clone,
- struct sockaddr *from);
-void sap_delete(struct sap_entry *sap);
-
-#endif /*_SAP_H_*/
-
diff --git a/usr.sbin/IPXrouted/sap_input.c b/usr.sbin/IPXrouted/sap_input.c
deleted file mode 100644
index a503471..0000000
--- a/usr.sbin/IPXrouted/sap_input.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by John Hay.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * IPX Routing Table Management Daemon
- */
-#include "defs.h"
-
-int dognreply = 1;
-
-/*
- * Process a newly received packet.
- */
-void
-sap_input(from, size)
- struct sockaddr *from;
- int size;
-{
- int newsize;
- int sapchanged = 0;
- struct sap_entry *sap;
- struct sap_info *n;
- struct interface *ifp = 0;
- struct afswitch *afp;
- struct sockaddr_ipx *ipxp;
-
- ifp = if_ifwithnet(from);
- ipxp = (struct sockaddr_ipx *)from;
- if (ifp == 0) {
- if(ftrace) {
- fprintf(ftrace, "Received bogus packet from %s\n",
- ipxdp_ntoa(&ipxp->sipx_addr));
- }
- return;
- }
-
- if (ftrace)
- dumpsappacket(ftrace, "received", from, (char *)sap_msg , size);
-
- if (from->sa_family >= AF_MAX)
- return;
- afp = &afswitch[from->sa_family];
-
- size -= sizeof (u_short) /* command */;
- n = sap_msg->sap;
-
- switch (ntohs(sap_msg->sap_cmd)) {
-
- case SAP_REQ_NEAR:
- if (ftrace)
- fprintf(ftrace, "Received a sap REQ_NEAR packet.\n");
- if (!dognreply)
- return;
- sap = sap_nearestserver(n->ServType, ifp);
- if (sap == NULL)
- return;
- sap_msg->sap_cmd = htons(SAP_RESP_NEAR);
- *n = sap->sap;
- n->hops = htons(ntohs(n->hops) + 1);
- if (ntohs(n->hops) >= HOPCNT_INFINITY)
- return;
-
- newsize = sizeof(struct sap_info) + sizeof(struct sap_packet);
- (*afp->af_output)(sapsock, 0, from, newsize);
- if (ftrace) {
- fprintf(ftrace, "sap_nearestserver %X %s returned:\n",
- ntohs(n->ServType),
- ifp->int_name);
- fprintf(ftrace, " service %04X %-20.20s "
- "addr %s.%04X metric %d\n",
- ntohs(sap->sap.ServType),
- sap->sap.ServName,
- ipxdp_ntoa(&sap->sap.ipx),
- ntohs(sap->sap.ipx.x_port),
- ntohs(sap->sap.hops));
- }
- return;
-
- case SAP_REQ:
- if (ftrace)
- fprintf(ftrace, "Received a sap REQ packet.\n");
-
- sap_supply(from, 0, ifp, n->ServType, 0);
- return;
-
- case SAP_RESP_NEAR:
- /* XXX We do nothing here, for the moment.
- * Maybe we should check if the service is in our table?
- *
- */
- if (ftrace)
- fprintf(ftrace, "Received a sap RESP_NEAR packet.\n");
-
- return;
-
- case SAP_RESP:
- if (ftrace)
- fprintf(ftrace, "Received a sap RESP packet.\n");
-
- (*afp->af_canon)(from);
-
- for (; size > 0; size -= sizeof (struct sap_info), n++) {
- if (size < sizeof (struct netinfo))
- break;
- /*
- * The idea here is that if the hop count is more
- * than INFINITY it is bogus and should be discarded.
- * If it is equal to INFINITY it is a message to say
- * that a service went down. If we don't already
- * have it in our tables discard it. Otherwise
- * update our table and set the timer to EXPIRE_TIME
- * so that it is removed next time we go through the
- * tables.
- */
- if (ntohs(n->hops) > HOPCNT_INFINITY)
- continue;
- sap = sap_lookup(n->ServType, n->ServName);
- if (sap == 0) {
- if (ntohs(n->hops) == HOPCNT_INFINITY)
- continue;
- sap_add(n, from);
- sapchanged = 1;
- continue;
- }
-
- /*
- * A clone is a different route to the same service
- * with exactly the same cost (metric).
- * They must all be recorded because those interfaces
- * must be handled in the same way as the first route
- * to that service. ie When using the split horizon
- * algorithm we must look at these interfaces also.
- *
- * Update if from gateway and different,
- * from anywhere and less hops or
- * getting stale and equivalent.
- */
- if (((ifp != sap->ifp) ||
- !equal(&sap->source, from)) &&
- (n->hops == sap->sap.hops) &&
- (ntohs(n->hops) != HOPCNT_INFINITY)) {
- register struct sap_entry *tsap = sap->clone;
-
- while (tsap) {
- if ((ifp == tsap->ifp) &&
- equal(&tsap->source, from)) {
- tsap->timer = 0;
- break;
- }
- tsap = tsap->clone;
- }
- if (tsap == NULL) {
- sap_add_clone(sap, n, from);
- }
- continue;
- }
- if ((ifp == sap->ifp) &&
- equal(&sap->source, from) &&
- (ntohs(n->hops) == ntohs(sap->sap.hops)))
- sap->timer = 0;
- else if (((ifp == sap->ifp) &&
- equal(&sap->source, from) &&
- (n->hops != sap->sap.hops)) ||
- (ntohs(n->hops) < ntohs(sap->sap.hops)) ||
- (sap->timer > (EXPIRE_TIME*2/3) &&
- ntohs(sap->sap.hops) == ntohs(n->hops) &&
- ntohs(n->hops) != HOPCNT_INFINITY)) {
- sap_change(sap, n, from);
- sapchanged = 1;
- }
- }
- if (sapchanged) {
- register struct sap_entry *sap;
- register struct sap_hash *sh;
- sap_supply_toall(1);
-
- for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++)
- for (sap = sh->forw;
- sap != (struct sap_entry *)sh;
- sap = sap->forw)
- sap->state &= ~RTS_CHANGED;
- }
- return;
- }
-}
diff --git a/usr.sbin/IPXrouted/sap_output.c b/usr.sbin/IPXrouted/sap_output.c
deleted file mode 100644
index d1f1a28..0000000
--- a/usr.sbin/IPXrouted/sap_output.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by John Hay.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*
- * Routing Table Management Daemon
- */
-#include <unistd.h>
-#include "defs.h"
-
-/*
- * Apply the function "f" to all non-passive
- * interfaces. If the interface supports the
- * use of broadcasting use it, otherwise address
- * the output to the known router.
- */
-void
-sap_supply_toall(changesonly)
- int changesonly;
-{
- register struct interface *ifp;
- struct sockaddr dst;
- register struct sockaddr_ipx *ipx_dst;
- register int flags;
- extern struct interface *ifnet;
-
- ipx_dst = (struct sockaddr_ipx *)&dst;
-
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
- if (ifp->int_flags & IFF_PASSIVE)
- continue;
-
- dst = ifp->int_flags & IFF_BROADCAST ? ifp->int_broadaddr :
- ifp->int_flags & IFF_POINTOPOINT ? ifp->int_dstaddr :
- ifp->int_addr;
-
- ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP);
-
- flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0;
- sap_supply(&dst, flags, ifp, SAP_WILDCARD, changesonly);
- }
-}
-
-void
-sapsndmsg(dst, flags, ifp, changesonly)
- struct sockaddr *dst;
- int flags;
- struct interface *ifp;
- int changesonly;
-{
- struct sockaddr t_dst;
- struct sockaddr_ipx *ipx_dst;
-
- t_dst = *dst;
- ipx_dst = (struct sockaddr_ipx *)&t_dst;
-
- if (ipx_dst->sipx_addr.x_port == 0)
- ipx_dst->sipx_addr.x_port = htons(IPXPORT_SAP);
-
- (*afswitch[dst->sa_family].af_output)
- (sapsock, flags, &t_dst,
- sizeof (struct sap_packet) + sizeof(u_short));
- TRACE_SAP_OUTPUT(ifp, &t_dst,
- sizeof (struct sap_packet) + sizeof(u_short));
-}
-
-/*
- * Supply dst with the contents of the SAP tables. If the ServType ==
- * SAP_WILDCARD (0xFFFF) supply the whole table, otherwise only the
- * services that are of ServType. If this won't fit in one packet, chop
- * it up into several.
- *
- * This must be done using the split horizon algorithm.
- * 1. Don't send SAP info to the interface from where it was received.
- * 2. If a service is received from more than one interface and the cost is
- * the same, don't publish it on either interface. I am calling this
- * clones.
- */
-void
-sap_supply(dst, flags, ifp, ServType, changesonly)
- struct sockaddr *dst;
- int flags;
- struct interface *ifp;
- int ServType;
- int changesonly;
-{
- register struct sap_entry *sap;
- register struct sap_entry *csap; /* Clone route */
- register struct sap_hash *sh;
- register struct sap_info *n = sap_msg->sap;
- struct sap_hash *base = sap_head;
- struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) dst;
- af_output_t *output = afswitch[dst->sa_family].af_output;
- int size, metric;
- int delay = 0;
-
- if (sipx->sipx_port == 0)
- sipx->sipx_port = htons(IPXPORT_SAP);
-
- sap_msg->sap_cmd = ntohs(SAP_RESP);
-
- for (sh = base; sh < &base[SAPHASHSIZ]; sh++)
- for (sap = sh->forw; sap != (struct sap_entry *)sh; sap = sap->forw) {
- size = (char *)n - (char *)sap_msg;
- if (size >= ((MAXSAPENTRIES * sizeof (struct sap_info)) +
- sizeof (sap_msg->sap_cmd))) {
- (*output)(sapsock, flags, dst, size);
- TRACE_SAP_OUTPUT(ifp, dst, size);
- n = sap_msg->sap;
- delay++;
- if(delay == 2) {
- usleep(50000);
- delay = 0;
- }
- }
-
- if (changesonly && !(sap->state & RTS_CHANGED))
- continue;
-
- /*
- * Check for the servicetype except if the ServType is
- * a wildcard (0xFFFF).
- */
- if ((ServType != SAP_WILDCARD) &&
- (ServType != sap->sap.ServType))
- continue;
-
- /*
- * This should do rule one and two of the split horizon
- * algorithm.
- */
- if (sap->ifp == ifp)
- continue;
-
- /*
- * Rule 2.
- * Look if we have clones (different routes to the same
- * place with exactly the same cost).
- *
- * We should not publish on any of the clone interfaces.
- */
- csap = sap->clone;
- while (csap) {
- if (csap->ifp == ifp)
- goto next;
- csap = csap->clone;
- }
-
- /*
- * Don't advertise services with more than 15 hops. It
- * will be confused with a service that has gone down.
- */
- if (ntohs(sap->sap.hops) == (HOPCNT_INFINITY - 1))
- continue;
- metric = min(ntohs(sap->sap.hops) + 1, HOPCNT_INFINITY);
-
- *n = sap->sap;
- n->hops = htons(metric);
- n++;
-next:
- ;
- }
- if (n != sap_msg->sap) {
- size = (char *)n - (char *)sap_msg;
- (*output)(sapsock, flags, dst, size);
- TRACE_SAP_OUTPUT(ifp, dst, size);
- }
-}
-
diff --git a/usr.sbin/IPXrouted/sap_tables.c b/usr.sbin/IPXrouted/sap_tables.c
deleted file mode 100644
index 57b5af5..0000000
--- a/usr.sbin/IPXrouted/sap_tables.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by John Hay.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY John Hay AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL John Hay OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include "defs.h"
-#include <search.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));}
-
-sap_hash sap_head[SAPHASHSIZ];
-
-void
-sapinit(void)
-{
- int i;
-
- for (i=0; i<SAPHASHSIZ; i++)
- sap_head[i].forw = sap_head[i].back =
- (struct sap_entry *)&sap_head[i];
-}
-
-/*
- * This hash use the first 14 letters of the ServName and the ServType
- * to create a 32 bit hash value.
- */
-int
-saphash(u_short ServType, char *ServName)
-{
- int hsh, i;
- char name[SERVNAMELEN];
-
- bzero(name, SERVNAMELEN);
- strncpy(name, ServName, SERVNAMELEN);
- ServName = name;
-
- hsh = 0;
-
-#define SMVAL 33
-
- hsh = hsh * SMVAL + (ServType & 0xff);
- hsh = hsh * SMVAL + (ServType >> 8);
-
- for (i=0;i<14;i++) {
- hsh = hsh * SMVAL + *ServName++;
- ServName++;
- }
-
-#undef SMVAL
-
- return hsh;
-}
-
-/*
- * Look for an exact match on ServType and ServName. It is
- * mostly used by the function that process SAP RESPONSE packets.
- *
- * A hash is created and used to index into the hash table. Then
- * that list is walk through searching for a match.
- *
- * If no match is found NULL is returned.
- */
-struct sap_entry *
-sap_lookup(u_short ServType, char *ServName)
-{
- register struct sap_entry *sap;
- register struct sap_hash *sh;
- int hsh;
-
- hsh = saphash(ServType, ServName);
- sh = &sap_head[hsh & SAPHASHMASK];
-
- for(sap = sh->forw; sap != (sap_entry *)sh; sap = sap->forw) {
- if ((hsh == sap->hash) &&
- (ServType == sap->sap.ServType) &&
- (strncmp(ServName, sap->sap.ServName, SERVNAMELEN) == 0)) {
- return sap;
- }
- }
- return NULL;
-}
-
-/*
- * This returns the nearest service of the specified type. If no
- * suitable service is found or if that service is on the interface
- * where the request came from, NULL is returned.
- *
- * When checking interfaces clones must be considered also.
- *
- * XXX TODO:
- * Maybe we can use RIP tables to get the fastest service (ticks).
- */
-struct sap_entry *
-sap_nearestserver(ushort ServType, struct interface *ifp)
-{
- register struct sap_entry *sap;
- struct sap_hash *sh;
- register struct sap_entry *best = NULL;
- register int besthops = HOPCNT_INFINITY;
-
- sh = sap_head;
-
- for (; sh < &sap_head[SAPHASHSIZ]; sh++)
- for(sap = sh->forw; sap != (sap_entry *)sh; sap = sap->forw) {
- if (ServType != sap->sap.ServType)
- continue;
-
- if (ntohs(sap->sap.hops) < besthops) {
- best = sap;
- besthops = ntohs(best->sap.hops);
- }
- }
- return best;
-}
-
-/*
- * Add an entry to the SAP table.
- *
- * If the malloc fail, the entry will silently be thrown away.
- */
-void
-sap_add(struct sap_info *si, struct sockaddr *from)
-{
- register struct sap_entry *nsap;
- register struct sap_hash *sh;
-
- if (ntohs(si->hops) == HOPCNT_INFINITY)
- return;
-
- FIXLEN(from);
- nsap = malloc(sizeof(struct sap_entry));
- if (nsap == NULL)
- return;
-
- nsap->sap = *si;
- nsap->source = *from;
- nsap->clone = NULL;
- nsap->ifp = if_ifwithnet(from);
- nsap->state = RTS_CHANGED;
- nsap->timer = 0;
- nsap->hash = saphash(si->ServType, si->ServName);
-
- sh = &sap_head[nsap->hash & SAPHASHMASK];
-
- insque(nsap, sh);
- TRACE_SAP_ACTION("ADD", nsap);
-}
-
-/*
- * Change an existing SAP entry. If a clone exist for the old one,
- * check if it is cheaper. If it is change to the clone, otherwise
- * delete all the clones.
- */
-void
-sap_change(struct sap_entry *sap,
- struct sap_info *si,
- struct sockaddr *from)
-{
- struct sap_entry *osap = NULL;
-
- FIXLEN(from);
- TRACE_SAP_ACTION("CHANGE FROM", sap);
- /*
- * If the hopcount (metric) is HOPCNT_INFINITY (16) it means that
- * a service has gone down. We should keep it like that for 30
- * seconds, so that it will get broadcast and then change to a
- * clone if one exist.
- */
- if (sap->clone && (ntohs(si->hops) != HOPCNT_INFINITY)) {
- /*
- * There are three possibilities:
- * 1. The new path is cheaper than the old one.
- * Free all the clones.
- *
- * 2. The new path is the same cost as the old ones.
- * If it is on the list of clones remove it
- * from the clone list and free it.
- *
- * 3. The new path is more expensive than the old one.
- * Use the values of the first clone and take it
- * out of the list, to be freed at the end.
- */
- osap = sap->clone;
- if (ntohs(osap->sap.hops) > ntohs(si->hops)) {
- struct sap_entry *nsap;
-
- while (osap) {
- nsap = osap->clone;
- TRACE_SAP_ACTION("DELETE", osap);
- free(osap);
- osap = nsap;
- }
- sap->clone = NULL;
- } else if (ntohs(osap->sap.hops) == ntohs(si->hops)) {
- struct sap_entry *psap;
-
- psap = sap;
- while (osap) {
- if (equal(&osap->source, from)) {
- psap->clone = osap->clone;
- TRACE_SAP_ACTION("DELETE", osap);
- free(osap);
- osap = psap->clone;
- } else {
- psap = osap;
- osap = osap->clone;
- }
- }
- } else {
- from = &osap->source;
- si = &osap->sap;
- sap->clone = osap->clone;
- }
- }
- sap->sap = *si;
- sap->source = *from;
- sap->ifp = if_ifwithnet(from);
- sap->state = RTS_CHANGED;
- if (ntohs(si->hops) == HOPCNT_INFINITY)
- sap->timer = EXPIRE_TIME;
- else
- sap->timer = 0;
-
- if (osap) {
- TRACE_SAP_ACTION("DELETE", osap);
- free(osap);
- }
- TRACE_SAP_ACTION("CHANGE TO", sap);
-}
-
-/*
- * Add a clone to the specified SAP entry. A clone is a different
- * route to the same service. We must know about them when we use
- * the split horizon algorithm.
- *
- * If the malloc fail, the entry will silently be thrown away.
- */
-void
-sap_add_clone(struct sap_entry *sap,
- struct sap_info *clone,
- struct sockaddr *from)
-{
- register struct sap_entry *nsap;
- register struct sap_entry *csap;
-
- if (ntohs(clone->hops) == HOPCNT_INFINITY)
- return;
-
- FIXLEN(from);
- nsap = malloc(sizeof(struct sap_entry));
- if (nsap == NULL)
- return;
-
- if (ftrace)
- fprintf(ftrace, "CLONE ADD %4.4X %s.\n",
- ntohs(clone->ServType),
- clone->ServName);
-
- nsap->sap = *clone;
- nsap->source = *from;
- nsap->clone = NULL;
- nsap->ifp = if_ifwithnet(from);
- nsap->state = RTS_CHANGED;
- nsap->timer = 0;
- nsap->hash = saphash(clone->ServType, clone->ServName);
-
- csap = sap;
- while (csap->clone)
- csap = csap->clone;
- csap->clone = nsap;
- TRACE_SAP_ACTION("ADD CLONE", nsap);
-}
-
-/*
- * Remove a SAP entry from the table and free the memory
- * used by it.
- *
- * If the service have clone, do a sap_change to it and free
- * the clone.
- */
-void
-sap_delete(struct sap_entry *sap)
-{
- if (sap->clone) {
- sap_change(sap, &sap->clone->sap, &sap->clone->source);
- return;
- }
- remque(sap);
- TRACE_SAP_ACTION("DELETE", sap);
- free(sap);
-}
diff --git a/usr.sbin/IPXrouted/startup.c b/usr.sbin/IPXrouted/startup.c
deleted file mode 100644
index 2b9ccfa..0000000
--- a/usr.sbin/IPXrouted/startup.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)startup.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * Routing Table Management Daemon
- */
-#include "defs.h"
-
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-
-#include <net/if.h>
-#include <net/if_dl.h>
-
-#include <errno.h>
-#include <nlist.h>
-#include <search.h>
-#include <stdlib.h>
-
-struct interface *ifnet;
-int lookforinterfaces = 1;
-int performnlist = 1;
-int gateway = 0;
-int externalinterfaces = 0; /* # of remote and local interfaces */
-
-void
-quit(s)
- char *s;
-{
- int sverrno = errno;
-
- (void) fprintf(stderr, "IPXroute: ");
- if (s)
- (void) fprintf(stderr, "%s: ", s);
- (void) fprintf(stderr, "%s\n", strerror(sverrno));
- exit(1);
- /* NOTREACHED */
-}
-
-struct rt_addrinfo info;
-/* XXX Sleazy use of local variables throughout file, warning!!!! */
-#define netmask info.rti_info[RTAX_NETMASK]
-#define ifaaddr info.rti_info[RTAX_IFA]
-#define brdaddr info.rti_info[RTAX_BRD]
-
-void
-rt_xaddrs(cp, cplim, rtinfo)
- register caddr_t cp, cplim;
- register struct rt_addrinfo *rtinfo;
-{
- register struct sockaddr *sa;
- register int i;
-
- bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
- for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
- if ((rtinfo->rti_addrs & (1 << i)) == 0)
- continue;
- rtinfo->rti_info[i] = sa = (struct sockaddr *)cp;
- cp += SA_SIZE(sa);
- }
-}
-
-/*
- * Find the network interfaces which have configured themselves.
- * If the interface is present but not yet up (for example an
- * ARPANET IMP), set the lookforinterfaces flag so we'll
- * come back later and look again.
- */
-void
-ifinit(void)
-{
- struct interface ifs, *ifp;
- size_t needed;
- int mib[6], no_ipxaddr = 0, flags = 0;
- char *buf, *cplim, *cp;
- register struct if_msghdr *ifm;
- register struct ifa_msghdr *ifam;
- struct sockaddr_dl *sdl = 0;
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = AF_IPX;
- mib[4] = NET_RT_IFLIST;
- mib[5] = 0;
- if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
- quit("route-sysctl-estimate");
- if ((buf = malloc(needed)) == NULL)
- quit("malloc");
- if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
- lookforinterfaces = 0;
- cplim = buf + needed;
- for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) {
- ifm = (struct if_msghdr *)cp;
- if (ifm->ifm_type == RTM_IFINFO) {
- bzero(&ifs, sizeof(ifs));
- ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE;
- if ((flags & IFF_UP) == 0 || no_ipxaddr)
- lookforinterfaces = 1;
- sdl = (struct sockaddr_dl *) (ifm + 1);
- sdl->sdl_data[sdl->sdl_nlen] = 0;
- no_ipxaddr = 1;
- continue;
- }
- if (ifm->ifm_type != RTM_NEWADDR)
- quit("ifinit: out of sync");
- if ((flags & IFF_UP) == 0)
- continue;
- ifam = (struct ifa_msghdr *)ifm;
- info.rti_addrs = ifam->ifam_addrs;
- rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info);
- if (ifaaddr == 0) {
- syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data);
- continue;
- }
- ifs.int_addr = *ifaaddr;
- if (ifs.int_addr.sa_family != AF_IPX)
- continue;
- no_ipxaddr = 0;
- if (ifs.int_flags & IFF_POINTOPOINT) {
- if (brdaddr == 0) {
- syslog(LOG_ERR, "%s: (get dstaddr)",
- sdl->sdl_data);
- continue;
- }
- if (brdaddr->sa_family == AF_UNSPEC) {
- lookforinterfaces = 1;
- continue;
- }
- ifs.int_dstaddr = *brdaddr;
- }
- if (ifs.int_flags & IFF_BROADCAST) {
- if (brdaddr == 0) {
- syslog(LOG_ERR, "%s: (get broadaddr)",
- sdl->sdl_data);
- continue;
- }
- ifs.int_dstaddr = *brdaddr;
- }
- if (ifs.int_flags & IFF_LOOPBACK) {
- ifs.int_dstaddr = ifs.int_addr;
- }
- /*
- * already known to us?
- * what makes a POINTOPOINT if unique is its dst addr,
- * NOT its source address
- */
- if ( ((ifs.int_flags & IFF_POINTOPOINT) &&
- if_ifwithdstaddr(&ifs.int_dstaddr)) ||
- ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) &&
- if_ifwithaddr(&ifs.int_addr)))
- continue;
- ifp = (struct interface *)
- malloc(sdl->sdl_nlen + 1 + sizeof(ifs));
- if (ifp == 0) {
- syslog(LOG_ERR, "IPXrouted: out of memory\n");
- lookforinterfaces = 1;
- break;
- }
- *ifp = ifs;
- /*
- * Count the # of directly connected networks
- * and point to point links which aren't looped
- * back to ourself. This is used below to
- * decide if we should be a routing ``supplier''.
- */
- if ((ifs.int_flags & IFF_POINTOPOINT) == 0 ||
- if_ifwithaddr(&ifs.int_dstaddr) == 0)
- externalinterfaces++;
- /*
- * If we have a point-to-point link, we want to act
- * as a supplier even if it's our only interface,
- * as that's the only way our peer on the other end
- * can tell that the link is up.
- */
- if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0)
- supplier = 1;
- ifp->int_name = (char *)(ifp + 1);
- strcpy(ifp->int_name, sdl->sdl_data);
-
- ifp->int_metric = ifam->ifam_metric;
- ifp->int_next = ifnet;
- ifnet = ifp;
- traceinit(ifp);
- addrouteforif(ifp);
- }
- if (externalinterfaces > 1 && supplier < 0)
- supplier = 1;
- free(buf);
-}
-
-void
-addrouteforif(ifp)
- struct interface *ifp;
-{
- struct sockaddr_ipx net;
- struct sockaddr *dst;
- struct rt_entry *rt;
-
- if (ifp->int_flags & IFF_POINTOPOINT) {
- int (*match)();
- register struct interface *ifp2 = ifnet;
-
- dst = &ifp->int_dstaddr;
-
- /* Search for interfaces with the same net */
- ifp->int_sq.n = ifp->int_sq.p = &(ifp->int_sq);
- match = afswitch[dst->sa_family].af_netmatch;
- if (match)
- for (ifp2 = ifnet; ifp2; ifp2 =ifp2->int_next) {
- if ((ifp->int_flags & IFF_POINTOPOINT) == 0)
- continue;
- if ((*match)(&ifp2->int_dstaddr,&ifp->int_dstaddr)) {
- insque(&ifp2->int_sq,&ifp->int_sq);
- break;
- }
- }
- } else {
- bzero(&net, sizeof(net));
- net.sipx_family = AF_IPX;
- net.sipx_len = sizeof (net);
- net.sipx_addr.x_net = satoipx_addr(ifp->int_broadaddr).x_net;
- dst = (struct sockaddr *)&net;
- }
- rt = rtlookup(dst);
- if (rt)
- rtdelete(rt);
- if (tracing)
- fprintf(stderr, "Adding route to interface %s\n", ifp->int_name);
- if (ifp->int_transitions++ > 0)
- syslog(LOG_ERR, "re-installing interface %s", ifp->int_name);
- rtadd(dst, &ifp->int_addr, ifp->int_metric, 0,
- ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE));
-}
-
diff --git a/usr.sbin/IPXrouted/table.h b/usr.sbin/IPXrouted/table.h
deleted file mode 100644
index 3f9693f..0000000
--- a/usr.sbin/IPXrouted/table.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)table.h 5.1 (Berkeley) 6/4/85 (routed/table.h)
- *
- * @(#)table.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-/*
- * Routing table management daemon.
- */
-
-/*
- * Routing table structure; differs a bit from kernel tables.
- *
- * Note: the union below must agree in the first 4 members
- * so the ioctl's will work.
- */
-struct rthash {
- struct rt_entry *rt_forw;
- struct rt_entry *rt_back;
-};
-
-#ifdef RTM_ADD
-#define rtentry ortentry
-#endif
-
-struct rt_entry {
- struct rt_entry *rt_forw;
- struct rt_entry *rt_back;
- union {
- struct rtentry rtu_rt;
- struct rtuentry {
- u_long rtu_hash;
- struct sockaddr rtu_dst;
- struct sockaddr rtu_router;
- short rtu_rtflags; /* used by old rtioctl */
- short rtu_wasted; /* XXX routed does it this way. */
- int rtu_flags;
- int rtu_state;
- int rtu_timer;
- int rtu_metric;
- int rtu_ticks;
- struct interface *rtu_ifp;
- } rtu_entry;
- } rt_rtu;
- struct rt_entry *rt_clone;
-};
-
-#define rt_rt rt_rtu.rtu_entry /* pass to ioctl */
-#define rt_hash rt_rtu.rtu_entry.rtu_hash /* for net or host */
-#define rt_dst rt_rtu.rtu_entry.rtu_dst /* match value */
-#define rt_router rt_rtu.rtu_entry.rtu_router /* who to forward to */
-#define rt_flags rt_rtu.rtu_entry.rtu_flags /* kernel flags */
-#define rt_timer rt_rtu.rtu_entry.rtu_timer /* for invalidation */
-#define rt_state rt_rtu.rtu_entry.rtu_state /* see below */
-#define rt_metric rt_rtu.rtu_entry.rtu_metric /* cost of route */
-#define rt_ticks rt_rtu.rtu_entry.rtu_ticks /* time of route */
-#define rt_ifp rt_rtu.rtu_entry.rtu_ifp /* interface to take */
-
-#define ROUTEHASHSIZ 128 /* must be a power of 2 */
-#define ROUTEHASHMASK (ROUTEHASHSIZ - 1)
-
-/*
- * "State" of routing table entry.
- */
-#define RTS_CHANGED 0x1 /* route has been altered recently */
-#define RTS_PASSIVE IFF_PASSIVE /* don't time out route */
-#define RTS_INTERFACE IFF_INTERFACE /* route is for network interface */
-#define RTS_REMOTE IFF_REMOTE /* route is for ``remote'' entity */
-
-extern struct rthash nethash[ROUTEHASHSIZ];
-struct rt_entry *rtlookup(struct sockaddr *);
-struct rt_entry *rtfind(struct sockaddr *);
-void rtadd(struct sockaddr *, struct sockaddr *, short, short, int);
-void rtadd_clone(struct rt_entry *, struct sockaddr *, struct sockaddr *,
- short, short, int);
-void rtchange(struct rt_entry *, struct sockaddr *, short, short);
-void rtdelete(struct rt_entry *);
-int rtioctl(int, struct rtuentry *);
-void rtinit(void);
-
diff --git a/usr.sbin/IPXrouted/tables.c b/usr.sbin/IPXrouted/tables.c
deleted file mode 100644
index aebc792..0000000
--- a/usr.sbin/IPXrouted/tables.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)tables.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * Routing Table Management Daemon
- */
-#include "defs.h"
-#include <sys/ioctl.h>
-#include <errno.h>
-#include <search.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifndef DEBUG
-#define DEBUG 0
-#endif
-
-#define FIXLEN(s) { if ((s)->sa_len == 0) (s)->sa_len = sizeof (*(s));}
-
-int install = !DEBUG; /* if 1 call kernel */
-int delete = 1;
-
-struct rthash nethash[ROUTEHASHSIZ];
-
-/*
- * Lookup dst in the tables for an exact match.
- */
-struct rt_entry *
-rtlookup(struct sockaddr *dst)
-{
- register struct rt_entry *rt;
- register struct rthash *rh;
- register u_int hash;
- struct afhash h;
-
- if (dst->sa_family >= AF_MAX)
- return (0);
- (*afswitch[dst->sa_family].af_hash)(dst, &h);
- hash = h.afh_nethash;
- rh = &nethash[hash & ROUTEHASHMASK];
- for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
- if (rt->rt_hash != hash)
- continue;
- if (equal(&rt->rt_dst, dst))
- return (rt);
- }
- return (0);
-}
-
-/*
- * Find a route to dst as the kernel would.
- */
-struct rt_entry *
-rtfind(struct sockaddr *dst)
-{
- register struct rt_entry *rt;
- register struct rthash *rh;
- register u_int hash;
- struct afhash h;
- int af = dst->sa_family;
- int (*match)() = 0;
-
- if (af >= AF_MAX)
- return (0);
- (*afswitch[af].af_hash)(dst, &h);
-
- hash = h.afh_nethash;
- rh = &nethash[hash & ROUTEHASHMASK];
- match = afswitch[af].af_netmatch;
- for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
- if (rt->rt_hash != hash)
- continue;
- if (rt->rt_dst.sa_family == af &&
- (*match)(&rt->rt_dst, dst))
- return (rt);
- }
- return (0);
-}
-
-void
-rtadd(struct sockaddr *dst, struct sockaddr *gate, short metric,
- short ticks, int state)
-{
- struct afhash h;
- register struct rt_entry *rt;
- struct rthash *rh;
- int af = dst->sa_family, flags;
- u_int hash;
-
- FIXLEN(dst);
- FIXLEN(gate);
- if (af >= AF_MAX)
- return;
- (*afswitch[af].af_hash)(dst, &h);
- flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
- hash = h.afh_nethash;
- rh = &nethash[hash & ROUTEHASHMASK];
- rt = (struct rt_entry *)malloc(sizeof (*rt));
- if (rt == 0)
- return;
- rt->rt_hash = hash;
- rt->rt_dst = *dst;
- rt->rt_router = *gate;
- rt->rt_metric = metric;
- rt->rt_ticks = ticks;
- rt->rt_timer = 0;
- rt->rt_flags = RTF_UP | flags;
- rt->rt_state = state | RTS_CHANGED;
- rt->rt_ifp = if_ifwithnet(&rt->rt_router);
- rt->rt_clone = NULL;
- if (metric)
- rt->rt_flags |= RTF_GATEWAY;
- insque(rt, rh);
- TRACE_ACTION("ADD", rt);
- /*
- * If the ioctl fails because the gateway is unreachable
- * from this host, discard the entry. This should only
- * occur because of an incorrect entry in /etc/gateways.
- */
- if (install && rtioctl(ADD, &rt->rt_rt) < 0) {
- if (errno != EEXIST)
- perror("SIOCADDRT");
- if (errno == ENETUNREACH) {
- TRACE_ACTION("DELETE", rt);
- remque(rt);
- free((char *)rt);
- }
- }
-}
-
-void
-rtadd_clone(struct rt_entry *ort, struct sockaddr *dst,
- struct sockaddr *gate, short metric, short ticks, int state)
-{
- struct afhash h;
- register struct rt_entry *rt;
- int af = dst->sa_family, flags;
- u_int hash;
-
- FIXLEN(dst);
- FIXLEN(gate);
- if (af >= AF_MAX)
- return;
- (*afswitch[af].af_hash)(dst, &h);
- flags = (*afswitch[af].af_ishost)(dst) ? RTF_HOST : 0;
- hash = h.afh_nethash;
- rt = (struct rt_entry *)malloc(sizeof (*rt));
- if (rt == 0)
- return;
- rt->rt_hash = hash;
- rt->rt_dst = *dst;
- rt->rt_router = *gate;
- rt->rt_metric = metric;
- rt->rt_ticks = ticks;
- rt->rt_timer = 0;
- rt->rt_flags = RTF_UP | flags;
- rt->rt_state = state | RTS_CHANGED;
- rt->rt_ifp = if_ifwithnet(&rt->rt_router);
- rt->rt_clone = NULL;
- rt->rt_forw = NULL;
- rt->rt_back = NULL;
- if (metric)
- rt->rt_flags |= RTF_GATEWAY;
-
- while(ort->rt_clone != NULL)
- ort = ort->rt_clone;
- ort->rt_clone = rt;
- TRACE_ACTION("ADD_CLONE", rt);
-}
-
-void
-rtchange(struct rt_entry *rt, struct sockaddr *gate, short metric,
- short ticks)
-{
- int doioctl = 0, metricchanged = 0;
-
- FIXLEN(gate);
- /*
- * Handling of clones.
- * When the route changed and it had clones, handle it special.
- * 1. If the new route is cheaper than the clone(s), free the clones.
- * 2. If the new route is the same cost, it may be one of the clones,
- * search for it and free it.
- * 3. If the new route is more expensive than the clone(s), use the
- * values of the clone(s).
- */
- if (rt->rt_clone) {
- if ((ticks < rt->rt_clone->rt_ticks) ||
- ((ticks == rt->rt_clone->rt_ticks) &&
- (metric < rt->rt_clone->rt_metric))) {
- /*
- * Free all clones.
- */
- struct rt_entry *trt, *nrt;
-
- trt = rt->rt_clone;
- rt->rt_clone = NULL;
- while(trt) {
- nrt = trt->rt_clone;
- free((char *)trt);
- trt = nrt;
- }
- } else if ((ticks == rt->rt_clone->rt_ticks) &&
- (metric == rt->rt_clone->rt_metric)) {
- struct rt_entry *prt, *trt;
-
- prt = rt;
- trt = rt->rt_clone;
-
- while(trt) {
- if (equal(&trt->rt_router, gate)) {
- prt->rt_clone = trt->rt_clone;
- free(trt);
- trt = prt->rt_clone;
- } else {
- prt = trt;
- trt = trt->rt_clone;
- }
- }
- } else {
- /*
- * Use the values of the first clone.
- * Delete the corresponding clone.
- */
- struct rt_entry *trt;
-
- trt = rt->rt_clone;
- rt->rt_clone = rt->rt_clone->rt_clone;
- metric = trt->rt_metric;
- ticks = trt->rt_ticks;
- *gate = trt->rt_router;
- free((char *)trt);
- }
- }
-
- if (!equal(&rt->rt_router, gate))
- doioctl++;
- if ((metric != rt->rt_metric) || (ticks != rt->rt_ticks))
- metricchanged++;
- if (doioctl || metricchanged) {
- TRACE_ACTION("CHANGE FROM", rt);
- if (doioctl) {
- rt->rt_router = *gate;
- }
- rt->rt_metric = metric;
- rt->rt_ticks = ticks;
- if ((rt->rt_state & RTS_INTERFACE) && metric) {
- rt->rt_state &= ~RTS_INTERFACE;
- if(rt->rt_ifp)
- syslog(LOG_ERR,
- "changing route from interface %s (timed out)",
- rt->rt_ifp->int_name);
- else
- syslog(LOG_ERR,
- "changing route from interface ??? (timed out)");
- }
- if (metric)
- rt->rt_flags |= RTF_GATEWAY;
- else
- rt->rt_flags &= ~RTF_GATEWAY;
- rt->rt_ifp = if_ifwithnet(&rt->rt_router);
- rt->rt_state |= RTS_CHANGED;
- TRACE_ACTION("CHANGE TO", rt);
- }
- if (doioctl && install) {
-#ifndef RTM_ADD
- if (rtioctl(ADD, &rt->rt_rt) < 0)
- syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
- ipx_ntoa(&((struct sockaddr_ipx *)&rt->rt_dst)->sipx_addr),
- ipx_ntoa(&((struct sockaddr_ipx *)&rt->rt_router)->sipx_addr));
- if (delete && rtioctl(DELETE, &oldroute) < 0)
- perror("rtioctl DELETE");
-#else
- if (delete == 0) {
- if (rtioctl(ADD, &rt->rt_rt) >= 0)
- return;
- } else {
- if (rtioctl(CHANGE, &rt->rt_rt) >= 0)
- return;
- }
- syslog(LOG_ERR, "rtioctl ADD dst %s, gw %s: %m",
- ipxdp_ntoa(&((struct sockaddr_ipx *)&rt->rt_dst)->sipx_addr),
- ipxdp_ntoa(&((struct sockaddr_ipx *)&rt->rt_router)->sipx_addr));
-#endif
- }
-}
-
-void
-rtdelete(struct rt_entry *rt)
-{
-
- struct sockaddr *sa = &(rt->rt_router);
- FIXLEN(sa);
- sa = &(rt->rt_dst);
- FIXLEN(sa);
- if (rt->rt_clone) {
- /*
- * If there is a clone we just do a rt_change to it.
- */
- struct rt_entry *trt = rt->rt_clone;
- rtchange(rt, &trt->rt_router, trt->rt_metric, trt->rt_ticks);
- return;
- }
- if (rt->rt_state & RTS_INTERFACE) {
- if (rt->rt_ifp)
- syslog(LOG_ERR,
- "deleting route to interface %s (timed out)",
- rt->rt_ifp->int_name);
- else
- syslog(LOG_ERR,
- "deleting route to interface ??? (timed out)");
- }
- TRACE_ACTION("DELETE", rt);
- if (install && rtioctl(DELETE, &rt->rt_rt) < 0)
- perror("rtioctl DELETE");
- remque(rt);
- free((char *)rt);
-}
-
-void
-rtinit(void)
-{
- register struct rthash *rh;
-
- for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++)
- rh->rt_forw = rh->rt_back = (struct rt_entry *)rh;
-}
-int seqno;
-
-int
-rtioctl(int action, struct rtuentry *ort)
-{
-#ifndef RTM_ADD
- if (install == 0)
- return (errno = 0);
-
- ort->rtu_rtflags = ort->rtu_flags;
-
- switch (action) {
-
- case ADD:
- return (ioctl(s, SIOCADDRT, (char *)ort));
-
- case DELETE:
- return (ioctl(s, SIOCDELRT, (char *)ort));
-
- default:
- return (-1);
- }
-#else /* RTM_ADD */
- struct {
- struct rt_msghdr w_rtm;
- struct sockaddr w_dst;
- struct sockaddr w_gate;
- struct sockaddr_ipx w_netmask;
- } w;
-#define rtm w.w_rtm
-
- bzero((char *)&w, sizeof(w));
- rtm.rtm_msglen = sizeof(w);
- rtm.rtm_version = RTM_VERSION;
- rtm.rtm_type = (action == ADD ? RTM_ADD :
- (action == DELETE ? RTM_DELETE : RTM_CHANGE));
- rtm.rtm_flags = ort->rtu_flags;
- rtm.rtm_seq = ++seqno;
- rtm.rtm_addrs = RTA_DST|RTA_GATEWAY;
- bcopy((char *)&ort->rtu_dst, (char *)&w.w_dst, sizeof(w.w_dst));
- bcopy((char *)&ort->rtu_router, (char *)&w.w_gate, sizeof(w.w_gate));
- w.w_gate.sa_family = w.w_dst.sa_family = AF_IPX;
- w.w_gate.sa_len = w.w_dst.sa_len = sizeof(w.w_dst);
- if (rtm.rtm_flags & RTF_HOST) {
- rtm.rtm_msglen -= sizeof(w.w_netmask);
- } else {
- rtm.rtm_addrs |= RTA_NETMASK;
- w.w_netmask = ipx_netmask;
- rtm.rtm_msglen -= sizeof(w.w_netmask) - ipx_netmask.sipx_len;
- }
- errno = 0;
- return write(r, (char *)&w, rtm.rtm_msglen);
-#endif /* RTM_ADD */
-}
diff --git a/usr.sbin/IPXrouted/timer.c b/usr.sbin/IPXrouted/timer.c
deleted file mode 100644
index 2159730..0000000
--- a/usr.sbin/IPXrouted/timer.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef lint
-static const char sccsid[] = "@(#)timer.c 8.1 (Berkeley) 6/5/93";
-#endif /* not lint */
-
-/*
- * Routing Table Management Daemon
- */
-#include "defs.h"
-#include <unistd.h>
-#include <stdlib.h>
-
-int timeval = -TIMER_RATE;
-
-/*
- * Timer routine. Performs routing information supply
- * duties and manages timers on routing and SAP table entries.
- */
-void
-timer()
-{
- register struct rthash *rh;
- register struct rt_entry *rt;
- register struct sap_hash *sh;
- register struct sap_entry *sap;
- struct sap_hash *sap_base = sap_head;
- int timetobroadcast, ripbroadcast, sapbroadcast;
-
- timeval += TIMER_RATE;
- if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0)
- ifinit();
- timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0;
- ripbroadcast = supplier && timetobroadcast &&
- (timeval % RIP_INTERVAL) == 0;
- sapbroadcast = timetobroadcast && dosap && !ripbroadcast;
-
- for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) {
- rt = rh->rt_forw;
- for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) {
- if (rt->rt_clone) {
- struct rt_entry *trt, *prt;
- /*
- * If a clone expire free it and mark the
- * main route RTS_CHANGED.
- */
- prt = rt;
- trt = rt->rt_clone;
- while (trt) {
- trt->rt_timer += TIMER_RATE;
- if (trt->rt_timer >= EXPIRE_TIME) {
- prt->rt_clone = trt->rt_clone;
- free((char *)trt);
- trt = prt->rt_clone;
- rt->rt_state |= RTS_CHANGED;
- } else {
- prt = trt;
- trt = prt->rt_clone;
- }
- }
- }
- /*
- * We don't advance time on a routing entry for
- * a passive gateway or that for our only interface.
- * The latter is excused because we don't act as
- * a routing information supplier and hence would
- * time it out. This is fair as if it's down
- * we're cut off from the world anyway and it's
- * not likely we'll grow any new hardware in
- * the mean time.
- */
- if (!(rt->rt_state & RTS_PASSIVE) &&
- !(rt->rt_state & RTS_INTERFACE))
- rt->rt_timer += TIMER_RATE;
- if (rt->rt_timer >= EXPIRE_TIME) {
- rt->rt_metric = HOPCNT_INFINITY;
- rt->rt_state |= RTS_CHANGED;
- }
- if (rt->rt_timer >= GARBAGE_TIME) {
- rt = rt->rt_back;
- /* Perhaps we should send a REQUEST for this route? */
- rtdelete(rt->rt_forw);
- continue;
- }
- if (rt->rt_state & RTS_CHANGED) {
- rt->rt_state &= ~RTS_CHANGED;
- /* don't send extraneous packets */
- if (!supplier || ripbroadcast)
- continue;
- if ((rt->rt_metric + 1) == HOPCNT_INFINITY)
- continue;
- msg->rip_cmd = htons(RIPCMD_RESPONSE);
- msg->rip_nets[0].rip_dst =
- (satoipx_addr(rt->rt_dst)).x_net;
- msg->rip_nets[0].rip_metric =
- htons(min(rt->rt_metric+1, HOPCNT_INFINITY));
- msg->rip_nets[0].rip_ticks =
- htons(rt->rt_ticks + 1);
- toall(sndmsg, rt, 0);
- }
- }
- }
- if (ripbroadcast)
- toall(supply, NULL, 0);
-
- /*
- * Now do the SAP stuff.
- */
- for (sh = sap_base; sh < &sap_base[SAPHASHSIZ]; sh++) {
- sap = sh->forw;
- for (; sap != (struct sap_entry *)sh; sap = sap->forw) {
- if (sap->clone) {
- struct sap_entry *tsap, *psap;
- /*
- * If a clone expire free it and mark the
- * main sap entry RTS_CHANGED.
- */
- psap = sap;
- tsap = sap->clone;
- while (tsap) {
- tsap->timer += TIMER_RATE;
- if (tsap->timer >= EXPIRE_TIME) {
- psap->clone = tsap->clone;
- free((char *)tsap);
- tsap = psap->clone;
- sap->state |= RTS_CHANGED;
- } else {
- psap = tsap;
- tsap = psap->clone;
- }
- }
- }
- sap->timer += TIMER_RATE;
- if (sap->timer >= EXPIRE_TIME) {
- sap->sap.hops = htons(HOPCNT_INFINITY);
- sap->state |= RTS_CHANGED;
- }
- if (sap->timer >= GARBAGE_TIME) {
- sap = sap->back;
- /* Perhaps we should send a REQUEST for this route? */
- sap_delete(sap->forw);
- continue;
- }
- /*
- * XXX sap_sndmsg on RTS_CHANGED
- */
- if (sap->state & RTS_CHANGED) {
- sap->state &= ~RTS_CHANGED;
-#ifdef notyet
- /* don't send extraneous packets */
- if (!supplier || sapbroadcast)
- continue;
- if ((ntohs(sap->sap.hops) + 1) == HOPCNT_INFINITY)
- continue;
- sap_msg->sap_cmd = htons(SAP_RESP);
- sap_msg->sap[0] = sap->sap;
- sap_msg->sap[0].hops =
- htons(min(sap->sap.hops+1, HOPCNT_INFINITY));
- toall(sapsndmsg, rt, 0);
-#endif
- }
- }
- }
- if (sapbroadcast)
- sap_supply_toall(0);
- if (ftrace && sapbroadcast)
- dumpsaptable(ftrace, sap_head);
-}
-
-/*
- * On hangup, let everyone know we're going away.
- */
-void
-hup()
-{
- register struct rthash *rh;
- register struct rt_entry *rt;
- register struct sap_hash *sh;
- register struct sap_entry *sap;
-
- if (supplier) {
- for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) {
- rt = rh->rt_forw;
- for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw)
- rt->rt_metric = HOPCNT_INFINITY;
- }
- toall(supply, NULL, 0);
-
- /*
- * Now for SAP.
- */
- for (sh = sap_head; sh < &sap_head[SAPHASHSIZ]; sh++) {
- sap = sh->forw;
- for (; sap != (struct sap_entry *)sh; sap = sap->forw)
- sap->sap.hops = htons(HOPCNT_INFINITY);
- }
- if (dosap)
- sap_supply_toall(0);
- }
- exit(1);
-}
diff --git a/usr.sbin/IPXrouted/trace.c b/usr.sbin/IPXrouted/trace.c
deleted file mode 100644
index d9e74b8..0000000
--- a/usr.sbin/IPXrouted/trace.c
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
- * Copyright (c) 1985, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-/*
- * Routing Table Management Daemon
- */
-#define RIPCMDS
-#define SAPCMDS
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <time.h>
-#include "defs.h"
-
-#define NRECORDS 50 /* size of circular trace buffer */
-#ifdef DEBUG
-FILE *ftrace = stdout;
-int tracing = 1;
-#else /* DEBUG */
-FILE *ftrace = NULL;
-int tracing = 0;
-#endif
-
-void dumpif(FILE *fd, struct interface *ifp);
-void dumptrace(FILE *fd, char *dir, struct ifdebug *ifd);
-static int iftraceinit(struct interface *ifp, struct ifdebug *ifd);
-
-void
-traceinit(ifp)
- register struct interface *ifp;
-{
- if (iftraceinit(ifp, &ifp->int_input) &&
- iftraceinit(ifp, &ifp->int_output))
- return;
- tracing = 0;
- syslog(LOG_ERR, "traceinit: can't init %s\n", ifp->int_name);
-}
-
-static int
-iftraceinit(ifp, ifd)
- struct interface *ifp;
- register struct ifdebug *ifd;
-{
- register struct iftrace *t;
-
- ifd->ifd_records =
- (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace));
- if (ifd->ifd_records == 0)
- return (0);
- ifd->ifd_front = ifd->ifd_records;
- ifd->ifd_count = 0;
- for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) {
- t->ift_size = 0;
- t->ift_packet = 0;
- }
- ifd->ifd_if = ifp;
- return (1);
-}
-
-void
-traceon(file)
- char *file;
-{
-
- if (ftrace != NULL)
- return;
- ftrace = fopen(file, "a");
- if (ftrace == NULL)
- return;
- dup2(fileno(ftrace), 1);
- dup2(fileno(ftrace), 2);
- tracing = 1;
-}
-
-void
-traceoff(void)
-{
- if (!tracing)
- return;
- if (ftrace != NULL)
- fclose(ftrace);
- ftrace = NULL;
- tracing = 0;
-}
-
-void
-trace(ifd, who, p, len, m)
- register struct ifdebug *ifd;
- struct sockaddr *who;
- char *p;
- int len, m;
-{
- register struct iftrace *t;
-
- if (ifd->ifd_records == 0)
- return;
- t = ifd->ifd_front++;
- if (ifd->ifd_front >= ifd->ifd_records + NRECORDS)
- ifd->ifd_front = ifd->ifd_records;
- if (ifd->ifd_count < NRECORDS)
- ifd->ifd_count++;
- if (t->ift_size > 0 && t->ift_packet)
- free(t->ift_packet);
- t->ift_packet = 0;
- t->ift_stamp = time(0);
- t->ift_who = *who;
- if (len > 0) {
- t->ift_packet = malloc(len);
- if (t->ift_packet)
- bcopy(p, t->ift_packet, len);
- else
- len = 0;
- }
- t->ift_size = len;
- t->ift_metric = m;
-}
-
-void
-traceaction(fd, action, rt)
- FILE *fd;
- char *action;
- struct rt_entry *rt;
-{
- struct sockaddr_ipx *dst, *gate;
- static struct bits {
- int t_bits;
- char *t_name;
- } flagbits[] = {
- { RTF_UP, "UP" },
- { RTF_GATEWAY, "GATEWAY" },
- { RTF_HOST, "HOST" },
- { 0 }
- }, statebits[] = {
- { RTS_PASSIVE, "PASSIVE" },
- { RTS_REMOTE, "REMOTE" },
- { RTS_INTERFACE,"INTERFACE" },
- { RTS_CHANGED, "CHANGED" },
- { 0 }
- };
- register struct bits *p;
- register int first;
- char *cp;
-
- if (fd == NULL)
- return;
- fprintf(fd, "%s ", action);
- dst = (struct sockaddr_ipx *)&rt->rt_dst;
- gate = (struct sockaddr_ipx *)&rt->rt_router;
- fprintf(fd, "dst %s, ", ipxdp_ntoa(&dst->sipx_addr));
- fprintf(fd, "router %s, metric %d, ticks %d, flags",
- ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
- cp = " %s";
- for (first = 1, p = flagbits; p->t_bits > 0; p++) {
- if ((rt->rt_flags & p->t_bits) == 0)
- continue;
- fprintf(fd, cp, p->t_name);
- if (first) {
- cp = "|%s";
- first = 0;
- }
- }
- fprintf(fd, " state");
- cp = " %s";
- for (first = 1, p = statebits; p->t_bits > 0; p++) {
- if ((rt->rt_state & p->t_bits) == 0)
- continue;
- fprintf(fd, cp, p->t_name);
- if (first) {
- cp = "|%s";
- first = 0;
- }
- }
- putc('\n', fd);
- if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp)
- dumpif(fd, rt->rt_ifp);
- fflush(fd);
-}
-
-void
-traceactionlog(action, rt)
- char *action;
- struct rt_entry *rt;
-{
- struct sockaddr_ipx *dst, *gate;
- static struct bits {
- int t_bits;
- char *t_name;
- } flagbits[] = {
- { RTF_UP, "UP" },
- { RTF_GATEWAY, "GATEWAY" },
- { RTF_HOST, "HOST" },
- { 0 }
- }, statebits[] = {
- { RTS_PASSIVE, "PASSIVE" },
- { RTS_REMOTE, "REMOTE" },
- { RTS_INTERFACE,"INTERFACE" },
- { RTS_CHANGED, "CHANGED" },
- { 0 }
- };
- register struct bits *p;
- register int first;
- char *cp;
- char *lstr, *olstr;
-
- dst = (struct sockaddr_ipx *)&rt->rt_dst;
- gate = (struct sockaddr_ipx *)&rt->rt_router;
- asprintf(&lstr, "%s dst %s,", action, ipxdp_ntoa(&dst->sipx_addr));
- olstr = lstr;
- asprintf(&lstr, "%s router %s, metric %d, ticks %d, flags",
- olstr, ipxdp_ntoa(&gate->sipx_addr), rt->rt_metric, rt->rt_ticks);
- free(olstr);
- olstr = lstr;
- cp = "%s %s";
- for (first = 1, p = flagbits; p->t_bits > 0; p++) {
- if ((rt->rt_flags & p->t_bits) == 0)
- continue;
- asprintf(&lstr, cp, olstr, p->t_name);
- free(olstr);
- olstr = lstr;
- if (first) {
- cp = "%s|%s";
- first = 0;
- }
- }
- asprintf(&lstr, "%s state", olstr);
- free(olstr);
- olstr = lstr;
- cp = "%s %s";
- for (first = 1, p = statebits; p->t_bits > 0; p++) {
- if ((rt->rt_state & p->t_bits) == 0)
- continue;
- asprintf(&lstr, cp, olstr, p->t_name);
- free(olstr);
- olstr = lstr;
- if (first) {
- cp = "%s|%s";
- first = 0;
- }
- }
- syslog(LOG_DEBUG, "%s", lstr);
- free(lstr);
-}
-
-void
-tracesapactionlog(action, sap)
- char *action;
- struct sap_entry *sap;
-{
- syslog(LOG_DEBUG, "%-12.12s service %04X %-20.20s "
- "addr %s.%04X %c metric %d\n",
- action,
- ntohs(sap->sap.ServType),
- sap->sap.ServName,
- ipxdp_ntoa(&sap->sap.ipx),
- ntohs(sap->sap.ipx.x_port),
- (sap->clone ? 'C' : ' '),
- ntohs(sap->sap.hops));
-}
-
-void
-dumpif(fd, ifp)
- register struct interface *ifp;
- FILE *fd;
-{
- if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) {
- fprintf(fd, "*** Packet history for interface %s ***\n",
- ifp->int_name);
- dumptrace(fd, "to", &ifp->int_output);
- dumptrace(fd, "from", &ifp->int_input);
- fprintf(fd, "*** end packet history ***\n");
- }
-}
-
-void
-dumptrace(fd, dir, ifd)
- FILE *fd;
- char *dir;
- register struct ifdebug *ifd;
-{
- register struct iftrace *t;
- char *cp = !strcmp(dir, "to") ? "Output" : "Input";
-
- if (ifd->ifd_front == ifd->ifd_records &&
- ifd->ifd_front->ift_size == 0) {
- fprintf(fd, "%s: no packets.\n", cp);
- return;
- }
- fprintf(fd, "%s trace:\n", cp);
- t = ifd->ifd_front - ifd->ifd_count;
- if (t < ifd->ifd_records)
- t += NRECORDS;
- for ( ; ifd->ifd_count; ifd->ifd_count--, t++) {
- if (t >= ifd->ifd_records + NRECORDS)
- t = ifd->ifd_records;
- if (t->ift_size == 0)
- continue;
- fprintf(fd, "%.24s: metric=%d\n", ctime(&t->ift_stamp),
- t->ift_metric);
- dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size);
- }
-}
-
-void
-dumppacket(fd, dir, source, cp, size)
- FILE *fd;
- char *dir;
- struct sockaddr *source;
- char *cp;
- register int size;
-{
- register struct rip *msg = (struct rip *)cp;
- register struct netinfo *n;
- struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
-
- if (msg->rip_cmd && ntohs(msg->rip_cmd) < RIPCMD_MAX)
- fprintf(fd, "%s %s %s#%x", ripcmds[ntohs(msg->rip_cmd)],
- dir, ipxdp_ntoa(&who->sipx_addr),
- ntohs(who->sipx_addr.x_port));
- else {
- fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->rip_cmd),
- dir, ipxdp_ntoa(&who->sipx_addr),
- ntohs(who->sipx_addr.x_port));
- fprintf(fd, "size=%d cp=%p packet=%p\n", size,
- cp, packet);
- return;
- }
- switch (ntohs(msg->rip_cmd)) {
-
- case RIPCMD_REQUEST:
- case RIPCMD_RESPONSE:
- fprintf(fd, ":\n");
- size -= sizeof (u_short);
- n = msg->rip_nets;
- for (; size > 0; n++, size -= sizeof (struct netinfo)) {
- if (size < sizeof (struct netinfo))
- break;
- fprintf(fd, "\tnet %s metric %d ticks %d\n",
- ipxdp_nettoa(n->rip_dst),
- ntohs(n->rip_metric),
- ntohs(n->rip_ticks));
- }
- break;
-
- }
-}
-
-void
-dumpsappacket(fd, dir, source, cp, size)
- FILE *fd;
- char *dir;
- struct sockaddr *source;
- char *cp;
- register int size;
-{
- register struct sap_packet *msg = (struct sap_packet *)cp;
- register struct sap_info *n;
- struct sockaddr_ipx *who = (struct sockaddr_ipx *)source;
-
- if (msg->sap_cmd && ntohs(msg->sap_cmd) < SAPCMD_MAX)
- fprintf(fd, "%s %s %s#%x", sapcmds[ntohs(msg->sap_cmd)],
- dir, ipxdp_ntoa(&who->sipx_addr),
- ntohs(who->sipx_addr.x_port));
- else {
- fprintf(fd, "Bad cmd 0x%x %s %s#%x\n", ntohs(msg->sap_cmd),
- dir, ipxdp_ntoa(&who->sipx_addr),
- ntohs(who->sipx_addr.x_port));
- fprintf(fd, "size=%d cp=%p packet=%p\n", size,
- cp, packet);
- return;
- }
- switch (ntohs(msg->sap_cmd)) {
-
- case SAP_REQ:
- case SAP_RESP:
- case SAP_REQ_NEAR:
- case SAP_RESP_NEAR:
- fprintf(fd, ":\n");
- size -= sizeof (u_short);
- n = msg->sap;
- for (; size > 0; n++, size -= sizeof (struct sap_info)) {
- if (size < sizeof (struct sap_info))
- break;
- fprintf(fd, " service %04X %-20.20s "
- "addr %s.%04X metric %d\n",
- ntohs(n->ServType),
- n->ServName,
- ipxdp_ntoa(&n->ipx),
- ntohs(n->ipx.x_port),
- ntohs(n->hops));
- }
- break;
-
- }
-}
-
-void
-dumpsaptable(fd, sh)
- FILE *fd;
- struct sap_hash *sh;
-{
- register struct sap_entry *sap;
- struct sap_hash *hash;
- int x = 0;
-
- fprintf(fd, "------- SAP table dump. -------\n");
- for (hash = sh; hash < &sh[SAPHASHSIZ]; hash++, x++) {
- fprintf(fd, "HASH %d\n", x);
- sap = hash->forw;
- for (; sap != (struct sap_entry *)hash; sap = sap->forw) {
- fprintf(fd, " service %04X %-20.20s "
- "addr %s.%04X %c metric %d\n",
- ntohs(sap->sap.ServType),
- sap->sap.ServName,
- ipxdp_ntoa(&sap->sap.ipx),
- ntohs(sap->sap.ipx.x_port),
- (sap->clone ? 'C' : ' '),
- ntohs(sap->sap.hops));
- }
- }
- fprintf(fd, "\n");
-}
-
-void
-dumpriptable(fd)
- FILE *fd;
-{
- register struct rt_entry *rip;
- struct rthash *hash;
- int x;
- struct rthash *rh = nethash;
-
- fprintf(fd, "------- RIP table dump. -------\n");
- x = 0;
- fprintf(fd, "Network table.\n");
-
- for (hash = rh; hash < &rh[ROUTEHASHSIZ]; hash++, x++) {
- fprintf(fd, "HASH %d\n", x);
- rip = hash->rt_forw;
- for (; rip != (struct rt_entry *)hash; rip = rip->rt_forw) {
- fprintf(fd, " dest %s\t",
- ipxdp_ntoa(&satoipx_addr(rip->rt_dst)));
- fprintf(fd, "%s metric %d, ticks %d\n",
- ipxdp_ntoa(&satoipx_addr(rip->rt_router)),
- rip->rt_metric,
- rip->rt_ticks);
- }
- }
- fprintf(fd, "\n");
-}
-
-union ipx_net_u net;
-
-char *
-ipxdp_nettoa(val)
-union ipx_net val;
-{
- static char buf[100];
- net.net_e = val;
- (void)sprintf(buf, "%u", ntohl(net.long_e));
- return (buf);
-}
-
-
-char *
-ipxdp_ntoa(addr)
-struct ipx_addr *addr;
-{
- static char buf[100];
-
- (void)sprintf(buf, "%s#%x:%x:%x:%x:%x:%x",
- ipxdp_nettoa(addr->x_net),
- addr->x_host.c_host[0], addr->x_host.c_host[1],
- addr->x_host.c_host[2], addr->x_host.c_host[3],
- addr->x_host.c_host[4], addr->x_host.c_host[5]);
-
- return(buf);
-}
diff --git a/usr.sbin/IPXrouted/trace.h b/usr.sbin/IPXrouted/trace.h
deleted file mode 100644
index c83a9d1..0000000
--- a/usr.sbin/IPXrouted/trace.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 1983, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Copyright (c) 1995 John Hay. All rights reserved.
- *
- * This file includes significant work done at Cornell University by
- * Bill Nesheim. That work included by permission.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)trace.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-/*
- * IPX Routing Information Protocol.
- */
-
-/*
- * Trace record format.
- */
-struct iftrace {
- time_t ift_stamp; /* time stamp */
- struct sockaddr ift_who; /* from/to */
- char *ift_packet; /* pointer to packet */
- short ift_size; /* size of packet */
- short ift_metric; /* metric */
-};
-
-/*
- * Per interface packet tracing buffers. An incoming and
- * outgoing circular buffer of packets is maintained, per
- * interface, for debugging. Buffers are dumped whenever
- * an interface is marked down.
- */
-struct ifdebug {
- struct iftrace *ifd_records; /* array of trace records */
- struct iftrace *ifd_front; /* next empty trace record */
- int ifd_count; /* number of unprinted records */
- struct interface *ifd_if; /* for locating stuff */
-};
-
-/*
- * Packet tracing stuff.
- */
-int tracepackets; /* watch packets as they go by */
-int tracing; /* on/off */
-FILE *ftrace; /* output trace file */
-
-#define TRACE_ACTION(action, route) { \
- if (tracing) \
- traceaction(ftrace, "action", route); \
- traceactionlog(action, route); \
- }
-#define TRACE_SAP_ACTION(action, service) { \
- tracesapactionlog(action, service); \
- }
-#define TRACE_INPUT(ifp, src, size) { \
- if (tracing) { \
- ifp = if_iflookup(src); \
- if (ifp) \
- trace(&ifp->int_input, src, \
- &packet[sizeof(struct ipx)], size, \
- ntohl(ifp->int_metric)); \
- } \
- if (tracepackets && ftrace) \
- dumppacket(ftrace, "from", src, \
- &packet[sizeof(struct ipx)], size); \
- }
-#define TRACE_OUTPUT(ifp, dst, size) { \
- if (tracing) { \
- ifp = if_iflookup(dst); \
- if (ifp) \
- trace(&ifp->int_output, dst, \
- &packet[sizeof(struct ipx)], \
- size, ifp->int_metric); \
- } \
- if (tracepackets && ftrace) \
- dumppacket(ftrace, "to", dst, \
- &packet[sizeof(struct ipx)], size); \
- }
-
-#define TRACE_SAP_OUTPUT(ifp, dst, size) { \
- if (tracing) { \
- ifp = if_iflookup(dst); \
- if (ifp) \
- trace(&ifp->int_output, dst, \
- &packet[sizeof(struct ipx)], \
- size, ifp->int_metric); \
- } \
- if (tracepackets && ftrace) \
- dumpsappacket(ftrace, "to", dst, \
- &packet[sizeof(struct ipx)], size); \
- }
-
-void traceinit(struct interface *);
-void traceon(char *file);
-void traceoff(void);
-void traceaction(FILE *, char *, struct rt_entry *);
-void traceactionlog(char *, struct rt_entry *);
-void tracesapactionlog(char *action, struct sap_entry *sap);
-void trace(struct ifdebug *, struct sockaddr *, char *, int, int);
-void dumppacket(FILE *, char *, struct sockaddr *, char *, int);
-void dumpsappacket(FILE *, char *, struct sockaddr *, char *, int);
-void dumpsaptable(FILE *fd, struct sap_hash *sh);
-void dumpriptable(FILE *fd);
-
-char *ipxdp_nettoa(union ipx_net);
-char *ipxdp_ntoa(struct ipx_addr *);
-
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index ba44cd3..b06dba7 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -5,6 +5,7 @@
SUBDIR= adduser \
arp \
+ binmiscctl \
bootparamd \
bsdconfig \
bsdinstall \
@@ -37,7 +38,6 @@ SUBDIR= adduser \
inetd \
iostat \
iscsid \
- isfctl \
kldxref \
mailwrapper \
makefs \
@@ -49,7 +49,7 @@ SUBDIR= adduser \
mountd \
mptutil \
mtest \
- mtree \
+ ${_mtree} \
newsyslog \
nfscbd \
nfsd \
@@ -143,6 +143,10 @@ SUBDIR+= fdread
SUBDIR+= fdwrite
.endif
+.if ${MK_FMTREE} != "no"
+SUBDIR+= mtree
+.endif
+
.if ${MK_FREEBSD_UPDATE} != "no"
SUBDIR+= freebsd-update
.endif
@@ -173,10 +177,6 @@ SUBDIR+= traceroute6
SUBDIR+= ipfwpcap
.endif
-.if ${MK_IPX} != "no"
-SUBDIR+= IPXrouted
-.endif
-
.if ${MK_JAIL} != "no"
SUBDIR+= jail
SUBDIR+= jexec
@@ -252,10 +252,6 @@ SUBDIR+= ftp-proxy
SUBDIR+= pkg
.endif
-.if ${MK_PKGTOOLS} != "no"
-SUBDIR+= pkg_install
-.endif
-
# XXX MK_TOOLCHAIN?
.if ${MK_PMC} != "no"
SUBDIR+= pmcannotate
@@ -289,6 +285,10 @@ SUBDIR+= praliases
SUBDIR+= sendmail
.endif
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.if ${MK_TOOLCHAIN} != "no"
SUBDIR+= config
SUBDIR+= crunch
@@ -321,4 +321,6 @@ SUBDIR+= wpa
SUBDIR:= ${SUBDIR:O}
+SUBDIR_PARALLEL=
+
.include <bsd.subdir.mk>
diff --git a/usr.sbin/acpi/acpidump/acpi.c b/usr.sbin/acpi/acpidump/acpi.c
index d3f9685..66cd7bd 100644
--- a/usr.sbin/acpi/acpidump/acpi.c
+++ b/usr.sbin/acpi/acpidump/acpi.c
@@ -501,6 +501,7 @@ acpi_handle_hpet(ACPI_TABLE_HEADER *sdp)
printf("FALSE}\n");
printf("\tPCI Vendor ID=0x%04x\n", hpet->Id >> 16);
printf("\tMinimal Tick=%d\n", hpet->MinimumTick);
+ printf("\tFlags=0x%02x\n", hpet->Flags);
printf(END_COMMENT);
}
diff --git a/usr.sbin/amd/include/newvers.sh b/usr.sbin/amd/include/newvers.sh
index e192ee9..0ca390e 100644
--- a/usr.sbin/amd/include/newvers.sh
+++ b/usr.sbin/amd/include/newvers.sh
@@ -31,13 +31,4 @@ fi
cat << __EOF
-/* Define name of host */
-#define BUILD_HOST "`hostname`"
-
-/* Define user name */
-#define BUILD_USER "`whoami`"
-
-/* Define configuration date */
-#define BUILD_DATE "`LC_ALL=C date`"
-
__EOF
diff --git a/usr.sbin/arp/arp.4 b/usr.sbin/arp/arp.4
index 93cfd07..7bfa8ec 100644
--- a/usr.sbin/arp/arp.4
+++ b/usr.sbin/arp/arp.4
@@ -28,7 +28,7 @@
.\" @(#)arp4.4 6.5 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
-.Dd May 11, 2013
+.Dd November 5, 2013
.Dt ARP 4
.Os
.Sh NAME
@@ -165,10 +165,6 @@ Default is 5 tries.
.It Va proxyall
Enables ARP proxying for all hosts on net.
Turned off by default.
-.It Va useloopback
-If an ARP entry is added for local address, force the traffic to go through
-the loopback interface.
-Turned on by default.
.It Va wait
Lifetime of an incomplete ARP entry.
Default is 20 seconds.
diff --git a/usr.sbin/arp/arp.c b/usr.sbin/arp/arp.c
index 25fbb23..932ac95 100644
--- a/usr.sbin/arp/arp.c
+++ b/usr.sbin/arp/arp.c
@@ -104,6 +104,8 @@ static char *rifname;
static time_t expire_time;
static int flags, doing_proxy;
+struct if_nameindex *ifnameindex;
+
/* which function we're supposed to do */
#define F_GET 1
#define F_SET 2
@@ -200,6 +202,9 @@ main(int argc, char *argv[])
break;
}
+ if (ifnameindex != NULL)
+ if_freenameindex(ifnameindex);
+
return (rtn);
}
@@ -558,8 +563,6 @@ search(u_long addr, action_fn *action)
/*
* Display an arp entry
*/
-static char lifname[IF_NAMESIZE];
-static int64_t lifindex = -1;
static void
print_entry(struct sockaddr_dl *sdl,
@@ -568,8 +571,13 @@ print_entry(struct sockaddr_dl *sdl,
const char *host;
struct hostent *hp;
struct iso88025_sockaddr_dl_data *trld;
+ struct if_nameindex *p;
int seg;
+ if (ifnameindex == NULL)
+ if ((ifnameindex = if_nameindex()) == NULL)
+ err(1, "cannot retrieve interface names");
+
if (nflag == 0)
hp = gethostbyaddr((caddr_t)&(addr->sin_addr),
sizeof addr->sin_addr, AF_INET);
@@ -596,12 +604,15 @@ print_entry(struct sockaddr_dl *sdl,
}
} else
printf("(incomplete)");
- if (sdl->sdl_index != lifindex &&
- if_indextoname(sdl->sdl_index, lifname) != NULL) {
- lifindex = sdl->sdl_index;
- printf(" on %s", lifname);
- } else if (sdl->sdl_index == lifindex)
- printf(" on %s", lifname);
+
+ for (p = ifnameindex; p && ifnameindex->if_index &&
+ ifnameindex->if_name; p++) {
+ if (p->if_index == sdl->sdl_index) {
+ printf(" on %s", p->if_name);
+ break;
+ }
+ }
+
if (rtm->rtm_rmx.rmx_expire == 0)
printf(" permanent");
else {
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
index 0644ed7..c73cb3d 100644
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -6,17 +6,42 @@ PROG= bhyve
DEBUG_FLAGS= -g -O0
-SRCS= acpi.c atpic.c bhyverun.c block_if.c consport.c dbgport.c elcr.c
-SRCS+= inout.c ioapic.c mem.c mevent.c mptbl.c pci_ahci.c
-SRCS+= pci_emul.c pci_hostbridge.c pci_passthru.c pci_virtio_block.c
-SRCS+= pci_virtio_net.c pci_uart.c pit_8254.c pmtmr.c post.c rtc.c
-SRCS+= virtio.c xmsr.c spinup_ap.c
+MAN= bhyve.8
+
+SRCS= \
+ atkbdc.c \
+ acpi.c \
+ bhyverun.c \
+ block_if.c \
+ consport.c \
+ dbgport.c \
+ inout.c \
+ ioapic.c \
+ mem.c \
+ mevent.c \
+ mptbl.c \
+ pci_ahci.c \
+ pci_emul.c \
+ pci_hostbridge.c \
+ pci_lpc.c \
+ pci_passthru.c \
+ pci_virtio_block.c \
+ pci_virtio_net.c \
+ pci_virtio_rnd.c \
+ pci_uart.c \
+ pm.c \
+ pmtmr.c \
+ post.c \
+ rtc.c \
+ smbiostbl.c \
+ uart_emul.c \
+ virtio.c \
+ xmsr.c \
+ spinup_ap.c
.PATH: ${.CURDIR}/../../sys/amd64/vmm
SRCS+= vmm_instruction_emul.c
-NO_MAN=
-
DPADD= ${LIBVMMAPI} ${LIBMD} ${LIBUTIL} ${LIBPTHREAD}
LDADD= -lvmmapi -lmd -lutil -lpthread
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
index 89c11bc..db7f0eb 100644
--- a/usr.sbin/bhyve/acpi.c
+++ b/usr.sbin/bhyve/acpi.c
@@ -39,13 +39,14 @@
*
* Layout
* ------
- * RSDP -> 0xf0400 (36 bytes fixed)
- * RSDT -> 0xf0440 (36 bytes + 4*N table addrs, 2 used)
- * XSDT -> 0xf0480 (36 bytes + 8*N table addrs, 2 used)
- * MADT -> 0xf0500 (depends on #CPUs)
- * FADT -> 0xf0600 (268 bytes)
- * FACS -> 0xf0780 (64 bytes)
- * DSDT -> 0xf0800 (variable - can go up to 0x100000)
+ * RSDP -> 0xf2400 (36 bytes fixed)
+ * RSDT -> 0xf2440 (36 bytes + 4*N table addrs, 2 used)
+ * XSDT -> 0xf2480 (36 bytes + 8*N table addrs, 2 used)
+ * MADT -> 0xf2500 (depends on #CPUs)
+ * FADT -> 0xf2600 (268 bytes)
+ * HPET -> 0xf2740 (56 bytes)
+ * FACS -> 0xf2780 (64 bytes)
+ * DSDT -> 0xf2800 (variable - can go up to 0x100000)
*/
#include <sys/cdefs.h>
@@ -56,23 +57,29 @@ __FBSDID("$FreeBSD$");
#include <sys/stat.h>
#include <paths.h>
+#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
#include "bhyverun.h"
#include "acpi.h"
+#include "pci_emul.h"
/*
* Define the base address of the ACPI tables, and the offsets to
* the individual tables
*/
-#define BHYVE_ACPI_BASE 0xf0400
+#define BHYVE_ACPI_BASE 0xf2400
#define RSDT_OFFSET 0x040
#define XSDT_OFFSET 0x080
#define MADT_OFFSET 0x100
#define FADT_OFFSET 0x200
+#define HPET_OFFSET 0x340
#define FACS_OFFSET 0x380
#define DSDT_OFFSET 0x400
@@ -80,12 +87,11 @@ __FBSDID("$FreeBSD$");
#define BHYVE_ASL_SUFFIX ".aml"
#define BHYVE_ASL_COMPILER "/usr/sbin/iasl"
-#define BHYVE_PM_TIMER_ADDR 0x408
-
static int basl_keep_temps;
static int basl_verbose_iasl;
static int basl_ncpu;
static uint32_t basl_acpi_base = BHYVE_ACPI_BASE;
+static uint32_t hpet_capabilities;
/*
* Contains the full pathname of the template to be passed
@@ -94,6 +100,13 @@ static uint32_t basl_acpi_base = BHYVE_ACPI_BASE;
static char basl_template[MAXPATHLEN];
static char basl_stemplate[MAXPATHLEN];
+/*
+ * State for dsdt_line(), dsdt_indent(), and dsdt_unindent().
+ */
+static FILE *dsdt_fp;
+static int dsdt_indent_level;
+static int dsdt_error;
+
struct basl_fio {
int fd;
FILE *fp;
@@ -158,11 +171,13 @@ basl_fwrite_rsdt(FILE *fp)
EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
EFPRINTF(fp, "\n");
- /* Add in pointers to the MADT and FADT */
+ /* Add in pointers to the MADT, FADT and HPET */
EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : %08X\n",
basl_acpi_base + MADT_OFFSET);
EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : %08X\n",
basl_acpi_base + FADT_OFFSET);
+ EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : %08X\n",
+ basl_acpi_base + HPET_OFFSET);
EFFLUSH(fp);
@@ -194,11 +209,13 @@ basl_fwrite_xsdt(FILE *fp)
EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
EFPRINTF(fp, "\n");
- /* Add in pointers to the MADT and FADT */
+ /* Add in pointers to the MADT, FADT and HPET */
EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : 00000000%08X\n",
basl_acpi_base + MADT_OFFSET);
EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : 00000000%08X\n",
basl_acpi_base + FADT_OFFSET);
+ EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : 00000000%08X\n",
+ basl_acpi_base + HPET_OFFSET);
EFFLUSH(fp);
@@ -249,25 +266,45 @@ basl_fwrite_madt(FILE *fp)
EFPRINTF(fp, "\n");
}
- /* Always a single IOAPIC entry, with ID ncpu+1 */
+ /* Always a single IOAPIC entry, with ID 0 */
EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n");
EFPRINTF(fp, "[0001]\t\tLength : 0C\n");
/* iasl expects a hex value for the i/o apic id */
- EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", basl_ncpu);
+ EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0);
EFPRINTF(fp, "[0001]\t\tReserved : 00\n");
EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n");
EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n");
EFPRINTF(fp, "\n");
- /* Override the 8259 chained vector. XXX maybe not needed */
+ /* Legacy IRQ0 is connected to pin 2 of the IOAPIC */
EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
EFPRINTF(fp, "[0001]\t\tBus : 00\n");
- EFPRINTF(fp, "[0001]\t\tSource : 09\n");
- EFPRINTF(fp, "[0004]\t\tInterrupt : 00000009\n");
+ EFPRINTF(fp, "[0001]\t\tSource : 00\n");
+ EFPRINTF(fp, "[0004]\t\tInterrupt : 00000002\n");
+ EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n");
+ EFPRINTF(fp, "\t\t\tPolarity : 1\n");
+ EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n");
+ EFPRINTF(fp, "[0001]\t\tLength : 0A\n");
+ EFPRINTF(fp, "[0001]\t\tBus : 00\n");
+ EFPRINTF(fp, "[0001]\t\tSource : %02X\n", SCI_INT);
+ EFPRINTF(fp, "[0004]\t\tInterrupt : %08X\n", SCI_INT);
EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0000\n");
- EFPRINTF(fp, "\t\t\tPolarity : 0\n");
- EFPRINTF(fp, "\t\t\tTrigger Mode : 0\n");
+ EFPRINTF(fp, "\t\t\tPolarity : 3\n");
+ EFPRINTF(fp, "\t\t\tTrigger Mode : 3\n");
+ EFPRINTF(fp, "\n");
+
+ /* Local APIC NMI is connected to LINT 1 on all CPUs */
+ EFPRINTF(fp, "[0001]\t\tSubtable Type : 04\n");
+ EFPRINTF(fp, "[0001]\t\tLength : 06\n");
+ EFPRINTF(fp, "[0001]\t\tProcessorId : FF\n");
+ EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n");
+ EFPRINTF(fp, "\t\t\tPolarity : 1\n");
+ EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n");
+ EFPRINTF(fp, "[0001]\t\tInterrupt : 01\n");
EFPRINTF(fp, "\n");
EFFLUSH(fp);
@@ -304,21 +341,27 @@ basl_fwrite_fadt(FILE *fp)
basl_acpi_base + FACS_OFFSET);
EFPRINTF(fp, "[0004]\t\tDSDT Address : %08X\n",
basl_acpi_base + DSDT_OFFSET);
- EFPRINTF(fp, "[0001]\t\tModel : 00\n");
+ EFPRINTF(fp, "[0001]\t\tModel : 01\n");
EFPRINTF(fp, "[0001]\t\tPM Profile : 00 [Unspecified]\n");
- EFPRINTF(fp, "[0002]\t\tSCI Interrupt : 0009\n");
- EFPRINTF(fp, "[0004]\t\tSMI Command Port : 00000000\n");
- EFPRINTF(fp, "[0001]\t\tACPI Enable Value : 00\n");
- EFPRINTF(fp, "[0001]\t\tACPI Disable Value : 00\n");
+ EFPRINTF(fp, "[0002]\t\tSCI Interrupt : %04X\n",
+ SCI_INT);
+ EFPRINTF(fp, "[0004]\t\tSMI Command Port : %08X\n",
+ SMI_CMD);
+ EFPRINTF(fp, "[0001]\t\tACPI Enable Value : %02X\n",
+ BHYVE_ACPI_ENABLE);
+ EFPRINTF(fp, "[0001]\t\tACPI Disable Value : %02X\n",
+ BHYVE_ACPI_DISABLE);
EFPRINTF(fp, "[0001]\t\tS4BIOS Command : 00\n");
EFPRINTF(fp, "[0001]\t\tP-State Control : 00\n");
- EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : %08X\n",
+ PM1A_EVT_ADDR);
EFPRINTF(fp, "[0004]\t\tPM1B Event Block Address : 00000000\n");
- EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : 00000000\n");
+ EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : %08X\n",
+ PM1A_CNT_ADDR);
EFPRINTF(fp, "[0004]\t\tPM1B Control Block Address : 00000000\n");
EFPRINTF(fp, "[0004]\t\tPM2 Control Block Address : 00000000\n");
EFPRINTF(fp, "[0004]\t\tPM Timer Block Address : %08X\n",
- BHYVE_PM_TIMER_ADDR);
+ IO_PMTMR);
EFPRINTF(fp, "[0004]\t\tGPE0 Block Address : 00000000\n");
EFPRINTF(fp, "[0004]\t\tGPE1 Block Address : 00000000\n");
EFPRINTF(fp, "[0001]\t\tPM1 Event Block Length : 04\n");
@@ -349,15 +392,15 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n");
EFPRINTF(fp, "\t\t\tWBINVD instruction is operational (V1) : 1\n");
EFPRINTF(fp, "\t\t\tWBINVD flushes all caches (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 0\n");
+ EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 1\n");
EFPRINTF(fp, "\t\t\tC2 works on MP system (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tControl Method Power Button (V1) : 1\n");
+ EFPRINTF(fp, "\t\t\tControl Method Power Button (V1) : 0\n");
EFPRINTF(fp, "\t\t\tControl Method Sleep Button (V1) : 1\n");
EFPRINTF(fp, "\t\t\tRTC wake not in fixed reg space (V1) : 0\n");
EFPRINTF(fp, "\t\t\tRTC can wake system from S4 (V1) : 0\n");
EFPRINTF(fp, "\t\t\t32-bit PM Timer (V1) : 1\n");
EFPRINTF(fp, "\t\t\tDocking Supported (V1) : 0\n");
- EFPRINTF(fp, "\t\t\tReset Register Supported (V2) : 0\n");
+ EFPRINTF(fp, "\t\t\tReset Register Supported (V2) : 1\n");
EFPRINTF(fp, "\t\t\tSealed Case (V3) : 0\n");
EFPRINTF(fp, "\t\t\tHeadless - No Video (V3) : 1\n");
EFPRINTF(fp, "\t\t\tUse native instr after SLP_TYPx (V3) : 0\n");
@@ -377,10 +420,10 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp, "[0001]\t\tBit Width : 08\n");
EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000CF9\n");
EFPRINTF(fp, "\n");
- EFPRINTF(fp, "[0001]\t\tValue to cause reset : 00\n");
+ EFPRINTF(fp, "[0001]\t\tValue to cause reset : 06\n");
EFPRINTF(fp, "[0003]\t\tReserved : 000000\n");
EFPRINTF(fp, "[0008]\t\tFACS Address : 00000000%08X\n",
basl_acpi_base + FACS_OFFSET);
@@ -392,7 +435,8 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp, "[0001]\t\tBit Width : 20\n");
EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
+ PM1A_EVT_ADDR);
EFPRINTF(fp, "\n");
EFPRINTF(fp,
@@ -411,7 +455,8 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp, "[0001]\t\tBit Width : 10\n");
EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n");
- EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000001\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
+ PM1A_CNT_ADDR);
EFPRINTF(fp, "\n");
EFPRINTF(fp,
@@ -443,7 +488,7 @@ basl_fwrite_fadt(FILE *fp)
EFPRINTF(fp,
"[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n");
EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n",
- BHYVE_PM_TIMER_ADDR);
+ IO_PMTMR);
EFPRINTF(fp, "\n");
EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n");
@@ -489,6 +534,55 @@ err_exit:
}
static int
+basl_fwrite_hpet(FILE *fp)
+{
+ int err;
+
+ err = 0;
+
+ EFPRINTF(fp, "/*\n");
+ EFPRINTF(fp, " * bhyve HPET template\n");
+ EFPRINTF(fp, " */\n");
+ EFPRINTF(fp, "[0004]\t\tSignature : \"HPET\"\n");
+ EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n");
+ EFPRINTF(fp, "[0001]\t\tRevision : 01\n");
+ EFPRINTF(fp, "[0001]\t\tChecksum : 00\n");
+ EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n");
+ EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVHPET \"\n");
+ EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n");
+
+ /* iasl will fill in the compiler ID/revision fields */
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n");
+ EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0004]\t\tTimer Block ID : %08X\n", hpet_capabilities);
+ EFPRINTF(fp,
+ "[0012]\t\tTimer Block Register : [Generic Address Structure]\n");
+ EFPRINTF(fp, "[0001]\t\tSpace ID : 00 [SystemMemory]\n");
+ EFPRINTF(fp, "[0001]\t\tBit Width : 00\n");
+ EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n");
+ EFPRINTF(fp,
+ "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n");
+ EFPRINTF(fp, "[0008]\t\tAddress : 00000000FED00000\n");
+ EFPRINTF(fp, "\n");
+
+ EFPRINTF(fp, "[0001]\t\tHPET Number : 00\n");
+ EFPRINTF(fp, "[0002]\t\tMinimum Clock Ticks : 0000\n");
+ EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n");
+ EFPRINTF(fp, "\t\t\t4K Page Protect : 1\n");
+ EFPRINTF(fp, "\t\t\t64K Page Protect : 0\n");
+ EFPRINTF(fp, "\n");
+
+ EFFLUSH(fp);
+
+ return (0);
+
+err_exit:
+ return (errno);
+}
+
+static int
basl_fwrite_facs(FILE *fp)
{
int err;
@@ -521,96 +615,122 @@ err_exit:
return (errno);
}
+/*
+ * Helper routines for writing to the DSDT from other modules.
+ */
+void
+dsdt_line(const char *fmt, ...)
+{
+ va_list ap;
+ int err;
+
+ if (dsdt_error != 0)
+ return;
+
+ if (strcmp(fmt, "") != 0) {
+ if (dsdt_indent_level != 0)
+ EFPRINTF(dsdt_fp, "%*c", dsdt_indent_level * 2, ' ');
+ va_start(ap, fmt);
+ if (vfprintf(dsdt_fp, fmt, ap) < 0)
+ goto err_exit;
+ va_end(ap);
+ }
+ EFPRINTF(dsdt_fp, "\n");
+ return;
+
+err_exit:
+ dsdt_error = errno;
+}
+
+void
+dsdt_indent(int levels)
+{
+
+ dsdt_indent_level += levels;
+ assert(dsdt_indent_level >= 0);
+}
+
+void
+dsdt_unindent(int levels)
+{
+
+ assert(dsdt_indent_level >= levels);
+ dsdt_indent_level -= levels;
+}
+
+void
+dsdt_fixed_ioport(uint16_t iobase, uint16_t length)
+{
+
+ dsdt_line("IO (Decode16,");
+ dsdt_line(" 0x%04X, // Range Minimum", iobase);
+ dsdt_line(" 0x%04X, // Range Maximum", iobase);
+ dsdt_line(" 0x01, // Alignment");
+ dsdt_line(" 0x%02X, // Length", length);
+ dsdt_line(" )");
+}
+
+void
+dsdt_fixed_irq(uint8_t irq)
+{
+
+ dsdt_line("IRQNoFlags ()");
+ dsdt_line(" {%d}", irq);
+}
+
+void
+dsdt_fixed_mem32(uint32_t base, uint32_t length)
+{
+
+ dsdt_line("Memory32Fixed (ReadWrite,");
+ dsdt_line(" 0x%08X, // Address Base", base);
+ dsdt_line(" 0x%08X, // Address Length", length);
+ dsdt_line(" )");
+}
+
static int
basl_fwrite_dsdt(FILE *fp)
{
int err;
err = 0;
-
- EFPRINTF(fp, "/*\n");
- EFPRINTF(fp, " * bhyve DSDT template\n");
- EFPRINTF(fp, " */\n");
- EFPRINTF(fp, "DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
- "\"BHYVE \", \"BVDSDT \", 0x00000001)\n");
- EFPRINTF(fp, "{\n");
- EFPRINTF(fp, " Scope (_SB)\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " Device (PCI0)\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0A03\"))\n");
- EFPRINTF(fp, " Name (_ADR, Zero)\n");
- EFPRINTF(fp, " Name (_UID, One)\n");
- EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " WordBusNumber (ResourceProducer, MinFixed,"
- "MaxFixed, PosDecode,\n");
- EFPRINTF(fp, " 0x0000, // Granularity\n");
- EFPRINTF(fp, " 0x0000, // Range Minimum\n");
- EFPRINTF(fp, " 0x00FF, // Range Maximum\n");
- EFPRINTF(fp, " 0x0000, // Transl Offset\n");
- EFPRINTF(fp, " 0x0100, // Length\n");
- EFPRINTF(fp, " ,, )\n");
- EFPRINTF(fp, " IO (Decode16,\n");
- EFPRINTF(fp, " 0x0CF8, // Range Minimum\n");
- EFPRINTF(fp, " 0x0CF8, // Range Maximum\n");
- EFPRINTF(fp, " 0x01, // Alignment\n");
- EFPRINTF(fp, " 0x08, // Length\n");
- EFPRINTF(fp, " )\n");
- EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed,"
- "PosDecode, EntireRange,\n");
- EFPRINTF(fp, " 0x0000, // Granularity\n");
- EFPRINTF(fp, " 0x0000, // Range Minimum\n");
- EFPRINTF(fp, " 0x0CF7, // Range Maximum\n");
- EFPRINTF(fp, " 0x0000, // Transl Offset\n");
- EFPRINTF(fp, " 0x0CF8, // Length\n");
- EFPRINTF(fp, " ,, , TypeStatic)\n");
- EFPRINTF(fp, " WordIO (ResourceProducer, MinFixed, MaxFixed,"
- "PosDecode, EntireRange,\n");
- EFPRINTF(fp, " 0x0000, // Granularity\n");
- EFPRINTF(fp, " 0x0D00, // Range Minimum\n");
- EFPRINTF(fp, " 0xFFFF, // Range Maximum\n");
- EFPRINTF(fp, " 0x0000, // Transl Offset\n");
- EFPRINTF(fp, " 0xF300, // Length\n");
- EFPRINTF(fp, " ,, , TypeStatic)\n");
- EFPRINTF(fp, " })\n");
- EFPRINTF(fp, " }\n");
- EFPRINTF(fp, " }\n");
- EFPRINTF(fp, "\n");
- EFPRINTF(fp, " Scope (_SB.PCI0)\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " Device (ISA)\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " Name (_ADR, 0x00010000)\n");
- EFPRINTF(fp, " OperationRegion (P40C, PCI_Config, 0x60, 0x04)\n");
- EFPRINTF(fp, " }\n");
- EFPRINTF(fp, " }\n");
- EFPRINTF(fp, "\n");
- EFPRINTF(fp, " Scope (_SB.PCI0.ISA)\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " Device (RTC)\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " Name (_HID, EisaId (\"PNP0B00\"))\n");
- EFPRINTF(fp, " Name (_CRS, ResourceTemplate ()\n");
- EFPRINTF(fp, " {\n");
- EFPRINTF(fp, " IO (Decode16,\n");
- EFPRINTF(fp, " 0x0070, // Range Minimum\n");
- EFPRINTF(fp, " 0x0070, // Range Maximum\n");
- EFPRINTF(fp, " 0x10, // Alignment\n");
- EFPRINTF(fp, " 0x02, // Length\n");
- EFPRINTF(fp, " )\n");
- EFPRINTF(fp, " IRQNoFlags ()\n");
- EFPRINTF(fp, " {8}\n");
- EFPRINTF(fp, " IO (Decode16,\n");
- EFPRINTF(fp, " 0x0072, // Range Minimum\n");
- EFPRINTF(fp, " 0x0072, // Range Maximum\n");
- EFPRINTF(fp, " 0x02, // Alignment\n");
- EFPRINTF(fp, " 0x06, // Length\n");
- EFPRINTF(fp, " )\n");
- EFPRINTF(fp, " })\n");
- EFPRINTF(fp, " }\n");
- EFPRINTF(fp, " }\n");
- EFPRINTF(fp, "}\n");
+ dsdt_fp = fp;
+ dsdt_error = 0;
+ dsdt_indent_level = 0;
+
+ dsdt_line("/*");
+ dsdt_line(" * bhyve DSDT template");
+ dsdt_line(" */");
+ dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2,"
+ "\"BHYVE \", \"BVDSDT \", 0x00000001)");
+ dsdt_line("{");
+ dsdt_line(" Name (_S5, Package (0x02)");
+ dsdt_line(" {");
+ dsdt_line(" 0x05,");
+ dsdt_line(" Zero,");
+ dsdt_line(" })");
+
+ pci_write_dsdt();
+
+ dsdt_line("");
+ dsdt_line(" Scope (_SB.PC00)");
+ dsdt_line(" {");
+ dsdt_line(" Device (HPET)");
+ dsdt_line(" {");
+ dsdt_line(" Name (_HID, EISAID(\"PNP0103\"))");
+ dsdt_line(" Name (_UID, 0)");
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+ dsdt_indent(4);
+ dsdt_fixed_mem32(0xFED00000, 0x400);
+ dsdt_unindent(4);
+ dsdt_line(" })");
+ dsdt_line(" }");
+ dsdt_line(" }");
+ dsdt_line("}");
+
+ if (dsdt_error != 0)
+ return (dsdt_error);
EFFLUSH(fp);
@@ -800,24 +920,23 @@ static struct {
{ basl_fwrite_xsdt, XSDT_OFFSET },
{ basl_fwrite_madt, MADT_OFFSET },
{ basl_fwrite_fadt, FADT_OFFSET },
+ { basl_fwrite_hpet, HPET_OFFSET },
{ basl_fwrite_facs, FACS_OFFSET },
{ basl_fwrite_dsdt, DSDT_OFFSET },
{ NULL }
};
int
-acpi_build(struct vmctx *ctx, int ncpu, int ioapic)
+acpi_build(struct vmctx *ctx, int ncpu)
{
int err;
int i;
- err = 0;
basl_ncpu = ncpu;
- if (!ioapic) {
- fprintf(stderr, "ACPI tables require an ioapic\n");
- return (EINVAL);
- }
+ err = vm_get_hpet_capabilities(ctx, &hpet_capabilities);
+ if (err != 0)
+ return (err);
/*
* For debug, allow the user to have iasl compiler output sent
diff --git a/usr.sbin/bhyve/acpi.h b/usr.sbin/bhyve/acpi.h
index fec6c9d..57edc48 100644
--- a/usr.sbin/bhyve/acpi.h
+++ b/usr.sbin/bhyve/acpi.h
@@ -29,6 +29,25 @@
#ifndef _ACPI_H_
#define _ACPI_H_
-int acpi_build(struct vmctx *ctx, int ncpu, int ioapic);
+#define SCI_INT 9
+
+#define SMI_CMD 0xb2
+#define BHYVE_ACPI_ENABLE 0xa0
+#define BHYVE_ACPI_DISABLE 0xa1
+
+#define PM1A_EVT_ADDR 0x400
+#define PM1A_CNT_ADDR 0x404
+
+#define IO_PMTMR 0x408 /* 4-byte i/o port for the timer */
+
+struct vmctx;
+
+int acpi_build(struct vmctx *ctx, int ncpu);
+void dsdt_line(const char *fmt, ...);
+void dsdt_fixed_ioport(uint16_t iobase, uint16_t length);
+void dsdt_fixed_irq(uint8_t irq);
+void dsdt_fixed_mem32(uint32_t base, uint32_t length);
+void dsdt_indent(int levels);
+void dsdt_unindent(int levels);
#endif /* _ACPI_H_ */
diff --git a/usr.sbin/bhyve/atkbdc.c b/usr.sbin/bhyve/atkbdc.c
new file mode 100644
index 0000000..1b7d66c
--- /dev/null
+++ b/usr.sbin/bhyve/atkbdc.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <machine/vmm.h>
+
+#include <stdio.h>
+
+#include "inout.h"
+#include "pci_lpc.h"
+
+#define KBD_DATA_PORT 0x60
+
+#define KBD_STS_CTL_PORT 0x64
+#define KDB_SYS_FLAG 0x4
+
+#define KBDC_RESET 0xfe
+
+static int
+atkbdc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ if (bytes != 1)
+ return (INOUT_ERROR);
+
+ *eax = 0;
+
+ return (INOUT_OK);
+}
+
+static int
+atkbdc_sts_ctl_handler(struct vmctx *ctx, int vcpu, int in, int port,
+ int bytes, uint32_t *eax, void *arg)
+{
+ int retval;
+
+ if (bytes != 1)
+ return (INOUT_ERROR);
+
+ retval = INOUT_OK;
+ if (in) {
+ *eax = KDB_SYS_FLAG; /* system passed POST */
+ } else {
+ switch (*eax) {
+ case KBDC_RESET: /* Pulse "reset" line. */
+ retval = INOUT_RESET;
+ break;
+ }
+ }
+
+ return (retval);
+}
+
+INOUT_PORT(atkdbc, KBD_DATA_PORT, IOPORT_F_INOUT, atkbdc_data_handler);
+SYSRES_IO(KBD_DATA_PORT, 1);
+INOUT_PORT(atkbdc, KBD_STS_CTL_PORT, IOPORT_F_INOUT,
+ atkbdc_sts_ctl_handler);
+SYSRES_IO(KBD_STS_CTL_PORT, 1);
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
new file mode 100644
index 0000000..88e7214
--- /dev/null
+++ b/usr.sbin/bhyve/bhyve.8
@@ -0,0 +1,306 @@
+.\" Copyright (c) 2013 Peter Grehan
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 2, 2014
+.Dt BHYVE 8
+.Os
+.Sh NAME
+.Nm bhyve
+.Nd "run a guest operating system inside a virtual machine"
+.Sh SYNOPSIS
+.Nm
+.Op Fl aehwxAHPW
+.Op Fl c Ar numcpus
+.Op Fl g Ar gdbport
+.Op Fl p Ar pinnedcpu
+.Op Fl s Ar slot,emulation Ns Op , Ns Ar conf
+.Op Fl l Ar lpcdev Ns Op , Ns Ar conf
+.Ar vmname
+.Sh DESCRIPTION
+.Nm
+is an experimental hypervisor that runs guest operating systems inside a
+virtual machine.
+.Pp
+Parameters such as the number of virtual CPUs, amount of guest memory, and
+I/O connectivity can be specified with command-line parameters.
+.Pp
+The guest operating system must be loaded with
+.Xr bhyveload 4
+or a similar boot loader before running
+.Nm .
+.Pp
+.Nm
+runs until the guest operating system reboots or an unhandled hypervisor
+exit is detected.
+.Sh OPTIONS
+.Bl -tag -width 10n
+.It Fl a
+The guest's local APIC is configured in xAPIC mode.
+
+The xAPIC mode is the default setting so this option is redundant. It will be
+deprecated in a future version.
+.It Fl A
+Generate ACPI tables.
+Required for
+.Fx Ns /amd64
+guests.
+.It Fl c Ar numcpus
+Number of guest virtual CPUs.
+The default is 1 and the maximum is 16.
+.It Fl H
+Yield the virtual CPU thread when a HLT instruction is detected.
+If this option is not specified, virtual CPUs will use 100% of a host CPU.
+.It Fl g Ar gdbport
+For
+.Fx Ns /amd64 kernels compiled with
+.Cd "option bvmdebug" ,
+allow a remote kernel kgdb to be relayed to the guest kernel gdb stub
+via a local IPv4 address and this port.
+This option will be deprecated in a future version.
+.It Fl p Ar pinnedcpu
+Force guest virtual CPUs to be pinned to host CPUs.
+Virtual CPU
+.Em n
+is pinned to host CPU
+.Em pinnedcpu+n .
+.It Fl P
+Force the guest virtual CPU to exit when a PAUSE instruction is detected.
+.It Fl W
+Force virtio PCI device emulations to use MSI interrupts instead of MSI-X
+interrupts.
+.It Fl s Ar slot,emulation Ns Op , Ns Ar conf
+Configure a virtual PCI slot and function.
+.Pp
+.Nm bhyve
+provides PCI bus emulation and virtual devices that can be attached to
+slots on the bus.
+There are 32 available slots, with the option of providing up to 8 functions
+per slot.
+.Bl -tag -width 10n
+.It Ar slot
+.Ar pcislot[:function]
+
+.Ar bus:pcislot:function
+.Pp
+The
+.Ar pcislot
+value is 0 to 31. The optional function value is 0 to 7. The optional
+.Ar bus
+value is 0 to 255.
+If not specified, the function value defaults to 0.
+If not specified, the bus value defaults to 0.
+.It Ar emulation
+.Bl -tag -width 10n
+.It Li hostbridge | Li amd_hostbridge
+.Pp
+Provide a simple host bridge.
+This is usually configured at slot 0, and is required by most guest
+operating systems.
+The
+.Li amd_hostbridge
+emulation is identical but uses a PCI vendor ID of
+.Li AMD .
+.It Li passthru
+PCI pass-through device.
+.It Li virtio-net
+Virtio network interface.
+.It Li virtio-blk
+Virtio block storage interface.
+.It Li virtio-rnd
+Virtio RNG interface.
+.It Li ahci-cd
+AHCI controller attached to an ATAPI CD/DVD.
+.It Li ahci-hd
+AHCI controller attached to a SATA hard-drive.
+.It Li uart
+PCI 16550 serial device.
+.It Li lpc
+LPC PCI-ISA bridge with COM1 and COM2 16550 serial ports. The LPC bridge
+emulation can only be configured on bus 0.
+.El
+.It Op Ar conf
+This optional parameter describes the backend for device emulations.
+If
+.Ar conf
+is not specified, the device emulation has no backend and can be
+considered unconnected.
+.Pp
+Network devices:
+.Bl -tag -width 10n
+.It Ar tapN Ns Op , Ns Ar mac=xx:xx:xx:xx:xx:xx
+.It Ar vmnetN Ns Op , Ns Ar mac=xx:xx:xx:xx:xx:xx
+.Pp
+If
+.Ar mac
+is not specified, the MAC address is derived from a fixed OUI and the
+remaining bytes from an MD5 hash of the slot and function numbers and
+the device name.
+.Pp
+The MAC address is an ASCII string in
+.Xr ethers 5
+format.
+.El
+.Pp
+Block storage devices:
+.Bl -tag -width 10n
+.It Pa /filename Ns Oo , Ns Li nocache Oc Ns Oo , Ns Li direct Oc Ns Oo , Ns Li ro Oc
+.It Pa /dev/xxx Ns Oo , Ns Ar nocache Oc Ns Oo , Ns Ar direct Oc Ns Oo , Ns Ar ro Oc
+.Bl -tag -width 8n
+.It Li nocache
+Open the file with
+.Dv O_DIRECT .
+.It Li direct
+Open the file using
+.Dv O_SYNC .
+.It Li ro
+Force the file to be opened read-only.
+.El
+.Pp
+The
+.Li nocache ,
+.Li direct ,
+and
+.Li ro
+options are not available for virtio block devices.
+.El
+.Pp
+TTY devices:
+.Bl -tag -width 10n
+.It Li stdio
+Connect the serial port to the standard input and output of
+the bhyve process.
+.It Pa /dev/xxx
+Use the host TTY device for serial port I/O.
+.El
+.Pp
+Pass-through devices:
+.Bl -tag -width 10n
+.It Ns Ar slot Ns / Ns Ar bus Ns / Ns Ar function
+Connect to a PCI device on the host at the selector described by
+.Ar slot ,
+.Ar bus ,
+and
+.Ar function
+numbers.
+.El
+.Pp
+The host device must have been reserved at boot-time using the
+.Va pptdev
+loader variable as described in
+.Xr vmm 4 .
+.El
+.It Fl l Ar lpcdev Ns Op , Ns Ar conf
+Allow devices behind the LPC PCI-ISA bridge to be configured.
+The only supported devices are the TTY-class devices,
+.Li com1
+and
+.Li com2 .
+.It Fl m Ar size Ns Op Ar K|k|M|m|G|g|T|t
+Guest physical memory size in bytes.
+This must be the same size that was given to
+.Xr bhyveload 8 .
+.Pp
+The size argument may be suffixed with one of K, M, G or T (either upper
+or lower case) to indicate a multiple of kilobytes, megabytes, gigabytes,
+or terabytes.
+If no suffix is given, the value is assumed to be in megabytes.
+.It Fl e
+Force
+.Nm
+to exit when a guest issues an access to an I/O port that is not emulated.
+This is intended for debug purposes.
+.It Fl w
+Ignore accesses to unimplemented Model Specific Registers (MSRs). This is intended for debug purposes.
+.It Fl x
+The guest's local APIC is configured in x2APIC mode.
+.It Fl h
+Print help message and exit.
+.It Ar vmname
+Alphanumeric name of the guest.
+This should be the same as that created by
+.Xr bhyveload 8 .
+.El
+.Sh EXAMPLES
+The guest operating system must have been loaded with
+.Xr bhyveload 4
+or a similar boot loader before
+.Xr bhyve 4
+can be run.
+.Pp
+To run a virtual machine with 1GB of memory, two virtual CPUs, a virtio
+block device backed by the
+.Pa /my/image
+filesystem image, and a serial port for the console:
+.Bd -literal -offset indent
+bhyve -c 2 -s 0,hostbridge -s 1,lpc -s 2,virtio-blk,/my/image \\
+ -l com1,stdio -A -H -P -m 1G vm1
+.Ed
+.Pp
+Run a 24GB single-CPU virtual machine with three network ports, one of which
+has a MAC address specified:
+.Bd -literal -offset indent
+bhyve -s 0,hostbridge -s 1,lpc -s 2:0,virtio-net,tap0 \\
+ -s 2:1,virtio-net,tap1 \\
+ -s 2:2,virtio-net,tap2,mac=00:be:fa:76:45:00 \\
+ -s 3,virtio-blk,/my/image -l com1,stdio \\
+ -A -H -P -m 24G bigvm
+.Ed
+.Pp
+Run an 8GB quad-CPU virtual machine with 8 AHCI SATA disks, an AHCI ATAPI
+CD-ROM, a single virtio network port, an AMD hostbridge, and the console
+port connected to an
+.Xr nmdm 4
+null-model device.
+.Bd -literal -offset indent
+bhyve -c 4 \e\
+ -s 0,amd_hostbridge -s 1,lpc \\
+ -s 1:0,ahci-hd,/images/disk.1 \\
+ -s 1:1,ahci-hd,/images/disk.2 \\
+ -s 1:2,ahci-hd,/images/disk.3 \\
+ -s 1:3,ahci-hd,/images/disk.4 \\
+ -s 1:4,ahci-hd,/images/disk.5 \\
+ -s 1:5,ahci-hd,/images/disk.6 \\
+ -s 1:6,ahci-hd,/images/disk.7 \\
+ -s 1:7,ahci-hd,/images/disk.8 \\
+ -s 2,ahci-cd,/images.install.iso \\
+ -s 3,virtio-net,tap0 \\
+ -l com1,/dev/nmdm0A \\
+ -A -H -P -m 8G
+.Ed
+.Sh SEE ALSO
+.Xr bhyve 4 ,
+.Xr nmdm 4 ,
+.Xr vmm 4 ,
+.Xr ethers 5 ,
+.Xr bhyvectl 8 ,
+.Xr bhyveload 8
+.Sh HISTORY
+.Nm
+first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An Neel Natu Aq neel@freebsd.org
+.An Peter Grehan Aq grehan@freebsd.org
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 5359442..e8010e6 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -33,10 +33,12 @@ __FBSDID("$FreeBSD$");
#include <sys/mman.h>
#include <sys/time.h>
+#include <machine/atomic.h>
#include <machine/segments.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <err.h>
#include <libgen.h>
#include <unistd.h>
@@ -53,12 +55,14 @@ __FBSDID("$FreeBSD$");
#include "acpi.h"
#include "inout.h"
#include "dbgport.h"
+#include "ioapic.h"
#include "mem.h"
#include "mevent.h"
#include "mptbl.h"
#include "pci_emul.h"
+#include "pci_lpc.h"
+#include "smbiostbl.h"
#include "xmsr.h"
-#include "ioapic.h"
#include "spinup_ap.h"
#include "rtc.h"
@@ -69,6 +73,7 @@ __FBSDID("$FreeBSD$");
#define VMEXIT_RESTART 2 /* restart current instruction */
#define VMEXIT_ABORT 3 /* abort the vm run loop */
#define VMEXIT_RESET 4 /* guest machine has reset */
+#define VMEXIT_POWEROFF 5 /* guest machine has powered off */
#define MB (1024UL * 1024)
#define GB (1024UL * MB)
@@ -78,20 +83,22 @@ typedef int (*vmexit_handler_t)(struct vmctx *, struct vm_exit *, int *vcpu);
char *vmname;
int guest_ncpus;
+char *guest_uuid_str;
static int pincpu = -1;
-static int guest_vmexit_on_hlt, guest_vmexit_on_pause, disable_x2apic;
-
-static int foundcpus;
+static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
+static int virtio_msix = 1;
+static int x2apic_mode = 0; /* default is xAPIC */
static int strictio;
+static int strictmsr = 1;
static int acpi;
static char *progname;
static const int BSP = 0;
-static int cpumask;
+static cpuset_t cpumask;
static void vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip);
@@ -120,23 +127,25 @@ usage(int code)
{
fprintf(stderr,
- "Usage: %s [-aehAHIP][-g <gdb port>][-s <pci>][-S <pci>]"
- "[-c vcpus][-p pincpu][-m mem]"
- " <vmname>\n"
- " -a: local apic is in XAPIC mode (default is X2APIC)\n"
+ "Usage: %s [-aehwAHIPW] [-g <gdb port>] [-s <pci>]\n"
+ " %*s [-c vcpus] [-p pincpu] [-m mem] [-l <lpc>] <vm>\n"
+ " -a: local apic is in xAPIC mode (deprecated)\n"
" -A: create an ACPI table\n"
" -g: gdb port\n"
" -c: # cpus (default 1)\n"
" -p: pin vcpu 'n' to host cpu 'pincpu + n'\n"
" -H: vmexit from the guest on hlt\n"
- " -I: present an ioapic to the guest\n"
" -P: vmexit from the guest on pause\n"
- " -e: exit on unhandled i/o access\n"
+ " -W: force virtio to use single-vector MSI\n"
+ " -e: exit on unhandled I/O access\n"
" -h: help\n"
" -s: <slot,driver,configinfo> PCI slot config\n"
- " -S: <slot,driver,configinfo> legacy PCI slot config\n"
- " -m: memory size in MB\n",
- progname);
+ " -l: LPC device configuration\n"
+ " -m: memory size in MB\n"
+ " -w: ignore unimplemented MSRs\n"
+ " -x: local apic is in x2APIC mode\n"
+ " -U: uuid\n",
+ progname, (int)strlen(progname), "");
exit(code);
}
@@ -149,24 +158,24 @@ paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
}
int
-fbsdrun_disable_x2apic(void)
+fbsdrun_vmexit_on_pause(void)
{
- return (disable_x2apic);
+ return (guest_vmexit_on_pause);
}
int
-fbsdrun_vmexit_on_pause(void)
+fbsdrun_vmexit_on_hlt(void)
{
- return (guest_vmexit_on_pause);
+ return (guest_vmexit_on_hlt);
}
int
-fbsdrun_vmexit_on_hlt(void)
+fbsdrun_virtio_msix(void)
{
- return (guest_vmexit_on_hlt);
+ return (virtio_msix);
}
static void *
@@ -179,7 +188,7 @@ fbsdrun_start_thread(void *param)
mtp = param;
vcpu = mtp->mt_vcpu;
- snprintf(tname, sizeof(tname), "%s vcpu %d", vmname, vcpu);
+ snprintf(tname, sizeof(tname), "vcpu %d", vcpu);
pthread_set_name_np(mtp->mt_thr, tname);
vm_loop(mtp->mt_ctx, vcpu, vmexit[vcpu].rip);
@@ -190,35 +199,44 @@ fbsdrun_start_thread(void *param)
}
void
-fbsdrun_addcpu(struct vmctx *ctx, int vcpu, uint64_t rip)
+fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip)
{
int error;
- if (cpumask & (1 << vcpu)) {
- fprintf(stderr, "addcpu: attempting to add existing cpu %d\n",
- vcpu);
- exit(1);
- }
+ assert(fromcpu == BSP);
- cpumask |= 1 << vcpu;
- foundcpus++;
+ CPU_SET_ATOMIC(newcpu, &cpumask);
/*
* Set up the vmexit struct to allow execution to start
* at the given RIP
*/
- vmexit[vcpu].rip = rip;
- vmexit[vcpu].inst_length = 0;
+ vmexit[newcpu].rip = rip;
+ vmexit[newcpu].inst_length = 0;
- mt_vmm_info[vcpu].mt_ctx = ctx;
- mt_vmm_info[vcpu].mt_vcpu = vcpu;
+ mt_vmm_info[newcpu].mt_ctx = ctx;
+ mt_vmm_info[newcpu].mt_vcpu = newcpu;
- error = pthread_create(&mt_vmm_info[vcpu].mt_thr, NULL,
- fbsdrun_start_thread, &mt_vmm_info[vcpu]);
+ error = pthread_create(&mt_vmm_info[newcpu].mt_thr, NULL,
+ fbsdrun_start_thread, &mt_vmm_info[newcpu]);
assert(error == 0);
}
static int
+fbsdrun_deletecpu(struct vmctx *ctx, int vcpu)
+{
+
+ if (!CPU_ISSET(vcpu, &cpumask)) {
+ fprintf(stderr, "addcpu: attempting to delete unknown cpu %d\n",
+ vcpu);
+ exit(1);
+ }
+
+ CPU_CLR_ATOMIC(vcpu, &cpumask);
+ return (CPU_EMPTY(&cpumask));
+}
+
+static int
vmexit_catch_reset(void)
{
stats.io_reset++;
@@ -263,21 +281,22 @@ vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
if (vme->u.inout.string || vme->u.inout.rep)
return (VMEXIT_ABORT);
- /* Special case of guest reset */
- if (out && port == 0x64 && (uint8_t)eax == 0xFE)
- return (vmexit_catch_reset());
-
/* Extra-special case of host notifications */
if (out && port == GUEST_NIO_PORT)
return (vmexit_handle_notify(ctx, vme, pvcpu, eax));
error = emulate_inout(ctx, vcpu, in, port, bytes, &eax, strictio);
- if (error == 0 && in)
+ if (error == INOUT_OK && in)
error = vm_set_register(ctx, vcpu, VM_REG_GUEST_RAX, eax);
- if (error == 0)
+ switch (error) {
+ case INOUT_OK:
return (VMEXIT_CONTINUE);
- else {
+ case INOUT_RESET:
+ return (VMEXIT_RESET);
+ case INOUT_POWEROFF:
+ return (VMEXIT_POWEROFF);
+ default:
fprintf(stderr, "Unhandled %s%c 0x%04x\n",
in ? "in" : "out",
bytes == 1 ? 'b' : (bytes == 2 ? 'w' : 'l'), port);
@@ -288,20 +307,49 @@ vmexit_inout(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
static int
vmexit_rdmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
{
- fprintf(stderr, "vm exit rdmsr 0x%x, cpu %d\n", vme->u.msr.code,
- *pvcpu);
- return (VMEXIT_ABORT);
+ uint64_t val;
+ uint32_t eax, edx;
+ int error;
+
+ val = 0;
+ error = emulate_rdmsr(ctx, *pvcpu, vme->u.msr.code, &val);
+ if (error != 0) {
+ fprintf(stderr, "rdmsr to register %#x on vcpu %d\n",
+ vme->u.msr.code, *pvcpu);
+ if (strictmsr) {
+ error = vm_inject_exception2(ctx, *pvcpu, IDT_GP, 0);
+ assert(error == 0);
+ return (VMEXIT_RESTART);
+ }
+ }
+
+ eax = val;
+ error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RAX, eax);
+ assert(error == 0);
+
+ edx = val >> 32;
+ error = vm_set_register(ctx, *pvcpu, VM_REG_GUEST_RDX, edx);
+ assert(error == 0);
+
+ return (VMEXIT_CONTINUE);
}
static int
vmexit_wrmsr(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
{
- int newcpu;
- int retval = VMEXIT_CONTINUE;
-
- newcpu = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code,vme->u.msr.wval);
+ int error;
- return (retval);
+ error = emulate_wrmsr(ctx, *pvcpu, vme->u.msr.code, vme->u.msr.wval);
+ if (error != 0) {
+ fprintf(stderr, "wrmsr to register %#x(%#lx) on vcpu %d\n",
+ vme->u.msr.code, vme->u.msr.wval, *pvcpu);
+ if (strictmsr) {
+ error = vm_inject_exception2(ctx, *pvcpu, IDT_GP, 0);
+ assert(error == 0);
+ return (VMEXIT_RESTART);
+ }
+ }
+ return (VMEXIT_CONTINUE);
}
static int
@@ -317,6 +365,17 @@ vmexit_spinup_ap(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
}
static int
+vmexit_spindown_cpu(struct vmctx *ctx, struct vm_exit *vme, int *pvcpu)
+{
+ int lastcpu;
+
+ lastcpu = fbsdrun_deletecpu(ctx, *pvcpu);
+ if (!lastcpu)
+ pthread_exit(NULL);
+ return (vmexit_catch_reset());
+}
+
+static int
vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
{
@@ -324,10 +383,12 @@ vmexit_vmx(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
fprintf(stderr, "\treason\t\tVMX\n");
fprintf(stderr, "\trip\t\t0x%016lx\n", vmexit->rip);
fprintf(stderr, "\tinst_length\t%d\n", vmexit->inst_length);
- fprintf(stderr, "\terror\t\t%d\n", vmexit->u.vmx.error);
+ fprintf(stderr, "\tstatus\t\t%d\n", vmexit->u.vmx.status);
fprintf(stderr, "\texit_reason\t%u\n", vmexit->u.vmx.exit_reason);
fprintf(stderr, "\tqualification\t0x%016lx\n",
vmexit->u.vmx.exit_qualification);
+ fprintf(stderr, "\tinst_type\t\t%d\n", vmexit->u.vmx.inst_type);
+ fprintf(stderr, "\tinst_error\t\t%d\n", vmexit->u.vmx.inst_error);
return (VMEXIT_ABORT);
}
@@ -398,6 +459,33 @@ vmexit_inst_emul(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
return (VMEXIT_CONTINUE);
}
+static pthread_mutex_t resetcpu_mtx = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t resetcpu_cond = PTHREAD_COND_INITIALIZER;
+static int resetcpu = -1;
+
+static int
+vmexit_suspend(struct vmctx *ctx, struct vm_exit *vmexit, int *pvcpu)
+{
+
+ assert(resetcpu != -1);
+
+ fbsdrun_deletecpu(ctx, *pvcpu);
+
+ if (*pvcpu != resetcpu) {
+ pthread_mutex_lock(&resetcpu_mtx);
+ pthread_cond_signal(&resetcpu_cond);
+ pthread_mutex_unlock(&resetcpu_mtx);
+ pthread_exit(NULL);
+ }
+
+ pthread_mutex_lock(&resetcpu_mtx);
+ while (!CPU_EMPTY(&cpumask)) {
+ pthread_cond_wait(&resetcpu_cond, &resetcpu_mtx);
+ }
+ pthread_mutex_unlock(&resetcpu_mtx);
+ exit(0);
+}
+
static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
[VM_EXITCODE_INOUT] = vmexit_inout,
[VM_EXITCODE_VMX] = vmexit_vmx,
@@ -407,6 +495,8 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
[VM_EXITCODE_MTRAP] = vmexit_mtrap,
[VM_EXITCODE_INST_EMUL] = vmexit_inst_emul,
[VM_EXITCODE_SPINUP_AP] = vmexit_spinup_ap,
+ [VM_EXITCODE_SPINDOWN_CPU] = vmexit_spindown_cpu,
+ [VM_EXITCODE_SUSPENDED] = vmexit_suspend
};
static void
@@ -426,19 +516,8 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
while (1) {
error = vm_run(ctx, vcpu, rip, &vmexit[vcpu]);
- if (error != 0) {
- /*
- * It is possible that 'vmmctl' or some other process
- * has transitioned the vcpu to CANNOT_RUN state right
- * before we tried to transition it to RUNNING.
- *
- * This is expected to be temporary so just retry.
- */
- if (errno == EBUSY)
- continue;
- else
- break;
- }
+ if (error != 0)
+ break;
prevcpu = vcpu;
@@ -459,7 +538,12 @@ vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
rip = vmexit[vcpu].rip;
break;
case VMEXIT_RESET:
- exit(0);
+ if (vm_suspend(ctx) == 0) {
+ assert(resetcpu == -1);
+ resetcpu = vcpu;
+ }
+ rip = vmexit[vcpu].rip + vmexit[vcpu].inst_length;
+ break;
default:
exit(1);
}
@@ -484,10 +568,54 @@ num_vcpus_allowed(struct vmctx *ctx)
return (1);
}
+void
+fbsdrun_set_capabilities(struct vmctx *ctx, int cpu)
+{
+ int err, tmp;
+
+ if (fbsdrun_vmexit_on_hlt()) {
+ err = vm_get_capability(ctx, cpu, VM_CAP_HALT_EXIT, &tmp);
+ if (err < 0) {
+ fprintf(stderr, "VM exit on HLT not supported\n");
+ exit(1);
+ }
+ vm_set_capability(ctx, cpu, VM_CAP_HALT_EXIT, 1);
+ if (cpu == BSP)
+ handler[VM_EXITCODE_HLT] = vmexit_hlt;
+ }
+
+ if (fbsdrun_vmexit_on_pause()) {
+ /*
+ * pause exit support required for this mode
+ */
+ err = vm_get_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, &tmp);
+ if (err < 0) {
+ fprintf(stderr,
+ "SMP mux requested, no pause support\n");
+ exit(1);
+ }
+ vm_set_capability(ctx, cpu, VM_CAP_PAUSE_EXIT, 1);
+ if (cpu == BSP)
+ handler[VM_EXITCODE_PAUSE] = vmexit_pause;
+ }
+
+ if (x2apic_mode)
+ err = vm_set_x2apic_state(ctx, cpu, X2APIC_ENABLED);
+ else
+ err = vm_set_x2apic_state(ctx, cpu, X2APIC_DISABLED);
+
+ if (err) {
+ fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
+ exit(1);
+ }
+
+ vm_set_capability(ctx, cpu, VM_CAP_ENABLE_INVPCID, 1);
+}
+
int
main(int argc, char *argv[])
{
- int c, error, gdb_port, tmp, err, ioapic, bvmcons;
+ int c, error, gdb_port, err, bvmcons;
int max_vcpus;
struct vmctx *ctx;
uint64_t rip;
@@ -497,13 +625,12 @@ main(int argc, char *argv[])
progname = basename(argv[0]);
gdb_port = 0;
guest_ncpus = 1;
- ioapic = 0;
memsize = 256 * MB;
- while ((c = getopt(argc, argv, "abehAHIPp:g:c:s:S:m:")) != -1) {
+ while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) {
switch (c) {
case 'a':
- disable_x2apic = 1;
+ x2apic_mode = 0;
break;
case 'A':
acpi = 1;
@@ -520,13 +647,14 @@ main(int argc, char *argv[])
case 'g':
gdb_port = atoi(optarg);
break;
+ case 'l':
+ if (lpc_device_parse(optarg) != 0) {
+ errx(EX_USAGE, "invalid lpc device "
+ "configuration '%s'", optarg);
+ }
+ break;
case 's':
- if (pci_parse_slot(optarg, 0) != 0)
- exit(1);
- else
- break;
- case 'S':
- if (pci_parse_slot(optarg, 1) != 0)
+ if (pci_parse_slot(optarg) != 0)
exit(1);
else
break;
@@ -539,7 +667,13 @@ main(int argc, char *argv[])
guest_vmexit_on_hlt = 1;
break;
case 'I':
- ioapic = 1;
+ /*
+ * The "-I" option was used to add an ioapic to the
+ * virtual machine.
+ *
+ * An ioapic is now provided unconditionally for each
+ * virtual machine and this option is now deprecated.
+ */
break;
case 'P':
guest_vmexit_on_pause = 1;
@@ -547,6 +681,18 @@ main(int argc, char *argv[])
case 'e':
strictio = 1;
break;
+ case 'U':
+ guest_uuid_str = optarg;
+ break;
+ case 'w':
+ strictmsr = 0;
+ break;
+ case 'W':
+ virtio_msix = 0;
+ break;
+ case 'x':
+ x2apic_mode = 1;
+ break;
case 'h':
usage(0);
default:
@@ -574,39 +720,7 @@ main(int argc, char *argv[])
exit(1);
}
- if (fbsdrun_vmexit_on_hlt()) {
- err = vm_get_capability(ctx, BSP, VM_CAP_HALT_EXIT, &tmp);
- if (err < 0) {
- fprintf(stderr, "VM exit on HLT not supported\n");
- exit(1);
- }
- vm_set_capability(ctx, BSP, VM_CAP_HALT_EXIT, 1);
- handler[VM_EXITCODE_HLT] = vmexit_hlt;
- }
-
- if (fbsdrun_vmexit_on_pause()) {
- /*
- * pause exit support required for this mode
- */
- err = vm_get_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, &tmp);
- if (err < 0) {
- fprintf(stderr,
- "SMP mux requested, no pause support\n");
- exit(1);
- }
- vm_set_capability(ctx, BSP, VM_CAP_PAUSE_EXIT, 1);
- handler[VM_EXITCODE_PAUSE] = vmexit_pause;
- }
-
- if (fbsdrun_disable_x2apic())
- err = vm_set_x2apic_state(ctx, BSP, X2APIC_DISABLED);
- else
- err = vm_set_x2apic_state(ctx, BSP, X2APIC_ENABLED);
-
- if (err) {
- fprintf(stderr, "Unable to set x2apic state (%d)\n", err);
- exit(1);
- }
+ fbsdrun_set_capabilities(ctx, BSP);
err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
if (err) {
@@ -616,6 +730,7 @@ main(int argc, char *argv[])
init_mem();
init_inout();
+ ioapic_init(ctx);
rtc_init(ctx);
@@ -625,9 +740,6 @@ main(int argc, char *argv[])
if (init_pci(ctx) != 0)
exit(1);
- if (ioapic)
- ioapic_init(0);
-
if (gdb_port != 0)
init_dbgport(gdb_port);
@@ -640,17 +752,25 @@ main(int argc, char *argv[])
/*
* build the guest tables, MP etc.
*/
- mptable_build(ctx, guest_ncpus, ioapic);
+ mptable_build(ctx, guest_ncpus);
+
+ error = smbios_build(ctx);
+ assert(error == 0);
if (acpi) {
- error = acpi_build(ctx, guest_ncpus, ioapic);
+ error = acpi_build(ctx, guest_ncpus);
assert(error == 0);
}
/*
+ * Change the proc title to include the VM name.
+ */
+ setproctitle("%s", vmname);
+
+ /*
* Add CPU 0
*/
- fbsdrun_addcpu(ctx, BSP, rip);
+ fbsdrun_addcpu(ctx, BSP, BSP, rip);
/*
* Head off to the main event dispatch loop
diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h
index 28ffb3c..f18d42f 100644
--- a/usr.sbin/bhyve/bhyverun.h
+++ b/usr.sbin/bhyve/bhyverun.h
@@ -37,13 +37,16 @@
struct vmctx;
extern int guest_ncpus;
+extern char *guest_uuid_str;
extern char *vmname;
void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);
-void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip);
+void fbsdrun_set_capabilities(struct vmctx *ctx, int cpu);
+void fbsdrun_addcpu(struct vmctx *ctx, int fromcpu, int newcpu, uint64_t rip);
int fbsdrun_muxed(void);
int fbsdrun_vmexit_on_hlt(void);
int fbsdrun_vmexit_on_pause(void);
int fbsdrun_disable_x2apic(void);
+int fbsdrun_virtio_msix(void);
#endif
diff --git a/usr.sbin/bhyve/block_if.c b/usr.sbin/bhyve/block_if.c
index 9228b9a..b29bc78 100644
--- a/usr.sbin/bhyve/block_if.c
+++ b/usr.sbin/bhyve/block_if.c
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
#define BLOCKIF_SIG 0xb109b109
-#define BLOCKIF_MAXREQ 16
+#define BLOCKIF_MAXREQ 32
enum blockop {
BOP_READ,
@@ -270,13 +270,12 @@ blockif_open(const char *optstr, const char *ident)
assert(sectsz != 0);
}
- bc = malloc(sizeof(struct blockif_ctxt));
+ bc = calloc(1, sizeof(struct blockif_ctxt));
if (bc == NULL) {
close(fd);
return (NULL);
}
- memset(bc, 0, sizeof(*bc));
bc->bc_magic = BLOCKIF_SIG;
bc->bc_fd = fd;
bc->bc_size = size;
@@ -293,7 +292,7 @@ blockif_open(const char *optstr, const char *ident)
pthread_create(&bc->bc_btid, NULL, blockif_thr, bc);
- snprintf(tname, sizeof(tname), "%s blk-%s", vmname, ident);
+ snprintf(tname, sizeof(tname), "blk-%s", ident);
pthread_set_name_np(bc->bc_btid, tname);
return (bc);
diff --git a/usr.sbin/bhyve/consport.c b/usr.sbin/bhyve/consport.c
index a31038a..4074e95 100644
--- a/usr.sbin/bhyve/consport.c
+++ b/usr.sbin/bhyve/consport.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <stdbool.h>
#include "inout.h"
+#include "pci_lpc.h"
#define BVM_CONSOLE_PORT 0x220
#define BVM_CONS_SIG ('b' << 8 | 'v')
@@ -109,6 +110,15 @@ console_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
return (0);
}
+ /*
+ * Guests might probe this port to look for old ISA devices
+ * using single-byte reads. Return 0xff for those.
+ */
+ if (bytes == 1 && in) {
+ *eax = 0xff;
+ return (0);
+ }
+
if (bytes != 4)
return (-1);
@@ -125,6 +135,8 @@ console_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
return (0);
}
+SYSRES_IO(BVM_CONSOLE_PORT, 4);
+
static struct inout_port consport = {
"bvmcons",
BVM_CONSOLE_PORT,
diff --git a/usr.sbin/bhyve/dbgport.c b/usr.sbin/bhyve/dbgport.c
index 97a86ef..534ae65 100644
--- a/usr.sbin/bhyve/dbgport.c
+++ b/usr.sbin/bhyve/dbgport.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include "inout.h"
#include "dbgport.h"
+#include "pci_lpc.h"
#define BVM_DBG_PORT 0x224
#define BVM_DBG_SIG ('B' << 8 | 'V')
@@ -110,6 +111,8 @@ static struct inout_port dbgport = {
dbg_handler
};
+SYSRES_IO(BVM_DBG_PORT, 4);
+
void
init_dbgport(int sport)
{
diff --git a/usr.sbin/bhyve/inout.c b/usr.sbin/bhyve/inout.c
index 29d9f17..5fbe99b 100644
--- a/usr.sbin/bhyve/inout.c
+++ b/usr.sbin/bhyve/inout.c
@@ -84,7 +84,7 @@ register_default_iohandler(int start, int size)
iop.name = "default";
iop.port = start;
iop.size = size;
- iop.flags = IOPORT_F_INOUT;
+ iop.flags = IOPORT_F_INOUT | IOPORT_F_DEFAULT;
iop.handler = default_inout;
register_inout(&iop);
@@ -95,9 +95,10 @@ emulate_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, int strict)
{
int flags;
- uint32_t mask;
+ uint32_t mask, val;
inout_func_t handler;
void *arg;
+ int error;
assert(port < MAX_IOPORTS);
@@ -106,28 +107,36 @@ emulate_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
if (strict && handler == default_inout)
return (-1);
+ switch (bytes) {
+ case 1:
+ mask = 0xff;
+ break;
+ case 2:
+ mask = 0xffff;
+ break;
+ default:
+ mask = 0xffffffff;
+ break;
+ }
+
if (!in) {
- switch (bytes) {
- case 1:
- mask = 0xff;
- break;
- case 2:
- mask = 0xffff;
- break;
- default:
- mask = 0xffffffff;
- break;
- }
- *eax = *eax & mask;
+ val = *eax & mask;
}
flags = inout_handlers[port].flags;
arg = inout_handlers[port].arg;
if ((in && (flags & IOPORT_F_IN)) || (!in && (flags & IOPORT_F_OUT)))
- return ((*handler)(ctx, vcpu, in, port, bytes, eax, arg));
+ error = (*handler)(ctx, vcpu, in, port, bytes, &val, arg);
else
- return (-1);
+ error = -1;
+
+ if (!error && in) {
+ *eax &= ~mask;
+ *eax |= val & mask;
+ }
+
+ return (error);
}
void
@@ -159,7 +168,18 @@ register_inout(struct inout_port *iop)
int i;
VERIFY_IOPORT(iop->port, iop->size);
-
+
+ /*
+ * Verify that the new registration is not overwriting an already
+ * allocated i/o range.
+ */
+ if ((iop->flags & IOPORT_F_DEFAULT) == 0) {
+ for (i = iop->port; i < iop->port + iop->size; i++) {
+ if ((inout_handlers[i].flags & IOPORT_F_DEFAULT) == 0)
+ return (-1);
+ }
+ }
+
for (i = iop->port; i < iop->port + iop->size; i++) {
inout_handlers[i].name = iop->name;
inout_handlers[i].flags = iop->flags;
diff --git a/usr.sbin/bhyve/inout.h b/usr.sbin/bhyve/inout.h
index 4de58d1..5117d79 100644
--- a/usr.sbin/bhyve/inout.h
+++ b/usr.sbin/bhyve/inout.h
@@ -33,6 +33,12 @@
struct vmctx;
+/* Handler return values. */
+#define INOUT_ERROR -1
+#define INOUT_OK 0
+#define INOUT_RESET 1
+#define INOUT_POWEROFF 2
+
typedef int (*inout_func_t)(struct vmctx *ctx, int vcpu, int in, int port,
int bytes, uint32_t *eax, void *arg);
@@ -46,7 +52,13 @@ struct inout_port {
};
#define IOPORT_F_IN 0x1
#define IOPORT_F_OUT 0x2
-#define IOPORT_F_INOUT 0x3
+#define IOPORT_F_INOUT (IOPORT_F_IN | IOPORT_F_OUT)
+
+/*
+ * The following flags are used internally and must not be used by
+ * device models.
+ */
+#define IOPORT_F_DEFAULT 0x80000000 /* claimed by default handler */
#define INOUT_PORT(name, port, flags, handler) \
static struct inout_port __CONCAT(__inout_port, __LINE__) = { \
diff --git a/usr.sbin/bhyve/ioapic.c b/usr.sbin/bhyve/ioapic.c
index aeb008e..2950d9a 100644
--- a/usr.sbin/bhyve/ioapic.c
+++ b/usr.sbin/bhyve/ioapic.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2012 NetApp, Inc.
+ * Copyright (c) 2014 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -22,8 +23,6 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
- *
- * $FreeBSD$
*/
#include <sys/cdefs.h>
@@ -31,294 +30,45 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
-#include <x86/apicreg.h>
#include <machine/vmm.h>
-
-#include <string.h>
-#include <assert.h>
-#include <stdbool.h>
-
#include <vmmapi.h>
-#include "inout.h"
-#include "mem.h"
-#include "bhyverun.h"
-
-#include <stdio.h>
-
-#define IOAPIC_PADDR 0xFEC00000
-
-#define IOREGSEL 0x00
-#define IOWIN 0x10
-
-#define REDIR_ENTRIES 16
-#define INTR_ASSERTED(ioapic, pin) ((ioapic)->pinstate[(pin)] == true)
-
-struct ioapic {
- int inited;
- uint32_t id;
- uint64_t redtbl[REDIR_ENTRIES];
- bool pinstate[REDIR_ENTRIES];
-
- uintptr_t paddr; /* gpa where the ioapic is mapped */
- uint32_t ioregsel;
- struct memory_region *region;
-};
-
-static struct ioapic ioapics[1]; /* only a single ioapic for now */
-
-static int ioapic_region_read(struct ioapic *ioapic, uintptr_t paddr,
- int size, uint64_t *data);
-static int ioapic_region_write(struct ioapic *ioapic, uintptr_t paddr,
- int size, uint64_t data);
-static int ioapic_region_handler(struct vmctx *vm, int vcpu, int dir,
- uintptr_t paddr, int size, uint64_t *val,
- void *arg1, long arg2);
-
-static void
-ioapic_set_pinstate(struct vmctx *ctx, int pin, bool newstate)
-{
- int vector, apicid, vcpu;
- uint32_t low, high;
- struct ioapic *ioapic;
-
- ioapic = &ioapics[0]; /* assume a single ioapic */
-
- if (pin < 0 || pin >= REDIR_ENTRIES)
- return;
-
- /* Nothing to do if interrupt pin has not changed state */
- if (ioapic->pinstate[pin] == newstate)
- return;
-
- ioapic->pinstate[pin] = newstate; /* record it */
-
- /* Nothing to do if interrupt pin is deasserted */
- if (!INTR_ASSERTED(ioapic, pin))
- return;
-
- /*
- * XXX
- * We only deal with:
- * - edge triggered interrupts
- * - fixed delivery mode
- * Level-triggered sources will work so long as there is
- * no sharing.
- */
- low = ioapic->redtbl[pin];
- high = ioapic->redtbl[pin] >> 32;
- if ((low & IOART_INTMASK) == IOART_INTMCLR &&
- (low & IOART_DESTMOD) == IOART_DESTPHY &&
- (low & IOART_DELMOD) == IOART_DELFIXED) {
- vector = low & IOART_INTVEC;
- apicid = high >> APIC_ID_SHIFT;
- if (apicid != 0xff) {
- /* unicast */
- vcpu = vm_apicid2vcpu(ctx, apicid);
- vm_lapic_irq(ctx, vcpu, vector);
- } else {
- /* broadcast */
- vcpu = 0;
- while (vcpu < guest_ncpus) {
- vm_lapic_irq(ctx, vcpu, vector);
- vcpu++;
- }
- }
- }
-}
-
-void
-ioapic_deassert_pin(struct vmctx *ctx, int pin)
-{
- ioapic_set_pinstate(ctx, pin, false);
-}
+#include "ioapic.h"
-void
-ioapic_assert_pin(struct vmctx *ctx, int pin)
-{
- ioapic_set_pinstate(ctx, pin, true);
-}
+/*
+ * Assign PCI INTx interrupts to I/O APIC pins in a round-robin
+ * fashion. Note that we have no idea what the HPET is using, but the
+ * HPET is also programmable whereas this is intended for hardwired
+ * PCI interrupts.
+ *
+ * This assumes a single I/O APIC where pins >= 16 are permitted for
+ * PCI devices.
+ */
+static int pci_pins;
void
-ioapic_init(int which)
-{
- struct mem_range memp;
- struct ioapic *ioapic;
- int error;
- int i;
-
- assert(which == 0);
-
- ioapic = &ioapics[which];
- assert(ioapic->inited == 0);
-
- bzero(ioapic, sizeof(struct ioapic));
-
- /* Initialize all redirection entries to mask all interrupts */
- for (i = 0; i < REDIR_ENTRIES; i++)
- ioapic->redtbl[i] = 0x0001000000010000UL;
-
- ioapic->paddr = IOAPIC_PADDR;
-
- /* Register emulated memory region */
- memp.name = "ioapic";
- memp.flags = MEM_F_RW;
- memp.handler = ioapic_region_handler;
- memp.arg1 = ioapic;
- memp.arg2 = which;
- memp.base = ioapic->paddr;
- memp.size = sizeof(struct IOAPIC);
- error = register_mem(&memp);
-
- assert (error == 0);
-
- ioapic->inited = 1;
-}
-
-static uint32_t
-ioapic_read(struct ioapic *ioapic, uint32_t addr)
-{
- int regnum, pin, rshift;
-
- assert(ioapic->inited);
-
- regnum = addr & 0xff;
- switch (regnum) {
- case IOAPIC_ID:
- return (ioapic->id);
- break;
- case IOAPIC_VER:
- return ((REDIR_ENTRIES << MAXREDIRSHIFT) | 0x11);
- break;
- case IOAPIC_ARB:
- return (ioapic->id);
- break;
- default:
- break;
- }
-
- /* redirection table entries */
- if (regnum >= IOAPIC_REDTBL &&
- regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
- pin = (regnum - IOAPIC_REDTBL) / 2;
- if ((regnum - IOAPIC_REDTBL) % 2)
- rshift = 32;
- else
- rshift = 0;
-
- return (ioapic->redtbl[pin] >> rshift);
- }
-
- return (0);
-}
-
-static void
-ioapic_write(struct ioapic *ioapic, uint32_t addr, uint32_t data)
-{
- int regnum, pin, lshift;
-
- assert(ioapic->inited);
-
- regnum = addr & 0xff;
- switch (regnum) {
- case IOAPIC_ID:
- ioapic->id = data & APIC_ID_MASK;
- break;
- case IOAPIC_VER:
- case IOAPIC_ARB:
- /* readonly */
- break;
- default:
- break;
- }
-
- /* redirection table entries */
- if (regnum >= IOAPIC_REDTBL &&
- regnum < IOAPIC_REDTBL + REDIR_ENTRIES * 2) {
- pin = (regnum - IOAPIC_REDTBL) / 2;
- if ((regnum - IOAPIC_REDTBL) % 2)
- lshift = 32;
- else
- lshift = 0;
-
- ioapic->redtbl[pin] &= ~((uint64_t)0xffffffff << lshift);
- ioapic->redtbl[pin] |= ((uint64_t)data << lshift);
- }
-}
-
-static int
-ioapic_region_read(struct ioapic *ioapic, uintptr_t paddr, int size,
- uint64_t *data)
+ioapic_init(struct vmctx *ctx)
{
- int offset;
- offset = paddr - ioapic->paddr;
-
- /*
- * The IOAPIC specification allows 32-bit wide accesses to the
- * IOREGSEL (offset 0) and IOWIN (offset 16) registers.
- */
- if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
-#if 1
- printf("invalid access to ioapic%d: size %d, offset %d\n",
- (int)(ioapic - ioapics), size, offset);
-#endif
- *data = 0;
- return (0);
+ if (vm_ioapic_pincount(ctx, &pci_pins) < 0) {
+ pci_pins = 0;
+ return;
}
- if (offset == IOREGSEL)
- *data = ioapic->ioregsel;
- else
- *data = ioapic_read(ioapic, ioapic->ioregsel);
-
- return (0);
-}
-
-static int
-ioapic_region_write(struct ioapic *ioapic, uintptr_t paddr, int size,
- uint64_t data)
-{
- int offset;
-
- offset = paddr - ioapic->paddr;
-
- /*
- * The ioapic specification allows 32-bit wide accesses to the
- * IOREGSEL (offset 0) and IOWIN (offset 16) registers.
- */
- if (size != 4 || (offset != IOREGSEL && offset != IOWIN)) {
-#if 1
- printf("invalid access to ioapic%d: size %d, offset %d\n",
- (int)(ioapic - ioapics), size, offset);
-#endif
- return (0);
+ /* Ignore the first 16 pins. */
+ if (pci_pins <= 16) {
+ pci_pins = 0;
+ return;
}
-
- if (offset == IOREGSEL)
- ioapic->ioregsel = data;
- else
- ioapic_write(ioapic, ioapic->ioregsel, data);
-
- return (0);
+ pci_pins -= 16;
}
-static int
-ioapic_region_handler(struct vmctx *vm, int vcpu, int dir, uintptr_t paddr,
- int size, uint64_t *val, void *arg1, long arg2)
+int
+ioapic_pci_alloc_irq(void)
{
- struct ioapic *ioapic;
- int which;
-
- ioapic = arg1;
- which = arg2;
-
- assert(ioapic == &ioapics[which]);
-
- if (dir == MEM_F_READ)
- ioapic_region_read(ioapic, paddr, size, val);
- else
- ioapic_region_write(ioapic, paddr, size, *val);
+ static int last_pin;
- return (0);
+ if (pci_pins == 0)
+ return (-1);
+ return (16 + (last_pin++ % pci_pins));
}
diff --git a/usr.sbin/bhyve/ioapic.h b/usr.sbin/bhyve/ioapic.h
index 4696f9a..3cfca4f 100644
--- a/usr.sbin/bhyve/ioapic.h
+++ b/usr.sbin/bhyve/ioapic.h
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2012 NetApp, Inc.
+ * Copyright (c) 2014 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +12,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -29,10 +30,10 @@
#ifndef _IOAPIC_H_
#define _IOAPIC_H_
-struct vmctx;
-
-void ioapic_init(int num);
-void ioapic_deassert_pin(struct vmctx *ctx, int pin);
-void ioapic_assert_pin(struct vmctx *ctx, int pin);
+/*
+ * Allocate a PCI IRQ from the I/O APIC.
+ */
+void ioapic_init(struct vmctx *ctx);
+int ioapic_pci_alloc_irq(void);
#endif
diff --git a/usr.sbin/bhyve/mevent.c b/usr.sbin/bhyve/mevent.c
index eff0610..b83ec69 100644
--- a/usr.sbin/bhyve/mevent.c
+++ b/usr.sbin/bhyve/mevent.c
@@ -135,6 +135,9 @@ mevent_kq_filter(struct mevent *mevp)
if (mevp->me_type == EVF_TIMER)
retval = EVFILT_TIMER;
+ if (mevp->me_type == EVF_SIGNAL)
+ retval = EVFILT_SIGNAL;
+
return (retval);
}
@@ -265,12 +268,11 @@ mevent_add(int tfd, enum ev_type type,
/*
* Allocate an entry, populate it, and add it to the change list.
*/
- mevp = malloc(sizeof(struct mevent));
+ mevp = calloc(1, sizeof(struct mevent));
if (mevp == NULL) {
goto exit;
}
- memset(mevp, 0, sizeof(struct mevent));
if (type == EVF_TIMER) {
mevp->me_msecs = tfd;
mevp->me_timid = mevent_timid++;
@@ -381,10 +383,8 @@ mevent_delete_close(struct mevent *evp)
static void
mevent_set_name(void)
{
- char tname[MAXCOMLEN + 1];
- snprintf(tname, sizeof(tname), "%s mevent", vmname);
- pthread_set_name_np(mevent_tid, tname);
+ pthread_set_name_np(mevent_tid, "mevent");
}
void
@@ -439,7 +439,7 @@ mevent_dispatch(void)
* Block awaiting events
*/
ret = kevent(mfd, NULL, 0, eventlist, MEVENT_MAX, NULL);
- if (ret == -1) {
+ if (ret == -1 && errno != EINTR) {
perror("Error return from kevent monitor");
}
diff --git a/usr.sbin/bhyve/mevent.h b/usr.sbin/bhyve/mevent.h
index 6c0f656..d6a59c6 100644
--- a/usr.sbin/bhyve/mevent.h
+++ b/usr.sbin/bhyve/mevent.h
@@ -32,7 +32,8 @@
enum ev_type {
EVF_READ,
EVF_WRITE,
- EVF_TIMER
+ EVF_TIMER,
+ EVF_SIGNAL
};
struct mevent;
diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c
index 74db2ea..e895835 100644
--- a/usr.sbin/bhyve/mptbl.c
+++ b/usr.sbin/bhyve/mptbl.c
@@ -36,8 +36,10 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
+#include "acpi.h"
#include "bhyverun.h"
#include "mptbl.h"
+#include "pci_emul.h"
#define MPTABLE_BASE 0xF0000
@@ -71,18 +73,8 @@ __FBSDID("$FreeBSD$");
#define MPEP_FEATURES (0xBFEBFBFF) /* XXX Intel i7 */
-/* Define processor entry struct since <x86/mptable.h> gets it wrong */
-typedef struct BPROCENTRY {
- u_char type;
- u_char apic_id;
- u_char apic_version;
- u_char cpu_flags;
- uint32_t cpu_signature;
- uint32_t feature_flags;
- uint32_t reserved1;
- uint32_t reserved2;
-} *bproc_entry_ptr;
-CTASSERT(sizeof(struct BPROCENTRY) == 20);
+/* Number of local intr entries */
+#define MPEII_NUM_LOCAL_IRQ 2
/* Bus entry defines */
#define MPE_NUM_BUSES 2
@@ -131,7 +123,7 @@ mpt_build_mpch(mpcth_t mpch)
}
static void
-mpt_build_proc_entries(bproc_entry_ptr mpep, int ncpu)
+mpt_build_proc_entries(proc_entry_ptr mpep, int ncpu)
{
int i;
@@ -150,19 +142,43 @@ mpt_build_proc_entries(bproc_entry_ptr mpep, int ncpu)
}
static void
+mpt_build_localint_entries(int_entry_ptr mpie)
+{
+
+ /* Hardcode LINT0 as ExtINT on all CPUs. */
+ memset(mpie, 0, sizeof(*mpie));
+ mpie->type = MPCT_ENTRY_LOCAL_INT;
+ mpie->int_type = INTENTRY_TYPE_EXTINT;
+ mpie->int_flags = INTENTRY_FLAGS_POLARITY_CONFORM |
+ INTENTRY_FLAGS_TRIGGER_CONFORM;
+ mpie->dst_apic_id = 0xff;
+ mpie->dst_apic_int = 0;
+ mpie++;
+
+ /* Hardcode LINT1 as NMI on all CPUs. */
+ memset(mpie, 0, sizeof(*mpie));
+ mpie->type = MPCT_ENTRY_LOCAL_INT;
+ mpie->int_type = INTENTRY_TYPE_NMI;
+ mpie->int_flags = INTENTRY_FLAGS_POLARITY_CONFORM |
+ INTENTRY_FLAGS_TRIGGER_CONFORM;
+ mpie->dst_apic_id = 0xff;
+ mpie->dst_apic_int = 1;
+}
+
+static void
mpt_build_bus_entries(bus_entry_ptr mpeb)
{
memset(mpeb, 0, sizeof(*mpeb));
mpeb->type = MPCT_ENTRY_BUS;
- mpeb->bus_id = ISA;
- memcpy(mpeb->bus_type, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN);
+ mpeb->bus_id = 0;
+ memcpy(mpeb->bus_type, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN);
mpeb++;
memset(mpeb, 0, sizeof(*mpeb));
mpeb->type = MPCT_ENTRY_BUS;
- mpeb->bus_id = PCI;
- memcpy(mpeb->bus_type, MPE_BUSNAME_PCI, MPE_BUSNAME_LEN);
+ mpeb->bus_id = 1;
+ memcpy(mpeb->bus_type, MPE_BUSNAME_ISA, MPE_BUSNAME_LEN);
}
static void
@@ -177,11 +193,49 @@ mpt_build_ioapic_entries(io_apic_entry_ptr mpei, int id)
mpei->apic_address = IOAPIC_PADDR;
}
-#ifdef notyet
+static int
+mpt_count_ioint_entries(void)
+{
+ int bus, count;
+
+ count = 0;
+ for (bus = 0; bus <= PCI_BUSMAX; bus++)
+ count += pci_count_lintr(bus);
+
+ /*
+ * Always include entries for the first 16 pins along with a entry
+ * for each active PCI INTx pin.
+ */
+ return (16 + count);
+}
+
+static void
+mpt_generate_pci_int(int bus, int slot, int pin, int ioapic_irq, void *arg)
+{
+ int_entry_ptr *mpiep, mpie;
+
+ mpiep = arg;
+ mpie = *mpiep;
+ memset(mpie, 0, sizeof(*mpie));
+
+ /*
+ * This is always after another I/O interrupt entry, so cheat
+ * and fetch the I/O APIC ID from the prior entry.
+ */
+ mpie->type = MPCT_ENTRY_INT;
+ mpie->int_type = INTENTRY_TYPE_INT;
+ mpie->src_bus_id = bus;
+ mpie->src_bus_irq = slot << 2 | (pin - 1);
+ mpie->dst_apic_id = mpie[-1].dst_apic_id;
+ mpie->dst_apic_int = ioapic_irq;
+
+ *mpiep = mpie + 1;
+}
+
static void
-mpt_build_ioint_entries(struct mpe_ioint *mpeii, int num_pins, int id)
+mpt_build_ioint_entries(int_entry_ptr mpie, int id)
{
- int pin;
+ int pin, bus;
/*
* The following config is taken from kernel mptable.c
@@ -189,147 +243,49 @@ mpt_build_ioint_entries(struct mpe_ioint *mpeii, int num_pins, int id)
* just use the default config, tweek later if needed.
*/
-
- /* Run through all 16 pins. */
- for (pin = 0; pin < num_pins; pin++) {
- memset(mpeii, 0, sizeof(*mpeii));
- mpeii->entry_type = MP_ENTRY_IOINT;
- mpeii->src_bus_id = MPE_BUSID_ISA;
- mpeii->dst_apic_id = id;
+ /* First, generate the first 16 pins. */
+ for (pin = 0; pin < 16; pin++) {
+ memset(mpie, 0, sizeof(*mpie));
+ mpie->type = MPCT_ENTRY_INT;
+ mpie->src_bus_id = 1;
+ mpie->dst_apic_id = id;
/*
* All default configs route IRQs from bus 0 to the first 16
* pins of the first I/O APIC with an APIC ID of 2.
*/
- mpeii->dst_apic_intin = pin;
+ mpie->dst_apic_int = pin;
switch (pin) {
case 0:
/* Pin 0 is an ExtINT pin. */
- mpeii->intr_type = MPEII_INTR_EXTINT;
+ mpie->int_type = INTENTRY_TYPE_EXTINT;
break;
case 2:
/* IRQ 0 is routed to pin 2. */
- mpeii->intr_type = MPEII_INTR_INT;
- mpeii->src_bus_irq = 0;
+ mpie->int_type = INTENTRY_TYPE_INT;
+ mpie->src_bus_irq = 0;
+ break;
+ case SCI_INT:
+ /* ACPI SCI is level triggered and active-lo. */
+ mpie->int_flags = INTENTRY_FLAGS_POLARITY_ACTIVELO |
+ INTENTRY_FLAGS_TRIGGER_LEVEL;
+ mpie->int_type = INTENTRY_TYPE_INT;
+ mpie->src_bus_irq = SCI_INT;
break;
- case 5:
- case 10:
- case 11:
- /*
- * PCI Irqs set to level triggered.
- */
- mpeii->intr_flags = MPEII_FLAGS_TRIGMODE_LEVEL;
- mpeii->src_bus_id = MPE_BUSID_PCI;
default:
/* All other pins are identity mapped. */
- mpeii->intr_type = MPEII_INTR_INT;
- mpeii->src_bus_irq = pin;
+ mpie->int_type = INTENTRY_TYPE_INT;
+ mpie->src_bus_irq = pin;
break;
}
- mpeii++;
+ mpie++;
}
+ /* Next, generate entries for any PCI INTx interrupts. */
+ for (bus = 0; bus <= PCI_BUSMAX; bus++)
+ pci_walk_lintr(bus, mpt_generate_pci_int, &mpie);
}
-#define COPYSTR(dest, src, bytes) \
- memcpy(dest, src, bytes); \
- str[bytes] = 0;
-
-static void
-mptable_dump(struct mp_floating_pointer *mpfp, struct mp_config_hdr *mpch)
-{
- static char str[16];
- int i;
- char *cur;
-
- union mpe {
- struct mpe_proc *proc;
- struct mpe_bus *bus;
- struct mpe_ioapic *ioapic;
- struct mpe_ioint *ioint;
- struct mpe_lint *lnit;
- char *p;
- };
-
- union mpe mpe;
-
- printf(" MP Floating Pointer :\n");
- COPYSTR(str, mpfp->signature, 4);
- printf("\tsignature:\t%s\n", str);
- printf("\tmpch paddr:\t%x\n", mpfp->mptable_paddr);
- printf("\tlength:\t%x\n", mpfp->length);
- printf("\tspecrec:\t%x\n", mpfp->specrev);
- printf("\tchecksum:\t%x\n", mpfp->checksum);
- printf("\tfeature1:\t%x\n", mpfp->feature1);
- printf("\tfeature2:\t%x\n", mpfp->feature2);
- printf("\tfeature3:\t%x\n", mpfp->feature3);
- printf("\tfeature4:\t%x\n", mpfp->feature4);
-
- printf(" MP Configuration Header :\n");
- COPYSTR(str, mpch->signature, 4);
- printf(" signature: %s\n", str);
- printf(" length: %x\n", mpch->length);
- printf(" specrec: %x\n", mpch->specrev);
- printf(" checksum: %x\n", mpch->checksum);
- COPYSTR(str, mpch->oemid, MPCH_OEMID_LEN);
- printf(" oemid: %s\n", str);
- COPYSTR(str, mpch->prodid, MPCH_PRODID_LEN);
- printf(" prodid: %s\n", str);
- printf(" oem_ptr: %x\n", mpch->oem_ptr);
- printf(" oem_sz: %x\n", mpch->oem_sz);
- printf(" nr_entries: %x\n", mpch->nr_entries);
- printf(" apic paddr: %x\n", mpch->lapic_paddr);
- printf(" ext_length: %x\n", mpch->ext_length);
- printf(" ext_checksum: %x\n", mpch->ext_checksum);
-
- cur = (char *)mpch + sizeof(*mpch);
- for (i = 0; i < mpch->nr_entries; i++) {
- mpe.p = cur;
- switch(*mpe.p) {
- case MP_ENTRY_PROC:
- printf(" MP Processor Entry :\n");
- printf(" lapic_id: %x\n", mpe.proc->lapic_id);
- printf(" lapic_version: %x\n", mpe.proc->lapic_version);
- printf(" proc_flags: %x\n", mpe.proc->proc_flags);
- printf(" proc_signature: %x\n", mpe.proc->proc_signature);
- printf(" feature_flags: %x\n", mpe.proc->feature_flags);
- cur += sizeof(struct mpe_proc);
- break;
- case MP_ENTRY_BUS:
- printf(" MP Bus Entry :\n");
- printf(" busid: %x\n", mpe.bus->busid);
- COPYSTR(str, mpe.bus->busname, MPE_BUSNAME_LEN);
- printf(" busname: %s\n", str);
- cur += sizeof(struct mpe_bus);
- break;
- case MP_ENTRY_IOAPIC:
- printf(" MP IOAPIC Entry :\n");
- printf(" ioapi_id: %x\n", mpe.ioapic->ioapic_id);
- printf(" ioapi_version: %x\n", mpe.ioapic->ioapic_version);
- printf(" ioapi_flags: %x\n", mpe.ioapic->ioapic_flags);
- printf(" ioapi_paddr: %x\n", mpe.ioapic->ioapic_paddr);
- cur += sizeof(struct mpe_ioapic);
- break;
- case MP_ENTRY_IOINT:
- printf(" MP IO Interrupt Entry :\n");
- printf(" intr_type: %x\n", mpe.ioint->intr_type);
- printf(" intr_flags: %x\n", mpe.ioint->intr_flags);
- printf(" src_bus_id: %x\n", mpe.ioint->src_bus_id);
- printf(" src_bus_irq: %x\n", mpe.ioint->src_bus_irq);
- printf(" dst_apic_id: %x\n", mpe.ioint->dst_apic_id);
- printf(" dst_apic_intin: %x\n", mpe.ioint->dst_apic_intin);
- cur += sizeof(struct mpe_ioint);
- break;
- case MP_ENTRY_LINT:
- printf(" MP Local Interrupt Entry :\n");
- cur += sizeof(struct mpe_lint);
- break;
- }
-
- }
-}
-#endif
-
void
mptable_add_oemtbl(void *tbl, int tblsz)
{
@@ -339,13 +295,15 @@ mptable_add_oemtbl(void *tbl, int tblsz)
}
int
-mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
+mptable_build(struct vmctx *ctx, int ncpu)
{
mpcth_t mpch;
bus_entry_ptr mpeb;
io_apic_entry_ptr mpei;
- bproc_entry_ptr mpep;
+ proc_entry_ptr mpep;
mpfps_t mpfp;
+ int_entry_ptr mpie;
+ int ioints;
char *curraddr;
char *startaddr;
@@ -364,7 +322,7 @@ mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
mpt_build_mpch(mpch);
curraddr += sizeof(*mpch);
- mpep = (bproc_entry_ptr)curraddr;
+ mpep = (proc_entry_ptr)curraddr;
mpt_build_proc_entries(mpep, ncpu);
curraddr += sizeof(*mpep) * ncpu;
mpch->entry_count += ncpu;
@@ -374,19 +332,21 @@ mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
curraddr += sizeof(*mpeb) * MPE_NUM_BUSES;
mpch->entry_count += MPE_NUM_BUSES;
- if (ioapic) {
- mpei = (io_apic_entry_ptr)curraddr;
- mpt_build_ioapic_entries(mpei, ncpu + 1);
- curraddr += sizeof(*mpei);
- mpch->entry_count++;
- }
-
-#ifdef notyet
- mpt_build_ioint_entries((struct mpe_ioint*)curraddr, MPEII_MAX_IRQ,
- ncpu + 1);
- curraddr += sizeof(struct mpe_ioint) * MPEII_MAX_IRQ;
- mpch->entry_count += MPEII_MAX_IRQ;
-#endif
+ mpei = (io_apic_entry_ptr)curraddr;
+ mpt_build_ioapic_entries(mpei, 0);
+ curraddr += sizeof(*mpei);
+ mpch->entry_count++;
+
+ mpie = (int_entry_ptr) curraddr;
+ ioints = mpt_count_ioint_entries();
+ mpt_build_ioint_entries(mpie, 0);
+ curraddr += sizeof(*mpie) * ioints;
+ mpch->entry_count += ioints;
+
+ mpie = (int_entry_ptr)curraddr;
+ mpt_build_localint_entries(mpie);
+ curraddr += sizeof(*mpie) * MPEII_NUM_LOCAL_IRQ;
+ mpch->entry_count += MPEII_NUM_LOCAL_IRQ;
if (oem_tbl_start) {
mpch->oem_table_pointer = curraddr - startaddr + MPTABLE_BASE;
diff --git a/usr.sbin/bhyve/mptbl.h b/usr.sbin/bhyve/mptbl.h
index 3c4c527..e9e1c42 100644
--- a/usr.sbin/bhyve/mptbl.h
+++ b/usr.sbin/bhyve/mptbl.h
@@ -29,7 +29,7 @@
#ifndef _MPTBL_H_
#define _MPTBL_H_
-int mptable_build(struct vmctx *ctx, int ncpu, int ioapic);
+int mptable_build(struct vmctx *ctx, int ncpu);
void mptable_add_oemtbl(void *tbl, int tblsz);
#endif /* _MPTBL_H_ */
diff --git a/usr.sbin/bhyve/pci_ahci.c b/usr.sbin/bhyve/pci_ahci.c
index f69f127..3f9fc7f 100644
--- a/usr.sbin/bhyve/pci_ahci.c
+++ b/usr.sbin/bhyve/pci_ahci.c
@@ -95,6 +95,13 @@ enum sata_fis_type {
#define MODEPAGE_CD_CAPABILITIES 0x2A
/*
+ * ATA commands
+ */
+#define ATA_SF_ENAB_SATA_SF 0x10
+#define ATA_SATA_SF_AN 0x05
+#define ATA_SF_DIS_SATA_SF 0x90
+
+/*
* Debug printf
*/
#ifdef AHCI_DEBUG
@@ -127,6 +134,7 @@ struct ahci_port {
uint8_t xfermode;
uint8_t sense_key;
uint8_t asc;
+ uint32_t pending;
uint32_t clb;
uint32_t clbu;
@@ -165,6 +173,7 @@ struct ahci_cmd_hdr {
struct ahci_prdt_entry {
uint64_t dba;
uint32_t reserved;
+#define DBCMASK 0x3fffff
uint32_t dbc;
};
@@ -253,6 +262,16 @@ ahci_write_fis(struct ahci_port *p, enum sata_fis_type ft, uint8_t *fis)
}
static void
+ahci_write_fis_piosetup(struct ahci_port *p)
+{
+ uint8_t fis[20];
+
+ memset(fis, 0, sizeof(fis));
+ fis[0] = FIS_TYPE_PIOSETUP;
+ ahci_write_fis(p, FIS_TYPE_PIOSETUP, fis);
+}
+
+static void
ahci_write_fis_sdb(struct ahci_port *p, int slot, uint32_t tfd)
{
uint8_t fis[8];
@@ -453,6 +472,10 @@ ahci_handle_dma(struct ahci_port *p, int slot, uint8_t *cfis, uint32_t done,
if (iovcnt > BLOCKIF_IOV_MAX) {
aior->prdtl = iovcnt - BLOCKIF_IOV_MAX;
iovcnt = BLOCKIF_IOV_MAX;
+ /*
+ * Mark this command in-flight.
+ */
+ p->pending |= 1 << slot;
} else
aior->prdtl = 0;
breq->br_iovcnt = iovcnt;
@@ -461,10 +484,13 @@ ahci_handle_dma(struct ahci_port *p, int slot, uint8_t *cfis, uint32_t done,
* Build up the iovec based on the prdt
*/
for (i = 0; i < iovcnt; i++) {
+ uint32_t dbcsz;
+
+ dbcsz = (prdt->dbc & DBCMASK) + 1;
breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc),
- prdt->dba, prdt->dbc + 1);
- breq->br_iov[i].iov_len = prdt->dbc + 1;
- aior->done += (prdt->dbc + 1);
+ prdt->dba, dbcsz);
+ breq->br_iov[i].iov_len = dbcsz;
+ aior->done += dbcsz;
prdt++;
}
if (readop)
@@ -473,7 +499,7 @@ ahci_handle_dma(struct ahci_port *p, int slot, uint8_t *cfis, uint32_t done,
err = blockif_write(p->bctx, breq);
assert(err == 0);
- if (!aior->prdtl && ncq)
+ if (ncq)
p->ci &= ~(1 << slot);
}
@@ -493,6 +519,8 @@ ahci_handle_flush(struct ahci_port *p, int slot, uint8_t *cfis)
aior->cfis = cfis;
aior->slot = slot;
aior->len = 0;
+ aior->done = 0;
+ aior->prdtl = 0;
breq = &aior->io_req;
err = blockif_flush(p->bctx, breq);
@@ -513,11 +541,16 @@ write_prdt(struct ahci_port *p, int slot, uint8_t *cfis,
from = buf;
prdt = (struct ahci_prdt_entry *)(cfis + 0x80);
for (i = 0; i < hdr->prdtl && len; i++) {
- uint8_t *ptr = paddr_guest2host(ahci_ctx(p->pr_sc),
- prdt->dba, prdt->dbc + 1);
- memcpy(ptr, from, prdt->dbc + 1);
- len -= (prdt->dbc + 1);
- from += (prdt->dbc + 1);
+ uint8_t *ptr;
+ uint32_t dbcsz;
+ int sublen;
+
+ dbcsz = (prdt->dbc & DBCMASK) + 1;
+ ptr = paddr_guest2host(ahci_ctx(p->pr_sc), prdt->dba, dbcsz);
+ sublen = len < dbcsz ? len : dbcsz;
+ memcpy(ptr, from, sublen);
+ len -= sublen;
+ from += sublen;
prdt++;
}
hdr->prdbc = size - len;
@@ -578,6 +611,7 @@ handle_identify(struct ahci_port *p, int slot, uint8_t *cfis)
buf[101] = (sectors >> 16);
buf[102] = (sectors >> 32);
buf[103] = (sectors >> 48);
+ ahci_write_fis_piosetup(p);
write_prdt(p, slot, cfis, (void *)buf, sizeof(buf));
p->tfd = ATA_S_DSC | ATA_S_READY;
p->is |= AHCI_P_IX_DP;
@@ -620,6 +654,7 @@ handle_atapi_identify(struct ahci_port *p, int slot, uint8_t *cfis)
buf[85] = (1 << 4);
buf[87] = (1 << 14);
buf[88] = (1 << 14 | 0x7f);
+ ahci_write_fis_piosetup(p);
write_prdt(p, slot, cfis, (void *)buf, sizeof(buf));
p->tfd = ATA_S_DSC | ATA_S_READY;
p->is |= AHCI_P_IX_DHR;
@@ -663,8 +698,7 @@ atapi_read_capacity(struct ahci_port *p, int slot, uint8_t *cfis)
uint8_t buf[8];
uint64_t sectors;
- sectors = blockif_size(p->bctx) / blockif_sectsz(p->bctx);
- sectors >>= 2;
+ sectors = blockif_size(p->bctx) / 2048;
be32enc(buf, sectors - 1);
be32enc(buf + 4, 2048);
cfis[4] = (cfis[4] & ~7) | ATA_I_CMD | ATA_I_IN;
@@ -908,11 +942,14 @@ atapi_read(struct ahci_port *p, int slot, uint8_t *cfis,
/*
* Build up the iovec based on the prdt
*/
- for (i = 0; i < hdr->prdtl; i++) {
+ for (i = 0; i < iovcnt; i++) {
+ uint32_t dbcsz;
+
+ dbcsz = (prdt->dbc & DBCMASK) + 1;
breq->br_iov[i].iov_base = paddr_guest2host(ahci_ctx(sc),
- prdt->dba, prdt->dbc + 1);
- breq->br_iov[i].iov_len = prdt->dbc + 1;
- aior->done += (prdt->dbc + 1);
+ prdt->dba, dbcsz);
+ breq->br_iov[i].iov_len = dbcsz;
+ aior->done += dbcsz;
prdt++;
}
err = blockif_read(p->bctx, breq);
@@ -1146,6 +1183,17 @@ ahci_handle_cmd(struct ahci_port *p, int slot, uint8_t *cfis)
case ATA_SETFEATURES:
{
switch (cfis[3]) {
+ case ATA_SF_ENAB_SATA_SF:
+ switch (cfis[12]) {
+ case ATA_SATA_SF_AN:
+ p->tfd = ATA_S_DSC | ATA_S_READY;
+ break;
+ default:
+ p->tfd = ATA_S_ERROR | ATA_S_READY;
+ p->tfd |= (ATA_ERROR_ABORT << 8);
+ break;
+ }
+ break;
case ATA_SF_ENAB_WCACHE:
case ATA_SF_DIS_WCACHE:
case ATA_SF_ENAB_RCACHE:
@@ -1171,9 +1219,7 @@ ahci_handle_cmd(struct ahci_port *p, int slot, uint8_t *cfis)
p->tfd |= (ATA_ERROR_ABORT << 8);
break;
}
- p->is |= AHCI_P_IX_DP;
- p->ci &= ~(1 << slot);
- ahci_generate_intr(p->pr_sc);
+ ahci_write_fis_d2h(p, slot, cfis, p->tfd);
break;
}
case ATA_SET_MULTI:
@@ -1288,8 +1334,12 @@ ahci_handle_port(struct ahci_port *p)
if (!(p->cmd & AHCI_P_CMD_ST))
return;
+ /*
+ * Search for any new commands to issue ignoring those that
+ * are already in-flight.
+ */
for (i = 0; (i < 32) && p->ci; i++) {
- if (p->ci & (1 << i))
+ if ((p->ci & (1 << i)) && !(p->pending & (1 << i)))
ahci_handle_slot(p, i);
}
}
@@ -1350,6 +1400,11 @@ ata_ioreq_cb(struct blockif_req *br, int err)
p->serr |= (1 << slot);
}
+ /*
+ * This command is now complete.
+ */
+ p->pending &= ~(1 << slot);
+
if (ncq) {
p->sact &= ~(1 << slot);
ahci_write_fis_sdb(p, slot, tfd);
@@ -1543,7 +1598,7 @@ pci_ahci_host_write(struct pci_ahci_softc *sc, uint64_t offset, uint64_t value)
case AHCI_PI:
case AHCI_VS:
case AHCI_CAP2:
- WPRINTF("pci_ahci_host: read only registers 0x%"PRIx64"\n", offset);
+ DPRINTF("pci_ahci_host: read only registers 0x%"PRIx64"\n", offset);
break;
case AHCI_GHC:
if (value & AHCI_GHC_HR)
@@ -1701,8 +1756,7 @@ pci_ahci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts, int atapi)
dbg = fopen("/tmp/log", "w+");
#endif
- sc = malloc(sizeof(struct pci_ahci_softc));
- memset(sc, 0, sizeof(struct pci_ahci_softc));
+ sc = calloc(1, sizeof(struct pci_ahci_softc));
pi->pi_arg = sc;
sc->asc_pi = pi;
sc->ports = MAX_PORTS;
@@ -1715,11 +1769,9 @@ pci_ahci_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts, int atapi)
/*
* Attempt to open the backing image. Use the PCI
- * slot/func/ahci_port for the identifier string
- * since that uniquely identifies a storage device.
+ * slot/func for the identifier string.
*/
- snprintf(bident, sizeof(bident), "%d:%d:%d", pi->pi_slot, pi->pi_func,
- 0);
+ snprintf(bident, sizeof(bident), "%d:%d", pi->pi_slot, pi->pi_func);
bctxt = blockif_open(opts, bident);
if (bctxt == NULL) {
ret = 1;
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index fe21cee..15f2fad 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <sys/errno.h>
#include <ctype.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -44,11 +45,13 @@ __FBSDID("$FreeBSD$");
#include <machine/vmm.h>
#include <vmmapi.h>
+#include "acpi.h"
#include "bhyverun.h"
#include "inout.h"
+#include "ioapic.h"
#include "mem.h"
#include "pci_emul.h"
-#include "ioapic.h"
+#include "pci_lpc.h"
#define CONF1_ADDR_PORT 0x0cf8
#define CONF1_DATA_PORT 0x0cfc
@@ -66,26 +69,34 @@ do { \
} \
} while (0)
+#define MAXBUSES (PCI_BUSMAX + 1)
#define MAXSLOTS (PCI_SLOTMAX + 1)
#define MAXFUNCS (PCI_FUNCMAX + 1)
-static struct slotinfo {
- char *si_name;
- char *si_param;
- struct pci_devinst *si_devi;
- int si_legacy;
-} pci_slotinfo[MAXSLOTS][MAXFUNCS];
+struct funcinfo {
+ char *fi_name;
+ char *fi_param;
+ struct pci_devinst *fi_devi;
+};
-/*
- * Used to keep track of legacy interrupt owners/requestors
- */
-#define NLIRQ 16
+struct intxinfo {
+ int ii_count;
+ int ii_ioapic_irq;
+};
+
+struct slotinfo {
+ struct intxinfo si_intpins[4];
+ struct funcinfo si_funcs[MAXFUNCS];
+};
+
+struct businfo {
+ uint16_t iobase, iolimit; /* I/O window */
+ uint32_t membase32, memlimit32; /* mmio window below 4GB */
+ uint64_t membase64, memlimit64; /* mmio window above 4GB */
+ struct slotinfo slotinfo[MAXSLOTS];
+};
-static struct lirqinfo {
- int li_generic;
- int li_acount;
- struct pci_devinst *li_owner; /* XXX should be a list */
-} lirq[NLIRQ];
+static struct businfo *pci_businfo[MAXBUSES];
SET_DECLARE(pci_devemu_set, struct pci_devemu);
@@ -96,14 +107,15 @@ static uint64_t pci_emul_membase64;
#define PCI_EMUL_IOBASE 0x2000
#define PCI_EMUL_IOLIMIT 0x10000
-#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */
+#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */
#define PCI_EMUL_MEMBASE64 0xD000000000UL
#define PCI_EMUL_MEMLIMIT64 0xFD00000000UL
static struct pci_devemu *pci_emul_finddev(char *name);
+static void pci_lintr_update(struct pci_devinst *pi);
-static int pci_emul_devices;
+static struct mem_range pci_mem_hole;
/*
* I/O access
@@ -112,6 +124,7 @@ static int pci_emul_devices;
/*
* Slot options are in the form:
*
+ * <bus>:<slot>:<func>,<emul>[,<config>]
* <slot>[:<func>],<emul>[,<config>]
*
* slot is 0..31
@@ -131,39 +144,55 @@ pci_parse_slot_usage(char *aopt)
}
int
-pci_parse_slot(char *opt, int legacy)
+pci_parse_slot(char *opt)
{
- char *slot, *func, *emul, *config;
- char *str, *cpy;
- int error, snum, fnum;
+ struct businfo *bi;
+ struct slotinfo *si;
+ char *emul, *config, *str, *cp;
+ int error, bnum, snum, fnum;
error = -1;
- str = cpy = strdup(opt);
-
- slot = strsep(&str, ",");
- func = NULL;
- if (strchr(slot, ':') != NULL) {
- func = cpy;
- (void) strsep(&func, ":");
- }
-
- emul = strsep(&str, ",");
- config = str;
-
- if (emul == NULL) {
+ str = strdup(opt);
+
+ emul = config = NULL;
+ if ((cp = strchr(str, ',')) != NULL) {
+ *cp = '\0';
+ emul = cp + 1;
+ if ((cp = strchr(emul, ',')) != NULL) {
+ *cp = '\0';
+ config = cp + 1;
+ }
+ } else {
pci_parse_slot_usage(opt);
goto done;
}
- snum = atoi(slot);
- fnum = func ? atoi(func) : 0;
+ /* <bus>:<slot>:<func> */
+ if (sscanf(str, "%d:%d:%d", &bnum, &snum, &fnum) != 3) {
+ bnum = 0;
+ /* <slot>:<func> */
+ if (sscanf(str, "%d:%d", &snum, &fnum) != 2) {
+ fnum = 0;
+ /* <slot> */
+ if (sscanf(str, "%d", &snum) != 1) {
+ snum = -1;
+ }
+ }
+ }
- if (snum < 0 || snum >= MAXSLOTS || fnum < 0 || fnum >= MAXFUNCS) {
+ if (bnum < 0 || bnum >= MAXBUSES || snum < 0 || snum >= MAXSLOTS ||
+ fnum < 0 || fnum >= MAXFUNCS) {
pci_parse_slot_usage(opt);
goto done;
}
- if (pci_slotinfo[snum][fnum].si_name != NULL) {
+ if (pci_businfo[bnum] == NULL)
+ pci_businfo[bnum] = calloc(1, sizeof(struct businfo));
+
+ bi = pci_businfo[bnum];
+ si = &bi->slotinfo[snum];
+
+ if (si->si_funcs[fnum].fi_name != NULL) {
fprintf(stderr, "pci slot %d:%d already occupied!\n",
snum, fnum);
goto done;
@@ -176,13 +205,12 @@ pci_parse_slot(char *opt, int legacy)
}
error = 0;
- pci_slotinfo[snum][fnum].si_name = emul;
- pci_slotinfo[snum][fnum].si_param = config;
- pci_slotinfo[snum][fnum].si_legacy = legacy;
+ si->si_funcs[fnum].fi_name = emul;
+ si->si_funcs[fnum].fi_param = config;
done:
if (error)
- free(cpy);
+ free(str);
return (error);
}
@@ -529,13 +557,7 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
addr = mask = lobits = 0;
break;
case PCIBAR_IO:
- if (hostbase &&
- pci_slotinfo[pdi->pi_slot][pdi->pi_func].si_legacy) {
- assert(hostbase < PCI_EMUL_IOBASE);
- baseptr = &hostbase;
- } else {
- baseptr = &pci_emul_iobase;
- }
+ baseptr = &pci_emul_iobase;
limit = PCI_EMUL_IOLIMIT;
mask = PCIM_BAR_IO_BASE;
lobits = PCIM_BAR_IO_SPACE;
@@ -608,48 +630,39 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
static int
pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen)
{
- int i, capoff, capid, reallen;
+ int i, capoff, reallen;
uint16_t sts;
- static u_char endofcap[4] = {
- PCIY_RESERVED, 0, 0, 0
- };
-
- assert(caplen > 0 && capdata[0] != PCIY_RESERVED);
+ assert(caplen > 0);
reallen = roundup2(caplen, 4); /* dword aligned */
sts = pci_get_cfgdata16(pi, PCIR_STATUS);
- if ((sts & PCIM_STATUS_CAPPRESENT) == 0) {
+ if ((sts & PCIM_STATUS_CAPPRESENT) == 0)
capoff = CAP_START_OFFSET;
- pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff);
- pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT);
- } else {
- capoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR);
- while (1) {
- assert((capoff & 0x3) == 0);
- capid = pci_get_cfgdata8(pi, capoff);
- if (capid == PCIY_RESERVED)
- break;
- capoff = pci_get_cfgdata8(pi, capoff + 1);
- }
- }
+ else
+ capoff = pi->pi_capend + 1;
/* Check if we have enough space */
- if (capoff + reallen + sizeof(endofcap) > PCI_REGMAX + 1)
+ if (capoff + reallen > PCI_REGMAX + 1)
return (-1);
+ /* Set the previous capability pointer */
+ if ((sts & PCIM_STATUS_CAPPRESENT) == 0) {
+ pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff);
+ pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT);
+ } else
+ pci_set_cfgdata8(pi, pi->pi_prevcap + 1, capoff);
+
/* Copy the capability */
for (i = 0; i < caplen; i++)
pci_set_cfgdata8(pi, capoff + i, capdata[i]);
/* Set the next capability pointer */
- pci_set_cfgdata8(pi, capoff + 1, capoff + reallen);
-
- /* Copy of the reserved capability which serves as the end marker */
- for (i = 0; i < sizeof(endofcap); i++)
- pci_set_cfgdata8(pi, capoff + reallen + i, endofcap[i]);
+ pci_set_cfgdata8(pi, capoff + 1, 0);
+ pi->pi_prevcap = capoff;
+ pi->pi_capend = capoff + reallen - 1;
return (0);
}
@@ -669,19 +682,22 @@ pci_emul_finddev(char *name)
}
static int
-pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
- char *params)
+pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int bus, int slot,
+ int func, struct funcinfo *fi)
{
struct pci_devinst *pdi;
int err;
- pdi = malloc(sizeof(struct pci_devinst));
- bzero(pdi, sizeof(*pdi));
+ pdi = calloc(1, sizeof(struct pci_devinst));
pdi->pi_vmctx = ctx;
- pdi->pi_bus = 0;
+ pdi->pi_bus = bus;
pdi->pi_slot = slot;
pdi->pi_func = func;
+ pthread_mutex_init(&pdi->pi_lintr.lock, NULL);
+ pdi->pi_lintr.pin = 0;
+ pdi->pi_lintr.state = IDLE;
+ pdi->pi_lintr.ioapic_irq = 0;
pdi->pi_d = pde;
snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot);
@@ -692,13 +708,11 @@ pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, int func,
pci_set_cfgdata8(pdi, PCIR_COMMAND,
PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
- err = (*pde->pe_init)(ctx, pdi, params);
- if (err != 0) {
+ err = (*pde->pe_init)(ctx, pdi, fi->fi_param);
+ if (err == 0)
+ fi->fi_devi = pdi;
+ else
free(pdi);
- } else {
- pci_emul_devices++;
- pci_slotinfo[slot][func].si_devi = pdi;
- }
return (err);
}
@@ -732,7 +746,7 @@ pci_emul_add_msicap(struct pci_devinst *pi, int msgnum)
static void
pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum,
- uint32_t msix_tab_size, int nextptr)
+ uint32_t msix_tab_size)
{
CTASSERT(sizeof(struct msixcap) == 12);
@@ -740,7 +754,6 @@ pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum,
bzero(msixcap, sizeof(struct msixcap));
msixcap->capid = PCIY_MSIX;
- msixcap->nextptr = nextptr;
/*
* Message Control Register, all fields set to
@@ -767,8 +780,7 @@ pci_msix_table_init(struct pci_devinst *pi, int table_entries)
assert(table_entries <= MAX_MSIX_TABLE_ENTRIES);
table_size = table_entries * MSIX_TABLE_ENTRY_SIZE;
- pi->pi_msix.table = malloc(table_size);
- bzero(pi->pi_msix.table, table_size);
+ pi->pi_msix.table = calloc(1, table_size);
/* set mask bit of vector control register */
for (i = 0; i < table_entries; i++)
@@ -778,7 +790,6 @@ pci_msix_table_init(struct pci_devinst *pi, int table_entries)
int
pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum)
{
- uint16_t pba_index;
uint32_t tab_size;
struct msixcap msixcap;
@@ -795,14 +806,11 @@ pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum)
pi->pi_msix.table_offset = 0;
pi->pi_msix.table_count = msgnum;
pi->pi_msix.pba_offset = tab_size;
-
- /* calculate the MMIO size required for MSI-X PBA */
- pba_index = (msgnum - 1) / (PBA_TABLE_ENTRY_SIZE * 8);
- pi->pi_msix.pba_size = (pba_index + 1) * PBA_TABLE_ENTRY_SIZE;
+ pi->pi_msix.pba_size = PBA_SIZE(msgnum);
pci_msix_table_init(pi, msgnum);
- pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size, 0);
+ pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size);
/* allocate memory for MSI-X Table and PBA */
pci_emul_alloc_bar(pi, barnum, PCIBAR_MEM32,
@@ -831,6 +839,7 @@ msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE;
pi->pi_msix.function_mask = val & PCIM_MSIXCTRL_FUNCTION_MASK;
+ pci_lintr_update(pi);
}
CFGWRITE(pi, offset, val, bytes);
@@ -860,20 +869,16 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
else
msgdata = pci_get_cfgdata16(pi, capoff + 8);
- /*
- * XXX check delivery mode, destination mode etc
- */
mme = msgctrl & PCIM_MSICTRL_MME_MASK;
pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0;
if (pi->pi_msi.enabled) {
- pi->pi_msi.cpu = (addrlo >> 12) & 0xff;
- pi->pi_msi.vector = msgdata & 0xff;
- pi->pi_msi.msgnum = 1 << (mme >> 4);
+ pi->pi_msi.addr = addrlo;
+ pi->pi_msi.msg_data = msgdata;
+ pi->pi_msi.maxmsgnum = 1 << (mme >> 4);
} else {
- pi->pi_msi.cpu = 0;
- pi->pi_msi.vector = 0;
- pi->pi_msi.msgnum = 0;
+ pi->pi_msi.maxmsgnum = 0;
}
+ pci_lintr_update(pi);
}
CFGWRITE(pi, offset, val, bytes);
@@ -928,11 +933,9 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val)
/* Find the capability that we want to update */
capoff = CAP_START_OFFSET;
while (1) {
- capid = pci_get_cfgdata8(pi, capoff);
- if (capid == PCIY_RESERVED)
- break;
-
nextoff = pci_get_cfgdata8(pi, capoff + 1);
+ if (nextoff == 0)
+ break;
if (offset >= capoff && offset < nextoff)
break;
@@ -955,6 +958,7 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val)
return;
}
+ capid = pci_get_cfgdata8(pi, capoff);
switch (capid) {
case PCIY_MSI:
msicap_cfgwrite(pi, capoff, offset, bytes, val);
@@ -973,25 +977,14 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val)
static int
pci_emul_iscap(struct pci_devinst *pi, int offset)
{
- int found;
uint16_t sts;
- uint8_t capid, lastoff;
- found = 0;
sts = pci_get_cfgdata16(pi, PCIR_STATUS);
if ((sts & PCIM_STATUS_CAPPRESENT) != 0) {
- lastoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR);
- while (1) {
- assert((lastoff & 0x3) == 0);
- capid = pci_get_cfgdata8(pi, lastoff);
- if (capid == PCIY_RESERVED)
- break;
- lastoff = pci_get_cfgdata8(pi, lastoff + 1);
- }
- if (offset >= CAP_START_OFFSET && offset <= lastoff)
- found = 1;
+ if (offset >= CAP_START_OFFSET && offset <= pi->pi_capend)
+ return (1);
}
- return (found);
+ return (0);
}
static int
@@ -1009,42 +1002,68 @@ pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
return (0);
}
+#define BUSIO_ROUNDUP 32
+#define BUSMEM_ROUNDUP (1024 * 1024)
+
int
init_pci(struct vmctx *ctx)
{
- struct mem_range memp;
struct pci_devemu *pde;
+ struct businfo *bi;
struct slotinfo *si;
+ struct funcinfo *fi;
size_t lowmem;
- int slot, func;
+ int bus, slot, func;
int error;
pci_emul_iobase = PCI_EMUL_IOBASE;
pci_emul_membase32 = vm_get_lowmem_limit(ctx);
pci_emul_membase64 = PCI_EMUL_MEMBASE64;
- /*
- * Allow ISA IRQs 5,10,11,12, and 15 to be available for
- * generic use
- */
- lirq[5].li_generic = 1;
- lirq[10].li_generic = 1;
- lirq[11].li_generic = 1;
- lirq[12].li_generic = 1;
- lirq[15].li_generic = 1;
-
- for (slot = 0; slot < MAXSLOTS; slot++) {
- for (func = 0; func < MAXFUNCS; func++) {
- si = &pci_slotinfo[slot][func];
- if (si->si_name != NULL) {
- pde = pci_emul_finddev(si->si_name);
+ for (bus = 0; bus < MAXBUSES; bus++) {
+ if ((bi = pci_businfo[bus]) == NULL)
+ continue;
+ /*
+ * Keep track of the i/o and memory resources allocated to
+ * this bus.
+ */
+ bi->iobase = pci_emul_iobase;
+ bi->membase32 = pci_emul_membase32;
+ bi->membase64 = pci_emul_membase64;
+
+ for (slot = 0; slot < MAXSLOTS; slot++) {
+ si = &bi->slotinfo[slot];
+ for (func = 0; func < MAXFUNCS; func++) {
+ fi = &si->si_funcs[func];
+ if (fi->fi_name == NULL)
+ continue;
+ pde = pci_emul_finddev(fi->fi_name);
assert(pde != NULL);
- error = pci_emul_init(ctx, pde, slot, func,
- si->si_param);
+ error = pci_emul_init(ctx, pde, bus, slot,
+ func, fi);
if (error)
return (error);
}
}
+
+ /*
+ * Add some slop to the I/O and memory resources decoded by
+ * this bus to give a guest some flexibility if it wants to
+ * reprogram the BARs.
+ */
+ pci_emul_iobase += BUSIO_ROUNDUP;
+ pci_emul_iobase = roundup2(pci_emul_iobase, BUSIO_ROUNDUP);
+ bi->iolimit = pci_emul_iobase;
+
+ pci_emul_membase32 += BUSMEM_ROUNDUP;
+ pci_emul_membase32 = roundup2(pci_emul_membase32,
+ BUSMEM_ROUNDUP);
+ bi->memlimit32 = pci_emul_membase32;
+
+ pci_emul_membase64 += BUSMEM_ROUNDUP;
+ pci_emul_membase64 = roundup2(pci_emul_membase64,
+ BUSMEM_ROUNDUP);
+ bi->memlimit64 = pci_emul_membase64;
}
/*
@@ -1060,19 +1079,187 @@ init_pci(struct vmctx *ctx)
error = vm_get_memory_seg(ctx, 0, &lowmem, NULL);
assert(error == 0);
- memset(&memp, 0, sizeof(struct mem_range));
- memp.name = "PCI hole";
- memp.flags = MEM_F_RW;
- memp.base = lowmem;
- memp.size = (4ULL * 1024 * 1024 * 1024) - lowmem;
- memp.handler = pci_emul_fallback_handler;
+ memset(&pci_mem_hole, 0, sizeof(struct mem_range));
+ pci_mem_hole.name = "PCI hole";
+ pci_mem_hole.flags = MEM_F_RW;
+ pci_mem_hole.base = lowmem;
+ pci_mem_hole.size = (4ULL * 1024 * 1024 * 1024) - lowmem;
+ pci_mem_hole.handler = pci_emul_fallback_handler;
- error = register_mem_fallback(&memp);
+ error = register_mem_fallback(&pci_mem_hole);
assert(error == 0);
return (0);
}
+static void
+pci_prt_entry(int bus, int slot, int pin, int ioapic_irq, void *arg)
+{
+ int *count;
+
+ count = arg;
+ dsdt_line(" Package (0x04)");
+ dsdt_line(" {");
+ dsdt_line(" 0x%X,", slot << 16 | 0xffff);
+ dsdt_line(" 0x%02X,", pin - 1);
+ dsdt_line(" Zero,");
+ dsdt_line(" 0x%X", ioapic_irq);
+ dsdt_line(" }%s", *count == 1 ? "" : ",");
+ (*count)--;
+}
+
+/*
+ * A bhyve virtual machine has a flat PCI hierarchy with a root port
+ * corresponding to each PCI bus.
+ */
+static void
+pci_bus_write_dsdt(int bus)
+{
+ struct businfo *bi;
+ struct slotinfo *si;
+ struct pci_devinst *pi;
+ int count, slot, func;
+
+ /*
+ * If there are no devices on this 'bus' then just return.
+ */
+ if ((bi = pci_businfo[bus]) == NULL) {
+ /*
+ * Bus 0 is special because it decodes the I/O ports used
+ * for PCI config space access even if there are no devices
+ * on it.
+ */
+ if (bus != 0)
+ return;
+ }
+
+ dsdt_indent(1);
+ dsdt_line("Scope (_SB)");
+ dsdt_line("{");
+ dsdt_line(" Device (PC%02X)", bus);
+ dsdt_line(" {");
+ dsdt_line(" Name (_HID, EisaId (\"PNP0A03\"))");
+ dsdt_line(" Name (_ADR, Zero)");
+
+ dsdt_line(" Method (_BBN, 0, NotSerialized)");
+ dsdt_line(" {");
+ dsdt_line(" Return (0x%08X)", bus);
+ dsdt_line(" }");
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+ dsdt_line(" WordBusNumber (ResourceProducer, MinFixed, "
+ "MaxFixed, PosDecode,");
+ dsdt_line(" 0x0000, // Granularity");
+ dsdt_line(" 0x%04X, // Range Minimum", bus);
+ dsdt_line(" 0x%04X, // Range Maximum", bus);
+ dsdt_line(" 0x0000, // Translation Offset");
+ dsdt_line(" 0x0001, // Length");
+ dsdt_line(" ,, )");
+
+ if (bus == 0) {
+ dsdt_indent(3);
+ dsdt_fixed_ioport(0xCF8, 8);
+ dsdt_unindent(3);
+
+ dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, "
+ "PosDecode, EntireRange,");
+ dsdt_line(" 0x0000, // Granularity");
+ dsdt_line(" 0x0000, // Range Minimum");
+ dsdt_line(" 0x0CF7, // Range Maximum");
+ dsdt_line(" 0x0000, // Translation Offset");
+ dsdt_line(" 0x0CF8, // Length");
+ dsdt_line(" ,, , TypeStatic)");
+
+ dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, "
+ "PosDecode, EntireRange,");
+ dsdt_line(" 0x0000, // Granularity");
+ dsdt_line(" 0x0D00, // Range Minimum");
+ dsdt_line(" 0x%04X, // Range Maximum",
+ PCI_EMUL_IOBASE - 1);
+ dsdt_line(" 0x0000, // Translation Offset");
+ dsdt_line(" 0x%04X, // Length",
+ PCI_EMUL_IOBASE - 0x0D00);
+ dsdt_line(" ,, , TypeStatic)");
+
+ if (bi == NULL) {
+ dsdt_line(" })");
+ goto done;
+ }
+ }
+ assert(bi != NULL);
+
+ /* i/o window */
+ dsdt_line(" WordIO (ResourceProducer, MinFixed, MaxFixed, "
+ "PosDecode, EntireRange,");
+ dsdt_line(" 0x0000, // Granularity");
+ dsdt_line(" 0x%04X, // Range Minimum", bi->iobase);
+ dsdt_line(" 0x%04X, // Range Maximum",
+ bi->iolimit - 1);
+ dsdt_line(" 0x0000, // Translation Offset");
+ dsdt_line(" 0x%04X, // Length",
+ bi->iolimit - bi->iobase);
+ dsdt_line(" ,, , TypeStatic)");
+
+ /* mmio window (32-bit) */
+ dsdt_line(" DWordMemory (ResourceProducer, PosDecode, "
+ "MinFixed, MaxFixed, NonCacheable, ReadWrite,");
+ dsdt_line(" 0x00000000, // Granularity");
+ dsdt_line(" 0x%08X, // Range Minimum\n", bi->membase32);
+ dsdt_line(" 0x%08X, // Range Maximum\n",
+ bi->memlimit32 - 1);
+ dsdt_line(" 0x00000000, // Translation Offset");
+ dsdt_line(" 0x%08X, // Length\n",
+ bi->memlimit32 - bi->membase32);
+ dsdt_line(" ,, , AddressRangeMemory, TypeStatic)");
+
+ /* mmio window (64-bit) */
+ dsdt_line(" QWordMemory (ResourceProducer, PosDecode, "
+ "MinFixed, MaxFixed, NonCacheable, ReadWrite,");
+ dsdt_line(" 0x0000000000000000, // Granularity");
+ dsdt_line(" 0x%016lX, // Range Minimum\n", bi->membase64);
+ dsdt_line(" 0x%016lX, // Range Maximum\n",
+ bi->memlimit64 - 1);
+ dsdt_line(" 0x0000000000000000, // Translation Offset");
+ dsdt_line(" 0x%016lX, // Length\n",
+ bi->memlimit64 - bi->membase64);
+ dsdt_line(" ,, , AddressRangeMemory, TypeStatic)");
+ dsdt_line(" })");
+
+ count = pci_count_lintr(bus);
+ if (count != 0) {
+ dsdt_indent(2);
+ dsdt_line("Name (_PRT, Package (0x%02X)", count);
+ dsdt_line("{");
+ pci_walk_lintr(bus, pci_prt_entry, &count);
+ dsdt_line("})");
+ dsdt_unindent(2);
+ }
+
+ dsdt_indent(2);
+ for (slot = 0; slot < MAXSLOTS; slot++) {
+ si = &bi->slotinfo[slot];
+ for (func = 0; func < MAXFUNCS; func++) {
+ pi = si->si_funcs[func].fi_devi;
+ if (pi != NULL && pi->pi_d->pe_write_dsdt != NULL)
+ pi->pi_d->pe_write_dsdt(pi);
+ }
+ }
+ dsdt_unindent(2);
+done:
+ dsdt_line(" }");
+ dsdt_line("}");
+ dsdt_unindent(1);
+}
+
+void
+pci_write_dsdt(void)
+{
+ int bus;
+
+ for (bus = 0; bus < MAXBUSES; bus++)
+ pci_bus_write_dsdt(bus);
+}
+
int
pci_msi_enabled(struct pci_devinst *pi)
{
@@ -1080,10 +1267,10 @@ pci_msi_enabled(struct pci_devinst *pi)
}
int
-pci_msi_msgnum(struct pci_devinst *pi)
+pci_msi_maxmsgnum(struct pci_devinst *pi)
{
if (pi->pi_msi.enabled)
- return (pi->pi_msi.msgnum);
+ return (pi->pi_msi.maxmsgnum);
else
return (0);
}
@@ -1112,81 +1299,161 @@ pci_generate_msix(struct pci_devinst *pi, int index)
mte = &pi->pi_msix.table[index];
if ((mte->vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {
/* XXX Set PBA bit if interrupt is disabled */
- vm_lapic_irq(pi->pi_vmctx,
- (mte->addr >> 12) & 0xff, mte->msg_data & 0xff);
+ vm_lapic_msi(pi->pi_vmctx, mte->addr, mte->msg_data);
}
}
void
-pci_generate_msi(struct pci_devinst *pi, int msg)
+pci_generate_msi(struct pci_devinst *pi, int index)
{
- if (pci_msi_enabled(pi) && msg < pci_msi_msgnum(pi)) {
- vm_lapic_irq(pi->pi_vmctx,
- pi->pi_msi.cpu,
- pi->pi_msi.vector + msg);
+ if (pci_msi_enabled(pi) && index < pci_msi_maxmsgnum(pi)) {
+ vm_lapic_msi(pi->pi_vmctx, pi->pi_msi.addr,
+ pi->pi_msi.msg_data + index);
}
}
-int
-pci_is_legacy(struct pci_devinst *pi)
+static bool
+pci_lintr_permitted(struct pci_devinst *pi)
{
+ uint16_t cmd;
- return (pci_slotinfo[pi->pi_slot][pi->pi_func].si_legacy);
+ cmd = pci_get_cfgdata16(pi, PCIR_COMMAND);
+ return (!(pi->pi_msi.enabled || pi->pi_msix.enabled ||
+ (cmd & PCIM_CMD_INTxDIS)));
}
-static int
-pci_lintr_alloc(struct pci_devinst *pi, int vec)
+int
+pci_lintr_request(struct pci_devinst *pi)
{
- int i;
+ struct businfo *bi;
+ struct slotinfo *si;
+ int bestpin, bestcount, irq, pin;
- assert(vec < NLIRQ);
+ bi = pci_businfo[pi->pi_bus];
+ assert(bi != NULL);
- if (vec == -1) {
- for (i = 0; i < NLIRQ; i++) {
- if (lirq[i].li_generic &&
- lirq[i].li_owner == NULL) {
- vec = i;
- break;
- }
- }
- } else {
- if (lirq[vec].li_owner != NULL) {
- vec = -1;
+ /*
+ * First, allocate a pin from our slot.
+ */
+ si = &bi->slotinfo[pi->pi_slot];
+ bestpin = 0;
+ bestcount = si->si_intpins[0].ii_count;
+ for (pin = 1; pin < 4; pin++) {
+ if (si->si_intpins[pin].ii_count < bestcount) {
+ bestpin = pin;
+ bestcount = si->si_intpins[pin].ii_count;
}
}
- assert(vec != -1);
- lirq[vec].li_owner = pi;
- pi->pi_lintr_pin = vec;
+ /*
+ * Attempt to allocate an I/O APIC pin for this intpin. If
+ * 8259A support is added we will need a separate field to
+ * assign the intpin to an input pin on the PCI interrupt
+ * router.
+ */
+ if (si->si_intpins[bestpin].ii_count == 0) {
+ irq = ioapic_pci_alloc_irq();
+ if (irq < 0)
+ return (-1);
+ si->si_intpins[bestpin].ii_ioapic_irq = irq;
+ } else
+ irq = si->si_intpins[bestpin].ii_ioapic_irq;
+ si->si_intpins[bestpin].ii_count++;
- return (vec);
+ pi->pi_lintr.pin = bestpin + 1;
+ pi->pi_lintr.ioapic_irq = irq;
+ pci_set_cfgdata8(pi, PCIR_INTLINE, irq);
+ pci_set_cfgdata8(pi, PCIR_INTPIN, bestpin + 1);
+ return (0);
}
-int
-pci_lintr_request(struct pci_devinst *pi, int vec)
+void
+pci_lintr_assert(struct pci_devinst *pi)
{
- vec = pci_lintr_alloc(pi, vec);
- pci_set_cfgdata8(pi, PCIR_INTLINE, vec);
- pci_set_cfgdata8(pi, PCIR_INTPIN, 1);
- return (0);
+ assert(pi->pi_lintr.pin > 0);
+
+ pthread_mutex_lock(&pi->pi_lintr.lock);
+ if (pi->pi_lintr.state == IDLE) {
+ if (pci_lintr_permitted(pi)) {
+ pi->pi_lintr.state = ASSERTED;
+ vm_ioapic_assert_irq(pi->pi_vmctx,
+ pi->pi_lintr.ioapic_irq);
+ } else
+ pi->pi_lintr.state = PENDING;
+ }
+ pthread_mutex_unlock(&pi->pi_lintr.lock);
}
void
-pci_lintr_assert(struct pci_devinst *pi)
+pci_lintr_deassert(struct pci_devinst *pi)
{
- assert(pi->pi_lintr_pin);
- ioapic_assert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
+ assert(pi->pi_lintr.pin > 0);
+
+ pthread_mutex_lock(&pi->pi_lintr.lock);
+ if (pi->pi_lintr.state == ASSERTED) {
+ pi->pi_lintr.state = IDLE;
+ vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq);
+ } else if (pi->pi_lintr.state == PENDING)
+ pi->pi_lintr.state = IDLE;
+ pthread_mutex_unlock(&pi->pi_lintr.lock);
+}
+
+static void
+pci_lintr_update(struct pci_devinst *pi)
+{
+
+ pthread_mutex_lock(&pi->pi_lintr.lock);
+ if (pi->pi_lintr.state == ASSERTED && !pci_lintr_permitted(pi)) {
+ vm_ioapic_deassert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq);
+ pi->pi_lintr.state = PENDING;
+ } else if (pi->pi_lintr.state == PENDING && pci_lintr_permitted(pi)) {
+ pi->pi_lintr.state = ASSERTED;
+ vm_ioapic_assert_irq(pi->pi_vmctx, pi->pi_lintr.ioapic_irq);
+ }
+ pthread_mutex_unlock(&pi->pi_lintr.lock);
+}
+
+int
+pci_count_lintr(int bus)
+{
+ int count, slot, pin;
+ struct slotinfo *slotinfo;
+
+ count = 0;
+ if (pci_businfo[bus] != NULL) {
+ for (slot = 0; slot < MAXSLOTS; slot++) {
+ slotinfo = &pci_businfo[bus]->slotinfo[slot];
+ for (pin = 0; pin < 4; pin++) {
+ if (slotinfo->si_intpins[pin].ii_count != 0)
+ count++;
+ }
+ }
+ }
+ return (count);
}
void
-pci_lintr_deassert(struct pci_devinst *pi)
+pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg)
{
+ struct businfo *bi;
+ struct slotinfo *si;
+ struct intxinfo *ii;
+ int slot, pin;
- assert(pi->pi_lintr_pin);
- ioapic_deassert_pin(pi->pi_vmctx, pi->pi_lintr_pin);
+ if ((bi = pci_businfo[bus]) == NULL)
+ return;
+
+ for (slot = 0; slot < MAXSLOTS; slot++) {
+ si = &bi->slotinfo[slot];
+ for (pin = 0; pin < 4; pin++) {
+ ii = &si->si_intpins[pin];
+ if (ii->ii_count != 0)
+ cb(bus, slot, pin + 1, ii->ii_ioapic_irq, arg);
+ }
+ }
}
/*
@@ -1194,14 +1461,19 @@ pci_lintr_deassert(struct pci_devinst *pi)
* Return 0 otherwise.
*/
static int
-pci_emul_is_mfdev(int slot)
+pci_emul_is_mfdev(int bus, int slot)
{
+ struct businfo *bi;
+ struct slotinfo *si;
int f, numfuncs;
numfuncs = 0;
- for (f = 0; f < MAXFUNCS; f++) {
- if (pci_slotinfo[slot][f].si_devi != NULL) {
- numfuncs++;
+ if ((bi = pci_businfo[bus]) != NULL) {
+ si = &bi->slotinfo[slot];
+ for (f = 0; f < MAXFUNCS; f++) {
+ if (si->si_funcs[f].fi_devi != NULL) {
+ numfuncs++;
+ }
}
}
return (numfuncs > 1);
@@ -1212,12 +1484,12 @@ pci_emul_is_mfdev(int slot)
* whether or not is a multi-function being emulated in the pci 'slot'.
*/
static void
-pci_emul_hdrtype_fixup(int slot, int off, int bytes, uint32_t *rv)
+pci_emul_hdrtype_fixup(int bus, int slot, int off, int bytes, uint32_t *rv)
{
int mfdev;
if (off <= PCIR_HDRTYPE && off + bytes > PCIR_HDRTYPE) {
- mfdev = pci_emul_is_mfdev(slot);
+ mfdev = pci_emul_is_mfdev(bus, slot);
switch (bytes) {
case 1:
case 2:
@@ -1236,7 +1508,7 @@ pci_emul_hdrtype_fixup(int slot, int off, int bytes, uint32_t *rv)
}
}
-static int cfgbus, cfgslot, cfgfunc, cfgoff;
+static int cfgenable, cfgbus, cfgslot, cfgfunc, cfgoff;
static int
pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
@@ -1255,9 +1527,12 @@ pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
(cfgslot << 11) |
(cfgfunc << 8) |
cfgoff;
- *eax = x | CONF1_ENABLE;
+ if (cfgenable)
+ x |= CONF1_ENABLE;
+ *eax = x;
} else {
x = *eax;
+ cfgenable = (x & CONF1_ENABLE) == CONF1_ENABLE;
cfgoff = x & PCI_REGMAX;
cfgfunc = (x >> 8) & PCI_FUNCMAX;
cfgslot = (x >> 11) & PCI_SLOTMAX;
@@ -1294,7 +1569,7 @@ pci_emul_cmdwrite(struct pci_devinst *pi, uint32_t new, int bytes)
* If the MMIO or I/O address space decoding has changed then
* register/unregister all BARs that decode that address space.
*/
- for (i = 0; i < PCI_BARMAX; i++) {
+ for (i = 0; i <= PCI_BARMAX; i++) {
switch (pi->pi_bar[i].type) {
case PCIBAR_NONE:
case PCIBAR_MEMHI64:
@@ -1322,22 +1597,31 @@ pci_emul_cmdwrite(struct pci_devinst *pi, uint32_t new, int bytes)
assert(0);
}
}
+
+ /*
+ * If INTx has been unmasked and is pending, assert the
+ * interrupt.
+ */
+ pci_lintr_update(pi);
}
static int
pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, void *arg)
{
+ struct businfo *bi;
+ struct slotinfo *si;
struct pci_devinst *pi;
struct pci_devemu *pe;
int coff, idx, needcfg;
uint64_t addr, bar, mask;
assert(bytes == 1 || bytes == 2 || bytes == 4);
-
- if (cfgbus == 0)
- pi = pci_slotinfo[cfgslot][cfgfunc].si_devi;
- else
+
+ if ((bi = pci_businfo[cfgbus]) != NULL) {
+ si = &bi->slotinfo[cfgslot];
+ pi = si->si_funcs[cfgfunc].fi_devi;
+ } else
pi = NULL;
coff = cfgoff + (port - CONF1_DATA_PORT);
@@ -1348,10 +1632,11 @@ pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
#endif
/*
- * Just return if there is no device at this cfgslot:cfgfunc or
- * if the guest is doing an un-aligned access
+ * Just return if there is no device at this cfgslot:cfgfunc,
+ * if the guest is doing an un-aligned access, or if the config
+ * address word isn't enabled.
*/
- if (pi == NULL || (coff & (bytes - 1)) != 0) {
+ if (!cfgenable || pi == NULL || (coff & (bytes - 1)) != 0) {
if (in)
*eax = 0xffffffff;
return (0);
@@ -1380,7 +1665,7 @@ pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
*eax = pci_get_cfgdata32(pi, coff);
}
- pci_emul_hdrtype_fixup(cfgslot, coff, bytes, eax);
+ pci_emul_hdrtype_fixup(cfgbus, cfgslot, coff, bytes, eax);
} else {
/* Let the device emulation override the default handler */
if (pe->pe_cfgwrite != NULL &&
@@ -1475,13 +1760,14 @@ pci_irq_port_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
}
INOUT_PORT(pci_irq, 0xC00, IOPORT_F_OUT, pci_irq_port_handler);
INOUT_PORT(pci_irq, 0xC01, IOPORT_F_OUT, pci_irq_port_handler);
+SYSRES_IO(0xC00, 2);
#define PCI_EMUL_TEST
#ifdef PCI_EMUL_TEST
/*
* Define a dummy test device
*/
-#define DIOSZ 20
+#define DIOSZ 8
#define DMEMSZ 4096
struct pci_emul_dsoftc {
uint8_t ioregs[DIOSZ];
@@ -1497,8 +1783,7 @@ pci_emul_dinit(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
int error;
struct pci_emul_dsoftc *sc;
- sc = malloc(sizeof(struct pci_emul_dsoftc));
- memset(sc, 0, sizeof(struct pci_emul_dsoftc));
+ sc = calloc(1, sizeof(struct pci_emul_dsoftc));
pi->pi_arg = sc;
@@ -1546,10 +1831,10 @@ pci_emul_diow(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
* Special magic value to generate an interrupt
*/
if (offset == 4 && size == 4 && pci_msi_enabled(pi))
- pci_generate_msi(pi, value % pci_msi_msgnum(pi));
+ pci_generate_msi(pi, value % pci_msi_maxmsgnum(pi));
if (value == 0xabcdef) {
- for (i = 0; i < pci_msi_msgnum(pi); i++)
+ for (i = 0; i < pci_msi_maxmsgnum(pi); i++)
pci_generate_msi(pi, i);
}
}
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
index 4e04a1e..7ad0a5d 100644
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -32,13 +32,13 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <sys/kernel.h>
+#include <sys/_pthreadtypes.h>
#include <dev/pci/pcireg.h>
#include <assert.h>
#define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */
-#define PCIY_RESERVED 0x00
struct vmctx;
struct pci_devinst;
@@ -51,6 +51,9 @@ struct pci_devemu {
int (*pe_init)(struct vmctx *, struct pci_devinst *,
char *opts);
+ /* ACPI DSDT enumeration */
+ void (*pe_write_dsdt)(struct pci_devinst *);
+
/* config space read/write callbacks */
int (*pe_cfgwrite)(struct vmctx *ctx, int vcpu,
struct pci_devinst *pi, int offset,
@@ -97,31 +100,45 @@ struct msix_table_entry {
*/
#define MSIX_TABLE_ENTRY_SIZE 16
#define MAX_MSIX_TABLE_ENTRIES 2048
-#define PBA_TABLE_ENTRY_SIZE 8
+#define PBA_SIZE(msgnum) (roundup2((msgnum), 64) / 8)
+
+enum lintr_stat {
+ IDLE,
+ ASSERTED,
+ PENDING
+};
struct pci_devinst {
struct pci_devemu *pi_d;
struct vmctx *pi_vmctx;
uint8_t pi_bus, pi_slot, pi_func;
- uint8_t pi_lintr_pin;
char pi_name[PI_NAMESZ];
int pi_bar_getsize;
+ int pi_prevcap;
+ int pi_capend;
struct {
- int enabled;
- int cpu;
- int vector;
- int msgnum;
+ int8_t pin;
+ enum lintr_stat state;
+ int ioapic_irq;
+ pthread_mutex_t lock;
+ } pi_lintr;
+
+ struct {
+ int enabled;
+ uint64_t addr;
+ uint64_t msg_data;
+ int maxmsgnum;
} pi_msi;
struct {
int enabled;
int table_bar;
int pba_bar;
- size_t table_offset;
+ uint32_t table_offset;
int table_count;
- size_t pba_offset;
- size_t pba_size;
+ uint32_t pba_offset;
+ int pba_size;
int function_mask;
struct msix_table_entry *table; /* allocated at runtime */
} pi_msix;
@@ -183,6 +200,8 @@ struct pciecap {
uint16_t slot_status2;
} __packed;
+typedef void (*pci_lintr_cb)(int b, int s, int pin, int ioapic_irq, void *arg);
+
int init_pci(struct vmctx *ctx);
void msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
int bytes, uint32_t val);
@@ -195,23 +214,25 @@ int pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx,
uint64_t hostbase, enum pcibar_type type, uint64_t size);
int pci_emul_add_msicap(struct pci_devinst *pi, int msgnum);
int pci_emul_add_pciecap(struct pci_devinst *pi, int pcie_device_type);
-int pci_is_legacy(struct pci_devinst *pi);
void pci_generate_msi(struct pci_devinst *pi, int msgnum);
void pci_generate_msix(struct pci_devinst *pi, int msgnum);
void pci_lintr_assert(struct pci_devinst *pi);
void pci_lintr_deassert(struct pci_devinst *pi);
-int pci_lintr_request(struct pci_devinst *pi, int ivec);
+int pci_lintr_request(struct pci_devinst *pi);
int pci_msi_enabled(struct pci_devinst *pi);
int pci_msix_enabled(struct pci_devinst *pi);
int pci_msix_table_bar(struct pci_devinst *pi);
int pci_msix_pba_bar(struct pci_devinst *pi);
int pci_msi_msgnum(struct pci_devinst *pi);
-int pci_parse_slot(char *opt, int legacy);
+int pci_parse_slot(char *opt);
void pci_populate_msicap(struct msicap *cap, int msgs, int nextptr);
int pci_emul_add_msixcap(struct pci_devinst *pi, int msgnum, int barnum);
int pci_emul_msix_twrite(struct pci_devinst *pi, uint64_t offset, int size,
uint64_t value);
uint64_t pci_emul_msix_tread(struct pci_devinst *pi, uint64_t offset, int size);
+int pci_count_lintr(int bus);
+void pci_walk_lintr(int bus, pci_lintr_cb cb, void *arg);
+void pci_write_dsdt(void);
static __inline void
pci_set_cfgdata8(struct pci_devinst *pi, int offset, uint8_t val)
diff --git a/usr.sbin/bhyve/pci_hostbridge.c b/usr.sbin/bhyve/pci_hostbridge.c
index dee0a47..54a25ae 100644
--- a/usr.sbin/bhyve/pci_hostbridge.c
+++ b/usr.sbin/bhyve/pci_hostbridge.c
@@ -47,6 +47,22 @@ pci_hostbridge_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
return (0);
}
+static int
+pci_amd_hostbridge_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ (void) pci_hostbridge_init(ctx, pi, opts);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, 0x1022); /* AMD */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, 0x7432); /* made up */
+
+ return (0);
+}
+
+struct pci_devemu pci_de_amd_hostbridge = {
+ .pe_emu = "amd_hostbridge",
+ .pe_init = pci_amd_hostbridge_init,
+};
+PCI_EMUL_SET(pci_de_amd_hostbridge);
+
struct pci_devemu pci_de_hostbridge = {
.pe_emu = "hostbridge",
.pe_init = pci_hostbridge_init,
diff --git a/usr.sbin/bhyve/pci_lpc.c b/usr.sbin/bhyve/pci_lpc.c
new file mode 100644
index 0000000..f5e4a69
--- /dev/null
+++ b/usr.sbin/bhyve/pci_lpc.c
@@ -0,0 +1,366 @@
+/*-
+ * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
+ * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/vmm.h>
+#include <machine/vmm_dev.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vmmapi.h>
+
+#include "acpi.h"
+#include "inout.h"
+#include "pci_emul.h"
+#include "pci_lpc.h"
+#include "uart_emul.h"
+
+#define IO_ICU1 0x20
+#define IO_ICU2 0xA0
+
+SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt);
+SET_DECLARE(lpc_sysres_set, struct lpc_sysres);
+
+#define ELCR_PORT 0x4d0
+SYSRES_IO(ELCR_PORT, 2);
+
+#define IO_TIMER1_PORT 0x40
+
+#define NMISC_PORT 0x61
+SYSRES_IO(NMISC_PORT, 1);
+
+static struct pci_devinst *lpc_bridge;
+
+#define LPC_UART_NUM 2
+static struct lpc_uart_softc {
+ struct uart_softc *uart_softc;
+ const char *opts;
+ int iobase;
+ int irq;
+ int enabled;
+} lpc_uart_softc[LPC_UART_NUM];
+
+static const char *lpc_uart_names[LPC_UART_NUM] = { "COM1", "COM2" };
+
+/*
+ * LPC device configuration is in the following form:
+ * <lpc_device_name>[,<options>]
+ * For e.g. "com1,stdio"
+ */
+int
+lpc_device_parse(const char *opts)
+{
+ int unit, error;
+ char *str, *cpy, *lpcdev;
+
+ error = -1;
+ str = cpy = strdup(opts);
+ lpcdev = strsep(&str, ",");
+ if (lpcdev != NULL) {
+ for (unit = 0; unit < LPC_UART_NUM; unit++) {
+ if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) {
+ lpc_uart_softc[unit].opts = str;
+ error = 0;
+ goto done;
+ }
+ }
+ }
+
+done:
+ if (error)
+ free(cpy);
+
+ return (error);
+}
+
+static void
+lpc_uart_intr_assert(void *arg)
+{
+ struct lpc_uart_softc *sc = arg;
+
+ assert(sc->irq >= 0);
+
+ vm_isa_pulse_irq(lpc_bridge->pi_vmctx, sc->irq, sc->irq);
+}
+
+static void
+lpc_uart_intr_deassert(void *arg)
+{
+ /*
+ * The COM devices on the LPC bus generate edge triggered interrupts,
+ * so nothing more to do here.
+ */
+}
+
+static int
+lpc_uart_io_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ int offset;
+ struct lpc_uart_softc *sc = arg;
+
+ offset = port - sc->iobase;
+
+ switch (bytes) {
+ case 1:
+ if (in)
+ *eax = uart_read(sc->uart_softc, offset);
+ else
+ uart_write(sc->uart_softc, offset, *eax);
+ break;
+ case 2:
+ if (in) {
+ *eax = uart_read(sc->uart_softc, offset);
+ *eax |= uart_read(sc->uart_softc, offset + 1) << 8;
+ } else {
+ uart_write(sc->uart_softc, offset, *eax);
+ uart_write(sc->uart_softc, offset + 1, *eax >> 8);
+ }
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+lpc_init(void)
+{
+ struct lpc_uart_softc *sc;
+ struct inout_port iop;
+ const char *name;
+ int unit, error;
+
+ /* COM1 and COM2 */
+ for (unit = 0; unit < LPC_UART_NUM; unit++) {
+ sc = &lpc_uart_softc[unit];
+ name = lpc_uart_names[unit];
+
+ if (uart_legacy_alloc(unit, &sc->iobase, &sc->irq) != 0) {
+ fprintf(stderr, "Unable to allocate resources for "
+ "LPC device %s\n", name);
+ return (-1);
+ }
+
+ sc->uart_softc = uart_init(lpc_uart_intr_assert,
+ lpc_uart_intr_deassert, sc);
+
+ if (uart_set_backend(sc->uart_softc, sc->opts) != 0) {
+ fprintf(stderr, "Unable to initialize backend '%s' "
+ "for LPC device %s\n", sc->opts, name);
+ return (-1);
+ }
+
+ bzero(&iop, sizeof(struct inout_port));
+ iop.name = name;
+ iop.port = sc->iobase;
+ iop.size = UART_IO_BAR_SIZE;
+ iop.flags = IOPORT_F_INOUT;
+ iop.handler = lpc_uart_io_handler;
+ iop.arg = sc;
+
+ error = register_inout(&iop);
+ assert(error == 0);
+ sc->enabled = 1;
+ }
+
+ return (0);
+}
+
+static void
+pci_lpc_write_dsdt(struct pci_devinst *pi)
+{
+ struct lpc_dsdt **ldpp, *ldp;
+
+ dsdt_line("");
+ dsdt_line("Device (ISA)");
+ dsdt_line("{");
+ dsdt_line(" Name (_ADR, 0x%04X%04X)", pi->pi_slot, pi->pi_func);
+ dsdt_line(" OperationRegion (P40C, PCI_Config, 0x60, 0x04)");
+
+ dsdt_indent(1);
+ SET_FOREACH(ldpp, lpc_dsdt_set) {
+ ldp = *ldpp;
+ ldp->handler();
+ }
+
+ dsdt_line("");
+ dsdt_line("Device (PIC)");
+ dsdt_line("{");
+ dsdt_line(" Name (_HID, EisaId (\"PNP0000\"))");
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+ dsdt_indent(2);
+ dsdt_fixed_ioport(IO_ICU1, 2);
+ dsdt_fixed_ioport(IO_ICU2, 2);
+ dsdt_fixed_irq(2);
+ dsdt_unindent(2);
+ dsdt_line(" })");
+ dsdt_line("}");
+
+ dsdt_line("");
+ dsdt_line("Device (TIMR)");
+ dsdt_line("{");
+ dsdt_line(" Name (_HID, EisaId (\"PNP0100\"))");
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+ dsdt_indent(2);
+ dsdt_fixed_ioport(IO_TIMER1_PORT, 4);
+ dsdt_fixed_irq(0);
+ dsdt_unindent(2);
+ dsdt_line(" })");
+ dsdt_line("}");
+ dsdt_unindent(1);
+
+ dsdt_line("}");
+}
+
+static void
+pci_lpc_sysres_dsdt(void)
+{
+ struct lpc_sysres **lspp, *lsp;
+
+ dsdt_line("");
+ dsdt_line("Device (SIO)");
+ dsdt_line("{");
+ dsdt_line(" Name (_HID, EisaId (\"PNP0C02\"))");
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+
+ dsdt_indent(2);
+ SET_FOREACH(lspp, lpc_sysres_set) {
+ lsp = *lspp;
+ switch (lsp->type) {
+ case LPC_SYSRES_IO:
+ dsdt_fixed_ioport(lsp->base, lsp->length);
+ break;
+ case LPC_SYSRES_MEM:
+ dsdt_fixed_mem32(lsp->base, lsp->length);
+ break;
+ }
+ }
+ dsdt_unindent(2);
+
+ dsdt_line(" })");
+ dsdt_line("}");
+}
+LPC_DSDT(pci_lpc_sysres_dsdt);
+
+static void
+pci_lpc_uart_dsdt(void)
+{
+ struct lpc_uart_softc *sc;
+ int unit;
+
+ for (unit = 0; unit < LPC_UART_NUM; unit++) {
+ sc = &lpc_uart_softc[unit];
+ if (!sc->enabled)
+ continue;
+ dsdt_line("");
+ dsdt_line("Device (%s)", lpc_uart_names[unit]);
+ dsdt_line("{");
+ dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))");
+ dsdt_line(" Name (_UID, %d)", unit + 1);
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+ dsdt_indent(2);
+ dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE);
+ dsdt_fixed_irq(sc->irq);
+ dsdt_unindent(2);
+ dsdt_line(" })");
+ dsdt_line("}");
+ }
+}
+LPC_DSDT(pci_lpc_uart_dsdt);
+
+static void
+pci_lpc_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size, uint64_t value)
+{
+}
+
+uint64_t
+pci_lpc_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
+ int baridx, uint64_t offset, int size)
+{
+ return (0);
+}
+
+#define LPC_DEV 0x7000
+#define LPC_VENDOR 0x8086
+
+static int
+pci_lpc_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ /*
+ * Do not allow more than one LPC bridge to be configured.
+ */
+ if (lpc_bridge != NULL) {
+ fprintf(stderr, "Only one LPC bridge is allowed.\n");
+ return (-1);
+ }
+
+ /*
+ * Enforce that the LPC can only be configured on bus 0. This
+ * simplifies the ACPI DSDT because it can provide a decode for
+ * all legacy i/o ports behind bus 0.
+ */
+ if (pi->pi_bus != 0) {
+ fprintf(stderr, "LPC bridge can be present only on bus 0.\n");
+ return (-1);
+ }
+
+ if (lpc_init() != 0)
+ return (-1);
+
+ /* initialize config space */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, LPC_DEV);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, LPC_VENDOR);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE);
+ pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_ISA);
+
+ lpc_bridge = pi;
+
+ return (0);
+}
+
+struct pci_devemu pci_de_lpc = {
+ .pe_emu = "lpc",
+ .pe_init = pci_lpc_init,
+ .pe_write_dsdt = pci_lpc_write_dsdt,
+ .pe_barwrite = pci_lpc_write,
+ .pe_barread = pci_lpc_read
+};
+PCI_EMUL_SET(pci_de_lpc);
diff --git a/usr.sbin/bhyve/elcr.c b/usr.sbin/bhyve/pci_lpc.h
index 2417ae1..e45bcb9 100644
--- a/usr.sbin/bhyve/elcr.c
+++ b/usr.sbin/bhyve/pci_lpc.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 NetApp, Inc.
+ * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,40 +26,45 @@
* $FreeBSD$
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#ifndef _LPC_H_
+#define _LPC_H_
-#include <sys/types.h>
+#include <sys/linker_set.h>
-#include "inout.h"
+typedef void (*lpc_write_dsdt_t)(void);
-/*
- * EISA interrupt Level Control Register.
- *
- * This is a 16-bit register with one bit for each of the IRQ0 through IRQ15.
- * A level triggered irq is indicated by setting the corresponding bit to '1'.
- */
-#define ELCR_PORT 0x4d0
+struct lpc_dsdt {
+ lpc_write_dsdt_t handler;
+};
+
+#define LPC_DSDT(handler) \
+ static struct lpc_dsdt __CONCAT(__lpc_dsdt, __LINE__) = { \
+ (handler), \
+ }; \
+ DATA_SET(lpc_dsdt_set, __CONCAT(__lpc_dsdt, __LINE__))
-static uint8_t elcr[2] = { 0x00, 0x00 };
+enum lpc_sysres_type {
+ LPC_SYSRES_IO,
+ LPC_SYSRES_MEM
+};
-static int
-elcr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
- uint32_t *eax, void *arg)
-{
- int idx;
+struct lpc_sysres {
+ enum lpc_sysres_type type;
+ uint32_t base;
+ uint32_t length;
+};
- if (bytes != 1)
- return (-1);
+#define LPC_SYSRES(type, base, length) \
+ static struct lpc_sysres __CONCAT(__lpc_sysres, __LINE__) = { \
+ (type), \
+ (base), \
+ (length) \
+ }; \
+ DATA_SET(lpc_sysres_set, __CONCAT(__lpc_sysres, __LINE__))
- idx = port - ELCR_PORT;
+#define SYSRES_IO(base, length) LPC_SYSRES(LPC_SYSRES_IO, base, length)
+#define SYSRES_MEM(base, length) LPC_SYSRES(LPC_SYSRES_MEM, base, length)
- if (in)
- *eax = elcr[idx];
- else
- elcr[idx] = *eax;
+int lpc_device_parse(const char *opt);
- return (0);
-}
-INOUT_PORT(elcr, ELCR_PORT + 0, IOPORT_F_INOUT, elcr_handler);
-INOUT_PORT(elcr, ELCR_PORT + 1, IOPORT_F_INOUT, elcr_handler);
+#endif
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index 43c542d..04d68c4 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -228,11 +228,11 @@ cfginitmsi(struct passthru_softc *sc)
pi->pi_msix.table_offset =
msixcap.table_info & ~PCIM_MSIX_BIR_MASK;
pi->pi_msix.table_count = MSIX_TABLE_COUNT(msixcap.msgctrl);
+ pi->pi_msix.pba_size = PBA_SIZE(pi->pi_msix.table_count);
/* Allocate the emulated MSI-X table array */
table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
- pi->pi_msix.table = malloc(table_size);
- bzero(pi->pi_msix.table, table_size);
+ pi->pi_msix.table = calloc(1, table_size);
/* Mask all table entries */
for (i = 0; i < pi->pi_msix.table_count; i++) {
@@ -279,8 +279,10 @@ msix_table_read(struct passthru_softc *sc, uint64_t offset, int size)
int index;
pi = sc->psc_pi;
- offset -= pi->pi_msix.table_offset;
+ if (offset < pi->pi_msix.table_offset)
+ return (-1);
+ offset -= pi->pi_msix.table_offset;
index = offset / MSIX_TABLE_ENTRY_SIZE;
if (index >= pi->pi_msix.table_count)
return (-1);
@@ -324,8 +326,10 @@ msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc,
int error, index;
pi = sc->psc_pi;
- offset -= pi->pi_msix.table_offset;
+ if (offset < pi->pi_msix.table_offset)
+ return;
+ offset -= pi->pi_msix.table_offset;
index = offset / MSIX_TABLE_ENTRY_SIZE;
if (index >= pi->pi_msix.table_count)
return;
@@ -345,12 +349,10 @@ msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc,
/* If the entry is masked, don't set it up */
if ((entry->vector_control & PCIM_MSIX_VCTRL_MASK) == 0 ||
(vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {
- error = vm_setup_msix(ctx, vcpu, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev,
- sc->psc_sel.pc_func,
- index, entry->msg_data,
- entry->vector_control,
- entry->addr);
+ error = vm_setup_pptdev_msix(ctx, vcpu,
+ sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, index, entry->addr,
+ entry->msg_data, entry->vector_control);
}
}
}
@@ -360,7 +362,9 @@ init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
{
int b, s, f;
int error, idx;
- size_t len, remaining, table_size;
+ size_t len, remaining;
+ uint32_t table_size, table_offset;
+ uint32_t pba_size, pba_offset;
vm_paddr_t start;
struct pci_devinst *pi = sc->psc_pi;
@@ -376,24 +380,37 @@ init_msix_table(struct vmctx *ctx, struct passthru_softc *sc, uint64_t base)
* either resides in its own page within the region,
* or it resides in a page shared with only the PBA.
*/
- if (pi->pi_msix.pba_bar == pi->pi_msix.table_bar &&
- ((pi->pi_msix.pba_offset - pi->pi_msix.table_offset) < 4096)) {
- /* Need to also emulate the PBA, not supported yet */
- printf("Unsupported MSI-X configuration: %d/%d/%d\n", b, s, f);
- return (-1);
- }
+ table_offset = rounddown2(pi->pi_msix.table_offset, 4096);
- /* Compute the MSI-X table size */
- table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
+ table_size = pi->pi_msix.table_offset - table_offset;
+ table_size += pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
table_size = roundup2(table_size, 4096);
+ if (pi->pi_msix.pba_bar == pi->pi_msix.table_bar) {
+ pba_offset = pi->pi_msix.pba_offset;
+ pba_size = pi->pi_msix.pba_size;
+ if (pba_offset >= table_offset + table_size ||
+ table_offset >= pba_offset + pba_size) {
+ /*
+ * The PBA can reside in the same BAR as the MSI-x
+ * tables as long as it does not overlap with any
+ * naturally aligned page occupied by the tables.
+ */
+ } else {
+ /* Need to also emulate the PBA, not supported yet */
+ printf("Unsupported MSI-X configuration: %d/%d/%d\n",
+ b, s, f);
+ return (-1);
+ }
+ }
+
idx = pi->pi_msix.table_bar;
start = pi->pi_bar[idx].addr;
remaining = pi->pi_bar[idx].size;
/* Map everything before the MSI-X table */
- if (pi->pi_msix.table_offset > 0) {
- len = pi->pi_msix.table_offset;
+ if (table_offset > 0) {
+ len = table_offset;
error = vm_map_pptdev_mmio(ctx, b, s, f, start, len, base);
if (error)
return (error);
@@ -426,7 +443,7 @@ cfginitbar(struct vmctx *ctx, struct passthru_softc *sc)
struct pci_devinst *pi;
struct pci_bar_io bar;
enum pcibar_type bartype;
- uint64_t base;
+ uint64_t base, size;
pi = sc->psc_pi;
@@ -455,15 +472,25 @@ cfginitbar(struct vmctx *ctx, struct passthru_softc *sc)
}
base = bar.pbi_base & PCIM_BAR_MEM_BASE;
}
+ size = bar.pbi_length;
+
+ if (bartype != PCIBAR_IO) {
+ if (((base | size) & PAGE_MASK) != 0) {
+ printf("passthru device %d/%d/%d BAR %d: "
+ "base %#lx or size %#lx not page aligned\n",
+ sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, i, base, size);
+ return (-1);
+ }
+ }
/* Cache information about the "real" BAR */
sc->psc_bar[i].type = bartype;
- sc->psc_bar[i].size = bar.pbi_length;
+ sc->psc_bar[i].size = size;
sc->psc_bar[i].addr = base;
/* Allocate the BAR in the guest I/O or MMIO space */
- error = pci_emul_alloc_pbar(pi, i, base, bartype,
- bar.pbi_length);
+ error = pci_emul_alloc_pbar(pi, i, base, bartype, size);
if (error)
return (-1);
@@ -473,7 +500,7 @@ cfginitbar(struct vmctx *ctx, struct passthru_softc *sc)
if (error)
return (-1);
} else if (bartype != PCIBAR_IO) {
- /* Map the physical MMIO space in the guest MMIO space */
+ /* Map the physical BAR in the guest MMIO space */
error = vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
sc->psc_sel.pc_dev, sc->psc_sel.pc_func,
pi->pi_bar[i].addr, pi->pi_bar[i].size, base);
@@ -546,8 +573,7 @@ passthru_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
if (vm_assign_pptdev(ctx, bus, slot, func) != 0)
goto done;
- sc = malloc(sizeof(struct passthru_softc));
- memset(sc, 0, sizeof(struct passthru_softc));
+ sc = calloc(1, sizeof(struct passthru_softc));
pi->pi_arg = sc;
sc->psc_pi = pi;
@@ -652,11 +678,12 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
if (msicap_access(sc, coff)) {
msicap_cfgwrite(pi, sc->psc_msi.capoff, coff, bytes, val);
- error = vm_setup_msi(ctx, vcpu, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev, sc->psc_sel.pc_func, pi->pi_msi.cpu,
- pi->pi_msi.vector, pi->pi_msi.msgnum);
+ error = vm_setup_pptdev_msi(ctx, vcpu, sc->psc_sel.pc_bus,
+ sc->psc_sel.pc_dev, sc->psc_sel.pc_func,
+ pi->pi_msi.addr, pi->pi_msi.msg_data,
+ pi->pi_msi.maxmsgnum);
if (error != 0) {
- printf("vm_setup_msi returned error %d\r\n", errno);
+ printf("vm_setup_pptdev_msi error %d\r\n", errno);
exit(1);
}
return (0);
@@ -667,15 +694,16 @@ passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
if (pi->pi_msix.enabled) {
msix_table_entries = pi->pi_msix.table_count;
for (i = 0; i < msix_table_entries; i++) {
- error = vm_setup_msix(ctx, vcpu, sc->psc_sel.pc_bus,
- sc->psc_sel.pc_dev,
- sc->psc_sel.pc_func, i,
- pi->pi_msix.table[i].msg_data,
- pi->pi_msix.table[i].vector_control,
- pi->pi_msix.table[i].addr);
+ error = vm_setup_pptdev_msix(ctx, vcpu,
+ sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
+ sc->psc_sel.pc_func, i,
+ pi->pi_msix.table[i].addr,
+ pi->pi_msix.table[i].msg_data,
+ pi->pi_msix.table[i].vector_control);
if (error) {
- printf("vm_setup_msix returned error %d\r\n", errno);
+ printf("vm_setup_pptdev_msix error "
+ "%d\r\n", errno);
exit(1);
}
}
diff --git a/usr.sbin/bhyve/pci_uart.c b/usr.sbin/bhyve/pci_uart.c
index dd30551..21b93bf 100644
--- a/usr.sbin/bhyve/pci_uart.c
+++ b/usr.sbin/bhyve/pci_uart.c
@@ -30,42 +30,12 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
-#include <sys/select.h>
-#include <dev/ic/ns16550.h>
#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <termios.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <string.h>
-#include <pthread.h>
#include "bhyverun.h"
#include "pci_emul.h"
-#include "mevent.h"
-
-#define COM1_BASE 0x3F8
-#define COM1_IRQ 4
-#define COM2_BASE 0x2F8
-#define COM2_IRQ 3
-
-#define DEFAULT_RCLK 1843200
-#define DEFAULT_BAUD 9600
-
-#define FCR_RX_MASK 0xC0
-
-#define MCR_OUT1 0x04
-#define MCR_OUT2 0x08
-
-#define MSR_DELTA_MASK 0x0f
-
-#ifndef REG_SCR
-#define REG_SCR com_scr
-#endif
-
-#define FIFOSZ 16
+#include "uart_emul.h"
/*
* Pick a PCI vid/did of a chip with a single uart at
@@ -75,544 +45,67 @@ __FBSDID("$FreeBSD$");
#define COM_VENDOR 0x131f
#define COM_DEV 0x2000
-static int pci_uart_stdio; /* stdio in use for i/o */
-
-static int pci_uart_nldevs; /* number of legacy devices - 2 max */
-
-static struct {
- uint64_t baddr;
- int vector;
-} pci_uart_lres[] = {
- { COM1_BASE, COM1_IRQ},
- { COM2_BASE, COM2_IRQ},
- { 0, 0 }
-};
-
-struct fifo {
- uint8_t buf[FIFOSZ];
- int rindex; /* index to read from */
- int windex; /* index to write to */
- int num; /* number of characters in the fifo */
- int size; /* size of the fifo */
-};
-
-struct pci_uart_softc {
- struct pci_devinst *pi;
- pthread_mutex_t mtx; /* protects all softc elements */
- uint8_t data; /* Data register (R/W) */
- uint8_t ier; /* Interrupt enable register (R/W) */
- uint8_t lcr; /* Line control register (R/W) */
- uint8_t mcr; /* Modem control register (R/W) */
- uint8_t lsr; /* Line status register (R/W) */
- uint8_t msr; /* Modem status register (R/W) */
- uint8_t fcr; /* FIFO control register (W) */
- uint8_t scr; /* Scratch register (R/W) */
-
- uint8_t dll; /* Baudrate divisor latch LSB */
- uint8_t dlh; /* Baudrate divisor latch MSB */
-
- struct fifo rxfifo;
-
- int opened;
- int stdio;
- bool thre_int_pending; /* THRE interrupt pending */
-};
-
-static void pci_uart_drain(int fd, enum ev_type ev, void *arg);
-
-static struct termios tio_orig, tio_new; /* I/O Terminals */
-
-static void
-ttyclose(void)
-{
- tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig);
-}
-
-static void
-ttyopen(void)
-{
- tcgetattr(STDIN_FILENO, &tio_orig);
-
- cfmakeraw(&tio_new);
- tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
-
- atexit(ttyclose);
-}
-
-static bool
-tty_char_available(void)
-{
- fd_set rfds;
- struct timeval tv;
-
- FD_ZERO(&rfds);
- FD_SET(STDIN_FILENO, &rfds);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0 ) {
- return (true);
- } else {
- return (false);
- }
-}
-
-static int
-ttyread(void)
-{
- char rb;
-
- if (tty_char_available()) {
- read(STDIN_FILENO, &rb, 1);
- return (rb & 0xff);
- } else {
- return (-1);
- }
-}
-
-static void
-ttywrite(unsigned char wb)
-{
- (void) write(STDIN_FILENO, &wb, 1);
-}
-
static void
-fifo_reset(struct fifo *fifo, int size)
+pci_uart_intr_assert(void *arg)
{
- bzero(fifo, sizeof(struct fifo));
- fifo->size = size;
-}
+ struct pci_devinst *pi = arg;
-static int
-fifo_putchar(struct fifo *fifo, uint8_t ch)
-{
-
- if (fifo->num < fifo->size) {
- fifo->buf[fifo->windex] = ch;
- fifo->windex = (fifo->windex + 1) % fifo->size;
- fifo->num++;
- return (0);
- } else
- return (-1);
-}
-
-static int
-fifo_getchar(struct fifo *fifo)
-{
- int c;
-
- if (fifo->num > 0) {
- c = fifo->buf[fifo->rindex];
- fifo->rindex = (fifo->rindex + 1) % fifo->size;
- fifo->num--;
- return (c);
- } else
- return (-1);
-}
-
-static int
-fifo_numchars(struct fifo *fifo)
-{
-
- return (fifo->num);
-}
-
-static int
-fifo_available(struct fifo *fifo)
-{
-
- return (fifo->num < fifo->size);
+ pci_lintr_assert(pi);
}
static void
-pci_uart_opentty(struct pci_uart_softc *sc)
+pci_uart_intr_deassert(void *arg)
{
- struct mevent *mev;
-
- assert(sc->opened == 0);
- assert(sc->stdio);
+ struct pci_devinst *pi = arg;
- ttyopen();
- mev = mevent_add(STDIN_FILENO, EVF_READ, pci_uart_drain, sc);
- assert(mev);
-}
-
-static void
-pci_uart_legacy_res(uint64_t *bar, int *ivec)
-{
- if (pci_uart_lres[pci_uart_nldevs].baddr != 0) {
- *bar = pci_uart_lres[pci_uart_nldevs].baddr;
- *ivec = pci_uart_lres[pci_uart_nldevs].vector;
- pci_uart_nldevs++;
- } else {
- /* TODO: print warning ? */
- *bar = 0;
- *ivec= -1;
- }
-}
-
-/*
- * The IIR returns a prioritized interrupt reason:
- * - receive data available
- * - transmit holding register empty
- * - modem status change
- *
- * Return an interrupt reason if one is available.
- */
-static int
-pci_uart_intr_reason(struct pci_uart_softc *sc)
-{
-
- if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0)
- return (IIR_RLS);
- else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0)
- return (IIR_RXTOUT);
- else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0)
- return (IIR_TXRDY);
- else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0)
- return (IIR_MLSC);
- else
- return (IIR_NOPEND);
-}
-
-static void
-pci_uart_reset(struct pci_uart_softc *sc)
-{
- uint16_t divisor;
-
- divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16;
- sc->dll = divisor;
- sc->dlh = divisor >> 16;
-
- fifo_reset(&sc->rxfifo, 1); /* no fifo until enabled by software */
-}
-
-/*
- * Toggle the COM port's intr pin depending on whether or not we have an
- * interrupt condition to report to the processor.
- */
-static void
-pci_uart_toggle_intr(struct pci_uart_softc *sc)
-{
- uint8_t intr_reason;
-
- intr_reason = pci_uart_intr_reason(sc);
-
- if (intr_reason == IIR_NOPEND)
- pci_lintr_deassert(sc->pi);
- else
- pci_lintr_assert(sc->pi);
-}
-
-static void
-pci_uart_drain(int fd, enum ev_type ev, void *arg)
-{
- struct pci_uart_softc *sc;
- int ch;
-
- sc = arg;
-
- assert(fd == STDIN_FILENO);
- assert(ev == EVF_READ);
-
- /*
- * This routine is called in the context of the mevent thread
- * to take out the softc lock to protect against concurrent
- * access from a vCPU i/o exit
- */
- pthread_mutex_lock(&sc->mtx);
-
- if ((sc->mcr & MCR_LOOPBACK) != 0) {
- (void) ttyread();
- } else {
- while (fifo_available(&sc->rxfifo) &&
- ((ch = ttyread()) != -1)) {
- fifo_putchar(&sc->rxfifo, ch);
- }
- pci_uart_toggle_intr(sc);
- }
-
- pthread_mutex_unlock(&sc->mtx);
+ pci_lintr_deassert(pi);
}
static void
pci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int baridx, uint64_t offset, int size, uint64_t value)
{
- struct pci_uart_softc *sc;
- int fifosz;
- uint8_t msr;
-
- sc = pi->pi_arg;
assert(baridx == 0);
assert(size == 1);
- /* Open terminal */
- if (!sc->opened && sc->stdio) {
- pci_uart_opentty(sc);
- sc->opened = 1;
- }
-
- pthread_mutex_lock(&sc->mtx);
-
- /*
- * Take care of the special case DLAB accesses first
- */
- if ((sc->lcr & LCR_DLAB) != 0) {
- if (offset == REG_DLL) {
- sc->dll = value;
- goto done;
- }
-
- if (offset == REG_DLH) {
- sc->dlh = value;
- goto done;
- }
- }
-
- switch (offset) {
- case REG_DATA:
- if (sc->mcr & MCR_LOOPBACK) {
- if (fifo_putchar(&sc->rxfifo, value) != 0)
- sc->lsr |= LSR_OE;
- } else if (sc->stdio) {
- ttywrite(value);
- } /* else drop on floor */
- sc->thre_int_pending = true;
- break;
- case REG_IER:
- /*
- * Apply mask so that bits 4-7 are 0
- * Also enables bits 0-3 only if they're 1
- */
- sc->ier = value & 0x0F;
- break;
- case REG_FCR:
- /*
- * When moving from FIFO and 16450 mode and vice versa,
- * the FIFO contents are reset.
- */
- if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) {
- fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1;
- fifo_reset(&sc->rxfifo, fifosz);
- }
-
- /*
- * The FCR_ENABLE bit must be '1' for the programming
- * of other FCR bits to be effective.
- */
- if ((value & FCR_ENABLE) == 0) {
- sc->fcr = 0;
- } else {
- if ((value & FCR_RCV_RST) != 0)
- fifo_reset(&sc->rxfifo, FIFOSZ);
-
- sc->fcr = value &
- (FCR_ENABLE | FCR_DMA | FCR_RX_MASK);
- }
- break;
- case REG_LCR:
- sc->lcr = value;
- break;
- case REG_MCR:
- /* Apply mask so that bits 5-7 are 0 */
- sc->mcr = value & 0x1F;
-
- msr = 0;
- if (sc->mcr & MCR_LOOPBACK) {
- /*
- * In the loopback mode certain bits from the
- * MCR are reflected back into MSR
- */
- if (sc->mcr & MCR_RTS)
- msr |= MSR_CTS;
- if (sc->mcr & MCR_DTR)
- msr |= MSR_DSR;
- if (sc->mcr & MCR_OUT1)
- msr |= MSR_RI;
- if (sc->mcr & MCR_OUT2)
- msr |= MSR_DCD;
- }
-
- /*
- * Detect if there has been any change between the
- * previous and the new value of MSR. If there is
- * then assert the appropriate MSR delta bit.
- */
- if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS))
- sc->msr |= MSR_DCTS;
- if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR))
- sc->msr |= MSR_DDSR;
- if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD))
- sc->msr |= MSR_DDCD;
- if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0)
- sc->msr |= MSR_TERI;
-
- /*
- * Update the value of MSR while retaining the delta
- * bits.
- */
- sc->msr &= MSR_DELTA_MASK;
- sc->msr |= msr;
- break;
- case REG_LSR:
- /*
- * Line status register is not meant to be written to
- * during normal operation.
- */
- break;
- case REG_MSR:
- /*
- * As far as I can tell MSR is a read-only register.
- */
- break;
- case REG_SCR:
- sc->scr = value;
- break;
- default:
- break;
- }
-
-done:
- pci_uart_toggle_intr(sc);
- pthread_mutex_unlock(&sc->mtx);
+ uart_write(pi->pi_arg, offset, value);
}
uint64_t
pci_uart_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int baridx, uint64_t offset, int size)
{
- struct pci_uart_softc *sc;
- uint8_t iir, intr_reason;
- uint64_t reg;
-
- sc = pi->pi_arg;
+ uint8_t val;
assert(baridx == 0);
assert(size == 1);
- /* Open terminal */
- if (!sc->opened && sc->stdio) {
- pci_uart_opentty(sc);
- sc->opened = 1;
- }
-
- pthread_mutex_lock(&sc->mtx);
-
- /*
- * Take care of the special case DLAB accesses first
- */
- if ((sc->lcr & LCR_DLAB) != 0) {
- if (offset == REG_DLL) {
- reg = sc->dll;
- goto done;
- }
-
- if (offset == REG_DLH) {
- reg = sc->dlh;
- goto done;
- }
- }
-
- switch (offset) {
- case REG_DATA:
- reg = fifo_getchar(&sc->rxfifo);
- break;
- case REG_IER:
- reg = sc->ier;
- break;
- case REG_IIR:
- iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0;
-
- intr_reason = pci_uart_intr_reason(sc);
-
- /*
- * Deal with side effects of reading the IIR register
- */
- if (intr_reason == IIR_TXRDY)
- sc->thre_int_pending = false;
-
- iir |= intr_reason;
-
- reg = iir;
- break;
- case REG_LCR:
- reg = sc->lcr;
- break;
- case REG_MCR:
- reg = sc->mcr;
- break;
- case REG_LSR:
- /* Transmitter is always ready for more data */
- sc->lsr |= LSR_TEMT | LSR_THRE;
-
- /* Check for new receive data */
- if (fifo_numchars(&sc->rxfifo) > 0)
- sc->lsr |= LSR_RXRDY;
- else
- sc->lsr &= ~LSR_RXRDY;
-
- reg = sc->lsr;
-
- /* The LSR_OE bit is cleared on LSR read */
- sc->lsr &= ~LSR_OE;
- break;
- case REG_MSR:
- /*
- * MSR delta bits are cleared on read
- */
- reg = sc->msr;
- sc->msr &= ~MSR_DELTA_MASK;
- break;
- case REG_SCR:
- reg = sc->scr;
- break;
- default:
- reg = 0xFF;
- break;
- }
-
-done:
- pci_uart_toggle_intr(sc);
- pthread_mutex_unlock(&sc->mtx);
-
- return (reg);
+ val = uart_read(pi->pi_arg, offset);
+ return (val);
}
static int
pci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
- struct pci_uart_softc *sc;
- uint64_t bar;
- int ivec;
+ struct uart_softc *sc;
- sc = malloc(sizeof(struct pci_uart_softc));
- memset(sc, 0, sizeof(struct pci_uart_softc));
-
- pi->pi_arg = sc;
- sc->pi = pi;
-
- pthread_mutex_init(&sc->mtx, NULL);
+ pci_emul_alloc_bar(pi, 0, PCIBAR_IO, UART_IO_BAR_SIZE);
+ pci_lintr_request(pi);
/* initialize config space */
pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV);
pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR);
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM);
- if (pci_is_legacy(pi)) {
- pci_uart_legacy_res(&bar, &ivec);
- pci_emul_alloc_pbar(pi, 0, bar, PCIBAR_IO, 8);
- } else {
- ivec = -1;
- pci_emul_alloc_bar(pi, 0, PCIBAR_IO, 8);
- }
- pci_lintr_request(pi, ivec);
- if (opts != NULL && !strcmp("stdio", opts) && !pci_uart_stdio) {
- pci_uart_stdio = 1;
- sc->stdio = 1;
- }
+ sc = uart_init(pci_uart_intr_assert, pci_uart_intr_deassert, pi);
+ pi->pi_arg = sc;
- pci_uart_reset(sc);
+ if (uart_set_backend(sc, opts) != 0) {
+ fprintf(stderr, "Unable to initialize backend '%s' for "
+ "pci uart at %d:%d\n", opts, pi->pi_slot, pi->pi_func);
+ return (-1);
+ }
return (0);
}
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
index 529cd42..3474fd7 100644
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -46,23 +46,36 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include <assert.h>
#include <pthread.h>
+#include <md5.h>
#include "bhyverun.h"
#include "pci_emul.h"
#include "virtio.h"
+#ifndef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
#define VTBLK_RINGSZ 64
#define VTBLK_MAXSEGS 32
#define VTBLK_S_OK 0
#define VTBLK_S_IOERR 1
+#define VTBLK_S_UNSUPP 2
+
+#define VTBLK_BLK_ID_BYTES 20
+
+/* Capability bits */
+#define VTBLK_F_SEG_MAX (1 << 2) /* Maximum request segments */
+#define VTBLK_F_BLK_SIZE (1 << 6) /* cfg block size valid */
/*
* Host capabilities
*/
#define VTBLK_S_HOSTCAPS \
- ( 0x00000004 | /* host maximum request segments */ \
+ ( VTBLK_F_SEG_MAX | \
+ VTBLK_F_BLK_SIZE | \
VIRTIO_RING_F_INDIRECT_DESC ) /* indirect descriptors */
/*
@@ -85,6 +98,7 @@ struct vtblk_config {
struct virtio_blk_hdr {
#define VBH_OP_READ 0
#define VBH_OP_WRITE 1
+#define VBH_OP_IDENT 8
#define VBH_FLAG_BARRIER 0x80000000 /* OR'ed into vbh_type */
uint32_t vbh_type;
uint32_t vbh_ioprio;
@@ -103,9 +117,11 @@ static int pci_vtblk_debug;
*/
struct pci_vtblk_softc {
struct virtio_softc vbsc_vs;
+ pthread_mutex_t vsc_mtx;
struct vqueue_info vbsc_vq;
int vbsc_fd;
struct vtblk_config vbsc_cfg;
+ char vbsc_ident[VTBLK_BLK_ID_BYTES];
};
static void pci_vtblk_reset(void *);
@@ -180,7 +196,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vqueue_info *vq)
for (i = 1; i < n; i++) {
/*
* - write op implies read-only descriptor,
- * - read op implies write-only descriptor,
+ * - read/ident op implies write-only descriptor,
* therefore test the inverse of the descriptor bit
* to the op.
*/
@@ -189,14 +205,34 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vqueue_info *vq)
}
DPRINTF(("virtio-block: %s op, %d bytes, %d segs, offset %ld\n\r",
- writeop ? "write" : "read", iolen, i - 1, offset));
+ writeop ? "write" : "read/ident", iolen, i - 1, offset));
- if (writeop)
+ switch (type) {
+ case VBH_OP_WRITE:
err = pwritev(sc->vbsc_fd, iov + 1, i - 1, offset);
- else
+ break;
+ case VBH_OP_READ:
err = preadv(sc->vbsc_fd, iov + 1, i - 1, offset);
+ break;
+ case VBH_OP_IDENT:
+ /* Assume a single buffer */
+ strlcpy(iov[1].iov_base, sc->vbsc_ident,
+ min(iov[1].iov_len, sizeof(sc->vbsc_ident)));
+ err = 0;
+ break;
+ default:
+ err = -ENOSYS;
+ break;
+ }
- *status = err < 0 ? VTBLK_S_IOERR : VTBLK_S_OK;
+ /* convert errno into a virtio block error return */
+ if (err < 0) {
+ if (err == -ENOSYS)
+ *status = VTBLK_S_UNSUPP;
+ else
+ *status = VTBLK_S_IOERR;
+ } else
+ *status = VTBLK_S_OK;
/*
* Return the descriptor back to the host.
@@ -220,12 +256,12 @@ static int
pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
struct stat sbuf;
+ MD5_CTX mdctx;
+ u_char digest[16];
struct pci_vtblk_softc *sc;
off_t size;
int fd;
int sectsz;
- int use_msix;
- const char *env_msi;
if (opts == NULL) {
printf("virtio-block: backing device required\n");
@@ -263,19 +299,32 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
assert(sectsz != 0);
}
- sc = malloc(sizeof(struct pci_vtblk_softc));
- memset(sc, 0, sizeof(struct pci_vtblk_softc));
+ sc = calloc(1, sizeof(struct pci_vtblk_softc));
/* record fd of storage device/file */
sc->vbsc_fd = fd;
+ pthread_mutex_init(&sc->vsc_mtx, NULL);
+
/* init virtio softc and virtqueues */
vi_softc_linkup(&sc->vbsc_vs, &vtblk_vi_consts, sc, pi, &sc->vbsc_vq);
+ sc->vbsc_vs.vs_mtx = &sc->vsc_mtx;
+
sc->vbsc_vq.vq_qsize = VTBLK_RINGSZ;
/* sc->vbsc_vq.vq_notify = we have no per-queue notify */
+ /*
+ * Create an identifier for the backing file. Use parts of the
+ * md5 sum of the filename
+ */
+ MD5Init(&mdctx);
+ MD5Update(&mdctx, opts, strlen(opts));
+ MD5Final(digest, &mdctx);
+ sprintf(sc->vbsc_ident, "BHYVE-%02X%02X-%02X%02X-%02X%02X",
+ digest[0], digest[1], digest[2], digest[3], digest[4], digest[5]);
+
/* setup virtio block config space */
- sc->vbsc_cfg.vbc_capacity = size / sectsz;
+ sc->vbsc_cfg.vbc_capacity = size / DEV_BSIZE; /* 512-byte units */
sc->vbsc_cfg.vbc_seg_max = VTBLK_MAXSEGS;
sc->vbsc_cfg.vbc_blk_size = sectsz;
sc->vbsc_cfg.vbc_size_max = 0; /* not negotiated */
@@ -294,12 +343,9 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_STORAGE);
pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_BLOCK);
- use_msix = 1;
- if ((env_msi = getenv("BHYVE_USE_MSI"))) {
- if (strcasecmp(env_msi, "yes") == 0)
- use_msix = 0;
- }
- if (vi_intr_init(&sc->vbsc_vs, 1, use_msix))
+ pci_lintr_request(pi);
+
+ if (vi_intr_init(&sc->vbsc_vs, 1, fbsdrun_virtio_msix()))
return (1);
vi_set_io_bar(&sc->vbsc_vs, 0);
return (0);
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
index 2939949..c3b8690 100644
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -509,18 +509,17 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
char nstr[80];
char tname[MAXCOMLEN + 1];
struct pci_vtnet_softc *sc;
- const char *env_msi;
char *devname;
char *vtopts;
int mac_provided;
- int use_msix;
- sc = malloc(sizeof(struct pci_vtnet_softc));
- memset(sc, 0, sizeof(struct pci_vtnet_softc));
+ sc = calloc(1, sizeof(struct pci_vtnet_softc));
pthread_mutex_init(&sc->vsc_mtx, NULL);
vi_softc_linkup(&sc->vsc_vs, &vtnet_vi_consts, sc, pi, sc->vsc_queues);
+ sc->vsc_vs.vs_mtx = &sc->vsc_mtx;
+
sc->vsc_queues[VTNET_RXQ].vq_qsize = VTNET_RINGSZ;
sc->vsc_queues[VTNET_RXQ].vq_notify = pci_vtnet_ping_rxq;
sc->vsc_queues[VTNET_TXQ].vq_qsize = VTNET_RINGSZ;
@@ -531,15 +530,6 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
#endif
/*
- * Use MSI if set by user
- */
- use_msix = 1;
- if ((env_msi = getenv("BHYVE_USE_MSI")) != NULL) {
- if (strcasecmp(env_msi, "yes") == 0)
- use_msix = 0;
- }
-
- /*
* Attempt to open the tap device and read the MAC address
* if specified
*/
@@ -599,7 +589,7 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
*/
if (!mac_provided) {
snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot,
- pi->pi_func, vmname);
+ pi->pi_func, vmname);
MD5Init(&mdctx);
MD5Update(&mdctx, nstr, strlen(nstr));
@@ -619,11 +609,13 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK);
pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET);
+ pci_lintr_request(pi);
+
/* link always up */
sc->vsc_config.status = 1;
/* use BAR 1 to map MSI-X table and PBA, if we're using MSI-X */
- if (vi_intr_init(&sc->vsc_vs, 1, use_msix))
+ if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix()))
return (1);
/* use BAR 0 to map config regs in IO space */
@@ -643,7 +635,8 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pthread_mutex_init(&sc->tx_mtx, NULL);
pthread_cond_init(&sc->tx_cond, NULL);
pthread_create(&sc->tx_tid, NULL, pci_vtnet_tx_thread, (void *)sc);
- snprintf(tname, sizeof(tname), "%s vtnet%d tx", vmname, pi->pi_slot);
+ snprintf(tname, sizeof(tname), "vtnet-%d:%d tx", pi->pi_slot,
+ pi->pi_func);
pthread_set_name_np(sc->tx_tid, tname);
return (0);
diff --git a/usr.sbin/bhyve/pci_virtio_rnd.c b/usr.sbin/bhyve/pci_virtio_rnd.c
new file mode 100644
index 0000000..4d53183
--- /dev/null
+++ b/usr.sbin/bhyve/pci_virtio_rnd.c
@@ -0,0 +1,188 @@
+/*-
+ * Copyright (c) 2014 Nahanni Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * virtio entropy device emulation.
+ * Randomness is sourced from /dev/random which does not block
+ * once it has been seeded at bootup.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/linker_set.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+#include <pthread.h>
+
+#include "bhyverun.h"
+#include "pci_emul.h"
+#include "virtio.h"
+
+#define VTRND_RINGSZ 64
+
+
+static int pci_vtrnd_debug;
+#define DPRINTF(params) if (pci_vtrnd_debug) printf params
+#define WPRINTF(params) printf params
+
+/*
+ * Per-device softc
+ */
+struct pci_vtrnd_softc {
+ struct virtio_softc vrsc_vs;
+ struct vqueue_info vrsc_vq;
+ pthread_mutex_t vrsc_mtx;
+ uint64_t vrsc_cfg;
+ int vrsc_fd;
+};
+
+static void pci_vtrnd_reset(void *);
+static void pci_vtrnd_notify(void *, struct vqueue_info *);
+
+static struct virtio_consts vtrnd_vi_consts = {
+ "vtrnd", /* our name */
+ 1, /* we support 1 virtqueue */
+ 0, /* config reg size */
+ pci_vtrnd_reset, /* reset */
+ pci_vtrnd_notify, /* device-wide qnotify */
+ NULL, /* read virtio config */
+ NULL, /* write virtio config */
+ 0, /* our capabilities */
+};
+
+
+static void
+pci_vtrnd_reset(void *vsc)
+{
+ struct pci_vtrnd_softc *sc;
+
+ sc = vsc;
+
+ DPRINTF(("vtrnd: device reset requested !\n"));
+ vi_reset_dev(&sc->vrsc_vs);
+}
+
+
+static void
+pci_vtrnd_notify(void *vsc, struct vqueue_info *vq)
+{
+ struct iovec iov;
+ struct pci_vtrnd_softc *sc;
+ int len;
+
+ sc = vsc;
+
+ vq_startchains(vq);
+
+ if (sc->vrsc_fd < 0) {
+ vq_endchains(vq, 0);
+ return;
+ }
+
+ while (vq_has_descs(vq)) {
+ vq_getchain(vq, &iov, 1, NULL);
+
+ len = read(sc->vrsc_fd, iov.iov_base, iov.iov_len);
+
+ DPRINTF(("vtrnd: vtrnd_notify(): %d\r\n", len));
+
+ /* Catastrophe if unable to read from /dev/random */
+ assert(len > 0);
+
+ /*
+ * Release this chain and handle more
+ */
+ vq_relchain(vq, len);
+ }
+ vq_endchains(vq, 1); /* Generate interrupt if appropriate. */
+}
+
+
+static int
+pci_vtrnd_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
+{
+ struct pci_vtrnd_softc *sc;
+ int fd;
+ int len;
+ uint8_t v;
+
+ /*
+ * Should always be able to open /dev/random.
+ */
+ fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+
+ assert(fd >= 0);
+
+ /*
+ * Check that device is seeded and non-blocking.
+ */
+ len = read(fd, &v, sizeof(v));
+ if (len <= 0) {
+ WPRINTF(("vtrnd: /dev/random not ready, read(): %d", len));
+ return (1);
+ }
+
+ sc = calloc(1, sizeof(struct pci_vtrnd_softc));
+
+ vi_softc_linkup(&sc->vrsc_vs, &vtrnd_vi_consts, sc, pi, &sc->vrsc_vq);
+ sc->vrsc_vs.vs_mtx = &sc->vrsc_mtx;
+
+ sc->vrsc_vq.vq_qsize = VTRND_RINGSZ;
+
+ /* keep /dev/random opened while emulating */
+ sc->vrsc_fd = fd;
+
+ /* initialize config space */
+ pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_RANDOM);
+ pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
+ pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_CRYPTO);
+ pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_ENTROPY);
+
+ if (vi_intr_init(&sc->vrsc_vs, 1, fbsdrun_virtio_msix()))
+ return (1);
+ vi_set_io_bar(&sc->vrsc_vs, 0);
+
+ return (0);
+}
+
+
+struct pci_devemu pci_de_vrnd = {
+ .pe_emu = "virtio-rnd",
+ .pe_init = pci_vtrnd_init,
+ .pe_barwrite = vi_pci_write,
+ .pe_barread = vi_pci_read
+};
+PCI_EMUL_SET(pci_de_vrnd);
diff --git a/usr.sbin/bhyve/pit_8254.c b/usr.sbin/bhyve/pit_8254.c
deleted file mode 100644
index 3987da3..0000000
--- a/usr.sbin/bhyve/pit_8254.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/*-
- * Copyright (c) 2011 NetApp, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <machine/vmm.h>
-
-#include <machine/clock.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <vmmapi.h>
-
-#include "bhyverun.h"
-#include "inout.h"
-#include "ioapic.h"
-#include "mevent.h"
-#include "pit_8254.h"
-
-#define TIMER_SEL_MASK 0xc0
-#define TIMER_RW_MASK 0x30
-#define TIMER_MODE_MASK 0x0f
-#define TIMER_SEL_READBACK 0xc0
-
-#define TIMER_DIV(freq, hz) (((freq) + (hz) / 2) / (hz))
-
-#define PIT_8254_FREQ 1193182
-static const int nsecs_per_tick = 1000000000 / PIT_8254_FREQ;
-
-struct counter {
- struct vmctx *ctx;
- struct mevent *tevp;
- struct timeval tv; /* uptime when counter was loaded */
- int mode;
- uint16_t initial; /* initial counter value */
- uint8_t cr[2];
- uint8_t ol[2];
- int crbyte;
- int olbyte;
- int frbyte;
-};
-
-
-static void
-timevalfix(struct timeval *t1)
-{
-
- if (t1->tv_usec < 0) {
- t1->tv_sec--;
- t1->tv_usec += 1000000;
- }
- if (t1->tv_usec >= 1000000) {
- t1->tv_sec++;
- t1->tv_usec -= 1000000;
- }
-}
-
-static void
-timevalsub(struct timeval *t1, const struct timeval *t2)
-{
-
- t1->tv_sec -= t2->tv_sec;
- t1->tv_usec -= t2->tv_usec;
- timevalfix(t1);
-}
-
-static uint64_t pit_mev_count;
-
-static void
-pit_mevent_cb(int fd, enum ev_type type, void *param)
-{
- struct counter *c;
-
- c = param;
-
- pit_mev_count++;
-
- ioapic_assert_pin(c->ctx, 0);
- ioapic_deassert_pin(c->ctx, 0);
-
- /*
- * Delete the timer for one-shots
- */
- if (c->mode != TIMER_RATEGEN) {
- mevent_delete(c->tevp);
- c->tevp = NULL;
- }
-}
-
-static void
-pit_timer_start(struct vmctx *ctx, struct counter *c)
-{
- int msecs;
-
- if (c->initial != 0) {
- msecs = c->initial * nsecs_per_tick / 1000000;
- if (msecs == 0)
- msecs = 1;
-
- if (c->tevp == NULL)
- c->tevp = mevent_add(msecs, EVF_TIMER, pit_mevent_cb,
- c);
- }
-}
-
-static uint16_t
-pit_update_counter(struct counter *c, int latch)
-{
- struct timeval tv2;
- uint16_t lval;
- uint64_t delta_nsecs, delta_ticks;
-
- /* cannot latch a new value until the old one has been consumed */
- if (latch && c->olbyte != 0)
- return (0);
-
- if (c->initial == 0 || c->initial == 1) {
- /*
- * XXX the program that runs the VM can be stopped and
- * restarted at any time. This means that state that was
- * created by the guest is destroyed between invocations
- * of the program.
- *
- * If the counter's initial value is not programmed we
- * assume a value that would be set to generate 100
- * interrupts per second.
- */
- c->initial = TIMER_DIV(PIT_8254_FREQ, 100);
- gettimeofday(&c->tv, NULL);
- }
-
- (void)gettimeofday(&tv2, NULL);
- timevalsub(&tv2, &c->tv);
- delta_nsecs = tv2.tv_sec * 1000000000 + tv2.tv_usec * 1000;
- delta_ticks = delta_nsecs / nsecs_per_tick;
-
- lval = c->initial - delta_ticks % c->initial;
-
- if (latch) {
- c->olbyte = 2;
- c->ol[1] = lval; /* LSB */
- c->ol[0] = lval >> 8; /* MSB */
- }
-
- return (lval);
-}
-
-static int
-pit_8254_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
- uint32_t *eax, void *arg)
-{
- int sel, rw, mode;
- uint8_t val;
- struct counter *c;
-
- static struct counter counter[3];
-
- if (bytes != 1)
- return (-1);
-
- val = *eax;
-
- if (port == TIMER_MODE) {
- assert(in == 0);
- sel = val & TIMER_SEL_MASK;
- rw = val & TIMER_RW_MASK;
- mode = val & TIMER_MODE_MASK;
-
- if (sel == TIMER_SEL_READBACK)
- return (-1);
- if (rw != TIMER_LATCH && rw != TIMER_16BIT)
- return (-1);
-
- if (rw != TIMER_LATCH) {
- /*
- * Counter mode is not affected when issuing a
- * latch command.
- */
- if (mode != TIMER_INTTC &&
- mode != TIMER_RATEGEN &&
- mode != TIMER_SQWAVE &&
- mode != TIMER_SWSTROBE)
- return (-1);
- }
-
- c = &counter[sel >> 6];
- c->ctx = ctx;
- c->mode = mode;
- if (rw == TIMER_LATCH)
- pit_update_counter(c, 1);
- else
- c->olbyte = 0; /* reset latch after reprogramming */
-
- return (0);
- }
-
- /* counter ports */
- assert(port >= TIMER_CNTR0 && port <= TIMER_CNTR2);
- c = &counter[port - TIMER_CNTR0];
-
- if (in) {
- /*
- * The spec says that once the output latch is completely
- * read it should revert to "following" the counter. Use
- * the free running counter for this case (i.e. Linux
- * TSC calibration). Assuming the access mode is 16-bit,
- * toggle the MSB/LSB bit on each read.
- */
- if (c->olbyte == 0) {
- uint16_t tmp;
-
- tmp = pit_update_counter(c, 0);
- if (c->frbyte)
- tmp >>= 8;
- tmp &= 0xff;
- *eax = tmp;
- c->frbyte ^= 1;
- } else
- *eax = c->ol[--c->olbyte];
- } else {
- c->cr[c->crbyte++] = *eax;
- if (c->crbyte == 2) {
- c->frbyte = 0;
- c->crbyte = 0;
- c->initial = c->cr[0] | (uint16_t)c->cr[1] << 8;
- /* Start an interval timer for counter 0 */
- if (port == 0x40)
- pit_timer_start(ctx, c);
- if (c->initial == 0)
- c->initial = 0xffff;
- gettimeofday(&c->tv, NULL);
- }
- }
-
- return (0);
-}
-
-INOUT_PORT(8254, TIMER_MODE, IOPORT_F_OUT, pit_8254_handler);
-INOUT_PORT(8254, TIMER_CNTR0, IOPORT_F_INOUT, pit_8254_handler);
-INOUT_PORT(8254, TIMER_CNTR1, IOPORT_F_INOUT, pit_8254_handler);
-INOUT_PORT(8254, TIMER_CNTR2, IOPORT_F_INOUT, pit_8254_handler);
diff --git a/usr.sbin/bhyve/pm.c b/usr.sbin/bhyve/pm.c
new file mode 100644
index 0000000..99087e4
--- /dev/null
+++ b/usr.sbin/bhyve/pm.c
@@ -0,0 +1,291 @@
+/*-
+ * Copyright (c) 2013 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/vmm.h>
+
+#include <assert.h>
+#include <pthread.h>
+#include <signal.h>
+#include <vmmapi.h>
+
+#include "acpi.h"
+#include "inout.h"
+#include "mevent.h"
+#include "pci_lpc.h"
+
+static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
+static struct mevent *power_button;
+static sig_t old_power_handler;
+
+/*
+ * Reset Control register at I/O port 0xcf9. Bit 2 forces a system
+ * reset when it transitions from 0 to 1. Bit 1 selects the type of
+ * reset to attempt: 0 selects a "soft" reset, and 1 selects a "hard"
+ * reset.
+ */
+static int
+reset_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+ static uint8_t reset_control;
+
+ if (bytes != 1)
+ return (-1);
+ if (in)
+ *eax = reset_control;
+ else {
+ reset_control = *eax;
+
+ /* Treat hard and soft resets the same. */
+ if (reset_control & 0x4)
+ return (INOUT_RESET);
+ }
+ return (0);
+}
+INOUT_PORT(reset_reg, 0xCF9, IOPORT_F_INOUT, reset_handler);
+
+/*
+ * ACPI's SCI is a level-triggered interrupt.
+ */
+static int sci_active;
+
+static void
+sci_assert(struct vmctx *ctx)
+{
+
+ if (sci_active)
+ return;
+ vm_isa_assert_irq(ctx, SCI_INT, SCI_INT);
+ sci_active = 1;
+}
+
+static void
+sci_deassert(struct vmctx *ctx)
+{
+
+ if (!sci_active)
+ return;
+ vm_isa_deassert_irq(ctx, SCI_INT, SCI_INT);
+ sci_active = 0;
+}
+
+/*
+ * Power Management 1 Event Registers
+ *
+ * The only power management event supported is a power button upon
+ * receiving SIGTERM.
+ */
+static uint16_t pm1_enable, pm1_status;
+
+#define PM1_TMR_STS 0x0001
+#define PM1_BM_STS 0x0010
+#define PM1_GBL_STS 0x0020
+#define PM1_PWRBTN_STS 0x0100
+#define PM1_SLPBTN_STS 0x0200
+#define PM1_RTC_STS 0x0400
+#define PM1_WAK_STS 0x8000
+
+#define PM1_TMR_EN 0x0001
+#define PM1_GBL_EN 0x0020
+#define PM1_PWRBTN_EN 0x0100
+#define PM1_SLPBTN_EN 0x0200
+#define PM1_RTC_EN 0x0400
+
+static void
+sci_update(struct vmctx *ctx)
+{
+ int need_sci;
+
+ /* See if the SCI should be active or not. */
+ need_sci = 0;
+ if ((pm1_enable & PM1_TMR_EN) && (pm1_status & PM1_TMR_STS))
+ need_sci = 1;
+ if ((pm1_enable & PM1_GBL_EN) && (pm1_status & PM1_GBL_STS))
+ need_sci = 1;
+ if ((pm1_enable & PM1_PWRBTN_EN) && (pm1_status & PM1_PWRBTN_STS))
+ need_sci = 1;
+ if ((pm1_enable & PM1_SLPBTN_EN) && (pm1_status & PM1_SLPBTN_STS))
+ need_sci = 1;
+ if ((pm1_enable & PM1_RTC_EN) && (pm1_status & PM1_RTC_STS))
+ need_sci = 1;
+ if (need_sci)
+ sci_assert(ctx);
+ else
+ sci_deassert(ctx);
+}
+
+static int
+pm1_status_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+
+ if (bytes != 2)
+ return (-1);
+
+ pthread_mutex_lock(&pm_lock);
+ if (in)
+ *eax = pm1_status;
+ else {
+ /*
+ * Writes are only permitted to clear certain bits by
+ * writing 1 to those flags.
+ */
+ pm1_status &= ~(*eax & (PM1_WAK_STS | PM1_RTC_STS |
+ PM1_SLPBTN_STS | PM1_PWRBTN_STS | PM1_BM_STS));
+ sci_update(ctx);
+ }
+ pthread_mutex_unlock(&pm_lock);
+ return (0);
+}
+
+static int
+pm1_enable_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+
+ if (bytes != 2)
+ return (-1);
+
+ pthread_mutex_lock(&pm_lock);
+ if (in)
+ *eax = pm1_enable;
+ else {
+ /*
+ * Only permit certain bits to be set. We never use
+ * the global lock, but ACPI-CA whines profusely if it
+ * can't set GBL_EN.
+ */
+ pm1_enable = *eax & (PM1_PWRBTN_EN | PM1_GBL_EN);
+ sci_update(ctx);
+ }
+ pthread_mutex_unlock(&pm_lock);
+ return (0);
+}
+INOUT_PORT(pm1_status, PM1A_EVT_ADDR, IOPORT_F_INOUT, pm1_status_handler);
+INOUT_PORT(pm1_enable, PM1A_EVT_ADDR + 2, IOPORT_F_INOUT, pm1_enable_handler);
+
+static void
+power_button_handler(int signal, enum ev_type type, void *arg)
+{
+ struct vmctx *ctx;
+
+ ctx = arg;
+ pthread_mutex_lock(&pm_lock);
+ if (!(pm1_status & PM1_PWRBTN_STS)) {
+ pm1_status |= PM1_PWRBTN_STS;
+ sci_update(ctx);
+ }
+ pthread_mutex_unlock(&pm_lock);
+}
+
+/*
+ * Power Management 1 Control Register
+ *
+ * This is mostly unimplemented except that we wish to handle writes that
+ * set SPL_EN to handle S5 (soft power off).
+ */
+static uint16_t pm1_control;
+
+#define PM1_SCI_EN 0x0001
+#define PM1_SLP_TYP 0x1c00
+#define PM1_SLP_EN 0x2000
+#define PM1_ALWAYS_ZERO 0xc003
+
+static int
+pm1_control_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+
+ if (bytes != 2)
+ return (-1);
+ if (in)
+ *eax = pm1_control;
+ else {
+ /*
+ * Various bits are write-only or reserved, so force them
+ * to zero in pm1_control. Always preserve SCI_EN as OSPM
+ * can never change it.
+ */
+ pm1_control = (pm1_control & PM1_SCI_EN) |
+ (*eax & ~(PM1_SLP_EN | PM1_ALWAYS_ZERO));
+
+ /*
+ * If SLP_EN is set, check for S5. Bhyve's _S5_ method
+ * says that '5' should be stored in SLP_TYP for S5.
+ */
+ if (*eax & PM1_SLP_EN) {
+ if ((pm1_control & PM1_SLP_TYP) >> 10 == 5)
+ return (INOUT_POWEROFF);
+ }
+ }
+ return (0);
+}
+INOUT_PORT(pm1_control, PM1A_CNT_ADDR, IOPORT_F_INOUT, pm1_control_handler);
+SYSRES_IO(PM1A_EVT_ADDR, 8);
+
+/*
+ * ACPI SMI Command Register
+ *
+ * This write-only register is used to enable and disable ACPI.
+ */
+static int
+smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
+ uint32_t *eax, void *arg)
+{
+
+ assert(!in);
+ if (bytes != 1)
+ return (-1);
+
+ pthread_mutex_lock(&pm_lock);
+ switch (*eax) {
+ case BHYVE_ACPI_ENABLE:
+ pm1_control |= PM1_SCI_EN;
+ if (power_button == NULL) {
+ power_button = mevent_add(SIGTERM, EVF_SIGNAL,
+ power_button_handler, ctx);
+ old_power_handler = signal(SIGTERM, SIG_IGN);
+ }
+ break;
+ case BHYVE_ACPI_DISABLE:
+ pm1_control &= ~PM1_SCI_EN;
+ if (power_button != NULL) {
+ mevent_delete(power_button);
+ power_button = NULL;
+ signal(SIGTERM, old_power_handler);
+ }
+ break;
+ }
+ pthread_mutex_unlock(&pm_lock);
+ return (0);
+}
+INOUT_PORT(smi_cmd, SMI_CMD, IOPORT_F_OUT, smi_cmd_handler);
+SYSRES_IO(SMI_CMD, 1);
diff --git a/usr.sbin/bhyve/pmtmr.c b/usr.sbin/bhyve/pmtmr.c
index c8fbd62..3a46f9b 100644
--- a/usr.sbin/bhyve/pmtmr.c
+++ b/usr.sbin/bhyve/pmtmr.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include <pthread.h>
+#include "acpi.h"
#include "inout.h"
/*
@@ -49,11 +50,10 @@ __FBSDID("$FreeBSD$");
* This implementation will be 32-bits
*/
-#define IO_PMTMR 0x408 /* 4-byte i/o port for the timer */
-
#define PMTMR_FREQ 3579545 /* 3.579545MHz */
static pthread_mutex_t pmtmr_mtx;
+static pthread_once_t pmtmr_once = PTHREAD_ONCE_INIT;
static uint64_t pmtmr_old;
@@ -123,6 +123,7 @@ pmtmr_init(void)
pmtmr_uptime_old = tsnew;
pmtmr_old = timespec_to_pmtmr(&tsnew, &tsold);
}
+ pthread_mutex_init(&pmtmr_mtx, NULL);
}
static uint32_t
@@ -133,13 +134,7 @@ pmtmr_val(void)
uint64_t pmtmr_new;
int error;
- static int inited = 0;
-
- if (!inited) {
- pthread_mutex_init(&pmtmr_mtx, NULL);
- pmtmr_init();
- inited = 1;
- }
+ pthread_once(&pmtmr_once, pmtmr_init);
pthread_mutex_lock(&pmtmr_mtx);
diff --git a/usr.sbin/bhyve/post.c b/usr.sbin/bhyve/post.c
index 092a551..5215a0c 100644
--- a/usr.sbin/bhyve/post.c
+++ b/usr.sbin/bhyve/post.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include <assert.h>
#include "inout.h"
+#include "pci_lpc.h"
static int
post_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
@@ -49,3 +50,4 @@ post_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
}
INOUT_PORT(post, 0x84, IOPORT_F_IN, post_data_handler);
+SYSRES_IO(0x84, 1);
diff --git a/usr.sbin/bhyve/rtc.c b/usr.sbin/bhyve/rtc.c
index c1a84d74..1187747 100644
--- a/usr.sbin/bhyve/rtc.c
+++ b/usr.sbin/bhyve/rtc.c
@@ -40,7 +40,9 @@ __FBSDID("$FreeBSD$");
#include <machine/vmm.h>
#include <vmmapi.h>
+#include "acpi.h"
#include "inout.h"
+#include "pci_lpc.h"
#include "rtc.h"
#define IO_RTC 0x70
@@ -331,7 +333,7 @@ rtc_init(struct vmctx *ctx)
memset(rtc_nvram, 0, sizeof(rtc_nvram));
- rtc_nvram[nvoff(RTC_CENTURY)] = rtcout(tm.tm_year / 100);
+ rtc_nvram[nvoff(RTC_CENTURY)] = bin2bcd((tm.tm_year + 1900) / 100);
/* XXX init diag/reset code/equipment/checksum ? */
@@ -358,3 +360,24 @@ rtc_init(struct vmctx *ctx)
INOUT_PORT(rtc, IO_RTC, IOPORT_F_INOUT, rtc_addr_handler);
INOUT_PORT(rtc, IO_RTC + 1, IOPORT_F_INOUT, rtc_data_handler);
+
+static void
+rtc_dsdt(void)
+{
+
+ dsdt_line("");
+ dsdt_line("Device (RTC)");
+ dsdt_line("{");
+ dsdt_line(" Name (_HID, EisaId (\"PNP0B00\"))");
+ dsdt_line(" Name (_CRS, ResourceTemplate ()");
+ dsdt_line(" {");
+ dsdt_indent(2);
+ dsdt_fixed_ioport(IO_RTC, 2);
+ dsdt_fixed_irq(8);
+ dsdt_unindent(2);
+ dsdt_line(" })");
+ dsdt_line("}");
+}
+LPC_DSDT(rtc_dsdt);
+
+SYSRES_IO(0x72, 6);
diff --git a/usr.sbin/bhyve/smbiostbl.c b/usr.sbin/bhyve/smbiostbl.c
new file mode 100644
index 0000000..9d1cfb3
--- /dev/null
+++ b/usr.sbin/bhyve/smbiostbl.c
@@ -0,0 +1,832 @@
+/*-
+ * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <md5.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <uuid.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include "bhyverun.h"
+#include "smbiostbl.h"
+
+#define MB (1024*1024)
+#define GB (1024ULL*1024*1024)
+
+#define SMBIOS_BASE 0xF1000
+
+/* BHYVE_ACPI_BASE - SMBIOS_BASE) */
+#define SMBIOS_MAX_LENGTH (0xF2400 - 0xF1000)
+
+#define SMBIOS_TYPE_BIOS 0
+#define SMBIOS_TYPE_SYSTEM 1
+#define SMBIOS_TYPE_CHASSIS 3
+#define SMBIOS_TYPE_PROCESSOR 4
+#define SMBIOS_TYPE_MEMARRAY 16
+#define SMBIOS_TYPE_MEMDEVICE 17
+#define SMBIOS_TYPE_MEMARRAYMAP 19
+#define SMBIOS_TYPE_BOOT 32
+#define SMBIOS_TYPE_EOT 127
+
+struct smbios_structure {
+ uint8_t type;
+ uint8_t length;
+ uint16_t handle;
+} __packed;
+
+typedef int (*initializer_func_t)(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+struct smbios_template_entry {
+ struct smbios_structure *entry;
+ const char **strings;
+ initializer_func_t initializer;
+};
+
+/*
+ * SMBIOS Structure Table Entry Point
+ */
+#define SMBIOS_ENTRY_EANCHOR "_SM_"
+#define SMBIOS_ENTRY_EANCHORLEN 4
+#define SMBIOS_ENTRY_IANCHOR "_DMI_"
+#define SMBIOS_ENTRY_IANCHORLEN 5
+
+struct smbios_entry_point {
+ char eanchor[4]; /* anchor tag */
+ uint8_t echecksum; /* checksum of entry point structure */
+ uint8_t eplen; /* length in bytes of entry point */
+ uint8_t major; /* major version of the SMBIOS spec */
+ uint8_t minor; /* minor version of the SMBIOS spec */
+ uint16_t maxssize; /* maximum size in bytes of a struct */
+ uint8_t revision; /* entry point structure revision */
+ uint8_t format[5]; /* entry point rev-specific data */
+ char ianchor[5]; /* intermediate anchor tag */
+ uint8_t ichecksum; /* intermediate checksum */
+ uint16_t stlen; /* len in bytes of structure table */
+ uint32_t staddr; /* physical addr of structure table */
+ uint16_t stnum; /* number of structure table entries */
+ uint8_t bcdrev; /* BCD value representing DMI ver */
+} __packed;
+
+/*
+ * BIOS Information
+ */
+#define SMBIOS_FL_ISA 0x00000010 /* ISA is supported */
+#define SMBIOS_FL_PCI 0x00000080 /* PCI is supported */
+#define SMBIOS_FL_SHADOW 0x00001000 /* BIOS shadowing is allowed */
+#define SMBIOS_FL_CDBOOT 0x00008000 /* Boot from CD is supported */
+#define SMBIOS_FL_SELBOOT 0x00010000 /* Selectable Boot supported */
+#define SMBIOS_FL_EDD 0x00080000 /* EDD Spec is supported */
+
+#define SMBIOS_XB1_FL_ACPI 0x00000001 /* ACPI is supported */
+
+#define SMBIOS_XB2_FL_BBS 0x00000001 /* BIOS Boot Specification */
+#define SMBIOS_XB2_FL_VM 0x00000010 /* Virtual Machine */
+
+struct smbios_table_type0 {
+ struct smbios_structure header;
+ uint8_t vendor; /* vendor string */
+ uint8_t version; /* version string */
+ uint16_t segment; /* address segment location */
+ uint8_t rel_date; /* release date */
+ uint8_t size; /* rom size */
+ uint64_t cflags; /* characteristics */
+ uint8_t xc_bytes[2]; /* characteristics ext bytes */
+ uint8_t sb_major_rel; /* system bios version */
+ uint8_t sb_minor_rele;
+ uint8_t ecfw_major_rel; /* embedded ctrl fw version */
+ uint8_t ecfw_minor_rel;
+} __packed;
+
+/*
+ * System Information
+ */
+#define SMBIOS_WAKEUP_SWITCH 0x06 /* power switch */
+
+struct smbios_table_type1 {
+ struct smbios_structure header;
+ uint8_t manufacturer; /* manufacturer string */
+ uint8_t product; /* product name string */
+ uint8_t version; /* version string */
+ uint8_t serial; /* serial number string */
+ uint8_t uuid[16]; /* uuid byte array */
+ uint8_t wakeup; /* wake-up event */
+ uint8_t sku; /* sku number string */
+ uint8_t family; /* family name string */
+} __packed;
+
+/*
+ * System Enclosure or Chassis
+ */
+#define SMBIOS_CHT_UNKNOWN 0x02 /* unknown */
+
+#define SMBIOS_CHST_SAFE 0x03 /* safe */
+
+#define SMBIOS_CHSC_NONE 0x03 /* none */
+
+struct smbios_table_type3 {
+ struct smbios_structure header;
+ uint8_t manufacturer; /* manufacturer string */
+ uint8_t type; /* type */
+ uint8_t version; /* version string */
+ uint8_t serial; /* serial number string */
+ uint8_t asset; /* asset tag string */
+ uint8_t bustate; /* boot-up state */
+ uint8_t psstate; /* power supply state */
+ uint8_t tstate; /* thermal state */
+ uint8_t security; /* security status */
+ uint8_t uheight; /* height in 'u's */
+ uint8_t cords; /* number of power cords */
+ uint8_t elems; /* number of element records */
+ uint8_t elemlen; /* length of records */
+ uint8_t sku; /* sku number string */
+} __packed;
+
+/*
+ * Processor Information
+ */
+#define SMBIOS_PRT_CENTRAL 0x03 /* central processor */
+
+#define SMBIOS_PRF_OTHER 0x01 /* other */
+
+#define SMBIOS_PRS_PRESENT 0x40 /* socket is populated */
+#define SMBIOS_PRS_ENABLED 0x1 /* enabled */
+
+#define SMBIOS_PRU_NONE 0x06 /* none */
+
+#define SMBIOS_PFL_64B 0x04 /* 64-bit capable */
+
+struct smbios_table_type4 {
+ struct smbios_structure header;
+ uint8_t socket; /* socket designation string */
+ uint8_t type; /* processor type */
+ uint8_t family; /* processor family */
+ uint8_t manufacturer; /* manufacturer string */
+ uint64_t cpuid; /* processor cpuid */
+ uint8_t version; /* version string */
+ uint8_t voltage; /* voltage */
+ uint16_t clkspeed; /* ext clock speed in mhz */
+ uint16_t maxspeed; /* maximum speed in mhz */
+ uint16_t curspeed; /* current speed in mhz */
+ uint8_t status; /* status */
+ uint8_t upgrade; /* upgrade */
+ uint16_t l1handle; /* l1 cache handle */
+ uint16_t l2handle; /* l2 cache handle */
+ uint16_t l3handle; /* l3 cache handle */
+ uint8_t serial; /* serial number string */
+ uint8_t asset; /* asset tag string */
+ uint8_t part; /* part number string */
+ uint8_t cores; /* cores per socket */
+ uint8_t ecores; /* enabled cores */
+ uint8_t threads; /* threads per socket */
+ uint16_t cflags; /* processor characteristics */
+ uint16_t family2; /* processor family 2 */
+} __packed;
+
+/*
+ * Physical Memory Array
+ */
+#define SMBIOS_MAL_SYSMB 0x03 /* system board or motherboard */
+
+#define SMBIOS_MAU_SYSTEM 0x03 /* system memory */
+
+#define SMBIOS_MAE_NONE 0x03 /* none */
+
+struct smbios_table_type16 {
+ struct smbios_structure header;
+ uint8_t location; /* physical device location */
+ uint8_t use; /* device functional purpose */
+ uint8_t ecc; /* err detect/correct method */
+ uint32_t size; /* max mem capacity in kb */
+ uint16_t errhand; /* handle of error (if any) */
+ uint16_t ndevs; /* num of slots or sockets */
+ uint64_t xsize; /* max mem capacity in bytes */
+} __packed;
+
+/*
+ * Memory Device
+ */
+#define SMBIOS_MDFF_UNKNOWN 0x02 /* unknown */
+
+#define SMBIOS_MDT_UNKNOWN 0x02 /* unknown */
+
+#define SMBIOS_MDF_UNKNOWN 0x0004 /* unknown */
+
+struct smbios_table_type17 {
+ struct smbios_structure header;
+ uint16_t arrayhand; /* handle of physl mem array */
+ uint16_t errhand; /* handle of mem error data */
+ uint16_t twidth; /* total width in bits */
+ uint16_t dwidth; /* data width in bits */
+ uint16_t size; /* size in bytes */
+ uint8_t form; /* form factor */
+ uint8_t set; /* set */
+ uint8_t dloc; /* device locator string */
+ uint8_t bloc; /* phys bank locator string */
+ uint8_t type; /* memory type */
+ uint16_t flags; /* memory characteristics */
+ uint16_t maxspeed; /* maximum speed in mhz */
+ uint8_t manufacturer; /* manufacturer string */
+ uint8_t serial; /* serial number string */
+ uint8_t asset; /* asset tag string */
+ uint8_t part; /* part number string */
+ uint8_t attributes; /* attributes */
+ uint32_t xsize; /* extended size in mbs */
+ uint16_t curspeed; /* current speed in mhz */
+ uint16_t minvoltage; /* minimum voltage */
+ uint16_t maxvoltage; /* maximum voltage */
+ uint16_t curvoltage; /* configured voltage */
+} __packed;
+
+/*
+ * Memory Array Mapped Address
+ */
+struct smbios_table_type19 {
+ struct smbios_structure header;
+ uint32_t saddr; /* start phys addr in kb */
+ uint32_t eaddr; /* end phys addr in kb */
+ uint16_t arrayhand; /* physical mem array handle */
+ uint8_t width; /* num of dev in row */
+ uint64_t xsaddr; /* start phys addr in bytes */
+ uint64_t xeaddr; /* end phys addr in bytes */
+} __packed;
+
+/*
+ * System Boot Information
+ */
+#define SMBIOS_BOOT_NORMAL 0 /* no errors detected */
+
+struct smbios_table_type32 {
+ struct smbios_structure header;
+ uint8_t reserved[6];
+ uint8_t status; /* boot status */
+} __packed;
+
+/*
+ * End-of-Table
+ */
+struct smbios_table_type127 {
+ struct smbios_structure header;
+} __packed;
+
+struct smbios_table_type0 smbios_type0_template = {
+ { SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 },
+ 1, /* bios vendor string */
+ 2, /* bios version string */
+ 0xF000, /* bios address segment location */
+ 3, /* bios release date */
+ 0x0, /* bios size (64k * (n + 1) is the size in bytes) */
+ SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW |
+ SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD,
+ { SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM },
+ 0x0, /* bios major release */
+ 0x0, /* bios minor release */
+ 0xff, /* embedded controller firmware major release */
+ 0xff /* embedded controller firmware minor release */
+};
+
+const char *smbios_type0_strings[] = {
+ "BHYVE", /* vendor string */
+ __TIME__, /* bios version string */
+ __DATE__, /* bios release date string */
+ NULL
+};
+
+struct smbios_table_type1 smbios_type1_template = {
+ { SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 },
+ 1, /* manufacturer string */
+ 2, /* product string */
+ 3, /* version string */
+ 4, /* serial number string */
+ { 0 },
+ SMBIOS_WAKEUP_SWITCH,
+ 5, /* sku string */
+ 6 /* family string */
+};
+
+static int smbios_type1_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+const char *smbios_type1_strings[] = {
+ " ", /* manufacturer string */
+ "BHYVE", /* product name string */
+ "1.0", /* version string */
+ "None", /* serial number string */
+ "None", /* sku string */
+ " ", /* family name string */
+ NULL
+};
+
+struct smbios_table_type3 smbios_type3_template = {
+ { SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 },
+ 1, /* manufacturer string */
+ SMBIOS_CHT_UNKNOWN,
+ 2, /* version string */
+ 3, /* serial number string */
+ 4, /* asset tag string */
+ SMBIOS_CHST_SAFE,
+ SMBIOS_CHST_SAFE,
+ SMBIOS_CHST_SAFE,
+ SMBIOS_CHSC_NONE,
+ 0, /* height in 'u's (0=enclosure height unspecified) */
+ 0, /* number of power cords (0=number unspecified) */
+ 0, /* number of contained element records */
+ 0, /* length of records */
+ 5 /* sku number string */
+};
+
+const char *smbios_type3_strings[] = {
+ " ", /* manufacturer string */
+ "1.0", /* version string */
+ "None", /* serial number string */
+ "None", /* asset tag string */
+ "None", /* sku number string */
+ NULL
+};
+
+struct smbios_table_type4 smbios_type4_template = {
+ { SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 },
+ 1, /* socket designation string */
+ SMBIOS_PRT_CENTRAL,
+ SMBIOS_PRF_OTHER,
+ 2, /* manufacturer string */
+ 0, /* cpuid */
+ 3, /* version string */
+ 0, /* voltage */
+ 0, /* external clock frequency in mhz (0=unknown) */
+ 0, /* maximum frequency in mhz (0=unknown) */
+ 0, /* current frequency in mhz (0=unknown) */
+ SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED,
+ SMBIOS_PRU_NONE,
+ -1, /* l1 cache handle */
+ -1, /* l2 cache handle */
+ -1, /* l3 cache handle */
+ 4, /* serial number string */
+ 5, /* asset tag string */
+ 6, /* part number string */
+ 0, /* cores per socket (0=unknown) */
+ 0, /* enabled cores per socket (0=unknown) */
+ 0, /* threads per socket (0=unknown) */
+ SMBIOS_PFL_64B,
+ SMBIOS_PRF_OTHER
+};
+
+const char *smbios_type4_strings[] = {
+ " ", /* socket designation string */
+ " ", /* manufacturer string */
+ " ", /* version string */
+ "None", /* serial number string */
+ "None", /* asset tag string */
+ "None", /* part number string */
+ NULL
+};
+
+static int smbios_type4_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+struct smbios_table_type16 smbios_type16_template = {
+ { SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16), 0 },
+ SMBIOS_MAL_SYSMB,
+ SMBIOS_MAU_SYSTEM,
+ SMBIOS_MAE_NONE,
+ 0x80000000, /* max mem capacity in kb (0x80000000=use extended) */
+ -1, /* handle of error (if any) */
+ 0, /* number of slots or sockets (TBD) */
+ 0 /* extended maximum memory capacity in bytes (TBD) */
+};
+
+static int smbios_type16_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+struct smbios_table_type17 smbios_type17_template = {
+ { SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17), 0 },
+ -1, /* handle of physical memory array */
+ -1, /* handle of memory error data */
+ 64, /* total width in bits including ecc */
+ 64, /* data width in bits */
+ 0x7fff, /* size in bytes (0x7fff=use extended)*/
+ SMBIOS_MDFF_UNKNOWN,
+ 0, /* set (0x00=none, 0xff=unknown) */
+ 1, /* device locator string */
+ 2, /* physical bank locator string */
+ SMBIOS_MDT_UNKNOWN,
+ SMBIOS_MDF_UNKNOWN,
+ 0, /* maximum memory speed in mhz (0=unknown) */
+ 3, /* manufacturer string */
+ 4, /* serial number string */
+ 5, /* asset tag string */
+ 6, /* part number string */
+ 0, /* attributes (0=unknown rank information) */
+ 0, /* extended size in mb (TBD) */
+ 0, /* current speed in mhz (0=unknown) */
+ 0, /* minimum voltage in mv (0=unknown) */
+ 0, /* maximum voltage in mv (0=unknown) */
+ 0 /* configured voltage in mv (0=unknown) */
+};
+
+const char *smbios_type17_strings[] = {
+ " ", /* device locator string */
+ " ", /* physical bank locator string */
+ " ", /* manufacturer string */
+ "None", /* serial number string */
+ "None", /* asset tag string */
+ "None", /* part number string */
+ NULL
+};
+
+static int smbios_type17_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+struct smbios_table_type19 smbios_type19_template = {
+ { SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19), 0 },
+ 0xffffffff, /* starting phys addr in kb (0xffffffff=use ext) */
+ 0xffffffff, /* ending phys addr in kb (0xffffffff=use ext) */
+ -1, /* physical memory array handle */
+ 1, /* number of devices that form a row */
+ 0, /* extended starting phys addr in bytes (TDB) */
+ 0 /* extended ending phys addr in bytes (TDB) */
+};
+
+static int smbios_type19_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+struct smbios_table_type32 smbios_type32_template = {
+ { SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32), 0 },
+ { 0, 0, 0, 0, 0, 0 },
+ SMBIOS_BOOT_NORMAL
+};
+
+struct smbios_table_type127 smbios_type127_template = {
+ { SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127), 0 }
+};
+
+static int smbios_generic_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size);
+
+static struct smbios_template_entry smbios_template[] = {
+ { (struct smbios_structure *)&smbios_type0_template,
+ smbios_type0_strings,
+ smbios_generic_initializer },
+ { (struct smbios_structure *)&smbios_type1_template,
+ smbios_type1_strings,
+ smbios_type1_initializer },
+ { (struct smbios_structure *)&smbios_type3_template,
+ smbios_type3_strings,
+ smbios_generic_initializer },
+ { (struct smbios_structure *)&smbios_type4_template,
+ smbios_type4_strings,
+ smbios_type4_initializer },
+ { (struct smbios_structure *)&smbios_type16_template,
+ NULL,
+ smbios_type16_initializer },
+ { (struct smbios_structure *)&smbios_type17_template,
+ smbios_type17_strings,
+ smbios_type17_initializer },
+ { (struct smbios_structure *)&smbios_type19_template,
+ NULL,
+ smbios_type19_initializer },
+ { (struct smbios_structure *)&smbios_type32_template,
+ NULL,
+ smbios_generic_initializer },
+ { (struct smbios_structure *)&smbios_type127_template,
+ NULL,
+ smbios_generic_initializer },
+ { NULL,NULL, NULL }
+};
+
+static uint64_t guest_lomem, guest_himem;
+static uint16_t type16_handle;
+
+static int
+smbios_generic_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size)
+{
+ struct smbios_structure *entry;
+
+ memcpy(curaddr, template_entry, template_entry->length);
+ entry = (struct smbios_structure *)curaddr;
+ entry->handle = *n + 1;
+ curaddr += entry->length;
+ if (template_strings != NULL) {
+ int i;
+
+ for (i = 0; template_strings[i] != NULL; i++) {
+ const char *string;
+ int len;
+
+ string = template_strings[i];
+ len = strlen(string) + 1;
+ memcpy(curaddr, string, len);
+ curaddr += len;
+ }
+ *curaddr = '\0';
+ curaddr++;
+ } else {
+ /* Minimum string section is double nul */
+ *curaddr = '\0';
+ curaddr++;
+ *curaddr = '\0';
+ curaddr++;
+ }
+ (*n)++;
+ *endaddr = curaddr;
+
+ return (0);
+}
+
+static int
+smbios_type1_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size)
+{
+ struct smbios_table_type1 *type1;
+
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type1 = (struct smbios_table_type1 *)curaddr;
+
+ if (guest_uuid_str != NULL) {
+ uuid_t uuid;
+ uint32_t status;
+
+ uuid_from_string(guest_uuid_str, &uuid, &status);
+ if (status != uuid_s_ok)
+ return (-1);
+
+ uuid_enc_le(&type1->uuid, &uuid);
+ } else {
+ MD5_CTX mdctx;
+ u_char digest[16];
+ char hostname[MAXHOSTNAMELEN];
+
+ /*
+ * Universally unique and yet reproducible are an
+ * oxymoron, however reproducible is desirable in
+ * this case.
+ */
+ if (gethostname(hostname, sizeof(hostname)))
+ return (-1);
+
+ MD5Init(&mdctx);
+ MD5Update(&mdctx, vmname, strlen(vmname));
+ MD5Update(&mdctx, hostname, sizeof(hostname));
+ MD5Final(digest, &mdctx);
+
+ /*
+ * Set the variant and version number.
+ */
+ digest[6] &= 0x0F;
+ digest[6] |= 0x30; /* version 3 */
+ digest[8] &= 0x3F;
+ digest[8] |= 0x80;
+
+ memcpy(&type1->uuid, digest, sizeof (digest));
+ }
+
+ return (0);
+}
+
+static int
+smbios_type4_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size)
+{
+ int i;
+
+ for (i = 0; i < guest_ncpus; i++) {
+ struct smbios_table_type4 *type4;
+ char *p;
+ int nstrings, len;
+
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type4 = (struct smbios_table_type4 *)curaddr;
+ p = curaddr + sizeof (struct smbios_table_type4);
+ nstrings = 0;
+ while (p < *endaddr - 1) {
+ if (*p++ == '\0')
+ nstrings++;
+ }
+ len = sprintf(*endaddr - 1, "CPU #%d", i) + 1;
+ *endaddr += len - 1;
+ *(*endaddr) = '\0';
+ (*endaddr)++;
+ type4->socket = nstrings + 1;
+ curaddr = *endaddr;
+ }
+
+ return (0);
+}
+
+static int
+smbios_type16_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size)
+{
+ struct smbios_table_type16 *type16;
+
+ type16_handle = *n;
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type16 = (struct smbios_table_type16 *)curaddr;
+ type16->xsize = guest_lomem + guest_himem;
+ type16->ndevs = guest_himem > 0 ? 2 : 1;
+
+ return (0);
+}
+
+static int
+smbios_type17_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size)
+{
+ struct smbios_table_type17 *type17;
+
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type17 = (struct smbios_table_type17 *)curaddr;
+ type17->arrayhand = type16_handle;
+ type17->xsize = guest_lomem;
+
+ if (guest_himem > 0) {
+ curaddr = *endaddr;
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type17 = (struct smbios_table_type17 *)curaddr;
+ type17->arrayhand = type16_handle;
+ type17->xsize = guest_himem;
+ }
+
+ return (0);
+}
+
+static int
+smbios_type19_initializer(struct smbios_structure *template_entry,
+ const char **template_strings, char *curaddr, char **endaddr,
+ uint16_t *n, uint16_t *size)
+{
+ struct smbios_table_type19 *type19;
+
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type19 = (struct smbios_table_type19 *)curaddr;
+ type19->arrayhand = type16_handle;
+ type19->xsaddr = 0;
+ type19->xeaddr = guest_lomem;
+
+ if (guest_himem > 0) {
+ curaddr = *endaddr;
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n, size);
+ type19 = (struct smbios_table_type19 *)curaddr;
+ type19->arrayhand = type16_handle;
+ type19->xsaddr = 4*GB;
+ type19->xeaddr = guest_himem;
+ }
+
+ return (0);
+}
+
+static void
+smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
+{
+ memset(smbios_ep, 0, sizeof(*smbios_ep));
+ memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR,
+ SMBIOS_ENTRY_EANCHORLEN);
+ smbios_ep->eplen = 0x1F;
+ assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen);
+ smbios_ep->major = 2;
+ smbios_ep->minor = 4;
+ smbios_ep->revision = 0;
+ memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
+ SMBIOS_ENTRY_IANCHORLEN);
+ smbios_ep->staddr = staddr;
+ smbios_ep->bcdrev = 0x24;
+}
+
+static void
+smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len,
+ uint16_t num, uint16_t maxssize)
+{
+ uint8_t checksum;
+ int i;
+
+ smbios_ep->maxssize = maxssize;
+ smbios_ep->stlen = len;
+ smbios_ep->stnum = num;
+
+ checksum = 0;
+ for (i = 0x10; i < 0x1f; i++) {
+ checksum -= ((uint8_t *)smbios_ep)[i];
+ }
+ smbios_ep->ichecksum = checksum;
+
+ checksum = 0;
+ for (i = 0; i < 0x1f; i++) {
+ checksum -= ((uint8_t *)smbios_ep)[i];
+ }
+ smbios_ep->echecksum = checksum;
+}
+
+int
+smbios_build(struct vmctx *ctx)
+{
+ struct smbios_entry_point *smbios_ep;
+ uint16_t n;
+ uint16_t maxssize;
+ char *curaddr, *startaddr, *ststartaddr;
+ int i;
+ int err;
+
+ err = vm_get_memory_seg(ctx, 0, &guest_lomem, NULL);
+ if (err != 0)
+ return (err);
+
+ err = vm_get_memory_seg(ctx, 4*GB, &guest_himem, NULL);
+ if (err != 0)
+ return (err);
+
+ startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
+ if (startaddr == NULL) {
+ fprintf(stderr, "smbios table requires mapped mem\n");
+ return (ENOMEM);
+ }
+
+ curaddr = startaddr;
+
+ smbios_ep = (struct smbios_entry_point *)curaddr;
+ smbios_ep_initializer(smbios_ep, SMBIOS_BASE +
+ sizeof(struct smbios_entry_point));
+ curaddr += sizeof(struct smbios_entry_point);
+ ststartaddr = curaddr;
+
+ n = 0;
+ maxssize = 0;
+ for (i = 0; smbios_template[i].entry != NULL; i++) {
+ struct smbios_structure *entry;
+ const char **strings;
+ initializer_func_t initializer;
+ char *endaddr;
+ uint16_t size;
+
+ entry = smbios_template[i].entry;
+ strings = smbios_template[i].strings;
+ initializer = smbios_template[i].initializer;
+
+ err = (*initializer)(entry, strings, curaddr, &endaddr,
+ &n, &size);
+ if (err != 0)
+ return (err);
+
+ if (size > maxssize)
+ maxssize = size;
+
+ curaddr = endaddr;
+ }
+
+ assert(curaddr - startaddr < SMBIOS_MAX_LENGTH);
+ smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize);
+
+ return (0);
+}
diff --git a/usr.sbin/bhyve/atpic.c b/usr.sbin/bhyve/smbiostbl.h
index 5b4dd79..e8b3a4f 100644
--- a/usr.sbin/bhyve/atpic.c
+++ b/usr.sbin/bhyve/smbiostbl.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 NetApp, Inc.
+ * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * 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 NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -26,42 +26,11 @@
* $FreeBSD$
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+#ifndef _SMBIOSTBL_H_
+#define _SMBIOSTBL_H_
-#include <sys/param.h>
+struct vmctx;
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
+int smbios_build(struct vmctx *ctx);
-#include "inout.h"
-
-#define IO_ICU1 0x20
-#define IO_ICU2 0xA0
-#define ICU_IMR_OFFSET 1
-
-static int
-atpic_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
- uint32_t *eax, void *arg)
-{
- if (bytes != 1)
- return (-1);
-
- if (in) {
- if (port & ICU_IMR_OFFSET) {
- /* all interrupts masked */
- *eax = 0xff;
- } else {
- *eax = 0x00;
- }
- }
-
- /* Pretend all writes to the 8259 are alright */
- return (0);
-}
-
-INOUT_PORT(atpic, IO_ICU1, IOPORT_F_INOUT, atpic_handler);
-INOUT_PORT(atpic, IO_ICU1 + ICU_IMR_OFFSET, IOPORT_F_INOUT, atpic_handler);
-INOUT_PORT(atpic, IO_ICU2, IOPORT_F_INOUT, atpic_handler);
-INOUT_PORT(atpic, IO_ICU2 + ICU_IMR_OFFSET, IOPORT_F_INOUT, atpic_handler);
+#endif /* _SMBIOSTBL_H_ */
diff --git a/usr.sbin/bhyve/spinup_ap.c b/usr.sbin/bhyve/spinup_ap.c
index 2632aed..c597023 100644
--- a/usr.sbin/bhyve/spinup_ap.c
+++ b/usr.sbin/bhyve/spinup_ap.c
@@ -85,22 +85,7 @@ spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip)
error = vcpu_reset(ctx, newcpu);
assert(error == 0);
- /* Set up capabilities */
- if (fbsdrun_vmexit_on_hlt()) {
- error = vm_set_capability(ctx, newcpu, VM_CAP_HALT_EXIT, 1);
- assert(error == 0);
- }
-
- if (fbsdrun_vmexit_on_pause()) {
- error = vm_set_capability(ctx, newcpu, VM_CAP_PAUSE_EXIT, 1);
- assert(error == 0);
- }
-
- if (fbsdrun_disable_x2apic())
- error = vm_set_x2apic_state(ctx, newcpu, X2APIC_DISABLED);
- else
- error = vm_set_x2apic_state(ctx, newcpu, X2APIC_ENABLED);
- assert(error == 0);
+ fbsdrun_set_capabilities(ctx, newcpu);
/*
* Enable the 'unrestricted guest' mode for 'newcpu'.
@@ -113,7 +98,7 @@ spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip)
spinup_ap_realmode(ctx, newcpu, &rip);
- fbsdrun_addcpu(ctx, newcpu, rip);
+ fbsdrun_addcpu(ctx, vcpu, newcpu, rip);
return (newcpu);
}
diff --git a/usr.sbin/bhyve/uart_emul.c b/usr.sbin/bhyve/uart_emul.c
new file mode 100644
index 0000000..38e14a9
--- /dev/null
+++ b/usr.sbin/bhyve/uart_emul.c
@@ -0,0 +1,622 @@
+/*-
+ * Copyright (c) 2012 NetApp, Inc.
+ * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <dev/ic/ns16550.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "mevent.h"
+#include "uart_emul.h"
+
+#define COM1_BASE 0x3F8
+#define COM1_IRQ 4
+#define COM2_BASE 0x2F8
+#define COM2_IRQ 3
+
+#define DEFAULT_RCLK 1843200
+#define DEFAULT_BAUD 9600
+
+#define FCR_RX_MASK 0xC0
+
+#define MCR_OUT1 0x04
+#define MCR_OUT2 0x08
+
+#define MSR_DELTA_MASK 0x0f
+
+#ifndef REG_SCR
+#define REG_SCR com_scr
+#endif
+
+#define FIFOSZ 16
+
+static bool uart_stdio; /* stdio in use for i/o */
+static struct termios tio_stdio_orig;
+
+static struct {
+ int baseaddr;
+ int irq;
+ bool inuse;
+} uart_lres[] = {
+ { COM1_BASE, COM1_IRQ, false},
+ { COM2_BASE, COM2_IRQ, false},
+};
+
+#define UART_NLDEVS (sizeof(uart_lres) / sizeof(uart_lres[0]))
+
+struct fifo {
+ uint8_t buf[FIFOSZ];
+ int rindex; /* index to read from */
+ int windex; /* index to write to */
+ int num; /* number of characters in the fifo */
+ int size; /* size of the fifo */
+};
+
+struct ttyfd {
+ bool opened;
+ int fd; /* tty device file descriptor */
+ struct termios tio_orig, tio_new; /* I/O Terminals */
+};
+
+struct uart_softc {
+ pthread_mutex_t mtx; /* protects all softc elements */
+ uint8_t data; /* Data register (R/W) */
+ uint8_t ier; /* Interrupt enable register (R/W) */
+ uint8_t lcr; /* Line control register (R/W) */
+ uint8_t mcr; /* Modem control register (R/W) */
+ uint8_t lsr; /* Line status register (R/W) */
+ uint8_t msr; /* Modem status register (R/W) */
+ uint8_t fcr; /* FIFO control register (W) */
+ uint8_t scr; /* Scratch register (R/W) */
+
+ uint8_t dll; /* Baudrate divisor latch LSB */
+ uint8_t dlh; /* Baudrate divisor latch MSB */
+
+ struct fifo rxfifo;
+
+ struct ttyfd tty;
+ bool thre_int_pending; /* THRE interrupt pending */
+
+ void *arg;
+ uart_intr_func_t intr_assert;
+ uart_intr_func_t intr_deassert;
+};
+
+static void uart_drain(int fd, enum ev_type ev, void *arg);
+
+static void
+ttyclose(void)
+{
+
+ tcsetattr(STDIN_FILENO, TCSANOW, &tio_stdio_orig);
+}
+
+static void
+ttyopen(struct ttyfd *tf)
+{
+
+ tcgetattr(tf->fd, &tf->tio_orig);
+
+ tf->tio_new = tf->tio_orig;
+ cfmakeraw(&tf->tio_new);
+ tf->tio_new.c_cflag |= CLOCAL;
+ tcsetattr(tf->fd, TCSANOW, &tf->tio_new);
+
+ if (tf->fd == STDIN_FILENO) {
+ tio_stdio_orig = tf->tio_orig;
+ atexit(ttyclose);
+ }
+}
+
+static bool
+tty_char_available(struct ttyfd *tf)
+{
+ fd_set rfds;
+ struct timeval tv;
+
+ FD_ZERO(&rfds);
+ FD_SET(tf->fd, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ if (select(tf->fd + 1, &rfds, NULL, NULL, &tv) > 0 ) {
+ return (true);
+ } else {
+ return (false);
+ }
+}
+
+static int
+ttyread(struct ttyfd *tf)
+{
+ char rb;
+
+ if (tty_char_available(tf)) {
+ read(tf->fd, &rb, 1);
+ return (rb & 0xff);
+ } else {
+ return (-1);
+ }
+}
+
+static void
+ttywrite(struct ttyfd *tf, unsigned char wb)
+{
+
+ (void)write(tf->fd, &wb, 1);
+}
+
+static void
+fifo_reset(struct fifo *fifo, int size)
+{
+
+ bzero(fifo, sizeof(struct fifo));
+ fifo->size = size;
+}
+
+static int
+fifo_putchar(struct fifo *fifo, uint8_t ch)
+{
+
+ if (fifo->num < fifo->size) {
+ fifo->buf[fifo->windex] = ch;
+ fifo->windex = (fifo->windex + 1) % fifo->size;
+ fifo->num++;
+ return (0);
+ } else
+ return (-1);
+}
+
+static int
+fifo_getchar(struct fifo *fifo)
+{
+ int c;
+
+ if (fifo->num > 0) {
+ c = fifo->buf[fifo->rindex];
+ fifo->rindex = (fifo->rindex + 1) % fifo->size;
+ fifo->num--;
+ return (c);
+ } else
+ return (-1);
+}
+
+static int
+fifo_numchars(struct fifo *fifo)
+{
+
+ return (fifo->num);
+}
+
+static int
+fifo_available(struct fifo *fifo)
+{
+
+ return (fifo->num < fifo->size);
+}
+
+static void
+uart_opentty(struct uart_softc *sc)
+{
+ struct mevent *mev;
+
+ ttyopen(&sc->tty);
+ mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc);
+ assert(mev);
+}
+
+/*
+ * The IIR returns a prioritized interrupt reason:
+ * - receive data available
+ * - transmit holding register empty
+ * - modem status change
+ *
+ * Return an interrupt reason if one is available.
+ */
+static int
+uart_intr_reason(struct uart_softc *sc)
+{
+
+ if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0)
+ return (IIR_RLS);
+ else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0)
+ return (IIR_RXTOUT);
+ else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0)
+ return (IIR_TXRDY);
+ else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0)
+ return (IIR_MLSC);
+ else
+ return (IIR_NOPEND);
+}
+
+static void
+uart_reset(struct uart_softc *sc)
+{
+ uint16_t divisor;
+
+ divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16;
+ sc->dll = divisor;
+ sc->dlh = divisor >> 16;
+
+ fifo_reset(&sc->rxfifo, 1); /* no fifo until enabled by software */
+}
+
+/*
+ * Toggle the COM port's intr pin depending on whether or not we have an
+ * interrupt condition to report to the processor.
+ */
+static void
+uart_toggle_intr(struct uart_softc *sc)
+{
+ uint8_t intr_reason;
+
+ intr_reason = uart_intr_reason(sc);
+
+ if (intr_reason == IIR_NOPEND)
+ (*sc->intr_deassert)(sc->arg);
+ else
+ (*sc->intr_assert)(sc->arg);
+}
+
+static void
+uart_drain(int fd, enum ev_type ev, void *arg)
+{
+ struct uart_softc *sc;
+ int ch;
+
+ sc = arg;
+
+ assert(fd == sc->tty.fd);
+ assert(ev == EVF_READ);
+
+ /*
+ * This routine is called in the context of the mevent thread
+ * to take out the softc lock to protect against concurrent
+ * access from a vCPU i/o exit
+ */
+ pthread_mutex_lock(&sc->mtx);
+
+ if ((sc->mcr & MCR_LOOPBACK) != 0) {
+ (void) ttyread(&sc->tty);
+ } else {
+ while (fifo_available(&sc->rxfifo) &&
+ ((ch = ttyread(&sc->tty)) != -1)) {
+ fifo_putchar(&sc->rxfifo, ch);
+ }
+ uart_toggle_intr(sc);
+ }
+
+ pthread_mutex_unlock(&sc->mtx);
+}
+
+void
+uart_write(struct uart_softc *sc, int offset, uint8_t value)
+{
+ int fifosz;
+ uint8_t msr;
+
+ pthread_mutex_lock(&sc->mtx);
+
+ /*
+ * Take care of the special case DLAB accesses first
+ */
+ if ((sc->lcr & LCR_DLAB) != 0) {
+ if (offset == REG_DLL) {
+ sc->dll = value;
+ goto done;
+ }
+
+ if (offset == REG_DLH) {
+ sc->dlh = value;
+ goto done;
+ }
+ }
+
+ switch (offset) {
+ case REG_DATA:
+ if (sc->mcr & MCR_LOOPBACK) {
+ if (fifo_putchar(&sc->rxfifo, value) != 0)
+ sc->lsr |= LSR_OE;
+ } else if (sc->tty.opened) {
+ ttywrite(&sc->tty, value);
+ } /* else drop on floor */
+ sc->thre_int_pending = true;
+ break;
+ case REG_IER:
+ /*
+ * Apply mask so that bits 4-7 are 0
+ * Also enables bits 0-3 only if they're 1
+ */
+ sc->ier = value & 0x0F;
+ break;
+ case REG_FCR:
+ /*
+ * When moving from FIFO and 16450 mode and vice versa,
+ * the FIFO contents are reset.
+ */
+ if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) {
+ fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1;
+ fifo_reset(&sc->rxfifo, fifosz);
+ }
+
+ /*
+ * The FCR_ENABLE bit must be '1' for the programming
+ * of other FCR bits to be effective.
+ */
+ if ((value & FCR_ENABLE) == 0) {
+ sc->fcr = 0;
+ } else {
+ if ((value & FCR_RCV_RST) != 0)
+ fifo_reset(&sc->rxfifo, FIFOSZ);
+
+ sc->fcr = value &
+ (FCR_ENABLE | FCR_DMA | FCR_RX_MASK);
+ }
+ break;
+ case REG_LCR:
+ sc->lcr = value;
+ break;
+ case REG_MCR:
+ /* Apply mask so that bits 5-7 are 0 */
+ sc->mcr = value & 0x1F;
+
+ msr = 0;
+ if (sc->mcr & MCR_LOOPBACK) {
+ /*
+ * In the loopback mode certain bits from the
+ * MCR are reflected back into MSR
+ */
+ if (sc->mcr & MCR_RTS)
+ msr |= MSR_CTS;
+ if (sc->mcr & MCR_DTR)
+ msr |= MSR_DSR;
+ if (sc->mcr & MCR_OUT1)
+ msr |= MSR_RI;
+ if (sc->mcr & MCR_OUT2)
+ msr |= MSR_DCD;
+ }
+
+ /*
+ * Detect if there has been any change between the
+ * previous and the new value of MSR. If there is
+ * then assert the appropriate MSR delta bit.
+ */
+ if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS))
+ sc->msr |= MSR_DCTS;
+ if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR))
+ sc->msr |= MSR_DDSR;
+ if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD))
+ sc->msr |= MSR_DDCD;
+ if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0)
+ sc->msr |= MSR_TERI;
+
+ /*
+ * Update the value of MSR while retaining the delta
+ * bits.
+ */
+ sc->msr &= MSR_DELTA_MASK;
+ sc->msr |= msr;
+ break;
+ case REG_LSR:
+ /*
+ * Line status register is not meant to be written to
+ * during normal operation.
+ */
+ break;
+ case REG_MSR:
+ /*
+ * As far as I can tell MSR is a read-only register.
+ */
+ break;
+ case REG_SCR:
+ sc->scr = value;
+ break;
+ default:
+ break;
+ }
+
+done:
+ uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
+}
+
+uint8_t
+uart_read(struct uart_softc *sc, int offset)
+{
+ uint8_t iir, intr_reason, reg;
+
+ pthread_mutex_lock(&sc->mtx);
+
+ /*
+ * Take care of the special case DLAB accesses first
+ */
+ if ((sc->lcr & LCR_DLAB) != 0) {
+ if (offset == REG_DLL) {
+ reg = sc->dll;
+ goto done;
+ }
+
+ if (offset == REG_DLH) {
+ reg = sc->dlh;
+ goto done;
+ }
+ }
+
+ switch (offset) {
+ case REG_DATA:
+ reg = fifo_getchar(&sc->rxfifo);
+ break;
+ case REG_IER:
+ reg = sc->ier;
+ break;
+ case REG_IIR:
+ iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0;
+
+ intr_reason = uart_intr_reason(sc);
+
+ /*
+ * Deal with side effects of reading the IIR register
+ */
+ if (intr_reason == IIR_TXRDY)
+ sc->thre_int_pending = false;
+
+ iir |= intr_reason;
+
+ reg = iir;
+ break;
+ case REG_LCR:
+ reg = sc->lcr;
+ break;
+ case REG_MCR:
+ reg = sc->mcr;
+ break;
+ case REG_LSR:
+ /* Transmitter is always ready for more data */
+ sc->lsr |= LSR_TEMT | LSR_THRE;
+
+ /* Check for new receive data */
+ if (fifo_numchars(&sc->rxfifo) > 0)
+ sc->lsr |= LSR_RXRDY;
+ else
+ sc->lsr &= ~LSR_RXRDY;
+
+ reg = sc->lsr;
+
+ /* The LSR_OE bit is cleared on LSR read */
+ sc->lsr &= ~LSR_OE;
+ break;
+ case REG_MSR:
+ /*
+ * MSR delta bits are cleared on read
+ */
+ reg = sc->msr;
+ sc->msr &= ~MSR_DELTA_MASK;
+ break;
+ case REG_SCR:
+ reg = sc->scr;
+ break;
+ default:
+ reg = 0xFF;
+ break;
+ }
+
+done:
+ uart_toggle_intr(sc);
+ pthread_mutex_unlock(&sc->mtx);
+
+ return (reg);
+}
+
+int
+uart_legacy_alloc(int which, int *baseaddr, int *irq)
+{
+
+ if (which < 0 || which >= UART_NLDEVS || uart_lres[which].inuse)
+ return (-1);
+
+ uart_lres[which].inuse = true;
+ *baseaddr = uart_lres[which].baseaddr;
+ *irq = uart_lres[which].irq;
+
+ return (0);
+}
+
+struct uart_softc *
+uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert,
+ void *arg)
+{
+ struct uart_softc *sc;
+
+ sc = calloc(1, sizeof(struct uart_softc));
+
+ sc->arg = arg;
+ sc->intr_assert = intr_assert;
+ sc->intr_deassert = intr_deassert;
+
+ pthread_mutex_init(&sc->mtx, NULL);
+
+ uart_reset(sc);
+
+ return (sc);
+}
+
+static int
+uart_tty_backend(struct uart_softc *sc, const char *opts)
+{
+ int fd;
+ int retval;
+
+ retval = -1;
+
+ fd = open(opts, O_RDWR | O_NONBLOCK);
+ if (fd > 0 && isatty(fd)) {
+ sc->tty.fd = fd;
+ sc->tty.opened = true;
+ retval = 0;
+ }
+
+ return (retval);
+}
+
+int
+uart_set_backend(struct uart_softc *sc, const char *opts)
+{
+ int retval;
+
+ retval = -1;
+
+ if (opts == NULL)
+ return (0);
+
+ if (strcmp("stdio", opts) == 0) {
+ if (!uart_stdio) {
+ sc->tty.fd = STDIN_FILENO;
+ sc->tty.opened = true;
+ uart_stdio = true;
+ retval = 0;
+ }
+ } else if (uart_tty_backend(sc, opts) == 0) {
+ retval = 0;
+ }
+
+ if (retval == 0)
+ uart_opentty(sc);
+
+ return (retval);
+}
diff --git a/usr.sbin/bhyve/pit_8254.h b/usr.sbin/bhyve/uart_emul.h
index 61bd15d..993b92e 100644
--- a/usr.sbin/bhyve/pit_8254.h
+++ b/usr.sbin/bhyve/uart_emul.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2011 NetApp, Inc.
+ * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,20 +26,20 @@
* $FreeBSD$
*/
-#ifndef _PIT_8254_H_
-#define _PIT_8254_H_
+#ifndef _UART_EMUL_H_
+#define _UART_EMUL_H_
-/*
- * Borrowed from amd64/include/timerreg.h because in that file it is
- * conditionally compiled for #ifdef _KERNEL only.
- */
-#include <dev/ic/i8253reg.h>
+#define UART_IO_BAR_SIZE 8
+
+struct uart_softc;
-#define IO_TIMER1 0x40 /* 8253 Timer #1 */
-#define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0)
-#define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1)
-#define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2)
-#define TIMER_MODE (IO_TIMER1 + TIMER_REG_MODE)
+typedef void (*uart_intr_func_t)(void *arg);
+struct uart_softc *uart_init(uart_intr_func_t intr_assert,
+ uart_intr_func_t intr_deassert, void *arg);
-#endif /* _PIT_8254_H_ */
+int uart_legacy_alloc(int unit, int *ioaddr, int *irq);
+uint8_t uart_read(struct uart_softc *sc, int offset);
+void uart_write(struct uart_softc *sc, int offset, uint8_t value);
+int uart_set_backend(struct uart_softc *sc, const char *opt);
+#endif
diff --git a/usr.sbin/bhyve/virtio.c b/usr.sbin/bhyve/virtio.c
index c26272b..4e58dd6 100644
--- a/usr.sbin/bhyve/virtio.c
+++ b/usr.sbin/bhyve/virtio.c
@@ -99,7 +99,11 @@ vi_reset_dev(struct virtio_softc *vs)
vs->vs_negotiated_caps = 0;
vs->vs_curq = 0;
/* vs->vs_status = 0; -- redundant */
+ VS_LOCK(vs);
+ if (vs->vs_isr)
+ pci_lintr_deassert(vs->vs_pi);
vs->vs_isr = 0;
+ VS_UNLOCK(vs);
vs->vs_msix_cfg_idx = VIRTIO_MSI_NO_VECTOR;
}
@@ -137,11 +141,10 @@ vi_intr_init(struct virtio_softc *vs, int barnum, int use_msix)
nvec = vs->vs_vc->vc_nvq + 1;
if (pci_emul_add_msixcap(vs->vs_pi, nvec, barnum))
return (1);
- } else {
+ } else
vs->vs_flags &= ~VIRTIO_USE_MSIX;
- /* Only 1 MSI vector for bhyve */
- pci_emul_add_msicap(vs->vs_pi, 1);
- }
+ /* Only 1 MSI vector for bhyve */
+ pci_emul_add_msicap(vs->vs_pi, 1);
return (0);
}
@@ -160,7 +163,7 @@ vi_vq_init(struct virtio_softc *vs, uint32_t pfn)
vq = &vs->vs_queues[vs->vs_curq];
vq->vq_pfn = pfn;
- phys = pfn << VRING_PFN;
+ phys = (uint64_t)pfn << VRING_PFN;
size = vring_size(vq->vq_qsize);
base = paddr_guest2host(vs->vs_pi->pi_vmctx, phys, size);
@@ -591,6 +594,8 @@ bad:
case VTCFG_R_ISR:
value = vs->vs_isr;
vs->vs_isr = 0; /* a read clears this flag */
+ if (value)
+ pci_lintr_deassert(pi);
break;
case VTCFG_R_CFGVEC:
value = vs->vs_msix_cfg_idx;
diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h
index 8975bf7..01b5f7b 100644
--- a/usr.sbin/bhyve/virtio.h
+++ b/usr.sbin/bhyve/virtio.h
@@ -33,7 +33,7 @@
* These are derived from several virtio specifications.
*
* Some useful links:
- * https://github.com/rustyrussel/virtio-spec
+ * https://github.com/rustyrussell/virtio-spec
* http://people.redhat.com/pbonzini/virtio-spec.pdf
*/
@@ -209,6 +209,7 @@ struct vring_used {
#define VIRTIO_VENDOR 0x1AF4
#define VIRTIO_DEV_NET 0x1000
#define VIRTIO_DEV_BLOCK 0x1001
+#define VIRTIO_DEV_RANDOM 0x1002
/*
* PCI config space constants.
@@ -328,6 +329,18 @@ struct virtio_softc {
uint16_t vs_msix_cfg_idx; /* MSI-X vector for config event */
};
+#define VS_LOCK(vs) \
+do { \
+ if (vs->vs_mtx) \
+ pthread_mutex_lock(vs->vs_mtx); \
+} while (0)
+
+#define VS_UNLOCK(vs) \
+do { \
+ if (vs->vs_mtx) \
+ pthread_mutex_unlock(vs->vs_mtx); \
+} while (0)
+
struct virtio_consts {
const char *vc_name; /* name of driver (for diagnostics) */
int vc_nvq; /* number of virtual queues */
@@ -431,11 +444,14 @@ static inline void
vq_interrupt(struct virtio_softc *vs, struct vqueue_info *vq)
{
- if (vs->vs_flags & VIRTIO_USE_MSIX)
+ if (pci_msix_enabled(vs->vs_pi))
pci_generate_msix(vs->vs_pi, vq->vq_msix_idx);
else {
+ VS_LOCK(vs);
vs->vs_isr |= VTCFG_ISR_QUEUES;
pci_generate_msi(vs->vs_pi, 0);
+ pci_lintr_assert(vs->vs_pi);
+ VS_UNLOCK(vs);
}
}
diff --git a/usr.sbin/bhyve/xmsr.c b/usr.sbin/bhyve/xmsr.c
index 9c05f02..ba94125 100644
--- a/usr.sbin/bhyve/xmsr.c
+++ b/usr.sbin/bhyve/xmsr.c
@@ -43,6 +43,19 @@ int
emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val)
{
- printf("Unknown WRMSR code %x, val %lx, cpu %d\n", code, val, vcpu);
- exit(1);
+ switch (code) {
+ case 0xd04: /* Sandy Bridge uncore PMC MSRs */
+ case 0xc24:
+ return (0);
+ default:
+ break;
+ }
+ return (-1);
+}
+
+int
+emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val)
+{
+
+ return (-1);
}
diff --git a/usr.sbin/bhyve/xmsr.h b/usr.sbin/bhyve/xmsr.h
index 8cebcea..b097cf8 100644
--- a/usr.sbin/bhyve/xmsr.h
+++ b/usr.sbin/bhyve/xmsr.h
@@ -30,5 +30,6 @@
#define _XMSR_H_
int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val);
+int emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val);
#endif
diff --git a/usr.sbin/bhyvectl/Makefile b/usr.sbin/bhyvectl/Makefile
index df3f19c..5f879fe 100644
--- a/usr.sbin/bhyvectl/Makefile
+++ b/usr.sbin/bhyvectl/Makefile
@@ -5,7 +5,7 @@
PROG= bhyvectl
SRCS= bhyvectl.c
-NO_MAN=
+MAN=
DPADD= ${LIBVMMAPI} ${LIBUTIL}
LDADD= -lvmmapi -lutil
diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c
index d6b32b8..2e732b5 100644
--- a/usr.sbin/bhyvectl/bhyvectl.c
+++ b/usr.sbin/bhyvectl/bhyvectl.c
@@ -189,12 +189,15 @@ usage(void)
" [--set-mem=<memory in units of MB>]\n"
" [--get-lowmem]\n"
" [--get-highmem]\n"
- " [--get-gpa-pmap]\n",
+ " [--get-gpa-pmap]\n"
+ " [--assert-lapic-lvt=<pin>]\n"
+ " [--inject-nmi]\n",
progname);
exit(1);
}
static int get_stats, getcap, setcap, capval, get_gpa_pmap;
+static int inject_nmi, assert_lapic_lvt;
static const char *capname;
static int create, destroy, get_lowmem, get_highmem;
static uint64_t memsize;
@@ -270,11 +273,13 @@ dump_vm_run_exitcode(struct vm_exit *vmexit, int vcpu)
break;
case VM_EXITCODE_VMX:
printf("\treason\t\tVMX\n");
- printf("\terror\t\t%d\n", vmexit->u.vmx.error);
+ printf("\tstatus\t\t%d\n", vmexit->u.vmx.status);
printf("\texit_reason\t0x%08x (%u)\n",
vmexit->u.vmx.exit_reason, vmexit->u.vmx.exit_reason);
printf("\tqualification\t0x%016lx\n",
vmexit->u.vmx.exit_qualification);
+ printf("\tinst_type\t\t%d\n", vmexit->u.vmx.inst_type);
+ printf("\tinst_error\t\t%d\n", vmexit->u.vmx.inst_error);
break;
default:
printf("*** unknown vm run exitcode %d\n", vmexit->exitcode);
@@ -379,6 +384,7 @@ enum {
CAPNAME,
UNASSIGN_PPTDEV,
GET_GPA_PMAP,
+ ASSERT_LAPIC_LVT,
};
int
@@ -431,6 +437,7 @@ main(int argc, char *argv[])
{ "unassign-pptdev", REQ_ARG, 0, UNASSIGN_PPTDEV },
{ "setcap", REQ_ARG, 0, SET_CAP },
{ "get-gpa-pmap", REQ_ARG, 0, GET_GPA_PMAP },
+ { "assert-lapic-lvt", REQ_ARG, 0, ASSERT_LAPIC_LVT },
{ "getcap", NO_ARG, &getcap, 1 },
{ "get-stats", NO_ARG, &get_stats, 1 },
{ "get-desc-ds",NO_ARG, &get_desc_ds, 1 },
@@ -557,10 +564,13 @@ main(int argc, char *argv[])
{ "run", NO_ARG, &run, 1 },
{ "create", NO_ARG, &create, 1 },
{ "destroy", NO_ARG, &destroy, 1 },
+ { "inject-nmi", NO_ARG, &inject_nmi, 1 },
{ NULL, 0, NULL, 0 }
};
vcpu = 0;
+ vmname = NULL;
+ assert_lapic_lvt = -1;
progname = basename(argv[0]);
while ((ch = getopt_long(argc, argv, "", opts, NULL)) != -1) {
@@ -682,6 +692,9 @@ main(int argc, char *argv[])
if (sscanf(optarg, "%d/%d/%d", &bus, &slot, &func) != 3)
usage();
break;
+ case ASSERT_LAPIC_LVT:
+ assert_lapic_lvt = atoi(optarg);
+ break;
default:
usage();
}
@@ -825,6 +838,14 @@ main(int argc, char *argv[])
vmcs_entry_interruption_info);
}
+ if (!error && inject_nmi) {
+ error = vm_inject_nmi(ctx, vcpu);
+ }
+
+ if (!error && assert_lapic_lvt != -1) {
+ error = vm_lapic_local_irq(ctx, vcpu, assert_lapic_lvt);
+ }
+
if (!error && (get_lowmem || get_all)) {
gpa = 0;
error = vm_get_memory_seg(ctx, gpa, &len, &wired);
@@ -1433,8 +1454,7 @@ main(int argc, char *argv[])
}
if (!error && (get_vmcs_exit_interruption_info || get_all)) {
- error = vm_get_vmcs_field(ctx, vcpu,
- VMCS_EXIT_INTERRUPTION_INFO, &u64);
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_INTR_INFO, &u64);
if (error == 0) {
printf("vmcs_exit_interruption_info[%d]\t0x%08lx\n",
vcpu, u64);
@@ -1442,8 +1462,8 @@ main(int argc, char *argv[])
}
if (!error && (get_vmcs_exit_interruption_error || get_all)) {
- error = vm_get_vmcs_field(ctx, vcpu,
- VMCS_EXIT_INTERRUPTION_ERROR, &u64);
+ error = vm_get_vmcs_field(ctx, vcpu, VMCS_EXIT_INTR_ERRCODE,
+ &u64);
if (error == 0) {
printf("vmcs_exit_interruption_error[%d]\t0x%08lx\n",
vcpu, u64);
@@ -1495,6 +1515,7 @@ main(int argc, char *argv[])
vm_capability_type2name(captype),
val ? "set" : "not set", vcpu);
} else if (errno == ENOENT) {
+ error = 0;
printf("Capability \"%s\" is not available\n",
vm_capability_type2name(captype));
} else {
diff --git a/usr.sbin/bhyveload/bhyveload.8 b/usr.sbin/bhyveload/bhyveload.8
index 2efcad0..3a300cc 100644
--- a/usr.sbin/bhyveload/bhyveload.8
+++ b/usr.sbin/bhyveload/bhyveload.8
@@ -38,6 +38,8 @@ guest inside a bhyve virtual machine
.Op Fl m Ar mem-size
.Op Fl d Ar disk-path
.Op Fl h Ar host-path
+.Op Fl e Ar name=value
+.Op Fl c Ar cons-dev
.Ar vmname
.Sh DESCRIPTION
.Nm
@@ -91,6 +93,24 @@ is the pathname of the guest's boot disk image.
The
.Ar host-path
is the directory at the top of the guest's boot filesystem.
+.It Fl e Ar name=value
+Set the FreeBSD loader environment variable
+.Ar name
+to
+.Ar value .
+.Pp
+The option may be used more than once to set more than one environment
+variable.
+.It Fl c Ar cons-dev
+.Ar cons-dev
+is a
+.Xr tty 4
+device to use for
+.Nm
+terminal I/O.
+.Pp
+The text string "stdio" is also accepted and selects the use of
+unbuffered standard I/O. This is the default value.
.El
.Sh EXAMPLES
To create a virtual machine named
@@ -100,11 +120,24 @@ that boots off the ISO image
and has 1GB memory allocated to it:
.Pp
.Dl "bhyveload -m 1G -d /freebsd/release.iso freebsd-vm"
+.Pp
+To create a virtual machine named
+.Ar test-vm
+with 256MB of memory allocated, the guest root filesystem under the host
+directory
+.Pa /user/images/test
+and terminal I/O sent to the
+.Xr nmdm 4
+device
+.Pa /dev/nmdm1B
+.Pp
+.Dl "bhyveload -m 256MB -h /usr/images/test -c /dev/nmdm1B test-vm"
.Sh SEE ALSO
.Xr bhyve 4 ,
+.Xr nmdm 4 ,
+.Xr vmm 4 ,
.Xr bhyve 8 ,
-.Xr loader 8 ,
-.Xr vmm 4
+.Xr loader 8
.Sh HISTORY
.Nm
first appeared in
diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c
index 6e541e8..c1a5432 100644
--- a/usr.sbin/bhyveload/bhyveload.c
+++ b/usr.sbin/bhyveload/bhyveload.c
@@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/disk.h>
+#include <sys/queue.h>
#include <machine/specialreg.h>
#include <machine/vmm.h>
@@ -70,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <fcntl.h>
#include <getopt.h>
+#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -86,9 +88,13 @@ __FBSDID("$FreeBSD$");
#define GB (1024 * 1024 * 1024UL)
#define BSP 0
-static char *host_base = "/";
+#define NDISKS 32
+
+static char *host_base;
static struct termios term, oldterm;
-static int disk_fd = -1;
+static int disk_fd[NDISKS];
+static int ndisks;
+static int consin_fd, consout_fd;
static char *vmname, *progname;
static struct vmctx *ctx;
@@ -106,7 +112,7 @@ cb_putc(void *arg, int ch)
{
char c = ch;
- write(1, &c, 1);
+ (void) write(consout_fd, &c, 1);
}
static int
@@ -114,7 +120,7 @@ cb_getc(void *arg)
{
char c;
- if (read(0, &c, 1) == 1)
+ if (read(consin_fd, &c, 1) == 1)
return (c);
return (-1);
}
@@ -124,7 +130,7 @@ cb_poll(void *arg)
{
int n;
- if (ioctl(0, FIONREAD, &n) >= 0)
+ if (ioctl(consin_fd, FIONREAD, &n) >= 0)
return (n > 0);
return (0);
}
@@ -284,9 +290,9 @@ cb_diskread(void *arg, int unit, uint64_t from, void *to, size_t size,
{
ssize_t n;
- if (unit != 0 || disk_fd == -1)
+ if (unit < 0 || unit >= ndisks )
return (EIO);
- n = pread(disk_fd, to, size, from);
+ n = pread(disk_fd[unit], to, size, from);
if (n < 0)
return (errno);
*resid = size - n;
@@ -298,7 +304,7 @@ cb_diskioctl(void *arg, int unit, u_long cmd, void *data)
{
struct stat sb;
- if (unit != 0 || disk_fd == -1)
+ if (unit < 0 || unit >= ndisks)
return (EBADF);
switch (cmd) {
@@ -306,7 +312,7 @@ cb_diskioctl(void *arg, int unit, u_long cmd, void *data)
*(u_int *)data = 512;
break;
case DIOCGMEDIASIZE:
- if (fstat(disk_fd, &sb) == 0)
+ if (fstat(disk_fd[unit], &sb) == 0)
*(off_t *)data = sb.st_size;
else
return (ENOTTY);
@@ -462,7 +468,12 @@ cb_exec(void *arg, uint64_t rip)
{
int error;
- error = vm_setup_freebsd_registers(ctx, BSP, rip, cr3, gdtbase, rsp);
+ if (cr3 == 0)
+ error = vm_setup_freebsd_registers_i386(ctx, BSP, rip, gdtbase,
+ rsp);
+ else
+ error = vm_setup_freebsd_registers(ctx, BSP, rip, cr3, gdtbase,
+ rsp);
if (error) {
perror("vm_setup_freebsd_registers");
cb_exit(NULL, USERBOOT_EXIT_QUIT);
@@ -486,7 +497,7 @@ static void
cb_exit(void *arg, int v)
{
- tcsetattr(0, TCSAFLUSH, &oldterm);
+ tcsetattr(consout_fd, TCSAFLUSH, &oldterm);
exit(v);
}
@@ -498,23 +509,37 @@ cb_getmem(void *arg, uint64_t *ret_lowmem, uint64_t *ret_highmem)
vm_get_memory_seg(ctx, 4 * GB, ret_highmem, NULL);
}
-static const char *
-cb_getenv(void *arg, int num)
+struct env {
+ const char *str; /* name=value */
+ SLIST_ENTRY(env) next;
+};
+
+static SLIST_HEAD(envhead, env) envhead;
+
+static void
+addenv(const char *str)
{
- int max;
+ struct env *env;
- static const char * var[] = {
- "smbios.bios.vendor=BHYVE",
- "boot_serial=1",
- NULL
- };
+ env = malloc(sizeof(struct env));
+ env->str = str;
+ SLIST_INSERT_HEAD(&envhead, env, next);
+}
- max = sizeof(var) / sizeof(var[0]);
+static const char *
+cb_getenv(void *arg, int num)
+{
+ int i;
+ struct env *env;
+
+ i = 0;
+ SLIST_FOREACH(env, &envhead, next) {
+ if (i == num)
+ return (env->str);
+ i++;
+ }
- if (num < max)
- return (var[num]);
- else
- return (NULL);
+ return (NULL);
}
static struct loader_callbacks cb = {
@@ -548,13 +573,66 @@ static struct loader_callbacks cb = {
.getenv = cb_getenv,
};
+static int
+altcons_open(char *path)
+{
+ struct stat sb;
+ int err;
+ int fd;
+
+ /*
+ * Allow stdio to be passed in so that the same string
+ * can be used for the bhyveload console and bhyve com-port
+ * parameters
+ */
+ if (!strcmp(path, "stdio"))
+ return (0);
+
+ err = stat(path, &sb);
+ if (err == 0) {
+ if (!S_ISCHR(sb.st_mode))
+ err = ENOTSUP;
+ else {
+ fd = open(path, O_RDWR | O_NONBLOCK);
+ if (fd < 0)
+ err = errno;
+ else
+ consin_fd = consout_fd = fd;
+ }
+ }
+
+ return (err);
+}
+
+static int
+disk_open(char *path)
+{
+ int err, fd;
+
+ if (ndisks > NDISKS)
+ return (ERANGE);
+
+ err = 0;
+ fd = open(path, O_RDONLY);
+
+ if (fd > 0) {
+ disk_fd[ndisks] = fd;
+ ndisks++;
+ } else
+ err = errno;
+
+ return (err);
+}
+
static void
usage(void)
{
fprintf(stderr,
- "usage: %s [-m mem-size][-d <disk-path>] [-h <host-path>] "
- "<vmname>\n", progname);
+ "usage: %s [-m mem-size] [-d <disk-path>] [-h <host-path>]\n"
+ " %*s [-e <name=value>] [-c <console-device>] <vmname>\n",
+ progname,
+ (int)strlen(progname), "");
exit(1);
}
@@ -565,17 +643,30 @@ main(int argc, char** argv)
void (*func)(struct loader_callbacks *, void *, int, int);
uint64_t mem_size;
int opt, error;
- char *disk_image;
- progname = argv[0];
+ progname = basename(argv[0]);
mem_size = 256 * MB;
- disk_image = NULL;
- while ((opt = getopt(argc, argv, "d:h:m:")) != -1) {
+ consin_fd = STDIN_FILENO;
+ consout_fd = STDOUT_FILENO;
+
+ while ((opt = getopt(argc, argv, "c:d:e:h:m:")) != -1) {
switch (opt) {
+ case 'c':
+ error = altcons_open(optarg);
+ if (error != 0)
+ errx(EX_USAGE, "Could not open '%s'", optarg);
+ break;
+
case 'd':
- disk_image = optarg;
+ error = disk_open(optarg);
+ if (error != 0)
+ errx(EX_USAGE, "Could not open '%s'", optarg);
+ break;
+
+ case 'e':
+ addenv(optarg);
break;
case 'h':
@@ -619,11 +710,13 @@ main(int argc, char** argv)
exit(1);
}
- tcgetattr(0, &term);
+ tcgetattr(consout_fd, &term);
oldterm = term;
- term.c_lflag &= ~(ICANON|ECHO);
- term.c_iflag &= ~ICRNL;
- tcsetattr(0, TCSAFLUSH, &term);
+ cfmakeraw(&term);
+ term.c_cflag |= CLOCAL;
+
+ tcsetattr(consout_fd, TCSAFLUSH, &term);
+
h = dlopen("/boot/userboot.so", RTLD_LOCAL);
if (!h) {
printf("%s\n", dlerror());
@@ -635,8 +728,8 @@ main(int argc, char** argv)
return (1);
}
- if (disk_image) {
- disk_fd = open(disk_image, O_RDONLY);
- }
- func(&cb, NULL, USERBOOT_VERSION_3, disk_fd >= 0);
+ addenv("smbios.bios.vendor=BHYVE");
+ addenv("boot_serial=1");
+
+ func(&cb, NULL, USERBOOT_VERSION_3, ndisks);
}
diff --git a/usr.sbin/binmiscctl/Makefile b/usr.sbin/binmiscctl/Makefile
new file mode 100644
index 0000000..f2c2870
--- /dev/null
+++ b/usr.sbin/binmiscctl/Makefile
@@ -0,0 +1,10 @@
+#
+# $FreeBSD$
+#
+
+.include <bsd.own.mk>
+
+PROG= binmiscctl
+MAN= binmiscctl.8
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/binmiscctl/binmiscctl.8 b/usr.sbin/binmiscctl/binmiscctl.8
new file mode 100644
index 0000000..646a5a3
--- /dev/null
+++ b/usr.sbin/binmiscctl/binmiscctl.8
@@ -0,0 +1,196 @@
+.\"-
+.\" Copyright (c) 2013 Stacey D. Son
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.\" Support for miscellaneous binary image activators
+.\"
+.Dd April 10, 2014
+.Dt BINMISCCTL 8
+.Os
+.Sh NAME
+.Nm binmiscctl
+.Nd manage binary image activators
+.Sh SYNOPSIS
+.Nm
+.Cm add
+.Ar name
+.Cm --interpreter
+.Ar path
+.Cm --magic
+.Ar magic
+.Cm --size
+.Ar size
+.Op Cm --mask Ar mask
+.Op Cm --offset Ar offset
+.Op Cm --set-enabled
+.Nm
+.Cm remove
+.Ar name
+.Nm
+.Cm disable
+.Ar name
+.Nm
+.Cm enable
+.Ar name
+.Nm
+.Cm lookup
+.Ar name
+.Nm
+.Cm list
+.Sh DESCRIPTION
+The
+.Nm
+utility
+is the management utility for configuring miscellaneous binaries image
+activators in the kernel.
+It allows adding, deleting, disabling,
+enabling, and looking up interpreters.
+Also, all the interpreters can
+be listed.
+.Pp
+The first argument on the command line indicates the operation to be
+performed.
+Operation must be one of the following:
+.Bl -tag -width indent
+.It Xo
+.Cm add
+.Ar name
+.Cm --interpreter
+.Ar path
+.Cm --magic
+.Ar magic
+.Cm --size
+.Ar size
+.Op Cm --mask Ar mask
+.Op Cm --offset Ar offset
+.Op Cm --set-enabled
+.Xc
+Add a new activator entry in the kernel.
+You must specify a
+unique
+.Ar name,
+interpreter path and its arguments
+.Ar path,
+header
+.Ar magic
+bytes that uniquely identify a suitable binary for the activator,
+and the
+.Ar size
+of the
+.Ar magic
+in bytes.
+.Pp
+Optionally you may specify a
+.Ar mask
+to do a bitwise AND with the header bytes.
+This effectively allows you to ignore fields in the binary header that
+do not uniquely indentify the binary file's type.
+.Pp
+An
+.Ar offset
+may be specified for the magic bytes using the
+.Cm --offset
+option.
+By default the
+.Ar offset
+is zero.
+.Pp
+To enable the activator entry the
+.Cm --set-enabled
+option is used.
+The activator default state is disabled.
+.Pp
+The interpreter
+.Ar path
+may also contain arguments for the interpreter including
+.Ar #a
+which gets replaced by the old
+.Dv argv0
+value in the interpreter string.
+.It Cm remove Ar name
+Remove the activator entry identified with
+.Ar name .
+.It Cm disable Ar name
+Disable the activator entry identified with
+.Ar name .
+.It Cm enable Ar name
+Enable the activator entry identified with
+.Ar name .
+.It Cm lookup Ar name
+Look up and print out the activator entry identified with
+.Ar name .
+.It Cm list
+Take a snapshot and print all the activator entries currently configured.
+.El
+.Sh EXAMPLES
+.Bl
+# binmiscctl add llvmbc --interpreter ''/usr/bin/lli --fake-argv0=#a'' \\
+ --magic ''BC\\xc0\\xde'' --size 4 --set-enabled
+.El
+.Pp
+Add an image activator to run the LLVM interpreter (lli) on bitcode
+compiled files.
+.Ar #a
+gets replaced with the old
+.Dv argv0
+value so that 'lli' can fake its
+.Dv argv0 .
+Set its state to enabled.
+.Pp
+.Dl # binmiscctl disable llvmbc
+.Pp
+Set the state of the
+.Ar llvmbc
+image activator to disabled.
+.Pp
+.Dl # binmiscctl enable llvmbc
+.Pp
+Set the state of the
+.Ar llvmbc
+image activator to enabled.
+.Pp
+.Dl # binmiscctl remove llvmbc
+.Pp
+Delete the
+.Ar llvmbc
+image activator.
+.Pp
+.Dl # binmiscctl lookup llvmbc
+.Pp
+Look up and list the record for the
+.Ar llvmbc
+image activator.
+.Sh SEE ALSO
+.Xr lli 1 ,
+.Xr execve 2
+.Sh HISTORY
+The
+.Cm binmiscctl
+command was added in
+.Fx 10.1 .
+It was developed to support the imgact_binmisc kernel module.
+.Sh AUTHORS
+Stacey D Son
diff --git a/usr.sbin/binmiscctl/binmiscctl.c b/usr.sbin/binmiscctl/binmiscctl.c
new file mode 100644
index 0000000..436e761
--- /dev/null
+++ b/usr.sbin/binmiscctl/binmiscctl.c
@@ -0,0 +1,508 @@
+/*-
+ * Copyright (c) 2013 Stacey D. Son
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/imgact_binmisc.h>
+#include <sys/linker.h>
+#include <sys/sysctl.h>
+
+enum cmd {
+ CMD_ADD = 0,
+ CMD_REMOVE,
+ CMD_DISABLE,
+ CMD_ENABLE,
+ CMD_LOOKUP,
+ CMD_LIST,
+};
+
+extern char *__progname;
+
+typedef int (*cmd_func_t)(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
+
+int add_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
+int name_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
+int noname_cmd(int argc, char *argv[], ximgact_binmisc_entry_t *xbe);
+
+static const struct {
+ const int token;
+ const char *name;
+ cmd_func_t func;
+ const char *desc;
+ const char *args;
+} cmds[] = {
+ {
+ CMD_ADD,
+ "add",
+ add_cmd,
+ "Add a new binary image activator (requires 'root' privilege)",
+ "<name> --interpreter <path_and_arguments> \\\n"
+ "\t\t--magic <magic_bytes> [--mask <mask_bytes>] \\\n"
+ "\t\t--size <magic_size> [--offset <magic_offset>] \\\n"
+ "\t\t[--set-enabled]"
+ },
+ {
+ CMD_REMOVE,
+ "remove",
+ name_cmd,
+ "Remove a binary image activator (requires 'root' privilege)",
+ "<name>"
+ },
+ {
+ CMD_DISABLE,
+ "disable",
+ name_cmd,
+ "Disable a binary image activator (requires 'root' privilege)",
+ "<name>"
+ },
+ {
+ CMD_ENABLE,
+ "enable",
+ name_cmd,
+ "Enable a binary image activator (requires 'root' privilege)",
+ "<name>"
+ },
+ {
+ CMD_LOOKUP,
+ "lookup",
+ name_cmd,
+ "Lookup a binary image activator",
+ "<name>"
+ },
+ {
+ CMD_LIST,
+ "list",
+ noname_cmd,
+ "List all the binary image activators",
+ ""
+ },
+};
+
+static const struct option
+add_opts[] = {
+ { "set-enabled", no_argument, NULL, 'e' },
+ { "interpreter", required_argument, NULL, 'i' },
+ { "mask", required_argument, NULL, 'M' },
+ { "magic", required_argument, NULL, 'm' },
+ { "offset", required_argument, NULL, 'o' },
+ { "size", required_argument, NULL, 's' },
+ { NULL, 0, NULL, 0 }
+};
+
+static char const *cmd_sysctl_name[] = {
+ IBE_SYSCTL_NAME_ADD,
+ IBE_SYSCTL_NAME_REMOVE,
+ IBE_SYSCTL_NAME_DISABLE,
+ IBE_SYSCTL_NAME_ENABLE,
+ IBE_SYSCTL_NAME_LOOKUP,
+ IBE_SYSCTL_NAME_LIST
+};
+
+static void
+usage(const char *format, ...)
+{
+ va_list args;
+ size_t i;
+ int error = 0;
+
+ va_start(args, format);
+ if (format) {
+ vfprintf(stderr, format, args);
+ error = -1;
+ }
+ va_end(args);
+ fprintf(stderr, "\n");
+ fprintf(stderr, "usage: %s command [args...]\n\n", __progname);
+
+ for(i = 0; i < ( sizeof (cmds) / sizeof (cmds[0])); i++) {
+ fprintf(stderr, "%s:\n", cmds[i].desc);
+ fprintf(stderr, "\t%s %s %s\n\n", __progname, cmds[i].name,
+ cmds[i].args);
+ }
+
+ exit (error);
+}
+
+static void
+fatal(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ if (format)
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+
+ exit(-1);
+}
+
+static void
+getoptstr(char *str, size_t size, const char *argname)
+{
+ if (strlen(optarg) > size)
+ usage("'%s' too large", argname);
+ strlcpy(str, optarg, size);
+}
+
+static void
+printxbe(ximgact_binmisc_entry_t *xbe)
+{
+ uint32_t i, flags = xbe->xbe_flags;
+
+ if (xbe->xbe_version != IBE_VERSION) {
+ fprintf(stderr, "Error: XBE version mismatch\n");
+ return;
+ }
+
+ printf("name: %s\n", xbe->xbe_name);
+ printf("interpreter: %s\n", xbe->xbe_interpreter);
+ printf("flags: %s%s\n", (flags & IBF_ENABLED) ? "ENABLED " : "",
+ (flags & IBF_USE_MASK) ? "USE_MASK " : "");
+ printf("magic size: %u\n", xbe->xbe_msize);
+ printf("magic offset: %u\n", xbe->xbe_moffset);
+
+ printf("magic: ");
+ for(i = 0; i < xbe->xbe_msize; i++) {
+ if (i && !(i % 12))
+ printf("\n ");
+ else
+ if (i && !(i % 4))
+ printf(" ");
+ printf("0x%02x ", xbe->xbe_magic[i]);
+ }
+ printf("\n");
+
+ if (flags & IBF_USE_MASK) {
+ printf("mask: ");
+ for(i = 0; i < xbe->xbe_msize; i++) {
+ if (i && !(i % 12))
+ printf("\n ");
+ else
+ if (i && !(i % 4))
+ printf(" ");
+ printf("0x%02x ", xbe->xbe_mask[i]);
+ }
+ printf("\n");
+ }
+
+ printf("\n");
+}
+
+static int
+demux_cmd(__unused int argc, char *const argv[])
+{
+ size_t i;
+
+ optind = 1;
+ optreset = 1;
+
+ for(i = 0; i < ( sizeof (cmds) / sizeof (cmds[0])); i++) {
+ if (!strcasecmp(cmds[i].name, argv[0])) {
+ return (i);
+ }
+ }
+
+ /* Unknown command */
+ return (-1);
+}
+
+static int
+strlit2bin_cpy(uint8_t *d, char *s, size_t size)
+{
+ int c;
+ size_t cnt = 0;
+
+ while((c = *s++) != '\0') {
+ if (c == '\\') {
+ /* Do '\' escapes. */
+ switch (*s) {
+ case '\\':
+ *d++ = '\\';
+ break;
+
+ case 'x':
+ s++;
+ c = toupper(*s++);
+ *d = (c - (isdigit(c) ? '0' : ('A' - 10))) << 4;
+ c = toupper(*s++);
+ *d++ |= c - (isdigit(c) ? '0' : ('A' - 10));
+ break;
+
+ default:
+ return (-1);
+ }
+ } else
+ *d++ = c;
+
+ if (++cnt > size)
+ return (-1);
+ }
+
+ return (cnt);
+}
+
+int
+add_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe)
+{
+ int ch;
+ char *magic = NULL, *mask = NULL;
+ int sz;
+
+ if (strlen(argv[0]) > IBE_NAME_MAX)
+ usage("'%s' string length longer than IBE_NAME_MAX (%d)",
+ IBE_NAME_MAX);
+ strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX);
+
+ while ((ch = getopt_long(argc, argv, "ei:m:M:o:s:", add_opts, NULL))
+ != -1) {
+
+ switch(ch) {
+ case 'i':
+ getoptstr(xbe->xbe_interpreter, IBE_INTERP_LEN_MAX,
+ "interpreter");
+ break;
+
+ case 'm':
+ magic = strdup(optarg);
+ break;
+
+ case 'M':
+ mask = strdup(optarg);
+ xbe->xbe_flags |= IBF_USE_MASK;
+ break;
+
+ case 'e':
+ xbe->xbe_flags |= IBF_ENABLED;
+ break;
+
+ case 'o':
+ xbe->xbe_moffset = atol(optarg);
+ break;
+
+ case 's':
+ xbe->xbe_msize = atol(optarg);
+ if (xbe->xbe_msize == 0 ||
+ xbe->xbe_msize > IBE_MAGIC_MAX)
+ usage("Error: Not valid '--size' value. "
+ "(Must be > 0 and < %u.)\n",
+ xbe->xbe_msize);
+ break;
+
+ default:
+ usage("Unknown argument: '%c'", ch);
+ }
+ }
+
+ if (xbe->xbe_msize == 0) {
+ if (NULL != magic)
+ free(magic);
+ if (NULL != mask)
+ free(mask);
+ usage("Error: Missing '--size' argument");
+ }
+
+ if (NULL != magic) {
+ if (xbe->xbe_msize == 0) {
+ if (magic)
+ free(magic);
+ if (mask)
+ free(mask);
+ usage("Error: Missing magic size argument");
+ }
+ sz = strlit2bin_cpy(xbe->xbe_magic, magic, IBE_MAGIC_MAX);
+ free(magic);
+ if (sz == -1 || (uint32_t)sz != xbe->xbe_msize) {
+ if (mask)
+ free(mask);
+ usage("Error: invalid magic argument");
+ }
+ if (mask) {
+ sz = strlit2bin_cpy(xbe->xbe_mask, mask, IBE_MAGIC_MAX);
+ free(mask);
+ if (sz == -1 || (uint32_t)sz != xbe->xbe_msize)
+ usage("Error: invalid mask argument");
+ }
+ } else {
+ if (mask)
+ free(mask);
+ usage("Error: Missing magic argument");
+ }
+
+ if (!xbe->xbe_interpreter) {
+ usage("Error: Missing 'interpreter' argument");
+ }
+
+ return (0);
+}
+
+int
+name_cmd(__unused int argc, char *argv[], ximgact_binmisc_entry_t *xbe)
+{
+ if (strlen(argv[0]) > IBE_NAME_MAX)
+ usage("'%s' string length longer than IBE_NAME_MAX (%d)",
+ IBE_NAME_MAX);
+ strlcpy(&xbe->xbe_name[0], argv[0], IBE_NAME_MAX);
+
+ return (0);
+}
+
+int
+noname_cmd(__unused int argc, __unused char *argv[],
+ __unused ximgact_binmisc_entry_t *xbe)
+{
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int error = 0, cmd = -1;
+ ximgact_binmisc_entry_t xbe_in, *xbe_inp = NULL;
+ ximgact_binmisc_entry_t xbe_out, *xbe_outp = NULL;
+ size_t xbe_in_sz = 0;
+ size_t xbe_out_sz = 0, *xbe_out_szp = NULL;
+ uint32_t i;
+
+ if (kldfind(KMOD_NAME) == -1) {
+ if (kldload(KMOD_NAME) == -1)
+ fatal("Can't load %s kernel module: %s",
+ KMOD_NAME, strerror(errno));
+ }
+
+ bzero(&xbe_in, sizeof(xbe_in));
+ bzero(&xbe_out, sizeof(xbe_out));
+ xbe_in.xbe_version = IBE_VERSION;
+
+ if (argc < 2)
+ usage("Error: requires at least one argument");
+
+ argc--, argv++;
+ cmd = demux_cmd(argc, argv);
+ if (cmd == -1)
+ usage("Error: Unknown command \"%s\"", argv[0]);
+ argc--, argv++;
+
+ error = (*cmds[cmd].func)(argc, argv, &xbe_in);
+ if (error)
+ usage("Can't parse command-line for '%s' command",
+ cmds[cmd].name);
+
+ if (cmd != CMD_LIST) {
+ xbe_inp = &xbe_in;
+ xbe_in_sz = sizeof(xbe_in);
+ } else
+ xbe_out_szp = &xbe_out_sz;
+ if (cmd == CMD_LOOKUP) {
+ xbe_out_sz = sizeof(xbe_out);
+ xbe_outp = &xbe_out;
+ xbe_out_szp = &xbe_out_sz;
+ }
+
+ error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp, xbe_out_szp,
+ xbe_inp, xbe_in_sz);
+
+ if (error)
+ switch(errno) {
+ case EINVAL:
+ usage("Invalid interpreter name or --interpreter, "
+ "--magic, --mask, or --size argument value");
+ break;
+
+ case EEXIST:
+ usage("'%s' is not unique in activator list",
+ xbe_in.xbe_name);
+ break;
+
+ case ENOENT:
+ usage("'%s' is not found in activator list",
+ xbe_in.xbe_name);
+ break;
+
+ case ENOSPC:
+ fatal("Fatal: no more room in the activator list "
+ "(limited to %d enties)", IBE_MAX_ENTRIES);
+ break;
+
+ case EPERM:
+ usage("Insufficient privileges for '%s' command",
+ cmds[cmd].name);
+ break;
+
+ default:
+ fatal("Fatal: sysctlbyname() returned: %s",
+ strerror(errno));
+ break;
+ }
+
+
+ if (cmd == CMD_LOOKUP)
+ printxbe(xbe_outp);
+
+ if (cmd == CMD_LIST && xbe_out_sz > 0) {
+ xbe_outp = malloc(xbe_out_sz);
+ if (!xbe_outp)
+ fatal("Fatal: out of memory");
+ while(1) {
+ size_t osize = xbe_out_sz;
+ error = sysctlbyname(cmd_sysctl_name[cmd], xbe_outp,
+ &xbe_out_sz, NULL, 0);
+
+ if (error == -1 && errno == ENOMEM &&
+ xbe_out_sz == osize) {
+ /*
+ * Buffer too small. Increase it by one
+ * entry.
+ */
+ xbe_out_sz += sizeof(xbe_out);
+ xbe_outp = realloc(xbe_outp, xbe_out_sz);
+ if (!xbe_outp)
+ fatal("Fatal: out of memory");
+ } else
+ break;
+ }
+ if (error) {
+ free(xbe_outp);
+ fatal("Fatal: %s", strerror(errno));
+ }
+ for(i = 0; i < (xbe_out_sz / sizeof(xbe_out)); i++)
+ printxbe(&xbe_outp[i]);
+ }
+
+ return (error);
+}
diff --git a/usr.sbin/bluetooth/bthidd/kbd.c b/usr.sbin/bluetooth/bthidd/kbd.c
index e1ab870..b5bdfe1 100644
--- a/usr.sbin/bluetooth/bthidd/kbd.c
+++ b/usr.sbin/bluetooth/bthidd/kbd.c
@@ -67,7 +67,7 @@ static int32_t kbd_xlate(int32_t code, int32_t make, int32_t *b, int32_t const *
* The "break" (key released) code is generated as "make" | 0x80
*/
-#define E0PREFIX (1 << 31)
+#define E0PREFIX (1U << 31)
#define NOBREAK (1 << 30)
#define CODEMASK (~(E0PREFIX|NOBREAK))
diff --git a/usr.sbin/bluetooth/btpand/btpand.8 b/usr.sbin/bluetooth/btpand/btpand.8
index 97a0d13..b89bf95 100644
--- a/usr.sbin/bluetooth/btpand/btpand.8
+++ b/usr.sbin/bluetooth/btpand/btpand.8
@@ -159,7 +159,6 @@ Network Access Point.
.It PANU
Personal Area Networking User.
.El
-.Pp
.It Fl S Ar service
As per
.Fl s
diff --git a/usr.sbin/bootparamd/bootparamd/main.c b/usr.sbin/bootparamd/bootparamd/main.c
index 8c93c1f..85a1fca 100644
--- a/usr.sbin/bootparamd/bootparamd/main.c
+++ b/usr.sbin/bootparamd/bootparamd/main.c
@@ -86,7 +86,7 @@ char **argv;
if ( stat(bootpfile, &buf ) )
err(1, "%s", bootpfile);
- if (route_addr == -1) {
+ if (route_addr == INADDR_NONE) {
get_myaddress(&my_addr);
bcopy(&my_addr.sin_addr.s_addr, &route_addr, sizeof (route_addr));
}
diff --git a/usr.sbin/bootparamd/callbootd/Makefile b/usr.sbin/bootparamd/callbootd/Makefile
index 0137407..28b1e26 100644
--- a/usr.sbin/bootparamd/callbootd/Makefile
+++ b/usr.sbin/bootparamd/callbootd/Makefile
@@ -2,7 +2,7 @@
# $FreeBSD$
PROG= callbootd
-NO_MAN=
+MAN=
SRCS= callbootd.c ${GENSRCS}
GENSRCS=bootparam_prot.h bootparam_prot_clnt.c bootparam_prot_xdr.c
diff --git a/usr.sbin/bootparamd/callbootd/callbootd.c b/usr.sbin/bootparamd/callbootd/callbootd.c
index a0a4ef6..7c32fee 100644
--- a/usr.sbin/bootparamd/callbootd/callbootd.c
+++ b/usr.sbin/bootparamd/callbootd/callbootd.c
@@ -104,7 +104,7 @@ char **argv;
case 3:
whoami_arg.client_address.address_type = IP_ADDR_TYPE;
the_inet_addr = inet_addr(argv[2]);
- if ( the_inet_addr == -1)
+ if ( the_inet_addr == INADDR_NONE)
errx(2, "bogus addr %s", argv[2]);
bcopy(&the_inet_addr,&whoami_arg.client_address.bp_address_u.ip_addr,4);
diff --git a/usr.sbin/bsdconfig/Makefile b/usr.sbin/bsdconfig/Makefile
index 13cc1c7..72187de 100644
--- a/usr.sbin/bsdconfig/Makefile
+++ b/usr.sbin/bsdconfig/Makefile
@@ -6,6 +6,7 @@ SUBDIR= console \
dot \
examples \
include \
+ includes \
mouse \
networking \
packages \
diff --git a/usr.sbin/bsdconfig/bsdconfig b/usr.sbin/bsdconfig/bsdconfig
index 2c0d513..62699f2 100755
--- a/usr.sbin/bsdconfig/bsdconfig
+++ b/usr.sbin/bsdconfig/bsdconfig
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -315,8 +315,7 @@ 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"
+ f_dprintf "pgm=[%s] cmd=[%s] *=[%s]" "$pgm" "$cmd" "$*"
exec "$cmd" "$@" || exit 1
else
f_include $BSDCFG_SHARE/script.subr
@@ -324,7 +323,7 @@ if [ "$pgm" != "bsdconfig" ]; then
[ "$pgm" = "$resword" ] || continue
# Found a match
f_dprintf "pgm=[%s] A valid resWord!" "$pgm"
- f_dispatch $resword
+ f_dispatch $resword $resword "$@"
exit $?
done
fi
@@ -342,7 +341,7 @@ while getopts f:h$GETOPTS_STDARGS flag; do
h|\?) usage ;;
esac
done
-shift $(( $OPTIND -1 ))
+shift $(( $OPTIND - 1 ))
# If we've loaded any scripts, do not continue any further
[ $scripts_loaded -gt 0 ] && exit
@@ -382,6 +381,7 @@ if [ "$1" ]; then
# Not reached
fi
+ f_dprintf "cmd=[%s] *=[%s]" "$cmd" "$*"
shift
exec $cmd ${USE_XDIALOG:+-X} "$@" || exit 1
# Not reached
diff --git a/usr.sbin/bsdconfig/console/console b/usr.sbin/bsdconfig/console/console
index ce3d014..cfa44be 100755
--- a/usr.sbin/bsdconfig/console/console
+++ b/usr.sbin/bsdconfig/console/console
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
diff --git a/usr.sbin/bsdconfig/console/font b/usr.sbin/bsdconfig/console/font
index 1ffa696..ce16730 100755
--- a/usr.sbin/bsdconfig/console/font
+++ b/usr.sbin/bsdconfig/console/font
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -174,14 +174,16 @@ 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
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set font8x8 "%s"' "$f8" || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set font8x14 "%s"' "$f14" || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set font8x16 "%s"' "$f16" || f_die
if [ "$mc_start" ]; then
- f_sysrc_set mousechar_start "$mc_start" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set mousechar_start "%s"' "$mc_start" || f_die
else
- f_sysrc_delete mousechar_start || f_die
+ f_eval_catch "$0" f_sysrc_delete \
+ 'f_sysrc_delete mousechar_start' || f_die
fi
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/console/include/messages.subr b/usr.sbin/bsdconfig/console/include/messages.subr
index 11e3022..295f3e3 100644
--- a/usr.sbin/bsdconfig/console/include/messages.subr
+++ b/usr.sbin/bsdconfig/console/include/messages.subr
@@ -51,8 +51,8 @@ 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_alternate_screenmap="Choose an alternate screenmap"
msg_choose_console_terminal_type="Choose console terminal type"
msg_configure_screen_saver="Configure the screen saver"
msg_console_menu_text="The system console driver for FreeBSD has a number of configuration\noptions which may be set according to your preference.\n\nWhen you are done setting configuration options, select Cancel."
@@ -74,9 +74,9 @@ 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_estonian_iso_desc="Estonian ISO keymap"
msg_exit="Exit"
msg_exit_this_menu="Exit this menu"
msg_fade="Fade"
@@ -97,8 +97,6 @@ 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"
@@ -109,10 +107,14 @@ msg_greek_104="Greek 104"
msg_greek_104_desc="Greek ISO keymap (104 keys)"
msg_greek_elot="Greek ELOT"
msg_greek_elot_desc="Greek ISO keymap (ELOT 1000)"
+msg_green="Green"
+msg_green_desc="\"Green\" power saving mode (if supported by monitor)"
msg_hungarian_101="Hungarian 101"
msg_hungarian_101_desc="Hungarian ISO keymap (101 key)"
msg_hungarian_102="Hungarian 102"
msg_hungarian_102_desc="Hungarian ISO keymap (102 key)"
+msg_ibm_1251="IBM 1251"
+msg_ibm_1251_desc="Cyrillic, MS Windows encoding"
msg_ibm_437="IBM 437"
msg_ibm_437_desc="English and others, VGA default"
msg_ibm_437_vga_default="IBM437 (VGA default)"
@@ -124,12 +126,12 @@ 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_15="ISO 8859-15"
+msg_iso_8859_15_desc="Europe, ISO encoding"
msg_iso_8859_1="ISO 8859-1"
msg_iso_8859_1_desc="Western Europe, ISO encoding"
msg_iso_8859_1_to_ibm437="ISO 8859-1 to IBM437"
@@ -144,8 +146,6 @@ 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"
@@ -153,9 +153,9 @@ 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="KOI8-U"
msg_koi8_u_to_ibm866u="KOI8-U to IBM866u"
msg_koi8_u_to_ibm866u_desc="Ukrainian KOI8-U to IBM 866u screenmap"
msg_latin_american="Latin American"
@@ -224,8 +224,8 @@ 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_keymap="System Console Keymap"
msg_system_console_screen_saver="System Console Screen Saver"
msg_system_console_screenmap="System Console Screenmap"
msg_system_console_terminal_type="System Console Terminal Type"
diff --git a/usr.sbin/bsdconfig/console/keymap b/usr.sbin/bsdconfig/console/keymap
index 99072b5..c163a1b 100755
--- a/usr.sbin/bsdconfig/console/keymap
+++ b/usr.sbin/bsdconfig/console/keymap
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -246,10 +246,8 @@ while :; do
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
+ debug= f_getvar msg_$name msg
+ [ "$msg" = "$mtag" ] && keymap_name="$name" break
done
[ "$keymap_name" ] || continue
@@ -319,7 +317,8 @@ while :; do
esac
if [ "$keymap_to_set" ]; then
- f_sysrc_set keymap "$keymap_to_set" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set keymap "%s"' "$keymap_to_set" || f_die
break
else
f_die 1 "$msg_unknown_keymap"
diff --git a/usr.sbin/bsdconfig/console/repeat b/usr.sbin/bsdconfig/console/repeat
index 54134c6..ff00023 100755
--- a/usr.sbin/bsdconfig/console/repeat
+++ b/usr.sbin/bsdconfig/console/repeat
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -129,7 +129,8 @@ case "$mtag" in
esac
if [ "$repeat_rate_to_set" ]; then
- f_sysrc_set keyrate "$repeat_rate_to_set" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set keyrate "%s"' "$repeat_rate_to_set" || f_die
break
else
f_die 1 "$msg_unknown_repeat_rate"
diff --git a/usr.sbin/bsdconfig/console/saver b/usr.sbin/bsdconfig/console/saver
index 00d9e94..0df487c 100755
--- a/usr.sbin/bsdconfig/console/saver
+++ b/usr.sbin/bsdconfig/console/saver
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -144,7 +144,8 @@ case "$mtag" in
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_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set blanktime "%s"' "$blanktime" || f_die
f_dialog_title_restore
exit $SUCCESS
esac
@@ -180,7 +181,8 @@ case "$mtag" in
esac
if [ "$saver_to_set" ]; then
- f_sysrc_set saver "$saver_to_set" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set saver "%s"' "$saver_to_set" || f_die
break
else
f_die 1 "$msg_unknown_saver"
diff --git a/usr.sbin/bsdconfig/console/screenmap b/usr.sbin/bsdconfig/console/screenmap
index f9bbcd8..5bf5bd8 100755
--- a/usr.sbin/bsdconfig/console/screenmap
+++ b/usr.sbin/bsdconfig/console/screenmap
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -141,7 +141,8 @@ case "$mtag" in
esac
if [ "$scrnmap_to_set" ]; then
- f_sysrc_set scrnmap "$scrnmap_to_set" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set scrnmap "%s"' "$scrnmap_to_set" || f_die
break
else
f_die 1 "$msg_unknown_screenmap_selection"
diff --git a/usr.sbin/bsdconfig/console/ttys b/usr.sbin/bsdconfig/console/ttys
index 80cc668..54dcb66 100755
--- a/usr.sbin/bsdconfig/console/ttys
+++ b/usr.sbin/bsdconfig/console/ttys
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -108,23 +108,28 @@ dialog_menu_main()
#
ttys_set_type()
{
+ local funcname=ttys_set_type
local consterm="$1" err
#
# Create new temporary file to write our ttys(5) update with new types.
#
- local tmpfile="$( mktemp -t "pgm" )"
- [ "$tmpfile" ] || return $FAILURE
+ local tmpfile
+ f_eval_catch -k tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm" ||
+ return $FAILURE
#
# Fixup permissions and ownership (mktemp(1) creates the temporary file
# with 0600 permissions -- change the permissions and ownership to
# match ttys(5) before we write it out and mv(1) it into place).
#
- local mode="$( 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"
+ local mode owner
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$ETC_TTYS" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$ETC_TTYS" || owner="root:wheel"
+ f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile"
#
# Operate on ttys(5), replacing only the types of `ttyv*' and
@@ -156,10 +161,8 @@ ttys_set_type()
f_dialog_msgbox "$err"
return $FAILURE
fi
- if ! err=$( mv -f "$tmpfile" "$ETC_TTYS" 2>&1 ); then
- f_dialog_msgbox "$err"
+ f_eval_catch $funcname mv 'mv -f "%s" "%s"' "$tmpfile" "$ETC_TTYS" ||
return $FAILURE
- fi
return $SUCCESS
}
diff --git a/usr.sbin/bsdconfig/diskmgmt/diskmgmt b/usr.sbin/bsdconfig/diskmgmt/diskmgmt
index 8c3435d..ec567f5 100755
--- a/usr.sbin/bsdconfig/diskmgmt/diskmgmt
+++ b/usr.sbin/bsdconfig/diskmgmt/diskmgmt
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
diff --git a/usr.sbin/bsdconfig/docsinstall/docsinstall b/usr.sbin/bsdconfig/docsinstall/docsinstall
index 5e3a0d3..19128fe 100755
--- a/usr.sbin/bsdconfig/docsinstall/docsinstall
+++ b/usr.sbin/bsdconfig/docsinstall/docsinstall
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
diff --git a/usr.sbin/bsdconfig/dot/dot b/usr.sbin/bsdconfig/dot/dot
index e13a269..9093d63 100755
--- a/usr.sbin/bsdconfig/dot/dot
+++ b/usr.sbin/bsdconfig/dot/dot
@@ -29,7 +29,7 @@
############################################################ INCLUDES
# Prevent common.subr from auto initializing debugging (this is not an inter-
-# active utility that requires debugging; also `-d' has been repurposed).
+# active utility so does not require debugging; also `-d' has been repurposed).
#
DEBUG_SELF_INITIALIZE=NO
@@ -41,8 +41,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -163,7 +163,7 @@ while getopts cdhi flag; do
done
shift $(( $OPTIND - 1 ))
-cd $BSDCFG_LIBE || f_die 1 "$msg_directory_not_found" "$BSDCFG_LIB"
+cd $BSDCFG_LIBE || f_die # Pedantic
#
# Get a list of menu programs
diff --git a/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh b/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh
index 1deb562..015d799 100755
--- a/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh
+++ b/usr.sbin/bsdconfig/examples/browse_packages_ftp.sh
@@ -18,7 +18,7 @@ if [ ! -e "$TMPDIR/packages/INDEX" ]; then
mediaSetFTP
mediaOpen
f_show_info "Downloading packages/INDEX from\n %s" "$_ftpPath"
- f_device_get media packages/INDEX > $TMPDIR/packages/INDEX
+ f_device_get device_media packages/INDEX > $TMPDIR/packages/INDEX
fi
_directoryPath=$TMPDIR
mediaSetDirectory
diff --git a/usr.sbin/bsdconfig/examples/browse_packages_http.sh b/usr.sbin/bsdconfig/examples/browse_packages_http.sh
index e88a576..a0e6801 100755
--- a/usr.sbin/bsdconfig/examples/browse_packages_http.sh
+++ b/usr.sbin/bsdconfig/examples/browse_packages_http.sh
@@ -18,7 +18,7 @@ if [ ! -e "$TMPDIR/packages/INDEX" ]; then
mediaSetHTTP
mediaOpen
f_show_info "Downloading packages/INDEX from\n %s" "$_httpPath"
- f_device_get media packages/INDEX > $TMPDIR/packages/INDEX
+ f_device_get device_media packages/INDEX > $TMPDIR/packages/INDEX
fi
_directoryPath=$TMPDIR
mediaSetDirectory
diff --git a/usr.sbin/bsdconfig/include/messages.subr b/usr.sbin/bsdconfig/include/messages.subr
index 1c558f2..bf16e08 100644
--- a/usr.sbin/bsdconfig/include/messages.subr
+++ b/usr.sbin/bsdconfig/include/messages.subr
@@ -40,6 +40,7 @@ msg_afterstep_desc="Ports to support the AfterStep window manager."
msg_all="All"
msg_all_desc="All available packages in all categories."
msg_always_try_sudo_when_run_as="Always try sudo(8) when run as %s"
+msg_an_unknown_error_occurred="An unknown error occurred"
msg_arabic_desc="Ported software for Arab countries."
msg_archivers_desc="Utilities for archiving and unarchiving data."
msg_armenia="Armenia"
@@ -48,7 +49,7 @@ msg_assume_yes_to_all_non_critical_dialogs="Assume \"Yes\" answers to all non-cr
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_attempting_to_update_repository_catalogue="Attempting to update repository catalogue from selected media."
msg_audio_desc="Audio utilities - most require a supported sound card."
msg_australia="Australia"
msg_austria="Austria"
@@ -137,9 +138,12 @@ 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_generating_index_from_pkg_database="Generating INDEX from pkg(8) database\n(this can take a while)..."
msg_geography_desc="Geography-related software."
msg_german_desc="Ported software for Germanic countries."
msg_germany="Germany"
+msg_getting_package_categories_via_pkg_rquery="Getting package categories via pkg-rquery(8)..."
+msg_getting_package_dependencies_via_pkg_rquery="Getting package dependencies via pkg-rquery(8)\n(this can take a while)..."
msg_gnome_desc="Components of the Gnome Desktop environment."
msg_gnustep_desc="Software for GNUstep desktop environment."
msg_graphics_desc="Graphics libraries and utilities."
@@ -166,8 +170,8 @@ 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_installed_lc="installed"
msg_invalid_gateway_ipv4_address_specified="Invalid gateway IPv4 address specified"
msg_invalid_hostname_value="Invalid hostname value"
msg_invalid_ipv4_address="Invalid IPv4 address"
@@ -175,7 +179,7 @@ msg_invalid_name_server_ip_address_specified="Invalid name server IP address spe
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_io_or_format_error_on_index_file="I/O or format error on INDEX file.\nPlease verify media (or path to media) and try again."
msg_ipv4_address="IPv4 Address"
msg_ipv4_gateway="IPv4 Gateway"
msg_ipv6="IPv6"
@@ -201,6 +205,7 @@ 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_for_keymap_files="Looking for keymap files..."
msg_looking_up_host="Looking up host %s"
msg_mail_desc="Electronic mail packages and utilities."
msg_main_menu="Main Menu"
@@ -244,6 +249,7 @@ msg_no_gateway_has_been_set="No gateway has been set. You will be unable to acce
msg_no_network_devices="No network devices available!"
msg_no_package_name_passed_in_package_variable="No package name passed in package variable"
msg_no_packages_were_selected_for_extraction="No packages were selected for extraction."
+msg_no_pkg_database_found="No pkg(8) database found!"
msg_no_such_file_or_directory="%s: %s: No such file or directory"
msg_no_usb_devices_found="No USB devices found (try Options/Re-scan Devices)"
msg_no_username="No username provided!"
@@ -255,10 +261,8 @@ 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"
@@ -268,7 +272,8 @@ 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_pkg_delete_failed="Warning: pkg-delete(8) of %s failed.\n Run with debugging for details."
+msg_pkg_install_apparently_did_not_like_the_package="pkg-install(8) apparently did not like the %s package."
msg_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):"
@@ -371,9 +376,12 @@ msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not
msg_unable_to_initialize_media_type_for_package_extract="Unable to initialize media type for package extract."
msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!"
msg_unable_to_open="Unable to open %s"
+msg_unable_to_pkg_rquery_package_categories="Unable to pkg-rquery(8) package categories!"
+msg_unable_to_pkg_rquery_package_dependencies="Unable to pkg-rquery(8) package dependencies!"
+msg_unable_to_update_pkg_from_selected_media="Unable to update pkg(8) from selected media."
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_uninstalling_package_waiting_for_pkg_delete="Uninstalling %s package - waiting for pkg-delete(8)"
msg_unknown="unknown"
msg_unknown_user="Unknown user: %s"
msg_url_was_not_found="%s was not found, maybe directory or release-version are wrong?"
diff --git a/usr.sbin/bsdconfig/includes/INDEX b/usr.sbin/bsdconfig/includes/INDEX
new file mode 100644
index 0000000..6e829be
--- /dev/null
+++ b/usr.sbin/bsdconfig/includes/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=""
+
+#
+# A short descriptive line shown at the bottom of the bsdconfig menu. keep it
+# short because any line longer than the terminal width will be truncated.
+#
+menu_help=""
+
+#
+# Two-part variable that defines an action to take when `keyword' is passed on
+# a bsdconfig command line. Variable takes the form "keyword|command" and
+# multiple occurrences of the variable (with different `keyword's, or different
+# `keyword's AND `command's) are allowed. If `command' begins with a '/' then
+# the full path to the program is needed. If `command' begins with anything
+# else it is a path relative to the directory this INDEX file is in. `keyword'
+# can be i18n'ed but `command' is the name of a script.
+#
+menu_selection="includes|includes"
+
+#
+# ------------ 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/includes/Makefile b/usr.sbin/bsdconfig/includes/Makefile
new file mode 100644
index 0000000..f7cbc1e
--- /dev/null
+++ b/usr.sbin/bsdconfig/includes/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+NO_OBJ=
+
+SUBDIR= include
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/includes
+FILES= INDEX USAGE
+
+SCRIPTSDIR= ${FILESDIR}
+SCRIPTS= includes
+
+beforeinstall:
+ mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/includes/USAGE b/usr.sbin/bsdconfig/includes/USAGE
new file mode 100644
index 0000000..4af1b73
--- /dev/null
+++ b/usr.sbin/bsdconfig/includes/USAGE
@@ -0,0 +1,71 @@
+# Copyright (c) 2013 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+Usage: bsdconfig @PROGRAM_NAME@ [OPTIONS] [include ...]
+
+OPTIONS:
+ -a Always use color even when output is not to a terminal.
+ -d Print description for each function selected. Implies `-f'.
+ -f Show functions for selected includes.
+ -F pattern
+ If `-f', only print functions matching pattern. Without `-f'
+ print only includes containing functions matching pattern.
+ -h Print this usage statement and exit.
+ -n Disable the use of color.
+
+EXAMPLES:
+ View a list of available includes:
+
+ bsdconfig @PROGRAM_NAME@
+
+ View functions for all available includes (function names are
+ highlighted):
+
+ bsdconfig @PROGRAM_NAME@ -f
+
+ View functions with less(1) (function names are not highlighted):
+
+ bsdconfig @PROGRAM_NAME@ -f | less
+
+ View functions with less(1) and color:
+
+ bsdconfig @PROGRAM_NAME@ -af | less -R
+
+ View functions from `common.subr':
+
+ bsdconfig @PROGRAM_NAME@ common.subr
+
+ NB: The `-f' flag is implied when given an include.
+
+ Show only functions containing the word `show' in common.subr:
+
+ bsdconfig @PROGRAM_NAME@ -F show common
+
+ NB: The `.subr' suffix on the end of the include is optional.
+
+ Show descriptions of each of the `show' functions:
+
+ bsdconfig @PROGRAM_NAME@ -dF show
diff --git a/usr.sbin/bsdconfig/includes/include/Makefile b/usr.sbin/bsdconfig/includes/include/Makefile
new file mode 100644
index 0000000..79c4481
--- /dev/null
+++ b/usr.sbin/bsdconfig/includes/include/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+NO_OBJ=
+
+FILESDIR= ${LIBEXECDIR}/bsdconfig/includes/include
+FILES= messages.subr
+
+beforeinstall:
+ mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/includes/include/messages.subr b/usr.sbin/bsdconfig/includes/include/messages.subr
new file mode 100644
index 0000000..8fa881b
--- /dev/null
+++ b/usr.sbin/bsdconfig/includes/include/messages.subr
@@ -0,0 +1,28 @@
+# Copyright (c) 2013 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+msg_functions_in="Functions in %s:"
+msg_functions_in_matching="Functions in %s matching \`%s':"
diff --git a/usr.sbin/bsdconfig/includes/includes b/usr.sbin/bsdconfig/includes/includes
new file mode 100755
index 0000000..d831649
--- /dev/null
+++ b/usr.sbin/bsdconfig/includes/includes
@@ -0,0 +1,203 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+# Prevent common.subr from auto initializing debugging (this is not an inter-
+# active utility that requires debugging; also `-d' has been repurposed).
+#
+DEBUG_SELF_INITIALIZE=NO
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="includes"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
+
+############################################################ GLOBALS
+
+#
+# Options
+#
+USE_COLOR=1
+SHOW_DESC=
+SHOW_FUNCS=
+FUNC_PATTERN=
+
+############################################################ FUNCTIONS
+
+# show_functions $file
+#
+# Show the functions in the given include file.
+#
+show_include()
+{
+ local file="${1#./}"
+
+ local pattern="${FUNC_PATTERN:-.*}"
+ output=$( awk \
+ -v use_color=${USE_COLOR:-0} \
+ -v re="$pattern" \
+ -v show_desc=${SHOW_DESC:-0} '
+ function asorti(src, dest)
+ {
+ # 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
+ }
+ /^$/,/^#/ {
+ if ($0 ~ /^# f_/) {
+ if (!match($2, re)) next
+ fn = $2
+ if (use_color)
+ syntax[fn] = sprintf("+%s%s%s\n",
+ substr($0, 2, RSTART),
+ substr($0, 2 + RSTART, RLENGTH),
+ substr($0, 2 + RSTART + RLENGTH))
+ else
+ syntax[fn] = "+" substr($0, 2) "\n"
+ if (show_desc)
+ print_more = 1
+ else
+ print_more = substr($0, length($0)) == "\\"
+ }
+ if (show_desc && print_more) {
+ getline
+ while ($0 ~ /^#/) {
+ syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
+ getline
+ }
+ print_more = 0
+ } else while (print_more) {
+ getline
+ syntax[fn] = syntax[fn] " " substr($0, 2) "\n"
+ print_more = substr($0, length($0)) == "\\"
+ }
+ }
+ END {
+ n = asorti(syntax, sorted_indices)
+ for (i = 1; i <= n; i++)
+ printf "%s", syntax[sorted_indices[i]]
+ }' "$file" )
+ if [ "$output" ]; then
+ if [ ! "$SHOW_FUNCS" ]; then
+ echo "$file"
+ return $SUCCESS
+ fi
+ if [ "$FUNC_PATTERN" ]; then
+ printf ">>> $msg_functions_in_matching\n" \
+ "$file" "$FUNC_PATTERN"
+ else
+ printf ">>> $msg_functions_in\n" "$file"
+ fi
+ echo "$output"
+ echo # blank line to simplify awk(1)-based reparse
+ fi
+}
+
+############################################################ MAIN
+
+# Incorporate rc-file if it exists
+[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
+
+# Are we in a terminal?
+[ -t 1 ] || USE_COLOR=
+
+#
+# Process command-line arguments
+#
+while getopts adfF:hn flag; do
+ case "$flag" in
+ a) USE_COLOR=1 ;;
+ d) SHOW_DESC=1 SHOW_FUNCS=1 ;;
+ f) SHOW_FUNCS=1 ;;
+ F) FUNC_PATTERN="$OPTARG" ;;
+ n) USE_COLOR= ;;
+ h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
+ esac
+done
+shift $(( $OPTIND - 1 ))
+
+# cd(1) to `share' dir so relative paths work for find and positional args
+cd $BSDCFG_SHARE || f_die # Pedantic
+
+#
+# If given an argument, operate on it specifically (implied `-f') and exit
+#
+[ $# -gt 0 ] && SHOW_FUNCS=1
+for include in "$@"; do
+ # See if they've just omitted the `*.subr' suffix
+ [ -f "$include.subr" -a ! -f "$include" ] && include="$include.subr"
+ if [ ! -f "$include" ]; then
+ printf "$msg_no_such_file_or_directory\n" "$0" "$include"
+ exit $FAILURE
+ elif [ ! -r "$include" ]; then
+ printf "$msg_permission_denied\n" "$0" "$include"
+ exit $FAILURE
+ fi
+ show_include "$include" || f_die
+done
+
+# Exit if we processed some include arguments
+[ $# -gt 0 ] && exit $SUCCESS
+
+#
+# Operate an all known include files
+# NB: If we get this far, we had no include arguments
+#
+find -s . -type f -and -iname '*.subr' | while read file; do
+ if [ "$SHOW_FUNCS" -o "$FUNC_PATTERN" ]; then
+ show_include "$file"
+ else
+ echo "${file#./}"
+ fi
+done
+
+exit $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdconfig/mouse/disable b/usr.sbin/bsdconfig/mouse/disable
index 6807abd..f2c528f 100755
--- a/usr.sbin/bsdconfig/mouse/disable
+++ b/usr.sbin/bsdconfig/mouse/disable
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -73,12 +73,16 @@ 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
+if [ -r "$MOUSED_PIDFILE" ]; then
+ f_eval_catch -dk pid "$0" cat 'cat "%s"' "$MOUSED_PIDFILE" &&
+ f_isinteger "$pid" &&
+ [ $pid -gt 0 ] &&
+ f_eval_catch -d "$0" kill 'kill %s' $pid
+fi
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_enable NO' || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_type NO' || f_die
+f_eval_catch "$0" f_sysrc_delete 'f_sysrc_delete moused_port' || f_die
+f_eval_catch "$0" f_sysrc_delete 'f_sysrc_delete moused_flags' || f_die
#
# Message box
diff --git a/usr.sbin/bsdconfig/mouse/enable b/usr.sbin/bsdconfig/mouse/enable
index 106faec..9ad6857 100755
--- a/usr.sbin/bsdconfig/mouse/enable
+++ b/usr.sbin/bsdconfig/mouse/enable
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -85,10 +85,15 @@ 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
+if [ -r "$MOUSED_PIDFILE" ]; then
+ f_eval_catch -dk pid "$0" cat 'cat "%s"' "$MOUSED_PIDFILE" &&
+ f_isinteger "$pid" &&
+ [ $pid -gt 0 ] &&
+ f_eval_catch -d "$0" kill 'kill %s' $pid
+fi
+f_eval_catch -d "$0" vidcontrol 'vidcontrol -m on'
+f_eval_catch -d "$0" moused \
+ 'moused -t "%s" -p "%s" %s' "$type" "$port" "$flags"
#
# Confirm with the user that the mouse is working
@@ -101,14 +106,19 @@ f_dialog_title_restore
#
# Stop the mouse daemon
#
-f_quietly vidcontrol -m off
+f_eval_catch -d "$0" vidcontrol 'vidcontrol -m off'
if [ $retval -eq $DIALOG_OK ]; then
- f_sysrc_set moused_enable "YES" || f_die
- ln -fs /dev/sysmouse /dev/mouse || f_die # backwards compat
+ f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_enable YES' || f_die
+ f_eval_catch "$0" ln \
+ 'ln -fs /dev/sysmouse /dev/mouse' || f_die # backwards compat
else
- [ -r "$MOUSED_PIDFILE" ] &&
- f_quietly kill "$( cat "$MOUSED_PIDFILE" )"
- f_sysrc_set moused_enable "NO" || f_die
+ if [ -r "$MOUSED_PIDFILE" ]; then
+ f_eval_catch -dk pid "$0" cat 'cat "%s"' "$MOUSED_PIDFILE" &&
+ f_isinteger "$pid" &&
+ [ $pid -gt 0 ] &&
+ f_eval_catch -d "$0" kill 'kill %s' $pid
+ fi
+ f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_enable NO' || f_die
fi
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/mouse/flags b/usr.sbin/bsdconfig/mouse/flags
index de2ca76..181ee3f 100755
--- a/usr.sbin/bsdconfig/mouse/flags
+++ b/usr.sbin/bsdconfig/mouse/flags
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -86,7 +86,7 @@ f_dialog_title_restore
#
# Save the new value
#
-f_sysrc_set moused_flags "$flags" || f_die
+f_eval_catch "$0" f_sysrc_set 'f_sysrc_set moused_flags "%s"' "$flags" || f_die
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/mouse/include/messages.subr b/usr.sbin/bsdconfig/mouse/include/messages.subr
index 74d9980..82cbad3 100644
--- a/usr.sbin/bsdconfig/mouse/include/messages.subr
+++ b/usr.sbin/bsdconfig/mouse/include/messages.subr
@@ -58,14 +58,14 @@ 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_mouseman="MouseMan"
+msg_mouseman_desc="Logitech MouseMan/TrackMan models (serial)"
+msg_mousesystems="MouseSystems"
+msg_mousesystems_desc="MouseSystems protocol (serial)"
msg_now_move_the_mouse="Now move the mouse and see if it works.\n(Note that buttons don't have any effect for now.)\n\n Is the mouse cursor moving?\n"
msg_ok="OK"
msg_please_configure_your_mouse="Please configure your mouse"
diff --git a/usr.sbin/bsdconfig/mouse/mouse b/usr.sbin/bsdconfig/mouse/mouse
index bafed04..0dce574 100755
--- a/usr.sbin/bsdconfig/mouse/mouse
+++ b/usr.sbin/bsdconfig/mouse/mouse
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
diff --git a/usr.sbin/bsdconfig/mouse/port b/usr.sbin/bsdconfig/mouse/port
index 41dd481..1040795 100755
--- a/usr.sbin/bsdconfig/mouse/port
+++ b/usr.sbin/bsdconfig/mouse/port
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -141,7 +141,8 @@ case "$mtag" in
esac
if [ "$moused_port_to_set" ]; then
- f_sysrc_set moused_port "$moused_port_to_set" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set moused_port "%s"' "$moused_port_to_set" || f_die
else
f_die 1 "$msg_unknown_mouse_port_selection"
fi
diff --git a/usr.sbin/bsdconfig/mouse/type b/usr.sbin/bsdconfig/mouse/type
index 30d2022..7d99753 100755
--- a/usr.sbin/bsdconfig/mouse/type
+++ b/usr.sbin/bsdconfig/mouse/type
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -157,7 +157,8 @@ case "$mtag" in
esac
if [ "$moused_type_to_set" ]; then
- f_sysrc_set moused_type "$moused_type_to_set" || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set moused_type "%s"' "$moused_type_to_set" || f_die
else
f_die 1 "$msg_unknown_mouse_protocol_selection"
fi
diff --git a/usr.sbin/bsdconfig/networking/defaultrouter b/usr.sbin/bsdconfig/networking/defaultrouter
index 4719e45..b65981f 100755
--- a/usr.sbin/bsdconfig/networking/defaultrouter
+++ b/usr.sbin/bsdconfig/networking/defaultrouter
@@ -28,6 +28,9 @@
#
############################################################ 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"
@@ -38,8 +41,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/networking/devices b/usr.sbin/bsdconfig/networking/devices
index 9d65c51..433f25c 100755
--- a/usr.sbin/bsdconfig/networking/devices
+++ b/usr.sbin/bsdconfig/networking/devices
@@ -28,6 +28,12 @@
#
############################################################ INCLUDES
+# Prevent device.subr (included indirectly) from auto scanning; this will be
+# performed indirectly later via f_dialog_menu_netdev() -- but only after we've
+# successfully completed f_mustberoot_init().
+#
+DEVICE_SELF_SCAN_ALL=NO
+
BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." "$0"
@@ -43,8 +49,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -137,8 +143,8 @@ while :; do
# 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 )
+ [ "$_ipaddr" ] || f_ifconfig_inet $interface _ipaddr
+ [ "$_netmask" ] || f_ifconfig_netmask $interface _netmask
# Get the extra options (this always comes from rc.conf(5))
_options=$( f_ifconfig_options $interface )
diff --git a/usr.sbin/bsdconfig/networking/hostname b/usr.sbin/bsdconfig/networking/hostname
index 23cf804..d0fff01 100755
--- a/usr.sbin/bsdconfig/networking/hostname
+++ b/usr.sbin/bsdconfig/networking/hostname
@@ -41,8 +41,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/networking/include/messages.subr b/usr.sbin/bsdconfig/networking/include/messages.subr
index ad5461c..bb94c36 100644
--- a/usr.sbin/bsdconfig/networking/include/messages.subr
+++ b/usr.sbin/bsdconfig/networking/include/messages.subr
@@ -59,15 +59,15 @@ msg_ipv4_addr_octet_contains_invalid_chars="ERROR! One or more individual octets
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_ipv6_addr_segment_contains_invalid_chars="ERROR! One or more individual segments within the IP address\n(separated by colons) contains one or more invalid characters.\nSegments must contain only combinations of the characters 0-9,\nA-F, or a-f.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_segment_contains_too_many_chars="ERROR! One or more individual segments within the IP address\n(separated by colons) exceeds the length of 4 hex-digits.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_too_few_or_extra_segments="ERROR! The IP address entered has either too few (less than 3), too\nmany (more than 8), or not enough segments, separated by colons.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_too_many_null_segments="ERROR! Too many/incorrect null segments. A single null\nsegment is allowed within the IP address (separated by\ncolons) but not allowed at the beginning or end (unless\na double-null segment; i.e., \"::*\" or \"*::\").\n\nInvalid IPv6 Address: %s"
msg_netmask="netmask"
msg_network_configuration="%s Network Configuration:\nChoose Save/Exit when finished or Cancel."
msg_network_interfaces="Network Interfaces"
diff --git a/usr.sbin/bsdconfig/networking/nameservers b/usr.sbin/bsdconfig/networking/nameservers
index 108c567..e18f004 100755
--- a/usr.sbin/bsdconfig/networking/nameservers
+++ b/usr.sbin/bsdconfig/networking/nameservers
@@ -41,8 +41,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/networking/networking b/usr.sbin/bsdconfig/networking/networking
index b320e5d..c61ce8f 100755
--- a/usr.sbin/bsdconfig/networking/networking
+++ b/usr.sbin/bsdconfig/networking/networking
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr
index f4198c1..42010ab 100644
--- a/usr.sbin/bsdconfig/networking/share/device.subr
+++ b/usr.sbin/bsdconfig/networking/share/device.subr
@@ -40,6 +40,7 @@ f_include $BSDCFG_SHARE/networking/media.subr
f_include $BSDCFG_SHARE/networking/netmask.subr
f_include $BSDCFG_SHARE/networking/resolv.subr
f_include $BSDCFG_SHARE/networking/routing.subr
+f_include $BSDCFG_SHARE/strings.subr
f_include $BSDCFG_SHARE/sysrc.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
@@ -62,7 +63,8 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
#
f_dialog_menu_netdev()
{
- local defaultitem="${1%\*}" # Tim trailing asterisk if present
+ local menu_list # Calculated below
+ local defaultitem="${1%\*}" # Trim trailing asterisk if present
#
# Display a message to let the user know we're working...
@@ -73,20 +75,18 @@ f_dialog_menu_netdev()
#
# 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/:/ /
- "`"
+ local dev devs if iflist= # Calculated below
+ f_device_rescan_network
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ for dev in $devs; do
+ f_struct "$dev" get name if || continue
+ # Skip unsavory interfaces
+ case "$if" in
+ lo[0-9]*|ppp[0-9]*|sl[0-9]*|faith[0-9]*) continue ;;
+ esac
+ iflist="$iflist $if"
+ done
+ iflist="${iflist# }"
#
# Optionally kick interfaces in the head to get them to accurately
@@ -95,9 +95,8 @@ f_dialog_menu_netdev()
if [ "$DIALOG_MENU_NETDEV_KICK_INTERFACES" ]; then
DIALOG_MENU_NETDEV_KICK_INTERFACES=
- local ifn
- for ifn in $iflist; do
- f_quietly ifconfig $ifn up
+ for if in $iflist; do
+ f_quietly ifconfig $if up
done
if [ "$DIALOG_MENU_NETDEV_SLEEP_AFTER_KICK" ]; then
@@ -110,46 +109,37 @@ f_dialog_menu_netdev()
# 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 )"
+ menu_list=$(
+ for if in $iflist; do
+ f_device_desc $if $DEVICE_TYPE_NETWORK desc
+ f_shell_escape "$desc" desc
+ if f_device_is_active $if; then
+ printf "'%s\*' '%s'\n" $if "$desc"
+ else
+ printf "'%s' '%s'\n" $if "$desc"
+ fi
done
)
- if [ ! "$interfaces" ]; then
+ if [ ! "$menu_list" ]; then
f_show_msg "$msg_no_network_interfaces"
return $DIALOG_CANCEL
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"
+ f_device_is_active "$defaultitem" && defaultitem="$defaultitem*"
#
# Ask user to select an interface
#
local prompt="$msg_select_network_interface"
+ local hline="$hline_arrows_tab_enter"
local height width rows
eval f_dialog_menu_size height width rows \
\"\$DIALOG_TITLE\" \
\"\$DIALOG_BACKTITLE\" \
\"\$prompt\" \
\"\$hline\" \
- $interfaces
+ $menu_list
local menu_choice
menu_choice=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
@@ -160,7 +150,7 @@ f_dialog_menu_netdev()
--default-item \"\$defaultitem\" \
--menu \"\$prompt\" \
$height $width $rows \
- $interfaces \
+ $menu_list \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
)
local retval=$?
@@ -175,6 +165,7 @@ f_dialog_menu_netdev()
#
f_dialog_menu_netdev_edit()
{
+ local funcname=f_dialog_menu_netdev_edit
local interface="$1" ipaddr="$2" netmask="$3" options="$4" dhcp="$5"
local prompt menu_list height width rows
@@ -187,7 +178,7 @@ f_dialog_menu_netdev_edit()
dhcp_orig="$5"
local hline="$hline_arrows_tab_enter"
- prompt=$( printf "$msg_network_configuration" "$interface" )
+ f_sprintf prompt "$msg_network_configuration" "$interface"
#
# Loop forever until the user has finished configuring the different
@@ -266,8 +257,9 @@ f_dialog_menu_netdev_edit()
# 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" )"
+ local setting
+ f_sprintf setting "$msg_current_dhcp_status" \
+ "$interface" "$dhcp_status"
f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
continue
fi
@@ -281,25 +273,26 @@ f_dialog_menu_netdev_edit()
trap - SIGINT
( # Execute within sub-shell to allow/catch Ctrl-C
trap 'exit $FAILURE' SIGINT
- msg=$( printf "$msg_scanning_for_dhcp" "$interface" )
+ f_sprintf msg "$msg_scanning_for_dhcp" "$interface"
if [ "$USE_XDIALOG" ]; then
(
- f_quietly ifconfig $interface delete
- f_quietly dhclient $interface
+ 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
+ f_quietly ifconfig "$interface" delete
+ f_quietly dhclient "$interface"
fi
)
retval=$?
trap 'interrupt' SIGINT
if [ $retval -eq $DIALOG_OK ]; then
dhcp=1
- ipaddr=$( f_ifconfig_inet $interface )
- netmask=$( f_ifconfig_netmask $interface )
+ f_ifconfig_inet "$interface" ipaddr
+ f_ifconfig_inet6 "$interface" ipaddr6
+ f_ifconfig_netmask "$interface" netmask
options=
# Fixup search/domain in resolv.conf(5)
@@ -330,14 +323,16 @@ f_dialog_menu_netdev_edit()
local value=
if [ "$dhcp" ]; then
- f_sysrc_delete defaultrouter
+ f_eval_catch $funcname f_sysrc_delete \
+ 'f_sysrc_delete defaultrouter'
value=DHCP
else
value="inet $ipaddr netmask $netmask"
value="$value${options:+ }$options"
fi
- f_sysrc_set ifconfig_$interface "$value"
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set "ifconfig_%s" "%s"' "$interface" "$value"
fi
#
@@ -348,10 +343,12 @@ f_dialog_menu_netdev_edit()
then
f_show_info "$msg_bring_interface_up" "$interface"
- local dr="$( f_sysrc_get defaultrouter )" err
+ local dr="$( f_sysrc_get defaultrouter )"
if [ "$dr" = "NO" -o ! "$dr" ]; then
- dr=$( f_route_get_default )
- [ "$dr" ] && f_sysrc_set defaultrouter "$dr"
+ f_route_get_default dr
+ [ "$dr" ] && f_eval_catch \
+ $funcname f_sysrc_set \
+ 'f_sysrc_set defaultrouter "%s"' "$dr"
fi
#
# Make a backup of resolv.conf(5) before using
@@ -362,16 +359,13 @@ f_dialog_menu_netdev_edit()
# 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"
+ if f_eval_catch $funcname ifconfig \
+ 'ifconfig "%s" inet "%s" netmask "%s" %s' \
+ "$interface" "$ipaddr" "$netmask" "$options"
+ then
+ [ "$dr" -a "$dr" != "NO" ] &&
+ f_eval_catch $funcname route \
+ 'route add default "%s"' "$dr"
fi
if cmp -s "$RESOLV_CONF" "$RESOLV_CONF.$$"; then
f_quietly rm -f "$RESOLV_CONF.$$"
diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr
index ab47494..1c3a67b 100644
--- a/usr.sbin/bsdconfig/networking/share/hostname.subr
+++ b/usr.sbin/bsdconfig/networking/share/hostname.subr
@@ -95,6 +95,7 @@ f_dialog_validate_hostname()
#
f_dialog_input_hostname()
{
+ local funcname=f_dialog_input_hostname
local hostname="$( f_sysrc_get 'hostname:-$(hostname)' )"
local hostname_orig="$hostname" # for change-tracking
@@ -120,7 +121,8 @@ f_dialog_input_hostname()
#
if [ "$hostname" != "$hostname_orig" ]; then
f_dialog_info "$msg_saving_hostname"
- f_sysrc_set hostname "$hostname"
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set hostname "%s"' "$hostname"
fi
#
diff --git a/usr.sbin/bsdconfig/networking/share/ipaddr.subr b/usr.sbin/bsdconfig/networking/share/ipaddr.subr
index f67713a..b7624cc 100644
--- a/usr.sbin/bsdconfig/networking/share/ipaddr.subr
+++ b/usr.sbin/bsdconfig/networking/share/ipaddr.subr
@@ -144,13 +144,14 @@ f_dialog_input_ipaddr()
# system may hang (if any NFS mounts are using that interface).
#
if f_nfs_mounted && ! f_jailed; then
- local setting="$( printf "$msg_current_ipaddr" \
- "$interface" "$_ipaddr" )"
+ local setting
+ f_sprintf setting "$msg_current_ipaddr" "$interface" "$_ipaddr"
f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
return $DIALOG_CANCEL
fi
- local msg="$( printf "$msg_please_enter_new_ip_addr" "$interface" )"
+ local msg
+ f_sprintf msg "$msg_please_enter_new_ip_addr" "$interface"
#
# Loop until the user provides taint-free input.
diff --git a/usr.sbin/bsdconfig/networking/share/media.subr b/usr.sbin/bsdconfig/networking/share/media.subr
index d4283c1..1cb77f8 100644
--- a/usr.sbin/bsdconfig/networking/share/media.subr
+++ b/usr.sbin/bsdconfig/networking/share/media.subr
@@ -115,13 +115,15 @@ f_dialog_input_options()
# the system may hang (if any NFS mounts are using that interface).
#
if f_nfs_mounted && ! f_jailed; then
- local setting="$( printf "$msg_current_options" \
- "$interface" "$options" )"
+ local setting
+ f_sprintf setting "$msg_current_options" \
+ "$interface" "$options"
f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
return $DIALOG_CANCEL
fi
- local msg="$( printf "$msg_please_enter_mediaopts" "$interface" )"
+ local msg
+ f_sprintf msg "$msg_please_enter_mediaopts" "$interface"
local hline="$hline_alnum_punc_tab_enter"
local _options
@@ -162,8 +164,9 @@ f_dialog_menu_media_options()
# the system may hang (if any NFS mounts are using that interface).
#
if f_nfs_mounted && ! f_jailed; then
- local setting="$( printf "$msg_current_options" \
- "$interface" "$_options" )"
+ local setting
+ f_sprintf setting "$msg_current_options" \
+ "$interface" "$_options"
f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
return $DIALOG_CANCEL
fi
@@ -196,11 +199,11 @@ f_dialog_menu_media_options()
local msg
if [ "$USE_XDIALOG" ]; then
- msg=$( printf "$xmsg_supported_media_options" \
- "$interface" "$interface" )
+ f_sprintf msg "$xmsg_supported_media_options" \
+ "$interface" "$interface"
else
- msg=$( printf "$msg_supported_media_options" \
- "$interface" "$interface" )
+ f_sprintf msg "$msg_supported_media_options" \
+ "$interface" "$interface"
fi
local hline="$hline_arrows_tab_enter"
diff --git a/usr.sbin/bsdconfig/networking/share/netmask.subr b/usr.sbin/bsdconfig/networking/share/netmask.subr
index ebd91fc..a7d44a5 100644
--- a/usr.sbin/bsdconfig/networking/share/netmask.subr
+++ b/usr.sbin/bsdconfig/networking/share/netmask.subr
@@ -94,8 +94,9 @@ f_dialog_input_netmask()
# the system may hang (if any NFS mounts are using that interface).
#
if f_nfs_mounted && ! f_jailed; then
- local setting="$( printf "$msg_current_subnet" \
- "$interface" "$_netmask" )"
+ local setting
+ f_sprintf setting "$msg_current_subnet" \
+ "$interface" "$_netmask"
f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
return $DIALOG_CANCEL
fi
@@ -103,7 +104,8 @@ f_dialog_input_netmask()
#
# Loop until the user provides taint-free input.
#
- local msg="$( printf "$msg_please_enter_subnet_mask" "$interface" )"
+ local msg
+ f_sprintf msg "$msg_please_enter_subnet_mask" "$interface"
while :; do
#
# Return error status if:
diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr
index dfeac34..fc42e12 100644
--- a/usr.sbin/bsdconfig/networking/share/resolv.subr
+++ b/usr.sbin/bsdconfig/networking/share/resolv.subr
@@ -162,20 +162,23 @@ END {
'
f_dialog_resolv_conf_update()
{
+ local funcname=f_dialog_resolv_conf_update
local hostname="$1"
#
# Extrapolate the desired domain search parameter for resolv.conf(5)
#
- local search ndots domain="${hostname#*.}"
+ local search nfields ndots domain="${hostname#*.}"
if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then
- search=""
- ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) )
+ search=
+ IFS=. f_count_ifs nfields "$domain"
+ ndots=$(( $nfields - 1 ))
while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do
- search="$search${search:+ }$domain"
+ search="$search $domain"
domain="${domain#*.}"
ndots=$(( $ndots - 1 ))
done
+ search="${search# }"
domain="${hostname#*.}"
else
search="$domain"
@@ -194,8 +197,9 @@ f_dialog_resolv_conf_update()
# 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 $DIALOG_CANCEL
+ local tmpfile
+ f_eval_catch -dk tmpfile $funcname mktemp \
+ 'mktemp -t "%s"' "$tmpfile" || return $DIALOG_CANCEL
#
# Fixup permissions and ownership (mktemp(1) creates the
@@ -203,10 +207,16 @@ f_dialog_resolv_conf_update()
# 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"
+ local mode owner
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$RESOLV_CONF" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$RESOLV_CONF" ||
+ owner="root:wheel"
+ f_eval_catch -d $funcname chmod \
+ 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown \
+ 'chown "%s" "%s"' "$owner" "$tmpfile"
#
# Operate on resolv.conf(5), replacing only the last
@@ -237,7 +247,8 @@ f_dialog_resolv_conf_update()
#
echo "$new_contents" | tail -r > "$tmpfile" ||
return $DIALOG_CANCEL
- f_quietly mv "$tmpfile" "$RESOLV_CONF"
+ f_eval_catch -d $funcname mv \
+ 'mv "%s" "%s"' "$tmpfile" "$RESOLV_CONF"
fi
}
@@ -288,6 +299,7 @@ END { if ( ! found ) exit 3 }
'
f_dialog_input_nameserver()
{
+ local funcname=f_dialog_input_nameserver
local index="${1:-0}" old_ns="$2" new_ns
local ns="$old_ns"
@@ -344,17 +356,23 @@ f_dialog_input_nameserver()
#
# Create a new temporary file to write our new resolv.conf(5)
#
- local tmpfile="$( mktemp -t "$pgm" )"
- [ "$tmpfile" ] || return $DIALOG_CANCEL
+ local tmpfile
+ f_eval_catch -dk tmpfile $funcname mktemp \
+ 'mktemp -t "%s"' "$pgm" || return $DIALOG_CANCEL
#
# 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"
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$RESOLV_CONF" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$RESOLV_CONF" ||
+ owner="root:wheel"
+ f_eval_catch -d $funcname chmod \
+ 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown \
+ 'chown "%s" "%s"' "$owner" "$tmpfile"
#
# Operate on resolv.conf(5)
@@ -383,7 +401,8 @@ f_dialog_input_nameserver()
# file into place.
#
echo "$new_contents" > "$tmpfile" || return $DIALOG_CANCEL
- f_quietly mv "$tmpfile" "$RESOLV_CONF"
+ f_eval_catch -d $funcname mv \
+ 'mv "%s" "%s"' "$tmpfile" "$RESOLV_CONF"
fi
}
@@ -409,7 +428,8 @@ f_dialog_menu_nameservers()
#
# Re/Build list of nameservers
#
- local nameservers="$( f_resolv_conf_nameservers )"
+ local nameservers
+ f_resolv_conf_nameservers nameservers
menu_list=$(
index=1
diff --git a/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr
index d0b8927..826ac6e 100644
--- a/usr.sbin/bsdconfig/networking/share/routing.subr
+++ b/usr.sbin/bsdconfig/networking/share/routing.subr
@@ -35,6 +35,7 @@ f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/media/tcpip.subr
f_include $BSDCFG_SHARE/networking/common.subr
f_include $BSDCFG_SHARE/networking/ipaddr.subr
+f_include $BSDCFG_SHARE/strings.subr
f_include $BSDCFG_SHARE/sysrc.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
@@ -48,6 +49,8 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
#
f_dialog_input_defaultrouter()
{
+ local funcname=f_dialog_input_defaultrouter
+
#
# Get the defaultrouter. When this is not configured, the default is
# "NO", however we don't ever want to present this default to the user
@@ -61,9 +64,7 @@ f_dialog_input_defaultrouter()
local defaultrouter="$( f_sysrc_get 'defaultrouter:-NO' )"
local defaultrouter_orig="$defaultrouter" # for change-tracking
case "$defaultrouter" in
- [Nn][Oo])
- defaultrouter=$( f_route_get_default )
- ;;
+ [Nn][Oo]) f_route_get_default defaultrouter ;;
esac
#
@@ -72,8 +73,9 @@ f_dialog_input_defaultrouter()
# mounted, the system will hang.
#
if f_nfs_mounted && ! f_jailed; then
- local setting="$( printf "$msg_current_default_router" \
- "$defaultrouter" )"
+ local setting
+ f_sprintf setting "$msg_current_default_router" \
+ "$defaultrouter"
f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
return $DIALOG_CANCEL
fi
@@ -101,27 +103,25 @@ f_dialog_input_defaultrouter()
f_dialog_info "$msg_saving_default_router"
# Save the default router/gateway
- f_sysrc_set defaultrouter "$defaultrouter"
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set defaultrouter "%s"' "$defaultrouter"
fi
#
# Only ask to apply setting if the current defaultrouter is different
# than the stored configuration (in rc.conf(5)).
#
- if [ "$( f_route_get_default )" != "$defaultrouter" ]; then
+ local dr
+ f_route_get_default dr
+ if [ "$dr" != "$defaultrouter" ]; then
f_dialog_clear
- f_yesno "$msg_activate_default_router" \
- "$( f_route_get_default )" "$defaultrouter"
+ f_yesno "$msg_activate_default_router" "$dr" "$defaultrouter"
if [ $? -eq $DIALOG_OK ]; 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"
+ f_eval_catch -d $funcname route 'route delete default'
+ f_eval_catch $funcname route \
+ 'route add default "%s"' "$defaultrouter" ||
return $DIALOG_CANCEL
- fi
fi
fi
}
diff --git a/usr.sbin/bsdconfig/networking/share/services.subr b/usr.sbin/bsdconfig/networking/share/services.subr
index b0cf95b..246d895 100644
--- a/usr.sbin/bsdconfig/networking/share/services.subr
+++ b/usr.sbin/bsdconfig/networking/share/services.subr
@@ -42,8 +42,9 @@ f_include $BSDCFG_SHARE/sysrc.subr
#
f_config_pcnfsd()
{
+ local funcname=f_config_pcnfsd
f_package_add "pcnfsd" || return $?
- f_sysrc_set mountd_flags "-n"
+ f_eval_catch $funcname f_sysrc_set 'f_sysrc_set mountd_flags -n'
return $SUCCESS
}
diff --git a/usr.sbin/bsdconfig/packages/packages b/usr.sbin/bsdconfig/packages/packages
index 5b01c3e..ec429f2 100755
--- a/usr.sbin/bsdconfig/packages/packages
+++ b/usr.sbin/bsdconfig/packages/packages
@@ -38,14 +38,15 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/common.subr
f_include $BSDCFG_SHARE/mustberoot.subr
f_include $BSDCFG_SHARE/packages/packages.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="030.packages"
f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -73,6 +74,7 @@ f_device_get_all
#
# Display the package configuration menu and exit
#
+trap 'f_media_close' EXIT
f_package_config
################################################################################
diff --git a/usr.sbin/bsdconfig/password/password b/usr.sbin/bsdconfig/password/password
index 662a536..b73a8d0 100755
--- a/usr.sbin/bsdconfig/password/password
+++ b/usr.sbin/bsdconfig/password/password
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -73,8 +73,8 @@ 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"
+ echo "$pw_password" | f_eval_catch "$0" pw \
+ 'pw usermod "%s" -h 0' "$USER_ROOT" || f_die
f_show_msg "$msg_password_changed"
fi
diff --git a/usr.sbin/bsdconfig/security/kern_securelevel b/usr.sbin/bsdconfig/security/kern_securelevel
index cce2ef0..9aa79b7 100755
--- a/usr.sbin/bsdconfig/security/kern_securelevel
+++ b/usr.sbin/bsdconfig/security/kern_securelevel
@@ -40,8 +40,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -143,19 +143,26 @@ done
case "$mtag" in
"$msg_disabled")
- f_sysrc_set kern_securelevel_enable "NO"
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable NO' || f_die
;;
"$msg_secure")
- f_sysrc_set kern_securelevel_enable "YES"
- f_sysrc_set kern_securelevel "1"
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable YES' || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel 1' || f_die
;;
"$msg_highly_secure")
- f_sysrc_set kern_securelevel_enable "YES"
- f_sysrc_set kern_securelevel "2"
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable YES' || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel 2' || f_die
;;
"$msg_network_secure")
- f_sysrc_set kern_securelevel_enable "YES"
- f_sysrc_set kern_securelevel "3"
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel_enable YES' || f_die
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set kern_securelevel 3' || f_die
;;
*)
f_die 1 "$msg_unknown_kern_securelevel_selection"
diff --git a/usr.sbin/bsdconfig/security/security b/usr.sbin/bsdconfig/security/security
index 7248982..e045ad8 100755
--- a/usr.sbin/bsdconfig/security/security
+++ b/usr.sbin/bsdconfig/security/security
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -162,9 +162,11 @@ while :; do
"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" ;;
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set nfs_reserved_port_only NO' ;;
"3 [ ] $msg_nfs_port") # Same; Toggle value
- f_sysrc_set nfs_reserved_port_only "YES" ;;
+ f_eval_catch "$0" f_sysrc_set \
+ 'f_sysrc_set nfs_reserved_port_only YES' ;;
*)
f_die 1 "$msg_unknown_security_menu_selection"
esac
diff --git a/usr.sbin/bsdconfig/share/Makefile b/usr.sbin/bsdconfig/share/Makefile
index 3392e2a..5b81af4 100644
--- a/usr.sbin/bsdconfig/share/Makefile
+++ b/usr.sbin/bsdconfig/share/Makefile
@@ -5,8 +5,9 @@ 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
+FILES= common.subr device.subr dialog.subr geom.subr keymap.subr \
+ mustberoot.subr script.subr strings.subr struct.subr \
+ sysrc.subr variable.subr
beforeinstall:
mkdir -p ${DESTDIR}${FILESDIR}
diff --git a/usr.sbin/bsdconfig/share/common.subr b/usr.sbin/bsdconfig/share/common.subr
index d087cca..762fd39 100644
--- a/usr.sbin/bsdconfig/share/common.subr
+++ b/usr.sbin/bsdconfig/share/common.subr
@@ -1,7 +1,7 @@
if [ ! "$_COMMON_SUBR" ]; then _COMMON_SUBR=1
#
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -58,9 +58,16 @@ 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)
+export UNAME_S="$( uname -s )" # Operating System (i.e. FreeBSD)
+export UNAME_P="$( uname -p )" # Processor Architecture (i.e. i386)
+export UNAME_M="$( uname -m )" # Machine platform (i.e. i386)
+export UNAME_R="$( uname -r )" # Release Level (i.e. X.Y-RELEASE)
+if [ ! "${PKG_ABI+set}" ]; then
+ export PKG_ABI="$(
+ ASSUME_ALWAYS_YES=1 pkg -vv 2> /dev/null |
+ awk '$1=="ABI"{print $3;exit}'
+ )"
+fi
#
# Default behavior is to call f_debug_init() automatically when loaded.
@@ -68,6 +75,14 @@ export UNAME_R="$(uname -r)" # Release Level (i.e. X.Y-RELEASE)
: ${DEBUG_SELF_INITIALIZE=1}
#
+# Default behavior of f_debug_init() is to truncate $debugFile (set to NULL to
+# disable truncating the debug file when initializing). To get child processes
+# to append to the same log file, export this variarable (with a NULL value)
+# and also export debugFile with the desired value.
+#
+: ${DEBUG_INITIALIZE_FILE=1}
+
+#
# Define standard optstring arguments that should be supported by all programs
# using this include (unless DEBUG_SELF_INITIALIZE is set to NULL to prevent
# f_debug_init() from autamatically processing "$@" for the below arguments):
@@ -106,7 +121,7 @@ GETOPTS_ALLFLAGS="${GETOPTS_ALLFLAGS}0123456789"
############################################################ FUNCTIONS
-# f_dprintf $fmt [ $opts ... ]
+# f_dprintf $format [$arguments ...]
#
# Sensible debug function. Override in ~/.bsdconfigrc if desired.
# See /usr/share/examples/bsdconfig/bsdconfigrc for example.
@@ -138,7 +153,7 @@ f_debug_init()
# Process stored command-line arguments
#
set -- $ARGV
- local OPTIND
+ local OPTIND OPTARG flag
f_dprintf "f_debug_init: ARGV=[%s] GETOPTS_STDARGS=[%s]" \
"$ARGV" "$GETOPTS_STDARGS"
while getopts "$GETOPTS_STDARGS$GETOPTS_EXTRA$GETOPTS_ALLFLAGS" flag \
@@ -164,18 +179,17 @@ f_debug_init()
[ "$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).
+ # Truncate debug file unless requested otherwise. 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 [ "$_debug_file" -a "$DEBUG_INITIALIZE_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
+ f_isset debug || debug=1 # turn debugging on if not set
else
unset debugFile
f_dprintf "Unable to initialize debugFile \`%s'" \
@@ -184,16 +198,16 @@ f_debug_init()
fi
}
-# f_err $fmt [ $opts ... ]
+# f_err $format [$arguments ...]
#
# Print a message to stderr (fd=2).
#
f_err()
{
- printf "$@" >&${TERMINAL_STDERR_PASSTHRU:-2}
+ printf "$@" >&2
}
-# f_quietly $command [ $arguments ... ]
+# f_quietly $command [$arguments ...]
#
# Run a command quietly (quell any output to stdout or stderr)
#
@@ -256,9 +270,9 @@ 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 ${__var_to_set:-value}=\"\${$__var_to_get}\"
eval f_dprintf '"f_getvar: var=[%s] value=[%s] r=%u"' \
\"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval
[ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; }
@@ -275,7 +289,7 @@ f_isset()
eval [ \"\${${1%%[$IFS]*}+set}\" ]
}
-# f_die [ $status [ $fmt [ $opts ... ]]]
+# f_die [$status [$format [$arguments ...]]]
#
# Abruptly terminate due to an error optionally displaying a message in a
# dialog box using printf(1) syntax.
@@ -309,7 +323,7 @@ f_interrupt()
f_die
}
-# f_show_info $fmt [ $opts ... ]
+# f_show_info $format [$arguments ...]
#
# Display a message in a dialog infobox using printf(1) syntax.
#
@@ -330,7 +344,7 @@ f_show_info()
fi
}
-# f_show_msg $fmt [ $opts ... ]
+# f_show_msg $format [$arguments ...]
#
# Display a message in a dialog box using printf(1) syntax.
#
@@ -351,8 +365,29 @@ f_show_msg()
fi
}
+# f_show_err $format [$arguments ...]
+#
+# Display a message in a dialog box with ``Error'' i18n title (overridden by
+# setting msg_error) using printf(1) syntax.
+#
+f_show_err()
+{
+ local msg
+ msg=$( printf "$@" )
+
+ : ${msg:=${msg_an_unknown_error_occurred:-An unknown error occurred}}
-# f_yesno $fmt [ $opts ... ]
+ if [ "$_DIALOG_SUBR" ]; then
+ f_dialog_title "${msg_error:-Error}"
+ f_dialog_msgbox "$msg"
+ f_dialog_title_restore
+ else
+ dialog --title "${msg_error:-Error}" --msgbox "$msg" 0 0
+ fi
+ return $SUCCESS
+}
+
+# f_yesno $format [$arguments ...]
#
# Display a message in a dialog yes/no box using printf(1) syntax.
#
@@ -373,7 +408,7 @@ f_yesno()
fi
}
-# f_noyes $fmt [ $opts ... ]
+# f_noyes $format [$arguments ...]
#
# Display a message in a dialog yes/no box using printf(1) syntax.
# NOTE: THis is just like the f_yesno function except "No" is default.
@@ -466,7 +501,7 @@ f_include_lang()
fi
}
-# f_usage $file [ $key1 $value1 ... ]
+# 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
@@ -485,7 +520,7 @@ f_include_lang()
# 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.
+# text "BAR" before being printed to the screen.
#
# This function is a two-parter. Below is the awk(1) portion of the function,
# afterward is the sh(1) function which utilizes the below awk script.
@@ -527,7 +562,7 @@ f_usage()
exit $FAILURE
}
-# f_index_file $keyword
+# f_index_file $keyword [$var_to_set]
#
# Process all INDEX files known to bsdconfig and return the path to first file
# containing a menu_selection line with a keyword portion matching $keyword.
@@ -537,6 +572,9 @@ f_usage()
#
# If no file is found, error status is returned along with the NULL string.
#
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
# This function is a two-parter. Below is the awk(1) portion of the function,
# afterward is the sh(1) function which utilizes the below awk script.
#
@@ -553,33 +591,55 @@ END { exit ! found }
'
f_index_file()
{
- local keyword="$1"
- local lang="${LANG:-$LC_ALL}"
+ local __keyword="$1" __var_to_set="$2"
+ local __lang="${LANG:-$LC_ALL}"
+ local __indexes="$BSDCFG_LIBE${BSDCFG_LIBE:+/}*/INDEX"
- f_dprintf "f_index_file: keyword=[%s] lang=[%s]" "$keyword" "$lang"
+ 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 $SUCCESS
+ if [ "$__lang" ]; then
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes.$__lang
+ )"' && return $SUCCESS
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" \
+ $__indexes.$__lang && return $SUCCESS
+ fi
# No match, fall-thru to non-i18n sources
fi
- awk -v keyword="$keyword" "$f_index_file_awk" \
- $BSDCFG_LIBE${BSDCFG_LIBE:+/}*/INDEX && return $SUCCESS
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes )"' && return $SUCCESS
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" $__indexes &&
+ return $SUCCESS
+ fi
# No match? Fall-thru to `local' libexec sources (add-on modules)
[ "$BSDCFG_LOCAL_LIBE" ] || return $FAILURE
- if [ "$lang" ]; then
- awk -v keyword="$keyword" "$f_index_file_awk" \
- $BSDCFG_LOCAL_LIBE/*/INDEX.$lang && return $SUCCESS
+ __indexes="$BSDCFG_LOCAL_LIBE/*/INDEX"
+ if [ "$__lang" ]; then
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='"$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes.$__lang
+ )"' && return $SUCCESS
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" \
+ $__indexes.$__lang && return $SUCCESS
+ fi
# No match, fall-thru to non-i18n sources
fi
- awk -v keyword="$keyword" "$f_index_file_awk" \
- $BSDCFG_LOCAL_LIBE/*/INDEX
+ if [ "$__var_to_set" ]; then
+ eval "$__var_to_set"='$( awk -v keyword="$__keyword" \
+ "$f_index_file_awk" $__indexes )"'
+ else
+ awk -v keyword="$__keyword" "$f_index_file_awk" $__indexes
+ fi
}
-# f_index_menusel_keyword $indexfile $pgm
+# f_index_menusel_keyword $indexfile $pgm [$var_to_set]
#
# Process $indexfile and return only the keyword portion of the menu_selection
# line with a command portion matching $pgm.
@@ -596,6 +656,9 @@ f_index_file()
#
# If $indexfile does not exist, error status is returned with NULL.
#
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
# This function is a two-parter. Below is the awk(1) portion of the function,
# afterward is the sh(1) function which utilizes the below awk script.
#
@@ -626,24 +689,23 @@ END { exit ! found }
'
f_index_menusel_keyword()
{
- local indexfile="$1" pgm="$2"
- local lang="${LANG:-$LC_ALL}"
+ local __indexfile="$1" __pgm="$2" __var_to_set="$3"
+ local __lang="${LANG:-$LC_ALL}" __file="$__indexfile"
+ [ -f "$__indexfile.$__lang" ] && __file="$__indexfile.$__lang"
f_dprintf "f_index_menusel_keyword: index=[%s] pgm=[%s] lang=[%s]" \
- "$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"
+ "$__file" "$__pgm" "$__lang"
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$( awk \
+ -v pgm="$__pgm" "$f_index_menusel_keyword_awk" "$__file"
+ )"
+ else
+ awk -v pgm="$__pgm" "$f_index_menusel_keyword_awk" "$__file"
fi
}
-# f_index_menusel_command $indexfile $keyword
+# f_index_menusel_command $indexfile $keyword [$var_to_set]
#
# Process $indexfile and return only the command portion of the menu_selection
# line with a keyword portion matching $keyword.
@@ -659,6 +721,9 @@ f_index_menusel_keyword()
#
# If $indexfile doesn't exist, error status is returned with NULL.
#
+# If $var_to_set is NULL or missing, output is printed to stdout (which is less
+# recommended due to performance degradation; in a loop for example).
+#
# This function is a two-parter. Below is the awk(1) portion of the function,
# afterward is the sh(1) function which utilizes the below awk script.
#
@@ -689,37 +754,34 @@ END { exit ! found }
'
f_index_menusel_command()
{
- local indexfile="$1" keyword="$2" command
- local lang="${LANG:-$LC_ALL}"
+ local __indexfile="$1" __keyword="$2" __var_to_set="$3" __command
+ local __lang="${LANG:-$LC_ALL}" __file="$__indexfile"
+ [ -f "$__indexfile.$__lang" ] && __file="$__indexfile.$__lang"
f_dprintf "f_index_menusel_command: index=[%s] key=[%s] lang=[%s]" \
- "$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
+ "$__file" "$__keyword" "$__lang"
+
+ [ -f "$__file" ] || return $FAILURE
+ __command=$( awk -v key="$__keyword" \
+ "$f_index_menusel_command_awk" "$__file" ) || return $FAILURE
#
# If the command pathname is not fully qualified fix-up/force to be
# relative to the $indexfile directory.
#
- case "$command" in
+ case "$__command" in
/*) : already fully qualified ;;
*)
- local indexdir="${indexfile%/*}"
- [ "$indexdir" != "$indexfile" ] || indexdir="."
- command="$indexdir/$command"
+ local __indexdir="${__indexfile%/*}"
+ [ "$__indexdir" != "$__indexfile" ] || __indexdir="."
+ __command="$__indexdir/$__command"
esac
- echo "$command"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__command"
+ else
+ echo "$__command"
+ fi
}
# f_running_as_init
@@ -736,14 +798,192 @@ f_running_as_init()
}
# f_mounted $local_directory
+# f_mounted -b $device
#
-# Return success if a filesystem is mounted on a particular directory.
+# Return success if a filesystem is mounted on a particular directory. If `-b'
+# is present, instead check that the block device (or a partition thereof) is
+# mounted.
#
f_mounted()
{
- local dir="$1"
- [ -d "$dir" ] || return $FAILURE
- mount | grep -Eq " on $dir \([^)]+\)$"
+ local OPTIND OPTARG flag use_device=
+ while getopts b flag; do
+ case "$flag" in
+ b) use_device=1 ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+ if [ "$use_device" ]; then
+ local device="$1"
+ mount | grep -Eq \
+ "^$device([[:space:]]|p[0-9]|s[0-9]|\.nop|\.eli)"
+ else
+ [ -d "$dir" ] || return $FAILURE
+ mount | grep -Eq " on $dir \([^)]+\)$"
+ fi
+ # Return status is that of last grep(1)
+}
+
+# f_eval_catch [-de] [-k $var_to_set] $funcname $utility \
+# $format [$arguments ...]
+#
+# Silently evaluate a command in a sub-shell and test for error. If debugging
+# is enabled a copy of the command and its output is sent to debug (either
+# stdout or file depending on environment). If an error occurs, output of the
+# command is displayed in a dialog(1) msgbox using the [above] f_show_err()
+# function (unless optional `-d' flag is given, then no dialog).
+#
+# The $funcname argument is sent to debugging while the $utility argument is
+# used in the title of the dialog box. The command that is executed as well as
+# sent to debugging with $funcname is the product of the printf(1) syntax
+# produced by $format with optional $arguments.
+#
+# The following options are supported:
+#
+# -d Do not use dialog(1).
+# -e Produce error text from failed command on stderr.
+# -k var Save output from the command in var.
+#
+# Example 1:
+#
+# debug=1
+# f_eval_catch myfunc echo 'echo "%s"' "Hello, World!"
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: echo "Hello, World!"
+# DEBUG: myfunc: retval=0 <output below>
+# Hello, World!
+#
+# Example 2:
+#
+# debug=1
+# f_eval_catch -k contents myfunc cat 'cat "%s"' /some/file
+# # dialog(1) Error ``cat: /some/file: No such file or directory''
+# # contents=[cat: /some/file: No such file or directory]
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: cat "/some/file"
+# DEBUG: myfunc: retval=1 <output below>
+# cat: /some/file: No such file or directory
+#
+# Example 3:
+#
+# debug=1
+# echo 123 | f_eval_catch myfunc rev rev
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: rev
+# DEBUG: myfunc: retval=0 <output below>
+# 321
+#
+# Example 4:
+#
+# debug=1
+# f_eval_catch myfunc true true
+#
+# Produces the following debug output:
+#
+# DEBUG: myfunc: true
+# DEBUG: myfunc: retval=0 <no output>
+#
+# Example 5:
+#
+# f_eval_catch -de myfunc ls 'ls "%s"' /some/dir
+# # Output on stderr ``ls: /some/dir: No such file or directory''
+#
+# Example 6:
+#
+# f_eval_catch -dek contents myfunc ls 'ls "%s"' /etc
+# # Output from `ls' sent to stderr and also saved in $contents
+#
+f_eval_catch()
+{
+ local __no_dialog= __show_err= __var_to_set=
+
+ #
+ # Process local function arguments
+ #
+ local OPTIND OPTARG __flag
+ while getopts "dek:" __flag > /dev/null; do
+ case "$__flag" in
+ d) __no_dialog=1 ;;
+ e) __show_err=1 ;;
+ k) __var_to_set="$OPTARG" ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
+ local __funcname="$1" __utility="$2"; shift 2
+ local __cmd __output __retval
+
+ __cmd=$( printf -- "$@" )
+ f_dprintf "%s: %s" "$__funcname" "$__cmd" # Log command *before* eval
+ __output=$( exec 2>&1; eval "$__cmd" )
+ __retval=$?
+ if [ "$__output" ]; then
+ [ "$__show_err" ] && echo "$__output" >&2
+ f_dprintf "%s: retval=%i <output below>\n%s" "$__funcname" \
+ $__retval "$__output"
+ else
+ f_dprintf "%s: retval=%i <no output>" "$__funcname" $__retval
+ fi
+
+ ! [ "$__no_dialog" -o "$nonInteractive" -o $__retval -eq $SUCCESS ] &&
+ msg_error="${msg_error:-Error}${__utility:+: $__utility}" \
+ f_show_err "%s" "$__output"
+ # NB: f_show_err will handle NULL output appropriately
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output"
+
+ return $__retval
+}
+
+# f_count $var_to_set arguments ...
+#
+# Sets $var_to_set to the number of arguments minus one (the effective number
+# of arguments following $var_to_set).
+#
+# Example:
+# f_count count dog house # count=[2]
+#
+f_count()
+{
+ setvar "$1" $(( $# - 1 ))
+}
+
+# f_count_ifs $var_to_set string ...
+#
+# Sets $var_to_set to the number of words (split by the internal field
+# separator, IFS) following $var_to_set.
+#
+# Example 1:
+#
+# string="word1 word2 word3"
+# f_count_ifs count "$string" # count=[3]
+# f_count_ifs count $string # count=[3]
+#
+# Example 2:
+#
+# IFS=. f_count_ifs count www.freebsd.org # count=[3]
+#
+# NB: Make sure to use double-quotes if you are using a custom value for IFS
+# and you don't want the current value to effect the result. See example 3.
+#
+# Example 3:
+#
+# string="a-b c-d"
+# IFS=- f_count_ifs count "$string" # count=[3]
+# IFS=- f_count_ifs count $string # count=[4]
+#
+f_count_ifs()
+{
+ local __var_to_set="$1"
+ shift 1
+ set -- $*
+ setvar "$__var_to_set" $#
}
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr
index b920809..d93cd9b 100644
--- a/usr.sbin/bsdconfig/share/device.subr
+++ b/usr.sbin/bsdconfig/share/device.subr
@@ -1,6 +1,6 @@
if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
#
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." device.subr
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/geom.subr
f_include $BSDCFG_SHARE/strings.subr
f_include $BSDCFG_SHARE/struct.subr
@@ -40,114 +41,128 @@ f_include_lang $BSDCFG_LIBE/include/messages.subr
############################################################ GLOBALS
-DEVICES=
-DEVICE_NAMES=
+NDEVICES=0 # Set by f_device_register(), used by f_device_*()
-# A "device" from sysinstall's point of view
+#
+# A "device" from legacy sysinstall's point of view (mostly)
+#
+# NB: Disk devices have their `private' property set to GEOM ident
+# NB: USB devices have their `private' property set to USB disk device name
+#
f_struct_define DEVICE \
- name \
+ capacity \
desc \
devname \
- type \
enabled \
- init \
- get \
- shutdown \
flags \
+ get \
+ init \
+ name \
private \
+ shutdown \
+ type \
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
+ extras \
+ ipaddr \
+ ipv6addr \
+ netmask \
+ use_dhcp \
+ use_rtsol
+
+#
+# Device types for f_device_register(), f_device_find(), et al.
+#
+setvar DEVICE_TYPE_ANY "any" # Any
+setvar DEVICE_TYPE_NONE "NONE" # Unknown
+setvar DEVICE_TYPE_DISK "DISK" # GEOM `DISK'
+setvar DEVICE_TYPE_FLOPPY "FD" # GEOM `FD'
+setvar DEVICE_TYPE_FTP "FTP" # Dynamic network device
+setvar DEVICE_TYPE_NETWORK "NETWORK" # See f_device_get_all_network
+setvar DEVICE_TYPE_CDROM "CDROM" # GEOM `DISK'
+setvar DEVICE_TYPE_USB "USB" # GEOM `PART'
+setvar DEVICE_TYPE_DOS "DOS" # GEOM `DISK' `PART' or `LABEL'
+setvar DEVICE_TYPE_UFS "UFS" # GEOM `DISK' `PART' or `LABEL'
+setvar DEVICE_TYPE_NFS "NFS" # Dynamic network device
+setvar DEVICE_TYPE_HTTP_PROXY "HTTP_PROXY" # Dynamic network device
+setvar DEVICE_TYPE_HTTP "HTTP" # Dynamic network device
+
+# Network devices have the following flags available
+setvar IF_ETHERNET 1
+setvar IF_WIRELESS 2
+setvar IF_ACTIVE 4
#
# Default behavior is to call f_device_get_all() automatically when loaded.
#
: ${DEVICE_SELF_SCAN_ALL=1}
-############################################################ 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.
+# Device Catalog variables
#
-# Returns success if the device path exists and is a cdev.
+DEVICE_CATALOG_APPEND_ONLY= # Used by f_device_catalog_set()
+NCATALOG_DEVICES=0 # Used by f_device_catalog_*() and MAIN
+
#
-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
-}
+# A ``catalog'' device is for mapping GEOM devices to media devices (for
+# example, determining if a $GEOM_CLASS_DISK geom is $DEVICE_TYPE_CDROM or
+# $DEVICE_TYPE_DISK) and also getting default descriptions for devices that
+# either lack a GEOM provided description or lack a presence in GEOM)
+#
+f_struct_define CATALOG_DEVICE \
+ desc \
+ name \
+ type
+
+############################################################ FUNCTIONS
-# f_device_register $name $desc $devname $type $enabled $init_function \
-# $get_function $shutdown_function $private
+# f_device_register $var_to_set $name $desc $devname $type $enabled
+# $init_function $get_function $shutdown_function
+# $private $capacity
#
-# Register a device. A `structure' (see struct.subr) is created 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).
+# Register a device. A `structure' (see struct.subr) is created and if
+# $var_to_set is non-NULL, upon success holds the name of the struct created.
+# The remaining positional arguments correspond to the properties of the
+# `DEVICE' structure-type to be assigned (defined above).
#
-# If not already registered, the device is then appended to the DEVICES
-# environment variable, a space-separated list of all registered devices.
+# If not already registered (based on $name and $type), a new device is created
+# and $NDEVICES is incremented.
#
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"
+ local __var_to_set="$1" __name="$2" __desc="$3" __devname="$4"
+ local __type="$5" __enabled="$6" __init_func="$7" __get_func="$8"
+ local __shutdown_func="$9" __private="${10}" __capacity="${11}"
+ # Required parameter(s)
+ [ "$__name" ] || return $FAILURE
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "" || return $FAILURE
+ fi
+
+ local __device
+ if f_device_find -1 "$__name" "$__type" __device; then
+ f_struct_free "$__device"
+ f_struct_new DEVICE "$__device" || return $FAILURE
+ else
+ __device=device_$(( NDEVICES + 1 ))
+ f_struct_new DEVICE "$__device" || return $FAILURE
+ NDEVICES=$(( $NDEVICES + 1 ))
+ fi
+ $__device set name "$__name"
+ $__device set desc "$__desc"
+ $__device set devname "$__devname"
+ $__device set type "$__type"
+ $__device set enabled "$__enabled"
+ $__device set init "$__init_func"
+ $__device set get "$__get_func"
+ $__device set shutdown "$__shutdown_func"
+ $__device set private "$__private"
+ $__device set capacity "$__capacity"
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" "$__device"
return $SUCCESS
}
@@ -157,33 +172,94 @@ f_device_register()
#
f_device_reset()
{
- local dev
- for dev in $DEVICES; do
- f_device_shutdown $dev
+ local n=1
+ while [ $n -le $NDEVICES ]; do
+ f_device_shutdown device_$n
#
- # XXX this potentially leaks $dev->private if it's being
+ # 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
+ # has its private member pointing somewhere anyway.
+ #
+ f_struct_free device_$n
+
+ n=$(( $n + 1 ))
+ done
+ NDEVICES=0
+}
+
+# f_device_reset_network
+#
+# Reset the registered network device chain.
+#
+f_device_reset_network()
+{
+ local n=1 device type private i
+ while [ $n -le $NDEVICES ]; do
+ device=device_$n
+ f_struct $device || continue
+ $device get type type
+ [ "$type" = "$DEVICE_TYPE_NETWORK" ] || continue
+
#
- f_struct_free device_$dev
+ # Leave the device up (don't call shutdown routine)
+ #
+
+ # Network devices may have DEVICE_INFO private member
+ $device get private private
+ [ "$private" ] && f_struct_free "$private"
+
+ # Free the network device
+ f_struct_free $device
+
+ # Fill the gap we just created
+ i=$n
+ while [ $i -lt $NDEVICES ]; do
+ f_struct_copy device_$(( $i + 1 )) device_$i
+ done
+ f_struct_free device_$NDEVICES
+
+ # Finally decrement the number of devices
+ NDEVICES=$(( $NDEVICES - 1 ))
+
+ n=$(( $n + 1 ))
done
- DEVICES=
}
# f_device_get_all
#
-# Get all device information for devices we have attached.
+# Get all device information for all devices.
#
f_device_get_all()
{
- local devname desc
+ local devname type desc capacity
f_dprintf "f_device_get_all: Probing devices..."
f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
# First go for the network interfaces
+ f_device_get_all_network
+
+ # Next, go for the GEOM devices we might want to use as media
+ local geom geoms geom_name
+ debug= f_geom_find "" $GEOM_CLASS_DEV geoms
+ for geom in $geoms; do
+ if ! f_device_probe_geom $geom; then
+ debug= $geom get name geom_name
+ f_dprintf "WARNING! Unable to classify %s as %s" \
+ "GEOM device $geom_name" "media source"
+ fi
+ done
+}
+
+# f_device_get_all_network
+#
+# Get all network device information for attached network devices.
+#
+f_device_get_all_network()
+{
+ local devname desc device flags
for devname in $( ifconfig -l ); do
# Eliminate network devices that don't make sense
case "$devname" in
@@ -193,232 +269,618 @@ f_device_get_all()
# 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 ""
+ f_dprintf "Found network device named %s" "$devname"
+ debug= f_device_register device $devname "$desc" \
+ "$devname" $DEVICE_TYPE_NETWORK 1 \
+ f_media_init_network "" f_media_shutdown_network "" -1
+
+ # Set flags based on media and status
+ flags=0
+ eval "$( ifconfig $devname 2> /dev/null | awk -v var=flags '
+ function _or(var, mask) {
+ printf "%s=$(( $%s | $%s ))\n", var, var, mask
+ }
+ BEGIN { S = "[[:space:]]+" }
+ {
+ if (!match($0, "^" S "(media|status):" S)) next
+ value = substr($0, RLENGTH + 1)
+ if ($1 == "media:") {
+ if (value ~ /Ethernet/) _or(var, "IF_ETHERNET")
+ if (value ~ /802\.11/) _or(var, "IF_WIRELESS")
+ } else if ($1 == "status:") {
+ if (value ~ /^active/) _or(var, "IF_ACTIVE")
+ }
+ }' )"
+ $device set flags $flags
done
+}
+
+# f_device_rescan
+#
+# Rescan all devices, after closing previous set - convenience function.
+#
+f_device_rescan()
+{
+ f_device_reset
+ f_geom_rescan
+ f_device_get_all
+}
+
+# f_device_rescan_network
+#
+# Rescan all network devices, after closing previous set - for convenience.
+#
+f_device_rescan_network()
+{
+ f_device_reset_network
+ f_device_get_all_network
+}
+
+# f_device_probe_geom $geom
+#
+# Probe a single GEOM device and if it can be classified as a media source,
+# register it using f_device_register() with known type-specific arguments.
+#
+f_device_probe_geom()
+{
+ local geom="$1"
+
+ f_struct "$geom" || return $FAILURE
+
+ # geom associated variables
+ local geom_name geom_consumer provider_ref geom_provider=
+ local provider_geom provider_config provider_class=
+ local provider_config_type catalog_struct catalog_type
+ local disk_ident
+
+ # gnop(8)/geli(8) associated variables (p for `parent device')
+ local p_devname p_geom p_consumer p_provider_ref p_provider
+ local p_provider_config p_provider_geom p_provider_class
+
+ # md(4) associated variables
+ local config config_type config_file magic=
+
+ # Temporarily disable debugging to keep debug output light
+ local old_debug="$debug" debug=
- # Next, try to find all the types of devices one might use
- # as a media source for content
#
+ # Get the GEOM name (for use below in device registration)
+ #
+ $geom get name devname || continue
- 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
+ #
+ # Attempt to get the consumer, provider, provider config, and
+ # provider class for this geom (errors ignored).
+ #
+ # NB: Each GEOM in the `DEV' class should have one consumer.
+ # That consumer should have a reference to its provider.
+ #
+ $geom get consumer1 geom_consumer
+ f_struct "$geom_consumer" get provider_ref provider_ref &&
+ f_geom_find_by id "$provider_ref" provider geom_provider
+ if f_struct "$geom_provider"; then
+ $geom_provider get config provider_config
+ f_geom_parent $geom_provider provider_geom &&
+ f_geom_parent $provider_geom provider_class
+ fi
- # 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
+ #
+ # Get values for device registration (errors ignored)
+ #
+ f_struct "$provider_class" get name type
+ f_struct "$geom_provider" get mediasize capacity
+ f_struct "$provider_config" get descr desc
+
+ #
+ # For gnop(8), geli(8), or combination thereof, change device type to
+ # that of the consumer
+ #
+ p_devname= p_geom= p_provider= p_provider_config=
+ case "$devname" in
+ *.nop.eli) p_devname="${devname%.nop.eli}" ;;
+ *.eli.nop) p_devname="${devname%.eli.nop}" ;;
+ *.eli) p_devname="${devname%.eli}" ;;
+ *.nop) p_devname="${devname%.nop}" ;;
+ esac
+ [ "$p_devname" ] && f_geom_find "$p_devname" $GEOM_CLASS_DEV p_geom
+ if [ "${p_geom:-$geom}" != "$geom" ]; then
+ f_struct "$p_geom" get consumer1 p_consumer
+ f_struct "$p_consumer" get provider_ref p_provider_ref &&
+ f_geom_find_by id "$p_provider_ref" provider p_provider
+ if f_struct "$p_provider"; then
+ $p_provider get config p_provider_config
+ f_geom_parent $p_provider p_provider_geom &&
+ f_geom_parent $p_provider_geom p_provider_class
+ fi
+ f_struct "$p_provider_class" get name type
+ fi
+
+ # Look up geom device in device catalog for default description
+ f_device_catalog_get \
+ $DEVICE_TYPE_ANY "${p_devname:-$devname}" catalog_struct
+ [ "$desc" ] || f_struct "catalog_device_$catalog_struct" get desc desc
+
+ # Use device catalog entry for potential re-classification(s)
+ f_struct "catalog_device_$catalog_struct" get type catalog_type
+
+ # Restore debugging for this next part (device registration)
+ debug="$old_debug"
- # 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 \
+ #
+ # Register the device
+ #
+ local retval device
+ case "$type" in
+ $GEOM_CLASS_DISK)
+ # First attempt to classify by device catalog (see MAIN)
+ case "$catalog_type" in
+ $DEVICE_TYPE_CDROM)
+ f_dprintf "Found CDROM device for disk %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
f_media_init_cdrom f_media_get_cdrom \
- f_media_shutdown_cdrom ""
- f_dprintf "Found a CDROM device for %s" "$devname"
+ f_media_shutdown_cdrom "" "$capacity" &&
+ return $SUCCESS
;;
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
+ # Fall back to register label device as a disk and taste it
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_struct "$p_provider_config" get \
+ ident disk_ident ||
+ debug= f_struct "$provider_config" get \
+ ident disk_ident
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "$disk_ident" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems (errors ignored)
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS
+
+ return $retval
+ ;;
+ $GEOM_CLASS_FD)
+ f_dprintf "Found floppy device named %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_FLOPPY 1 \
+ f_media_init_floppy f_media_get_floppy \
+ f_media_shutdown_floppy "" "$capacity"
+ return $?
+ ;;
+ $GEOM_CLASS_LABEL)
+ : fall through to below section # reduces indentation level
+ ;;
+ $GEOM_CLASS_MD)
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ #
+ # Attempt to get file(1) magic to potentially classify as
+ # alternate media type. If unable to get magic, fall back to
+ # md(4) characteristics (such as vnode filename).
+ #
+ [ -r "/dev/$devname" ] &&
+ magic=$( file -bs "/dev/$devname" 2> /dev/null )
+ if [ ! "$magic" ]; then
+ # Fall back to md(4) characteristics
+ if f_struct "$p_provider_config"; then
+ config="$p_provider_config"
+ else
+ config="$provider_config"
+ fi
+ debug= f_struct "$config" get type config_type
+ debug= f_struct "$config" get file config_file
- # 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 }' )
+ # Substitute magic for below based on type and file
+ case "$config_type=$config_file" in
+ vnode=*.iso) magic="ISO 9660" ;;
+ esac
+ fi
+ f_device_probe_disk_fs device \
+ "$devname" "$capacity" "$magic" &&
+ retval=$SUCCESS # Errors ignored
+
+ return $retval
+ ;;
+ $GEOM_CLASS_PART)
+ if f_struct "$p_provider_config"; then
+ config="$p_provider_config"
+ else
+ config="$provider_config"
+ fi
+ debug= f_struct "$config" get type provider_config_type
+ f_device_probe_geom_part device \
+ "$provider_config_type" "$devname" "$capacity"
+ retval=$?
+ device_type=$DEVICE_TYPE_NONE
+ [ $retval -eq $SUCCESS ] &&
+ debug= f_struct "$device" get type device_type
+
+ # Potentially re-classify as USB device
+ if [ "$device_type" = "$DEVICE_TYPE_UFS" -a \
+ "$catalog_type" = "$DEVICE_TYPE_USB" ]
then
- f_dprintf "Unable to open disk %s" "$diskname"
- continue
+ f_dprintf "Found USB device for partition %s" \
+ "$devname"
+ debug= f_struct "$p_provider_geom" get \
+ name disk_name ||
+ debug= f_struct "$provider_geom" get \
+ name disk_name
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_USB 1 \
+ f_media_init_usb f_media_get_usb \
+ f_media_shutdown_usb "$disk_name" "$capacity"
+ retval=$?
fi
- 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
+ return $retval
+ ;;
+ $GEOM_CLASS_RAID)
+ # Use the provider geom name as the description
+ if [ ! "$desc" ]; then
+ f_struct "$p_provider_geom" get name desc ||
+ f_struct "$provider_geom" get name desc
+ fi
+
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "${desc:-GEOM RAID device}" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS # Errors ignored
+
+ return $retval
+ ;;
+ $GEOM_CLASS_ZFS_ZVOL)
+ f_dprintf "Found disk device named %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "${desc:-GEOM ZFS::ZVOL device}" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS # Errors ignored
+
+ return $retval
+ ;;
+ *)
+ return $FAILURE # Unknown GEOM class
+ esac
+
+ #
+ # Still here? Must be $GEOM_CLASS_LABEL
+ #
+
+ local label_geom label_devname label_devgeom= label_devconsumer
+ local label_devprovider= label_devprovider_ref label_devprovider_config
+ local label_gpart_type
+
+ if f_struct "$p_provider"; then
+ label_geom="$p_provider_geom"
+ else
+ label_geom="$provider_geom"
+ fi
+
+ case "$devname" in
+ gpt/*|gptid/*)
+ #
+ # Attempt to get the partition type by getting the `config'
+ # member of the provider for our device (which is named in the
+ # parent geom of our current provider).
+ #
+ debug= f_struct "$label_geom" get name label_devname &&
+ debug= f_geom_find "$label_devname" $GEOM_CLASS_DEV \
+ label_devgeom
+ debug= f_struct "$label_devgeom" get \
+ consumer1 label_devconsumer
+ debug= f_struct "$label_devconsumer" get \
+ provider_ref label_devprovider_ref &&
+ debug= f_geom_find_by id "$label_devprovider_ref" \
+ provider label_devprovider
+ debug= f_struct "$label_devprovider" get \
+ config label_devprovider_config
+ debug= f_struct "$label_devprovider_config" get \
+ type label_gpart_type
- done # disks
+ #
+ # Register device label based on partition type
+ #
+ f_device_probe_geom_part device \
+ "$label_gpart_type" "$devname" "$capacity"
+ return $?
+ ;;
+ iso9660/*)
+ f_dprintf "Found CDROM device labeled %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "ISO9660 file system" \
+ "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$capacity"
+ return $?
+ ;;
+ label/*)
+ # For generic labels, use provider geom name as real device
+ debug= f_struct "$label_geom" get name label_devname
+
+ # Look up label geom device in device catalog for default desc
+ debug= f_device_catalog_get \
+ $DEVICE_TYPE_ANY "$label_devname" catalog_struct
+ [ "$desc" ] || debug= f_struct \
+ "catalog_device_$catalog_struct" get desc desc
+
+ # Use device catalog entry for potential re-classification(s)
+ debug= f_struct "catalog_device_$catalog_struct" get \
+ type catalog_type
+
+ # First attempt to classify by device catalog (see MAIN)
+ case "$catalog_type" in
+ $DEVICE_TYPE_CDROM)
+ f_dprintf "Found CDROM device for disk %s" "$devname"
+ debug= f_device_register device "$devname" "$desc" \
+ "/dev/$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$capacity" &&
+ return $SUCCESS
+ ;;
+ esac
+
+ # Fall back to register label device as a disk and taste it
+ f_dprintf "Found disk device labeled %s" "$devname"
+ debug= f_device_register device \
+ "$devname" "GEOM LABEL device" \
+ "/dev/$devname" $DEVICE_TYPE_DISK 1 \
+ "" "" "" "" "$capacity"
+ retval=$?
+
+ # Detect ``dangerously dedicated'' filesystems (errors ignored)
+ f_device_probe_disk_fs device "$devname" "$capacity" &&
+ retval=$SUCCESS
+
+ return $retval
+ ;;
+ msdosfs/*)
+ f_dprintf "Found DOS partition labeled %s" "$devname"
+ debug= f_device_register device "$devname" "DOS file system" \
+ "/dev/$devname" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos "" "$capacity"
+ return $?
+ ;;
+ ufs/*|ufsid/*)
+ f_dprintf "Found UFS partition labeled %s" "$devname"
+ debug= f_device_register device "$devname" "UFS file system" \
+ "/dev/$devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$capacity"
+ return $?
+ ;;
+ ext2fs/*|ntfs/*|reiserfs/*)
+ return $FAILURE # No media device handlers for these labels
+ ;;
+ esac
+
+ # Unable to classify GEOM label
+ return $FAILURE
}
-# f_device_name_get $type $name type|desc|max [$var_to_set]
+# f_device_probe_geom_part $var_to_set $gpart_type $devname $capacity [$magic]
+#
+# Given a gpart(8) partition type and a device name, register the device if it
+# is a known partition type that we can handle. If $var_to_set is non-NULL,
+# upon success holds the DEVICE struct name of the registered device.
+#
+# Returns success if the device was successfully registered, failure otherwise.
#
-# 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.
+f_device_probe_geom_part()
+{
+ local __var_to_set="$1" __gpart_type="$2" __devname="$3"
+ local __capacity="${4:--1}" __magic="$5"
+
+ #
+ # Register device based on partition type
+ # NB: !0 equates to `unused' bsdlabel
+ #
+ case "$__gpart_type" in
+ fat16|fat32)
+ f_dprintf "Found DOS partition named %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "DOS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos "" "$__capacity"
+ return $?
+ ;;
+ freebsd|!0) # Commonly used inappropriately, taste for FreeBSD
+ [ -r "/dev/$__devname" -a ! "$__magic" ] &&
+ __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
+ case "$__magic" in
+ *"Unix Fast File system"*)
+ f_dprintf "Found UFS partition named %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "UFS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$__capacity"
+ return $?
+ esac
+ return $FAILURE
+ ;;
+ freebsd-ufs)
+ f_dprintf "Found UFS partition named %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "UFS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$__capacity"
+ return $?
+ ;;
+ apple-*|linux-*|ms-*|netbsd-*|ntfs|vmware-*)
+ return $FAILURE # No device types for these
+ ;;
+ bios-*|ebr|efi|mbr|freebsd-boot|freebsd-swap)
+ return $FAILURE # Not a source for media
+ ;;
+ freebsd-nandfs|freebsd-vinum|freebsd-zfs)
+ return $FAILURE # Unsupported as media source
+ ;;
+ esac
+
+ return $FAILURE # Unknown partition type
+}
+
+# f_device_probe_disk_fs $var_to_set $devname [$capacity [$magic]]
+#
+# Given a device name, taste it and register the device if it is a so-called
+# ``dangerously dedicated'' file system written without a partition table.
+# Tasting is done using file(1) (specifically `file -bs') but if $magic is
+# present and non-NULL it is used instead. If $var_to_set is non-NULL, upon
+# success holds the DEVICE struct name of the registered device.
+#
+# Returns success if the device was successfully registered, failure otherwise.
+#
+f_device_probe_disk_fs()
+{
+ local __var_to_set="$1" __devname="$2" __capacity="${3:--1}"
+ local __magic="$4"
+
+ [ -r "/dev/${__devname#/dev/}" -a ! "$__magic" ] &&
+ __magic=$( file -bs "/dev/$__devname" 2> /dev/null )
+
+ case "$__magic" in
+ *"ISO 9660"*)
+ f_dprintf "Found CDROM device for disk %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "ISO9660 file system" \
+ "/dev/$__devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom "" "$__capacity"
+ return $?
+ ;;
+ *"Unix Fast File system"*)
+ f_dprintf "Found UFS device for disk %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "UFS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs f_media_get_ufs \
+ f_media_shutdown_ufs "" "$__capacity"
+ return $?
+ ;;
+ *"FAT (12 bit)"*|*"FAT (16 bit)"*|*"FAT (32 bit)"*)
+ f_dprintf "Found DOS device for disk %s" "$__devname"
+ debug= f_device_register "$__var_to_set" \
+ "$__devname" "DOS file system" \
+ "/dev/$__devname" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos "" "$__capacity"
+ return $?
+ ;;
+ esac
+
+ return $FAILURE # Unknown file system type
+}
+
+# f_device_catalog_get $type $name [$var_to_set]
+#
+# Fetch the struct name of the catalog device matching device $name. If $type
+# is either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
# Returns success if a match was found, otherwise failure.
#
-# If $var_to_set is missing or NULL, the device name is printed to standard out
+# If $var_to_set is missing or NULL, the struct name is printed to standard out
# for capturing in a sub-shell (which is less-recommended because of
# performance degredation; for example, when called in a loop).
#
-f_device_name_get()
+f_device_catalog_get()
{
- local __type="$1" __name="$2" __prop="$3" __var_to_set="$4"
- local __dev __devtype __n=0
+ local __type="$1" __name="$2" __var_to_set="$3"
+ local __dname=
- # Return failure if no $name or $prop is an unknown property
+ # Return failure if no $name
[ "$__name" ] || return $FAILURE
- case "$__prop" in type|desc|max) : good ;;
- *) return $FAILURE; esac
+
+ # Disable debugging to keep debug output light
+ local debug=
+
+ #
+ # Attempt to create an alternate-form of $__name that contains the
+ # first contiguous string of numbers replaced with `%d' for comparison
+ # against stored pattern names (see MAIN).
+ #
+ local __left="${__name%%[0-9]*}" __right="${__name#*[0-9]}"
+ if [ "$__left" != "$__name" ]; then
+ # Chop leading digits from right 'til we hit first non-digit
+ while :; do
+ case "$__right" in
+ [0-9]*) __right="${__right#[0-9]}" ;;
+ *) break
+ esac
+ done
+ __dname="${__left}%d$__right"
+ fi
[ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
- 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
+ local __dev __dev_name __dev_type
+ for __dev in $DEVICE_CATALOG; do
+ catalog_device_$__dev get name __dev_name
+ [ "$__dev_name" = "$__name" -o "$__dev_name" = "$__dname" ] ||
+ continue
+ catalog_device_$__dev get type __dev_type
+ [ "${__type:-$__dev_type}" = "$__dev_type" ] || continue
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__dev
+ else
+ echo $__dev
+ fi
return $?
done
+
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
return $FAILURE
}
-# f_device_name_set $type $name $desc [$max]
+# f_device_catalog_set $type $name $desc
#
-# 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.
+# Store a description (desc) in-association with device $type and $name.
+# Returns success unless $name is NULL or missing. Use f_device_catalog_get()
+# routine with the same $name and optionally $type to retrieve catalog device
+# structure (see CATALOG_DEVICE struct definition in GLOBALS section).
#
-f_device_name_set()
+f_device_catalog_set()
{
- local type="$1" name="$2" desc="$3" max="$4"
- local dev devtype n=0 found=
+ local type="$1" name="$2" desc="$3"
+ local struct dev dev_type 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 ))
+
+ # Disable debugging to keep debug output light
+ local debug=
+
+ f_str2varname "$name" struct
+ if [ ! "$DEVICE_CATALOG_APPEND_ONLY" ]; then
+ for dev in $DEVICE_CATALOG; do
+ [ "$dev" = "$struct" ] || continue
+ found=1 break
+ done
+ fi
+ if [ "$found" ]; then
+ f_struct_free "catalog_device_$struct"
+ else
+ DEVICE_CATALOG="$DEVICE_CATALOG $struct"
fi
- setvar _device_type$n "$type"
- setvar _device_desc$n "$desc"
- [ "${4+set}" ] && setvar _device_max$n "$max"
+ f_struct_new CATALOG_DEVICE "catalog_device_$struct" || return $FAILURE
+ catalog_device_$struct set type "$type"
+ catalog_device_$struct set name "$name"
+ catalog_device_$struct set desc "$desc"
return $SUCCESS
}
@@ -442,8 +904,8 @@ f_device_desc()
[ "$__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.
+ # Return sysctl MIB dev.NAME.UNIT.%desc if it exists, otherwise fall
+ # through to further alternate methods.
#
if f_have sysctl; then
__devname="${__name%%[0-9]*}"
@@ -463,24 +925,11 @@ f_device_desc()
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
+ # Look up device in catalog for default description
+ local __catalog_struct
+ debug= f_device_catalog_get "$__type" "$__name" __catalog_struct
+ debug= f_struct "catalog_device_$__catalog_struct" get \
+ desc "$__var_to_set" && return $SUCCESS
#
# Sensible fall-backs for specific types
@@ -489,7 +938,7 @@ f_device_desc()
$DEVICE_TYPE_CDROM) __cp="<unknown cdrom device type>" ;;
$DEVICE_TYPE_DISK) __cp="<unknown disk device type>" ;;
$DEVICE_TYPE_FLOPPY) __cp="<unknown floppy device type>" ;;
- $DEVICE_TYPE_USB) __cp="<unknown usb storage device type>" ;;
+ $DEVICE_TYPE_USB) __cp="<unknown USB storage device type>" ;;
$DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>" ;;
*)
__cp="<unknown device type>"
@@ -504,39 +953,108 @@ f_device_desc()
return $FAILURE
}
-# f_device_rescan
+# f_device_is_ethernet $device
#
-# Rescan all devices, after closing previous set - convenience function.
+# Returns true if $device is a wired Ethernet network interface. Otherwise
+# returns false. Example wired interfaces include: fxp0 em0 bge0 rl0 etc.
#
-f_device_rescan()
+f_device_is_ethernet()
{
- f_device_reset
- f_device_get_all
+ local dev="$1" type flags
+
+ # Make sure we have an actual device by that name
+ f_struct "$dev" || return $FAILURE
+
+ # Make sure that the device is a network device
+ $dev get type type
+ [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
+
+ # Make sure that the media flags indicate that it is Ethernet
+ $dev get flags flags
+ [ $(( ${flags:-0} & $IF_ETHERNET )) -eq $IF_ETHERNET ]
+}
+
+# f_device_is_wireless $device
+#
+# Returns true if $device is a Wireless network interface. Otherwise returns
+# false. Examples of wireless interfaces include: iwn0
+#
+f_device_is_wireless()
+{
+ local dev="$1" type flags
+
+ # Make sure we have an actual device by that name
+ f_struct "$dev" || return $FAILURE
+
+ # Make sure that the device is a network device
+ $dev get type type
+ [ "$type" = "$DEVICE_TYPE_NETWORK" ] || return $FAILURE
+
+ # Make sure that the media flags indicate that it is 802.11 wireless
+ $dev get flags flags
+ [ $(( ${flags:-0} & $IF_WIRELESS )) -eq $IF_WIRELESS ]
+}
+
+# f_device_is_active $device
+#
+# Returns true if $device is active. Otherwise returns false. Currently this
+# only works for network interfaces.
+#
+f_device_is_active()
+{
+ local dev="$1" type flags=0
+
+ # Make sure we have an actual device by that name
+ f_struct "$dev" || return $FAILURE
+
+ $dev get type type
+ case "$type" in
+ $DEVICE_TYPE_NETWORK)
+ # Make sure that the media flags indicate that it is active
+ $dev get flags flags
+ [ $(( ${flags:-0} & $IF_ACTIVE )) -eq $IF_ACTIVE ]
+ ;;
+ *)
+ return $FAILURE
+ esac
}
-# f_device_find $name [$type [$var_to_set]]
+# f_device_find [-1] $name [$type [$var_to_set]]
#
# Find one or more registered devices by name, type, or both. Returns a space-
# separated list of devices matching the search criterion.
#
+# If `-1' option flag is given, only the first matching device is returned.
+#
# If $var_to_set is missing or NULL, the device name(s) are printed to standard
# out for capturing in a sub-shell (which is less-recommended because of
# performance degredation; for example, when called in a loop).
#
f_device_find()
{
+ local OPTIND OPTARG flag only_one=
+ while getopts 1 flag; do
+ case "$flag" in
+ 1) only_one=1 ;;
+ esac
+ done
+ shift $(( $OPTIND - 1 ))
+
local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
- local __dev __devname __devtype __found=
- for __dev in $DEVICES; do
- device_$__dev get name __devname
- device_$__dev get type __devtype
+ local __n=1 __devname __devtype __found=
+ while [ $__n -le $NDEVICES ]; do
+ device_$__n get name __devname
+ device_$__n get type __devtype
if [ "$__name" = "$__devname" -o ! "$__name" ] &&
[ "$__type" = "$DEVICE_TYPE_ANY" -o \
"$__type" = "$__devtype" ]
then
- __found="$__found $__dev"
+ __found="$__found device_$__n"
+ [ "$only_one" ] && break
fi
+ __n=$(( $__n + 1 ))
done
+
if [ "$__var_to_set" ]; then
setvar "$__var_to_set" "${__found# }"
else
@@ -545,38 +1063,100 @@ f_device_find()
[ "$__found" ] # Return status
}
-# f_device_init $name
+# f_device_init $device
#
-# Initialize a device by evaluating its `init' function.
+# Initialize a device by evaluating its `init' function. The $device argument
+# is a DEVICE struct name.
#
f_device_init()
{
- local name="$1" init_func
- device_$name get init init_func || return $?
- ${init_func:-:} $name
+ local device="$1" init_func
+ f_struct "$device" || return $?
+ $device get init init_func
+ ${init_func:-:} "$device"
}
-# f_device_get $name $file [$probe]
+# f_device_get $device $file [$probe]
#
# Read $file by evaluating the device's `get' function. The file is commonly
# produced on standard output (but it truly depends on the function called).
+# The $device argument is a DEVICE struct name.
#
f_device_get()
{
- local name="$1" file="$2" probe="$3" get_func
- device_$name get get get_func || return $?
- ${get_func:-:} $name "$file" ${3+"$probe"}
+ local device="$1" file="$2" probe="$3" get_func
+ f_struct "$device" || return $?
+ $device get get get_func
+ ${get_func:-:} "$device" "$file" ${3+"$probe"}
}
-# f_device_shutdown $name
+# f_device_shutdown $device
#
-# Shutdown a device by evaluating its `shutdown' function.
+# Shutdown a device by evaluating its `shutdown' function. The $device argument
+# is a DEVICE struct name.
#
f_device_shutdown()
{
- local name="$1" shutdown_func
- device_$name get shutdown shutdown_func || return $?
- ${shutdown_func:-:} $name
+ local device="$1" shutdown_func
+ f_struct "$device" || return $?
+ $device get shutdown shutdown_func
+ ${shutdown_func:-:} "$device"
+}
+
+# f_devices_sort_by $property $var_to_get [$var_to_set]
+#
+# Take list of devices from $var_to_get (separated by whitespace, newline
+# included) and sort them by $property (e.g., `name'). The sorted list of
+# DEVICE struct names is returned on standard output separated by whitespace
+# (newline to be specific) unless $var_to_set is present and non-NULL.
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_device_sort_by_awk='
+# Variables that should be defined on the invocation line:
+# -v prop="property"
+function asorti(src, dest)
+{
+ for (i in src) dest[++nitems] = i
+ for (i = 1; i <= nitems; k = i++) {
+ idx = dest[i]
+ while ((k > 0) && (dest[k] > idx)) {
+ dest[k+1] = dest[k]; k--
+ }
+ dest[k+1] = idx
+ }
+ return nitems
+}
+{
+ split($0, devs, FS)
+ for (d in devs) {
+ name = ENVIRON["_struct_value_" devs[d] "_" prop]
+ devices[name] = devs[d]
+ }
+}
+END {
+ nitems = asorti(devices, devices_sorted)
+ for (i = 1; i <= nitems; i++) print devices[devices_sorted[i]]
+}
+'
+f_device_sort_by()
+{
+ local __property="${1:-name}" __var_to_get="$2" __var_to_set="$3"
+
+ f_isset "$__var_to_get" || return $FAILURE
+
+ local __dev
+ for __dev in $( f_getvar "$__var_to_get" ); do
+ export _struct_value_${__dev}_$__property
+ done
+
+ local __cp
+ setvar "${__var_to_set:-__cp}" "$(
+ f_getvar "$__var_to_get" |
+ awk -v prop="$__property" "$f_device_sort_by_awk"
+ )"
+ [ "$__var_to_set" ] || echo "$__cp"
}
# f_device_menu $title $prompt $hline $device_type [$helpfile]
@@ -591,20 +1171,20 @@ f_device_menu()
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 $DIALOG_CANCEL
+ local devs
+ f_device_find "" "$type" devs || return $DIALOG_CANCEL
- local desc menu_list=
+ local name desc menu_list=
+ f_device_sort_by name devs devs
for dev in $devs; do
- device_$dev get desc desc
+ $dev get name name
+ $dev get desc desc
+ f_shell_escape "$name" name
f_shell_escape "$desc" desc
- menu_list="$menu_list '$dev' '$desc'"
+ menu_list="$menu_list
+ '$name' '$desc'" # END-QUOTE
done
+ menu_list="${menu_list#$NL}"
local height width rows
eval f_dialog_menu_size height width rows \
@@ -623,6 +1203,7 @@ f_device_menu()
mtag=$( eval $DIALOG \
--title \"\$title\" \
--backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
${helpfile:+ \
@@ -647,9 +1228,15 @@ f_device_menu()
[ "$errexit" ] && set -e
if [ $retval -eq $DIALOG_OK ]; then
- # Clean up the output of [X]dialog(1) and return it
+ # Clean up the output of [X]dialog(1)
f_dialog_data_sanitize mtag
- echo "$mtag" >&2
+
+ # Map the user's choice back to a struct name
+ local index device
+ index=$( eval f_dialog_menutag2index \"\$mtag\" $menu_list )
+ device=$( set -- $devs; eval echo \${$index} )
+
+ echo "$device" >&2
fi
return $retval
@@ -658,133 +1245,141 @@ f_device_menu()
#
# 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"; }
+f_cdrom() { f_device_catalog_set $DEVICE_TYPE_CDROM "$1" "$2"; }
+f_disk() { f_device_catalog_set $DEVICE_TYPE_DISK "$1" "$2"; }
+f_floppy() { f_device_catalog_set $DEVICE_TYPE_FLOPPY "$1" "$2"; }
+f_usb() { f_device_catalog_set $DEVICE_TYPE_USB "$1" "$2"; }
+f_network() { f_device_catalog_set $DEVICE_TYPE_NETWORK "$1" "$2"; }
############################################################ MAIN
-# 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
+#
+# The below classifications allow us to re-group the GEOM devices from the
+# `DEV' GEOM class appropriately while providing fall-back descriptions both
+# for making the below code more maintainable and handling the rare case the
+# GEOM device lacks a description.
+#
+
+DEVICE_CATALOG_APPEND_ONLY=1 # Make initial loading faster
+
+# CDROM, Disk, Floppy, and USB devices/names
+f_cdrom "cd%d" "SCSI CDROM drive"
+f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive"
+f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type"
+f_disk "aacd%d" "Adaptec FSA RAID array"
+f_disk "ada%d" "ATA/SATA disk device"
+f_disk "amrd%d" "AMI MegaRAID drive"
+f_disk "da%d" "SCSI disk device"
+f_disk "idad%d" "Compaq RAID array"
+f_disk "ipsd%d" "IBM ServeRAID RAID array"
+f_disk "md%d" "md(4) disk device"
+f_disk "mfid%d" "LSI MegaRAID SAS array"
+f_disk "mlxd%d" "Mylex RAID disk"
+f_disk "twed%d" "3ware ATA RAID array"
+f_disk "vtbd%d" "VirtIO Block Device"
+f_floppy "fd%d" "Floppy Drive unit A"
+f_usb "da%da" "USB Mass Storage Device"
# Network interfaces/names
-f_network "ae" "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 $# )"
+f_network "ae%d" "Attansic/Atheros L2 Fast Ethernet"
+f_network "age%d" "Attansic/Atheros L1 Gigabit Ethernet"
+f_network "alc%d" "Atheros AR8131/AR8132 PCIe Ethernet"
+f_network "ale%d" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
+f_network "an%d" "Aironet 4500/4800 802.11 wireless adapter"
+f_network "ath%d" "Atheros IEEE 802.11 wireless adapter"
+f_network "aue%d" "ADMtek USB Ethernet adapter"
+f_network "axe%d" "ASIX Electronics USB Ethernet adapter"
+f_network "bce%d" "Broadcom NetXtreme II Gigabit Ethernet card"
+f_network "bfe%d" "Broadcom BCM440x PCI Ethernet card"
+f_network "bge%d" "Broadcom BCM570x PCI Gigabit Ethernet card"
+f_network "bm%d" "Apple BMAC Built-in Ethernet"
+f_network "bwn%d" "Broadcom BCM43xx IEEE 802.11 wireless adapter"
+f_network "cas%d" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
+f_network "cc3i%d" "SDL HSSI sync serial PCI card"
+f_network "cue%d" "CATC USB Ethernet adapter"
+f_network "cxgb%d" "Chelsio T3 10Gb Ethernet card"
+f_network "dc%d" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
+f_network "de%d" "DEC DE435 PCI NIC or other DC21040-AA based card"
+f_network "disc%d" "Software discard network interface"
+f_network "ed%d" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
+f_network "el%d" "3Com 3C501 Ethernet card"
+f_network "em%d" "Intel(R) PRO/1000 Ethernet card"
+f_network "en%d" "Efficient Networks ATM PCI card"
+f_network "ep%d" "3Com 3C509 Ethernet card/3C589 PCMCIA"
+f_network "et%d" "Agere ET1310 based PCI Express Gigabit Ethernet card"
+f_network "ex%d" "Intel EtherExpress Pro/10 Ethernet card"
+f_network "fe%d" "Fujitsu MB86960A/MB86965A Ethernet card"
+f_network "fpa%d" "DEC DEFPA PCI FDDI card"
+f_network "fwe%d" "FireWire Ethernet emulation"
+f_network "fwip%d" "IP over FireWire"
+f_network "fxp%d" "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
+f_network "gem%d" "Apple GMAC or Sun ERI/GEM Ethernet adapter"
+f_network "hme%d" "Sun HME (Happy Meal Ethernet) Ethernet adapter"
+f_network "ie%d" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
+f_network "igb%d" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
+f_network "ipw%d" "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
+f_network "iwi%d" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
+f_network "iwn%d" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
+f_network "ix%d" "Intel Etherexpress Ethernet card"
+f_network "ixgb%d" "Intel(R) PRO/10Gb Ethernet card"
+f_network "ixgbe%d" "Intel(R) PRO/10Gb Ethernet card"
+f_network "jme%d" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
+f_network "kue%d" "Kawasaki LSI USB Ethernet adapter"
+f_network "le%d" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
+f_network "lge%d" "Level 1 LXT1001 Gigabit Ethernet card"
+f_network "lnc%d" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
+f_network "lo%d" "Loop-back (local) network interface"
+f_network "lp%d" "Parallel Port IP (PLIP) peer connection"
+f_network "malo%d" "Marvell Libertas 88W8335 802.11 wireless adapter"
+f_network "msk%d" "Marvell/SysKonnect Yukon II Gigabit Ethernet"
+f_network "mxge%d" "Myricom Myri10GE 10Gb Ethernet card"
+f_network "nfe%d" "NVIDIA nForce MCP Ethernet"
+f_network "ng%d" "Vimage netgraph(4) bridged Ethernet device"
+f_network "nge%d" "NatSemi PCI Gigabit Ethernet card"
+f_network "nve%d" "NVIDIA nForce MCP Ethernet"
+f_network "nxge%d" "Neterion Xframe 10GbE Server/Storage adapter"
+f_network "pcn%d" "AMD Am79c79x PCI Ethernet card"
+f_network "plip%d" "Parallel Port IP (PLIP) peer connection"
+f_network "ral%d" "Ralink Technology IEEE 802.11 wireless adapter"
+f_network "ray%d" "Raytheon Raylink 802.11 wireless adapter"
+f_network "re%d" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
+f_network "rl%d" "RealTek 8129/8139 PCI Ethernet card"
+f_network "rue%d" "RealTek USB Ethernet card"
+f_network "rum%d" "Ralink Technology USB IEEE 802.11 wireless adapter"
+f_network "sf%d" "Adaptec AIC-6915 PCI Ethernet card"
+f_network "sge%d" "Silicon Integrated Systems SiS190/191 Ethernet"
+f_network "sis%d" "SiS 900/SiS 7016 PCI Ethernet card"
+f_network "sk%d" "SysKonnect PCI Gigabit Ethernet card"
+f_network "sn%d" "SMC/Megahertz Ethernet card"
+f_network "snc%d" "SONIC Ethernet card"
+f_network "sr%d" "SDL T1/E1 sync serial PCI card"
+f_network "ste%d" "Sundance ST201 PCI Ethernet card"
+f_network "stge%d" "Sundance/Tamarack TC9021 Gigabit Ethernet"
+f_network "ti%d" "Alteon Networks PCI Gigabit Ethernet card"
+f_network "tl%d" "Texas Instruments ThunderLAN PCI Ethernet card"
+f_network "tx%d" "SMC 9432TX Ethernet card"
+f_network "txp%d" "3Com 3cR990 Ethernet card"
+f_network "uath%d" "Atheros AR5005UG and AR5005UX USB wireless adapter"
+f_network "upgt%d" "Conexant/Intersil PrismGT USB wireless adapter"
+f_network "ural%d" "Ralink Technology RT2500USB 802.11 wireless adapter"
+f_network "urtw%d" "Realtek 8187L USB wireless adapter"
+f_network "vge%d" "VIA VT612x PCI Gigabit Ethernet card"
+f_network "vlan%d" "IEEE 802.1Q VLAN network interface"
+f_network "vr%d" "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
+f_network "vx%d" "3COM 3c590 / 3c595 Ethernet card"
+f_network "wb%d" "Winbond W89C840F PCI Ethernet card"
+f_network "wi%d" "Lucent WaveLAN/IEEE 802.11 wireless adapter"
+f_network "wpi%d" "Intel 3945ABG IEEE 802.11 wireless adapter"
+f_network "wx%d" "Intel Gigabit Ethernet (82452) card"
+f_network "xe%d" "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
+f_network "xl%d" "3COM 3c90x / 3c90xB PCI Ethernet card"
+f_network "zyd%d" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
+
+DEVICE_CATALOG_APPEND_ONLY= # Additional loading modifies existing devices
+
+f_count NCATALOG_DEVICES $DEVICE_CATALOG
+f_dprintf "%s: Initialized device catalog with %u names/descriptions." \
+ device.subr $NCATALOG_DEVICES
#
# Scan for the above devices unless requeted otherwise
diff --git a/usr.sbin/bsdconfig/share/dialog.subr b/usr.sbin/bsdconfig/share/dialog.subr
index ff7fc86..e0dfe80 100644
--- a/usr.sbin/bsdconfig/share/dialog.subr
+++ b/usr.sbin/bsdconfig/share/dialog.subr
@@ -1,6 +1,6 @@
if [ ! "$_DIALOG_SUBR" ]; then _DIALOG_SUBR=1
#
-# Copyright (c) 2006-2013 Devin Teske
+# Copyright (c) 2006-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -296,12 +296,25 @@ f_dialog_backtitle_restore()
#
f_dialog_max_size()
{
+ local funcname=f_dialog_max_size
local __var_height="$1" __var_width="$2" __max_size
[ "$__var_height" -o "$__var_width" ] || return $FAILURE
if [ "$USE_XDIALOG" ]; then
__max_size="$XDIALOG_MAXSIZE" # see CONFIGURATION
else
- __max_size=$( stty size 2> /dev/null ) # usually "24 80"
+ if __max_size=$( $DIALOG --print-maxsize \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ then
+ f_dprintf "$funcname: %s --print-maxsize = [%s]" \
+ "$DIALOG" "$__max_size"
+ # usually "MaxSize: 24, 80"
+ __max_size="${__max_size#*: }"
+ f_replaceall "$__max_size" "," "" __max_size
+ else
+ f_eval_catch -dk __max_size $funcname stty \
+ 'stty size' || __max_size=
+ # usually "24 80"
+ fi
: ${__max_size:=$DEFAULT_TERMINAL_SIZE}
fi
if [ "$__var_height" ]; then
@@ -415,8 +428,8 @@ f_dialog_size_constrain()
if [ "$debug" ]; then
# Print final constrained values to debugging
- f_quietly f_getvar "$__var_height"
- f_quietly f_getvar "$__var_width"
+ [ "$__var_height" ] && f_quietly f_getvar "$__var_height"
+ [ "$__var_width" ] && f_quietly f_getvar "$__var_width"
fi
return $__retval # success if no debug warnings were printed
@@ -456,16 +469,17 @@ f_dialog_menu_constrain()
# 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 __height_menu_constrain __width_menu_constrain
+ local __rows_menu_constrain
local __arg __cp __fname=f_dialog_menu_constrain
for __arg in height width rows; do
debug= f_getvar __var_$__arg __cp
[ "$__cp" ] || continue
- if ! debug= f_getvar "$__cp" __$__arg; then
+ if ! debug= f_getvar "$__cp" __${__arg}_menu_constrain; then
f_dprintf "%s: var_%s variable \`%s' not set" \
$__fname $__arg "$__cp"
__retval=$FAILURE
- elif ! eval f_isinteger \$__$__arg; then
+ elif ! eval f_isinteger \$__${__arg}_menu_constrain; then
f_dprintf "%s: var_%s variable value not a number" \
$__fname $__arg
__retval=$FAILURE
@@ -489,9 +503,11 @@ f_dialog_menu_constrain()
# Adjust height if desired
if [ "$__var_height" ]; then
- if [ $__height -lt ${__min_height:-0} ]; then
+ if [ $__height_menu_constrain -lt ${__min_height:-0} ]; then
setvar "$__var_height" $__min_height
- elif [ $__height -gt $__max_height_menu_constrain ]; then
+ elif [ $__height_menu_constrain -gt \
+ $__max_height_menu_constrain ]
+ then
setvar "$__var_height" $__max_height_menu_constrain
fi
fi
@@ -503,9 +519,11 @@ f_dialog_menu_constrain()
else
: ${__min_width:=${DIALOG_MIN_WIDTH:-24}}
fi
- if [ $__width -lt $__min_width ]; then
+ if [ $__width_menu_constrain -lt $__min_width ]; then
setvar "$__var_width" $__min_width
- elif [ $__width -gt $__max_width_menu_constrain ]; then
+ elif [ $__width_menu_constrain -gt \
+ $__max_width_menu_constrain ]
+ then
setvar "$__var_width" $__max_width_menu_constrain
fi
fi
@@ -518,24 +536,28 @@ f_dialog_menu_constrain()
: ${__min_rows:=0}
fi
- local __max_rows=$(( $__max_height_menu_constrain - 8 ))
+ local __max_rows_menu_constrain=$((
+ $__max_height_menu_constrain - 7
+ ))
# If prompt_len is zero (no prompt), bump the max-rows by 1
# Default assumption is (if no argument) that there's no prompt
- [ ${__prompt_len:-0} -gt 0 ] ||
- __max_rows=$(( $__max_rows + 1 ))
+ [ ${__prompt_len:-0} -gt 0 ] || __max_rows_menu_constrain=$((
+ $__max_rows_menu_constrain + 1
+ ))
- if [ $__rows -lt $__min_rows ]; then
+ if [ $__rows_menu_constrain -lt $__min_rows ]; then
setvar "$__var_rows" $__min_rows
- elif [ $__rows -gt $__max_rows ]; then
- setvar "$__var_rows" $__max_rows
+ elif [ $__rows_menu_constrain -gt $__max_rows_menu_constrain ]
+ then
+ setvar "$__var_rows" $__max_rows_menu_constrain
fi
fi
if [ "$debug" ]; then
- # Print final constrained values to debuggin
- f_quietly f_getvar "$__var_height"
- f_quietly f_getvar "$__var_width"
- f_quietly f_getvar "$__var_rows"
+ # Print final constrained values to debugging
+ [ "$__var_height" ] && f_quietly f_getvar "$__var_height"
+ [ "$__var_width" ] && f_quietly f_getvar "$__var_width"
+ [ "$__var_rows" ] && f_quietly f_getvar "$__var_rows"
fi
return $__retval # success if no debug warnings were printed
@@ -1087,19 +1109,20 @@ f_dialog_radiolist_size()
# 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
+ local __longest_tag=0 __longest_item=0 __rows_rlist_size=0
while [ $# -ge 3 ]; do
local __tag="$1" __item="$2"
shift 3 # tag/item/status
[ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag}
[ ${#__item} -gt $__longest_item ] && __longest_item=${#__item}
- __rows=$(( $__rows + 1 ))
+ __rows_rlist_size=$(( $__rows_rlist_size + 1 ))
done
# Adjust rows early (for up-coming height calculation)
if [ "$__var_height" -o "$__var_rows" ]; then
# Add a row for visual aid if using Xdialog(1)
- [ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 ))
+ [ "$USE_XDIALOG" ] &&
+ __rows_rlist_size=$(( $__rows_rlist_size + 1 ))
fi
# Adjust height if desired
@@ -1107,10 +1130,12 @@ f_dialog_radiolist_size()
# Add rows to height
if [ "$USE_XDIALOG" ]; then
__height_rlist_size=$((
- $__height_rlist_size + $__rows + 7 ))
+ $__height_rlist_size + $__rows_rlist_size + 7
+ ))
else
__height_rlist_size=$((
- $__height_rlist_size + $__rows + 4 ))
+ $__height_rlist_size + $__rows_rlist_size + 4
+ ))
fi
setvar "$__var_height" $__height_rlist_size
fi
@@ -1127,7 +1152,7 @@ f_dialog_radiolist_size()
fi
# Store adjusted rows if desired
- [ "$__var_rows" ] && setvar "$__var_rows" $__rows
+ [ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_size
# Constrain height, width, and rows to sensible minimum/maximum values
# Return success if no-constrain, else return status from constrain
@@ -1207,20 +1232,26 @@ f_dialog_radiolist_with_help_size()
# 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
+ local __longest_tag=0 __longest_item=0 __longest_help=0
+ local __rows_rlist_with_help_size=0
while [ $# -ge 4 ]; do
local __tag="$1" __item="$2" __status="$3" __help="$4"
shift 4 # tag/item/status/help
[ ${#__tag} -gt $__longest_tag ] && __longest_tag=${#__tag}
[ ${#__item} -gt $__longest_item ] && __longest_item=${#__item}
[ ${#__help} -gt $__longest_help ] && __longest_help=${#__help}
- __rows=$(( $__rows + 1 ))
+ __rows_rlist_with_help_size=$((
+ $__rows_rlist_with_help_size + 1
+ ))
done
# Adjust rows early (for up-coming height calculation)
if [ "$__var_height" -o "$__var_rows" ]; then
# Add a row for visual aid if using Xdialog(1)
- [ "$USE_XDIALOG" ] && __rows=$(( $__rows + 1 ))
+ [ "$USE_XDIALOG" ] &&
+ __rows_rlist_with_help_size=$((
+ $__rows_rlist_with_help_size + 1
+ ))
fi
# Adjust height if desired
@@ -1228,10 +1259,14 @@ f_dialog_radiolist_with_help_size()
# Add rows to height
if [ "$USE_XDIALOG" ]; then
__height_rlist_with_help_size=$((
- $__height_rlist_with_help_size + $__rows + 7 ))
+ $__height_rlist_with_help_size +
+ $__rows_rlist_with_help_size + 7
+ ))
else
__height_rlist_with_help_size=$((
- $__height_rlist_with_help_size + $__rows + 4 ))
+ $__height_rlist_with_help_size +
+ $__rows_rlist_with_help_size + 4
+ ))
fi
setvar "$__var_height" $__height
fi
@@ -1257,7 +1292,7 @@ f_dialog_radiolist_with_help_size()
fi
# Store adjusted rows if desired
- [ "$__var_rows" ] && setvar "$__var_rows" $__rows
+ [ "$__var_rows" ] && setvar "$__var_rows" $__rows_rlist_with_help_size
# Constrain height, width, and rows to sensible minimum/maximum values
# Return success if no-constrain, else return status from constrain
@@ -2043,7 +2078,10 @@ f_dialog_menutag2index_with_help()
#
f_dialog_init()
{
+ local funcname=f_dialog_init
+
DIALOG_SELF_INITIALIZE=
+ USE_DIALOG=1
#
# Clone terminal stdout so we can redirect to it from within sub-shells
@@ -2087,7 +2125,7 @@ f_dialog_init()
#
# Process `-X' command-line option
#
- [ "$USE_XDIALOG" ] && DIALOG=Xdialog
+ [ "$USE_XDIALOG" ] && DIALOG=Xdialog USE_DIALOG=
#
# Sanity check, or die gracefully
@@ -2130,7 +2168,7 @@ f_dialog_init()
DIALOG=dialog
f_die 1 "$msg_no_such_file_or_directory" "$pgm" "xauth"
fi
- HOSTNAME=$(hostname)
+ HOSTNAME=$( hostname )
local displaynum="${DISPLAY#*:}"
eval xauth -if \~$SUDO_USER/.Xauthority extract - \
\"\$HOSTNAME/unix:\$displaynum\" \
@@ -2144,7 +2182,8 @@ f_dialog_init()
#
if [ "$USE_XDIALOG" ]; then
local maxsize
- if ! maxsize=$( LANG= LC_ALL= $DIALOG --print-maxsize 2>&1 )
+ if ! f_eval_catch -dk maxsize $funcname "$DIALOG" \
+ 'LANG= LC_ALL= %s --print-maxsize' "$DIALOG"
then
# Xdialog(1) failed, fall back to dialog(1)
unset USE_XDIALOG
diff --git a/usr.sbin/bsdconfig/share/geom.subr b/usr.sbin/bsdconfig/share/geom.subr
new file mode 100644
index 0000000..19ed784
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/geom.subr
@@ -0,0 +1,430 @@
+if [ ! "$_GEOM_SUBR" ]; then _GEOM_SUBR=1
+#
+# Copyright (c) 2012-2014 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." geom.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+############################################################ GLOBALS
+
+NGEOM_CLASSES=0 # Set by f_geom_get_all()/f_geom_reset()
+
+#
+# GEOM classes for use with f_geom_find()
+#
+# NB: Since $GEOM_CLASS_ANY is the NULL string, make sure you quote it whenever
+# you put arguments after it.
+#
+setvar GEOM_CLASS_ANY "any"
+setvar GEOM_CLASS_DEV "DEV"
+setvar GEOM_CLASS_DISK "DISK"
+setvar GEOM_CLASS_ELI "ELI"
+setvar GEOM_CLASS_FD "FD"
+setvar GEOM_CLASS_LABEL "LABEL"
+setvar GEOM_CLASS_MD "MD"
+setvar GEOM_CLASS_NOP "NOP"
+setvar GEOM_CLASS_PART "PART"
+setvar GEOM_CLASS_RAID "RAID"
+setvar GEOM_CLASS_SWAP "SWAP"
+setvar GEOM_CLASS_VFS "VFS"
+setvar GEOM_CLASS_ZFS_VDEV "ZFS::VDEV"
+setvar GEOM_CLASS_ZFS_ZVOL "ZFS::ZVOL"
+
+#
+# GEOM structure definitions
+#
+f_struct_define GEOM_CLASS \
+ id name ngeoms
+f_struct_define GEOM_GEOM \
+ id class_ref config name nconsumers nproviders rank
+ # Also consumerN where N is 1 through nconsumers
+ # Also providerN where N is 1 through nproviders
+f_struct_define GEOM_CONSUMER \
+ id geom_ref config mode provider_ref
+f_struct_define GEOM_PROVIDER \
+ id geom_ref config mode name mediasize
+
+# The config property of GEOM_GEOM struct is defined as this
+f_struct_define GEOM_GEOM_CONFIG \
+ entries first fwheads fwsectors last modified scheme state
+
+# The config property of GEOM_PROVIDER struct is defined as this
+f_struct_define GEOM_PROVIDER_CONFIG \
+ descr file fwheads fwsectors ident length type unit
+
+#
+# Default behavior is to call f_geom_get_all() automatically when loaded.
+#
+: ${GEOM_SELF_SCAN_ALL=1}
+
+############################################################ FUNCTIONS
+
+# f_geom_get_all
+#
+# Parse sysctl(8) `kern.geom.confxml' data into a series of structs. GEOM
+# classes are at the top of the heirarchy and are stored as numbered structs
+# from 1 to $NGEOM_CLASSES (set by this function) named `geom_class_C'. GEOM
+# objects within each class are stored as numbered structs from 1 to `ngeoms'
+# (a property of the GEOM class struct) named `geom_class_C_geom_N' (where C
+# is the class number and N is the geom number).
+#
+# Use the function f_geom_find() to get a list of geoms (execute without
+# arguments) or find specific geoms by class or name.
+#
+f_geom_get_all()
+{
+ eval "$( sysctl -n kern.geom.confxml | awk '
+ BEGIN {
+ struct_count["class"] = 0
+ struct_count["geom"] = 0
+ struct_count["consumer"] = 0
+ struct_count["provider"] = 0
+ }
+ ############################################### FUNCTIONS
+ function set_value(prop, value)
+ {
+ if (!struct_stack[cur_struct]) return
+ printf "%s set %s \"%s\"\n",
+ struct_stack[cur_struct], prop, value
+ }
+ function create(type, id)
+ {
+ if (struct = created[type "_" id])
+ print "f_struct_free", struct
+ else {
+ struct = struct_stack[cur_struct]
+ struct = struct ( struct ? "" : "geom" )
+ struct = struct "_" type "_" ++struct_count[type]
+ created[type "_" id] = struct
+ }
+ print "debug= f_struct_new GEOM_" toupper(type), struct
+ cur_struct++
+ struct_stack[cur_struct] = struct
+ type_stack[cur_struct] = type
+ set_value("id", id)
+ }
+ function create_config()
+ {
+ struct = struct_stack[cur_struct]
+ struct = struct ( struct ? "" : "geom" )
+ struct = struct "_config"
+ set_value("config", struct)
+ type = type_stack[cur_struct]
+ print "debug= f_struct_new GEOM_" toupper(type) "_CONFIG", \
+ struct
+ cur_struct++
+ struct_stack[cur_struct] = struct
+ type_stack[cur_struct] = type "_config"
+ }
+ function extract_attr(field, attr)
+ {
+ if (match(field, attr "=\"0x[[:xdigit:]]+\"")) {
+ len = length(attr)
+ return substr($2, len + 3, RLENGTH - len - 3)
+ }
+ }
+ function extract_data(type)
+ {
+ data = $0
+ sub("^[[:space:]]*<" type ">", "", data)
+ sub("</" type ">.*$", "", data)
+ return data
+ }
+ ############################################### OPENING PATTERNS
+ $1 == "<mesh>" { mesh = 1 }
+ $1 ~ /^<(class|geom)$/ && mesh {
+ prop = substr($1, 2)
+ if ((ref = extract_attr($2, "ref")) != "")
+ set_value(prop "_ref", ref)
+ else if ((id = extract_attr($2, "id")) != "")
+ create(prop, id)
+ }
+ $1 ~ /^<(consumer|provider)$/ && mesh {
+ prop = substr($1, 2)
+ if ((ref = extract_attr($2, "ref")) != "")
+ set_value(prop "_ref", ref)
+ else if ((id = extract_attr($2, "id")) != "") {
+ create(prop, id)
+ cur_struct--
+ propn = struct_count[prop]
+ set_value(prop propn, struct_stack[cur_struct+1])
+ cur_struct++
+ }
+ }
+ $1 == "<config>" && mesh { create_config() }
+ ############################################### PROPERTIES
+ $1 ~ /^<[[:alnum:]]+>/ {
+ prop = $1
+ sub(/^</, "", prop); sub(/>.*/, "", prop)
+ set_value(prop, extract_data(prop))
+ }
+ ############################################### CLOSING PATTERNS
+ $1 ~ "^</(consumer|provider|config)>$" { cur_struct-- }
+ $1 == "</geom>" {
+ set_value("nconsumers", struct_count["consumer"])
+ set_value("nproviders", struct_count["provider"])
+ cur_struct--
+ struct_count["consumer"] = 0
+ struct_count["provider"] = 0
+ }
+ $1 == "</class>" {
+ set_value("ngeoms", struct_count["geom"])
+ cur_struct--
+ struct_count["consumer"] = 0
+ struct_count["provider"] = 0
+ struct_count["geom"] = 0
+ }
+ $1 == "</mesh>" {
+ printf "NGEOM_CLASSES=%u\n", struct_count["class"]
+ delete struct_count
+ mesh = 0
+ }' )"
+}
+
+# f_geom_reset
+#
+# Reset the registered GEOM chain.
+#
+f_geom_reset()
+{
+ local classn=1 class ngeoms geomn geom
+ while [ $classn -le ${NGEOM_CLASSES:-0} ]; do
+ class=geom_class_$classn
+ $class get ngeoms ngeoms
+ geomn=1
+ while [ $geomn -le $ngeoms ]; do
+ f_struct_free ${class}_geom_$geomn
+ geomn=$(( $geomn + 1 ))
+ done
+ classn=$(( $classn + 1 ))
+ done
+ NGEOM_CLASSES=0
+}
+
+# f_geom_rescan
+#
+# Rescan all GEOMs - convenience function.
+#
+f_geom_rescan()
+{
+ f_geom_reset
+ f_geom_get_all
+}
+
+# f_geom_find $name [$type [$var_to_set]]
+#
+# Find one or more registered GEOMs by name, type, or both. Returns a space-
+# separated list of GEOMs matching the search criterion. The $type argument
+# should be the GEOM class (see $GEOM_CLASS_* variables in GLOBALS above).
+#
+# If $var_to_set is missing or NULL, the GEOM name(s) are printed to standard
+# out for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example, when called in a loop).
+#
+f_geom_find()
+{
+ local __name="$1" __type="${2:-$GEOM_CLASS_ANY}" __var_to_set="$3"
+ local __classn=1 __class __class_name __ngeoms
+ local __geomn __geom __geom_name __found=
+ while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
+ __class=geom_class_$__classn
+ $__class get name __class_name
+ if [ "$__type" != "$GEOM_CLASS_ANY" -a \
+ "$__type" != "$__class_name" ]
+ then
+ __classn=$(( $__classn + 1 ))
+ continue
+ fi
+
+ __geomn=1
+ $__class get ngeoms __ngeoms || __ngeoms=0
+ while [ $__geomn -le $__ngeoms ]; do
+ __geom=${__class}_geom_$__geomn
+ $__geom get name __geom_name
+ [ "$__name" = "$__geom_name" -o ! "$__name" ] &&
+ __found="$__found $__geom"
+ __geomn=$(( $__geomn + 1 ))
+ done
+ __classn=$(( $__classn + 1 ))
+ done
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "${__found# }"
+ else
+ echo $__found
+ fi
+ [ "$__found" ] # Return status
+}
+
+# f_geom_find_by $prop $find [$type [$var_to_set]]
+#
+# Find GEOM-related struct where $prop of the struct is equal to $find. Returns
+# NULL or the name of the first GEOM struct to match. The $type argument should
+# be one of the following:
+#
+# NULL Find any of the below
+# class Find GEOM_CLASS struct
+# geom Find GEOM_GEOM struct
+# consumer Find GEOM_CONSUMER struct
+# provider Find GEOM_PROVIDER struct
+#
+# The $prop argument can be any property of the given type of struct. Some
+# properties are common to all types (such as id) so the $type argument is
+# optional (allowing you to return any struct whose property matches $find).
+#
+# If $var_to_set is missing or NULL, the GEOM struct name is printed to
+# standard out for capturing in a sub-shell (which is less-recommended because
+# of performance degredation; for example when called in a loop).
+#
+f_geom_find_by()
+{
+ local __prop="$1" __find="$2" __type="$3" __var_to_set="$4"
+ local __classn=1 __class __ngeoms
+ local __geomn __geom __nitems
+ local __itype __itemn __item
+ local __value __found=
+
+ if [ ! "$__prop" ]; then
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return $FAILURE
+ fi
+
+ case "$__type" in
+ "") : OK ;;
+ class|GEOM_CLASS) __type=class ;;
+ geom|GEOM_GEOM) __type=geom ;;
+ consumer|GEOM_CONSUMER) __type=consumer ;;
+ provider|GEOM_PROVIDER) __type=provider ;;
+ *)
+ [ "$__var_to_set" ] && setvar "$__var_to_set" ""
+ return $FAILURE
+ esac
+
+ while [ $__classn -le ${NGEOM_CLASSES:-0} ]; do
+ __class=geom_class_$__classn
+
+ if [ "${__type:-class}" = "class" ]; then
+ $__class get "$__prop" __value || __value=
+ [ "$__value" = "$__find" ] && __found="$__class" break
+ [ "$__type" ] && __classn=$(( $__classn + 1 )) continue
+ fi
+
+ __geomn=1
+ $__class get ngeoms __ngeoms || __ngeoms=0
+ while [ $__geomn -le $__ngeoms ]; do
+ __geom=${__class}_geom_$__geomn
+
+ if [ "${__type:-geom}" = "geom" ]; then
+ $__geom get "$__prop" __value || __value=
+ [ "$__value" = "$__find" ] &&
+ __found="$__geom" break
+ [ "$__type" ] &&
+ __geomn=$(( $__geomn + 1 )) continue
+ fi
+
+ for __itype in ${__type:-consumer provider}; do
+ $__geom get n${__itype}s __nitems || continue
+ __itemn=1
+ while [ $__itemn -le $__nitems ]; do
+ __item=${__geom}_${__itype}_$__itemn
+
+ $__item get "$__prop" __value ||
+ __value=
+ [ "$__value" = "$__find" ] &&
+ __found="$__item" break
+ __itemn=$(( $__itemn + 1 ))
+ done
+ [ "$__found" ] && break
+ done
+ [ "$__found" ] && break
+ __geomn=$(( $__geomn + 1 ))
+ done
+ [ "$__found" ] && break
+ __classn=$(( $__classn + 1 ))
+ done
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__found"
+ else
+ [ "$__found" ] && echo "$__found"
+ fi
+ [ "$__found" ] # Return status
+}
+
+# f_geom_parent $geom|$consumer|$provider|$config [$var_to_set]
+#
+# Get the GEOM class associated with one of $geom, $consumer, $provider or
+# $config.
+#
+# If $var_to_set is missing or NULL, the GEOM class name is printed to standard
+# out for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example when called in a loop).
+#
+f_geom_parent()
+{
+ local __struct="$1" __var_to_set="$2"
+ # NB: Order of pattern matches below is important
+ case "$__struct" in
+ *_config*) __struct="${__struct%_config*}" ;;
+ *_consumer_*) __struct="${__struct%_consumer_[0-9]*}" ;;
+ *_provider_*) __struct="${__struct%_provider_[0-9]*}" ;;
+ *_geom_*) __struct="${__struct%_geom_[0-9]*}" ;;
+ *) __struct=
+ esac
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__struct"
+ else
+ echo "$__struct"
+ fi
+ f_struct "$__struct" # Return status
+}
+
+############################################################ MAIN
+
+#
+# Parse GEOM configuration unless requeted otherwise
+#
+f_dprintf "%s: GEOM_SELF_SCAN_ALL=[%s]" geom.subr "$GEOM_SELF_SCAN_ALL"
+case "$GEOM_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*)
+ f_geom_get_all
+ if [ "$debug" ]; then
+ debug= f_geom_find "" "$GEOM_CLASS_ANY" geoms
+ f_count ngeoms $geoms
+ f_dprintf "%s: Initialized %u geom devices in %u classes." \
+ geom.subr "$ngeoms" "$NGEOM_CLASSES"
+ unset geoms ngeoms
+ fi
+esac
+
+f_dprintf "%s: Successfully loaded." geom.subr
+
+fi # ! $_GEOM_SUBR
diff --git a/usr.sbin/bsdconfig/share/keymap.subr b/usr.sbin/bsdconfig/share/keymap.subr
new file mode 100644
index 0000000..d4f391c
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/keymap.subr
@@ -0,0 +1,263 @@
+if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_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..." keymap.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+############################################################ CONFIGURATION
+
+#
+# Defaults taken from usr.sbin/kbdmap/kbdmap.h
+#
+: ${DEFAULT_LANG:=en}
+: ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps}
+
+############################################################ GLOBALS
+
+KEYMAPS=
+NKEYMAPS=0
+
+# A "keymap" from kbdmap's point of view
+f_struct_define KEYMAP \
+ desc \
+ keym \
+ mark
+
+#
+# Default behavior is to call f_keymap_get_all() automatically when loaded.
+#
+: ${KEYMAP_SELF_SCAN_ALL=1}
+
+############################################################ FUNCTIONS
+
+# f_keymap_register $name $desc $keym $mark
+#
+# Register a keymap. A `structure' (see struct.subr) is created with the name
+# keymap_$name (so make sure $name contains only alpha-numeric characters or
+# the underscore, `_'). The remaining arguments after $name correspond to the
+# propertise of the `KEYMAP' structure-type (defined above).
+#
+# If not already registered, the keymap is then appended to the KEYMAPS
+# environment variable, a space-separated list of all registered keymaps.
+#
+f_keymap_register()
+{
+ local name="$1" desc="$2" keym="$3" mark="$4"
+
+ f_struct_new KEYMAP "keymap_$name" || return $FAILURE
+ keymap_$name set desc "$desc"
+ keymap_$name set keym "$keym"
+ keymap_$name set mark "$mark"
+
+ # Scan our global register to see if needs ammending
+ local k found=
+ for k in $KEYMAPS; do
+ [ "$k" = "$name" ] || continue
+ found=1 && break
+ done
+ [ "$found" ] || KEYMAPS="$KEYMAPS $name"
+
+ return $SUCCESS
+}
+
+# f_keymap_checkfile $keymap
+#
+# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap
+# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure.
+# If debugging is enabled, an appropriate debug error message is printed if
+# $keymap is not available.
+#
+f_keymap_checkfile()
+{
+ local keym="$1"
+
+ # Fixup keymap if it doesn't already contain at least one `/'
+ [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
+
+ # Short-cuts
+ [ -f "$keym" -a -r "$keym" ] && return $SUCCESS
+ f_debugging || return $FAILURE
+
+ # Print an appropriate debug error message
+ if [ ! -e "$keym" ]; then
+ f_dprintf "%s: No such file or directory" "$keym"
+ elif [ ! -f "$keym" ]; then
+ f_dprintf "%s: Not a file!" "$keym"
+ elif [ ! -r "$keym" ]; then
+ f_dprintf "%s: Permission denied" "$keym"
+ fi
+
+ return $FAILURE
+}
+
+# f_keymap_get_all
+#
+# Get all keymap information for kbdmap(5) entries both in the database and
+# loosely existing in $DEFAULT_KEYMAP_DIR.
+#
+f_keymap_get_all()
+{
+ local fname=f_keymap_get_all
+ local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
+ [ "$lang" = "C" ] && lang="$DEFAULT_LANG"
+
+ f_dprintf "%s: Looking for keymap files..." $fname
+ f_dialog_info "$msg_looking_for_keymap_files"
+ f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG"
+
+ eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
+ BEGIN {
+ # en_US.ISO8859-1 -> en_..\.ISO8859-1
+ dialect = lang
+ if (length(dialect) >= 6 &&
+ substr(dialect, 3, 1) == "_")
+ dialect = substr(dialect, 1, 3) ".." \
+ substr(dialect, 6)
+ printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
+
+ # en_US.ISO8859-1 -> en
+ lang_abk = lang
+ if (length(lang_abk) >= 3 &&
+ substr(lang_abk, 3, 1) == "_")
+ lang_abk = substr(lang_abk, 1, 2)
+ printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n",
+ lang_abk
+ }
+ function find_token(buffer, token)
+ {
+ if (split(buffer, tokens, /,/) == 0) return 0
+ found = 0
+ for (t in tokens)
+ if (token == tokens[t]) { found = 1; break }
+ return found
+ }
+ function add_keymap(desc,mark,keym)
+ {
+ marks[keym] = mark
+ name = keym
+ gsub(/[^[:alnum:]_]/, "_", name)
+ gsub(/'\''/, "'\''\\'\'\''", desc);
+ printf "f_keymap_checkfile %s && " \
+ "f_keymap_register %s '\'%s\'' %s %u\n",
+ keym, name, desc, keym, mark
+ }
+ !/^[[:space:]]*(#|$)/ {
+ sub(/^[[:space:]]*/, "", $0)
+ keym = $1
+ if (keym ~ /^(MENU|FONT)$/) next
+ lg = ($2 == "" ? lang_default : $2)
+
+ # Match the entry and store the type of match we made
+ # as the mark value (so that if we make a better match
+ # later on with a higher mark, it overwrites previous)
+
+ mark = marks[keym];
+ if (find_token(lg, lang))
+ add_keymap($3, 4, keym) # Best match
+ else if (mark <= 3 && find_token(lg, dialect))
+ add_keymap($3, 3, keym)
+ else if (mark <= 2 && find_token(lg, lang_abk))
+ add_keymap($3, 2, keym)
+ else if (mark <= 1 && find_token(lg, lang_default))
+ add_keymap($3, 1, keym)
+ else if (mark <= 0)
+ add_keymap($3, 0, keym)
+ }
+ ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
+
+
+ #
+ # Look for keymaps not in database
+ #
+ local direntry keym name
+ set +f # glob
+ for direntry in "$DEFAULT_KEYMAP_DIR"/*; do
+ [ "${direntry##*.}" = ".kbd" ] || continue
+ keym="${direntry##*/}"
+ f_str2varname "$keym" name
+ f_struct keymap_$name && continue
+ f_keymap_checkfile "$keym" &&
+ f_keymap_register $name "${keym%.*}" "$keym" 0
+ f_dprintf "%s: not in kbdmap(5) database" "$keym"
+ done
+
+ #
+ # Sort the items by their descriptions
+ #
+ f_dprintf "%s: Sorting keymap entries by description..." $fname
+ KEYMAPS=$(
+ for k in $KEYMAPS; do
+ echo -n "$k "
+ # NOTE: Translate '8x8' to '8x08' before sending to
+ # sort(1) so that things work out as we might expect.
+ debug= keymap_$k get desc | sed -e 's/8x8/8x08/g'
+ done | sort -k2 | awk '{
+ printf "%s%s", (started ? " " : ""), $1; started = 1
+ }'
+ )
+
+ return $SUCCESS
+}
+
+# f_keymap_kbdcontrol $keymap
+#
+# Install keyboard map file from $keymap.
+#
+f_keymap_kbdcontrol()
+{
+ local keymap="$1"
+
+ [ "$keymap" ] || return $SUCCESS
+
+ # Fixup keymap if it doesn't already contain at least one `/'
+ [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
+
+ [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
+}
+
+############################################################ MAIN
+
+#
+# Scan for keymaps unless requeted otherwise
+#
+f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
+case "$KEYMAP_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_keymap_get_all
+esac
+
+f_count NKEYMAPS $KEYMAPS
+f_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS
+
+f_dprintf "%s: Successfully loaded." keymap.subr
+
+fi # ! $_KEYMAP_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/cdrom.subr b/usr.sbin/bsdconfig/share/media/cdrom.subr
index c59f88a..bbbd638 100644
--- a/usr.sbin/bsdconfig/share/media/cdrom.subr
+++ b/usr.sbin/bsdconfig/share/media/cdrom.subr
@@ -58,31 +58,25 @@ f_media_set_cdrom()
local devs ndevs
f_device_find "" $DEVICE_TYPE_CDROM devs
- ndevs=$( set -- $devs; echo $# )
+ f_count ndevs $devs
if [ ${ndevs:=0} -eq 0 ]; then
f_interactive && f_show_msg "$msg_no_cd_dvd_devices_found"
return $FAILURE
- elif [ $ndevs -gt 1 ]; then
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
local title="$msg_choose_a_cd_dvd_type"
local prompt="$msg_please_select_a_cd_dvd_drive"
- local hline=""
+ 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]*}"
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
- f_struct_copy device_$dev device_media
- [ $retval -eq $SUCCESS ] || return $FAILURE
- else
- f_struct_copy device_$devs device_media
+ f_struct_copy "$dev" device_media
fi
f_struct device_media || return $FAILURE
@@ -95,9 +89,10 @@ f_media_set_cdrom()
#
f_media_init_cdrom()
{
+ local funcname=f_media_init_cdrom
local dev="$1" devname err
- device_$dev get devname devname || return $FAILURE
+ f_struct "$dev" get devname devname || return $FAILURE
f_dprintf "Init routine called for CDROM device. devname=[%s]" \
"$devname"
@@ -106,14 +101,13 @@ f_media_init_cdrom()
return $SUCCESS
fi
- if [ ! -e "$MOUNTPOINT" ] &&
- ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
- then
- f_dialog_msgbox "$err"
- return $FAILURE
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
fi
- if ! err=$( mount_cd9660 "$devname" "$MOUNTPOINT" 2>&1 )
+ if ! f_eval_catch -dk err $funcname mount_cd9660 \
+ 'mount_cd9660 "%s" "%s"' "$devname" "$MOUNTPOINT"
then
err="${err#mount_cd9660: }"; err="${err#$devname: }"
case "$err" in
@@ -154,20 +148,22 @@ f_media_init_cdrom()
f_media_get_cdrom()
{
local dev="$1" file="$2" probe_type="$3"
+ local name
+ $dev get name name
f_dprintf "f_media_get_cdrom: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
}
# 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.
+# Shuts down the CDROM device. Return status should be ignored.
#
f_media_shutdown_cdrom()
{
+ local funcname=f_media_shutdown_cdrom
local dev="$1" err
[ "$CDROM_MOUNTED" ] || return $FAILURE
@@ -177,15 +173,15 @@ f_media_shutdown_cdrom()
return $SUCCESS
fi
- if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
err="${err#umount: }"; err="${err#*: }"
f_show_msg "$msg_could_not_unmount_the_cdrom_dvd" \
"$MOUNTPOINT" "$err"
else
CDROM_MOUNTED=
fi
-
- f_media_eject_cdrom "$dev"
}
# f_media_eject_cdrom $device
@@ -194,11 +190,20 @@ f_media_shutdown_cdrom()
#
f_media_eject_cdrom()
{
- local dev="$1" devname err
- device_$dev get name devname || return $SUCCESS
- case "$devname" in /dev/iso9660/*) return $SUCCESS; esac
+ local funcname=f_media_eject_cdrom
+ local dev="$1" name devname err
+
+ f_struct "$dev" || return $SUCCESS
+ $dev get name name || return $SUCCESS
+ $dev get devname devname || return $SUCCESS
+
+ # Don't eject labels
+ case "$name" in */*) return $SUCCESS; esac
+
f_dprintf "Ejecting CDROM/DVD at %s" "$devname"
- if ! err=$( cdcontrol -f "$devname" eject 2>&1 ); then
+ if ! f_eval_catch -dk err $funcname cdcontrol \
+ 'cdcontrol -f "%s" eject' "$devname"
+ then
f_dprintf "Could not eject the CDROM/DVD from %s: %s" \
"$devname" "${err#cdcontrol: }"
fi
diff --git a/usr.sbin/bsdconfig/share/media/common.subr b/usr.sbin/bsdconfig/share/media/common.subr
index 01d50a1..7a6ddaa 100644
--- a/usr.sbin/bsdconfig/share/media/common.subr
+++ b/usr.sbin/bsdconfig/share/media/common.subr
@@ -61,7 +61,7 @@ f_media_open()
{ # Verify and initialize device media if-defined
f_struct device_media &&
f_media_verify &&
- f_device_init media
+ f_device_init device_media
} || return $FAILURE
}
@@ -74,7 +74,7 @@ f_media_close()
{
f_dprintf "f_media_close: Shutting down media device"
f_struct device_media &&
- f_device_shutdown media
+ f_device_shutdown device_media
f_struct_free device_media
}
@@ -99,6 +99,7 @@ f_media_verify()
#
f_media_generic_get()
{
+ local funcname=f_media_generic_get
local base="$1" file="$2" probe_type="$3"
local fname=f_media_generic_get
@@ -117,13 +118,10 @@ f_media_generic_get()
f_dprintf "%s: file exists path=[%s]" $fname "$path"
if [ "$probe_type" = "$PROBE_SIZE" ]; then
local size
- if ! size=$( stat -f %z "$path" 2>&1 ); then
- f_dprintf "stat: %s" "$size"
- echo "-1"
- else
- f_isinteger "$size" || size=-1
- echo $size
- fi
+ f_eval_catch -dk size $funcname stat \
+ 'stat -f %%z "%s"' "$path" || size=-1
+ f_isinteger "$size" || size=-1
+ echo $size
fi
[ "$probe_type" ] && return $SUCCESS
cat "$path"
@@ -136,13 +134,10 @@ f_media_generic_get()
f_dprintf "%s: file exists path=[%s]" $fname "$path"
if [ "$probe_type" = "$PROBE_SIZE" ]; then
local size
- if ! size=$( stat -f %z "$path" 2>&1 ); then
- f_dprintf "stat: %s" "$size"
- echo "-1"
- else
- f_isinteger "$size" || size=-1
- echo $size
- fi
+ f_eval_catch -dk size $funcname stat \
+ 'stat -f %%z "%s"' "$path" || size=-1
+ f_isinteger "$size" || size=-1
+ echo $size
fi
[ "$probe_type" ] && return $SUCCESS
elif [ "$probe_type" ]; then
diff --git a/usr.sbin/bsdconfig/share/media/directory.subr b/usr.sbin/bsdconfig/share/media/directory.subr
index 3f46293..004cb74 100644
--- a/usr.sbin/bsdconfig/share/media/directory.subr
+++ b/usr.sbin/bsdconfig/share/media/directory.subr
@@ -90,7 +90,7 @@ f_media_init_directory()
{
local dev="$1" path
- device_$dev get private path || return $FAILURE
+ $dev get private path || return $FAILURE
f_dprintf "Init routine called for Directory device. path=[%s]" \
"$path"
@@ -125,11 +125,13 @@ f_media_init_directory()
f_media_get_directory()
{
local dev="$1" file="$2" probe_type="$3" path
+ local name
+ $dev get name name
f_dprintf "f_media_get_directory: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
- device_$dev get private path
+ $dev get private path
f_media_generic_get "$path" "$file" "$probe_type"
}
diff --git a/usr.sbin/bsdconfig/share/media/dos.subr b/usr.sbin/bsdconfig/share/media/dos.subr
index be4cfc7..df91aeb 100644
--- a/usr.sbin/bsdconfig/share/media/dos.subr
+++ b/usr.sbin/bsdconfig/share/media/dos.subr
@@ -56,31 +56,25 @@ f_media_set_dos()
local devs ndevs
f_device_find "" $DEVICE_TYPE_DOS devs
- ndevs=$( set -- $devs; echo $# )
+ f_count ndevs $devs
if [ ${ndevs:=0} -eq 0 ]; then
f_show_msg "$msg_no_dos_primary_partitions_found"
return $FAILURE
- elif [ $ndevs -gt 1 ]; then
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
local title="$msg_choose_a_dos_partition"
local prompt="$msg_please_select_dos_partition"
- local hline=""
+ 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]*}"
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
- f_struct_copy device_$dev device_media
- [ $retval -eq $SUCCESS ] || return $FAILURE
- else
- f_struct_copy device_$devs device_media
+ f_struct_copy "$dev" device_media
fi
f_struct device_media || return $FAILURE
@@ -93,9 +87,10 @@ f_media_set_dos()
#
f_media_init_dos()
{
+ local funcname=f_media_init_dos
local dev="$1" devname err
- device_$dev get devname devname || return $FAILURE
+ $dev get devname devname || return $FAILURE
f_dprintf "Init routine called for DOS device. devname=[%s]" \
"$devname"
@@ -104,14 +99,13 @@ f_media_init_dos()
return $SUCCESS
fi
- if [ ! -e "$MOUNTPOINT" ] &&
- ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
- then
- f_dialog_msgbox "$err"
- return $FAILURE
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
fi
- if ! err=$( mount_msdosfs "$devname" "$MOUNTPOINT" 2>&1 )
+ if ! f_eval_catch -dk err $funcname mount_msdosfs \
+ 'mount_msdosfs "%s" "%s"' "$devname" "$MOUNTPOINT"
then
err="${err#mount_msdosfs: }"; err="${err#$devname: }"
f_show_msg "$msg_error_mounting_device" \
@@ -132,9 +126,11 @@ f_media_init_dos()
f_media_get_dos()
{
local dev="$1" file="$2" probe_type="$3"
+ local name
+ $dev get name name
f_dprintf "f_media_get_dos: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
}
@@ -146,11 +142,14 @@ f_media_get_dos()
#
f_media_shutdown_dos()
{
+ local funcname=f_media_shutdown_dos
local dev="$1" err
[ "$DOS_MOUNTED" ] || return $FAILURE
- if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
err="${err#umount: }"; err="${err#*: }"
f_show_msg "$msg_could_not_unmount_the_dos_partition" \
"$MOUNTPOINT" "$err"
diff --git a/usr.sbin/bsdconfig/share/media/floppy.subr b/usr.sbin/bsdconfig/share/media/floppy.subr
index 62fe64b..bf402e5 100644
--- a/usr.sbin/bsdconfig/share/media/floppy.subr
+++ b/usr.sbin/bsdconfig/share/media/floppy.subr
@@ -57,31 +57,25 @@ f_media_set_floppy()
local devs ndevs
f_device_find "" $DEVICE_TYPE_FLOPPY devs
- ndevs=$( set -- $devs; echo $# )
+ f_count ndevs $devs
if [ ${ndevs:=0} -eq 0 ]; then
f_interactive && f_show_msg "$msg_no_floppy_devices_found"
return $FAILURE
- elif [ $ndevs -gt 1 ]; then
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
local title="$msg_choose_a_floppy_drive"
local prompt="$msg_please_select_a_floppy_drive"
- local hline=""
+ 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]*}"
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
- f_struct_copy device_$dev device_media
- [ $retval -eq $SUCCESS ] || return $FAILURE
- else
- f_struct_copy device_$devs device_media
+ f_struct_copy "$dev" device_media
fi
f_struct device_media &&
@@ -98,9 +92,10 @@ f_media_set_floppy()
#
f_media_init_floppy()
{
+ local funcname=f_media_init_floppy
local dev="$1" devname err
- device_$dev get devname devname || return $FAILURE
+ $dev get devname devname || return $FAILURE
f_dprintf "Init floppy called for %s distribution. devname=[%s]" \
"${FLOPPY_DISTWANTED:-some}" "$devname"
@@ -110,7 +105,7 @@ f_media_init_floppy()
fi
local mp
- device_$dev get private mp
+ $dev get private mp
if [ ! -e "${mp:=$MOUNTPOINT}" ] && ! f_quietly mkdir -p "$mp"; then
f_show_msg "$msg_unable_to_make_directory_mountpoint" \
"$mp" "$devname"
@@ -119,7 +114,7 @@ f_media_init_floppy()
if f_interactive; then
local desc
- device_$dev get desc desc
+ $dev get desc desc
if [ "$FLOPPY_DISTWANTED" ]; then
f_show_msg "$msg_please_insert_floppy_in_drive" "$desc"
else
@@ -129,12 +124,15 @@ f_media_init_floppy()
fi
if ! {
- f_quietly mount_msdosfs -o ro -m 0777 -u 0 -g 0 "$devname" "$mp" ||
- err=$( mount -o ro "$devname" "$mp" 2>&1 )
+ f_eval_catch -dk err $funcname mount_msdosfs \
+ 'mount_msdosfs -o ro -m 0777 -u 0 -g 0 "%s" "%s"' \
+ "$devname" "$mp" ||
+ f_eval_catch -dk err $funcname mount \
+ 'mount -o ro "%s" "%s"' "$devname" "$mp"
}; then
err="${err#mount: }"; err="${err#*: }"
local name
- device_$dev get name name
+ $dev get name name
f_show_msg "$msg_error_mounting_floppy_device" \
"$name" "$devname" "$mp" "$err"
return $FAILURE
@@ -153,10 +151,13 @@ f_media_init_floppy()
#
f_media_get_floppy()
{
+ local funcname=f_media_get_floppy
local dev="$1" file="$2" probe_type="$3"
+ local name
+ $dev get name name
f_dprintf "f_media_get_floppy: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
#
# floppies don't use f_media_generic_get() because it's too expensive
@@ -164,7 +165,7 @@ f_media_get_floppy()
# right or give up with floppies.
#
local mp
- device_$dev get private mp
+ $dev get private mp
local fp="${mp:=$MOUNTPOINT}/$file"
if ! [ -f "$fp" -a -r "$fp" ]; then
local nretries=4
@@ -188,7 +189,7 @@ f_media_get_floppy()
#
if [ "$probe_type" = "$PROBE_SIZE" ]; then
local size
- size=$( stat -f %z "$fp" 2>&1 ) || f_dprintf "stat: %s" "$size"
+ f_eval_catch -dk size $funcname stat 'stat -f %%z "%s"' "$fp"
f_isinteger "$size" || size=-1
echo "$size"
fi
@@ -203,19 +204,19 @@ f_media_get_floppy()
#
f_media_shutdown_floppy()
{
+ local funcname=f_media_shutdown_floppy
local dev="$1" err mp
[ "$FLOPPY_MOUNTED" ] || return $FAILURE
- 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
+ $dev get private mp
+ if f_eval_catch -d $funcname umount \
+ 'umount -f "%s"' "${mp:=$MOUNTPOINT}"
+ then
FLOPPY_MOUNTED=
if f_interactive && [ "$_systemState" != "fixit" ]; then
local desc
- device_$dev get desc desc
+ $dev get desc desc
f_show_msg "$msg_you_may_remove_the_floppy" "$desc"
fi
fi
diff --git a/usr.sbin/bsdconfig/share/media/ftp.subr b/usr.sbin/bsdconfig/share/media/ftp.subr
index d7f33bb..a249a01 100644
--- a/usr.sbin/bsdconfig/share/media/ftp.subr
+++ b/usr.sbin/bsdconfig/share/media/ftp.subr
@@ -328,16 +328,17 @@ f_media_set_ftp()
! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
then
f_struct device_network &&
- f_device_shutdown network
+ f_device_shutdown device_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
+ local dev if
+ f_getvar $VAR_NETWORK_DEVICE if
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_struct_copy "$dev" device_network
fi
- if ! f_device_init network; then
+ if ! f_device_init device_network; then
f_dprintf "f_media_set_ftp: %s" "$msg_net_device_init_failed"
unset $VAR_FTP_PATH
return $FAILURE
@@ -420,7 +421,7 @@ f_media_set_ftp()
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_device_shutdown device_network
f_struct_free device_network
unset $VAR_FTP_PATH
return $FAILURE
@@ -436,7 +437,7 @@ f_media_set_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
+ device_ftp set private device_network
f_struct_copy device_ftp device_media
f_struct_free device_ftp
@@ -503,8 +504,9 @@ f_media_set_ftp_userpass()
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_struct "$dev" || return $FAILURE
+ $dev get private netDev || return $SUCCESS # No net == happy net
+debug=1 f_dprintf "netDev=[$netDev]"
f_device_init $netDev
}
@@ -515,8 +517,8 @@ f_device_network_up()
f_device_network_down()
{
local dev="$1" netDev
- f_struct device_$dev || return $FAILURE
- device_$dev get private netDev || return $SUCCESS
+ f_struct "$dev" || return $FAILURE
+ $dev get private netDev || return $SUCCESS
f_device_shutdown $netDev
}
@@ -576,9 +578,9 @@ f_device_network_down()
f_media_init_ftp()
{
local dev="$1"
-
local url
- device_$dev get name url
+
+ $dev get name url
f_dprintf "Init routine called for FTP device. url=[%s]" "$url"
if [ "$FTP_INITIALIZED" ]; then
@@ -724,7 +726,6 @@ f_media_init_ftp()
local fdir
if fdir=$( echo "$rx" | awk '
- BEGIN { found = 0 }
/^Remote directory: / {
sub(/^[^:]*:[[:space:]]*/, "")
if ($0 == "/") next
@@ -794,6 +795,7 @@ f_media_init_ftp()
#
f_media_get_ftp()
{
+ local funcname=f_media_get_ftp
local dev="$1" file="$2" probe_type="$3" hosts=
f_dprintf "f_media_get_ftp: dev=[%s] file=[%s] probe_type=%s" \
@@ -870,9 +872,10 @@ f_media_get_ftp()
if [ "$probe_type" ]; then
local url="ftp://$userpass$host$port/$dir/$file" size
[ "$use_anon" ] && url="ftp://$host$port/$dir/$file"
- if ! size=$( fetch -s "$url" 2>&1 ) || ! f_isinteger "$size"
+ if ! f_eval_catch -dk size $funcname fetch \
+ 'fetch -s "%s"' "$url" || ! f_isinteger "$size"
then
- f_dprintf "request failed! size response=[%s]" "$size"
+ f_dprintf "size request failed!"
[ "$probe_type" = "$PROBE_SIZE" ] && echo "-1"
return $FAILURE
fi
diff --git a/usr.sbin/bsdconfig/share/media/http.subr b/usr.sbin/bsdconfig/share/media/http.subr
index 97c4ed0..6d6aa10 100644
--- a/usr.sbin/bsdconfig/share/media/http.subr
+++ b/usr.sbin/bsdconfig/share/media/http.subr
@@ -77,7 +77,8 @@ f_dialog_menu_media_http()
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'
+ 'dist $msg_main_site' 'ftp.freebsd.org'
+ 'pkg $msg_main_site' 'pkg.freebsd.org'
'URL' '$msg_specify_some_other_http_site'
" # END-QUOTE
local hline="$msg_select_a_site_thats_close"
@@ -214,16 +215,17 @@ f_media_set_http()
! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
then
f_struct device_network &&
- f_device_shutdown network
+ f_device_shutdown device_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
+ local dev if
+ f_getvar $VAR_NETWORK_DEVICE if
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_struct_copy "$dev" device_network
fi
- if ! f_device_init network; then
+ if ! f_device_init device_network; then
f_dprintf "f_media_set_http: %s" "$msg_net_device_init_failed"
unset $VAR_HTTP_PATH
return $FAILURE
@@ -306,7 +308,7 @@ f_media_set_http()
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_device_shutdown device_network
f_struct_free device_network
unset $VAR_HTTP_PATH
return $FAILURE
@@ -322,7 +324,7 @@ f_media_set_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
+ device_http set private device_network
f_struct_copy device_http device_media
f_struct_free device_http
@@ -452,6 +454,11 @@ f_media_init_http()
local dev="$1"
f_dprintf "Init routine called for HTTP device. dev=[%s]" "$dev"
+ if [ "$HTTP_INITIALIZED" ]; then
+ f_dprintf "HTTP device already initialized."
+ return $SUCCESS
+ fi
+
#
# First verify access
#
@@ -481,7 +488,7 @@ f_media_init_http()
case "$rel" in
__RELEASE|any)
- setvar $VAR_HTTP_PATH "$VAR_HTTP_DIR"
+ f_getvar $VAR_HTTP_DIR $VAR_HTTP_PATH
f_http_check_access
http_found=$?
;;
@@ -493,22 +500,31 @@ f_media_init_http()
#
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
+ setvar $VAR_HTTP_PATH "$hp/$PKG_ABI/latest"
+ if [ "$PKG_ABI" ] && f_http_check_access; then
+ http_found=$SUCCESS
+ setvar $VAR_HTTP_PATH "$hp"
+ else
+ for fdir in $HTTP_DIRS; do
+ setvar $VAR_HTTP_PATH "$hp/$fdir/$rel"
+ if f_http_check_access; then
+ http_found=$SUCCESS
+ break
+ fi
+ done
+ fi
esac
- [ $http_found -eq $SUCCESS ] && break
+ if [ $http_found -eq $SUCCESS ]; then
+ HTTP_INITIALIZED=YES
+ break
+ fi
f_getvar $VAR_HTTP_PATH http_path
f_show_msg "$msg_please_check_the_url_and_try_again" \
"$http_path"
- unset $VAR_HTTP_PATH
+ unset HTTP_INITIALIZED $VAR_HTTP_PATH
f_media_set_http || break
done
@@ -550,14 +566,21 @@ f_media_init_http()
f_media_get_http()
{
local dev="$1" file="$2" probe_type="$3" hosts=
+ local name
+ $dev get name name
f_dprintf "f_media_get_http: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
local http_host http_port
f_getvar $VAR_HTTP_HOST http_host
f_getvar $VAR_HTTP_PORT http_port
+ if [ ! "$HTTP_INITIALIZED" ]; then
+ f_dprintf "No HTTP connection open, can't get file %s" "$file"
+ return $FAILURE
+ fi
+
if ! {
f_validate_ipaddr "$http_host" ||
f_validate_ipaddr6 "$http_host" ||
@@ -595,6 +618,7 @@ f_media_get_http()
local url="$http_path/$file" rx
f_dprintf "sending http request for: %s" "$url"
+ f_dprintf "using nc to connect to: %s:%s" "$host" "$http_port"
printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$http_port" |
(
#
@@ -648,6 +672,18 @@ f_media_get_http()
return $FAILURE
}
+# f_media_shutdown_http $device
+#
+# Shuts down the HTTP device. Return status should be ignored. Note that since
+# we don't maintain an open connection to the HTTP server, nothing to do.
+#
+f_media_shutdown_http()
+{
+ [ "$HTTP_INITIALIZED" ] || return $SUCCESS
+
+ unset HTTP_INITIALIZED
+}
+
############################################################ MAIN
f_dprintf "%s: Successfully loaded." media/http.subr
diff --git a/usr.sbin/bsdconfig/share/media/nfs.subr b/usr.sbin/bsdconfig/share/media/nfs.subr
index 8db5a06..d83661f 100644
--- a/usr.sbin/bsdconfig/share/media/nfs.subr
+++ b/usr.sbin/bsdconfig/share/media/nfs.subr
@@ -93,13 +93,14 @@ f_media_set_nfs()
! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
then
f_struct device_network &&
- f_device_shutdown network
+ f_device_shutdown device_network
f_device_select_tcp || return $FAILURE
- local dev
- f_getvar $VAR_NETWORK_DEVICE dev
- f_struct_copy "device_$dev" device_network
+ local dev if
+ f_getvar $VAR_NETWORK_DEVICE if
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_struct_copy "$dev" device_network
fi
- f_device_init network ||
+ f_device_init device_network ||
f_dprintf "%s: $msg_net_device_init_failed\n" f_media_set_nfs
local hostname="${nfs%%:*}"
@@ -112,7 +113,7 @@ f_media_set_nfs()
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_device_shutdown device_network
f_struct_free device_network
unset $VAR_NFS_PATH
return $FAILURE
@@ -154,9 +155,10 @@ f_media_set_nfs()
#
f_media_init_nfs()
{
+ local funcname=f_media_init_nfs
local dev="$1" name err
- device_$dev get name name || return $FAILURE
+ $dev get name name || return $FAILURE
f_dprintf "Init routine called for NFS device. name=[%s]" \
"$name"
@@ -165,16 +167,14 @@ f_media_init_nfs()
return $SUCCESS
fi
- if ! f_device_init network; then
+ if ! f_device_init device_network; then
f_dprintf "f_media_init_nfs: %s" "$msg_net_device_init_failed"
return $FAILURE
fi
- if [ ! -e "$MOUNTPOINT" ] &&
- ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
- then
- f_dialog_msgbox "$err"
- return $FAILURE
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
fi
local cp tcp="" use3="" secure="" readsize=4096 writesize=4096
@@ -191,14 +191,15 @@ f_media_init_nfs()
[ "$use3" ] && options="$options,nfsv3"
[ "$tcp" ] && options="$options,tcp"
- if ! err=$( mount_nfs \
- ${secure:+-P} -o "$options" "$name" "$MOUNTPOINT" 2>&1 )
+ if ! f_eval_catch -dk err $funcname mount_nfs \
+ 'mount_nfs %s -o "%s" "%s" "%s"' \
+ "${secure:+-P}" "$options" "$name" "$MOUNTPOINT"
then
err="${err#mount_nfs: }"
f_show_msg "$msg_error_mounting_device" \
"$name" "$MOUNTPOINT" "$err"
f_struct device_network &&
- f_device_shutdown network
+ f_device_shutdown device_network
return $FAILURE
fi
NFS_MOUNTED=1
@@ -218,9 +219,11 @@ f_media_init_nfs()
f_media_get_nfs()
{
local dev="$1" file="$2" probe_type="$3"
+ local name
+ $dev get name name
f_dprintf "f_media_get_nfs: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
}
@@ -231,12 +234,15 @@ f_media_get_nfs()
#
f_media_shutdown_nfs()
{
+ local funcname=f_media_shutdown_nfs
local dev="$1" err
[ "$NFS_MOUNTED" ] || return $FAILURE
f_dprintf "Unmounting NFS partition on %s" "$MOUNTPOINT"
- if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
err="${err#umount: }"; err="${err#*: }"
f_show_msg "$msg_could_not_unmount_the_nfs_partition" \
"$MOUNTPOINT" "$err"
diff --git a/usr.sbin/bsdconfig/share/media/tcpip.subr b/usr.sbin/bsdconfig/share/media/tcpip.subr
index 5957b90..42c6e20 100644
--- a/usr.sbin/bsdconfig/share/media/tcpip.subr
+++ b/usr.sbin/bsdconfig/share/media/tcpip.subr
@@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." media/tcpip.subr
f_include $BSDCFG_SHARE/device.subr
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
f_include $BSDCFG_SHARE/struct.subr
f_include $BSDCFG_SHARE/variable.subr
@@ -110,10 +111,11 @@ f_struct_define DHCP_LEASE \
# begin or end with a hyphen).
# 3 One or more individual labels within the hostname are null.
#
-# f_dialog_validate_hostname $hostname
+# To call this function and display an appropriate error message to the user
+# based on the above error codes, use the following function defined in
+# dialog.subr:
#
-# If the hostname is determined to be invalid, the appropriate error will be
-# displayed using the f_show_msg function.
+# f_dialog_validate_hostname $hostname
#
f_validate_hostname()
{
@@ -167,8 +169,9 @@ 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 )) )
+ local IFS=.
+ set -- $__addr
+ __num=$(( ($1 << 24) + ($2 << 16) + ($3 << 8) + $4 ))
fi
if [ "$__var_to_set" ]; then
setvar "$__var_to_set" $__num
@@ -201,8 +204,7 @@ f_validate_ipaddr()
# Track number of octets for error checking
local noctets=0
- local oldIFS="$IFS"
- local IFS="." # Split on `dot'
+ local oldIFS="$IFS" IFS="." # Split on `dot'
for octet in $ip; do
# Return error if the octet is null
[ "$octet" ] || return 2
@@ -573,7 +575,7 @@ f_ifconfig_netmask()
local __octet __netmask=
for __octet in $__octets; do
- __netmask="$__netmask.$( printf "%u" "0x$__octet" )"
+ f_sprintf __netmask "%s.%u" "$__netmask" "0x$__octet"
done
__netmask="${__netmask#.}"
if [ "$__var_to_set" ]; then
@@ -1020,10 +1022,42 @@ f_host_lookup()
# 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 ))"
+ local __output __ip6 __addrs=
f_getvar $VAR_IPV6_ENABLE __ip6
+
+ # If we have a TCP media type configured, check for an SRV record
+ local __srvtypes=
+ { f_quietly f_getvar $VAR_HTTP_PATH ||
+ f_quietly f_getvar $VAR_HTTP_PROXY_PATH
+ } && __srvtypes="$__srvtypes _http._tcp"
+ f_quietly f_getvar $VAR_FTP_PATH && __srvtypes="$__srvtypes _ftp._tcp"
+ f_quietly f_getvar $VAR_NFS_PATH &&
+ __srvtypes="$__srvtypes _nfs._tcp _nfs._udp"
+
+ # Calculate wait time as dividend of total time and host(1) invocations
+ local __host_runs __wait
+ f_count __host_runs $__srvtypes
+ if [ "$__ip6" = "YES" ]; then
+ __host_runs=$(( $__host_runs + 2 ))
+ else
+ __host_runs=$(( $__host_runs + 1 ))
+ fi
+ f_getvar $VAR_MEDIA_TIMEOUT __wait
+ [ "$__wait" ] && __wait="-W $(( $__wait / $__host_runs ))"
+
+ # Query SRV types first (1st host response taken as new host to query)
+ for __type in $__srvtypes; do
+ if __output=$(
+ host -t SRV $__wait -- "$__type.$__host" \
+ 2> /dev/null
+ ); then
+ __host=$( echo "$__output" |
+ awk '/ SRV /{print $NF;exit}' )
+ break
+ fi
+ done
+
+ # Try IPv6 first (if enabled)
if [ "$__ip6" = "YES" ]; then
if ! __output=$( host -t AAAA $__wait -- "$__host" 2>&1 ); then
# An error occurred, display in-full and return error
@@ -1031,13 +1065,17 @@ f_host_lookup()
setvar "$__var_to_set" "$__output"
return $FAILURE
fi
+ # Add the IPv6 addresses and fall-through to collect IPv4 too
__addrs=$( echo "$__output" | awk '/ address /{print $NF}' )
fi
+
+ # Good ol' IPv4
if ! __output=$( host -t A $__wait -- "$__host" 2>&1 ); then
# An error occurred, display it in-full and return error
[ "$__var_to_set" ] && setvar "$__var_to_set" "$__output"
return $FAILURE
fi
+
__addrs="$__addrs${__addrs:+ }$(
echo "$__output" | awk '/ address /{print $NF}' )"
if [ "$__var_to_set" ]; then
@@ -1098,15 +1136,16 @@ f_host_lookup()
#
f_device_dialog_tcp()
{
- local dev="$1" cp n
+ local dev="$1" devname cp n
local use_dhcp="" use_rtsol=""
local _ipaddr _netmask _extras
[ "$dev" ] || return $DIALOG_CANCEL
+ f_struct "$dev" get name devname || return $DIALOG_CANCEL
# Initialize vars from previous device values
local private
- device_$dev get private private
+ $dev get private private
if [ "$private" ] && f_struct "$private"; then
$private get ipaddr _ipaddr
$private get netmask _netmask
@@ -1144,17 +1183,17 @@ f_device_dialog_tcp()
f_quietly sysctl net.inet6.ip6.forwarding=0
f_quietly sysctl net.inet6.ip6.accept_rtadv=1
- f_quietly ifconfig $dev up
+ f_quietly ifconfig $devname up
i=$( sysctl -n net.inet6.ip6.dad_count )
sleep $(( $i + 1 ))
f_quietly mkdir -p /var/run
f_dialog_info "$msg_scanning_for_ra_servers"
- if f_quietly rtsol $dev; then
+ if f_quietly rtsol $devname; then
i=$( sysctl -n net.inet6.ip6.dad_count )
sleep $(( $i + 1 ))
- f_rtsol_get_info $dev
+ f_rtsol_get_info $devname
use_rtsol=1
else
use_rtsol=
@@ -1173,7 +1212,7 @@ f_device_dialog_tcp()
! f_isset $VAR_TRY_DHCP &&
f_dialog_noyes "$msg_try_dhcp_configuration"
}; then
- f_quietly ifconfig $dev delete
+ f_quietly ifconfig $devname delete
f_quietly mkdir -p /var/db
f_quietly mkdir -p /var/run
f_quietly mkdir -p /tmp
@@ -1183,17 +1222,17 @@ f_device_dialog_tcp()
( # Execute in sub-shell to allow/catch Ctrl-C
trap 'exit $FAILURE' SIGINT
if [ "$USE_XDIALOG" ]; then
- f_quietly dhclient $dev |
+ f_quietly dhclient $devname |
f_xdialog_info "$msg"
else
f_dialog_info "$msg"
- f_quietly dhclient $dev
+ f_quietly dhclient $devname
fi
)
local retval=$?
trap 'f_interrupt' SIGINT
if [ $retval -eq $SUCCESS ]; then
- f_dhcp_get_info $dev
+ f_dhcp_get_info $devname
use_dhcp=1
else
use_dhcp=
@@ -1214,7 +1253,7 @@ f_device_dialog_tcp()
if [ ! "$_ipaddr" ]; then
if f_getvar $VAR_IPADDR cp; then
_ipaddr="$cp"
- elif f_getvar ${dev}_$VAR_IPADDR cp; then
+ elif f_getvar ${devname}_$VAR_IPADDR cp; then
_ipaddr="$cp"
fi
fi
@@ -1223,7 +1262,7 @@ f_device_dialog_tcp()
if [ ! "$_netmask" ]; then
if f_getvar $VAR_NETMASK cp; then
_netmask="$cp"
- elif f_getvar ${dev}_$VAR_NETMASK cp; then
+ elif f_getvar ${devname}_$VAR_NETMASK cp; then
_netmask="$cp"
fi
fi
@@ -1232,7 +1271,7 @@ f_device_dialog_tcp()
if [ ! "$_extras" ]; then
if f_getvar $VAR_EXTRAS cp; then
_extras="$cp"
- elif f_getvar ${dev}_$VAR_EXTRAS cp; then
+ elif f_getvar ${devname}_$VAR_EXTRAS cp; then
_extras="$cp"
fi
fi
@@ -1256,8 +1295,8 @@ f_device_dialog_tcp()
[ "$_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
+ [ "$_ipaddr" ] || f_ifconfig_inet $devname _ipaddr
+ [ "$_netmask" ] || f_ifconfig_netmask $devname _netmask
# If non-interactive, jump over dialog section and into config section
if f_netinteractive || f_interactive || [ ! "$_hostname" ]
@@ -1270,7 +1309,7 @@ f_device_dialog_tcp()
local extras_help="$tcplayout_extras_help"
# Modify the help line for PLIP config
- [ "${dev#plip}" != "$dev" ] &&
+ [ "${devname#plip}" != "$devname" ] &&
extras_help="$tcplayout_extras_help_for_plip"
f_getvar $VAR_IPV6ADDR cp && [ "$cp" ] &&
@@ -1279,7 +1318,8 @@ f_device_dialog_tcp()
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 devlabel="$msg_configuration_for_interface"
+ devlabel="$devlabel $devname"
local width=54
local n=$(( $width/2 - (${#devlabel} + 4)/2 - 2 ))
@@ -1465,7 +1505,7 @@ f_device_dialog_tcp()
f_dprintf "Creating struct DEVICE_INFO devinfo_%s" "$dev"
f_struct_new DEVICE_INFO devinfo_$dev
- device_$dev set private devinfo_$dev
+ $dev set private devinfo_$dev
devinfo_$dev set ipaddr $_ipaddr
devinfo_$dev set netmask $_netmask
@@ -1479,7 +1519,7 @@ f_device_dialog_tcp()
else
cp="inet $_ipaddr netmask $_netmask${extras:+ $extras}"
fi
- setvar $VAR_IFCONFIG$dev "$cp"
+ setvar $VAR_IFCONFIG$devname "$cp"
fi
[ "$use_rtsol" ] &&
setvar $VAR_IPV6_ENABLE "YES"
@@ -1552,7 +1592,7 @@ f_device_scan_tcp()
#
f_device_select_tcp()
{
- local devs dev cnt network_dev
+ local devs dev cnt if network_dev
f_getvar $VAR_NETWORK_DEVICE network_dev
f_dprintf "f_device_select_tcp: %s=[%s]" \
@@ -1570,23 +1610,18 @@ f_device_select_tcp()
while [ "$network_dev" ]; do
case "$network_dev" in
- *,*) dev="${network_dev%%,*}"
+ *,*) if="${network_dev%%,*}"
network_dev="${network_dev#*,}"
;;
- *) dev="$network_dev"
+ *) if="$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 $DIALOG_OK ]; then
- setvar $VAR_NETWORK_DEVICE $dev
- return $DIALOG_OK
- fi
+ f_device_find -1 "$if" $DEVICE_TYPE_NETWORK dev
+ f_device_dialog_tcp $dev
+ if [ $? -eq $DIALOG_OK ]; then
+ setvar $VAR_NETWORK_DEVICE $if
+ return $DIALOG_OK
fi
done
@@ -1596,8 +1631,9 @@ f_device_select_tcp()
fi # $network_dev
f_device_find "" $DEVICE_TYPE_NETWORK devs
- cnt=$( set -- $devs; echo $# )
+ f_count cnt $devs
dev="${devs%%[$IFS]*}"
+ $dev get name if
f_quietly f_getvar NETWORK_CONFIGURED # for debugging info
if ! f_running_as_init &&
@@ -1606,7 +1642,7 @@ f_device_select_tcp()
trap 'f_interrupt' SIGINT
if f_dialog_yesno "$msg_assume_network_is_already_configured"
then
- setvar $VAR_NETWORK_DEVICE $dev
+ setvar $VAR_NETWORK_DEVICE $if
return $DIALOG_OK
fi
fi
@@ -1618,7 +1654,7 @@ f_device_select_tcp()
elif [ $cnt -eq 1 ]; then
f_device_dialog_tcp $dev
retval=$?
- [ $retval -eq $DIALOG_OK ] && setvar $VAR_NETWORK_DEVICE $dev
+ [ $retval -eq $DIALOG_OK ] && setvar $VAR_NETWORK_DEVICE $if
else
local title="$msg_network_interface_information_required"
local prompt="$msg_please_select_ethernet_device_to_configure"
@@ -1627,19 +1663,14 @@ f_device_select_tcp()
dev=$( f_device_menu \
"$title" "$prompt" "$hline" $DEVICE_TYPE_NETWORK \
"$NETWORK_DEVICE_HELPFILE" \
- 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
- retval=$?
- [ "$dev" ] || return $DIALOG_CANCEL
-
- f_device_find "$dev" $DEVICE_TYPE_NETWORK devs
- [ "$devs" ] || return $DIALOG_CANCEL
- dev="${devs%%[$IFS]*}"
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $DIALOG_CANCEL
f_device_dialog_tcp $dev
retval=$?
if [ $retval -eq $DIALOG_OK ]; then
- f_struct_copy device_$dev device_network
- setvar $VAR_NETWORK_DEVICE network
+ f_struct_copy "$dev" device_network
+ setvar $VAR_NETWORK_DEVICE device_network
else
f_struct_free device_network
fi
@@ -1667,7 +1698,7 @@ f_dialog_menu_select_tcp()
device_network get name name &&
f_yesno "$msg_would_you_like_to_bring_interface_up" "$name"
then
- if ! f_device_init network; then
+ if ! f_device_init device_network; then
f_show_msg "$msg_initialization_of_device_failed" \
"$name"
fi
diff --git a/usr.sbin/bsdconfig/share/media/ufs.subr b/usr.sbin/bsdconfig/share/media/ufs.subr
index 2de29b3..27e2f27 100644
--- a/usr.sbin/bsdconfig/share/media/ufs.subr
+++ b/usr.sbin/bsdconfig/share/media/ufs.subr
@@ -67,7 +67,7 @@ f_media_set_ufs()
local devs ndevs
f_device_find "" $DEVICE_TYPE_UFS devs
- ndevs=$( set -- $devs; echo $# )
+ f_count ndevs $devs
if [ ${ndevs:=0} -eq 0 ]; then
f_variable_get_value $VAR_UFS_PATH \
@@ -89,22 +89,20 @@ f_media_set_ufs()
f_struct_copy device_ufs device_media
f_struct_free device_ufs
- elif [ $ndevs -gt 1 ]; then
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
local title="$msg_choose_a_ufs_partition"
local prompt="$msg_please_select_ufs_partition"
local hline=""
- local dev retval
dev=$( f_device_menu \
"$title" "$prompt" "$hline" $DEVICE_TYPE_UFS \
- 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
- retval=$?
- [ "$dev" ] || return $FAILURE
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
- f_struct_copy device_$dev device_media
- [ $retval -eq $SUCCESS ] || return $FAILURE
- else
- f_struct_copy device_$devs device_media
+ f_struct_copy "$dev" device_media
fi
f_struct device_media || return $FAILURE
@@ -117,9 +115,10 @@ f_media_set_ufs()
#
f_media_init_ufs()
{
+ local funcname=f_media_init_ufs
local dev="$1" devname err
- device_$dev get devname devname || return $FAILURE
+ $dev get devname devname || return $FAILURE
f_dprintf "Init routine called for UFS device. devname=[%s]" \
"$devname"
@@ -134,14 +133,13 @@ f_media_init_ufs()
return $FAILURE
fi
- if [ ! -e "$MOUNTPOINT" ] &&
- ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
- then
- f_dialog_msgbox "$err"
- return $FAILURE
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
fi
- if ! err=$( mount "$devname" "$MOUNTPOINT" 2>&1 )
+ if ! f_eval_catch -dk err $funcname mount \
+ 'mount "%s" "%s"' "$devname" "$MOUNTPOINT"
then
err="${err#mount: }"; err="${err#$devname : }"
f_show_msg "$msg_error_mounting_device" \
@@ -162,9 +160,11 @@ f_media_init_ufs()
f_media_get_ufs()
{
local dev="$1" file="$2" probe_type="$3"
+ local name
+ $dev get name name
f_dprintf "f_media_get_ufs: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
}
@@ -175,11 +175,14 @@ f_media_get_ufs()
#
f_media_shutdown_ufs()
{
+ local funcname=f_media_shutdown_ufs
local dev="$1" err
[ "$UFS_MOUNTED" ] || return $FAILURE
- if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
err="${err#umount: }"; err="${err#*: }"
f_show_msg "$msg_could_not_unmount_the_ufs_partition" \
"$MOUNTPOINT" "$err"
diff --git a/usr.sbin/bsdconfig/share/media/usb.subr b/usr.sbin/bsdconfig/share/media/usb.subr
index f7afc29..5ee9bc0 100644
--- a/usr.sbin/bsdconfig/share/media/usb.subr
+++ b/usr.sbin/bsdconfig/share/media/usb.subr
@@ -57,31 +57,25 @@ f_media_set_usb()
local devs ndevs
f_device_find "" $DEVICE_TYPE_USB devs
- ndevs=$( set -- $devs; echo $# )
+ f_count ndevs $devs
if [ ${ndevs:=0} -eq 0 ]; then
f_show_msg "$msg_no_usb_devices_found"
return $FAILURE
- elif [ $ndevs -gt 1 ]; then
+ elif [ $ndevs -eq 1 ]; then
+ f_struct_copy $devs device_media
+ else
+ local dev
local title="$msg_choose_a_usb_drive"
local prompt="$msg_please_select_a_usb_drive"
- local hline=""
+ 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]*}"
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD ) ||
+ return $FAILURE
- f_struct_copy device_$dev device_media
- [ $retval -eq $SUCCESS ] || return $FAILURE
- else
- f_struct_copy device_$devs device_media
+ f_struct_copy "$dev" device_media
fi
f_struct device_media &&
@@ -103,9 +97,10 @@ f_media_set_usb()
#
f_media_init_usb()
{
+ local funcname=f_media_init_usb
local dev="$1" devname err
- device_$dev get devname devname || return $FAILURE
+ $dev get devname devname || return $FAILURE
f_dprintf "Init routine called for USB device. devname=[%s]" \
"$devname"
@@ -114,14 +109,14 @@ f_media_init_usb()
return $SUCCESS
fi
- if [ ! -e "$MOUNTPOINT" ] &&
- ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
- then
- f_dialog_msgbox "$err"
- return $FAILURE
+ if [ ! -e "$MOUNTPOINT" ]; then
+ f_eval_catch $funcname mkdir 'mkdir -p "%s"' "$MOUNTPOINT" ||
+ return $FAILURE
fi
- if err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ); then
+ if f_eval_catch -dk err $funcname mount \
+ 'mount "%s" "%s"' "$devname" "$MOUNTPOINT"
+ then
USB_MOUNTED=1
return $SUCCESS
fi
@@ -142,9 +137,11 @@ f_media_init_usb()
f_media_get_usb()
{
local dev="$1" file="$2" probe_type="$3"
+ local name
+ $dev get name name
f_dprintf "f_media_get_usb: dev=[%s] file=[%s] probe_type=%s" \
- "$dev" "$file" "$probe_type"
+ "$name" "$file" "$probe_type"
f_media_generic_get "$MOUNTPOINT" "$file" "$probe_type"
}
@@ -156,11 +153,14 @@ f_media_get_usb()
#
f_media_shutdown_usb()
{
+ local funcname=f_media_shutdown_usb
local dev="$1" err
[ "$USB_MOUNTED" ] || return $FAILURE
- if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ if ! f_eval_catch -dk err $funcname umount \
+ 'umount -f "%s"' "$MOUNTPOINT"
+ then
err="${err#umount: }"; err="${err#*: }"
f_show_msg "$msg_could_not_unmount_the_ufs_partition" \
"$MOUNTPOINT" "$err"
diff --git a/usr.sbin/bsdconfig/share/mustberoot.subr b/usr.sbin/bsdconfig/share/mustberoot.subr
index 67b4c3e..88ff818 100644
--- a/usr.sbin/bsdconfig/share/mustberoot.subr
+++ b/usr.sbin/bsdconfig/share/mustberoot.subr
@@ -32,6 +32,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." mustberoot.subr
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig"
f_include_lang $BSDCFG_LIBE/include/messages.subr
@@ -77,6 +78,7 @@ SECURE_DIVULGE_UNKNOWN_USER=
#
f_become_root_via_sudo()
{
+ local funcname=f_become_root_via_sudo
local prompt hline height width rows msg
[ "$( id -u )" = "0" ] && return $SUCCESS
@@ -90,8 +92,8 @@ f_become_root_via_sudo()
#
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" )
+ f_sprintf prompt "$msg_you_are_not_root_but" bsdconfig
+ f_sprintf msg "$msg_always_try_sudo_when_run_as" "$USER"
local menu_list="
'X' '$msg_cancel_exit'
'1' '$msg'
@@ -124,12 +126,9 @@ f_become_root_via_sudo()
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_eval_catch $funcname touch \
+ 'touch "%s"' "$checkpath" &&
f_show_msg "$msg_created_path" "$checkpath"
- fi
esac
else
#
@@ -225,7 +224,7 @@ f_become_root_via_sudo()
# the security event and exit immediately.
#
if [ $nfailures -ge $PASSWD_TRIES ]; then
- msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
+ f_sprintf msg "$msg_nfailed_attempts" "$nfailures"
logger -p auth.notice -t sudo " " \
"$USER : $msg" \
"; TTY=$(tty)" \
@@ -387,7 +386,7 @@ f_authenticate_some_user()
# the security event and exit immediately.
#
if [ $nfailures -ge $PASSWD_TRIES ]; then
- msg=$( printf "$msg_nfailed_attempts" "$nfailures" )
+ f_sprintf msg "$msg_nfailed_attempts" "$nfailures"
logger -p auth.notice -t sudo " " \
"${SUDO_USER:-$USER} : $msg" \
"; TTY=$(tty)" \
diff --git a/usr.sbin/bsdconfig/share/packages/categories.subr b/usr.sbin/bsdconfig/share/packages/categories.subr
index dd2fa8f..474c41d 100755
--- a/usr.sbin/bsdconfig/share/packages/categories.subr
+++ b/usr.sbin/bsdconfig/share/packages/categories.subr
@@ -39,6 +39,7 @@ f_include_lang $BSDCFG_LIBE/include/messages.subr
############################################################ GLOBALS
CATEGORIES=
+NCATEGORIES=0
############################################################ FUNCTIONS
@@ -199,8 +200,9 @@ f_category x11-wm "$msg_x11_wm_desc"
f_category xfce "$msg_xfce_desc"
f_category zope "$msg_zope_desc"
+f_count NCATEGORIES $CATEGORIES
f_dprintf "%s: Initialized %u package category descriptions." \
- packages/categories.subr "$( set -- $CATEGORIES; echo $# )"
+ packages/categories.subr $NCATEGORIES
f_dprintf "%s: Successfully loaded." packages/categories.subr
diff --git a/usr.sbin/bsdconfig/share/packages/index.subr b/usr.sbin/bsdconfig/share/packages/index.subr
index 863249c..9586501 100755
--- a/usr.sbin/bsdconfig/share/packages/index.subr
+++ b/usr.sbin/bsdconfig/share/packages/index.subr
@@ -43,45 +43,231 @@ f_include_lang $BSDCFG_LIBE/include/messages.subr
PACKAGE_INDEX=
_INDEX_INITTED=
+#
+# Default path to pkg(8) repo-packagesite.sqlite database
+#
+SQLITE_REPO="/var/db/pkg/repo-packagesite.sqlite"
+
+#
+# Default path to on-disk cache INDEX file
+#
+PACKAGES_INDEX_CACHEFILE="/var/run/bsdconfig/packages_INDEX.cache"
+
+#
+# INDEX format for FreeBSD-6.0 or higher:
+#
+# package|port-origin|install-prefix|comment|port-desc-file|maintainer|
+# categories|build-deps|run-deps|www-site|reserve|reserve|reserve|disc
+#
+INDEX_FORMAT="%n-%v" # package
+INDEX_FORMAT="$INDEX_FORMAT|/usr/ports/%o" # port-origin
+INDEX_FORMAT="$INDEX_FORMAT|%p" # install-prefix
+INDEX_FORMAT="$INDEX_FORMAT|%c" # comment
+INDEX_FORMAT="$INDEX_FORMAT|/usr/ports/%o/pkg-descr" # port-desc-file
+INDEX_FORMAT="$INDEX_FORMAT|%m" # maintainer
+INDEX_FORMAT="$INDEX_FORMAT|@CATEGORIES@" # place-holder
+INDEX_FORMAT="$INDEX_FORMAT|" # build-deps
+INDEX_FORMAT="$INDEX_FORMAT|@RUNDEPS@" # place-holder
+INDEX_FORMAT="$INDEX_FORMAT|%w" # www-site
+INDEX_FORMAT="$INDEX_FORMAT|" # reserved
+INDEX_FORMAT="$INDEX_FORMAT|" # reserved
+INDEX_FORMAT="$INDEX_FORMAT|" # reserved
+INDEX_FORMAT="$INDEX_FORMAT|" # disc
+
############################################################ FUNCTIONS
-# f_index_initialize $path [$var_to_set]
+# f_index_initialize [$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.
+# Read and initialize the global index. Returns success unless media cannot be
+# initialized for any reason (e.g. user cancels media selection dialog or an
+# error occurs). The index is sorted before being loaded into $var_to_set.
#
# NOTE: The index is processed with f_index_read() [below] after being loaded.
#
f_index_initialize()
{
- local __path="$1" __var_to_set="${2:-PACKAGE_INDEX}"
+ local __funcname=f_index_initialize
+ local __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
+ f_device_init device_media || return $FAILURE
+
+ f_show_info "$msg_attempting_to_update_repository_catalogue"
+
+ #
+ # Generate $PACKAGESITE variable for pkg(8) based on media type
+ #
+ local __type __data __site
+ device_media get type __type
+ device_media get private __data
+ case "$__type" in
+ $DEVICE_TYPE_DIRECTORY)
+ __site="file://$__data/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_FLOPPY)
+ __site="file://${__data:-$MOUNTPOINT}/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_FTP)
+ f_getvar $VAR_FTP_PATH __site
+ __site="$__site/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_HTTP)
+ f_getvar $VAR_HTTP_PATH __site
+ __site="$__site/$PKG_ABI/latest" ;;
+ $DEVICE_TYPE_HTTP_PROXY)
+ f_getvar $VAR_HTTP_PROXY_PATH __site
+ __site="$__site/packages/$PKG_ABI" ;;
+ $DEVICE_TYPE_CDROM)
+ __site="file://$MOUNTPOINT/packages/$PKG_ABI"
+ export REPOS_DIR="$MOUNTPOINT/packages/repos" ;;
+ *) # UFS, DISK, CDROM, USB, DOS, NFS, etc.
+ __site="file://$MOUNTPOINT/packages/$PKG_ABI"
+ esac
+
+ export PACKAGESITE="$__site"
+ f_dprintf "PACKAGESITE=[%s]" "$PACKAGESITE"
+ if ! f_eval_catch $__funcname pkg "pkg update"; then
+ f_show_err "$msg_unable_to_update_pkg_from_selected_media"
+ f_device_shutdown device_media
+ return $FAILURE
+ fi
+
+ #
+ # Try to get contents from validated on-disk cache
+ #
+
+ #
+ # Calculate digest used to determine if the on-disk persistant cache
+ # INDEX (containing this digest on the first line) is valid and can be
+ # used to quickly populate the environment.
+ #
+ local __sqlite_digest
+ if ! __sqlite_digest=$( md5 < "$SQLITE_REPO" 2> /dev/null ); then
+ f_show_err "$msg_no_pkg_database_found"
+ f_device_shutdown device_media
+ return $FAILURE
+ fi
+
+ #
+ # Check to see if the persistant cache INDEX file exists
+ #
+ if [ -f "$PACKAGES_INDEX_CACHEFILE" ]; then
+ #
+ # Attempt to populate the environment with the (soon to be)
+ # validated on-disk cache. If validation fails, fall-back to
+ # generating a fresh cache.
+ #
+ if eval $__var_to_set='$(
+ ( # Get digest as the first word on first line
+ read digest rest_ignored
+
+ #
+ # If the stored digest matches the calculated-
+ # one populate the environment from the on-disk
+ # cache and provide success exit status.
+ #
+ if [ "$digest" = "$__sqlite_digest" ]; then
+ cat
+ exit $SUCCESS
+ else
+ # Otherwise, return the current value
+ eval echo \"\$__var_to_set\"
+ exit $FAILURE
+ fi
+ ) < "$PACKAGES_INDEX_CACHEFILE" 2> /dev/null
+ )'; then
+ f_show_info \
+ "$msg_located_index_now_reading_package_data_from_it"
+ if ! f_index_read "$__var_to_set"; then
+ f_show_err \
+ "$msg_io_or_format_error_on_index_file"
+ return $FAILURE
+ fi
+ _INDEX_INITTED=1
+ return $SUCCESS
+ fi
+ # Otherwise, fall-thru to create a fresh cache from scratch
+ fi
+
+ #
+ # If we reach this point, we need to generate the data from scratch
+ #
+
+ f_show_info "$msg_getting_package_categories_via_pkg_rquery"
+ if ! eval "$( pkg rquery "%n-%v %C" | awk '
+ { categories[$1] = categories[$1] " " $2 }
+ END {
+ for (package in categories)
+ {
+ cats = categories[package]
+ sub(/^ /, "", cats)
+ gsub(/[^[:alnum:]_]/, "_", package)
+ printf "local _%s_categories=\"%s\";\n", package, cats
+ }
+ }' )"; then
+ f_show_err "$msg_unable_to_pkg_rquery_package_dependencies"
+ f_device_shutdown device_media
return $FAILURE
fi
+
+ f_show_info "$msg_getting_package_dependencies_via_pkg_rquery"
+ if ! eval "$( pkg rquery "%n-%v %dn-%dv" | awk '
+ { rundeps[$1] = rundeps[$1] " " $2 }
+ END {
+ for (package in rundeps)
+ {
+ deps = rundeps[package]
+ sub(/^ /, "", deps)
+ gsub(/[^[:alnum:]_]/, "_", package)
+ printf "local _%s_rundeps=\"%s\";\n", package, deps
+ }
+ }' )"; then
+ f_show_err "$msg_unable_to_pkg_rquery_package_dependencies"
+ f_device_shutdown device_media
+ return $FAILURE
+ fi
+
+ f_show_info "$msg_generating_index_from_pkg_database"
+ eval "$__var_to_set"='$( pkg rquery "$INDEX_FORMAT" |
+ while read LINE; do
+ package="${LINE%%|*}";
+ f_str2varname "$package" varpkg;
+ eval f_replaceall \"\$LINE\" \"\|@CATEGORIES@\|\" \
+ \"\|\$_${varpkg}_categories\|\" LINE
+ eval f_replaceall \"\$LINE\" \"\|@RUNDEPS@\|\" \
+ \"\|\$_${varpkg}_rundeps\|\" LINE
+ echo "$LINE"
+ done
+ )' # always returns true (status of last item in pipe-chain)
eval "$__var_to_set"='$( debug= f_getvar "$__var_to_set" | sort )'
+ #
+ # Attempt to create the persistant on-disk cache
+ #
+
+ # Create a new temporary file to write to
+ local __tmpfile
+ if f_eval_catch -dk __tmpfile $__funcname mktemp \
+ 'mktemp -t "%s"' "$pgm"
+ then
+ # Write the temporary file contents
+ echo "$__sqlite_digest" > "$__tmpfile"
+ debug= f_getvar "$__var_to_set" >> "$__tmpfile"
+
+ # Finally, move the temporary file into place
+ case "$PACKAGES_INDEX_CACHEFILE" in
+ */*) f_eval_catch -d $funcname mkdir \
+ 'mkdir -p "%s"' "${PACKAGES_INDEX_CACHEFILE%/*}"
+ esac
+ f_eval_catch -d $__funcname mv 'mv -f "%s" "%s"' \
+ "$__tmpfile" "$PACKAGES_INDEX_CACHEFILE"
+ fi
+
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"
+ f_show_err "$msg_io_or_format_error_on_index_file"
return $FAILURE
fi
diff --git a/usr.sbin/bsdconfig/share/packages/packages.subr b/usr.sbin/bsdconfig/share/packages/packages.subr
index 85aebc8..6fc936f 100755
--- a/usr.sbin/bsdconfig/share/packages/packages.subr
+++ b/usr.sbin/bsdconfig/share/packages/packages.subr
@@ -53,7 +53,7 @@ f_include_lang $BSDCFG_LIBE/include/messages.subr
#
# Package extensions to try
#
-PACKAGE_EXTENSIONS=".tbz .tbz2 .tgz"
+PACKAGE_EXTENSIONS=".txz .tbz .tbz2 .tgz"
#
# Variables used to track runtime states
@@ -164,24 +164,13 @@ f_package_deselect()
# f_package_detect_installed
#
-# Detect installed packages. Currently this searches /var/db/pkg for directory
+# Detect installed packages. Currently this uses pkg-query(8) for querying
# entries and marks each entry as an installed/selected package.
#
f_package_detect_installed()
{
- local 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 <name>' 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
+ local package varpkg
+ for package in $( pkg query "%n-%v" ); do
f_str2varname $package varpkg
export _mark_$varpkg=X # exported for awk(1) ENVIRON[]
f_package_select $package
@@ -483,8 +472,7 @@ f_package_menu_select()
"$msg_all"|"") f_category_desc_get "All" prompt ;;
*) f_category_desc_get "$category" prompt ;;
esac
- prompt="$prompt $( printf "$msg_page_of_npages" \
- "$page" "$npages" )"
+ f_sprintf prompt "%s $msg_page_of_npages" "$prompt" "$page" "$npages"
local mheight mwidth mrows
eval f_dialog_menu${SHOW_DESC:+_with_help}_size mheight mwidth mrows \
@@ -547,7 +535,7 @@ f_package_menu_deselect()
" # End-Quote
local hline="$hline_alnum_arrows_punc_tab_enter"
- prompt=$( printf "$msg_what_would_you_like_to_do_with" "$package" )
+ f_sprintf prompt "$msg_what_would_you_like_to_do_with" "$package"
local height width rows
eval f_dialog_menu_size height width rows \
@@ -582,14 +570,14 @@ f_package_menu_deselect()
#
f_package_review()
{
+ local funcname=f_package_review
local prompt # Calculated below
local menu_list # Calculated below
local hline="$hline_alnum_arrows_punc_tab_enter"
- local fname=f_package_review
- f_dprintf "%s: SELECTED_PACKAGES=[%s]" $fname "$SELECTED_PACKAGES"
+ f_dprintf "$funcname: SELECTED_PACKAGES=[%s]" "$SELECTED_PACKAGES"
- prompt=$( printf "$msg_reviewing_selected_packages" "$_All_nselected" )
+ f_sprintf prompt "$msg_reviewing_selected_packages" "$_All_nselected"
local package varpkg mark
for package in $SELECTED_PACKAGES; do
@@ -639,7 +627,7 @@ f_package_review()
f_str2varname "$package" varpkg
debug= f_getvar _mark_$varpkg mark
[ "$mark" = "I" ] || continue
- f_dprintf "%s: Installing %s package" $fname "$package"
+ f_dprintf "$funcname: Installing %s package" "$package"
f_package_add "$package"
done
for package in $SELECTED_PACKAGES; do
@@ -647,7 +635,7 @@ f_package_review()
f_str2varname "$package" varpkg
debug= f_getvar _mark_$varpkg mark
[ "$mark" = "R" ] || continue
- f_dprintf "%s: Reinstalling %s package" $fname "$package"
+ f_dprintf "$funcname: Reinstalling %s package" "$package"
f_package_reinstall "$package"
done
for package in $SELECTED_PACKAGES; do
@@ -655,7 +643,7 @@ f_package_review()
f_str2varname "$package" varpkg
debug= f_getvar _mark_$varpkg mark
[ "$mark" = "U" ] || continue
- f_dprintf "%s: Uninstalling %s package" $fname "$package"
+ f_dprintf "$funcname: Uninstalling %s package" "$package"
f_package_delete "$package" || continue
f_package_deselect "$package"
done
@@ -850,7 +838,7 @@ f_package_add()
{ # Verify and initialize device media if-defined
f_media_verify &&
- f_device_init media &&
+ f_device_init device_media &&
f_index_initialize packages/INDEX
} || return $FAILURE
@@ -935,7 +923,7 @@ f_package_add()
# Done with the deps? Try to load the real m'coy.
#
- f_package_extract media "$name" "$depended"
+ f_package_extract device_media "$name" "$depended"
retval=$?
if [ $retval -ne $SUCCESS ]; then
status=$(( $status | $retval ))
@@ -954,11 +942,13 @@ f_package_add()
#
f_package_extract()
{
+ local funcname=f_package_extract
local device="$1" name="$2" depended="$3"
+ local devname=
- local fname=f_package_extract
- f_dprintf "%s: device=[%s] name=[%s] depended=[%s]" \
- $fname "$device" "$name" "$depended"
+ $device get name devname
+ f_dprintf "$funcname: device=[%s] name=[%s] depended=[%s]" \
+ "$devname" "$name" "$depended"
# Check to make sure it's not already there
local varpkg mark=
@@ -982,43 +972,51 @@ f_package_extract()
f_getvar $VAR_PKG_TMPDIR:-/var/tmp tmpdir
f_quietly mkdir -p -m 1777 "$tmpdir"
- local path
+ local path device_type
+ $device get type device_type
case "$name" in
*/*) path="$name" ;;
*)
- case "$name" in
- *-*|*_*) path="packages/All/$name" ;;
- *) path="packages/Latest/$name"
- esac
+ if [ "$device_type" = "$DEVICE_TYPE_HTTP" ]; then
+ path="$PKG_ABI/latest/All/$name"
+ else
+ path="packages/$PKG_ABI/All/$name"
+ fi
esac
- # We have a path, call the device strategy routine to get the file
+ # We have a path, call the device strategy routine to check the file
local pkg_ext found=
for pkg_ext in "" $PACKAGE_EXTENSIONS; do
if f_device_get $device "$path$pkg_ext" $PROBE_EXIST; then
path="$path$pkg_ext"
- f_dprintf "%s: found path=[%s] dev=[%s]" \
- $fname "$path" "$device"
+ found=1
+ break
+ elif [ "$device_type" = "$DEVICE_TYPE_HTTP" ] &&
+ f_device_get $device \
+ "packages/$PKG_ABI/All/$name$pkg_ext" $PROBE_EXIST
+ then
+ # Mirroring physical media over HTTP
+ path="packages/$PKG_ABI/All/$name$pkg_ext"
found=1
break
fi
done
+ [ "$found" ] && f_dprintf "$funcname: found path=[%s] dev=[%s]" \
+ "$path" "$devname"
local alert=f_show_msg no_confirm=
f_getvar $VAR_NO_CONFIRM no_confirm
[ "$no_confirm" ] && alert=f_show_info
if [ ! "$found" ]; then
- f_dprintf "%s: No such %s file on %s device" \
- $fname "$path" "$device"
+ f_dprintf "$funcname: No such %s file on %s device" \
+ "$path" "$devname"
$alert "$msg_unable_to_fetch_package_from_selected_media" \
"$name"
[ "$no_confirm" ] && sleep 2
return $FAILURE
fi
- 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"
@@ -1026,27 +1024,14 @@ f_package_extract()
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
- }
+ # Request the package be added via pkg-install(8)
+ if f_debugging; then
+ f_eval_catch $funcname pkg 'pkg -d install -y "%s"' "$name"
+ else
+ f_eval_catch $funcname pkg 'pkg install -y "%s"' "$name"
+ fi
if [ $? -ne $SUCCESS ]; then
- $alert "$msg_pkg_add_apparently_did_not_like_the_package" \
+ $alert "$msg_pkg_install_apparently_did_not_like_the_package" \
"$name"
[ "$no_confirm" ] && sleep 2
else
@@ -1063,8 +1048,8 @@ f_package_extract()
#
f_package_delete()
{
+ local funcname=f_package_delete
local name="$1"
- local fname=f_package_delete
if ! { [ "$name" ] || { f_getvar $VAR_PACKAGE name && [ "$name" ]; }; }
then
@@ -1073,13 +1058,13 @@ f_package_delete()
return $FAILURE
fi
- f_dprintf "%s: name=[%s]" $fname "$name"
+ f_dprintf "$funcname: name=[%s]" "$name"
[ "$name" ] || return $FAILURE
{ # Verify and initialize device media if-defined
f_media_verify &&
- f_device_init media &&
+ f_device_init device_media &&
f_index_initialize packages/INDEX
} || return $FAILURE
@@ -1110,7 +1095,7 @@ f_package_delete()
# detected the installed packages -- something we should do only once.
#
if [ ! "$PACKAGES_DETECTED" ]; then
- f_dprintf "%s: Detecting installed packages" $fname
+ f_dprintf "$funcname: Detecting installed packages"
f_package_detect_installed
export PACKAGES_DETECTED=1 # exported for awk(1) ENVIRON[]
fi
@@ -1162,8 +1147,8 @@ f_package_delete()
# Chase dependencies that are marked for uninstallation
#
for pkgsel in $udeps; do
- f_dprintf "%s: Uninstalling dependecy %s (marked for delete)" \
- $fname "$pkgsel"
+ f_dprintf "$funcname: Uninstalling dependency %s (%s)" \
+ "$pkgsel" "marked for delete"
f_package_delete "$pkgsel"
done
@@ -1172,15 +1157,15 @@ f_package_delete()
#
f_show_info "$msg_uninstalling_package_waiting_for_pkg_delete" "$name"
if f_debugging; then
- pkg_delete -v "$name"
+ f_eval_catch $funcname pkg 'pkg -d delete -y "%s"' "$name"
else
- f_quietly pkg_delete "$name"
+ f_eval_catch $funcname pkg 'pkg delete -y "%s"' "$name"
fi
if [ $? -ne $SUCCESS ]; then
f_show_msg "$msg_pkg_delete_failed" "$name"
return $FAILURE
else
- f_dprintf "%s: pkg_delete(1) of %s successful" $fname "$name"
+ f_dprintf "$funcname: pkg-delete(8) of %s successful" "$name"
f_str2varname "$name" varpkg
setvar _mark_$varpkg ""
fi
diff --git a/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr
index a227419..b562e99 100644
--- a/usr.sbin/bsdconfig/share/script.subr
+++ b/usr.sbin/bsdconfig/share/script.subr
@@ -1,6 +1,6 @@
if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1
#
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,8 @@ f_include $BSDCFG_SHARE/media/tcpip.subr
f_include $BSDCFG_SHARE/mustberoot.subr
f_include $BSDCFG_SHARE/networking/services.subr
f_include $BSDCFG_SHARE/packages/packages.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
f_include $BSDCFG_SHARE/variable.subr
############################################################ GLOBALS
@@ -50,25 +52,23 @@ RESWORDS=
# 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()).
+# 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\; }
+ eval $resword\(\){ f_dispatch $func $resword \"\$@\"\; }
RESWORDS="$RESWORDS${RESWORDS:+ }$resword"
}
-# f_dispatch $func [$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,
@@ -78,9 +78,10 @@ f_resword_new()
#
f_dispatch()
{
- local func="$1" resword="${2:-$1}"
+ local func="$1" resword="$2"
+ shift 2 # func resword
f_dprintf "f_dispatch: calling resword \`%s'" "$resword"
- eval $func
+ eval $func "$@"
local retval=$?
if [ $retval -ne $SUCCESS ]; then
local _ignore_this_error
@@ -96,7 +97,7 @@ f_dispatch()
# Load a script (usually filled with reswords). If $file is missing or NULL,
# use one of the following instead (in order):
#
-# $configFile
+# $configFile (global)
# install.cfg
# /stand/install.fg
# /tmp/install.cfg
@@ -108,9 +109,10 @@ f_dispatch()
#
f_script_load()
{
+ local funcname=f_script_load
local script="$1" config_file retval=$SUCCESS
- f_dprintf "f_script_load: script=[%s]" "$script"
+ f_dprintf "$funcname: script=[%s]" "$script"
if [ ! "$script" ]; then
f_getvar $VAR_CONFIG_FILE config_file
for script in \
@@ -130,11 +132,11 @@ f_script_load()
setvar $VAR_NONINTERACTIVE yes
if [ "$script" = "-" ]; then
- f_dprintf "f_script_load: Loading script from stdin"
+ f_dprintf "$funcname: Loading script from stdin"
eval "$( cat )"
retval=$?
else
- f_dprintf "f_script_load: Loading script \`%s'" "$script"
+ f_dprintf "$funcname: Loading script \`%s'" "$script"
if [ ! -e "$script" ]; then
f_show_msg "$msg_unable_to_open" "$script"
return $FAILURE
@@ -198,6 +200,16 @@ f_resword_new packageAdd f_package_add
f_resword_new packageDelete f_package_delete
f_resword_new packageReinstall f_package_reinstall
+# usermgmt/group.subr
+f_resword_new addGroup f_group_add
+f_resword_new deleteGroup f_group_delete
+f_resword_new editGroup f_group_edit
+
+# usermgmt/user.subr
+f_resword_new addUser f_user_add
+f_resword_new deleteUser f_user_delete
+f_resword_new editUser f_user_edit
+
# variable.subr
f_resword_new installVarDefaults f_variable_set_defaults
f_resword_new dumpVariables f_dump_variables
diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr
index 0a77048..487e061 100644
--- a/usr.sbin/bsdconfig/share/strings.subr
+++ b/usr.sbin/bsdconfig/share/strings.subr
@@ -26,9 +26,20 @@ if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1
#
# $FreeBSD$
#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
############################################################ GLOBALS
#
+# A Literal newline (for use with f_replace_all(), or IFS, or whatever)
+#
+NL="
+" # END-QUOTE
+
+#
# Valid characters that can appear in an sh(1) variable name
#
# Please note that the character ranges A-Z and a-z should be avoided because
@@ -41,7 +52,7 @@ VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
############################################################ FUNCTIONS
-# f_substr "$string" $start [ $length ]
+# f_substr "$string" $start [$length]
#
# Simple wrapper to awk(1)'s `substr' function.
#
@@ -51,17 +62,18 @@ f_substr()
echo "$string" | awk "{ print substr(\$0, $start, $len) }"
}
-# f_snprintf $var_to_set $size $format ...
+# f_snprintf $var_to_set $size $format [$arguments ...]
#
# Similar to snprintf(3), write at most $size number of bytes into $var_to_set
-# using printf(1) syntax (`$format ...'). The value of $var_to_set is NULL
-# unless at-least one byte is stored from the output.
+# using printf(1) syntax (`$format [$arguments ...]'). 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\" \''
+ shift 2 # var_to_set size
+ eval "$__var_to_set"=\$\( printf -- \"\$@\" \| \
+ awk -v max=\"\$__size\" \''
{
len = length($0)
max -= len
@@ -71,6 +83,18 @@ f_snprintf()
}'\' \)
}
+# f_sprintf $var_to_set $format [$arguments ...]
+#
+# Similar to sprintf(3), write a string into $var_to_set using printf(1) syntax
+# (`$format [$arguments ...]').
+#
+f_sprintf()
+{
+ local __var_to_set="$1"
+ shift 1 # var_to_set
+ eval "$__var_to_set"=\$\( printf -- \"\$@\" \)
+}
+
# f_vsnprintf $var_to_set $size $format $format_args
#
# Similar to vsnprintf(3), write at most $size number of bytes into $var_to_set
@@ -106,6 +130,16 @@ f_vsnprintf()
eval f_snprintf \"\$1\" \"\$2\" \"\$3\" $4
}
+# f_vsprintf $var_to_set $format $format_args
+#
+# Similar to vsprintf(3), write a string into $var_to_set using printf(1)
+# syntax (`$format $format_args').
+#
+f_vsprintf()
+{
+ eval f_sprintf \"\$1\" \"\$2\" $3
+}
+
# f_longest_line_length
#
# Simple wrapper to an awk(1) script to print the length of the longest line of
@@ -160,15 +194,8 @@ f_number_of_lines()
#
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
+ local arg="${1#-}"
+ [ "${arg:-x}" = "${arg%[!0-9]*}" ]
}
# f_uriencode [$text]
@@ -244,6 +271,9 @@ f_uridecode()
# capturing in a sub-shell (which is less recommended due to performance
# degradation).
#
+# To replace newlines or a sequence containing the newline character, use $NL
+# as `\n' is not supported.
+#
f_replaceall()
{
local __left="" __right="$1"
@@ -319,6 +349,104 @@ f_shell_unescape()
f_replaceall "$__string" "'\\''" "'" "$__var_to_set"
}
+# f_expand_number $string [$var_to_set]
+#
+# Unformat $string into a number, optionally to be stored in $var_to_set. This
+# function follows the SI power of two convention.
+#
+# The prefixes are:
+#
+# Prefix Description Multiplier
+# k kilo 1024
+# M mega 1048576
+# G giga 1073741824
+# T tera 1099511627776
+# P peta 1125899906842624
+# E exa 1152921504606846976
+#
+# NOTE: Prefixes are case-insensitive.
+#
+# Upon successful completion, success status is returned; otherwise the number
+# -1 is produced ($var_to_set set to -1 or if $var_to_set is NULL or missing)
+# on standard output. In the case of failure, the error status will be one of:
+#
+# Status Reason
+# 1 Given $string contains no digits
+# 2 An unrecognized prefix was given
+# 3 Result too large to calculate
+#
+f_expand_number()
+{
+ local __string="$1" __var_to_set="$2"
+ local __cp __num __bshift __maxinput
+
+ # Remove any leading non-digits
+ __string="${__string#${__string%%[0-9]*}}"
+
+ # Store the numbers (no trailing suffix)
+ __num="${__string%%[!0-9]*}"
+
+ # Produce `-1' if string didn't contain any digits
+ if [ ! "$__num" ]; then
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" -1
+ else
+ echo -1
+ fi
+ return 1 # 1 = "Given $string contains no digits"
+ fi
+
+ # Remove all the leading numbers from the string to get at the prefix
+ __string="${__string#"$__num"}"
+
+ #
+ # Test for invalid prefix (and determine bitshift length)
+ #
+ case "$__string" in
+ ""|[[:space:]]*) # Shortcut
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__num
+ else
+ echo $__num
+ fi
+ return $SUCCESS ;;
+ [Kk]*) __bshift=10 ;;
+ [Mm]*) __bshift=20 ;;
+ [Gg]*) __bshift=30 ;;
+ [Tt]*) __bshift=40 ;;
+ [Pp]*) __bshift=50 ;;
+ [Ee]*) __bshift=60 ;;
+ *)
+ # Unknown prefix
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" -1
+ else
+ echo -1
+ fi
+ return 2 # 2 = "An unrecognized prefix was given"
+ esac
+
+ # Determine if the wheels fall off
+ __maxinput=$(( 0x7fffffffffffffff >> $__bshift ))
+ if [ $__num -gt $__maxinput ]; then
+ # Input (before expanding) would exceed 64-bit signed int
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" -1
+ else
+ echo -1
+ fi
+ return 3 # 3 = "Result too large to calculate"
+ fi
+
+ # Shift the number out and produce it
+ __num=$(( $__num << $__bshift ))
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__num
+ else
+ echo $__num
+ fi
+}
+
############################################################ MAIN
f_dprintf "%s: Successfully loaded." strings.subr
diff --git a/usr.sbin/bsdconfig/share/struct.subr b/usr.sbin/bsdconfig/share/struct.subr
index fc4f711..78c785f 100644
--- a/usr.sbin/bsdconfig/share/struct.subr
+++ b/usr.sbin/bsdconfig/share/struct.subr
@@ -132,7 +132,7 @@ f_struct()
local __name="$1" __action="$2" __property="$3"
case $# in
0) return $FAILURE ;;
- 1) f_have $__name ;;
+ 1) f_have "$__name" ;;
*) case "$__action" in
get) local __var_to_set="$4"
f_getvar "_struct_value_${__name}_$__property" "$__var_to_set"
diff --git a/usr.sbin/bsdconfig/share/sysrc.subr b/usr.sbin/bsdconfig/share/sysrc.subr
index 66a4cf3..d863ba0 100644
--- a/usr.sbin/bsdconfig/share/sysrc.subr
+++ b/usr.sbin/bsdconfig/share/sysrc.subr
@@ -118,8 +118,8 @@ f_clean_env()
# 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).
+# configuration files (in order: /etc/defaults/rc.conf /etc/rc.conf and
+# /etc/rc.conf.local)
#
# NOTE: Additional shell parameter-expansion formats are supported. For
# example, passing an argument of "hostname%%.*" (properly quoted) will
@@ -428,6 +428,7 @@ END { exit retval }
'
f_sysrc_set()
{
+ local funcname=f_sysrc_set
local varname="$1" new_value="$2"
# Check arguments
@@ -478,8 +479,12 @@ f_sysrc_set()
#
# Create a new temporary file to write to.
#
- local tmpfile="$( mktemp -t "$pgm" )"
- [ "$tmpfile" ] || return $FAILURE
+ local tmpfile
+ if ! f_eval_catch -dk tmpfile $funcname mktemp 'mktemp -t "%s"' "$pgm"
+ then
+ echo "$tmpfile" >&2
+ return $FAILURE
+ fi
#
# Fixup permissions (else we're in for a surprise, as mktemp(1) creates
@@ -488,8 +493,9 @@ f_sysrc_set()
# permissions from the temporary file).
#
local mode
- mode=$( stat -f '%#Lp' "$file" 2> /dev/null )
- f_quietly chmod "${mode:-0644}" "$tmpfile"
+ f_eval_catch -dk mode $funcname stat 'stat -f "%%#Lp" "%s"' "$file" ||
+ mode=0644
+ f_eval_catch -d $funcname chmod 'chmod "%s" "%s"' "$mode" "$tmpfile"
#
# Fixup ownership. The destination file _is_ writable (we tested
@@ -497,8 +503,9 @@ f_sysrc_set()
# 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"
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel"
+ f_eval_catch -d $funcname chown 'chown "%s" "%s"' "$owner" "$tmpfile"
#
# Operate on the matching file, replacing only the last occurrence.
@@ -520,7 +527,7 @@ f_sysrc_set()
#
# Taint-check our results.
#
- if ! /bin/sh -n "$tmpfile"; then
+ if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"; then
f_err "$msg_previous_syntax_errors\n" "$pgm" "$file"
rm -f "$tmpfile"
return $FAILURE
@@ -529,7 +536,7 @@ f_sysrc_set()
#
# Finally, move the temporary file into place.
#
- mv "$tmpfile" "$file"
+ f_eval_catch -de $funcname mv 'mv "%s" "%s"' "$tmpfile" "$file"
}
# f_sysrc_delete $varname
@@ -560,6 +567,7 @@ END { exit ! found }
'
f_sysrc_delete()
{
+ local funcname=f_sysrc_delete
local varname="$1"
local file
@@ -569,24 +577,33 @@ f_sysrc_delete()
#
# Operate on each of the specified files
#
+ local tmpfile
for file in ${RC_CONFS-$( f_sysrc_get rc_conf_files )}; do
[ -e "$file" ] || continue
#
# Create a new temporary file to write to.
#
- local tmpfile="$( mktemp -t "$pgm" )"
- [ "$tmpfile" ] || return $FAILURE
+ if ! f_eval_catch -dk tmpfile $funcname mktemp \
+ 'mktemp -t "%s"' "$pgm"
+ then
+ echo "$tmpfile" >&2
+ return $FAILURE
+ fi
#
# Fixup permissions and ownership (mktemp(1) defaults to 0600
# permissions) to instead match the destination file.
#
local mode owner
- 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"
+ f_eval_catch -dk mode $funcname stat \
+ 'stat -f "%%#Lp" "%s"' "$file" || mode=0644
+ f_eval_catch -dk owner $funcname stat \
+ 'stat -f "%%u:%%g" "%s"' "$file" || owner="root:wheel"
+ f_eval_catch -d $funcname chmod \
+ 'chmod "%s" "%s"' "$mode" "$tmpfile"
+ f_eval_catch -d $funcname chown \
+ 'chown "%s" "%s"' "$owner" "$tmpfile"
#
# Operate on the file, removing all occurrences, saving the
@@ -603,7 +620,8 @@ f_sysrc_delete()
#
# Taint-check our results.
#
- if ! /bin/sh -n "$tmpfile"; then
+ if ! f_eval_catch -d $funcname sh '/bin/sh -n "%s"' "$tmpfile"
+ then
f_err "$msg_previous_syntax_errors\n" \
"$pgm" "$file"
rm -f "$tmpfile"
@@ -622,7 +640,8 @@ f_sysrc_delete()
#
# Finally, move the temporary file into place.
#
- mv "$tmpfile" "$file"
+ f_eval_catch -de $funcname mv \
+ 'mv "%s" "%s"' "$tmpfile" "$file" || return $FAILURE
done
}
diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr
index 86523d6..c453f67 100644
--- a/usr.sbin/bsdconfig/share/variable.subr
+++ b/usr.sbin/bsdconfig/share/variable.subr
@@ -1,6 +1,6 @@
if [ ! "$_VARIABLE_SUBR" ]; then _VARIABLE_SUBR=1
#
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -179,7 +179,7 @@ f_debugging()
f_getvar $VAR_DEBUG value && [ "$value" ]
}
-# f_interactive()
+# f_interactive
#
# Are we running interactively? Return error if $nonInteractive is set and non-
# NULL, otherwise return success.
@@ -190,7 +190,7 @@ f_interactive()
! f_getvar $VAR_NONINTERACTIVE value || [ ! "$value" ]
}
-# f_netinteractive()
+# 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
@@ -205,6 +205,21 @@ f_netinteractive()
f_getvar $VAR_NETINTERACTIVE value && [ "$value" ]
}
+# f_zfsinteractive
+#
+# Has the user specifically requested the ZFS-portion of configuration and
+# setup to be performed interactively? Returns success if the user has asked
+# for the ZFS configuration to be done interactively even if perhaps overall
+# non-interactive mode has been requested (by setting nonInteractive).
+#
+# Returns success if $zfsInteractive is set and non-NULL.
+#
+f_zfsinteractive()
+{
+ local value
+ f_getvar $VAR_ZFSINTERACTIVE value && [ "$value" ]
+}
+
############################################################ MAIN
#
@@ -226,6 +241,10 @@ f_variable_new VAR_FTP_PORT ftpPort
f_variable_new VAR_FTP_STATE ftpState
f_variable_new VAR_FTP_USER ftpUser
f_variable_new VAR_GATEWAY defaultrouter
+f_variable_new VAR_GROUP group
+f_variable_new VAR_GROUP_GID groupGid
+f_variable_new VAR_GROUP_MEMBERS groupMembers
+f_variable_new VAR_GROUP_PASSWORD groupPassword
f_variable_new VAR_HOSTNAME hostname
f_variable_new VAR_HTTP_DIR httpDirectory
f_variable_new VAR_HTTP_FTP_MODE httpFtpMode
@@ -240,6 +259,7 @@ f_variable_new VAR_IFCONFIG ifconfig_
f_variable_new VAR_IPADDR ipaddr
f_variable_new VAR_IPV6ADDR ipv6addr
f_variable_new VAR_IPV6_ENABLE ipv6_activate_all_interfaces
+f_variable_new VAR_KEYMAP keymap
f_variable_new VAR_MEDIA_TIMEOUT MEDIA_TIMEOUT
f_variable_new VAR_MEDIA_TYPE mediaType
f_variable_new VAR_NAMESERVER nameserver
@@ -263,6 +283,22 @@ f_variable_new VAR_SLOW_ETHER slowEthernetCard
f_variable_new VAR_TRY_DHCP tryDHCP
f_variable_new VAR_TRY_RTSOL tryRTSOL
f_variable_new VAR_UFS_PATH ufs
+f_variable_new VAR_USER user
+f_variable_new VAR_USER_ACCOUNT_EXPIRE userAccountExpire
+f_variable_new VAR_USER_DOTFILES_CREATE userDotfilesCreate
+f_variable_new VAR_USER_GECOS userGecos
+f_variable_new VAR_USER_GID userGid
+f_variable_new VAR_USER_GROUPS userGroups
+f_variable_new VAR_USER_GROUP_DELETE userGroupDelete
+f_variable_new VAR_USER_HOME userHome
+f_variable_new VAR_USER_HOME_CREATE userHomeCreate
+f_variable_new VAR_USER_HOME_DELETE userHomeDelete
+f_variable_new VAR_USER_LOGIN_CLASS userLoginClass
+f_variable_new VAR_USER_PASSWORD userPassword
+f_variable_new VAR_USER_PASSWORD_EXPIRE userPasswordExpire
+f_variable_new VAR_USER_SHELL userShell
+f_variable_new VAR_USER_UID userUid
+f_variable_new VAR_ZFSINTERACTIVE zfsInteractive
#
# Self-initialize unless requested otherwise
diff --git a/usr.sbin/bsdconfig/startup/include/messages.subr b/usr.sbin/bsdconfig/startup/include/messages.subr
index 87bde26..78daa8a 100644
--- a/usr.sbin/bsdconfig/startup/include/messages.subr
+++ b/usr.sbin/bsdconfig/startup/include/messages.subr
@@ -39,8 +39,8 @@ 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_are_you_sure_you_want_to_delete="Are you sure you want to delete the \`%s' directive\nfrom the rc.conf(5) collection of system configuration files?"
msg_cancel="Cancel"
msg_choose_view_details="Choose View Details"
msg_creating_menu_list="Creating menu list...\nThis may take a while."
@@ -67,8 +67,8 @@ 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_miscellaneous_startup_services="Miscellaneous Startup Services"
msg_named="named"
msg_named_desc="Run a local name server on this host"
msg_named_flags="named flags"
diff --git a/usr.sbin/bsdconfig/startup/misc b/usr.sbin/bsdconfig/startup/misc
index 738f730..a792daf 100755
--- a/usr.sbin/bsdconfig/startup/misc
+++ b/usr.sbin/bsdconfig/startup/misc
@@ -38,15 +38,8 @@ 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)
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
@@ -346,87 +339,61 @@ while :; do
case "$mtag" in
"X $msg_exit") break ;;
- ?" [X] "*) toggled=1 ;;
- *) toggled=
+ ?" [X] "*) toggled=1 reverse=NO ;;
+ *) toggled= reverse=YES
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
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set apm_enable "%s"' "$reverse" ;;
?" ["?"] $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
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set named_enable "%s"' "$reverse" ;;
?" ["?"] $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
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set accounting_enable "%s"' "$reverse" ;;
?" ["?"] $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
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set lpd_enable "%s"' "$reverse" ;;
?" ["?"] $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
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set ibcs2_enable "%s"' "$reverse" ;;
?" ["?"] $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
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set svr4_enable "%s"' "$reverse" ;;
# 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
- ;;
+ if f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set nis_client_enable "%s"' "$reverse"
+ then
+ [ "$reverse" = "NO" ] || f_eval_catch -dk err "$0" \
+ f_sysrc_set 'f_sysrc_set rpcbind_enable YES'
+ fi ;;
?" ["?"] $msg_nis_server")
- if [ "$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
- ;;
+ if f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set nis_server_enable "%s"' "$reverse"
+ then
+ [ "$reverse" = "NO" ] || f_eval_catch -dk err "$0" \
+ f_sysrc_set 'f_sysrc_set rpcbind_enable YES'
+ fi ;;
# Checkboxes for non-boolean options
?" ["?"] $msg_nis_domainname")
dialog_input_value "$msg_nis_domainname_desc" \
"$( f_sysrc_get nisdomainname )" || continue
- err=$( f_sysrc_set nisdomainname "$value" 2>&1 )
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set nisdomainname "%s"' "$value" ;;
?" ["?"] $msg_startup_dirs")
dialog_input_value "$msg_startup_dirs_desc" \
"$( f_sysrc_get local_startup )" || continue
- err=$( f_sysrc_set local_startup "$value" 2>&1 )
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set local_startup "%s"' "$value" ;;
?" ["?"] $msg_named_flags")
dialog_input_value "$msg_named_flags_desc" \
"$( f_sysrc_get named_flags )" || continue
- err=$( f_sysrc_set named_flags "$value" 2>&1 )
- ;;
+ f_eval_catch -dk err "$0" f_sysrc_set \
+ 'f_sysrc_set named_flags "%s"' "$value" ;;
esac
[ $? -eq $DIALOG_OK ] || f_dialog_msgbox "$err\n"
diff --git a/usr.sbin/bsdconfig/startup/rcadd b/usr.sbin/bsdconfig/startup/rcadd
index 9fd3bdd..7b536c2 100755
--- a/usr.sbin/bsdconfig/startup/rcadd
+++ b/usr.sbin/bsdconfig/startup/rcadd
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ GLOBALS
diff --git a/usr.sbin/bsdconfig/startup/rcconf b/usr.sbin/bsdconfig/startup/rcconf
index 6154d27..6a6247b 100755
--- a/usr.sbin/bsdconfig/startup/rcconf
+++ b/usr.sbin/bsdconfig/startup/rcconf
@@ -39,8 +39,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ GLOBALS
diff --git a/usr.sbin/bsdconfig/startup/rcdelete b/usr.sbin/bsdconfig/startup/rcdelete
index 5769be9..ccc15ba 100755
--- a/usr.sbin/bsdconfig/startup/rcdelete
+++ b/usr.sbin/bsdconfig/startup/rcdelete
@@ -39,8 +39,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ GLOBALS
@@ -364,18 +364,17 @@ while :; do
"> $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"
+ f_getvar _${var}_delete _delete
+ [ "$_delete" ] || continue
+ delete_vars="$delete_vars $var"
done
if dialog_menu_confirm_delete $delete_vars; then
f_dialog_title "$msg_info"
f_dialog_info "$msg_deleting_selected_directives"
f_dialog_title_restore
for var in $delete_vars; do
- if ! err=$( f_sysrc_delete $var 2>&1 ); then
- f_dialog_msgbox "$err\n"
- break
- fi
+ f_eval_catch "$0" f_sysrc_delete \
+ 'f_sysrc_delete "%s"' "$var" || break
done
dialog_create_main
fi
diff --git a/usr.sbin/bsdconfig/startup/rcedit b/usr.sbin/bsdconfig/startup/rcedit
index de7f321..54061b5 100755
--- a/usr.sbin/bsdconfig/startup/rcedit
+++ b/usr.sbin/bsdconfig/startup/rcedit
@@ -38,8 +38,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/startup/rcvar b/usr.sbin/bsdconfig/startup/rcvar
index e206ed4..ddca906 100755
--- a/usr.sbin/bsdconfig/startup/rcvar
+++ b/usr.sbin/bsdconfig/startup/rcvar
@@ -39,8 +39,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ GLOBALS
@@ -210,7 +210,7 @@ while :; do
*) value="YES"
esac
- err=$( f_sysrc_set "$rcvar" "$value" 2>&1 ) || f_dialog_msgbox "$err"
+ f_eval_catch "$0" f_sysrc_set 'f_sysrc_set "%s" "%s"' "$rcvar" "$value"
done
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/startup/share/rcconf.subr b/usr.sbin/bsdconfig/startup/share/rcconf.subr
index f8f9a66..38b4cc8 100644
--- a/usr.sbin/bsdconfig/startup/share/rcconf.subr
+++ b/usr.sbin/bsdconfig/startup/share/rcconf.subr
@@ -106,6 +106,7 @@ f_startup_rcconf_list()
#
f_startup_rcconf_map()
{
+ local __funcname=f_startup_rcconf_map
local __var_to_set="$1"
# If the in-memory cached value is available, return it immediately
@@ -119,7 +120,7 @@ f_startup_rcconf_map()
fi
#
- # create the in-memory cache (potentially from validated on-disk cache)
+ # Create the in-memory cache (potentially from validated on-disk cache)
#
#
@@ -128,7 +129,7 @@ f_startup_rcconf_map()
# can be used to quickly populate the cache value for immediate return.
#
local __rc_defaults_digest
- __rc_defaults_digest=$( md5 < "$RC_DEFAULTS" )
+ __rc_defaults_digest=$( exec 2> /dev/null; md5 < "$RC_DEFAULTS" )
#
# Check to see if the global persistant cache file exists
@@ -140,7 +141,7 @@ f_startup_rcconf_map()
# the current value and provide error exit status.
#
STARTUP_RCCONF_MAP=$(
- ( # Get digest as the first word on the first line
+ ( # Get digest as the first word on first line
read digest rest_ignored
#
@@ -218,8 +219,9 @@ f_startup_rcconf_map()
#
# Create a new temporary file to write to
- local __tmpfile="$( mktemp -t "$pgm" )"
- [ "$__tmpfile" ] || return $FAILURE
+ local __tmpfile
+ f_eval_catch -dk __tmpfile $__funcname mktemp \
+ 'mktemp -t "%s"' "$pgm" || return $FAILURE
# Write the temporary file contents
echo "$__rc_defaults_digest" > "$__tmpfile"
@@ -227,9 +229,11 @@ f_startup_rcconf_map()
# Finally, move the temporary file into place
case "$STARTUP_RCCONF_MAP_CACHEFILE" in
- */*) f_quietly mkdir -p "${STARTUP_RCCONF_MAP_CACHEFILE%/*}"
+ */*) f_eval_catch -d $__funcname mkdir \
+ 'mkdir -p "%s"' "${STARTUP_RCCONF_MAP_CACHEFILE%/*}"
esac
- mv "$__tmpfile" "$STARTUP_RCCONF_MAP_CACHEFILE"
+ f_eval_catch -d $__funcname mv \
+ 'mv "%s" "%s"' "$__tmpfile" "$STARTUP_RCCONF_MAP_CACHEFILE"
}
# f_startup_rcconf_map_expand $var_to_get
@@ -243,7 +247,7 @@ f_startup_rcconf_map()
f_startup_rcconf_map_expand()
{
local var_to_get="$1"
- eval "$( f_getvar "$var_to_get" | awk '
+ eval "$( debug= f_getvar "$var_to_get" | awk '
BEGIN {
rword = "^[[:space:]]*[^[:space:]]*[[:space:]]*"
}
diff --git a/usr.sbin/bsdconfig/startup/share/rcedit.subr b/usr.sbin/bsdconfig/startup/share/rcedit.subr
index fe0989d..1adca47 100644
--- a/usr.sbin/bsdconfig/startup/share/rcedit.subr
+++ b/usr.sbin/bsdconfig/startup/share/rcedit.subr
@@ -32,6 +32,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." startup/rcedit.subr
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
f_include $BSDCFG_SHARE/sysrc.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="140.startup"
@@ -54,10 +55,11 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
#
f_dialog_rcedit()
{
+ local funcname=f_dialog_rcedit
local msg var="$1" _input
- msg=$( printf "$msg_please_enter_a_new_value" \
- "$var" "$( f_sysrc_get_default "$var" )" )
+ f_sprintf msg "$msg_please_enter_a_new_value" \
+ "$var" "$( f_sysrc_get_default "$var" )"
shift 1 # var
if [ "$1" ]; then
@@ -77,7 +79,8 @@ f_dialog_rcedit()
f_dprintf "%s: [%s]->[%s]" "$var" "$cur_val" "$_input"
- err=$( f_sysrc_set "$var" "$_input" 2>&1 ) || f_dialog_msgbox "$err"
+ f_eval_catch $funcname f_sysrc_set \
+ 'f_sysrc_set "%s" "%s"' "$var" "$_input"
}
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/startup/share/rcvar.subr b/usr.sbin/bsdconfig/startup/share/rcvar.subr
index 0986895..c5a7885 100644
--- a/usr.sbin/bsdconfig/startup/share/rcvar.subr
+++ b/usr.sbin/bsdconfig/startup/share/rcvar.subr
@@ -85,6 +85,7 @@ STARTUP_RCVAR_MAP_CACHEFILE="/var/run/bsdconfig/startup_rcvar_map.cache"
#
f_startup_rcvar_map()
{
+ local __funcname=f_startup_rcvar_map
local __var_to_set="$1"
# If the in-memory cached value is available, return it immediately
@@ -125,8 +126,8 @@ f_startup_rcvar_map()
# value for immediate return.
#
local __rc_script_list_digest
- __rc_script_list_digest=$( cd "$ETC_RC_D" &&
- cksum "$RC_DEFAULTS" $__rc_script_list | md5 )
+ __rc_script_list_digest=$( cd "$ETC_RC_D" 2> /dev/null &&
+ cksum "$RC_DEFAULTS" $__rc_script_list 2> /dev/null | md5 )
#
# Check to see if the global persistant cache file exists
@@ -179,7 +180,7 @@ f_startup_rcvar_map()
STARTUP_RCVAR_MAP=$(
for script in $__rc_script_list; do
- rcvar_list=$( $script rcvar | awk -F= \
+ rcvar_list=$( $script rcvar 2> /dev/null | awk -F= \
-v script="$script" '
/^'"$STARTUP_RCVAR_REGEX"'/ {
if ( $2 ~ /^"[Yy][Ee][Ss]"$/ )
@@ -211,8 +212,9 @@ f_startup_rcvar_map()
#
# Create a new temporary file to write to
- local __tmpfile="$( mktemp -t "$pgm" )"
- [ "$__tmpfile" ] || return $FAILURE
+ local __tmpfile
+ f_eval_catch -dk __tmpfile $__funcname mktemp \
+ 'mktemp -t "%s"' "$__tmpfile" || return $FAILURE
# Write the temporary file contents
echo "$__rc_script_list_digest" > "$__tmpfile"
@@ -220,9 +222,11 @@ f_startup_rcvar_map()
# Finally, move the temporary file into place
case "$STARTUP_RCVAR_MAP_CACHEFILE" in
- */*) f_quietly mkdir -p "${STARTUP_RCVAR_MAP_CACHEFILE%/*}"
+ */*) f_eval_catch -d $__funcname mkdir \
+ 'mkdir -p "%s"' "${STARTUP_RCVAR_MAP_CACHEFILE%/*}"
esac
- mv "$__tmpfile" "$STARTUP_RCVAR_MAP_CACHEFILE"
+ f_eval_catch -d $__funcname mv \
+ 'mv "%s" "%s"' "$__tmpfile" "$STARTUP_RCVAR_MAP_CACHEFILE"
}
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/startup/startup b/usr.sbin/bsdconfig/startup/startup
index 6b02cb4..17755d1 100755
--- a/usr.sbin/bsdconfig/startup/startup
+++ b/usr.sbin/bsdconfig/startup/startup
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
diff --git a/usr.sbin/bsdconfig/timezone/share/menus.subr b/usr.sbin/bsdconfig/timezone/share/menus.subr
index 2028bf3..ef3979b 100644
--- a/usr.sbin/bsdconfig/timezone/share/menus.subr
+++ b/usr.sbin/bsdconfig/timezone/share/menus.subr
@@ -104,7 +104,7 @@ f_make_menus_awk='
function add_zone_n_to_country_menu(tlc, n)
{
zone_title = ENVIRON["country_" tlc "_descr_" n]
- gsub(/'\''/, "'\''\\'\'''\''", zone_title)
+ gsub(/'\''/, "'\''\\'\'\''", zone_title)
country_menu_list[tlc] = country_menu_list[tlc] \
( length(country_menu_list[tlc]) > 0 ? "\n" : "" ) \
n " '\''" zone_title "'\''"
@@ -121,7 +121,7 @@ BEGIN {
{
tlc = countries[cp]
title = ENVIRON["country_" tlc "_name"]
- gsub(/'\''/, "'\''\\'\'''\''", title)
+ gsub(/'\''/, "'\''\\'\'\''", title)
nzones = ENVIRON["country_" tlc "_nzones"]
if (!nzones)
{
diff --git a/usr.sbin/bsdconfig/timezone/share/zones.subr b/usr.sbin/bsdconfig/timezone/share/zones.subr
index b356323..59a9330 100644
--- a/usr.sbin/bsdconfig/timezone/share/zones.subr
+++ b/usr.sbin/bsdconfig/timezone/share/zones.subr
@@ -32,6 +32,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." timezone/zones.subr
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
f_include $BSDCFG_SHARE/timezone/continents.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="090.timezone"
@@ -347,8 +348,9 @@ f_read_zones()
#
f_install_zoneinfo_file()
{
+ local funcname=f_install_zoneinfo_file
local zoneinfo_file="$1"
- local copymode title msg err height width
+ local copymode title msg height width
if [ -L "$_PATH_LOCALTIME" ]; then
copymode=
@@ -361,13 +363,13 @@ f_install_zoneinfo_file()
if [ "$VERBOSE" ]; then
if [ ! "$zoneinfo_file" ]; then
- msg=$( printf "$msg_removing_file" "$_PATH_LOCALTIME" )
+ f_sprintf msg "$msg_removing_file" "$_PATH_LOCALTIME"
elif [ "$copymode" ]; then
- msg=$( printf "$msg_copying_file" \
- "$zoneinfo_file" "$_PATH_LOCALTIME" )
+ f_sprintf msg "$msg_copying_file" \
+ "$zoneinfo_file" "$_PATH_LOCALTIME"
else
- msg=$( printf "$msg_creating_symlink" \
- "$_PATH_LOCALTIME" "$zoneinfo_file" )
+ f_sprintf msg "$msg_creating_symlink" \
+ "$_PATH_LOCALTIME" "$zoneinfo_file"
fi
if [ "$USEDIALOG" ]; then
f_dialog_title "$msg_info"
@@ -380,33 +382,17 @@ f_install_zoneinfo_file()
[ "$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
+ local catch_args="-de"
+ [ "$USEDIALOG" ] && catch_args=
- 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 [ ! "$zoneinfo_file" ]; then
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_DB" || return $FAILURE
if [ "$VERBOSE" ]; then
- msg=$( printf "$msg_removed_file" "$_PATH_LOCALTIME" )
+ f_sprintf msg "$msg_removed_file" "$_PATH_LOCALTIME"
if [ "$USEDIALOG" ]; then
f_dialog_title "$msg_done"
f_dialog_msgbox "$msg"
@@ -415,96 +401,35 @@ f_install_zoneinfo_file()
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
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname sh \
+ 'umask 222 && :> "%s"' "$_PATH_LOCALTIME" ||
return $FAILURE
- 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
-
+ f_eval_catch $catch_args $funcname sh \
+ 'cat "%s" > "%s"' \
+ "$zoneinfo_file" "$_PATH_LOCALTIME" || return $FAILURE
+ else
+ f_eval_catch $catch_args $funcname sh \
+ '( :< "%s" )' "$zoneinfo_file" || return $FAILURE
+ f_eval_catch $catch_args $funcname rm \
+ 'rm -f "%s"' "$_PATH_LOCALTIME" || return $FAILURE
+ f_eval_catch $catch_args $funcname ln \
+ 'ln -s "%s" "%s"' \
+ "$zoneinfo_file" "$_PATH_LOCALTIME" || return $FAILURE
fi # copymode
if [ "$VERBOSE" ]; then
if [ "$copymode" ]; then
- msg=$( printf "$msg_copied_timezone_file" \
- "$zoneinfo_file" "$_PATH_LOCALTIME" )
+ f_sprintf msg "$msg_copied_timezone_file" \
+ "$zoneinfo_file" "$_PATH_LOCALTIME"
else
- msg=$( printf "$msg_created_symlink" \
- "$_PATH_LOCALTIME" "$zoneinfo_file" )
+ f_sprintf msg "$msg_created_symlink" \
+ "$_PATH_LOCALTIME" "$zoneinfo_file"
fi
if [ "$USEDIALOG" ]; then
f_dialog_title "$msg_done"
@@ -559,16 +484,17 @@ f_confirm_zone()
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 prompt # Calculated below
local height=5 width=72
+ f_sprintf prompt "$msg_look_reasonable" "$tm_zone"
if [ "$USE_XDIALOG" ]; then
height=$(( $height + 4 ))
$DIALOG \
- --title "$title" \
- --backtitle "$btitle" \
- --ok-label "$msg_yes" \
- --cancel-label "$msg_no" \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --ok-label "$msg_yes" \
+ --cancel-label "$msg_no" \
--yesno "$prompt" $height $width
else
$DIALOG \
diff --git a/usr.sbin/bsdconfig/timezone/timezone b/usr.sbin/bsdconfig/timezone/timezone
index d4b7ab5..0452230 100755
--- a/usr.sbin/bsdconfig/timezone/timezone
+++ b/usr.sbin/bsdconfig/timezone/timezone
@@ -43,8 +43,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
@@ -164,7 +164,7 @@ fi
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_eval_catch -dk zoneinfo "$0" cat 'cat "%s"' "$_PATH_DB" ||
f_die 1 "$msg_error_reading" "$_PATH_DB"
[ "$zoneinfo" ] ||
f_die 1 "$msg_unable_to_determine_name_from_db" "$_PATH_DB"
@@ -244,7 +244,7 @@ if [ $# -ge 1 ]; then
default="$1"
f_dialog_title "$msg_default_zone_provided"
- msg=$( printf "\n$msg_use_default_zone" "$default" )
+ f_sprintf msg "\n$msg_use_default_zone" "$default"
hline=
f_dialog_yesno "$msg" "$hline"
result=$?
@@ -322,16 +322,16 @@ while :; do
# It's amazing how much good grammar really matters...
#
if [ ! "$isocean" ]; then
- title=$( printf "$msg_country_title" \
- "$cont_title" )
+ f_sprintf title "$msg_country_title" \
+ "$cont_title"
f_dialog_title "$title"
title="$DIALOG_TITLE"
btitle="$DIALOG_BACKTITLE"
f_dialog_title_restore
prompt="$msg_select_country"
else
- title=$( printf "$msg_island_and_group_title" \
- "$cont_title" )
+ f_sprintf title "$msg_island_and_group_title" \
+ "$cont_title"
f_dialog_title "$title"
title="$DIALOG_TITLE"
btitle="$DIALOG_BACKTITLE"
@@ -397,11 +397,10 @@ while :; do
continue
fi
else
- title=$( printf "$msg_country_time_zones" \
- "$( f_country $tlc name )" )
+ f_sprintf title "$msg_country_time_zones" \
+ "$( f_country $tlc name )"
f_dialog_title "$title"
- title="$DIALOG_TITLE"
- btitle="$DIALOG_BACKTITLE"
+ title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
f_dialog_title_restore
prompt="$msg_select_zone"
menu_list=$( f_country $tlc menu_list )
diff --git a/usr.sbin/bsdconfig/ttys/ttys b/usr.sbin/bsdconfig/ttys/ttys
index 999ce76..ed7ba75 100755
--- a/usr.sbin/bsdconfig/ttys/ttys
+++ b/usr.sbin/bsdconfig/ttys/ttys
@@ -37,8 +37,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ CONFIGURATION
diff --git a/usr.sbin/bsdconfig/usermgmt/Makefile b/usr.sbin/bsdconfig/usermgmt/Makefile
index 910d380..5211c3c 100644
--- a/usr.sbin/bsdconfig/usermgmt/Makefile
+++ b/usr.sbin/bsdconfig/usermgmt/Makefile
@@ -8,8 +8,7 @@ FILESDIR= ${LIBEXECDIR}/bsdconfig/070.usermgmt
FILES= INDEX USAGE
SCRIPTSDIR= ${FILESDIR}
-SCRIPTS= groupadd groupdel groupedit groupinput \
- useradd userdel useredit userinput usermgmt
+SCRIPTS= groupadd groupdel groupedit useradd userdel useredit usermgmt
beforeinstall:
mkdir -p ${DESTDIR}${FILESDIR}
diff --git a/usr.sbin/bsdconfig/usermgmt/groupadd b/usr.sbin/bsdconfig/usermgmt/groupadd
index 6f806a6..cba0f2b 100755
--- a/usr.sbin/bsdconfig/usermgmt/groupadd
+++ b/usr.sbin/bsdconfig/usermgmt/groupadd
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,11 +33,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -55,9 +58,19 @@ done
shift $(( $OPTIND - 1 ))
#
-# Chain-load to groupinput to centralize code and minimize duplication
+# Initialize
#
-$BSDCFG_LIBE/$APP_DIR/groupinput ${USE_XDIALOG:+-X} mode="Add"
+f_dialog_title "$msg_add $msg_group"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Add a group
+#
+# NB: If given an argument on the command-line use it; otherwise fall-back to
+# environment variable $group (handle $VAR_GROUP).
+#
+f_group_add ${1:+"$1"}
################################################################################
# END
diff --git a/usr.sbin/bsdconfig/usermgmt/groupdel b/usr.sbin/bsdconfig/usermgmt/groupdel
index 2f41164..ea55489 100755
--- a/usr.sbin/bsdconfig/usermgmt/groupdel
+++ b/usr.sbin/bsdconfig/usermgmt/groupdel
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
f_include $BSDCFG_SHARE/usermgmt/group_input.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -65,9 +66,17 @@ f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
f_mustberoot_init
#
+# If given a group name, operate on it and exit
+#
+if [ "$1" ]; then
+ f_group_delete "$1"
+ exit $SUCCESS
+fi
+
+#
# Loop until the user Exits, Cancels or presses ESC
#
-defaultitem=""
+defaultitem=
while :; do
f_dialog_menu_group_list "$defaultitem"
retval=$?
@@ -81,8 +90,7 @@ while :; do
# Anything else is a group name
- $BSDCFG_LIBE/$APP_DIR/groupinput \
- ${USE_XDIALOG:+-X} mode="Delete" group="$mtag"
+ f_group_delete "$mtag"
done
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/usermgmt/groupedit b/usr.sbin/bsdconfig/usermgmt/groupedit
index 3eacaff..2338d57 100755
--- a/usr.sbin/bsdconfig/usermgmt/groupedit
+++ b/usr.sbin/bsdconfig/usermgmt/groupedit
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/group.subr
f_include $BSDCFG_SHARE/usermgmt/group_input.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -65,9 +66,17 @@ f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
f_mustberoot_init
#
-# Loop until the user Exits, Cancels or presses ESC
+# If given a group name, operate on it and exit
#
-defaultitem=""
+if [ "$1" ]; then
+ f_group_edit "$1"
+ exit $SUCCESS
+fi
+
+#
+# Present a list of groups and loop until user Exits, Cancels or presses ESC
+#
+defaultitem=
while :; do
f_dialog_menu_group_list "$defaultitem"
retval=$?
@@ -81,8 +90,7 @@ while :; do
# Anything else is a group name
- $BSDCFG_LIBE/$APP_DIR/groupinput \
- ${USE_XDIALOG:+-X} mode="Edit/View" group="$mtag"
+ f_group_edit "$mtag"
done
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/usermgmt/groupinput b/usr.sbin/bsdconfig/usermgmt/groupinput
deleted file mode 100755
index 5b60bb2..0000000
--- a/usr.sbin/bsdconfig/usermgmt/groupinput
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/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 $DIALOG_ESC ]; then
- exit $SUCCESS
- elif [ $retval -ne $DIALOG_OK ]; 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 $SUCCESS; }
- f_dialog_input_group_gid || exit $SUCCESS
- f_dialog_input_group_members || exit $SUCCESS
- 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 $DIALOG_OK ] || f_die
-
- case "$mtag" in
- X) # Exit
- [ "$save_flag" ] && { save_changes || continue; }
- 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 $DIALOG_OK ] || 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/messages.subr b/usr.sbin/bsdconfig/usermgmt/include/messages.subr
index 71cc51d..f56b844 100644
--- a/usr.sbin/bsdconfig/usermgmt/include/messages.subr
+++ b/usr.sbin/bsdconfig/usermgmt/include/messages.subr
@@ -1,5 +1,5 @@
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -32,9 +32,9 @@ 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_account_expire_manual_edit="Enter account expiration time. Format is one of:\n\n a) decimal for UNIX time since %s\n b) dd-mmm-yy[yy] for day, month, and 2- or 4-digit year\n c) +n[mhdwoy] for relative time from current date\n\nNOTE: Value of zero disables expiration."
+msg_account_expires_on="Account Expires on"
msg_add="Add"
msg_add_group="Add Group"
msg_add_login="Add Login"
@@ -56,6 +56,7 @@ msg_edit_group="Edit/View Group"
msg_edit_login="Edit/View Login"
msg_edit_view="Edit/View"
msg_enter_group_members_manually="Enter Group Members manually"
+msg_enter_groups_manually="Enter Groups manually"
msg_enter_number_of_days_into_the_future="Enter number of days into the future"
msg_enter_value_manually="Edit value manually"
msg_error="ERROR!"
@@ -65,18 +66,17 @@ 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_is_empty="Group is empty."
msg_group_members="Group Members"
msg_group_must_start_with_letter="Group must start with a letter."
msg_group_not_found="%s: Group not found."
msg_group_password="Group Password"
msg_group_passwords_do_not_match="Group Passwords do not match."
msg_group_updated="Group Updated"
+msg_groups="Groups"
msg_home_directory="Home Directory"
-msg_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."
@@ -85,25 +85,30 @@ 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_not_found="%s: 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_no_group_specified="No group specified!"
+msg_no_user_specified="No user specified!"
+msg_number_of_seconds_since_epoch="Number of seconds since the Epoch\n(1 = %s)\nNULL or zero to disable:"
msg_ok="OK"
msg_password="Password"
-msg_password_expires_in_how_many_days="Password expires in how many days?"
+msg_password_does_not_expire="Password does not expire"
+msg_password_expire_manual_edit="Enter password expiration time. Format is one of:\n\n a) decimal for UNIX time since %s\n b) dd-mmm-yy[yy] for day, month, and 2- or 4-digit year\n c) +n[mhdwoy] for relative time from current date\n\nNOTE: Value of zero disables expiration."
msg_password_expires_on="Password Expires on"
msg_passwords_do_not_match="Passwords do not match."
-msg_password_does_not_expire="Password does not expire"
+msg_please_enter_a_group_name="Please enter a group name!"
+msg_please_enter_a_user_name="Please enter a user name!"
msg_reenter_group_password="Re-enter Group Password"
msg_reenter_password="Re-enter Password"
msg_save="Save"
msg_save_exit_or_cancel="Choose Save/Exit when finished or Cancel."
-msg_separated_by_commas="Separated by commas"
msg_select_group_members_from_list="Select Group Members from a list"
+msg_select_groups_from_list="Select Groups from a list"
msg_select_login_shell="Select Login Shell"
+msg_separated_by_commas="Separated by commas"
msg_shell="Shell"
msg_unknown_user_management_menu_selection="Unknown user management menu selection"
msg_use_default_values_for_all_account_details="Use default values for all account details?"
diff --git a/usr.sbin/bsdconfig/usermgmt/share/Makefile b/usr.sbin/bsdconfig/usermgmt/share/Makefile
index d6b9e3a..7f27c92 100644
--- a/usr.sbin/bsdconfig/usermgmt/share/Makefile
+++ b/usr.sbin/bsdconfig/usermgmt/share/Makefile
@@ -3,7 +3,7 @@
NO_OBJ=
FILESDIR= ${SHAREDIR}/bsdconfig/usermgmt
-FILES= group_input.subr user_input.subr
+FILES= group.subr group_input.subr user.subr user_input.subr
beforeinstall:
mkdir -p ${DESTDIR}${FILESDIR}
diff --git a/usr.sbin/bsdconfig/usermgmt/share/group.subr b/usr.sbin/bsdconfig/usermgmt/share/group.subr
new file mode 100644
index 0000000..fb320d1
--- /dev/null
+++ b/usr.sbin/bsdconfig/usermgmt/share/group.subr
@@ -0,0 +1,518 @@
+if [ ! "$_USERMGMT_GROUP_SUBR" ]; then _USERMGMT_GROUP_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/group.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${passwdtype:="yes"}
+
+############################################################ FUNCTIONS
+
+# f_group_add [$group]
+#
+# Add a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to enter the name
+# of a new group and (if $VAR_NO_CONFIRM is unset or NULL) prompt the user to
+# answer some questions about the new group. Variables that can be used to
+# script user input:
+#
+# VAR_GROUP [Optional if running interactively]
+# The group to add. Ignored if given non-NULL first-argument.
+# VAR_GROUP_GID [Optional]
+# Numerical group ID to use. If NULL or unset, the group ID is
+# automatically chosen.
+# VAR_GROUP_MEMBERS [Optional]
+# Comma separated list of users that are a member of this group.
+# VAR_GROUP_PASSWORD [Optional]
+# newgrp(1) password to set for the group. Default if NULL or
+# unset is to disable newgrp(1) password authentication.
+#
+# Returns success if the group was successfully added.
+#
+f_group_add()
+{
+ local funcname=f_group_add
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_GROUP input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as GID
+ # instead of name. Work-around is to also pass `-g GID' at the same
+ # time (any GID will do; but `-1' is appropriate for this context).
+ #
+ if [ "$input" ] && f_quietly pw groupshow -n "$input" -g -1; then
+ f_show_err "$msg_group_already_used" "$input"
+ return $FAILURE
+ fi
+
+ local group_name="$input"
+ while f_interactive && [ ! "$group_name" ]; do
+ f_dialog_input_group_name group_name "$group_name" ||
+ return $SUCCESS
+ [ "$group_name" ] ||
+ f_show_err "$msg_please_enter_a_group_name"
+ done
+ if [ ! "$group_name" ]; then
+ f_show_err "$msg_no_group_specified"
+ return $FAILURE
+ fi
+
+ local group_password group_gid group_members
+ f_getvar $VAR_GROUP_PASSWORD group_password
+ f_getvar $VAR_GROUP_GID group_gid
+ f_getvar $VAR_GROUP_MEMBERS group_members
+
+ local group_password_disable=
+ f_interactive || [ "$group_password" ] || group_password_disable=1
+
+ if f_interactive && [ ! "$no_confirm" ]; then
+ f_dialog_noyes \
+ "$msg_use_default_values_for_all_account_details"
+ retval=$?
+ if [ $retval -eq $DIALOG_ESC ]; then
+ return $SUCCESS
+ elif [ $retval -ne $DIALOG_OK ]; then
+ #
+ # Ask series of questions to pre-fill the editor screen
+ #
+ # Defaults used in each dialog should allow the user to
+ # simply hit ENTER to proceed and cancelling a single
+ # dialog cause them to return to the previous menu.
+ #
+
+ if [ "$passwdtype" = "yes" ]; then
+ f_dialog_input_group_password group_password \
+ group_password_disable ||
+ return $FAILURE
+ fi
+ f_dialog_input_group_gid group_gid "$group_gid" ||
+ return $FAILURE
+ f_dialog_input_group_members group_members \
+ "$group_members" || return $FAILURE
+ fi
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_add $msg_group: $group_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_group_add "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Add/Exit
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \
+ \"\$group_$var\" _group_$var
+ done
+
+ local cmd="pw groupadd -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" ] &&
+ cmd="$cmd -M '$_group_members'"
+
+ # Execute the command (break on success)
+ if [ "$group_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" ]; then
+ echo "$group_password" |
+ f_eval_catch $funcname \
+ pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi && break
+ ;;
+ 1) # Group Name (prompt for new group name)
+ f_dialog_input_group_name input "$group_name" ||
+ continue
+ if f_quietly pw groupshow -n "$input" -g -1; then
+ f_show_err "$msg_group_already_used" "$input"
+ continue
+ fi
+ group_name="$input"
+ title="$msg_add $msg_group: $group_name"
+ ;;
+ 2) # Password
+ f_dialog_input_group_password group_password \
+ group_password_disable
+ ;;
+ 3) # Group ID
+ f_dialog_input_group_gid group_gid "$group_gid"
+ ;;
+ 4) # Group Members
+ f_dialog_input_group_members group_members \
+ "$group_members"
+ ;;
+ esac
+ done
+ else
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ # Form the command
+ local cmd="pw groupadd -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" ] && cmd="$cmd -M '$_group_members'"
+
+ # Execute the command
+ local retval err
+ if [ "$group_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" ]; then
+ err=$( echo "$group_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_group_added"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_group_delete [$group]
+#
+# Delete a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to select a group
+# from a list of available groups. Variables that can be used to script user
+# input:
+#
+# VAR_GROUP [Optional if running interactively]
+# The group to delete. Ignored if given non-NULL first-argument.
+#
+# Returns success if the group was successfully deleted.
+#
+f_group_delete()
+{
+ local funcname=f_group_delete
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_GROUP input "$1"
+
+ local group_name group_password group_gid group_members
+ if [ "$input" ] && ! f_input_group "$input"; then
+ f_show_err "$msg_group_not_found" "$input"
+ return $FAILURE
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_delete $msg_group: $group_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_group_delete "$group_name" "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Delete/Exit
+ local _group_name
+ f_shell_escape "$group_name" _group_name
+ f_eval_catch $funcname pw 'pw groupdel "%s"' \
+ "$_group_name" && break
+ ;;
+ 1) # Group Name (select different group from list)
+ f_dialog_menu_group_list "$group_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_group "$mtag"; then
+ f_show_err "$msg_group_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_group "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ ;;
+ esac
+ done
+ else
+ local retval err _group_name
+ f_shell_escape "$group_name" _group_name
+ f_eval_catch -k err $funcname pw \
+ "pw groupdel '%s'" "$_group_name"
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_group_deleted"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_group_edit [$group]
+#
+# Modify a group. If both $group (as a first argument) and $VAR_GROUP are unset
+# or NULL and we are running interactively, prompt the user to select a group
+# from a list of available groups. Variables that can be used to script user
+# input:
+#
+# VAR_GROUP [Optional if running interactively]
+# The group to modify. Ignored if given non-NULL first-argument.
+# VAR_GROUP_GID [Optional]
+# Numerical group ID to set. If NULL or unset, the group ID is
+# unchanged.
+# VAR_GROUP_MEMBERS [Optional]
+# Comma separated list of users that are a member of this group.
+# If set but NULL, group memberships are reset (no users will be
+# a member of this group). If unset, group membership is
+# unmodified.
+# VAR_GROUP_PASSWORD [Optional]
+# newgrp(1) password to set for the group. If unset, the password
+# is unmodified. If NULL, the newgrp(1) password is disabled.
+#
+# Returns success if the group was successfully modified.
+#
+f_group_edit()
+{
+ local funcname=f_group_edit
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_GROUP input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as GID
+ # instead of name. Work-around is to also pass `-g GID' at the same
+ # time (any GID will do; but `-1' is appropriate for this context).
+ #
+ if [ "$input" ] && ! f_quietly pw groupshow -n "$input" -g -1; then
+ f_show_err "$msg_group_not_found" "$input"
+ return $FAILURE
+ fi
+
+ if f_interactive && [ ! "$input" ]; then
+ f_dialog_menu_group_list || return $SUCCESS
+ f_dialog_menutag_fetch input
+ [ "$input" = "X $msg_exit" ] && return $SUCCESS
+ elif [ ! "$input" ]; then
+ f_show_err "$msg_no_group_specified"
+ return $FAILURE
+ fi
+
+ local group_name group_password group_gid group_members
+ if ! f_input_group "$input"; then
+ f_show_err "$msg_group_not_found" "$input"
+ return $FAILURE
+ fi
+
+ f_isset $VAR_GROUP_GID && f_getvar $VAR_GROUP_GID group_gid
+ local null_members=
+ if f_isset $VAR_GROUP_MEMBERS; then
+ f_getvar $VAR_GROUP_MEMBERS group_members
+ [ "$group_members" ] || null_members=1
+ fi
+ local group_password_disable=
+ if f_isset $VAR_GROUP_PASSWORD; then
+ f_getvar $VAR_GROUP_PASSWORD group_password
+ [ "$group_password" ] || group_password_disable=1
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_edit_view $msg_group: $group_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_group_edit "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Save/Exit
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \
+ \"\$group_$var\" _group_$var
+ done
+
+ local cmd="pw groupmod -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" -o "$null_members" ] &&
+ cmd="$cmd -M '$_group_members'"
+
+ # Execute the command (break on success)
+ if [ "$group_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" ]; then
+ echo "$group_password" | f_eval_catch \
+ $funcname pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi && break
+ ;;
+ 1) # Group Name (select different group from list)
+ f_dialog_menu_group_list "$group_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_group "$mtag"; then
+ f_show_err "$msg_group_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_group "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ title="$msg_edit_view $msg_group: $group_name"
+ ;;
+ 2) # Password
+ f_dialog_input_group_password group_password \
+ group_password_disable
+ ;;
+ 3) # Group ID
+ f_dialog_input_group_gid group_gid "$group_gid"
+ ;;
+ 4) # Group Members
+ f_dialog_input_group_members group_members \
+ "$group_members" && [ ! "$group_members" ] &&
+ null_members=1
+ ;;
+ esac
+ done
+ else
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ # Form the command
+ local cmd="pw groupmod -n '$_group_name'"
+ [ "$group_gid" ] && cmd="$cmd -g '$_group_gid'"
+ [ "$group_members" -o "$null_members" ] &&
+ cmd="$cmd -M '$_group_members'"
+
+ # Execute the command
+ local retval err
+ if [ "$group_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$group_password" -o "$null_password" ]; then
+ err=$( echo "$group_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_group_updated"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/group.subr
+
+fi # ! $_USERMGMT_GROUP_SUBR
diff --git a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
index 2ca141e..2e8c086 100644
--- a/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
+++ b/usr.sbin/bsdconfig/usermgmt/share/group_input.subr
@@ -1,7 +1,7 @@
if [ ! "$_USERMGMT_GROUP_INPUT_SUBR" ]; then _USERMGMT_GROUP_INPUT_SUBR=1
#
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -48,14 +48,24 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
#
f_input_group()
{
- eval $( pw groupshow "$1" | awk -F: '
+ local funcname=f_input_group
+ local group="$1"
+
+ f_dprintf "$funcname: Getting info for group \`%s'" "$group"
+ eval "$( pw groupshow "$group" 2> /dev/null | awk -F: '
+ function set_value(var, value) {
+ gsub(/'\''/, "'\''\\'\'\''", value)
+ printf "group_%s='\'%s\''\n", var, value
+ }
{
- printf "group_name='\'%s\''\n", $1
- printf "group_password=\n"
- printf "group_gid='\'%s\''\n", $3
- printf "group_members='\'%s\''\n", $4
+ found = $1 != ""
+ set_value("name", $1)
+ set_value("password", "")
+ set_value("gid", $3)
+ set_value("members", $4)
exit
- }' )
+ }
+ END { if (!found) print "false" }' )"
}
# f_dialog_menu_group_list [$default]
@@ -74,10 +84,13 @@ f_dialog_menu_group_list()
# Add groups from group(5)
menu_list="$menu_list $( pw groupshow -a | awk -F: '
- !/^[[:space:]]*(#|$)/ {
- printf "'\'%s\'\ \'%s\''\n", $1, $1
- }'
- )"
+ function mprint(tag, item) {
+ gsub(/'\''/, "'\''\\'\'\''", tag)
+ gsub(/'\''/, "'\''\\'\'\''", item)
+ printf "'\'%s\'\ \'%s\''\n", tag, item
+ }
+ !/^[[:space:]]*(#|$)/ { mprint($1, $1) }
+ ' )"
local height width rows
eval f_dialog_menu_size height width rows \
@@ -105,303 +118,477 @@ f_dialog_menu_group_list()
return $retval
}
-# f_dialog_input_group_name [$group_name]
+# f_dialog_input_group_name $var_to_set [$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).
+# Allows the user to enter a name for a new group. If the user does not cancel
+# or press ESC, the $var_to_set variable will hold the newly-configured value
+# upon return.
#
f_dialog_input_group_name()
{
+ local __var_to_set="$1" __name="$2"
+
#
# Loop until the user provides taint-free/valid input
#
- local _name="$1" _input="$1"
+ local __input="$__name"
while :; do
-
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_group" "$_input" \
+ f_dialog_input __input "$msg_group" "$__input" \
"$hline_alnum_tab_enter" || return $?
# Check for no-change
- [ "$_input" = "$_name" ] && return $DIALOG_OK
-
- # Check for reversion
- if [ "$_input" = "$cur_group_name" ]; then
- group_name="$cur_group_name"
+ if [ "$__input" = "$__name" ]; then
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
fi
# Check for NULL entry
- if [ ! "$_input" ]; then
+ if [ ! "$__input" ]; then
f_show_msg "$msg_group_is_empty"
continue
fi
# Check for invalid entry
- if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
+ case "$__input" in [!a-zA-Z]*)
f_show_msg "$msg_group_must_start_with_letter"
continue
- fi
+ esac
# Check for duplicate entry
- if f_quietly pw groupshow -n "$_input"; then
- f_show_msg "$msg_group_already_used" "$_input"
+ if f_quietly pw groupshow -n "$__input"; then
+ f_show_msg "$msg_group_already_used" "$__input"
continue
fi
- group_name="$_input"
+ setvar "$__var_to_set" "$__input"
break
done
- save_flag=1
-
- f_dprintf "group_name: [%s]->[%s]" "$cur_group_name" "$group_name"
return $DIALOG_OK
}
-# f_dialog_input_group_password
+# f_dialog_input_group_password $var_to_set $dvar_to_set
#
-# Prompt the user to enter a password (twice).
+# Prompt the user to enter a password (twice). If the user does not cancel or
+# press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the
+# user cancels or enters a NULL password (twice), they are given the choice to
+# disable password authentication for the given group, wherein $dvar_to_set has
+# a value of 1 to indicate password authentication should be disabled.
#
f_dialog_input_group_password()
{
- local prompt1="$msg_group_password"
- local prompt2="$msg_reenter_group_password"
- local hline="$hline_alnum_punc_tab_enter"
+ local __var_to_set="$1" __dvar_to_set="$2"
+ local __prompt1="$msg_group_password"
+ local __prompt2="$msg_reenter_group_password"
+ local __hline="$hline_alnum_punc_tab_enter"
- local height1 width1
- f_dialog_inputbox_size height1 width1 \
+ local __height1 __width1
+ f_dialog_inputbox_size __height1 __width1 \
"$DIALOG_TITLE" \
"$DIALOG_BACKTITLE" \
- "$prompt1" \
+ "$__prompt1" \
"" \
- "$hline"
+ "$__hline"
- local height2 width2
- f_dialog_inputbox_size height2 width2 \
+ local __height2 __width2
+ f_dialog_inputbox_size __height2 __width2 \
"$DIALOG_TITLE" \
"$DIALOG_BACKTITLE" \
- "$prompt2" \
+ "$__prompt2" \
"" \
- "$hline"
+ "$__hline"
#
# Loop until the user provides taint-free/valid input
#
- local retval _password1 _password2
+ local __retval __password1 __password2
while :; do
- _password1=$( $DIALOG \
+ __password1=$( $DIALOG \
--title "$DIALOG_TITLE" \
--backtitle "$DIALOG_BACKTITLE" \
- --hline "$hline" \
+ --hline "$__hline" \
--ok-label "$msg_ok" \
--cancel-label "$msg_cancel" \
--insecure \
- --passwordbox "$prompt1" \
- $height1 $width1 \
+ --passwordbox "$__prompt1" \
+ $__height1 $__width1 \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
)
- retval=$?
- debug= f_dialog_line_sanitize _password1
+ __retval=$?
+ debug= f_dialog_line_sanitize __password1
# Return if user has either pressed ESC or chosen Cancel/No
- [ $retval -eq $DIALOG_OK ] || return $retval
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
- _password2=$( $DIALOG \
+ __password2=$( $DIALOG \
--title "$DIALOG_TITLE" \
--backtitle "$DIALOG_BACKTITLE" \
- --hline "$hline" \
+ --hline "$__hline" \
--ok-label "$msg_ok" \
--cancel-label "$msg_cancel" \
--insecure \
- --passwordbox "$prompt2" \
- $height2 $width2 \
+ --passwordbox "$__prompt2" \
+ $__height2 $__width2 \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
)
- retval=$?
- debug= f_dialog_line_sanitize _password2
+ __retval=$?
+ debug= f_dialog_line_sanitize __password2
# Return if user has either pressed ESC or chosen Cancel/No
- [ $retval -eq $DIALOG_OK ] || return $retval
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
# Check for password mismatch
- if [ "$_password1" != "$_password2" ]; then
+ if [ "$__password1" != "$__password2" ]; then
f_show_msg "$msg_group_passwords_do_not_match"
continue
fi
# Check for NULL entry
- if [ ! "$_password1" ]; then
+ if [ ! "$__password1" ]; then
f_dialog_yesno "$msg_disable_password_auth_for_group"
- local retval=$?
- if [ $retval -eq $DIALOG_ESC ]; then
- return $retval
- elif [ $retval -eq $DIALOG_OK ]; then
- pw_group_password_disable=1
+ __retval=$?
+ if [ $__retval -eq $DIALOG_ESC ]; then
+ return $__retval
+ elif [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__dvar_to_set" 1
else
continue # back to password prompt
fi
else
- pw_group_password_disable=
+ setvar "$__dvar_to_set" ""
fi
- group_password="$_password1"
+ setvar "$__var_to_set" "$__password1"
break
done
- save_flag=1
-
- f_dprintf "group_password: [%s]->[%s]" \
- "$cur_group_password" "$group_password"
return $DIALOG_OK
}
-# f_dialog_input_group_gid [$group_gid]
+# f_dialog_input_group_gid $var_to_set [$group_gid]
#
# Allow the user to enter a new GID for a given group. If the user does not
-# cancel or press ESC, the $group_gid variable will hold the newly-configured
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
# value upon return.
#
f_dialog_input_group_gid()
{
- local _input="$1"
+ local __var_to_set="$1" __input="$2"
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_group_id_leave_empty_for_default" \
- "$_input" "$hline_num_tab_enter" || return $?
-
- group_gid="$_input"
- save_flag=1
-
- f_dprintf "group_gid: [%s]->[%s]" "$cur_group_gid" "$group_gid"
+ f_dialog_input __input "$msg_group_id_leave_empty_for_default" \
+ "$__input" "$hline_num_tab_enter" || return $?
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_group_members [$group_members]
+# f_dialog_input_group_members $var_to_set [$group_members]
#
# Allow the user to modify a list of members for a given group. If the user
-# does not cancel or press ESC, the $group_members variable will hold the
-# newly-configured value upon return.
+# does not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
#
f_dialog_input_group_members()
{
- local _input="$1"
- local prompt="$msg_group_members:"
- local menu_list="
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_group_members:"
+ local __menu_list="
'X' '$msg_continue'
'1' '$msg_select_group_members_from_list'
'2' '$msg_enter_group_members_manually'
" # END-QUOTE
- local defaultitem=
- local hline="$hline_num_arrows_tab_enter"
+ local __defaultitem=
+ local __hline="$hline_num_arrows_tab_enter"
- local mheight mwidth mrows
- eval f_dialog_menu_size mheight mwidth mrows \
+ local __mheight __mwidth __mrows
+ eval f_dialog_menu_size __mheight __mwidth __mrows \
\"\$DIALOG_TITLE\" \
\"\$DIALOG_BACKTITLE\" \
- \"\$prompt\" \
- \"\$hline\" \
- $menu_list
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__menu_list
- local menu_choice retval
+ local __menu_choice __retval
while :; do
- menu_choice=$( eval $DIALOG \
+ __menu_choice=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --default-item \"\$defaultitem\" \
- --menu \"\$prompt\" \
- $mheight $mwidth $mrows \
- $menu_list \
+ --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"
+ __retval=$?
+ f_dialog_data_sanitize __menu_choice
+ __defaultitem="$__menu_choice"
+ f_dprintf "retval=%u menu_choice=[%s]" \
+ $__retval "$__menu_choice"
# Return if user has either pressed ESC or chosen Cancel/No
- [ $retval -eq $DIALOG_OK ] || return $retval
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
- local _group_members
- case "$menu_choice" in
+ 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
+ local __check_list= # Calculated below
+ local __user_list __u __user __length=0
+ __user_list=$( pw usershow -a |
+ awk -F: '!/^[[:space:]]*(#|$)/{print $1}' )
+ while [ $__length -ne ${#__user_list} ]; do
+ __u="${__user_list%%$NL*}" # First line
+ f_shell_escape "$__u" __user
+
# Format of a checklist entry: tag item status
- if echo "$_input" | grep -q "\<$user\>"; then
- check_list="$check_list $user '' on"
- else
- check_list="$check_list $user '' off"
- fi
+ __check_list="$__check_list '$__user' ''"
+ case "$__input" in
+ "$__u"|"$__u",*|*,"$__u",*|*,"$__u")
+ __check_list="$__check_list on" ;;
+ *)
+ __check_list="$__check_list off"
+ esac
+
+ __length=${#__user_list}
+ __user_list="${__user_list#*$NL}" # Kill line
done
- local cheight cwidth crows
- eval f_dialog_checklist_size cheight cwidth crows \
- \"\$DIALOG_TITLE\" \
- \"\$DIALOG_BACKTITLE\" \
- \"\$prompt\" \
- \"\$hline\" \
- $check_list
- _group_members=$( eval $DIALOG \
+ 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\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --checklist \"\$prompt\" \
- $cheight $cwidth $crows \
- $check_list \
+ --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
+ 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"
+ #
+ f_replaceall "$__group_members" "[$NL]" "," __input
;;
2) # Enter Group Members manually
- local p="$msg_group_members ($msg_separated_by_commas)"
+ local __prompt2="$msg_group_members"
+ __prompt2="$__prompt2 ($msg_separated_by_commas)"
- f_dialog_input _group_members "$p" "$_input" \
+ f_dialog_input __group_members \
+ "$__prompt2" "$__input" \
"$hline_num_tab_enter" || continue
# Return to previous menu if user either
# pressed ESC or chose Cancel/No
- _input="$_group_members"
+ __input="$__group_members"
;;
esac
done
- group_members="$_input"
- save_flag=1
- f_dprintf "group_members: [%s]->[%s]" \
- "$cur_group_members" "$group_members"
-
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
+# f_dialog_menu_group_add [$defaultitem]
+#
+# Present a menu detailing the properties of a group that is about to be added.
+# The user's menu choice is available using f_dialog_menutag_fetch(). Returns
+# success unless the user chose Cancel or pressed ESC. Data to display is taken
+# from environment variables group_name, group_gid, and group_members. If
+# $defaultitem is present and non-NULL, initially highlight the item in the
+# menu.
+#
+f_dialog_menu_group_add()
+{
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ menu_list="
+ 'X' '$msg_add/$msg_exit'
+ '1' '$msg_group: $_group_name'
+ '2' '$msg_password: -----'
+ '3' '$msg_group_id: $_group_gid'
+ '4' '$msg_group_members: $_group_members'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_group_delete $group [$defaultitem]
+#
+# Present a menu detailing the properties of a group that is about to be
+# deleted. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is populated automatically from the system accounting database for the given
+# $group argument. If $defaultitem is present and non-NULL, initially highlight
+# the item in the menu.
+#
+f_dialog_menu_group_delete()
+{
+ local prompt="$msg_delete_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$2"
+ local hline="$hline_arrows_tab_enter"
+
+ local group_name group_password group_gid group_members
+ f_input_group "$1"
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ menu_list="
+ 'X' '$msg_delete/$msg_exit'
+ '1' '$msg_group: $_group_name'
+ '-' '$msg_password: -----'
+ '-' '$msg_group_id: $_group_gid'
+ '-' '$msg_group_members: $_group_members'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_group_edit [$defaultitem]
+#
+# Present a menu detailing the properties of a group that is about to be
+# modified. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is taken from environment variables group_name, group_gid, and group_members.
+# If $defaultitem is present and non-NULL, initially highlight the item in the
+# menu.
+#
+f_dialog_menu_group_edit()
+{
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in gid members name; do
+ local _group_$var
+ eval f_shell_escape \"\$group_$var\" _group_$var
+ done
+
+ menu_list="
+ 'X' '$msg_save/$msg_exit'
+ '1' '$msg_group: $_group_name'
+ '2' '$msg_password: -----'
+ '3' '$msg_group_id: $_group_gid'
+ '4' '$msg_group_members: $_group_members'
+ " # END-QUOTE
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
############################################################ MAIN
f_dprintf "%s: Successfully loaded." usermgmt/group_input.subr
diff --git a/usr.sbin/bsdconfig/usermgmt/share/user.subr b/usr.sbin/bsdconfig/usermgmt/share/user.subr
new file mode 100644
index 0000000..5fd65fb
--- /dev/null
+++ b/usr.sbin/bsdconfig/usermgmt/share/user.subr
@@ -0,0 +1,1184 @@
+if [ ! "$_USERMGMT_USER_SUBR" ]; then _USERMGMT_USER_SUBR=1
+#
+# Copyright (c) 2012 Ron McDowell
+# Copyright (c) 2012-2014 Devin Teske
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." usermgmt/user.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/usermgmt/group_input.subr
+f_include $BSDCFG_SHARE/usermgmt/user_input.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
+
+############################################################ CONFIGURATION
+
+# set some reasonable defaults if /etc/adduser.conf does not exist.
+[ -f /etc/adduser.conf ] && f_include /etc/adduser.conf
+: ${defaultclass:=""}
+: ${defaultshell:="/bin/sh"}
+: ${homeprefix:="/home"}
+: ${passwdtype:="yes"}
+: ${udotdir:="/usr/share/skel"}
+: ${uexpire:=""}
+ # Default account expire time. Format is similar to upwexpire variable.
+: ${ugecos:="User &"}
+: ${upwexpire:=""}
+ # The default password expiration time. Format of the date is either a
+ # UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where dd is
+ # the day, mmm is the month in either numeric or alphabetic format, and
+ # yy[yy] is either a two or four digit year. This variable also accepts
+ # a relative date in the form of n[mhdwoy] where n is a decimal, octal
+ # (leading 0) or hexadecimal (leading 0x) digit followed by the number
+ # of Minutes, Hours, Days, Weeks, Months or Years from the current date
+ # at which the expiration time is to be set.
+
+#
+# uexpire and upwexpire from adduser.conf(5) differ only slightly from what
+# pw(8) accepts as `date' argument(s); pw(8) requires a leading `+' for the
+# relative date syntax (n[mhdwoy]).
+#
+case "$uexpire" in *[mhdwoy])
+ f_isinteger "${uexpire%[mhdwoy]}" && uexpire="+$uexpire"
+esac
+case "$upwexpire" in *[mhdwoy])
+ f_isinteger "${upwexpire%[mhdwoy]}" && upwexpire="+$upwexpire"
+esac
+
+############################################################ FUNCTIONS
+
+# f_user_create_homedir $user
+#
+# Create home directory for $user.
+#
+f_user_create_homedir()
+{
+ local funcname=f_user_create_homedir
+ local user="$1"
+
+ [ "$user" ] || return $FAILURE
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ f_input_user "$user" || return $FAILURE
+
+ f_dprintf "Creating home directory \`%s' for user \`%s'" \
+ "$user_home_dir" "$user"
+
+ local _user_gid _user_home_dir _user_uid
+ f_shell_escape "$user_gid" _user_gid
+ f_shell_escape "$user_home_dir" _user_home_dir
+ f_shell_escape "$user_uid" _user_uid
+ f_eval_catch $funcname mkdir "mkdir -p '%s'" "$_user_home_dir" ||
+ return $FAILURE
+ f_eval_catch $funcname chown "chown '%i:%i' '%s'" \
+ "$_user_uid" "$_user_gid" "$_user_home_dir" || return $FAILURE
+}
+
+# f_user_copy_dotfiles $user
+#
+# Copy `skel' dot-files from $udotdir (global inherited from /etc/adduser.conf)
+# to the home-directory of $user. Attempts to create the home-directory first
+# if it doesn't exist.
+#
+f_user_copy_dotfiles()
+{
+ local funcname=f_user_copy_dotfiles
+ local user="$1"
+
+ [ "$udotdir" ] || return $FAILURE
+ [ "$user" ] || return $FAILURE
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ f_input_user "$user" || return $FAILURE
+
+ f_dprintf "Copying dot-files from \`%s' to \`%s'" \
+ "$udotdir" "$user_home_dir"
+
+ # Attempt to create the home directory if it doesn't exist
+ [ -d "$user_home_dir" ] ||
+ f_user_create_homedir "$user" || return $FAILURE
+
+ local _user_gid _user_home_dir _user_uid
+ f_shell_escape "$user_gid" _user_gid
+ f_shell_escape "$user_home_dir" _user_home_dir
+ f_shell_escape "$user_uid" _user_uid
+
+ local - # Localize `set' to this function
+ set +f # Enable glob pattern-matching for paths
+ cd "$udotdir" || return $FAILURE
+
+ local _file file retval
+ for file in dot.*; do
+ [ -e "$file" ] || continue # no-match
+
+ f_shell_escape "$file" "_file"
+ f_eval_catch $funcname cp "cp -n '%s' '%s'" \
+ "$_file" "$_user_home_dir/${_file#dot}"
+ retval=$?
+ [ $retval -eq $SUCCESS ] || break
+ f_eval_catch $funcname chown \
+ "chown -h '%i:%i' '%s'" \
+ "$_user_uid" "$_user_gid" \
+ "$_user_home_dir/${_file#dot}"
+ retval=$?
+ [ $retval -eq $SUCCESS ] || break
+ done
+
+ cd -
+ return $retval
+}
+
+# f_user_add [$user]
+#
+# Create a login account. If both $user (as a first argument) and $VAR_USER are
+# unset or NULL and we are running interactively, prompt the end-user to enter
+# the name of a new login account and (if $VAR_NO_CONFIRM is unset or NULL)
+# prompt the end-user to answer some questions about the new account. Variables
+# that can be used to script user input:
+#
+# VAR_USER [Optional if running interactively]
+# The login to add. Ignored if given non-NULL first-argument.
+# VAR_USER_ACCOUNT_EXPIRE [Optional]
+# The account expiration time. Format is similar to
+# VAR_USER_PASSWORD_EXPIRE variable below. Default is to never
+# expire the account.
+# VAR_USER_DOTFILES_CREATE [Optional]
+# If non-NULL, populate the user's home directory with the
+# template files found in $udotdir (`/usr/share/skel' default).
+# VAR_USER_GECOS [Optional]
+# Often the full name of the account holder. Default is NULL.
+# VAR_USER_GID [Optional]
+# Numerical primary-group ID to use. If NULL or unset, the group
+# ID is automatically chosen.
+# VAR_USER_GROUPS [Optional]
+# Comma-separated list of additional groups to which the user is
+# a member of. Default is NULL (no additional groups).
+# VAR_USER_HOME [Optional]
+# The home directory to set. If NULL or unset, the home directory
+# is automatically calculated.
+# VAR_USER_HOME_CREATE [Optional]
+# If non-NULL, create the user's home directory if it doesn't
+# already exist.
+# VAR_USER_LOGIN_CLASS [Optional]
+# Login class to use when creating the login. Default is NULL.
+# VAR_USER_PASSWORD [Optional]
+# Unencrypted password to use. If unset or NULL, password
+# authentication for the login is disabled.
+# VAR_USER_PASSWORD_EXPIRE [Optional]
+# The password expiration time. Format of the date is either a
+# UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where
+# dd is the day, mmm is the month in either numeric or alphabetic
+# format, and yy[yy] is either a two or four digit year. This
+# variable also accepts a relative date in the form of +n[mhdwoy]
+# where n is a decimal, octal (leading 0) or hexadecimal (leading
+# 0x) digit followed by the number of Minutes, Hours, Days,
+# Weeks, Months or Years from the current date at which the
+# expiration time is to be set. Default is to never expire the
+# account password.
+# VAR_USER_SHELL [Optional]
+# Path to login shell to use. Default is `/bin/sh'.
+# VAR_USER_UID [Optional]
+# Numerical user ID to use. If NULL or unset, the user ID is
+# automatically chosen.
+#
+# Returns success if the user account was successfully created.
+#
+f_user_add()
+{
+ local funcname=f_user_add
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_USER input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as UID
+ # instead of name. Work-around is to also pass `-u UID' at the same
+ # time (any UID will do; but `-1' is appropriate for this context).
+ #
+ if [ "$input" ] && f_quietly pw usershow -n "$input" -u -1; then
+ f_show_err "$msg_login_already_used" "$input"
+ return $FAILURE
+ fi
+
+ local user_name="$input"
+ while f_interactive && [ ! "$user_name" ]; do
+ f_dialog_input_name user_name "$user_name" ||
+ return $SUCCESS
+ [ "$user_name" ] ||
+ f_show_err "$msg_please_enter_a_user_name"
+ done
+ if [ ! "$user_name" ]; then
+ f_show_err "$msg_no_user_specified"
+ return $FAILURE
+ fi
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_password user_password_expire user_shell
+ local user_uid user_dotfiles_create= user_home_create=
+ f_getvar $VAR_USER_ACCOUNT_EXPIRE-\$uexpire user_account_expire
+ f_getvar $VAR_USER_DOTFILES_CREATE:+\$msg_yes user_dotfiles_create
+ f_getvar $VAR_USER_GECOS-\$ugecos user_gecos
+ f_getvar $VAR_USER_GID user_gid
+ f_getvar $VAR_USER_GROUPS user_member_groups
+ f_getvar $VAR_USER_HOME:-\${homeprefix%/}/\$user_name \
+ user_home_dir
+ f_getvar $VAR_USER_HOME_CREATE:+\$msg_yes user_home_create
+ f_getvar $VAR_USER_LOGIN_CLASS-\$defaultclass user_class
+ f_getvar $VAR_USER_PASSWORD user_password
+ f_getvar $VAR_USER_PASSWORD_EXPIRE-\$upwexpire user_password_expire
+ f_getvar $VAR_USER_SHELL-\$defaultshell user_shell
+ f_getvar $VAR_USER_UID user_uid
+
+ # Create home-dir if no script-override and does not exist
+ f_isset $VAR_USER_HOME_CREATE || [ -d "$user_home_dir" ] ||
+ user_home_create="$msg_yes"
+ # Copy dotfiles if home-dir creation is desired, does not yet exist,
+ # and no script-override has been set
+ f_isset $VAR_USER_DOTFILES_CREATE ||
+ [ "$user_home_create" != "$msg_yes" ] ||
+ [ -d "$user_home_dir" ] || user_dotfiles_create="$msg_yes"
+ # Create home-dir if copying dotfiles but home-dir does not exist
+ [ "$user_dotfiles_create" -a ! -d "$user_home_dir" ] &&
+ user_home_create="$msg_yes"
+
+ # Set flags for meaningful NULL values if-provided
+ local no_account_expire= no_password_expire= null_gecos= null_members=
+ local user_password_disable=
+ f_isset $VAR_USER_ACCOUNT_EXPIRE &&
+ [ ! "$user_account_expire" ] && no_account_expire=1
+ f_isset $VAR_USER_GECOS &&
+ [ ! "$user_gecos" ] && null_gecos=1
+ f_isset $VAR_USER_GROUPS &&
+ [ ! "$user_member_groups" ] && null_members=1
+ f_isset $VAR_USER_PASSWORD &&
+ [ ! "$user_password" ] && user_password_disable=1
+ f_isset $VAR_USER_PASSWORD_EXPIRE &&
+ [ ! "$user_password_expire" ] && no_password_expire=1
+
+ if f_interactive && [ ! "$no_confirm" ]; then
+ f_dialog_noyes \
+ "$msg_use_default_values_for_all_account_details"
+ retval=$?
+ if [ $retval -eq $DIALOG_ESC ]; then
+ return $SUCCESS
+ elif [ $retval -ne $DIALOG_OK ]; then
+ #
+ # Ask series of questions to pre-fill the editor screen
+ #
+ # Defaults used in each dialog should allow the user to
+ # simply hit ENTER to proceed, because cancelling any
+ # single dialog will cause them to be returned to the
+ # previous menu.
+ #
+
+ f_dialog_input_gecos user_gecos "$user_gecos" ||
+ return $FAILURE
+ if [ "$passwdtype" = "yes" ]; then
+ f_dialog_input_password user_password \
+ user_password_disable ||
+ return $FAILURE
+ fi
+ f_dialog_input_uid user_uid "$user_uid" ||
+ return $FAILURE
+ f_dialog_input_gid user_gid "$user_gid" ||
+ return $FAILURE
+ f_dialog_input_member_groups user_member_groups \
+ "$user_member_groups" || return $FAILURE
+ f_dialog_input_class user_class "$user_class" ||
+ return $FAILURE
+ f_dialog_input_expire_password user_password_expire \
+ "$user_password_expire" || return $FAILURE
+ f_dialog_input_expire_account user_account_expire \
+ "$user_account_expire" || return $FAILURE
+ f_dialog_input_home_dir user_home_dir \
+ "$user_home_dir" || return $FAILURE
+ if [ ! -d "$user_home_dir" ]; then
+ f_dialog_input_home_create user_home_create ||
+ return $FAILURE
+ if [ "$user_home_create" = "$msg_yes" ]; then
+ f_dialog_input_dotfiles_create \
+ user_dotfiles_create ||
+ return $FAILURE
+ fi
+ fi
+ f_dialog_input_shell user_shell "$user_shell" ||
+ return $FAILURE
+ fi
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_add $msg_user: $user_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_user_add "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Add/Exit
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ local cmd="pw useradd -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o \
+ "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_home_dir" ] &&
+ cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_member_groups" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o \
+ "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ if [ "$user_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ echo "$user_password" | f_eval_catch \
+ $funcname pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi || continue
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ] && f_user_copy_dotfiles "$user_name"
+
+ break # to success
+ ;;
+ 1) # Login (prompt for new login name)
+ f_dialog_input_name input "$user_name" ||
+ continue
+ if f_quietly pw usershow -n "$input" -u -1; then
+ f_show_err "$msg_login_already_used" "$input"
+ continue
+ fi
+ user_name="$input"
+ title="$msg_add $msg_user: $user_name"
+ user_home_dir="${homeprefix%/}/$user_name"
+ ;;
+ 2) # Full Name
+ f_dialog_input_gecos user_gecos "$user_gecos" &&
+ [ ! "$user_gecos" ] && null_gecos=1 ;;
+ 3) # Password
+ f_dialog_input_password \
+ user_password user_password_disable ;;
+ 4) # User ID
+ f_dialog_input_uid user_uid "$user_uid" ;;
+ 5) # Group ID
+ f_dialog_input_gid user_gid "$user_gid" ;;
+ 6) # Member of Groups
+ f_dialog_input_member_groups \
+ user_member_groups "$user_member_groups" &&
+ [ ! "$user_member_groups" ] &&
+ null_members=1 ;;
+ 7) # Login Class
+ f_dialog_input_class user_class "$user_class" &&
+ [ ! "$user_class" ] && null_class=1 ;;
+ 8) # Password Expires On
+ f_dialog_input_expire_password \
+ user_password_expire "$user_password_expire" &&
+ [ ! "$user_password_expire" ] &&
+ no_password_expire=1 ;;
+ 9) # Account Expires On
+ f_dialog_input_expire_account \
+ user_account_expire "$user_account_expire" &&
+ [ ! "$user_account_expire" ] &&
+ no_account_expire=1 ;;
+ A) # Home Directory
+ f_dialog_input_home_dir \
+ user_home_dir "$user_home_dir" ;;
+ B) # Shell
+ f_dialog_input_shell user_shell "$user_shell" ;;
+ C) # Create Home Directory?
+ if [ "${user_home_create:-$msg_no}" != "$msg_no" ]
+ then
+ user_home_create="$msg_no"
+ else
+ user_home_create="$msg_yes"
+ fi ;;
+ D) # Create Dotfiles?
+ if [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ]
+ then
+ user_dotfiles_create="$msg_no"
+ else
+ user_dotfiles_create="$msg_yes"
+ fi ;;
+ esac
+ done
+ else
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Form the command
+ local cmd="pw useradd -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_member_groups" -o "$null_members" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ local retval err
+ if [ "$user_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ err=$( echo "$user_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_copy_dotfiles "$user_name"
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_login_added"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_user_delete [$user]
+#
+# Delete a user. If both $user (as a first argument) and $VAR_USER are unset or
+# NULL and we are running interactively, prompt the end-user to select a user
+# account from a list of those available. Variables that can be used to script
+# user input:
+#
+# VAR_USER [Optional if running interactively]
+# The user to delete. Ignored if given non-NULL first-argument.
+#
+# Returns success if the user account was successfully deleted.
+#
+f_user_delete()
+{
+ local funcname=f_user_delete
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_USER input "$1"
+
+ if f_interactive && [ ! "$input" ]; then
+ f_dialog_menu_user_list || return $SUCCESS
+ f_dialog_menutag_fetch input
+ [ "$input" = "X $msg_exit" ] && return $SUCCESS
+ elif [ ! "$input" ]; then
+ f_show_err "$msg_no_user_specified"
+ return $FAILURE
+ fi
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ if [ "$input" ] && ! f_input_user "$input"; then
+ f_show_err "$msg_login_not_found" "$input"
+ return $FAILURE
+ fi
+
+ local user_group_delete= user_home_delete=
+ f_getvar $VAR_USER_GROUP_DELETE:-\$msg_no user_group_delete
+ f_getvar $VAR_USER_HOME_DELETE:-\$msg_no user_home_delete
+
+ # Attempt to translate user GID into a group name
+ local user_group
+ if user_group=$( pw groupshow -g "$user_gid" 2> /dev/null ); then
+ user_group="${user_group%%:*}"
+ # Default to delete the primary group if no script-override and
+ # exists with same name as the user (same logic used by pw(8))
+ f_isset $VAR_USER_GROUP_DELETE ||
+ [ "$user_group" != "$user_name" ] ||
+ user_group_delete="$msg_yes"
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_delete $msg_user: $user_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_user_delete "$user_name" "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Delete/Exit
+ f_shell_escape "$user_uid" _user_uid
+
+ # Save group information in case pw(8) deletes it
+ # and we wanted to keep it (to be restored below)
+ if [ "${user_group_delete:-$msg_no}" = "$msg_no" ]
+ then
+ local v vars="gid members name password"
+ for v in $vars; do local group_$var; done
+ f_input_group "$user_group"
+
+ # Remove user-to-delete from group members
+ # NB: Otherwise group restoration could fail
+ local name length=0 _members=
+ while [ $length -ne ${#group_members} ]; do
+ name="${group_members%%,*}"
+ [ "$name" != "$user_name" ] &&
+ _members="$_members,$name"
+ length=${#group_members}
+ group_members="${group_members#*,}"
+ done
+ group_members="${_members#,}"
+
+ # Create escaped variables for f_eval_catch()
+ for v in $vars; do
+ local _group_$v
+ eval f_shell_escape \
+ \"\$group_$v\" _group_$v
+ done
+ fi
+
+ # Delete the user (if asked to delete home directory
+ # display [X]dialog notification to show activity)
+ local cmd="pw userdel -u '$_user_uid'"
+ if [ "$user_home_delete" = "$msg_yes" -a \
+ "$USE_XDIALOG" ]
+ then
+ local err
+ err=$(
+ exec 9>&1
+ f_eval_catch -e $funcname pw \
+ "%s -r" "$cmd" \
+ >&$DIALOG_TERMINAL_PASSTHRU_FD 2>&9 |
+ f_xdialog_info \
+ "$msg_deleting_home_directory"
+ )
+ [ ! "$err" ]
+ elif [ "$user_home_delete" = "$msg_yes" ]; then
+ f_dialog_info "$msg_deleting_home_directory"
+ f_eval_catch $funcname pw '%s -r' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi || continue
+
+ #
+ # pw(8) may conditionally delete the primary group,
+ # which may not be what is desired.
+ #
+ # If we've been asked to delete the group and pw(8)
+ # chose not to, delete it. Otherwise, if we're told
+ # to NOT delete the group, we may need to restore it
+ # since pw(8) doesn't have a flag to tell `userdel'
+ # to not delete the group.
+ #
+ # NB: If primary group and user have different names
+ # the group may not have been deleted (again, see PR
+ # 169471 and SVN r263114 for details).
+ #
+ if [ "${user_group_delete:-$msg_no}" != "$msg_no" ]
+ then
+ f_quietly pw groupshow -g "$user_gid" &&
+ f_eval_catch $funcname pw \
+ "pw groupdel -g '%s'" "$_user_gid"
+ elif ! f_quietly pw groupshow -g "$group_gid" &&
+ [ "$group_name" -a "$group_gid" ]
+ then
+ # Group deleted by pw(8), so restore it
+ local cmd="pw groupadd -n '$_group_name'"
+ cmd="$cmd -g '$_group_gid'"
+ cmd="$cmd -M '$_group_members'"
+
+ # Get the group password (pw(8) groupshow does
+ # NOT provide this (even if running privileged)
+ local group_password_enc
+ group_password_enc=$( getent group | awk -F: '
+ !/^[[:space:]]*(#|$)/ && \
+ $1 == ENVIRON["group_name"] && \
+ $3 == ENVIRON["group_gid"] && \
+ $4 == ENVIRON["group_members"] \
+ { print $2; exit }
+ ' )
+ if [ "$group_password_enc" ]; then
+ echo "$group_password_enc" |
+ f_eval_catch $funcname \
+ pw '%s -H 0' "$cmd"
+ else
+ f_eval_catch $funcname \
+ pw '%s -h -' "$cmd"
+ fi
+ fi
+
+ break # to success
+ ;;
+ 1) # Login (select different login from list)
+ f_dialog_menu_user_list "$user_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_user "$mtag"; then
+ f_show_err "$msg_login_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_user "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ title="$msg_delete $msg_user: $user_name"
+ ;;
+ C) # Delete Primary Group?
+ if [ "${user_group_delete:-$msg_no}" != "$msg_no" ]
+ then
+ user_group_delete="$msg_no"
+ else
+ user_group_delete="$msg_yes"
+ fi ;;
+ D) # Delete Home Directory?
+ if [ "${user_home_delete:-$msg_no}" != "$msg_no" ]
+ then
+ user_home_delete="$msg_no"
+ else
+ user_home_delete="$msg_yes"
+ fi ;;
+ esac
+ done
+ else
+ f_shell_escape "$user_uid" _user_uid
+
+ # Save group information in case pw(8) deletes it
+ # and we wanted to keep it (to be restored below)
+ if [ "${user_group_delete:-$msg_no}" = "$msg_no" ]; then
+ local v vars="gid members name password"
+ for v in $vars; do local group_$v; done
+ f_input_group "$user_group"
+
+ # Remove user we're about to delete from group members
+ # NB: Otherwise group restoration could fail
+ local name length=0 _members=
+ while [ $length -ne ${#group_members} ]; do
+ name="${group_members%%,*}"
+ [ "$name" != "$user_name" ] &&
+ _members="$_members,$name"
+ length=${#group_members}
+ group_members="${group_members#*,}"
+ done
+ group_members="${_members#,}"
+
+ # Create escaped variables for later f_eval_catch()
+ for v in $vars; do
+ local _group_$v
+ eval f_shell_escape \"\$group_$v\" _group_$v
+ done
+ fi
+
+ # Delete the user (if asked to delete home directory
+ # display [X]dialog notification to show activity)
+ local err cmd="pw userdel -u '$_user_uid'"
+ if [ "$user_home_delete" = "$msg_yes" -a "$USE_XDIALOG" ]; then
+ err=$(
+ exec 9>&1
+ f_eval_catch -de $funcname pw \
+ '%s -r' "$cmd" 2>&9 | f_xdialog_info \
+ "$msg_deleting_home_directory"
+ )
+ [ ! "$err" ]
+ elif [ "$user_home_delete" = "$msg_yes" ]; then
+ f_dialog_info "$msg_deleting_home_directory"
+ f_eval_catch -k err $funcname pw '%s -r' "$cmd"
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ local retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+
+ #
+ # pw(8) may conditionally delete the primary group, which may
+ # not be what is desired.
+ #
+ # If we've been asked to delete the group and pw(8) chose not
+ # to, delete it. Otherwise, if we're told to NOT delete the
+ # group, we may need to restore it since pw(8) doesn't have a
+ # flag to tell `userdel' to not delete the group.
+ #
+ # NB: If primary group and user have different names the group
+ # may not have been deleted (again, see PR 169471 and SVN
+ # r263114 for details).
+ #
+ if [ "${user_group_delete:-$msg_no}" != "$msg_no" ]
+ then
+ f_quietly pw groupshow -g "$user_gid" &&
+ f_eval_catch $funcname pw \
+ "pw groupdel -g '%s'" "$_user_gid"
+ elif ! f_quietly pw groupshow -g "$group_gid" &&
+ [ "$group_name" -a "$group_gid" ]
+ then
+ # Group deleted by pw(8), so restore it
+ local cmd="pw groupadd -n '$_group_name'"
+ cmd="$cmd -g '$_group_gid'"
+ cmd="$cmd -M '$_group_members'"
+ local group_password_enc
+ group_password_enc=$( getent group | awk -F: '
+ !/^[[:space:]]*(#|$)/ && \
+ $1 == ENVIRON["group_name"] && \
+ $3 == ENVIRON["group_gid"] && \
+ $4 == ENVIRON["group_members"] \
+ { print $2; exit }
+ ' )
+ if [ "$group_password_enc" ]; then
+ echo "$group_password_enc" |
+ f_eval_catch $funcname \
+ pw '%s -H 0' "$cmd"
+ else
+ f_eval_catch $funcname \
+ pw '%s -h -' "$cmd"
+ fi
+ fi
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_login_deleted"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+# f_user_edit [$user]
+#
+# Modify a login account. If both $user (as a first argument) and $VAR_USER are
+# unset or NULL and we are running interactively, prompt the end-user to select
+# a login account from a list of those available. Variables that can be used to
+# script user input:
+#
+# VAR_USER [Optional if running interactively]
+# The login to modify. Ignored if given non-NULL first-argument.
+# VAR_USER_ACCOUNT_EXPIRE [Optional]
+# The account expiration time. Format is similar to
+# VAR_USER_PASSWORD_EXPIRE variable below. If unset, account
+# expiry is unchanged. If set but NULL, account expiration is
+# disabled (same as setting a value of `0').
+# VAR_USER_DOTFILES_CREATE [Optional]
+# If non-NULL, re-populate the user's home directory with the
+# template files found in $udotdir (`/usr/share/skel' default).
+# VAR_USER_GECOS [Optional]
+# Often the full name of the account holder. If unset, the GECOS
+# field is unmodified. If set but NULL, the field is blanked.
+# VAR_USER_GID [Optional]
+# Numerical primary-group ID to set. If NULL or unset, the group
+# ID is unchanged.
+# VAR_USER_GROUPS [Optional]
+# Comma-separated list of additional groups to which the user is
+# a member of. If set but NULL, group memberships are reset (this
+# login will not be a member of any additional groups besides the
+# primary group). If unset, group membership is unmodified.
+# VAR_USER_HOME [Optional]
+# The home directory to set. If NULL or unset, the home directory
+# is unchanged.
+# VAR_USER_HOME_CREATE [Optional]
+# If non-NULL, create the user's home directory if it doesn't
+# already exist.
+# VAR_USER_LOGIN_CLASS [Optional]
+# Login class to set. If unset, the login class is unchanged. If
+# set but NULL, the field is blanked.
+# VAR_USER_PASSWORD [Optional]
+# Unencrypted password to set. If unset, the login password is
+# unmodified. If set but NULL, password authentication for the
+# login is disabled.
+# VAR_USER_PASSWORD_EXPIRE [Optional]
+# The password expiration time. Format of the date is either a
+# UNIX time in decimal, or a date in dd-mmm-yy[yy] format, where
+# dd is the day, mmm is the month in either numeric or alphabetic
+# format, and yy[yy] is either a two or four digit year. This
+# variable also accepts a relative date in the form of +n[mhdwoy]
+# where n is a decimal, octal (leading 0) or hexadecimal (leading
+# 0x) digit followed by the number of Minutes, Hours, Days,
+# Weeks, Months or Years from the current date at which the
+# expiration time is to be set. If unset, password expiry is
+# unchanged. If set but NULL, password expiration is disabled
+# (same as setting a value of `0').
+# VAR_USER_SHELL [Optional]
+# Path to login shell to set. If NULL or unset, the shell is
+# unchanged.
+# VAR_USER_UID [Optional]
+# Numerical user ID to set. If NULL or unset, the user ID is
+# unchanged.
+#
+# Returns success if the user account was successfully modified.
+#
+f_user_edit()
+{
+ local funcname=f_user_edit
+ local title # Calculated below
+ local alert=f_show_msg no_confirm=
+
+ f_getvar $VAR_NO_CONFIRM no_confirm
+ [ "$no_confirm" ] && alert=f_show_info
+
+ local input
+ f_getvar 3:-\$$VAR_USER input "$1"
+
+ #
+ # NB: pw(8) has a ``feature'' wherein `-n name' can be taken as UID
+ # instead of name. Work-around is to also pass `-u UID' at the same
+ # time (any UID will do; but `-1' is appropriate for this context).
+ #
+ if [ "$input" ] && ! f_quietly pw usershow -n "$input" -u -1; then
+ f_show_err "$msg_login_not_found" "$input"
+ return $FAILURE
+ fi
+
+ if f_interactive && [ ! "$input" ]; then
+ f_dialog_menu_user_list || return $SUCCESS
+ f_dialog_menutag_fetch input
+ [ "$input" = "X $msg_exit" ] && return $SUCCESS
+ elif [ ! "$input" ]; then
+ f_show_err "$msg_no_user_specified"
+ return $FAILURE
+ fi
+
+ local user_account_expire user_class user_gecos user_gid user_home_dir
+ local user_member_groups user_name user_password user_password_expire
+ local user_shell user_uid # Variables created by f_input_user() below
+ if ! f_input_user "$input"; then
+ f_show_err "$msg_login_not_found" "$input"
+ return $FAILURE
+ fi
+
+ #
+ # Override values probed by f_input_user() with desired values
+ #
+ f_isset $VAR_USER_GID && f_getvar $VAR_USER_GID user_gid
+ f_isset $VAR_USER_HOME && f_getvar $VAR_USER_HOME user_home_dir
+ f_isset $VAR_USER_SHELL && f_getvar $VAR_USER_SHELL user_shell
+ f_isset $VAR_USER_UID && f_getvar $VAR_USER_UID user_uid
+ local user_dotfiles_create= user_home_create=
+ f_getvar $VAR_USER_DOTFILES_CREATE:+\$msg_yes user_dotfiles_create
+ f_getvar $VAR_USER_HOME_CREATE:+\$msg_yes user_home_create
+ local no_account_expire=
+ if f_isset $VAR_USER_ACCOUNT_EXPIRE; then
+ f_getvar $VAR_USER_ACCOUNT_EXPIRE user_account_expire
+ [ "$user_account_expire" ] || no_account_expire=1
+ fi
+ local null_gecos=
+ if f_isset $VAR_USER_GECOS; then
+ f_getvar $VAR_USER_GECOS user_gecos
+ [ "$user_gecos" ] || null_gecos=1
+ fi
+ local null_members=
+ if f_isset $VAR_USER_GROUPS; then
+ f_getvar $VAR_USER_GROUPS user_member_groups
+ [ "$user_member_groups" ] || null_members=1
+ fi
+ local null_class=
+ if f_isset $VAR_USER_LOGIN_CLASS; then
+ f_getvar $VAR_USER_LOGIN_CLASS user_class
+ [ "$user_class" ] || null_class=1
+ fi
+ local user_password_disable=
+ if f_isset $VAR_USER_PASSWORD; then
+ f_getvar $VAR_USER_PASSWORD user_password
+ [ "$user_password" ] || user_password_disable=1
+ fi
+ local no_password_expire=
+ if f_isset $VAR_USER_PASSWORD_EXPIRE; then
+ f_getvar $VAR_USER_PASSWORD_EXPIRE user_password_expire
+ [ "$user_password_expire" ] || no_password_expire=1
+ fi
+
+ #
+ # Loop until the user decides to Exit, Cancel, or presses ESC
+ #
+ title="$msg_edit_view $msg_user: $user_name"
+ if f_interactive; then
+ local mtag retval defaultitem=
+ while :; do
+ f_dialog_title "$title"
+ f_dialog_menu_user_edit "$defaultitem"
+ retval=$?
+ f_dialog_title_restore
+ f_dialog_menutag_fetch mtag
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ defaultitem="$mtag"
+
+ # Return if user either pressed ESC or chose Cancel/No
+ [ $retval -eq $DIALOG_OK ] || return $FAILURE
+
+ case "$mtag" in
+ X) # Save/Exit
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ local cmd="pw usermod -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o \
+ "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_home_dir" ] &&
+ cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_member_groups" -o "$null_members" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o \
+ "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ if [ "$user_password_disable" ]; then
+ f_eval_catch $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ echo "$user_password" | f_eval_catch \
+ $funcname pw '%s -h 0' "$cmd"
+ else
+ f_eval_catch $funcname pw '%s' "$cmd"
+ fi || continue
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ] && f_user_copy_dotfiles "$user_name"
+
+ break # to success
+ ;;
+ 1) # Login (select different login from list)
+ f_dialog_menu_user_list "$user_name" || continue
+ f_dialog_menutag_fetch mtag
+
+ [ "$mtag" = "X $msg_exit" ] && continue
+
+ if ! f_input_user "$mtag"; then
+ f_show_err "$msg_login_not_found" "$mtag"
+ # Attempt to fall back to previous selection
+ f_input_user "$input" || return $FAILURE
+ else
+ input="$mtag"
+ fi
+ title="$msg_edit_view $msg_user: $user_name"
+ ;;
+ 2) # Full Name
+ f_dialog_input_gecos user_gecos "$user_gecos" &&
+ [ ! "$user_gecos" ] && null_gecos=1 ;;
+ 3) # Password
+ f_dialog_input_password \
+ user_password user_password_disable ;;
+ 4) # User ID
+ f_dialog_input_uid user_uid "$user_uid" ;;
+ 5) # Group ID
+ f_dialog_input_gid user_gid "$user_gid" ;;
+ 6) # Member of Groups
+ f_dialog_input_member_groups \
+ user_member_groups "$user_member_groups" &&
+ [ ! "$user_member_groups" ] &&
+ null_members=1 ;;
+ 7) # Login Class
+ f_dialog_input_class user_class "$user_class" &&
+ [ ! "$user_class" ] && null_class=1 ;;
+ 8) # Password Expires On
+ f_dialog_input_expire_password \
+ user_password_expire "$user_password_expire" &&
+ [ ! "$user_password_expire" ] &&
+ no_password_expire=1 ;;
+ 9) # Account Expires On
+ f_dialog_input_expire_account \
+ user_account_expire "$user_account_expire" &&
+ [ ! "$user_account_expire" ] &&
+ no_account_expire=1 ;;
+ A) # Home Directory
+ f_dialog_input_home_dir \
+ user_home_dir "$user_home_dir" ;;
+ B) # Shell
+ f_dialog_input_shell user_shell "$user_shell" ;;
+ C) # Create Home Directory?
+ if [ "${user_home_create:-$msg_no}" != "$msg_no" ]
+ then
+ user_home_create="$msg_no"
+ else
+ user_home_create="$msg_yes"
+ fi ;;
+ D) # Create Dotfiles?
+ if [ "${user_dotfiles_create:-$msg_no}" != \
+ "$msg_no" ]
+ then
+ user_dotfiles_create="$msg_no"
+ else
+ user_dotfiles_create="$msg_yes"
+ fi ;;
+ esac
+ done
+ else
+ local var
+ for var in account_expire class gecos gid home_dir \
+ member_groups name password_expire shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ # Form the command
+ local cmd="pw usermod -n '$_user_name'"
+ [ "$user_gid" ] && cmd="$cmd -g '$_user_gid'"
+ [ "$user_home_dir" ] && cmd="$cmd -d '$_user_home_dir'"
+ [ "$user_shell" ] && cmd="$cmd -s '$_user_shell'"
+ [ "$user_uid" ] && cmd="$cmd -u '$_user_uid'"
+ [ "$user_account_expire" -o "$no_account_expire" ] &&
+ cmd="$cmd -e '$_user_account_expire'"
+ [ "$user_class" -o "$null_class" ] &&
+ cmd="$cmd -L '$_user_class'"
+ [ "$user_gecos" -o "$null_gecos" ] &&
+ cmd="$cmd -c '$_user_gecos'"
+ [ "$user_member_groups" -o "$null_members" ] &&
+ cmd="$cmd -G '$_user_member_groups'"
+ [ "$user_password_expire" -o "$no_password_expire" ] &&
+ cmd="$cmd -p '$_user_password_expire'"
+
+ # Execute the command
+ local retval err
+ if [ "$user_password_disable" ]; then
+ f_eval_catch -k err $funcname pw '%s -h -' "$cmd"
+ elif [ "$user_password" ]; then
+ err=$( echo "$user_password" | f_eval_catch -de \
+ $funcname pw '%s -h 0' "$cmd" 2>&1 )
+ else
+ f_eval_catch -k err $funcname pw '%s' "$cmd"
+ fi
+ retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ f_show_err "%s" "$err"
+ return $retval
+ fi
+
+ # Create home directory if desired
+ [ "${user_home_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_create_homedir "$user_name"
+
+ # Copy dotfiles if desired
+ [ "${user_dotfiles_create:-$msg_no}" != "$msg_no" ] &&
+ f_user_copy_dotfiles "$user_name"
+ fi
+
+ f_dialog_title "$title"
+ $alert "$msg_login_updated"
+ f_dialog_title_restore
+ [ "$no_confirm" -a "$USE_DIALOG" ] && sleep 1
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." usermgmt/user.subr
+
+fi # ! $_USERMGMT_USER_SUBR
diff --git a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
index bd2fc9b..39578c8 100644
--- a/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
+++ b/usr.sbin/bsdconfig/usermgmt/share/user_input.subr
@@ -1,7 +1,7 @@
if [ ! "$_USERMGMT_USER_INPUT_SUBR" ]; then _USERMGMT_USER_INPUT_SUBR=1
#
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -48,39 +48,57 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
############################################################ FUNCTIONS
-# f_get_member_groups $user
+# f_get_member_groups $var_to_set $user
#
# Get a list of additional groups $user is a member of in group(5).
#
f_get_member_groups()
{
- echo $( pw groupshow -a | awk -F: "/[:,]$1(,|\$)/{print \$1}" )
+ f_replaceall "$( pw groupshow -a | awk -F: -v user="$2" '{
+ if (!split($4, users, /,/)) next
+ for (u in users) if (users[u] == user) { print $1; next }
+ }' )" "[$NL]" "," "$1"
}
# f_input_user $user
#
-# Given $user name or id, create the environment variables 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).
+# Given $user name or id, create the environment variables user_name, user_uid,
+# user_gid, user_class, user_password_expire, user_account_expire, user_gecos,
+# user_home_dir, user_shell, and user_member_groups (and user_password is reset
+# to NULL).
#
f_input_user()
{
+ local funcname=f_input_user
local user="$1"
- eval $( pw usershow "$user" | awk -F: '
+
+ f_dprintf "$funcname: Getting info for user \`%s'" "$user"
+ eval "$( pw usershow "$user" 2> /dev/null | awk -F: '
+ function set_value(var, value) {
+ gsub(/'\''/, "'\''\\'\'\''", value)
+ printf "user_%s='\'%s\''\n", var, value
+ }
{
- 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" )
+ found = $1 != ""
+ set_value("name", $1 )
+ set_value("password", "" )
+ set_value("uid", $3 )
+ set_value("gid", $4 )
+ set_value("class", $5 )
+ set_value("password_expire", $6 )
+ set_value("account_expire", $7 )
+ set_value("gecos", $8 )
+ set_value("home_dir", $9 )
+ set_value("shell", $10)
+ exit
+ }
+ END { if (!found) print "false" }' )"
+ local retval=$?
+
+ f_dprintf "$funcname: Getting group memberships for user \`%s'" "$user"
+ f_get_member_groups user_member_groups "$user"
+
+ return $retval
}
# f_dialog_menu_user_list [$default]
@@ -99,10 +117,13 @@ f_dialog_menu_user_list()
# Add users from passwd(5)
menu_list="$menu_list $( pw usershow -a | awk -F: '
- !/^[[:space:]]*(#|$)/ {
- printf "'\'%s\'\ \'%s\''\n", $1, $8
- }'
- )"
+ function mprint(tag, item) {
+ gsub(/'\''/, "'\''\\'\'\''", tag)
+ gsub(/'\''/, "'\''\\'\'\''", item)
+ printf "'\'%s\'\ \'%s\''\n", tag, item
+ }
+ !/^[[:space:]]*(#|$)/ { mprint($1, $8) }
+ ' )"
local height width rows
eval f_dialog_menu_size height width rows \
@@ -130,760 +151,710 @@ f_dialog_menu_user_list()
return $retval
}
-# f_dialog_input_member_groups [$member_groups]
+# f_dialog_input_member_groups $var_to_set [$member_groups]
#
# Allows the user to edit group memberships for a given user. If the user does
-# not cancel or press ESC, the $pw_member_groups variable will hold the newly-
+# not cancel or press ESC, the $var_to_set 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
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_member_of_groups"
+ local __menu_list="
+ 'X' '$msg_continue'
+ '1' '$msg_select_groups_from_list'
+ '2' '$msg_enter_groups_manually'
+ " # END-QUOTE
+ local __defaultitem=
+ local __hline="$hline_alnum_space_tab_enter"
- #
- # 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
+ local __mheight __mwidth __mrows
+ eval f_dialog_menu_size __mheight __mwidth __mrows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__menu_list
- #
- # Loop until the user provides taint-free/valid input
- #
- local height width rows
+ local __menu_choice __retval
while :; do
- eval f_dialog_checklist_size height width rows \
- \"\$DIALOG_TITLE\" \
- \"\$DIALOG_BACKTITLE\" \
- \"\$prompt\" \
- \"\$hline\" \
- $check_list
- _member_groups=$( eval $DIALOG \
+ __menu_choice=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --separate-output \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --checklist \"\$prompt\" \
- $height $width $rows \
- $check_list \
+ --default-item \"\$__defaultitem\" \
+ --menu \"\$__prompt\" \
+ $__mheight $__mwidth $__mrows \
+ $__menu_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
+ )
+ __retval=$?
+ f_dialog_data_sanitize __menu_choice
+ __defaultitem="$__menu_choice"
+ f_dprintf "retval=%u menu_choice=[%s]" \
+ $__retval "$__menu_choice"
- pw_member_groups="$_member_groups"
- break
- done
- save_flag=1
+ # Return if user has either pressed ESC or chosen Cancel/No
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
- f_dprintf "pw_member_groups: [%s]->[%s]" \
- "$cur_pw_member_groups" "$pw_member_groups"
+ local __member_groups
+ case "$__menu_choice" in
+ X) # Exit
+ break ;;
+ 1) # Select Groups from a list
+ local __check_list= # Calculated below
+ local __group_list __g __grp __length=0
+ __group_list=$( pw groupshow -a |
+ awk -F: '!/^[[:space:]]*(#|$)/{print $1}' )
+ while [ $__length -ne ${#__group_list} ]; do
+ __g="${__group_list%%$NL*}" # First line
+ f_shell_escape "$__g" __grp
+
+ # Format of a checklist entry: tag item status
+ # NB: Setting both tag/item to group name below
+ __check_list="$__check_list '$__grp' '$__grp'"
+ case "$__input" in
+ "$__g"|"$__g",*|*,"$__g",*|*,"$__g")
+ __check_list="$__check_list on" ;;
+ *)
+ __check_list="$__check_list off"
+ esac
+
+ __length=${#__group_list}
+ __group_list="${__group_list#*$NL}" # Kill line
+ done
+
+ local __cheight __cwidth __crows
+
+ eval f_dialog_checklist_size \
+ __cheight __cwidth __crows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__check_list
+ __member_groups=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --separate-output \
+ --hline \"\$__hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --checklist \"\$__prompt\" \
+ $__cheight $__cwidth $__crows \
+ $__check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || continue
+ # Return to previous menu if user either
+ # pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize __member_groups
+
+ #
+ # Convert the newline separated list into a comma-
+ # separated one so that if the user switches over to
+ # manual editing, list reflects checklist selections
+ #
+ f_replaceall "$__member_groups" "[$NL]" "," __input
+ ;;
+ 2) # Enter Groups manually
+ local __prompt2="$msg_groups"
+ __prompt2="$__prompt2 ($msg_separated_by_commas)"
+
+ f_dialog_input __member_groups \
+ "$__prompt2" "$__input" \
+ "$hline_num_tab_enter" || continue
+ # Return to previous menu if user either
+ # pressed ESC or chose Cancel/No
+
+ #
+ # Validate each of the groups the user has entered
+ #
+ local __all_groups_valid=1 __grp __grp_list
+ f_replaceall "$__member_groups" "," " " __grp_list
+ for __grp in $__grp_list; do
+ if ! f_quietly pw groupshow -n "$__grp"; then
+ f_show_msg "$msg_group_not_found" \
+ "$__grp"
+ __all_groups_valid=
+ break
+ fi
+ done
+ [ "$__all_groups_valid" ] || continue
+
+ __input="$__member_groups"
+ ;;
+ esac
+ done
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_name [$name]
+# f_dialog_input_name $var_to_set [$name]
#
# Allows the user to enter a new username for a given user. If the user does
-# not cancel or press ESC, the $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).
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
#
f_dialog_input_name()
{
+ local __var_to_set="$1" __name="$2"
+
#
# Loop until the user provides taint-free/valid input
#
- local _name="$1" _input="$1"
+ local __input="$__name"
while :; do
-
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_login" "$_input" \
+ f_dialog_input __input "$msg_login" "$__input" \
"$hline_alnum_tab_enter" || return $?
# Check for no-change
- [ "$_input" = "$_name" ] && return $DIALOG_OK
-
- # Check for reversion
- if [ "$_input" = "$cur_pw_name" ]; then
- pw_name="$cur_pw_name"
+ if [ "$__input" = "$__name" ]; then
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
fi
# Check for NULL entry
- if [ ! "$_input" ]; then
+ if [ ! "$__input" ]; then
f_show_msg "$msg_login_is_empty"
continue
fi
# Check for invalid entry
- if ! echo "$_input" | grep -q "^[[:alpha:]]"; then
+ case "$__input" in [!a-zA-Z]*)
f_show_msg "$msg_login_must_start_with_letter"
continue
- fi
+ esac
# Check for duplicate entry
- if f_quietly pw usershow -n "$_input"; then
- f_show_msg "$msg_login_already_used" "$_input"
+ if f_quietly pw usershow -n "$__input"; then
+ f_show_msg "$msg_login_already_used" "$__input"
continue
fi
- pw_name="$_input"
+ setvar "$__var_to_set" "$__input"
break
done
- save_flag=1
-
- f_dprintf "pw_name: [%s]->[%s]" "$cur_pw_name" "$pw_name"
return $DIALOG_OK
}
-# f_dialog_input_password
+# f_dialog_input_password $var_to_set $dvar_to_set
#
-# Prompt the user to enter a password (twice).
+# Prompt the user to enter a password (twice). If the user does not cancel or
+# press ESC, $var_to_set will hold the confirmed user entry. Otherwise, if the
+# user cancels or enters a NULL password (twice), they are given the choice to
+# disable password authentication for the given login, wherein $dvar_to_set has
+# a value of 1 to indicate password authentication should be disabled.
#
f_dialog_input_password()
{
- local prompt1="$msg_password"
- local prompt2="$msg_reenter_password"
- local hline="$hline_alnum_punc_tab_enter"
+ local __var_to_set="$1" __dvar_to_set="$2"
+ local __prompt1="$msg_password"
+ local __prompt2="$msg_reenter_password"
+ local __hline="$hline_alnum_punc_tab_enter"
- local height1 width1
- f_dialog_inputbox_size height1 width1 \
+ local __height1 __width1
+ f_dialog_inputbox_size __height1 __width1 \
"$DIALOG_TITLE" \
"$DIALOG_BACKTITLE" \
- "$prompt1" \
+ "$__prompt1" \
"" \
- "$hline"
- local height2 width2
- f_dialog_inputbox_size height2 width2 \
+ "$__hline"
+ local __height2 __width2
+ f_dialog_inputbox_size __height2 __width2 \
"$DIALOG_TITLE" \
"$DIALOG_BACKTITLE" \
- "$prompt2" \
+ "$__prompt2" \
"" \
- "$hline"
+ "$__hline"
#
# Loop until the user provides taint-free/valid input
#
- local _password1 _password2
+ local __retval __password1 __password2
while :; do
- _password1=$( $DIALOG \
+ __password1=$( $DIALOG \
--title "$DIALOG_TITLE" \
--backtitle "$DIALOG_BACKTITLE" \
- --hline "$hline" \
+ --hline "$__hline" \
--ok-label "$msg_ok" \
--cancel-label "$msg_cancel" \
--insecure \
- --passwordbox "$prompt1" \
- $height1 $width1 \
+ --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
+ debug= f_dialog_line_sanitize __password1
- _password2=$( $DIALOG \
+ __password2=$( $DIALOG \
--title "$DIALOG_TITLE" \
--backtitle "$DIALOG_BACKTITLE" \
- --hline "$hline" \
+ --hline "$__hline" \
--ok-label "$msg_ok" \
--cancel-label "$msg_cancel" \
--insecure \
- --passwordbox "$prompt2" \
- $height2 $width2 \
+ --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
+ debug= f_dialog_line_sanitize __password2
# Check for password mismatch
- if [ "$_password1" != "$_password2" ]; then
+ if [ "$__password1" != "$__password2" ]; then
f_show_msg "$msg_passwords_do_not_match"
continue
fi
# Check for NULL entry
- if [ ! "$_password1" ]; then
+ if [ ! "$__password1" ]; then
f_dialog_yesno "$msg_disable_password_auth_for_account"
- local retval=$?
- if [ $retval -eq $DIALOG_ESC ]; then
- return $retval
- elif [ $retval -eq $DIALOG_OK ]; then
- pw_password_disable=1
+ __retval=$?
+ if [ $__retval -eq $DIALOG_ESC ]; then
+ return $__retval
+ elif [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__dvar_to_set" 1
else
continue # back to password prompt
fi
else
- pw_password_disable=
+ setvar "$__dvar_to_set" ""
fi
- pw_password="$_password1"
+ setvar "$__var_to_set" "$__password1"
break
done
- save_flag=1
-
- f_dprintf "pw_password: [%s]->[%s]" "$cur_pw_password" "$pw_password"
return $DIALOG_OK
}
-# f_dialog_input_gecos [$gecos]
+# f_dialog_input_gecos $var_to_set [$gecos]
#
# Allow the user to enter new GECOS information for a given user. This
# information is commonly used to store the ``Full Name'' of the user. If the
-# user does not cancel or press ESC, the $pw_gecos variable will hold the
+# user does not cancel or press ESC, the $var_to_set variable will hold the
# newly-configured value upon return.
#
f_dialog_input_gecos()
{
- local _input="$1"
+ local __var_to_set="$1" __input="$2"
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_full_name" "$_input" \
+ 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"
-
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_uid [$uid]
+# f_dialog_input_uid $var_to_set [$uid]
#
# Allow the user to enter a new UID for a given user. If the user does not
-# cancel or press ESC, the $pw_uid variable will hold the newly-configured
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
# value upon return.
#
f_dialog_input_uid()
{
- local _input="$1"
+ local __var_to_set="$1" __input="$2"
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_user_id_leave_empty_for_default" \
- "$_input" "$hline_num_tab_enter" || return $?
-
- pw_uid="$_input"
- save_flag=1
-
- f_dprintf "pw_uid: [%s]->[%s]" "$cur_pw_uid" "$pw_uid"
+ f_dialog_input __input "$msg_user_id_leave_empty_for_default" \
+ "$__input" "$hline_num_tab_enter" || return $?
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_gid [$gid]
+# f_dialog_input_gid $var_to_set [$gid]
#
# Allow the user to enter a new primary GID for a given user. If the user does
-# not cancel or press ESC, the $pw_gid variable will hold the newly-configured
-# value upon return.
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
+# configured value upon return.
#
f_dialog_input_gid()
{
- local _input="$1"
+ local __var_to_set="$1" __input="$2"
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_group_id_leave_empty_for_default" \
- "$_input" "$hline_num_tab_enter" || return $?
-
- pw_gid="$_input"
- save_flag=1
-
- f_dprintf "pw_gid: [%s]->[%s]" "$cur_pw_gid" "$pw_gid"
+ f_dialog_input __input "$msg_group_id_leave_empty_for_default" \
+ "$__input" "$hline_num_tab_enter" || return $?
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_class [$class]
+# f_dialog_input_class $var_to_set [$class]
#
# Allow the user to enter a new login class for a given user. If the user does
-# not cancel or press ESC, the $pw_class variable will hold the newly-
+# not cancel or press ESC, the $var_to_set variable will hold the newly-
# configured value upon return.
#
f_dialog_input_class()
{
- local _input="$1"
+ local __var_to_set="$1" __input="$2"
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_login_class" "$_input" \
+ 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"
-
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_expire_password [$seconds]
+# f_dialog_input_expire_password $var_to_set [$seconds]
#
# Allow the user to enter a date/time (in number-of-seconds since the `epoch')
# for when a given user's password must be changed. If the user does not cancel
-# or press ESC, the $pw_password_expire variable will hold the newly-
-# configured value upon return.
+# or press ESC, the $var_to_set variable will hold the newly-configured value
+# upon return.
#
f_dialog_input_expire_password()
{
- local prompt="$msg_password_expires_on"
- local menu_list="
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_password_expires_on"
+ local __menu_list="
'1' '$msg_password_does_not_expire'
'2' '$msg_edit_date_time_with_a_calendar'
- '3' '$msg_enter_number_of_days_into_the_future'
- '4' '$msg_enter_value_manually'
+ '3' '$msg_enter_value_manually'
" # END-QUOTE
- local hline="$hline_num_arrows_tab_enter"
- local retval _input="$1"
+ local __defaultitem= # Calculated below
+ local __hline="$hline_num_arrows_tab_enter"
- local mheight mwidth mrows
- eval f_dialog_menu_size mheight mwidth mrows \
+ 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 \
+ \"\$__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 \
+ "$__prompt" \
+ "$__hline"
+ local __theight __twidth
+ f_dialog_timebox_size __theight __twidth \
"$DIALOG_TITLE" \
"$DIALOG_BACKTITLE" \
- "$prompt" \
- "$hline"
+ "$__prompt" \
+ "$__hline"
#
# Loop until the user provides taint-free/cancellation-free input
#
- local date_type defaultitem=
+ local __retval __date_type
while :; do
- date_type=$( eval $DIALOG \
+ __date_type=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
- --default-item \"\$defaultitem\" \
+ --hline \"\$__hline\" \
+ --default-item \"\$__defaultitem\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --menu \"\$prompt\" \
- $mheight $mwidth $mrows \
- $menu_list \
+ --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"
+ __retval=$?
+ f_dialog_data_sanitize __date_type
+ __defaultitem="$__date_type"
+ f_dprintf "retval=%u date_type=[%s]" $__retval "$__date_type"
# Return if user has either pressed ESC or chosen Cancel/No
- [ $retval -eq $DIALOG_OK ] || return $retval
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
- case "$date_type" in
+ case "$__date_type" in
1) # Password does not expire
- _input=""
- break ;;
+ __input= break ;;
2) # Edit date/time with a calendar
- local _input_date _input_time ret_date ret_time
+ 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" \
+ local __seconds="$__input"
+ { f_isinteger "$__seconds" && [ $__seconds -gt 0 ]; } ||
+ __seconds=
+ __input_date=$( date -j -f "%s" -- "$__seconds" \
"+%d %m %Y" 2> /dev/null )
- ret_date=$( eval $DIALOG \
+ __ret_date=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --calendar \"\$prompt\" \
- $cheight $cwidth \
- $_input_date \
+ --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"
+ __retval=$?
+ f_dialog_data_sanitize __ret_date
+ f_dprintf "retval=%u ret_date=[%s]" \
+ $__retval "$__ret_date"
# Return to menu if either ESC or Cancel/No
- [ $retval -eq $DIALOG_OK ] || continue
+ [ $__retval -eq $DIALOG_OK ] || continue
- _input_time=
- [ "$secs" ] && _input_time=$( date -j \
- -f %s -- "$_input" "+%H %M %S" 2> /dev/null )
- ret_time=$( eval $DIALOG \
+ __input_time=
+ [ "$__seconds" ] && __input_time=$( date -j \
+ -f %s -- "$__input" "+%H %M %S" 2> /dev/null )
+ __ret_time=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --timebox \"\$prompt\" \
- $theight $twidth \
- $_input_time \
+ --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"
+ __retval=$?
+ f_dialog_data_sanitize __ret_time
+ f_dprintf "retval=%u ret_time=[%s]" \
+ $__retval "$__ret_time"
# Return to menu if either ESC or Cancel/No
- [ $retval -eq $DIALOG_OK ] || continue
+ [ $__retval -eq $DIALOG_OK ] || continue
- _input=$( date \
- -j -f "%d/%m/%Y %T" \
- -- "$ret_date $ret_time" \
- +%s 2> /dev/null )
- f_dprintf "_input=[%s]" "$_input"
+ __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 ))
+ 3) # Enter value manually
+ local __msg __new_input
+ f_sprintf __msg "$msg_password_expire_manual_edit" \
+ "$( date -r 0 "+%c %Z" )"
# Return to menu if either ESC or Cancel/No
- f_dialog_input 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_dialog_input __new_input \
+ "$__msg" "$__input" "$__hline" || continue
- 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"
+ __input="$__new_input"
+ 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"
-
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_expire_account [$seconds]
+# f_dialog_input_expire_account $var_to_set [$seconds]
#
# Allow the user to enter a date/time (in number-of-seconds since the `epoch')
# for when a given user's account should become expired. If the user does not
-# cancel or press ESC, the $pw_account_expire variable will hold the newly-
-# configured value upon return.
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
+# value upon return.
#
f_dialog_input_expire_account()
{
- local prompt="$msg_account_expires_on"
- local menu_list="
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_account_expires_on"
+ local __menu_list="
'1' '$msg_account_does_not_expire'
'2' '$msg_edit_date_time_with_a_calendar'
- '3' '$msg_enter_number_of_days_into_the_future'
- '4' '$msg_enter_value_manually'
+ '3' '$msg_enter_value_manually'
" # END-QUOTE
- local hline="$hline_num_arrows_tab_enter"
- local retval _input="$1"
+ local __defaultitem= # Calculated below
+ local __hline="$hline_num_arrows_tab_enter"
- local mheight mwidth mrows
- eval f_dialog_menu_size mheight mwidth mrows \
+ 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 \
+ \"\$__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 \
+ "$__prompt" \
+ "$__hline"
+ local __theight __twidth
+ f_dialog_timebox_size __theight __twidth \
"$DIALOG_TITLE" \
"$DIALOG_BACKTITLE" \
- "$prompt" \
- "$hline"
+ "$__prompt" \
+ "$__hline"
#
# Loop until the user provides taint-free/cancellation-free input
#
- local date_type defaultitem=
+ local __retval __date_type
while :; do
- date_type=$( eval $DIALOG \
+ __date_type=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
- --default-item \"\$defaultitem\" \
+ --hline \"\$__hline\" \
+ --default-item \"\$__defaultitem\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --menu \"\$prompt\" \
- $mheight $mwidth $mrows \
- $menu_list \
+ --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"
+ __retval=$?
+ f_dialog_data_sanitize __date_type
+ __defaultitem="$__date_type"
+ f_dprintf "retval=%u date_type=[%s]" $__retval "$__date_type"
# Return if user has either pressed ESC or chosen Cancel/No
- [ $retval -eq $DIALOG_OK ] || return $retval
+ [ $__retval -eq $DIALOG_OK ] || return $__retval
- case "$date_type" in
+ case "$__date_type" in
1) # Account does not expire
- _input=""
- break ;;
+ __input= break ;;
2) # Edit date/time with a calendar
- local _input_date _input_time ret_date ret_time
+ 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" \
+ local __seconds="$__input"
+ { f_isinteger "$__seconds" && [ $__seconds -gt 0 ]; } ||
+ __seconds=
+ __input_date=$( date -j -f "%s" -- "$__seconds" \
"+%d %m %Y" 2> /dev/null )
- ret_date=$( eval $DIALOG \
+ __ret_date=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --calendar \"\$prompt\" \
- $cheight $cwidth \
- $_input_date \
+ --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"
+ __retval=$?
+ f_dialog_data_sanitize __ret_date
+ f_dprintf "retval=%u ret_date=[%s]" \
+ $__retval "$__ret_date"
# Return to menu if either ESC or Cancel/No
- [ $retval -eq $DIALOG_OK ] || continue
+ [ $__retval -eq $DIALOG_OK ] || continue
- _input_time=
- [ "$secs" ] && _input_time=$( date -j \
- -f %s -- "$_input" "+%H %M %S" 2> /dev/null )
- ret_time=$( eval $DIALOG \
+ __input_time=
+ [ "$__seconds" ] && __input_time=$( date -j \
+ -f %s -- "$__input" "+%H %M %S" 2> /dev/null )
+ __ret_time=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --timebox \"\$prompt\" \
- $theight $twidth \
- $_input_time \
+ --timebox \"\$__prompt\" \
+ $__theight $__twidth \
+ $__input_time \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
)
- retval=$?
- f_dialog_data_sanitize ret_time
- f_dprintf "retval=%u ret_time=[%s]" $retval "$ret_time"
-
- # Return to menu if either ESC or Cancel/No
- [ $retval -eq $DIALOG_OK ] || continue
-
- _input=$( date \
- -j -f "%d/%m/%Y %T" \
- -- "$ret_date $ret_time" \
- +%s 2> /dev/null )
- f_dprintf "_input=[%s]" "$_input"
- break ;;
-
- 3) # Enter 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 ))
+ __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
- 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
+ [ $__retval -eq $DIALOG_OK ] || continue
- 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"
+ __input=$( date -j -f "%d/%m/%Y %T" -- \
+ "$ret_date $ret_time" +%s 2> /dev/null )
+ 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" )" )
+ 3) # Enter value manually
+ local __msg __new_input
+ f_sprintf __msg "$msg_account_expire_manual_edit" \
+ "$( date -r 0 "+%c %Z" )"
# Return to menu if either ESC or Cancel/No
- f_dialog_input 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_dialog_input __new_input \
+ "$__msg" "$__input" "$__hline" || continue
- f_dprintf "_input=[%s]" "$_input"
+ __input="$__new_input"
+ 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"
-
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_home_dir [$home_dir]
+# f_dialog_input_home_dir $var_to_set [$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-
+# Allow the user to enter a new home directory for a given login. If the user
+# does not cancel or press ESC, the $var_to_set variable will hold the newly-
# configured value upon return.
#
f_dialog_input_home_dir()
{
- local _input="$1"
+ local __var_to_set="$1" __input="$2"
# Return if user has either pressed ESC or chosen Cancel/No
- f_dialog_input _input "$msg_home_directory" "$_input" \
+ 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"
-
+ setvar "$__var_to_set" "$__input"
return $DIALOG_OK
}
-# f_dialog_input_home_create
+# f_dialog_input_home_create $var_to_set
#
-# 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
+# Prompt the user to confirm creation of a given login's home directory. If the
+# user does not cancel (by choosing "No") or press ESC, the $var_to_set
# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return
# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible.
#
f_dialog_input_home_create()
{
- local retval
+ local __var_to_set="$1"
f_dialog_yesno "$msg_create_home_directory"
- retval=$?
+ local __retval=$?
- if [ $retval -eq $DIALOG_OK ]; then
- pw_home_create="$msg_yes"
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
else
- pw_home_create="$msg_no"
+ setvar "$__var_to_set" "$msg_no"
fi
- save_flag=1
- f_dprintf "pw_home_create: [%s]->[%s]" \
- "$cur_pw_home_create" "$pw_home_create"
-
- [ $retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
}
-# f_dialog_input_group_delete
+# f_dialog_input_group_delete $var_to_set [$group]
#
-# 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
+# Prompt the user to confirm deletion of a given login's primary group. If the
+# user does not cancel (by choosing "No") or press ESC, the $var_to_set
# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return
# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible.
#
f_dialog_input_group_delete()
{
- local retval
+ local __var_to_set="$1" __group="$2"
- if f_isinteger "$pw_gid"; then
- if [ $pw_gid -lt 1000 ]; then
+ if f_isinteger "$__group"; then
+ if [ $__group -lt 1000 ]; then
f_dialog_noyes "$msg_delete_primary_group"
else
f_dialog_yesno "$msg_delete_primary_group"
fi
- elif [ "$pw_gid" ]; then
- local gid=0
- gid=$( pw groupshow "$pw_gid" | awk -F: '{print $3}' )
- if f_isinteger "$gid" && [ $gid -lt 1000 ]; then
+ elif [ "$__group" ]; then
+ local __gid=0
+ __gid=$( pw groupshow "$__group" | awk -F: '{print $3}' )
+ if f_isinteger "$__gid" && [ $__gid -lt 1000 ]; then
f_dialog_noyes "$msg_delete_primary_group"
else
f_dialog_yesno "$msg_delete_primary_group"
@@ -891,131 +862,473 @@ f_dialog_input_group_delete()
else
f_dialog_yesno "$msg_delete_primary_group"
fi
- retval=$?
+ local __retval=$?
- if [ $retval -eq $DIALOG_OK ]; then
- pw_group_delete="$msg_yes"
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
else
- pw_group_delete="$msg_no"
+ setvar "$__var_to_set" "$msg_no"
fi
- save_flag=1
-
- f_dprintf "pw_group_delete: [%s]->[%s]" \
- "$cur_pw_group_delete" "$pw_group_delete"
- [ $retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
}
-# f_dialog_input_home_delete
+# f_dialog_input_home_delete $var_to_set
#
-# 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
+# Prompt the user to confirm deletion of a given login's home directory. If the
+# user does not cancel (by choosing "No") or press ESC, the $var_to_set
# variable will hold $msg_yes upon return, otherwise $msg_no. Use these return
# variables ($msg_yes and $msg_no) for comparisons to be i18n-compatible.
#
f_dialog_input_home_delete()
{
- local retval
+ local __var_to_set="$1"
f_dialog_yesno "$msg_delete_home_directory"
- retval=$?
+ local __retval=$?
- if [ $retval -eq $DIALOG_OK ]; then
- pw_home_delete="$msg_yes"
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
else
- pw_home_delete="$msg_no"
+ setvar "$__var_to_set" "$msg_no"
fi
- save_flag=1
- f_dprintf "pw_home_delete: [%s]->[%s]" \
- "$cur_pw_home_delete" "$pw_home_delete"
-
- [ $retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+ [ $__retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
}
-# f_dialog_input_dotfiles_create
+# f_dialog_input_dotfiles_create $var_to_set
#
-# Prompt the user to confirm population of a given user's home directory with
+# Prompt the user to confirm population of a given login's home directory with
# sample dotfiles. If the user does not cancel (by choosing "No") or press ESC,
-# the $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.
+# the $var_to_set variable will hold $msg_yes upon return, otherwise $msg_no.
+# Use these return variables ($msg_yes and $msg_no) for comparison to be i18n-
+# compatible.
#
f_dialog_input_dotfiles_create()
{
- local retval
+ local __var_to_set="$1"
f_dialog_yesno "$msg_create_dotfiles"
- retval=$?
+ local __retval=$?
- if [ $retval -eq $DIALOG_OK ]; then
- pw_dotfiles_create="$msg_yes"
+ if [ $__retval -eq $DIALOG_OK ]; then
+ setvar "$__var_to_set" "$msg_yes"
else
- pw_dotfiles_create="$msg_no"
+ setvar "$__var_to_set" "$msg_no"
fi
- save_flag=1
-
- f_dprintf "pw_dotfiles_create: [%s]->[%s]" \
- "$cur_pw_dotfiles_create" "$pw_dotfiles_create"
- [ $retval -ne $DIALOG_ESC ] # return failure if user pressed ESC
+ [ $__retval -ne $DIALOG_ESC ] # 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 $var_to_set [$shell]
#
+# Allow the user to select a new shell for a given login. If the user does not
+# cancel or press ESC, the $var_to_set variable will hold the newly-configured
+# value upon return.
#
f_dialog_input_shell()
{
- local _input="$1"
- local prompt="$msg_select_login_shell"
- local radio_list= # Calculated below
- local hline="$hline_arrows_space_tab_enter"
+ local __funcname=f_dialog_input_shell
+ local __var_to_set="$1" __input="$2"
+ local __prompt="$msg_select_login_shell"
+ local __radio_list= # Calculated below
+ local __defaultitem="$2"
+ local __hline="$hline_arrows_space_tab_enter"
#
# Generate the radiolist of shells
#
- local shell
- 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'"
+ local __shell_list __s __shell __length=0
+ f_eval_catch -k __shell_list $__funcname awk "awk '%s' \"%s\"" \
+ '!/^[[:space:]]*(#|$)/{print}' "$ETC_SHELLS" || return $FAILURE
+ while [ $__length -ne ${#__shell_list} ]; do
+ __s="${__shell_list%%$NL*}" # First line
+ f_shell_escape "$__s" __shell
+
+ # Format of a radiolist entry: tag item status
+ if [ "$__s" = "$__input" ]; then
+ __radio_list="$__radio_list '$__shell' '' 'on'"
else
- radio_list="$radio_list '$shell' '' 'off'"
+ __radio_list="$__radio_list '$__shell' '' 'off'"
fi
+
+ __length=${#__shell_list}
+ __shell_list="${__shell_list#*$NL}" # Kill line
done
- local height width rows
- eval f_dialog_radiolist_size height width rows \
+ local __height __width __rows
+ eval f_dialog_radiolist_size __height __width __rows \
\"\$DIALOG_TITLE\" \
\"\$DIALOG_BACKTITLE\" \
- \"\$prompt\" \
- \"\$hline\" \
- $radio_list
+ \"\$__prompt\" \
+ \"\$__hline\" \
+ $__radio_list
- _input=$( eval $DIALOG \
+ __input=$( eval $DIALOG \
--title \"\$DIALOG_TITLE\" \
--backtitle \"\$DIALOG_BACKTITLE\" \
- --hline \"\$hline\" \
+ --hline \"\$__hline\" \
--ok-label \"\$msg_ok\" \
--cancel-label \"\$msg_cancel\" \
- --radiolist \"\$prompt\" \
- $height $width $rows \
- $radio_list \
+ --default-item \"\$__defaultitem\" \
+ --radiolist \"\$__prompt\" \
+ $__height $__width $__rows \
+ $__radio_list \
2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
) || return $?
# Return if user either pressed ESC or chose Cancel/No
- f_dialog_data_sanitize _input
+ f_dialog_data_sanitize __input
- pw_shell="$_input"
- save_flag=1
+ setvar "$__var_to_set" "$__input"
+ return $DIALOG_OK
+}
- f_dprintf "pw_shell: [%s]->[%s]" "$cur_pw_shell" "$pw_shell"
+# f_dialog_menu_user_add [$defaultitem]
+#
+# Present a menu detailing the properties of a login that is about to be added.
+# The user's menu choice is available using f_dialog_menutag_fetch(). Returns
+# success unless the user chose Cancel or pressed ESC. Data to display is taken
+# from environment variables user_account_expire, user_class,
+# user_dotfiles_create, user_gecos, user_gid, user_home_create, user_home_dir,
+# user_member_groups, user_name, user_password_expire, user_shell, and
+# user_uid. If $defaultitem is present and non-NULL, initially highlight the
+# item in the menu.
+#
+f_dialog_menu_user_add()
+{
+ local funcname=f_dialog_menu_user_add
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
- return $DIALOG_OK
+ # Attempt to convert numeric UNIX time to calendar date/time
+ local user_account_expires_on=
+ if f_isinteger "$user_account_expire"; then
+ [ "$user_account_expire" -ne 0 ] && user_account_expires_on=$(
+ date -r "$user_account_expire" "+%F %T %Z"
+ )
+ else
+ user_account_expires_on="$user_account_expire"
+ fi
+ local user_password_expires_on=
+ if f_isinteger "$user_password_expire"; then
+ [ $user_password_expire -ne 0 ] && user_password_expires_on=$(
+ date -r "$user_password_expire" "+%F %T %Z"
+ )
+ else
+ user_password_expires_on="$user_password_expire"
+ fi
+
+ # Attempt to translate a numeric GID into `number (name)'
+ if f_isinteger "$user_gid"; then
+ local user_group
+ user_group=$( pw groupshow -g "$user_gid" 2> /dev/null ) &&
+ user_gid="$user_gid (${user_group%%:*})"
+ fi
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in account_expires_on class dotfiles_create gecos gid \
+ home_create home_dir member_groups name password_expires_on \
+ shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ menu_list="
+ 'X' '$msg_add/$msg_exit'
+ '1' '$msg_login: $_user_name'
+ '2' '$msg_full_name: $_user_gecos'
+ '3' '$msg_password: -----'
+ '4' '$msg_user_id: $_user_uid'
+ '5' '$msg_group_id: $_user_gid'
+ '6' '$msg_member_of_groups: $_user_member_groups'
+ '7' '$msg_login_class: $_user_class'
+ '8' '$msg_password_expires_on: $_user_password_expires_on'
+ '9' '$msg_account_expires_on: $_user_account_expires_on'
+ 'A' '$msg_home_directory: $_user_home_dir'
+ 'B' '$msg_shell: $_user_shell'
+ " # END-QUOTE
+ case "$user_home_dir" in
+ /|/nonexistent|/var/empty) menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ '-' '$msg_create_dotfiles: $msg_n_a'
+ " # END-QUOTE
+ ;;
+ *) if [ -d "$user_home_dir" ]; then menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ 'C' '$msg_create_home_directory: ${_user_home_create:-$msg_no}'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ fi
+ esac
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --keep-tite \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_user_delete $user [$defaultitem]
+#
+# Present a menu detailing the properties of a login that is about to be
+# deleted. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is populated automatically from the system accounting database for the given
+# $user argument with the exception of two environment variables:
+# user_group_delete and user_home_delete. If $defaultitem is present and non-
+# NULL, initially highlight the item in the menu.
+#
+f_dialog_menu_user_delete()
+{
+ local prompt="$msg_delete_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$2"
+ local hline="$hline_arrows_tab_enter"
+
+ local user_name user_password user_uid user_gid user_class
+ local user_password_expire user_account_expire user_gecos
+ local user_home_dir user_shell user_member_groups
+ f_input_user "$1"
+
+ # Attempt to convert numeric UNIX time to calendar date/time
+ local user_account_expires_on=
+ if f_isinteger "$user_account_expire"; then
+ [ "$user_account_expire" -ne 0 ] && user_account_expires_on=$(
+ date -r "$user_account_expire" "+%F %T %Z"
+ )
+ else
+ user_account_expires_on="$user_account_expire"
+ fi
+ local user_password_expires_on=
+ if f_isinteger "$user_password_expire"; then
+ [ $user_password_expire -ne 0 ] && user_password_expires_on=$(
+ date -r "$user_password_expire" "+%F %T %Z"
+ )
+ else
+ user_password_expires_on="$user_password_expire"
+ fi
+
+ # Attempt to translate a numeric GID into `number (name)'
+ if f_isinteger "$user_gid"; then
+ local user_group
+ user_group=$( pw groupshow -g "$user_gid" 2> /dev/null ) &&
+ user_gid="$user_gid (${user_group%%:*})"
+ fi
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in account_expires_on class gecos gid group_delete \
+ home_delete home_dir member_groups name password_expires_on \
+ shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ menu_list="
+ 'X' '$msg_delete/$msg_exit'
+ '1' '$msg_login: $_user_name'
+ '-' '$msg_full_name: $_user_gecos'
+ '-' '$msg_password: -----'
+ '-' '$msg_user_id: $_user_uid'
+ '-' '$msg_group_id: $_user_gid'
+ '-' '$msg_group_members: $_user_member_groups'
+ '-' '$msg_login_class: $_user_class'
+ '-' '$msg_password_expires_on: $_user_password_expires_on'
+ '-' '$msg_account_expires_on: $_user_account_expires_on'
+ '-' '$msg_home_directory: $_user_home_dir'
+ '-' '$msg_shell: $_user_shell'
+ " # END-QUOTE
+ if f_quietly pw groupshow -g "$user_gid"; then menu_list="$menu_list
+ 'C' '$msg_delete_primary_group: ${_user_group_delete:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ '-' '$msg_delete_primary_group: $msg_n_a'
+ " # END-QUOTE
+ fi
+ case "$user_home_dir" in
+ /|/nonexistent|/var/empty) menu_list="$menu_list
+ '-' '$msg_delete_home_directory: $msg_n_a'
+ " # END-QUOTE
+ ;;
+ *) if [ -d "$user_home_dir" ]; then menu_list="$menu_list
+ 'D' '$msg_delete_home_directory: ${_user_home_delete:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ '-' '$msg_delete_home_directory: $msg_n_a'
+ " # END-QUOTE
+ fi
+ esac
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --keep-tite \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
+}
+
+# f_dialog_menu_user_edit [$defaultitem]
+#
+# Present a menu detailing the properties of a login that is about to be
+# modified. The user's menu choice is available using f_dialog_menutag_fetch().
+# Returns success unless the user chose Cancel or pressed ESC. Data to display
+# is taken from environment variables user_account_expire, user_class,
+# user_dotfiles_create, user_gecos, user_gid, user_home_create, user_home_dir,
+# user_member_groups, user_name, user_password_expire, user_shell, and
+# user_uid. If $defaultitem is present and non-NULL, initially highlight the
+# item in the menu.
+#
+f_dialog_menu_user_edit()
+{
+ local prompt="$msg_save_exit_or_cancel"
+ local menu_list # Calculated below
+ local defaultitem="$1"
+ local hline="$hline_arrows_tab_enter"
+
+ # Attempt to convert numeric UNIX time to calendar date/time
+ local user_account_expires_on=
+ if f_isinteger "$user_account_expire"; then
+ [ "$user_account_expire" -ne 0 ] && user_account_expires_on=$(
+ date -r "$user_account_expire" "+%F %T %Z"
+ )
+ else
+ user_account_expires_on="$user_account_expire"
+ fi
+ local user_password_expires_on=
+ if f_isinteger "$user_password_expire"; then
+ [ $user_password_expire -ne 0 ] && user_password_expires_on=$(
+ date -r "$user_password_expire" "+%F %T %Z"
+ )
+ else
+ user_password_expires_on="$user_password_expire"
+ fi
+
+ # Attempt to translate a numeric GID into `number (name)'
+ if f_isinteger "$user_gid"; then
+ local user_group
+ user_group=$( pw groupshow -g "$user_gid" 2> /dev/null ) &&
+ user_gid="$user_gid (${user_group%%:*})"
+ fi
+
+ # Localize potentially hostile variables and escape their values
+ # to the local variable (see f_shell_escape() of `strings.subr')
+ local var
+ for var in account_expires_on class dotfiles_create gecos gid \
+ home_create home_dir member_groups name password_expires_on \
+ shell uid \
+ ; do
+ local _user_$var
+ eval f_shell_escape \"\$user_$var\" _user_$var
+ done
+
+ menu_list="
+ 'X' '$msg_save/$msg_exit'
+ '1' '$msg_login: $_user_name'
+ '2' '$msg_full_name: $_user_gecos'
+ '3' '$msg_password: -----'
+ '4' '$msg_user_id: $_user_uid'
+ '5' '$msg_group_id: $_user_gid'
+ '6' '$msg_member_of_groups: $_user_member_groups'
+ '7' '$msg_login_class: $_user_class'
+ '8' '$msg_password_expires_on: $_user_password_expires_on'
+ '9' '$msg_account_expires_on: $_user_account_expires_on'
+ 'A' '$msg_home_directory: $_user_home_dir'
+ 'B' '$msg_shell: $_user_shell'
+ " # END-QUOTE
+ case "$user_home_dir" in
+ /|/nonexistent|/var/empty) menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ '-' '$msg_create_dotfiles: $msg_n_a'
+ " # END-QUOTE
+ ;;
+ *) if [ -d "$user_home_dir" ]; then menu_list="$menu_list
+ '-' '$msg_create_home_directory: $msg_n_a'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ else menu_list="$menu_list
+ 'C' '$msg_create_home_directory: ${_user_home_create:-$msg_no}'
+ 'D' '$msg_create_dotfiles: ${_user_dotfiles_create:-$msg_no}'
+ " # END-QUOTE
+ fi
+ esac
+
+ local height width rows
+ eval f_dialog_menu_size height width rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --keep-tite \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+ return $retval
}
############################################################ MAIN
diff --git a/usr.sbin/bsdconfig/usermgmt/useradd b/usr.sbin/bsdconfig/usermgmt/useradd
index b8cac27..d372be4 100755
--- a/usr.sbin/bsdconfig/usermgmt/useradd
+++ b/usr.sbin/bsdconfig/usermgmt/useradd
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,11 +33,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
+f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -55,9 +58,19 @@ done
shift $(( $OPTIND - 1 ))
#
-# Chain-load to userinput to centralize code and minimize duplication
+# Initialize
#
-$BSDCFG_LIBE/$APP_DIR/userinput ${USE_XDIALOG:+-X} mode="Add"
+f_dialog_title "$msg_add $msg_user"
+f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
+f_mustberoot_init
+
+#
+# Add a user
+#
+# NB: If given an argument on the command-line use it; otherwise fall-back to
+# environment variable $user (handle $VAR_USER).
+#
+f_user_add ${1:+"$1"}
################################################################################
# END
diff --git a/usr.sbin/bsdconfig/usermgmt/userdel b/usr.sbin/bsdconfig/usermgmt/userdel
index 299e25b..9425c7b 100755
--- a/usr.sbin/bsdconfig/usermgmt/userdel
+++ b/usr.sbin/bsdconfig/usermgmt/userdel
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
f_include $BSDCFG_SHARE/usermgmt/user_input.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -65,9 +66,17 @@ f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
f_mustberoot_init
#
+# If given a user name, operate on it and exit
+#
+if [ "$1" ]; then
+ f_user_delete "$1"
+ exit $SUCCESS
+fi
+
+#
# Loop until the user Exits, Cancels or presses ESC
#
-defaultitem=""
+defaultitem=
while :; do
f_dialog_menu_user_list "$defaultitem"
retval=$?
@@ -81,8 +90,7 @@ while :; do
# Anything else is a userid
- $BSDCFG_LIBE/$APP_DIR/userinput \
- ${USE_XDIALOG:+-X} mode="Delete" user="$mtag"
+ f_user_delete "$mtag"
done
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/usermgmt/useredit b/usr.sbin/bsdconfig/usermgmt/useredit
index a4bee68..612f3a6 100755
--- a/usr.sbin/bsdconfig/usermgmt/useredit
+++ b/usr.sbin/bsdconfig/usermgmt/useredit
@@ -1,7 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012-2013 Devin Teske
+# Copyright (c) 2012-2014 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -34,13 +34,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/usermgmt/user.subr
f_include $BSDCFG_SHARE/usermgmt/user_input.subr
BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="070.usermgmt"
f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
-ipgm=$( f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" )
-[ $? -eq $SUCCESS -a "$ipgm" ] && pgm="$ipgm"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ MAIN
@@ -65,9 +66,17 @@ f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
f_mustberoot_init
#
-# Loop until the user Exits, Cancels or presses ESC
+# If given a user name, operate on it and exit
#
-defaultitem=""
+if [ "$1" ]; then
+ f_user_edit "$1"
+ exit $SUCCESS
+fi
+
+#
+# Present a list of users and loop until user Exits, Cancels or presses ESC
+#
+defaultitem=
while :; do
f_dialog_menu_user_list "$defaultitem"
retval=$?
@@ -81,8 +90,7 @@ while :; do
# Anything else is a userid
- $BSDCFG_LIBE/$APP_DIR/userinput \
- ${USE_XDIALOG:+-X} mode="Edit/View" user="$mtag"
+ f_user_edit "$mtag"
done
exit $SUCCESS
diff --git a/usr.sbin/bsdconfig/usermgmt/userinput b/usr.sbin/bsdconfig/usermgmt/userinput
deleted file mode 100755
index aad6ef3..0000000
--- a/usr.sbin/bsdconfig/usermgmt/userinput
+++ /dev/null
@@ -1,529 +0,0 @@
-#!/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 $DIALOG_ESC ]; then
- exit $SUCCESS
- elif [ $retval -ne $DIALOG_OK ]; 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 $DIALOG_OK ] || 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 $DIALOG_OK ] || 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
index 5335bd6..79fbc95 100755
--- a/usr.sbin/bsdconfig/usermgmt/usermgmt
+++ b/usr.sbin/bsdconfig/usermgmt/usermgmt
@@ -40,8 +40,8 @@ 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"
+f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
+ pgm="${ipgm:-$pgm}"
############################################################ FUNCTIONS
diff --git a/usr.sbin/bsdinstall/bsdinstall b/usr.sbin/bsdinstall/bsdinstall
index 2b55501..a258e47 100755
--- a/usr.sbin/bsdinstall/bsdinstall
+++ b/usr.sbin/bsdinstall/bsdinstall
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,15 +26,63 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+# Delay processing of debug flags as the parent until MAIN. export'd to disable
+# re-processing of flags (all children log to the parent's log file).
+#
+export DEBUG_SELF_INITIALIZE=
+export DEBUG_INITIALIZE_FILE=
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ GLOBALS
-: ${BSDINSTALL_LOG="/tmp/bsdinstall_log"}; export BSDINSTALL_LOG
: ${BSDINSTALL_TMPETC="/tmp/bsdinstall_etc"}; export BSDINSTALL_TMPETC
+: ${BSDINSTALL_TMPBOOT="/tmp/bsdinstall_boot"}; export BSDINSTALL_TMPBOOT
: ${PATH_FSTAB="$BSDINSTALL_TMPETC/fstab"}; export PATH_FSTAB
: ${BSDINSTALL_DISTDIR="/usr/freebsd-dist"}; export BSDINSTALL_DISTDIR
: ${BSDINSTALL_CHROOT="/mnt"}; export BSDINSTALL_CHROOT
-VERB=${1:-auto}; shift
+export debugFile="${debugFile-${BSDINSTALL_LOG-/tmp/bsdinstall_log}}"
+
+############################################################ MAIN
+
+#
+# Process command-line arguments
+#
+while getopts $GETOPTS_STDARGS ignored; do
+ : just skipping known flags
+done
+shift $(( $OPTIND - 1 ))
+
+# What are we here to do?
+VERB="${1:-auto}"; shift
[ -d "$BSDINSTALL_TMPETC" ] || mkdir -p "$BSDINSTALL_TMPETC"
-echo "Running installation step: $VERB $@" >> "$BSDINSTALL_LOG"
-exec "/usr/libexec/bsdinstall/$VERB" "$@" 2>> "$BSDINSTALL_LOG"
+[ -d "$BSDINSTALL_TMPBOOT" ] || mkdir -p "$BSDINSTALL_TMPBOOT"
+
+# Only enable debugging if debugFile is non-NULL and can be initialized
+f_quietly f_debug_init
+f_isset debugFile || debug=
+
+f_dprintf "Running installation step: %s %s" "$VERB" "$*"
+if [ "$debug" ]; then
+ case "$debugFile" in
+ # If NULL, send errors to the bit-bucket
+ "") exec "/usr/libexec/bsdinstall/$VERB" "$@" 2> /dev/null ;;
+ # If begins with `+', send errors to both terminal and file (no `+')
+ +*) exec "/usr/libexec/bsdinstall/$VERB" "$@" \
+ 2>&1 >&$TERMINAL_STDOUT_PASSTHRU | tee "${debugFile#+}" ;;
+ # Otherwise, just send errors to the file specified
+ *) exec "/usr/libexec/bsdinstall/$VERB" "$@" 2>> "$debugFile"
+ esac
+else
+ exec "/usr/libexec/bsdinstall/$VERB" "$@" 2> /dev/null
+fi
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/bsdinstall.8 b/usr.sbin/bsdinstall/bsdinstall.8
index 095062f..b841c36 100644
--- a/usr.sbin/bsdinstall/bsdinstall.8
+++ b/usr.sbin/bsdinstall/bsdinstall.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 21, 2013
+.Dd October 15, 2013
.Dt BSDINSTALL 8
.Os
.Sh NAME
@@ -33,6 +33,7 @@
.Nd system installer
.Sh SYNOPSIS
.Nm
+.Op Ar options
.Op Ar target
.Op Ar ...
.Sh DESCRIPTION
@@ -49,6 +50,18 @@ invoked with no arguments, it will invoke the
target, which provides a standard interactive installation, invoking the
others in sequence. To perform a scripted installation, these subtargets
can be invoked separately by an installation script.
+.Sh OPTIONS
+.Nm
+supports the following options, global to all targets:
+.Bl -tag -width indent+
+.It Fl D Ar file
+Provide a path for the installation log file
+.Pq overrides Ev BSDINSTALL_LOG .
+See
+.Sx ENVIRONMENT VARIABLES
+for more information on
+.Ev BSDINSTALL_LOG .
+.El
.Sh TARGETS
Most of the following targets are only useful for scripting the installer.
For interactive use, most users will be interested only in the
@@ -60,6 +73,10 @@ targets.
.Bl -tag -width ".Cm jail Ar destination"
.It Cm auto
Run the standard interactive installation, including disk partitioning.
+.It Cm entropy
+Reads a small amount of data from
+.Pa /dev/random
+and stores it in a file in the new system's root directory.
.It Cm jail Ar destination
Sets up a new chroot system at
.Pa destination ,
@@ -104,6 +121,21 @@ installations. Partitions disks, runs
.Xr newfs 8 ,
and writes the new system's
.Pa fstab .
+.It Cm zfsboot
+Provides the installer's
+.Pq experimental
+interactive/scriptable ZFS partitioner for multi-disk installations.
+Creates a single
+.Ic zpool
+with datasets and writes to the new system's
+.Pa rc.conf ,
+.Pa loader.conf ,
+and
+.Pa fstab .
+Supports
+.Xr geli 8 ,
+.Xr gnop 8 ,
+and many other features.
.It Cm partedit
Provides the installer's interactive manual disk partitioner, with support
for multi disk setups, non-UFS file systems, and manual selection of
@@ -250,6 +282,14 @@ will be stored until the
target is executed. If this directory does not already exist, it will be
created. Default:
.Pa /tmp/bsdinstall_etc
+.It Ev BSDINSTALL_TMPBOOT
+Directory where files destined for the new system's
+.Pa /boot
+will be stored until the
+.Cm config
+target is executed. If this directory does not already exist, it will be
+created. Default:
+.Pa /tmp/bsdinstall_boot
.El
.Sh SCRIPTING
.Nm
@@ -303,6 +343,15 @@ the preamble can contain a variable
which is passed to the
.Cm scriptedpart
target to control disk setup.
+Alternatively,
+instead of
+.Ev PARTITIONS ,
+the preamble can contain the variable
+.Ev ZFSBOOT_DATASETS
+which is parsed by the
+.Pq experimental
+.Cm zfsboot
+target to control ZFS datasets/options of the boot pool setup.
.Ss SETUP SCRIPT
Following the preamble is an optional shell script, beginning with a #!
declaration. This script will be run at the end of the installation process
diff --git a/usr.sbin/bsdinstall/distextract/Makefile b/usr.sbin/bsdinstall/distextract/Makefile
index a76e764..1910b23 100644
--- a/usr.sbin/bsdinstall/distextract/Makefile
+++ b/usr.sbin/bsdinstall/distextract/Makefile
@@ -2,10 +2,20 @@
BINDIR= /usr/libexec/bsdinstall
PROG= distextract
-DPADD= ${LIBARCHIVE} ${LIBNCURSESW} ${LIBDIALOG} ${LIBM}
-LDADD= -larchive -lncursesw -ldialog -lm
+DPADD= ${LIBARCHIVE} ${LIBDIALOG} ${LIBM}
+LDADD= -larchive -ldialog -lm
WARNS?= 6
-NO_MAN= true
+MAN=
+
+.include <bsd.own.mk>
+
+.if ${MK_NCURSESW} == "no"
+DPADD+= ${LIBNCURSES}
+LDADD+= -lncurses
+.else
+DPADD+= ${LIBNCURSESW}
+LDADD+= -lncursesw
+.endif
.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdinstall/distfetch/Makefile b/usr.sbin/bsdinstall/distfetch/Makefile
index bb82908..08eb91c 100644
--- a/usr.sbin/bsdinstall/distfetch/Makefile
+++ b/usr.sbin/bsdinstall/distfetch/Makefile
@@ -2,10 +2,20 @@
BINDIR= /usr/libexec/bsdinstall
PROG= distfetch
-DPADD= ${LIBFETCH} ${LIBNCURSESW} ${LIBDIALOG} ${LIBM}
-LDADD= -lfetch -lncursesw -ldialog -lm
+DPADD= ${LIBFETCH} ${LIBDIALOG} ${LIBM}
+LDADD= -lfetch -ldialog -lm
WARNS?= 6
-NO_MAN= true
+MAN=
+
+.include <bsd.own.mk>
+
+.if ${MK_NCURSESW} == "no"
+DPADD+= ${LIBNCURSES}
+LDADD+= -lncurses
+.else
+DPADD+= ${LIBNCURSESW}
+LDADD+= -lncursesw
+.endif
.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdinstall/partedit/Makefile b/usr.sbin/bsdinstall/partedit/Makefile
index fb75888..3eb0d3f 100644
--- a/usr.sbin/bsdinstall/partedit/Makefile
+++ b/usr.sbin/bsdinstall/partedit/Makefile
@@ -5,8 +5,8 @@ PROG= partedit
LINKS= ${BINDIR}/partedit ${BINDIR}/autopart \
${BINDIR}/partedit ${BINDIR}/scriptedpart
SYMLINKS= ${BINDIR}/partedit /usr/sbin/sade
-DPADD= ${LIBGEOM} ${LIBNCURSESW} ${LIBUTIL} ${LIBDIALOG} ${LIBM}
-LDADD= -lgeom -lncursesw -lutil -ldialog -lm
+DPADD= ${LIBGEOM} ${LIBUTIL} ${LIBDIALOG} ${LIBM}
+LDADD= -lgeom -lutil -ldialog -lm
PARTEDIT_ARCH= ${MACHINE}
.if ${MACHINE} == "i386" || ${MACHINE} == "amd64"
@@ -22,4 +22,14 @@ SRCS= diskeditor.c partedit.c gpart_ops.c partedit_${PARTEDIT_ARCH}.c \
WARNS?= 3
MAN= sade.8
+.include <bsd.own.mk>
+
+.if ${MK_NCURSESW} == "no"
+DPADD+= ${LIBNCURSES}
+LDADD+= -lncurses
+.else
+DPADD+= ${LIBNCURSESW}
+LDADD+= -lncursesw
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdinstall/partedit/gpart_ops.c b/usr.sbin/bsdinstall/partedit/gpart_ops.c
index 289ac98..27feb57 100644
--- a/usr.sbin/bsdinstall/partedit/gpart_ops.c
+++ b/usr.sbin/bsdinstall/partedit/gpart_ops.c
@@ -584,7 +584,7 @@ set_default_part_metadata(const char *name, const char *scheme,
if (strcmp(type, "freebsd-swap") == 0)
mountpoint = "none";
- if (strcmp(type, "freebsd-boot") == 0)
+ if (strcmp(type, bootpart_type(scheme)) == 0)
md->bootcode = 1;
/* VTOC8 needs partcode in UFS partitions */
@@ -949,7 +949,8 @@ addpartform:
LIST_FOREACH(gc, &pp->lg_config, lg_config)
if (strcmp(gc->lg_name, "type") == 0)
break;
- if (gc != NULL && strcmp(gc->lg_val, "freebsd-boot") == 0)
+ if (gc != NULL && strcmp(gc->lg_val,
+ bootpart_type(scheme)) == 0)
break;
}
@@ -971,7 +972,7 @@ addpartform:
gctl_ro_param(r, "arg0", -1, geom->lg_name);
gctl_ro_param(r, "flags", -1, GPART_FLAGS);
gctl_ro_param(r, "verb", -1, "add");
- gctl_ro_param(r, "type", -1, "freebsd-boot");
+ gctl_ro_param(r, "type", -1, bootpart_type(scheme));
snprintf(sizestr, sizeof(sizestr), "%jd",
bootpart_size(scheme) / sector);
gctl_ro_param(r, "size", -1, sizestr);
@@ -1031,7 +1032,7 @@ addpartform:
gctl_issue(r); /* Error usually expected and non-fatal */
gctl_free(r);
- if (strcmp(items[0].text, "freebsd-boot") == 0)
+ if (strcmp(items[0].text, bootpart_type(scheme)) == 0)
get_part_metadata(newpartname, 1)->bootcode = 1;
else if (strcmp(items[0].text, "freebsd") == 0)
gpart_partition(newpartname, "BSD");
diff --git a/usr.sbin/bsdinstall/partedit/partedit.h b/usr.sbin/bsdinstall/partedit/partedit.h
index 121e3a2..32e3a36 100644
--- a/usr.sbin/bsdinstall/partedit/partedit.h
+++ b/usr.sbin/bsdinstall/partedit/partedit.h
@@ -74,9 +74,10 @@ void set_default_part_metadata(const char *name, const char *scheme,
/* machine-dependent bootability checks */
const char *default_scheme(void);
-int is_scheme_bootable(const char *part_type);
-size_t bootpart_size(const char *part_type);
-const char *bootcode_path(const char *part_type);
-const char *partcode_path(const char *part_type);
+int is_scheme_bootable(const char *scheme);
+size_t bootpart_size(const char *scheme);
+const char *bootpart_type(const char *scheme);
+const char *bootcode_path(const char *scheme);
+const char *partcode_path(const char *scheme);
#endif
diff --git a/usr.sbin/bsdinstall/partedit/partedit_generic.c b/usr.sbin/bsdinstall/partedit/partedit_generic.c
index 96faafa..8498a78 100644
--- a/usr.sbin/bsdinstall/partedit/partedit_generic.c
+++ b/usr.sbin/bsdinstall/partedit/partedit_generic.c
@@ -58,6 +58,11 @@ bootpart_size(const char *part_type) {
}
const char *
+bootpart_type(const char *scheme) {
+ return ("freebsd-boot");
+}
+
+const char *
bootcode_path(const char *part_type) {
return (NULL);
}
diff --git a/usr.sbin/bsdinstall/partedit/partedit_pc98.c b/usr.sbin/bsdinstall/partedit/partedit_pc98.c
index ec438f6..dd075a1 100644
--- a/usr.sbin/bsdinstall/partedit/partedit_pc98.c
+++ b/usr.sbin/bsdinstall/partedit/partedit_pc98.c
@@ -52,6 +52,11 @@ bootpart_size(const char *part_type) {
}
const char *
+bootpart_type(const char *scheme) {
+ return ("freebsd-boot");
+}
+
+const char *
bootcode_path(const char *part_type) {
if (strcmp(part_type, "PC98") == 0)
return ("/boot/pc98boot");
diff --git a/usr.sbin/bsdinstall/partedit/partedit_powerpc.c b/usr.sbin/bsdinstall/partedit/partedit_powerpc.c
index 06129c7..4fa2e05 100644
--- a/usr.sbin/bsdinstall/partedit/partedit_powerpc.c
+++ b/usr.sbin/bsdinstall/partedit/partedit_powerpc.c
@@ -74,6 +74,11 @@ bootpart_size(const char *part_type) {
}
const char *
+bootpart_type(const char *scheme) {
+ return ("freebsd-boot");
+}
+
+const char *
bootcode_path(const char *part_type) {
return (NULL);
}
diff --git a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c
index b8ee052..8232c55 100644
--- a/usr.sbin/bsdinstall/partedit/partedit_sparc64.c
+++ b/usr.sbin/bsdinstall/partedit/partedit_sparc64.c
@@ -50,6 +50,11 @@ bootpart_size(const char *part_type) {
}
const char *
+bootpart_type(const char *scheme) {
+ return ("freebsd-boot");
+}
+
+const char *
bootcode_path(const char *part_type) {
return (NULL);
}
diff --git a/usr.sbin/bsdinstall/partedit/partedit_x86.c b/usr.sbin/bsdinstall/partedit/partedit_x86.c
index a03a7a7..156674b 100644
--- a/usr.sbin/bsdinstall/partedit/partedit_x86.c
+++ b/usr.sbin/bsdinstall/partedit/partedit_x86.c
@@ -26,10 +26,15 @@
* $FreeBSD$
*/
+#include <sys/types.h>
+#include <sys/sysctl.h>
#include <string.h>
#include "partedit.h"
+static char platform[255] = "";
+static const char *platform_sysctl = "machdep.bootmethod";
+
const char *
default_scheme(void) {
return ("GPT");
@@ -37,27 +42,60 @@ default_scheme(void) {
int
is_scheme_bootable(const char *part_type) {
- if (strcmp(part_type, "BSD") == 0)
- return (1);
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
+
if (strcmp(part_type, "GPT") == 0)
return (1);
- if (strcmp(part_type, "MBR") == 0)
- return (1);
+ if (strcmp(platform, "BIOS") == 0) {
+ if (strcmp(part_type, "BSD") == 0)
+ return (1);
+ if (strcmp(part_type, "MBR") == 0)
+ return (1);
+ }
return (0);
}
size_t
-bootpart_size(const char *part_type) {
- if (strcmp(part_type, "GPT") == 0)
- return (64*1024);
+bootpart_size(const char *scheme) {
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
/* No partcode except for GPT */
+ if (strcmp(scheme, "GPT") != 0)
+ return (0);
+
+ if (strcmp(platform, "BIOS") == 0)
+ return (64*1024);
+ else
+ return (800*1024);
+
return (0);
}
const char *
+bootpart_type(const char *scheme) {
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
+
+ if (strcmp(platform, "UEFI") == 0)
+ return ("efi");
+
+ return ("freebsd-boot");
+}
+
+const char *
bootcode_path(const char *part_type) {
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
+ if (strcmp(platform, "UEFI") == 0)
+ return (NULL);
+
if (strcmp(part_type, "GPT") == 0)
return ("/boot/pmbr");
if (strcmp(part_type, "MBR") == 0)
@@ -70,8 +108,16 @@ bootcode_path(const char *part_type) {
const char *
partcode_path(const char *part_type) {
- if (strcmp(part_type, "GPT") == 0)
- return ("/boot/gptboot");
+ size_t platlen = sizeof(platform);
+ if (strlen(platform) == 0)
+ sysctlbyname(platform_sysctl, platform, &platlen, NULL, -1);
+
+ if (strcmp(part_type, "GPT") == 0) {
+ if (strcmp(platform, "UEFI") == 0)
+ return ("/boot/boot1.efifat");
+ else
+ return ("/boot/gptboot");
+ }
/* No partcode except for GPT */
return (NULL);
diff --git a/usr.sbin/bsdinstall/scripts/Makefile b/usr.sbin/bsdinstall/scripts/Makefile
index bcfafc0..efe9700 100644
--- a/usr.sbin/bsdinstall/scripts/Makefile
+++ b/usr.sbin/bsdinstall/scripts/Makefile
@@ -1,10 +1,10 @@
# $FreeBSD$
-SCRIPTS= auto adduser checksum config docsinstall hostname jail keymap \
- mirrorselect mount netconfig netconfig_ipv4 netconfig_ipv6 rootpass \
- script services time umount wlanconfig
+SCRIPTS= auto adduser checksum config docsinstall entropy hostname jail \
+ keymap mirrorselect mount netconfig netconfig_ipv4 netconfig_ipv6 \
+ rootpass script services time umount wlanconfig zfsboot
BINDIR= /usr/libexec/bsdinstall
-NO_MAN= true
+MAN=
.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdinstall/scripts/auto b/usr.sbin/bsdinstall/scripts/auto
index fe4e041..c2d8fc0 100755
--- a/usr.sbin/bsdinstall/scripts/auto
+++ b/usr.sbin/bsdinstall/scripts/auto
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,8 +26,13 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
-echo "Begun Installation at $(date)" > $BSDINSTALL_LOG
+############################################################ FUNCTIONS
error() {
test -n "$DISTDIR_IS_UNIONFS" && umount -f $BSDINSTALL_DISTDIR
@@ -41,6 +47,9 @@ error() {
fi
}
+############################################################ MAIN
+
+f_dprintf "Began Installation at %s" "$( date )"
rm -rf $BSDINSTALL_TMPETC
mkdir $BSDINSTALL_TMPETC
@@ -90,25 +99,51 @@ if [ -n "$FETCH_DISTRIBUTIONS" ]; then
export BSDINSTALL_DISTSITE
fi
-rm $PATH_FSTAB
+rm -f $PATH_FSTAB
touch $PATH_FSTAB
-dialog --backtitle "FreeBSD Installer" --title "Partitioning" --extra-button \
- --extra-label "Manual" --ok-label "Guided" --cancel-label "Shell" \
- --yesno "Would you like to use the guided partitioning tool (recommended for beginners) or to set up partitions manually (experts)? You can also open a shell and set up partitions entirely by hand." 0 0
+PMODES="\
+Guided \"Partitioning Tool (Recommended for Beginners)\" \
+Manual \"Manually Configure Partitions (Expert)\" \
+Shell \"Open a shell and partition by hand\""
+
+CURARCH=$( uname -m )
+case $CURARCH in
+ amd64|i386) # Booting ZFS Supported
+ PMODES="$PMODES ZFS \"Automatic Root-on-ZFS (Experimental)\""
+ ;;
+ *) # Booting ZFS Unspported
+ ;;
+esac
-case $? in
-0) # Guided
+exec 3>&1
+PARTMODE=`echo $PMODES | xargs dialog --backtitle "FreeBSD Installer" \
+ --title "Partitioning" \
+ --menu "How would you like to partition your disk?" \
+ 0 0 0 2>&1 1>&3` || exit 1
+exec 3>&-
+
+case "$PARTMODE" in
+"Guided") # Guided
bsdinstall autopart || error
bsdinstall mount || error
;;
-1) # Shell
+"Shell") # Shell
clear
echo "Use this shell to set up partitions for the new system. When finished, mount the system at $BSDINSTALL_CHROOT and place an fstab file for the new system at $PATH_FSTAB. Then type 'exit'. You can also enter the partition editor at any time by entering 'bsdinstall partedit'."
sh 2>&1
;;
-3) # Manual
- bsdinstall partedit || error
+"Manual") # Manual
+ if f_isset debugFile; then
+ # Give partedit the path to our logfile so it can append
+ BSDINSTALL_LOG="${debugFile#+}" bsdinstall partedit || error
+ else
+ bsdinstall partedit || error
+ fi
+ bsdinstall mount || error
+ ;;
+"ZFS") # ZFS
+ bsdinstall zfsboot || error
bsdinstall mount || error
;;
*)
@@ -222,5 +257,11 @@ if [ $? -eq 0 ]; then
chroot "$BSDINSTALL_CHROOT" /bin/sh 2>&1
fi
-echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG
+bsdinstall entropy
+bsdinstall umount
+
+f_dprintf "Installation Completed at %s" "$( date )"
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/config b/usr.sbin/bsdinstall/scripts/config
index 4340450..98baade 100755
--- a/usr.sbin/bsdinstall/scripts/config
+++ b/usr.sbin/bsdinstall/scripts/config
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,12 +26,24 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ MAIN
cat $BSDINSTALL_TMPETC/rc.conf.* >> $BSDINSTALL_TMPETC/rc.conf
rm $BSDINSTALL_TMPETC/rc.conf.*
cp $BSDINSTALL_TMPETC/* $BSDINSTALL_CHROOT/etc
+cat $BSDINSTALL_TMPBOOT/loader.conf.* >> $BSDINSTALL_TMPBOOT/loader.conf
+rm $BSDINSTALL_TMPBOOT/loader.conf.*
+
+cp $BSDINSTALL_TMPBOOT/* $BSDINSTALL_CHROOT/boot
+
+[ "${debugFile#+}" ] && cp "${debugFile#+}" $BSDINSTALL_CHROOT/var/log/
+
# Set up other things from installed config
-chroot $BSDINSTALL_CHROOT /usr/bin/newaliases
+chroot $BSDINSTALL_CHROOT /usr/bin/newaliases > /dev/null 2>&1
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/docsinstall b/usr.sbin/bsdinstall/scripts/docsinstall
index e16116c..f0bc8f5 100644..100755
--- a/usr.sbin/bsdinstall/scripts/docsinstall
+++ b/usr.sbin/bsdinstall/scripts/docsinstall
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Marc Fonvieille
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,55 +26,138 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/mustberoot.subr
+f_include $BSDCFG_SHARE/packages/packages.subr
-exec 3>&1
-DOCS=$(dialog --backtitle "FreeBSD Installer" \
- --title "FreeBSD Documentation Installation" --separate-output \
- --checklist "This menu will allow you to install the whole documentation set
-from the FreeBSD Documentation Project: Handbook, FAQ and articles.\n\n
-Please select the language versions you wish to install. At minimum,
-you should install the English version, this is the original version
-of the documentation.\n\n
-NB: This requires a working, configured network connection." 0 0 0 \
- bn "Bengali Documentation" ${DIST_DOC_BN:-off} \
- da "Danish Documentation" ${DIST_DOC_DA:-off} \
- de "German Documentation" ${DIST_DOC_DE:-off} \
- el "Greek Documentation" ${DIST_DOC_EL:-off} \
- en "English Documentation (recommended)" ${DIST_DOC_EN:-on} \
- es "Spanish Documentation" ${DIST_DOC_ES:-off} \
- fr "French Documentation" ${DIST_DOC_FR:-off} \
- hu "Hungarian Documentation" ${DIST_DOC_HU:-off} \
- it "Italian Documentation" ${DIST_DOC_IT:-off} \
- ja "Japanese Documentation" ${DIST_DOC_JA:-off} \
- mn "Mongolian Documentation" ${DIST_DOC_MN:-off} \
- nl "Dutch Documentation" ${DIST_DOC_NL:-off} \
- pl "Polish Documentation" ${DIST_DOC_PL:-off} \
- pt "Portuguese Documentation" ${DIST_DOC_PT:-off} \
- ru "Russian Documentation" ${DIST_DOC_RU:-off} \
- sr "Serbian Documentation" ${DIST_DOC_SR:-off} \
- tr "Turkish Documentation" ${DIST_DOC_TR:-off} \
- zh_cn "Simplified Chinese Documentation" ${DIST_DOC_ZH_CN:-off} \
- zh_tw "Traditional Chinese Documentation" ${DIST_DOC_ZH_TW:-off} \
-2>&1 1>&3)
-test $? -eq 0 || exit 0
-exec 3>&-
+############################################################ CONFIGURATION
-# Let pkg_add be able to use name servers
-cp ${BSDINSTALL_TMPETC}/resolv.conf ${BSDINSTALL_CHROOT}/etc
+#
+# List of languages to display (descriptions pulled from $msg_{lang}doc_desc)
+#
+: ${DOCSINSTALL_LANGS:=\
+ bn da de el en es fr hu it ja mn nl pl pt ru sr tr zh_cn zh_tw \
+}
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER"
+msg_bndoc_desc="Bengali Documentation"
+msg_cancel="Cancel"
+msg_dadoc_desc="Danish Documentation"
+msg_dedoc_desc="German Documentation"
+msg_docsinstall_menu_text="This menu allows you to install the whole documentation set from\nthe FreeBSD Documentation Project: Handbook, FAQ, and articles.\n\nPlease select the language versions you wish to install. At\nminimum, you should install the English version, the original\nversion of the documentation."
+msg_eldoc_desc="Greek Documentation"
+msg_endoc_desc="English Documentation (recommended)"
+msg_esdoc_desc="Spanish Documentation"
+msg_frdoc_desc="French Documentation"
+msg_freebsd_documentation_installation="FreeBSD Documentation Installation"
+msg_freebsd_installer="FreeBSD Installer"
+msg_hudoc_desc="Hungarian Documentation"
+msg_itdoc_desc="Italian Documentation"
+msg_jadoc_desc="Japanese Documentation"
+msg_mndoc_desc="Mongolian Documentation"
+msg_nldoc_desc="Dutch Documentation"
+msg_ok="OK"
+msg_pldoc_desc="Polish Documentation"
+msg_ptdoc_desc="Portuguese Documentation"
+msg_rudoc_desc="Russian Documentation"
+msg_srdoc_desc="Serbian Documentation"
+msg_trdoc_desc="Turkish Documentation"
+msg_zh_cndoc_desc="Simplified Chinese Documentation"
+msg_zh_twdoc_desc="Traditional Chinese Documentation"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt="$msg_docsinstall_menu_text"
+ local check_list= # Calculated below
+ local hline="$hline_arrows_space_tab_enter"
-error() {
- dialog --backtitle "FreeBSD Installer" --title "Error" --msgbox \
- "Could not install package $1 (`tail -n 1 ${BSDINSTALL_LOG}`)" 0 0
- exit 1
+ local lang desc upper status
+ for lang in $DOCSINSTALL_LANGS; do
+ # Fetch the i18n description to display
+ f_getvar msg_${lang}doc_desc desc
+ f_shell_escape "$desc" desc
+
+ # Get default status for each language
+ upper=$( echo "$lang" | awk '{print toupper($0)}' )
+ case "$lang" in
+ en) f_getvar DIST_DOC_$upper:-on status ;;
+ *) f_getvar DIST_DOC_$upper:-off status
+ esac
+
+ check_list="$check_list
+ '$lang' '$desc' '$status'
+ " # END-QUOTE
+ done
+
+ local height width rows
+ eval f_dialog_checklist_size height width rows \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $check_list
+ local selected
+ selected=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --separate-output \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --checklist \"\$prompt\" \
+ $height $width $rows \
+ $check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_menutag_store -s "$selected"
+ return $retval
}
+############################################################ MAIN
-clear
-echo "FreeBSD Installer"
-echo "========================"
-echo
+#
+# Initialize
+#
+f_dialog_title "$msg_freebsd_documentation_installation"
+f_dialog_backtitle "$msg_freebsd_installer"
+f_mustberoot_init
-for i in $DOCS; do
- pkg_add -C ${BSDINSTALL_CHROOT} -r ${i}-freebsd-doc || error $i-freebsd-doc
+#
+# Launch application main menu
+#
+dialog_menu_main || f_die
+f_dialog_menutag_fetch selected
+
+# Let pkg_add be able to use name servers
+f_quietly cp -f $BSDINSTALL_TMPETC/resolv.conf $BSDINSTALL_CHROOT/etc/
+
+#
+# Install each of the selected packages
+#
+for lang in $selected; do
+ f_package_add $lang-freebsd-doc || return $FAILURE
done
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/entropy b/usr.sbin/bsdinstall/scripts/entropy
new file mode 100755
index 0000000..add6f30
--- /dev/null
+++ b/usr.sbin/bsdinstall/scripts/entropy
@@ -0,0 +1,29 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 Dag-Erling Smørgrav
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+dd if=/dev/random of=$BSDINSTALL_CHROOT/entropy bs=4096 count=1
diff --git a/usr.sbin/bsdinstall/scripts/jail b/usr.sbin/bsdinstall/scripts/jail
index 78fd4c8..e709145 100755
--- a/usr.sbin/bsdinstall/scripts/jail
+++ b/usr.sbin/bsdinstall/scripts/jail
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,8 +26,15 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
-echo "Begun Installation at $(date)" > $BSDINSTALL_LOG
+############################################################ MAIN
+
+f_dprintf "Began Installation at %s" "$( date )"
export BSDINSTALL_CHROOT=$1
error() {
@@ -110,5 +118,10 @@ bsdinstall config || error
cp /etc/resolv.conf $1/etc
cp /etc/localtime $1/etc
-echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG
+bsdinstall entropy
+
+f_dprintf "Installation Completed at %s" "$(date)"
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/keymap b/usr.sbin/bsdinstall/scripts/keymap
index 97ae833..c36651f 100755
--- a/usr.sbin/bsdinstall/scripts/keymap
+++ b/usr.sbin/bsdinstall/scripts/keymap
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,11 +26,212 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/keymap.subr
+f_include $BSDCFG_SHARE/sysrc.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default file to store keymap selection in
+#
+: ${KEYMAPFILE:=$BSDINSTALL_TMPETC/rc.conf.keymap}
+
+#
+# Default path to keymap INDEX containing descriptions
+#
+: ${MAPDESCFILE:=/usr/share/syscons/keymaps/INDEX.keymaps}
+
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_continue_with_keymap="Continue with %s keymap"
+msg_default="default"
+msg_error="Error"
+msg_freebsd_installer="FreeBSD Installer"
+msg_keymap_menu_text="The system console driver for FreeBSD defaults to standard \"US\"\nkeyboard map. Other keymaps can be chosen below."
+msg_keymap_selection="Keymap Selection"
+msg_ok="OK"
+msg_select="Select"
+msg_test_keymap="Test %s keymap"
+msg_test_the_currently_selected_keymap="Test the currently selected keymap"
+msg_test_the_keymap_by_typing="Test the keymap by typing letters, numbers, and symbols. Characters\nshould match labels on the keyboard keys. Press Enter to stop testing."
+
+############################################################ FUNCTIONS
+
+# dialog_keymap_test $keymap
+#
+# Activate $keymap and display an input box (without cancel button) for the
+# user to test keyboard input and return. Always returns success.
+#
+dialog_keymap_test()
+{
+ local keym="$1"
+ local title= # Calculated below
+ local btitle= # Calculated below
+ local prompt="$msg_test_the_keymap_by_typing"
+ local hline=
+
+ # Attempt to activate the keymap
+ if [ "$keym" ]; then
+ local err
+ err=$( f_keymap_kbdcontrol "$keym" 2>&1 > /dev/null )
+ if [ "$err" ]; then
+ f_dialog_title "$msg_error"
+ f_dialog_msgbox "$err"
+ f_dialog_title_restore
+ return $FAILURE
+ fi
+ fi
+
+ f_dialog_title "$( printf "$msg_test_keymap" "${keym:-$msg_default}" )"
+ title="$DIALOG_TITLE"
+ btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+
+ local height width
+ f_dialog_inputbox_size height width \
+ "$title" "$btitle" "$prompt" "" "$hline"
+
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --ok-label "$msg_ok" \
+ --no-cancel \
+ --inputbox "$prompt" \
+ $height $width \
+ 2>/dev/null >&$DIALOG_TERMINAL_PASSTHRU_FD
-kbdcontrol -d >/dev/null 2>&1
-if [ $? -eq 0 ]; then
- dialog --backtitle "FreeBSD Installer" --title "Keymap Selection" \
- --yesno "Would you like to set a non-default key mapping for your keyboard?" 0 0 || exit 0
- exec 3>&1
- kbdmap 2>&1 1>&3 | grep 'keymap=' > $BSDINSTALL_TMPETC/rc.conf.keymap
+ return $DIALOG_OK
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_keymap_selection"
+f_dialog_backtitle "$msg_freebsd_installer"
+
+#
+# Die immediately if we can't dump the current keyboard map
+#
+#error=$( kbdcontrol -d 2>&1 > /dev/null ) || f_die $FAILURE "%s" "$error"
+
+# Capture Ctrl-C for clean-up
+trap 'rm -f $KEYMAPFILE; exit $FAILURE' SIGINT
+
+# Get a value from rc.conf(5) as initial value (if not being scripted)
+f_getvar $VAR_KEYMAP keymap
+if [ ! "$keymap" ]; then
+ keymap=$( f_sysrc_get keymap )
+ case "$keymap" in [Nn][Oo]) keymap="";; esac
fi
+
+#
+# Loop until the user has finalized their selection (by clicking the
+# [relabeled] Cancel button).
+#
+width=67 first_pass=1 back_from_testing=
+[ "$USE_XDIALOG" ] && width=70
+prompt="$msg_keymap_menu_text"
+hline="$hline_arrows_tab_enter"
+while :; do
+ #
+ # Re/Build list of keymaps
+ #
+ cont_msg=$( printf "$msg_continue_with_keymap" \
+ "${keymap:-$msg_default}" )
+ test_msg=$( printf "$msg_test_keymap" "${keymap:-$msg_default}" )
+ menu_list="
+ '>>> $cont_msg' '' '$msg_continue_with_current_keymap'
+ '->- $test_msg' '' '$msg_test_the_currently_selected_keymap'
+ " # END-QUOTE
+ if [ "$first_pass" ]; then
+ defaultitem=
+ first_pass=
+ else
+ defaultitem="->- $test_msg"
+ fi
+ for k in $KEYMAPS; do
+ keymap_$k get keym keym
+ keymap_$k get desc desc
+ radio=" "
+ if [ "$keym" = "$keymap" ]; then
+ radio="*"
+ if [ "$back_from_testing" ]; then
+ defaultitem="(*) $desc"
+ back_from_testing=
+ fi
+ fi
+ f_shell_escape "$desc" desc
+ menu_list="$menu_list
+ '($radio) $desc' '' '$keym: $desc'
+ " # END-QUOTE
+ done
+ back_from_testing=
+
+ #
+ # Display keymap configuration menu
+ #
+ eval f_dialog_menu_with_help_size height \"\" rows \
+ \"\$DIALOG_TITLE\" \
+ \"\$DIALOG_BACKTITLE\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list
+ menu_choice=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --hline \"\$hline\" \
+ --keep-tite \
+ --item-help \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || {
+ f_quietly rm -f "$KEYMAPFILE"
+ exit $FAILURE # Exit with an error so bsdinstall restarts
+ }
+ f_dialog_data_sanitize menu_choice
+
+ case "$menu_choice" in
+ ">>> "*) # Continue with keymap
+ break ;;
+ "->-"*) # Test keymap
+ dialog_keymap_test "$keymap"
+ back_from_testing=1
+ continue ;;
+ esac
+
+ # Turn the user's choice into a number
+ n=$( eval f_dialog_menutag2index_with_help \
+ \"\$menu_choice\" $menu_list )
+
+ # Turn that number ithe name of the keymap struct
+ k=$( set -- $KEYMAPS; eval echo \"\${$(( $n - 2))}\" )
+
+ # Get actual keymap setting while we update $keymap and $KEYMAPFILE
+ keymap_$k get keym keymap
+ echo "keymap=\"$keymap\"" > "$KEYMAPFILE"
+done
+
+f_quietly f_keymap_kbdcontrol "$keymap"
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/netconfig b/usr.sbin/bsdinstall/scripts/netconfig
index 382ff2c..d5a14ce 100755
--- a/usr.sbin/bsdinstall/scripts/netconfig
+++ b/usr.sbin/bsdinstall/scripts/netconfig
@@ -41,11 +41,19 @@ DIALOG_TAGS=""
: ${DIALOG_ITEM_HELP=4}
: ${DIALOG_ESC=255}
+# Do a dirty check to see if this a wireless interface -- there should be a
+# better way
+is_wireless_if() {
+ ifconfig $1 | grep -q 'media: IEEE 802.11 Wireless'
+}
+
for IF in `ifconfig -l`; do
test "$IF" = "lo0" && continue
(ifconfig -g wlan | egrep -wq $IF) && continue
INTERFACES="$INTERFACES $IF"
DESC=`sysctl -n dev.$(echo $IF | sed -E 's/([[:alpha:]]*)([[:digit:]]*)/\1.\2/g').%desc`
+ is_wireless_if $IF && echo $DESC |
+ grep -iqv wireless && DESC="Wireless $DESC"
DIALOG_TAGS="$DIALOG_TAGS $IF \"$DESC\""
done
@@ -63,10 +71,8 @@ exec 3>&-
: > $BSDINSTALL_TMPETC/._rc.conf.net
-# Do a dirty check to see if this a wireless interface -- there should be a
-# better way
IFCONFIG_PREFIX=""
-if ifconfig $INTERFACE | grep -q 'media: IEEE 802.11 Wireless'; then
+if is_wireless_if $INTERFACE; then
NEXT_WLAN_IFACE=wlan0 # XXX
echo wlans_$INTERFACE=\"$NEXT_WLAN_IFACE\" >> $BSDINSTALL_TMPETC/._rc.conf.net
IFCONFIG_PREFIX="WPA "
diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv4 b/usr.sbin/bsdinstall/scripts/netconfig_ipv4
index 452a592..856c999 100755
--- a/usr.sbin/bsdinstall/scripts/netconfig_ipv4
+++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv4
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,13 +26,15 @@
# 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
-: ${DIALOG_OK=0}
-: ${DIALOG_CANCEL=1}
-: ${DIALOG_HELP=2}
-: ${DIALOG_EXTRA=3}
-: ${DIALOG_ITEM_HELP=4}
-: ${DIALOG_ESC=255}
+############################################################ MAIN
INTERFACE=$1
IFCONFIG_PREFIX="$2"
@@ -49,8 +52,9 @@ if [ $? -eq $DIALOG_OK ]; then
if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
dialog --backtitle 'FreeBSD Installer' --infobox "Acquiring DHCP lease..." 0 0
- dhclient $INTERFACE 2>> $BSDINSTALL_LOG
+ err=$( dhclient $INTERFACE 2>&1 )
if [ $? -ne 0 ]; then
+ f_dprintf "%s" "$err"
dialog --backtitle 'FreeBSD Installer' --msgbox "DHCP lease acquisition failed." 0 0
exec $0 ${INTERFACE} "${IFCONFIG_PREFIX}"
fi
@@ -86,3 +90,6 @@ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
fi
fi
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/netconfig_ipv6 b/usr.sbin/bsdinstall/scripts/netconfig_ipv6
index dc0d69f..aa1a579 100755
--- a/usr.sbin/bsdinstall/scripts/netconfig_ipv6
+++ b/usr.sbin/bsdinstall/scripts/netconfig_ipv6
@@ -1,8 +1,8 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
-# All rights reserved.
# Copyright (c) 2011 The FreeBSD Foundation
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Portions of this software were developed by Bjoern Zeeb
@@ -30,19 +30,21 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+
+############################################################ MAIN
#
# TODO:
# - Add DHCPv6 support once FreeBSD ships with it.
#
-: ${DIALOG_OK=0}
-: ${DIALOG_CANCEL=1}
-: ${DIALOG_HELP=2}
-: ${DIALOG_EXTRA=3}
-: ${DIALOG_ITEM_HELP=4}
-: ${DIALOG_ESC=255}
-
INTERFACE=$1
case "${INTERFACE}" in
"") dialog --backtitle 'FreeBSD Installer' --title 'Network Configuration' \
@@ -61,8 +63,9 @@ while : ; do
dialog --backtitle 'FreeBSD Installer' \
--infobox "Sending Router Solicitation ..." 0 0
ifconfig ${INTERFACE} inet6 -ifdisabled accept_rtadv up
- rtsol -F $INTERFACE 2>> $BSDINSTALL_LOG
+ err=$( rtsol -F $INTERFACE 2>&1 )
if [ $? -ne 0 ]; then
+ f_dprintf "%s" "$err"
dialog --backtitle 'FreeBSD Installer' --msgbox "SLAAC failed." 0 0
AGAIN=" again"
continue
@@ -148,3 +151,6 @@ if [ ! -z $BSDINSTALL_CONFIGCURRENT ]; then
fi
fi
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/script b/usr.sbin/bsdinstall/scripts/script
index 58ae6e9..19cd392 100755
--- a/usr.sbin/bsdinstall/scripts/script
+++ b/usr.sbin/bsdinstall/scripts/script
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2013 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,27 +26,55 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." "$0"
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+############################################################ CONFIGURATION
# VARIABLES:
# PARTITIONS
# DISTRIBUTIONS
# BSDINSTALL_DISTDIR
-error() {
- test -f $PATH_FSTAB && bsdinstall umount
- echo "Installation Error!"
- cat $BSDINSTALL_LOG
- echo "Installation Error!"
+############################################################ GLOBALS
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+msg_installation_error="Installation Error!"
+
+############################################################ FUNCTIONS
+
+error()
+{
+ [ -f "$PATH_FSTAB" ] && bsdinstall umount
+
+ local file
+ f_getvar "$VAR_DEBUG_FILE#+" file
+ if [ "$file" ]; then
+ f_dialog_title "$msg_installation_error"
+ f_dialog_textbox "$file"
+ # No need to restore title, pining for the fjords
+ fi
+
exit 1
}
+############################################################ MAIN
+
set -e
trap error EXIT
SCRIPT="$1"
shift
-echo "Begun Installation at $(date)" > $BSDINSTALL_LOG
+f_dprintf "Began Installation at %s" "$( date )"
rm -rf $BSDINSTALL_TMPETC
mkdir $BSDINSTALL_TMPETC
@@ -55,10 +84,22 @@ split -a 2 -p '^#!.*' "$SCRIPT" /tmp/bsdinstall-installscript-
: ${DISTRIBUTIONS="kernel.txz base.txz"}; export DISTRIBUTIONS
export BSDINSTALL_DISTDIR
+# Re-initialize a new log if preamble changed BSDINSTALL_LOG
+if [ "$BSDINSTALL_LOG" != "${debugFile#+}" ]; then
+ export debugFile="$BSDINSTALL_LOG"
+ f_quietly f_debug_init
+ # NB: Being scripted, let debug go to terminal for invalid debugFile
+ f_dprintf "Began Instalation at %s" "$( date )"
+fi
+
# Make partitions
rm -f $PATH_FSTAB
touch $PATH_FSTAB
-bsdinstall scriptedpart "$PARTITIONS"
+if [ "$ZFSBOOT_DISKS" ]; then
+ bsdinstall zfsboot
+else
+ bsdinstall scriptedpart "$PARTITIONS"
+fi
bsdinstall mount
# Unpack distributions
@@ -83,8 +124,13 @@ if [ -f /tmp/bsdinstall-installscript-ab ]; then
rm $BSDINSTALL_CHROOT/tmp/installscript
fi
+bsdinstall entropy
bsdinstall umount
-echo "Installation Completed at $(date)" >> $BSDINSTALL_LOG
+f_dprintf "Installation Completed at %s" "$( date )"
trap true EXIT
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/services b/usr.sbin/bsdinstall/scripts/services
index a4cfd46..54c5018 100755
--- a/usr.sbin/bsdinstall/scripts/services
+++ b/usr.sbin/bsdinstall/scripts/services
@@ -29,7 +29,8 @@
: ${DIALOG_OK=0}
if [ -f $BSDINSTALL_TMPETC/rc.conf.services ]; then
- eval `sed -e s/YES/on/I -e s/NO/off/I $BSDINSTALL_TMPETC/rc.conf.services`
+ eval $( sed -e s/YES/on/i -e s/NO/off/i \
+ $BSDINSTALL_TMPETC/rc.conf.services )
else
# Default service states. Everything is off if not enabled.
sshd_enable="on"
@@ -38,29 +39,28 @@ fi
echo -n > $BSDINSTALL_TMPETC/rc.conf.services
exec 3>&1
-DAEMONS=$(dialog --backtitle "FreeBSD Installer" \
+DAEMONS=$( dialog --backtitle "FreeBSD Installer" \
--title "System Configuration" --nocancel --separate-output \
--checklist "Choose the services you would like to be started at boot:" \
0 0 0 \
sshd "Secure shell daemon" ${sshd_enable:-off} \
moused "PS/2 mouse pointer on console" ${moused_enable:-off} \
ntpd "Synchronize system and network time" ${ntpd_enable:-off} \
- powerd "Adjust CPU frequency dynamically if supported" ${powerd_enable:-off} \
-2>&1 1>&3)
+ powerd "Adjust CPU frequency dynamically if supported" \
+ ${powerd_enable:-off} \
+ dumpdev "Enable kernel crash dumps to /var/crash" ${dumpdev:-on} \
+2>&1 1>&3 )
exec 3>&-
+havedump=
for daemon in $DAEMONS; do
+ [ "$daemon" = "dumpdev" ] && havedump=1 continue
echo ${daemon}_enable=\"YES\" >> $BSDINSTALL_TMPETC/rc.conf.services
done
-echo \# Set dumpdev to \"AUTO\" to enable crash dumps, \"NO\" to disable >> \
- $BSDINSTALL_TMPETC/rc.conf.services
-
-dialog --backtitle "FreeBSD Installer" --title "Dumpdev Configuration" \
- --nocancel --yesno \
- "Would you like to enable crash dumps? If you start having problems with the system it can help the FreeBSD developers debug the problem. But the crash dumps can take up a lot of disk space in /var." 0 0
-
-if [ $? -eq $DIALOG_OK ]; then
+echo '# Set dumpdev to "AUTO" to enable crash dumps, "NO"' \
+ 'to disable' >> $BSDINSTALL_TMPETC/rc.conf.services
+if [ "$havedump" ]; then
echo dumpdev=\"AUTO\" >> $BSDINSTALL_TMPETC/rc.conf.services
else
echo dumpdev=\"NO\" >> $BSDINSTALL_TMPETC/rc.conf.services
diff --git a/usr.sbin/bsdinstall/scripts/wlanconfig b/usr.sbin/bsdinstall/scripts/wlanconfig
index 0a3599c..cefc2cb 100755
--- a/usr.sbin/bsdinstall/scripts/wlanconfig
+++ b/usr.sbin/bsdinstall/scripts/wlanconfig
@@ -1,6 +1,7 @@
#!/bin/sh
#-
# Copyright (c) 2011 Nathan Whitehorn
+# Copyright (c) 2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -25,6 +26,13 @@
# SUCH DAMAGE.
#
# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ MAIN
echo -n > $BSDINSTALL_TMPETC/wpa_supplicant.conf
chmod 0600 $BSDINSTALL_TMPETC/wpa_supplicant.conf
@@ -50,7 +58,8 @@ if [ $? -ne 0 -a -z $BSDINSTALL_CONFIGCURRENT ]; then
exit 1
fi
-wpa_cli scan >>$BSDINSTALL_LOG
+output=$( wpa_cli scan 2>&1 )
+f_dprintf "%s" "$output"
dialog --backtitle "FreeBSD Installer" --title "Scanning" --ok-label "Skip" \
--pause "Waiting 5 seconds to scan for wireless networks..." \
9 40 5 || exit 1
@@ -101,8 +110,30 @@ echo "network={
psk=\"$PASS\"
priority=5
}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf
+elif echo $ENCRYPTION | grep -q EAP; then
+ exec 3>&1
+ USERPASS=`dialog --insecure --backtitle "FreeBSD Installer" \
+ --title "WPA-Enterprise Setup" --mixedform "" 0 0 0 \
+ "SSID" 1 0 "$NETWORK" 1 12 0 0 2 \
+ "Username" 2 0 "" 2 12 25 63 0 \
+ "Password" 3 0 "" 3 12 25 63 1 \
+ 2>&1 1>&3` \
+ || exec $0 $@
+ exec 3>&-
+echo "network={
+ ssid=\"$NETWORK\"
+ key_mgmt=WPA-EAP" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf
+echo "$USERPASS" | awk '
+{
+ if (NR == 1) {
+ printf " identity=\"%s\"\n", $1;
+ } else if (NR == 2) {
+ printf " password=\"%s\"\n", $1;
+ }
+}' >> $BSDINSTALL_TMPETC/wpa_supplicant.conf
+echo " priority=5
+}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf
elif echo $ENCRYPTION | grep -q WEP; then
- echo FOO
exec 3>&1
WEPKEY=`dialog --insecure --backtitle "FreeBSD Installer" \
--title "WEP Setup" --mixedform "" 0 0 0 \
@@ -127,11 +158,18 @@ fi
# Connect to any open networks policy
echo "network={
- priority=5
+ priority=0
key_mgmt=NONE
}" >> $BSDINSTALL_TMPETC/wpa_supplicant.conf
# Bring up new network
-test ! -z $BSDINSTALL_CONFIGCURRENT && wpa_cli reconfigure >>$BSDINSTALL_LOG
+if [ "$BSDINSTALL_CONFIGCURRENT" ]; then
+ output=$( wpa_cli reconfigure 2>&1 )
+ f_dprintf "%s" "$output"
+fi
exit 0
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsdinstall/scripts/zfsboot b/usr.sbin/bsdinstall/scripts/zfsboot
new file mode 100755
index 0000000..f565655
--- /dev/null
+++ b/usr.sbin/bsdinstall/scripts/zfsboot
@@ -0,0 +1,1458 @@
+#!/bin/sh
+#-
+# Copyright (c) 2013 Allan Jude
+# 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/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/password/password.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+############################################################ CONFIGURATION
+
+#
+# Default name of the boot-pool
+#
+: ${ZFSBOOT_POOL_NAME:=zroot}
+
+#
+# Default name for the boot environment parent dataset
+#
+: ${ZFSBOOT_BEROOT_NAME:=ROOT}
+
+#
+# Default name for the primany boot environment
+#
+: ${ZFSBOOT_BOOTFS_NAME:=default}
+
+#
+# Default Virtual Device (vdev) type to create
+#
+: ${ZFSBOOT_VDEV_TYPE:=stripe}
+
+#
+# Should we use gnop(8) to configure a transparent mapping to 4K sectors?
+#
+: ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:=1}
+
+#
+# Should we use geli(8) to encrypt the drives?
+# NB: Automatically enables ZFSBOOT_BOOT_POOL
+#
+: ${ZFSBOOT_GELI_ENCRYPTION=}
+
+#
+# Default path to the geli(8) keyfile used in drive encryption
+#
+: ${ZFSBOOT_GELI_KEY_FILE:=/boot/encryption.key}
+
+#
+# Create a separate boot pool?
+# NB: Automatically set when using geli(8) or MBR
+#
+: ${ZFSBOOT_BOOT_POOL=}
+
+#
+# Default name for boot pool when enabled (e.g., geli(8) or MBR)
+#
+: ${ZFSBOOT_BOOT_POOL_NAME:=bootpool}
+
+#
+# Default size for boot pool when enabled (e.g., geli(8) or MBR)
+#
+: ${ZFSBOOT_BOOT_POOL_SIZE:=2g}
+
+#
+# Default disks to use (always empty unless being scripted)
+#
+: ${ZFSBOOT_DISKS:=}
+
+#
+# Default partitioning scheme to use on disks
+#
+: ${ZFSBOOT_PARTITION_SCHEME:=GPT}
+
+#
+# How much swap to put on each block device in the boot zpool
+# NOTE: Value passed to gpart(8); which supports SI unit suffixes.
+#
+: ${ZFSBOOT_SWAP_SIZE:=2g}
+
+#
+# Default ZFS datasets for root zpool
+#
+# NOTE: Requires /tmp, /var/tmp, /$ZFSBOOT_BOOTFS_NAME/$ZFSBOOT_BOOTFS_NAME
+# NOTE: Anything after pound/hash character [#] is ignored as a comment.
+#
+f_isset ZFSBOOT_DATASETS || ZFSBOOT_DATASETS="
+ # DATASET OPTIONS (comma or space separated; or both)
+
+ # Boot Environment [BE] root and default boot dataset
+ /$ZFSBOOT_BEROOT_NAME mountpoint=none
+ /$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME mountpoint=/
+
+ # Compress /tmp, allow exec but not setuid
+ /tmp mountpoint=/tmp,compression=lz4,exec=on,setuid=off
+
+ # Don't mount /usr so that 'base' files go to the BEROOT
+ /usr mountpoint=/usr,canmount=off
+
+ # Home directories separated so they are common to all BEs
+ /usr/home # NB: /home is a symlink to /usr/home
+
+ # Ports tree
+ /usr/ports compression=lz4,setuid=off
+
+ # Source tree (compressed)
+ /usr/src compression=lz4,exec=off,setuid=off
+
+ # Create /var and friends
+ /var mountpoint=/var
+ /var/crash compression=lz4,exec=off,setuid=off
+ /var/log compression=lz4,exec=off,setuid=off
+ /var/mail compression=lz4,atime=on
+ /var/tmp compression=lz4,exec=on,setuid=off
+" # END-QUOTE
+
+#
+# If interactive and the user has not explicitly chosen a vdev type or disks,
+# make the user confirm scripted/default choices when proceeding to install.
+#
+: ${ZFSBOOT_CONFIRM_LAYOUT:=1}
+
+############################################################ GLOBALS
+
+#
+# Format of a line in printf(1) syntax to add to fstab(5)
+#
+FSTAB_FMT="%s\t\t%s\t%s\t%s\t\t%s\t%s\n"
+
+#
+# Command strings for various tasks
+#
+CHMOD_MODE='chmod %s "%s"'
+DD_WITH_OPTIONS='dd if="%s" of="%s" %s'
+ECHO_APPEND='echo "%s" >> "%s"'
+GELI_ATTACH='geli attach -j - -k "%s" "%s"'
+GELI_DETACH_F='geli detach -f "%s"'
+GELI_PASSWORD_INIT='geli init -b -B "%s" -e %s -J - -K "%s" -l 256 -s 4096 "%s"'
+GNOP_CREATE='gnop create -S 4096 "%s"'
+GNOP_DESTROY='gnop destroy "%s"'
+GPART_ADD='gpart add -t %s "%s"'
+GPART_ADD_INDEX='gpart add -i %s -t %s "%s"'
+GPART_ADD_INDEX_WITH_SIZE='gpart add -i %s -t %s -s %s "%s"'
+GPART_ADD_LABEL='gpart add -l %s -t %s "%s"'
+GPART_ADD_LABEL_WITH_SIZE='gpart add -l %s -t %s -s %s "%s"'
+GPART_BOOTCODE='gpart bootcode -b "%s" "%s"'
+GPART_BOOTCODE_PART='gpart bootcode -b "%s" -p "%s" -i %s "%s"'
+GPART_CREATE='gpart create -s %s "%s"'
+GPART_DESTROY_F='gpart destroy -F "%s"'
+GPART_SET_ACTIVE='gpart set -a active -i %s "%s"'
+GRAID_DELETE='graid delete "%s"'
+LN_SF='ln -sf "%s" "%s"'
+MKDIR_P='mkdir -p "%s"'
+MOUNT_TYPE='mount -t %s "%s" "%s"'
+PRINTF_CONF="printf '%s=\"%%s\"\\\n' %s >> \"%s\""
+PRINTF_FSTAB='printf "$FSTAB_FMT" "%s" "%s" "%s" "%s" "%s" "%s" >> "%s"'
+SHELL_TRUNCATE=':> "%s"'
+UMOUNT='umount "%s"'
+ZFS_CREATE_WITH_OPTIONS='zfs create %s "%s"'
+ZFS_SET='zfs set "%s" "%s"'
+ZFS_UNMOUNT='zfs unmount "%s"'
+ZPOOL_CREATE_WITH_OPTIONS='zpool create %s "%s" %s %s'
+ZPOOL_DESTROY='zpool destroy "%s"'
+ZPOOL_EXPORT='zpool export "%s"'
+ZPOOL_IMPORT_WITH_OPTIONS='zpool import %s "%s"'
+ZPOOL_LABELCLEAR_F='zpool labelclear -f "%s"'
+ZPOOL_SET='zpool set %s "%s"'
+
+#
+# Strings that should be moved to an i18n file and loaded with f_include_lang()
+#
+hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER"
+hline_arrows_space_tab_enter="Use arrows, SPACE, TAB or ENTER"
+hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+msg_an_unknown_error_occurred="An unknown error occurred"
+msg_back="Back"
+msg_cancel="Cancel"
+msg_change_selection="Change Selection"
+msg_configure_options="Configure Options:"
+msg_detailed_disk_info="gpart(8) show %s:\n%s\n\ncamcontrol(8) inquiry %s:\n%s\n\n\ncamcontrol(8) identify %s:\n%s\n"
+msg_disk_info="Disk Info"
+msg_disk_info_help="Get detailed information on disk device(s)"
+msg_encrypt_disks="Encrypt Disks?"
+msg_encrypt_disks_help="Use geli(8) to encrypt all data partitions"
+msg_error="Error"
+msg_force_4k_sectors="Force 4K Sectors?"
+msg_force_4k_sectors_help="Use gnop(8) to configure forced 4K sector alignment"
+msg_freebsd_installer="FreeBSD Installer"
+msg_geli_password="Enter a strong passphrase, used to protect your encryption keys. You will be required to enter this passphrase each time the system is booted"
+msg_geli_setup="Initializing encryption on selected disks,\n this will take several seconds per disk"
+msg_install="Install"
+msg_install_desc="Proceed with Installation"
+msg_install_help="Create ZFS boot pool with displayed options"
+msg_invalid_boot_pool_size="Invalid boot pool size \`%s'"
+msg_invalid_disk_argument="Invalid disk argument \`%s'"
+msg_invalid_index_argument="Invalid index argument \`%s'"
+msg_invalid_swap_size="Invalid swap size \`%s'"
+msg_invalid_virtual_device_type="Invalid Virtual Device type \`%s'"
+msg_last_chance_are_you_sure="Last Chance! Are you sure you want to destroy\nthe current contents of the following disks:\n\n %s"
+msg_last_chance_are_you_sure_color='\\ZrLast Chance!\\ZR Are you \\Z1sure\\Zn you want to \\Zr\\Z1destroy\\Zn\nthe current contents of the following disks:\n\n %s'
+msg_mirror_desc="Mirror - n-Way Mirroring"
+msg_mirror_help="[2+ Disks] Mirroring provides the best performance, but the least storage"
+msg_missing_disk_arguments="missing disk arguments"
+msg_missing_one_or_more_scripted_disks="Missing one or more scripted disks!"
+msg_no="NO"
+msg_no_disks_present_to_configure="No disk(s) present to configure"
+msg_no_disks_selected="No disks selected."
+msg_not_enough_disks_selected="Not enough disks selected. (%u < %u minimum)"
+msg_null_disk_argument="NULL disk argument"
+msg_null_index_argument="NULL index argument"
+msg_null_poolname="NULL poolname"
+msg_ok="OK"
+msg_partition_scheme="Partition Scheme"
+msg_partition_scheme_help="Toggle between GPT and MBR partitioning schemes"
+msg_please_enter_a_name_for_your_zpool="Please enter a name for your zpool:"
+msg_please_enter_amount_of_swap_space="Please enter amount of swap space (SI-Unit suffixes\nrecommended; e.g., \`2g' for 2 Gigabytes):"
+msg_please_select_one_or_more_disks="Please select one or more disks to create a zpool:"
+msg_pool_name="Pool Name"
+msg_pool_name_cannot_be_empty="Pool name cannot be empty."
+msg_pool_name_help="Customize the name of the zpool to be created (Required)"
+msg_pool_type_disks="Pool Type/Disks:"
+msg_pool_type_disks_help="Choose type of ZFS Virtual Device and disks to use (Required)"
+msg_processing_selection="Processing selection..."
+msg_raidz1_desc="RAID-Z1 - Single Redundant RAID"
+msg_raidz1_help="[3+ Disks] Withstand failure of 1 disk. Recommended for: 3, 5 or 9 disks"
+msg_raidz2_desc="RAID-Z2 - Double Redundant RAID"
+msg_raidz2_help="[4+ Disks] Withstand failure of 2 disks. Recommended for: 4, 6 or 10 disks"
+msg_raidz3_desc="RAID-Z3 - Triple Redundant RAID"
+msg_raidz3_help="[5+ Disks] Withstand failure of 3 disks. Recommended for: 5, 7 or 11 disks"
+msg_rescan_devices="Rescan Devices"
+msg_rescan_devices_help="Scan for device changes"
+msg_select="Select"
+msg_select_a_disk_device="Select a disk device"
+msg_select_virtual_device_type="Select Virtual Device type:"
+msg_stripe_desc="Stripe - No Redundancy"
+msg_stripe_help="[1+ Disks] Striping provides maximum storage but no redundancy"
+msg_swap_size="Swap Size"
+msg_swap_size_help="Customize how much swap space is allocated to each selected disk"
+msg_these_disks_are_too_small="These disks are too small given the amount of requested\nswap (%s) and/or geli(8) (%s) partitions, which would\ntake 50%% or more of each of the following selected disk\ndevices (not recommended):\n\n %s\n\nRecommend changing partition size(s) and/or selecting a\ndifferent set of devices."
+msg_unable_to_get_disk_capacity="Unable to get disk capacity of \`%s'"
+msg_unsupported_partition_scheme="%s is an unsupported partition scheme"
+msg_user_cancelled="User Cancelled."
+msg_yes="YES"
+msg_zfs_configuration="ZFS Configuration"
+
+############################################################ FUNCTIONS
+
+# dialog_menu_main
+#
+# Display the dialog(1)-based application main menu.
+#
+dialog_menu_main()
+{
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt="$msg_configure_options"
+ local force4k="$msg_no"
+ local usegeli="$msg_no"
+ [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ] && force4k="$msg_yes"
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] && usegeli="$msg_yes"
+ local disks n
+ f_count n $ZFSBOOT_DISKS
+ { [ $n -eq 1 ] && disks=disk; } || disks=disks # grammar
+ local menu_list="
+ '>>> $msg_install' '$msg_install_desc'
+ '$msg_install_help'
+ 'T $msg_pool_type_disks' '$ZFSBOOT_VDEV_TYPE: $n $disks'
+ '$msg_pool_type_disks_help'
+ '- $msg_rescan_devices' '*'
+ '$msg_rescan_devices_help'
+ '- $msg_disk_info' '*'
+ '$msg_disk_info_help'
+ 'N $msg_pool_name' '$ZFSBOOT_POOL_NAME'
+ '$msg_pool_name_help'
+ '4 $msg_force_4k_sectors' '$force4k'
+ '$msg_force_4k_sectors_help'
+ 'E $msg_encrypt_disks' '$usegeli'
+ '$msg_encrypt_disks_help'
+ 'P $msg_partition_scheme' '$ZFSBOOT_PARTITION_SCHEME'
+ '$msg_partition_scheme_help'
+ 'S $msg_swap_size' '$ZFSBOOT_SWAP_SIZE'
+ '$msg_swap_size_help'
+ " # END-QUOTE
+ local defaultitem= # Calculated below
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+
+ local height width rows
+ eval f_dialog_menu_with_help_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \"\$hline\" $menu_list
+
+ # Obtain default-item from previously stored selection
+ f_dialog_default_fetch defaultitem
+
+ local menu_choice
+ menu_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --item-help \
+ --ok-label \"\$msg_select\" \
+ --cancel-label \"\$msg_cancel\" \
+ --default-item \"\$defaultitem\" \
+ --menu \"\$prompt\" \
+ $height $width $rows \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dialog_data_sanitize menu_choice
+ f_dialog_menutag_store "$menu_choice"
+
+ # Only update default-item on success
+ [ $retval -eq $DIALOG_OK ] && f_dialog_default_store "$menu_choice"
+
+ return $retval
+}
+
+# dialog_last_chance $disks ...
+#
+# Display a list of the disks that the user is about to destroy. The default
+# action is to return error status unless the user explicitly (non-default)
+# selects "Yes" from the noyes dialog.
+#
+dialog_last_chance()
+{
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local prompt # Calculated below
+ local hline="$hline_arrows_tab_enter"
+
+ local height=8 width=50 prefix=" "
+ local plen=${#prefix} list= line=
+ local max_width=$(( $width - 3 - $plen ))
+
+ local yes no defaultno extra_args format
+ if [ "$USE_XDIALOG" ]; then
+ yes=ok no=cancel defaultno=default-no
+ extra_args="--wrap --left"
+ format="$msg_last_chance_are_you_sure"
+ else
+ yes=yes no=no defaultno=defaultno
+ extra_args="--colors --cr-wrap"
+ format="$msg_last_chance_are_you_sure_color"
+ fi
+
+ local disk line_width
+ for disk in $*; do
+ if [ "$line" ]; then
+ line_width=${#line}
+ else
+ line_width=$plen
+ fi
+ line_width=$(( $line_width + 1 + ${#disk} ))
+ # Add newline before disk if it would exceed max_width
+ if [ $line_width -gt $max_width ]; then
+ list="$list$line\n"
+ line="$prefix"
+ height=$(( $height + 1 ))
+ fi
+ # Add the disk to the list
+ line="$line $disk"
+ done
+ # Append the left-overs
+ if [ "${line#$prefix}" ]; then
+ list="$list$line"
+ height=$(( $height + 1 ))
+ fi
+
+ # Add height for Xdialog(1)
+ [ "$USE_XDIALOG" ] && height=$(( $height + $height / 5 + 3 ))
+
+ prompt=$( printf "$format" "$list" )
+ f_dprintf "%s: Last Chance!" "$0"
+ $DIALOG \
+ --title "$title" \
+ --backtitle "$btitle" \
+ --hline "$hline" \
+ --$defaultno \
+ --$yes-label "$msg_yes" \
+ --$no-label "$msg_no" \
+ $extra_args \
+ --yesno "$prompt" $height $width
+}
+
+# dialog_menu_layout
+#
+# Configure Virtual Device type and disks to use for the ZFS boot pool. User
+# must select enough disks to satisfy the chosen vdev type.
+#
+dialog_menu_layout()
+{
+ local funcname=dialog_menu_layout
+ local title="$DIALOG_TITLE"
+ local btitle="$DIALOG_BACKTITLE"
+ local vdev_prompt="$msg_select_virtual_device_type"
+ local disk_prompt="$msg_please_select_one_or_more_disks"
+ local vdev_menu_list="
+ 'stripe' '$msg_stripe_desc' '$msg_stripe_help'
+ 'mirror' '$msg_mirror_desc' '$msg_mirror_help'
+ 'raidz1' '$msg_raidz1_desc' '$msg_raidz1_help'
+ 'raidz2' '$msg_raidz2_desc' '$msg_raidz2_help'
+ 'raidz3' '$msg_raidz3_desc' '$msg_raidz3_help'
+ " # END-QUOTE
+ local disk_check_list= # Calculated below
+ local vdev_hline="$hline_arrows_tab_enter"
+ local disk_hline="$hline_arrows_space_tab_enter"
+
+ # Warn the user if vdev type is not valid
+ case "$ZFSBOOT_VDEV_TYPE" in
+ stripe|mirror|raidz1|raidz2|raidz3) : known good ;;
+ *)
+ f_dprintf "%s: Invalid virtual device type \`%s'" \
+ $funcname "$ZFSBOOT_VDEV_TYPE"
+ f_show_err "$msg_invalid_virtual_device_type" \
+ "$ZFSBOOT_VDEV_TYPE"
+ f_interactive || return $FAILURE
+ esac
+
+ # Calculate size of vdev menu once only
+ local vheight vwidth vrows
+ eval f_dialog_menu_with_help_size vheight vwidth vrows \
+ \"\$title\" \"\$btitle\" \"\$vdev_prompt\" \"\$vdev_hline\" \
+ $vdev_menu_list
+
+ # Get a list of probed disk devices
+ local disks=
+ debug= f_device_find "" $DEVICE_TYPE_DISK disks
+
+ # Prune out mounted md(4) devices that may be part of the boot process
+ local disk name new_list=
+ for disk in $disks; do
+ debug= $disk get name name
+ case "$name" in
+ md[0-9]*) f_mounted -b "/dev/$name" && continue ;;
+ esac
+ new_list="$new_list $disk"
+ done
+ disks="${new_list# }"
+
+ # Debugging
+ if [ "$debug" ]; then
+ local disk_names=
+ for disk in $disks; do
+ debug= $disk get name name
+ disk_names="$disk_names $name"
+ done
+ f_dprintf "$funcname: disks=[%s]" "${disk_names# }"
+ fi
+
+ if [ ! "$disks" ]; then
+ f_dprintf "No disk(s) present to configure"
+ f_show_err "$msg_no_disks_present_to_configure"
+ return $FAILURE
+ fi
+
+ # Lets sort the disks array to be more user friendly
+ f_device_sort_by name disks disks
+
+ #
+ # Operate in a loop so we can (if interactive) repeat if not enough
+ # disks are selected to satisfy the chosen vdev type or user wants to
+ # back-up to the previous menu.
+ #
+ local vardisk ndisks onoff selections vdev_choice breakout device
+ local valid_disks all_valid want_disks desc height width rows
+ while :; do
+ #
+ # Confirm the vdev type that was selected
+ #
+ if f_interactive && [ "$ZFSBOOT_CONFIRM_LAYOUT" ]; then
+ vdev_choice=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$vdev_hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --item-help \
+ --default-item \"\$ZFSBOOT_VDEV_TYPE\" \
+ --menu \"\$vdev_prompt\" \
+ $vheight $vwidth $vrows \
+ $vdev_menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || return $?
+ # Exit if user pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize vdev_choice
+
+ ZFSBOOT_VDEV_TYPE="$vdev_choice"
+ f_dprintf "$funcname: ZFSBOOT_VDEV_TYPE=[%s]" \
+ "$ZFSBOOT_VDEV_TYPE"
+ fi
+
+ # Determine the number of disks needed for this vdev type
+ want_disks=0
+ case "$ZFSBOOT_VDEV_TYPE" in
+ stripe) want_disks=1 ;;
+ mirror) want_disks=2 ;;
+ raidz1) want_disks=3 ;;
+ raidz2) want_disks=4 ;;
+ raidz3) want_disks=5 ;;
+ esac
+
+ #
+ # Warn the user if any scripted disks are invalid
+ #
+ valid_disks= all_valid=${ZFSBOOT_DISKS:+1} # optimism
+ for disk in $ZFSBOOT_DISKS; do
+ if debug= f_device_find -1 \
+ $disk $DEVICE_TYPE_DISK device
+ then
+ valid_disks="$valid_disks $disk"
+ continue
+ fi
+ f_dprintf "$funcname: \`%s' is not a real disk" "$disk"
+ all_valid=
+ done
+ if [ ! "$all_valid" ]; then
+ if [ "$ZFSBOOT_DISKS" ]; then
+ f_show_err \
+ "$msg_missing_one_or_more_scripted_disks"
+ else
+ f_dprintf "No disks selected."
+ f_interactive ||
+ f_show_err "$msg_no_disks_selected"
+ fi
+ f_interactive || return $FAILURE
+ fi
+ ZFSBOOT_DISKS="${valid_disks# }"
+
+ #
+ # Short-circuit if we're running non-interactively
+ #
+ if ! f_interactive || [ ! "$ZFSBOOT_CONFIRM_LAYOUT" ]; then
+ f_count ndisks $ZFSBOOT_DISKS
+ [ $ndisks -ge $want_disks ] && break # to success
+
+ # Not enough disks selected
+ f_dprintf "$funcname: %s: %s (%u < %u minimum)" \
+ "$ZFSBOOT_VDEV_TYPE" \
+ "Not enough disks selected." \
+ $ndisks $want_disks
+ f_interactive || return $FAILURE
+ msg_yes="$msg_change_selection" msg_no="$msg_cancel" \
+ f_yesno "%s: $msg_not_enough_disks_selected" \
+ "$ZFSBOOT_VDEV_TYPE" $ndisks $want_disks ||
+ return $FAILURE
+ fi
+
+ #
+ # Confirm the disks that were selected
+ # Loop until the user cancels or selects enough disks
+ #
+ breakout=
+ while :; do
+ # Loop over list of available disks, resetting state
+ for disk in $disks; do
+ f_isset _${disk}_status && _${disk}_status=
+ done
+
+ # Loop over list of selected disks and create temporary
+ # locals to map statuses onto up-to-date list of disks
+ for disk in $ZFSBOOT_DISKS; do
+ debug= f_device_find -1 \
+ $disk $DEVICE_TYPE_DISK disk
+ f_isset _${disk}_status ||
+ local _${disk}_status
+ _${disk}_status=on
+ done
+
+ # Create the checklist menu of discovered disk devices
+ disk_check_list=
+ for disk in $disks; do
+ desc=
+ $disk get name name
+ $disk get desc desc
+ f_shell_escape "$desc" desc
+ f_getvar _${disk}_status:-off onoff
+ disk_check_list="$disk_check_list
+ $name '$desc' $onoff"
+ done
+
+ eval f_dialog_checklist_size height width rows \
+ \"\$title\" \"\$btitle\" \"\$prompt\" \
+ \"\$hline\" $disk_check_list
+
+ selections=$( eval $DIALOG \
+ --title \"\$DIALOG_TITLE\" \
+ --backtitle \"\$DIALOG_BACKTITLE\" \
+ --separate-output \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_back\" \
+ --checklist \"\$prompt\" \
+ $height $width $rows \
+ $disk_check_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ ) || break
+ # Loop if user pressed ESC or chose Cancel/No
+ f_dialog_data_sanitize selections
+
+ ZFSBOOT_DISKS="$selections"
+ f_dprintf "$funcname: ZFSBOOT_DISKS=[%s]" \
+ "$ZFSBOOT_DISKS"
+
+ f_count ndisks $ZFSBOOT_DISKS
+ [ $ndisks -ge $want_disks ] &&
+ breakout=break && break
+
+ # Not enough disks selected
+ f_dprintf "$funcname: %s: %s (%u < %u minimum)" \
+ "$ZFSBOOT_VDEV_TYPE" \
+ "Not enough disks selected." \
+ $ndisks $want_disks
+ msg_yes="$msg_change_selection" msg_no="$msg_cancel" \
+ f_yesno "%s: $msg_not_enough_disks_selected" \
+ "$ZFSBOOT_VDEV_TYPE" $ndisks $want_disks ||
+ break
+ done
+ [ "$breakout" = "break" ] && break
+ [ "$ZFSBOOT_CONFIRM_LAYOUT" ] || return $FAILURE
+ done
+
+ return $DIALOG_OK
+}
+
+# zfs_create_diskpart $disk $index
+#
+# For each block device to be used in the zpool, rather than just create the
+# zpool with the raw block devices (e.g., da0, da1, etc.) we create partitions
+# so we can have some real swap. This also provides wiggle room incase your
+# replacement drivers do not have the exact same sector counts.
+#
+# NOTE: $swapsize and $bootsize should be defined by the calling function.
+# NOTE: Sets $bootpart and $targetpart for the calling function.
+#
+zfs_create_diskpart()
+{
+ local funcname=zfs_create_diskpart
+ local disk="$1" index="$2"
+
+ # Check arguments
+ if [ ! "$disk" ]; then
+ f_dprintf "$funcname: NULL disk argument"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_null_disk_argument"
+ return $FAILURE
+ fi
+ if [ "${disk#*[$IFS]}" != "$disk" ]; then
+ f_dprintf "$funcname: Invalid disk argument \`%s'" "$disk"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_invalid_disk_argument" "$disk"
+ return $FAILURE
+ fi
+ if [ ! "$index" ]; then
+ f_dprintf "$funcname: NULL index argument"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_null_index_argument"
+ return $FAILURE
+ fi
+ if ! f_isinteger "$index"; then
+ f_dprintf "$funcname: Invalid index argument \`%s'" "$index"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_invalid_index_argument" "$index"
+ return $FAILURE
+ fi
+ f_dprintf "$funcname: disk=[%s] index=[%s]" "$disk" "$index"
+
+ # Check for unknown partition scheme before proceeding further
+ case "$ZFSBOOT_PARTITION_SCHEME" in
+ ""|MBR|GPT) : known good ;;
+ *)
+ f_dprintf "$funcname: %s is an unsupported partition scheme" \
+ "$ZFSBOOT_PARTITION_SCHEME"
+ msg_error="$msg_error: $funcname" f_show_err \
+ "$msg_unsupported_partition_scheme" \
+ "$ZFSBOOT_PARTITION_SCHEME"
+ return $FAILURE
+ esac
+
+ #
+ # Destroy whatever partition layout is currently on disk.
+ # NOTE: `-F' required to destroy if partitions still exist.
+ # NOTE: Failure is ok here, blank disk will have nothing to destroy.
+ #
+ f_dprintf "$funcname: Destroying all data/layouts on \`%s'..." "$disk"
+ f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk
+ f_eval_catch -d $funcname graid "$GRAID_DELETE" $disk
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" /dev/$disk
+
+ # Make doubly-sure backup GPT is destroyed
+ f_eval_catch -d $funcname gpart "$GPART_CREATE" gpt $disk
+ f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" $disk
+
+ #
+ # Enable boot pool if encryption is desired
+ #
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] && ZFSBOOT_BOOT_POOL=1
+
+ #
+ # Lay down the desired type of partition scheme
+ #
+ local setsize mbrindex
+ case "$ZFSBOOT_PARTITION_SCHEME" in
+ ""|GPT) f_dprintf "$funcname: Creating GPT layout..."
+ #
+ # 1. Create GPT layout using labels
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" gpt $disk ||
+ return $FAILURE
+
+ #
+ # 2. Add small freebsd-boot partition labeled `boot#'
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD_LABEL_WITH_SIZE" \
+ gptboot$index freebsd-boot 512k $disk ||
+ return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_BOOTCODE_PART" \
+ /boot/pmbr /boot/gptzfsboot 1 $disk ||
+ return $FAILURE
+
+ # NB: zpool will use the `zfs#' GPT labels
+ bootpart=p2 targetpart=p2
+ [ ${swapsize:-0} -gt 0 ] && targetpart=p3
+
+ #
+ # Prepare boot pool if enabled (e.g., for geli(8))
+ #
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ bootpart=p2 targetpart=p3
+ [ ${swapsize:-0} -gt 0 ] && targetpart=p4
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_LABEL_WITH_SIZE" boot$index \
+ freebsd-zfs ${bootsize}b $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Pedantically detach targetpart for later
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$targetpart
+ fi
+ fi
+
+ #
+ # 3. Add freebsd-swap partition labeled `swap#'
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_LABEL_WITH_SIZE" swap$index \
+ freebsd-swap ${swapsize}b $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/gpt/swap$index
+ # Update fstab(5)
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ /dev/gpt/swap$index none swap sw 0 0 \
+ $BSDINSTALL_TMPETC/fstab ||
+ return $FAILURE
+ fi
+
+ #
+ # 4. Add freebsd-zfs partition labeled `zfs#' for zroot
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD_LABEL" \
+ zfs$index freebsd-zfs $disk || return $FAILURE
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$targetpart
+ ;;
+
+ MBR) f_dprintf "$funcname: Creating MBR layout..."
+ #
+ # 1. Create MBR layout (no labels)
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" mbr $disk ||
+ return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_BOOTCODE" /boot/mbr \
+ $disk || return $FAILURE
+
+ #
+ # 2. Add freebsd slice with all available space
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD" freebsd $disk ||
+ return $FAILURE
+ f_eval_catch $funcname gpart "$GPART_SET_ACTIVE" 1 $disk ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/${disk}s1
+ # Pedantically nuke any old scheme
+ f_eval_catch -d $funcname gpart "$GPART_DESTROY_F" ${disk}s1
+
+ #
+ # 3. Write BSD scheme to the freebsd slice
+ #
+ f_eval_catch $funcname gpart "$GPART_CREATE" BSD ${disk}s1 ||
+ return $FAILURE
+
+ # NB: zpool will use s1a (no labels)
+ bootpart=s1a targetpart=s1d mbrindex=4
+
+ #
+ # Always prepare a boot pool on MBR
+ #
+ ZFSBOOT_BOOT_POOL=1
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" \
+ 1 freebsd-zfs ${bootsize}b ${disk}s1 ||
+ return $FAILURE
+ # Pedantically nuke any old labels
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$bootpart
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Pedantically detach targetpart for later
+ f_eval_catch -d $funcname geli \
+ "$GELI_DETACH_F" \
+ /dev/$disk$targetpart
+ fi
+
+ #
+ # 4. Add freebsd-swap partition
+ #
+ if [ ${swapsize:-0} -gt 0 ]; then
+ f_eval_catch $funcname gpart \
+ "$GPART_ADD_INDEX_WITH_SIZE" 2 \
+ freebsd-swap ${swapsize}b ${disk}s1 ||
+ return $FAILURE
+ # Pedantically nuke any old labels on the swap
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/${disk}s1b
+ # Update fstab(5)
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ /dev/${disk}s1b none swap sw 0 0 \
+ $BSDINSTALL_TMPETC/fstab ||
+ return $FAILURE
+ fi
+
+ #
+ # 5. Add freebsd-zfs partition for zroot
+ #
+ f_eval_catch $funcname gpart "$GPART_ADD_INDEX" \
+ $mbrindex freebsd-zfs ${disk}s1 || return $FAILURE
+ f_eval_catch -d $funcname zpool "$ZPOOL_LABELCLEAR_F" \
+ /dev/$disk$targetpart # Pedantic
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/${disk}s1 count=1 ||
+ return $FAILURE
+ ;;
+
+ esac # $ZFSBOOT_PARTITION_SCHEME
+
+ return $SUCCESS
+}
+
+# zfs_create_boot $poolname $vdev_type $disks ...
+#
+# Creates boot pool and dataset layout. Returns error if something goes wrong.
+# Errors are printed to stderr for collection and display.
+#
+zfs_create_boot()
+{
+ local funcname=zfs_create_boot
+ local zroot_name="$1"
+ local zroot_vdevtype="$2"
+ local zroot_vdevs= # Calculated below
+ local boot_vdevs= # Used for geli(8) and/or MBR layouts
+ shift 2 # poolname vdev_type
+ local disks="$*" disk
+ local bootpart targetpart # Set by zfs_create_diskpart() below
+
+ #
+ # Pedantic checks; should never be seen
+ #
+ if [ ! "$zroot_name" ]; then
+ f_dprintf "$funcname: NULL poolname"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_null_poolname"
+ return $FAILURE
+ fi
+ if [ $# -lt 1 ]; then
+ f_dprintf "$funcname: missing disk arguments"
+ msg_error="$msg_error: $funcname" \
+ f_show_err "$msg_missing_disk_arguments"
+ return $FAILURE
+ fi
+ f_dprintf "$funcname: poolname=[%s] vdev_type=[%s]" \
+ "$zroot_name" "$zroot_vdevtype"
+
+ #
+ # Initialize fstab(5)
+ #
+ f_dprintf "$funcname: Initializing temporary fstab(5) file..."
+ f_eval_catch $funcname sh "$SHELL_TRUNCATE" $BSDINSTALL_TMPETC/fstab ||
+ return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_FSTAB" \
+ "# Device" Mountpoint FStype Options Dump "Pass#" \
+ $BSDINSTALL_TMPETC/fstab || return $FAILURE
+
+ #
+ # Expand SI units in desired sizes
+ #
+ f_dprintf "$funcname: Expanding supplied size values..."
+ local swapsize bootsize
+ if ! f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize; then
+ f_dprintf "$funcname: Invalid swap size \`%s'" \
+ "$ZFSBOOT_SWAP_SIZE"
+ f_show_err "$msg_invalid_swap_size" "$ZFSBOOT_SWAP_SIZE"
+ return $FAILURE
+ fi
+ if ! f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize; then
+ f_dprintf "$funcname: Invalid boot pool size \`%s'" \
+ "$ZFSBOOT_BOOT_POOL_SIZE"
+ f_show_err "$msg_invalid_boot_pool_size" \
+ "$ZFSBOOT_BOOT_POOL_SIZE"
+ return $FAILURE
+ fi
+ f_dprintf "$funcname: ZFSBOOT_SWAP_SIZE=[%s] swapsize=[%s]" \
+ "$ZFSBOOT_SWAP_SIZE" "$swapsize"
+ f_dprintf "$funcname: ZFSBOOT_BOOT_POOL_SIZE=[%s] bootsize=[%s]" \
+ "$ZFSBOOT_BOOT_POOL_SIZE" "$bootsize"
+
+ #
+ # Destroy the pool in-case this is our second time 'round (case of
+ # failure and installer presented ``Retry'' option to come back).
+ #
+ # NB: If we don't destroy the pool, later gpart(8) destroy commands
+ # that try to clear existing partitions (see zfs_create_diskpart())
+ # will fail with a `Device Busy' error, leading to `GEOM exists'.
+ #
+ f_eval_catch -d $funcname zpool "$ZPOOL_DESTROY" "$zroot_name"
+
+ #
+ # Prepare the disks and build pool device list(s)
+ #
+ f_dprintf "$funcname: Preparing disk partitions for ZFS pool..."
+ [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ] &&
+ f_dprintf "$funcname: With 4k alignment using gnop(8)..."
+ local n=0
+ for disk in $disks; do
+ zfs_create_diskpart $disk $n || return $FAILURE
+ # Now $bootpart and $targetpart are set (suffix for $disk)
+
+ # Forced 4k alignment support using Geom NOP (see gnop(8))
+ if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ boot_vdevs="$boot_vdevs $disk$bootpart.nop"
+ f_eval_catch $funcname gnop "$GNOP_CREATE" \
+ $disk$bootpart || return $FAILURE
+ fi
+ # Don't gnop encrypted partition
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ zroot_vdevs="$zroot_vdevs $disk$targetpart.eli"
+ else
+ zroot_vdevs="$zroot_vdevs $disk$targetpart.nop"
+ f_eval_catch $funcname gnop "$GNOP_CREATE" \
+ $disk$targetpart ||
+ return $FAILURE
+ fi
+ else
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ boot_vdevs="$boot_vdevs $disk$bootpart"
+ fi
+ zroot_vdevs="$zroot_vdevs $disk$targetpart"
+ fi
+
+ n=$(( $n + 1 ))
+ done # disks
+
+ #
+ # If we need/want a boot pool, create it
+ #
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ local bootpool_vdevtype= # Calculated below
+ local bootpool_options= # Calculated below
+ local bootpool_name="$ZFSBOOT_BOOT_POOL_NAME"
+ local bootpool="$BSDINSTALL_CHROOT/$bootpool_name"
+ local zroot_key="${ZFSBOOT_GELI_KEY_FILE#/}"
+
+ f_dprintf "$funcname: Setting up boot pool..."
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] &&
+ f_dprintf "$funcname: For encrypted root disk..."
+
+ # Create parent directory for boot pool
+ f_eval_catch -d $funcname umount "$UMOUNT" /mnt
+ f_eval_catch $funcname mount "$MOUNT_TYPE" tmpfs none \
+ $BSDINSTALL_CHROOT || return $FAILURE
+
+ # Create mirror across the boot partition on all disks
+ local nvdevs
+ f_count nvdevs $boot_vdevs
+ [ $nvdevs -gt 1 ] && bootpool_vdevtype=mirror
+
+ bootpool_options="-o altroot=$BSDINSTALL_CHROOT"
+ bootpool_options="$bootpool_options -m \"/$bootpool_name\" -f"
+ f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \
+ "$bootpool_options" "$bootpool_name" \
+ "$bootpool_vdevtype" "$boot_vdevs" ||
+ return $FAILURE
+
+ f_eval_catch $funcname mkdir "$MKDIR_P" "$bootpool/boot" ||
+ return $FAILURE
+
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Generate an encryption key using random(4)
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /dev/random "$bootpool/$zroot_key" \
+ "bs=4096 count=1" || return $FAILURE
+ else
+ # Clean up
+ f_eval_catch $funcname zfs "$ZFS_UNMOUNT" \
+ "$bootpool_name" || return $FAILURE
+ f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs
+ fi
+
+ fi
+
+ #
+ # Create the geli(8) GEOMS
+ #
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ # Prompt user for password (twice)
+ if ! msg_enter_new_password="$msg_geli_password" \
+ f_dialog_input_password
+ then
+ f_dprintf "$funcname: User cancelled"
+ f_show_err "$msg_user_cancelled"
+ return $FAILURE
+ fi
+
+ # Initialize geli(8) on each of the target partitions
+ for disk in $disks; do
+ f_dialog_info "$msg_geli_setup" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ if ! echo "$pw_password" | f_eval_catch \
+ $funcname geli "$GELI_PASSWORD_INIT" \
+ "$bootpool/boot/$disk$targetpart.eli" \
+ AES-XTS "$bootpool/$zroot_key" \
+ $disk$targetpart
+ then
+ f_interactive || f_die
+ unset pw_password # Sensitive info
+ return $FAILURE
+ fi
+ if ! echo "$pw_password" | f_eval_catch \
+ $funcname geli "$GELI_ATTACH" \
+ "$bootpool/$zroot_key" $disk$targetpart
+ then
+ f_interactive || f_die
+ unset pw_password # Sensitive info
+ return $FAILURE
+ fi
+ done
+ unset pw_password # Sensitive info
+
+ # Clean up
+ f_eval_catch $funcname zfs "$ZFS_UNMOUNT" "$bootpool_name" ||
+ return $FAILURE
+ f_eval_catch -d $funcname umount "$UMOUNT" /mnt # tmpfs
+ fi
+
+ #
+ # Create the ZFS root pool with desired type and disk devices
+ #
+ f_dprintf "$funcname: Creating root pool..."
+ f_eval_catch $funcname zpool "$ZPOOL_CREATE_WITH_OPTIONS" \
+ "-o altroot=$BSDINSTALL_CHROOT -m none -f" \
+ "$zroot_name" "$zroot_vdevtype" "$zroot_vdevs" ||
+ return $FAILURE
+
+ # Customize the zroot a bit...
+ local option
+ f_dprintf "$funcname: Setting miscellaneous options on root pool..."
+ for option in atime=off; do
+ f_eval_catch $funcname zfs "$ZFS_SET" $option "$zroot_name" ||
+ return $FAILURE
+ done
+
+ #
+ # Create ZFS dataset layout within the new root pool
+ #
+ f_dprintf "$funcname: Creating ZFS datasets..."
+ echo "$ZFSBOOT_DATASETS" | while read dataset options; do
+ # Skip blank lines and comments
+ case "$dataset" in "#"*|"") continue; esac
+ # Remove potential inline comments in options
+ options="${options%%#*}"
+ # Replace tabs with spaces
+ f_replaceall "$options" " " " " options
+ # Reduce contiguous runs of space to one single space
+ oldoptions=
+ while [ "$oldoptions" != "$options" ]; do
+ oldoptions="$options"
+ f_replaceall "$options" " " " " options
+ done
+ # Replace both commas and spaces with ` -o '
+ f_replaceall "$options" "[ ,]" " -o " options
+ # Create the dataset with desired options
+ f_eval_catch $funcname zfs "$ZFS_CREATE_WITH_OPTIONS" \
+ "${options:+-o $options}" "$zroot_name$dataset" ||
+ return $FAILURE
+ done
+
+ # Touch up permissions on the tmp directories
+ f_dprintf "$funcname: Modifying directory permissions..."
+ local dir
+ for dir in /tmp /var/tmp; do
+ f_eval_catch $funcname chmod "$CHMOD_MODE" 1777 \
+ $BSDINSTALL_CHROOTDIR$dir || return $FAILURE
+ done
+
+ # Create symlink(s)
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_dprintf "$funcname: Creating /boot symlink for boot pool..."
+ f_eval_catch $funcname ln "$LN_SF" "$bootpool_name/boot" \
+ $BSDINSTALL_CHROOT/boot || return $FAILURE
+ fi
+
+ # Set bootfs property
+ local zroot_bootfs="$ZFSBOOT_BEROOT_NAME/$ZFSBOOT_BOOTFS_NAME"
+ f_dprintf "$funcname: Setting bootfs property..."
+ f_eval_catch $funcname zpool "$ZPOOL_SET" \
+ "bootfs=\"$zroot_name/$zroot_bootfs\"" "$zroot_name" ||
+ return $FAILURE
+
+ # Export the pool(s)
+ f_dprintf "$funcname: Temporarily exporting ZFS pool(s)..."
+ f_eval_catch $funcname zpool "$ZPOOL_EXPORT" "$zroot_name" ||
+ return $FAILURE
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch $funcname zpool "$ZPOOL_EXPORT" \
+ "$bootpool_name" || return $FAILURE
+ fi
+
+ # Destroy the gnop devices (if enabled)
+ for disk in ${ZFSBOOT_GNOP_4K_FORCE_ALIGN:+$disks}; do
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch -d $funcname gnop "$GNOP_DESTROY" \
+ $disk$bootpart.nop
+ fi
+ if [ ! "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ f_eval_catch -d $funcname gnop "$GNOP_DESTROY" \
+ $disk$targetpart.nop
+ fi
+ done
+
+ # MBR boot loader touch-up
+ if [ "$ZFSBOOT_PARTITION_SCHEME" = "MBR" ]; then
+ f_dprintf "$funcname: Updating MBR boot loader on disks..."
+ # Stick the ZFS boot loader in the "convienient hole" after
+ # the ZFS internal metadata
+ for disk in $disks; do
+ f_eval_catch $funcname dd "$DD_WITH_OPTIONS" \
+ /boot/zfsboot /dev/$disk$bootpart \
+ "skip=1 seek=1024" || return $FAILURE
+ done
+ fi
+
+ # Re-import the ZFS pool(s)
+ f_dprintf "$funcname: Re-importing ZFS pool(s)..."
+ f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \
+ "-o altroot=\"$BSDINSTALL_CHROOT\"" "$zroot_name" ||
+ return $FAILURE
+ if [ "$ZFSBOOT_BOOT_POOL" ]; then
+ f_eval_catch $funcname zpool "$ZPOOL_IMPORT_WITH_OPTIONS" \
+ "-o altroot=\"$BSDINSTALL_CHROOT\"" \
+ "$bootpool_name" || return $FAILURE
+ fi
+
+ # While this is apparently not needed, it seems to help MBR
+ f_dprintf "$funcname: Configuring zpool.cache for zroot..."
+ f_eval_catch $funcname mkdir "$MKDIR_P" $BSDINSTALL_CHROOT/boot/zfs ||
+ return $FAILURE
+ f_eval_catch $funcname zpool "$ZPOOL_SET" \
+ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \
+ "$zroot_name" || return $FAILURE
+
+ # Last, but not least... required lines for rc.conf(5)/loader.conf(5)
+ # NOTE: We later concatenate these into their destination
+ f_dprintf "%s: Configuring rc.conf(5)/loader.conf(5) additions..." \
+ "$funcname"
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_enable=\"YES\"' \
+ $BSDINSTALL_TMPETC/rc.conf.zfs || return $FAILURE
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'zfs_load=\"YES\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE
+ f_eval_catch $funcname echo "$ECHO_APPEND" \
+ 'kern.geom.label.disk_ident.enable=\"0\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.zfs || return $FAILURE
+
+ # We're all done unless we should go on for boot pool
+ [ "$ZFSBOOT_BOOT_POOL" ] || return $SUCCESS
+
+ # Set cachefile for boot pool so it auto-imports at system start
+ f_dprintf "$funcname: Configuring zpool.cache for boot pool..."
+ f_eval_catch $funcname zpool "$ZPOOL_SET" \
+ "cachefile=\"$BSDINSTALL_CHROOT/boot/zfs/zpool.cache\"" \
+ "$bootpool_name" || return $FAILURE
+
+ # Some additional geli(8) requirements for loader.conf(5)
+ for option in \
+ 'zpool_cache_load=\"YES\"' \
+ 'zpool_cache_type=\"/boot/zfs/zpool.cache\"' \
+ 'zpool_cache_name=\"/boot/zfs/zpool.cache\"' \
+ ; do
+ f_eval_catch $funcname echo "$ECHO_APPEND" "$option" \
+ $BSDINSTALL_TMPBOOT/loader.conf.zfs ||
+ return $FAILURE
+ done
+ f_eval_catch $funcname printf "$PRINTF_CONF" vfs.root.mountfrom \
+ "\"zfs:$zroot_name/$zroot_bootfs\"" \
+ $BSDINSTALL_TMPBOOT/loader.conf.root || return $FAILURE
+
+ # We're all done unless we should go on to do encryption
+ [ "$ZFSBOOT_GELI_ENCRYPTION" ] || return $SUCCESS
+
+ #
+ # Configure geli(8)-based encryption
+ #
+ f_dprintf "$funcname: Configuring disk encryption..."
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'aesni_load=\"YES\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.aesni || return $FAILURE
+ f_eval_catch $funcname echo "$ECHO_APPEND" 'geom_eli_load=\"YES\"' \
+ $BSDINSTALL_TMPBOOT/loader.conf.geli || return $FAILURE
+ for disk in $disks; do
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ geli_%s_keyfile0_load "$disk$targetpart YES" \
+ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart ||
+ return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ geli_%s_keyfile0_type \
+ "$disk$targetpart $disk$targetpart:geli_keyfile0" \
+ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart ||
+ return $FAILURE
+ f_eval_catch $funcname printf "$PRINTF_CONF" \
+ geli_%s_keyfile0_name \
+ "$disk$targetpart \"$ZFSBOOT_GELI_KEY_FILE\"" \
+ $BSDINSTALL_TMPBOOT/loader.conf.$disk$targetpart ||
+ return $FAILURE
+ done
+
+ return $SUCCESS
+}
+
+# dialog_menu_diskinfo
+#
+# Prompt the user to select a disk and then provide detailed info on it.
+#
+dialog_menu_diskinfo()
+{
+ local device disk
+
+ #
+ # Break from loop when user cancels disk selection
+ #
+ while :; do
+ device=$( msg_cancel="$msg_back" f_device_menu \
+ "$DIALOG_TITLE" "$msg_select_a_disk_device" "" \
+ $DEVICE_TYPE_DISK 2>&1 ) || break
+ $device get name disk
+
+ # Show gpart(8) `show' and camcontrol(8) `inquiry' data
+ f_show_msg "$msg_detailed_disk_info" \
+ "$disk" "$( gpart show $disk 2> /dev/null )" \
+ "$disk" "$( camcontrol inquiry $disk 2> /dev/null )" \
+ "$disk" "$( camcontrol identify $disk 2> /dev/null )"
+ done
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+#
+# Initialize
+#
+f_dialog_title "$msg_zfs_configuration"
+f_dialog_backtitle "$msg_freebsd_installer"
+
+# User may have specifically requested ZFS-related operations be interactive
+! f_interactive && f_zfsinteractive && unset $VAR_NONINTERACTIVE
+
+#
+# Debugging
+#
+f_dprintf "BSDINSTALL_CHROOT=[%s]" "$BSDINSTALL_CHROOT"
+f_dprintf "BSDINSTALL_TMPETC=[%s]" "$BSDINSTALL_TMPETC"
+f_dprintf "FSTAB_FMT=[%s]" "$FSTAB_FMT"
+
+#
+# Loop over the main menu until we've accomplished what we came here to do
+#
+while :; do
+ if ! f_interactive; then
+ retval=$DIALOG_OK
+ mtag=">>> $msg_install"
+ else
+ dialog_menu_main
+ retval=$?
+ f_dialog_menutag_fetch mtag
+ fi
+
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+ [ $retval -eq $DIALOG_OK ] || f_die
+
+ case "$mtag" in
+ ">>> $msg_install")
+ #
+ # First, validate the user's selections
+ #
+
+ # Make sure they gave us a name for the pool
+ if [ ! "$ZFSBOOT_POOL_NAME" ]; then
+ f_dprintf "Pool name cannot be empty."
+ f_show_err "$msg_pool_name_cannot_be_empty"
+ continue
+ fi
+
+ # Validate vdev type against number of disks selected/scripted
+ # (also validates that ZFSBOOT_DISKS are real [probed] disks)
+ # NB: dialog_menu_layout supports running non-interactively
+ dialog_menu_layout || continue
+
+ # Make sure each disk will be at least 50% ZFS
+ if f_expand_number "$ZFSBOOT_SWAP_SIZE" swapsize &&
+ f_expand_number "$ZFSBOOT_BOOT_POOL_SIZE" bootsize
+ then
+ minsize=$swapsize teeny_disks=
+ [ "$ZFSBOOT_BOOT_POOL" ] &&
+ minsize=$(( $minsize + $bootsize ))
+ for disk in $ZFSBOOT_DISKS; do
+ debug= f_device_find -1 \
+ $disk $DEVICE_TYPE_DISK device
+ $device get capacity disksize || continue
+ [ ${disksize:-0} -ge 0 ] || disksize=0
+ disksize=$(( $disksize - $minsize ))
+ [ $disksize -lt $minsize ] &&
+ teeny_disks="$teeny_disks $disk"
+ done
+ if [ "$teeny_disks" ]; then
+ f_dprintf "swapsize=[%s] bootsize[%s] %s" \
+ "$ZFSBOOT_SWAP_SIZE" \
+ "$ZFSBOOT_BOOT_POOL_SIZE" \
+ "minsize=[$minsize]"
+ f_dprintf "These disks are too small: %s" \
+ "$teeny_disks"
+ f_show_err "$msg_these_disks_are_too_small" \
+ "$ZFSBOOT_SWAP_SIZE" \
+ "$ZFSBOOT_BOOT_POOL_SIZE" \
+ "$teeny_disks"
+ continue
+ fi
+ fi
+
+ #
+ # Last Chance!
+ #
+ if f_interactive; then
+ dialog_last_chance $ZFSBOOT_DISKS || continue
+ fi
+
+ #
+ # Let's do this
+ #
+
+ vdev_type="$ZFSBOOT_VDEV_TYPE"
+
+ # Blank the vdev type for the default layout
+ [ "$vdev_type" = "stripe" ] && vdev_type=
+
+ zfs_create_boot "$ZFSBOOT_POOL_NAME" \
+ "$vdev_type" $ZFSBOOT_DISKS || continue
+
+ break # to success
+ ;;
+ ?" $msg_pool_type_disks")
+ ZFSBOOT_CONFIRM_LAYOUT=1
+ dialog_menu_layout
+ # User has poked settings, disable later confirmation
+ ZFSBOOT_CONFIRM_LAYOUT=
+ ;;
+ "- $msg_rescan_devices") f_device_rescan ;;
+ "- $msg_disk_info") dialog_menu_diskinfo ;;
+ ?" $msg_pool_name")
+ # Prompt the user to input/change the name for the new pool
+ f_dialog_input input \
+ "$msg_please_enter_a_name_for_your_zpool" \
+ "$ZFSBOOT_POOL_NAME" &&
+ ZFSBOOT_POOL_NAME="$input"
+ ;;
+ ?" $msg_force_4k_sectors")
+ # Toggle the variable referenced both by the menu and later
+ if [ "$ZFSBOOT_GNOP_4K_FORCE_ALIGN" ]; then
+ ZFSBOOT_GNOP_4K_FORCE_ALIGN=
+ else
+ ZFSBOOT_GNOP_4K_FORCE_ALIGN=1
+ fi
+ ;;
+ ?" $msg_encrypt_disks")
+ # Toggle the variable referenced both by the menu and later
+ if [ "$ZFSBOOT_GELI_ENCRYPTION" ]; then
+ ZFSBOOT_GELI_ENCRYPTION=
+ else
+ ZFSBOOT_GNOP_4K_FORCE_ALIGN=1
+ ZFSBOOT_GELI_ENCRYPTION=1
+ fi
+ ;;
+ ?" $msg_partition_scheme")
+ # Toggle between GPT and MBR
+ if [ "$ZFSBOOT_PARTITION_SCHEME" = GPT ]; then
+ ZFSBOOT_PARTITION_SCHEME=MBR
+ else
+ ZFSBOOT_PARTITION_SCHEME=GPT
+ fi
+ ;;
+ ?" $msg_swap_size")
+ # Prompt the user to input/change the swap size for each disk
+ f_dialog_input input \
+ "$msg_please_enter_amount_of_swap_space" \
+ "$ZFSBOOT_SWAP_SIZE" &&
+ ZFSBOOT_SWAP_SIZE="${input:-0}"
+ ;;
+ esac
+done
+
+return $SUCCESS
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/bsnmpd/modules/Makefile b/usr.sbin/bsnmpd/modules/Makefile
index d5706fe..45558b7 100644
--- a/usr.sbin/bsnmpd/modules/Makefile
+++ b/usr.sbin/bsnmpd/modules/Makefile
@@ -13,12 +13,15 @@ SUBDIR= ${_snmp_atm} \
snmp_hast \
snmp_hostres \
snmp_mibII \
- snmp_pf \
snmp_target \
snmp_usm \
snmp_vacm \
snmp_wlan
+.if ${MK_PF} != "no"
+SUBDIR+=snmp_pf
+.endif
+
.if ${MK_NETGRAPH_SUPPORT} != "no"
SUBDIR+=snmp_netgraph
.endif
diff --git a/usr.sbin/bsnmpd/modules/snmp_hast/BEGEMOT-HAST-MIB.txt b/usr.sbin/bsnmpd/modules/snmp_hast/BEGEMOT-HAST-MIB.txt
index 6e20bdd..0f330c1 100644
--- a/usr.sbin/bsnmpd/modules/snmp_hast/BEGEMOT-HAST-MIB.txt
+++ b/usr.sbin/bsnmpd/modules/snmp_hast/BEGEMOT-HAST-MIB.txt
@@ -60,6 +60,11 @@ begemotHast MODULE-IDENTITY
REVISION "201307010000Z"
DESCRIPTION
"Added hastResourceWorkerPid."
+ REVISION "201312290000Z"
+ DESCRIPTION
+ "Added hastResourceLocalQueue, hastResourceSendQueue,
+ hastResourceRecvQueue, hastResourceDoneQueue,
+ hastResourceIdleQueue."
::= { begemot 220 }
begemotHastObjects OBJECT IDENTIFIER ::= { begemotHast 1 }
@@ -120,7 +125,12 @@ HastResourceEntry ::= SEQUENCE {
hastResourceWriteErrors Counter64,
hastResourceDeleteErrors Counter64,
hastResourceFlushErrors Counter64,
- hastResourceWorkerPid INTEGER
+ hastResourceWorkerPid INTEGER,
+ hastResourceLocalQueue UNSIGNED32,
+ hastResourceSendQueue UNSIGNED32,
+ hastResourceRecvQueue UNSIGNED32,
+ hastResourceDoneQueue UNSIGNED32,
+ hastResourceIdleQueue UNSIGNED32
}
hastResourceIndex OBJECT-TYPE
@@ -307,4 +317,46 @@ hastResourceWorkerPid OBJECT-TYPE
"Worker process ID."
::= { hastResourceEntry 22 }
+hastResourceLocalQueue OBJECT-TYPE
+ SYNTAX UNSIGNED32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of outstanding I/O requests to the local component."
+ ::= { hastResourceEntry 23 }
+
+hastResourceSendQueue OBJECT-TYPE
+ SYNTAX UNSIGNED32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of outstanding I/O requests to send to the remote
+ component."
+ ::= { hastResourceEntry 24 }
+
+hastResourceRecvQueue OBJECT-TYPE
+ SYNTAX UNSIGNED32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of outstanding I/O requests waiting for response
+ from the remote component."
+ ::= { hastResourceEntry 25 }
+
+hastResourceDoneQueue OBJECT-TYPE
+ SYNTAX UNSIGNED32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of processed I/O requests to return to the kernel."
+ ::= { hastResourceEntry 26 }
+
+hastResourceIdleQueue OBJECT-TYPE
+ SYNTAX UNSIGNED32
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of request objects in the free bucket."
+ ::= { hastResourceEntry 27 }
+
END
diff --git a/usr.sbin/bsnmpd/modules/snmp_hast/hast_snmp.c b/usr.sbin/bsnmpd/modules/snmp_hast/hast_snmp.c
index ef8832a..210db9e 100644
--- a/usr.sbin/bsnmpd/modules/snmp_hast/hast_snmp.c
+++ b/usr.sbin/bsnmpd/modules/snmp_hast/hast_snmp.c
@@ -79,6 +79,11 @@ struct hast_snmp_resource {
uint64_t delete_errors;
uint64_t flush_errors;
pid_t workerpid;
+ uint32_t local_queue;
+ uint32_t send_queue;
+ uint32_t recv_queue;
+ uint32_t done_queue;
+ uint32_t idle_queue;
};
static TAILQ_HEAD(, hast_snmp_resource) resources =
@@ -345,6 +350,16 @@ update_resources(void)
res->flush_errors =
nv_get_uint64(nvout, "stat_flush_error%u", i);
res->workerpid = nv_get_int32(nvout, "workerpid%u", i);
+ res->local_queue =
+ nv_get_uint64(nvout, "local_queue_size%u", i);
+ res->send_queue =
+ nv_get_uint64(nvout, "send_queue_size%u", i);
+ res->recv_queue =
+ nv_get_uint64(nvout, "recv_queue_size%u", i);
+ res->done_queue =
+ nv_get_uint64(nvout, "done_queue_size%u", i);
+ res->idle_queue =
+ nv_get_uint64(nvout, "idle_queue_size%u", i);
TAILQ_INSERT_TAIL(&resources, res, link);
}
nv_free(nvout);
@@ -503,6 +518,21 @@ op_hastResourceTable(struct snmp_context *context __unused,
case LEAF_hastResourceWorkerPid:
value->v.integer = res->workerpid;
break;
+ case LEAF_hastResourceLocalQueue:
+ value->v.uint32 = res->local_queue;
+ break;
+ case LEAF_hastResourceSendQueue:
+ value->v.uint32 = res->send_queue;
+ break;
+ case LEAF_hastResourceRecvQueue:
+ value->v.uint32 = res->recv_queue;
+ break;
+ case LEAF_hastResourceDoneQueue:
+ value->v.uint32 = res->done_queue;
+ break;
+ case LEAF_hastResourceIdleQueue:
+ value->v.uint32 = res->idle_queue;
+ break;
default:
ret = SNMP_ERR_RES_UNAVAIL;
break;
diff --git a/usr.sbin/bsnmpd/modules/snmp_hast/hast_tree.def b/usr.sbin/bsnmpd/modules/snmp_hast/hast_tree.def
index 3769bd2..980de92 100644
--- a/usr.sbin/bsnmpd/modules/snmp_hast/hast_tree.def
+++ b/usr.sbin/bsnmpd/modules/snmp_hast/hast_tree.def
@@ -60,6 +60,11 @@
(20 hastResourceDeleteErrors COUNTER64 GET)
(21 hastResourceFlushErrors COUNTER64 GET)
(22 hastResourceWorkerPid INTEGER GET)
+ (23 hastResourceLocalQueue UNSIGNED32 GET)
+ (24 hastResourceSendQueue UNSIGNED32 GET)
+ (25 hastResourceRecvQueue UNSIGNED32 GET)
+ (26 hastResourceDoneQueue UNSIGNED32 GET)
+ (27 hastResourceIdleQueue UNSIGNED32 GET)
)
)
)
diff --git a/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1 b/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
index 16eec25..41e5056 100644
--- a/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
+++ b/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
@@ -106,18 +106,18 @@ management information to a Simple Network Management Protocol (SNMP) agent.
.Pp
Depending on the options
.Nm bsnmpget
-constructs either a SMNP GetRequest, GetNextRequest
+constructs either a SNMP GetRequest, GetNextRequest
or a GetBulkRequest packet, fills in the object identifiers (OIDs) of the
objects whose values will be retrieved, waits for a response and prints it if
received successfully.
.Pp
.Nm Bsnmpwalk
-queries an agent with ether SMNP GetNextRequest or GetBulkRequest packets,
+queries an agent with ether SNMP GetNextRequest or GetBulkRequest packets,
asking for values of OID instances that are a part of the object subtree
rooted at the provided OIDs.
.Pp
.Nm Bsnmpset
-constructs a SMNP SetRequest packet, fills in the OIDs (object identifiers),
+constructs a SNMP SetRequest packet, fills in the OIDs (object identifiers),
syntaxes and values of the objects whose values are to be set and waits for a
response from server.
.Sh OPTIONS
@@ -151,7 +151,8 @@ The context to query with SNMPv3 PDUs.
The context name. Default is "" (empty).
.It Cm context-engine=engine-id
The SNMP Engine ID of the context to query with SNMPv3 PDUs, represented as
-binary octet string. By default, this is set to the Engine ID of the SNMP agent.
+binary octet string.
+By default, this is set to the Engine ID of the SNMP agent.
.El
.It Fl D
Perform SNMP USM Engine Discovery, rather than sending a request for the value
@@ -177,7 +178,8 @@ Specifies the initial OID that was cut by
.Xr gensnmpdef 1
when producing the MIB description file.
The default value is .iso(1).org(3).dod(6) which is what should have been
-used for all the files installed under /usr/share/snmp/defs.
+used for all the files installed under
+.Pa /usr/share/snmp/defs .
Use this only if you generated your own files, providing a
.Fl c
option to
@@ -198,7 +200,8 @@ If using spaces make sure the entire option string is one argument, for
example using quotes.
.It Fl i Ar filelist
List of MIB description files produced by
-.Xr gensnmpdef 1 which
+.Xr gensnmpdef 1
+which
.Nm bsnmpget ,
.Nm bsnmpwalk
or
@@ -207,12 +210,13 @@ will search to translate numerical OIDs to their symbolic object names.
Multiple files can be provided either giving this option multiple times
or a comma separated list of file names.
If a filename begins with a letter the default directory,
-/usr/share/snmp/defs,
+.Pa /usr/share/snmp/defs ,
will be searched.
.It Fl K
Calculate and display the localized authentication and privacy keys
-corresponding to a plain text password. The password is obtain via the
-environment. Additionally, if one or more OIDs are specified, the calculated
+corresponding to a plain text password.
+The password is obtained via the environment.
+Additionally, if one or more OIDs are specified, the calculated
keys are used when processing the SNMPv3 requests.
.It Fl l Ar filename
The path of the posix local (unix domain) socket if local
@@ -242,9 +246,9 @@ In addition to the short output verbose prints the type before the value.
Privacy options to use with SNMPv3 PDUs
.Bl -tag -width \&
.It Cm proto=[aes|des]
-The protocol to use when encypting/decrypting SNMPv3 PDU data.
+The protocol to use when encrypting/decrypting SNMPv3 PDU data.
.It Cm key=privkey
-A binary localized privacy key to use when encypting/decrypting SNMPv3 PDU data.
+A binary localized privacy key to use when encrypting/decrypting SNMPv3 PDU data.
.El
.Pp
By default plain text SNMPv3 PDUs are sent.
@@ -267,14 +271,14 @@ not respond after the first try.
Default is 3.
.It Fl s Ar [trans::] Ns Ar [community@] Ns Ar [server] Ns Ar [:port]
Each of the server specification components is optional but at least one
-has to be provided if
+has to be provided if the
.Ar s
option is used.
The server specification is constructed in the following manner:
.Bl -tag -width \&
.It Cm trans::
Transport type may be one of udp, stream or dgram.
-If this option is not provided an udp inet/inet6 socket will be used, which
+If this option is not provided an UDP inet/inet6 socket will be used, which
is the most common.
Stream stands for a posix local stream socket and a posix local datagram
socket will be used if dgram is specified.
@@ -317,11 +321,13 @@ The value of the snmpEngineTime of the SNMP agent.
If any of the above is not specified, SNMP USM Engine Discovery is attempted.
This is also the default behavior.
.It Cm name=username
-The USM user name to include in the SNMPv3 PDUs. By default, the user name is
-obtain via the environment
+The USM user name to include in the SNMPv3 PDUs.
+By default, the user name is
+obtained via the environment.
.El
.It Fl v Ar version
-The SNMP protocol version to use when sending requests. SNMP versions 1, 2 and
+The SNMP protocol version to use when sending requests.
+SNMP versions 1, 2 and
3 are supported.
If no version option is provided
.Nm bsnmpget ,
@@ -330,7 +336,7 @@ and
.Nm bsnmpset
will use version 2.
Note that GetBulkRequest-PDUs were introduced in SNMPv2 thus setting the
-version to 1 is incompatiable with sending a GetBulk PDU.
+version to 1 is incompatible with sending a GetBulk PDU.
.It OID
The object identifier whose value to retrieve.
At least one OID should be provided for
@@ -355,7 +361,7 @@ is valid as input OID:
.It ifRcvAddressStatus.2.6.255.255.255.255.255.255
.It ifRcvAddressType[2,ff:ff:ff:ff:ff:ff]
.It ifRcvAddressStatus[Integer:1,OctetString:ff:ff:ff:ff:ff:ff]
-(requires
+(requires the
.Fl o Ar verbose
option)
.El
@@ -373,14 +379,14 @@ to be able to send a request.
.It Cm OID
OID may be input as a string, a string followed by a random number of integers
(suboids) separated by dots, a sequence of integers separated by dots - that is
-if
+if the
.Ar n
-options is used - and in such case a syntax is required for every value,
+option is used - and in such case a syntax is required for every value,
or a string followed by square brackets (used to denote an entry's indexes) and
corresponding indexes.
-Any of formats used to print a single variable by
-.Nm bsnmpset is
-valid for inpit OID as well:
+Any of the formats used to print a single variable by
+.Nm bsnmpset
+is valid as input OID as well:
.Bl -tag -width \&
.It 1.3.6.1.2.1.25.1.1.0=TimeTicks:537615486
.It sysLocation=OctetString:"@ Home" (with Fl o Ar verbose No option)
@@ -389,17 +395,17 @@ valid for inpit OID as well:
.It ifPhysAddress.1="00:02:b3:1d:1c:a3"
.It ifRcvAddressStatus.1.6.255.255.255.255.255.255=1
.It "ifRcvAddressStatus[Integer:1,OctetString:ff:ff:ff:ff:ff:ff]=Integer:1"
-(with
+(with the
.Fl o Ar verbose
option)
.El
.It Cm syntax
-where syntax string is one of:
+where the syntax string is one of:
Integer, OctetString, OID, IpAddress, Counter32, Gauge, TimeTicks, Counter64.
.It Cm value
The value to be set - IP address in form of u.u.u.u - for example
1.3.1.6.1.2.0=IpAddress:192.168.0.1, strings require inverted-commas if they
-contain any special characters or spaces, all other numeric types don't.
+contain any special characters or spaces, all other numeric types do not.
.El
.El
.Sh ENVIRONMENT
@@ -417,8 +423,9 @@ Specifies a default SNMP USM privacy protocol.
Specifies a default SNMP USM user name.
.It Ev SNMPPASSWD
Specifies the SNMP USM plain text password to use when calculating localized
-authentication and privacy keys. If this variable exists in the environment,
-SMNPv3 is the default version to use for outgoing requests.
+authentication and privacy keys.
+If this variable exists in the environment,
+SNMPv3 is the default version to use for outgoing requests.
.El
.Sh SEE ALSO
.Xr gensnmpdef 1
diff --git a/usr.sbin/btxld/btxld.c b/usr.sbin/btxld/btxld.c
index 1102b5c..7984c4c 100644
--- a/usr.sbin/btxld/btxld.c
+++ b/usr.sbin/btxld/btxld.c
@@ -426,7 +426,7 @@ puthdr(int fd, struct hdr *hdr)
le32toh(eh.p[0].p_filesz));
eh.p[1].p_vaddr = eh.p[1].p_paddr =
htole32(align(le32toh(eh.p[0].p_paddr) + le32toh(eh.p[0].p_memsz),
- 4));
+ 4096));
eh.p[1].p_filesz = eh.p[1].p_memsz = htole32(hdr->data);
eh.sh[2].sh_addr = eh.p[0].p_vaddr;
eh.sh[2].sh_offset = eh.p[0].p_offset;
diff --git a/usr.sbin/config/config.8 b/usr.sbin/config/config.8
index 784b06b..79520a7 100644
--- a/usr.sbin/config/config.8
+++ b/usr.sbin/config/config.8
@@ -37,6 +37,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl CVgp
+.Op Fl I Ar path
.Op Fl d Ar destdir
.Ar SYSTEM_NAME
.Nm
@@ -69,6 +70,12 @@ If the INCLUDE_CONFIG_FILE is present in a configuration file,
kernel image will contain full configuration files included
literally (preserving comments).
This flag is kept for backward compatibility.
+.It Fl I Ar path
+Search in
+.Ar path
+for any file included by the
+.Ic include
+directive. This option may be specified more than once.
.It Fl d Ar destdir
Use
.Ar destdir
diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h
index f275749..93b2086 100644
--- a/usr.sbin/config/config.h
+++ b/usr.sbin/config/config.h
@@ -144,6 +144,13 @@ struct hint {
STAILQ_HEAD(hint_head, hint) hints;
+struct includepath {
+ char *path;
+ SLIST_ENTRY(includepath) path_next;
+};
+
+SLIST_HEAD(, includepath) includepath;
+
/*
* Tag present in the kernelconf.tmlp template file. It's mandatory for those
* two strings to be the same. Otherwise you'll get into trouble.
diff --git a/usr.sbin/config/configvers.h b/usr.sbin/config/configvers.h
index 6e044b8..56ca85c 100644
--- a/usr.sbin/config/configvers.h
+++ b/usr.sbin/config/configvers.h
@@ -49,5 +49,5 @@
*
* $FreeBSD$
*/
-#define CONFIGVERS 600012
+#define CONFIGVERS 600013
#define MAJOR_VERS(x) ((x) / 100000)
diff --git a/usr.sbin/config/lang.l b/usr.sbin/config/lang.l
index 3e4e115..14fa7da 100644
--- a/usr.sbin/config/lang.l
+++ b/usr.sbin/config/lang.l
@@ -34,6 +34,7 @@
#include <assert.h>
#include <ctype.h>
#include <err.h>
+#include <stdlib.h>
#include <string.h>
#include "y.tab.h"
#include "config.h"
@@ -257,6 +258,7 @@ include(const char *fname, int ateof)
{
FILE *fp;
struct incl *in;
+ struct includepath* ipath;
char *fnamebuf;
fnamebuf = NULL;
@@ -269,6 +271,17 @@ include(const char *fname, int ateof)
}
}
if (fp == NULL) {
+ SLIST_FOREACH(ipath, &includepath, path_next) {
+ asprintf(&fnamebuf, "%s/%s", ipath->path, fname);
+ if (fnamebuf != NULL) {
+ fp = fopen(fnamebuf, "r");
+ free(fnamebuf);
+ }
+ if (fp != NULL)
+ break;
+ }
+ }
+ if (fp == NULL) {
yyerror("cannot open included file");
return (-1);
}
diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c
index 78bb13d..86ecfa6 100644
--- a/usr.sbin/config/main.c
+++ b/usr.sbin/config/main.c
@@ -110,15 +110,25 @@ main(int argc, char **argv)
int ch, len;
char *p;
char *kernfile;
+ struct includepath* ipath;
int printmachine;
printmachine = 0;
kernfile = NULL;
- while ((ch = getopt(argc, argv, "Cd:gmpVx:")) != -1)
+ SLIST_INIT(&includepath);
+ while ((ch = getopt(argc, argv, "CI:d:gmpVx:")) != -1)
switch (ch) {
case 'C':
filebased = 1;
break;
+ case 'I':
+ ipath = (struct includepath *) \
+ calloc(1, sizeof (struct includepath));
+ if (ipath == NULL)
+ err(EXIT_FAILURE, "calloc");
+ ipath->path = optarg;
+ SLIST_INSERT_HEAD(&includepath, ipath, path_next);
+ break;
case 'm':
printmachine = 1;
break;
diff --git a/usr.sbin/config/mkmakefile.c b/usr.sbin/config/mkmakefile.c
index 324ad3b..cae2efc 100644
--- a/usr.sbin/config/mkmakefile.c
+++ b/usr.sbin/config/mkmakefile.c
@@ -43,6 +43,7 @@ static const char rcsid[] =
#include <ctype.h>
#include <err.h>
+#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <sys/param.h>
@@ -50,21 +51,6 @@ static const char rcsid[] =
#include "config.h"
#include "configvers.h"
-#define next_word(fp, wd) \
- { char *word = get_word(fp); \
- if (word == (char *)EOF) \
- return; \
- else \
- wd = word; \
- }
-#define next_quoted_word(fp, wd) \
- { char *word = get_quoted_word(fp); \
- if (word == (char *)EOF) \
- return; \
- else \
- wd = word; \
- }
-
static char *tail(char *);
static void do_clean(FILE *);
static void do_rules(FILE *);
@@ -74,6 +60,16 @@ static void do_before_depend(FILE *);
static int opteq(const char *, const char *);
static void read_files(void);
+static void errout(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
/*
* Lookup a file, by name.
*/
@@ -313,8 +309,8 @@ read_file(char *fname)
struct opt *op;
char *wd, *this, *compilewith, *depends, *clean, *warning;
const char *objprefix;
- int compile, match, nreqs, std, filetype,
- imp_rule, no_obj, before_depend, mandatory, nowerror;
+ int compile, match, nreqs, std, filetype, not,
+ imp_rule, no_obj, before_depend, nowerror;
fp = fopen(fname, "r");
if (fp == 0)
@@ -322,7 +318,7 @@ read_file(char *fname)
next:
/*
* include "filename"
- * filename [ standard | mandatory | optional ]
+ * filename [ standard | optional ]
* [ dev* [ | dev* ... ] | profiling-routine ] [ no-obj ]
* [ compile-with "compile rule" [no-implicit-rule] ]
* [ dependency "dependency-list"] [ before-depend ]
@@ -343,12 +339,9 @@ next:
goto next;
}
if (eq(wd, "include")) {
- next_quoted_word(fp, wd);
- if (wd == 0) {
- fprintf(stderr, "%s: missing include filename.\n",
- fname);
- exit(1);
- }
+ wd = get_quoted_word(fp);
+ if (wd == (char *)EOF || wd == 0)
+ errout("%s: missing include filename.\n", fname);
(void) snprintf(ifname, sizeof(ifname), "../../%s", wd);
read_file(ifname);
while (((wd = get_word(fp)) != (char *)EOF) && wd)
@@ -356,11 +349,11 @@ next:
goto next;
}
this = ns(wd);
- next_word(fp, wd);
- if (wd == 0) {
- fprintf(stderr, "%s: No type for %s.\n", fname, this);
- exit(1);
- }
+ wd = get_word(fp);
+ if (wd == (char *)EOF)
+ return;
+ if (wd == 0)
+ errout("%s: No type for %s.\n", fname, this);
tp = fl_lookup(this);
compile = 0;
match = 1;
@@ -369,186 +362,154 @@ next:
depends = 0;
clean = 0;
warning = 0;
- std = mandatory = 0;
+ std = 0;
imp_rule = 0;
no_obj = 0;
before_depend = 0;
nowerror = 0;
+ not = 0;
filetype = NORMAL;
objprefix = "";
- if (eq(wd, "standard")) {
+ if (eq(wd, "standard"))
std = 1;
- /*
- * If an entry is marked "mandatory", config will abort if it's
- * not called by a configuration line in the config file. Apart
- * from this, the device is handled like one marked "optional".
- */
- } else if (eq(wd, "mandatory")) {
- mandatory = 1;
- } else if (!eq(wd, "optional")) {
- fprintf(stderr,
- "%s: \"%s\" %s must be optional, mandatory or standard\n",
+ else if (!eq(wd, "optional"))
+ errout("%s: \"%s\" %s must be optional or standard\n",
fname, wd, this);
- exit(1);
- }
-nextparam:
- next_word(fp, wd);
- if (wd == 0) {
- compile += match;
- if (compile && tp == NULL)
- goto doneparam;
- goto next;
- }
- if (eq(wd, "|")) {
- if (nreqs == 0) {
- fprintf(stderr, "%s: syntax error describing %s\n",
- fname, this);
- exit(1);
+ for (wd = get_word(fp); wd; wd = get_word(fp)) {
+ if (wd == (char *)EOF)
+ return;
+ if (eq(wd, "!")) {
+ not = 1;
+ continue;
}
- compile += match;
- match = 1;
- nreqs = 0;
- goto nextparam;
- }
- if (eq(wd, "no-obj")) {
- no_obj++;
- goto nextparam;
- }
- if (eq(wd, "no-implicit-rule")) {
- if (compilewith == 0) {
- fprintf(stderr, "%s: alternate rule required when "
- "\"no-implicit-rule\" is specified.\n",
- fname);
+ if (eq(wd, "|")) {
+ if (nreqs == 0)
+ errout("%s: syntax error describing %s\n",
+ fname, this);
+ if (not)
+ compile += !match;
+ else
+ compile += match;
+ match = 1;
+ nreqs = 0;
+ not = 0;
+ continue;
}
- imp_rule++;
- goto nextparam;
- }
- if (eq(wd, "before-depend")) {
- before_depend++;
- goto nextparam;
- }
- if (eq(wd, "dependency")) {
- next_quoted_word(fp, wd);
- if (wd == 0) {
- fprintf(stderr,
- "%s: %s missing dependency string.\n",
- fname, this);
- exit(1);
+ if (eq(wd, "no-obj")) {
+ no_obj++;
+ continue;
}
- depends = ns(wd);
- goto nextparam;
- }
- if (eq(wd, "clean")) {
- next_quoted_word(fp, wd);
- if (wd == 0) {
- fprintf(stderr, "%s: %s missing clean file list.\n",
- fname, this);
- exit(1);
+ if (eq(wd, "no-implicit-rule")) {
+ if (compilewith == 0)
+ errout("%s: alternate rule required when "
+ "\"no-implicit-rule\" is specified for"
+ " %s.\n",
+ fname, this);
+ imp_rule++;
+ continue;
}
- clean = ns(wd);
- goto nextparam;
- }
- if (eq(wd, "compile-with")) {
- next_quoted_word(fp, wd);
- if (wd == 0) {
- fprintf(stderr,
- "%s: %s missing compile command string.\n",
- fname, this);
- exit(1);
+ if (eq(wd, "before-depend")) {
+ before_depend++;
+ continue;
}
- compilewith = ns(wd);
- goto nextparam;
- }
- if (eq(wd, "warning")) {
- next_quoted_word(fp, wd);
- if (wd == 0) {
- fprintf(stderr,
- "%s: %s missing warning text string.\n",
- fname, this);
- exit(1);
+ if (eq(wd, "dependency")) {
+ wd = get_quoted_word(fp);
+ if (wd == (char *)EOF || wd == 0)
+ errout("%s: %s missing dependency string.\n",
+ fname, this);
+ depends = ns(wd);
+ continue;
}
- warning = ns(wd);
- goto nextparam;
- }
- if (eq(wd, "obj-prefix")) {
- next_quoted_word(fp, wd);
- if (wd == 0) {
- printf("%s: %s missing object prefix string.\n",
- fname, this);
- exit(1);
+ if (eq(wd, "clean")) {
+ wd = get_quoted_word(fp);
+ if (wd == (char *)EOF || wd == 0)
+ errout("%s: %s missing clean file list.\n",
+ fname, this);
+ clean = ns(wd);
+ continue;
}
- objprefix = ns(wd);
- goto nextparam;
- }
- nreqs++;
- if (eq(wd, "local")) {
- filetype = LOCAL;
- goto nextparam;
- }
- if (eq(wd, "no-depend")) {
- filetype = NODEPEND;
- goto nextparam;
- }
- if (eq(wd, "profiling-routine")) {
- filetype = PROFILING;
- goto nextparam;
- }
- if (eq(wd, "nowerror")) {
- nowerror = 1;
- goto nextparam;
- }
- STAILQ_FOREACH(dp, &dtab, d_next)
- if (eq(dp->d_name, wd)) {
- dp->d_done |= DEVDONE;
- goto nextparam;
+ if (eq(wd, "compile-with")) {
+ wd = get_quoted_word(fp);
+ if (wd == (char *)EOF || wd == 0)
+ errout("%s: %s missing compile command string.\n",
+ fname, this);
+ compilewith = ns(wd);
+ continue;
}
- if (mandatory) {
- fprintf(stderr, "%s: mandatory device \"%s\" not found\n",
- fname, wd);
- exit(1);
- }
- if (std) {
- fprintf(stderr,
- "standard entry %s has a device keyword - %s!\n",
- this, wd);
- exit(1);
- }
- SLIST_FOREACH(op, &opt, op_next)
- if (op->op_value == 0 && opteq(op->op_name, wd))
- goto nextparam;
- match = 0;
- goto nextparam;
-
-doneparam:
- if (std == 0 && nreqs == 0) {
- fprintf(stderr, "%s: what is %s optional on?\n",
- fname, this);
- exit(1);
- }
-
- if (wd) {
- fprintf(stderr, "%s: syntax error describing %s\n",
- fname, this);
- exit(1);
+ if (eq(wd, "warning")) {
+ wd = get_quoted_word(fp);
+ if (wd == (char *)EOF || wd == 0)
+ errout("%s: %s missing warning text string.\n",
+ fname, this);
+ warning = ns(wd);
+ continue;
+ }
+ if (eq(wd, "obj-prefix")) {
+ wd = get_quoted_word(fp);
+ if (wd == (char *)EOF || wd == 0)
+ errout("%s: %s missing object prefix string.\n",
+ fname, this);
+ objprefix = ns(wd);
+ continue;
+ }
+ if (eq(wd, "nowerror")) {
+ nowerror = 1;
+ continue;
+ }
+ if (eq(wd, "local")) {
+ filetype = LOCAL;
+ continue;
+ }
+ if (eq(wd, "no-depend")) {
+ filetype = NODEPEND;
+ continue;
+ }
+ nreqs++;
+ if (eq(wd, "profiling-routine")) {
+ filetype = PROFILING;
+ continue;
+ }
+ if (std)
+ errout("standard entry %s has optional inclusion specifier %s!\n",
+ this, wd);
+ STAILQ_FOREACH(dp, &dtab, d_next)
+ if (eq(dp->d_name, wd)) {
+ dp->d_done |= DEVDONE;
+ goto nextparam;
+ }
+ SLIST_FOREACH(op, &opt, op_next)
+ if (op->op_value == 0 && opteq(op->op_name, wd))
+ goto nextparam;
+ match = 0;
+nextparam:;
+ }
+ if (not)
+ compile += !match;
+ else
+ compile += match;
+ if (compile && tp == NULL) {
+ if (std == 0 && nreqs == 0)
+ errout("%s: what is %s optional on?\n",
+ fname, this);
+ if (filetype == PROFILING && profiling == 0)
+ goto next;
+ tp = new_fent();
+ tp->f_fn = this;
+ tp->f_type = filetype;
+ if (imp_rule)
+ tp->f_flags |= NO_IMPLCT_RULE;
+ if (no_obj)
+ tp->f_flags |= NO_OBJ;
+ if (before_depend)
+ tp->f_flags |= BEFORE_DEPEND;
+ if (nowerror)
+ tp->f_flags |= NOWERROR;
+ tp->f_compilewith = compilewith;
+ tp->f_depends = depends;
+ tp->f_clean = clean;
+ tp->f_warn = warning;
+ tp->f_objprefix = objprefix;
}
- if (filetype == PROFILING && profiling == 0)
- goto next;
- tp = new_fent();
- tp->f_fn = this;
- tp->f_type = filetype;
- if (imp_rule)
- tp->f_flags |= NO_IMPLCT_RULE;
- if (no_obj)
- tp->f_flags |= NO_OBJ;
- if (before_depend)
- tp->f_flags |= BEFORE_DEPEND;
- if (nowerror)
- tp->f_flags |= NOWERROR;
- tp->f_compilewith = compilewith;
- tp->f_depends = depends;
- tp->f_clean = clean;
- tp->f_warn = warning;
- tp->f_objprefix = objprefix;
goto next;
}
diff --git a/usr.sbin/crashinfo/crashinfo.sh b/usr.sbin/crashinfo/crashinfo.sh
index cf60a62..557d810 100755
--- a/usr.sbin/crashinfo/crashinfo.sh
+++ b/usr.sbin/crashinfo/crashinfo.sh
@@ -181,9 +181,9 @@ fi
echo
echo "------------------------------------------------------------------------"
-echo "ps -axl"
+echo "ps -axlww"
echo
-ps -M $VMCORE -N $KERNEL -axl
+ps -M $VMCORE -N $KERNEL -axlww
echo
echo "------------------------------------------------------------------------"
@@ -268,12 +268,6 @@ netstat -M $VMCORE -N $KERNEL -m
echo
echo "------------------------------------------------------------------------"
-echo "netstat -idW"
-echo
-netstat -M $VMCORE -N $KERNEL -idW
-echo
-
-echo "------------------------------------------------------------------------"
echo "netstat -anr"
echo
netstat -M $VMCORE -N $KERNEL -anr
diff --git a/usr.sbin/cron/cron/cron.c b/usr.sbin/cron/cron/cron.c
index d374319..0cdb9e3 100644
--- a/usr.sbin/cron/cron/cron.c
+++ b/usr.sbin/cron/cron/cron.c
@@ -376,30 +376,17 @@ cron_sync(int secres) {
}
}
-static int
+static void
timespec_subtract(struct timespec *result, struct timespec *x,
struct timespec *y)
{
- time_t nsec;
-
- /* Perform the carry for the later subtraction by updating y. */
- if (x->tv_nsec < y->tv_nsec) {
- nsec = (y->tv_nsec - x->tv_nsec) / 10000000 + 1;
- y->tv_nsec -= 1000000000 * nsec;
- y->tv_sec += nsec;
- }
- if (x->tv_nsec - y->tv_nsec > 1000000000) {
- nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
- y->tv_nsec += 1000000000 * nsec;
- y->tv_sec -= nsec;
+ *result = *x;
+ result->tv_sec -= y->tv_sec;
+ result->tv_nsec -= y->tv_nsec;
+ if (result->tv_nsec < 0) {
+ result->tv_sec--;
+ result->tv_nsec += 1000000000;
}
-
- /* tv_nsec is certainly positive. */
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_nsec = x->tv_nsec - y->tv_nsec;
-
- /* Return True if result is negative. */
- return (x->tv_sec < y->tv_sec);
}
static void
diff --git a/usr.sbin/crunch/examples/Makefile b/usr.sbin/crunch/examples/Makefile
index 1208301..01b9242 100644
--- a/usr.sbin/crunch/examples/Makefile
+++ b/usr.sbin/crunch/examples/Makefile
@@ -11,7 +11,7 @@ CONF= $(CRUNCHED).conf
OUTMK= $(CRUNCHED).mk
OUTPUTS= $(OUTMK) $(CRUNCHED).c $(CRUNCHED).cache
-NO_MAN=
+MAN=
CLEANFILES+= $(CRUNCHED) *.o *.lo *.c *.mk *.cache
CLEANDIRFILES+= $(OUTPUTS)
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index b9d4e61..005225c 100644
--- a/usr.sbin/ctladm/ctladm.8
+++ b/usr.sbin/ctladm/ctladm.8
@@ -34,7 +34,7 @@
.\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $
.\" $FreeBSD$
.\"
-.Dd April 2, 2013
+.Dd October 30, 2013
.Dt CTLADM 8
.Os
.Sh NAME
@@ -202,10 +202,10 @@
.Op Fl x
.Nm
.Ic islogout
-.Aq Fl a | Fl h Ar host | Fl c Ar connection-id | Fl i Ar name
+.Aq Fl a | Fl c Ar connection-id | Fl i Ar name | Fl p Ar portal
.Nm
.Ic isterminate
-.Aq Fl a | Fl h Ar host | Fl c Ar connection-id | Fl i Ar name
+.Aq Fl a | Fl c Ar connection-id | Fl i Ar name | Fl p Ar portal
.Nm
.Ic help
.Sh DESCRIPTION
@@ -909,24 +909,24 @@ Ask the initiator to log out iSCSI connections matching criteria.
.Bl -tag -width 11n
.It Fl a
Log out all connections.
-.It Fl h
-Specify initiator IP address.
.It Fl c
Specify connection ID.
.It Fl i
Specify initiator name.
+.It Fl p
+Specify initiator portal (hostname or IP address).
.El
.It Ic isterminate
Forcibly terminate iSCSI connections matching criteria.
.Bl -tag -width 11n
.It Fl a
Terminate all connections.
-.It Fl h
-Specify initiator IP address.
.It Fl c
Specify connection ID.
.It Fl i
Specify initiator name.
+.It Fl p
+Specify initiator portal (hostname or IP address).
.El
.It Ic help
Display
diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c
index 6f03de0..7833155 100644
--- a/usr.sbin/ctladm/ctladm.c
+++ b/usr.sbin/ctladm/ctladm.c
@@ -184,8 +184,8 @@ static struct ctladm_opts option_table[] = {
{"inject", CTLADM_CMD_ERR_INJECT, CTLADM_ARG_NEED_TL, "cd:i:p:r:s:"},
{"inquiry", CTLADM_CMD_INQUIRY, CTLADM_ARG_NEED_TL, NULL},
{"islist", CTLADM_CMD_ISLIST, CTLADM_ARG_NONE, "vx"},
- {"islogout", CTLADM_CMD_ISLOGOUT, CTLADM_ARG_NONE, "ah:c:i:"},
- {"isterminate", CTLADM_CMD_ISTERMINATE, CTLADM_ARG_NONE, "ah:c:i:"},
+ {"islogout", CTLADM_CMD_ISLOGOUT, CTLADM_ARG_NONE, "ac:i:p:"},
+ {"isterminate", CTLADM_CMD_ISTERMINATE, CTLADM_ARG_NONE, "ac:i:p:"},
{"lunlist", CTLADM_CMD_LUNLIST, CTLADM_ARG_NONE, NULL},
{"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"},
{"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:s:"},
@@ -3633,21 +3633,21 @@ retry:
if (verbose != 0) {
STAILQ_FOREACH(conn, &islist.conn_list, links) {
- printf("Session ID: %d\n", conn->connection_id);
- printf("Initiator name: %s\n", conn->initiator);
- printf("Initiator addr: %s\n", conn->initiator_addr);
- printf("Initiator alias: %s\n", conn->initiator_alias);
- printf("Target name: %s\n", conn->target);
- printf("Target alias: %s\n", conn->target_alias);
- printf("Header digest: %s\n", conn->header_digest);
- printf("Data digest: %s\n", conn->data_digest);
- printf("DataSegmentLen: %s\n", conn->max_data_segment_length);
- printf("ImmediateData: %s\n", conn->immediate_data ? "Yes" : "No");
- printf("iSER (RDMA): %s\n", conn->iser ? "Yes" : "No");
+ printf("Session ID: %d\n", conn->connection_id);
+ printf("Initiator name: %s\n", conn->initiator);
+ printf("Initiator portal: %s\n", conn->initiator_addr);
+ printf("Initiator alias: %s\n", conn->initiator_alias);
+ printf("Target name: %s\n", conn->target);
+ printf("Target alias: %s\n", conn->target_alias);
+ printf("Header digest: %s\n", conn->header_digest);
+ printf("Data digest: %s\n", conn->data_digest);
+ printf("DataSegmentLen: %s\n", conn->max_data_segment_length);
+ printf("ImmediateData: %s\n", conn->immediate_data ? "Yes" : "No");
+ printf("iSER (RDMA): %s\n", conn->iser ? "Yes" : "No");
printf("\n");
}
} else {
- printf("%4s %-16s %-36s %-36s\n", "ID", "Address", "Initiator name",
+ printf("%4s %-16s %-36s %-36s\n", "ID", "Portal", "Initiator name",
"Target name");
STAILQ_FOREACH(conn, &islist.conn_list, links) {
printf("%4u %-16s %-36s %-36s\n",
@@ -3675,12 +3675,6 @@ cctl_islogout(int fd, int argc, char **argv, char *combinedopt)
all = 1;
nargs++;
break;
- case 'h':
- initiator_addr = strdup(optarg);
- if (initiator_addr == NULL)
- err(1, "%s: strdup", __func__);
- nargs++;
- break;
case 'c':
connection_id = strtoul(optarg, NULL, 0);
nargs++;
@@ -3691,16 +3685,22 @@ cctl_islogout(int fd, int argc, char **argv, char *combinedopt)
err(1, "%s: strdup", __func__);
nargs++;
break;
+ case 'p':
+ initiator_addr = strdup(optarg);
+ if (initiator_addr == NULL)
+ err(1, "%s: strdup", __func__);
+ nargs++;
+ break;
default:
break;
}
}
if (nargs == 0)
- errx(1, "%s: either -a, -h, -c, or -i must be specified",
+ errx(1, "%s: either -a, -c, -i, or -p must be specified",
__func__);
if (nargs > 1)
- errx(1, "%s: only one of -a, -h, -c, or -i may be specified",
+ errx(1, "%s: only one of -a, -c, -i, or -p may be specified",
__func__);
bzero(&req, sizeof(req));
@@ -3748,12 +3748,6 @@ cctl_isterminate(int fd, int argc, char **argv, char *combinedopt)
all = 1;
nargs++;
break;
- case 'h':
- initiator_addr = strdup(optarg);
- if (initiator_addr == NULL)
- err(1, "%s: strdup", __func__);
- nargs++;
- break;
case 'c':
connection_id = strtoul(optarg, NULL, 0);
nargs++;
@@ -3764,16 +3758,22 @@ cctl_isterminate(int fd, int argc, char **argv, char *combinedopt)
err(1, "%s: strdup", __func__);
nargs++;
break;
+ case 'p':
+ initiator_addr = strdup(optarg);
+ if (initiator_addr == NULL)
+ err(1, "%s: strdup", __func__);
+ nargs++;
+ break;
default:
break;
}
}
if (nargs == 0)
- errx(1, "%s: either -a, -h, -c, or -i must be specified",
+ errx(1, "%s: either -a, -c, -i, or -p must be specified",
__func__);
if (nargs > 1)
- errx(1, "%s: only one of -a, -h, -c, or -i may be specified",
+ errx(1, "%s: only one of -a, -c, -i, or -p may be specified",
__func__);
bzero(&req, sizeof(req));
@@ -4121,8 +4121,8 @@ usage(int error)
" ctladm port <-l | -o <on|off> | [-w wwnn][-W wwpn]>\n"
" [-p targ_port] [-t port_type] [-q] [-x]\n"
" ctladm islist [-v | -x]\n"
-" ctladm islogout <-A | -a addr | -c connection-id | -n name>\n"
-" ctladm isterminate <-A | -a addr | -c connection-id | -n name>\n"
+" ctladm islogout <-a | -c connection-id | -i name | -p portal>\n"
+" ctladm isterminate <-a | -c connection-id | -i name | -p portal>\n"
" ctladm dumpooa\n"
" ctladm dumpstructs\n"
" ctladm help\n"
diff --git a/usr.sbin/ctld/ctl.conf.5 b/usr.sbin/ctld/ctl.conf.5
index fb8bc2a..3570667 100644
--- a/usr.sbin/ctld/ctl.conf.5
+++ b/usr.sbin/ctld/ctl.conf.5
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 24, 2013
+.Dd April 24, 2014
.Dt CTL.CONF 5
.Os
.Sh NAME
@@ -41,7 +41,7 @@ configuration file is used by the
daemon.
Lines starting with
.Ql #
-and empty lines are interpreted as comments.
+are interpreted as comments.
The general syntax of the
.Nm
file is:
@@ -98,25 +98,44 @@ will be forcibly terminated.
The default is 60.
Setting it to 0 disables the timeout.
.El
-.Ss auth-grup level
+.Ss auth-group level
The following statements are available at the auth-group level:
.Bl -tag -width indent
+.It Ic auth-type Ao Ar type Ac
+Specifies authentication type.
+Type can be either "none", "deny", "chap", or "chap-mutual".
+In most cases it is not neccessary to set the type using this clause;
+it is usually used to disable authentication for a given auth-group.
.It Ic chap Ao Ar user Ac Aq Ar secret
Specifies CHAP authentication credentials.
.It Ic chap-mutual Ao Ar user Ac Ao Ar secret Ac Ao Ar mutualuser Ac Aq Ar mutualsecret
Specifies mutual CHAP authentication credentials.
Note that for any auth-group, configuration may contain either chap,
or chap-mutual entries; it's an error to mix them.
+.It Ic initiator-name Ao Ar initiator-name Ac
+Specifies iSCSI initiator name.
+If not defined, there will be no restrictions based on initiator
+name.
+Otherwise, only initiators with names matching one of defined
+ones will be allowed to connect.
+.It Ic initiator-portal Ao Ar address Ac
+Specifies iSCSI initiator portal - IPv4 or IPv6 address.
+If not defined, there will be no restrictions based on initiator
+address.
+Otherwise, only initiators with addresses matching one of defined
+ones will be allowed to connect.
.El
.Ss portal-group level
The following statements are available at the portal-group level:
.Bl -tag -width indent
.It Ic discovery-auth-group Aq Ar name
-Assigns previously defined authentication group to that portal group,
+Assigns previously defined authentication group to the portal group,
to be used for target discovery.
-By default, the discovery will be denied.
-A special auth-group, "no-authentication", may be used to allow for discovery
-without authentication.
+By default, portal groups that do not specify their own auth settings,
+using clauses such as "chap" or "initiator-name", are assigned
+predefined auth-group "default", which denies discovery.
+Another predefined auth-group, "no-authentication", may be used
+to permit discovery without authentication.
.It Ic listen Aq Ar address
Specifies IPv4 or IPv6 address and port to listen on for incoming connections.
.It Ic listen-iser Aq Ar address
@@ -127,24 +146,48 @@ using iSER (iSCSI over RDMA) protocol.
The following statements are available at the target level:
.Bl -tag -width indent
.It Ic alias Aq Ar text
-Assigns human-readable description to that target.
+Assigns human-readable description to the target.
There is no default.
.It Ic auth-group Aq Ar name
-Assigns previously defined authentication group to that target.
-There is no default; every target must use either auth-group,
-or chap, or chap-mutual statements.
-A special auth-group, "no-authentication", may be used to permit access
+Assigns previously defined authentication group to the target.
+By default, targets that do not specify their own auth settings,
+using clauses such as "chap" or "initiator-name", are assigned
+predefined auth-group "default", which denies all access.
+Another predefined auth-group, "no-authentication", may be used to permit access
without authentication.
+.It Ic auth-type Ao Ar type Ac
+Specifies authentication type.
+Type can be either "none", "deny", "chap", or "chap-mutual".
+In most cases it is not neccessary to set the type using this clause;
+it is usually used to disable authentication for a given target.
+This clause is mutually exclusive with auth-group; one cannot use
+both in a single target.
.It Ic chap Ao Ar user Ac Aq Ar secret
Specifies CHAP authentication credentials.
Note that targets must use either auth-group, or chap,
or chap-mutual clauses; it's a configuration error to mix them in one target.
.It Ic chap-mutual Ao Ar user Ac Ao Ar secret Ac Ao Ar mutualuser Ac Aq Ar mutualsecret
Specifies mutual CHAP authentication credentials.
-Note that targets must use either auth-group, chap,
+Note that targets must use either auth-group, chap, or
chap-mutual clauses; it's a configuration error to mix them in one target.
+.It Ic initiator-name Ao Ar initiator-name Ac
+Specifies iSCSI initiator name.
+If not defined, there will be no restrictions based on initiator
+name.
+Otherwise, only initiators with names matching one of defined
+ones will be allowed to connect.
+This clause is mutually exclusive with auth-group; one cannot use
+both in a single target.
+.It Ic initiator-portal Ao Ar address Ac
+Specifies iSCSI initiator portal - IPv4 or IPv6 address.
+If not defined, there will be no restrictions based on initiator
+address.
+Otherwise, only initiators with addresses matching one of defined
+ones will be allowed to connect.
+This clause is mutually exclusive with auth-group; one cannot use
+both in a single target.
.It Ic portal-group Aq Ar name
-Assigns previously defined portal group to that target.
+Assigns previously defined portal group to the target.
Default portal group is "default", which makes the target available
on TCP port 3260 on all configured IPv4 and IPv6 addresses.
.It Ic lun Aq Ar number
@@ -160,7 +203,7 @@ Valid choices are
and
.Dq ramdisk ;
block is used for LUNs backed
-by files in the filesystem; ramdisk is a bitsink device, used mostly for
+by files or disk device nodes; ramdisk is a bitsink device, used mostly for
testing.
The default backend is block.
.It Ic blocksize Aq Ar size
@@ -171,7 +214,7 @@ Specifies SCSI Device Identification string presented to the initiator.
.It Ic option Ao Ar name Ac Aq Ar value
Specifies CTL-specific options passed to the kernel.
.It Ic path Aq Ar path
-Specifies path to file used to back the LUN.
+Specifies path to file or device node used to back the LUN.
.It Ic serial Aq Ar string
Specifies SCSI serial number presented to the initiator.
.It Ic size Aq Ar size
@@ -202,7 +245,7 @@ portal-group example2 {
}
target iqn.2012-06.com.example:target0 {
- alias "Testing target"
+ alias "Example target"
auth-group no-authentication
lun 0 {
path /dev/zvol/example_0
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index a5472ab..2cda316 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -48,6 +48,8 @@
#include "ctld.h"
+bool proxy_mode = false;
+
static volatile bool sighup_received = false;
static volatile bool sigterm_received = false;
static volatile bool sigalrm_received = false;
@@ -137,7 +139,7 @@ auth_delete(struct auth *auth)
}
const struct auth *
-auth_find(struct auth_group *ag, const char *user)
+auth_find(const struct auth_group *ag, const char *user)
{
const struct auth *auth;
@@ -149,57 +151,6 @@ auth_find(struct auth_group *ag, const char *user)
return (NULL);
}
-struct auth_group *
-auth_group_new(struct conf *conf, const char *name)
-{
- struct auth_group *ag;
-
- if (name != NULL) {
- ag = auth_group_find(conf, name);
- if (ag != NULL) {
- log_warnx("duplicated auth-group \"%s\"", name);
- return (NULL);
- }
- }
-
- ag = calloc(1, sizeof(*ag));
- if (ag == NULL)
- log_err(1, "calloc");
- if (name != NULL)
- ag->ag_name = checked_strdup(name);
- TAILQ_INIT(&ag->ag_auths);
- ag->ag_conf = conf;
- TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
-
- return (ag);
-}
-
-void
-auth_group_delete(struct auth_group *ag)
-{
- struct auth *auth, *tmp;
-
- TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
-
- TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, tmp)
- auth_delete(auth);
- free(ag->ag_name);
- free(ag);
-}
-
-struct auth_group *
-auth_group_find(struct conf *conf, const char *name)
-{
- struct auth_group *ag;
-
- TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
- if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
- return (ag);
- }
-
- return (NULL);
-}
-
static void
auth_check_secret_length(struct auth *auth)
{
@@ -215,7 +166,7 @@ auth_check_secret_length(struct auth *auth)
log_warnx("secret for user \"%s\", target \"%s\", "
"is too long; it should be at most 16 characters "
"long", auth->a_user,
- auth->a_auth_group->ag_target->t_iqn);
+ auth->a_auth_group->ag_target->t_name);
}
if (len < 12) {
if (auth->a_auth_group->ag_name != NULL)
@@ -227,7 +178,7 @@ auth_check_secret_length(struct auth *auth)
log_warnx("secret for user \"%s\", target \"%s\", "
"is too short; it should be at least 16 characters "
"long", auth->a_user,
- auth->a_auth_group->ag_target->t_iqn);
+ auth->a_auth_group->ag_target->t_name);
}
if (auth->a_mutual_secret != NULL) {
@@ -243,7 +194,7 @@ auth_check_secret_length(struct auth *auth)
"target \"%s\", is too long; it should "
"be at most 16 characters long",
auth->a_user,
- auth->a_auth_group->ag_target->t_iqn);
+ auth->a_auth_group->ag_target->t_name);
}
if (len < 12) {
if (auth->a_auth_group->ag_name != NULL)
@@ -256,7 +207,7 @@ auth_check_secret_length(struct auth *auth)
"target \"%s\", is too short; it should be "
"at least 16 characters long",
auth->a_user,
- auth->a_auth_group->ag_target->t_iqn);
+ auth->a_auth_group->ag_target->t_name);
}
}
}
@@ -276,7 +227,7 @@ auth_new_chap(struct auth_group *ag, const char *user,
else
log_warnx("cannot mix \"chap\" authentication with "
"other types for target \"%s\"",
- ag->ag_target->t_iqn);
+ ag->ag_target->t_name);
return (NULL);
}
@@ -305,7 +256,7 @@ auth_new_chap_mutual(struct auth_group *ag, const char *user,
else
log_warnx("cannot mix \"chap-mutual\" authentication "
"with other types for target \"%s\"",
- ag->ag_target->t_iqn);
+ ag->ag_target->t_name);
return (NULL);
}
@@ -320,6 +271,208 @@ auth_new_chap_mutual(struct auth_group *ag, const char *user,
return (auth);
}
+const struct auth_name *
+auth_name_new(struct auth_group *ag, const char *name)
+{
+ struct auth_name *an;
+
+ an = calloc(1, sizeof(*an));
+ if (an == NULL)
+ log_err(1, "calloc");
+ an->an_auth_group = ag;
+ an->an_initator_name = checked_strdup(name);
+ TAILQ_INSERT_TAIL(&ag->ag_names, an, an_next);
+ return (an);
+}
+
+static void
+auth_name_delete(struct auth_name *an)
+{
+ TAILQ_REMOVE(&an->an_auth_group->ag_names, an, an_next);
+
+ free(an->an_initator_name);
+ free(an);
+}
+
+bool
+auth_name_defined(const struct auth_group *ag)
+{
+ if (TAILQ_EMPTY(&ag->ag_names))
+ return (false);
+ return (true);
+}
+
+const struct auth_name *
+auth_name_find(const struct auth_group *ag, const char *name)
+{
+ const struct auth_name *auth_name;
+
+ TAILQ_FOREACH(auth_name, &ag->ag_names, an_next) {
+ if (strcmp(auth_name->an_initator_name, name) == 0)
+ return (auth_name);
+ }
+
+ return (NULL);
+}
+
+const struct auth_portal *
+auth_portal_new(struct auth_group *ag, const char *portal)
+{
+ struct auth_portal *ap;
+
+ ap = calloc(1, sizeof(*ap));
+ if (ap == NULL)
+ log_err(1, "calloc");
+ ap->ap_auth_group = ag;
+ ap->ap_initator_portal = checked_strdup(portal);
+ TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
+ return (ap);
+}
+
+static void
+auth_portal_delete(struct auth_portal *ap)
+{
+ TAILQ_REMOVE(&ap->ap_auth_group->ag_portals, ap, ap_next);
+
+ free(ap->ap_initator_portal);
+ free(ap);
+}
+
+bool
+auth_portal_defined(const struct auth_group *ag)
+{
+ if (TAILQ_EMPTY(&ag->ag_portals))
+ return (false);
+ return (true);
+}
+
+const struct auth_portal *
+auth_portal_find(const struct auth_group *ag, const char *portal)
+{
+ const struct auth_portal *auth_portal;
+
+ TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next) {
+ if (strcmp(auth_portal->ap_initator_portal, portal) == 0)
+ return (auth_portal);
+ }
+
+ return (NULL);
+}
+
+struct auth_group *
+auth_group_new(struct conf *conf, const char *name)
+{
+ struct auth_group *ag;
+
+ if (name != NULL) {
+ ag = auth_group_find(conf, name);
+ if (ag != NULL) {
+ log_warnx("duplicated auth-group \"%s\"", name);
+ return (NULL);
+ }
+ }
+
+ ag = calloc(1, sizeof(*ag));
+ if (ag == NULL)
+ log_err(1, "calloc");
+ if (name != NULL)
+ ag->ag_name = checked_strdup(name);
+ TAILQ_INIT(&ag->ag_auths);
+ TAILQ_INIT(&ag->ag_names);
+ TAILQ_INIT(&ag->ag_portals);
+ ag->ag_conf = conf;
+ TAILQ_INSERT_TAIL(&conf->conf_auth_groups, ag, ag_next);
+
+ return (ag);
+}
+
+void
+auth_group_delete(struct auth_group *ag)
+{
+ struct auth *auth, *auth_tmp;
+ struct auth_name *auth_name, *auth_name_tmp;
+ struct auth_portal *auth_portal, *auth_portal_tmp;
+
+ TAILQ_REMOVE(&ag->ag_conf->conf_auth_groups, ag, ag_next);
+
+ TAILQ_FOREACH_SAFE(auth, &ag->ag_auths, a_next, auth_tmp)
+ auth_delete(auth);
+ TAILQ_FOREACH_SAFE(auth_name, &ag->ag_names, an_next, auth_name_tmp)
+ auth_name_delete(auth_name);
+ TAILQ_FOREACH_SAFE(auth_portal, &ag->ag_portals, ap_next,
+ auth_portal_tmp)
+ auth_portal_delete(auth_portal);
+ free(ag->ag_name);
+ free(ag);
+}
+
+struct auth_group *
+auth_group_find(const struct conf *conf, const char *name)
+{
+ struct auth_group *ag;
+
+ TAILQ_FOREACH(ag, &conf->conf_auth_groups, ag_next) {
+ if (ag->ag_name != NULL && strcmp(ag->ag_name, name) == 0)
+ return (ag);
+ }
+
+ return (NULL);
+}
+
+static int
+auth_group_set_type(struct auth_group *ag, int type)
+{
+
+ if (ag->ag_type == AG_TYPE_UNKNOWN) {
+ ag->ag_type = type;
+ return (0);
+ }
+
+ if (ag->ag_type == type)
+ return (0);
+
+ return (1);
+}
+
+int
+auth_group_set_type_str(struct auth_group *ag, const char *str)
+{
+ int error, type;
+
+ if (strcmp(str, "none") == 0) {
+ type = AG_TYPE_NO_AUTHENTICATION;
+ } else if (strcmp(str, "deny") == 0) {
+ type = AG_TYPE_DENY;
+ } else if (strcmp(str, "chap") == 0) {
+ type = AG_TYPE_CHAP;
+ } else if (strcmp(str, "chap-mutual") == 0) {
+ type = AG_TYPE_CHAP_MUTUAL;
+ } else {
+ if (ag->ag_name != NULL)
+ log_warnx("invalid auth-type \"%s\" for auth-group "
+ "\"%s\"", str, ag->ag_name);
+ else
+ log_warnx("invalid auth-type \"%s\" for target "
+ "\"%s\"", str, ag->ag_target->t_name);
+ return (1);
+ }
+
+ error = auth_group_set_type(ag, type);
+ if (error != 0) {
+ if (ag->ag_name != NULL)
+ log_warnx("cannot set auth-type to \"%s\" for "
+ "auth-group \"%s\"; already has a different "
+ "type", str, ag->ag_name);
+ else
+ log_warnx("cannot set auth-type to \"%s\" for target "
+ "\"%s\"; already has a different type",
+ str, ag->ag_target->t_name);
+ return (1);
+ }
+
+ return (error);
+}
+
static struct portal *
portal_new(struct portal_group *pg)
{
@@ -381,7 +534,7 @@ portal_group_delete(struct portal_group *pg)
}
struct portal_group *
-portal_group_find(struct conf *conf, const char *name)
+portal_group_find(const struct conf *conf, const char *name)
{
struct portal_group *pg;
@@ -402,14 +555,6 @@ portal_group_add_listen(struct portal_group *pg, const char *value, bool iser)
const char *port;
int error, colons = 0;
-#ifndef ICL_KERNEL_PROXY
- if (iser) {
- log_warnx("ctld(8) compiled without ICL_KERNEL_PROXY "
- "does not support iSER protocol");
- return (-1);
- }
-#endif
-
portal = portal_new(pg);
portal->p_listen = checked_strdup(value);
portal->p_iser = iser;
@@ -589,31 +734,31 @@ valid_iscsi_name(const char *name)
}
struct target *
-target_new(struct conf *conf, const char *iqn)
+target_new(struct conf *conf, const char *name)
{
struct target *targ;
int i, len;
- targ = target_find(conf, iqn);
+ targ = target_find(conf, name);
if (targ != NULL) {
- log_warnx("duplicated target \"%s\"", iqn);
+ log_warnx("duplicated target \"%s\"", name);
return (NULL);
}
- if (valid_iscsi_name(iqn) == false) {
- log_warnx("target name \"%s\" is invalid", iqn);
+ if (valid_iscsi_name(name) == false) {
+ log_warnx("target name \"%s\" is invalid", name);
return (NULL);
}
targ = calloc(1, sizeof(*targ));
if (targ == NULL)
log_err(1, "calloc");
- targ->t_iqn = checked_strdup(iqn);
+ targ->t_name = checked_strdup(name);
/*
* RFC 3722 requires us to normalize the name to lowercase.
*/
- len = strlen(iqn);
+ len = strlen(name);
for (i = 0; i < len; i++)
- targ->t_iqn[i] = tolower(targ->t_iqn[i]);
+ targ->t_name[i] = tolower(targ->t_name[i]);
TAILQ_INIT(&targ->t_luns);
targ->t_conf = conf;
@@ -631,17 +776,17 @@ target_delete(struct target *targ)
TAILQ_FOREACH_SAFE(lun, &targ->t_luns, l_next, tmp)
lun_delete(lun);
- free(targ->t_iqn);
+ free(targ->t_name);
free(targ);
}
struct target *
-target_find(struct conf *conf, const char *iqn)
+target_find(struct conf *conf, const char *name)
{
struct target *targ;
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
- if (strcasecmp(targ->t_iqn, iqn) == 0)
+ if (strcasecmp(targ->t_name, name) == 0)
return (targ);
}
@@ -656,7 +801,7 @@ lun_new(struct target *targ, int lun_id)
lun = lun_find(targ, lun_id);
if (lun != NULL) {
log_warnx("duplicated lun %d for target \"%s\"",
- lun_id, targ->t_iqn);
+ lun_id, targ->t_name);
return (NULL);
}
@@ -688,7 +833,7 @@ lun_delete(struct lun *lun)
}
struct lun *
-lun_find(struct target *targ, int lun_id)
+lun_find(const struct target *targ, int lun_id)
{
struct lun *lun;
@@ -757,7 +902,7 @@ lun_option_new(struct lun *lun, const char *name, const char *value)
lo = lun_option_find(lun, name);
if (lo != NULL) {
log_warnx("duplicated lun option %s for lun %d, target \"%s\"",
- name, lun->l_lun, lun->l_target->t_iqn);
+ name, lun->l_lun, lun->l_target->t_name);
return (NULL);
}
@@ -784,7 +929,7 @@ lun_option_delete(struct lun_option *lo)
}
struct lun_option *
-lun_option_find(struct lun *lun, const char *name)
+lun_option_find(const struct lun *lun, const char *name)
{
struct lun_option *lo;
@@ -832,6 +977,8 @@ conf_print(struct conf *conf)
{
struct auth_group *ag;
struct auth *auth;
+ struct auth_name *auth_name;
+ struct auth_portal *auth_portal;
struct portal_group *pg;
struct portal *portal;
struct target *targ;
@@ -844,6 +991,12 @@ conf_print(struct conf *conf)
fprintf(stderr, "\t chap-mutual %s %s %s %s\n",
auth->a_user, auth->a_secret,
auth->a_mutual_user, auth->a_mutual_secret);
+ TAILQ_FOREACH(auth_name, &ag->ag_names, an_next)
+ fprintf(stderr, "\t initiator-name %s\n",
+ auth_name->an_initator_name);
+ TAILQ_FOREACH(auth_portal, &ag->ag_portals, an_next)
+ fprintf(stderr, "\t initiator-portal %s\n",
+ auth_portal->an_initator_portal);
fprintf(stderr, "}\n");
}
TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
@@ -853,7 +1006,7 @@ conf_print(struct conf *conf)
fprintf(stderr, "}\n");
}
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
- fprintf(stderr, "target %s {\n", targ->t_iqn);
+ fprintf(stderr, "target %s {\n", targ->t_name);
if (targ->t_alias != NULL)
fprintf(stderr, "\t alias %s\n", targ->t_alias);
TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
@@ -869,95 +1022,104 @@ conf_print(struct conf *conf)
}
#endif
+static int
+conf_verify_lun(struct lun *lun)
+{
+ const struct lun *lun2;
+ const struct target *targ2;
+
+ if (lun->l_backend == NULL)
+ lun_set_backend(lun, "block");
+ if (strcmp(lun->l_backend, "block") == 0) {
+ if (lun->l_path == NULL) {
+ log_warnx("missing path for lun %d, target \"%s\"",
+ lun->l_lun, lun->l_target->t_name);
+ return (1);
+ }
+ } else if (strcmp(lun->l_backend, "ramdisk") == 0) {
+ if (lun->l_size == 0) {
+ log_warnx("missing size for ramdisk-backed lun %d, "
+ "target \"%s\"", lun->l_lun, lun->l_target->t_name);
+ return (1);
+ }
+ if (lun->l_path != NULL) {
+ log_warnx("path must not be specified "
+ "for ramdisk-backed lun %d, target \"%s\"",
+ lun->l_lun, lun->l_target->t_name);
+ return (1);
+ }
+ }
+ if (lun->l_lun < 0 || lun->l_lun > 255) {
+ log_warnx("invalid lun number for lun %d, target \"%s\"; "
+ "must be between 0 and 255", lun->l_lun,
+ lun->l_target->t_name);
+ return (1);
+ }
+ if (lun->l_blocksize == 0) {
+ lun_set_blocksize(lun, DEFAULT_BLOCKSIZE);
+ } else if (lun->l_blocksize < 0) {
+ log_warnx("invalid blocksize for lun %d, target \"%s\"; "
+ "must be larger than 0", lun->l_lun, lun->l_target->t_name);
+ return (1);
+ }
+ if (lun->l_size != 0 && lun->l_size % lun->l_blocksize != 0) {
+ log_warnx("invalid size for lun %d, target \"%s\"; "
+ "must be multiple of blocksize", lun->l_lun,
+ lun->l_target->t_name);
+ return (1);
+ }
+ TAILQ_FOREACH(targ2, &lun->l_target->t_conf->conf_targets, t_next) {
+ TAILQ_FOREACH(lun2, &targ2->t_luns, l_next) {
+ if (lun == lun2)
+ continue;
+ if (lun->l_path != NULL && lun2->l_path != NULL &&
+ strcmp(lun->l_path, lun2->l_path) == 0) {
+ log_debugx("WARNING: path \"%s\" duplicated "
+ "between lun %d, target \"%s\", and "
+ "lun %d, target \"%s\"", lun->l_path,
+ lun->l_lun, lun->l_target->t_name,
+ lun2->l_lun, lun2->l_target->t_name);
+ }
+ }
+ }
+
+ return (0);
+}
+
int
conf_verify(struct conf *conf)
{
struct auth_group *ag;
struct portal_group *pg;
struct target *targ;
- struct lun *lun, *lun2;
- bool found_lun0;
+ struct lun *lun;
+ bool found_lun;
+ int error;
if (conf->conf_pidfile_path == NULL)
conf->conf_pidfile_path = checked_strdup(DEFAULT_PIDFILE);
TAILQ_FOREACH(targ, &conf->conf_targets, t_next) {
if (targ->t_auth_group == NULL) {
- log_warnx("missing authentication for target \"%s\"; "
- "must specify either \"auth-group\", \"chap\", "
- "or \"chap-mutual\"", targ->t_iqn);
- return (1);
+ targ->t_auth_group = auth_group_find(conf,
+ "default");
+ assert(targ->t_auth_group != NULL);
}
if (targ->t_portal_group == NULL) {
targ->t_portal_group = portal_group_find(conf,
"default");
assert(targ->t_portal_group != NULL);
}
- found_lun0 = false;
+ found_lun = false;
TAILQ_FOREACH(lun, &targ->t_luns, l_next) {
- if (lun->l_lun == 0)
- found_lun0 = true;
- if (lun->l_backend == NULL)
- lun_set_backend(lun, "block");
- if (strcmp(lun->l_backend, "block") == 0 &&
- lun->l_path == NULL) {
- log_warnx("missing path for lun %d, "
- "target \"%s\"", lun->l_lun, targ->t_iqn);
- return (1);
- }
- if (strcmp(lun->l_backend, "ramdisk") == 0) {
- if (lun->l_size == 0) {
- log_warnx("missing size for "
- "ramdisk-backed lun %d, "
- "target \"%s\"",
- lun->l_lun, targ->t_iqn);
- return (1);
- }
- if (lun->l_path != NULL) {
- log_warnx("path must not be specified "
- "for ramdisk-backed lun %d, "
- "target \"%s\"",
- lun->l_lun, targ->t_iqn);
- return (1);
- }
- }
- if (lun->l_lun < 0 || lun->l_lun > 255) {
- log_warnx("invalid lun number for lun %d, "
- "target \"%s\"; must be between 0 and 255",
- lun->l_lun, targ->t_iqn);
- return (1);
- }
-#if 1 /* Should we? */
- TAILQ_FOREACH(lun2, &targ->t_luns, l_next) {
- if (lun == lun2)
- continue;
- if (lun->l_path != NULL &&
- lun2->l_path != NULL &&
- strcmp(lun->l_path, lun2->l_path) == 0)
- log_debugx("WARNING: duplicate path "
- "for lun %d, target \"%s\"",
- lun->l_lun, targ->t_iqn);
- }
-#endif
- if (lun->l_blocksize == 0) {
- lun_set_blocksize(lun, DEFAULT_BLOCKSIZE);
- } else if (lun->l_blocksize <= 0) {
- log_warnx("invalid blocksize for lun %d, "
- "target \"%s\"; must be larger than 0",
- lun->l_lun, targ->t_iqn);
- return (1);
- }
- if (lun->l_size != 0 &&
- lun->l_size % lun->l_blocksize != 0) {
- log_warnx("invalid size for lun %d, target "
- "\"%s\"; must be multiple of blocksize",
- lun->l_lun, targ->t_iqn);
- return (1);
- }
+ error = conf_verify_lun(lun);
+ if (error != 0)
+ return (error);
+ found_lun = true;
}
- if (!found_lun0) {
- log_warnx("mandatory LUN 0 not configured "
- "for target \"%s\"", targ->t_iqn);
+ if (!found_lun) {
+ log_warnx("no LUNs defined for target \"%s\"",
+ targ->t_name);
return (1);
}
}
@@ -965,7 +1127,7 @@ conf_verify(struct conf *conf)
assert(pg->pg_name != NULL);
if (pg->pg_discovery_auth_group == NULL) {
pg->pg_discovery_auth_group =
- auth_group_find(conf, "no-access");
+ auth_group_find(conf, "default");
assert(pg->pg_discovery_auth_group != NULL);
}
@@ -992,6 +1154,7 @@ conf_verify(struct conf *conf)
break;
}
if (targ == NULL && ag->ag_name != NULL &&
+ strcmp(ag->ag_name, "default") != 0 &&
strcmp(ag->ag_name, "no-authentication") != 0 &&
strcmp(ag->ag_name, "no-access") != 0) {
log_warnx("auth-group \"%s\" not assigned "
@@ -1011,9 +1174,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
struct portal *oldp, *newp;
pid_t otherpid;
int changed, cumulated_error = 0, error;
-#ifndef ICL_KERNEL_PROXY
int one = 1;
-#endif
if (oldconf->conf_debug != newconf->conf_debug) {
log_debugx("changing debug level to %d", newconf->conf_debug);
@@ -1048,25 +1209,45 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
}
}
+ if (oldconf->conf_kernel_port_on != newconf->conf_kernel_port_on) {
+ if (newconf->conf_kernel_port_on == true) {
+ log_debugx("enabling CTL iSCSI port");
+ error = kernel_port_on();
+ if (error != 0)
+ log_errx(1, "failed to enable CTL iSCSI port; exiting");
+ } else {
+ error = kernel_port_off();
+ if (error != 0)
+ log_warnx("failed to disable CTL iSCSI port");
+ }
+ }
+
+ /*
+ * XXX: If target or lun removal fails, we should somehow "move"
+ * the old lun or target into newconf, so that subsequent
+ * conf_apply() would try to remove them again. That would
+ * be somewhat hairy, though, and lun deletion failures don't
+ * really happen, so leave it as it is for now.
+ */
TAILQ_FOREACH_SAFE(oldtarg, &oldconf->conf_targets, t_next, tmptarg) {
/*
* First, remove any targets present in the old configuration
* and missing in the new one.
*/
- newtarg = target_find(newconf, oldtarg->t_iqn);
+ newtarg = target_find(newconf, oldtarg->t_name);
if (newtarg == NULL) {
TAILQ_FOREACH_SAFE(oldlun, &oldtarg->t_luns, l_next,
tmplun) {
- log_debugx("target %s not found in the "
- "configuration file; removing its lun %d, "
+ log_debugx("target %s not found in new "
+ "configuration; removing its lun %d, "
"backed by CTL lun %d",
- oldtarg->t_iqn, oldlun->l_lun,
+ oldtarg->t_name, oldlun->l_lun,
oldlun->l_ctl_lun);
error = kernel_lun_remove(oldlun);
if (error != 0) {
log_warnx("failed to remove lun %d, "
"target %s, CTL lun %d",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
cumulated_error++;
}
@@ -1084,14 +1265,14 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
newlun = lun_find(newtarg, oldlun->l_lun);
if (newlun == NULL) {
log_debugx("lun %d, target %s, CTL lun %d "
- "not found in the configuration file; "
- "removing", oldlun->l_lun, oldtarg->t_iqn,
+ "not found in new configuration; "
+ "removing", oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
error = kernel_lun_remove(oldlun);
if (error != 0) {
log_warnx("failed to remove lun %d, "
"target %s, CTL lun %d",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
cumulated_error++;
}
@@ -1108,14 +1289,14 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
if (strcmp(newlun->l_backend, oldlun->l_backend) != 0) {
log_debugx("backend for lun %d, target %s, "
"CTL lun %d changed; removing",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
changed = 1;
}
if (oldlun->l_blocksize != newlun->l_blocksize) {
log_debugx("blocksize for lun %d, target %s, "
"CTL lun %d changed; removing",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
changed = 1;
}
@@ -1125,7 +1306,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
0)) {
log_debugx("device-id for lun %d, target %s, "
"CTL lun %d changed; removing",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
changed = 1;
}
@@ -1134,7 +1315,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
strcmp(oldlun->l_path, newlun->l_path) != 0)) {
log_debugx("path for lun %d, target %s, "
"CTL lun %d, changed; removing",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
changed = 1;
}
@@ -1143,7 +1324,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
strcmp(oldlun->l_serial, newlun->l_serial) != 0)) {
log_debugx("serial for lun %d, target %s, "
"CTL lun %d changed; removing",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
changed = 1;
}
@@ -1152,7 +1333,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
if (error != 0) {
log_warnx("failed to remove lun %d, "
"target %s, CTL lun %d",
- oldlun->l_lun, oldtarg->t_iqn,
+ oldlun->l_lun, oldtarg->t_name,
oldlun->l_ctl_lun);
cumulated_error++;
}
@@ -1168,9 +1349,9 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
* Now add new targets or modify existing ones.
*/
TAILQ_FOREACH(newtarg, &newconf->conf_targets, t_next) {
- oldtarg = target_find(oldconf, newtarg->t_iqn);
+ oldtarg = target_find(oldconf, newtarg->t_name);
- TAILQ_FOREACH(newlun, &newtarg->t_luns, l_next) {
+ TAILQ_FOREACH_SAFE(newlun, &newtarg->t_luns, l_next, tmplun) {
if (oldtarg != NULL) {
oldlun = lun_find(oldtarg, newlun->l_lun);
if (oldlun != NULL) {
@@ -1178,7 +1359,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
log_debugx("resizing lun %d, "
"target %s, CTL lun %d",
newlun->l_lun,
- newtarg->t_iqn,
+ newtarg->t_name,
newlun->l_ctl_lun);
error =
kernel_lun_resize(newlun);
@@ -1188,7 +1369,7 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
"target %s, "
"CTL lun %d",
newlun->l_lun,
- newtarg->t_iqn,
+ newtarg->t_name,
newlun->l_lun);
cumulated_error++;
}
@@ -1197,11 +1378,12 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
}
}
log_debugx("adding lun %d, target %s",
- newlun->l_lun, newtarg->t_iqn);
+ newlun->l_lun, newtarg->t_name);
error = kernel_lun_add(newlun);
if (error != 0) {
log_warnx("failed to add lun %d, target %s",
- newlun->l_lun, newtarg->t_iqn);
+ newlun->l_lun, newtarg->t_name);
+ lun_delete(newlun);
cumulated_error++;
}
}
@@ -1246,10 +1428,18 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
}
#ifdef ICL_KERNEL_PROXY
- log_debugx("listening on %s, portal-group \"%s\" using ICL proxy",
- newp->p_listen, newpg->pg_name);
- kernel_listen(newp->p_ai, newp->p_iser);
-#else
+ if (proxy_mode) {
+ newpg->pg_conf->conf_portal_id++;
+ newp->p_id = newpg->pg_conf->conf_portal_id;
+ log_debugx("listening on %s, portal-group "
+ "\"%s\", portal id %d, using ICL proxy",
+ newp->p_listen, newpg->pg_name, newp->p_id);
+ kernel_listen(newp->p_ai, newp->p_iser,
+ newp->p_id);
+ continue;
+ }
+#endif
+ assert(proxy_mode == false);
assert(newp->p_iser == false);
log_debugx("listening on %s, portal-group \"%s\"",
@@ -1292,7 +1482,6 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
cumulated_error++;
continue;
}
-#endif /* !ICL_KERNEL_PROXY */
}
}
@@ -1407,14 +1596,11 @@ wait_for_children(bool block)
}
static void
-handle_connection(struct portal *portal, int fd, bool dont_fork)
+handle_connection(struct portal *portal, int fd,
+ const struct sockaddr *client_sa, socklen_t client_salen, bool dont_fork)
{
struct connection *conn;
-#ifndef ICL_KERNEL_PROXY
- struct sockaddr_storage ss;
- socklen_t sslen = sizeof(ss);
int error;
-#endif
pid_t pid;
char host[NI_MAXHOST + 1];
struct conf *conf;
@@ -1446,25 +1632,15 @@ handle_connection(struct portal *portal, int fd, bool dont_fork)
}
pidfile_close(conf->conf_pidfh);
-#ifdef ICL_KERNEL_PROXY
- /*
- * XXX
- */
- log_set_peer_addr("XXX");
-#else
- error = getpeername(fd, (struct sockaddr *)&ss, &sslen);
- if (error != 0)
- log_err(1, "getpeername");
- error = getnameinfo((struct sockaddr *)&ss, sslen,
+ error = getnameinfo(client_sa, client_salen,
host, sizeof(host), NULL, 0, NI_NUMERICHOST);
if (error != 0)
- log_errx(1, "getaddrinfo: %s", gai_strerror(error));
+ log_errx(1, "getnameinfo: %s", gai_strerror(error));
log_debugx("accepted connection from %s; portal group \"%s\"",
host, portal->p_portal_group->pg_name);
log_set_peer_addr(host);
setproctitle("%s", host);
-#endif
conn = connection_new(portal, fd, host);
set_timeout(conf);
@@ -1481,7 +1657,6 @@ handle_connection(struct portal *portal, int fd, bool dont_fork)
exit(0);
}
-#ifndef ICL_KERNEL_PROXY
static int
fd_add(int fd, fd_set *fdset, int nfds)
{
@@ -1497,19 +1672,20 @@ fd_add(int fd, fd_set *fdset, int nfds)
nfds = fd;
return (nfds);
}
-#endif
static void
main_loop(struct conf *conf, bool dont_fork)
{
struct portal_group *pg;
struct portal *portal;
+ struct sockaddr_storage client_sa;
+ socklen_t client_salen;
#ifdef ICL_KERNEL_PROXY
int connection_id;
-#else
+ int portal_id;
+#endif
fd_set fdset;
int error, nfds, client_fd;
-#endif
pidfile_write(conf->conf_pidfh);
@@ -1518,42 +1694,63 @@ main_loop(struct conf *conf, bool dont_fork)
return;
#ifdef ICL_KERNEL_PROXY
- connection_id = kernel_accept();
- if (connection_id == 0)
- continue;
+ if (proxy_mode) {
+ client_salen = sizeof(client_sa);
+ kernel_accept(&connection_id, &portal_id,
+ (struct sockaddr *)&client_sa, &client_salen);
+
+ log_debugx("incoming connection, id %d, portal id %d",
+ connection_id, portal_id);
+ TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
+ TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
+ if (portal->p_id == portal_id) {
+ goto found;
+ }
+ }
+ }
- /*
- * XXX: This is obviously temporary.
- */
- pg = TAILQ_FIRST(&conf->conf_portal_groups);
- portal = TAILQ_FIRST(&pg->pg_portals);
-
- handle_connection(portal, connection_id, dont_fork);
-#else
- FD_ZERO(&fdset);
- nfds = 0;
- TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
- TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
- nfds = fd_add(portal->p_socket, &fdset, nfds);
- }
- error = select(nfds + 1, &fdset, NULL, NULL, NULL);
- if (error <= 0) {
- if (errno == EINTR)
- return;
- log_err(1, "select");
- }
- TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
- TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
- if (!FD_ISSET(portal->p_socket, &fdset))
- continue;
- client_fd = accept(portal->p_socket, NULL, 0);
- if (client_fd < 0)
- log_err(1, "accept");
- handle_connection(portal, client_fd, dont_fork);
- break;
+ log_errx(1, "kernel returned invalid portal_id %d",
+ portal_id);
+
+found:
+ handle_connection(portal, connection_id,
+ (struct sockaddr *)&client_sa, client_salen,
+ dont_fork);
+ } else {
+#endif
+ assert(proxy_mode == false);
+
+ FD_ZERO(&fdset);
+ nfds = 0;
+ TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
+ TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
+ nfds = fd_add(portal->p_socket, &fdset, nfds);
+ }
+ error = select(nfds + 1, &fdset, NULL, NULL, NULL);
+ if (error <= 0) {
+ if (errno == EINTR)
+ return;
+ log_err(1, "select");
}
+ TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
+ TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
+ if (!FD_ISSET(portal->p_socket, &fdset))
+ continue;
+ client_salen = sizeof(client_sa);
+ client_fd = accept(portal->p_socket,
+ (struct sockaddr *)&client_sa,
+ &client_salen);
+ if (client_fd < 0)
+ log_err(1, "accept");
+ handle_connection(portal, client_fd,
+ (struct sockaddr *)&client_sa,
+ client_salen, dont_fork);
+ break;
+ }
+ }
+#ifdef ICL_KERNEL_PROXY
}
-#endif /* !ICL_KERNEL_PROXY */
+#endif
}
}
@@ -1572,6 +1769,17 @@ sigterm_handler(int dummy __unused)
}
static void
+sigchld_handler(int dummy __unused)
+{
+
+ /*
+ * The only purpose of this handler is to make SIGCHLD
+ * interrupt the ISCSIDWAIT ioctl(2), so we can call
+ * wait_for_children().
+ */
+}
+
+static void
register_signals(void)
{
struct sigaction sa;
@@ -1593,6 +1801,11 @@ register_signals(void)
error = sigaction(SIGINT, &sa, NULL);
if (error != 0)
log_err(1, "sigaction");
+
+ sa.sa_handler = sigchld_handler;
+ error = sigaction(SIGCHLD, &sa, NULL);
+ if (error != 0)
+ log_err(1, "sigaction");
}
int
@@ -1603,7 +1816,7 @@ main(int argc, char **argv)
int debug = 0, ch, error;
bool dont_daemonize = false;
- while ((ch = getopt(argc, argv, "df:")) != -1) {
+ while ((ch = getopt(argc, argv, "df:R")) != -1) {
switch (ch) {
case 'd':
dont_daemonize = true;
@@ -1612,6 +1825,13 @@ main(int argc, char **argv)
case 'f':
config_path = optarg;
break;
+ case 'R':
+#ifndef ICL_KERNEL_PROXY
+ log_errx(1, "ctld(8) compiled without ICL_KERNEL_PROXY "
+ "does not support iSER protocol");
+#endif
+ proxy_mode = true;
+ break;
case '?':
default:
usage();
@@ -1627,41 +1847,29 @@ main(int argc, char **argv)
oldconf = conf_new_from_kernel();
newconf = conf_new_from_file(config_path);
if (newconf == NULL)
- log_errx(1, "configuration error, exiting");
+ log_errx(1, "configuration error; exiting");
if (debug > 0) {
oldconf->conf_debug = debug;
newconf->conf_debug = debug;
}
- if (dont_daemonize == false) {
- if (daemon(0, 0) == -1) {
- log_warn("cannot daemonize");
- pidfile_remove(newconf->conf_pidfh);
- exit(1);
- }
- }
-
-#ifdef ICL_KERNEL_PROXY
- log_debugx("enabling CTL iSCSI port");
- error = kernel_port_on();
- if (error != 0)
- log_errx(1, "failed to enable CTL iSCSI port, exiting");
-#endif
-
error = conf_apply(oldconf, newconf);
if (error != 0)
- log_errx(1, "failed to apply configuration, exiting");
+ log_errx(1, "failed to apply configuration; exiting");
+
conf_delete(oldconf);
oldconf = NULL;
register_signals();
-#ifndef ICL_KERNEL_PROXY
- log_debugx("enabling CTL iSCSI port");
- error = kernel_port_on();
- if (error != 0)
- log_errx(1, "failed to enable CTL iSCSI port, exiting");
-#endif
+ if (dont_daemonize == false) {
+ log_debugx("daemonizing");
+ if (daemon(0, 0) == -1) {
+ log_warn("cannot daemonize");
+ pidfile_remove(newconf->conf_pidfh);
+ exit(1);
+ }
+ }
for (;;) {
main_loop(newconf, dont_daemonize);
@@ -1690,9 +1898,6 @@ main(int argc, char **argv)
log_debugx("disabling CTL iSCSI port "
"and terminating all connections");
- error = kernel_port_off();
- if (error != 0)
- log_warnx("failed to disable CTL iSCSI port");
oldconf = newconf;
newconf = conf_new();
diff --git a/usr.sbin/ctld/ctld.h b/usr.sbin/ctld/ctld.h
index 3557978..3399648 100644
--- a/usr.sbin/ctld/ctld.h
+++ b/usr.sbin/ctld/ctld.h
@@ -33,6 +33,10 @@
#define CTLD_H
#include <sys/queue.h>
+#ifdef ICL_KERNEL_PROXY
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
#include <stdbool.h>
#include <libutil.h>
@@ -53,10 +57,23 @@ struct auth {
char *a_mutual_secret;
};
+struct auth_name {
+ TAILQ_ENTRY(auth_name) an_next;
+ struct auth_group *an_auth_group;
+ char *an_initator_name;
+};
+
+struct auth_portal {
+ TAILQ_ENTRY(auth_portal) ap_next;
+ struct auth_group *ap_auth_group;
+ char *ap_initator_portal;
+};
+
#define AG_TYPE_UNKNOWN 0
-#define AG_TYPE_NO_AUTHENTICATION 1
-#define AG_TYPE_CHAP 2
-#define AG_TYPE_CHAP_MUTUAL 3
+#define AG_TYPE_DENY 1
+#define AG_TYPE_NO_AUTHENTICATION 2
+#define AG_TYPE_CHAP 3
+#define AG_TYPE_CHAP_MUTUAL 4
struct auth_group {
TAILQ_ENTRY(auth_group) ag_next;
@@ -65,6 +82,8 @@ struct auth_group {
struct target *ag_target;
int ag_type;
TAILQ_HEAD(, auth) ag_auths;
+ TAILQ_HEAD(, auth_name) ag_names;
+ TAILQ_HEAD(, auth_portal) ag_portals;
};
struct portal {
@@ -73,6 +92,9 @@ struct portal {
bool p_iser;
char *p_listen;
struct addrinfo *p_ai;
+#ifdef ICL_KERNEL_PROXY
+ int p_id;
+#endif
TAILQ_HEAD(, target) p_targets;
int p_socket;
@@ -117,7 +139,7 @@ struct target {
struct conf *t_conf;
struct auth_group *t_auth_group;
struct portal_group *t_portal_group;
- char *t_iqn;
+ char *t_name;
char *t_alias;
};
@@ -131,7 +153,14 @@ struct conf {
int conf_maxproc;
uint16_t conf_last_portal_group_tag;
+#ifdef ICL_KERNEL_PROXY
+ int conf_portal_id;
+#endif
struct pidfh *conf_pidfh;
+
+ bool conf_default_pg_defined;
+ bool conf_default_ag_defined;
+ bool conf_kernel_port_on;
};
#define CONN_SESSION_TYPE_NONE 0
@@ -182,30 +211,46 @@ int conf_verify(struct conf *conf);
struct auth_group *auth_group_new(struct conf *conf, const char *name);
void auth_group_delete(struct auth_group *ag);
-struct auth_group *auth_group_find(struct conf *conf, const char *name);
+struct auth_group *auth_group_find(const struct conf *conf,
+ const char *name);
+int auth_group_set_type_str(struct auth_group *ag,
+ const char *type);
const struct auth *auth_new_chap(struct auth_group *ag,
const char *user, const char *secret);
const struct auth *auth_new_chap_mutual(struct auth_group *ag,
const char *user, const char *secret,
const char *user2, const char *secret2);
-const struct auth *auth_find(struct auth_group *ag,
+const struct auth *auth_find(const struct auth_group *ag,
const char *user);
+const struct auth_name *auth_name_new(struct auth_group *ag,
+ const char *initiator_name);
+bool auth_name_defined(const struct auth_group *ag);
+const struct auth_name *auth_name_find(const struct auth_group *ag,
+ const char *initiator_name);
+
+const struct auth_portal *auth_portal_new(struct auth_group *ag,
+ const char *initiator_portal);
+bool auth_portal_defined(const struct auth_group *ag);
+const struct auth_portal *auth_portal_find(const struct auth_group *ag,
+ const char *initiator_portal);
+
struct portal_group *portal_group_new(struct conf *conf, const char *name);
void portal_group_delete(struct portal_group *pg);
-struct portal_group *portal_group_find(struct conf *conf, const char *name);
+struct portal_group *portal_group_find(const struct conf *conf,
+ const char *name);
int portal_group_add_listen(struct portal_group *pg,
const char *listen, bool iser);
-struct target *target_new(struct conf *conf, const char *iqn);
+struct target *target_new(struct conf *conf, const char *name);
void target_delete(struct target *target);
struct target *target_find(struct conf *conf,
- const char *iqn);
+ const char *name);
struct lun *lun_new(struct target *target, int lun_id);
void lun_delete(struct lun *lun);
-struct lun *lun_find(struct target *target, int lun_id);
+struct lun *lun_find(const struct target *target, int lun_id);
void lun_set_backend(struct lun *lun, const char *value);
void lun_set_blocksize(struct lun *lun, size_t value);
void lun_set_device_id(struct lun *lun, const char *value);
@@ -217,7 +262,8 @@ void lun_set_ctl_lun(struct lun *lun, uint32_t value);
struct lun_option *lun_option_new(struct lun *lun,
const char *name, const char *value);
void lun_option_delete(struct lun_option *clo);
-struct lun_option *lun_option_find(struct lun *lun, const char *name);
+struct lun_option *lun_option_find(const struct lun *lun,
+ const char *name);
void lun_option_set(struct lun_option *clo,
const char *value);
@@ -230,13 +276,15 @@ int kernel_port_on(void);
int kernel_port_off(void);
void kernel_capsicate(void);
-/*
- * ICL_KERNEL_PROXY
- */
-void kernel_listen(struct addrinfo *ai, bool iser);
-int kernel_accept(void);
+#ifdef ICL_KERNEL_PROXY
+void kernel_listen(struct addrinfo *ai, bool iser,
+ int portal_id);
+void kernel_accept(int *connection_id, int *portal_id,
+ struct sockaddr *client_sa,
+ socklen_t *client_salen);
void kernel_send(struct pdu *pdu);
void kernel_receive(struct pdu *pdu);
+#endif
struct keys *keys_new(void);
void keys_delete(struct keys *keys);
@@ -263,12 +311,12 @@ void log_init(int level);
void log_set_peer_name(const char *name);
void log_set_peer_addr(const char *addr);
void log_err(int, const char *, ...)
- __dead2 __printf0like(2, 3);
+ __dead2 __printflike(2, 3);
void log_errx(int, const char *, ...)
- __dead2 __printf0like(2, 3);
-void log_warn(const char *, ...) __printf0like(1, 2);
+ __dead2 __printflike(2, 3);
+void log_warn(const char *, ...) __printflike(1, 2);
void log_warnx(const char *, ...) __printflike(1, 2);
-void log_debugx(const char *, ...) __printf0like(1, 2);
+void log_debugx(const char *, ...) __printflike(1, 2);
char *checked_strdup(const char *);
bool valid_iscsi_name(const char *name);
diff --git a/usr.sbin/ctld/discovery.c b/usr.sbin/ctld/discovery.c
index bef7da6..3612ce3 100644
--- a/usr.sbin/ctld/discovery.c
+++ b/usr.sbin/ctld/discovery.c
@@ -61,9 +61,6 @@ text_receive(struct connection *conn)
*/
if ((bhstr->bhstr_flags & BHSTR_FLAGS_CONTINUE) != 0)
log_errx(1, "received Text PDU with unsupported \"C\" flag");
- if (request->pdu_data_len == 0)
- log_errx(1, "received Text PDU with empty data segment");
-
if (ntohl(bhstr->bhstr_cmdsn) < conn->conn_cmdsn) {
log_errx(1, "received Text PDU with decreasing CmdSN: "
"was %d, is %d", conn->conn_cmdsn, ntohl(bhstr->bhstr_cmdsn));
@@ -186,10 +183,10 @@ discovery(struct connection *conn)
conn->conn_portal->p_portal_group) {
log_debugx("not returning target \"%s\"; "
"belongs to a different portal group",
- targ->t_iqn);
+ targ->t_name);
continue;
}
- keys_add(response_keys, "TargetName", targ->t_iqn);
+ keys_add(response_keys, "TargetName", targ->t_name);
}
} else {
targ = target_find(conn->conn_portal->p_portal_group->pg_conf,
@@ -198,7 +195,7 @@ discovery(struct connection *conn)
log_debugx("initiator requested information on unknown "
"target \"%s\"; returning nothing", send_targets);
} else {
- keys_add(response_keys, "TargetName", targ->t_iqn);
+ keys_add(response_keys, "TargetName", targ->t_name);
}
}
keys_save(response_keys, response);
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
index dc55594..0d8383c 100644
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -43,7 +43,7 @@
#include <sys/queue.h>
#include <sys/callout.h>
#include <sys/sbuf.h>
-#include <sys/capability.h>
+#include <sys/capsicum.h>
#include <assert.h>
#include <bsdxml.h>
#include <ctype.h>
@@ -65,11 +65,13 @@
#include <cam/ctl/ctl_util.h>
#include <cam/ctl/ctl_scsi_all.h>
+#include "ctld.h"
+
#ifdef ICL_KERNEL_PROXY
#include <netdb.h>
#endif
-#include "ctld.h"
+extern bool proxy_mode;
static int ctl_fd = 0;
@@ -352,7 +354,7 @@ retry:
log_warnx("found CTL lun %ju, backing lun %d, target "
"%s, also backed by CTL lun %d; ignoring",
(uintmax_t) lun->lun_id, cl->l_lun,
- cl->l_target->t_iqn, cl->l_ctl_lun);
+ cl->l_target->t_name, cl->l_ctl_lun);
continue;
}
@@ -382,7 +384,7 @@ retry:
log_warnx("unable to add CTL lun option %s "
"for CTL lun %ju for lun %d, target %s",
nv->name, (uintmax_t) lun->lun_id,
- cl->l_lun, cl->l_target->t_iqn);
+ cl->l_lun, cl->l_target->t_name);
}
}
@@ -434,10 +436,10 @@ kernel_lun_add(struct lun *lun)
lo = lun_option_find(lun, "cfiscsi_target");
if (lo != NULL) {
- lun_option_set(lo, lun->l_target->t_iqn);
+ lun_option_set(lo, lun->l_target->t_name);
} else {
lo = lun_option_new(lun, "cfiscsi_target",
- lun->l_target->t_iqn);
+ lun->l_target->t_name);
assert(lo != NULL);
}
@@ -598,8 +600,15 @@ kernel_handoff(struct connection *conn)
conn->conn_initiator_alias, sizeof(req.data.handoff.initiator_alias));
}
strlcpy(req.data.handoff.target_name,
- conn->conn_target->t_iqn, sizeof(req.data.handoff.target_name));
+ conn->conn_target->t_name, sizeof(req.data.handoff.target_name));
+#ifdef ICL_KERNEL_PROXY
+ if (proxy_mode)
+ req.data.handoff.connection_id = conn->conn_socket;
+ else
+ req.data.handoff.socket = conn->conn_socket;
+#else
req.data.handoff.socket = conn->conn_socket;
+#endif
req.data.handoff.portal_group_tag =
conn->conn_portal->p_portal_group->pg_tag;
if (conn->conn_header_digest == CONN_DIGEST_CRC32C)
@@ -613,13 +622,15 @@ kernel_handoff(struct connection *conn)
req.data.handoff.max_burst_length = conn->conn_max_burst_length;
req.data.handoff.immediate_data = conn->conn_immediate_data;
- if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1)
+ if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
log_err(1, "error issuing CTL_ISCSI ioctl; "
"dropping connection");
+ }
- if (req.status != CTL_ISCSI_OK)
+ if (req.status != CTL_ISCSI_OK) {
log_errx(1, "error returned from CTL iSCSI handoff request: "
"%s; dropping connection", req.error_str);
+ }
}
int
@@ -664,7 +675,7 @@ kernel_port_off(void)
#ifdef ICL_KERNEL_PROXY
void
-kernel_listen(struct addrinfo *ai, bool iser)
+kernel_listen(struct addrinfo *ai, bool iser, int portal_id)
{
struct ctl_iscsi req;
@@ -677,26 +688,41 @@ kernel_listen(struct addrinfo *ai, bool iser)
req.data.listen.protocol = ai->ai_protocol;
req.data.listen.addr = ai->ai_addr;
req.data.listen.addrlen = ai->ai_addrlen;
+ req.data.listen.portal_id = portal_id;
if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1)
- log_warn("error issuing CTL_ISCSI_LISTEN ioctl");
+ log_err(1, "error issuing CTL_ISCSI ioctl");
+
+ if (req.status != CTL_ISCSI_OK) {
+ log_errx(1, "error returned from CTL iSCSI listen: %s",
+ req.error_str);
+ }
}
-int
-kernel_accept(void)
+void
+kernel_accept(int *connection_id, int *portal_id,
+ struct sockaddr *client_sa, socklen_t *client_salen)
{
struct ctl_iscsi req;
+ struct sockaddr_storage ss;
bzero(&req, sizeof(req));
req.type = CTL_ISCSI_ACCEPT;
+ req.data.accept.initiator_addr = (struct sockaddr *)&ss;
- if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
- log_warn("error issuing CTL_ISCSI_LISTEN ioctl");
- return (0);
+ if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1)
+ log_err(1, "error issuing CTL_ISCSI ioctl");
+
+ if (req.status != CTL_ISCSI_OK) {
+ log_errx(1, "error returned from CTL iSCSI accept: %s",
+ req.error_str);
}
- return (req.data.accept.connection_id);
+ *connection_id = req.data.accept.connection_id;
+ *portal_id = req.data.accept.portal_id;
+ *client_salen = req.data.accept.initiator_addrlen;
+ memcpy(client_sa, &ss, *client_salen);
}
void
@@ -712,13 +738,15 @@ kernel_send(struct pdu *pdu)
req.data.send.data_segment_len = pdu->pdu_data_len;
req.data.send.data_segment = pdu->pdu_data;
- if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1)
+ if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
log_err(1, "error issuing CTL_ISCSI ioctl; "
"dropping connection");
+ }
- if (req.status != CTL_ISCSI_OK)
+ if (req.status != CTL_ISCSI_OK) {
log_errx(1, "error returned from CTL iSCSI send: "
"%s; dropping connection", req.error_str);
+ }
}
void
@@ -738,13 +766,15 @@ kernel_receive(struct pdu *pdu)
req.data.receive.data_segment_len = MAX_DATA_SEGMENT_LENGTH;
req.data.receive.data_segment = pdu->pdu_data;
- if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1)
+ if (ioctl(ctl_fd, CTL_ISCSI, &req) == -1) {
log_err(1, "error issuing CTL_ISCSI ioctl; "
"dropping connection");
+ }
- if (req.status != CTL_ISCSI_OK)
+ if (req.status != CTL_ISCSI_OK) {
log_errx(1, "error returned from CTL iSCSI receive: "
"%s; dropping connection", req.error_str);
+ }
}
diff --git a/usr.sbin/ctld/keys.c b/usr.sbin/ctld/keys.c
index 0ea4aa0..1474bd3 100644
--- a/usr.sbin/ctld/keys.c
+++ b/usr.sbin/ctld/keys.c
@@ -64,7 +64,7 @@ keys_load(struct keys *keys, const struct pdu *pdu)
size_t pair_len;
if (pdu->pdu_data_len == 0)
- log_errx(1, "protocol error: empty data segment");
+ return;
if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
log_errx(1, "protocol error: key not NULL-terminated\n");
diff --git a/usr.sbin/ctld/login.c b/usr.sbin/ctld/login.c
index 042cf2a..f830d15 100644
--- a/usr.sbin/ctld/login.c
+++ b/usr.sbin/ctld/login.c
@@ -128,10 +128,6 @@ login_receive(struct connection *conn, bool initial)
log_errx(1, "received Login PDU with unsupported "
"Version-min 0x%x", bhslr->bhslr_version_min);
}
- if (request->pdu_data_len == 0) {
- login_send_error(request, 0x02, 0x00);
- log_errx(1, "received Login PDU with empty data segment");
- }
if (ntohl(bhslr->bhslr_cmdsn) < conn->conn_cmdsn) {
login_send_error(request, 0x02, 0x05);
log_errx(1, "received Login PDU with decreasing CmdSN: "
@@ -791,7 +787,7 @@ login_negotiate(struct connection *conn, struct pdu *request)
bool skipped_security;
if (request == NULL) {
- log_debugx("beginning parameter negotiation; "
+ log_debugx("beginning operational parameter negotiation; "
"waiting for Login PDU");
request = login_receive(conn, false);
skipped_security = false;
@@ -817,7 +813,7 @@ login_negotiate(struct connection *conn, struct pdu *request)
response_keys);
}
- log_debugx("parameter negotiation done; "
+ log_debugx("operational parameter negotiation done; "
"transitioning to Full Feature Phase");
keys_save(response_keys, response);
@@ -922,11 +918,11 @@ login(struct connection *conn)
if (ag->ag_name != NULL) {
log_debugx("initiator requests to connect "
"to target \"%s\"; auth-group \"%s\"",
- conn->conn_target->t_iqn,
+ conn->conn_target->t_name,
conn->conn_target->t_auth_group->ag_name);
} else {
log_debugx("initiator requests to connect "
- "to target \"%s\"", conn->conn_target->t_iqn);
+ "to target \"%s\"", conn->conn_target->t_name);
}
} else {
assert(conn->conn_session_type == CONN_SESSION_TYPE_DISCOVERY);
@@ -940,6 +936,33 @@ login(struct connection *conn)
}
/*
+ * Enforce initiator-name and initiator-portal.
+ */
+ if (auth_name_defined(ag)) {
+ if (auth_name_find(ag, initiator_name) == NULL) {
+ login_send_error(request, 0x02, 0x02);
+ log_errx(1, "initiator does not match allowed "
+ "initiator names");
+ }
+ log_debugx("initiator matches allowed initiator names");
+ } else {
+ log_debugx("auth-group does not define initiator name "
+ "restrictions");
+ }
+
+ if (auth_portal_defined(ag)) {
+ if (auth_portal_find(ag, conn->conn_initiator_addr) == NULL) {
+ login_send_error(request, 0x02, 0x02);
+ log_errx(1, "initiator does not match allowed "
+ "initiator portals");
+ }
+ log_debugx("initiator matches allowed initiator portals");
+ } else {
+ log_debugx("auth-group does not define initiator portal "
+ "restrictions");
+ }
+
+ /*
* Let's see if the initiator intends to do any kind of authentication
* at all.
*/
@@ -964,7 +987,7 @@ login(struct connection *conn)
* but we don't need it.
*/
log_debugx("authentication not required; "
- "transitioning to parameter negotiation");
+ "transitioning to operational parameter negotiation");
if ((bhslr->bhslr_flags & BHSLR_FLAGS_TRANSIT) == 0)
log_warnx("initiator did not set the \"T\" flag; "
@@ -1007,6 +1030,19 @@ login(struct connection *conn)
return;
}
+ if (ag->ag_type == AG_TYPE_DENY) {
+ login_send_error(request, 0x02, 0x01);
+ log_errx(1, "auth-type is \"deny\"");
+ }
+
+ if (ag->ag_type == AG_TYPE_UNKNOWN) {
+ /*
+ * This can happen with empty auth-group.
+ */
+ login_send_error(request, 0x02, 0x01);
+ log_errx(1, "auth-type not set, denying access");
+ }
+
log_debugx("CHAP authentication required");
auth_method = keys_find(request_keys, "AuthMethod");
diff --git a/usr.sbin/ctld/parse.y b/usr.sbin/ctld/parse.y
index 333e964..e4b160e 100644
--- a/usr.sbin/ctld/parse.y
+++ b/usr.sbin/ctld/parse.y
@@ -57,10 +57,10 @@ extern void yyrestart(FILE *);
%}
-%token ALIAS AUTH_GROUP BACKEND BLOCKSIZE CHAP CHAP_MUTUAL CLOSING_BRACKET
-%token DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP LISTEN LISTEN_ISER LUN MAXPROC NUM
-%token OPENING_BRACKET OPTION PATH PIDFILE PORTAL_GROUP SERIAL SIZE STR TARGET
-%token TIMEOUT
+%token ALIAS AUTH_GROUP AUTH_TYPE BACKEND BLOCKSIZE CHAP CHAP_MUTUAL
+%token CLOSING_BRACKET DEBUG DEVICE_ID DISCOVERY_AUTH_GROUP INITIATOR_NAME
+%token INITIATOR_PORTAL LISTEN LISTEN_ISER LUN MAXPROC NUM OPENING_BRACKET
+%token OPTION PATH PIDFILE PORTAL_GROUP SERIAL SIZE STR TARGET TIMEOUT
%union
{
@@ -79,40 +79,40 @@ statements:
;
statement:
- debug_statement
+ debug
|
- timeout_statement
+ timeout
|
- maxproc_statement
+ maxproc
|
- pidfile_statement
+ pidfile
|
- auth_group_definition
+ auth_group
|
- portal_group_definition
+ portal_group
|
- target_statement
+ target
;
-debug_statement: DEBUG NUM
+debug: DEBUG NUM
{
conf->conf_debug = $2;
}
;
-timeout_statement: TIMEOUT NUM
+timeout: TIMEOUT NUM
{
conf->conf_timeout = $2;
}
;
-maxproc_statement: MAXPROC NUM
+maxproc: MAXPROC NUM
{
conf->conf_maxproc = $2;
}
;
-pidfile_statement: PIDFILE STR
+pidfile: PIDFILE STR
{
if (conf->conf_pidfile_path != NULL) {
log_warnx("pidfile specified more than once");
@@ -123,7 +123,7 @@ pidfile_statement: PIDFILE STR
}
;
-auth_group_definition: AUTH_GROUP auth_group_name
+auth_group: AUTH_GROUP auth_group_name
OPENING_BRACKET auth_group_entries CLOSING_BRACKET
{
auth_group = NULL;
@@ -132,7 +132,17 @@ auth_group_definition: AUTH_GROUP auth_group_name
auth_group_name: STR
{
- auth_group = auth_group_new(conf, $1);
+ /*
+ * Make it possible to redefine default
+ * auth-group. but only once.
+ */
+ if (strcmp($1, "default") == 0 &&
+ conf->conf_default_ag_defined == false) {
+ auth_group = auth_group_find(conf, $1);
+ conf->conf_default_ag_defined = true;
+ } else {
+ auth_group = auth_group_new(conf, $1);
+ }
free($1);
if (auth_group == NULL)
return (1);
@@ -145,9 +155,26 @@ auth_group_entries:
;
auth_group_entry:
+ auth_group_auth_type
+ |
auth_group_chap
|
auth_group_chap_mutual
+ |
+ auth_group_initiator_name
+ |
+ auth_group_initiator_portal
+ ;
+
+auth_group_auth_type: AUTH_TYPE STR
+ {
+ int error;
+
+ error = auth_group_set_type_str(auth_group, $2);
+ free($2);
+ if (error != 0)
+ return (1);
+ }
;
auth_group_chap: CHAP STR STR
@@ -176,7 +203,29 @@ auth_group_chap_mutual: CHAP_MUTUAL STR STR STR STR
}
;
-portal_group_definition: PORTAL_GROUP portal_group_name
+auth_group_initiator_name: INITIATOR_NAME STR
+ {
+ const struct auth_name *an;
+
+ an = auth_name_new(auth_group, $2);
+ free($2);
+ if (an == NULL)
+ return (1);
+ }
+ ;
+
+auth_group_initiator_portal: INITIATOR_PORTAL STR
+ {
+ const struct auth_portal *ap;
+
+ ap = auth_portal_new(auth_group, $2);
+ free($2);
+ if (ap == NULL)
+ return (1);
+ }
+ ;
+
+portal_group: PORTAL_GROUP portal_group_name
OPENING_BRACKET portal_group_entries CLOSING_BRACKET
{
portal_group = NULL;
@@ -185,7 +234,17 @@ portal_group_definition: PORTAL_GROUP portal_group_name
portal_group_name: STR
{
- portal_group = portal_group_new(conf, $1);
+ /*
+ * Make it possible to redefine default
+ * portal-group. but only once.
+ */
+ if (strcmp($1, "default") == 0 &&
+ conf->conf_default_pg_defined == false) {
+ portal_group = portal_group_find(conf, $1);
+ conf->conf_default_pg_defined = true;
+ } else {
+ portal_group = portal_group_new(conf, $1);
+ }
free($1);
if (portal_group == NULL)
return (1);
@@ -247,14 +306,14 @@ portal_group_listen_iser: LISTEN_ISER STR
}
;
-target_statement: TARGET target_iqn
+target: TARGET target_name
OPENING_BRACKET target_entries CLOSING_BRACKET
{
target = NULL;
}
;
-target_iqn: STR
+target_name: STR
{
target = target_new(conf, $1);
free($1);
@@ -269,61 +328,93 @@ target_entries:
;
target_entry:
- alias_statement
+ target_alias
|
- auth_group_statement
+ target_auth_group
|
- chap_statement
+ target_auth_type
|
- chap_mutual_statement
+ target_chap
|
- portal_group_statement
+ target_chap_mutual
|
- lun_statement
+ target_initiator_name
+ |
+ target_initiator_portal
+ |
+ target_portal_group
+ |
+ target_lun
;
-alias_statement: ALIAS STR
+target_alias: ALIAS STR
{
if (target->t_alias != NULL) {
log_warnx("alias for target \"%s\" "
- "specified more than once", target->t_iqn);
+ "specified more than once", target->t_name);
return (1);
}
target->t_alias = $2;
}
;
-auth_group_statement: AUTH_GROUP STR
+target_auth_group: AUTH_GROUP STR
{
if (target->t_auth_group != NULL) {
if (target->t_auth_group->ag_name != NULL)
log_warnx("auth-group for target \"%s\" "
- "specified more than once", target->t_iqn);
+ "specified more than once", target->t_name);
else
- log_warnx("cannot mix auth-grup with explicit "
+ log_warnx("cannot use both auth-group and explicit "
"authorisations for target \"%s\"",
- target->t_iqn);
+ target->t_name);
return (1);
}
target->t_auth_group = auth_group_find(conf, $2);
if (target->t_auth_group == NULL) {
log_warnx("unknown auth-group \"%s\" for target "
- "\"%s\"", $2, target->t_iqn);
+ "\"%s\"", $2, target->t_name);
return (1);
}
free($2);
}
;
-chap_statement: CHAP STR STR
+target_auth_type: AUTH_TYPE STR
+ {
+ int error;
+
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL) {
+ log_warnx("cannot use both auth-group and "
+ "auth-type for target \"%s\"",
+ target->t_name);
+ return (1);
+ }
+ } else {
+ target->t_auth_group = auth_group_new(conf, NULL);
+ if (target->t_auth_group == NULL) {
+ free($2);
+ return (1);
+ }
+ target->t_auth_group->ag_target = target;
+ }
+ error = auth_group_set_type_str(target->t_auth_group, $2);
+ free($2);
+ if (error != 0)
+ return (1);
+ }
+ ;
+
+target_chap: CHAP STR STR
{
const struct auth *ca;
if (target->t_auth_group != NULL) {
if (target->t_auth_group->ag_name != NULL) {
- log_warnx("cannot mix auth-grup with explicit "
- "authorisations for target \"%s\"",
- target->t_iqn);
+ log_warnx("cannot use both auth-group and "
+ "chap for target \"%s\"",
+ target->t_name);
free($2);
free($3);
return (1);
@@ -345,15 +436,15 @@ chap_statement: CHAP STR STR
}
;
-chap_mutual_statement: CHAP_MUTUAL STR STR STR STR
+target_chap_mutual: CHAP_MUTUAL STR STR STR STR
{
const struct auth *ca;
if (target->t_auth_group != NULL) {
if (target->t_auth_group->ag_name != NULL) {
- log_warnx("cannot mix auth-grup with explicit "
- "authorisations for target \"%s\"",
- target->t_iqn);
+ log_warnx("cannot use both auth-group and "
+ "chap-mutual for target \"%s\"",
+ target->t_name);
free($2);
free($3);
free($4);
@@ -382,18 +473,72 @@ chap_mutual_statement: CHAP_MUTUAL STR STR STR STR
}
;
-portal_group_statement: PORTAL_GROUP STR
+target_initiator_name: INITIATOR_NAME STR
+ {
+ const struct auth_name *an;
+
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL) {
+ log_warnx("cannot use both auth-group and "
+ "initiator-name for target \"%s\"",
+ target->t_name);
+ free($2);
+ return (1);
+ }
+ } else {
+ target->t_auth_group = auth_group_new(conf, NULL);
+ if (target->t_auth_group == NULL) {
+ free($2);
+ return (1);
+ }
+ target->t_auth_group->ag_target = target;
+ }
+ an = auth_name_new(target->t_auth_group, $2);
+ free($2);
+ if (an == NULL)
+ return (1);
+ }
+ ;
+
+target_initiator_portal: INITIATOR_PORTAL STR
+ {
+ const struct auth_portal *ap;
+
+ if (target->t_auth_group != NULL) {
+ if (target->t_auth_group->ag_name != NULL) {
+ log_warnx("cannot use both auth-group and "
+ "initiator-portal for target \"%s\"",
+ target->t_name);
+ free($2);
+ return (1);
+ }
+ } else {
+ target->t_auth_group = auth_group_new(conf, NULL);
+ if (target->t_auth_group == NULL) {
+ free($2);
+ return (1);
+ }
+ target->t_auth_group->ag_target = target;
+ }
+ ap = auth_portal_new(target->t_auth_group, $2);
+ free($2);
+ if (ap == NULL)
+ return (1);
+ }
+ ;
+
+target_portal_group: PORTAL_GROUP STR
{
if (target->t_portal_group != NULL) {
log_warnx("portal-group for target \"%s\" "
- "specified more than once", target->t_iqn);
+ "specified more than once", target->t_name);
free($2);
return (1);
}
target->t_portal_group = portal_group_find(conf, $2);
if (target->t_portal_group == NULL) {
log_warnx("unknown portal-group \"%s\" for target "
- "\"%s\"", $2, target->t_iqn);
+ "\"%s\"", $2, target->t_name);
free($2);
return (1);
}
@@ -401,8 +546,8 @@ portal_group_statement: PORTAL_GROUP STR
}
;
-lun_statement: LUN lun_number
- OPENING_BRACKET lun_statement_entries CLOSING_BRACKET
+target_lun: LUN lun_number
+ OPENING_BRACKET lun_entries CLOSING_BRACKET
{
lun = NULL;
}
@@ -416,33 +561,33 @@ lun_number: NUM
}
;
-lun_statement_entries:
+lun_entries:
|
- lun_statement_entries lun_statement_entry
+ lun_entries lun_entry
;
-lun_statement_entry:
- backend_statement
+lun_entry:
+ lun_backend
|
- blocksize_statement
+ lun_blocksize
|
- device_id_statement
+ lun_device_id
|
- option_statement
+ lun_option
|
- path_statement
+ lun_path
|
- serial_statement
+ lun_serial
|
- size_statement
+ lun_size
;
-backend_statement: BACKEND STR
+lun_backend: BACKEND STR
{
if (lun->l_backend != NULL) {
log_warnx("backend for lun %d, target \"%s\" "
"specified more than once",
- lun->l_lun, target->t_iqn);
+ lun->l_lun, target->t_name);
free($2);
return (1);
}
@@ -451,24 +596,24 @@ backend_statement: BACKEND STR
}
;
-blocksize_statement: BLOCKSIZE NUM
+lun_blocksize: BLOCKSIZE NUM
{
if (lun->l_blocksize != 0) {
log_warnx("blocksize for lun %d, target \"%s\" "
"specified more than once",
- lun->l_lun, target->t_iqn);
+ lun->l_lun, target->t_name);
return (1);
}
lun_set_blocksize(lun, $2);
}
;
-device_id_statement: DEVICE_ID STR
+lun_device_id: DEVICE_ID STR
{
if (lun->l_device_id != NULL) {
log_warnx("device_id for lun %d, target \"%s\" "
"specified more than once",
- lun->l_lun, target->t_iqn);
+ lun->l_lun, target->t_name);
free($2);
return (1);
}
@@ -477,7 +622,7 @@ device_id_statement: DEVICE_ID STR
}
;
-option_statement: OPTION STR STR
+lun_option: OPTION STR STR
{
struct lun_option *clo;
@@ -489,12 +634,12 @@ option_statement: OPTION STR STR
}
;
-path_statement: PATH STR
+lun_path: PATH STR
{
if (lun->l_path != NULL) {
log_warnx("path for lun %d, target \"%s\" "
"specified more than once",
- lun->l_lun, target->t_iqn);
+ lun->l_lun, target->t_name);
free($2);
return (1);
}
@@ -503,12 +648,12 @@ path_statement: PATH STR
}
;
-serial_statement: SERIAL STR
+lun_serial: SERIAL STR
{
if (lun->l_serial != NULL) {
log_warnx("serial for lun %d, target \"%s\" "
"specified more than once",
- lun->l_lun, target->t_iqn);
+ lun->l_lun, target->t_name);
free($2);
return (1);
}
@@ -517,12 +662,12 @@ serial_statement: SERIAL STR
}
;
-size_statement: SIZE NUM
+lun_size: SIZE NUM
{
if (lun->l_size != 0) {
log_warnx("size for lun %d, target \"%s\" "
"specified more than once",
- lun->l_lun, target->t_iqn);
+ lun->l_lun, target->t_name);
return (1);
}
lun_set_size(lun, $2);
@@ -577,19 +722,19 @@ conf_new_from_file(const char *path)
conf = conf_new();
+ ag = auth_group_new(conf, "default");
+ assert(ag != NULL);
+
ag = auth_group_new(conf, "no-authentication");
+ assert(ag != NULL);
ag->ag_type = AG_TYPE_NO_AUTHENTICATION;
- /*
- * Here, the type doesn't really matter, as the group doesn't contain
- * any entries and thus will always deny access.
- */
ag = auth_group_new(conf, "no-access");
- ag->ag_type = AG_TYPE_CHAP;
+ assert(ag != NULL);
+ ag->ag_type = AG_TYPE_DENY;
pg = portal_group_new(conf, "default");
- portal_group_add_listen(pg, "0.0.0.0:3260", false);
- portal_group_add_listen(pg, "[::]:3260", false);
+ assert(pg != NULL);
yyin = fopen(path, "r");
if (yyin == NULL) {
@@ -598,7 +743,7 @@ conf_new_from_file(const char *path)
return (NULL);
}
check_perms(path);
- lineno = 0;
+ lineno = 1;
yyrestart(yyin);
error = yyparse();
auth_group = NULL;
@@ -611,6 +756,25 @@ conf_new_from_file(const char *path)
return (NULL);
}
+ if (conf->conf_default_ag_defined == false) {
+ log_debugx("auth-group \"default\" not defined; "
+ "going with defaults");
+ ag = auth_group_find(conf, "default");
+ assert(ag != NULL);
+ ag->ag_type = AG_TYPE_DENY;
+ }
+
+ if (conf->conf_default_pg_defined == false) {
+ log_debugx("portal-group \"default\" not defined; "
+ "going with defaults");
+ pg = portal_group_find(conf, "default");
+ assert(pg != NULL);
+ portal_group_add_listen(pg, "0.0.0.0:3260", false);
+ portal_group_add_listen(pg, "[::]:3260", false);
+ }
+
+ conf->conf_kernel_port_on = true;
+
error = conf_verify(conf);
if (error != 0) {
conf_delete(conf);
diff --git a/usr.sbin/ctld/pdu.c b/usr.sbin/ctld/pdu.c
index eb8921e..084423c 100644
--- a/usr.sbin/ctld/pdu.c
+++ b/usr.sbin/ctld/pdu.c
@@ -44,6 +44,8 @@
#include <sys/ioctl.h>
#endif
+extern bool proxy_mode;
+
static int
pdu_ahs_length(const struct pdu *pdu)
{
@@ -101,11 +103,13 @@ pdu_new_response(struct pdu *request)
#ifdef ICL_KERNEL_PROXY
-void
-pdu_receive(struct pdu *pdu)
+static void
+pdu_receive_proxy(struct pdu *pdu)
{
size_t len;
+ assert(proxy_mode);
+
kernel_receive(pdu);
len = pdu_ahs_length(pdu);
@@ -117,15 +121,17 @@ pdu_receive(struct pdu *pdu)
pdu->pdu_data_len = len;
}
-void
-pdu_send(struct pdu *pdu)
+static void
+pdu_send_proxy(struct pdu *pdu)
{
+ assert(proxy_mode);
+
pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
kernel_send(pdu);
}
-#else /* !ICL_KERNEL_PROXY */
+#endif /* ICL_KERNEL_PROXY */
static size_t
pdu_padding(const struct pdu *pdu)
@@ -161,6 +167,13 @@ pdu_receive(struct pdu *pdu)
size_t len, padding;
char dummy[4];
+#ifdef ICL_KERNEL_PROXY
+ if (proxy_mode)
+ return (pdu_receive_proxy(pdu));
+#endif
+
+ assert(proxy_mode == false);
+
pdu_read(pdu->pdu_connection->conn_socket,
(char *)pdu->pdu_bhs, sizeof(*pdu->pdu_bhs));
@@ -202,6 +215,13 @@ pdu_send(struct pdu *pdu)
struct iovec iov[3];
int iovcnt;
+#ifdef ICL_KERNEL_PROXY
+ if (proxy_mode)
+ return (pdu_send_proxy(pdu));
+#endif
+
+ assert(proxy_mode == false);
+
pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
iov[0].iov_base = pdu->pdu_bhs;
iov[0].iov_len = sizeof(*pdu->pdu_bhs);
@@ -234,8 +254,6 @@ pdu_send(struct pdu *pdu)
log_errx(1, "short write");
}
-#endif /* !ICL_KERNEL_PROXY */
-
void
pdu_delete(struct pdu *pdu)
{
diff --git a/usr.sbin/ctld/token.l b/usr.sbin/ctld/token.l
index f968d97..2846097 100644
--- a/usr.sbin/ctld/token.l
+++ b/usr.sbin/ctld/token.l
@@ -50,6 +50,7 @@ extern int yylex(void);
%%
alias { return ALIAS; }
auth-group { return AUTH_GROUP; }
+auth-type { return AUTH_TYPE; }
backend { return BACKEND; }
blocksize { return BLOCKSIZE; }
chap { return CHAP; }
@@ -57,6 +58,8 @@ chap-mutual { return CHAP_MUTUAL; }
debug { return DEBUG; }
device-id { return DEVICE_ID; }
discovery-auth-group { return DISCOVERY_AUTH_GROUP; }
+initiator-name { return INITIATOR_NAME; }
+initiator-portal { return INITIATOR_PORTAL; }
listen { return LISTEN; }
listen-iser { return LISTEN_ISER; }
lun { return LUN; }
@@ -82,4 +85,5 @@ timeout { return TIMEOUT; }
#.*$ /* ignore comments */;
\n { lineno++; }
[ \t]+ /* ignore whitespace */;
+. { yylval.str = strdup(yytext); return STR; }
%%
diff --git a/usr.sbin/ctm/ctm_dequeue/Makefile b/usr.sbin/ctm/ctm_dequeue/Makefile
index 18dd525..d2f5648 100644
--- a/usr.sbin/ctm/ctm_dequeue/Makefile
+++ b/usr.sbin/ctm/ctm_dequeue/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../ctm_rmail
PROG= ctm_dequeue
-NO_MAN=
+MAN=
SRCS= ctm_dequeue.c error.c
CFLAGS+= -I${.CURDIR}/../ctm_rmail
diff --git a/usr.sbin/ctm/ctm_smail/Makefile b/usr.sbin/ctm/ctm_smail/Makefile
index 15209e4..4c98d31 100644
--- a/usr.sbin/ctm/ctm_smail/Makefile
+++ b/usr.sbin/ctm/ctm_smail/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../ctm_rmail
PROG= ctm_smail
-NO_MAN=
+MAN=
SRCS= ctm_smail.c error.c
CFLAGS+= -I${.CURDIR}/../ctm_rmail
diff --git a/usr.sbin/ctm/mkCTM/Makefile b/usr.sbin/ctm/mkCTM/Makefile
index cefd704..745956c 100644
--- a/usr.sbin/ctm/mkCTM/Makefile
+++ b/usr.sbin/ctm/mkCTM/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= mkctm
-NO_MAN=
+MAN=
DPADD= ${LIBMD}
LDADD= -lmd
diff --git a/usr.sbin/daemon/daemon.c b/usr.sbin/daemon/daemon.c
index 322c0d4..7bdd2a6 100644
--- a/usr.sbin/daemon/daemon.c
+++ b/usr.sbin/daemon/daemon.c
@@ -139,7 +139,7 @@ main(int argc, char *argv[])
* get SIGCHLD eventually.
*/
pid = -1;
- if (pidfile != NULL || restart) {
+ if (pidfile != NULL || ppidfile != NULL || restart) {
/*
* Restore default action for SIGTERM in case the
* parent process decided to ignore it.
diff --git a/usr.sbin/edquota/edquota.c b/usr.sbin/edquota/edquota.c
index a92a3c8..0cd117f 100644
--- a/usr.sbin/edquota/edquota.c
+++ b/usr.sbin/edquota/edquota.c
@@ -284,7 +284,7 @@ main(int argc, char *argv[])
freeprivs(protoprivs);
exit(0);
}
- tmpfd = mkstemp(tmpfil);
+ tmpfd = mkostemp(tmpfil, O_CLOEXEC);
fchown(tmpfd, getuid(), getgid());
if (tflag) {
if ((protoprivs = getprivs(0, quotatype, fspath)) != NULL) {
diff --git a/usr.sbin/eeprom/ofw_options.c b/usr.sbin/eeprom/ofw_options.c
index eb7437f..6e6aa85 100644
--- a/usr.sbin/eeprom/ofw_options.c
+++ b/usr.sbin/eeprom/ofw_options.c
@@ -63,7 +63,7 @@ static int ofwo_secmode(const struct ofwo_extabent *, int, const void *,
static int ofwo_secpwd(const struct ofwo_extabent *, int, const void *,
int, const char *);
-static const struct ofwo_extabent const ofwo_extab[] = {
+static const struct ofwo_extabent ofwo_extab[] = {
{ "oem-logo", ofwo_oemlogo },
{ "security-mode", ofwo_secmode },
{ "security-password", ofwo_secpwd },
diff --git a/usr.sbin/etcupdate/Makefile b/usr.sbin/etcupdate/Makefile
index 9f6d17e..765533a 100644
--- a/usr.sbin/etcupdate/Makefile
+++ b/usr.sbin/etcupdate/Makefile
@@ -1,6 +1,12 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
SCRIPTS=etcupdate.sh
MAN= etcupdate.8
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/etcupdate/etcupdate.8 b/usr.sbin/etcupdate/etcupdate.8
index a61f181..ffd0516 100644
--- a/usr.sbin/etcupdate/etcupdate.8
+++ b/usr.sbin/etcupdate/etcupdate.8
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2010-2012 Advanced Computing Technologies LLC
+.\" Copyright (c) 2010-2013 Advanced Computing Technologies LLC
.\" Written by: John H. Baldwin <jhb@FreeBSD.org>
.\" All rights reserved.
.\"
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 16, 2012
+.Dd December 9, 2013
.Dt ETCUPDATE 8
.Os
.Sh NAME
@@ -33,7 +33,7 @@
.Nd "manage updates to system files not updated by installworld"
.Sh SYNOPSIS
.Nm
-.Op Fl nBF
+.Op Fl npBF
.Op Fl d Ar workdir
.Op Fl r | Fl s Ar source | Fl t Ar tarball
.Op Fl A Ar patterns
@@ -64,6 +64,7 @@
.Op Fl M Ar options
.Nm
.Cm resolve
+.Op Fl p
.Op Fl d Ar workdir
.Op Fl D Ar destdir
.Op Fl L Ar logfile
@@ -342,27 +343,7 @@ then nothing will be output.
.Sh OPTIONS
The following options are available.
Note that most options do not apply to all modes.
-.Bl -tag -width ".Fl d Ar workdir"
-.It Fl B
-Do not build generated files in a private object tree.
-Instead,
-reuse the generated files from a previously built object tree that matches
-the source tree.
-This can be useful to avoid gratuitous conflicts in
-.Xr sendmail 8
-configuration
-files when bootstrapping.
-It can also be useful for building a tarball that matches a specific
-world build.
-.It Fl d Ar workdir
-Specify an alternate directory to use as the work directory.
-The work directory is used to store the
-.Dq current
-and
-.Dq previous
-trees as well as unresolved conflicts.
-The default work directory is
-.Pa <destdir>/var/db/etcupdate .
+.Bl -tag -width ".Fl A Ar patterns"
.It Fl A Ar patterns
Always install the new version of any files that match any of the patterns
listed in
@@ -378,6 +359,17 @@ Note that ignored files specified via the
variable or the
.Fl I
option will not be installed.
+.It Fl B
+Do not build generated files in a private object tree.
+Instead,
+reuse the generated files from a previously built object tree that matches
+the source tree.
+This can be useful to avoid gratuitous conflicts in
+.Xr sendmail 8
+configuration
+files when bootstrapping.
+It can also be useful for building a tarball that matches a specific
+world build.
.It Fl D Ar destdir
Specify an alternate destination directory as the target of a merge.
This is analogous to the
@@ -388,6 +380,15 @@ The default destination directory is an empty string which results in
merges updating
.Pa /etc
on the local machine.
+.It Fl d Ar workdir
+Specify an alternate directory to use as the work directory.
+The work directory is used to store the
+.Dq current
+and
+.Dq previous
+trees as well as unresolved conflicts.
+The default work directory is
+.Pa <destdir>/var/db/etcupdate .
.It Fl F
Ignore changes in the FreeBSD ID string when comparing files in the
destination directory to files in either of the
@@ -481,6 +482,33 @@ option is not specified,
then a temporary
.Dq current
tree will be extracted to perform the comparison.
+.It Fl p
+Enable
+.Dq pre-world
+mode.
+Only merge changes to files that are necessary to successfully run
+.Sq make installworld
+or
+.Sq make installkernel .
+When this flag is enabled,
+the existing
+.Dq current
+and
+.Dq previous
+trees are left alone.
+Instead,
+a temporary tree is populated with the necessary files.
+This temporary tree is compared against the
+.Dq current
+tree.
+This allows a normal update to be run after
+.Sq make installworld
+has completed.
+Any conflicts generated during a
+.Dq pre-world
+update should be resolved by a
+.Dq pre-world
+.Cm resolve .
.It Fl r
Do not update the
.Dq current
@@ -667,6 +695,25 @@ has been removed from the
tree,
but it has been locally modified.
The modified version of the file remains in the destination directory.
+.It "Needs update: /etc/localtime (required manual update via tzsetup(1))"
+The
+.Fa /var/db/zoneinfo
+file does not exist,
+so
+.Nm
+was not able to refresh
+.Fa /etc/localtime
+from its source file in
+.Fa /usr/share/zoneinfo .
+Running
+.Xr tzsetup 1
+will both refresh
+.Fa /etc/localtime
+and generate
+.Fa /var/db/zoneinfo
+permitting future updates to refresh
+.Fa /etc/localtime
+automatically.
.It "Needs update: /etc/mail/aliases.db (required manual update via newaliases(1))"
The file
.Pa /etc/mail/aliases
diff --git a/usr.sbin/etcupdate/etcupdate.sh b/usr.sbin/etcupdate/etcupdate.sh
index 2216836..a4728fa 100755
--- a/usr.sbin/etcupdate/etcupdate.sh
+++ b/usr.sbin/etcupdate/etcupdate.sh
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Copyright (c) 2010-2013 Advanced Computing Technologies LLC
# Written by: John H. Baldwin <jhb@FreeBSD.org>
# All rights reserved.
#
@@ -61,14 +61,15 @@
usage()
{
cat <<EOF
-usage: etcupdate [-nBF] [-d workdir] [-r | -s source | -t tarball] [-A patterns]
- [-D destdir] [-I patterns] [-L logfile] [-M options]
+usage: etcupdate [-npBF] [-d workdir] [-r | -s source | -t tarball]
+ [-A patterns] [-D destdir] [-I patterns] [-L logfile]
+ [-M options]
etcupdate build [-B] [-d workdir] [-s source] [-L logfile] [-M options]
<tarball>
etcupdate diff [-d workdir] [-D destdir] [-I patterns] [-L logfile]
etcupdate extract [-B] [-d workdir] [-s source | -t tarball] [-L logfile]
[-M options]
- etcupdate resolve [-d workdir] [-D destdir] [-L logfile]
+ etcupdate resolve [-p] [-d workdir] [-D destdir] [-L logfile]
etcupdate status [-d workdir] [-D destdir]
EOF
exit 1
@@ -181,29 +182,39 @@ always_install()
# $1 - directory to store new tree in
build_tree()
{
- local make
+ local destdir dir file make
make="make $MAKE_OPTIONS"
log "Building tree at $1 with $make"
mkdir -p $1/usr/obj >&3 2>&1
- (cd $SRCDIR; $make DESTDIR=$1 distrib-dirs) >&3 2>&1 || return 1
-
- if ! [ -n "$nobuild" ]; then
- (cd $SRCDIR; \
- MAKEOBJDIRPREFIX=$1/usr/obj $make _obj SUBDIR_OVERRIDE=etc &&
- MAKEOBJDIRPREFIX=$1/usr/obj $make everything SUBDIR_OVERRIDE=etc &&
- MAKEOBJDIRPREFIX=$1/usr/obj $make DESTDIR=$1 distribution) \
+ destdir=`realpath $1`
+
+ if [ -n "$preworld" ]; then
+ # Build a limited tree that only contains files that are
+ # crucial to installworld.
+ for file in $PREWORLD_FILES; do
+ dir=`dirname /$file`
+ mkdir -p $1/$dir >&3 2>&1 || return 1
+ cp -p $SRCDIR/$file $1/$file || return 1
+ done
+ elif ! [ -n "$nobuild" ]; then
+ (cd $SRCDIR; $make DESTDIR=$destdir distrib-dirs &&
+ MAKEOBJDIRPREFIX=$destdir/usr/obj $make _obj SUBDIR_OVERRIDE=etc &&
+ MAKEOBJDIRPREFIX=$destdir/usr/obj $make everything SUBDIR_OVERRIDE=etc &&
+ MAKEOBJDIRPREFIX=$destdir/usr/obj $make DESTDIR=$destdir distribution) \
>&3 2>&1 || return 1
else
- (cd $SRCDIR; $make DESTDIR=$1 distribution) >&3 2>&1 || return 1
+ (cd $SRCDIR; $make DESTDIR=$destdir distrib-dirs &&
+ $make DESTDIR=$destdir distribution) >&3 2>&1 || return 1
fi
chflags -R noschg $1 >&3 2>&1 || return 1
rm -rf $1/usr/obj >&3 2>&1 || return 1
# Purge auto-generated files. Only the source files need to
# be updated after which these files are regenerated.
- rm -f $1/etc/*.db $1/etc/passwd >&3 2>&1 || return 1
+ rm -f $1/etc/*.db $1/etc/passwd $1/var/db/services.db >&3 2>&1 || \
+ return 1
# Remove empty files. These just clutter the output of 'diff'.
find $1 -type f -size 0 -delete >&3 2>&1 || return 1
@@ -218,9 +229,15 @@ build_tree()
# source tree.
extract_tree()
{
+ local files
+
# If we have a tarball, extract that into the new directory.
if [ -n "$tarball" ]; then
- if ! (mkdir -p $NEWTREE && tar xf $tarball -C $NEWTREE) \
+ files=
+ if [ -n "$preworld" ]; then
+ files="$PREWORLD_FILES"
+ fi
+ if ! (mkdir -p $NEWTREE && tar xf $tarball -C $NEWTREE $files) \
>&3 2>&1; then
echo "Failed to extract new tree."
remove_tree $NEWTREE
@@ -470,6 +487,39 @@ diffnode()
esac
}
+# Run one-off commands after an update has completed. These commands
+# are not tied to a specific file, so they cannot be handled by
+# post_install_file().
+post_update()
+{
+ local args
+
+ # None of these commands should be run for a pre-world update.
+ if [ -n "$preworld" ]; then
+ return
+ fi
+
+ # If /etc/localtime exists and is not a symlink and /var/db/zoneinfo
+ # exists, run tzsetup -r to refresh /etc/localtime.
+ if [ -f ${DESTDIR}/etc/localtime -a \
+ ! -L ${DESTDIR}/etc/localtime ]; then
+ if [ -f ${DESTDIR}/var/db/zoneinfo ]; then
+ if [ -n "${DESTDIR}" ]; then
+ args="-C ${DESTDIR}"
+ else
+ args=""
+ fi
+ log "tzsetup -r ${args}"
+ if [ -z "$dryrun" ]; then
+ tzsetup -r ${args} >&3 2>&1
+ fi
+ else
+ warn "Needs update: /etc/localtime (required" \
+ "manual update via tzsetup(1))"
+ fi
+ fi
+}
+
# Create missing parent directories of a node in a target tree
# preserving the owner, group, and permissions from a specified
# template tree.
@@ -567,6 +617,14 @@ post_install_file()
fi
fi
;;
+ /etc/services)
+ log "services_mkdb -q -o $DESTDIR/var/db/services.db" \
+ "${DESTDIR}$1"
+ if [ -z "$dryrun" ]; then
+ services_mkdb -q -o $DESTDIR/var/db/services.db \
+ ${DESTDIR}$1 >&3 2>&1
+ fi
+ ;;
esac
}
@@ -1010,16 +1068,6 @@ handle_modified_file()
fi
fi
- # If the only change in the new file versus the old file is a
- # change in the FreeBSD ID string and -F is specified, just
- # update the FreeBSD ID string in the local file.
- if [ -n "$FREEBSD_ID" -a $cmp -eq $COMPARE_DIFFFILES ] && \
- fbsdid_only $OLDTREE/$file $NEWTREE/$file; then
- if update_freebsdid $file; then
- continue
- fi
- fi
-
# If the file was removed from the dest tree, just whine.
if [ $newdestcmp -eq $COMPARE_ONLYFIRST ]; then
# If the removed file matches an ALWAYS_INSTALL glob,
@@ -1034,6 +1082,14 @@ handle_modified_file()
return
fi
+ # If the only change in the new file versus the old
+ # file is a change in the FreeBSD ID string and -F is
+ # specified, don't warn.
+ if [ -n "$FREEBSD_ID" -a $cmp -eq $COMPARE_DIFFFILES ] && \
+ fbsdid_only $OLDTREE/$file $NEWTREE/$file; then
+ return
+ fi
+
case $cmp in
$COMPARE_DIFFTYPE)
old=`file_type $OLDTREE/$file`
@@ -1064,6 +1120,16 @@ handle_modified_file()
fi
fi
+ # If the only change in the new file versus the old file is a
+ # change in the FreeBSD ID string and -F is specified, just
+ # update the FreeBSD ID string in the local file.
+ if [ -n "$FREEBSD_ID" -a $cmp -eq $COMPARE_DIFFFILES ] && \
+ fbsdid_only $OLDTREE/$file $NEWTREE/$file; then
+ if update_freebsdid $file; then
+ continue
+ fi
+ fi
+
# If the file changed types between the old and new trees but
# the files in the new and dest tree are both of the same
# type, treat it like an added file just comparing the new and
@@ -1298,6 +1364,11 @@ resolve_cmd()
return
fi
+ if ! [ -d $NEWTREE ]; then
+ echo "The current tree is not present to resolve conflicts."
+ exit 1
+ fi
+
conflicts=`(cd $CONFLICTS; find . ! -type d) | sed -e 's/^\.//'`
for file in $conflicts; do
resolve_conflict $file
@@ -1343,7 +1414,7 @@ update_cmd()
usage
fi
- log "update command: rerun=$rerun tarball=$tarball"
+ log "update command: rerun=$rerun tarball=$tarball preworld=$preworld"
if [ `id -u` -ne 0 ]; then
echo "Must be root to update a tree."
@@ -1376,9 +1447,22 @@ update_cmd()
echo "Unable to create temporary directory."
exit 1
fi
- OLDTREE=$NEWTREE
+
+ # A pre-world dryrun has already set OLDTREE to
+ # point to the current stock tree.
+ if [ -z "$preworld" ]; then
+ OLDTREE=$NEWTREE
+ fi
NEWTREE=$dir
+ # For a pre-world update, blow away any pre-existing
+ # NEWTREE.
+ elif [ -n "$preworld" ]; then
+ if ! remove_tree $NEWTREE; then
+ echo "Unable to remove pre-world tree."
+ exit 1
+ fi
+
# Rotate the existing stock tree to the old tree.
elif [ -d $NEWTREE ]; then
# First, delete the previous old tree if it exists.
@@ -1421,6 +1505,12 @@ EOF
# Initialize conflicts and warnings handling.
rm -f $WARNINGS
mkdir -p $CONFLICTS
+
+ # Ignore removed files for the pre-world case. A pre-world
+ # update uses a stripped-down tree.
+ if [ -n "$preworld" ]; then
+ > $WORKDIR/removed.files
+ fi
# The order for the following sections is important. In the
# odd case that a directory is converted into a file, the
@@ -1458,6 +1548,9 @@ EOF
"(requires manual update via newaliases(1))"
fi
+ # Run any special one-off commands after an update has completed.
+ post_update
+
if [ -s $WARNINGS ]; then
echo "Warnings:"
cat $WARNINGS
@@ -1535,7 +1628,8 @@ always=
dryrun=
ignore=
nobuild=
-while getopts "d:nrs:t:A:BD:FI:L:M:" option; do
+preworld=
+while getopts "d:nprs:t:A:BD:FI:L:M:" option; do
case "$option" in
d)
WORKDIR=$OPTARG
@@ -1543,6 +1637,9 @@ while getopts "d:nrs:t:A:BD:FI:L:M:" option; do
n)
dryrun=YES
;;
+ p)
+ preworld=YES
+ ;;
r)
rerun=YES
;;
@@ -1633,6 +1730,9 @@ WARNINGS=$WORKDIR/warnings
# Use $EDITOR for resolving conflicts. If it is not set, default to vi.
EDITOR=${EDITOR:-/usr/bin/vi}
+# Files that need to be updated before installworld.
+PREWORLD_FILES="etc/master.passwd etc/group"
+
# Handle command-specific argument processing such as complaining
# about unsupported options. Since the configuration file is always
# included, do not complain about extra command line arguments that
@@ -1644,19 +1744,39 @@ case $command in
echo
usage
fi
+ if [ -n "$rerun" -a -n "$preworld" ]; then
+ echo "Only one of -p or -r can be specified."
+ echo
+ usage
+ fi
+ ;;
+ build|diff|status)
+ if [ -n "$dryrun" -o -n "$rerun" -o -n "$tarball" -o \
+ -n "$preworld" ]; then
+ usage
+ fi
;;
- build|diff|resolve|status)
+ resolve)
if [ -n "$dryrun" -o -n "$rerun" -o -n "$tarball" ]; then
usage
fi
;;
extract)
- if [ -n "$dryrun" -o -n "$rerun" ]; then
+ if [ -n "$dryrun" -o -n "$rerun" -o -n "$preworld" ]; then
usage
fi
;;
esac
+# Pre-world mode uses a different set of trees. It leaves the current
+# tree as-is so it is still present for a full etcupdate run after the
+# world install is complete. Instead, it installs a few critical files
+# into a separate tree.
+if [ -n "$preworld" ]; then
+ OLDTREE=$NEWTREE
+ NEWTREE=$WORKDIR/preworld
+fi
+
# Open the log file. Don't truncate it if doing a minor operation so
# that a minor operation doesn't lose log info from a major operation.
if ! mkdir -p $WORKDIR 2>/dev/null; then
diff --git a/usr.sbin/etcupdate/tests/Makefile b/usr.sbin/etcupdate/tests/Makefile
new file mode 100644
index 0000000..da83397
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/Makefile
@@ -0,0 +1,17 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/usr.sbin/etcupdate
+
+PLAIN_TESTS_SH=
+.for test in always_test \
+ conflicts_test \
+ fbsdid_test \
+ ignore_test \
+ preworld_test \
+ tests_test \
+ tzsetup_test
+PLAIN_TESTS_SH+= ${test}
+TEST_METADATA.${test}+= required_user="root"
+.endfor
+
+.include <bsd.test.mk>
diff --git a/usr.sbin/etcupdate/tests/always_test.sh b/usr.sbin/etcupdate/tests/always_test.sh
new file mode 100644
index 0000000..514481e
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/always_test.sh
@@ -0,0 +1,630 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests to test the -A flag to the 'update' command.
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: always.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+# The various states of the comparison of a file between two trees.
+states="equal first second difftype difflinks difffiles"
+
+# These tests deal with ignoring certain patterns of files. We run
+# the test multiple times forcing the install of different patterns.
+build_trees()
+{
+ local i
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+
+ for i in $states; do
+ for j in $states; do
+ for k in $states; do
+ mkdir -p $OLD/$i/$j/$k $NEW/$i/$j/$k \
+ $TEST/$i/$j/$k
+ done
+ done
+ done
+
+ # What follows are the various warning/conflict cases from the
+ # larger regression tests. These results of many of these
+ # tests should be changed when installation is forced. The
+ # cases when these updates should still fail even when forced
+ # are: 1) it should not force the removal of a modified file
+ # and 2) it should not remove a subdirectory that contains a
+ # modified or added file.
+
+ # /first/difftype/second: File with different local type
+ # removed. Should generate a warning.
+ mkfifo $OLD/first/difftype/second/fifo
+ mkdir $TEST/first/difftype/second/fifo
+
+ # /first/difflinks/second: Modified link removed. Should
+ # generate a warning.
+ ln -s "old link" $OLD/first/difflinks/second/link
+ ln -s "test link" $TEST/first/difflinks/second/link
+
+ # /first/difffiles/second: Modified file removed. Should
+ # generate a warning.
+ echo "foo" > $OLD/first/difffiles/second/file
+ echo "bar" > $TEST/first/difffiles/second/file
+
+ # /second/second/difftype: Newly added file conflicts with
+ # existing file in test tree of a different type. Should
+ # generate a warning.
+ mkdir $NEW/second/second/difftype/dir
+ mkfifo $TEST/second/second/difftype/dir
+
+ # /second/second/difflinks: Newly added link conflicts with
+ # existing link in test tree. Should generate a warning.
+ ln -s "new link" $NEW/second/second/difflinks/link
+ ln -s "test link" $TEST/second/second/difflinks/link
+
+ # /second/second/difffiles: Newly added file conflicts with
+ # existing file in test tree. Should generate a warning.
+ echo "new" > $NEW/second/second/difffiles/file
+ echo "test" > $TEST/second/second/difffiles/file
+
+ # /difftype/first/first: A removed file has changed type.
+ # This should generate a warning.
+ mkfifo $OLD/difftype/first/first/fifo
+ mkdir $NEW/difftype/first/first/fifo
+
+ # /difftype/difftype/difftype: All three files (old, new, and
+ # test) are different types from each other. This should
+ # generate a warning.
+ mkfifo $OLD/difftype/difftype/difftype/one
+ mkdir $NEW/difftype/difftype/difftype/one
+ echo "foo" > $TEST/difftype/difftype/difftype/one
+ mkdir $OLD/difftype/difftype/difftype/two
+ echo "baz" > $NEW/difftype/difftype/difftype/two
+ ln -s "bar" $TEST/difftype/difftype/difftype/two
+
+ # /difftype/difftype/difflinks: A file has changed from a
+ # non-link to a link in both the new and test trees, but the
+ # target of the new and test links differ. This should
+ # generate a new link conflict.
+ mkfifo $OLD/difftype/difftype/difflinks/link
+ ln -s "new" $NEW/difftype/difftype/difflinks/link
+ ln -s "test" $TEST/difftype/difftype/difflinks/link
+
+ # /difftype/difftype/difffile: A file has changed from a
+ # non-regular file to a regular file in both the new and test
+ # trees, but the contents in the new and test files differ.
+ # This should generate a new file conflict.
+ ln -s "old" $OLD/difftype/difftype/difffiles/file
+ echo "foo" > $NEW/difftype/difftype/difffiles/file
+ echo "bar" > $TEST/difftype/difftype/difffiles/file
+
+ # /difflinks/first/first: A modified link is missing in the
+ # test tree. This should generate a warning.
+ ln -s "old" $OLD/difflinks/first/first/link
+ ln -s "new" $NEW/difflinks/first/first/link
+
+ # /difflinks/difftype/difftype: An updated link has been
+ # changed to a different file type in the test tree. This
+ # should generate a warning.
+ ln -s "old" $OLD/difflinks/difftype/difftype/link
+ ln -s "new" $NEW/difflinks/difftype/difftype/link
+ echo "test" > $TEST/difflinks/difftype/difftype/link
+
+ # /difflinks/difflinks/difflinks: An updated link has been
+ # modified in the test tree and doesn't match either the old
+ # or new links. This should generate a warning.
+ ln -s "old" $OLD/difflinks/difflinks/difflinks/link
+ ln -s "new" $NEW/difflinks/difflinks/difflinks/link
+ ln -s "test" $TEST/difflinks/difflinks/difflinks/link
+
+ # /difffiles/first/first: A removed file has been changed in
+ # the new tree. This should generate a warning.
+ echo "foo" > $OLD/difffiles/first/first/file
+ echo "bar" > $NEW/difffiles/first/first/file
+
+ # /difffiles/difftype/difftype: An updated regular file has
+ # been changed to a different file type in the test tree.
+ # This should generate a warning.
+ echo "old" > $OLD/difffiles/difftype/difftype/file
+ echo "new" > $NEW/difffiles/difftype/difftype/file
+ mkfifo $TEST/difffiles/difftype/difftype/file
+
+ # /difffiles/difffiles/difffiles: A modified regular file was
+ # updated in the new tree. The changes should be merged into
+ # to the new file if possible. If the merge fails, a conflict
+ # should be generated. For this test we just include the
+ # conflict case.
+ cat > $OLD/difffiles/difffiles/difffiles/conflict <<EOF
+this is an old file
+EOF
+ cat > $NEW/difffiles/difffiles/difffiles/conflict <<EOF
+this is a new file
+EOF
+ cat > $TEST/difffiles/difffiles/difffiles/conflict <<EOF
+this is a test file
+EOF
+
+ ## Tests for adding directories
+ mkdir -p $OLD/adddir $NEW/adddir $TEST/adddir
+
+ # /adddir/conflict: Add a new file in a directory that already
+ # exists as a file. This should generate two warnings.
+ mkdir $NEW/adddir/conflict
+ touch $NEW/adddir/conflict/newfile
+ touch $TEST/adddir/conflict
+
+ ## Tests for removing directories
+ mkdir -p $OLD/rmdir $NEW/rmdir $TEST/rmdir
+
+ # /rmdir/extra: Do not remove a directory with an extra local file.
+ # This should generate a warning.
+ for i in $OLD $TEST; do
+ mkdir $i/rmdir/extra
+ done
+ echo "foo" > $TEST/rmdir/extra/localfile.txt
+
+ # /rmdir/conflict: Do not remove a directory with a conflicted
+ # remove file. This should generate a warning.
+ for i in $OLD $TEST; do
+ mkdir $i/rmdir/conflict
+ done
+ mkfifo $OLD/rmdir/conflict/difftype
+ mkdir $TEST/rmdir/conflict/difftype
+
+ ## Tests for converting files to directories and vice versa
+ for i in $OLD $NEW $TEST; do
+ for j in already old fromdir todir; do
+ mkdir -p $i/dirchange/$j
+ done
+ done
+
+ # /dirchange/fromdir/extradir: Convert a directory tree to a
+ # file. The test tree includes an extra file in the directory
+ # that is not present in the old tree. This should generate a
+ # warning.
+ for i in $OLD $TEST; do
+ mkdir $i/dirchange/fromdir/extradir
+ echo "foo" > $i/dirchange/fromdir/extradir/file
+ done
+ mkfifo $TEST/dirchange/fromdir/extradir/fifo
+ ln -s "bar" $NEW/dirchange/fromdir/extradir
+
+ # /dirchange/fromdir/conflict: Convert a directory tree to a
+ # file. The test tree includes a local change that generates
+ # a warning and prevents the removal of the directory.
+ for i in $OLD $TEST; do
+ mkdir $i/dirchange/fromdir/conflict
+ done
+ echo "foo" > $OLD/dirchange/fromdir/conflict/somefile
+ echo "bar" > $TEST/dirchange/fromdir/conflict/somefile
+ mkfifo $NEW/dirchange/fromdir/conflict
+
+ # /dirchange/todir/difffile: Convert a file to a directory
+ # tree. The test tree has a locally modified version of the
+ # file so that the conversion fails with a warning.
+ echo "foo" > $OLD/dirchange/todir/difffile
+ mkdir $NEW/dirchange/todir/difffile
+ echo "baz" > $NEW/dirchange/todir/difffile/file
+ echo "bar" > $TEST/dirchange/todir/difffile
+
+ # /dirchange/todir/difftype: Similar to the previous test, but
+ # the conflict is due to a change in the file type.
+ echo "foo" > $OLD/dirchange/todir/difftype
+ mkdir $NEW/dirchange/todir/difftype
+ echo "baz" > $NEW/dirchange/todir/difftype/file
+ mkfifo $TEST/dirchange/todir/difftype
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be present in TEST
+present()
+{
+ if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be present"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a fifo in TEST
+fifo()
+{
+ if ! [ -p $TEST/$1 ]; then
+ echo "File $1 should be a FIFO"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a directory in TEST
+dir()
+{
+ if ! [ -d $TEST/$1 ]; then
+ echo "File $1 should be a directory"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a symlink in TEST
+# $2 - optional value of the link
+link()
+{
+ local val
+
+ if ! [ -L $TEST/$1 ]; then
+ echo "File $1 should be a link"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ val=`readlink $TEST/$1`
+ if [ "$val" != "$2" ]; then
+ echo "Link $1 should link to \"$2\""
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should have a conflict
+# $2 - optional MD5 of the conflict file contents
+conflict()
+{
+ local sum
+
+ if ! [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 missing conflict"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ sum=`md5 -q $CONFLICTS/$1`
+ if [ "$sum" != "$2" ]; then
+ echo "Conflict $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should not have a conflict
+noconflict()
+{
+ if [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 should not have a conflict"
+ FAILED=yes
+ fi
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+# First run the test ignoring no patterns.
+
+build_trees
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+cat > $WORKDIR/correct.out <<EOF
+ D /dirchange/fromdir/extradir/file
+ C /difffiles/difffiles/difffiles/conflict
+ C /difftype/difftype/difffiles/file
+ C /second/second/difffiles/file
+Warnings:
+ Modified regular file remains: /dirchange/fromdir/conflict/somefile
+ Modified regular file remains: /first/difffiles/second/file
+ Modified symbolic link remains: /first/difflinks/second/link
+ Modified directory remains: /first/difftype/second/fifo
+ Modified directory remains: /rmdir/conflict/difftype
+ Non-empty directory remains: /rmdir/extra
+ Non-empty directory remains: /rmdir/conflict
+ Modified mismatch: /difffiles/difftype/difftype/file (regular file vs fifo file)
+ Removed file changed: /difffiles/first/first/file
+ Modified link changed: /difflinks/difflinks/difflinks/link ("old" became "new")
+ Modified mismatch: /difflinks/difftype/difftype/link (symbolic link vs regular file)
+ Removed link changed: /difflinks/first/first/link ("old" became "new")
+ New link conflict: /difftype/difftype/difflinks/link ("new" vs "test")
+ Modified regular file changed: /difftype/difftype/difftype/one (fifo file became directory)
+ Modified symbolic link changed: /difftype/difftype/difftype/two (directory became regular file)
+ Remove mismatch: /difftype/first/first/fifo (fifo file became directory)
+ Modified directory changed: /dirchange/fromdir/conflict (directory became fifo file)
+ Modified directory changed: /dirchange/fromdir/extradir (directory became symbolic link)
+ Modified regular file changed: /dirchange/todir/difffile (regular file became directory)
+ Modified fifo file changed: /dirchange/todir/difftype (regular file became directory)
+ New file mismatch: /adddir/conflict (directory vs regular file)
+ Directory mismatch: $TEST/adddir/conflict (regular file)
+ Directory mismatch: $TEST/dirchange/todir/difffile (regular file)
+ Directory mismatch: $TEST/dirchange/todir/difftype (fifo file)
+ New link conflict: /second/second/difflinks/link ("new link" vs "test link")
+ New file mismatch: /second/second/difftype/dir (directory vs fifo file)
+EOF
+
+echo "Differences for regular:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+## /first/difftype/second:
+present /first/difftype/second/fifo
+
+## /first/difflinks/second:
+link /first/difflinks/second/link "test link"
+
+## /first/difffiles/second:
+file /first/difffiles/second/file "bar"
+
+## /second/second/difftype:
+fifo /second/second/difftype/dir
+
+## /second/second/difflinks:
+link /second/second/difflinks/link "test link"
+
+## /second/second/difffiles:
+file /second/second/difffiles/file "test"
+conflict /second/second/difffiles/file 4f2ee8620a251fd53f06bb6112eb6ffa
+
+## /difftype/first/first:
+missing /difftype/first/first/fifo
+
+## /difftype/difftype/difftype:
+file /difftype/difftype/difftype/one "foo"
+link /difftype/difftype/difftype/two "bar"
+
+## /difftype/difftype/difflinks:
+link /difftype/difftype/difflinks/link "test"
+
+## /difftype/difftype/difffile:
+conflict /difftype/difftype/difffiles/file 117f2bcd1f6491f6044e79e5a57a9229
+
+## /difflinks/first/first:
+missing /difflinks/first/first/link
+
+## /difflinks/difftype/difftype:
+file /difflinks/difftype/difftype/link "test"
+
+## /difflinks/difflinks/difflinks:
+link /difflinks/difflinks/difflinks/link "test"
+
+## /difffiles/first/first:
+missing /difffiles/first/first/file
+
+## /difffiles/difftype/difftype:
+fifo /difffiles/difftype/difftype/file
+
+## /difffiles/difffiles/difffiles:
+file /difffiles/difffiles/difffiles/conflict "this is a test file"
+conflict /difffiles/difffiles/difffiles/conflict \
+ 8261cfdd89280c4a6c26e4ac86541fe9
+
+## /adddir/conflict:
+file /adddir/conflict
+
+## /rmdir/extra:
+dir /rmdir/extra
+file /rmdir/extra/localfile.txt "foo"
+
+## /rmdir/conflict:
+dir /rmdir/conflict/difftype
+present /rmdir/conflict
+
+## /dirchange/fromdir/extradir:
+missing /dirchange/fromdir/extradir/file
+fifo /dirchange/fromdir/extradir/fifo
+
+## /dirchange/fromdir/conflict:
+file /dirchange/fromdir/conflict/somefile "bar"
+
+## /dirchange/todir/difffile:
+file /dirchange/todir/difffile "bar"
+
+## /dirchange/todir/difftype:
+fifo /dirchange/todir/difftype
+
+# Now test with -A '/first*' -A '/second* /*di*'. This should remove
+# most of the warnings and conflicts.
+
+build_trees
+
+$COMMAND -r -A '/first*' -A '/second* /*di*' -d $WORKDIR -D $TEST > \
+ $WORKDIR/test1.out
+
+cat > $WORKDIR/correct1.out <<EOF
+ D /dirchange/fromdir/extradir/file
+ U /difffiles/difffiles/difffiles/conflict
+ U /difffiles/difftype/difftype/file
+ A /difffiles/first/first/file
+ U /difflinks/difflinks/difflinks/link
+ U /difflinks/difftype/difftype/link
+ A /difflinks/first/first/link
+ U /difftype/difftype/difffiles/file
+ U /difftype/difftype/difflinks/link
+ D /difftype/difftype/difftype/one
+ U /difftype/difftype/difftype/two
+ U /dirchange/todir/difffile
+ U /dirchange/todir/difftype
+ U /adddir/conflict
+ A /adddir/conflict/newfile
+ A /dirchange/todir/difffile/file
+ A /dirchange/todir/difftype/file
+ U /second/second/difffiles/file
+ U /second/second/difflinks/link
+ D /second/second/difftype/dir
+Warnings:
+ Modified regular file remains: /dirchange/fromdir/conflict/somefile
+ Modified regular file remains: /first/difffiles/second/file
+ Modified symbolic link remains: /first/difflinks/second/link
+ Modified directory remains: /first/difftype/second/fifo
+ Modified directory remains: /rmdir/conflict/difftype
+ Non-empty directory remains: /rmdir/extra
+ Non-empty directory remains: /rmdir/conflict
+ Modified directory changed: /dirchange/fromdir/conflict (directory became fifo file)
+ Modified directory changed: /dirchange/fromdir/extradir (directory became symbolic link)
+EOF
+
+echo "Differences for -A '/first*' -A '/second* /*di*':"
+diff -u -L "correct" $WORKDIR/correct1.out -L "test" $WORKDIR/test1.out \
+ || FAILED=yes
+
+## /first/difftype/second:
+present /first/difftype/second/fifo
+
+## /first/difflinks/second:
+link /first/difflinks/second/link "test link"
+
+## /first/difffiles/second:
+file /first/difffiles/second/file "bar"
+
+## /second/second/difftype:
+missing /second/second/difftype/dir
+
+## /second/second/difflinks:
+link /second/second/difflinks/link "new link"
+
+## /second/second/difffiles:
+file /second/second/difffiles/file "new"
+noconflict /second/second/difffiles/file
+
+## /difftype/first/first:
+missing /difftype/first/first/fifo
+
+## /difftype/difftype/difftype:
+missing /difftype/difftype/difftype/one
+file /difftype/difftype/difftype/two "baz"
+
+## /difftype/difftype/difflinks:
+link /difftype/difftype/difflinks/link "new"
+
+## /difftype/difftype/difffile:
+noconflict /difftype/difftype/difffiles/file
+file /difftype/difftype/difffiles/file "foo"
+
+## /difflinks/first/first:
+link /difflinks/first/first/link "new"
+
+## /difflinks/difftype/difftype:
+link /difflinks/difftype/difftype/link "new"
+
+## /difflinks/difflinks/difflinks:
+link /difflinks/difflinks/difflinks/link "new"
+
+## /difffiles/first/first:
+file /difffiles/first/first/file "bar"
+
+## /difffiles/difftype/difftype:
+file /difffiles/difftype/difftype/file "new"
+
+## /difffiles/difffiles/difffiles:
+noconflict /difffiles/difffiles/difffiles/conflict
+file /difffiles/difffiles/difffiles/conflict "this is a new file"
+
+## /adddir/conflict:
+file /adddir/conflict/newfile
+
+## /rmdir/extra:
+dir /rmdir/extra
+file /rmdir/extra/localfile.txt "foo"
+
+## /rmdir/conflict:
+dir /rmdir/conflict/difftype
+present /rmdir/conflict
+
+## /dirchange/fromdir/extradir:
+missing /dirchange/fromdir/extradir/file
+fifo /dirchange/fromdir/extradir/fifo
+
+## /dirchange/fromdir/conflict:
+file /dirchange/fromdir/conflict/somefile "bar"
+
+## /dirchange/todir/difffile:
+file /dirchange/todir/difffile/file "baz"
+
+## /dirchange/todir/difftype:
+file /dirchange/todir/difftype/file "baz"
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/etcupdate/tests/conflicts_test.sh b/usr.sbin/etcupdate/tests/conflicts_test.sh
new file mode 100644
index 0000000..816c180
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/conflicts_test.sh
@@ -0,0 +1,294 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests to run for the 'resolve' command.
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: conflicts.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+# These tests deal with conflicts to a single file. For each test, we
+# generate a conflict in /etc/login.conf. Each resolve option is tested
+# to ensure it DTRT.
+build_login_conflict()
+{
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+ mkdir -p $OLD/etc $NEW/etc $TEST/etc
+
+ # Generate a conflict in /etc/login.conf.
+ cat > $OLD/etc/login.conf <<EOF
+default:\\
+ :passwd_format=md5:
+EOF
+ cat > $NEW/etc/login.conf <<EOF
+default:\\
+ :passwd_format=md5:\\
+ :copyright=/etc/COPYRIGHT
+EOF
+ cat > $TEST/etc/login.conf <<EOF
+default:\\
+ :passwd_format=md5:\\
+ :welcome=/etc/motd:
+EOF
+
+ $COMMAND -r -d $WORKDIR -D $TEST >/dev/null
+}
+
+# This is used to verify special handling for /etc/mail/aliases and
+# the newaliases warning.
+build_aliases_conflict()
+{
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+ mkdir -p $OLD/etc/mail $NEW/etc/mail $TEST/etc/mail
+
+ # Generate a conflict in /etc/mail/aliases
+ cat > $OLD/etc/mail/aliases <<EOF
+# root: me@my.domain
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: root
+EOF
+ cat > $NEW/etc/mail/aliases <<EOF
+# root: me@my.domain
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: root
+
+# General redirections for pseudo accounts
+_dhcp: root
+_pflogd: root
+EOF
+ cat > $TEST/etc/mail/aliases <<EOF
+root: someone@example.com
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: foo
+EOF
+
+ $COMMAND -r -d $WORKDIR -D $TEST >/dev/null
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be present in TEST
+present()
+{
+ if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be present"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should have a conflict
+# $2 - optional MD5 of the conflict file contents
+conflict()
+{
+ local sum
+
+ if ! [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 missing conflict"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ sum=`md5 -q $CONFLICTS/$1`
+ if [ "$sum" != "$2" ]; then
+ echo "Conflict $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should no longer have a conflict
+resolved()
+{
+ if [ -f $CONFLICTS/$1 ]; then
+ echo "Conflict $1 should be resolved"
+ FAILED=yes
+ fi
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+# Test each of the following resolve options: 'p', 'mf', 'tf', 'r'.
+
+build_login_conflict
+
+# Verify that 'p' doesn't do anything.
+echo "Checking 'p':"
+echo 'p' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
+
+file /etc/login.conf "" 95de92ea3f1bb1bf4f612a8b5908cddd
+missing /etc/login.conf.db
+conflict /etc/login.conf
+
+# Verify that 'mf' removes the conflict, but does nothing else.
+echo "Checking 'mf':"
+echo 'mf' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
+
+file /etc/login.conf "" 95de92ea3f1bb1bf4f612a8b5908cddd
+missing /etc/login.conf.db
+resolved /etc/login.conf
+
+build_login_conflict
+
+# Verify that 'tf' installs the new version of the file.
+echo "Checking 'tf':"
+echo 'tf' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
+
+file /etc/login.conf "" 7774a0f9a3a372c7c109c32fd31c4b6b
+file /etc/login.conf.db
+resolved /etc/login.conf
+
+build_login_conflict
+
+# Verify that 'r' installs the resolved version of the file. To
+# simulate this, manually edit the merged file so that it doesn't
+# contain conflict markers.
+echo "Checking 'r':"
+cat > $CONFLICTS/etc/login.conf <<EOF
+default:\\
+ :passwd_format=md5:\\
+ :copyright=/etc/COPYRIGHT\\
+ :welcome=/etc/motd:
+EOF
+
+echo 'r' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
+
+file /etc/login.conf "" 966e25984b9b63da8eaac8479dcb0d4d
+file /etc/login.conf.db
+resolved /etc/login.conf
+
+build_aliases_conflict
+
+# Verify that 'p' and 'mf' do not generate the newaliases warning.
+echo "Checking newalias warning for 'p'":
+echo 'p' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
+if [ $? -eq 0 ]; then
+ echo "+ Extra warning"
+ FAILED=yes
+fi
+echo "Checking newalias warning for 'mf'":
+echo 'mf' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
+if [ $? -eq 0 ]; then
+ echo "+ Extra warning"
+ FAILED=yes
+fi
+
+# Verify that 'tf' and 'r' do generate the newaliases warning.
+build_aliases_conflict
+echo "Checking newalias warning for 'tf'":
+echo 'tf' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
+if [ $? -ne 0 ]; then
+ echo "- Missing warning"
+ FAILED=yes
+fi
+
+build_aliases_conflict
+cp $TEST/etc/mail/aliases $CONFLICTS/etc/mail/aliases
+echo 'r' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
+if [ $? -ne 0 ]; then
+ echo "- Missing warning"
+ FAILED=yes
+fi
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/etcupdate/tests/fbsdid_test.sh b/usr.sbin/etcupdate/tests/fbsdid_test.sh
new file mode 100644
index 0000000..c062c06
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/fbsdid_test.sh
@@ -0,0 +1,394 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests to test the -F flag to the 'update' command.
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: fbsdid.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+# Store a FreeBSD ID string in a specified file. The first argument
+# is the file, the remaining arguments are the comment to use.
+store_id()
+{
+ local file
+
+ file=$1
+ shift
+
+ echo -n '# $FreeBSD' >> $file
+ echo -n "$@" >> $file
+ echo '$' >> $file
+}
+
+# These tests deal with FreeBSD ID string conflicts. We run the test
+# twice, once without -F and once with -F.
+build_trees()
+{
+ local i
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+ mkdir -p $OLD $NEW $TEST
+
+ # remove: Remove a file where the only local difference is a
+ # change in the FreeBSD ID string.
+ store_id $OLD/remove
+ store_id $TEST/remove ": head/remove 12345 jhb "
+
+ # old: Modify a file where the only local difference between
+ # the old and test files is a change in the FreeBSD ID string.
+ store_id $OLD/old ": src/old,v 1.1 jhb Exp "
+ store_id $NEW/old ": head/old 12345 jhb "
+ store_id $TEST/old ": head/old 12000 jhb "
+ for i in $OLD $TEST; do
+ cat >> $i/old <<EOF
+
+an old file
+EOF
+ done
+ cat >> $NEW/old <<EOF
+
+a new file
+EOF
+
+ # already: Modify a file where the local file already matches
+ # the new file except for a change in the FreeBSD ID string.
+ store_id $OLD/already ": src/already,v 1.1 jhb Exp "
+ store_id $NEW/already ": head/already 12345 jhb "
+ store_id $TEST/already ": src/already,v 1.2 jhb Exp "
+ cat >> $OLD/already <<EOF
+
+another old file
+EOF
+ for i in $NEW $TEST; do
+ cat >> $i/already <<EOF
+
+another new file
+EOF
+ done
+
+ # add: Add a file that already exists where the only local
+ # difference is a change in the FreeBSD ID string.
+ store_id $NEW/add ": head/add 12345 jhb "
+ store_id $TEST/add ""
+
+ # conflict: Modify a file where the local file has a different
+ # FreeBSD ID string. This should still generate a conflict
+ # even in the -F case.
+ store_id $OLD/conflict ": head/conflict 12000 jhb "
+ store_id $NEW/conflict ": head/conflict 12345 jhb "
+ store_id $TEST/conflict ""
+ cat >> $OLD/conflict <<EOF
+
+this is the old file
+EOF
+ cat >> $NEW/conflict <<EOF
+
+this is the new file
+EOF
+ cat >> $TEST/conflict <<EOF
+
+this is the local file
+EOF
+
+ # local: A file with local modifications has a different
+ # FreeBSD ID string and the only differences between the old
+ # and new versions are a change in the FreeBSD ID string.
+ # This will just update the FreeBSD ID string in the -F case.
+ for i in $OLD $NEW $TEST; do
+ cat >> $i/local <<EOF
+# Some leading text
+#
+EOF
+ done
+
+ store_id $OLD/local ": head/local 12000 jhb "
+ store_id $NEW/local ": head/local 12345 jhb "
+ store_id $TEST/local ": src/local,v 1.5 jhb Exp "
+
+ for i in $OLD $NEW $TEST; do
+ cat >> $i/local <<EOF
+
+this is a file
+EOF
+ done
+
+ cat >> $TEST/local <<EOF
+
+these are some local mods to the file
+EOF
+
+ # local-already: A file with local modifications has the same
+ # FreeBSD ID string as the new version of the file and the
+ # only differences between the old and new versions are a
+ # change in the FreeBSD ID string. Nothing should happen in
+ # the -F case.
+ store_id $OLD/local-already ": head/local 12000 jhb "
+ for i in $NEW $TEST; do
+ store_id $i/local-already ": head/local 12345 jhb "
+ done
+
+ for i in $OLD $NEW $TEST; do
+ cat >> $i/local-already <<EOF
+
+this is a file
+EOF
+ done
+
+ cat >> $TEST/local-already <<EOF
+
+these are some local mods to the file
+EOF
+
+ # local-remove: A file removed locally changed it's FreeBSD ID
+ # but nothing else
+ store_id $OLD/local-remove ": head/local-remove 12000 jhb "
+ store_id $NEW/local-remove ": head/local-remove 12345 jhb "
+ for i in $OLD $NEW; do
+ cat >> $i/local-remove <<EOF
+
+this is a file
+EOF
+ done
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be present in TEST
+present()
+{
+ if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be present"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should have a conflict
+# $2 - optional MD5 of the conflict file contents
+conflict()
+{
+ local sum
+
+ if ! [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 missing conflict"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ sum=`md5 -q $CONFLICTS/$1`
+ if [ "$sum" != "$2" ]; then
+ echo "Conflict $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should not have a conflict
+noconflict()
+{
+ if [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 should not have a conflict"
+ FAILED=yes
+ fi
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+# First run the test without -F.
+
+build_trees
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+cat > $WORKDIR/correct.out <<EOF
+ C /already
+ C /conflict
+ C /local
+ M /local-already
+ C /old
+ C /add
+Warnings:
+ Modified regular file remains: /remove
+ Removed file changed: /local-remove
+EOF
+
+echo "Differences for regular:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+file /remove "" 1bb4776213af107077be78fead8a351c
+file /old "" 2f799a7addc4132563ef9b44adc66157
+conflict /old 8441be64a1540f2ff584015279682425
+file /already "" aa53bd506f65d01d766e7ba028585e1d
+conflict /already f44105abb1fa3293e95c5d77e428d418
+file /add "" 1dc8c617e541d1fd1b4c70212f71d8ae
+conflict /add f99081e0da9a07f3cfebb430c0414941
+file /conflict "" dc27978df125b0daeb7d9b93265f03fd
+conflict /conflict 868452f666fea1c60ffb918ad9ad9607
+file /local "" aa33e614b5e749449f230e2a2b0072eb
+conflict /local 3df93e64043c8e348fc625b93ea220f4
+file /local-already "" 0298b958a603049f45ae6a109c4f7fea
+missing /local-remove
+
+# Now test with -F.
+
+build_trees
+
+$COMMAND -rF -d $WORKDIR -D $TEST > $WORKDIR/testF.out
+
+cat > $WORKDIR/correctF.out <<EOF
+ D /remove
+ U /already
+ C /conflict
+ M /local
+ U /old
+ U /add
+EOF
+
+echo "Differences for -F:"
+diff -u -L "correct" $WORKDIR/correctF.out -L "test" $WORKDIR/testF.out \
+ || FAILED=yes
+
+missing /remove
+file /old "" 6a9f34f109d94406a4de3bc5d72de259
+noconflict /old
+file /already "" 21f4eca3aacc702c49878c8da7afd3d0
+noconflict /already
+file /add "" 0208bd647111fedf6318511712ab9e97
+noconflict /add
+file /conflict "" dc27978df125b0daeb7d9b93265f03fd
+conflict /conflict 868452f666fea1c60ffb918ad9ad9607
+file /local "" 3ed5a35e380c8a93fb5f599d4c052713
+file /local-already "" 0298b958a603049f45ae6a109c4f7fea
+missing /local-remove
+
+# Now test with -F and -A forcing all installs. (-A should have
+# precedence over -F)
+
+build_trees
+
+$COMMAND -A '/*' -rF -d $WORKDIR -D $TEST > $WORKDIR/testAF.out
+
+cat > $WORKDIR/correctAF.out <<EOF
+ D /remove
+ U /already
+ U /conflict
+ U /local
+ U /local-already
+ A /local-remove
+ U /old
+ U /add
+EOF
+
+echo "Differences for -A '/*' -F:"
+diff -u -L "correct" $WORKDIR/correctAF.out -L "test" $WORKDIR/testAF.out \
+ || FAILED=yes
+
+missing /remove
+file /old "" 6a9f34f109d94406a4de3bc5d72de259
+noconflict /old
+file /already "" 21f4eca3aacc702c49878c8da7afd3d0
+noconflict /already
+file /add "" 0208bd647111fedf6318511712ab9e97
+noconflict /add
+file /conflict "" 75ee141c4136beaf14e39de92efa84e4
+noconflict /conflict
+file /local "" 6a8fc5c2755b7a49015089f5e1dbe092
+file /local-already "" 49045f8b51542dd634655301cd296f66
+file /local-remove "" 5c38322efed4014797d7127f5c652d9d
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/etcupdate/tests/ignore_test.sh b/usr.sbin/etcupdate/tests/ignore_test.sh
new file mode 100644
index 0000000..2d3d2f5
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/ignore_test.sh
@@ -0,0 +1,276 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests to test the -I flag to the 'update' command.
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: ignore.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+# These tests deal with ignoring certain patterns of files. We run the
+# test multiple times ignoring different patterns.
+build_trees()
+{
+ local i
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+ mkdir -p $OLD $NEW $TEST
+
+ for i in $OLD $NEW $TEST; do
+ mkdir -p $i/tree
+ done
+
+ # tree: Test three different cases (add, modify, remove) that all
+ # match the tree/* glob.
+ echo "foo" > $NEW/tree/add
+ for i in $OLD $TEST; do
+ echo "old" > $i/tree/modify
+ done
+ echo "new" > $NEW/tree/modify
+ for i in $OLD $TEST; do
+ echo "old" > $i/tree/remove
+ done
+
+ # rmdir: Remove a whole tree.
+ for i in $OLD $TEST; do
+ mkdir $i/rmdir
+ echo "foo" > $i/rmdir/file
+ done
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be present in TEST
+present()
+{
+ if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be present"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a directory in TEST
+dir()
+{
+ if ! [ -d $TEST/$1 ]; then
+ echo "File $1 should be a directory"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should have a conflict
+# $2 - optional MD5 of the conflict file contents
+conflict()
+{
+ local sum
+
+ if ! [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 missing conflict"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ sum=`md5 -q $CONFLICTS/$1`
+ if [ "$sum" != "$2" ]; then
+ echo "Conflict $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should not have a conflict
+noconflict()
+{
+ if [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 should not have a conflict"
+ FAILED=yes
+ fi
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+# First run the test ignoring no patterns.
+
+build_trees
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+cat > $WORKDIR/correct.out <<EOF
+ D /rmdir/file
+ D /tree/remove
+ D /rmdir
+ U /tree/modify
+ A /tree/add
+EOF
+
+echo "Differences for regular:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+missing /tree/remove
+file /tree/modify "new"
+file /tree/add "foo"
+missing /rmdir/file
+missing /rmdir
+
+# Now test with -I '/tree/*'. This should preserve the /tree files.
+
+build_trees
+
+$COMMAND -r -I '/tree/*' -d $WORKDIR -D $TEST > $WORKDIR/test1.out
+
+cat > $WORKDIR/correct1.out <<EOF
+ D /rmdir/file
+ D /rmdir
+EOF
+
+echo "Differences for -I '/tree/*':"
+diff -u -L "correct" $WORKDIR/correct1.out -L "test" $WORKDIR/test1.out \
+ || FAILED=yes
+
+file /tree/remove "old"
+file /tree/modify "old"
+missing /tree/add
+missing /rmdir/file
+missing /rmdir
+
+# Now test with two patterns. This should preserve everything.
+
+build_trees
+
+$COMMAND -r -I '/tree/*' -I '/rmdir*' -d $WORKDIR -D $TEST > \
+ $WORKDIR/test2.out
+
+cat > $WORKDIR/correct2.out <<EOF
+EOF
+
+echo "Differences for -I '/tree/*' -I '/rmdir*':"
+
+diff -u -L "correct" $WORKDIR/correct2.out -L "test" $WORKDIR/test2.out \
+ || FAILED=yes
+
+file /tree/remove "old"
+file /tree/modify "old"
+missing /tree/add
+file /rmdir/file "foo"
+
+# Now test with a pattern that should cause a warning on /rmdir by
+# only ignoring the files under that directory. Note that this also
+# tests putting two patterns into a single -I argument.
+
+build_trees
+
+$COMMAND -r -I '/tree/* /rmdir/*' -d $WORKDIR -D $TEST > \
+ $WORKDIR/test3.out
+
+cat > $WORKDIR/correct3.out <<EOF
+Warnings:
+ Non-empty directory remains: /rmdir
+EOF
+
+echo "Differences for -I '/tree/* /rmdir/*':"
+
+diff -u -L "correct" $WORKDIR/correct3.out -L "test" $WORKDIR/test3.out \
+ || FAILED=yes
+
+file /tree/remove "old"
+file /tree/modify "old"
+missing /tree/add
+file /rmdir/file "foo"
+dir /rmdir
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/etcupdate/tests/preworld_test.sh b/usr.sbin/etcupdate/tests/preworld_test.sh
new file mode 100644
index 0000000..c731293
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/preworld_test.sh
@@ -0,0 +1,252 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Regression tests for the pre-world (-p) mode
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: preworld.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+SRC=$WORKDIR/src
+OLD=$WORKDIR/current
+TEST=$WORKDIR/test
+
+build_trees()
+{
+
+ # Populate trees with pre-world files and additional files
+ # that should not be touched.
+
+ rm -rf $SRC $OLD $TEST $CONFLICTS
+
+ # Create the "old" source tree as the starting point
+ mkdir -p $OLD/etc
+ cat >> $OLD/etc/master.passwd <<EOF
+#
+root::0:0::0:0:Charlie &:/root:/bin/csh
+toor:*:0:0::0:0:Bourne-again Superuser:/root:
+daemon:*:1:1::0:0:Owner of many system processes:/root:/usr/sbin/nologin
+operator:*:2:5::0:0:System &:/:/usr/sbin/nologin
+_dhcp:*:65:65::0:0:dhcp programs:/var/empty:/usr/sbin/nologin
+uucp:*:66:66::0:0:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico
+pop:*:68:6::0:0:Post Office Owner:/nonexistent:/usr/sbin/nologin
+www:*:80:80::0:0:World Wide Web Owner:/nonexistent:/usr/sbin/nologin
+hast:*:845:845::0:0:HAST unprivileged user:/var/empty:/usr/sbin/nologin
+nobody:*:65534:65534::0:0:Unprivileged user:/nonexistent:/usr/sbin/nologin
+EOF
+ cat >> $OLD/etc/group <<EOF
+#
+wheel:*:0:root
+daemon:*:1:
+kmem:*:2:
+sys:*:3:
+tty:*:4:
+operator:*:5:root
+_dhcp:*:65:
+uucp:*:66:
+dialer:*:68:
+network:*:69:
+www:*:80:
+hast:*:845:
+nogroup:*:65533:
+nobody:*:65534:
+EOF
+ cat >> $OLD/etc/inetd.conf <<EOF
+# Yet another file
+EOF
+
+ # Copy the "old" source tree to the test tree and make local
+ # modifications.
+ cp -R $OLD $TEST
+ sed -I "" -e 's/root::/root:<rpass>:/' $TEST/etc/master.passwd
+ cat >> $TEST/etc/master.passwd <<EOF
+john:<password>:1001:1001::0:0:John Baldwin:/home/john:/bin/tcsh
+messagebus:*:556:556::0:0:D-BUS Daemon User:/nonexistent:/usr/sbin/nologin
+polkit:*:562:562::0:0:PolicyKit User:/nonexistent:/usr/sbin/nologin
+haldaemon:*:560:560::0:0:HAL Daemon User:/nonexistent:/usr/sbin/nologin
+EOF
+ awk '/wheel/ { printf "%s,john\n", $0; next } // { print }' \
+ $OLD/etc/group > $TEST/etc/group
+ cat >> $TEST/etc/group <<EOF
+john:*:1001:
+messagebus:*:556:
+polkit:*:562:
+haldaemon:*:560:
+EOF
+ rm $TEST/etc/inetd.conf
+ touch $TEST/etc/localtime
+
+ # Copy the "old" source tree to the new source tree and
+ # make upstream modifications.
+ cp -R $OLD $SRC
+ sed -I "" -e '/:80:/i\
+auditdistd:*:78:77::0:0:Auditdistd unprivileged user:/var/empty:/usr/sbin/nologin' \
+ $SRC/etc/master.passwd
+ sed -I "" -e '/:80:/i\
+audit:*:77:' \
+ $SRC/etc/group
+ cat >> $SRC/etc/inetd.conf <<EOF
+# Making this larger
+EOF
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be present in TEST
+present()
+{
+ if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be present"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should have a conflict
+# $2 - optional MD5 of the conflict file contents
+conflict()
+{
+ local sum
+
+ if ! [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 missing conflict"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ sum=`md5 -q $CONFLICTS/$1`
+ if [ "$sum" != "$2" ]; then
+ echo "Conflict $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+check_trees()
+{
+
+ echo "Checking tree for correct results:"
+
+ file /etc/master.passwd "" 1385366e8b424d33d59b7d8a2bdb15d3
+ file /etc/group "" 21273f845f6ec0cda9188c4ddac9ed47
+ missing /etc/inetd.conf
+
+ # These should be auto-generated by pwd_mkdb
+ file /etc/passwd "" 9831537874bdc99adccaa2b0293248a1
+ file /etc/pwd.db
+ file /etc/spwd.db
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+build_trees
+
+$COMMAND -np -s $SRC -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+ M /etc/group
+ M /etc/master.passwd
+EOF
+
+echo "Differences for -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
+ || FAILED=yes
+
+$COMMAND -p -s $SRC -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for real:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+check_trees
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/etcupdate/tests/tests_test.sh b/usr.sbin/etcupdate/tests/tests_test.sh
new file mode 100644
index 0000000..b99bbef
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/tests_test.sh
@@ -0,0 +1,1021 @@
+#!/bin/sh
+#
+# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests to run for the 'update' command.
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: tests.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+# The various states of the comparison of a file between two trees.
+states="equal first second difftype difflinks difffiles"
+
+build_trees()
+{
+ local i j k
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+ mkdir -p $OLD/etc $NEW/etc $TEST/etc
+
+ # For an given file, there are three different pair-wise
+ # relations between the three threes (old, new, and test): old
+ # vs new, old vs test, and new vs test. Each of these
+ # relations takes on one of six different states from the
+ # 'compare()' function in etcupdate: equal, onlyfirst,
+ # onlysecond, difftype, difflinks, difffiles. In addition,
+ # there are special considerations for considering cases such
+ # as a file merge that results in conflicts versus one that
+ # does not, special treatment of directories, etc. The tests
+ # below attempt to enumerate the three dimensional test matrix
+ # by having the path name use the three different tree states
+ # for the parent directories.
+ #
+ # Note that if the old and new files are identical (so first
+ # compare is "equal"), then the second and third comparisons
+ # will be the same.
+ #
+ # Note also that etcupdate only cares about files that are
+ # present in at least one of the old or new trees. Thus, none
+ # of the '*/second/second' cases are relevant.
+
+ for i in $states; do
+ for j in $states; do
+ for k in $states; do
+ mkdir -p $OLD/$i/$j/$k $NEW/$i/$j/$k \
+ $TEST/$i/$j/$k
+ done
+ done
+ done
+
+ # /equal/equal/equal: Everything is equal. Nothing should happen.
+ for i in $OLD $NEW $TEST; do
+ mkfifo $i/equal/equal/equal/fifo
+ echo "foo" > $i/equal/equal/equal/file
+ mkdir $i/equal/equal/equal/dir
+ ln -s "bar" $i/equal/equal/equal/link
+ done
+
+ # /equal/first/first: The file is missing from the test
+ # directory. Nothing should happen.
+ for i in $OLD $NEW; do
+ mkfifo $i/equal/first/first/fifo
+ echo "foo" > $i/equal/first/first/file
+ mkdir $i/equal/first/first/dir
+ ln -s "bar" $i/equal/first/first/link
+ done
+
+ # /equal/difftype/difftype: The local file is a different
+ # type. Nothing should happen.
+ for i in $OLD $NEW; do
+ mkfifo $i/equal/difftype/difftype/fifo
+ mkdir $i/equal/difftype/difftype/fromdir
+ done
+ echo "bar" > $TEST/equal/difftype/difftype/fifo
+ ln -s "test" $TEST/equal/difftype/difftype/fromdir
+
+ # /equal/difflinks/difflinks: The local file is a modified
+ # link. Nothing should happen.
+ for i in $OLD $NEW; do
+ ln -s "foo" $i/equal/difflinks/difflinks/link
+ done
+ ln -s "bar" $TEST/equal/difflinks/difflinks/link
+
+ # /equal/difffiles/difffiles: The local file is a modified
+ # file. Nothing should happen.
+ for i in $OLD $NEW; do
+ echo "foo" > $i/equal/difffiles/difffiles/file
+ done
+ echo "bar" > $TEST/equal/difffiles/difffiles/file
+
+ # /first/equal/second: Remove unmodified files. The files
+ # should all be removed.
+ for i in $OLD $TEST; do
+ mkfifo $i/first/equal/second/fifo
+ echo "foo" > $i/first/equal/second/file
+ mkdir $i/first/equal/second/emptydir
+ ln -s "bar" $i/first/equal/second/link
+ mkdir $i/first/equal/second/fulldir
+ echo "foo" > $i/first/equal/second/fulldir/file
+ done
+
+ # /first/equal/*: Cannot occur. If the file is missing from
+ # new, then new vs test will always be 'second'.
+
+ # /first/first/equal: Removed files are already removed.
+ # Nothing should happen.
+ mkfifo $OLD/first/first/equal/fifo
+ echo "foo" > $OLD/first/first/equal/file
+ mkdir $OLD/first/first/equal/dir
+ ln -s "bar" $OLD/first/first/equal/link
+
+ # /first/first/*: Cannot occur. The files are missing from
+ # both new and test.
+
+ # /first/second/*: Cannot happen, if the file is in old for
+ # old vs new, it cannot be missing for old vs test.
+
+ # /first/difftype/second: File with different local type
+ # removed. Should generate a warning.
+ mkfifo $OLD/first/difftype/second/fifo
+ mkdir $TEST/first/difftype/second/fifo
+
+ # /first/difftype/*: Cannot happen since the file is missing
+ # from new but present in test.
+
+ # /first/difflinks/second: Modified link removed. Should
+ # generate a warning.
+ ln -s "old link" $OLD/first/difflinks/second/link
+ ln -s "test link" $TEST/first/difflinks/second/link
+
+ # /first/difflinks/*: Cannot happen since the file is missing
+ # from new but present in test.
+
+ # /first/difffiles/second: Modified file removed. Should
+ # generate a warning.
+ echo "foo" > $OLD/first/difffiles/second/file
+ echo "bar" > $TEST/first/difffiles/second/file
+
+ # /first/difffiles/*: Cannot happen since the file is missing
+ # from new but present in test.
+
+ # /second/equal/first: Added a new file that isn't present in
+ # test. The empty directory should be ignored.
+ echo "bar" > $NEW/second/equal/first/file
+ mkfifo $NEW/second/equal/first/fifo
+ ln -s "new" $NEW/second/equal/first/link
+ mkdir $NEW/second/equal/first/emptydir
+ mkdir $NEW/second/equal/first/fulldir
+ echo "foo" > $NEW/second/equal/first/fulldir/file
+
+ # /second/equal/*: Cannot happen since the file is missing
+ # from test but present in new.
+
+ # /second/first/*: Cannot happen since the file is missing
+ # from old.
+
+ # /second/second/equal: Newly added file is already present in
+ # the test directory and identical to the new file. Nothing
+ # should happen.
+ for i in $NEW $TEST; do
+ mkfifo $i/second/second/equal/fifo
+ echo "foo" > $i/second/second/equal/file
+ mkdir $i/second/second/equal/dir
+ ln -s "bar" $i/second/second/equal/link
+ done
+
+ # /second/second/first: Cannot happen. The file is in dest in
+ # the second test, so it can't be missing from the third test.
+
+ # /second/second/second: Cannot happen. The file is in new in
+ # the first test, so it can't be missing from the third test.
+
+ # /second/second/difftype: Newly added file conflicts with
+ # existing file in test tree of a different type. Should
+ # generate a warning.
+ mkdir $NEW/second/second/difftype/dir
+ mkfifo $TEST/second/second/difftype/dir
+
+ # /second/second/difflinks: Newly added link conflicts with
+ # existing link in test tree. Should generate a warning.
+ ln -s "new link" $NEW/second/second/difflinks/link
+ ln -s "test link" $TEST/second/second/difflinks/link
+
+ # /second/second/difffiles: Newly added file conflicts with
+ # existing file in test tree. Should generate a warning.
+ echo "new" > $NEW/second/second/difffiles/file
+ echo "test" > $TEST/second/second/difffiles/file
+
+ # /second/difftype/*: Cannot happen since the file is missing
+ # from old.
+
+ # /second/difflinks/*: Cannot happen since the file is missing
+ # from old.
+
+ # /second/difffiles/*: Cannot happen since the file is missing
+ # from old.
+
+ # /difftype/equal/difftype: Unmodified file has changed type.
+ # File should be updated to the new file. In the 'todir' case
+ # the directory won't actually be created because it is empty.
+ for i in $OLD $TEST; do
+ echo "foo" > $i/difftype/equal/difftype/file
+ mkdir $i/difftype/equal/difftype/fromdir
+ ln -s "old" $i/difftype/equal/difftype/todir
+ done
+ ln -s "test" $NEW/difftype/equal/difftype/file
+ mkfifo $NEW/difftype/equal/difftype/fromdir
+ mkdir $NEW/difftype/equal/difftype/todir
+
+ # /difftype/equal/*: Cannot happen. Since the old file is a
+ # difftype from the new file and the test file is identical to
+ # the old file, the test file must be a difftype from the new
+ # file.
+
+ # /difftype/first/first: A removed file has changed type.
+ # This should generate a warning.
+ mkfifo $OLD/difftype/first/first/fifo
+ mkdir $NEW/difftype/first/first/fifo
+
+ # /difftype/first/*: Cannot happen. Since the new file exists
+ # and the dest file is missing, the last test must be 'first'.
+
+ # /difftype/second/*: Cannot happen. The old file exists in
+ # the first test, so it cannot be missing in the second test.
+
+ # /difftype/difftype/equal: A file has changed type, but the
+ # file in the test directory already matches the new file. Do
+ # nothing.
+ echo "foo" > $OLD/difftype/difftype/equal/fifo
+ mkfifo $OLD/difftype/difftype/equal/file
+ for i in $NEW $TEST; do
+ mkfifo $i/difftype/difftype/equal/fifo
+ echo "bar" > $i/difftype/difftype/equal/file
+ done
+
+ # /difftype/difftype/first: Cannot happen. The dest file
+ # exists in the second test.
+
+ # /difftype/difftype/second: Cannot happen. The new file
+ # exists in the first test.
+
+ # /difftype/difftype/difftype: All three files (old, new, and
+ # test) are different types from each other. This should
+ # generate a warning.
+ mkfifo $OLD/difftype/difftype/difftype/one
+ mkdir $NEW/difftype/difftype/difftype/one
+ echo "foo" > $TEST/difftype/difftype/difftype/one
+ mkdir $OLD/difftype/difftype/difftype/two
+ echo "baz" > $NEW/difftype/difftype/difftype/two
+ ln -s "bar" $TEST/difftype/difftype/difftype/two
+
+ # /difftype/difftype/difflinks: A file has changed from a
+ # non-link to a link in both the new and test trees, but the
+ # target of the new and test links differ. This should
+ # generate a new link conflict.
+ mkfifo $OLD/difftype/difftype/difflinks/link
+ ln -s "new" $NEW/difftype/difftype/difflinks/link
+ ln -s "test" $TEST/difftype/difftype/difflinks/link
+
+ # /difftype/difftype/difffile: A file has changed from a
+ # non-regular file to a regular file in both the new and test
+ # trees, but the contents in the new and test files differ.
+ # This should generate a new file conflict.
+ ln -s "old" $OLD/difftype/difftype/difffiles/file
+ echo "foo" > $NEW/difftype/difftype/difffiles/file
+ echo "bar" > $TEST/difftype/difftype/difffiles/file
+
+ # /difflinks/equal/difflinks: An unmodified symlink has
+ # changed. The link should be updated.
+ for i in $OLD $TEST; do
+ ln -s "old" $i/difflinks/equal/difflinks/link
+ done
+ ln -s "new" $NEW/difflinks/equal/difflinks/link
+
+ # /difflinks/equal/*: Cannot happen. Since old is identical
+ # to test, the third test must be 'difflinks'.
+
+ # /difflinks/first/first: A modified link is missing in the
+ # test tree. This should generate a warning.
+ ln -s "old" $OLD/difflinks/first/first/link
+ ln -s "new" $NEW/difflinks/first/first/link
+
+ # /difflinks/first/*: Cannot happen. Since the test file is
+ # missing in the second test, it must be missing in the third
+ # test.
+
+ # /difflinks/second/*: Cannot happen. The old link is present
+ # in the first test, so it cannot be missing in the second
+ # test.
+
+ # /difflinks/difftype/difftype: An updated link has been
+ # changed to a different file type in the test tree. This
+ # should generate a warning.
+ ln -s "old" $OLD/difflinks/difftype/difftype/link
+ ln -s "new" $NEW/difflinks/difftype/difftype/link
+ echo "test" > $TEST/difflinks/difftype/difftype/link
+
+ # /difflinks/difftype/*: Cannot happen. The old and new files
+ # are both links and the test file is not a link, so the third
+ # test must be 'difftype'.
+
+ # /difflinks/difflinks/equal: An updated link has already been
+ # updated to the new target in the test tree. Nothing should
+ # happen.
+ ln -s "old" $OLD/difflinks/difflinks/equal/link
+ for i in $NEW $TEST; do
+ ln -s "new" $i/difflinks/difflinks/equal/link
+ done
+
+ # /difflinks/difflinks/difflinks: An updated link has been
+ # modified in the test tree and doesn't match either the old
+ # or new links. This should generate a warning.
+ ln -s "old" $OLD/difflinks/difflinks/difflinks/link
+ ln -s "new" $NEW/difflinks/difflinks/difflinks/link
+ ln -s "test" $TEST/difflinks/difflinks/difflinks/link
+
+ # /difflinks/difflinks/*: Cannot happen. All three files are
+ # links from the first two tests, so the third test can only
+ # be 'equal' or 'difflink'.
+
+ # /difflinks/difffiles/*: Cannot happen. The old file is a
+ # link in the first test, so it cannot be a regular file in
+ # the second.
+
+ # /difffiles/equal/difffiles: An unmodified file has been
+ # changed in new tree. The file should be updated to the new
+ # version.
+ for i in $OLD $TEST; do
+ echo "foo" > $i/difffiles/equal/difffiles/file
+ done
+ echo "bar" > $NEW/difffiles/equal/difffiles/file
+
+ # /difffiles/equal/*: Cannot happen. Since the old file is
+ # identical to the test file, the third test must be
+ # 'difffiles'.
+
+ # /difffiles/first/first: A removed file has been changed in
+ # the new tree. This should generate a warning.
+ echo "foo" > $OLD/difffiles/first/first/file
+ echo "bar" > $NEW/difffiles/first/first/file
+
+ # /difffiles/first/*: Cannot happen. The new file is a
+ # regular file from the first test and the test file is
+ # missing in the second test, so the third test must be
+ # 'first'.
+
+ # /difffiles/second/*: Cannot happen. The old file is present
+ # in the first test, so it must be present in the second test.
+
+ # /difffiles/difftype/difftype: An updated regular file has
+ # been changed to a different file type in the test tree.
+ # This should generate a warning.
+ echo "old" > $OLD/difffiles/difftype/difftype/file
+ echo "new" > $NEW/difffiles/difftype/difftype/file
+ mkfifo $TEST/difffiles/difftype/difftype/file
+
+ # /difffiles/difftype/*: Cannot happen. The new file is known
+ # to be a regular file from the first test, and the test file
+ # is known to exist as a different file type from the second
+ # test. The third test must be 'difftype'.
+
+ # /difffiles/difflink/*: Cannot happen. The old file is known
+ # to be a regular file from the first test, so it cannot be a
+ # link in the second test.
+
+ # /difffiles/difffiles/equal: An updated regular file has
+ # already been updated to match the new file in the test tree.
+ # Nothing should happen.
+ echo "foo" > $OLD/difffiles/difffiles/equal/file
+ for i in $NEW $TEST; do
+ echo "bar" > $i/difffiles/difffiles/equal/file
+ done
+
+ # /difffiles/difffiles/difffiles: A modified regular file was
+ # updated in the new tree. The changes should be merged into
+ # to the new file if possible. If the merge fails, a conflict
+ # should be generated.
+ cat > $OLD/difffiles/difffiles/difffiles/simple <<EOF
+this is an old line
+
+EOF
+ cat > $NEW/difffiles/difffiles/difffiles/simple <<EOF
+this is a new line
+
+EOF
+ cat > $TEST/difffiles/difffiles/difffiles/simple <<EOF
+this is an old line
+
+this is a local line
+EOF
+ cat > $OLD/difffiles/difffiles/difffiles/conflict <<EOF
+this is an old file
+EOF
+ cat > $NEW/difffiles/difffiles/difffiles/conflict <<EOF
+this is a new file
+EOF
+ cat > $TEST/difffiles/difffiles/difffiles/conflict <<EOF
+this is a test file
+EOF
+
+ # /difffiles/difffiles/*: Cannot happen. From the first three
+ # tests, all three files are regular files. The test file can
+ # either be identical to the new file ('equal') or not
+ # ('difffiles').
+
+ ## Tests for adding directories
+ mkdir -p $OLD/adddir $NEW/adddir $TEST/adddir
+
+ # /adddir/conflict: Add a new file in a directory that already
+ # exists as a file. This should generate two warnings.
+ mkdir $NEW/adddir/conflict
+ touch $NEW/adddir/conflict/newfile
+ touch $TEST/adddir/conflict
+
+ # /adddir/partial: Add a new file in a directory. The
+ # directory already exists in the test tree and contains a
+ # different local file. The new file from the new tree should
+ # be added.
+ for i in $NEW $TEST; do
+ mkdir $i/adddir/partial
+ done
+ echo "foo" > $NEW/adddir/partial/file
+ mkfifo $TEST/adddir/partial/fifo
+
+ ## Tests for removing directories
+ mkdir -p $OLD/rmdir $NEW/rmdir $TEST/rmdir
+
+ # /rmdir/extra: Do not remove a directory with an extra local file.
+ # This should generate a warning.
+ for i in $OLD $TEST; do
+ mkdir $i/rmdir/extra
+ done
+ echo "foo" > $TEST/rmdir/extra/localfile.txt
+
+ # /rmdir/conflict: Do not remove a directory with a conflicted
+ # remove file. This should generate a warning.
+ for i in $OLD $TEST; do
+ mkdir $i/rmdir/conflict
+ done
+ mkfifo $OLD/rmdir/conflict/difftype
+ mkdir $TEST/rmdir/conflict/difftype
+
+ # /rmdir/partial: Remove a complete hierarchy when part of the
+ # tree has already been removed locally.
+ for i in $OLD $TEST; do
+ mkdir -p $i/rmdir/partial/subdir
+ mkfifo $i/rmdir/partial/subdir/fifo
+ done
+ echo "foo" > $OLD/rmdir/partial/subdir/file
+
+ ## Tests for converting files to directories and vice versa
+ for i in $OLD $NEW $TEST; do
+ for j in already old fromdir todir; do
+ mkdir -p $i/dirchange/$j
+ done
+ done
+
+ # /dirchange/already/fromdir: Convert a directory tree to a
+ # file without conflicts where the test tree already has the
+ # new file. Nothing should happen.
+ mkdir $OLD/dirchange/already/fromdir
+ echo "blah" > $OLD/dirchange/already/fromdir/somefile
+ for i in $NEW $TEST; do
+ echo "bar" > $i/dirchange/already/fromdir
+ done
+
+ # /dirchange/already/todir: Convert an unmodified file to a
+ # directory tree where the test tree already has the new
+ # tree. Nothing should happen.
+ echo "baz" > $OLD/dirchange/already/todir
+ for i in $NEW $TEST; do
+ mkdir $i/dirchange/already/todir
+ echo "blah" > $i/dirchange/already/todir/somefile
+ done
+
+ # /dirchange/old/fromdir: Convert a directory tree to a file.
+ # The old files are unmodified and should be changed to the new tree.
+ for i in $OLD $TEST; do
+ mkdir $i/dirchange/old/fromdir
+ echo "blah" > $i/dirchange/old/fromdir/somefile
+ done
+ echo "bar" > $NEW/dirchange/old/fromdir
+
+ # /dirchange/old/todir: Convert a file to a directory tree.
+ # The old file is unmodified and should be changed to the new
+ # tree.
+ for i in $OLD $TEST; do
+ echo "foo" > $i/dirchange/old/todir
+ done
+ mkdir $NEW/dirchange/old/todir
+ echo "bar" > $NEW/dirchange/old/todir/file
+
+ # /dirchange/fromdir/extradir: Convert a directory tree to a
+ # file. The test tree includes an extra file in the directory
+ # that is not present in the old tree. This should generate a
+ # warning.
+ for i in $OLD $TEST; do
+ mkdir $i/dirchange/fromdir/extradir
+ echo "foo" > $i/dirchange/fromdir/extradir/file
+ done
+ mkfifo $TEST/dirchange/fromdir/extradir/fifo
+ ln -s "bar" $NEW/dirchange/fromdir/extradir
+
+ # /dirchange/fromdir/conflict: Convert a directory tree to a
+ # file. The test tree includes a local change that generates
+ # a warning and prevents the removal of the directory.
+ for i in $OLD $TEST; do
+ mkdir $i/dirchange/fromdir/conflict
+ done
+ echo "foo" > $OLD/dirchange/fromdir/conflict/somefile
+ echo "bar" > $TEST/dirchange/fromdir/conflict/somefile
+ mkfifo $NEW/dirchange/fromdir/conflict
+
+ # /dirchange/todir/difffile: Convert a file to a directory
+ # tree. The test tree has a locally modified version of the
+ # file so that the conversion fails with a warning.
+ echo "foo" > $OLD/dirchange/todir/difffile
+ mkdir $NEW/dirchange/todir/difffile
+ echo "baz" > $NEW/dirchange/todir/difffile/file
+ echo "bar" > $TEST/dirchange/todir/difffile
+
+ # /dirchange/todir/difftype: Similar to the previous test, but
+ # the conflict is due to a change in the file type.
+ echo "foo" > $OLD/dirchange/todir/difftype
+ mkdir $NEW/dirchange/todir/difftype
+ echo "baz" > $NEW/dirchange/todir/difftype/file
+ mkfifo $TEST/dirchange/todir/difftype
+
+ ## Tests for post-install actions
+
+ # - Adding /etc/master.passwd should cause pwd_mkdb to be run
+ echo "foo:*:16000:100::0:0:& user:/home/foo:/bin/tcsh" > \
+ $NEW/etc/master.passwd
+
+ # - Verify that updating an unmodified /etc/login.conf builds
+ # /etc/login.conf.db.
+ cat > $OLD/etc/login.conf <<EOF
+default:\\
+ :passwd_format=md5:
+EOF
+ cat > $NEW/etc/login.conf <<EOF
+default:\\
+ :passwd_format=md5:\\
+ :copyright=/etc/COPYRIGHT
+EOF
+ cp $OLD/etc/login.conf $TEST/etc/login.conf
+
+ # - Verify that a merge without conflicts to /etc/mail/aliases
+ # will trigger a newaliases run request.
+ mkdir -p $OLD/etc/mail $NEW/etc/mail $TEST/etc/mail
+ cat > $OLD/etc/mail/aliases <<EOF
+# root: me@my.domain
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: root
+EOF
+ cat > $NEW/etc/mail/aliases <<EOF
+# root: me@my.domain
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: root
+
+# General redirections for pseudo accounts
+_dhcp: root
+_pflogd: root
+EOF
+ cat > $TEST/etc/mail/aliases <<EOF
+root: someone@example.com
+
+# Basic system aliases -- these MUST be present
+MAILER-DAEMON: postmaster
+postmaster: root
+EOF
+
+ # - Verify that updating an unmodified /etc/services builds
+ # /var/db/services.db.
+ cat > $OLD/etc/services <<EOF
+rtmp 1/ddp #Routing Table Maintenance Protocol
+tcpmux 1/tcp #TCP Port Service Multiplexer
+tcpmux 1/udp #TCP Port Service Multiplexer
+EOF
+ cat > $NEW/etc/services <<EOF
+rtmp 1/ddp #Routing Table Maintenance Protocol
+tcpmux 1/tcp #TCP Port Service Multiplexer
+tcpmux 1/udp #TCP Port Service Multiplexer
+nbp 2/ddp #Name Binding Protocol
+compressnet 2/tcp #Management Utility
+compressnet 2/udp #Management Utility
+EOF
+ cp $OLD/etc/services $TEST/etc/services
+ mkdir -p $TEST/var/db
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be present in TEST
+present()
+{
+ if ! [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be present"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a fifo in TEST
+fifo()
+{
+ if ! [ -p $TEST/$1 ]; then
+ echo "File $1 should be a FIFO"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a directory in TEST
+dir()
+{
+ if ! [ -d $TEST/$1 ]; then
+ echo "File $1 should be a directory"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a symlink in TEST
+# $2 - optional value of the link
+link()
+{
+ local val
+
+ if ! [ -L $TEST/$1 ]; then
+ echo "File $1 should be a link"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ val=`readlink $TEST/$1`
+ if [ "$val" != "$2" ]; then
+ echo "Link $1 should link to \"$2\""
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to a regular file that should have a conflict
+# $2 - optional MD5 of the conflict file contents
+conflict()
+{
+ local sum
+
+ if ! [ -f $CONFLICTS/$1 ]; then
+ echo "File $1 missing conflict"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ sum=`md5 -q $CONFLICTS/$1`
+ if [ "$sum" != "$2" ]; then
+ echo "Conflict $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+check_trees()
+{
+
+ echo "Checking tree for correct results:"
+
+ ## /equal/equal/equal:
+ fifo /equal/equal/equal/fifo
+ file /equal/equal/equal/file "foo"
+ dir /equal/equal/equal/dir
+ link /equal/equal/equal/link "bar"
+
+ ## /equal/first/first:
+ missing /equal/first/first/fifo
+ missing /equal/first/first/file
+ missing /equal/first/first/dir
+ missing /equal/first/first/link
+
+ ## /equal/difftype/difftype:
+ file /equal/difftype/difftype/fifo "bar"
+ link /equal/difftype/difftype/fromdir "test"
+
+ ## /equal/difflinks/difflinks:
+ link /equal/difflinks/difflinks/link "bar"
+
+ ## /equal/difffiles/difffiles:
+ file /equal/difffiles/difffiles/file "bar"
+
+ ## /first/equal/second:
+ missing /first/equal/second/fifo
+ missing /first/equal/second/file
+ missing /first/equal/second/emptydir
+ missing /first/equal/second/link
+ missing /first/equal/second/fulldir
+
+ ## /first/first/equal:
+ missing /first/first/equal/fifo
+ missing /first/first/equal/file
+ missing /first/first/equal/dir
+ missing /first/first/equal/link
+
+ ## /first/difftype/second:
+ present /first/difftype/second/fifo
+
+ ## /first/difflinks/second:
+ link /first/difflinks/second/link "test link"
+
+ ## /first/difffiles/second:
+ file /first/difffiles/second/file "bar"
+
+ ## /second/equal/first:
+ file /second/equal/first/file "bar"
+ fifo /second/equal/first/fifo
+ link /second/equal/first/link "new"
+ missing /second/equal/first/emptydir
+ file /second/equal/first/fulldir/file "foo"
+
+ ## /second/second/equal:
+ fifo /second/second/equal/fifo
+ file /second/second/equal/file "foo"
+ dir /second/second/equal/dir
+ link /second/second/equal/link "bar"
+
+ ## /second/second/difftype:
+ fifo /second/second/difftype/dir
+
+ ## /second/second/difflinks:
+ link /second/second/difflinks/link "test link"
+
+ ## /second/second/difffiles:
+ file /second/second/difffiles/file "test"
+ conflict /second/second/difffiles/file 4f2ee8620a251fd53f06bb6112eb6ffa
+
+ ## /difftype/equal/difftype:
+ link /difftype/equal/difftype/file "test"
+ fifo /difftype/equal/difftype/fromdir
+ missing /difftype/equal/difftype/todir
+
+ ## /difftype/first/first:
+ missing /difftype/first/first/fifo
+
+ ## /difftype/difftype/equal:
+ fifo /difftype/difftype/equal/fifo
+ file /difftype/difftype/equal/file "bar"
+
+ ## /difftype/difftype/difftype:
+ file /difftype/difftype/difftype/one "foo"
+ link /difftype/difftype/difftype/two "bar"
+
+ ## /difftype/difftype/difflinks:
+ link /difftype/difftype/difflinks/link "test"
+
+ ## /difftype/difftype/difffile:
+ conflict /difftype/difftype/difffiles/file \
+ 117f2bcd1f6491f6044e79e5a57a9229
+
+ ## /difflinks/equal/difflinks:
+ link /difflinks/equal/difflinks/link "new"
+
+ ## /difflinks/first/first:
+ missing /difflinks/first/first/link
+
+ ## /difflinks/difftype/difftype:
+ file /difflinks/difftype/difftype/link "test"
+
+ ## /difflinks/difflinks/equal:
+ link /difflinks/difflinks/equal/link "new"
+
+ ## /difflinks/difflinks/difflinks:
+ link /difflinks/difflinks/difflinks/link "test"
+
+ ## /difffiles/equal/difffiles:
+ file /difffiles/equal/difffiles/file "bar"
+
+ ## /difffiles/first/first:
+ missing /difffiles/first/first/file
+
+ ## /difffiles/difftype/difftype:
+ fifo /difffiles/difftype/difftype/file
+
+ ## /difffiles/difffiles/equal:
+ file /difffiles/difffiles/equal/file "bar"
+
+ ## /difffiles/difffiles/difffiles:
+ file /difffiles/difffiles/difffiles/simple "" \
+ cabc7e5e80b0946d79edd555e9648486
+ file /difffiles/difffiles/difffiles/conflict "this is a test file"
+ conflict /difffiles/difffiles/difffiles/conflict \
+ 8261cfdd89280c4a6c26e4ac86541fe9
+
+ ## /adddir/conflict:
+ file /adddir/conflict
+
+ ## /adddir/partial:
+ file /adddir/partial/file "foo"
+ fifo /adddir/partial/fifo
+
+ ## /rmdir/extra:
+ dir /rmdir/extra
+ file /rmdir/extra/localfile.txt "foo"
+
+ ## /rmdir/conflict:
+ dir /rmdir/conflict/difftype
+ present /rmdir/conflict
+
+ ## /rmdir/partial:
+ missing /rmdir/partial
+
+ ## /dirchange/already/fromdir:
+ file /dirchange/already/fromdir "bar"
+
+ ## /dirchange/already/todir:
+ file /dirchange/already/todir/somefile "blah"
+
+ ## /dirchange/old/fromdir:
+ file /dirchange/old/fromdir "bar"
+
+ ## /dirchange/old/todir
+ file /dirchange/old/todir/file "bar"
+
+ ## /dirchange/fromdir/extradir:
+ missing /dirchange/fromdir/extradir/file
+ fifo /dirchange/fromdir/extradir/fifo
+
+ ## /dirchange/fromdir/conflict:
+ file /dirchange/fromdir/conflict/somefile "bar"
+
+ ## /dirchange/todir/difffile:
+ file /dirchange/todir/difffile "bar"
+
+ ## /dirchange/todir/difftype:
+ fifo /dirchange/todir/difftype
+
+ ## Tests for post-install actions
+ file /etc/master.passwd
+ file /etc/passwd
+ file /etc/pwd.db
+ file /etc/spwd.db
+ file /etc/login.conf "" 7774a0f9a3a372c7c109c32fd31c4b6b
+ file /etc/login.conf.db
+ file /etc/mail/aliases "" 7d598f89ec040ab56af54011bdb83337
+ file /etc/services "" 37fb6a8d1273f3b78329d431f21d9c7d
+ file /var/db/services.db
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+build_trees
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+ D /dirchange/fromdir/extradir/file
+ D /dirchange/old/fromdir/somefile
+ D /first/equal/second/fifo
+ D /first/equal/second/file
+ D /first/equal/second/fulldir/file
+ D /first/equal/second/link
+ D /rmdir/partial/subdir/fifo
+ D /rmdir/partial/subdir
+ D /rmdir/partial
+ D /first/equal/second/fulldir
+ D /first/equal/second/emptydir
+ C /difffiles/difffiles/difffiles/conflict
+ M /difffiles/difffiles/difffiles/simple
+ U /difffiles/equal/difffiles/file
+ U /difflinks/equal/difflinks/link
+ C /difftype/difftype/difffiles/file
+ U /difftype/equal/difftype/file
+ U /difftype/equal/difftype/fromdir
+ D /difftype/equal/difftype/todir
+ U /dirchange/old/fromdir
+ U /dirchange/old/todir
+ U /etc/login.conf
+ M /etc/mail/aliases
+ U /etc/services
+ A /adddir/partial/file
+ A /dirchange/old/todir/file
+ A /etc/master.passwd
+ A /second/equal/first/fifo
+ A /second/equal/first/file
+ A /second/equal/first/fulldir/file
+ A /second/equal/first/link
+ C /second/second/difffiles/file
+Warnings:
+ Modified regular file remains: /dirchange/fromdir/conflict/somefile
+ Modified regular file remains: /first/difffiles/second/file
+ Modified symbolic link remains: /first/difflinks/second/link
+ Modified directory remains: /first/difftype/second/fifo
+ Modified directory remains: /rmdir/conflict/difftype
+ Non-empty directory remains: /rmdir/extra
+ Non-empty directory remains: /rmdir/conflict
+ Modified mismatch: /difffiles/difftype/difftype/file (regular file vs fifo file)
+ Removed file changed: /difffiles/first/first/file
+ Modified link changed: /difflinks/difflinks/difflinks/link ("old" became "new")
+ Modified mismatch: /difflinks/difftype/difftype/link (symbolic link vs regular file)
+ Removed link changed: /difflinks/first/first/link ("old" became "new")
+ New link conflict: /difftype/difftype/difflinks/link ("new" vs "test")
+ Modified regular file changed: /difftype/difftype/difftype/one (fifo file became directory)
+ Modified symbolic link changed: /difftype/difftype/difftype/two (directory became regular file)
+ Remove mismatch: /difftype/first/first/fifo (fifo file became directory)
+ Modified directory changed: /dirchange/fromdir/conflict (directory became fifo file)
+ Modified directory changed: /dirchange/fromdir/extradir (directory became symbolic link)
+ Modified regular file changed: /dirchange/todir/difffile (regular file became directory)
+ Modified fifo file changed: /dirchange/todir/difftype (regular file became directory)
+ New file mismatch: /adddir/conflict (directory vs regular file)
+ Directory mismatch: $TEST/adddir/conflict (regular file)
+ Directory mismatch: $TEST/dirchange/todir/difffile (regular file)
+ Directory mismatch: $TEST/dirchange/todir/difftype (fifo file)
+ New link conflict: /second/second/difflinks/link ("new link" vs "test link")
+ New file mismatch: /second/second/difftype/dir (directory vs fifo file)
+ Needs update: /etc/mail/aliases.db (requires manual update via newaliases(1))
+EOF
+
+echo "Differences for -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
+ || failed=YES
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for real:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || failed=YES
+
+check_trees
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/etcupdate/tests/tzsetup_test.sh b/usr.sbin/etcupdate/tests/tzsetup_test.sh
new file mode 100644
index 0000000..b102938
--- /dev/null
+++ b/usr.sbin/etcupdate/tests/tzsetup_test.sh
@@ -0,0 +1,239 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb@FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests for the tzsetup handling in the 'update' command.
+
+FAILED=no
+WORKDIR=work
+
+usage()
+{
+ echo "Usage: tzsetup.sh [-s script] [-w workdir]"
+ exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+ case $option in
+ s)
+ COMMAND="sh $OPTARG"
+ ;;
+ w)
+ WORKDIR=$OPTARG
+ ;;
+ *)
+ echo
+ usage
+ ;;
+ esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+ usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+build_trees()
+{
+
+ # Build the base tree, but not /etc/localtime itself
+ local i j k
+
+ rm -rf $OLD $NEW $TEST $CONFLICTS
+ mkdir -p $OLD $NEW $TEST
+ mkdir -p $TEST/etc
+ mkdir -p $TEST/var/db
+ mkdir -p $TEST/usr/share/zoneinfo
+
+ # Create a dummy timezone file
+ echo "foo" > $TEST/usr/share/zoneinfo/foo
+
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+ if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+ echo "File $1 should be missing"
+ FAILED=yes
+ fi
+}
+
+# $1 - relative path to file that should be a symlink in TEST
+# $2 - optional value of the link
+link()
+{
+ local val
+
+ if ! [ -L $TEST/$1 ]; then
+ echo "File $1 should be a link"
+ FAILED=yes
+ elif [ $# -gt 1 ]; then
+ val=`readlink $TEST/$1`
+ if [ "$val" != "$2" ]; then
+ echo "Link $1 should link to \"$2\""
+ FAILED=yes
+ fi
+ fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+ local contents sum
+
+ if ! [ -f $TEST/$1 ]; then
+ echo "File $1 should be a regular file"
+ FAILED=yes
+ elif [ $# -eq 2 ]; then
+ contents=`cat $TEST/$1`
+ if [ "$contents" != "$2" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ elif [ $# -eq 3 ]; then
+ sum=`md5 -q $TEST/$1`
+ if [ "$sum" != "$3" ]; then
+ echo "File $1 has wrong contents"
+ FAILED=yes
+ fi
+ fi
+}
+
+if [ `id -u` -ne 0 ]; then
+ echo "must be root"
+ exit 0
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+ echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+# First, test for /etc/localtime not existing
+
+build_trees
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+EOF
+
+echo "Differences for no /etc/localtime with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
+ || FAILED=yes
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for no /etc/localtime:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+missing /etc/localtime
+missing /var/db/zoneinfo
+
+# Second, test for /etc/localtime being a symlink
+
+build_trees
+ln -s /dev/null $TEST/etc/localtime
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+EOF
+
+echo "Differences for symlinked /etc/localtime with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
+ || FAILED=yes
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for symlinked /etc/localtime:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+link /etc/localtime "/dev/null"
+missing /var/db/zoneinfo
+
+# Third, test for /etc/localtime as a file and a missing /var/db/zoneinfo
+
+build_trees
+echo "bar" > $TEST/etc/localtime
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+Warnings:
+ Needs update: /etc/localtime (required manual update via tzsetup(1))
+EOF
+
+echo "Differences for missing /var/db/zoneinfo with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
+ || FAILED=yes
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for missing /var/db/zoneinfo:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+file /etc/localtime "bar"
+missing /var/db/zoneinfo
+
+# Finally, test the case where it should update /etc/localtime
+
+build_trees
+echo "bar" > $TEST/etc/localtime
+echo "foo" > $TEST/var/db/zoneinfo
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+EOF
+
+echo "Differences for real update with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out \
+ || FAILED=yes
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for real update:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out \
+ || FAILED=yes
+
+file /etc/localtime "foo"
+file /var/db/zoneinfo "foo"
+
+[ "${FAILED}" = no ]
diff --git a/usr.sbin/fifolog/fifolog_reader/Makefile b/usr.sbin/fifolog/fifolog_reader/Makefile
index 7dcc8c2..c88f10e 100644
--- a/usr.sbin/fifolog/fifolog_reader/Makefile
+++ b/usr.sbin/fifolog/fifolog_reader/Makefile
@@ -4,7 +4,7 @@ PROG= fifolog_reader
CFLAGS+= -I${.CURDIR}/../lib
-NO_MAN= # see ../fifolog_create/fifolog.1
+MAN=
DPADD= ${LIBFIFOLOG} ${LIBUTIL} ${LIBZ}
LDADD= ${LIBFIFOLOG} -lutil -lz
diff --git a/usr.sbin/fifolog/fifolog_writer/Makefile b/usr.sbin/fifolog/fifolog_writer/Makefile
index b6ceb63..9d802c7 100644
--- a/usr.sbin/fifolog/fifolog_writer/Makefile
+++ b/usr.sbin/fifolog/fifolog_writer/Makefile
@@ -4,7 +4,7 @@ PROG= fifolog_writer
CFLAGS+= -I${.CURDIR}/../lib
-NO_MAN= # see ../fifolog_create/fifolog.1
+MAN=
DPADD= ${LIBFIFOLOG} ${LIBUTIL} ${LIBZ}
LDADD= ${LIBFIFOLOG} -lutil -lz
diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh
index ea4099a..ee702e3 100644
--- a/usr.sbin/freebsd-update/freebsd-update.sh
+++ b/usr.sbin/freebsd-update/freebsd-update.sh
@@ -1200,7 +1200,7 @@ fetch_metadata_sanity () {
# Some aliases to save space later: ${P} is a character which can
# appear in a path; ${M} is the four numeric metadata fields; and
# ${H} is a sha256 hash.
- P="[-+./:=%@_[[:alnum:]]"
+ P="[-+./:=%@_[~[:alnum:]]"
M="[0-9]+\|[0-9]+\|[0-9]+\|[0-9]+"
H="[0-9a-f]{64}"
@@ -2814,16 +2814,24 @@ Kernel updates have been installed. Please reboot and run
# If we haven't already dealt with the world, deal with it.
if ! [ -f $1/worlddone ]; then
+ # Create any necessary directories first
+ grep -vE '^/boot/' $1/INDEX-NEW |
+ grep -E '^[^|]+\|d\|' > INDEX-NEW
+ install_from_index INDEX-NEW || return 1
+
# Install new shared libraries next
grep -vE '^/boot/' $1/INDEX-NEW |
- grep -E '/lib/.*\.so\.[0-9]+\|' > INDEX-NEW
+ grep -vE '^[^|]+\|d\|' |
+ grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
install_from_index INDEX-NEW || return 1
# Deal with everything else
grep -vE '^/boot/' $1/INDEX-OLD |
- grep -vE '/lib/.*\.so\.[0-9]+\|' > INDEX-OLD
+ grep -vE '^[^|]+\|d\|' |
+ grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-OLD
grep -vE '^/boot/' $1/INDEX-NEW |
- grep -vE '/lib/.*\.so\.[0-9]+\|' > INDEX-NEW
+ grep -vE '^[^|]+\|d\|' |
+ grep -vE '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
install_from_index INDEX-NEW || return 1
install_delete INDEX-OLD INDEX-NEW || return 1
@@ -2844,11 +2852,11 @@ Kernel updates have been installed. Please reboot and run
# Do we need to ask the user to portupgrade now?
grep -vE '^/boot/' $1/INDEX-NEW |
- grep -E '/lib/.*\.so\.[0-9]+\|' |
+ grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' |
cut -f 1 -d '|' |
sort > newfiles
if grep -vE '^/boot/' $1/INDEX-OLD |
- grep -E '/lib/.*\.so\.[0-9]+\|' |
+ grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' |
cut -f 1 -d '|' |
sort |
join -v 1 - newfiles |
@@ -2868,9 +2876,18 @@ again to finish installing updates.
# Remove old shared libraries
grep -vE '^/boot/' $1/INDEX-NEW |
- grep -E '/lib/.*\.so\.[0-9]+\|' > INDEX-NEW
+ grep -vE '^[^|]+\|d\|' |
+ grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-NEW
grep -vE '^/boot/' $1/INDEX-OLD |
- grep -E '/lib/.*\.so\.[0-9]+\|' > INDEX-OLD
+ grep -vE '^[^|]+\|d\|' |
+ grep -E '^[^|]*/lib/[^|]*\.so\.[0-9]+\|' > INDEX-OLD
+ install_delete INDEX-OLD INDEX-NEW || return 1
+
+ # Remove old directories
+ grep -vE '^/boot/' $1/INDEX-NEW |
+ grep -E '^[^|]+\|d\|' > INDEX-NEW
+ grep -vE '^/boot/' $1/INDEX-OLD |
+ grep -E '^[^|]+\|d\|' > INDEX-OLD
install_delete INDEX-OLD INDEX-NEW || return 1
# Remove temporary files
@@ -3033,21 +3050,8 @@ IDS_compare () {
mv INDEX-NOTMATCHING.tmp INDEX-NOTMATCHING
# Go through the lines and print warnings.
- while read LINE; do
- FPATH=`echo "${LINE}" | cut -f 1 -d '|'`
- TYPE=`echo "${LINE}" | cut -f 2 -d '|'`
- OWNER=`echo "${LINE}" | cut -f 3 -d '|'`
- GROUP=`echo "${LINE}" | cut -f 4 -d '|'`
- PERM=`echo "${LINE}" | cut -f 5 -d '|'`
- HASH=`echo "${LINE}" | cut -f 6 -d '|'`
- LINK=`echo "${LINE}" | cut -f 7 -d '|'`
- P_TYPE=`echo "${LINE}" | cut -f 8 -d '|'`
- P_OWNER=`echo "${LINE}" | cut -f 9 -d '|'`
- P_GROUP=`echo "${LINE}" | cut -f 10 -d '|'`
- P_PERM=`echo "${LINE}" | cut -f 11 -d '|'`
- P_HASH=`echo "${LINE}" | cut -f 12 -d '|'`
- P_LINK=`echo "${LINE}" | cut -f 13 -d '|'`
-
+ local IFS='|'
+ while read FPATH TYPE OWNER GROUP PERM HASH LINK P_TYPE P_OWNER P_GROUP P_PERM P_HASH P_LINK; do
# Warn about different object types.
if ! [ "${TYPE}" = "${P_TYPE}" ]; then
echo -n "${FPATH} is a "
diff --git a/usr.sbin/gpioctl/gpioctl.8 b/usr.sbin/gpioctl/gpioctl.8
index c1abb5e..4db6714 100644
--- a/usr.sbin/gpioctl/gpioctl.8
+++ b/usr.sbin/gpioctl/gpioctl.8
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 13, 2013
+.Dd November 7, 2013
.Dt GPIOCTL 1
.Os
.Sh NAME
@@ -109,6 +109,8 @@ gpioctl -f /dev/gpioc0 -c 12 IN
.El
.Sh SEE ALSO
.Xr gpio 4
+.Xr gpioiic 4
+.Xr gpioled 4
.Sh HISTORY
The
.Nm
diff --git a/usr.sbin/ifmcstat/ifmcstat.8 b/usr.sbin/ifmcstat/ifmcstat.8
index 015184a..70b9791 100644
--- a/usr.sbin/ifmcstat/ifmcstat.8
+++ b/usr.sbin/ifmcstat/ifmcstat.8
@@ -54,7 +54,6 @@ The following options are supported:
.Bl -tag -width Fl
.It Fl i Ar interface
specifies the interface to be displayed.
-.Pp
.It Fl f Ar address-family
specifies the address family to be displayed;
.Ar inet ,
diff --git a/usr.sbin/ifmcstat/ifmcstat.c b/usr.sbin/ifmcstat/ifmcstat.c
index 599e850..9f51877 100644
--- a/usr.sbin/ifmcstat/ifmcstat.c
+++ b/usr.sbin/ifmcstat/ifmcstat.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/tree.h>
#include <net/if.h>
+#define _WANT_IFADDR
#include <net/if_var.h>
#include <net/if_types.h>
#include <net/if_dl.h>
@@ -115,9 +116,6 @@ int Kflag = 0;
#endif
int vflag = 0;
-#define sa_equal(a1, a2) \
- (bcmp((a1), (a2), ((a1))->sa_len) == 0)
-
#define sa_dl_equal(a1, a2) \
((((struct sockaddr_dl *)(a1))->sdl_len == \
((struct sockaddr_dl *)(a2))->sdl_len) && \
diff --git a/usr.sbin/iostat/iostat.c b/usr.sbin/iostat/iostat.c
index 92b98e4..f566f39 100644
--- a/usr.sbin/iostat/iostat.c
+++ b/usr.sbin/iostat/iostat.c
@@ -117,10 +117,10 @@
#include <unistd.h>
struct nlist namelist[] = {
-#define X_TK_NIN 0
- { "_tk_nin" },
-#define X_TK_NOUT 1
- { "_tk_nout" },
+#define X_TTY_NIN 0
+ { "_tty_nin" },
+#define X_TTY_NOUT 1
+ { "_tty_nout" },
#define X_BOOTTIME 2
{ "_boottime" },
#define X_END 2
@@ -448,9 +448,9 @@ main(int argc, char **argv)
long double etime;
if (Tflag > 0) {
- if ((readvar(kd, "kern.tty_nin", X_TK_NIN, &cur.tk_nin,
+ if ((readvar(kd, "kern.tty_nin", X_TTY_NIN, &cur.tk_nin,
sizeof(cur.tk_nin)) != 0)
- || (readvar(kd, "kern.tty_nout", X_TK_NOUT,
+ || (readvar(kd, "kern.tty_nout", X_TTY_NOUT,
&cur.tk_nout, sizeof(cur.tk_nout))!= 0)) {
Tflag = 0;
warnx("disabling TTY statistics");
diff --git a/usr.sbin/iscsid/discovery.c b/usr.sbin/iscsid/discovery.c
index b5731de..9f0db81 100644
--- a/usr.sbin/iscsid/discovery.c
+++ b/usr.sbin/iscsid/discovery.c
@@ -62,8 +62,6 @@ text_receive(struct connection *conn)
*/
if ((bhstr->bhstr_flags & BHSTR_FLAGS_CONTINUE) != 0)
log_errx(1, "received Text PDU with unsupported \"C\" flag");
- if (response->pdu_data_len == 0)
- log_errx(1, "received Text PDU with empty data segment");
if (ntohl(bhstr->bhstr_statsn) != conn->conn_statsn + 1) {
log_errx(1, "received Text PDU with wrong StatSN: "
"is %d, should be %d", ntohl(bhstr->bhstr_statsn),
diff --git a/usr.sbin/iscsid/iscsid.c b/usr.sbin/iscsid/iscsid.c
index c22d7fd..cea996d 100644
--- a/usr.sbin/iscsid/iscsid.c
+++ b/usr.sbin/iscsid/iscsid.c
@@ -35,7 +35,7 @@
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/socket.h>
-#include <sys/capability.h>
+#include <sys/capsicum.h>
#include <sys/wait.h>
#include <assert.h>
#include <errno.h>
@@ -194,30 +194,32 @@ connection_new(unsigned int session_id, const struct iscsi_session_conf *conf,
resolve_addr(conn, to_addr, &to_ai, false);
#ifdef ICL_KERNEL_PROXY
+ if (conn->conn_conf.isc_iser) {
+ memset(&idc, 0, sizeof(idc));
+ idc.idc_session_id = conn->conn_session_id;
+ if (conn->conn_conf.isc_iser)
+ idc.idc_iser = 1;
+ idc.idc_domain = to_ai->ai_family;
+ idc.idc_socktype = to_ai->ai_socktype;
+ idc.idc_protocol = to_ai->ai_protocol;
+ if (from_ai != NULL) {
+ idc.idc_from_addr = from_ai->ai_addr;
+ idc.idc_from_addrlen = from_ai->ai_addrlen;
+ }
+ idc.idc_to_addr = to_ai->ai_addr;
+ idc.idc_to_addrlen = to_ai->ai_addrlen;
- memset(&idc, 0, sizeof(idc));
- idc.idc_session_id = conn->conn_session_id;
- if (conn->conn_conf.isc_iser)
- idc.idc_iser = 1;
- idc.idc_domain = to_ai->ai_family;
- idc.idc_socktype = to_ai->ai_socktype;
- idc.idc_protocol = to_ai->ai_protocol;
- if (from_ai != NULL) {
- idc.idc_from_addr = from_ai->ai_addr;
- idc.idc_from_addrlen = from_ai->ai_addrlen;
- }
- idc.idc_to_addr = to_ai->ai_addr;
- idc.idc_to_addrlen = to_ai->ai_addrlen;
+ log_debugx("connecting to %s using ICL kernel proxy", to_addr);
+ error = ioctl(iscsi_fd, ISCSIDCONNECT, &idc);
+ if (error != 0) {
+ fail(conn, strerror(errno));
+ log_err(1, "failed to connect to %s "
+ "using ICL kernel proxy: ISCSIDCONNECT", to_addr);
+ }
- log_debugx("connecting to %s using ICL kernel proxy", to_addr);
- error = ioctl(iscsi_fd, ISCSIDCONNECT, &idc);
- if (error != 0) {
- fail(conn, strerror(errno));
- log_err(1, "failed to connect to %s using ICL kernel proxy",
- to_addr);
+ return (conn);
}
-
-#else /* !ICL_KERNEL_PROXY */
+#endif /* ICL_KERNEL_PROXY */
if (conn->conn_conf.isc_iser) {
fail(conn, "iSER not supported");
@@ -246,8 +248,6 @@ connection_new(unsigned int session_id, const struct iscsi_session_conf *conf,
log_err(1, "failed to connect to %s", to_addr);
}
-#endif /* !ICL_KERNEL_PROXY */
-
return (conn);
}
@@ -261,9 +261,7 @@ handoff(struct connection *conn)
memset(&idh, 0, sizeof(idh));
idh.idh_session_id = conn->conn_session_id;
-#ifndef ICL_KERNEL_PROXY
idh.idh_socket = conn->conn_socket;
-#endif
strlcpy(idh.idh_target_alias, conn->conn_target_alias,
sizeof(idh.idh_target_alias));
memcpy(idh.idh_isid, conn->conn_isid, sizeof(idh.idh_isid));
@@ -394,6 +392,32 @@ set_timeout(int timeout)
}
static void
+sigchld_handler(int dummy __unused)
+{
+
+ /*
+ * The only purpose of this handler is to make SIGCHLD
+ * interrupt the ISCSIDWAIT ioctl(2), so we can call
+ * wait_for_children().
+ */
+}
+
+static void
+register_sigchld(void)
+{
+ struct sigaction sa;
+ int error;
+
+ bzero(&sa, sizeof(sa));
+ sa.sa_handler = sigchld_handler;
+ sigfillset(&sa.sa_mask);
+ error = sigaction(SIGCHLD, &sa, NULL);
+ if (error != 0)
+ log_err(1, "sigaction");
+
+}
+
+static void
handle_request(int iscsi_fd, const struct iscsi_daemon_request *request, int timeout)
{
struct connection *conn;
@@ -522,6 +546,8 @@ main(int argc, char **argv)
pidfile_write(pidfh);
+ register_sigchld();
+
for (;;) {
log_debugx("waiting for request from the kernel");
diff --git a/usr.sbin/iscsid/iscsid.h b/usr.sbin/iscsid/iscsid.h
index 5af994a..b19542d 100644
--- a/usr.sbin/iscsid/iscsid.h
+++ b/usr.sbin/iscsid/iscsid.h
@@ -46,9 +46,7 @@
struct connection {
int conn_iscsi_fd;
-#ifndef ICL_KERNEL_PROXY
int conn_socket;
-#endif
unsigned int conn_session_id;
struct iscsi_session_conf conn_conf;
char conn_target_alias[ISCSI_ADDR_LEN];
@@ -106,12 +104,12 @@ void log_init(int level);
void log_set_peer_name(const char *name);
void log_set_peer_addr(const char *addr);
void log_err(int, const char *, ...)
- __dead2 __printf0like(2, 3);
+ __dead2 __printflike(2, 3);
void log_errx(int, const char *, ...)
- __dead2 __printf0like(2, 3);
-void log_warn(const char *, ...) __printf0like(1, 2);
+ __dead2 __printflike(2, 3);
+void log_warn(const char *, ...) __printflike(1, 2);
void log_warnx(const char *, ...) __printflike(1, 2);
-void log_debugx(const char *, ...) __printf0like(1, 2);
+void log_debugx(const char *, ...) __printflike(1, 2);
char *checked_strdup(const char *);
bool timed_out(void);
diff --git a/usr.sbin/iscsid/keys.c b/usr.sbin/iscsid/keys.c
index d9055a2..49340e0 100644
--- a/usr.sbin/iscsid/keys.c
+++ b/usr.sbin/iscsid/keys.c
@@ -65,7 +65,7 @@ keys_load(struct keys *keys, const struct pdu *pdu)
size_t pair_len;
if (pdu->pdu_data_len == 0)
- log_errx(1, "protocol error: empty data segment");
+ return;
if (pdu->pdu_data[pdu->pdu_data_len - 1] != '\0')
log_errx(1, "protocol error: key not NULL-terminated\n");
diff --git a/usr.sbin/iscsid/login.c b/usr.sbin/iscsid/login.c
index 2ae36e8..4f53258 100644
--- a/usr.sbin/iscsid/login.c
+++ b/usr.sbin/iscsid/login.c
@@ -189,10 +189,6 @@ login_receive(struct connection *conn, bool initial)
fail(conn, errorstr);
log_errx(1, "target returned error: %s", errorstr);
}
-#if 0
- if (response->pdu_data_len == 0)
- log_errx(1, "received Login PDU with empty data segment");
-#endif
if (initial == false &&
ntohl(bhslr->bhslr_statsn) != conn->conn_statsn + 1) {
/*
@@ -787,7 +783,6 @@ login(struct connection *conn)
request = login_new_request(conn);
bhslr = (struct iscsi_bhs_login_request *)request->pdu_bhs;
- bhslr->bhslr_flags |= BHSLR_FLAGS_TRANSIT;
request_keys = keys_new();
if (conn->conn_conf.isc_mutual_user[0] != '\0') {
diff --git a/usr.sbin/iscsid/pdu.c b/usr.sbin/iscsid/pdu.c
index 24b63d7..6b5630e 100644
--- a/usr.sbin/iscsid/pdu.c
+++ b/usr.sbin/iscsid/pdu.c
@@ -101,13 +101,15 @@ pdu_new_response(struct pdu *request)
#ifdef ICL_KERNEL_PROXY
-void
-pdu_receive(struct pdu *pdu)
+static void
+pdu_receive_proxy(struct pdu *pdu)
{
struct iscsi_daemon_receive *idr;
size_t len;
int error;
+ assert(pdu->pdu_connection->conn_conf.isc_iser != 0);
+
pdu->pdu_data = malloc(ISCSI_MAX_DATA_SEGMENT_LENGTH);
if (pdu->pdu_data == NULL)
log_err(1, "malloc");
@@ -136,12 +138,14 @@ pdu_receive(struct pdu *pdu)
free(idr);
}
-void
-pdu_send(struct pdu *pdu)
+static void
+pdu_send_proxy(struct pdu *pdu)
{
struct iscsi_daemon_send *ids;
int error;
+ assert(pdu->pdu_connection->conn_conf.isc_iser != 0);
+
pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
ids = calloc(1, sizeof(*ids));
@@ -160,7 +164,7 @@ pdu_send(struct pdu *pdu)
free(ids);
}
-#else /* !ICL_KERNEL_PROXY */
+#endif /* ICL_KERNEL_PROXY */
static size_t
pdu_padding(const struct pdu *pdu)
@@ -196,6 +200,13 @@ pdu_receive(struct pdu *pdu)
size_t len, padding;
char dummy[4];
+#ifdef ICL_KERNEL_PROXY
+ if (pdu->pdu_connection->conn_conf.isc_iser != 0)
+ return (pdu_receive_proxy(pdu));
+#endif
+
+ assert(pdu->pdu_connection->conn_conf.isc_iser == 0);
+
pdu_read(pdu->pdu_connection->conn_socket,
(char *)pdu->pdu_bhs, sizeof(*pdu->pdu_bhs));
@@ -237,6 +248,13 @@ pdu_send(struct pdu *pdu)
struct iovec iov[3];
int iovcnt;
+#ifdef ICL_KERNEL_PROXY
+ if (pdu->pdu_connection->conn_conf.isc_iser != 0)
+ return (pdu_send_proxy(pdu));
+#endif
+
+ assert(pdu->pdu_connection->conn_conf.isc_iser == 0);
+
pdu_set_data_segment_length(pdu, pdu->pdu_data_len);
iov[0].iov_base = pdu->pdu_bhs;
iov[0].iov_len = sizeof(*pdu->pdu_bhs);
@@ -269,8 +287,6 @@ pdu_send(struct pdu *pdu)
log_errx(1, "short write");
}
-#endif /* !ICL_KERNEL_PROXY */
-
void
pdu_delete(struct pdu *pdu)
{
diff --git a/usr.sbin/isfctl/Makefile b/usr.sbin/isfctl/Makefile
deleted file mode 100644
index 30f8e5b..0000000
--- a/usr.sbin/isfctl/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-
-PROG= isfctl
-
-MAN= isfctl.8
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/isfctl/Makefile.depend b/usr.sbin/isfctl/Makefile.depend
deleted file mode 100644
index 65ce567..0000000
--- a/usr.sbin/isfctl/Makefile.depend
+++ /dev/null
@@ -1,18 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/isfctl/isfctl.8 b/usr.sbin/isfctl/isfctl.8
deleted file mode 100644
index 06b2f3a..0000000
--- a/usr.sbin/isfctl/isfctl.8
+++ /dev/null
@@ -1,89 +0,0 @@
-.\"-
-.\" Copyright (c) 2012 SRI International
-.\" All rights reserved.
-.\"
-.\" This software was developed by SRI International and the University of
-.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
-.\" ("CTSRD"), as part of the DARPA CRASH research programme.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd August 3, 2012
-.Dt ISFCTL 8
-.Os
-.Sh NAME
-.Nm isfctl
-.Nd Intel StrataFlash device control program
-.Sh SYNOPSIS
-.Nm
-.Ar device
-.Ic erase
-.Ar offset
-.Ar size
-.Sh DESCRIPTION
-The
-.Nm
-utility provides a way for administrators to control aspects of
-.Xr isf 4
-devices that can not be managed though the
-.Xr disk 9
-interface.
-.Pp
-The
-.Nm
-utility takes a device name as its first argument followed by a command.
-Currently supported commands are:
-.Bl -tag -width erase
-.It Ic erase
-Erase blocks beginning at
-.Ar offset
-covering a total of
-.Ar size
-bytes.
-The
-.Ar offset
-argument must be a multiple of 128K.
-The
-.Ar size
-argument must either be a multiple of 128K or a number less than 32K in
-which case it is treated as a number of 128K blocks to erase.
-.El
-.Sh EXAMPLES
-.Dl isfctl isf0 erase 0 0x20000
-.Pp
-Erase the first block of the isf0 device.
-.Sh SEE ALSO
-.Xr isf 4
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 10.0 .
-.Sh AUTHORS
-This software and this manual page were
-developed by SRI International and the University of Cambridge Computer
-Laboratory under DARPA/AFRL contract
-.Pq FA8750-10-C-0237
-.Pq Do CTSRD Dc ,
-as part of the DARPA CRASH research programme.
diff --git a/usr.sbin/isfctl/isfctl.c b/usr.sbin/isfctl/isfctl.c
deleted file mode 100644
index af99093..0000000
--- a/usr.sbin/isfctl/isfctl.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/*-
- * Copyright (c) 2012 SRI International
- * All rights reserved.
- *
- * This software was developed by SRI International and the University of
- * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
- * ("CTSRD"), as part of the DARPA CRASH research programme.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-
-#include <err.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-/* XXXBED: should install and include sys/dev/isf.h */
-struct isf_range {
- off_t ir_off; /* Offset of range to delete (set to 0xFF) */
- size_t ir_size; /* Size of range */
-};
-
-#define ISF_ERASE _IOW('I', 1, struct isf_range)
-
-#define ISF_ERASE_BLOCK (128 * 1024)
-
-static enum {UNSET, ERASE} action = UNSET;
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: isfctl <device> erase <offset> <size>\n");
- exit(1);
-}
-
-int
-main(int argc, char **argv)
-{
- struct isf_range ir;
- int fd, i;
- char *p, *dev;
-
- if (argc < 2)
- usage();
- argc--; argv++;
-
- if (*argv[0] == '/')
- dev = argv[0];
- else
- asprintf(&dev, "/dev/%s", argv[0]);
- argc--; argv++;
- fd = open(dev, O_RDWR);
- if (fd < 0)
- err(1, "unable to open device -- %s", dev);
-
- if (strcmp(argv[0], "erase") == 0) {
- if (argc != 3)
- usage();
- action = ERASE;
- ir.ir_off = strtol(argv[1], &p, 0);
- if (*p)
- errx(1, "invalid offset -- %s", argv[2]);
- ir.ir_size = strtol(argv[2], &p, 0);
- if (*p)
- errx(1, "invalid size -- %s", argv[3]);
- /*
- * If the user requests to delete less than 32K of space
- * then assume that they want to delete a number of 128K
- * blocks.
- */
- if (ir.ir_size < 32 * 1024)
- ir.ir_size *= 128 * 1024;
- }
-
- switch (action) {
- case ERASE:
- i = ioctl(fd, ISF_ERASE, &ir);
- if (i < 0)
- err(1, "ioctl(%s, %jx, %zx)", dev,
- (intmax_t)ir.ir_off, ir.ir_size);
- break;
- default:
- usage();
- }
-
- close(fd);
- return (0);
-}
diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c
index 452a079..04a4514 100644
--- a/usr.sbin/jail/command.c
+++ b/usr.sbin/jail/command.c
@@ -106,7 +106,12 @@ next_command(struct cfjail *j)
case IP_MOUNT_DEVFS:
if (!bool_param(j->intparams[IP_MOUNT_DEVFS]))
continue;
- /* FALLTHROUGH */
+ j->comstring = &dummystring;
+ break;
+ case IP_MOUNT_FDESCFS:
+ if (!bool_param(j->intparams[IP_MOUNT_FDESCFS]))
+ continue;
+ j->comstring = &dummystring;
case IP__OP:
case IP_STOP_TIMEOUT:
j->comstring = &dummystring;
@@ -452,6 +457,32 @@ run_command(struct cfjail *j)
}
break;
+ case IP_MOUNT_FDESCFS:
+ argv = alloca(7 * sizeof(char *));
+ path = string_param(j->intparams[KP_PATH]);
+ if (path == NULL) {
+ jail_warnx(j, "mount.fdescfs: no path");
+ return -1;
+ }
+ devpath = alloca(strlen(path) + 8);
+ sprintf(devpath, "%s/dev/fd", path);
+ if (check_path(j, "mount.fdescfs", devpath, 0,
+ down ? "fdescfs" : NULL) < 0)
+ return -1;
+ if (down) {
+ *(const char **)&argv[0] = "/sbin/umount";
+ argv[1] = devpath;
+ argv[2] = NULL;
+ } else {
+ *(const char **)&argv[0] = _PATH_MOUNT;
+ *(const char **)&argv[1] = "-t";
+ *(const char **)&argv[2] = "fdescfs";
+ *(const char **)&argv[3] = ".";
+ argv[4] = devpath;
+ argv[5] = NULL;
+ }
+ break;
+
case IP_COMMAND:
if (j->name != NULL)
goto default_command;
diff --git a/usr.sbin/jail/config.c b/usr.sbin/jail/config.c
index a201f31..5796708 100644
--- a/usr.sbin/jail/config.c
+++ b/usr.sbin/jail/config.c
@@ -83,6 +83,7 @@ static const struct ipspec intparams[] = {
#endif
[IP_MOUNT] = {"mount", PF_INTERNAL | PF_REV},
[IP_MOUNT_DEVFS] = {"mount.devfs", PF_INTERNAL | PF_BOOL},
+ [IP_MOUNT_FDESCFS] = {"mount.fdescfs", PF_INTERNAL | PF_BOOL},
[IP_MOUNT_FSTAB] = {"mount.fstab", PF_INTERNAL},
[IP_STOP_TIMEOUT] = {"stop.timeout", PF_INTERNAL | PF_INT},
[IP_VNET_INTERFACE] = {"vnet.interface", PF_INTERNAL},
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index 88d69f9..8ebe210 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 23, 2013
+.Dd October 12, 2013
.Dt JAIL 8
.Os
.Sh NAME
@@ -682,7 +682,7 @@ to.
An alias for each address will be added to the interface before the
prison is created, and will be removed from the interface after the
prison is removed.
-.It Op Va ip4.addr
+.It Va ip4.addr
In addition to the IP addresses that are passed to the kernel, and
interface and/or a netmask may also be specified, in the form
.Dq Ar interface Ns | Ns Ar ip-address Ns / Ns Ar netmask .
@@ -691,7 +691,7 @@ will be added to that interface, as it is with the
.Va interface
parameter. If a netmask in either dotted-quad or CIDR form is given
after IP address, it will be used when adding the IP alias.
-.It Op Va ip6.addr
+.It Va ip6.addr
In addition to the IP addresses that are passed to the kernel,
and interface and/or a prefix may also be specified, in the form
.Dq Ar interface Ns | Ns Ar ip-address Ns / Ns Ar prefix .
@@ -722,11 +722,19 @@ An
format file containing filesystems to mount before creating a jail.
.It Va mount.devfs
Mount a
-.Xr devfs
-filesystem on the chrooted /dev directory, and apply the ruleset in the
+.Xr devfs 5
+filesystem on the chrooted
+.Pa /dev
+directory, and apply the ruleset in the
.Va devfs_ruleset
parameter (or a default of ruleset 4: devfsrules_jail)
to restrict the devices visible inside the prison.
+.It Va mount.fdescfs
+Mount a
+.Xr fdescfs 5
+filesystem on the chrooted
+.Pa /dev/fd
+directory.
.It Va allow.dying
Allow making changes to a
.Va dying
@@ -890,8 +898,9 @@ or for running a virtual server.
.Pp
Start a shell in the jail:
.Bd -literal -offset indent
-jail -c path=/data/jail/testjail mount.devfs host.hostname=testhostname \\
- ip4.addr=192.0.2.100 command=/bin/sh
+jail -c path=/data/jail/testjail mount.devfs \\
+ host.hostname=testhostname ip4.addr=192.0.2.100 \\
+ command=/bin/sh
.Ed
.Pp
Assuming no errors, you will end up with a shell prompt within the jail.
@@ -1165,6 +1174,8 @@ environment of the first jail.
.Xr ps 1 ,
.Xr quota 1 ,
.Xr jail_set 2 ,
+.Xr devfs 5 ,
+.Xr fdescfs 5 ,
.Xr jail.conf 5 ,
.Xr procfs 5 ,
.Xr rc.conf 5 ,
diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c
index 9930dbb..661c4ad 100644
--- a/usr.sbin/jail/jail.c
+++ b/usr.sbin/jail/jail.c
@@ -92,6 +92,7 @@ static const enum intparam startcommands[] = {
IP_MOUNT,
IP__MOUNT_FROM_FSTAB,
IP_MOUNT_DEVFS,
+ IP_MOUNT_FDESCFS,
IP_EXEC_PRESTART,
IP__OP,
IP_VNET_INTERFACE,
@@ -108,6 +109,7 @@ static const enum intparam stopcommands[] = {
IP_STOP_TIMEOUT,
IP__OP,
IP_EXEC_POSTSTOP,
+ IP_MOUNT_FDESCFS,
IP_MOUNT_DEVFS,
IP__MOUNT_FROM_FSTAB,
IP_MOUNT,
diff --git a/usr.sbin/jail/jail.conf.5 b/usr.sbin/jail/jail.conf.5
index 2e48829..d83bf61 100644
--- a/usr.sbin/jail/jail.conf.5
+++ b/usr.sbin/jail/jail.conf.5
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 23, 2012
+.Dd February 13, 2014
.Dt JAIL.CONF 5
.Os
.Sh NAME
@@ -206,8 +206,9 @@ bar {
}
.Ed
.Sh SEE ALSO
-.Xr jail_set 2
-.Xr jail 8
+.Xr jail_set 2 ,
+.Xr rc.conf 5 ,
+.Xr jail 8 ,
.Xr jls 8
.Sh HISTORY
The
diff --git a/usr.sbin/jail/jailp.h b/usr.sbin/jail/jailp.h
index 63995b2..3f89392 100644
--- a/usr.sbin/jail/jailp.h
+++ b/usr.sbin/jail/jailp.h
@@ -95,6 +95,7 @@ enum intparam {
#endif
IP_MOUNT, /* Mount points in fstab(5) form */
IP_MOUNT_DEVFS, /* Mount /dev under prison root */
+ IP_MOUNT_FDESCFS, /* Mount /dev/fd under prison root */
IP_MOUNT_FSTAB, /* A standard fstab(5) file */
IP_STOP_TIMEOUT, /* Time to wait after sending SIGTERM */
IP_VNET_INTERFACE, /* Assign interface(s) to vnet jail */
diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c
index e74be96..9144ba0 100644
--- a/usr.sbin/kldxref/kldxref.c
+++ b/usr.sbin/kldxref/kldxref.c
@@ -274,7 +274,7 @@ usage(void)
exit(1);
}
-int
+static int
compare(const FTSENT *const *a, const FTSENT *const *b)
{
if ((*a)->fts_info == FTS_D && (*b)->fts_info != FTS_D)
diff --git a/usr.sbin/lpr/filters.ru/koi2855/Makefile b/usr.sbin/lpr/filters.ru/koi2855/Makefile
index 361783e..71ffc09 100644
--- a/usr.sbin/lpr/filters.ru/koi2855/Makefile
+++ b/usr.sbin/lpr/filters.ru/koi2855/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= koi2855
-NO_MAN=
+MAN=
CFLAGS+= -I${.CURDIR}/../../common_source
diff --git a/usr.sbin/lpr/filters.ru/koi2alt/Makefile b/usr.sbin/lpr/filters.ru/koi2alt/Makefile
index e410d9a..98f7ffe 100644
--- a/usr.sbin/lpr/filters.ru/koi2alt/Makefile
+++ b/usr.sbin/lpr/filters.ru/koi2alt/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= koi2alt
-NO_MAN=
+MAN=
CFLAGS+= -I${.CURDIR}/../../common_source
diff --git a/usr.sbin/lpr/filters/Makefile b/usr.sbin/lpr/filters/Makefile
index b55b536..f1bc586 100644
--- a/usr.sbin/lpr/filters/Makefile
+++ b/usr.sbin/lpr/filters/Makefile
@@ -4,7 +4,7 @@
BINDIR= /usr/libexec/lpr
PROG= lpf
-NO_MAN=
+MAN=
CFLAGS+= -I${.CURDIR}/../common_source
diff --git a/usr.sbin/lpr/lpr/printcap.5 b/usr.sbin/lpr/lpr/printcap.5
index 7076b5f..3cccd3a 100644
--- a/usr.sbin/lpr/lpr/printcap.5
+++ b/usr.sbin/lpr/lpr/printcap.5
@@ -82,6 +82,7 @@ call)
.It "df str" Ta Dv NULL Ta No "tex data filter"
.Tn ( DVI
format)
+.It "du num 1 UID to run daemon as"
.It "ff str" Ta So Li \ef Sc Ta No "string to send for a form feed"
.It "fo bool false print a form feed when device is opened"
.It "gf str" Ta Dv NULL Ta No "graph data filter"
diff --git a/usr.sbin/makefs/cd9660/iso9660_rrip.c b/usr.sbin/makefs/cd9660/iso9660_rrip.c
index 40acf40..5382857 100644
--- a/usr.sbin/makefs/cd9660/iso9660_rrip.c
+++ b/usr.sbin/makefs/cd9660/iso9660_rrip.c
@@ -634,7 +634,7 @@ cd9660_createSL(cd9660node *node)
int
cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo)
{
- v->attr.rr_entry.PX.h.length[0] = 36;
+ v->attr.rr_entry.PX.h.length[0] = 44;
v->attr.rr_entry.PX.h.version[0] = 1;
cd9660_bothendian_dword(pxinfo->inode->st.st_mode,
v->attr.rr_entry.PX.mode);
@@ -644,8 +644,9 @@ cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo)
v->attr.rr_entry.PX.uid);
cd9660_bothendian_dword(pxinfo->inode->st.st_gid,
v->attr.rr_entry.PX.gid);
+ cd9660_bothendian_dword(pxinfo->inode->st.st_ino,
+ v->attr.rr_entry.PX.serial);
- /* Ignoring the serial number for now */
return 1;
}
diff --git a/usr.sbin/makefs/cd9660/iso9660_rrip.h b/usr.sbin/makefs/cd9660/iso9660_rrip.h
index 3653ac6..3570301 100644
--- a/usr.sbin/makefs/cd9660/iso9660_rrip.h
+++ b/usr.sbin/makefs/cd9660/iso9660_rrip.h
@@ -103,7 +103,7 @@ typedef struct {
u_char links [ISODCL(13,20)];
u_char uid [ISODCL(21,28)];
u_char gid [ISODCL(29,36)];
- u_char serial [ISODCL(37,44)];/* Not used */
+ u_char serial [ISODCL(37,44)];
} ISO_RRIP_PX;
typedef struct {
diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c
index 0417d86..92d5508 100644
--- a/usr.sbin/makefs/ffs.c
+++ b/usr.sbin/makefs/ffs.c
@@ -361,6 +361,13 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
if (ffs_opts->avgfpdir == -1)
ffs_opts->avgfpdir = AFPDIR;
+ if (roundup(fsopts->minsize, ffs_opts->bsize) > fsopts->maxsize)
+ errx(1, "`%s' minsize of %lld rounded up to ffs bsize of %d "
+ "exceeds maxsize %lld. Lower bsize, or round the minimum "
+ "and maximum sizes to bsize.", dir,
+ (long long)fsopts->minsize, ffs_opts->bsize,
+ (long long)fsopts->maxsize);
+
/* calculate size of tree */
ffs_size_dir(root, fsopts);
fsopts->inodes += ROOTINO; /* include first two inodes */
diff --git a/usr.sbin/makefs/mtree.c b/usr.sbin/makefs/mtree.c
index d772bc1..9d396d1 100644
--- a/usr.sbin/makefs/mtree.c
+++ b/usr.sbin/makefs/mtree.c
@@ -157,7 +157,7 @@ mtree_file_path(fsnode *node)
rp[++depth] = pnode->name;
}
- sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
+ sb = sbuf_new_auto();
if (sb == NULL) {
errno = ENOMEM;
return (NULL);
@@ -348,6 +348,13 @@ read_word(FILE *fp, char *buf, size_t bufsz)
if (error == -1)
mtree_error("unexpected end of file");
return (error);
+ case '#': /* comment -- skip to end of line. */
+ if (!esc) {
+ error = skip_to(fp, "\n");
+ if (!error)
+ continue;
+ }
+ break;
case '\\':
esc++;
if (esc == 1)
@@ -660,6 +667,8 @@ read_mtree_keywords(FILE *fp, fsnode *node)
st->st_atime = num;
st->st_ctime = num;
st->st_mtime = num;
+ if (p == NULL)
+ break;
error = read_number(p, 10, &num, 0,
INTMAX_MAX);
if (error)
diff --git a/usr.sbin/mergemaster/mergemaster.sh b/usr.sbin/mergemaster/mergemaster.sh
index 361cef9..a200088 100755
--- a/usr.sbin/mergemaster/mergemaster.sh
+++ b/usr.sbin/mergemaster/mergemaster.sh
@@ -492,8 +492,14 @@ MM_MAKE="make ${ARCHSTRING} -m ${SOURCEDIR}/share/mk"
# files the user changed from the reference files.
#
if [ -n "${AUTO_UPGRADE}" -a -s "${MTREEFILE}" ]; then
+ # Force FreeBSD 9 compatible output when available.
+ if mtree -F freebsd9 -c -p /var/empty/ > /dev/null 2>&1; then
+ MTREE_FLAVOR="-F freebsd9"
+ else
+ MTREE_FLAVOR=
+ fi
CHANGED=:
- for file in `mtree -eqL -f ${MTREEFILE} -p ${DESTDIR}/ \
+ for file in `mtree -eqL ${MTREE_FLAVOR} -f ${MTREEFILE} -p ${DESTDIR}/ \
2>/dev/null | awk '($2 == "changed") {print $1}'`; do
if [ -f "${DESTDIR}/$file" ]; then
CHANGED="${CHANGED}${DESTDIR}/${file}:"
@@ -693,7 +699,8 @@ case "${RERUN}" in
# or spwd.db. Instead, we want to compare the text versions, and run *_mkdb.
# Prompt the user to do so below, as needed.
#
- rm -f ${TEMPROOT}/etc/*.db ${TEMPROOT}/etc/passwd
+ rm -f ${TEMPROOT}/etc/*.db ${TEMPROOT}/etc/passwd \
+ ${TEMPROOT}/var/db/services.db
# We only need to compare things like freebsd.cf once
find ${TEMPROOT}/usr/obj -type f -delete 2>/dev/null
@@ -702,7 +709,7 @@ case "${RERUN}" in
# and to make the actual comparison faster.
find ${TEMPROOT}/usr -type l -delete 2>/dev/null
find ${TEMPROOT} -type f -size 0 -delete 2>/dev/null
- find -d ${TEMPROOT} -type d -empty -delete 2>/dev/null
+ find -d ${TEMPROOT} -type d -empty -mindepth 1 -delete 2>/dev/null
# Build the mtree database in a temporary location.
case "${PRE_WORLD}" in
diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile
index f6e358a..4fe6f03 100644
--- a/usr.sbin/mfiutil/Makefile
+++ b/usr.sbin/mfiutil/Makefile
@@ -2,10 +2,11 @@
PROG= mfiutil
SRCS= mfiutil.c mfi_bbu.c mfi_cmd.c mfi_config.c mfi_drive.c mfi_evt.c \
- mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c mfi_foreign.c
+ mfi_flash.c mfi_patrol.c mfi_show.c mfi_volume.c mfi_foreign.c \
+ mfi_properties.c
MAN8= mfiutil.8
-CFLAGS+= -fno-builtin-strftime
+CFLAGS.gcc+= -fno-builtin-strftime
DPADD= ${LIBUTIL}
LDADD= -lutil
diff --git a/usr.sbin/mfiutil/mfi_evt.c b/usr.sbin/mfiutil/mfi_evt.c
index c9a1a6d..901c0bd 100644
--- a/usr.sbin/mfiutil/mfi_evt.c
+++ b/usr.sbin/mfiutil/mfi_evt.c
@@ -33,6 +33,7 @@
#include <sys/errno.h>
#include <err.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
@@ -534,6 +535,7 @@ show_events(int ac, char **av)
struct mfi_evt_log_state info;
struct mfi_evt_list *list;
union mfi_evt filter;
+ bool first;
long val;
char *cp;
ssize_t size;
@@ -640,7 +642,9 @@ show_events(int ac, char **av)
close(fd);
return (ENOMEM);
}
- for (seq = start;;) {
+ first = true;
+ seq = start;
+ for (;;) {
if (mfi_get_events(fd, list, num_events, filter, seq,
&status) < 0) {
error = errno;
@@ -650,8 +654,6 @@ show_events(int ac, char **av)
return (error);
}
if (status == MFI_STAT_NOT_FOUND) {
- if (seq == start)
- warnx("No matching events found");
break;
}
if (status != MFI_STAT_OK) {
@@ -669,13 +671,14 @@ show_events(int ac, char **av)
* the case that our stop point is earlier in
* the buffer than our start point.
*/
- if (list->event[i].seq >= stop) {
+ if (list->event[i].seq > stop) {
if (start <= stop)
- break;
+ goto finish;
else if (list->event[i].seq < start)
- break;
+ goto finish;
}
mfi_decode_evt(fd, &list->event[i], verbose);
+ first = false;
}
/*
@@ -686,6 +689,9 @@ show_events(int ac, char **av)
seq = list->event[list->count - 1].seq + 1;
}
+finish:
+ if (first)
+ warnx("No matching events found");
free(list);
close(fd);
diff --git a/usr.sbin/mfiutil/mfi_properties.c b/usr.sbin/mfiutil/mfi_properties.c
new file mode 100644
index 0000000..c9c9204
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_properties.c
@@ -0,0 +1,171 @@
+/*-
+ * Copyright (c) 2013 Yahoo!, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/uio.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "mfiutil.h"
+#include <dev/mfi/mfi_ioctl.h>
+
+MFI_TABLE(top, ctrlprop);
+
+static int
+mfi_ctrl_get_properties(int fd, struct mfi_ctrl_props *info)
+{
+
+ return (mfi_dcmd_command(fd, MFI_DCMD_CTRL_GET_PROPS, info,
+ sizeof(struct mfi_ctrl_props), NULL, 0, NULL));
+}
+
+static int
+mfi_ctrl_set_properties(int fd, struct mfi_ctrl_props *info)
+{
+
+ return (mfi_dcmd_command(fd, MFI_DCMD_CTRL_SET_PROPS, info,
+ sizeof(struct mfi_ctrl_props), NULL, 0, NULL));
+}
+
+/*
+ * aquite the controller properties data structure modify the
+ * rebuild rate if requested and then retun
+ */
+static int
+mfi_ctrl_rebuild_rate(int ac, char **av)
+{
+ int error, fd;
+ struct mfi_ctrl_props ctrl_props;
+
+ if (ac > 2) {
+ warn("mfi_ctrl_set_rebuild_rate");
+ return(-1);
+ }
+
+ fd = mfi_open(mfi_unit, O_RDWR);
+ if (fd < 0) {
+ error = errno;
+ warn("mfi_open");
+ return (error);
+ }
+
+ error = mfi_ctrl_get_properties(fd, &ctrl_props);
+ if ( error < 0) {
+ error = errno;
+ warn("Failed to get controller properties");
+ close(fd);
+ return (error);
+ }
+ /*
+ * User requested a change to the rebuild rate
+ */
+ if (ac > 1) {
+ ctrl_props.rebuild_rate = atoi(av[ac - 1]);
+ error = mfi_ctrl_set_properties(fd, &ctrl_props);
+ if ( error < 0) {
+ error = errno;
+ warn("Failed to set controller properties");
+ close(fd);
+ return (error);
+ }
+
+ error = mfi_ctrl_get_properties(fd, &ctrl_props);
+ if ( error < 0) {
+ error = errno;
+ warn("Failed to get controller properties");
+ close(fd);
+ return (error);
+ }
+ }
+ printf ("controller rebuild rate: %%%u \n",
+ ctrl_props.rebuild_rate);
+ return (0);
+}
+MFI_COMMAND(ctrlprop, rebuild, mfi_ctrl_rebuild_rate);
+
+static int
+mfi_ctrl_alarm_enable(int ac, char **av)
+{
+ int error, fd;
+ struct mfi_ctrl_props ctrl_props;
+
+ if (ac > 2) {
+ warn("mfi_ctrl_alarm_enable");
+ return(-1);
+ }
+
+ fd = mfi_open(mfi_unit, O_RDWR);
+ if (fd < 0) {
+ error = errno;
+ warn("mfi_open");
+ return (error);
+ }
+
+ error = mfi_ctrl_get_properties(fd, &ctrl_props);
+ if ( error < 0) {
+ error = errno;
+ warn("Failed to get controller properties");
+ close(fd);
+ return (error);
+ }
+ printf ("controller alarm was : %s\n",
+ (ctrl_props.alarm_enable ? "enabled" : "disabled"));
+
+ if (ac > 1) {
+ ctrl_props.alarm_enable = atoi(av[ac - 1]);
+ error = mfi_ctrl_set_properties(fd, &ctrl_props);
+ if ( error < 0) {
+ error = errno;
+ warn("Failed to set controller properties");
+ close(fd);
+ return (error);
+ }
+
+ error = mfi_ctrl_get_properties(fd, &ctrl_props);
+ if ( error < 0) {
+ error = errno;
+ warn("Failed to get controller properties");
+ close(fd);
+ return (error);
+ }
+ }
+ printf ("controller alarm was : %s\n",
+ (ctrl_props.alarm_enable ? "enabled" : "disabled"));
+ return (0);
+}
+
+MFI_COMMAND(ctrlprop, alarm, mfi_ctrl_alarm_enable);
diff --git a/usr.sbin/mfiutil/mfi_show.c b/usr.sbin/mfiutil/mfi_show.c
index 6bb8612..f541045 100644
--- a/usr.sbin/mfiutil/mfi_show.c
+++ b/usr.sbin/mfiutil/mfi_show.c
@@ -320,7 +320,7 @@ print_pd(struct mfi_pd_info *info, int state_len)
const char *s;
char buf[256];
- humanize_number(buf, sizeof(buf), info->raw_size * 512, "",
+ humanize_number(buf, 6, info->raw_size * 512, "",
HN_AUTOSCALE, HN_B | HN_NOSPACE |HN_DECIMAL);
printf("(%6s) ", buf);
if (info->state.ddf.v.pd_type.is_foreign) {
@@ -766,7 +766,7 @@ show_progress(int ac, char **av __unused)
printf("drive %s ", mfi_drive_name(NULL, device_id,
MFI_DNAME_DEVICE_ID|MFI_DNAME_HONOR_OPTS));
mfi_display_progress("Clear", &pinfo.prog_info.clear);
-
+ busy = 1;
}
}
diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8
index 8346922..e999c77 100644
--- a/usr.sbin/mfiutil/mfiutil.8
+++ b/usr.sbin/mfiutil/mfiutil.8
@@ -168,6 +168,12 @@
.Nm
.Op Fl u Ar unit
.Cm bbu Ar setting Ar value
+.Nm
+.Op Fl u Ar unit
+.Cm ctrlprop Ar rebuild Op Ar rate
+.Nm
+.Op Fl u Ar unit
+.Cm ctrlprop Ar alarm Op Ar 0/1
.Sh DESCRIPTION
The
.Nm
@@ -659,6 +665,12 @@ inclusive.
Modes 1, 2 and 3 enable a transparent learn cycle, whereas modes 4 and 5 do not.
The BBU's data retention time is greater when transparent learning is not used.
.El
+.It Cm ctrlprop Ar rebuild Op Ar rate
+With no arguments display the rate of rebuild (percentage)a for volumes.
+With an integer argument (0-100), set that value as the new rebuild rate for volumes.
+.It Cm ctrlprop Ar alarm Op Ar 0/1
+With no arguments display the current alarm enable/disable status.
+With a 0, disable alarms. With a 1, enable alarms.
.El
.Sh EXAMPLES
Configure the cache for volume mfid0 to cache only writes:
@@ -699,6 +711,9 @@ patrol read starting in 5 minutes:
Display the second detected foreign configuration:
.Pp
.Dl Nm Cm show foreign 1
+.Pp
+Set the current rebuild rate for volumes to 40%:
+.Dl Nm Cm ctrlprop rebuild 40
.Sh SEE ALSO
.Xr mfi 4
.Sh HISTORY
diff --git a/usr.sbin/mfiutil/mfiutil.c b/usr.sbin/mfiutil/mfiutil.c
index a8d9ef8..85ce25c 100644
--- a/usr.sbin/mfiutil/mfiutil.c
+++ b/usr.sbin/mfiutil/mfiutil.c
@@ -78,7 +78,7 @@ usage(void)
fprintf(stderr, " name <volume> <name>\n");
fprintf(stderr, " volume progress <volume> - display status of active operations\n");
fprintf(stderr, " clear - clear volume configuration\n");
- fprintf(stderr, " create <type> [-v] <drive>[,<drive>[,...]] [<drive>[,<drive>[,...]]\n");
+ fprintf(stderr, " create <type> [-v] [-s stripe_size] <drive>[,<drive>[,...]] [<drive>[,<drive>[,...]]\n");
fprintf(stderr, " delete <volume>\n");
fprintf(stderr, " add <drive> [volume] - add a hot spare\n");
fprintf(stderr, " remove <drive> - remove a hot spare\n");
@@ -93,6 +93,8 @@ usage(void)
fprintf(stderr, " flash <firmware>\n");
fprintf(stderr, " start learn - start a BBU relearn\n");
fprintf(stderr, " bbu <setting> <value> - set BBU properties\n");
+ fprintf(stderr, " ctrlprop rebuild [rate] - get/set the volume rebuild rate\n");
+ fprintf(stderr, " ctrlprop alarm [0/1] - enable/disable controller alarms\n");
#ifdef DEBUG
fprintf(stderr, " debug - debug 'show config'\n");
fprintf(stderr, " dump - display 'saved' config\n");
diff --git a/usr.sbin/mount_smbfs/Makefile b/usr.sbin/mount_smbfs/Makefile
index 9b73944..bbc084f 100644
--- a/usr.sbin/mount_smbfs/Makefile
+++ b/usr.sbin/mount_smbfs/Makefile
@@ -11,11 +11,6 @@ CFLAGS+= -DSMBFS -I${MOUNTDIR} -I${CONTRIBDIR}/include
LDADD= -lsmb -lkiconv
DPADD= ${LIBSMB} ${LIBKICONV}
-# Needs to be dynamically linked for optional dlopen() access to
-# userland libiconv (see the -E option).
-#
-NO_SHARED?= NO
-
.PATH: ${CONTRIBDIR}/mount_smbfs
.PATH: ${MOUNTDIR}
diff --git a/usr.sbin/mptable/mptable.c b/usr.sbin/mptable/mptable.c
index 01fa897..2c29934 100644
--- a/usr.sbin/mptable/mptable.c
+++ b/usr.sbin/mptable/mptable.c
@@ -43,9 +43,12 @@ static const char rcsid[] =
#define OEM_PROCESSING_READY_NOT
#include <sys/param.h>
+#include <sys/mman.h>
+#include <x86/mptable.h>
#include <err.h>
#include <fcntl.h>
#include <paths.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -74,23 +77,8 @@ static const char rcsid[] =
#define GROPE_AREA2 0x90000
#define GROPE_SIZE 0x10000
-#define PROCENTRY_FLAG_EN 0x01
-#define PROCENTRY_FLAG_BP 0x02
-#define IOAPICENTRY_FLAG_EN 0x01
-
#define MAXPNSTR 132
-enum busTypes {
- CBUS = 1,
- CBUSII = 2,
- EISA = 3,
- ISA = 6,
- PCI = 13,
- XPRESS = 18,
- MAX_BUSTYPE = 18,
- UNKNOWN_BUSTYPE = 0xff
-};
-
typedef struct BUSTYPENAME {
u_char type;
char name[ 7 ];
@@ -129,140 +117,25 @@ static const char *whereStrings[] = {
"GROPE AREA #2"
};
-typedef struct TABLE_ENTRY {
- u_char type;
- u_char length;
- char name[ 32 ];
-} tableEntry;
-
-static const tableEntry extendedtableEntryTypes[] =
-{
- { 128, 20, "System Address Space" },
- { 129, 8, "Bus Hierarchy" },
- { 130, 8, "Compatibility Bus Address" }
-};
-
-/* MP Floating Pointer Structure */
-typedef struct MPFPS {
- char signature[ 4 ];
- u_int32_t pap;
- u_char length;
- u_char spec_rev;
- u_char checksum;
- u_char mpfb1;
- u_char mpfb2;
- u_char mpfb3;
- u_char mpfb4;
- u_char mpfb5;
-} mpfps_t;
-
-/* MP Configuration Table Header */
-typedef struct MPCTH {
- char signature[ 4 ];
- u_short base_table_length;
- u_char spec_rev;
- u_char checksum;
- u_char oem_id[ 8 ];
- u_char product_id[ 12 ];
- u_int32_t oem_table_pointer;
- u_short oem_table_size;
- u_short entry_count;
- u_int32_t apic_address;
- u_short extended_table_length;
- u_char extended_table_checksum;
- u_char reserved;
-} mpcth_t;
-
-
-typedef struct PROCENTRY {
- u_char type;
- u_char apicID;
- u_char apicVersion;
- u_char cpuFlags;
- u_int32_t cpuSignature;
- u_int32_t featureFlags;
- u_int32_t reserved1;
- u_int32_t reserved2;
-} ProcEntry;
-
-typedef struct BUSENTRY {
- u_char type;
- u_char busID;
- char busType[ 6 ];
-} BusEntry;
-
-typedef struct IOAPICENTRY {
- u_char type;
- u_char apicID;
- u_char apicVersion;
- u_char apicFlags;
- u_int32_t apicAddress;
-} IOApicEntry;
-
-typedef struct INTENTRY {
- u_char type;
- u_char intType;
- u_short intFlags;
- u_char srcBusID;
- u_char srcBusIRQ;
- u_char dstApicID;
- u_char dstApicINT;
-} IntEntry;
-
-
-/*
- * extended entry type structures
- */
-
-typedef struct SASENTRY {
- u_char type;
- u_char length;
- u_char busID;
- u_char addressType;
- u_int64_t addressBase;
- u_int64_t addressLength;
-} __attribute__((__packed__)) SasEntry;
-
-
-typedef struct BHDENTRY {
- u_char type;
- u_char length;
- u_char busID;
- u_char busInfo;
- u_char busParent;
- u_char reserved[ 3 ];
-} BhdEntry;
-
-
-typedef struct CBASMENTRY {
- u_char type;
- u_char length;
- u_char busID;
- u_char addressMod;
- u_int predefinedRange;
-} CbasmEntry;
-
-
-
static void apic_probe( u_int32_t* paddr, int* where );
static void MPConfigDefault( int featureByte );
-static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps );
+static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp );
static void MPConfigTableHeader( u_int32_t pap );
-static int readType( void );
static void seekEntry( u_int32_t addr );
static void readEntry( void* entry, int size );
+static void *mapEntry( u_int32_t addr, int size );
-static void processorEntry( void );
-static void busEntry( void );
-static void ioApicEntry( void );
-static void intEntry( void );
+static void processorEntry( proc_entry_ptr entry );
+static void busEntry( bus_entry_ptr entry );
+static void ioApicEntry( io_apic_entry_ptr entry );
+static void intEntry( int_entry_ptr entry );
-static void sasEntry( void );
-static void bhdEntry( void );
-static void cbasmEntry( void );
+static void sasEntry( sas_entry_ptr entry );
+static void bhdEntry( bhd_entry_ptr entry );
+static void cbasmEntry( cbasm_entry_ptr entry );
static void doDmesg( void );
static void pnstr( char* s, int c );
@@ -360,10 +233,10 @@ main( int argc, char *argv[] )
puts( SEP_LINE );
/* check whether an MP config table exists */
- if ( (defaultConfig = mpfps.mpfb1) )
+ if ( (defaultConfig = mpfps->config_type) )
MPConfigDefault( defaultConfig );
else
- MPConfigTableHeader( mpfps.pap );
+ MPConfigTableHeader( mpfps->pap );
/* do a dmesg output */
if ( dmesg )
@@ -524,12 +397,12 @@ apic_probe( u_int32_t* paddr, int* where )
*
*/
static void
-MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps )
+MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp )
{
-
- /* read in mpfps structure*/
- seekEntry( paddr );
- readEntry( mpfps, sizeof( mpfps_t ) );
+ mpfps_t mpfps;
+
+ /* map in mpfps structure*/
+ *mpfpsp = mpfps = mapEntry( paddr, sizeof( *mpfps ) );
/* show its contents */
printf( "MP Floating Pointer Structure:\n\n" );
@@ -576,7 +449,7 @@ MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfps )
}
/* bit 7 is IMCRP */
- printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ?
+ printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) ?
"PIC" : "Virtual Wire" );
/* MP feature bytes 3-5 are expected to be ZERO */
@@ -652,59 +525,53 @@ MPConfigDefault( int featureByte )
static void
MPConfigTableHeader( u_int32_t pap )
{
- u_int32_t paddr;
mpcth_t cth;
int x;
int totalSize;
- int count, c;
- int type;
+ int c;
int oldtype, entrytype;
+ u_int8_t *entry;
if ( pap == 0 ) {
printf( "MP Configuration Table Header MISSING!\n" );
exit( 1 );
}
- /* convert physical address to virtual address */
- paddr = pap;
-
- /* read in cth structure */
- seekEntry( paddr );
- readEntry( &cth, sizeof( cth ) );
+ /* map in cth structure */
+ cth = mapEntry( pap, sizeof( *cth ) );
printf( "MP Config Table Header:\n\n" );
printf( " physical address:\t\t0x%08x\n", pap );
printf( " signature:\t\t\t'" );
- pnstr( cth.signature, 4 );
+ pnstr( cth->signature, 4 );
printf( "'\n" );
- printf( " base table length:\t\t%d\n", cth.base_table_length );
+ printf( " base table length:\t\t%d\n", cth->base_table_length );
- printf( " version:\t\t\t1.%1d\n", cth.spec_rev );
- printf( " checksum:\t\t\t0x%02x\n", cth.checksum );
+ printf( " version:\t\t\t1.%1d\n", cth->spec_rev );
+ printf( " checksum:\t\t\t0x%02x\n", cth->checksum );
printf( " OEM ID:\t\t\t'" );
- pnstr( cth.oem_id, 8 );
+ pnstr( cth->oem_id, 8 );
printf( "'\n" );
printf( " Product ID:\t\t\t'" );
- pnstr( cth.product_id, 12 );
+ pnstr( cth->product_id, 12 );
printf( "'\n" );
- printf( " OEM table pointer:\t\t0x%08x\n", cth.oem_table_pointer );
- printf( " OEM table size:\t\t%d\n", cth.oem_table_size );
+ printf( " OEM table pointer:\t\t0x%08x\n", cth->oem_table_pointer );
+ printf( " OEM table size:\t\t%d\n", cth->oem_table_size );
- printf( " entry count:\t\t\t%d\n", cth.entry_count );
+ printf( " entry count:\t\t\t%d\n", cth->entry_count );
- printf( " local APIC address:\t\t0x%08x\n", cth.apic_address );
+ printf( " local APIC address:\t\t0x%08x\n", cth->apic_address );
- printf( " extended table length:\t%d\n", cth.extended_table_length );
- printf( " extended table checksum:\t%d\n", cth.extended_table_checksum );
+ printf( " extended table length:\t%d\n", cth->extended_table_length );
+ printf( " extended table checksum:\t%d\n", cth->extended_table_checksum );
- totalSize = cth.base_table_length - sizeof( struct MPCTH );
- count = cth.entry_count;
+ totalSize = cth->base_table_length - sizeof( struct MPCTH );
puts( SEP_LINE );
@@ -723,101 +590,99 @@ MPConfigTableHeader( u_int32_t pap )
nintr = 0;
oldtype = -1;
- for (c = count; c; c--) {
- entrytype = readType();
+ entry = mapEntry(pap + sizeof(*cth), cth->base_table_length);
+ for (c = cth->entry_count; c; c--) {
+ entrytype = *entry;
if (entrytype != oldtype)
printf("--\n");
if (entrytype < oldtype)
printf("MPTABLE OUT OF ORDER!\n");
switch (entrytype) {
- case 0:
- if (oldtype != 0)
+ case MPCT_ENTRY_PROCESSOR:
+ if (oldtype != MPCT_ENTRY_PROCESSOR)
printf( "Processors:\tAPIC ID\tVersion\tState"
"\t\tFamily\tModel\tStep\tFlags\n" );
- oldtype = 0;
- processorEntry();
+ processorEntry((proc_entry_ptr)entry);
+ entry += sizeof(struct PROCENTRY);
break;
- case 1:
- if (oldtype != 1)
+ case MPCT_ENTRY_BUS:
+ if (oldtype != MPCT_ENTRY_BUS)
printf( "Bus:\t\tBus ID\tType\n" );
- oldtype = 1;
- busEntry();
+ busEntry((bus_entry_ptr)entry);
+ entry += sizeof(struct BUSENTRY);
break;
- case 2:
- if (oldtype != 2)
+ case MPCT_ENTRY_IOAPIC:
+ if (oldtype != MPCT_ENTRY_IOAPIC)
printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" );
- oldtype = 2;
- ioApicEntry();
+ ioApicEntry((io_apic_entry_ptr)entry);
+ entry += sizeof(struct IOAPICENTRY);
break;
- case 3:
- if (oldtype != 3)
+ case MPCT_ENTRY_INT:
+ if (oldtype != MPCT_ENTRY_INT)
printf( "I/O Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
- oldtype = 3;
- intEntry();
+ intEntry((int_entry_ptr)entry);
+ entry += sizeof(struct INTENTRY);
break;
- case 4:
- if (oldtype != 4)
+ case MPCT_ENTRY_LOCAL_INT:
+ if (oldtype != MPCT_ENTRY_LOCAL_INT)
printf( "Local Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
- oldtype = 4;
- intEntry();
+ intEntry((int_entry_ptr)entry);
+ entry += sizeof(struct INTENTRY);
break;
default:
printf("MPTABLE HOSED! record type = %d\n", entrytype);
exit(1);
}
+ oldtype = entrytype;
}
#if defined( EXTENDED_PROCESSING_READY )
/* process any extended data */
- if ( (totalSize = cth.extended_table_length) ) {
+ if ( cth->extended_table_length ) {
+ ext_entry_ptr ext_entry, end;
+
puts( SEP_LINE );
printf( "MP Config Extended Table Entries:\n\n" );
- while ( totalSize > 0 ) {
- switch ( type = readType() ) {
- case 128:
- sasEntry();
+ ext_entry = mapEntry(pap + cth->base_table_length,
+ cth->extended_table_length);
+ end = (ext_entry_ptr)((char *)ext_entry + cth->extended_table_length);
+ while (ext_entry < end) {
+ switch (ext_entry->type) {
+ case MPCT_EXTENTRY_SAS:
+ sasEntry((sas_entry_ptr)ext_entry);
break;
- case 129:
- bhdEntry();
+ case MPCT_EXTENTRY_BHD:
+ bhdEntry((bhd_entry_ptr)ext_entry);
break;
- case 130:
- cbasmEntry();
+ case MPCT_EXTENTRY_CBASM:
+ cbasmEntry((cbasm_entry_ptr)ext_entry);
break;
default:
printf( "Extended Table HOSED!\n" );
exit( 1 );
}
- totalSize -= extendedtableEntryTypes[ type-128 ].length;
+ ext_entry = (ext_entry_ptr)((char *)ext_entry + ext_entry->length);
}
}
#endif /* EXTENDED_PROCESSING_READY */
/* process any OEM data */
- if ( cth.oem_table_pointer && (cth.oem_table_size > 0) ) {
+ if ( cth->oem_table_pointer && (cth->oem_table_size > 0) ) {
#if defined( OEM_PROCESSING_READY )
# error your on your own here!
- /* convert OEM table pointer to virtual address */
- poemtp = (u_int32_t)cth.oem_table_pointer;
-
- /* read in oem table structure */
- if ( (oemdata = (void*)malloc( cth.oem_table_size )) == NULL )
- err( 1, "oem malloc" );
-
- seekEntry( poemtp );
- readEntry( oemdata, cth.oem_table_size );
+ /* map in oem table structure */
+ oemdata = mapEntry( cth->oem_table_pointer, cth->oem_table_size);
/** process it */
-
- free( oemdata );
#else
printf( "\nyou need to modify the source to handle OEM data!\n\n" );
#endif /* OEM_PROCESSING_READY */
@@ -828,11 +693,11 @@ MPConfigTableHeader( u_int32_t pap )
#if defined( RAW_DUMP )
{
int ofd;
- u_char dumpbuf[ 4096 ];
+ void *dumpbuf;
ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR, 0666 );
- seekEntry( paddr );
- readEntry( dumpbuf, 1024 );
+
+ dumpbuf = mapEntry( paddr, 1024 );
write( ofd, dumpbuf, 1024 );
close( ofd );
}
@@ -843,24 +708,6 @@ MPConfigTableHeader( u_int32_t pap )
/*
*
*/
-static int
-readType( void )
-{
- u_char type;
-
- if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) )
- err( 1, "type read; pfd: %d", pfd );
-
- if ( lseek( pfd, -1, SEEK_CUR ) < 0 )
- err( 1, "type seek" );
-
- return (int)type;
-}
-
-
-/*
- *
- */
static void
seekEntry( u_int32_t addr )
{
@@ -879,31 +726,37 @@ readEntry( void* entry, int size )
err( 1, "readEntry" );
}
+static void *
+mapEntry( u_int32_t addr, int size )
+{
+ void *p;
+
+ p = mmap( NULL, size, PROT_READ, MAP_SHARED, pfd, addr );
+ if (p == MAP_FAILED)
+ err( 1, "mapEntry" );
+ return (p);
+}
static void
-processorEntry( void )
+processorEntry( proc_entry_ptr entry )
{
- ProcEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
/* count it */
++ncpu;
- printf( "\t\t%2d", entry.apicID );
- printf( "\t 0x%2x", entry.apicVersion );
+ printf( "\t\t%2d", entry->apic_id );
+ printf( "\t 0x%2x", entry->apic_version );
printf( "\t %s, %s",
- (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
- (entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" );
+ (entry->cpu_flags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
+ (entry->cpu_flags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" );
printf( "\t %d\t %d\t %d",
- (entry.cpuSignature >> 8) & 0x0f,
- (entry.cpuSignature >> 4) & 0x0f,
- entry.cpuSignature & 0x0f );
+ (entry->cpu_signature >> 8) & 0x0f,
+ (entry->cpu_signature >> 4) & 0x0f,
+ entry->cpu_signature & 0x0f );
- printf( "\t 0x%04x\n", entry.featureFlags );
+ printf( "\t 0x%04x\n", entry->feature_flags );
}
@@ -924,50 +777,42 @@ lookupBusType( char* name )
static void
-busEntry( void )
+busEntry( bus_entry_ptr entry )
{
int x;
char name[ 8 ];
char c;
- BusEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
/* count it */
++nbus;
- printf( "\t\t%2d", entry.busID );
- printf( "\t " ); pnstr( entry.busType, 6 ); printf( "\n" );
+ printf( "\t\t%2d", entry->bus_id );
+ printf( "\t " ); pnstr( entry->bus_type, 6 ); printf( "\n" );
for ( x = 0; x < 6; ++x ) {
- if ( (c = entry.busType[ x ]) == ' ' )
+ if ( (c = entry->bus_type[ x ]) == ' ' )
break;
name[ x ] = c;
}
name[ x ] = '\0';
- busses[ entry.busID ] = lookupBusType( name );
+ busses[ entry->bus_id ] = lookupBusType( name );
}
static void
-ioApicEntry( void )
+ioApicEntry( io_apic_entry_ptr entry )
{
- IOApicEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
/* count it */
++napic;
- printf( "\t\t%2d", entry.apicID );
- printf( "\t 0x%02x", entry.apicVersion );
+ printf( "\t\t%2d", entry->apic_id );
+ printf( "\t 0x%02x", entry->apic_version );
printf( "\t %s",
- (entry.apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" );
- printf( "\t\t 0x%x\n", entry.apicAddress );
+ (entry->apic_flags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" );
+ printf( "\t\t 0x%x\n", entry->apic_address );
- apics[ entry.apicID ] = entry.apicID;
+ apics[ entry->apic_id ] = entry->apic_id;
}
@@ -983,53 +828,45 @@ static const char *triggerMode[] = {
};
static void
-intEntry( void )
+intEntry( int_entry_ptr entry )
{
- IntEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
/* count it */
- if ( (int)entry.type == 3 )
+ if ( entry->type == MPCT_ENTRY_INT )
++nintr;
- printf( "\t\t%s", intTypes[ (int)entry.intType ] );
+ printf( "\t\t%s", intTypes[ entry->int_type ] );
- printf( "\t%9s", polarityMode[ (int)entry.intFlags & 0x03 ] );
- printf( "%12s", triggerMode[ ((int)entry.intFlags >> 2) & 0x03 ] );
+ printf( "\t%9s", polarityMode[ entry->int_flags & INTENTRY_FLAGS_POLARITY ] );
+ printf( "%12s", triggerMode[ (entry->int_flags & INTENTRY_FLAGS_TRIGGER) >> 2 ] );
- printf( "\t %5d", (int)entry.srcBusID );
- if ( busses[ (int)entry.srcBusID ] == PCI )
+ printf( "\t %5d", entry->src_bus_id );
+ if ( busses[ entry->src_bus_id ] == PCI )
printf( "\t%2d:%c",
- ((int)entry.srcBusIRQ >> 2) & 0x1f,
- ((int)entry.srcBusIRQ & 0x03) + 'A' );
+ (entry->src_bus_irq >> 2) & 0x1f,
+ (entry->src_bus_irq & 0x03) + 'A' );
else
- printf( "\t %3d", (int)entry.srcBusIRQ );
- printf( "\t %6d", (int)entry.dstApicID );
- printf( "\t %3d\n", (int)entry.dstApicINT );
+ printf( "\t %3d", entry->src_bus_irq );
+ printf( "\t %6d", entry->dst_apic_id );
+ printf( "\t %3d\n", entry->dst_apic_int );
}
static void
-sasEntry( void )
+sasEntry( sas_entry_ptr entry )
{
- SasEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
- printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name );
- printf( " bus ID: %d", entry.busID );
+ printf( "--\nSystem Address Space\n");
+ printf( " bus ID: %d", entry->bus_id );
printf( " address type: " );
- switch ( entry.addressType ) {
- case 0:
+ switch ( entry->address_type ) {
+ case SASENTRY_TYPE_IO:
printf( "I/O address\n" );
break;
- case 1:
+ case SASENTRY_TYPE_MEMORY:
printf( "memory address\n" );
break;
- case 2:
+ case SASENTRY_TYPE_PREFETCH:
printf( "prefetch address\n" );
break;
default:
@@ -1037,39 +874,32 @@ sasEntry( void )
break;
}
- printf( " address base: 0x%llx\n", (long long)entry.addressBase );
- printf( " address range: 0x%llx\n", (long long)entry.addressLength );
+ printf( " address base: 0x%jx\n", (uintmax_t)entry->address_base );
+ printf( " address range: 0x%jx\n", (uintmax_t)entry->address_length );
}
static void
-bhdEntry( void )
+bhdEntry( bhd_entry_ptr entry )
{
- BhdEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
- printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name );
- printf( " bus ID: %d", entry.busID );
- printf( " bus info: 0x%02x", entry.busInfo );
- printf( " parent bus ID: %d\n", entry.busParent );
+ printf( "--\nBus Hierarchy\n" );
+ printf( " bus ID: %d", entry->bus_id );
+ printf( " bus info: 0x%02x", entry->bus_info );
+ printf( " parent bus ID: %d\n", entry->parent_bus );
}
static void
-cbasmEntry( void )
+cbasmEntry( cbasm_entry_ptr entry )
{
- CbasmEntry entry;
-
- /* read it into local memory */
- readEntry( &entry, sizeof( entry ) );
- printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name );
- printf( " bus ID: %d", entry.busID );
- printf( " address modifier: %s\n", (entry.addressMod & 0x01) ?
- "subtract" : "add" );
- printf( " predefined range: 0x%08x\n", entry.predefinedRange );
+ printf( "--\nCompatibility Bus Address\n" );
+ printf( " bus ID: %d", entry->bus_id );
+ printf( " address modifier: %s\n",
+ (entry->address_mod & CBASMENTRY_ADDRESS_MOD_SUBTRACT) ?
+ "subtract" : "add" );
+ printf( " predefined range: 0x%08x\n", entry->predefined_range );
}
diff --git a/usr.sbin/mtest/mtest.8 b/usr.sbin/mtest/mtest.8
index dca6a5f..5ccfa94 100644
--- a/usr.sbin/mtest/mtest.8
+++ b/usr.sbin/mtest/mtest.8
@@ -131,9 +131,9 @@ to allow traffic from source
Print
.Ar n
source filter entries for
-.An mcast-addr
+.Ar mcast-addr
on interface
-.An ifname .
+.Ar ifname .
.\"
.Pp
.It Ic f Ar filename
diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile
index c378455..e73815a 100644
--- a/usr.sbin/mtree/Makefile
+++ b/usr.sbin/mtree/Makefile
@@ -6,7 +6,7 @@
.PATH: ${.CURDIR}/../../usr.bin/cksum
PROG= fmtree
-MAN= fmtree.8 mtree.5
+MAN= fmtree.8
SRCS= compare.c crc.c create.c excludes.c misc.c mtree.c spec.c verify.c
SRCS+= specspec.c
@@ -14,11 +14,6 @@ CFLAGS+= -DMD5 -DSHA1 -DRMD160 -DSHA256
DPADD= ${LIBMD}
LDADD= -lmd
-.if ${MK_NMTREE} == "no"
-LINKS= ${BINDIR}/fmtree ${BINDIR}/mtree
-MLINKS= fmtree.8 mtree.8
-.endif
-
CLEANFILES+= fmtree.8
fmtree.8: mtree.8
diff --git a/usr.sbin/ndiscvt/ndisgen.sh b/usr.sbin/ndiscvt/ndisgen.sh
index e8c8ce3..97e8364 100644
--- a/usr.sbin/ndiscvt/ndisgen.sh
+++ b/usr.sbin/ndiscvt/ndisgen.sh
@@ -493,7 +493,7 @@ convert_driver () {
return
}
-ICONVPATH=/usr/local/bin/iconv
+ICONVPATH=/usr/bin/iconv
NDISCVT=/usr/sbin/ndiscvt
STUBPATH=/usr/share/misc
STUBFILE=windrv_stub.c
diff --git a/usr.sbin/ndp/ndp.c b/usr.sbin/ndp/ndp.c
index 2ff1e31..3888b05 100644
--- a/usr.sbin/ndp/ndp.c
+++ b/usr.sbin/ndp/ndp.c
@@ -109,11 +109,6 @@
#include <unistd.h>
#include "gmt2local.h"
-/* packing rule for routing socket */
-#define ROUNDUP(a) \
- ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
-#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
-
#define NEXTADDR(w, s) \
if (rtm->rtm_addrs & (w)) { \
bcopy((char *)&s, cp, sizeof(s)); cp += SA_SIZE(&s);}
@@ -136,7 +131,7 @@ void getsocket(void);
int set(int, char **);
void get(char *);
int delete(char *);
-void dump(struct in6_addr *, int);
+void dump(struct sockaddr_in6 *, int);
static struct in6_nbrinfo *getnbrinfo(struct in6_addr *, int, int);
static char *ether_str(struct sockaddr_dl *);
int ndp_ether_aton(char *, u_char *);
@@ -168,9 +163,7 @@ int mode = 0;
char *arg = NULL;
int
-main(argc, argv)
- int argc;
- char **argv;
+main(int argc, char **argv)
{
int ch;
@@ -320,8 +313,7 @@ main(argc, argv)
* Process a file to set standard ndp entries
*/
int
-file(name)
- char *name;
+file(char *name)
{
FILE *fp;
int i, retval;
@@ -378,9 +370,7 @@ struct {
* Set an individual neighbor cache entry
*/
int
-set(argc, argv)
- int argc;
- char **argv;
+set(int argc, char **argv)
{
register struct sockaddr_in6 *sin = &sin_m;
register struct sockaddr_dl *sdl;
@@ -426,7 +416,7 @@ set(argc, argv)
/* NOTREACHED */
}
sin = (struct sockaddr_in6 *)(rtm + 1);
- sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin6_len) + (char *)sin);
+ sdl = (struct sockaddr_dl *)(ALIGN(sin->sin6_len) + (char *)sin);
if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) {
if (sdl->sdl_family == AF_LINK &&
!(rtm->rtm_flags & RTF_GATEWAY)) {
@@ -455,8 +445,7 @@ overwrite:
* Display an individual neighbor cache entry
*/
void
-get(host)
- char *host;
+get(char *host)
{
struct sockaddr_in6 *sin = &sin_m;
struct addrinfo hints, *res;
@@ -472,7 +461,9 @@ get(host)
return;
}
sin->sin6_addr = ((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
- dump(&sin->sin6_addr, 0);
+ sin->sin6_scope_id =
+ ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id;
+ dump(sin, 0);
if (found_entry == 0) {
getnameinfo((struct sockaddr *)sin, sin->sin6_len, host_buf,
sizeof(host_buf), NULL ,0,
@@ -486,8 +477,7 @@ get(host)
* Delete a neighbor cache entry
*/
int
-delete(host)
- char *host;
+delete(char *host)
{
struct sockaddr_in6 *sin = &sin_m;
register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
@@ -515,7 +505,7 @@ delete(host)
/* NOTREACHED */
}
sin = (struct sockaddr_in6 *)(rtm + 1);
- sdl = (struct sockaddr_dl *)(ROUNDUP(sin->sin6_len) + (char *)sin);
+ sdl = (struct sockaddr_dl *)(ALIGN(sin->sin6_len) + (char *)sin);
if (IN6_ARE_ADDR_EQUAL(&sin->sin6_addr, &sin_m.sin6_addr)) {
if (sdl->sdl_family == AF_LINK &&
!(rtm->rtm_flags & RTF_GATEWAY)) {
@@ -555,9 +545,7 @@ delete:
* Dump the entire neighbor cache
*/
void
-dump(addr, cflag)
- struct in6_addr *addr;
- int cflag;
+dump(struct sockaddr_in6 *addr, int cflag)
{
int mib[6];
size_t needed;
@@ -607,7 +595,7 @@ again:;
rtm = (struct rt_msghdr *)next;
sin = (struct sockaddr_in6 *)(rtm + 1);
- sdl = (struct sockaddr_dl *)((char *)sin + ROUNDUP(sin->sin6_len));
+ sdl = (struct sockaddr_dl *)((char *)sin + ALIGN(sin->sin6_len));
/*
* Some OSes can produce a route that has the LINK flag but
@@ -629,7 +617,9 @@ again:;
continue;
if (addr) {
- if (!IN6_ARE_ADDR_EQUAL(addr, &sin->sin6_addr))
+ if (IN6_ARE_ADDR_EQUAL(&addr->sin6_addr,
+ &sin->sin6_addr) == 0 ||
+ addr->sin6_scope_id != sin->sin6_scope_id)
continue;
found_entry = 1;
} else if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr))
@@ -762,10 +752,7 @@ again:;
}
static struct in6_nbrinfo *
-getnbrinfo(addr, ifindex, warning)
- struct in6_addr *addr;
- int ifindex;
- int warning;
+getnbrinfo(struct in6_addr *addr, int ifindex, int warning)
{
static struct in6_nbrinfo nbi;
int s;
@@ -806,9 +793,7 @@ ether_str(struct sockaddr_dl *sdl)
}
int
-ndp_ether_aton(a, n)
- char *a;
- u_char *n;
+ndp_ether_aton(char *a, u_char *n)
{
int i, o[6];
@@ -840,8 +825,7 @@ usage()
}
int
-rtmsg(cmd)
- int cmd;
+rtmsg(int cmd)
{
static int seq;
int rlen;
@@ -906,10 +890,7 @@ doit:
}
void
-ifinfo(ifname, argc, argv)
- char *ifname;
- int argc;
- char **argv;
+ifinfo(char *ifname, int argc, char **argv)
{
struct in6_ndireq nd;
int i, s;
@@ -1478,8 +1459,7 @@ harmonize_rtr()
#ifdef SIOCSDEFIFACE_IN6 /* XXX: check SIOCGDEFIFACE_IN6 as well? */
static void
-setdefif(ifname)
- char *ifname;
+setdefif(char *ifname)
{
struct in6_ndifreq ndifreq;
unsigned int ifindex;
@@ -1532,8 +1512,7 @@ getdefif()
#endif
static char *
-sec2str(total)
- time_t total;
+sec2str(time_t total)
{
static char result[256];
int days, hours, mins, secs;
@@ -1578,8 +1557,7 @@ sec2str(total)
* from tcpdump/util.c
*/
static void
-ts_print(tvp)
- const struct timeval *tvp;
+ts_print(const struct timeval *tvp)
{
int s;
diff --git a/usr.sbin/newsyslog/Makefile b/usr.sbin/newsyslog/Makefile
index ebc297b..4e3ae55 100644
--- a/usr.sbin/newsyslog/Makefile
+++ b/usr.sbin/newsyslog/Makefile
@@ -1,7 +1,13 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
PROG= newsyslog
MAN= newsyslog.8 newsyslog.conf.5
SRCS= newsyslog.c ptimes.c
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index 69a63c4..ff9e937 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -1491,6 +1491,7 @@ validate_old_timelog(int fd, const struct dirent *dp, const char *logfname,
&dp->d_name[logfname_len]);
return (0);
}
+ memset(tm, 0, sizeof(*tm));
if ((s = strptime(&dp->d_name[logfname_len + 1],
timefnamefmt, tm)) == NULL) {
/*
@@ -2283,7 +2284,7 @@ sizefile(const char *file)
if (stat(file, &sb) < 0)
return (-1);
- return (kbytes(dbtob(sb.st_blocks)));
+ return (kbytes(sb.st_size));
}
/*
diff --git a/usr.sbin/newsyslog/tests/Makefile b/usr.sbin/newsyslog/tests/Makefile
new file mode 100644
index 0000000..f8ad273
--- /dev/null
+++ b/usr.sbin/newsyslog/tests/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/usr.sbin/newsyslog
+
+TAP_TESTS_SH= legacy_test
+
+.include <bsd.test.mk>
diff --git a/usr.sbin/newsyslog/tests/legacy_test.sh b/usr.sbin/newsyslog/tests/legacy_test.sh
new file mode 100644
index 0000000..ba10f2c
--- /dev/null
+++ b/usr.sbin/newsyslog/tests/legacy_test.sh
@@ -0,0 +1,444 @@
+#!/bin/sh
+
+# $FreeBSD$
+
+COUNT=0
+TMPDIR=$(pwd)/work
+if [ $? -ne 0 ]; then
+ echo "$0: Can't create temp dir, exiting..."
+ exit 1
+fi
+
+# Begin an individual test
+begin()
+{
+ COUNT=`expr $COUNT + 1`
+ OK=1
+ NAME="$1"
+}
+
+# End an individual test
+end()
+{
+ if [ $OK = 1 ]
+ then
+ printf 'ok '
+ else
+ printf 'not ok '
+ fi
+ echo "$COUNT - $NAME"
+}
+
+# Make a file that can later be verified
+mkf()
+{
+ CN=`basename $1`
+ echo "$CN-$CN" >$1
+}
+
+# Verify that the file specified is correct
+ckf()
+{
+ if [ -f $2 ] && echo "$1-$1" | diff - $2 >/dev/null
+ then
+ ok
+ else
+ notok
+ fi
+}
+
+# Check that a file exists
+ckfe()
+{
+ if [ -f $1 ]
+ then
+ ok
+ else
+ notok
+ fi
+}
+
+# Verify that the specified file does not exist
+# (is not there)
+cknt()
+{
+ if [ -r $1 ]
+ then
+ notok
+ else
+ ok
+ fi
+}
+
+# Check if a file is there, depending of if it's supposed to or not -
+# basically how many log files we are supposed to keep vs. how many we
+# actually keep.
+ckntfe()
+{
+ curcnt=$1
+ keepcnt=$2
+ f=$3
+
+ if [ $curcnt -le $keepcnt ]
+ then
+ #echo Assuming file there
+ ckfe $f
+ else
+ #echo Assuming file NOT there
+ cknt $f
+ fi
+}
+
+
+
+# A part of a test succeeds
+ok()
+{
+ :
+}
+
+# A part of a test fails
+notok()
+{
+ OK=0
+}
+
+# Verify that the exit code passed is for unsuccessful termination
+ckfail()
+{
+ if [ $1 -gt 0 ]
+ then
+ ok
+ else
+ notok
+ fi
+}
+
+# Verify that the exit code passed is for successful termination
+ckok()
+{
+ if [ $1 -eq 0 ]
+ then
+ ok
+ else
+ notok
+ fi
+}
+
+# Check that there are X files which match expr
+chkfcnt()
+{
+ cnt=$1; shift
+ if [ $cnt -eq `echo "$@" | wc -w` ]
+ then
+ ok
+ else
+ notok
+ fi
+}
+
+# Check that two strings are alike
+ckstr()
+{
+ if [ "$1" = "$2" ]
+ then
+ ok
+ else
+ notok
+ fi
+}
+
+tmpdir_create()
+{
+ mkdir -p ${TMPDIR}/log ${TMPDIR}/alog
+ cd ${TMPDIR}/log
+}
+
+tmpdir_clean()
+{
+ cd ${TMPDIR}
+ rm -rf "${TMPDIR}/log" "${TMPDIR}/alog" newsyslog.conf
+}
+
+run_newsyslog()
+{
+
+ newsyslog -f ../newsyslog.conf -F -r "$@"
+}
+
+tests_normal_rotate() {
+ ext="$1"
+ dir="$2"
+
+ if [ -n "$dir" ]; then
+ newsyslog_args=" -a ${dir}"
+ name_postfix="${ext} archive dir"
+ else
+ newsyslog_args=""
+ name_postfix="${ext}"
+ fi
+
+ tmpdir_create
+
+ begin "create file ${name_postfix}" -newdir
+ run_newsyslog -C
+ ckfe $LOGFNAME
+ cknt ${dir}${LOGFNAME}.0${ext}
+ end
+
+ begin "rotate normal 1 ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckfe ${dir}${LOGFNAME}.0${ext}
+ cknt ${dir}${LOGFNAME}.1${ext}
+ end
+
+ begin "rotate normal 2 ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckfe ${dir}${LOGFNAME}.0${ext}
+ ckfe ${dir}${LOGFNAME}.1${ext}
+ cknt ${dir}${LOGFNAME}.2${ext}
+ end
+
+ begin "rotate normal 3 ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckfe ${dir}${LOGFNAME}.0${ext}
+ ckfe ${dir}${LOGFNAME}.1${ext}
+ ckfe ${dir}${LOGFNAME}.2${ext}
+ cknt ${dir}${LOGFNAME}.3${ext}
+ end
+
+ begin "rotate normal 4 ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckfe ${dir}${LOGFNAME}.0${ext}
+ ckfe ${dir}${LOGFNAME}.1${ext}
+ ckfe ${dir}${LOGFNAME}.2${ext}
+ cknt ${dir}${LOGFNAME}.4${ext}
+ end
+
+ begin "rotate normal 5 ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckfe ${dir}${LOGFNAME}.0${ext}
+ ckfe ${dir}${LOGFNAME}.1${ext}
+ ckfe ${dir}${LOGFNAME}.2${ext}
+ cknt ${dir}${LOGFNAME}.4${ext}
+ end
+
+ # Wait a bit so we can see if the noaction test rotates files
+ sleep 1.1
+
+ begin "noaction ${name_postfix}"
+ ofiles=`ls -Tl ${dir}${LOGFNAME}.*${ext} | tr -d '\n'`
+ run_newsyslog ${newsyslog_args} -n >/dev/null
+ ckfe ${LOGFNAME}
+ ckstr "$ofiles" "`ls -lT ${dir}${LOGFNAME}.*${ext} | tr -d '\n'`"
+ end
+
+ tmpdir_clean
+}
+
+tests_normal_rotate_keepn() {
+ cnt="$1"
+ ext="$2"
+ dir="$3"
+
+ if [ -n "$dir" ]; then
+ newsyslog_args=" -a ${dir}"
+ name_postfix="${ext} archive dir"
+ else
+ newsyslog_args=""
+ name_postfix="${ext}"
+ fi
+
+ tmpdir_create
+
+ begin "create file ${name_postfix}" -newdir
+ run_newsyslog -C
+ ckfe $LOGFNAME
+ cknt ${dir}${LOGFNAME}.0${ext}
+ end
+
+ begin "rotate normal 1 cnt=$cnt ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckntfe 1 $cnt ${dir}${LOGFNAME}.0${ext}
+ cknt ${dir}${LOGFNAME}.1${ext}
+ end
+
+ begin "rotate normal 2 cnt=$cnt ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckntfe 1 $cnt ${dir}${LOGFNAME}.0${ext}
+ ckntfe 2 $cnt ${dir}${LOGFNAME}.1${ext}
+ cknt ${dir}${LOGFNAME}.2${ext}
+ end
+
+ begin "rotate normal 3 cnt=$cnt ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckntfe 1 $cnt ${dir}${LOGFNAME}.0${ext}
+ ckntfe 2 $cnt ${dir}${LOGFNAME}.1${ext}
+ ckntfe 3 $cnt ${dir}${LOGFNAME}.2${ext}
+ cknt ${dir}${LOGFNAME}.3${ext}
+ end
+
+ begin "rotate normal 3 cnt=$cnt ${name_postfix}"
+ run_newsyslog $newsyslog_args
+ ckfe ${LOGFNAME}
+ ckntfe 1 $cnt ${dir}${LOGFNAME}.0${ext}
+ ckntfe 2 $cnt ${dir}${LOGFNAME}.1${ext}
+ ckntfe 3 $cnt ${dir}${LOGFNAME}.2${ext}
+ ckntfe 4 $cnt ${dir}${LOGFNAME}.3${ext}
+ cknt ${dir}${LOGFNAME}.4${ext}
+ end
+
+ # Wait a bit so we can see if the noaction test rotates files
+ sleep 1.1
+
+ begin "noaction ${name_postfix}"
+ osum=`md5 ${dir}${LOGFNAME} | tr -d '\n'`
+ run_newsyslog ${newsyslog_args} -n >/dev/null
+ ckfe ${LOGFNAME}
+ ckstr "$osum" "`md5 ${dir}${LOGFNAME} | tr -d '\n'`"
+ end
+
+ tmpdir_clean
+}
+
+tests_time_rotate() {
+ ext="$1"
+ dir="$2"
+
+ if [ -n "$dir" ]; then
+ newsyslog_args="-t DEFAULT -a ${dir}"
+ name_postfix="${ext} archive dir"
+ else
+ newsyslog_args="-t DEFAULT"
+ name_postfix="${ext}"
+ fi
+
+ tmpdir_create
+
+ begin "create file ${name_postfix}" -newdir
+ run_newsyslog -C ${newsyslog_args}
+ ckfe ${LOGFNAME}
+ end
+
+ begin "rotate time 1 ${name_postfix}"
+ run_newsyslog ${newsyslog_args}
+ ckfe ${LOGFNAME}
+ chkfcnt 1 ${dir}${LOGFNAME}.*${ext}
+ end
+
+ sleep 1.1
+
+ begin "rotate time 2 ${name_postfix}"
+ run_newsyslog ${newsyslog_args}
+ ckfe ${LOGFNAME}
+ chkfcnt 2 ${dir}${LOGFNAME}.*${ext}
+ end
+
+ sleep 1.1
+
+ begin "rotate time 3 ${name_postfix}"
+ run_newsyslog ${newsyslog_args}
+ ckfe ${LOGFNAME}
+ chkfcnt 3 ${dir}${LOGFNAME}.*${ext}
+ end
+
+ sleep 1.1
+
+ begin "rotate time 4 ${name_postfix}"
+ run_newsyslog ${newsyslog_args}
+ ckfe ${LOGFNAME}
+ chkfcnt 3 ${dir}${LOGFNAME}.*${ext}
+ end
+
+ begin "noaction ${name_postfix}"
+ ofiles=`ls -1 ${dir}${LOGFNAME}.*${ext} | tr -d '\n'`
+ run_newsyslog ${newsyslog_args} -n >/dev/null
+ ckfe ${LOGFNAME}
+ ckstr "$ofiles" "`ls -1 ${dir}${LOGFNAME}.*${ext} | tr -d '\n'`"
+ end
+
+ tmpdir_clean
+}
+
+echo 1..126
+mkdir -p ${TMPDIR}
+cd ${TMPDIR}
+
+LOGFNAME=foo.log
+LOGFPATH=${TMPDIR}/log/${LOGFNAME}
+
+# Normal, no archive dir, keep X files
+echo "$LOGFPATH 640 0 * @T00 NC" > newsyslog.conf
+tests_normal_rotate_keepn 0
+
+echo "$LOGFPATH 640 1 * @T00 NC" > newsyslog.conf
+tests_normal_rotate_keepn 1
+
+echo "$LOGFPATH 640 2 * @T00 NC" > newsyslog.conf
+tests_normal_rotate_keepn 2
+
+echo "$LOGFPATH 640 3 * @T00 NC" > newsyslog.conf
+tests_normal_rotate_keepn 3
+
+# Normal, no archive dir, keep X files, gz
+echo "$LOGFPATH 640 0 * @T00 NCZ" > newsyslog.conf
+tests_normal_rotate_keepn 0 ".gz"
+
+echo "$LOGFPATH 640 1 * @T00 NCZ" > newsyslog.conf
+tests_normal_rotate_keepn 1 ".gz"
+
+echo "$LOGFPATH 640 2 * @T00 NCZ" > newsyslog.conf
+tests_normal_rotate_keepn 2 ".gz"
+
+echo "$LOGFPATH 640 3 * @T00 NCZ" > newsyslog.conf
+tests_normal_rotate_keepn 3 ".gz"
+
+# Normal, no archive dir
+echo "$LOGFPATH 640 3 * @T00 NC" > newsyslog.conf
+tests_normal_rotate
+
+echo "$LOGFPATH 640 3 * @T00 NCZ" > newsyslog.conf
+tests_normal_rotate ".gz"
+
+echo "$LOGFPATH 640 3 * @T00 NCJ" > newsyslog.conf
+tests_normal_rotate ".bz2"
+
+# Normal, archive dir
+echo "$LOGFPATH 640 3 * @T00 NC" > newsyslog.conf
+tests_normal_rotate "" "${TMPDIR}/alog/"
+
+echo "$LOGFPATH 640 3 * @T00 NCZ" > newsyslog.conf
+tests_normal_rotate ".gz" "${TMPDIR}/alog/"
+
+echo "$LOGFPATH 640 3 * @T00 NCJ" > newsyslog.conf
+tests_normal_rotate ".bz2" "${TMPDIR}/alog/"
+
+# Time based, no archive dir
+echo "$LOGFPATH 640 3 * @T00 NC" > newsyslog.conf
+tests_time_rotate
+
+echo "$LOGFPATH 640 3 * @T00 NCZ" > newsyslog.conf
+tests_time_rotate "gz" ""
+
+echo "$LOGFPATH 640 3 * @T00 NCJ" > newsyslog.conf
+tests_time_rotate "bz2" ""
+
+# Time based, archive dir
+echo "$LOGFPATH 640 3 * @T00 NC" > newsyslog.conf
+tests_time_rotate "" "${TMPDIR}/alog/"
+
+echo "$LOGFPATH 640 3 * @T00 NCZ" > newsyslog.conf
+tests_time_rotate "gz" "${TMPDIR}/alog/"
+
+echo "$LOGFPATH 640 3 * @T00 NCJ" > newsyslog.conf
+tests_time_rotate "bz2" "${TMPDIR}/alog/"
+
+rm -rf "${TMPDIR}"
diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile
index 138e28d..9d24c0c 100644
--- a/usr.sbin/nmtree/Makefile
+++ b/usr.sbin/nmtree/Makefile
@@ -4,8 +4,8 @@
.PATH: ${.CURDIR}/../../contrib/mtree
-PROG= nmtree
-MAN= nmtree.8
+PROG= mtree
+MAN= mtree.5 mtree.8
SRCS= compare.c crc.c create.c excludes.c getid.c misc.c mtree.c \
only.c spec.c specspec.c verify.c
LDADD+= -lmd -lutil
@@ -20,14 +20,7 @@ LIBNETBSD= ${LIBNETBSDDIR}/libnetbsd.a
DPADD+= ${LIBNETBSD}
LDADD+= ${LIBNETBSD}
-.if ${MK_NMTREE} != "no"
-LINKS= ${BINDIR}/nmtree ${BINDIR}/mtree
-MLINKS= nmtree.8 mtree.8
-.endif
-
-CLEANFILES+= nmtree.8
-
-nmtree.8: mtree.8
- cp ${.ALLSRC} ${.TARGET}
+LINKS= ${BINDIR}/mtree ${BINDIR}/nmtree
+MLINKS= mtree.8 nmtree.8
.include <bsd.prog.mk>
diff --git a/usr.sbin/mtree/mtree.5 b/usr.sbin/nmtree/mtree.5
index 92bf3f8..afcdae8 100644
--- a/usr.sbin/mtree/mtree.5
+++ b/usr.sbin/nmtree/mtree.5
@@ -259,13 +259,6 @@ The
entry format was added by
.Nx .
.Sh BUGS
-The
-.Fx
-implementation of mtree does not currently support
-the
-.Nm
-2.0
-format.
The requirement for a
.Dq #mtree
signature line is new and not yet widely implemented.
diff --git a/usr.sbin/ntp/ntp-keygen/Makefile b/usr.sbin/ntp/ntp-keygen/Makefile
index a0fee44..26716c2 100644
--- a/usr.sbin/ntp/ntp-keygen/Makefile
+++ b/usr.sbin/ntp/ntp-keygen/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-NO_MAN=
+MAN=
.include <bsd.own.mk>
diff --git a/usr.sbin/ntp/ntpd/Makefile b/usr.sbin/ntp/ntpd/Makefile
index 175ad67..1ac4c72 100644
--- a/usr.sbin/ntp/ntpd/Makefile
+++ b/usr.sbin/ntp/ntpd/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-NO_MAN=
+MAN=
.include <bsd.own.mk>
diff --git a/usr.sbin/ntp/ntpdate/Makefile b/usr.sbin/ntp/ntpdate/Makefile
index 0814e8e..f55ec92 100644
--- a/usr.sbin/ntp/ntpdate/Makefile
+++ b/usr.sbin/ntp/ntpdate/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../contrib/ntp/ntpdate
PROG= ntpdate
-NO_MAN=
+MAN=
SRCS= ntpdate.c version.c
CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../
diff --git a/usr.sbin/ntp/ntpdc/Makefile b/usr.sbin/ntp/ntpdc/Makefile
index 17c5f39..81d2671 100644
--- a/usr.sbin/ntp/ntpdc/Makefile
+++ b/usr.sbin/ntp/ntpdc/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-NO_MAN=
+MAN=
.include <bsd.own.mk>
diff --git a/usr.sbin/ntp/ntpq/Makefile b/usr.sbin/ntp/ntpq/Makefile
index 205a0be..eb42973 100644
--- a/usr.sbin/ntp/ntpq/Makefile
+++ b/usr.sbin/ntp/ntpq/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-NO_MAN=
+MAN=
.include <bsd.own.mk>
diff --git a/usr.sbin/ntp/ntptime/Makefile b/usr.sbin/ntp/ntptime/Makefile
index db5885d..d3bf7a7 100644
--- a/usr.sbin/ntp/ntptime/Makefile
+++ b/usr.sbin/ntp/ntptime/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../contrib/ntp/util
PROG= ntptime
-NO_MAN=
+MAN=
CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../
diff --git a/usr.sbin/ntp/sntp/Makefile b/usr.sbin/ntp/sntp/Makefile
index 3bc9084..11316c5 100644
--- a/usr.sbin/ntp/sntp/Makefile
+++ b/usr.sbin/ntp/sntp/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../../../contrib/ntp/sntp
PROG= sntp
-NO_MAN=
+MAN= sntp.1
SRCS= internet.c main.c socket.c timing.c unix.c
CFLAGS+= -I${.CURDIR}/../../../contrib/ntp/include -I${.CURDIR}/../ \
diff --git a/usr.sbin/pciconf/cap.c b/usr.sbin/pciconf/cap.c
index d7296a3..bdcbe1d 100644
--- a/usr.sbin/pciconf/cap.c
+++ b/usr.sbin/pciconf/cap.c
@@ -410,7 +410,7 @@ aspm_string(uint8_t aspm)
static void
cap_express(int fd, struct pci_conf *p, uint8_t ptr)
{
- uint32_t cap;
+ uint32_t cap, cap2;
uint16_t ctl, flags, sta;
flags = read_config(fd, &p->pc_sel, ptr + PCIER_FLAGS, 2);
@@ -452,6 +452,7 @@ cap_express(int fd, struct pci_conf *p, uint8_t ptr)
if (flags & PCIEM_FLAGS_IRQ)
printf(" IRQ %d", (flags & PCIEM_FLAGS_IRQ) >> 9);
cap = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP, 4);
+ cap2 = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CAP2, 4);
ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL, 2);
printf(" max data %d(%d)",
MAX_PAYLOAD((ctl & PCIEM_CTL_MAX_PAYLOAD) >> 5),
@@ -474,6 +475,11 @@ cap_express(int fd, struct pci_conf *p, uint8_t ptr)
printf(" ASPM %s(%s)", aspm_string(ctl & PCIEM_LINK_CTL_ASPMC),
aspm_string((cap & PCIEM_LINK_CAP_ASPM) >> 10));
}
+ if ((cap2 & PCIEM_CAP2_ARI) != 0) {
+ ctl = read_config(fd, &p->pc_sel, ptr + PCIER_DEVICE_CTL2, 4);
+ printf(" ARI %s",
+ (ctl & PCIEM_CTL2_ARI) ? "enabled" : "disabled");
+ }
}
static void
diff --git a/usr.sbin/pciconf/pciconf.8 b/usr.sbin/pciconf/pciconf.8
index b416abc..e0caf1f 100644
--- a/usr.sbin/pciconf/pciconf.8
+++ b/usr.sbin/pciconf/pciconf.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 1, 2012
+.Dd January 20, 2014
.Dt PCICONF 8
.Os
.Sh NAME
@@ -33,13 +33,13 @@
.Nd diagnostic utility for the PCI bus
.Sh SYNOPSIS
.Nm
-.Fl l Op Fl bcev
+.Fl l Oo Fl bcevV Oc Op Ar device
.Nm
-.Fl a Ar selector
+.Fl a Ar device
.Nm
-.Fl r Oo Fl b | h Oc Ar selector addr Ns Op : Ns Ar addr2
+.Fl r Oo Fl b | h Oc Ar device addr Ns Op : Ns Ar addr2
.Nm
-.Fl w Oo Fl b | h Oc Ar selector addr value
+.Fl w Oo Fl b | h Oc Ar device addr value
.Sh DESCRIPTION
The
.Nm
@@ -54,7 +54,9 @@ normally only the super-user.
.Pp
With the
.Fl l
-option, it lists all devices found by the boot probe in the following format:
+option,
+.Nm
+lists PCI devices in the following format:
.Bd -literal
foo0@pci0:0:4:0: class=0x010000 card=0x00000000 chip=0x000f1000 rev=0x01 \
hdr=0x00
@@ -65,16 +67,14 @@ hdr=0x00
.Ed
.Pp
The first column gives the
-device name, unit number, and
-.Ar selector .
-If there is no device configured in the kernel for the
+driver name, unit number, and selector .
+If there is no driver attached to the
.Tn PCI
-device in question, the device name will be
+device in question, the driver name will be
.Dq none .
-Unit numbers for unconfigured devices start at zero and are incremented for
-each unconfigured device that is encountered.
-The
-.Ar selector
+Unit numbers for detached devices start at zero and are incremented for
+each detached device that is encountered.
+The selector
is in a form which may directly be used for the other forms of the command.
The second column is the class code, with the class byte printed as two
hex digits, followed by the sub-class and the interface bytes.
@@ -182,18 +182,58 @@ option is supplied,
will attempt to load the vendor/device information database, and print
vendor, device, class and subclass identification strings for each device.
.Pp
+If the
+.Fl V
+option is supplied,
+.Nm
+will list any vital product data
+.Pq VPD
+provided by each device.
+Each VPD keyword is enumerated via a line in the following format:
+.Bd -literal
+ VPD ro PN = '110114640C0 '
+.Ed
+.Pp
+The first string after the
+.Dq Li VPD
+prefix indicates if the keyword is read-only
+.Dq ro
+or read-write
+.Dq rw .
+The second string provides the keyword name.
+The text after the the equals sign lists the value of the keyword which is
+usually an ASCII string.
+.Pp
+If the optional
+.Ar device
+argument is given with the
+.Fl l
+flag,
+.Nm
+will only list details about a single device instead of all devices.
+.Pp
All invocations of
.Nm
except for
.Fl l
require a
-.Ar selector
-of the form
+.Ar device .
+The device can be identified either by a device name if the device is
+attached to a driver or by a selector.
+Selectors identify a PCI device by its address in PCI config space and
+can take one of the following forms:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
.Li pci Ns Va domain Ns \&: Ns Va bus Ns \&: Ns Va device Ns \&: \
-Ns Va function Ns ,
-.Li pci Ns Va bus Ns \&: Ns Va device Ns \&: Ns Va function Ns , or
-.Li pci Ns Va bus Ns \&: Ns Va device Ns .
-In case of an abridged form, omitted selector components are assumed to be 0.
+Ns Va function Ns
+.It
+.Li pci Ns Va bus Ns \&: Ns Va device Ns \&: Ns Va function Ns
+.It
+.Li pci Ns Va bus Ns \&: Ns Va device Ns
+.El
+.Pp
+In the case of an abridged form, omitted selector components are assumed to be 0.
An optional leading device name followed by @ and an optional final colon
will be ignored; this is so that the first column in the output of
.Nm
diff --git a/usr.sbin/pciconf/pciconf.c b/usr.sbin/pciconf/pciconf.c
index 58ffddd..0177dc9 100644
--- a/usr.sbin/pciconf/pciconf.c
+++ b/usr.sbin/pciconf/pciconf.c
@@ -35,6 +35,7 @@ static const char rcsid[] =
#include <sys/types.h>
#include <sys/fcntl.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <inttypes.h>
@@ -67,9 +68,12 @@ struct pci_vendor_info
TAILQ_HEAD(,pci_vendor_info) pci_vendors;
+static struct pcisel getsel(const char *str);
static void list_bars(int fd, struct pci_conf *p);
-static void list_devs(int verbose, int bars, int caps, int errors);
+static void list_devs(const char *name, int verbose, int bars, int caps,
+ int errors, int vpd);
static void list_verbose(struct pci_conf *p);
+static void list_vpd(int fd, struct pci_conf *p);
static const char *guess_class(struct pci_conf *p);
static const char *guess_subclass(struct pci_conf *p);
static int load_vendors(void);
@@ -83,10 +87,10 @@ static void
usage(void)
{
fprintf(stderr, "%s\n%s\n%s\n%s\n",
- "usage: pciconf -l [-bcev]",
- " pciconf -a selector",
- " pciconf -r [-b | -h] selector addr[:addr2]",
- " pciconf -w [-b | -h] selector addr value");
+ "usage: pciconf -l [-bcevV] [device]",
+ " pciconf -a device",
+ " pciconf -r [-b | -h] device addr[:addr2]",
+ " pciconf -w [-b | -h] device addr value");
exit (1);
}
@@ -95,13 +99,13 @@ main(int argc, char **argv)
{
int c;
int listmode, readmode, writemode, attachedmode;
- int bars, caps, errors, verbose;
+ int bars, caps, errors, verbose, vpd;
int byte, isshort;
listmode = readmode = writemode = attachedmode = 0;
- bars = caps = errors = verbose = byte = isshort = 0;
+ bars = caps = errors = verbose = vpd = byte = isshort = 0;
- while ((c = getopt(argc, argv, "abcehlrwv")) != -1) {
+ while ((c = getopt(argc, argv, "abcehlrwvV")) != -1) {
switch(c) {
case 'a':
attachedmode = 1;
@@ -140,19 +144,24 @@ main(int argc, char **argv)
verbose = 1;
break;
+ case 'V':
+ vpd = 1;
+ break;
+
default:
usage();
}
}
- if ((listmode && optind != argc)
+ if ((listmode && optind >= argc + 1)
|| (writemode && optind + 3 != argc)
|| (readmode && optind + 2 != argc)
|| (attachedmode && optind + 1 != argc))
usage();
if (listmode) {
- list_devs(verbose, bars, caps, errors);
+ list_devs(optind + 1 == argc ? argv[optind] : NULL, verbose,
+ bars, caps, errors, vpd);
} else if (attachedmode) {
chkattached(argv[optind]);
} else if (readmode) {
@@ -169,11 +178,13 @@ main(int argc, char **argv)
}
static void
-list_devs(int verbose, int bars, int caps, int errors)
+list_devs(const char *name, int verbose, int bars, int caps, int errors,
+ int vpd)
{
int fd;
struct pci_conf_io pc;
struct pci_conf conf[255], *p;
+ struct pci_match_conf patterns[1];
int none_count = 0;
if (verbose)
@@ -186,6 +197,16 @@ list_devs(int verbose, int bars, int caps, int errors)
bzero(&pc, sizeof(struct pci_conf_io));
pc.match_buf_len = sizeof(conf);
pc.matches = conf;
+ if (name != NULL) {
+ bzero(&patterns, sizeof(patterns));
+ patterns[0].pc_sel = getsel(name);
+ patterns[0].flags = PCI_GETCONF_MATCH_DOMAIN |
+ PCI_GETCONF_MATCH_BUS | PCI_GETCONF_MATCH_DEV |
+ PCI_GETCONF_MATCH_FUNC;
+ pc.num_patterns = 1;
+ pc.pat_buf_len = sizeof(patterns);
+ pc.patterns = patterns;
+ }
do {
if (ioctl(fd, PCIOCGETCONF, &pc) == -1)
@@ -231,6 +252,8 @@ list_devs(int verbose, int bars, int caps, int errors)
list_caps(fd, p);
if (errors)
list_errors(fd, p);
+ if (vpd)
+ list_vpd(fd, p);
}
} while (pc.status == PCI_GETCONF_MORE_DEVS);
@@ -324,6 +347,63 @@ list_verbose(struct pci_conf *p)
printf(" subclass = %s\n", dp);
}
+static void
+list_vpd(int fd, struct pci_conf *p)
+{
+ struct pci_list_vpd_io list;
+ struct pci_vpd_element *vpd, *end;
+
+ list.plvi_sel = p->pc_sel;
+ list.plvi_len = 0;
+ list.plvi_data = NULL;
+ if (ioctl(fd, PCIOCLISTVPD, &list) < 0 || list.plvi_len == 0)
+ return;
+
+ list.plvi_data = malloc(list.plvi_len);
+ if (ioctl(fd, PCIOCLISTVPD, &list) < 0) {
+ free(list.plvi_data);
+ return;
+ }
+
+ vpd = list.plvi_data;
+ end = (struct pci_vpd_element *)((char *)vpd + list.plvi_len);
+ for (; vpd < end; vpd = PVE_NEXT(vpd)) {
+ if (vpd->pve_flags == PVE_FLAG_IDENT) {
+ printf(" VPD ident = '%.*s'\n",
+ (int)vpd->pve_datalen, vpd->pve_data);
+ continue;
+ }
+
+ /* Ignore the checksum keyword. */
+ if (!(vpd->pve_flags & PVE_FLAG_RW) &&
+ memcmp(vpd->pve_keyword, "RV", 2) == 0)
+ continue;
+
+ /* Ignore remaining read-write space. */
+ if (vpd->pve_flags & PVE_FLAG_RW &&
+ memcmp(vpd->pve_keyword, "RW", 2) == 0)
+ continue;
+
+ /* Handle extended capability keyword. */
+ if (!(vpd->pve_flags & PVE_FLAG_RW) &&
+ memcmp(vpd->pve_keyword, "CP", 2) == 0) {
+ printf(" VPD ro CP = ID %02x in map 0x%x[0x%x]\n",
+ (unsigned int)vpd->pve_data[0],
+ PCIR_BAR((unsigned int)vpd->pve_data[1]),
+ (unsigned int)vpd->pve_data[3] << 8 |
+ (unsigned int)vpd->pve_data[2]);
+ continue;
+ }
+
+ /* Remaining keywords should all have ASCII values. */
+ printf(" VPD %s %c%c = '%.*s'\n",
+ vpd->pve_flags & PVE_FLAG_RW ? "rw" : "ro",
+ vpd->pve_keyword[0], vpd->pve_keyword[1],
+ (int)vpd->pve_datalen, vpd->pve_data);
+ }
+ free(list.plvi_data);
+}
+
/*
* This is a direct cut-and-paste from the table in sys/dev/pci/pci.c.
*/
@@ -557,7 +637,61 @@ read_config(int fd, struct pcisel *sel, long reg, int width)
}
static struct pcisel
-getsel(const char *str)
+getdevice(const char *name)
+{
+ struct pci_conf_io pc;
+ struct pci_conf conf[1];
+ struct pci_match_conf patterns[1];
+ char *cp;
+ int fd;
+
+ fd = open(_PATH_DEVPCI, O_RDONLY, 0);
+ if (fd < 0)
+ err(1, "%s", _PATH_DEVPCI);
+
+ bzero(&pc, sizeof(struct pci_conf_io));
+ pc.match_buf_len = sizeof(conf);
+ pc.matches = conf;
+
+ bzero(&patterns, sizeof(patterns));
+
+ /*
+ * The pattern structure requires the unit to be split out from
+ * the driver name. Walk backwards from the end of the name to
+ * find the start of the unit.
+ */
+ if (name[0] == '\0')
+ err(1, "Empty device name");
+ cp = strchr(name, '\0');
+ assert(cp != NULL && cp != name);
+ cp--;
+ while (cp != name && isdigit(cp[-1]))
+ cp--;
+ if (cp == name)
+ errx(1, "Invalid device name");
+ if ((size_t)(cp - name) + 1 > sizeof(patterns[0].pd_name))
+ errx(1, "Device name i2s too long");
+ memcpy(patterns[0].pd_name, name, cp - name);
+ patterns[0].pd_unit = strtol(cp, &cp, 10);
+ assert(*cp == '\0');
+ patterns[0].flags = PCI_GETCONF_MATCH_NAME | PCI_GETCONF_MATCH_UNIT;
+ pc.num_patterns = 1;
+ pc.pat_buf_len = sizeof(patterns);
+ pc.patterns = patterns;
+
+ if (ioctl(fd, PCIOCGETCONF, &pc) == -1)
+ err(1, "ioctl(PCIOCGETCONF)");
+ if (pc.status != PCI_GETCONF_LAST_DEVICE &&
+ pc.status != PCI_GETCONF_MORE_DEVS)
+ errx(1, "error returned from PCIOCGETCONF ioctl");
+ close(fd);
+ if (pc.num_matches == 0)
+ errx(1, "Device not found");
+ return (conf[0].pc_sel);
+}
+
+static struct pcisel
+parsesel(const char *str)
{
char *ep = strchr(str, '@');
char *epbase;
@@ -595,6 +729,20 @@ getsel(const char *str)
return sel;
}
+static struct pcisel
+getsel(const char *str)
+{
+
+ /*
+ * No device names contain colons and selectors always contain
+ * at least one colon.
+ */
+ if (strchr(str, ':') == NULL)
+ return (getdevice(str));
+ else
+ return (parsesel(str));
+}
+
static void
readone(int fd, struct pcisel *sel, long reg, int width)
{
diff --git a/usr.sbin/pkg/Makefile b/usr.sbin/pkg/Makefile
index d244bd2..3892ecc5 100644
--- a/usr.sbin/pkg/Makefile
+++ b/usr.sbin/pkg/Makefile
@@ -2,9 +2,13 @@
PROG= pkg
SRCS= pkg.c dns_utils.c config.c
+MAN= pkg.7
-NO_MAN= yes
-DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH} ${LIBBSDYML} ${LIBSBUF}
-LDADD= -larchive -lelf -lfetch -lbsdyml -lsbuf
+CFLAGS+=-I${.CURDIR}/../../contrib/libucl/include
+.PATH: ${.CURDIR}/../../contrib/libucl/include
+DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH} ${LIBUCL} ${LIBSBUF} ${LIBSSL} \
+ ${LIBCRYPTO} ${LIBM}
+LDADD= -larchive -lelf -lfetch -lucl -lsbuf -lssl -lcrypto -lm
+USEPRIVATELIB= ucl
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg/config.c b/usr.sbin/pkg/config.c
index 01eaa9f..fded95e 100644
--- a/usr.sbin/pkg/config.c
+++ b/usr.sbin/pkg/config.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,12 +29,15 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/queue.h>
#include <sys/sbuf.h>
#include <sys/elf_common.h>
#include <sys/endian.h>
+#include <sys/types.h>
#include <assert.h>
-#include <bsdyml.h>
+#include <dirent.h>
+#include <ucl.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
@@ -50,20 +54,29 @@ __FBSDID("$FreeBSD$");
#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
+struct config_value {
+ char *value;
+ STAILQ_ENTRY(config_value) next;
+};
+
struct config_entry {
uint8_t type;
const char *key;
const char *val;
char *value;
+ STAILQ_HEAD(, config_value) *list;
bool envset;
+ bool main_only; /* Only set in pkg.conf. */
};
static struct config_entry c[] = {
[PACKAGESITE] = {
PKG_CONFIG_STRING,
"PACKAGESITE",
- "http://pkg.FreeBSD.org/${ABI}/latest",
+ URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest",
NULL,
+ NULL,
+ false,
false,
},
[ABI] = {
@@ -71,13 +84,17 @@ static struct config_entry c[] = {
"ABI",
NULL,
NULL,
+ NULL,
false,
+ true,
},
[MIRROR_TYPE] = {
PKG_CONFIG_STRING,
"MIRROR_TYPE",
"SRV",
NULL,
+ NULL,
+ false,
false,
},
[ASSUME_ALWAYS_YES] = {
@@ -85,8 +102,37 @@ static struct config_entry c[] = {
"ASSUME_ALWAYS_YES",
"NO",
NULL,
+ NULL,
false,
- }
+ true,
+ },
+ [SIGNATURE_TYPE] = {
+ PKG_CONFIG_STRING,
+ "SIGNATURE_TYPE",
+ NULL,
+ NULL,
+ NULL,
+ false,
+ false,
+ },
+ [FINGERPRINTS] = {
+ PKG_CONFIG_STRING,
+ "FINGERPRINTS",
+ NULL,
+ NULL,
+ NULL,
+ false,
+ false,
+ },
+ [REPOS_DIR] = {
+ PKG_CONFIG_LIST,
+ "REPOS_DIR",
+ NULL,
+ NULL,
+ NULL,
+ false,
+ true,
+ },
};
static const char *
@@ -459,122 +505,298 @@ subst_packagesite(const char *abi)
c[PACKAGESITE].value = strdup(sbuf_data(newval));
}
+static int
+boolstr_to_bool(const char *str)
+{
+ if (str != NULL && (strcasecmp(str, "true") == 0 ||
+ strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 ||
+ str[0] == '1'))
+ return (true);
+
+ return (false);
+}
+
static void
-config_parse(yaml_document_t *doc, yaml_node_t *node)
+config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype)
{
- yaml_node_pair_t *pair;
- yaml_node_t *key, *val;
struct sbuf *buf = sbuf_new_auto();
+ const ucl_object_t *cur, *seq;
+ ucl_object_iter_t it = NULL, itseq = NULL;
+ struct config_entry *temp_config;
+ struct config_value *cv;
+ const char *key;
int i;
size_t j;
- pair = node->data.mapping.pairs.start;
+ /* Temporary config for configs that may be disabled. */
+ temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry));
- while (pair < node->data.mapping.pairs.top) {
- key = yaml_document_get_node(doc, pair->key);
- val = yaml_document_get_node(doc, pair->value);
-
- /*
- * ignoring silently empty keys can be empty lines
- * or user mistakes
- */
- if (key->data.scalar.length <= 0) {
- ++pair;
+ while ((cur = ucl_iterate_object(obj, &it, true))) {
+ key = ucl_object_key(cur);
+ if (key == NULL)
continue;
- }
+ sbuf_clear(buf);
- /*
- * silently skip on purpose to allow user to leave
- * empty lines without complaining
- */
- if (val->type == YAML_NO_NODE ||
- (val->type == YAML_SCALAR_NODE &&
- val->data.scalar.length <= 0)) {
- ++pair;
- continue;
+ if (conftype == CONFFILE_PKG) {
+ for (j = 0; j < strlen(key); ++j)
+ sbuf_putc(buf, key[j]);
+ sbuf_finish(buf);
+ } else if (conftype == CONFFILE_REPO) {
+ if (strcasecmp(key, "url") == 0)
+ sbuf_cpy(buf, "PACKAGESITE");
+ else if (strcasecmp(key, "mirror_type") == 0)
+ sbuf_cpy(buf, "MIRROR_TYPE");
+ else if (strcasecmp(key, "signature_type") == 0)
+ sbuf_cpy(buf, "SIGNATURE_TYPE");
+ else if (strcasecmp(key, "fingerprints") == 0)
+ sbuf_cpy(buf, "FINGERPRINTS");
+ else if (strcasecmp(key, "enabled") == 0) {
+ if ((cur->type != UCL_BOOLEAN) ||
+ !ucl_object_toboolean(cur))
+ goto cleanup;
+ } else
+ continue;
+ sbuf_finish(buf);
}
- sbuf_clear(buf);
- for (j = 0; j < strlen(key->data.scalar.value); ++j)
- sbuf_putc(buf, toupper(key->data.scalar.value[j]));
-
- sbuf_finish(buf);
for (i = 0; i < CONFIG_SIZE; i++) {
if (strcmp(sbuf_data(buf), c[i].key) == 0)
break;
}
- if (i == CONFIG_SIZE) {
- ++pair;
+ /* Silently skip unknown keys to be future compatible. */
+ if (i == CONFIG_SIZE)
continue;
- }
/* env has priority over config file */
- if (c[i].envset) {
- ++pair;
+ if (c[i].envset)
continue;
+
+ /* Parse sequence value ["item1", "item2"] */
+ switch (c[i].type) {
+ case PKG_CONFIG_LIST:
+ if (cur->type != UCL_ARRAY) {
+ warnx("Skipping invalid array "
+ "value for %s.\n", c[i].key);
+ continue;
+ }
+ temp_config[i].list =
+ malloc(sizeof(*temp_config[i].list));
+ STAILQ_INIT(temp_config[i].list);
+
+ while ((seq = ucl_iterate_object(cur, &itseq, true))) {
+ if (seq->type != UCL_STRING)
+ continue;
+ cv = malloc(sizeof(struct config_value));
+ cv->value =
+ strdup(ucl_object_tostring(seq));
+ STAILQ_INSERT_TAIL(temp_config[i].list, cv,
+ next);
+ }
+ break;
+ case PKG_CONFIG_BOOL:
+ temp_config[i].value =
+ strdup(ucl_object_toboolean(cur) ? "yes" : "no");
+ break;
+ default:
+ /* Normal string value. */
+ temp_config[i].value = strdup(ucl_object_tostring(cur));
+ break;
}
+ }
- c[i].value = strdup(val->data.scalar.value);
- ++pair;
+ /* Repo is enabled, copy over all settings from temp_config. */
+ for (i = 0; i < CONFIG_SIZE; i++) {
+ if (c[i].envset)
+ continue;
+ /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */
+ if (conftype != CONFFILE_PKG && c[i].main_only == true)
+ continue;
+ switch (c[i].type) {
+ case PKG_CONFIG_LIST:
+ c[i].list = temp_config[i].list;
+ break;
+ default:
+ c[i].value = temp_config[i].value;
+ break;
+ }
}
+cleanup:
+ free(temp_config);
sbuf_delete(buf);
}
+/*-
+ * Parse new repo style configs in style:
+ * Name:
+ * URL:
+ * MIRROR_TYPE:
+ * etc...
+ */
+static void
+parse_repo_file(ucl_object_t *obj)
+{
+ ucl_object_iter_t it = NULL;
+ const ucl_object_t *cur;
+ const char *key;
+
+ while ((cur = ucl_iterate_object(obj, &it, true))) {
+ key = ucl_object_key(cur);
+
+ if (key == NULL)
+ continue;
+
+ if (cur->type != UCL_OBJECT)
+ continue;
+
+ config_parse(cur, CONFFILE_REPO);
+ }
+}
+
+
+static int
+read_conf_file(const char *confpath, pkg_conf_file_t conftype)
+{
+ struct ucl_parser *p;
+ ucl_object_t *obj = NULL;
+
+ p = ucl_parser_new(0);
+
+ if (!ucl_parser_add_file(p, confpath)) {
+ if (errno != ENOENT)
+ errx(EXIT_FAILURE, "Unable to parse configuration "
+ "file %s: %s", confpath, ucl_parser_get_error(p));
+ ucl_parser_free(p);
+ /* no configuration present */
+ return (1);
+ }
+
+ obj = ucl_parser_get_object(p);
+ if (obj->type != UCL_OBJECT)
+ warnx("Invalid configuration format, ignoring the "
+ "configuration file %s", confpath);
+ else {
+ if (conftype == CONFFILE_PKG)
+ config_parse(obj, conftype);
+ else if (conftype == CONFFILE_REPO)
+ parse_repo_file(obj);
+ }
+
+ ucl_object_unref(obj);
+ ucl_parser_free(p);
+
+ return (0);
+}
+
+static int
+load_repositories(const char *repodir)
+{
+ struct dirent *ent;
+ DIR *d;
+ char *p;
+ size_t n;
+ char path[MAXPATHLEN];
+ int ret;
+
+ ret = 0;
+
+ if ((d = opendir(repodir)) == NULL)
+ return (1);
+
+ while ((ent = readdir(d))) {
+ /* Trim out 'repos'. */
+ if ((n = strlen(ent->d_name)) <= 5)
+ continue;
+ p = &ent->d_name[n - 5];
+ if (strcmp(p, ".conf") == 0) {
+ snprintf(path, sizeof(path), "%s%s%s",
+ repodir,
+ repodir[strlen(repodir) - 1] == '/' ? "" : "/",
+ ent->d_name);
+ if (access(path, F_OK) == 0 &&
+ read_conf_file(path, CONFFILE_REPO)) {
+ ret = 1;
+ goto cleanup;
+ }
+ }
+ }
+
+cleanup:
+ closedir(d);
+
+ return (ret);
+}
+
int
config_init(void)
{
- FILE *fp;
- yaml_parser_t parser;
- yaml_document_t doc;
- yaml_node_t *node;
- const char *val;
+ char *val;
int i;
const char *localbase;
+ char *env_list_item;
char confpath[MAXPATHLEN];
+ struct config_value *cv;
char abi[BUFSIZ];
for (i = 0; i < CONFIG_SIZE; i++) {
val = getenv(c[i].key);
if (val != NULL) {
- c[i].val = val;
c[i].envset = true;
+ switch (c[i].type) {
+ case PKG_CONFIG_LIST:
+ /* Split up comma-separated items from env. */
+ c[i].list = malloc(sizeof(*c[i].list));
+ STAILQ_INIT(c[i].list);
+ for (env_list_item = strtok(val, ",");
+ env_list_item != NULL;
+ env_list_item = strtok(NULL, ",")) {
+ cv =
+ malloc(sizeof(struct config_value));
+ cv->value =
+ strdup(env_list_item);
+ STAILQ_INSERT_TAIL(c[i].list, cv,
+ next);
+ }
+ break;
+ default:
+ c[i].val = val;
+ break;
+ }
}
}
+ /* Read LOCALBASE/etc/pkg.conf first. */
localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE;
- snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase);
+ snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf",
+ localbase);
- if ((fp = fopen(confpath, "r")) == NULL) {
- if (errno != ENOENT)
- err(EXIT_FAILURE, "Unable to open configuration file %s", confpath);
- /* no configuration present */
+ if (access(confpath, F_OK) == 0 && read_conf_file(confpath,
+ CONFFILE_PKG))
goto finalize;
- }
-
- yaml_parser_initialize(&parser);
- yaml_parser_set_input_file(&parser, fp);
- yaml_parser_load(&parser, &doc);
-
- node = yaml_document_get_root_node(&doc);
- if (node != NULL) {
- if (node->type != YAML_MAPPING_NODE)
- warnx("Invalid configuration format, ignoring the configuration file");
- else
- config_parse(&doc, node);
- } else {
- warnx("Invalid configuration format, ignoring the configuration file");
+ /* Then read in all repos from REPOS_DIR list of directories. */
+ if (c[REPOS_DIR].list == NULL) {
+ c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list));
+ STAILQ_INIT(c[REPOS_DIR].list);
+ cv = malloc(sizeof(struct config_value));
+ cv->value = strdup("/etc/pkg");
+ STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next);
+ cv = malloc(sizeof(struct config_value));
+ if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0)
+ goto finalize;
+ STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next);
}
- yaml_document_delete(&doc);
- yaml_parser_delete(&parser);
+ STAILQ_FOREACH(cv, c[REPOS_DIR].list, next)
+ if (load_repositories(cv->value))
+ goto finalize;
finalize:
if (c[ABI].val == NULL && c[ABI].value == NULL) {
if (pkg_get_myabi(abi, BUFSIZ) != 0)
- errx(EXIT_FAILURE, "Failed to determine the system ABI");
+ errx(EXIT_FAILURE, "Failed to determine the system "
+ "ABI");
c[ABI].val = abi;
}
@@ -612,10 +834,7 @@ config_bool(pkg_config_key k, bool *val)
else
value = c[k].val;
- if (strcasecmp(value, "true") == 0 ||
- strcasecmp(value, "yes") == 0 ||
- strcasecmp(value, "on") == 0 ||
- *value == '1')
+ if (boolstr_to_bool(value))
*val = true;
return (0);
diff --git a/usr.sbin/pkg/config.h b/usr.sbin/pkg/config.h
index e592f6d..ea0d000 100644
--- a/usr.sbin/pkg/config.h
+++ b/usr.sbin/pkg/config.h
@@ -30,20 +30,30 @@
#define _PKG_CONFIG_H
#define _LOCALBASE "/usr/local"
+#define URL_SCHEME_PREFIX "pkg+"
typedef enum {
PACKAGESITE = 0,
ABI,
MIRROR_TYPE,
ASSUME_ALWAYS_YES,
+ SIGNATURE_TYPE,
+ FINGERPRINTS,
+ REPOS_DIR,
CONFIG_SIZE
} pkg_config_key;
typedef enum {
PKG_CONFIG_STRING=0,
PKG_CONFIG_BOOL,
+ PKG_CONFIG_LIST,
} pkg_config_t;
+typedef enum {
+ CONFFILE_PKG=0,
+ CONFFILE_REPO,
+} pkg_conf_file_t;
+
int config_init(void);
void config_finish(void);
int config_string(pkg_config_key, const char **);
diff --git a/usr.sbin/pkg/dns_utils.c b/usr.sbin/pkg/dns_utils.c
index cbdb3d5..ce88048 100644
--- a/usr.sbin/pkg/dns_utils.c
+++ b/usr.sbin/pkg/dns_utils.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2012-2013 Baptiste Daroussin <bapt@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,77 @@ typedef union {
unsigned char buf[1024];
} dns_query;
+static int
+srv_priority_cmp(const void *a, const void *b)
+{
+ const struct dns_srvinfo *da, *db;
+ unsigned int r, l;
+
+ da = *(struct dns_srvinfo * const *)a;
+ db = *(struct dns_srvinfo * const *)b;
+
+ l = da->priority;
+ r = db->priority;
+
+ return ((l > r) - (l < r));
+}
+
+static int
+srv_final_cmp(const void *a, const void *b)
+{
+ const struct dns_srvinfo *da, *db;
+ unsigned int r, l, wr, wl;
+ int res;
+
+ da = *(struct dns_srvinfo * const *)a;
+ db = *(struct dns_srvinfo * const *)b;
+
+ l = da->priority;
+ r = db->priority;
+
+ res = ((l > r) - (l < r));
+
+ if (res == 0) {
+ wl = da->finalweight;
+ wr = db->finalweight;
+ res = ((wr > wl) - (wr < wl));
+ }
+
+ return (res);
+}
+
+static void
+compute_weight(struct dns_srvinfo **d, int first, int last)
+{
+ int i, j, totalweight;
+ int *chosen;
+
+ chosen = malloc(sizeof(int) * (last - first + 1));
+ totalweight = 0;
+
+ for (i = 0; i <= last; i++)
+ totalweight += d[i]->weight;
+
+ if (totalweight == 0)
+ return;
+
+ for (i = 0; i <= last; i++) {
+ for (;;) {
+ chosen[i] = random() % (d[i]->weight * 100 / totalweight);
+ for (j = 0; j < i; j++) {
+ if (chosen[i] == chosen[j])
+ break;
+ }
+ if (j == i) {
+ d[i]->finalweight = chosen[i];
+ break;
+ }
+ }
+ }
+
+ free(chosen);
+}
+
struct dns_srvinfo *
dns_getsrvinfo(const char *zone)
{
@@ -46,7 +117,7 @@ dns_getsrvinfo(const char *zone)
unsigned char *end, *p;
char host[MAXHOSTNAMELEN];
dns_query q;
- int len, qdcount, ancount, n, i;
+ int len, qdcount, ancount, n, i, f, l;
unsigned int type, class, ttl, priority, weight, port;
if ((len = res_query(zone, C_IN, T_SRV, q.buf, sizeof(q.buf))) == -1 ||
@@ -125,6 +196,21 @@ dns_getsrvinfo(const char *zone)
n++;
}
+ qsort(res, n, sizeof(res[0]), srv_priority_cmp);
+
+ priority = f = l = 0;
+ for (i = 0; i < n; i++) {
+ if (res[i]->priority != priority) {
+ if (f != l)
+ compute_weight(res, f, l);
+ f = i;
+ priority = res[i]->priority;
+ }
+ l = i;
+ }
+
+ qsort(res, n, sizeof(res[0]), srv_final_cmp);
+
for (i = 0; i < n - 1; i++)
res[i]->next = res[i + 1];
diff --git a/usr.sbin/pkg/dns_utils.h b/usr.sbin/pkg/dns_utils.h
index 0f3367b..b1418bb 100644
--- a/usr.sbin/pkg/dns_utils.h
+++ b/usr.sbin/pkg/dns_utils.h
@@ -35,6 +35,7 @@ struct dns_srvinfo {
unsigned int priority;
unsigned int weight;
unsigned int port;
+ unsigned int finalweight;
char host[MAXHOSTNAMELEN];
struct dns_srvinfo *next;
};
diff --git a/usr.sbin/pkg/pkg.7 b/usr.sbin/pkg/pkg.7
new file mode 100644
index 0000000..342c934
--- /dev/null
+++ b/usr.sbin/pkg/pkg.7
@@ -0,0 +1,281 @@
+.\" Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 12, 2013
+.Dt PKG 7
+.Os
+.Sh NAME
+.Nm pkg
+.Nd a utility for manipulating packages
+.Sh SYNOPSIS
+.Nm
+.Ao Ar command Ac
+.Nm
+add
+.Op Fl f
+.Ao Pa pkg.txz Ac
+.Nm
+.Fl N
+.Nm
+bootstrap
+.Op Fl f
+.Sh DESCRIPTION
+.Nm
+is the package management tool.
+It is used to manage local packages installed from
+.Xr ports 7
+and install/upgrade packages from remote repositories.
+.Pp
+To avoid backwards incompatibility issues, the actual
+.Xr pkg 8
+tool is not installed in the base system.
+The first time invoked,
+.Nm
+will bootstrap the real
+.Xr pkg 8
+from a remote repository.
+.Bl -tag -width "pkg bootstrap"
+.It Nm Ao Ar command Ac
+If
+.Xr pkg 8
+is not installed yet, it will be fetched, have its signature verified,
+installed, and then have the original command forwarded to it.
+If already installed, the command requested will be forwarded to the real
+.Xr pkg 8 .
+.It Nm Li add Oo Fl f Oc Ao Pa pkg.txz Ac
+Install
+.Xr pkg 8
+from a local package instead of fetching from remote.
+If a
+.Pa pkg.txz.sig
+file exists and
+signature checking is enabled, then the signature will be verified
+before installing the package.
+If the
+.Fl f
+flag is specified, then
+.Xr pkg 8
+will be installed regardless if it is already installed.
+.It Nm Fl N
+Do not bootstrap, just determine if
+.Xr pkg 8
+is actually installed or not.
+Returns 0 and the number of packages installed
+if it is, otherwise 1.
+.It Nm Li bootstrap Op Fl f
+Attempt to bootstrap and do not forward anything to
+.Xr pkg 8
+after it is installed.
+If the
+.Fl f
+flag is specified, then
+.Xr pkg 8
+will be fetched and installed regardless if it is already installed.
+.El
+.Sh CONFIGURATION
+Configuration varies in whether it is in a repository configuration file
+or the global configuration file.
+.Pp
+Repository configuration can be stored in
+.Pa /etc/pkg/FreeBSD.conf
+in the following format:
+.Bd -literal -offset indent
+FreeBSD: {
+ url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
+ mirror_type: "srv",
+ signature_type: "none",
+ fingerprints: "/usr/share/keys/pkg",
+ enabled: yes
+}
+.Ed
+.Bl -tag -width signature_type -compact
+.It url
+Refer to
+.Dv PACKAGESITE
+in
+.Sx ENVIRONMENT
+.It mirror_type
+Refer to
+.Dv MIRROR_TYPE
+in
+.Sx ENVIRONMENT
+.It signature_type
+Refer to
+.Dv SIGNATURE_TYPE
+in
+.Sx ENVIRONMENT
+.It fingerprints
+Refer to
+.Dv FINGERPRINTS
+in
+.Sx ENVIRONMENT
+.It enabled
+Defines whether this repository should be used or not.
+Valid values are
+.Dv yes ,
+.Dv true ,
+.Dv 1 ,
+.Dv no ,
+.Dv false ,
+.Dv 0 .
+.El
+.Pp
+Global configuration can be stored in
+.Pa /usr/local/etc/pkg.conf
+in the following format:
+.Bd -literal -offset indent
+PACKAGESITE: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
+MIRROR_TYPE: "srv",
+SIGNATURE_TYPE: "none",
+FINGERPRINTS: "/usr/share/keys/pkg",
+ASSUME_ALWAYS_YES: "yes"
+REPOS_DIR: ["/etc/pkg", "/usr/local/etc/pkg/repos"]
+.Ed
+.Pp
+Reference
+.Sx ENVIRONMENT
+for each variable.
+.Sh ENVIRONMENT
+The following environment variables can be set to override the settings
+from the
+.Pa pkg.conf
+file used.
+.Bl -tag -width "ASSUME_ALWAYS_YES"
+.It Ev MIRROR_TYPE
+This defines which mirror type should be used.
+Valid values are
+.Dv SRV ,
+.Dv HTTP ,
+.Dv NONE .
+.It Ev ABI
+This defines the ABI for the package to be installed.
+Default ABI is determined from
+.Pa /bin/sh .
+.It Ev ASSUME_ALWAYS_YES
+If set, no confirmation will be asked when bootstrapping
+.Xr pkg 8 .
+.It Ev SIGNATURE_TYPE
+If set to
+.Dv FINGERPRINTS
+then a signature will be required and validated against known
+certificate fingerprints when bootstrapping
+.Xr pkg 8 .
+.It Ev FINGERPRINTS
+If
+.Sy SIGNATURE_TYPE
+is set to
+.Dv FINGERPRINTS
+this value should be set to the directory path where known fingerprints are
+located.
+.It Ev PACKAGESITE
+The URL that
+.Xr pkg 8
+and other packages
+will be fetched from.
+.It Ev REPOS_DIR
+Comma-separated list of directories that should be searched for repository
+configuration files.
+.El
+.Sh FILES
+Configuration is read from the files in the listed order.
+This path can be changed by setting
+.Sy REPOS_DIR .
+The last enabled repository is the one used for bootstrapping
+.Xr pkg 8 .
+.Bl -tag -width "/usr/local/etc/pkg/repos/*.conf"
+.It Pa /usr/local/etc/pkg.conf
+.It Pa /etc/pkg/FreeBSD.conf
+.It Pa /usr/local/etc/pkg/repos/*.conf
+.El
+.Sh EXAMPLES
+Some examples are listed here.
+The full list of available commands are available in
+.Xr pkg 8
+once it is bootstrapped.
+.Pp
+Search for a package:
+.Dl $ pkg search perl
+.Pp
+Install a package:
+.Dl % pkg install perl
+.Pp
+List installed packages:
+.Dl $ pkg info
+.Pp
+Upgrade from remote repository:
+.Dl % pkg upgrade
+.Pp
+List non-automatic packages:
+.Dl $ pkg query -e '%a = 0' %o
+.Pp
+List automatic packages:
+.Dl $ pkg query -e '%a = 1' %o
+.Pp
+Delete an installed package:
+.Dl % pkg delete perl
+.Pp
+Remove unneeded dependencies:
+.Dl % pkg autoremove
+.Pp
+Change a package from automatic to non-automatic, which will prevent
+.Ic autoremove
+from removing it:
+.Dl % pkg set -A 0 perl
+.Pp
+Change a package from non-automatic to automatic, which will make
+.Ic autoremove
+allow it be removed once nothing depends on it:
+.Dl % pkg set -A 1 perl
+.Pp
+Create package file from an installed package:
+.Dl % pkg create -o /usr/ports/packages/All perl
+.Pp
+Determine which package installed a file:
+.Dl $ pkg which /usr/local/bin/perl
+.Pp
+Audit installed packages for security advisories:
+.Dl $ pkg audit
+.Pp
+Check installed packages for checksum mismatches:
+.Dl # pkg check -s -a
+.Pp
+Check for missing dependencies:
+.Dl # pkg check -d -a
+.Sh SEE ALSO
+.Xr ports 7 ,
+.Xr pkg 8
+.Sh HISTORY
+The
+.Nm
+command first appeared in
+.Fx 9.1 .
+It became the default package tool in
+.Fx 10.0 ,
+replacing the
+pkg_install suite of tools
+.Xr pkg_add 1 ,
+.Xr pkg_info 1 and
+.Xr pkg_create 1 .
diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c
index 0aef3da..1b1a01c 100644
--- a/usr.sbin/pkg/pkg.c
+++ b/usr.sbin/pkg/pkg.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2012-2013 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2012-2014 Baptiste Daroussin <bapt@FreeBSD.org>
+ * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,12 +29,18 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/sbuf.h>
#include <sys/wait.h>
+#define _WITH_GETLINE
#include <archive.h>
#include <archive_entry.h>
+#include <dirent.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <fetch.h>
#include <paths.h>
#include <stdbool.h>
@@ -42,10 +49,37 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <ucl.h>
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
#include "dns_utils.h"
#include "config.h"
+struct sig_cert {
+ char *name;
+ unsigned char *sig;
+ int siglen;
+ unsigned char *cert;
+ int certlen;
+ bool trusted;
+};
+
+typedef enum {
+ HASH_UNKNOWN,
+ HASH_SHA256,
+} hash_t;
+
+struct fingerprint {
+ hash_t type;
+ char *name;
+ char hash[BUFSIZ];
+ STAILQ_ENTRY(fingerprint) next;
+};
+
+STAILQ_HEAD(fingerprint_list, fingerprint);
+
static int
extract_pkg_static(int fd, char *p, int sz)
{
@@ -101,7 +135,7 @@ cleanup:
}
static int
-install_pkg_static(char *path, char *pkgpath)
+install_pkg_static(const char *path, const char *pkgpath, bool force)
{
int pstat;
pid_t pid;
@@ -110,7 +144,12 @@ install_pkg_static(char *path, char *pkgpath)
case -1:
return (-1);
case 0:
- execl(path, "pkg-static", "add", pkgpath, (char *)NULL);
+ if (force)
+ execl(path, "pkg-static", "add", "-f", pkgpath,
+ (char *)NULL);
+ else
+ execl(path, "pkg-static", "add", pkgpath,
+ (char *)NULL);
_exit(1);
default:
break;
@@ -128,51 +167,34 @@ install_pkg_static(char *path, char *pkgpath)
}
static int
-bootstrap_pkg(void)
+fetch_to_fd(const char *url, char *path)
{
struct url *u;
- FILE *remote;
- FILE *config;
- char *site;
struct dns_srvinfo *mirrors, *current;
- /* To store _https._tcp. + hostname + \0 */
- char zone[MAXHOSTNAMELEN + 13];
- char url[MAXPATHLEN];
- char conf[MAXPATHLEN];
- char tmppkg[MAXPATHLEN];
- const char *packagesite, *mirror_type;
- char buf[10240];
- char pkgstatic[MAXPATHLEN];
- int fd, retry, ret, max_retry;
struct url_stat st;
+ FILE *remote;
+ /* To store _https._tcp. + hostname + \0 */
+ int fd;
+ int retry, max_retry;
off_t done, r;
- time_t now;
- time_t last;
+ time_t now, last;
+ char buf[10240];
+ char zone[MAXHOSTNAMELEN + 13];
+ static const char *mirror_type = NULL;
done = 0;
last = 0;
max_retry = 3;
- ret = -1;
- remote = NULL;
- config = NULL;
current = mirrors = NULL;
+ remote = NULL;
- printf("Bootstrapping pkg please wait\n");
-
- if (config_string(PACKAGESITE, &packagesite) != 0) {
- warnx("No PACKAGESITE defined");
- return (-1);
- }
- if (config_string(MIRROR_TYPE, &mirror_type) != 0) {
+ if (mirror_type == NULL && config_string(MIRROR_TYPE, &mirror_type)
+ != 0) {
warnx("No MIRROR_TYPE defined");
return (-1);
}
- snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite);
- snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX",
- getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
-
- if ((fd = mkstemp(tmppkg)) == -1) {
+ if ((fd = mkstemp(path)) == -1) {
warn("mkstemp()");
return (-1);
}
@@ -191,8 +213,10 @@ bootstrap_pkg(void)
}
}
- if (mirrors != NULL)
+ if (mirrors != NULL) {
strlcpy(u->host, current->host, sizeof(u->host));
+ u->port = current->port;
+ }
remote = fetchXGet(u, &st, "");
if (remote == NULL) {
@@ -209,16 +233,13 @@ bootstrap_pkg(void)
}
}
- if (remote == NULL)
- goto fetchfail;
-
while (done < st.size) {
if ((r = fread(buf, 1, sizeof(buf), remote)) < 1)
break;
if (write(fd, buf, r) != r) {
warn("write()");
- goto cleanup;
+ goto fetchfail;
}
done += r;
@@ -230,40 +251,554 @@ bootstrap_pkg(void)
if (ferror(remote))
goto fetchfail;
- if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0)
- ret = install_pkg_static(pkgstatic, tmppkg);
+ goto cleanup;
- snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf",
- getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
+fetchfail:
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ unlink(path);
+ }
- if (access(conf, R_OK) == -1) {
- site = strrchr(url, '/');
- if (site == NULL)
- goto cleanup;
- site[0] = '\0';
- site = strrchr(url, '/');
- if (site == NULL)
- goto cleanup;
- site[0] = '\0';
+cleanup:
+ if (remote != NULL)
+ fclose(remote);
+
+ return fd;
+}
+
+static struct fingerprint *
+parse_fingerprint(ucl_object_t *obj)
+{
+ const ucl_object_t *cur;
+ ucl_object_iter_t it = NULL;
+ const char *function, *fp, *key;
+ struct fingerprint *f;
+ hash_t fct = HASH_UNKNOWN;
+
+ function = fp = NULL;
+
+ while ((cur = ucl_iterate_object(obj, &it, true))) {
+ key = ucl_object_key(cur);
+ if (cur->type != UCL_STRING)
+ continue;
+ if (strcasecmp(key, "function") == 0) {
+ function = ucl_object_tostring(cur);
+ continue;
+ }
+ if (strcasecmp(key, "fingerprint") == 0) {
+ fp = ucl_object_tostring(cur);
+ continue;
+ }
+ }
+
+ if (fp == NULL || function == NULL)
+ return (NULL);
+
+ if (strcasecmp(function, "sha256") == 0)
+ fct = HASH_SHA256;
+
+ if (fct == HASH_UNKNOWN) {
+ warnx("Unsupported hashing function: %s", function);
+ return (NULL);
+ }
+
+ f = calloc(1, sizeof(struct fingerprint));
+ f->type = fct;
+ strlcpy(f->hash, fp, sizeof(f->hash));
+
+ return (f);
+}
+
+static void
+free_fingerprint_list(struct fingerprint_list* list)
+{
+ struct fingerprint *fingerprint, *tmp;
+
+ STAILQ_FOREACH_SAFE(fingerprint, list, next, tmp) {
+ free(fingerprint->name);
+ free(fingerprint);
+ }
+ free(list);
+}
+
+static struct fingerprint *
+load_fingerprint(const char *dir, const char *filename)
+{
+ ucl_object_t *obj = NULL;
+ struct ucl_parser *p = NULL;
+ struct fingerprint *f;
+ char path[MAXPATHLEN];
+
+ f = NULL;
+
+ snprintf(path, MAXPATHLEN, "%s/%s", dir, filename);
+
+ p = ucl_parser_new(0);
+ if (!ucl_parser_add_file(p, path)) {
+ warnx("%s: %s", path, ucl_parser_get_error(p));
+ ucl_parser_free(p);
+ return (NULL);
+ }
+
+ obj = ucl_parser_get_object(p);
+
+ if (obj->type == UCL_OBJECT)
+ f = parse_fingerprint(obj);
+
+ if (f != NULL)
+ f->name = strdup(filename);
- config = fopen(conf, "w+");
- if (config == NULL)
+ ucl_object_unref(obj);
+ ucl_parser_free(p);
+
+ return (f);
+}
+
+static struct fingerprint_list *
+load_fingerprints(const char *path, int *count)
+{
+ DIR *d;
+ struct dirent *ent;
+ struct fingerprint *finger;
+ struct fingerprint_list *fingerprints;
+
+ *count = 0;
+
+ fingerprints = calloc(1, sizeof(struct fingerprint_list));
+ if (fingerprints == NULL)
+ return (NULL);
+ STAILQ_INIT(fingerprints);
+
+ if ((d = opendir(path)) == NULL)
+ return (NULL);
+
+ while ((ent = readdir(d))) {
+ if (strcmp(ent->d_name, ".") == 0 ||
+ strcmp(ent->d_name, "..") == 0)
+ continue;
+ finger = load_fingerprint(path, ent->d_name);
+ if (finger != NULL) {
+ STAILQ_INSERT_TAIL(fingerprints, finger, next);
+ ++(*count);
+ }
+ }
+
+ closedir(d);
+
+ return (fingerprints);
+}
+
+static void
+sha256_hash(unsigned char hash[SHA256_DIGEST_LENGTH],
+ char out[SHA256_DIGEST_LENGTH * 2 + 1])
+{
+ int i;
+
+ for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
+ sprintf(out + (i * 2), "%02x", hash[i]);
+
+ out[SHA256_DIGEST_LENGTH * 2] = '\0';
+}
+
+static void
+sha256_buf(char *buf, size_t len, char out[SHA256_DIGEST_LENGTH * 2 + 1])
+{
+ unsigned char hash[SHA256_DIGEST_LENGTH];
+ SHA256_CTX sha256;
+
+ out[0] = '\0';
+
+ SHA256_Init(&sha256);
+ SHA256_Update(&sha256, buf, len);
+ SHA256_Final(hash, &sha256);
+ sha256_hash(hash, out);
+}
+
+static int
+sha256_fd(int fd, char out[SHA256_DIGEST_LENGTH * 2 + 1])
+{
+ int my_fd;
+ FILE *fp;
+ char buffer[BUFSIZ];
+ unsigned char hash[SHA256_DIGEST_LENGTH];
+ size_t r;
+ int ret;
+ SHA256_CTX sha256;
+
+ my_fd = -1;
+ fp = NULL;
+ r = 0;
+ ret = 1;
+
+ out[0] = '\0';
+
+ /* Duplicate the fd so that fclose(3) does not close it. */
+ if ((my_fd = dup(fd)) == -1) {
+ warnx("dup");
+ goto cleanup;
+ }
+
+ if ((fp = fdopen(my_fd, "rb")) == NULL) {
+ warnx("fdopen");
+ goto cleanup;
+ }
+
+ SHA256_Init(&sha256);
+
+ while ((r = fread(buffer, 1, BUFSIZ, fp)) > 0)
+ SHA256_Update(&sha256, buffer, r);
+
+ if (ferror(fp) != 0) {
+ warnx("fread");
+ goto cleanup;
+ }
+
+ SHA256_Final(hash, &sha256);
+ sha256_hash(hash, out);
+ ret = 0;
+
+cleanup:
+ if (fp != NULL)
+ fclose(fp);
+ else if (my_fd != -1)
+ close(my_fd);
+ (void)lseek(fd, 0, SEEK_SET);
+
+ return (ret);
+}
+
+static EVP_PKEY *
+load_public_key_buf(const unsigned char *cert, int certlen)
+{
+ EVP_PKEY *pkey;
+ BIO *bp;
+ char errbuf[1024];
+
+ bp = BIO_new_mem_buf(__DECONST(void *, cert), certlen);
+
+ if ((pkey = PEM_read_bio_PUBKEY(bp, NULL, NULL, NULL)) == NULL)
+ warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+
+ BIO_free(bp);
+
+ return (pkey);
+}
+
+static bool
+rsa_verify_cert(int fd, const unsigned char *key, int keylen,
+ unsigned char *sig, int siglen)
+{
+ EVP_MD_CTX *mdctx;
+ EVP_PKEY *pkey;
+ char sha256[(SHA256_DIGEST_LENGTH * 2) + 2];
+ char errbuf[1024];
+ bool ret;
+
+ pkey = NULL;
+ mdctx = NULL;
+ ret = false;
+
+ /* Compute SHA256 of the package. */
+ if (lseek(fd, 0, 0) == -1) {
+ warn("lseek");
+ goto cleanup;
+ }
+ if ((sha256_fd(fd, sha256)) == -1) {
+ warnx("Error creating SHA256 hash for package");
+ goto cleanup;
+ }
+
+ if ((pkey = load_public_key_buf(key, keylen)) == NULL) {
+ warnx("Error reading public key");
+ goto cleanup;
+ }
+
+ /* Verify signature of the SHA256(pkg) is valid. */
+ if ((mdctx = EVP_MD_CTX_create()) == NULL) {
+ warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+ goto error;
+ }
+
+ if (EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pkey) != 1) {
+ warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+ goto error;
+ }
+ if (EVP_DigestVerifyUpdate(mdctx, sha256, strlen(sha256)) != 1) {
+ warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+ goto error;
+ }
+
+ if (EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) {
+ warnx("%s", ERR_error_string(ERR_get_error(), errbuf));
+ goto error;
+ }
+
+ ret = true;
+ printf("done\n");
+ goto cleanup;
+
+error:
+ printf("failed\n");
+
+cleanup:
+ if (pkey)
+ EVP_PKEY_free(pkey);
+ if (mdctx)
+ EVP_MD_CTX_destroy(mdctx);
+ ERR_free_strings();
+
+ return (ret);
+}
+
+static struct sig_cert *
+parse_cert(int fd) {
+ int my_fd;
+ struct sig_cert *sc;
+ FILE *fp;
+ struct sbuf *buf, *sig, *cert;
+ char *line;
+ size_t linecap;
+ ssize_t linelen;
+
+ buf = NULL;
+ my_fd = -1;
+ sc = NULL;
+ line = NULL;
+ linecap = 0;
+
+ if (lseek(fd, 0, 0) == -1) {
+ warn("lseek");
+ return (NULL);
+ }
+
+ /* Duplicate the fd so that fclose(3) does not close it. */
+ if ((my_fd = dup(fd)) == -1) {
+ warnx("dup");
+ return (NULL);
+ }
+
+ if ((fp = fdopen(my_fd, "rb")) == NULL) {
+ warn("fdopen");
+ close(my_fd);
+ return (NULL);
+ }
+
+ sig = sbuf_new_auto();
+ cert = sbuf_new_auto();
+
+ while ((linelen = getline(&line, &linecap, fp)) > 0) {
+ if (strcmp(line, "SIGNATURE\n") == 0) {
+ buf = sig;
+ continue;
+ } else if (strcmp(line, "CERT\n") == 0) {
+ buf = cert;
+ continue;
+ } else if (strcmp(line, "END\n") == 0) {
+ break;
+ }
+ if (buf != NULL)
+ sbuf_bcat(buf, line, linelen);
+ }
+
+ fclose(fp);
+
+ /* Trim out unrelated trailing newline */
+ sbuf_setpos(sig, sbuf_len(sig) - 1);
+
+ sbuf_finish(sig);
+ sbuf_finish(cert);
+
+ sc = calloc(1, sizeof(struct sig_cert));
+ sc->siglen = sbuf_len(sig);
+ sc->sig = calloc(1, sc->siglen);
+ memcpy(sc->sig, sbuf_data(sig), sc->siglen);
+
+ sc->certlen = sbuf_len(cert);
+ sc->cert = strdup(sbuf_data(cert));
+
+ sbuf_delete(sig);
+ sbuf_delete(cert);
+
+ return (sc);
+}
+
+static bool
+verify_signature(int fd_pkg, int fd_sig)
+{
+ struct fingerprint_list *trusted, *revoked;
+ struct fingerprint *fingerprint;
+ struct sig_cert *sc;
+ bool ret;
+ int trusted_count, revoked_count;
+ const char *fingerprints;
+ char path[MAXPATHLEN];
+ char hash[SHA256_DIGEST_LENGTH * 2 + 1];
+
+ sc = NULL;
+ trusted = revoked = NULL;
+ ret = false;
+
+ /* Read and parse fingerprints. */
+ if (config_string(FINGERPRINTS, &fingerprints) != 0) {
+ warnx("No CONFIG_FINGERPRINTS defined");
+ goto cleanup;
+ }
+
+ snprintf(path, MAXPATHLEN, "%s/trusted", fingerprints);
+ if ((trusted = load_fingerprints(path, &trusted_count)) == NULL) {
+ warnx("Error loading trusted certificates");
+ goto cleanup;
+ }
+
+ if (trusted_count == 0 || trusted == NULL) {
+ fprintf(stderr, "No trusted certificates found.\n");
+ goto cleanup;
+ }
+
+ snprintf(path, MAXPATHLEN, "%s/revoked", fingerprints);
+ if ((revoked = load_fingerprints(path, &revoked_count)) == NULL) {
+ warnx("Error loading revoked certificates");
+ goto cleanup;
+ }
+
+ /* Read certificate and signature in. */
+ if ((sc = parse_cert(fd_sig)) == NULL) {
+ warnx("Error parsing certificate");
+ goto cleanup;
+ }
+ /* Explicitly mark as non-trusted until proven otherwise. */
+ sc->trusted = false;
+
+ /* Parse signature and pubkey out of the certificate */
+ sha256_buf(sc->cert, sc->certlen, hash);
+
+ /* Check if this hash is revoked */
+ if (revoked != NULL) {
+ STAILQ_FOREACH(fingerprint, revoked, next) {
+ if (strcasecmp(fingerprint->hash, hash) == 0) {
+ fprintf(stderr, "The package was signed with "
+ "revoked certificate %s\n",
+ fingerprint->name);
+ goto cleanup;
+ }
+ }
+ }
+
+ STAILQ_FOREACH(fingerprint, trusted, next) {
+ if (strcasecmp(fingerprint->hash, hash) == 0) {
+ sc->trusted = true;
+ sc->name = strdup(fingerprint->name);
+ break;
+ }
+ }
+
+ if (sc->trusted == false) {
+ fprintf(stderr, "No trusted fingerprint found matching "
+ "package's certificate\n");
+ goto cleanup;
+ }
+
+ /* Verify the signature. */
+ printf("Verifying signature with trusted certificate %s... ", sc->name);
+ if (rsa_verify_cert(fd_pkg, sc->cert, sc->certlen, sc->sig,
+ sc->siglen) == false) {
+ fprintf(stderr, "Signature is not valid\n");
+ goto cleanup;
+ }
+
+ ret = true;
+
+cleanup:
+ if (trusted)
+ free_fingerprint_list(trusted);
+ if (revoked)
+ free_fingerprint_list(revoked);
+ if (sc) {
+ free(sc->cert);
+ free(sc->sig);
+ free(sc->name);
+ free(sc);
+ }
+
+ return (ret);
+}
+
+static int
+bootstrap_pkg(bool force)
+{
+ int fd_pkg, fd_sig;
+ int ret;
+ char url[MAXPATHLEN];
+ char tmppkg[MAXPATHLEN];
+ char tmpsig[MAXPATHLEN];
+ const char *packagesite;
+ const char *signature_type;
+ char pkgstatic[MAXPATHLEN];
+
+ fd_sig = -1;
+ ret = -1;
+
+ if (config_string(PACKAGESITE, &packagesite) != 0) {
+ warnx("No PACKAGESITE defined");
+ return (-1);
+ }
+
+ if (config_string(SIGNATURE_TYPE, &signature_type) != 0) {
+ warnx("Error looking up SIGNATURE_TYPE");
+ return (-1);
+ }
+
+ printf("Bootstrapping pkg from %s, please wait...\n", packagesite);
+
+ /* Support pkg+http:// for PACKAGESITE which is the new format
+ in 1.2 to avoid confusion on why http://pkg.FreeBSD.org has
+ no A record. */
+ if (strncmp(URL_SCHEME_PREFIX, packagesite,
+ strlen(URL_SCHEME_PREFIX)) == 0)
+ packagesite += strlen(URL_SCHEME_PREFIX);
+ snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite);
+
+ snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX",
+ getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
+
+ if ((fd_pkg = fetch_to_fd(url, tmppkg)) == -1)
+ goto fetchfail;
+
+ if (signature_type != NULL &&
+ strcasecmp(signature_type, "FINGERPRINTS") == 0) {
+ snprintf(tmpsig, MAXPATHLEN, "%s/pkg.txz.sig.XXXXXX",
+ getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP);
+ snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz.sig",
+ packagesite);
+
+ if ((fd_sig = fetch_to_fd(url, tmpsig)) == -1) {
+ fprintf(stderr, "Signature for pkg not available.\n");
+ goto fetchfail;
+ }
+
+ if (verify_signature(fd_pkg, fd_sig) == false)
goto cleanup;
- fprintf(config, "packagesite: %s\n", url);
- fclose(config);
}
+ if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
+ ret = install_pkg_static(pkgstatic, tmppkg, force);
+
goto cleanup;
fetchfail:
warnx("Error fetching %s: %s", url, fetchLastErrString);
- fprintf(stderr, "A pre-built version of pkg could not be found for your system.\n");
- fprintf(stderr, "Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.\n");
+ fprintf(stderr, "A pre-built version of pkg could not be found for "
+ "your system.\n");
+ fprintf(stderr, "Consider changing PACKAGESITE or installing it from "
+ "ports: 'ports-mgmt/pkg'.\n");
cleanup:
- if (remote != NULL)
- fclose(remote);
- close(fd);
+ if (fd_sig != -1) {
+ close(fd_sig);
+ unlink(tmpsig);
+ }
+ close(fd_pkg);
unlink(tmppkg);
return (ret);
@@ -273,6 +808,11 @@ static const char confirmation_message[] =
"The package management tool is not yet installed on your system.\n"
"Do you want to fetch and install it now? [y/N]: ";
+static const char non_interactive_message[] =
+"The package management tool is not yet installed on your system.\n"
+"Please set ASSUME_ALWAYS_YES=yes environment variable to be able to bootstrap "
+"in non-interactive (stdin not being a tty)\n";
+
static int
pkg_query_yes_no(void)
{
@@ -291,16 +831,71 @@ pkg_query_yes_no(void)
return (ret);
}
+static int
+bootstrap_pkg_local(const char *pkgpath, bool force)
+{
+ char path[MAXPATHLEN];
+ char pkgstatic[MAXPATHLEN];
+ const char *signature_type;
+ int fd_pkg, fd_sig, ret;
+
+ fd_sig = -1;
+ ret = -1;
+
+ fd_pkg = open(pkgpath, O_RDONLY);
+ if (fd_pkg == -1)
+ err(EXIT_FAILURE, "Unable to open %s", pkgpath);
+
+ if (config_string(SIGNATURE_TYPE, &signature_type) != 0) {
+ warnx("Error looking up SIGNATURE_TYPE");
+ return (-1);
+ }
+ if (signature_type != NULL &&
+ strcasecmp(signature_type, "FINGERPRINTS") == 0) {
+ snprintf(path, sizeof(path), "%s.sig", pkgpath);
+
+ if ((fd_sig = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, "Signature for pkg not available.\n");
+ goto cleanup;
+ }
+
+ if (verify_signature(fd_pkg, fd_sig) == false)
+ goto cleanup;
+ }
+
+ if ((ret = extract_pkg_static(fd_pkg, pkgstatic, MAXPATHLEN)) == 0)
+ ret = install_pkg_static(pkgstatic, pkgpath, force);
+
+cleanup:
+ close(fd_pkg);
+ if (fd_sig != -1)
+ close(fd_sig);
+
+ return (ret);
+}
+
int
-main(__unused int argc, char *argv[])
+main(int argc, char *argv[])
{
char pkgpath[MAXPATHLEN];
- bool yes = false;
+ const char *pkgarg;
+ bool bootstrap_only, force, yes;
+
+ bootstrap_only = false;
+ force = false;
+ pkgarg = NULL;
+ yes = false;
snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg",
getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
- if (access(pkgpath, X_OK) == -1) {
+ if (argc > 1 && strcmp(argv[1], "bootstrap") == 0) {
+ bootstrap_only = true;
+ if (argc == 3 && strcmp(argv[2], "-f") == 0)
+ force = true;
+ }
+
+ if ((bootstrap_only && force) || access(pkgpath, X_OK) == -1) {
/*
* To allow 'pkg -N' to be used as a reliable test for whether
* a system is configured to use pkg, don't bootstrap pkg
@@ -309,24 +904,51 @@ main(__unused int argc, char *argv[])
if (argv[1] != NULL && strcmp(argv[1], "-N") == 0)
errx(EXIT_FAILURE, "pkg is not installed");
+ config_init();
+
+ if (argc > 1 && strcmp(argv[1], "add") == 0) {
+ if (argc > 2 && strcmp(argv[2], "-f") == 0) {
+ force = true;
+ pkgarg = argv[3];
+ } else
+ pkgarg = argv[2];
+ if (pkgarg == NULL) {
+ fprintf(stderr, "Path to pkg.txz required\n");
+ exit(EXIT_FAILURE);
+ }
+ if (access(pkgarg, R_OK) == -1) {
+ fprintf(stderr, "No such file: %s\n", pkgarg);
+ exit(EXIT_FAILURE);
+ }
+ if (bootstrap_pkg_local(pkgarg, force) != 0)
+ exit(EXIT_FAILURE);
+ exit(EXIT_SUCCESS);
+ }
/*
* Do not ask for confirmation if either of stdin or stdout is
* not tty. Check the environment to see if user has answer
* tucked in there already.
*/
- config_init();
config_bool(ASSUME_ALWAYS_YES, &yes);
if (!yes) {
- printf("%s", confirmation_message);
- if (!isatty(fileno(stdin)))
+ if (!isatty(fileno(stdin))) {
+ fprintf(stderr, non_interactive_message);
exit(EXIT_FAILURE);
+ }
+ printf("%s", confirmation_message);
if (pkg_query_yes_no() == 0)
exit(EXIT_FAILURE);
}
- if (bootstrap_pkg() != 0)
+ if (bootstrap_pkg(force) != 0)
exit(EXIT_FAILURE);
config_finish();
+
+ if (bootstrap_only)
+ exit(EXIT_SUCCESS);
+ } else if (bootstrap_only) {
+ printf("pkg already bootstrapped at %s\n", pkgpath);
+ exit(EXIT_SUCCESS);
}
execv(pkgpath, argv);
diff --git a/usr.sbin/pkg_install/Makefile b/usr.sbin/pkg_install/Makefile
deleted file mode 100644
index bf1a213..0000000
--- a/usr.sbin/pkg_install/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# $FreeBSD$
-
-.include <bsd.own.mk>
-
-SUBDIR= lib add create delete info updating version
-
-.include <bsd.subdir.mk>
-
-DATE!= grep PKG_INSTALL_VERSION ${.CURDIR}/lib/lib.h | sed 's|.*[ ]||'
-
-distfile: clean
- @(cd ${.CURDIR}/..; \
- cp -r pkg_install pkg_install-${DATE}; \
- tar -czf pkg_install/pkg_install-${DATE}.tar.gz \
- --exclude .#* --exclude *~ --exclude CVS \
- --exclude .svn --exclude pkg_install-*.tar.gz \
- pkg_install-${DATE}; \
- rm -rf pkg_install-${DATE})
-
-
diff --git a/usr.sbin/pkg_install/Makefile.inc b/usr.sbin/pkg_install/Makefile.inc
deleted file mode 100644
index 2fa20aa..0000000
--- a/usr.sbin/pkg_install/Makefile.inc
+++ /dev/null
@@ -1,17 +0,0 @@
-# $FreeBSD$
-
-.include <bsd.own.mk>
-
-LIBINSTALL= ${.OBJDIR}/../lib/libinstall.a
-
-DPADD+= ${LIBUTIL}
-LDADD+= -lutil
-
-.if ${MK_OPENSSL} != "no" && \
- defined(LDADD) && ${LDADD:M-lfetch} != ""
-DPADD+= ${LIBSSL} ${LIBCRYPTO}
-LDADD+= -lssl -lcrypto
-.endif
-
-# Inherit BINDIR from one level up.
-.include "../Makefile.inc"
diff --git a/usr.sbin/pkg_install/README b/usr.sbin/pkg_install/README
deleted file mode 100644
index 874b588..0000000
--- a/usr.sbin/pkg_install/README
+++ /dev/null
@@ -1,10 +0,0 @@
-$FreeBSD$
-
-This is the pkg_install suite of tools for doing maintenance of
-software "packages". More documentation is available in the man pages
-for each individual command.
-
-This code was written by Jordan Hubbard for FreeBSD, snatched and
-mildly reshaped by John Kohl in NetBSD and the changes taken back into
-FreeBSD again by Jordan, who then proceeded to add another couple
-of dozen features on top. Whee! :-)
diff --git a/usr.sbin/pkg_install/add/Makefile b/usr.sbin/pkg_install/add/Makefile
deleted file mode 100644
index 89988e7..0000000
--- a/usr.sbin/pkg_install/add/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# $FreeBSD$
-
-PROG= pkg_add
-SRCS= main.c perform.c futil.c extract.c
-
-CFLAGS+= -I${.CURDIR}/../lib
-
-WARNS?= 3
-WFORMAT?= 1
-
-DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
-LDADD= ${LIBINSTALL} -lfetch -lmd
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/add/Makefile.depend b/usr.sbin/pkg_install/add/Makefile.depend
deleted file mode 100644
index 9507bb2..0000000
--- a/usr.sbin/pkg_install/add/Makefile.depend
+++ /dev/null
@@ -1,24 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libfetch \
- lib/libmd \
- lib/libutil \
- secure/lib/libcrypto \
- secure/lib/libssl \
- usr.sbin/pkg_install/lib \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/add/add.h b/usr.sbin/pkg_install/add/add.h
deleted file mode 100644
index e796120..0000000
--- a/usr.sbin/pkg_install/add/add.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Include and define various things wanted by the add command.
- *
- */
-
-#ifndef _INST_ADD_H_INCLUDE
-#define _INST_ADD_H_INCLUDE
-
-typedef enum { NORMAL, MASTER, SLAVE } add_mode_t;
-
-extern char *Prefix;
-extern Boolean PrefixRecursive;
-extern Boolean NoInstall;
-extern Boolean NoRecord;
-extern Boolean FailOnAlreadyInstalled;
-extern Boolean KeepPackage;
-extern Boolean IgnoreDeps;
-extern char *Mode;
-extern char *Owner;
-extern char *Group;
-extern char *Directory;
-extern char *PkgName;
-extern char *PkgAddCmd;
-extern char FirstPen[];
-extern add_mode_t AddMode;
-
-int make_hierarchy(char *, Boolean);
-void extract_plist(const char *, Package *);
-void apply_perms(const char *, const char *);
-
-#endif /* _INST_ADD_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/add/extract.c b/usr.sbin/pkg_install/add/extract.c
deleted file mode 100644
index 9913126..0000000
--- a/usr.sbin/pkg_install/add/extract.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the package extraction code for the add module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <ctype.h>
-#include <err.h>
-#include "lib.h"
-#include "add.h"
-
-
-#define STARTSTRING "/usr/bin/tar cf -"
-#define TOOBIG(str) \
- (((int)strlen(str) + FILENAME_MAX + where_count > maxargs) ||\
- ((int)strlen(str) + FILENAME_MAX + perm_count > maxargs))
-
-#define PUSHOUT(todir) /* push out string */ \
- if (where_count > (int)sizeof(STARTSTRING)-1) { \
- strcat(where_args, "|/usr/bin/tar --unlink -xpPf - -C "); \
- strcat(where_args, todir); \
- if (system(where_args)) { \
- cleanup(0); \
- errx(2, "%s: can not invoke %ld byte tar pipeline: %s", \
- __func__, (long)strlen(where_args), where_args); \
- } \
- strcpy(where_args, STARTSTRING); \
- where_count = sizeof(STARTSTRING)-1; \
- } \
- if (perm_count) { \
- apply_perms(todir, perm_args); \
- perm_args[0] = 0;\
- perm_count = 0; \
- }
-
-static void
-rollback(const char *name, const char *home, PackingList start, PackingList stop)
-{
- PackingList q;
- char try[FILENAME_MAX], bup[FILENAME_MAX];
- const char *dir;
- char *prefix = NULL;
-
- dir = home;
- for (q = start; q != stop; q = q->next) {
- if (q->type == PLIST_FILE) {
- snprintf(try, FILENAME_MAX, "%s/%s", dir, q->name);
- if (make_preserve_name(bup, FILENAME_MAX, name, try) && fexists(bup)) {
- (void)chflags(try, 0);
- (void)unlink(try);
- if (rename(bup, try))
- warnx("rollback: unable to rename %s back to %s", bup, try);
- }
- }
- else if (q->type == PLIST_CWD) {
- if (!prefix)
- prefix = q->name;
- if (q->name == NULL)
- q->name = prefix;
- else if (strcmp(q->name, "."))
- dir = q->name;
- else
- dir = home;
- }
- }
-}
-
-#define add_char(buf, len, pos, ch) do {\
- if ((pos) < (len)) { \
- buf[(pos)] = (ch); \
- buf[(pos) + 1] = '\0'; \
- } \
- ++(pos); \
-} while (0)
-
-static int
-add_arg(char *buf, int len, const char *str)
-{
- int i = 0;
-
- add_char(buf, len, i, ' ');
- for (; *str != '\0'; ++str) {
- if (!isalnum(*str) && *str != '/' && *str != '.' && *str != '-')
- add_char(buf, len, i, '\\');
- add_char(buf, len, i, *str);
- }
- return (i);
-}
-
-void
-extract_plist(const char *home, Package *pkg)
-{
- PackingList p = pkg->head;
- char *last_file, *prefix = NULL;
- char *where_args, *perm_args, *last_chdir;
- long maxargs;
- int where_count = 0, perm_count = 0, add_count;
- Boolean preserve;
-
- maxargs = sysconf(_SC_ARG_MAX) / 2; /* Just use half the argument space */
- where_args = alloca(maxargs);
- if (!where_args) {
- cleanup(0);
- errx(2, "%s: can't get argument list space", __func__);
- }
- perm_args = alloca(maxargs);
- if (!perm_args) {
- cleanup(0);
- errx(2, "%s: can't get argument list space", __func__);
- }
-
- strcpy(where_args, STARTSTRING);
- where_count = sizeof(STARTSTRING)-1;
- perm_args[0] = 0;
-
- last_chdir = 0;
- preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
-
- /* Reset the world */
- Owner = NULL;
- Group = NULL;
- Mode = NULL;
- last_file = NULL;
- Directory = (char *)home;
-
- /* Do it */
- while (p) {
- char cmd[FILENAME_MAX];
-
- switch(p->type) {
- case PLIST_NAME:
- PkgName = p->name;
- if (Verbose)
- printf("extract: Package name is %s\n", p->name);
- break;
-
- case PLIST_FILE:
- last_file = p->name;
- if (Verbose)
- printf("extract: %s/%s\n", Directory, p->name);
- if (!Fake) {
- char try[FILENAME_MAX];
-
- /* first try to rename it into place */
- snprintf(try, FILENAME_MAX, "%s/%s", Directory, p->name);
- if (fexists(try)) {
- (void)chflags(try, 0); /* XXX hack - if truly immutable, rename fails */
- if (preserve && PkgName) {
- char pf[FILENAME_MAX];
-
- if (make_preserve_name(pf, FILENAME_MAX, PkgName, try)) {
- if (rename(try, pf)) {
- warnx(
- "unable to back up %s to %s, aborting pkg_add",
- try, pf);
- rollback(PkgName, home, pkg->head, p);
- return;
- }
- }
- }
- }
- if (rename(p->name, try) == 0) {
- /* try to add to list of perms to be changed and run in bulk. */
- if (p->name[0] == '/' || TOOBIG(p->name)) {
- PUSHOUT(Directory);
- }
- add_count = add_arg(&perm_args[perm_count], maxargs - perm_count, p->name);
- if (add_count < 0 || add_count >= maxargs - perm_count) {
- cleanup(0);
- errx(2, "%s: oops, miscounted strings!", __func__);
- }
- perm_count += add_count;
- }
- else {
- /* rename failed, try copying with a big tar command */
- if (last_chdir != Directory) {
- if (last_chdir == NULL) {
- PUSHOUT(Directory);
- } else {
- PUSHOUT(last_chdir);
- }
- last_chdir = Directory;
- }
- else if (p->name[0] == '/' || TOOBIG(p->name)) {
- PUSHOUT(Directory);
- }
- add_count = add_arg(&where_args[where_count], maxargs - where_count, p->name);
- if (add_count < 0 || add_count >= maxargs - where_count) {
- cleanup(0);
- errx(2, "%s: oops, miscounted strings!", __func__);
- }
- where_count += add_count;
- add_count = add_arg(&perm_args[perm_count], maxargs - perm_count, p->name);
- if (add_count < 0 || add_count >= maxargs - perm_count) {
- cleanup(0);
- errx(2, "%s: oops, miscounted strings!", __func__);
- }
- perm_count += add_count;
- }
- }
- break;
-
- case PLIST_CWD:
- if (!prefix)
- prefix = p->name;
- if (p->name == NULL)
- p->name = strdup(prefix);
- if (Verbose)
- printf("extract: CWD to %s\n", p->name);
- PUSHOUT(Directory);
- if (strcmp(p->name, ".")) {
- if (!Fake && make_hierarchy(p->name, TRUE) == FAIL) {
- cleanup(0);
- errx(2, "%s: unable to cwd to '%s'", __func__, p->name);
- }
- Directory = p->name;
- }
- else
- Directory = (char *)home;
- break;
-
- case PLIST_CMD:
- if ((strstr(p->name, "%B") || strstr(p->name, "%F") ||
- strstr(p->name, "%f")) && last_file == NULL) {
- cleanup(0);
- errx(2, "%s: no last file specified for '%s' command",
- __func__, p->name);
- }
- if (strstr(p->name, "%D") && Directory == NULL) {
- cleanup(0);
- errx(2, "%s: no directory specified for '%s' command",
- __func__, p->name);
- }
- format_cmd(cmd, FILENAME_MAX, p->name, Directory, last_file);
- PUSHOUT(Directory);
- if (Verbose)
- printf("extract: execute '%s'\n", cmd);
- if (!Fake && system(cmd))
- warnx("command '%s' failed", cmd);
- break;
-
- case PLIST_CHMOD:
- PUSHOUT(Directory);
- Mode = p->name;
- break;
-
- case PLIST_CHOWN:
- PUSHOUT(Directory);
- Owner = p->name;
- break;
-
- case PLIST_CHGRP:
- PUSHOUT(Directory);
- Group = p->name;
- break;
-
- case PLIST_COMMENT: /* FALLTHROUGH */
- case PLIST_NOINST:
- break;
-
- case PLIST_IGNORE:
- p = p->next;
- break;
-
- default:
- break;
- }
- p = p->next;
- }
- PUSHOUT(Directory);
-}
diff --git a/usr.sbin/pkg_install/add/futil.c b/usr.sbin/pkg_install/add/futil.c
deleted file mode 100644
index 82217f5..0000000
--- a/usr.sbin/pkg_install/add/futil.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Miscellaneous file access utilities.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <err.h>
-#include "lib.h"
-#include "add.h"
-
-/*
- * Assuming dir is a desired directory name, make it and all intervening
- * directories necessary.
- */
-
-int
-make_hierarchy(char *dir, Boolean set_perm)
-{
- char *cp1, *cp2;
-
- if (dir[0] == '/')
- cp1 = cp2 = dir + 1;
- else
- cp1 = cp2 = dir;
- while (cp2) {
- if ((cp2 = strchr(cp1, '/')) !=NULL )
- *cp2 = '\0';
- if (fexists(dir)) {
- if (!isdir(dir)) {
- if (cp2)
- *cp2 = '/';
- return FAIL;
- }
- }
- else {
- if (mkdir(dir, 0777) < 0) {
- if (cp2)
- *cp2 = '/';
- return FAIL;
- }
- if (set_perm)
- apply_perms(NULL, dir);
- }
- /* Put it back */
- if (cp2) {
- *cp2 = '/';
- cp1 = cp2 + 1;
- }
- }
- return SUCCESS;
-}
-
-/* Using permission defaults, apply them as necessary */
-void
-apply_perms(const char *dir, const char *arg)
-{
- const char *cd_to;
-
- if (!dir || *arg == '/') /* absolute path? */
- cd_to = "/";
- else
- cd_to = dir;
-
- if (Mode)
- if (vsystem("cd %s && /bin/chmod -R %s %s", cd_to, Mode, arg))
- warnx("couldn't change modes of '%s' to '%s'", arg, Mode);
- if (Owner && Group) {
- if (vsystem("cd %s && /usr/sbin/chown -R %s:%s %s", cd_to, Owner, Group, arg))
- warnx("couldn't change owner/group of '%s' to '%s:%s'",
- arg, Owner, Group);
- return;
- }
- if (Owner) {
- if (vsystem("cd %s && /usr/sbin/chown -R %s %s", cd_to, Owner, arg))
- warnx("couldn't change owner of '%s' to '%s'", arg, Owner);
- return;
- } else if (Group)
- if (vsystem("cd %s && /usr/bin/chgrp -R %s %s", cd_to, Group, arg))
- warnx("couldn't change group of '%s' to '%s'", arg, Group);
-}
-
diff --git a/usr.sbin/pkg_install/add/main.c b/usr.sbin/pkg_install/add/main.c
deleted file mode 100644
index 548f92e..0000000
--- a/usr.sbin/pkg_install/add/main.c
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- *
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the add module.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <err.h>
-#include <getopt.h>
-
-#include "lib.h"
-#include "add.h"
-
-char *Prefix = NULL;
-Boolean PrefixRecursive = FALSE;
-char *Chroot = NULL;
-Boolean NoInstall = FALSE;
-Boolean NoRecord = FALSE;
-Boolean Remote = FALSE;
-Boolean KeepPackage = FALSE;
-Boolean FailOnAlreadyInstalled = TRUE;
-Boolean IgnoreDeps = FALSE;
-
-char *Mode = NULL;
-char *Owner = NULL;
-char *Group = NULL;
-char *PkgName = NULL;
-char *PkgAddCmd = NULL;
-char *Directory = NULL;
-char FirstPen[FILENAME_MAX];
-add_mode_t AddMode = NORMAL;
-
-char **pkgs;
-
-struct {
- int lowver; /* Lowest version number to match */
- int hiver; /* Highest version number to match */
- const char *directory; /* Directory it lives in */
-} releases[] = {
- { 410000, 410000, "/packages-4.1-release" },
- { 420000, 420000, "/packages-4.2-release" },
- { 430000, 430000, "/packages-4.3-release" },
- { 440000, 440000, "/packages-4.4-release" },
- { 450000, 450000, "/packages-4.5-release" },
- { 460000, 460001, "/packages-4.6-release" },
- { 460002, 460099, "/packages-4.6.2-release" },
- { 470000, 470099, "/packages-4.7-release" },
- { 480000, 480099, "/packages-4.8-release" },
- { 490000, 490099, "/packages-4.9-release" },
- { 491000, 491099, "/packages-4.10-release" },
- { 492000, 492099, "/packages-4.11-release" },
- { 500000, 500099, "/packages-5.0-release" },
- { 501000, 501099, "/packages-5.1-release" },
- { 502000, 502009, "/packages-5.2-release" },
- { 502010, 502099, "/packages-5.2.1-release" },
- { 503000, 503099, "/packages-5.3-release" },
- { 504000, 504099, "/packages-5.4-release" },
- { 505000, 505099, "/packages-5.5-release" },
- { 600000, 600099, "/packages-6.0-release" },
- { 601000, 601099, "/packages-6.1-release" },
- { 602000, 602099, "/packages-6.2-release" },
- { 603000, 603099, "/packages-6.3-release" },
- { 604000, 604099, "/packages-6.4-release" },
- { 700000, 700099, "/packages-7.0-release" },
- { 701000, 701099, "/packages-7.1-release" },
- { 702000, 702099, "/packages-7.2-release" },
- { 703000, 703099, "/packages-7.3-release" },
- { 704000, 704099, "/packages-7.4-release" },
- { 800000, 800499, "/packages-8.0-release" },
- { 801000, 801499, "/packages-8.1-release" },
- { 802000, 802499, "/packages-8.2-release" },
- { 803000, 803499, "/packages-8.3-release" },
- { 900000, 900499, "/packages-9.0-release" },
- { 901000, 901499, "/packages-9.1-release" },
- { 902000, 902499, "/packages-9.2-release" },
- { 300000, 399000, "/packages-3-stable" },
- { 400000, 499000, "/packages-4-stable" },
- { 502100, 502128, "/packages-5-current" },
- { 503100, 599000, "/packages-5-stable" },
- { 600100, 699000, "/packages-6-stable" },
- { 700100, 799000, "/packages-7-stable" },
- { 800500, 899000, "/packages-8-stable" },
- { 900500, 999000, "/packages-9-stable" },
- { 1000000, 1099000, "/packages-10-current" },
- { 0, 9999999, "/packages-current" },
- { 0, 0, NULL }
-};
-
-static char *getpackagesite(void);
-int getosreldate(void);
-
-static void usage(void);
-
-static char opts[] = "hviIRfFnrp:P:SMt:C:K";
-static struct option longopts[] = {
- { "chroot", required_argument, NULL, 'C' },
- { "dry-run", no_argument, NULL, 'n' },
- { "force", no_argument, NULL, 'f' },
- { "help", no_argument, NULL, 'h' },
- { "keep", no_argument, NULL, 'K' },
- { "master", no_argument, NULL, 'M' },
- { "no-deps", no_argument, NULL, 'i' },
- { "no-record", no_argument, NULL, 'R' },
- { "no-script", no_argument, NULL, 'I' },
- { "prefix", required_argument, NULL, 'p' },
- { "remote", no_argument, NULL, 'r' },
- { "template", required_argument, NULL, 't' },
- { "slave", no_argument, NULL, 'S' },
- { "verbose", no_argument, NULL, 'v' },
- { NULL, 0, NULL, 0 }
-};
-
-int
-main(int argc, char **argv)
-{
- int ch, error;
- char **start;
- char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr;
- static char temppackageroot[MAXPATHLEN];
- static char pkgaddpath[MAXPATHLEN];
-
- if (*argv[0] != '/' && strchr(argv[0], '/') != NULL)
- PkgAddCmd = realpath(argv[0], pkgaddpath);
- else
- PkgAddCmd = argv[0];
-
- start = argv;
- while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
- switch(ch) {
- case 'v':
- Verbose++;
- break;
-
- case 'p':
- Prefix = optarg;
- PrefixRecursive = FALSE;
- break;
-
- case 'P':
- Prefix = optarg;
- PrefixRecursive = TRUE;
- break;
-
- case 'I':
- NoInstall = TRUE;
- break;
-
- case 'R':
- NoRecord = TRUE;
- break;
-
- case 'f':
- Force = TRUE;
- break;
-
- case 'F':
- FailOnAlreadyInstalled = FALSE;
- break;
-
- case 'K':
- KeepPackage = TRUE;
- break;
-
- case 'n':
- Fake = TRUE;
- break;
-
- case 'r':
- Remote = TRUE;
- break;
-
- case 't':
- if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen))
- errx(1, "-t Argument too long.");
- break;
-
- case 'S':
- AddMode = SLAVE;
- break;
-
- case 'M':
- AddMode = MASTER;
- break;
-
- case 'C':
- Chroot = optarg;
- break;
-
- case 'i':
- IgnoreDeps = TRUE;
- break;
-
- case 'h':
- default:
- usage();
- break;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (AddMode != SLAVE) {
- pkgs = (char **)malloc((argc+1) * sizeof(char *));
- for (ch = 0; ch <= argc; pkgs[ch++] = NULL) ;
-
- /* Get all the remaining package names, if any */
- for (ch = 0; *argv; ch++, argv++) {
- char temp[MAXPATHLEN];
- if (Remote) {
- if ((packagesite = getpackagesite()) == NULL)
- errx(1, "package name too long");
- if (strlcpy(temppackageroot, packagesite,
- sizeof(temppackageroot)) >= sizeof(temppackageroot))
- errx(1, "package name too long");
- if (strlcat(temppackageroot, *argv, sizeof(temppackageroot))
- >= sizeof(temppackageroot))
- errx(1, "package name too long");
- remotepkg = temppackageroot;
- if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' &&
- (ptr[2] == 'b' || ptr[2] == 'g' || ptr[2] == 'x') &&
- ptr[3] == 'z' && !ptr[4])) {
- if (getenv("PACKAGESUFFIX")) {
- if (strlcat(remotepkg, getenv("PACKAGESUFFIX"),
- sizeof(temppackageroot)) >= sizeof(temppackageroot))
- errx(1, "package name too long");
- } else {
- if (strlcat(remotepkg, ".tbz",
- sizeof(temppackageroot)) >= sizeof(temppackageroot))
- errx(1, "package name too long");
- }
- }
- }
- if (!strcmp(*argv, "-")) /* stdin? */
- pkgs[ch] = (char *)"-";
- else if (isURL(*argv)) { /* preserve URLs */
- if (strlcpy(temp, *argv, sizeof(temp)) >= sizeof(temp))
- errx(1, "package name too long");
- pkgs[ch] = strdup(temp);
- }
- else if ((Remote) && isURL(remotepkg)) {
- if (strlcpy(temp, remotepkg, sizeof(temp)) >= sizeof(temp))
- errx(1, "package name too long");
- pkgs[ch] = strdup(temp);
- } else { /* expand all pathnames to fullnames */
- if (fexists(*argv)) /* refers to a file directly */
- pkgs[ch] = strdup(realpath(*argv, temp));
- else { /* look for the file in the expected places */
- if (!(cp = fileFindByPath(NULL, *argv))) {
- /* let pkg_do() fail later, so that error is reported */
- if (strlcpy(temp, *argv, sizeof(temp)) >= sizeof(temp))
- errx(1, "package name too long");
- pkgs[ch] = strdup(temp);
- } else {
- if (strlcpy(temp, cp, sizeof(temp)) >= sizeof(temp))
- errx(1, "package name too long");
- pkgs[ch] = strdup(temp);
- }
- }
- }
- if (packagesite != NULL)
- packagesite[0] = '\0';
- }
- }
- /* If no packages, yelp */
- if (!ch) {
- warnx("missing package name(s)");
- usage();
- }
- else if (ch > 1 && AddMode == MASTER) {
- warnx("only one package name may be specified with master mode");
- usage();
- }
- /* Perform chroot if requested */
- if (Chroot != NULL) {
- if (chdir(Chroot))
- errx(1, "chdir to %s failed", Chroot);
- if (chroot("."))
- errx(1, "chroot to %s failed", Chroot);
- }
- warnpkgng();
- /* Make sure the sub-execs we invoke get found */
- setenv("PATH",
- "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin",
- 1);
-
- /* Set a reasonable umask */
- umask(022);
-
- if ((error = pkg_perform(pkgs)) != 0) {
- if (Verbose)
- warnx("%d package addition(s) failed", error);
- return error;
- }
- else
- return 0;
-}
-
-static char *
-getpackagesite(void)
-{
- int reldate, i;
- static char sitepath[MAXPATHLEN];
- int archmib[] = { CTL_HW, HW_MACHINE_ARCH };
- char arch[64];
- size_t archlen = sizeof(arch);
-
- if (getenv("PACKAGESITE")) {
- if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath))
- >= sizeof(sitepath))
- return NULL;
- return sitepath;
- }
-
- if (getenv("PACKAGEROOT")) {
- if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath))
- >= sizeof(sitepath))
- return NULL;
- } else {
- if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath))
- >= sizeof(sitepath))
- return NULL;
- }
-
- if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath))
- >= sizeof(sitepath))
- return NULL;
-
- if (sysctl(archmib, 2, arch, &archlen, NULL, 0) == -1)
- return NULL;
- arch[archlen-1] = 0;
- if (strlcat(sitepath, arch, sizeof(sitepath)) >= sizeof(sitepath))
- return NULL;
-
- reldate = getosreldate();
- for(i = 0; releases[i].directory != NULL; i++) {
- if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) {
- if (strlcat(sitepath, releases[i].directory, sizeof(sitepath))
- >= sizeof(sitepath))
- return NULL;
- break;
- }
- }
-
- if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath))
- return NULL;
-
- return sitepath;
-
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "%s\n%s\n",
- "usage: pkg_add [-viInfFrRMSK] [-t template] [-p prefix] [-P prefix] [-C chrootdir]",
- " pkg-name [pkg-name ...]");
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/add/perform.c b/usr.sbin/pkg_install/add/perform.c
deleted file mode 100644
index 638e046..0000000
--- a/usr.sbin/pkg_install/add/perform.c
+++ /dev/null
@@ -1,709 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the main body of the add module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <err.h>
-#include <paths.h>
-#include "lib.h"
-#include "add.h"
-
-#include <libgen.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-static int pkg_do(char *);
-static int sanity_check(char *);
-static char LogDir[FILENAME_MAX];
-static int zapLogDir; /* Should we delete LogDir? */
-
-int
-pkg_perform(char **pkgs)
-{
- int i, err_cnt = 0;
-
- signal(SIGINT, cleanup);
- signal(SIGHUP, cleanup);
-
- if (AddMode == SLAVE)
- err_cnt = pkg_do(NULL);
- else {
- for (i = 0; pkgs[i]; i++)
- err_cnt += pkg_do(pkgs[i]);
- }
- return err_cnt;
-}
-
-/*
- * This is seriously ugly code following. Written very fast!
- * [And subsequently made even worse.. Sigh! This code was just born
- * to be hacked, I guess.. :) -jkh]
- */
-static int
-pkg_do(char *pkg)
-{
- Package Plist;
- char pkg_fullname[FILENAME_MAX];
- char playpen[FILENAME_MAX];
- char extract_contents[FILENAME_MAX];
- char *extract;
- const char *where_to;
- FILE *cfile;
- int code;
- PackingList p;
- struct stat sb;
- int inPlace, conflictsfound, errcode;
- /* support for separate pre/post install scripts */
- int new_m = 0;
- char pre_script[FILENAME_MAX] = INSTALL_FNAME;
- char post_script[FILENAME_MAX];
- char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX];
- char *conflict[2];
- char **matched;
- int fd;
-
- conflictsfound = 0;
- code = 0;
- zapLogDir = 0;
- LogDir[0] = '\0';
- strcpy(playpen, FirstPen);
- inPlace = 0;
-
- memset(&Plist, '\0', sizeof(Plist));
-
- /* Are we coming in for a second pass, everything already extracted? */
- if (!pkg) {
- fgets(playpen, FILENAME_MAX, stdin);
- playpen[strlen(playpen) - 1] = '\0'; /* pesky newline! */
- if (chdir(playpen) == FAIL) {
- warnx("pkg_add in SLAVE mode can't chdir to %s", playpen);
- return 1;
- }
- read_plist(&Plist, stdin);
- where_to = playpen;
- }
- /* Nope - do it now */
- else {
- /* Is it an ftp://foo.bar.baz/file.t[bg]z specification? */
- if (isURL(pkg)) {
- if (!(where_to = fileGetURL(NULL, pkg, KeepPackage))) {
- warnx("unable to fetch '%s' by URL", pkg);
- return 1;
- }
- strcpy(pkg_fullname, pkg);
- cfile = fopen(CONTENTS_FNAME, "r");
- if (!cfile) {
- warnx(
- "unable to open table of contents file '%s' - not a package?",
- CONTENTS_FNAME);
- goto bomb;
- }
- read_plist(&Plist, cfile);
- fclose(cfile);
- }
- else {
- strcpy(pkg_fullname, pkg); /*
- * Copy for sanity's sake,
- * could remove pkg_fullname
- */
- if (strcmp(pkg, "-")) {
- if (stat(pkg_fullname, &sb) == FAIL) {
- warnx("can't stat package file '%s'", pkg_fullname);
- goto bomb;
- }
- sprintf(extract_contents, "--fast-read %s", CONTENTS_FNAME);
- extract = extract_contents;
- }
- else {
- extract = NULL;
- sb.st_size = 100000; /* Make up a plausible average size */
- }
- if (!(where_to = make_playpen(playpen, sb.st_size * 4)))
- errx(1, "unable to make playpen for %lld bytes", (long long)sb.st_size * 4);
- /* Since we can call ourselves recursively, keep notes on where we came from */
- if (!getenv("_TOP"))
- setenv("_TOP", where_to, 1);
- if (unpack(pkg_fullname, extract)) {
- warnx(
- "unable to extract table of contents file from '%s' - not a package?",
- pkg_fullname);
- goto bomb;
- }
- cfile = fopen(CONTENTS_FNAME, "r");
- if (!cfile) {
- warnx(
- "unable to open table of contents file '%s' - not a package?",
- CONTENTS_FNAME);
- goto bomb;
- }
- read_plist(&Plist, cfile);
- fclose(cfile);
-
- /* Extract directly rather than moving? Oh goodie! */
- if (find_plist_option(&Plist, "extract-in-place")) {
- if (Verbose)
- printf("Doing in-place extraction for %s\n", pkg_fullname);
- p = find_plist(&Plist, PLIST_CWD);
- if (p) {
- if (!isdir(p->name) && !Fake) {
- if (Verbose)
- printf("Desired prefix of %s does not exist, creating..\n", p->name);
- vsystem("/bin/mkdir -p %s", p->name);
- if (chdir(p->name) == -1) {
- warn("unable to change directory to '%s'", p->name);
- goto bomb;
- }
- }
- where_to = p->name;
- inPlace = 1;
- }
- else {
- warnx(
- "no prefix specified in '%s' - this is a bad package!",
- pkg_fullname);
- goto bomb;
- }
- }
-
- /*
- * Apply a crude heuristic to see how much space the package will
- * take up once it's unpacked. I've noticed that most packages
- * compress an average of 75%, so multiply by 4 for good measure.
- */
-
- if (!extract && !inPlace && min_free(playpen) < sb.st_size * 4) {
- warnx("projected size of %lld exceeds available free space.\n"
-"Please set your PKG_TMPDIR variable to point to a location with more\n"
- "free space and try again", (long long)sb.st_size * 4);
- warnx("not extracting %s\ninto %s, sorry!",
- pkg_fullname, where_to);
- goto bomb;
- }
-
- /* If this is a direct extract and we didn't want it, stop now */
- if (inPlace && Fake)
- goto success;
-
- /* Finally unpack the whole mess. If extract is null we
- already + did so so don't bother doing it again. */
- if (extract && unpack(pkg_fullname, NULL)) {
- warnx("unable to extract '%s'!", pkg_fullname);
- goto bomb;
- }
- }
-
- /* Check for sanity and dependencies */
- if (sanity_check(pkg))
- goto bomb;
-
- /* If we're running in MASTER mode, just output the plist and return */
- if (AddMode == MASTER) {
- printf("%s\n", where_playpen());
- write_plist(&Plist, stdout);
- return 0;
- }
- }
-
- /*
- * If we have a prefix, delete the first one we see and add this
- * one in place of it.
- */
- if (Prefix) {
- delete_plist(&Plist, FALSE, PLIST_CWD, NULL);
- add_plist_top(&Plist, PLIST_CWD, Prefix);
- }
-
- setenv(PKG_PREFIX_VNAME, (p = find_plist(&Plist, PLIST_CWD)) ? p->name : ".", 1);
- /* Protect against old packages with bogus @name and origin fields */
- if (Plist.name == NULL)
- Plist.name = "anonymous";
- if (Plist.origin == NULL)
- Plist.origin = "anonymous/anonymous";
-
- /*
- * See if we're already registered either with the same name (the same
- * version) or some other version with the same origin.
- */
- if ((isinstalledpkg(Plist.name) > 0 ||
- matchbyorigin(Plist.origin, NULL) != NULL) && !Force) {
- warnx("package '%s' or its older version already installed%s",
- Plist.name, FailOnAlreadyInstalled ? "" : " (ignored)");
- code = FailOnAlreadyInstalled != FALSE;
- goto success; /* close enough for government work */
- }
-
- /* Now check the packing list for conflicts */
- if (!IgnoreDeps){
- for (p = Plist.head; p != NULL; p = p->next) {
- if (p->type == PLIST_CONFLICTS) {
- int i;
- conflict[0] = strdup(p->name);
- conflict[1] = NULL;
- matched = matchinstalled(MATCH_GLOB, conflict, &errcode);
- free(conflict[0]);
- if (errcode == 0 && matched != NULL)
- for (i = 0; matched[i] != NULL; i++)
- if (isinstalledpkg(matched[i]) > 0) {
- warnx("package '%s' conflicts with %s", Plist.name,
- matched[i]);
- conflictsfound = 1;
- }
-
- continue;
- }
- }
- if(conflictsfound) {
- if(!Force) {
- warnx("please use pkg_delete first to remove conflicting package(s) or -f to force installation");
- code = 1;
- goto bomb;
- } else
- warnx("-f specified; proceeding anyway");
- }
-
-#if ENSURE_THAT_ALL_REQUIREMENTS_ARE_MET
- /*
- * Before attempting to do the slave mode bit, ensure that we've
- * downloaded & processed everything we need.
- * It's possible that we haven't already installed all of our
- * dependencies if the dependency list was misgenerated due to
- * other dynamic dependencies or if a dependency was added to a
- * package without all REQUIRED_BY packages being regenerated.
- */
- for (p = pkg ? Plist.head : NULL; p; p = p->next) {
- const char *ext;
- char *deporigin;
-
- if (p->type != PLIST_PKGDEP)
- continue;
- deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;
-
- if (isinstalledpkg(p->name) <= 0 &&
- !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
- char subpkg[FILENAME_MAX], *sep;
-
- strlcpy(subpkg, pkg, sizeof subpkg);
- if ((sep = strrchr(subpkg, '/')) != NULL) {
- *sep = '\0';
- if ((sep = strrchr(subpkg, '/')) != NULL) {
- *sep = '\0';
- strlcat(subpkg, "/All/", sizeof subpkg);
- strlcat(subpkg, p->name, sizeof subpkg);
- if ((ext = strrchr(pkg, '.')) == NULL) {
- if (getenv("PACKAGESUFFIX"))
- ext = getenv("PACKAGESUFFIX");
- else
- ext = ".tbz";
- }
- strlcat(subpkg, ext, sizeof subpkg);
- pkg_do(subpkg);
- }
- }
- }
- }
-#endif
-
- /* Now check the packing list for dependencies */
- for (p = Plist.head; p ; p = p->next) {
- char *deporigin;
-
- if (p->type != PLIST_PKGDEP)
- continue;
- deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name : NULL;
- if (Verbose) {
- printf("Package '%s' depends on '%s'", Plist.name, p->name);
- if (deporigin != NULL)
- printf(" with '%s' origin", deporigin);
- printf(".\n");
- }
- if (isinstalledpkg(p->name) <= 0 &&
- !(deporigin != NULL && matchbyorigin(deporigin, NULL) != NULL)) {
- char path[FILENAME_MAX];
- const char *cp = NULL;
-
- if (!Fake) {
- char prefixArg[2 + MAXPATHLEN]; /* "-P" + Prefix */
- if (PrefixRecursive) {
- strlcpy(prefixArg, "-P", sizeof(prefixArg));
- strlcat(prefixArg, Prefix, sizeof(prefixArg));
- }
- if (!isURL(pkg) && !getenv("PKG_ADD_BASE")) {
- const char *ext;
-
- ext = strrchr(pkg_fullname, '.');
- if (ext == NULL) {
- if (getenv("PACKAGESUFFIX")) {
- ext = getenv("PACKAGESUFFIX");
- } else {
- ext = ".tbz";
- }
- }
- snprintf(path, FILENAME_MAX, "%s/%s%s", getenv("_TOP"), p->name, ext);
- if (fexists(path))
- cp = path;
- else
- cp = fileFindByPath(pkg, p->name);
- if (cp) {
- if (Verbose)
- printf("Loading it from %s.\n", cp);
- if (vsystem("%s %s %s '%s'", PkgAddCmd, Verbose ? "-v " : "", PrefixRecursive ? prefixArg : "", cp)) {
- warnx("autoload of dependency '%s' failed%s",
- cp, Force ? " (proceeding anyway)" : "!");
- if (!Force)
- ++code;
- }
- }
- else {
- warnx("could not find package %s %s",
- p->name, Force ? " (proceeding anyway)" : "!");
- if (!Force)
- ++code;
- }
- }
- else if ((cp = fileGetURL(pkg, p->name, KeepPackage)) != NULL) {
- if (Verbose)
- printf("Finished loading %s via a URL\n", p->name);
- if (!fexists("+CONTENTS")) {
- warnx("autoloaded package %s has no +CONTENTS file?",
- p->name);
- if (!Force)
- ++code;
- }
- else if (vsystem("(pwd; /bin/cat +CONTENTS) | %s %s %s %s -S", PkgAddCmd, Verbose ? "-v" : "", PrefixRecursive ? prefixArg : "", KeepPackage ? "-K" : "")) {
- warnx("pkg_add of dependency '%s' failed%s",
- p->name, Force ? " (proceeding anyway)" : "!");
- if (!Force)
- ++code;
- }
- else if (Verbose)
- printf("\t'%s' loaded successfully.\n", p->name);
- /* Nuke the temporary playpen */
- leave_playpen();
- }
- }
- else {
- if (Verbose)
- printf("and was not found%s.\n", Force ? " (proceeding anyway)" : "");
- else
- printf("Package dependency %s for %s not found%s\n", p->name, pkg,
- Force ? " (proceeding anyway)" : "!");
- if (!Force)
- ++code;
- }
- }
- else if (Verbose)
- printf(" - already installed.\n");
- }
- } /* if (!IgnoreDeps) */
-
- if (code != 0)
- goto bomb;
-
- /* Look for the requirements file */
- if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) {
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */
- close(fd);
- if (Verbose)
- printf("Running requirements file first for %s..\n", Plist.name);
- if (!Fake && vsystem("./%s %s INSTALL", REQUIRE_FNAME, Plist.name)) {
- warnx("package %s fails requirements %s", pkg_fullname,
- Force ? "installing anyway" : "- not installed");
- if (!Force) {
- code = 1;
- goto success; /* close enough for government work */
- }
- }
- }
-
- /*
- * Test whether to use the old method of passing tokens to installation
- * scripts, and set appropriate variables..
- */
-
- if (fexists(POST_INSTALL_FNAME)) {
- new_m = 1;
- sprintf(post_script, "%s", POST_INSTALL_FNAME);
- pre_arg[0] = '\0';
- post_arg[0] = '\0';
- } else {
- if (fexists(INSTALL_FNAME)) {
- sprintf(post_script, "%s", INSTALL_FNAME);
- sprintf(pre_arg, "PRE-INSTALL");
- sprintf(post_arg, "POST-INSTALL");
- }
- }
-
- /* If we're really installing, and have an installation file, run it */
- if (!NoInstall && (fd = open(pre_script, O_RDWR)) != -1) {
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */
- close(fd);
- if (Verbose)
- printf("Running pre-install for %s..\n", Plist.name);
- if (!Fake && vsystem("./%s %s %s", pre_script, Plist.name, pre_arg)) {
- warnx("install script returned error status");
- unlink(pre_script);
- code = 1;
- goto success; /* nothing to uninstall yet */
- }
- }
-
- /* Now finally extract the entire show if we're not going direct */
- if (!inPlace && !Fake)
- extract_plist(".", &Plist);
-
- if (!Fake && fexists(MTREE_FNAME)) {
- if (Verbose)
- printf("Running mtree for %s..\n", Plist.name);
- p = find_plist(&Plist, PLIST_CWD);
- if (Verbose)
- printf("mtree -U -f %s -d -e -p %s >%s\n", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL);
- if (!Fake) {
- if (vsystem("/usr/sbin/mtree -U -f %s -d -e -p %s >%s", MTREE_FNAME, p ? p->name : "/", _PATH_DEVNULL))
- warnx("mtree returned a non-zero status - continuing");
- }
- }
-
- /* Run the installation script one last time? */
- if (!NoInstall && (fd = open(post_script, O_RDWR)) != -1) {
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */
- close(fd);
- if (Verbose)
- printf("Running post-install for %s..\n", Plist.name);
- if (!Fake && vsystem("./%s %s %s", post_script, Plist.name, post_arg)) {
- warnx("install script returned error status");
- unlink(post_script);
- code = 1;
- goto fail;
- }
- }
-
- /* Time to record the deed? */
- if (!NoRecord && !Fake) {
- char contents[FILENAME_MAX];
- char **depnames = NULL, **deporigins = NULL, ***depmatches;
- int i, dep_count = 0;
- FILE *contfile;
-
- if (getuid() != 0)
- warnx("not running as root - trying to record install anyway");
- sprintf(LogDir, "%s/%s", LOG_DIR, Plist.name);
- zapLogDir = 1;
- if (Verbose)
- printf("Attempting to record package into %s..\n", LogDir);
- if (make_hierarchy(LogDir, FALSE)) {
- warnx("can't record package into '%s', you're on your own!",
- LogDir);
- bzero(LogDir, FILENAME_MAX);
- code = 1;
- goto success; /* close enough for government work */
- }
- /* Make sure pkg_info can read the entry */
- fd = open(LogDir, O_RDWR);
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IRALL | S_IXALL); /* be sure, chmod a+rx */
- close(fd);
- move_file(".", DESC_FNAME, LogDir);
- move_file(".", COMMENT_FNAME, LogDir);
- if (fexists(INSTALL_FNAME))
- move_file(".", INSTALL_FNAME, LogDir);
- if (fexists(POST_INSTALL_FNAME))
- move_file(".", POST_INSTALL_FNAME, LogDir);
- if (fexists(DEINSTALL_FNAME))
- move_file(".", DEINSTALL_FNAME, LogDir);
- if (fexists(POST_DEINSTALL_FNAME))
- move_file(".", POST_DEINSTALL_FNAME, LogDir);
- if (fexists(REQUIRE_FNAME))
- move_file(".", REQUIRE_FNAME, LogDir);
- if (fexists(DISPLAY_FNAME))
- move_file(".", DISPLAY_FNAME, LogDir);
- if (fexists(MTREE_FNAME))
- move_file(".", MTREE_FNAME, LogDir);
- sprintf(contents, "%s/%s", LogDir, CONTENTS_FNAME);
- contfile = fopen(contents, "w");
- if (!contfile) {
- warnx("can't open new contents file '%s'! can't register pkg",
- contents);
- goto success; /* can't log, but still keep pkg */
- }
- write_plist(&Plist, contfile);
- fclose(contfile);
- for (p = Plist.head; p ; p = p->next) {
- char *deporigin;
-
- if (p->type != PLIST_PKGDEP)
- continue;
- deporigin = (p->next->type == PLIST_DEPORIGIN) ? p->next->name :
- NULL;
- if (Verbose) {
- printf("Trying to record dependency on package '%s'", p->name);
- if (deporigin != NULL)
- printf(" with '%s' origin", deporigin);
- printf(".\n");
- }
-
- if (deporigin) {
- /* Defer to origin lookup */
- depnames = realloc(depnames, (dep_count + 1) * sizeof(*depnames));
- depnames[dep_count] = p->name;
- deporigins = realloc(deporigins, (dep_count + 2) * sizeof(*deporigins));
- deporigins[dep_count] = deporigin;
- deporigins[dep_count + 1] = NULL;
- dep_count++;
- } else {
- /* No origin recorded, try to register on literal package name */
- sprintf(contents, "%s/%s/%s", LOG_DIR, p->name,
- REQUIRED_BY_FNAME);
- contfile = fopen(contents, "a");
- if (!contfile) {
- warnx("can't open dependency file '%s'!\n"
- "dependency registration is incomplete", contents);
- } else {
- fprintf(contfile, "%s\n", Plist.name);
- if (fclose(contfile) == EOF) {
- warnx("cannot properly close file %s", contents);
- }
- }
- }
- }
- if (dep_count > 0) {
- depmatches = matchallbyorigin((const char **)deporigins, NULL);
- free(deporigins);
- if (!IgnoreDeps && depmatches) {
- for (i = 0; i < dep_count; i++) {
- if (depmatches[i]) {
- int j;
- char **tmp = depmatches[i];
- for (j = 0; tmp[j] != NULL; j++) {
- /* Origin looked up */
- sprintf(contents, "%s/%s/%s", LOG_DIR, tmp[j],
- REQUIRED_BY_FNAME);
- if (depnames[i] && strcmp(depnames[i], tmp[j]) != 0)
- warnx("warning: package '%s' requires '%s', but '%s' "
- "is installed", Plist.name, depnames[i], tmp[j]);
- contfile = fopen(contents, "a");
- if (!contfile) {
- warnx("can't open dependency file '%s'!\n"
- "dependency registration is incomplete", contents);
- } else {
- fprintf(contfile, "%s\n", Plist.name);
- if (fclose(contfile) == EOF)
- warnx("cannot properly close file %s", contents);
- }
- }
- } else if (depnames[i]) {
- /* No package present with this origin, try literal package name */
- sprintf(contents, "%s/%s/%s", LOG_DIR, depnames[i],
- REQUIRED_BY_FNAME);
- contfile = fopen(contents, "a");
- if (!contfile) {
- warnx("can't open dependency file '%s'!\n"
- "dependency registration is incomplete", contents);
- } else {
- fprintf(contfile, "%s\n", Plist.name);
- if (fclose(contfile) == EOF) {
- warnx("cannot properly close file %s", contents);
- }
- }
- }
- }
- }
- }
- if (Verbose)
- printf("Package %s registered in %s\n", Plist.name, LogDir);
- }
-
- if ((p = find_plist(&Plist, PLIST_DISPLAY)) != NULL) {
- FILE *fp;
- char buf[BUFSIZ];
-
- snprintf(buf, sizeof buf, "%s/%s", LogDir, p->name);
- fp = fopen(buf, "r");
- if (fp) {
- putc('\n', stdout);
- while (fgets(buf, sizeof(buf), fp))
- fputs(buf, stdout);
- putc('\n', stdout);
- (void) fclose(fp);
- } else {
- if (!Fake) {
- warnx("cannot open %s as display file", buf);
- }
- }
- }
-
- goto success;
-
- bomb:
- code = 1;
- goto success;
-
- fail:
- /* Nuke the whole (installed) show, XXX but don't clean directories */
- if (!Fake)
- delete_package(FALSE, FALSE, &Plist);
-
- success:
- /* delete the packing list contents */
- free_plist(&Plist);
- leave_playpen();
- return code;
-}
-
-static int
-sanity_check(char *pkg)
-{
- int code = 0;
-
- if (!fexists(CONTENTS_FNAME)) {
- warnx("package %s has no CONTENTS file!", pkg);
- code = 1;
- }
- else if (!fexists(COMMENT_FNAME)) {
- warnx("package %s has no COMMENT file!", pkg);
- code = 1;
- }
- else if (!fexists(DESC_FNAME)) {
- warnx("package %s has no DESC file!", pkg);
- code = 1;
- }
- return code;
-}
-
-void
-cleanup(int sig)
-{
- static int in_cleanup = 0;
-
- if (!in_cleanup) {
- in_cleanup = 1;
- if (sig)
- printf("Signal %d received, cleaning up..\n", sig);
- if (!Fake && zapLogDir && LogDir[0])
- vsystem("%s -rf %s", REMOVE_CMD, LogDir);
- while (leave_playpen())
- ;
- }
- if (sig)
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/add/pkg_add.1 b/usr.sbin/pkg_install/add/pkg_add.1
deleted file mode 100644
index 923fe45..0000000
--- a/usr.sbin/pkg_install/add/pkg_add.1
+++ /dev/null
@@ -1,612 +0,0 @@
-.\"
-.\" FreeBSD install - a package for the installation and maintenance
-.\" of non-core utilities.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" Jordan K. Hubbard
-.\"
-.\" $FreeBSD$
-.\"
-.Dd November 9, 2012
-.Dt PKG_ADD 1
-.Os
-.Sh NAME
-.Nm pkg_add
-.Nd a utility for installing software package distributions
-.Sh SYNOPSIS
-.Nm
-.Op Fl viInfFrRMSK
-.Op Fl t Ar template
-.Op Fl p Ar prefix
-.Op Fl P Ar prefix
-.Op Fl C Ar chrootdir
-.Ar pkg-name Op Ar pkg-name ...
-.Sh DESCRIPTION
-The
-.Nm
-command is used to extract packages that have been previously created
-with the
-.Xr pkg_create 1
-command.
-.Sh WARNING
-.Bf -emphasis
-Since the
-.Nm
-command may execute scripts or programs contained within a package file,
-your system may be susceptible to
-.Dq Em trojan horses
-or other subtle
-attacks from miscreants who create dangerous package files.
-.Pp
-You are advised to verify the competence and identity of those who
-provide installable package files.
-For extra protection, use the
-.Fl M
-flag to extract the package file, and inspect its contents and scripts to
-ensure it poses no danger to your system's integrity.
-Pay particular
-attention to any +INSTALL, +POST-INSTALL, +DEINSTALL, +POST-DEINSTALL,
-+REQUIRE or +MTREE_DIRS files, and inspect the +CONTENTS file for
-.Cm @cwd ,
-.Cm @mode
-(check for setuid),
-.Cm @dirrm ,
-.Cm @exec ,
-and
-.Cm @unexec
-directives, and/or use the
-.Xr pkg_info 1
-command to examine the package file.
-.Ef
-.Sh OPTIONS
-The following command line arguments are supported:
-.Bl -tag -width indent
-.It Ar pkg-name Op Ar pkg-name ...
-The named packages are installed.
-A package name of
-.Fl
-will cause
-.Nm
-to read from stdin.
-If the packages are not found in the current
-working directory,
-.Nm
-will search them in each directory named by
-.Ev PKG_PATH .
-.It Fl v , -verbose
-Turn on verbose output.
-.It Fl K , -keep
-Keep any downloaded package in
-.Ev PKGDIR
-if it is defined or in current directory by default.
-.It Fl i , -no-deps
-Install the package without fetching and installing
-dependencies.
-.It Fl I , -no-script
-If any installation scripts (pre-install or post-install) exist for a given
-package, do not execute them.
-.It Fl n , -dry-run
-Do not actually install a package, just report the steps that
-would be taken if it was.
-.It Fl R , -no-record
-Do not record the installation of a package.
-This means
-that you cannot deinstall it later, so only use this option if
-you know what you are doing!
-.It Fl r , -remote
-Use the remote fetching feature.
-This will determine the appropriate
-objformat and release and then fetch and install the package.
-.It Fl f , -force
-Force installation to proceed even if prerequisite packages are not
-installed or the requirements script fails.
-Although
-.Nm
-will still try to find and auto-install missing prerequisite packages,
-a failure to find one will not be fatal.
-.It Fl F
-Already installed packages are not an error.
-.It Fl p , -prefix Ar prefix
-Set
-.Ar prefix
-as the directory in which to extract files from a package.
-If a package has set its default directory, it will be overridden
-by this flag.
-Note that only the first
-.Cm @cwd
-directive will be replaced, since
-.Nm
-has no way of knowing which directory settings are relative and
-which are absolute.
-It is rare in any case to see more than one
-directory transition made, but when such does happen and you wish
-to have control over *all* directory transitions, then you
-may then wish to look into the use of
-.Cm MASTER
-and
-.Cm SLAVE
-modes (see the
-.Fl M
-and
-.Fl S
-options).
-If the
-.Fl p
-flag appears after any
-.Fl P
-flag on the command line, it overrides its effect, causing
-.Nm
-not to use the given
-.Ar prefix
-recursively.
-.It Fl P Ar prefix
-Does the same as the
-.Fl p
-option, except that the given
-.Ar prefix
-is also used recursively for the dependency packages, if any.
-If the
-.Fl P
-flag appears after any
-.Fl p
-flag on the command line, it overrides its effect, causing
-.Nm
-to use the given
-.Ar prefix
-recursively.
-.It Fl t , -template Ar template
-Use
-.Ar template
-as the input to
-.Xr mktemp 3
-when creating a
-.Dq staging area .
-By default, this is the string
-.Pa /var/tmp/instmp.XXXXXX ,
-but it may be necessary to override it in the situation where
-space in your
-.Pa /var/tmp
-directory is limited.
-Be sure to leave some number of `X' characters
-for
-.Xr mktemp 3
-to fill in with a unique ID.
-.Pp
-You can get a performance boost by setting the staging area
-.Ar template
-to reside on the same disk partition as target directories for package
-file installation; often this is
-.Pa /usr .
-.It Fl M , -master
-Run in
-.Cm MASTER
-mode.
-This is a very specialized mode for running
-.Nm
-and is meant to be run in conjunction with
-.Cm SLAVE
-mode.
-When run in this mode,
-.Nm
-does no work beyond extracting the package into a temporary staging
-area (see the
-.Fl t
-option), reading in the packing list, and then dumping it (prefaced by
-the current staging area) to stdout where it may be filtered by a
-program such as
-.Xr sed 1 .
-When used in conjunction with
-.Cm SLAVE
-mode, it allows you to make radical changes to the package structure
-before acting on its contents.
-.It Fl S , -slave
-Run in
-.Cm SLAVE
-mode.
-This is a very specialized mode for running
-.Nm
-and is meant to be run in conjunction with
-.Cm MASTER
-mode.
-When run in this mode,
-.Nm
-expects the release contents to be already extracted and waiting
-in the staging area, the location of which is read as a string
-from stdin.
-The complete packing list is also read from stdin,
-and the contents then acted on as normal.
-.It Fl C , -chroot Ar chrootdir
-Before doing any operations,
-.Xr chroot 2
-to the
-.Ar chrootdir
-directory so that all package files, and the package database, are
-installed to
-.Ar chrootdir .
-Note that
-.Ar chrootdir
-needs to be a fairly complete file system, including everything normally
-needed by
-.Nm
-to run.
-This flag was added to help support operations done by
-.Xr sysinstall 8
-and is not expected to be useful for much else.
-Be careful that
-.Ar chrootdir
-is properly configured and cannot be modified by normal users,
-versions of commands like
-.Xr fetch 1
-may be run inside
-.Ar chrootdir
-as a side effect.
-.El
-.Pp
-One or more
-.Ar pkg-name
-arguments may be specified, each being either a file containing the
-package (these usually end with a
-.Dq .tbz
-suffix) or a
-URL pointing at a file available on an ftp site.
-Thus you may
-extract files directly from their anonymous ftp locations (e.g.\&
-.Nm
-.Li ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/packages/shells/bash-1.14.7.tbz ) .
-Note: If you wish to use
-.Bf -emphasis
-passive mode
-.Ef
-ftp in such transfers, set
-the variable
-.Bf -emphasis
-FTP_PASSIVE_MODE
-.Ef
-to some value in your environment.
-Otherwise, the more standard
-ACTIVE mode may be used.
-If
-.Nm
-consistently fails to fetch a package from a site known to work,
-it may be because you have a firewall that demands the usage of
-.Bf -emphasis
-passive mode
-.Ef
-ftp.
-.Sh TECHNICAL DETAILS
-The
-.Nm
-utility extracts each package's
-.Dq "packing list"
-into a special staging directory (see
-.Sx ENVIRONMENT ) ,
-parses it, and then runs
-through the following sequence to fully extract the contents of the package:
-.Bl -enum
-.It
-A check is made to determine if the package is already recorded as installed.
-If it is, installation is terminated.
-.It
-A check is made to determine if the package conflicts (from
-.Ic @conflicts
-directives, see
-.Xr pkg_create 1 )
-with an already installed package.
-If it is, installation is terminated.
-.It
-Scan all the package dependencies (from
-.Ic @pkgdep
-directives, see
-.Xr pkg_create 1 )
-are read from the packing list.
-If any of these required packages is not currently installed,
-an attempt is made to find and install it;
-if the missing package cannot be found or installed,
-the installation is terminated.
-.It
-Search for any
-.Ic @option
-directives which control how the package is added to the system.
-At the time of this writing, the only currently implemented option is
-.Ic @option Cm extract-in-place
-which will cause the package to be extracted directly into its
-prefix directory without moving through a staging area.
-.It
-If
-.Ic @option Cm extract-in-place
-is enabled, the package is now extracted directly into its
-final location, otherwise it is extracted into the staging area.
-.It
-If a requirements script
-.Pa +REQUIRE
-exists for the package (see the
-.Fl r
-flag of
-.Xr pkg_create 1 ) ,
-then execute it with the following arguments:
-.Pp
-.D1 Ar pkg-name Li INSTALL
-.Pp
-where
-.Ar pkg-name
-is the name of the package in question and the
-.Dq Li INSTALL
-keyword denotes this as an installation requirements check (useful if
-you want to have one script serving multiple functions).
-.It
-If a pre-install script
-.Pa +INSTALL
-exists for the package,
-it is then executed with the following arguments:
-.Pp
-.D1 Ar pkg-name Li PRE-INSTALL
-.Pp
-where
-.Ar pkg-name
-is the name of the package in question and
-.Dq Li PRE-INSTALL
-is a keyword denoting this as the preinstallation phase.
-.Pp
-.Sy Note :
-The
-.Dq Li PRE-INSTALL
-keyword will not appear if separate scripts for pre-install and post-install
-are given during package creation time (using the
-.Fl i
-and
-.Fl I
-flags to
-.Xr pkg_create 1 ) .
-.It
-If
-.Cm @option Cm extract-in-place
-is not used, then the packing list (this is the
-.Pa +CONTENTS
-file) is now used as a guide for moving (or copying, as necessary) files from
-the staging area into their final locations.
-.It
-If an mtree file
-.Pa +MTREE_DIRS
-exists for the package (see the
-.Fl m
-flag of
-.Xr pkg_create 1 ) ,
-then
-.Xr mtree 8
-is invoked as:
-.Pp
-.D1 Nm mtree Fl U f Pa +MTREE_DIRS Fl d e p Ar prefix
-.Pp
-where
-.Ar prefix
-is either the prefix specified with the
-.Fl p
-or
-.Fl P
-flag or,
-if neither flag was specified, the name of the first directory named by a
-.Ic @cwd
-directive within this package.
-.It
-If a post-install script
-.Pa +POST-INSTALL
-exists for the package,
-it is then executed with the following arguments:
-.Pp
-.D1 Ar pkg-name Li POST-INSTALL
-.Pp
-where
-.Ar pkg-name
-is the name of the package in question and
-.Dq Li POST-INSTALL
-is a keyword denoting this as the post-installation phase.
-.Pp
-.Sy Note :
-The
-.Dq Li POST-INSTALL
-keyword will not appear if separate scripts for pre-install and post-install
-are given during package creation time (using the
-.Fl i
-and
-.Fl I
-flags to
-.Xr pkg_create 1 ) .
-.Pp
-Reasoning behind passing keywords such as
-.Dq Li POST-INSTALL
-and
-.Dq Li PRE-INSTALL
-is that this allows you to write a single
-install
-script that does both
-.Dq before
-and
-.Dq after
-actions.
-But, separating the
-functionality is more advantageous and easier from a maintenance viewpoint.
-.It
-After installation is complete, a copy of the
-description
-.Pq Pa +DESC ,
-comment
-.Pq Pa +COMMENT ,
-pre-install script
-.Pq Pa +INSTALL ,
-post-install script
-.Pq Pa +POST-INSTALL ,
-deinstall script
-.Pq Pa +DEINSTALL ,
-post-deinstall script
-.Pq Pa +POST-DEINSTALL ,
-requirements script
-.Pq Pa +REQUIRE ,
-display
-.Pq Pa +DISPLAY ,
-mtree
-.Pq Pa +MTREE_DIRS ,
-and packing list
-.Pq Pa +CONTENTS
-files are copied into
-.Pa /var/db/pkg/ Ns Aq Ar pkg-name
-for subsequent possible use by
-.Xr pkg_delete 1 .
-Any package dependencies are recorded in the other packages'
-.Pa /var/db/pkg/ Ns Ao Ar other-pkg Ac Ns Pa /+REQUIRED_BY
-file
-(if the environment variable
-.Ev PKG_DBDIR
-is set, this overrides the
-.Pa /var/db/pkg/
-path shown above).
-.It
-Finally, the staging area is deleted and the program terminates.
-.El
-.Pp
-All the scripts are called with the environment variable
-.Ev PKG_PREFIX
-set to the installation prefix (see the
-.Fl p
-and
-.Fl P
-options above).
-This allows a package author to write a script
-that reliably performs some action on the directory where the package
-is installed, even if the user might change it with the
-.Fl p
-or
-.Fl P
-flags to
-.Nm .
-.Sh ENVIRONMENT
-The value of the
-.Ev PKG_PATH
-is used if a given package cannot be found.
-The environment variable
-should be a series of entries separated by colons.
-Each entry
-consists of a directory name.
-The current directory may be indicated
-implicitly by an empty directory name, or explicitly by a single
-period.
-.Pp
-The environment variable
-.Ev PKG_DBDIR
-specifies an alternative location for the installed package database,
-default location is
-.Pa /var/db/pkg .
-.Pp
-The environment variables
-.Ev PKG_TMPDIR
-and
-.Ev TMPDIR ,
-in that order, are taken to name temporary directories where
-.Nm
-will attempt to create its staging area in.
-If these variables are not present or if the directories named lack
-sufficient space, then
-.Nm
-will use the first of
-.Pa /var/tmp ,
-.Pa /tmp
-or
-.Pa /usr/tmp
-with sufficient space.
-.Pp
-The environment variable
-.Ev PACKAGEROOT
-specifies an alternate location for
-.Nm
-to fetch from.
-The fetch URL is built using this environment variable and the automatic
-directory logic that
-.Nm
-uses when the
-.Fl r
-option is invoked.
-An example setting would be
-.Qq Li ftp://ftp3.FreeBSD.org .
-.Pp
-The environment variable
-.Ev PACKAGESITE
-specifies an alternate location for
-.Nm
-to fetch from.
-This variable subverts the automatic directory logic
-that
-.Nm
-uses when the
-.Fl r
-option is invoked.
-Thus it should be a complete URL to the remote package file(s).
-.Pp
-The environment variable
-.Ev PKGDIR
-specifies an alternative location to save downloaded packages to when
-.Fl K
-option is used.
-.Pp
-The environment variable
-.Ev PACKAGESUFFIX
-specifies an alternative file extension to use when fetching remote
-packages. Default is .tbz
-.Sh FILES
-.Bl -tag -width /var/db/pkg -compact
-.It Pa /var/tmp
-Temporary directory for creating the staging area, if environmental variables
-.Ev PKG_TMPDIR
-or
-.Ev TMPDIR
-do not point to a suitable directory.
-.It Pa /tmp
-Next choice if
-.Pa /var/tmp
-does not exist or has insufficient space.
-.It Pa /usr/tmp
-Last choice if
-.Pa /var/tmp
-and
-.Pa /tmp
-are not suitable for creating the staging area.
-.It Pa /var/db/pkg
-Default location of the installed package database.
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh SEE ALSO
-.Xr pkg_create 1 ,
-.Xr pkg_delete 1 ,
-.Xr pkg_info 1 ,
-.Xr pkg_version 1 ,
-.Xr mktemp 3 ,
-.Xr sysconf 3 ,
-.Xr mtree 8
-.Sh AUTHORS
-.An Jordan Hubbard
-.Sh CONTRIBUTORS
-.An John Kohl Aq jtk@rational.com
-.Sh BUGS
-Hard links between files in a distribution are only preserved if either
-(1) the staging area is on the same file system as the target directory of
-all the links to the file, or (2) all the links to the file are bracketed by
-.Cm @cwd
-directives in the contents file,
-.Em and
-the link names are extracted with a single
-.Cm tar
-command (not split between
-invocations due to exec argument-space limitations--this depends on the
-value returned by
-.Fn sysconf _SC_ARG_MAX ) .
-.Pp
-Sure to be others.
diff --git a/usr.sbin/pkg_install/create/Makefile b/usr.sbin/pkg_install/create/Makefile
deleted file mode 100644
index 42718c6..0000000
--- a/usr.sbin/pkg_install/create/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-# $FreeBSD$
-
-PROG= pkg_create
-SRCS= main.c perform.c pl.c
-
-CFLAGS+= -I${.CURDIR}/../lib
-
-WARNS?= 3
-WFORMAT?= 1
-
-DPADD= ${LIBINSTALL} ${LIBMD}
-LDADD= ${LIBINSTALL} -lmd
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/create/Makefile.depend b/usr.sbin/pkg_install/create/Makefile.depend
deleted file mode 100644
index 86f84fe..0000000
--- a/usr.sbin/pkg_install/create/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libmd \
- lib/libutil \
- usr.sbin/pkg_install/lib \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/create/create.h b/usr.sbin/pkg_install/create/create.h
deleted file mode 100644
index 301bcff..0000000
--- a/usr.sbin/pkg_install/create/create.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Include and define various things wanted by the create command.
- *
- */
-
-#ifndef _INST_CREATE_H_INCLUDE
-#define _INST_CREATE_H_INCLUDE
-
-extern match_t MatchType;
-extern char *Prefix;
-extern char *Comment;
-extern char *Desc;
-extern char *Display;
-extern char *Install;
-extern char *PostInstall;
-extern char *DeInstall;
-extern char *PostDeInstall;
-extern char *Contents;
-extern char *Require;
-extern char *SrcDir;
-extern char *BaseDir;
-extern char *ExcludeFrom;
-extern char *Mtree;
-extern char *Pkgdeps;
-extern char *Conflicts;
-extern char *Origin;
-extern char *InstalledPkg;
-extern char PlayPen[];
-extern int Dereference;
-extern int PlistOnly;
-extern int Recursive;
-extern int Regenerate;
-
-enum zipper {NONE, GZIP, BZIP, BZIP2, XZ };
-extern enum zipper Zipper;
-
-void add_cksum(Package *, PackingList, const char *);
-void check_list(const char *, Package *);
-void copy_plist(const char *, Package *);
-
-#endif /* _INST_CREATE_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/create/main.c b/usr.sbin/pkg_install/create/main.c
deleted file mode 100644
index 4f68697..0000000
--- a/usr.sbin/pkg_install/create/main.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the create module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <getopt.h>
-#include <err.h>
-
-#include "lib.h"
-#include "create.h"
-
-match_t MatchType = MATCH_GLOB;
-char *Prefix = NULL;
-char *Comment = NULL;
-char *Desc = NULL;
-char *SrcDir = NULL;
-char *BaseDir = NULL;
-char *Display = NULL;
-char *Install = NULL;
-char *PostInstall = NULL;
-char *DeInstall = NULL;
-char *PostDeInstall = NULL;
-char *Contents = NULL;
-char *Require = NULL;
-char *ExcludeFrom = NULL;
-char *Mtree = NULL;
-char *Pkgdeps = NULL;
-char *Conflicts = NULL;
-char *Origin = NULL;
-char *InstalledPkg = NULL;
-char PlayPen[FILENAME_MAX];
-int Dereference = FALSE;
-int PlistOnly = FALSE;
-int Recursive = FALSE;
-int Regenerate = TRUE;
-int Help = FALSE;
-enum zipper Zipper = BZIP2;
-
-
-static void usage(void);
-
-static char opts[] = "EGYNnORhjJvxyzf:p:P:C:c:d:i:I:k:K:r:t:X:D:m:s:S:o:b:";
-static struct option longopts[] = {
- { "backup", required_argument, NULL, 'b' },
- { "extended", no_argument, NULL, 'E' },
- { "help", no_argument, &Help, TRUE },
- { "no", no_argument, NULL, 'N' },
- { "no-glob", no_argument, NULL, 'G' },
- { "origin", required_argument, NULL, 'o' },
- { "plist-only", no_argument, NULL, 'O' },
- { "prefix", required_argument, NULL, 'p' },
- { "recursive", no_argument, NULL, 'R' },
- { "regex", no_argument, NULL, 'x' },
- { "template", required_argument, NULL, 't' },
- { "verbose", no_argument, NULL, 'v' },
- { "yes", no_argument, NULL, 'Y' },
- { NULL, 0, NULL, 0 },
-};
-
-int
-main(int argc, char **argv)
-{
- int ch;
- char **pkgs, **start, *tmp;
-
- warnpkgng();
- pkgs = start = argv;
- while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1)
- switch(ch) {
- case 'v':
- Verbose++;
- break;
-
- case 'x':
- MatchType = MATCH_REGEX;
- break;
-
- case 'E':
- MatchType = MATCH_EREGEX;
- break;
-
- case 'G':
- MatchType = MATCH_EXACT;
- break;
-
- case 'N':
- AutoAnswer = NO;
- break;
-
- case 'Y':
- AutoAnswer = YES;
- break;
-
- case 'O':
- PlistOnly = TRUE;
- break;
-
- case 'p':
- Prefix = optarg;
- break;
-
- case 's':
- SrcDir = optarg;
- break;
-
- case 'S':
- BaseDir = optarg;
- break;
-
- case 'f':
- Contents = optarg;
- break;
-
- case 'C':
- Conflicts = optarg;
- break;
-
- case 'c':
- Comment = optarg;
- break;
-
- case 'd':
- Desc = optarg;
- break;
-
- case 'i':
- Install = optarg;
- break;
-
- case 'I':
- PostInstall = optarg;
- break;
-
- case 'k':
- DeInstall = optarg;
- break;
-
- case 'K':
- PostDeInstall = optarg;
- break;
-
- case 'r':
- Require = optarg;
- break;
-
- case 't':
- strlcpy(PlayPen, optarg, sizeof(PlayPen));
- break;
-
- case 'X':
- ExcludeFrom = optarg;
- break;
-
- case 'h':
- Dereference = TRUE;
- break;
-
- case 'D':
- Display = optarg;
- break;
-
- case 'm':
- Mtree = optarg;
- break;
-
- case 'P':
- Pkgdeps = optarg;
- break;
-
- case 'o':
- Origin = optarg;
- break;
-
- case 'y':
- case 'j':
- Zipper = BZIP2;
- break;
-
- case 'z':
- Zipper = GZIP;
- break;
-
- case 'J':
- Zipper = XZ;
- break;
-
- case 'b':
- InstalledPkg = optarg;
- while ((tmp = strrchr(optarg, (int)'/')) != NULL) {
- *tmp++ = '\0';
- /*
- * If character after the '/' is alphanumeric, then we've
- * found the package name. Otherwise we've come across
- * a trailing '/' and need to continue our quest.
- */
- if (isalpha(*tmp)) {
- InstalledPkg = tmp;
- break;
- }
- }
- break;
-
- case 'R':
- Recursive = TRUE;
- break;
-
- case 'n':
- Regenerate = FALSE;
- break;
-
- case 0:
- if (Help)
- usage();
- break;
-
- default:
- usage();
- break;
- }
-
- argc -= optind;
- argv += optind;
-
- /* Get all the remaining package names, if any */
- while (*argv)
- *pkgs++ = *argv++;
-
- /* If no packages, yelp */
- if ((pkgs == start) && (InstalledPkg == NULL))
- warnx("missing package name"), usage();
- *pkgs = NULL;
- if ((start[0] != NULL) && (start[1] != NULL)) {
- warnx("only one package name allowed ('%s' extraneous)", start[1]);
- usage();
- }
- if (start[0] == NULL)
- start[0] = InstalledPkg;
- if (!pkg_perform(start)) {
- if (Verbose)
- warnx("package creation failed");
- return 1;
- }
- else
- return 0;
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
-"usage: pkg_create [-YNOhjnvyz] [-C conflicts] [-P pkgs] [-p prefix]",
-" [-i iscript] [-I piscript] [-k dscript] [-K pdscript]",
-" [-r rscript] [-s srcdir] [-S basedir]",
-" [-t template] [-X excludefile]",
-" [-D displayfile] [-m mtreefile] [-o originpath]",
-" -c comment -d description -f packlist pkg-filename",
-" pkg_create [-EGYNRhnvxy] -b pkg-name [pkg-filename]");
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/create/perform.c b/usr.sbin/pkg_install/create/perform.c
deleted file mode 100644
index e2a884a..0000000
--- a/usr.sbin/pkg_install/create/perform.c
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the main body of the create module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include "create.h"
-
-#include <err.h>
-#include <libgen.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/syslimits.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-static void sanity_check(void);
-static void make_dist(const char *, const char *, const char *, Package *);
-static int create_from_installed_recursive(const char *, const char *);
-static int create_from_installed(const char *, const char *, const char *);
-
-int
-pkg_perform(char **pkgs)
-{
- static const char *home;
- char *pkg = *pkgs; /* Only one arg to create */
- char *cp;
- FILE *pkg_in, *fp;
- Package plist;
- int len;
- const char *suf;
-
- /* Preliminary setup */
- if (InstalledPkg == NULL)
- sanity_check();
- if (Verbose && !PlistOnly)
- printf("Creating package %s\n", pkg);
-
- /* chop suffix off if already specified, remembering if we want to compress */
- len = strlen(pkg);
- if (len > 4) {
- if (!strcmp(&pkg[len - 4], ".tbz")) {
- Zipper = BZIP2;
- pkg[len - 4] = '\0';
- }
- else if (!strcmp(&pkg[len - 4], ".tgz")) {
- Zipper = GZIP;
- pkg[len - 4] = '\0';
- }
- else if (!strcmp(&pkg[len - 4], ".txz")) {
- Zipper = XZ;
- pkg[len - 4] = '\0';
- }
- else if (!strcmp(&pkg[len - 4], ".tar")) {
- Zipper = NONE;
- pkg[len - 4] = '\0';
- }
- }
- if (Zipper == BZIP2) {
- suf = "tbz";
- setenv("BZIP2", "--best", 0);
- } else if (Zipper == GZIP) {
- suf = "tgz";
- setenv("GZIP", "-9", 0);
- } else if (Zipper == XZ) {
- suf = "txz";
- } else
- suf = "tar";
-
- if (InstalledPkg != NULL) {
- char *pkgglob[] = { InstalledPkg, NULL };
- char **matched, **pkgs;
- int i, error;
-
- pkgs = pkgglob;
- if (MatchType != MATCH_EXACT) {
- matched = matchinstalled(MatchType, pkgs, &error);
- if (!error && matched != NULL)
- pkgs = matched;
- else if (MatchType != MATCH_GLOB)
- errx(1, "no packages match pattern");
- }
- /*
- * Is there is only one installed package matching the pattern,
- * we need to respect the optional pkg-filename parameter. If,
- * however, the pattern matches several packages, this parameter
- * makes no sense and is ignored.
- */
- if (pkgs[1] == NULL) {
- if (pkg == InstalledPkg)
- pkg = *pkgs;
- InstalledPkg = *pkgs;
- if (!Recursive)
- return (create_from_installed(InstalledPkg, pkg, suf));
- return (create_from_installed_recursive(pkg, suf));
- }
- for (i = 0; pkgs[i] != NULL; i++) {
- InstalledPkg = pkg = pkgs[i];
- if (!Recursive)
- create_from_installed(pkg, pkg, suf);
- else
- create_from_installed_recursive(pkg, suf);
- }
- return TRUE;
- }
-
- get_dash_string(&Comment);
- get_dash_string(&Desc);
- if (!strcmp(Contents, "-"))
- pkg_in = stdin;
- else {
- pkg_in = fopen(Contents, "r");
- if (!pkg_in) {
- cleanup(0);
- errx(2, "%s: unable to open contents file '%s' for input",
- __func__, Contents);
- }
- }
- plist.head = plist.tail = NULL;
-
- /* Stick the dependencies, if any, at the top */
- if (Pkgdeps) {
- char **deps, *deporigin;
- int i;
- int ndeps = 0;
-
- if (Verbose && !PlistOnly)
- printf("Registering depends:");
-
- /* Count number of dependencies */
- for (cp = Pkgdeps; cp != NULL && *cp != '\0';
- cp = strpbrk(++cp, " \t\n")) {
- ndeps++;
- }
-
- if (ndeps != 0) {
- /* Create easy to use NULL-terminated list */
- deps = alloca(sizeof(*deps) * ndeps + 1);
- if (deps == NULL) {
- errx(2, "%s: alloca() failed", __func__);
- /* Not reached */
- }
- for (i = 0; Pkgdeps;) {
- cp = strsep(&Pkgdeps, " \t\n");
- if (*cp) {
- deps[i] = cp;
- i++;
- }
- }
- ndeps = i;
- deps[ndeps] = NULL;
-
- sortdeps(deps);
- for (i = 0; i < ndeps; i++) {
- deporigin = strchr(deps[i], ':');
- if (deporigin != NULL) {
- *deporigin = '\0';
- add_plist_top(&plist, PLIST_DEPORIGIN, ++deporigin);
- }
- add_plist_top(&plist, PLIST_PKGDEP, deps[i]);
- if (Verbose && !PlistOnly)
- printf(" %s", deps[i]);
- }
- }
-
- if (Verbose && !PlistOnly)
- printf(".\n");
- }
-
- /* Put the conflicts directly after the dependencies, if any */
- if (Conflicts) {
- if (Verbose && !PlistOnly)
- printf("Registering conflicts:");
- while (Conflicts) {
- cp = strsep(&Conflicts, " \t\n");
- if (*cp) {
- add_plist(&plist, PLIST_CONFLICTS, cp);
- if (Verbose && !PlistOnly)
- printf(" %s", cp);
- }
- }
- if (Verbose && !PlistOnly)
- printf(".\n");
- }
-
- /* If a SrcDir override is set, add it now */
- if (SrcDir) {
- if (Verbose && !PlistOnly)
- printf("Using SrcDir value of %s\n", SrcDir);
- add_plist(&plist, PLIST_SRC, SrcDir);
- }
-
- /* Slurp in the packing list */
- read_plist(&plist, pkg_in);
-
- /* Prefix should add an @cwd to the packing list */
- if (Prefix) {
- if (Prefix[0] != '/') {
- char resolved_prefix[PATH_MAX];
- if (realpath(Prefix, resolved_prefix) == NULL)
- err(EXIT_FAILURE, "couldn't resolve path for prefix: %s", Prefix);
- add_plist_top(&plist, PLIST_CWD, resolved_prefix);
- } else {
- add_plist_top(&plist, PLIST_CWD, Prefix);
- }
- }
-
- /* Add the origin if asked, at the top */
- if (Origin)
- add_plist_top(&plist, PLIST_ORIGIN, Origin);
-
- /*
- * Run down the list and see if we've named it, if not stick in a name
- * at the top.
- */
- if (find_plist(&plist, PLIST_NAME) == NULL)
- add_plist_top(&plist, PLIST_NAME, basename(pkg));
-
- if (asprintf(&cp, "PKG_FORMAT_REVISION:%d.%d", PLIST_FMT_VER_MAJOR,
- PLIST_FMT_VER_MINOR) == -1) {
- errx(2, "%s: asprintf() failed", __func__);
- }
- add_plist_top(&plist, PLIST_COMMENT, cp);
- free(cp);
-
- /*
- * We're just here for to dump out a revised plist for the FreeBSD ports
- * hack. It's not a real create in progress.
- */
- if (PlistOnly) {
- check_list(home, &plist);
- write_plist(&plist, stdout);
- exit(0);
- }
-
- /* Make a directory to stomp around in */
- home = make_playpen(PlayPen, 0);
- signal(SIGINT, cleanup);
- signal(SIGHUP, cleanup);
-
- /* Make first "real contents" pass over it */
- check_list(home, &plist);
- (void) umask(022); /*
- * Make sure gen'ed directories, files don't have
- * group or other write bits.
- */
- /* copy_plist(home, &plist); */
- /* mark_plist(&plist); */
-
- /* Now put the release specific items in */
- if (!Prefix) {
- add_plist(&plist, PLIST_CWD, ".");
- }
- write_file(COMMENT_FNAME, Comment);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
- add_cksum(&plist, plist.tail, COMMENT_FNAME);
- write_file(DESC_FNAME, Desc);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, DESC_FNAME);
- add_cksum(&plist, plist.tail, DESC_FNAME);
-
- if (Install) {
- copy_file(home, Install, INSTALL_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
- add_cksum(&plist, plist.tail, INSTALL_FNAME);
- }
- if (PostInstall) {
- copy_file(home, PostInstall, POST_INSTALL_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
- add_cksum(&plist, plist.tail, POST_INSTALL_FNAME);
- }
- if (DeInstall) {
- copy_file(home, DeInstall, DEINSTALL_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
- add_cksum(&plist, plist.tail, DEINSTALL_FNAME);
- }
- if (PostDeInstall) {
- copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
- add_cksum(&plist, plist.tail, POST_DEINSTALL_FNAME);
- }
- if (Require) {
- copy_file(home, Require, REQUIRE_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
- add_cksum(&plist, plist.tail, REQUIRE_FNAME);
- }
- if (Display) {
- copy_file(home, Display, DISPLAY_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
- add_cksum(&plist, plist.tail, DISPLAY_FNAME);
- add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME);
- }
- if (Mtree) {
- copy_file(home, Mtree, MTREE_FNAME);
- add_plist(&plist, PLIST_IGNORE, NULL);
- add_plist(&plist, PLIST_FILE, MTREE_FNAME);
- add_cksum(&plist, plist.tail, MTREE_FNAME);
- add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
- }
-
- /* Finally, write out the packing list */
- fp = fopen(CONTENTS_FNAME, "w");
- if (!fp) {
- cleanup(0);
- errx(2, "%s: can't open file %s for writing",
- __func__, CONTENTS_FNAME);
- }
- write_plist(&plist, fp);
- if (fclose(fp)) {
- cleanup(0);
- errx(2, "%s: error while closing %s",
- __func__, CONTENTS_FNAME);
- }
-
- /* And stick it into a tar ball */
- make_dist(home, pkg, suf, &plist);
-
- /* Cleanup */
- free(Comment);
- free(Desc);
- free_plist(&plist);
- leave_playpen();
- return TRUE; /* Success */
-}
-
-static void
-make_dist(const char *homedir, const char *pkg, const char *suff, Package *plist)
-{
- struct stat sb;
- char tball[FILENAME_MAX];
- PackingList p;
- int ret;
- const char *args[50]; /* Much more than enough. */
- int nargs = 0;
- int pipefds[2];
- FILE *totar;
- pid_t pid;
- const char *cname;
- char *prefix = NULL;
-
-
- args[nargs++] = "tar"; /* argv[0] */
-
- if (*pkg == '/')
- snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suff);
- else
- snprintf(tball, FILENAME_MAX, "%s/%s.%s", homedir, pkg, suff);
-
- /*
- * If the package tarball exists already, and we are running in `no
- * clobber' mode, skip this package.
- */
- if (stat(tball, &sb) == 0 && Regenerate == FALSE) {
- if (Verbose)
- printf("Skipping package '%s'. It already exists.\n", tball);
- return;
- }
-
- args[nargs++] = "-c";
- args[nargs++] = "-f";
- args[nargs++] = tball;
- if (strchr(suff, 'z')) { /* Compress/gzip/bzip2? */
- if (Zipper == BZIP2) {
- args[nargs++] = "-j";
- cname = "bzip'd ";
- }
- else if (Zipper == XZ) {
- args[nargs++] = "-J";
- cname = "xz'd ";
- }
- else {
- args[nargs++] = "-z";
- cname = "gzip'd ";
- }
- } else {
- cname = "";
- }
- if (Dereference)
- args[nargs++] = "-h";
- if (ExcludeFrom) {
- args[nargs++] = "-X";
- args[nargs++] = ExcludeFrom;
- }
- args[nargs++] = "-T"; /* Take filenames from file instead of args. */
- args[nargs++] = "-"; /* Use stdin for the file. */
- args[nargs] = NULL;
-
- if (Verbose)
- printf("Creating %star ball in '%s'\n", cname, tball);
-
- /* Set up a pipe for passing the filenames, and fork off a tar process. */
- if (pipe(pipefds) == -1) {
- cleanup(0);
- errx(2, "%s: cannot create pipe", __func__);
- }
- if ((pid = fork()) == -1) {
- cleanup(0);
- errx(2, "%s: cannot fork process for tar", __func__);
- }
- if (pid == 0) { /* The child */
- dup2(pipefds[0], 0);
- close(pipefds[0]);
- close(pipefds[1]);
- execv("/usr/bin/tar", (char * const *)(uintptr_t)args);
- cleanup(0);
- errx(2, "%s: failed to execute tar command", __func__);
- }
-
- /* Meanwhile, back in the parent process ... */
- close(pipefds[0]);
- if ((totar = fdopen(pipefds[1], "w")) == NULL) {
- cleanup(0);
- errx(2, "%s: fdopen failed", __func__);
- }
-
- fprintf(totar, "%s\n", CONTENTS_FNAME);
- fprintf(totar, "%s\n", COMMENT_FNAME);
- fprintf(totar, "%s\n", DESC_FNAME);
-
- if (Install)
- fprintf(totar, "%s\n", INSTALL_FNAME);
- if (PostInstall)
- fprintf(totar, "%s\n", POST_INSTALL_FNAME);
- if (DeInstall)
- fprintf(totar, "%s\n", DEINSTALL_FNAME);
- if (PostDeInstall)
- fprintf(totar, "%s\n", POST_DEINSTALL_FNAME);
- if (Require)
- fprintf(totar, "%s\n", REQUIRE_FNAME);
- if (Display)
- fprintf(totar, "%s\n", DISPLAY_FNAME);
- if (Mtree)
- fprintf(totar, "%s\n", MTREE_FNAME);
-
- for (p = plist->head; p; p = p->next) {
- if (p->type == PLIST_FILE)
- fprintf(totar, "%s\n", p->name);
- else if (p->type == PLIST_CWD && p->name == NULL)
- fprintf(totar, "-C\n%s\n", prefix);
- else if (p->type == PLIST_CWD && BaseDir && p->name && p->name[0] == '/')
- fprintf(totar, "-C\n%s%s\n", BaseDir, p->name);
- else if (p->type == PLIST_CWD || p->type == PLIST_SRC)
- fprintf(totar, "-C\n%s\n", p->name);
- else if (p->type == PLIST_IGNORE)
- p = p->next;
- if (p->type == PLIST_CWD && !prefix)
- prefix = p->name;
-
- }
-
- fclose(totar);
- wait(&ret);
- /* assume either signal or bad exit is enough for us */
- if (ret) {
- cleanup(0);
- errx(2, "%s: tar command failed with code %d", __func__, ret);
- }
-}
-
-static void
-sanity_check()
-{
- if (!Comment) {
- cleanup(0);
- errx(2, "%s: required package comment string is missing (-c comment)",
- __func__);
- }
- if (!Desc) {
- cleanup(0);
- errx(2, "%s: required package description string is missing (-d desc)",
- __func__);
- }
- if (!Contents) {
- cleanup(0);
- errx(2, "%s: required package contents list is missing (-f [-]file)",
- __func__);
- }
-}
-
-
-/* Clean up those things that would otherwise hang around */
-void
-cleanup(int sig)
-{
- int in_cleanup = 0;
-
- if (!in_cleanup) {
- in_cleanup = 1;
- leave_playpen();
- }
- if (sig)
- exit(1);
-}
-
-static int
-create_from_installed_recursive(const char *pkg, const char *suf)
-{
- FILE *fp;
- Package plist;
- PackingList p;
- char tmp[PATH_MAX];
- int rval;
-
- if (!create_from_installed(InstalledPkg, pkg, suf))
- return FALSE;
- snprintf(tmp, sizeof(tmp), "%s/%s/%s", LOG_DIR, InstalledPkg, CONTENTS_FNAME);
- if (!fexists(tmp)) {
- warnx("can't find package '%s' installed!", InstalledPkg);
- return FALSE;
- }
- /* Suck in the contents list */
- plist.head = plist.tail = NULL;
- fp = fopen(tmp, "r");
- if (!fp) {
- warnx("unable to open %s file", tmp);
- return FALSE;
- }
- read_plist(&plist, fp);
- fclose(fp);
- rval = TRUE;
- for (p = plist.head; p ; p = p->next) {
- if (p->type != PLIST_PKGDEP)
- continue;
- if (Verbose)
- printf("Creating package %s\n", p->name);
- if (!create_from_installed(p->name, p->name, suf)) {
- rval = FALSE;
- break;
- }
- }
- free_plist(&plist);
- return rval;
-}
-
-static int
-create_from_installed(const char *ipkg, const char *pkg, const char *suf)
-{
- FILE *fp;
- Package plist;
- char homedir[MAXPATHLEN], log_dir[FILENAME_MAX];
-
- snprintf(log_dir, sizeof(log_dir), "%s/%s", LOG_DIR, ipkg);
- if (!fexists(log_dir)) {
- warnx("can't find package '%s' installed!", ipkg);
- return FALSE;
- }
- getcwd(homedir, sizeof(homedir));
- if (chdir(log_dir) == FAIL) {
- warnx("can't change directory to '%s'!", log_dir);
- return FALSE;
- }
- /* Suck in the contents list */
- plist.head = plist.tail = NULL;
- fp = fopen(CONTENTS_FNAME, "r");
- if (!fp) {
- warnx("unable to open %s file", CONTENTS_FNAME);
- return FALSE;
- }
- read_plist(&plist, fp);
- fclose(fp);
-
- Install = isfile(INSTALL_FNAME) ? (char *)INSTALL_FNAME : NULL;
- PostInstall = isfile(POST_INSTALL_FNAME) ?
- (char *)POST_INSTALL_FNAME : NULL;
- DeInstall = isfile(DEINSTALL_FNAME) ? (char *)DEINSTALL_FNAME : NULL;
- PostDeInstall = isfile(POST_DEINSTALL_FNAME) ?
- (char *)POST_DEINSTALL_FNAME : NULL;
- Require = isfile(REQUIRE_FNAME) ? (char *)REQUIRE_FNAME : NULL;
- Display = isfile(DISPLAY_FNAME) ? (char *)DISPLAY_FNAME : NULL;
- Mtree = isfile(MTREE_FNAME) ? (char *)MTREE_FNAME : NULL;
-
- make_dist(homedir, pkg, suf, &plist);
-
- free_plist(&plist);
- if (chdir(homedir) == FAIL) {
- warnx("can't change directory to '%s'!", homedir);
- return FALSE;
- }
- return TRUE;
-}
diff --git a/usr.sbin/pkg_install/create/pkg_create.1 b/usr.sbin/pkg_install/create/pkg_create.1
deleted file mode 100644
index 18780a0..0000000
--- a/usr.sbin/pkg_install/create/pkg_create.1
+++ /dev/null
@@ -1,670 +0,0 @@
-.\"
-.\" FreeBSD install - a package for the installation and maintenance
-.\" of non-core utilities.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" Jordan K. Hubbard
-.\"
-.\"
-.\" @(#)pkg_create.1
-.\" $FreeBSD$
-.\"
-.\" hacked up by John Kohl for NetBSD--fixed a few bugs, extended keywords,
-.\" added dependency tracking, etc.
-.\"
-.\" [jkh] Took John's changes back and made some additional extensions for
-.\" better integration with FreeBSD's new ports collection.
-.\"
-.Dd November 9, 2012
-.Dt PKG_CREATE 1
-.Os
-.Sh NAME
-.Nm pkg_create
-.Nd a utility for creating software package distributions
-.Sh SYNOPSIS
-.Nm
-.Op Fl YNOhjnvyz
-.Op Fl C Ar conflicts
-.Op Fl P Ar pkgs
-.Op Fl p Ar prefix
-.Op Fl i Ar iscript
-.Op Fl I Ar piscript
-.Op Fl k Ar dscript
-.Op Fl K Ar pdscript
-.Op Fl r Ar rscript
-.Op Fl s Ar srcdir
-.Op Fl S Ar basedir
-.Op Fl t Ar template
-.Op Fl X Ar excludefile
-.Op Fl D Ar displayfile
-.Op Fl m Ar mtreefile
-.Op Fl o Ar originpath
-.Fl c Ar comment
-.Fl d Ar description
-.Fl f Ar packlist
-.Ar pkg-filename
-.Nm
-.Op Fl EGYNRhnvxy
-.Fl b Ar pkg-name
-.Op Ar pkg-filename
-.Sh DESCRIPTION
-The
-.Nm
-command is used to create packages that will subsequently be fed to
-one of the package extraction/info utilities.
-The input description
-and command line arguments for the creation of a package are not
-meant to be human-generated, though it is easy enough to do so.
-It is more expected that you will use a front-end tool for
-the job rather than muddling through it yourself.
-Nonetheless, a short
-description of the input syntax is included in this document.
-.Sh OPTIONS
-The following command line options are supported:
-.Bl -tag -width indent
-.It Fl f Ar packinglist
-Fetch
-.Dq packing list
-for package from the file
-.Ar packinglist
-or
-.Cm stdin
-if
-.Ar packinglist
-is a
-.Cm -
-(dash).
-.It Fl c Xo
-.Oo Fl Oc Ns Ar desc
-.Xc
-Fetch package
-.Dq one line description
-from file
-.Ar desc
-or, if preceded by
-.Cm - ,
-the argument itself.
-This string should also
-give some idea of which version of the product (if any) the package
-represents.
-.It Fl d Xo
-.Oo Fl Oc Ns Ar desc
-.Xc
-Fetch long description for package from file
-.Ar desc
-or, if preceded by
-.Cm - ,
-the argument itself.
-.It Fl Y , -yes
-Assume a default answer of `Yes' for any questions asked.
-.It Fl N , -no
-Assume a default answer of `No' for any questions asked.
-.It Fl O , -plist-only
-Go into a `packing list Only' mode.
-This is a custom hack for the
-.Fx
-.Em "Ports Collection"
-and is used to do `fake pkg_add' operations when a port is installed.
-In such cases, it is necessary to know what the final, adjusted packing
-list will look like.
-.It Fl v , -verbose
-Turn on verbose output.
-.It Fl h
-Force tar to follow symbolic links, so that the files they point to
-are dumped, rather than the links themselves.
-.It Fl i Ar iscript
-Set
-.Ar iscript
-to be the pre-install procedure for the package.
-This can be any executable
-program (or shell script).
-It will be invoked automatically when the
-package is later installed.
-It will be passed the package's name as the
-first argument.
-.Pp
-.Sy Note :
-if the
-.Fl I
-option is not given, this script will serve as both the pre-install and the
-post-install script for the package, differentiating between the
-functionality by passing the keywords
-.Ar PRE-INSTALL
-and
-.Ar POST-INSTALL
-respectively, after the package's name.
-.It Fl I Ar piscript
-Set
-.Ar piscript
-to be the post-install procedure for the package.
-This can be any
-executable program (or shell script).
-It will be invoked automatically
-when the package is later installed.
-It will be passed the package's name as
-the first argument.
-.It Fl C Ar conflicts
-Set the initial package conflict list to
-.Ar conflicts .
-This is assumed to be a whitespace separated list of package names
-and is meant as a convenient shorthand for specifying multiple
-.Cm @conflicts
-directives in the packing list (see PACKING LIST DETAILS section below).
-.It Fl P Ar pkgs
-Set the initial package dependency list to
-.Ar pkgs .
-This is assumed to be a whitespace separated list of package names
-and is meant as a convenient shorthand for specifying multiple
-.Cm @pkgdep
-directives in the packing list (see
-.Sx "PACKING LIST DETAILS"
-section below).
-Each argument from the
-.Ar pkgs
-list could be in the form
-.Ar pkgname Ns Op : Ns Ar pkgorigin ,
-where optional
-.Ar pkgorigin
-element denotes origin of each dependency from the list and it is
-recorded into the packing list along with the
-.Ar pkgname
-using
-.Cm @comment
-directive.
-.It Fl p , -prefix Ar prefix
-Set
-.Ar prefix
-as the initial directory
-.Dq base
-to start from in selecting files for
-the package.
-.It Fl k Ar dscript
-Set
-.Ar dscript
-to be the de-install procedure for the package.
-This can be any executable
-program (or shell script).
-It will be invoked automatically when the
-package is later (if ever) de-installed.
-It will be passed the package's
-name as the first argument.
-.Pp
-.Sy Note :
-if the
-.Fl K
-option is not given, this script will serve as both the de-install and the
-post-deinstall script for the package, differentiating between the
-functionality by passing the keywords
-.Ar DEINSTALL
-and
-.Ar POST-DEINSTALL
-respectively, along with the package's name.
-.It Fl K Ar pdscript
-Set
-.Ar pdscript
-to be the post-deinstall procedure for the package.
-This can be any
-executable program (or shell script).
-It will be invoked automatically when
-the package is later de-installed.
-It will be passed the package's name as
-the first argument.
-.It Fl r Ar rscript
-Set
-.Ar rscript
-to be the
-.Dq requirements
-procedure for the package.
-This can be any
-executable program (or shell script).
-It will be invoked automatically
-at installation/deinstallation time to determine whether or not
-installation/deinstallation should proceed.
-To differentiate between installation and deinstallation, the keywords
-.Ar INSTALL
-and
-.Ar DEINSTALL
-are passed respectively, along with the package's name.
-.It Fl s Ar srcdir
-.Ar srcdir
-will override the value of
-.Cm @cwd
-during package creation.
-.It Fl S Ar basedir
-.Ar basedir
-will be prefixed to all
-.Cm @cwd
-during package creation.
-.It Fl t , -template Ar template
-Use
-.Ar template
-as the input to
-.Xr mktemp 3 .
-By default, this is the string
-.Pa /tmp/instmp.XXXXXX ,
-but it may be necessary to override it in the situation where
-space in your
-.Pa /tmp
-directory is limited.
-Be sure to leave some number of `X' characters
-for
-.Xr mktemp 3
-to fill in with a unique ID.
-.It Fl X Ar excludefile
-Pass
-.Ar excludefile
-as a
-.Fl exclude-from
-argument to
-.Cm tar
-when creating final package.
-See
-.Cm tar
-man page (or run
-.Cm tar
-with
-.Fl -help
-flag) for further information on using this flag.
-.It Fl D Ar displayfile
-Display the file (by concatenating it to stdout)
-after installing the package.
-Useful for things like
-legal notices on almost-free software, etc.
-.It Fl m Ar mtreefile
-Run
-.Xr mtree 8
-with input from mtreefile before the package is installed.
-Mtree is invoked as
-.Cm mtree
-.Fl u
-.Fl f
-.Ar mtreefile
-.Fl d
-.Fl e
-.Fl p
-.Pa prefix ,
-where
-.Pa prefix
-is the name of the first directory named by a
-.Cm @cwd
-directive.
-.It Fl o , -origin Ar originpath
-Record an
-.Ar originpath ,
-as location of the port from which package has been created in the
-.Fx
-.Em "Ports Collection" .
-It should be in the form
-.Pa MASTERCATEGORY/PORTDIR .
-.It Fl j
-Use
-.Xr bzip2 1
-utility to compress package tarball instead of
-.Xr gzip 1 .
-Please note that this option is a NO-OP if the format of the resulting
-archive is explicitly specified by the recognizable suffix of
-.Ar pkg-filename .
-Currently
-.Nm
-recognizes the following suffixes:
-.Pa .tbz , .tgz, .txz
-and
-.Pa .tar .
-.It Fl y
-Compatibility synonym for
-.Fl j .
-.It Fl z
-Use
-.Xr gzip 1
-utility to compress package tarball.
-.It Fl J
-Use
-.Xr xz 1
-utility to compress package tarball instead of
-.Xr gzip 1 .
-Please note that this option is a NO-OP if the format of the resulting
-archive is explicitly specified by the recognizable suffix of
-.Ar pkg-filename .
-Currently
-.Nm
-recognizes the following suffixes:
-.Pa .tbz , .tgz, .txz
-and
-.Pa .tar .
-.It Fl b , -backup Ar pkg-name
-Create package file from a locally installed package named
-.Ar pkg-name .
-If the
-.Ar pkg-filename
-is not specified, then resulting archive will be created in the
-current directory and named
-.Ar pkg-name
-with an appropriate extraction suffix applied.
-.It Fl R , -recursive
-When creating package file from a locally installed package
-also create package files for all packages required by
-.Ar pkg-name .
-Resulting archive(s) will be created in the current directory
-and named using name of the respective package with appropriate
-extraction suffix applied.
-.It Fl x , -regex
-Use basic regular expressions for
-.Ar pkg-name .
-.It Fl E , -extended
-Use extended (modern) regular expressions for
-.Ar pkg-name .
-.It Fl G , -no-glob
-Use exact matching for
-.Ar pkg-name .
-.It Fl n
-Run in
-.Dq no clobber
-mode.
-If a package tarball exists, the
-.Nm
-utility will not overwrite it.
-This is useful, for example, when multiple packages are saved with
-several consecutive runs of
-.Nm
-with the
-.Fl Rb
-options.
-Saving common dependencies multiple times would do a lot of duplicate
-work in this case.
-The
-.Fl n
-option avoids repackaging common dependencies multiple times.
-.El
-.Sh PACKING LIST DETAILS
-The
-.Dq packing list
-format (see
-.Fl f )
-is fairly simple, being
-nothing more than a single column of filenames to include in the
-package.
-However, since absolute pathnames are generally a bad idea
-for a package that could be installed potentially anywhere, there is
-another method of specifying where things are supposed to go
-and, optionally, what ownership and mode information they should be
-installed with.
-This is done by embedding specialized command sequences
-in the packing list.
-Briefly described, these sequences are:
-.Bl -tag -width indent -compact
-.It Cm @cwd Op Ar directory
-Set the internal directory pointer to point to
-.Ar directory .
-All subsequent filenames will be assumed relative to this directory.
-If no
-.Ar directory
-argument is given, it will set the internal directory pointer to the
-first prefix value.
-Note:
-.Cm @cd
-is also an alias for this command.
-.It Cm @srcdir Ar directory
-Set the internal directory pointer for _creation only_ to
-.Ar directory .
-That is to say that it overrides
-.Cm @cwd
-for package creation but not extraction.
-.It Cm @exec Ar command
-Execute
-.Ar command
-as part of the unpacking process.
-If
-.Ar command
-contains any of the following sequences somewhere in it, they will
-be expanded inline.
-For the following examples, assume that
-.Cm @cwd
-is set to
-.Pa /usr/local
-and the last extracted file was
-.Pa bin/emacs .
-.Bl -tag -width indent -compact
-.It Cm "%F"
-Expands to the last filename extracted (as specified), in the example case
-.Pa bin/emacs
-.It Cm "\&%D"
-Expand to the current directory prefix, as set with
-.Cm @cwd ,
-in the example case
-.Pa /usr/local .
-.It Cm "\&%B"
-Expand to the
-.Dq basename
-of the fully qualified filename, that
-is the current directory prefix, plus the last filespec, minus
-the trailing filename.
-In the example case, that would be
-.Pa /usr/local/bin .
-.It Cm "%f"
-Expand to the
-filename
-part of the fully qualified name, or
-the converse of
-.Cm \&%B ,
-being in the example case,
-.Pa emacs .
-.El
-.It Cm @unexec Ar command
-Execute
-.Ar command
-as part of the deinstallation process.
-Expansion of special
-.Cm %
-sequences is the same as for
-.Cm @exec .
-This command is not executed during the package add, as
-.Cm @exec
-is, but rather when the package is deleted.
-This is useful
-for deleting links and other ancillary files that were created
-as a result of adding the package, but not directly known to
-the package's table of contents (and hence not automatically
-removable).
-The advantage of using
-.Cm @unexec
-over a deinstallation script is that you can use the
-.Dq special sequence expansion
-to get at files regardless of where they have
-been potentially redirected (see
-.Fl p ) .
-.It Cm @mode Ar mode
-Set default permission for all subsequently extracted files to
-.Ar mode .
-Format is the same as that used by the
-.Cm chmod
-command (well, considering that it is later handed off to it, that is
-no surprise).
-Use without an arg to set back to default (extraction)
-permissions.
-.It Cm @option Ar option
-Set internal package options, the only two currently supported ones
-being
-.Ar extract-in-place ,
-which tells the pkg_add command not to extract the package's tarball
-into a staging area but rather directly into the target
-hierarchy (this is typically meant to be used only by distributions
-or other special package types), and
-.Ar preserve ,
-which tells pkg_add to move any existing files out of the way,
-preserving the previous contents (which are also resurrected on
-pkg_delete, so caveat emptor).
-.It Cm @owner Ar user
-Set default ownership for all subsequently extracted files to
-.Ar user .
-Use without an arg to set back to default (extraction)
-ownership.
-.It Cm @group Ar group
-Set default group ownership for all subsequently extracted files to
-.Ar group .
-Use without an arg to set back to default (extraction)
-group ownership.
-.It Cm @comment Ar string
-Imbed a comment in the packing list.
-Useful in
-trying to document some particularly hairy sequence that
-may trip someone up later.
-.It Cm @noinst Ar option Ar file
-Specify that the package would have installed
-.Pa file
-if
-.Pa option
-had been specified at build time.
-The action of
-.Cm @noinst
-is the same that
-.Cm @comment
-(which is doing nothing, it is just additional information).
-.It Cm @ignore
-Used internally to tell extraction to ignore the next file (do not
-copy it anywhere), as it is used for some special purpose.
-.It Cm @ignore_inst
-Similar to
-.Cm @ignore ,
-but the ignoring of the next file is delayed one evaluation cycle.
-This
-makes it possible to use this directive in the
-.Ar packinglist
-file, so you can pack a
-specialized datafile in with a distribution for your install script (or
-something) yet have the installer ignore it.
-.It Cm @name Ar name
-Set the name of the package.
-This is mandatory and is usually
-put at the top.
-This name is potentially different from the name of
-the file it came in, and is used when keeping track of the package
-for later deinstallation.
-Note that
-.Nm
-will derive this field from the package name and add it automatically
-if none is given.
-.It Cm @dirrm Ar name
-Declare directory
-.Pa name
-to be deleted at deinstall time.
-By default, directories created by a
-package installation are not deleted when the package is deinstalled;
-this provides an explicit directory cleanup method.
-This directive
-should appear at the end of the package list.
-If more than one
-.Cm @dirrm
-directives are used, the directories are removed in the order specified.
-The
-.Pa name
-directory will not be removed unless it is empty.
-.It Cm @mtree Ar name
-Declare
-.Pa name
-as an
-.Xr mtree 8
-input file to be used at install time (see
-.Fl m
-above).
-Only the first
-.Cm @mtree
-directive is honored.
-.It Cm @display Ar name
-Declare
-.Pa name
-as the file to be displayed at install time (see
-.Fl D
-above).
-.It Cm @pkgdep Ar pkgname
-Declare a dependency on the
-.Ar pkgname
-package.
-The
-.Ar pkgname
-package must be installed before this package may be
-installed, and this package must be deinstalled before the
-.Ar pkgname
-package is deinstalled.
-Multiple
-.Cm @pkgdep
-directives may be used if the package depends on multiple other packages.
-.It Cm @conflicts Ar pkgcflname
-Declare a conflict with the
-.Ar pkgcflname
-package, as the two packages contain references to the same files,
-and so cannot co-exist on the same system.
-.El
-.Sh ENVIRONMENT
-The environment variable
-.Ev PKG_TMPDIR
-names the directory where
-.Nm
-will attempt to create its temporary files.
-If
-.Ev PKG_TMPDIR
-is not set,
-the directory named by the contents of
-.Ev TMPDIR
-will be used.
-If neither of
-.Ev PKG_TMPDIR
-and
-.Ev TMPDIR
-are set, the builtin defaults are used.
-.Sh FILES
-.Bl -tag -width /usr/tmp -compact
-.It Pa /var/tmp
-Temporary directory if environmental variables
-.Ev PKG_TMPDIR
-and
-.Ev TMPDIR
-are not set.
-.It Pa /tmp
-The next choice if
-.Pa /var/tmp
-does not exist.
-.It Pa /usr/tmp
-The last choice if
-.Pa /tmp
-is unsuitable.
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh SEE ALSO
-.Xr pkg_add 1 ,
-.Xr pkg_delete 1 ,
-.Xr pkg_info 1 ,
-.Xr pkg_version 1 ,
-.Xr sysconf 3
-.Sh HISTORY
-The
-.Nm
-command first appeared in
-.Fx .
-.Sh AUTHORS
-.An Jordan Hubbard
-.Sh CONTRIBUTORS
-.An John Kohl Aq jtk@rational.com ,
-.An Oliver Eikemeier Aq eik@FreeBSD.org
-.Sh BUGS
-Hard links between files in a distribution must be bracketed by
-.Cm @cwd
-directives in order to be preserved as hard links when the package is
-extracted.
-They additionally must not end up being split between
-.Cm tar
-invocations due to exec argument-space limitations (this depends on the
-value returned by
-.Fn sysconf _SC_ARG_MAX ) .
-.Pp
-Sure to be others.
diff --git a/usr.sbin/pkg_install/create/pl.c b/usr.sbin/pkg_install/create/pl.c
deleted file mode 100644
index 1316eda..0000000
--- a/usr.sbin/pkg_install/create/pl.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Routines for dealing with the packing list.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include "create.h"
-#include <errno.h>
-#include <err.h>
-#include <md5.h>
-
-/* Add an MD5 checksum entry for a file or link */
-void
-add_cksum(Package *pkg, PackingList p, const char *fname)
-{
- char *cp = NULL, buf[33];
-
- if (issymlink(fname)) {
- int len;
- char lnk[FILENAME_MAX];
-
- if ((len = readlink(fname, lnk, FILENAME_MAX)) > 0)
- cp = MD5Data((unsigned char *)lnk, len, buf);
- } else if (isfile(fname)) {
- /* Don't record MD5 checksum for device nodes and such */
- cp = MD5File(fname, buf);
- }
-
- if (cp != NULL) {
- PackingList tmp = new_plist_entry();
-
- tmp->name = copy_string(strconcat("MD5:", cp));
- tmp->type = PLIST_COMMENT;
- tmp->next = p->next;
- tmp->prev = p;
- p->next = tmp;
- if (pkg->tail == p)
- pkg->tail = tmp;
- }
-}
-
-/* Check a list for files that require preconversion */
-void
-check_list(const char *home, Package *pkg)
-{
- const char *where = home;
- const char *there = NULL;
- char name[FILENAME_MAX];
- char *prefix = NULL;
- PackingList p;
-
- for (p = pkg->head; p != NULL; p = p->next)
- switch (p->type) {
- case PLIST_CWD:
- if (!prefix)
- prefix = p->name;
- where = (p->name == NULL) ? prefix : p->name;
- break;
-
- case PLIST_IGNORE:
- p = p->next;
- break;
-
- case PLIST_SRC:
- there = p->name;
- break;
-
- case PLIST_FILE:
- if (there)
- snprintf(name, sizeof(name), "%s/%s", there, p->name);
- else
- snprintf(name, sizeof(name), "%s%s/%s",
- BaseDir && where && where[0] == '/' ? BaseDir : "", where, p->name);
-
- add_cksum(pkg, p, name);
- break;
- default:
- break;
- }
-}
-
-static int
-trylink(const char *from, const char *to)
-{
- if (link(from, to) == 0)
- return 0;
- if (errno == ENOENT) {
- /* try making the container directory */
- char *cp = strrchr(to, '/');
- if (cp)
- vsystem("/bin/mkdir -p %.*s", cp - to,
- to);
- return link(from, to);
- }
- return -1;
-}
-
-#define STARTSTRING "/usr/bin/tar cf -"
-#define TOOBIG(str) (int)strlen(str) + 6 + (int)strlen(home) + where_count > maxargs
-#define PUSHOUT() /* push out string */ \
- if (where_count > (int)sizeof(STARTSTRING)-1) { \
- strcat(where_args, "|/usr/bin/tar xpf -"); \
- if (system(where_args)) { \
- cleanup(0); \
- errx(2, "%s: can't invoke tar pipeline", __func__); \
- } \
- memset(where_args, 0, maxargs); \
- last_chdir = NULL; \
- strcpy(where_args, STARTSTRING); \
- where_count = sizeof(STARTSTRING)-1; \
- }
-
-/*
- * Copy unmarked files in packing list to playpen - marked files
- * have already been copied in an earlier pass through the list.
- */
-void
-copy_plist(const char *home, Package *plist)
-{
- PackingList p = plist->head;
- const char *where = home;
- const char *there = NULL, *mythere;
- char *where_args, *prefix = NULL;
- const char *last_chdir, *root = "/";
- long maxargs;
- int where_count = 0, add_count;
- struct stat stb;
- dev_t curdir;
-
- maxargs = sysconf(_SC_ARG_MAX);
- maxargs -= 64; /*
- * Some slop for the tar cmd text,
- * and sh -c
- */
- where_args = malloc(maxargs);
- if (!where_args) {
- cleanup(0);
- errx(2, "%s: can't get argument list space", __func__);
- }
-
- memset(where_args, 0, maxargs);
- strcpy(where_args, STARTSTRING);
- where_count = sizeof(STARTSTRING)-1;
- last_chdir = 0;
-
- if (stat(".", &stb) == 0)
- curdir = stb.st_dev;
- else
- curdir = (dev_t) -1; /*
- * It's ok if this is a valid dev_t;
- * this is just a hint for an
- * optimization.
- */
-
- while (p) {
- if (p->type == PLIST_CWD)
- {
- if (!prefix)
- prefix = p->name;
- where = p->name == NULL ? prefix : p->name;
- }
- else if (p->type == PLIST_SRC)
- there = p->name;
- else if (p->type == PLIST_IGNORE)
- p = p->next;
- else if (p->type == PLIST_FILE && !p->marked) {
- char fn[FILENAME_MAX];
-
-
- /* First, look for it in the "home" dir */
- sprintf(fn, "%s/%s", home, p->name);
- if (fexists(fn)) {
- if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
- S_ISREG(stb.st_mode)) {
- /*
- * If we can link it to the playpen, that avoids a copy
- * and saves time.
- */
- if (p->name[0] != '/') {
- /*
- * Don't link abspn stuff--it doesn't come from
- * local dir!
- */
- if (trylink(fn, p->name) == 0) {
- p = p->next;
- continue;
- }
- }
- }
- if (TOOBIG(fn)) {
- PUSHOUT();
- }
- if (p->name[0] == '/') {
- add_count = snprintf(&where_args[where_count],
- maxargs - where_count,
- " %s %s",
- last_chdir == root ? "" : "-C /",
- p->name);
- last_chdir = root;
- } else {
- add_count = snprintf(&where_args[where_count],
- maxargs - where_count,
- " %s%s %s",
- last_chdir == home ? "" : "-C ",
- last_chdir == home ? "" : home,
- p->name);
- last_chdir = home;
- }
- if (add_count < 0 || add_count >= maxargs - where_count) {
- cleanup(0);
- errx(2, "%s: oops, miscounted strings!", __func__);
- }
- where_count += add_count;
- }
- /*
- * Otherwise, try along the actual extraction path..
- */
- else {
- if (p->name[0] == '/')
- mythere = root;
- else mythere = there;
- if (mythere)
- snprintf(fn, sizeof(fn), "%s/%s", mythere, p->name);
- else
- snprintf(fn, sizeof(fn), "%s%s/%s",
- BaseDir && where && where[0] == '/' ? BaseDir : "", where, p->name);
- if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
- S_ISREG(stb.st_mode)) {
- /*
- * If we can link it to the playpen, that avoids a copy
- * and saves time.
- */
- if (trylink(fn, p->name) == 0) {
- p = p->next;
- continue;
- }
- }
- if (TOOBIG(p->name)) {
- PUSHOUT();
- }
- if (last_chdir == (mythere ? mythere : where))
- add_count = snprintf(&where_args[where_count],
- maxargs - where_count,
- " %s", p->name);
- else
- add_count = snprintf(&where_args[where_count],
- maxargs - where_count,
- " -C %s %s",
- mythere ? mythere : where,
- p->name);
- if (add_count < 0 || add_count >= maxargs - where_count) {
- cleanup(0);
- errx(2, "%s: oops, miscounted strings!", __func__);
- }
- where_count += add_count;
- last_chdir = (mythere ? mythere : where);
- }
- }
- p = p->next;
- }
- PUSHOUT();
- free(where_args);
-}
diff --git a/usr.sbin/pkg_install/delete/Makefile b/usr.sbin/pkg_install/delete/Makefile
deleted file mode 100644
index c9a0fde..0000000
--- a/usr.sbin/pkg_install/delete/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $FreeBSD$
-
-PROG= pkg_delete
-SRCS= main.c perform.c
-
-CFLAGS+= -I${.CURDIR}/../lib
-
-WFORMAT?= 1
-
-DPADD= ${LIBINSTALL} ${LIBMD}
-LDADD= ${LIBINSTALL} -lmd
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/delete/Makefile.depend b/usr.sbin/pkg_install/delete/Makefile.depend
deleted file mode 100644
index 86f84fe..0000000
--- a/usr.sbin/pkg_install/delete/Makefile.depend
+++ /dev/null
@@ -1,21 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libmd \
- lib/libutil \
- usr.sbin/pkg_install/lib \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/delete/delete.h b/usr.sbin/pkg_install/delete/delete.h
deleted file mode 100644
index f2f4057..0000000
--- a/usr.sbin/pkg_install/delete/delete.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Include and define various things wanted by the delete command.
- *
- */
-
-#ifndef _INST_DELETE_H_INCLUDE
-#define _INST_DELETE_H_INCLUDE
-
-extern char *Prefix;
-extern Boolean CleanDirs;
-extern Boolean Interactive;
-extern Boolean NoDeInstall;
-extern Boolean Recursive;
-extern char *Directory;
-extern char *PkgName;
-extern match_t MatchType;
-
-#endif /* _INST_DELETE_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/delete/main.c b/usr.sbin/pkg_install/delete/main.c
deleted file mode 100644
index 0b97ddd..0000000
--- a/usr.sbin/pkg_install/delete/main.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- *
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the delete module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <getopt.h>
-#include <err.h>
-
-#include "lib.h"
-#include "delete.h"
-
-char *Prefix = NULL;
-Boolean CleanDirs = FALSE;
-Boolean Interactive = FALSE;
-Boolean NoDeInstall = FALSE;
-Boolean Recursive = FALSE;
-match_t MatchType = MATCH_GLOB;
-
-static void usage(void);
-
-static char opts[] = "adDfGhinp:rvxX";
-static struct option longopts[] = {
- { "all", no_argument, NULL, 'a' },
- { "clean-dirs", no_argument, NULL, 'd' },
- { "dry-run", no_argument, NULL, 'n' },
- { "extended", no_argument, NULL, 'X' },
- { "force", no_argument, NULL, 'f' },
- { "help", no_argument, NULL, 'h' },
- { "interactive",no_argument, NULL, 'i' },
- { "prefix", required_argument, NULL, 'p' },
- { "recursive", no_argument, NULL, 'r' },
- { "regex", no_argument, NULL, 'x' },
- { "no-glob", no_argument, NULL, 'G' },
- { "no-script", no_argument, NULL, 'D' },
- { "no-scripts", no_argument, NULL, 'D' },
- { "verbose", no_argument, NULL, 'v' },
- { NULL, 0, NULL, 0 },
-};
-
-int
-main(int argc, char **argv)
-{
- int ch, error;
- char **pkgs, **start;
- char *pkgs_split;
- const char *tmp;
- struct stat stat_s;
-
- warnpkgng();
- pkgs = start = argv;
- while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1)
- switch(ch) {
- case 'v':
- Verbose++;
- break;
-
- case 'f':
- Force = TRUE;
- break;
-
- case 'p':
- Prefix = optarg;
- break;
-
- case 'D':
- NoDeInstall = TRUE;
- break;
-
- case 'd':
- CleanDirs = TRUE;
- break;
-
- case 'n':
- Fake = TRUE;
- Verbose = TRUE;
- break;
-
- case 'a':
- MatchType = MATCH_ALL;
- break;
-
- case 'G':
- MatchType = MATCH_EXACT;
- break;
-
- case 'x':
- MatchType = MATCH_REGEX;
- break;
-
- case 'X':
- MatchType = MATCH_EREGEX;
- break;
-
- case 'i':
- Interactive = TRUE;
- break;
-
- case 'r':
- Recursive = TRUE;
- break;
-
- case 'h':
- default:
- usage();
- break;
- }
-
- argc -= optind;
- argv += optind;
-
- /* Get all the remaining package names, if any */
- while (*argv) {
- /* Don't try to apply heuristics if arguments are regexs */
- if (MatchType != MATCH_REGEX)
- while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) {
- *pkgs_split++ = '\0';
- /*
- * If character after the '/' is alphanumeric, then we've found the
- * package name. Otherwise we've come across a trailing '/' and
- * need to continue our quest.
- */
- if (isalnum(*pkgs_split) || ((MatchType == MATCH_GLOB) && \
- strpbrk(pkgs_split, "*?[]") != NULL)) {
- *argv = pkgs_split;
- break;
- }
- }
- *pkgs++ = *argv++;
- }
-
- /* If no packages, yelp */
- if (pkgs == start && MatchType != MATCH_ALL)
- warnx("missing package name(s)"), usage();
- *pkgs = NULL;
- tmp = LOG_DIR;
- (void) stat(tmp, &stat_s);
- if (!Fake && getuid() && geteuid() != stat_s.st_uid) {
- if (!Force)
- errx(1, "you do not own %s, use -f to force", tmp);
- else
- warnx("you do not own %s (proceeding anyways)", tmp);
- }
- if ((error = pkg_perform(start)) != 0) {
- if (Verbose)
- warnx("%d package deletion(s) failed", error);
- return error;
- }
- else
- return 0;
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "%s\n%s\n",
- "usage: pkg_delete [-dDfGinrvxX] [-p prefix] pkg-name ...",
- " pkg_delete -a [flags]");
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/delete/perform.c b/usr.sbin/pkg_install/delete/perform.c
deleted file mode 100644
index ea00055..0000000
--- a/usr.sbin/pkg_install/delete/perform.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the main body of the delete module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <err.h>
-#include "lib.h"
-#include "delete.h"
-
-static int pkg_do(char *);
-static void sanity_check(char *);
-static void undepend(char *, char *);
-static char LogDir[FILENAME_MAX];
-
-
-int
-pkg_perform(char **pkgs)
-{
- char **matched, **rb, **rbtmp;
- int errcode, i, j;
- int err_cnt = 0;
- struct reqr_by_entry *rb_entry;
- struct reqr_by_head *rb_list;
-
- if (MatchType != MATCH_EXACT) {
- matched = matchinstalled(MatchType, pkgs, &errcode);
- if (errcode != 0)
- return 1;
- /* Not reached */
-
- /*
- * Copy matched[] into pkgs[], because we'll need to use
- * matchinstalled() later on.
- */
- if (matched != NULL) {
- pkgs = NULL;
- for (i = 0; matched[i] != NULL; i++) {
- pkgs = realloc(pkgs, sizeof(*pkgs) * (i + 2));
- pkgs[i] = strdup(matched[i]);
- }
- pkgs[i] = NULL;
- }
- else switch (MatchType) {
- case MATCH_GLOB:
- break;
- case MATCH_ALL:
- warnx("no packages installed");
- return 0;
- case MATCH_EREGEX:
- case MATCH_REGEX:
- warnx("no packages match pattern(s)");
- return 1;
- default:
- break;
- }
- }
-
- err_cnt += sortdeps(pkgs);
- for (i = 0; pkgs[i]; i++) {
- if (Recursive == TRUE) {
- errcode = requiredby(pkgs[i], &rb_list, FALSE, TRUE);
- if (errcode < 0) {
- err_cnt++;
- } else if (errcode > 0) {
- /*
- * Copy values from the rb_list queue into argv-like NULL
- * terminated list because requiredby() uses some static
- * storage, while pkg_do() below will call this function,
- * thus blowing our rb_list away.
- */
- rbtmp = rb = alloca((errcode + 1) * sizeof(*rb));
- if (rb == NULL) {
- warnx("%s(): alloca() failed", __func__);
- err_cnt++;
- continue;
- }
- STAILQ_FOREACH(rb_entry, rb_list, link) {
- *rbtmp = alloca(strlen(rb_entry->pkgname) + 1);
- if (*rbtmp == NULL) {
- warnx("%s(): alloca() failed", __func__);
- err_cnt++;
- continue;
- }
- strcpy(*rbtmp, rb_entry->pkgname);
- rbtmp++;
- }
- *rbtmp = NULL;
-
- err_cnt += sortdeps(rb);
- for (j = 0; rb[j]; j++)
- err_cnt += pkg_do(rb[j]);
- }
- }
- err_cnt += pkg_do(pkgs[i]);
- }
-
- return err_cnt;
-}
-
-static Package Plist;
-
-/* This is seriously ugly code following. Written very fast! */
-static int
-pkg_do(char *pkg)
-{
- FILE *cfile;
- char *deporigin, **deporigins = NULL, **depnames = NULL, ***depmatches, home[FILENAME_MAX];
- PackingList p;
- int i, len;
- int isinstalled;
- /* support for separate pre/post install scripts */
- int new_m = 0, dep_count = 0;
- const char *pre_script = DEINSTALL_FNAME;
- const char *post_script, *pre_arg, *post_arg;
- struct reqr_by_entry *rb_entry;
- struct reqr_by_head *rb_list;
- int fd;
- struct stat sb;
-
- if (!pkg || !(len = strlen(pkg)))
- return 1;
- if (pkg[len - 1] == '/')
- pkg[len - 1] = '\0';
-
- /* Reset some state */
- if (Plist.head)
- free_plist(&Plist);
-
- sprintf(LogDir, "%s/%s", LOG_DIR, pkg);
-
- isinstalled = isinstalledpkg(pkg);
- if (isinstalled == 0) {
- warnx("no such package '%s' installed", pkg);
- return 1;
- } else if (isinstalled < 0) {
- warnx("the package info for package '%s' is corrupt%s",
- pkg, Force ? " (but I'll delete it anyway)" : " (use -f to force removal)");
- if (!Force)
- return 1;
- if (!Fake) {
- if (vsystem("%s -rf %s", REMOVE_CMD, LogDir)) {
- warnx("couldn't remove log entry in %s, deinstall failed", LogDir);
- } else {
- warnx("couldn't completely deinstall package '%s',\n"
- "only the log entry in %s was removed", pkg, LogDir);
- }
- }
- return 0;
- }
-
- if (!getcwd(home, FILENAME_MAX)) {
- cleanup(0);
- errx(2, "%s: unable to get current working directory!", __func__);
- }
-
- if (chdir(LogDir) == FAIL) {
- warnx("unable to change directory to %s! deinstall failed", LogDir);
- return 1;
- }
-
- if (Interactive == TRUE) {
- int first, ch;
-
- (void)fprintf(stderr, "delete %s? ", pkg);
- (void)fflush(stderr);
- first = ch = getchar();
- while (ch != '\n' && ch != EOF)
- ch = getchar();
- if (first != 'y' && first != 'Y')
- return 0;
- /* Not reached */
- }
-
- if (requiredby(pkg, &rb_list, FALSE, TRUE) < 0)
- return 1;
- if (!STAILQ_EMPTY(rb_list)) {
- warnx("package '%s' is required by these other packages\n"
- "and may not be deinstalled%s:",
- pkg, Force ? " (but I'll delete it anyway)" : "");
- STAILQ_FOREACH(rb_entry, rb_list, link)
- fprintf(stderr, "%s\n", rb_entry->pkgname);
- if (!Force)
- return 1;
- }
-
- sanity_check(LogDir);
- cfile = fopen(CONTENTS_FNAME, "r");
-
- if (!cfile) {
- warnx("unable to open '%s' file", CONTENTS_FNAME);
- return 1;
- }
-
- /* If we have a prefix, add it now */
- if (Prefix)
- add_plist(&Plist, PLIST_CWD, Prefix);
- read_plist(&Plist, cfile);
- fclose(cfile);
- p = find_plist(&Plist, PLIST_CWD);
-
- if (!p) {
- warnx("package '%s' doesn't have a prefix", pkg);
- return 1;
- }
-
- setenv(PKG_PREFIX_VNAME, p->name, 1);
-
- if ((fd = open(REQUIRE_FNAME, O_RDWR)) != -1) {
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */
- close(fd);
- if (Verbose)
- printf("Executing 'require' script.\n");
- if (vsystem("./%s %s DEINSTALL", REQUIRE_FNAME, pkg)) {
- warnx("package %s fails requirements %s", pkg,
- Force ? "" : "- not deleted");
- if (!Force)
- return 1;
- }
- }
-
- /*
- * Test whether to use the old method of passing tokens to deinstallation
- * scripts, and set appropriate variables..
- */
-
- if (fexists(POST_DEINSTALL_FNAME)) {
- new_m = 1;
- post_script = POST_DEINSTALL_FNAME;
- pre_arg = post_arg = "";
- } else if (fexists(DEINSTALL_FNAME)) {
- post_script = DEINSTALL_FNAME;
- pre_arg = "DEINSTALL";
- post_arg = "POST-DEINSTALL";
- } else {
- post_script = pre_arg = post_arg = NULL;
- }
-
- if (!NoDeInstall && pre_script != NULL && (fd = open(pre_script, O_RDWR)) != -1) {
- if (Fake)
- printf("Would execute de-install script at this point.\n");
- else {
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */
- close(fd);
- if (vsystem("./%s %s %s", pre_script, pkg, pre_arg)) {
- warnx("deinstall script returned error status");
- if (!Force)
- return 1;
- }
- }
- }
-
- for (p = Plist.head; p ; p = p->next) {
- if (p->type != PLIST_PKGDEP)
- continue;
- deporigin = (p->next != NULL && p->next->type == PLIST_DEPORIGIN) ? p->next->name :
- NULL;
- if (Verbose) {
- printf("Trying to remove dependency on package '%s'", p->name);
- if (deporigin != NULL)
- printf(" with '%s' origin", deporigin);
- printf(".\n");
- }
- if (!Fake) {
- if (deporigin) {
- deporigins = realloc(deporigins, (dep_count + 2) * sizeof(*deporigins));
- depnames = realloc(depnames, (dep_count + 1) * sizeof(*depnames));
- deporigins[dep_count] = deporigin;
- deporigins[dep_count + 1] = NULL;
- depnames[dep_count] = p->name;
- dep_count++;
- } else {
- undepend(p->name, pkg);
- }
- }
- }
-
- if (dep_count > 0) {
- /* Undepend all the dependencies at once */
- depmatches = matchallbyorigin((const char **)deporigins, NULL);
- free(deporigins);
- if (depmatches) {
- for (i = 0; i < dep_count; i++) {
- if (depmatches[i]) {
- char **tmp = depmatches[i];
- int j;
- for (j = 0; tmp[j] != NULL; j++)
- undepend(tmp[j], pkg);
- } else if (depnames[i]) {
- undepend(depnames[i], pkg);
- }
- }
- }
- }
-
- if (chdir(home) == FAIL) {
- cleanup(0);
- errx(2, "%s: unable to return to working directory %s!", __func__,
- home);
- }
-
- /*
- * Some packages aren't packed right, so we need to just ignore
- * delete_package()'s status. Ugh! :-(
- */
- if (delete_package(FALSE, CleanDirs, &Plist) == FAIL)
- warnx(
- "couldn't entirely delete package `%s'\n"
- "(perhaps the packing list is incorrectly specified?)", pkg);
-
- if (chdir(LogDir) == FAIL) {
- warnx("unable to change directory to %s! deinstall failed", LogDir);
- return 1;
- }
-
- if (!NoDeInstall && post_script != NULL && (fd = open(post_script, O_RDWR)) != -1) {
- if (Fake)
- printf("Would execute post-deinstall script at this point.\n");
- else {
- fstat(fd, &sb);
- fchmod(fd, sb.st_mode | S_IXALL); /* be sure, chmod a+x */
- close(fd);
- if (vsystem("./%s %s %s", post_script, pkg, post_arg)) {
- warnx("post-deinstall script returned error status");
- if (!Force)
- return 1;
- }
- }
- }
-
- if (chdir(home) == FAIL) {
- cleanup(0);
- errx(2, "%s: unable to return to working directory %s!", __func__,
- home);
- }
-
- if (!Fake) {
- if (vsystem("%s -r%c %s", REMOVE_CMD, Force ? 'f' : ' ', LogDir)) {
- warnx("couldn't remove log entry in %s, deinstall failed", LogDir);
- if (!Force)
- return 1;
- }
- }
- return 0;
-}
-
-static void
-sanity_check(char *pkg)
-{
- if (!fexists(CONTENTS_FNAME)) {
- cleanup(0);
- errx(2, "%s: installed package %s has no %s file!", __func__,
- pkg, CONTENTS_FNAME);
- }
-}
-
-void
-cleanup(int sig)
-{
- if (sig)
- exit(1);
-}
-
-static void
-undepend(char *p, char *pkgname)
-{
- char fname[FILENAME_MAX], ftmp[FILENAME_MAX];
- FILE *fpwr;
- int s;
- struct reqr_by_entry *rb_entry;
- struct reqr_by_head *rb_list;
-
-
- if (requiredby(p, &rb_list, Verbose, FALSE) <= 0)
- return;
- snprintf(fname, sizeof(fname), "%s/%s/%s", LOG_DIR, p, REQUIRED_BY_FNAME);
- snprintf(ftmp, sizeof(ftmp), "%s.XXXXXX", fname);
- s = mkstemp(ftmp);
- if (s == -1) {
- warnx("couldn't open temp file '%s'", ftmp);
- return;
- }
- fpwr = fdopen(s, "w");
- if (fpwr == NULL) {
- close(s);
- warnx("couldn't fdopen temp file '%s'", ftmp);
- goto cleanexit;
- }
- STAILQ_FOREACH(rb_entry, rb_list, link)
- if (strcmp(rb_entry->pkgname, pkgname)) /* no match */
- fputs(rb_entry->pkgname, fpwr), putc('\n', fpwr);
- if (fchmod(s, 0644) == FAIL) {
- warnx("error changing permission of temp file '%s'", ftmp);
- fclose(fpwr);
- goto cleanexit;
- }
- if (fclose(fpwr) == EOF) {
- warnx("error closing temp file '%s'", ftmp);
- goto cleanexit;
- }
- if (rename(ftmp, fname) == -1)
- warnx("error renaming '%s' to '%s'", ftmp, fname);
-cleanexit:
- remove(ftmp);
- return;
-}
diff --git a/usr.sbin/pkg_install/delete/pkg_delete.1 b/usr.sbin/pkg_install/delete/pkg_delete.1
deleted file mode 100644
index a07b1b6..0000000
--- a/usr.sbin/pkg_install/delete/pkg_delete.1
+++ /dev/null
@@ -1,297 +0,0 @@
-.\"
-.\" FreeBSD install - a package for the installation and maintenance
-.\" of non-core utilities.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" Jordan K. Hubbard
-.\"
-.\"
-.\" @(#)pkg_delete.1
-.\" $FreeBSD$
-.\"
-.Dd November 9, 2012
-.Dt PKG_DELETE 1
-.Os
-.Sh NAME
-.Nm pkg_delete
-.Nd a utility for deleting previously installed software package distributions
-.Sh SYNOPSIS
-.Nm
-.Op Fl dDfGinrvxX
-.Op Fl p Ar prefix
-.Ar pkg-name ...
-.Nm
-.Fl a
-.Op Ar flags
-.Sh DESCRIPTION
-The
-.Nm
-command is used to delete packages that have been previously installed
-with the
-.Xr pkg_add 1
-command.
-.Sh WARNING
-.Bf -emphasis
-Since the
-.Nm
-command may execute scripts or programs provided by a package file,
-your system may be susceptible to
-.Dq Em trojan horses
-or other subtle
-attacks from miscreants who create dangerous package files.
-.Pp
-You are advised to verify the competence and identity of those who
-provide installable package files.
-For extra protection, examine all
-the package control files in the package record directory
-.Pa ( /var/db/pkg/<pkg-name>/ ) .
-Pay particular attention to any +INSTALL, +POST-INSTALL, +DEINSTALL,
-+POST-DEINSTALL, +REQUIRE or +MTREE_DIRS files, and inspect the +CONTENTS
-file for
-.Cm @cwd ,
-.Cm @mode
-(check for setuid),
-.Cm @dirrm ,
-.Cm @exec ,
-and
-.Cm @unexec
-directives, and/or use the
-.Xr pkg_info 1
-command to examine the installed package control files.
-.Ef
-.Sh OPTIONS
-The following command line options are supported:
-.Bl -tag -width indent
-.It Ar pkg-name ...
-The named packages are deinstalled.
-.It Fl a , -all
-Unconditionally delete all currently installed packages.
-.It Fl i , -interactive
-Request confirmation before attempting to delete each package,
-regardless whether or not the standard input device is a
-terminal.
-.It Fl v , -verbose
-Turn on verbose output.
-.It Fl D , -no-script , -no-scripts
-If a deinstallation script exists for a given package, do not execute it.
-.It Fl n , -dry-run
-Do not actually deinstall a package, just report the steps that
-would be taken if it were.
-.It Fl p , -prefix Ar prefix
-Set
-.Ar prefix
-as the directory in which to delete files from any installed packages
-which do not explicitly set theirs.
-For most packages, the prefix will
-be set automatically to the installed location by
-.Xr pkg_add 1 .
-.It Fl d , -clean-dirs
-Remove empty directories created by file cleanup.
-By default, only
-files/directories explicitly listed in a package's contents (either as
-normal files/directories or with the
-.Cm @dirrm
-directive) will be removed at deinstallation time.
-This option tells
-.Nm
-to also remove any directories that were emptied as a result of removing
-the package.
-.It Fl f , -force
-Force removal of the package, even if a dependency is recorded or the
-deinstall or require script fails.
-.It Fl G , -no-glob
-Do not try to expand shell glob patterns in the
-.Ar pkg-name
-when selecting packages to be deleted (by default
-.Nm
-automatically expands shell glob patterns in the
-.Ar pkg-name ) .
-.It Fl x , -regex
-Treat the
-.Ar pkg-name
-as a regular expression and delete all packages whose names match
-that regular expression.
-Multiple regular expressions could be
-provided, in that case
-.Nm
-deletes all packages that match at least one
-regular expression from the list.
-.It Fl X , -extended
-Like
-.Fl x ,
-but treats the
-.Ar pkg-name
-as an extended regular expression.
-.It Fl r , -recursive
-Recursive removal.
-In addition to specified packages, delete all
-packages that depend on those packages as well.
-.El
-.Sh TECHNICAL DETAILS
-The
-.Nm
-utility
-does pretty much what it says.
-It examines installed package records in
-.Pa /var/db/pkg/<pkg-name> ,
-deletes the package contents, and finally removes the package records.
-If the environment variable
-.Ev PKG_DBDIR
-is set, this overrides the
-.Pa /var/db/pkg/
-path shown above.
-.Pp
-If a package is required by other installed packages,
-.Nm
-will list those dependent packages and refuse to delete the package
-(unless the
-.Fl f
-option is given).
-.Pp
-If the package contains a
-.Ar require
-file (see
-.Xr pkg_create 1 ) ,
-then this is executed first as
-.Bd -ragged -offset indent -compact
-.Cm require
-.Ar <pkg-name>
-.Ar DEINSTALL
-.Ed
-(where
-.Ar pkg-name
-is the name of the package in question and
-.Ar DEINSTALL
-is a keyword denoting that this is a deinstallation)
-to see whether or not deinstallation should continue.
-A non-zero exit
-status means no, unless the
-.Fl f
-option is specified.
-.Pp
-If a
-.Cm deinstall
-script exists for the package, it is executed before any files are removed.
-It is this script's responsibility to clean up any additional messy details
-around the package's installation, since all
-.Nm
-knows how to do is delete the files created in the original distribution.
-The
-.Nm deinstall
-script is called as:
-.Bd -ragged -offset indent -compact
-.Cm script
-.Ar <pkg-name>
-.Ar DEINSTALL
-.Ed
-where
-.Ar pkg-name
-is the name of the package in question and
-.Ar DEINSTALL
-is a keyword denoting this as the pre-deinstallation phase.
-.Pp
-.Sy Note :
-The
-.Ar DEINSTALL
-keyword will not appear if separate scripts for deinstall and post-deinstall
-are given during package creation time (using the
-.Fl k
-and
-.Fl K
-flags to
-.Xr pkg_create 1 ) .
-.Pp
-If a
-.Cm post-deinstall
-script exists for the package, it is executed
-.Cm after
-all files are removed.
-It is this script's responsibility to clean up any
-additional messy details around the package's installation, and leave the
-system (hopefully) in the same state that it was prior to the installation
-of the package.
-.Pp
-The
-.Nm post-deinstall
-script is called as:
-.Bd -ragged -offset indent -compact
-.Cm script
-.Ar <pkg-name>
-.Ar POST-DEINSTALL
-.Ed
-where
-.Ar pkg-name
-is the name of the package in question and
-.Ar POST-DEINSTALL
-is a keyword denoting this as the post-deinstallation phase.
-.Pp
-.Sy Note :
-The
-.Ar POST-DEINSTALL
-keyword will not appear if separate scripts for deinstall and post-deinstall
-are given during package creation time (using the
-.Fl k
-and
-.Fl K
-flags to
-.Xr pkg_create 1 ) .
-.Pp
-Reasoning behind passing keywords such as
-.Ar DEINSTALL
-and
-.Ar POST-DEINSTALL
-is that it lets you potentially write only one program/script that handles
-all aspects of installation and deletion.
-.Pp
-But experience has proved that this is a lot more difficult to maintain and
-is not as advantageous as having separate scripts that handle each aspect of
-installation and deinstallation.
-.Pp
-All scripts are called with the environment variable
-.Ev PKG_PREFIX
-set to the installation prefix (see the
-.Fl p
-option above).
-This allows a package author to write a script
-that reliably performs some action on the directory where the package
-is installed, even if the user might have changed it by specifying the
-.Fl p
-option when running
-.Nm
-or
-.Cm pkg_add .
-.Sh ENVIRONMENT
-The environment variable
-.Ev PKG_DBDIR
-specifies an alternative location for the installed package database.
-.Sh FILES
-.Bl -tag -width /var/db/pkg -compact
-.It Pa /var/db/pkg
-Default location of the installed package database.
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh SEE ALSO
-.Xr pkg_add 1 ,
-.Xr pkg_create 1 ,
-.Xr pkg_info 1 ,
-.Xr pkg_version 1 ,
-.Xr mktemp 3 ,
-.Xr mtree 8
-.Sh AUTHORS
-.An Jordan Hubbard
-.Sh CONTRIBUTORS
-.An John Kohl Aq jtk@rational.com ,
-.An Oliver Eikemeier Aq eik@FreeBSD.org
-.Sh BUGS
-Sure to be some.
diff --git a/usr.sbin/pkg_install/info/Makefile b/usr.sbin/pkg_install/info/Makefile
deleted file mode 100644
index 485cb22..0000000
--- a/usr.sbin/pkg_install/info/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $FreeBSD$
-
-PROG= pkg_info
-SRCS= main.c perform.c show.c
-
-CFLAGS+= -I${.CURDIR}/../lib
-
-WFORMAT?= 1
-
-DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
-LDADD= ${LIBINSTALL} -lfetch -lmd
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/info/Makefile.depend b/usr.sbin/pkg_install/info/Makefile.depend
deleted file mode 100644
index 9507bb2..0000000
--- a/usr.sbin/pkg_install/info/Makefile.depend
+++ /dev/null
@@ -1,24 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libfetch \
- lib/libmd \
- lib/libutil \
- secure/lib/libcrypto \
- secure/lib/libssl \
- usr.sbin/pkg_install/lib \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/info/info.h b/usr.sbin/pkg_install/info/info.h
deleted file mode 100644
index 6569b5f..0000000
--- a/usr.sbin/pkg_install/info/info.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 23 August 1993
- *
- * Include and define various things wanted by the info command.
- *
- */
-
-#ifndef _INST_INFO_H_INCLUDE
-#define _INST_INFO_H_INCLUDE
-
-#include <sys/queue.h>
-
-#ifndef MAXINDEXSIZE
-#define MAXINDEXSIZE 59
-#endif
-
-#ifndef MAXNAMESIZE
-#define MAXNAMESIZE 20
-#endif
-
-#define SHOW_COMMENT 0x00001
-#define SHOW_DESC 0x00002
-#define SHOW_PLIST 0x00004
-#define SHOW_INSTALL 0x00008
-#define SHOW_DEINSTALL 0x00010
-#define SHOW_REQUIRE 0x00020
-#define SHOW_PREFIX 0x00040
-#define SHOW_INDEX 0x00080
-#define SHOW_FILES 0x00100
-#define SHOW_DISPLAY 0x00200
-#define SHOW_REQBY 0x00400
-#define SHOW_MTREE 0x00800
-#define SHOW_SIZE 0x01000
-#define SHOW_ORIGIN 0x02000
-#define SHOW_CKSUM 0x04000
-#define SHOW_FMTREV 0x08000
-#define SHOW_PTREV 0x10000
-#define SHOW_DEPEND 0x20000
-#define SHOW_PKGNAME 0x40000
-
-struct which_entry {
- TAILQ_ENTRY(which_entry) next;
- char file[PATH_MAX];
- char package[PATH_MAX];
- Boolean skip;
-};
-TAILQ_HEAD(which_head, which_entry);
-
-extern int Flags;
-extern Boolean QUIET;
-extern Boolean UseBlkSz;
-extern Boolean KeepPackage;
-extern char *InfoPrefix;
-extern char PlayPen[];
-extern char *CheckPkg;
-extern char *LookUpOrigin;
-extern match_t MatchType;
-extern struct which_head *whead;
-
-extern void show_file(const char *, const char *);
-extern void show_plist(const char *, Package *, plist_t, Boolean);
-extern void show_files(const char *, Package *);
-extern void show_index(const char *, const char *);
-extern void show_size(const char *, Package *);
-extern int show_cksum(const char *, Package *);
-extern void show_origin(const char *, Package *);
-extern void show_fmtrev(const char *, Package *);
-
-#endif /* _INST_INFO_H_INCLUDE */
diff --git a/usr.sbin/pkg_install/info/main.c b/usr.sbin/pkg_install/info/main.c
deleted file mode 100644
index ff2ea79..0000000
--- a/usr.sbin/pkg_install/info/main.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- *
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * This is the info module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <getopt.h>
-#include <err.h>
-
-#include "lib.h"
-#include "info.h"
-
-int Flags = 0;
-match_t MatchType = MATCH_GLOB;
-Boolean QUIET = FALSE;
-Boolean UseBlkSz = FALSE;
-char *InfoPrefix = (char *)(uintptr_t)"";
-char PlayPen[FILENAME_MAX];
-char *CheckPkg = NULL;
-char *LookUpOrigin = NULL;
-Boolean KeepPackage = FALSE;
-struct which_head *whead;
-
-static void usage(void);
-
-static char opts[] = "abcdDe:EfgGhiIjkKl:LmoO:pPqQrRst:vVW:xX";
-static struct option longopts[] = {
- { "all", no_argument, NULL, 'a' },
- { "blocksize", no_argument, NULL, 'b' },
- { "exist", required_argument, NULL, 'X' },
- { "exists", required_argument, NULL, 'X' },
- { "extended", no_argument, NULL, 'e' },
- { "help", no_argument, NULL, 'h' },
- { "keep", no_argument, NULL, 'K' },
- { "no-glob", no_argument, NULL, 'G' },
- { "origin", required_argument, NULL, 'O' },
- { "quiet", no_argument, NULL, 'q' },
- { "regex", no_argument, NULL, 'x' },
- { "template", required_argument, NULL, 't' },
- { "verbose", no_argument, NULL, 'v' },
- { "version", no_argument, NULL, 'P' },
- { "which", required_argument, NULL, 'W' },
- { NULL, 0, NULL, 0 }
-};
-
-int
-main(int argc, char **argv)
-{
- int ch;
- char **pkgs, **start;
- char *pkgs_split;
-
- warnpkgng();
- whead = malloc(sizeof(struct which_head));
- if (whead == NULL)
- err(2, NULL);
- TAILQ_INIT(whead);
-
- pkgs = start = argv;
- if (argc == 1) {
- MatchType = MATCH_ALL;
- Flags = SHOW_INDEX;
- }
- else while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
- switch(ch) {
- case 'a':
- MatchType = MATCH_ALL;
- break;
-
- case 'b':
- UseBlkSz = TRUE;
- break;
-
- case 'v':
- Verbose++;
- /* Reasonable definition of 'everything' */
- Flags = SHOW_COMMENT | SHOW_DESC | SHOW_PLIST | SHOW_INSTALL |
- SHOW_DEINSTALL | SHOW_REQUIRE | SHOW_DISPLAY | SHOW_MTREE;
- break;
-
- case 'E':
- Flags |= SHOW_PKGNAME;
- break;
-
- case 'I':
- Flags |= SHOW_INDEX;
- break;
-
- case 'p':
- Flags |= SHOW_PREFIX;
- break;
-
- case 'c':
- Flags |= SHOW_COMMENT;
- break;
-
- case 'd':
- Flags |= SHOW_DESC;
- break;
-
- case 'D':
- Flags |= SHOW_DISPLAY;
- break;
-
- case 'f':
- Flags |= SHOW_PLIST;
- break;
-
- case 'g':
- Flags |= SHOW_CKSUM;
- break;
-
- case 'G':
- MatchType = MATCH_EXACT;
- break;
-
- case 'i':
- Flags |= SHOW_INSTALL;
- break;
-
- case 'j':
- Flags |= SHOW_REQUIRE;
- break;
-
- case 'k':
- Flags |= SHOW_DEINSTALL;
- break;
-
- case 'K':
- KeepPackage = TRUE;
- break;
-
- case 'r':
- Flags |= SHOW_DEPEND;
- break;
-
- case 'R':
- Flags |= SHOW_REQBY;
- break;
-
- case 'L':
- Flags |= SHOW_FILES;
- break;
-
- case 'm':
- Flags |= SHOW_MTREE;
- break;
-
- case 's':
- Flags |= SHOW_SIZE;
- break;
-
- case 'o':
- Flags |= SHOW_ORIGIN;
- break;
-
- case 'O':
- LookUpOrigin = strdup(optarg);
- if (LookUpOrigin == NULL)
- err(2, NULL);
- break;
-
- case 'V':
- Flags |= SHOW_FMTREV;
- break;
-
- case 'l':
- InfoPrefix = optarg;
- break;
-
- case 'q':
- Quiet = TRUE;
- break;
-
- case 'Q':
- Quiet = TRUE;
- QUIET = TRUE;
- break;
-
- case 't':
- strlcpy(PlayPen, optarg, sizeof(PlayPen));
- break;
-
- case 'x':
- MatchType = MATCH_REGEX;
- break;
-
- case 'X':
- MatchType = MATCH_EREGEX;
- break;
-
- case 'e':
- CheckPkg = optarg;
- break;
-
- case 'W':
- {
- struct which_entry *entp;
-
- entp = calloc(1, sizeof(struct which_entry));
- if (entp == NULL)
- err(2, NULL);
-
- strlcpy(entp->file, optarg, PATH_MAX);
- entp->skip = FALSE;
- TAILQ_INSERT_TAIL(whead, entp, next);
- break;
- }
-
- case 'P':
- Flags = SHOW_PTREV;
- break;
-
- case 'h':
- default:
- usage();
- break;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (Flags & SHOW_PTREV) {
- if (!Quiet)
- printf("Package tools revision: ");
- printf("%d\n", PKG_INSTALL_VERSION);
- exit(0);
- }
-
- /* Set some reasonable defaults */
- if (!Flags)
- Flags = SHOW_COMMENT | SHOW_DESC | SHOW_REQBY;
-
- /* Get all the remaining package names, if any */
- while (*argv) {
- /*
- * Don't try to apply heuristics if arguments are regexs or if
- * the argument refers to an existing file.
- */
- if (MatchType != MATCH_REGEX && MatchType != MATCH_EREGEX && !isfile(*argv) && !isURL(*argv))
- while ((pkgs_split = strrchr(*argv, (int)'/')) != NULL) {
- *pkgs_split++ = '\0';
- /*
- * If character after the '/' is alphanumeric or shell
- * metachar, then we've found the package name. Otherwise
- * we've come across a trailing '/' and need to continue our
- * quest.
- */
- if (isalnum(*pkgs_split) || ((MatchType == MATCH_GLOB) && \
- strpbrk(pkgs_split, "*?[]") != NULL)) {
- *argv = pkgs_split;
- break;
- }
- }
- *pkgs++ = *argv++;
- }
-
- /* If no packages, yelp */
- if (pkgs == start && MatchType != MATCH_ALL && !CheckPkg &&
- TAILQ_EMPTY(whead) && LookUpOrigin == NULL)
- warnx("missing package name(s)"), usage();
- *pkgs = NULL;
- return pkg_perform(start);
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
- "usage: pkg_info [-bcdDEfgGiIjkKLmopPqQrRsvVxX] [-e package] [-l prefix]",
- " [-t template] -a | pkg-name ...",
- " pkg_info [-qQ] -W filename",
- " pkg_info [-qQ] -O origin",
- " pkg_info");
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/info/perform.c b/usr.sbin/pkg_install/info/perform.c
deleted file mode 100644
index 551f862..0000000
--- a/usr.sbin/pkg_install/info/perform.c
+++ /dev/null
@@ -1,476 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 23 Aug 1993
- *
- * This is the main body of the info module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include "info.h"
-#include <err.h>
-#include <signal.h>
-
-static int pkg_do(char *);
-static int find_pkg(struct which_head *);
-static int cmp_path(const char *, const char *, const char *);
-static char *abspath(const char *);
-static int find_pkgs_by_origin(const char *);
-static int matched_packages(char **pkgs);
-
-int
-pkg_perform(char **pkgs)
-{
- char **matched;
- int err_cnt = 0;
- int i, errcode;
-
- signal(SIGINT, cleanup);
-
- /* Overriding action? */
- if (Flags & SHOW_PKGNAME) {
- return matched_packages(pkgs);
- } else if (CheckPkg) {
- return isinstalledpkg(CheckPkg) > 0 ? 0 : 1;
- /* Not reached */
- } else if (!TAILQ_EMPTY(whead)) {
- return find_pkg(whead);
- } else if (LookUpOrigin != NULL) {
- return find_pkgs_by_origin(LookUpOrigin);
- }
-
- if (MatchType != MATCH_EXACT) {
- matched = matchinstalled(MatchType, pkgs, &errcode);
- if (errcode != 0)
- return 1;
- /* Not reached */
-
- if (matched != NULL)
- pkgs = matched;
- else switch (MatchType) {
- case MATCH_GLOB:
- break;
- case MATCH_ALL:
- warnx("no packages installed");
- return 0;
- /* Not reached */
- case MATCH_REGEX:
- case MATCH_EREGEX:
- warnx("no packages match pattern(s)");
- return 1;
- /* Not reached */
- default:
- break;
- }
- }
-
- for (i = 0; pkgs[i]; i++)
- err_cnt += pkg_do(pkgs[i]);
-
- return err_cnt;
-}
-
-static int
-pkg_do(char *pkg)
-{
- Boolean installed = FALSE, isTMP = FALSE;
- char log_dir[FILENAME_MAX];
- char fname[FILENAME_MAX];
- Package plist;
- FILE *fp;
- struct stat sb;
- const char *cp = NULL;
- int code = 0;
-
- if (isURL(pkg)) {
- if ((cp = fileGetURL(NULL, pkg, KeepPackage)) != NULL) {
- if (!getcwd(fname, FILENAME_MAX))
- upchuck("getcwd");
- isTMP = TRUE;
- } else {
- goto bail;
- }
- }
- else if (fexists(pkg) && isfile(pkg)) {
- int len;
-
- if (*pkg != '/') {
- if (!getcwd(fname, FILENAME_MAX))
- upchuck("getcwd");
- len = strlen(fname);
- snprintf(&fname[len], FILENAME_MAX - len, "/%s", pkg);
- }
- else
- strcpy(fname, pkg);
- cp = fname;
- }
- else {
- if ((cp = fileFindByPath(NULL, pkg)) != NULL)
- strncpy(fname, cp, FILENAME_MAX);
- }
- if (cp) {
- if (!isURL(pkg)) {
- /*
- * Apply a crude heuristic to see how much space the package will
- * take up once it's unpacked. I've noticed that most packages
- * compress an average of 75%, but we're only unpacking the + files so
- * be very optimistic.
- */
- if (stat(fname, &sb) == FAIL) {
- warnx("can't stat package file '%s'", fname);
- code = 1;
- goto bail;
- }
- make_playpen(PlayPen, sb.st_size / 2);
- if (unpack(fname, "'+*'")) {
- warnx("error during unpacking, no info for '%s' available", pkg);
- code = 1;
- goto bail;
- }
- }
- }
- /* It's not an uninstalled package, try and find it among the installed */
- else {
- int isinstalled = isinstalledpkg(pkg);
- if (isinstalled < 0) {
- warnx("the package info for package '%s' is corrupt", pkg);
- return 1;
- } else if (isinstalled == 0) {
- warnx("can't find package '%s' installed or in a file!", pkg);
- return 1;
- }
- sprintf(log_dir, "%s/%s", LOG_DIR, pkg);
- if (chdir(log_dir) == FAIL) {
- warnx("can't change directory to '%s'!", log_dir);
- return 1;
- }
- installed = TRUE;
- }
-
- /* Suck in the contents list */
- plist.head = plist.tail = NULL;
- fp = fopen(CONTENTS_FNAME, "r");
- if (!fp) {
- warnx("unable to open %s file", CONTENTS_FNAME);
- code = 1;
- goto bail;
- }
- /* If we have a prefix, add it now */
- read_plist(&plist, fp);
- fclose(fp);
-
- /*
- * Index is special info type that has to override all others to make
- * any sense.
- */
- if (Flags & SHOW_INDEX) {
- char tmp[FILENAME_MAX];
-
- snprintf(tmp, FILENAME_MAX, "%-19s ", pkg);
- show_index(tmp, COMMENT_FNAME);
- }
- else {
- /* Start showing the package contents */
- if (!Quiet)
- printf("%sInformation for %s:\n\n", InfoPrefix, pkg);
- else if (QUIET)
- printf("%s%s:", InfoPrefix, pkg);
- if (Flags & SHOW_COMMENT)
- show_file("Comment:\n", COMMENT_FNAME);
- if (Flags & SHOW_DEPEND)
- show_plist("Depends on:\n", &plist, PLIST_PKGDEP, FALSE);
- if ((Flags & SHOW_REQBY) && !isemptyfile(REQUIRED_BY_FNAME))
- show_file("Required by:\n", REQUIRED_BY_FNAME);
- if (Flags & SHOW_DESC)
- show_file("Description:\n", DESC_FNAME);
- if ((Flags & SHOW_DISPLAY) && fexists(DISPLAY_FNAME))
- show_file("Install notice:\n", DISPLAY_FNAME);
- if (Flags & SHOW_PLIST)
- show_plist("Packing list:\n", &plist, (plist_t)0, TRUE);
- if (Flags & SHOW_REQUIRE && fexists(REQUIRE_FNAME))
- show_file("Requirements script:\n", REQUIRE_FNAME);
- if ((Flags & SHOW_INSTALL) && fexists(INSTALL_FNAME))
- show_file("Install script:\n", INSTALL_FNAME);
- if ((Flags & SHOW_INSTALL) && fexists(POST_INSTALL_FNAME))
- show_file("Post-Install script:\n", POST_INSTALL_FNAME);
- if ((Flags & SHOW_DEINSTALL) && fexists(DEINSTALL_FNAME))
- show_file("De-Install script:\n", DEINSTALL_FNAME);
- if ((Flags & SHOW_DEINSTALL) && fexists(POST_DEINSTALL_FNAME))
- show_file("Post-DeInstall script:\n", POST_DEINSTALL_FNAME);
- if ((Flags & SHOW_MTREE) && fexists(MTREE_FNAME))
- show_file("mtree file:\n", MTREE_FNAME);
- if (Flags & SHOW_PREFIX)
- show_plist("Prefix(s):\n", &plist, PLIST_CWD, FALSE);
- if (Flags & SHOW_FILES)
- show_files("Files:\n", &plist);
- if ((Flags & SHOW_SIZE) && installed)
- show_size("Package Size:\n", &plist);
- if ((Flags & SHOW_CKSUM) && installed)
- code += show_cksum("Mismatched Checksums:\n", &plist);
- if (Flags & SHOW_ORIGIN)
- show_origin("Origin:\n", &plist);
- if (Flags & SHOW_FMTREV)
- show_fmtrev("Packing list format revision:\n", &plist);
- if (!Quiet)
- puts(InfoPrefix);
- }
- free_plist(&plist);
- bail:
- leave_playpen();
- if (isTMP)
- unlink(fname);
- return (code ? 1 : 0);
-}
-
-void
-cleanup(int sig)
-{
- static int in_cleanup = 0;
-
- if (!in_cleanup) {
- in_cleanup = 1;
- leave_playpen();
- }
- if (sig)
- exit(1);
-}
-
-/*
- * Return an absolute path, additionally removing all .'s, ..'s, and extraneous
- * /'s, as realpath() would, but without resolving symlinks, because that can
- * potentially screw up our comparisons later.
- */
-static char *
-abspath(const char *pathname)
-{
- char *tmp, *tmp1, *resolved_path;
- char *cwd = NULL;
- int len;
-
- if (pathname[0] != '/') {
- cwd = getcwd(NULL, MAXPATHLEN);
- asprintf(&resolved_path, "%s/%s/", cwd, pathname);
- } else
- asprintf(&resolved_path, "%s/", pathname);
-
- if (resolved_path == NULL)
- errx(2, NULL);
-
- if (cwd != NULL)
- free(cwd);
-
- while ((tmp = strstr(resolved_path, "//")) != NULL)
- strcpy(tmp, tmp + 1);
-
- while ((tmp = strstr(resolved_path, "/./")) != NULL)
- strcpy(tmp, tmp + 2);
-
- while ((tmp = strstr(resolved_path, "/../")) != NULL) {
- *tmp = '\0';
- if ((tmp1 = strrchr(resolved_path, '/')) == NULL)
- tmp1 = resolved_path;
- strcpy(tmp1, tmp + 3);
- }
-
- len = strlen(resolved_path);
- if (len > 1 && resolved_path[len - 1] == '/')
- resolved_path[len - 1] = '\0';
-
- return resolved_path;
-}
-
-/*
- * Comparison to see if the path we're on matches the
- * one we are looking for.
- */
-static int
-cmp_path(const char *target, const char *current, const char *cwd)
-{
- char *resolved, *temp;
- int rval;
-
- asprintf(&temp, "%s/%s", cwd, current);
- if (temp == NULL)
- errx(2, NULL);
-
- /*
- * Make sure there's no multiple /'s or other weird things in the PLIST,
- * since some plists seem to have them and it could screw up our strncmp.
- */
- resolved = abspath(temp);
-
- if (strcmp(target, resolved) == 0)
- rval = 1;
- else
- rval = 0;
-
- free(temp);
- free(resolved);
- return rval;
-}
-
-/*
- * Look through package dbs in LOG_DIR and find which
- * packages installed the files in which_list.
- */
-static int
-find_pkg(struct which_head *which_list)
-{
- char **installed;
- int errcode, i;
- struct which_entry *wp;
-
- TAILQ_FOREACH(wp, which_list, next) {
- const char *msg = "file cannot be found";
- char *tmp;
-
- wp->skip = TRUE;
- /* If it's not a file, we'll see if it's an executable. */
- if (isfile(wp->file) == FALSE) {
- if (strchr(wp->file, '/') == NULL) {
- tmp = vpipe("/usr/bin/which %s", wp->file);
- if (tmp != NULL) {
- strlcpy(wp->file, tmp, PATH_MAX);
- wp->skip = FALSE;
- free(tmp);
- } else
- msg = "file is not in PATH";
- }
- } else {
- tmp = abspath(wp->file);
- if (isfile(tmp)) {
- strlcpy(wp->file, tmp, PATH_MAX);
- wp->skip = FALSE;
- }
- free(tmp);
- }
- if (wp->skip == TRUE)
- warnx("%s: %s", wp->file, msg);
- }
-
- installed = matchinstalled(MATCH_ALL, NULL, &errcode);
- if (installed == NULL)
- return errcode;
-
- for (i = 0; installed[i] != NULL; i++) {
- FILE *fp;
- Package pkg;
- PackingList itr;
- char *cwd = NULL;
- char tmp[PATH_MAX];
-
- snprintf(tmp, PATH_MAX, "%s/%s/%s", LOG_DIR, installed[i],
- CONTENTS_FNAME);
- fp = fopen(tmp, "r");
- if (fp == NULL) {
- warn("%s", tmp);
- return 1;
- }
-
- pkg.head = pkg.tail = NULL;
- read_plist(&pkg, fp);
- fclose(fp);
- for (itr = pkg.head; itr != pkg.tail; itr = itr->next) {
- if (itr->type == PLIST_CWD) {
- cwd = itr->name;
- } else if (itr->type == PLIST_FILE) {
- TAILQ_FOREACH(wp, which_list, next) {
- if (wp->skip == TRUE)
- continue;
- if (!cmp_path(wp->file, itr->name, cwd))
- continue;
- if (wp->package[0] != '\0') {
- warnx("both %s and %s claim to have installed %s\n",
- wp->package, installed[i], wp->file);
- } else {
- strlcpy(wp->package, installed[i], PATH_MAX);
- }
- }
- }
- }
- free_plist(&pkg);
- }
-
- TAILQ_FOREACH(wp, which_list, next) {
- if (wp->package[0] != '\0') {
- if (Quiet)
- puts(wp->package);
- else
- printf("%s was installed by package %s\n", \
- wp->file, wp->package);
- }
- }
- while (!TAILQ_EMPTY(which_list)) {
- wp = TAILQ_FIRST(which_list);
- TAILQ_REMOVE(which_list, wp, next);
- free(wp);
- }
-
- free(which_list);
- return 0;
-}
-
-/*
- * Look through package dbs in LOG_DIR and find which
- * packages have the given origin. Don't use read_plist()
- * because this increases time necessary for lookup by 40
- * times, as we don't really have to parse all plist to
- * get origin.
- */
-static int
-find_pkgs_by_origin(const char *origin)
-{
- char **matched;
- int errcode, i;
-
- if (!Quiet)
- printf("The following installed package(s) has %s origin:\n", origin);
-
- matched = matchbyorigin(origin, &errcode);
- if (matched == NULL)
- return errcode;
-
- for (i = 0; matched[i] != NULL; i++)
- puts(matched[i]);
-
- return 0;
-}
-
-/*
- * List only the matching package names.
- * Mainly intended for scripts.
- */
-static int
-matched_packages(char **pkgs)
-{
- char **matched;
- int i, errcode;
-
- matched = matchinstalled(MatchType == MATCH_GLOB ? MATCH_NGLOB : MatchType, pkgs, &errcode);
-
- if (errcode != 0 || matched == NULL)
- return 1;
-
- for (i = 0; matched[i]; i++)
- if (!Quiet)
- printf("%s\n", matched[i]);
- else if (QUIET)
- printf("%s%s\n", InfoPrefix, matched[i]);
-
- return 0;
-}
diff --git a/usr.sbin/pkg_install/info/pkg_info.1 b/usr.sbin/pkg_install/info/pkg_info.1
deleted file mode 100644
index c29687d..0000000
--- a/usr.sbin/pkg_install/info/pkg_info.1
+++ /dev/null
@@ -1,302 +0,0 @@
-.\"
-.\" FreeBSD install - a package for the installation and maintenance
-.\" of non-core utilities.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" Jordan K. Hubbard
-.\"
-.\"
-.\" @(#)pkg_info.1
-.\" $FreeBSD$
-.\"
-.Dd November 9, 2012
-.Dt PKG_INFO 1
-.Os
-.Sh NAME
-.Nm pkg_info
-.Nd a utility for displaying information on software packages
-.Sh SYNOPSIS
-.Nm
-.Op Fl bcdDEfghGiIjkKLmopPqQrRsvVxX
-.Op Fl e Ar package
-.Op Fl l Ar prefix
-.Op Fl t Ar template
-.Fl a | Ar pkg-name ...
-.Nm
-.Op Fl qQ
-.Fl W Ar filename
-.Nm
-.Op Fl qQ
-.Fl O Ar origin
-.Nm
-.Sh DESCRIPTION
-The
-.Nm
-command is used to dump out information for packages, either packed up in
-files with the
-.Xr pkg_create 1
-command or already installed on the system
-with the
-.Xr pkg_add 1
-command.
-.Sh OPTIONS
-The following command line options are supported:
-.Bl -tag -width indent
-.It Ar pkg-name ...
-The named packages are described.
-A package name may either be the name of
-an installed package, the pathname to a package distribution file or a
-URL to an FTP available package.
-Package version numbers can also be matched in a relational manner using the
-.Pa >= , <= , >
-and
-.Pa <
-operators.
-For example,
-.Pp
-.Dl "pkg_info 'portupgrade>=20030723'"
-.Pp
-will match versions 20030723 and later of the
-.Pa portupgrade
-package.
-.It Fl a , -all
-Show all currently installed packages.
-.It Fl b , -blocksize
-Use the
-.Ev BLOCKSIZE
-environment variable for output even when the
-.Fl q
-or
-.Fl Q
-flag is present.
-.It Fl h , -help
-Print help message.
-.It Fl v , -verbose
-Turn on verbose output.
-.It Fl p
-Show the installation prefix for each package.
-.It Fl q , -quiet
-Be
-.Dq quiet
-in emitting report headers and such, just dump the
-raw info (basically, assume a non-human reading).
-.It Fl Q
-Be
-.Dq quiet
-as above but print preface output with the package name.
-.It Fl c
-Show the (one line) comment field for each package.
-.It Fl d
-Show the long description field for each package.
-.It Fl D
-Show the install-message file for each package.
-.It Fl f
-Show the packing list instructions for each package.
-.It Fl g
-Show files that do not match the recorded checksum.
-.It Fl i
-Show the install script (if any) for each package.
-.It Fl I
-Show an index line for each package.
-This option takes
-precedence over all other package formatting options.
-.It Fl j
-Show the requirements script (if any) for each package.
-.It Fl k
-Show the de-install script (if any) for each package.
-.It Fl K , -keep
-Keep any downloaded package in
-.Ev PKGDIR
-if it is defined or in current directory by default.
-.It Fl r
-For each of the specified packages,
-show the list of packages on which it depends.
-.It Fl R
-For each of the specified packages,
-show the list of installed packages which require it.
-.It Fl m
-Show the
-.Xr mtree 8
-file (if any) for each package.
-.It Fl L
-Show the files within each package.
-This is different from just
-viewing the packing list, since full pathnames for everything
-are generated.
-.It Fl s
-Show the total size occupied by files installed within each package.
-.It Fl o
-Show the
-.Dq origin
-path recorded on package generation.
-This path is the directory name in the
-.Fx
-.Em "Ports Collection"
-of the underlying port from which the package was generated.
-.It Fl G , -no-glob
-Do not try to expand shell glob patterns in the
-.Ar pkg-name
-when selecting packages to be displayed (by default
-.Nm
-automatically expands shell glob patterns in the
-.Ar pkg-name ) .
-.It Fl W , -which Ar filename
-For the specified
-.Ar filename
-argument show which package it belongs to.
-If the file is not in the
-current directory, and does not have an absolute path, then the
-directories specified in the environment variable
-.Ev PATH
-are searched using
-.Xr which 1 .
-.It Fl O , -origin Ar origin
-List all packages having the specified
-.Ar origin .
-.It Fl x , -regex
-Treat the
-.Ar pkg-name
-as a regular expression and display information only for packages
-whose names match that regular expression.
-Multiple regular
-expressions could be provided, in that case
-.Nm
-displays information about all packages that match at least one
-regular expression from the list.
-.It Fl X , -extended
-Like
-.Fl x ,
-but treats the
-.Ar pkg-name
-as an extended regular expression.
-.It Fl e , -exists Ar package
-If the package identified by
-.Ar package
-is currently installed, return 0, otherwise return 1.
-This option
-allows you to easily test for the presence of another (perhaps
-prerequisite) package from a script.
-.It Fl E
-Show only matching package names.
-This option takes
-precedence over all other package formatting options.
-If any packages match, return 0, otherwise return 1.
-.It Fl l Ar prefix
-Prefix each information category header (see
-.Fl q )
-shown with
-.Ar prefix .
-This is primarily of use to front-end programs that want to request a
-lot of different information fields at once for a package, but do not
-necessarily want the output intermingled in such a way that they cannot
-organize it.
-This lets you add a special token to the start of
-each field.
-.It Fl t , -template Ar template
-Use
-.Ar template
-as the argument to
-.Xr mktemp 3
-when creating a
-.Dq staging area .
-By default, this is the string
-.Pa /tmp/instmp.XXXXXX ,
-but it may be necessary to override it in the situation where
-space in your
-.Pa /tmp
-directory is limited.
-Be sure to leave some number of
-.Ql X
-characters for
-.Xr mktemp 3
-to fill in with a unique ID.
-.Bd -ragged -offset indent -compact
-Note: This should really not be necessary with
-.Nm ,
-since very little information is extracted from each package
-and one would have to have a very small
-.Pa /tmp
-indeed to overflow it.
-.Ed
-.It Fl V
-Show revision number of the packing list format.
-.It Fl P , -version
-Show revision number of package tools.
-.El
-.Sh TECHNICAL DETAILS
-Package info is either extracted from package files named on the
-command line, or from already installed package information
-in
-.Pa /var/db/pkg/ Ns Aq Ar pkg-name .
-.Sh ENVIRONMENT
-.Bl -tag -width ".Ev PKG_TMPDIR"
-.It Ev BLOCKSIZE
-If the environment variable
-.Ev BLOCKSIZE
-is set the block counts will be displayed in units of that
-size block.
-.It Ev PKG_TMPDIR
-Points to the directory where
-.Nm
-creates its temporary files.
-If this variable is not set,
-.Ev TMPDIR
-is used.
-If both are unset, the builtin defaults are used.
-.It Ev PKG_DBDIR
-Specifies an alternative location for the installed package database.
-.It Ev PKG_PATH
-Specifies an alternative package location, if a given package cannot be
-found.
-.It Ev PKGDIR
-Specifies an alternative location to save downloaded packages to.
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh FILES
-.Bl -tag -width ".Pa /var/db/pkg" -compact
-.It Pa /var/tmp
-Used if the environment variables
-.Ev PKG_TMPDIR
-and
-.Ev TMPDIR
-are not set, or if the directories named have insufficient space.
-.It Pa /tmp
-The next choice if
-.Pa /var/tmp
-does not exist or has insufficient space.
-.It Pa /usr/tmp
-The last choice if
-.Pa /tmp
-is unsuitable.
-.It Pa /var/db/pkg
-Default location of the installed package database.
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh SEE ALSO
-.Xr pkg_add 1 ,
-.Xr pkg_create 1 ,
-.Xr pkg_delete 1 ,
-.Xr pkg_version 1 ,
-.Xr mktemp 3 ,
-.Xr mtree 8
-.Sh AUTHORS
-.An Jordan Hubbard
-.Sh CONTRIBUTORS
-.An John Kohl Aq jtk@rational.com ,
-.An Oliver Eikemeier Aq eik@FreeBSD.org
-.Sh BUGS
-Sure to be some.
diff --git a/usr.sbin/pkg_install/info/show.c b/usr.sbin/pkg_install/info/show.c
deleted file mode 100644
index be05695..0000000
--- a/usr.sbin/pkg_install/info/show.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 23 Aug 1993
- *
- * Various display routines for the info module.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include "info.h"
-#include <err.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <md5.h>
-
-void
-show_file(const char *title, const char *fname)
-{
- FILE *fp;
- char line[1024];
- int n;
-
- if (!Quiet)
- printf("%s%s", InfoPrefix, title);
- fp = fopen(fname, "r");
- if (fp == (FILE *) NULL)
- printf("ERROR: show_file: Can't open '%s' for reading!\n", fname);
- else {
- int append_nl = 0;
- while ((n = fread(line, 1, 1024, fp)) != 0)
- fwrite(line, 1, n, stdout);
- fclose(fp);
- append_nl = (line[n - 1] != '\n'); /* Do we have a trailing \n ? */
- if (append_nl)
- printf("\n");
- }
- printf("\n"); /* just in case */
-}
-
-void
-show_index(const char *title, const char *fname)
-{
- FILE *fp;
- char line[MAXINDEXSIZE+2];
-
- strlcpy(line, "???\n", sizeof(line));
-
- if (!Quiet) {
- printf("%s%s", InfoPrefix, title);
- fflush(stdout);
- }
- fp = fopen(fname, "r");
- if (fp == (FILE *) NULL) {
- warnx("show_file: can't open '%s' for reading", fname);
- } else {
- if(fgets(line, MAXINDEXSIZE + 1, fp)) {
- size_t line_length = strlen(line);
-
- if (line[line_length - 1] != '\n') { /* Do we have a trailing \n ? */
- line[line_length] = '\n'; /* Add a trailing \n */
- line[line_length + 1] = '\0'; /* Terminate string */
- }
- }
- fclose(fp);
- }
- fputs(line, stdout);
-}
-
-/* Show a packing list item type. If showall is TRUE, show all */
-void
-show_plist(const char *title, Package *plist, plist_t type, Boolean showall)
-{
- PackingList p;
- Boolean ign = FALSE;
- char *prefix = NULL;
-
- if (!Quiet) {
- printf("%s%s", InfoPrefix, title);
- fflush(stdout);
- }
- p = plist->head;
- while (p) {
- if (p->type != type && showall != TRUE) {
- p = p->next;
- continue;
- }
- switch(p->type) {
- case PLIST_FILE:
- if (ign) {
- printf(Quiet ? "%s\n" : "File: %s (ignored)\n", p->name);
- ign = FALSE;
- }
- else
- printf(Quiet ? "%s\n" : "File: %s\n", p->name);
- break;
-
- case PLIST_CWD:
- if (!prefix)
- prefix = p->name;
- printf(Quiet ? "@cwd %s\n" : "\tCWD to %s\n", (p->name == NULL) ? prefix : p->name);
- break;
-
- case PLIST_SRC:
- printf(Quiet ? "@srcdir %s\n" : "\tSRCDIR to %s\n", p->name);
- break;
-
- case PLIST_CMD:
- printf(Quiet ? "@exec %s\n" : "\tEXEC '%s'\n", p->name);
- break;
-
- case PLIST_UNEXEC:
- printf(Quiet ? "@unexec %s\n" : "\tUNEXEC '%s'\n", p->name);
- break;
-
- case PLIST_CHMOD:
- printf(Quiet ? "@chmod %s\n" : "\tCHMOD to %s\n",
- p->name ? p->name : "(clear default)");
- break;
-
- case PLIST_CHOWN:
- printf(Quiet ? "@chown %s\n" : "\tCHOWN to %s\n",
- p->name ? p->name : "(clear default)");
- break;
-
- case PLIST_CHGRP:
- printf(Quiet ? "@chgrp %s\n" : "\tCHGRP to %s\n",
- p->name ? p->name : "(clear default)");
- break;
-
- case PLIST_COMMENT:
- printf(Quiet ? "@comment %s\n" : "\tComment: %s\n", p->name);
- break;
-
- case PLIST_NOINST:
- printf(Quiet ? "@noinst %s\n" : "\tNot installed: %s\n", p->name);
- break;
-
- case PLIST_IGNORE:
- ign = TRUE;
- break;
-
- case PLIST_IGNORE_INST:
- printf(Quiet ? "@ignore_inst ??? doesn't belong here.\n" :
- "\tIgnore next file installation directive (doesn't belong)\n");
- ign = TRUE;
- break;
-
- case PLIST_NAME:
- printf(Quiet ? "@name %s\n" : "\tPackage name: %s\n", p->name);
- break;
-
- case PLIST_DISPLAY:
- printf(Quiet ? "@display %s\n" : "\tInstall message file: %s\n", p->name);
- break;
-
- case PLIST_PKGDEP:
- printf(Quiet ? "@pkgdep %s\n" : "Dependency: %s\n", p->name);
- break;
-
- case PLIST_DEPORIGIN:
- printf(Quiet ? "@comment DEPORIGIN:%s\n" :
- "\tdependency origin: %s\n", p->name);
- break;
-
- case PLIST_CONFLICTS:
- printf(Quiet ? "@conflicts %s\n" : "Conflicts: %s\n", p->name);
- break;
-
- case PLIST_MTREE:
- printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name);
- break;
-
- case PLIST_DIR_RM:
- printf(Quiet ? "@dirrm %s\n" : "\tDeinstall directory remove: %s\n", p->name);
- break;
-
- case PLIST_OPTION:
- printf(Quiet ? "@option %s\n" :
- "\tOption \"%s\" controlling package installation behaviour\n",
- p->name);
- break;
-
- case PLIST_ORIGIN:
- printf(Quiet ? "@comment ORIGIN:%s\n" :
- "\tPackage origin: %s\n", p->name);
- break;
-
- default:
- cleanup(0);
- errx(2, "%s: unknown command type %d (%s)",
- __func__, p->type, p->name);
- break;
- }
- p = p->next;
- }
-}
-
-static const char *
-elide_root(const char *dir)
-{
- if (strcmp(dir, "/") == 0)
- return "";
- return dir;
-}
-
-/* Show all files in the packing list (except ignored ones) */
-void
-show_files(const char *title, Package *plist)
-{
- PackingList p;
- Boolean ign = FALSE;
- char *prefix = NULL;
- const char *dir = ".";
-
- if (!Quiet)
- printf("%s%s", InfoPrefix, title);
- p = plist->head;
- while (p) {
- switch(p->type) {
- case PLIST_FILE:
- if (!ign)
- printf("%s/%s\n", elide_root(dir), p->name);
- ign = FALSE;
- break;
-
- case PLIST_CWD:
- if (!prefix)
- prefix = p->name;
- if (p->name == NULL)
- dir = prefix;
- else
- dir = p->name;
- break;
-
- case PLIST_IGNORE:
- ign = TRUE;
- break;
-
- /* Silence GCC in the -Wall mode */
- default:
- break;
- }
- p = p->next;
- }
-}
-
-/* Calculate and show size of all installed package files (except ignored ones) */
-void
-show_size(const char *title, Package *plist)
-{
- PackingList p;
- Boolean ign = FALSE;
- const char *dir = ".";
- struct stat sb;
- char tmp[FILENAME_MAX];
- unsigned long size = 0;
- long blksize;
- int headerlen;
- char *descr;
- char *prefix = NULL;
-
- descr = getbsize(&headerlen, &blksize);
- if (!Quiet) {
- printf("%s%s", InfoPrefix, title);
- fflush(stdout);
- }
- for (p = plist->head; p != NULL; p = p->next) {
- switch (p->type) {
- case PLIST_FILE:
- if (!ign) {
- snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name);
- if (!lstat(tmp, &sb)) {
- size += sb.st_size;
- if (Verbose)
- printf("%lu\t%s\n", (unsigned long) howmany(sb.st_size, blksize), tmp);
- }
- }
- ign = FALSE;
- break;
-
- case PLIST_CWD:
- if (!prefix)
- prefix = p->name;
- if (p->name == NULL)
- dir = prefix;
- else
- dir = p->name;
- break;
-
- case PLIST_IGNORE:
- ign = TRUE;
- break;
-
- /* Silence GCC in the -Wall mode */
- default:
- break;
- }
- }
- if (!Quiet)
- printf("%lu\t(%s)\n", howmany(size, blksize), descr);
- else
- if (UseBlkSz)
- printf("%lu\n", howmany(size, blksize));
- else
- printf("%lu\n", size);
-}
-
-/* Show files that don't match the recorded checksum */
-int
-show_cksum(const char *title, Package *plist)
-{
- PackingList p;
- const char *dir = ".";
- char *prefix = NULL;
- char tmp[FILENAME_MAX];
- int errcode = 0;
-
- if (!Quiet) {
- printf("%s%s", InfoPrefix, title);
- fflush(stdout);
- }
-
- for (p = plist->head; p != NULL; p = p->next)
- if (p->type == PLIST_CWD) {
- if (!prefix)
- prefix = p->name;
- if (p->name == NULL)
- dir = prefix;
- else
- dir = p->name;
- } else if (p->type == PLIST_FILE) {
- snprintf(tmp, FILENAME_MAX, "%s/%s", elide_root(dir), p->name);
- if (!fexists(tmp)) {
- warnx("%s doesn't exist", tmp);
- errcode = 1;
- } else if (p->next && p->next->type == PLIST_COMMENT &&
- (strncmp(p->next->name, "MD5:", 4) == 0)) {
- char *cp = NULL, buf[33];
-
- /*
- * For packing lists whose version is 1.1 or greater, the md5
- * hash for a symlink is calculated on the string returned
- * by readlink().
- */
- if (issymlink(tmp) && verscmp(plist, 1, 0) > 0) {
- int len;
- char linkbuf[FILENAME_MAX];
-
- if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
- cp = MD5Data((unsigned char *)linkbuf, len, buf);
- } else if (isfile(tmp) || verscmp(plist, 1, 1) < 0)
- cp = MD5File(tmp, buf);
-
- if (cp != NULL) {
- /* Mismatch? */
- if (strcmp(cp, p->next->name + 4))
- printf("%s fails the original MD5 checksum\n", tmp);
- else if (Verbose)
- printf("%s matched the original MD5 checksum\n", tmp);
- }
- }
- }
- return (errcode);
-}
-
-/* Show an "origin" path (usually category/portname) */
-void
-show_origin(const char *title, Package *plist)
-{
-
- if (!Quiet) {
- printf("%s%s", InfoPrefix, title);
- fflush(stdout);
- }
- printf("%s\n", plist->origin != NULL ? plist->origin : "");
-}
-
-/* Show revision number of the packing list */
-void
-show_fmtrev(const char *title, Package *plist)
-{
-
- if (!Quiet) {
- printf("%s%s", InfoPrefix, title);
- fflush(stdout);
- }
- printf("%d.%d\n", plist->fmtver_maj, plist->fmtver_mnr);
-}
diff --git a/usr.sbin/pkg_install/lib/Makefile b/usr.sbin/pkg_install/lib/Makefile
deleted file mode 100644
index 12cc307..0000000
--- a/usr.sbin/pkg_install/lib/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# $FreeBSD$
-
-LIB= install
-INTERNALLIB=
-SRCS= file.c msg.c plist.c str.c exec.c global.c pen.c match.c \
- deps.c version.c pkgwrap.c url.c pkgng.c
-
-WARNS?= 3
-WFORMAT?= 1
-
-.include <bsd.lib.mk>
diff --git a/usr.sbin/pkg_install/lib/Makefile.depend b/usr.sbin/pkg_install/lib/Makefile.depend
deleted file mode 100644
index 87f72c2..0000000
--- a/usr.sbin/pkg_install/lib/Makefile.depend
+++ /dev/null
@@ -1,17 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- include \
- include/xlocale \
- lib/libfetch \
- lib/libmd \
- lib/libutil \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/lib/deps.c b/usr.sbin/pkg_install/lib/deps.c
deleted file mode 100644
index c6e70fe..0000000
--- a/usr.sbin/pkg_install/lib/deps.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Maxim Sobolev
- * 14 March 2001
- *
- * Routines used to do various operations with dependencies
- * among installed packages.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <stdio.h>
-
-void list_deps(const char *pkgname, char **pkgs, char *listed,
- char *check_loop, char **newpkgs, int *nrnewpkgs,
- int *err_cnt);
-
-/*
- * Sort given NULL-terminated list of installed packages (pkgs) in
- * such a way that if package A depends on package B then after
- * sorting A will be listed before B no matter how they were
- * originally positioned in the list.
- *
- * Works by performing a recursive depth-first search on the
- * required-by lists.
- */
-
-int
-sortdeps(char **pkgs)
-{
- int i, err_cnt=0;
- int nrpkgs, nrnewpkgs;
- char *listed, *check_loop, **newpkgs;
- char *cp;
-
- if (pkgs[0] == NULL || pkgs[1] == NULL)
- return (0);
-
- nrpkgs = 0;
- while (pkgs[nrpkgs]) nrpkgs++;
- listed = alloca(nrpkgs);
- if (listed == NULL) {
- warnx("%s(): alloca() failed", __func__);
- return 1;
- }
- bzero(listed,nrpkgs);
- check_loop = alloca(nrpkgs);
- if (check_loop == NULL) {
- warnx("%s(): alloca() failed", __func__);
- return 1;
- }
- bzero(check_loop,nrpkgs);
- newpkgs = alloca(nrpkgs*sizeof(char*));
- if (newpkgs == NULL) {
- warnx("%s(): alloca() failed", __func__);
- return 1;
- }
- nrnewpkgs = 0;
-
- for (i = 0; pkgs[i]; i++) if (!listed[i]) {
- check_loop[i] = 1;
- cp = strchr(pkgs[i], ':');
- if (cp != NULL)
- *cp = '\0';
- list_deps(pkgs[i],pkgs,listed,check_loop,newpkgs,&nrnewpkgs,&err_cnt);
- if (cp != NULL)
- *cp = ':';
- listed[i] = 1;
- newpkgs[nrnewpkgs] = pkgs[i];
- nrnewpkgs++;
- }
-
- if (nrnewpkgs != nrpkgs) {
- fprintf(stderr,"This shouldn't happen, and indicates a huge error in the code.\n");
- exit(1);
- }
- for (i = 0; i < nrnewpkgs; i++) pkgs[i] = newpkgs[i];
-
- return err_cnt;
-}
-
-/*
- * This recursive function lists the dependencies (that is, the
- * "required-by"s) for pkgname, putting them into newpkgs.
- */
-
-void list_deps(const char *pkgname, char **pkgs, char *listed,
- char *check_loop, char **newpkgs, int *nrnewpkgs,
- int *err_cnt) {
- char **rb, **rbtmp;
- char *cp;
- int errcode, i, j;
- struct reqr_by_entry *rb_entry;
- struct reqr_by_head *rb_list;
-
- if (isinstalledpkg(pkgname) <= 0)
- return;
-
- errcode = requiredby(pkgname, &rb_list, FALSE, TRUE);
- if (errcode < 0)
- return;
- /*
- * We put rb_list into an argv style NULL terminated list,
- * because requiredby uses some static storage, and list_deps
- * is a recursive function.
- */
-
- rbtmp = rb = alloca((errcode + 1) * sizeof(*rb));
- if (rb == NULL) {
- warnx("%s(): alloca() failed", __func__);
- (*err_cnt)++;
- return;
- }
- STAILQ_FOREACH(rb_entry, rb_list, link) {
- *rbtmp = alloca(strlen(rb_entry->pkgname) + 1);
- if (*rbtmp == NULL) {
- warnx("%s(): alloca() failed", __func__);
- (*err_cnt)++;
- return;
- }
- strcpy(*rbtmp, rb_entry->pkgname);
- rbtmp++;
- }
- *rbtmp = NULL;
-
- for (i = 0; rb[i]; i++)
- for (j = 0; pkgs[j]; j++) if (!listed[j]) {
- cp = strchr(pkgs[j], ':');
- if (cp != NULL)
- *cp = '\0';
- if (strcmp(rb[i], pkgs[j]) == 0) { /*match */
- /*
- * Try to avoid deadlock if package A depends on B which in
- * turn depends on C and C due to an error depends on A.
- * It Should Never Happen[tm] in real life.
- */
- if (check_loop[j]) {
- warnx("dependency loop detected for package %s", pkgs[j]);
- (*err_cnt)++;
- }
- else {
- check_loop[j] = 1;
- list_deps(pkgs[j],pkgs,listed,check_loop,newpkgs,nrnewpkgs,err_cnt);
- listed[j] = 1;
- newpkgs[*nrnewpkgs] = pkgs[j];
- (*nrnewpkgs)++;
- }
- }
- if (cp != NULL)
- *cp = ':';
- }
-}
-
-/*
- * Load +REQUIRED_BY file and return a list with names of
- * packages that require package referred to by `pkgname'.
- *
- * Optionally check that packages listed there are actually
- * installed and filter out those that don't (filter == TRUE).
- *
- * strict argument controls whether the caller want warnings
- * to be emitted when there are some non-fatal conditions,
- * i.e. package doesn't have +REQUIRED_BY file or some packages
- * listed in +REQUIRED_BY don't exist.
- *
- * Result returned in the **list, while return value is equal
- * to the number of entries in the resulting list. Print error
- * message and return -1 on error.
- */
-int
-requiredby(const char *pkgname, struct reqr_by_head **list, Boolean strict, Boolean filter)
-{
- FILE *fp;
- char fbuf[FILENAME_MAX], fname[FILENAME_MAX];
- int retval;
- struct reqr_by_entry *rb_entry;
- static struct reqr_by_head rb_list = STAILQ_HEAD_INITIALIZER(rb_list);
-
- *list = &rb_list;
- /* Deallocate any previously allocated space */
- while (!STAILQ_EMPTY(&rb_list)) {
- rb_entry = STAILQ_FIRST(&rb_list);
- STAILQ_REMOVE_HEAD(&rb_list, link);
- free(rb_entry);
- }
-
- if (isinstalledpkg(pkgname) <= 0) {
- if (strict == TRUE)
- warnx("no such package '%s' installed", pkgname);
- return -1;
- }
-
- snprintf(fname, sizeof(fname), "%s/%s/%s", LOG_DIR, pkgname,
- REQUIRED_BY_FNAME);
- fp = fopen(fname, "r");
- if (fp == NULL) {
- /* Probably pkgname doesn't have any packages that depend on it */
- if (strict == TRUE)
- warnx("couldn't open dependency file '%s'", fname);
- return 0;
- }
-
- retval = 0;
- while (fgets(fbuf, sizeof(fbuf), fp) != NULL) {
- if (fbuf[strlen(fbuf) - 1] == '\n')
- fbuf[strlen(fbuf) - 1] = '\0';
- if (filter == TRUE && isinstalledpkg(fbuf) <= 0) {
- if (strict == TRUE)
- warnx("package '%s' is recorded in the '%s' but isn't "
- "actually installed", fbuf, fname);
- continue;
- }
- retval++;
- rb_entry = malloc(sizeof(*rb_entry));
- if (rb_entry == NULL) {
- warnx("%s(): malloc() failed", __func__);
- retval = -1;
- break;
- }
- strlcpy(rb_entry->pkgname, fbuf, sizeof(rb_entry->pkgname));
- STAILQ_INSERT_TAIL(&rb_list, rb_entry, link);
- }
- fclose(fp);
-
- return retval;
-}
diff --git a/usr.sbin/pkg_install/lib/exec.c b/usr.sbin/pkg_install/lib/exec.c
deleted file mode 100644
index c0b4ac3..0000000
--- a/usr.sbin/pkg_install/lib/exec.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Miscellaneous system routines.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-
-/*
- * Unusual system() substitute. Accepts format string and args,
- * builds and executes command. Returns exit code.
- */
-
-int
-vsystem(const char *fmt, ...)
-{
- va_list args;
- char *cmd;
- long maxargs;
- int ret;
-
- maxargs = sysconf(_SC_ARG_MAX);
- maxargs -= 32; /* some slop for the sh -c */
- cmd = malloc(maxargs);
- if (!cmd) {
- warnx("vsystem can't alloc arg space");
- return 1;
- }
-
- va_start(args, fmt);
- if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
- warnx("vsystem args are too long");
- va_end(args);
- return 1;
- }
-#ifdef DEBUG
-printf("Executing %s\n", cmd);
-#endif
- ret = system(cmd);
- va_end(args);
- free(cmd);
- return ret;
-}
-
-char *
-vpipe(const char *fmt, ...)
-{
- FILE *fp;
- char *cmd, *rp;
- long maxargs;
- va_list args;
-
- rp = malloc(MAXPATHLEN);
- if (!rp) {
- warnx("vpipe can't alloc buffer space");
- return NULL;
- }
- maxargs = sysconf(_SC_ARG_MAX);
- maxargs -= 32; /* some slop for the sh -c */
- cmd = alloca(maxargs);
- if (!cmd) {
- warnx("vpipe can't alloc arg space");
- return NULL;
- }
-
- va_start(args, fmt);
- if (vsnprintf(cmd, maxargs, fmt, args) > maxargs) {
- warnx("vsystem args are too long");
- va_end(args);
- return NULL;
- }
-#ifdef DEBUG
- fprintf(stderr, "Executing %s\n", cmd);
-#endif
- fflush(NULL);
- fp = popen(cmd, "r");
- if (fp == NULL) {
- warnx("popen() failed");
- va_end(args);
- return NULL;
- }
- get_string(rp, MAXPATHLEN, fp);
-#ifdef DEBUG
- fprintf(stderr, "Returned %s\n", rp);
-#endif
- va_end(args);
- if (pclose(fp) || (strlen(rp) == 0)) {
- free(rp);
- return NULL;
- }
- return rp;
-}
diff --git a/usr.sbin/pkg_install/lib/file.c b/usr.sbin/pkg_install/lib/file.c
deleted file mode 100644
index 98413c6..0000000
--- a/usr.sbin/pkg_install/lib/file.c
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Miscellaneous file access utilities.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <pwd.h>
-#include <time.h>
-#include <sys/wait.h>
-
-/* Quick check to see if a file exists */
-Boolean
-fexists(const char *fname)
-{
- int fd;
-
- if ((fd = open(fname, O_RDONLY)) == -1)
- return FALSE;
-
- close(fd);
- return TRUE;
-}
-
-/* Quick check to see if something is a directory or symlink to a directory */
-Boolean
-isdir(const char *fname)
-{
- struct stat sb;
-
- if (lstat(fname, &sb) != FAIL && S_ISDIR(sb.st_mode))
- return TRUE;
- else if (lstat(strconcat(fname, "/."), &sb) != FAIL && S_ISDIR(sb.st_mode))
- return TRUE;
- else
- return FALSE;
-}
-
-/* Check to see if file is a dir or symlink to a dir, and is empty */
-Boolean
-isemptydir(const char *fname)
-{
- if (isdir(fname)) {
- DIR *dirp;
- struct dirent *dp;
-
- dirp = opendir(fname);
- if (!dirp)
- return FALSE; /* no perms, leave it alone */
- for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) {
- closedir(dirp);
- return FALSE;
- }
- }
- (void)closedir(dirp);
- return TRUE;
- }
- return FALSE;
-}
-
-/*
- * Returns TRUE if file is a regular file or symlink pointing to a regular
- * file
- */
-Boolean
-isfile(const char *fname)
-{
- struct stat sb;
- if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode))
- return TRUE;
- return FALSE;
-}
-
-/*
- * Check to see if file is a file or symlink pointing to a file and is empty.
- * If nonexistent or not a file, say "it's empty", otherwise return TRUE if
- * zero sized.
- */
-Boolean
-isemptyfile(const char *fname)
-{
- struct stat sb;
- if (stat(fname, &sb) != FAIL && S_ISREG(sb.st_mode)) {
- if (sb.st_size != 0)
- return FALSE;
- }
- return TRUE;
-}
-
-/* Returns TRUE if file is a symbolic link. */
-Boolean
-issymlink(const char *fname)
-{
- struct stat sb;
- if (lstat(fname, &sb) != FAIL && S_ISLNK(sb.st_mode))
- return TRUE;
- return FALSE;
-}
-
-/* Returns TRUE if file is a URL specification */
-Boolean
-isURL(const char *fname)
-{
- /*
- * I'm sure there are other types of URL specifications that I could
- * also be looking for here, but for now I'll just be happy to get ftp
- * and http working.
- */
- if (!fname)
- return FALSE;
- while (isspace(*fname))
- ++fname;
- if (!strncmp(fname, "ftp://", 6) || !strncmp(fname, "http://", 7) ||
- !strncmp(fname, "https://", 8) || !strncmp(fname, "file://", 7))
- return TRUE;
- return FALSE;
-}
-
-char *
-fileFindByPath(const char *base, const char *fname)
-{
- static char tmp[FILENAME_MAX];
- char *cp;
- const char *suffixes[] = {".tbz", ".tgz", ".tar", ".txz", NULL};
- int i;
-
- if (fexists(fname) && isfile(fname)) {
- strcpy(tmp, fname);
- return tmp;
- }
- if (base) {
- strcpy(tmp, base);
-
- cp = strrchr(tmp, '/');
- if (cp) {
- *cp = '\0'; /* chop name */
- cp = strrchr(tmp, '/');
- }
- if (cp)
- for (i = 0; suffixes[i] != NULL; i++) {
- *(cp + 1) = '\0';
- strcat(cp, "All/");
- strcat(cp, fname);
- strcat(cp, suffixes[i]);
- if (fexists(tmp))
- return tmp;
- }
- }
-
- cp = getenv("PKG_PATH");
- while (cp) {
- char *cp2 = strsep(&cp, ":");
-
- for (i = 0; suffixes[i] != NULL; i++) {
- snprintf(tmp, FILENAME_MAX, "%s/%s%s", cp2 ? cp2 : cp, fname, suffixes[i]);
- if (fexists(tmp) && isfile(tmp))
- return tmp;
- }
- }
- return NULL;
-}
-
-char *
-fileGetContents(const char *fname)
-{
- char *contents;
- struct stat sb;
- int fd;
-
- if (stat(fname, &sb) == FAIL) {
- cleanup(0);
- errx(2, "%s: can't stat '%s'", __func__, fname);
- }
-
- contents = (char *)malloc(sb.st_size + 1);
- fd = open(fname, O_RDONLY, 0);
- if (fd == FAIL) {
- cleanup(0);
- errx(2, "%s: unable to open '%s' for reading", __func__, fname);
- }
- if (read(fd, contents, sb.st_size) != sb.st_size) {
- cleanup(0);
- errx(2, "%s: short read on '%s' - did not get %lld bytes", __func__,
- fname, (long long)sb.st_size);
- }
- close(fd);
- contents[sb.st_size] = '\0';
- return contents;
-}
-
-/*
- * Takes a filename and package name, returning (in "try") the
- * canonical "preserve" name for it.
- */
-Boolean
-make_preserve_name(char *try, int max, const char *name, const char *file)
-{
- int len, i;
-
- if ((len = strlen(file)) == 0)
- return FALSE;
- else
- i = len - 1;
- strncpy(try, file, max);
- if (try[i] == '/') /* Catch trailing slash early and save checking in the loop */
- --i;
- for (; i; i--) {
- if (try[i] == '/') {
- try[i + 1]= '.';
- strncpy(&try[i + 2], &file[i + 1], max - i - 2);
- break;
- }
- }
- if (!i) {
- try[0] = '.';
- strncpy(try + 1, file, max - 1);
- }
- /* I should probably be called rude names for these inline assignments */
- strncat(try, ".", max -= strlen(try));
- strncat(try, name, max -= strlen(name));
- strncat(try, ".", max--);
- strncat(try, "backup", max -= 6);
- return TRUE;
-}
-
-/* Write the contents of "str" to a file */
-void
-write_file(const char *name, const char *str)
-{
- FILE *fp;
- size_t len;
-
- fp = fopen(name, "w");
- if (!fp) {
- cleanup(0);
- errx(2, "%s: cannot fopen '%s' for writing", __func__, name);
- }
- len = strlen(str);
- if (fwrite(str, 1, len, fp) != len) {
- cleanup(0);
- errx(2, "%s: short fwrite on '%s', tried to write %ld bytes",
- __func__, name, (long)len);
- }
- if (fclose(fp)) {
- cleanup(0);
- errx(2, "%s: failure to fclose '%s'", __func__, name);
- }
-}
-
-void
-copy_file(const char *dir, const char *fname, const char *to)
-{
- char cmd[FILENAME_MAX];
-
- if (fname[0] == '/')
- snprintf(cmd, FILENAME_MAX, "/bin/cp -r %s %s", fname, to);
- else
- snprintf(cmd, FILENAME_MAX, "/bin/cp -r %s/%s %s", dir, fname, to);
- if (vsystem(cmd)) {
- cleanup(0);
- errx(2, "%s: could not perform '%s'", __func__, cmd);
- }
-}
-
-void
-move_file(const char *dir, const char *fname, const char *tdir)
-{
- char from[FILENAME_MAX];
- char to[FILENAME_MAX];
-
- if (fname[0] == '/')
- strncpy(from, fname, FILENAME_MAX);
- else
- snprintf(from, FILENAME_MAX, "%s/%s", dir, fname);
-
- snprintf(to, FILENAME_MAX, "%s/%s", tdir, fname);
-
- if (rename(from, to) == -1) {
- if (vsystem("/bin/mv %s %s", from, to)) {
- cleanup(0);
- errx(2, "%s: could not move '%s' to '%s'", __func__, from, to);
- }
- }
-}
-
-/*
- * Copy a hierarchy (possibly from dir) to the current directory, or
- * if "to" is TRUE, from the current directory to a location someplace
- * else.
- *
- * Though slower, using tar to copy preserves symlinks and everything
- * without me having to write some big hairy routine to do it.
- */
-void
-copy_hierarchy(const char *dir, const char *fname, Boolean to)
-{
- char cmd[FILENAME_MAX * 3];
-
- if (!to) {
- /* If absolute path, use it */
- if (*fname == '/')
- dir = "/";
- snprintf(cmd, FILENAME_MAX * 3, "/usr/bin/tar cf - -C %s %s | /usr/bin/tar xpf -",
- dir, fname);
- }
- else
- snprintf(cmd, FILENAME_MAX * 3, "/usr/bin/tar cf - %s | /usr/bin/tar xpf - -C %s",
- fname, dir);
-#ifdef DEBUG
- printf("Using '%s' to copy trees.\n", cmd);
-#endif
- if (system(cmd)) {
- cleanup(0);
- errx(2, "%s: could not perform '%s'", __func__, cmd);
- }
-}
-
-/* Unpack a tar file */
-int
-unpack(const char *pkg, const char *flist)
-{
- const char *comp, *cp;
- char suff[80];
-
- comp = "";
- /*
- * Figure out by a crude heuristic whether this or not this is probably
- * compressed and whichever compression utility was used (gzip or bzip2).
- */
- if (strcmp(pkg, "-")) {
- cp = strrchr(pkg, '.');
- if (cp) {
- strcpy(suff, cp + 1);
- if (strchr(suff, 'z') || strchr(suff, 'Z')) {
- if (strchr(suff, 'b'))
- comp = "-j";
- else
- comp = "-z";
- }
- }
- }
- else
- comp = "-j";
- if (vsystem("/usr/bin/tar -xp %s -f '%s' %s", comp, pkg, flist ? flist : "")) {
- warnx("tar extract of %s failed!", pkg);
- return 1;
- }
- return 0;
-}
-
-/*
- * Using fmt, replace all instances of:
- *
- * %F With the parameter "name"
- * %D With the parameter "dir"
- * %B Return the directory part ("base") of %D/%F
- * %f Return the filename part of %D/%F
- *
- * Does not check for overflow - caution!
- *
- */
-void
-format_cmd(char *buf, int max, const char *fmt, const char *dir, const char *name)
-{
- char *cp, scratch[FILENAME_MAX * 2];
- int l;
-
- while (*fmt && max > 0) {
- if (*fmt == '%') {
- switch (*++fmt) {
- case 'F':
- strncpy(buf, name, max);
- l = strlen(name);
- buf += l, max -= l;
- break;
-
- case 'D':
- strncpy(buf, dir, max);
- l = strlen(dir);
- buf += l, max -= l;
- break;
-
- case 'B':
- snprintf(scratch, FILENAME_MAX * 2, "%s/%s", dir, name);
- cp = &scratch[strlen(scratch) - 1];
- while (cp != scratch && *cp != '/')
- --cp;
- *cp = '\0';
- strncpy(buf, scratch, max);
- l = strlen(scratch);
- buf += l, max -= l;
- break;
-
- case 'f':
- snprintf(scratch, FILENAME_MAX * 2, "%s/%s", dir, name);
- cp = &scratch[strlen(scratch) - 1];
- while (cp != scratch && *(cp - 1) != '/')
- --cp;
- strncpy(buf, cp, max);
- l = strlen(cp);
- buf += l, max -= l;
- break;
-
- default:
- *buf++ = *fmt;
- --max;
- break;
- }
- ++fmt;
- }
- else {
- *buf++ = *fmt++;
- --max;
- }
- }
- *buf = '\0';
-}
diff --git a/usr.sbin/pkg_install/lib/global.c b/usr.sbin/pkg_install/lib/global.c
deleted file mode 100644
index 25d2a53..0000000
--- a/usr.sbin/pkg_install/lib/global.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
-
- * 18 July 1993
- *
- * Semi-convenient place to stick some needed globals.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-
-/* These are global for all utils */
-Boolean Quiet = FALSE;
-Boolean Fake = FALSE;
-Boolean Force = FALSE;
-int AutoAnswer = FALSE;
-int Verbose = 0; /* Allow multiple levels of verbose. */
diff --git a/usr.sbin/pkg_install/lib/lib.h b/usr.sbin/pkg_install/lib/lib.h
deleted file mode 100644
index 77b2c71..0000000
--- a/usr.sbin/pkg_install/lib/lib.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Include and define various things wanted by the library routines.
- *
- */
-
-#ifndef _INST_LIB_LIB_H_
-#define _INST_LIB_LIB_H_
-
-/* Includes */
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/queue.h>
-#include <sys/utsname.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/* Macros */
-#define SUCCESS (0)
-#define FAIL (-1)
-
-#ifndef TRUE
-#define TRUE (1)
-#endif
-
-#ifndef FALSE
-#define FALSE (0)
-#endif
-
-#define YES 2
-#define NO 1
-
-/* Some more stat macros. */
-#define S_IRALL 0000444
-#define S_IWALL 0000222
-#define S_IXALL 0000111
-
-/* Usually "rm", but often "echo" during debugging! */
-#define REMOVE_CMD "/bin/rm"
-
-/* Usually "rm", but often "echo" during debugging! */
-#define RMDIR_CMD "/bin/rmdir"
-
-/* Where the ports lives by default */
-#define DEF_PORTS_DIR "/usr/ports"
-/* just in case we change the environment variable name */
-#define PORTSDIR "PORTSDIR"
-/* macro to get name of directory where the ports lives */
-#define PORTS_DIR (getenv(PORTSDIR) ? getenv(PORTSDIR) : DEF_PORTS_DIR)
-
-/* Where we put logging information by default, else ${PKG_DBDIR} if set */
-#define DEF_LOG_DIR "/var/db/pkg"
-/* just in case we change the environment variable name */
-#define PKG_DBDIR "PKG_DBDIR"
-/* macro to get name of directory where we put logging information */
-#define LOG_DIR (getenv(PKG_DBDIR) ? getenv(PKG_DBDIR) : DEF_LOG_DIR)
-
-/* The names of our "special" files */
-#define CONTENTS_FNAME "+CONTENTS"
-#define COMMENT_FNAME "+COMMENT"
-#define DESC_FNAME "+DESC"
-#define INSTALL_FNAME "+INSTALL"
-#define POST_INSTALL_FNAME "+POST-INSTALL"
-#define DEINSTALL_FNAME "+DEINSTALL"
-#define POST_DEINSTALL_FNAME "+POST-DEINSTALL"
-#define REQUIRE_FNAME "+REQUIRE"
-#define REQUIRED_BY_FNAME "+REQUIRED_BY"
-#define DISPLAY_FNAME "+DISPLAY"
-#define MTREE_FNAME "+MTREE_DIRS"
-
-#define CMD_CHAR '@' /* prefix for extended PLIST cmd */
-
-/* The name of the "prefix" environment variable given to scripts */
-#define PKG_PREFIX_VNAME "PKG_PREFIX"
-
-/*
- * Version of the package tools - increase whenever you make a change
- * in the code that is not cosmetic only.
- */
-#define PKG_INSTALL_VERSION 20130122
-
-#define PKG_WRAPCONF_FNAME "/var/db/pkg_install.conf"
-#define main(argc, argv) real_main(argc, argv)
-
-/* Version numbers to assist with changes in package file format */
-#define PLIST_FMT_VER_MAJOR 1
-#define PLIST_FMT_VER_MINOR 1
-
-enum _plist_t {
- PLIST_FILE, PLIST_CWD, PLIST_CMD, PLIST_CHMOD,
- PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, PLIST_IGNORE,
- PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY,
- PLIST_PKGDEP, PLIST_CONFLICTS, PLIST_MTREE, PLIST_DIR_RM,
- PLIST_IGNORE_INST, PLIST_OPTION, PLIST_ORIGIN, PLIST_DEPORIGIN,
- PLIST_NOINST
-};
-typedef enum _plist_t plist_t;
-
-enum _match_t {
- MATCH_ALL, MATCH_EXACT, MATCH_GLOB, MATCH_NGLOB, MATCH_EREGEX, MATCH_REGEX
-};
-typedef enum _match_t match_t;
-
-/* Types */
-typedef unsigned int Boolean;
-
-struct _plist {
- struct _plist *prev, *next;
- char *name;
- Boolean marked;
- plist_t type;
-};
-typedef struct _plist *PackingList;
-
-struct _pack {
- struct _plist *head, *tail;
- const char *name;
- const char *origin;
- int fmtver_maj, fmtver_mnr;
-};
-typedef struct _pack Package;
-
-struct reqr_by_entry {
- STAILQ_ENTRY(reqr_by_entry) link;
- char pkgname[PATH_MAX];
-};
-STAILQ_HEAD(reqr_by_head, reqr_by_entry);
-
-/* Prototypes */
-/* Misc */
-int vsystem(const char *, ...);
-char *vpipe(const char *, ...);
-void cleanup(int);
-const char *make_playpen(char *, off_t);
-char *where_playpen(void);
-int leave_playpen(void);
-off_t min_free(const char *);
-void warnpkgng(void);
-
-/* String */
-char *get_dash_string(char **);
-char *copy_string(const char *);
-char *copy_string_adds_newline(const char *);
-Boolean suffix(const char *, const char *);
-void nuke_suffix(char *);
-void str_lowercase(char *);
-char *strconcat(const char *, const char *);
-char *get_string(char *, int, FILE *);
-
-/* File */
-Boolean fexists(const char *);
-Boolean isdir(const char *);
-Boolean isemptydir(const char *fname);
-Boolean isemptyfile(const char *fname);
-Boolean isfile(const char *);
-Boolean isempty(const char *);
-Boolean issymlink(const char *);
-Boolean isURL(const char *);
-const char *fileGetURL(const char *, const char *, int);
-char *fileFindByPath(const char *, const char *);
-char *fileGetContents(const char *);
-void write_file(const char *, const char *);
-void copy_file(const char *, const char *, const char *);
-void move_file(const char *, const char *, const char *);
-void copy_hierarchy(const char *, const char *, Boolean);
-int delete_hierarchy(const char *, Boolean, Boolean);
-int unpack(const char *, const char *);
-void format_cmd(char *, int, const char *, const char *, const char *);
-
-/* Msg */
-void upchuck(const char *);
-void barf(const char *, ...);
-void whinge(const char *, ...);
-Boolean y_or_n(Boolean, const char *, ...);
-
-/* Packing list */
-PackingList new_plist_entry(void);
-PackingList last_plist(Package *);
-PackingList find_plist(Package *, plist_t);
-char *find_plist_option(Package *, const char *name);
-void plist_delete(Package *, Boolean, plist_t, const char *);
-void free_plist(Package *);
-void mark_plist(Package *);
-void csum_plist_entry(char *, PackingList);
-void add_plist(Package *, plist_t, const char *);
-void add_plist_top(Package *, plist_t, const char *);
-void delete_plist(Package *pkg, Boolean all, plist_t type, const char *name);
-void write_plist(Package *, FILE *);
-void read_plist(Package *, FILE *);
-int plist_cmd(const char *, char **);
-int delete_package(Boolean, Boolean, Package *);
-Boolean make_preserve_name(char *, int, const char *, const char *);
-
-/* For all */
-int pkg_perform(char **);
-int real_main(int, char **);
-
-/* Query installed packages */
-char **matchinstalled(match_t, char **, int *);
-char **matchbyorigin(const char *, int *);
-char ***matchallbyorigin(const char **, int *);
-int isinstalledpkg(const char *name);
-int pattern_match(match_t MatchType, char *pattern, const char *pkgname);
-
-/* Dependencies */
-int sortdeps(char **);
-int chkifdepends(const char *, const char *);
-int requiredby(const char *, struct reqr_by_head **, Boolean, Boolean);
-
-/* Version */
-int verscmp(Package *, int, int);
-int version_cmp(const char *, const char *);
-
-/* Externs */
-extern Boolean Quiet;
-extern Boolean Fake;
-extern Boolean Force;
-extern int AutoAnswer;
-extern int Verbose;
-
-#endif /* _INST_LIB_LIB_H_ */
diff --git a/usr.sbin/pkg_install/lib/match.c b/usr.sbin/pkg_install/lib/match.c
deleted file mode 100644
index 905d7cb..0000000
--- a/usr.sbin/pkg_install/lib/match.c
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Maxim Sobolev
- * 24 February 2001
- *
- * Routines used to query installed packages.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <fnmatch.h>
-#include <fts.h>
-#include <regex.h>
-
-/*
- * Simple structure representing argv-like
- * NULL-terminated list.
- */
-struct store {
- int currlen;
- int used;
- char **store;
-};
-
-static int rex_match(const char *, const char *, int);
-static int csh_match(const char *, const char *, int);
-struct store *storecreate(struct store *);
-static int storeappend(struct store *, const char *);
-static int fname_cmp(const FTSENT * const *, const FTSENT * const *);
-
-/*
- * Function to query names of installed packages.
- * MatchType - one of MATCH_ALL, MATCH_EREGEX, MATCH_REGEX, MATCH_GLOB, MATCH_NGLOB;
- * patterns - NULL-terminated list of glob or regex patterns
- * (could be NULL for MATCH_ALL);
- * retval - return value (could be NULL if you don't want/need
- * return value).
- * Returns NULL-terminated list with matching names.
- * Names in list returned are dynamically allocated and should
- * not be altered by the caller.
- */
-char **
-matchinstalled(match_t MatchType, char **patterns, int *retval)
-{
- int i, errcode, len;
- char *matched;
- const char *paths[2] = {LOG_DIR, NULL};
- static struct store *store = NULL;
- FTS *ftsp;
- FTSENT *f;
- Boolean *lmatched = NULL;
-
- store = storecreate(store);
- if (store == NULL) {
- if (retval != NULL)
- *retval = 1;
- return NULL;
- }
-
- if (retval != NULL)
- *retval = 0;
-
- if (!isdir(paths[0])) {
- if (retval != NULL)
- *retval = 1;
- return NULL;
- /* Not reached */
- }
-
- /* Count number of patterns */
- if (patterns != NULL) {
- for (len = 0; patterns[len]; len++) {}
- lmatched = alloca(sizeof(*lmatched) * len);
- if (lmatched == NULL) {
- warnx("%s(): alloca() failed", __func__);
- if (retval != NULL)
- *retval = 1;
- return NULL;
- }
- } else
- len = 0;
-
- for (i = 0; i < len; i++)
- lmatched[i] = FALSE;
-
- ftsp = fts_open((char * const *)(uintptr_t)paths, FTS_LOGICAL | FTS_NOCHDIR | FTS_NOSTAT, fname_cmp);
- if (ftsp != NULL) {
- while ((f = fts_read(ftsp)) != NULL) {
- if (f->fts_info == FTS_D && f->fts_level == 1) {
- fts_set(ftsp, f, FTS_SKIP);
- matched = NULL;
- errcode = 0;
- if (MatchType == MATCH_ALL)
- matched = f->fts_name;
- else
- for (i = 0; patterns[i]; i++) {
- errcode = pattern_match(MatchType, patterns[i], f->fts_name);
- if (errcode == 1) {
- matched = f->fts_name;
- lmatched[i] = TRUE;
- errcode = 0;
- }
- if (matched != NULL || errcode != 0)
- break;
- }
- if (errcode == 0 && matched != NULL)
- errcode = storeappend(store, matched);
- if (errcode != 0) {
- if (retval != NULL)
- *retval = 1;
- return NULL;
- /* Not reached */
- }
- }
- }
- fts_close(ftsp);
- }
-
- if (MatchType == MATCH_GLOB) {
- for (i = 0; i < len; i++)
- if (lmatched[i] == FALSE)
- storeappend(store, patterns[i]);
- }
-
- if (store->used == 0)
- return NULL;
- else
- return store->store;
-}
-
-int
-pattern_match(match_t MatchType, char *pattern, const char *pkgname)
-{
- int errcode = 0;
- const char *fname = pkgname;
- char basefname[PATH_MAX];
- char condchar = '\0';
- char *condition;
-
- /* do we have an appended condition? */
- condition = strpbrk(pattern, "<>=");
- if (condition) {
- const char *ch;
- /* yes, isolate the pattern from the condition ... */
- if (condition > pattern && condition[-1] == '!')
- condition--;
- condchar = *condition;
- *condition = '\0';
- /* ... and compare the name without version */
- ch = strrchr(fname, '-');
- if (ch && ch - fname < PATH_MAX) {
- strlcpy(basefname, fname, ch - fname + 1);
- fname = basefname;
- }
- }
-
- switch (MatchType) {
- case MATCH_EREGEX:
- case MATCH_REGEX:
- errcode = rex_match(pattern, fname, MatchType == MATCH_EREGEX ? 1 : 0);
- break;
- case MATCH_NGLOB:
- case MATCH_GLOB:
- errcode = (csh_match(pattern, fname, 0) == 0) ? 1 : 0;
- break;
- case MATCH_EXACT:
- errcode = (strcmp(pattern, fname) == 0) ? 1 : 0;
- break;
- case MATCH_ALL:
- errcode = 1;
- break;
- default:
- break;
- }
-
- /* loop over all appended conditions */
- while (condition) {
- /* restore the pattern */
- *condition = condchar;
- /* parse the condition (fun with bits) */
- if (errcode == 1) {
- char *nextcondition;
- /* compare version numbers */
- int match = 0;
- if (*++condition == '=') {
- match = 2;
- condition++;
- }
- switch(condchar) {
- case '<':
- match |= 1;
- break;
- case '>':
- match |= 4;
- break;
- case '=':
- match |= 2;
- break;
- case '!':
- match = 5;
- break;
- }
- /* isolate the version number from the next condition ... */
- nextcondition = strpbrk(condition, "<>=!");
- if (nextcondition) {
- condchar = *nextcondition;
- *nextcondition = '\0';
- }
- /* and compare the versions (version_cmp removes the filename for us) */
- if ((match & (1 << (version_cmp(pkgname, condition) + 1))) == 0)
- errcode = 0;
- condition = nextcondition;
- } else {
- break;
- }
- }
-
- return errcode;
-}
-
-/*
- * Synopsis is similar to matchinstalled(), but use origin
- * as a key for matching packages.
- */
-char ***
-matchallbyorigin(const char **origins, int *retval)
-{
- char **installed, **allorigins = NULL;
- char ***matches = NULL;
- int i, j;
-
- if (retval != NULL)
- *retval = 0;
-
- installed = matchinstalled(MATCH_ALL, NULL, retval);
- if (installed == NULL)
- return NULL;
-
- /* Gather origins for all installed packages */
- for (i = 0; installed[i] != NULL; i++) {
- FILE *fp;
- char *buf, *cp, tmp[PATH_MAX];
- int cmd;
-
- allorigins = realloc(allorigins, (i + 1) * sizeof(*allorigins));
- allorigins[i] = NULL;
-
- snprintf(tmp, PATH_MAX, "%s/%s", LOG_DIR, installed[i]);
- /*
- * SPECIAL CASE: ignore empty dirs, since we can can see them
- * during port installation.
- */
- if (isemptydir(tmp))
- continue;
- strncat(tmp, "/" CONTENTS_FNAME, PATH_MAX);
- fp = fopen(tmp, "r");
- if (fp == NULL) {
- warnx("the package info for package '%s' is corrupt", installed[i]);
- continue;
- }
-
- cmd = -1;
- while (fgets(tmp, sizeof(tmp), fp)) {
- int len = strlen(tmp);
-
- while (len && isspace(tmp[len - 1]))
- tmp[--len] = '\0';
- if (!len)
- continue;
- cp = tmp;
- if (tmp[0] != CMD_CHAR)
- continue;
- cmd = plist_cmd(tmp + 1, &cp);
- if (cmd == PLIST_ORIGIN) {
- asprintf(&buf, "%s", cp);
- allorigins[i] = buf;
- break;
- }
- }
- if (cmd != PLIST_ORIGIN && ( Verbose || 0 != strncmp("bsdpan-", installed[i], 7 ) ) )
- warnx("package %s has no origin recorded", installed[i]);
- fclose(fp);
- }
-
- /* Resolve origins into package names, retaining the sequence */
- for (i = 0; origins[i] != NULL; i++) {
- matches = realloc(matches, (i + 1) * sizeof(*matches));
- struct store *store = NULL;
- store = storecreate(store);
-
- for (j = 0; installed[j] != NULL; j++) {
- if (allorigins[j]) {
- if (csh_match(origins[i], allorigins[j], FNM_PATHNAME) == 0) {
- storeappend(store, installed[j]);
- }
- }
- }
- if (store->used == 0)
- matches[i] = NULL;
- else
- matches[i] = store->store;
- }
-
- if (allorigins) {
- for (i = 0; installed[i] != NULL; i++)
- if (allorigins[i])
- free(allorigins[i]);
- free(allorigins);
- }
-
- return matches;
-}
-
-/*
- * Synopsis is similar to matchinstalled(), but use origin
- * as a key for matching packages.
- */
-char **
-matchbyorigin(const char *origin, int *retval)
-{
- const char *origins[2];
- char ***tmp;
-
- origins[0] = origin;
- origins[1] = NULL;
-
- tmp = matchallbyorigin(origins, retval);
- if (tmp && tmp[0]) {
- return tmp[0];
- } else {
- return NULL;
- }
-}
-
-/*
- * Small linked list to memoize results of isinstalledpkg(). A hash table
- * would be faster but for n ~= 1000 may be overkill.
- */
-struct iip_memo {
- LIST_ENTRY(iip_memo) iip_link;
- char *iip_name;
- int iip_result;
-};
-LIST_HEAD(, iip_memo) iip_memo = LIST_HEAD_INITIALIZER(iip_memo);
-
-/*
- *
- * Return 1 if the specified package is installed,
- * 0 if not, and -1 if an error occurred.
- */
-int
-isinstalledpkg(const char *name)
-{
- int result;
- char *buf, *buf2;
- struct iip_memo *memo;
-
- LIST_FOREACH(memo, &iip_memo, iip_link) {
- if (strcmp(memo->iip_name, name) == 0)
- return memo->iip_result;
- }
-
- buf2 = NULL;
- asprintf(&buf, "%s/%s", LOG_DIR, name);
- if (buf == NULL)
- goto errout;
- if (!isdir(buf) || access(buf, R_OK) == FAIL) {
- result = 0;
- } else {
- asprintf(&buf2, "%s/%s", buf, CONTENTS_FNAME);
- if (buf2 == NULL)
- goto errout;
-
- if (!isfile(buf2) || access(buf2, R_OK) == FAIL)
- result = -1;
- else
- result = 1;
- }
-
- free(buf);
- buf = strdup(name);
- if (buf == NULL)
- goto errout;
- free(buf2);
- buf2 = NULL;
-
- memo = malloc(sizeof *memo);
- if (memo == NULL)
- goto errout;
- memo->iip_name = buf;
- memo->iip_result = result;
- LIST_INSERT_HEAD(&iip_memo, memo, iip_link);
- return result;
-
-errout:
- if (buf != NULL)
- free(buf);
- if (buf2 != NULL)
- free(buf2);
- return -1;
-}
-
-/*
- * Returns 1 if specified pkgname matches RE pattern.
- * Otherwise returns 0 if doesn't match or -1 if RE
- * engine reported an error (usually invalid syntax).
- */
-static int
-rex_match(const char *pattern, const char *pkgname, int extended)
-{
- char errbuf[128];
- int errcode;
- int retval;
- regex_t rex;
-
- retval = 0;
-
- errcode = regcomp(&rex, pattern, (extended ? REG_EXTENDED : REG_BASIC) | REG_NOSUB);
- if (errcode == 0)
- errcode = regexec(&rex, pkgname, 0, NULL, 0);
-
- if (errcode == 0) {
- retval = 1;
- } else if (errcode != REG_NOMATCH) {
- regerror(errcode, &rex, errbuf, sizeof(errbuf));
- warnx("%s: %s", pattern, errbuf);
- retval = -1;
- }
-
- regfree(&rex);
-
- return retval;
-}
-
-/*
- * Match string by a csh-style glob pattern. Returns 0 on
- * match and FNM_NOMATCH otherwise, to be compatible with
- * fnmatch(3).
- */
-static int
-csh_match(const char *pattern, const char *string, int flags)
-{
- int ret = FNM_NOMATCH;
-
-
- const char *nextchoice = pattern;
- const char *current = NULL;
-
- int prefixlen = -1;
- int currentlen = 0;
-
- int level = 0;
-
- do {
- const char *pos = nextchoice;
- const char *postfix = NULL;
-
- Boolean quoted = FALSE;
-
- nextchoice = NULL;
-
- do {
- const char *eb;
- if (!*pos) {
- postfix = pos;
- } else if (quoted) {
- quoted = FALSE;
- } else {
- switch (*pos) {
- case '{':
- ++level;
- if (level == 1) {
- current = pos+1;
- prefixlen = pos-pattern;
- }
- break;
- case ',':
- if (level == 1 && !nextchoice) {
- nextchoice = pos+1;
- currentlen = pos-current;
- }
- break;
- case '}':
- if (level == 1) {
- postfix = pos+1;
- if (!nextchoice)
- currentlen = pos-current;
- }
- level--;
- break;
- case '[':
- eb = pos+1;
- if (*eb == '!' || *eb == '^')
- eb++;
- if (*eb == ']')
- eb++;
- while(*eb && *eb != ']')
- eb++;
- if (*eb)
- pos=eb;
- break;
- case '\\':
- quoted = TRUE;
- break;
- default:
- ;
- }
- }
- pos++;
- } while (!postfix);
-
- if (current) {
- char buf[FILENAME_MAX];
- snprintf(buf, sizeof(buf), "%.*s%.*s%s", prefixlen, pattern, currentlen, current, postfix);
- ret = csh_match(buf, string, flags);
- if (ret) {
- current = nextchoice;
- level = 1;
- } else
- current = NULL;
- } else
- ret = fnmatch(pattern, string, flags);
- } while (current);
-
- return ret;
-}
-
-/*
- * Create an empty store, optionally deallocating
- * any previously allocated space if store != NULL.
- */
-struct store *
-storecreate(struct store *store)
-{
- int i;
-
- if (store == NULL) {
- store = malloc(sizeof *store);
- if (store == NULL) {
- warnx("%s(): malloc() failed", __func__);
- return NULL;
- }
- store->currlen = 0;
- store->store = NULL;
- } else if (store->store != NULL) {
- /* Free previously allocated memory */
- for (i = 0; store->store[i] != NULL; i++)
- free(store->store[i]);
- store->store[0] = NULL;
- }
- store->used = 0;
-
- return store;
-}
-
-/*
- * Append specified element to the provided store.
- */
-static int
-storeappend(struct store *store, const char *item)
-{
- if (store->used + 2 > store->currlen) {
- store->currlen += 16;
- store->store = reallocf(store->store,
- store->currlen * sizeof(*(store->store)));
- if (store->store == NULL) {
- store->currlen = 0;
- warnx("%s(): reallocf() failed", __func__);
- return 1;
- }
- }
-
- asprintf(&(store->store[store->used]), "%s", item);
- if (store->store[store->used] == NULL) {
- warnx("%s(): malloc() failed", __func__);
- return 1;
- }
- store->used++;
- store->store[store->used] = NULL;
-
- return 0;
-}
-
-static int
-fname_cmp(const FTSENT * const *a, const FTSENT * const *b)
-{
- return strcmp((*a)->fts_name, (*b)->fts_name);
-}
diff --git a/usr.sbin/pkg_install/lib/msg.c b/usr.sbin/pkg_install/lib/msg.c
deleted file mode 100644
index 57c84d3..0000000
--- a/usr.sbin/pkg_install/lib/msg.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Miscellaneous message routines.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <paths.h>
-
-/* Die a relatively simple death */
-void
-upchuck(const char *message)
-{
- cleanup(0);
- errx(1, "fatal error during execution: %s", message);
-}
-
-/*
- * As a yes/no question, prompting from the varargs string and using
- * default if user just hits return.
- */
-Boolean
-y_or_n(Boolean def, const char *msg, ...)
-{
- va_list args;
- int ch = 0;
- FILE *tty;
-
- va_start(args, msg);
- /*
- * Need to open /dev/tty because file collection may have been
- * collected on stdin
- */
- tty = fopen(_PATH_TTY, "r");
- if (!tty) {
- cleanup(0);
- errx(2, "can't open %s!", _PATH_TTY);
- }
- while (ch != 'Y' && ch != 'N') {
- vfprintf(stderr, msg, args);
- if (def)
- fprintf(stderr, " [yes]? ");
- else
- fprintf(stderr, " [no]? ");
- fflush(stderr);
- if (AutoAnswer) {
- ch = (AutoAnswer == YES) ? 'Y' : 'N';
- fprintf(stderr, "%c\n", ch);
- }
- else
- ch = toupper(fgetc(tty));
- if (ch == '\n')
- ch = (def) ? 'Y' : 'N';
- }
- fclose(tty) ;
- va_end(args);
- return (ch == 'Y') ? TRUE : FALSE;
-}
diff --git a/usr.sbin/pkg_install/lib/pen.c b/usr.sbin/pkg_install/lib/pen.c
deleted file mode 100644
index f4ecd75..0000000
--- a/usr.sbin/pkg_install/lib/pen.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Routines for managing the "play pen".
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <libutil.h>
-#include <libgen.h>
-#include <sys/signal.h>
-#include <sys/param.h>
-#include <sys/mount.h>
-
-/* For keeping track of where we are */
-static char PenLocation[FILENAME_MAX];
-
-char *
-where_playpen(void)
-{
- return PenLocation;
-}
-
-/* Find a good place to play. */
-static char *
-find_play_pen(char *pen, off_t sz)
-{
- char *cp;
- struct stat sb;
- char humbuf[6];
-
- if (pen[0] && isdir(dirname(pen)) == TRUE && (min_free(dirname(pen)) >= sz))
- return pen;
- else if ((cp = getenv("PKG_TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz))
- sprintf(pen, "%s/instmp.XXXXXX", cp);
- else if ((cp = getenv("TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz))
- sprintf(pen, "%s/instmp.XXXXXX", cp);
- else if (stat("/var/tmp", &sb) != FAIL && min_free("/var/tmp") >= sz)
- strcpy(pen, "/var/tmp/instmp.XXXXXX");
- else if (stat("/tmp", &sb) != FAIL && min_free("/tmp") >= sz)
- strcpy(pen, "/tmp/instmp.XXXXXX");
- else if ((stat("/usr/tmp", &sb) == SUCCESS || mkdir("/usr/tmp", 01777) == SUCCESS) && min_free("/usr/tmp") >= sz)
- strcpy(pen, "/usr/tmp/instmp.XXXXXX");
- else {
- cleanup(0);
- humanize_number(humbuf, sizeof humbuf, sz, "", HN_AUTOSCALE,
- HN_NOSPACE);
- errx(2,
-"%s: can't find enough temporary space to extract the files, please set your\n"
-"PKG_TMPDIR environment variable to a location with at least %s bytes\n"
-"free", __func__, humbuf);
- return NULL;
- }
- return pen;
-}
-
-#define MAX_STACK 20
-static char *pstack[MAX_STACK];
-static int pdepth = -1;
-
-static const char *
-pushPen(const char *pen)
-{
- if (++pdepth == MAX_STACK)
- errx(2, "%s: stack overflow.\n", __func__);
- pstack[pdepth] = strdup(pen);
-
- return pstack[pdepth];
-}
-
-static void
-popPen(char *pen)
-{
- if (pdepth == -1) {
- pen[0] = '\0';
- return;
- }
- strcpy(pen, pstack[pdepth]);
- free(pstack[pdepth--]);
-}
-
-/*
- * Make a temporary directory to play in and chdir() to it, returning
- * pathname of previous working directory.
- */
-const char *
-make_playpen(char *pen, off_t sz)
-{
- char humbuf1[6], humbuf2[6];
- char cwd[FILENAME_MAX];
-
- if (!find_play_pen(pen, sz))
- return NULL;
-
- if (!mkdtemp(pen)) {
- cleanup(0);
- errx(2, "%s: can't mktemp '%s'", __func__, pen);
- }
-
- if (Verbose) {
- if (sz) {
- humanize_number(humbuf1, sizeof humbuf1, sz, "", HN_AUTOSCALE,
- HN_NOSPACE);
- humanize_number(humbuf2, sizeof humbuf2, min_free(pen),
- "", HN_AUTOSCALE, HN_NOSPACE);
- fprintf(stderr, "Requested space: %s bytes, free space: %s bytes in %s\n", humbuf1, humbuf2, pen);
- }
- }
-
- if (min_free(pen) < sz) {
- rmdir(pen);
- cleanup(0);
- errx(2, "%s: not enough free space to create '%s'.\n"
- "Please set your PKG_TMPDIR environment variable to a location\n"
- "with more space and\ntry the command again", __func__, pen);
- }
-
- if (!getcwd(cwd, FILENAME_MAX)) {
- upchuck("getcwd");
- return NULL;
- }
-
- if (chdir(pen) == FAIL) {
- cleanup(0);
- errx(2, "%s: can't chdir to '%s'", __func__, pen);
- }
-
- strcpy(PenLocation, pen);
- return pushPen(cwd);
-}
-
-/* Convenience routine for getting out of playpen */
-int
-leave_playpen()
-{
- static char left[FILENAME_MAX];
- void (*oldsig)(int);
-
- if (!PenLocation[0])
- return 0;
-
- /* Don't interrupt while we're cleaning up */
- oldsig = signal(SIGINT, SIG_IGN);
- strcpy(left, PenLocation);
- popPen(PenLocation);
-
- if (chdir(PenLocation) == FAIL) {
- cleanup(0);
- errx(2, "%s: can't chdir back to '%s'", __func__, PenLocation);
- }
-
- if (left[0] == '/' && vsystem("/bin/rm -rf %s", left))
- warnx("couldn't remove temporary dir '%s'", left);
- signal(SIGINT, oldsig);
-
- return 1;
-}
-
-off_t
-min_free(const char *tmpdir)
-{
- struct statfs buf;
-
- if (statfs(tmpdir, &buf) != 0) {
- warn("statfs");
- return -1;
- }
- return (off_t)buf.f_bavail * (off_t)buf.f_bsize;
-}
diff --git a/usr.sbin/pkg_install/lib/pkgwrap.c b/usr.sbin/pkg_install/lib/pkgwrap.c
deleted file mode 100644
index cbd15cd..0000000
--- a/usr.sbin/pkg_install/lib/pkgwrap.c
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Maxim Sobolev
- * 8 September 2002
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#undef main
-
-#define SEPARATORS " \t"
-
-extern char **environ;
-
-int
-main(int argc, char **argv)
-{
- FILE *f;
- char buffer[FILENAME_MAX], *cp, *verstr;
- int len;
-
- if (getenv("PKG_NOWRAP") != NULL)
- goto nowrap;
- f = fopen(PKG_WRAPCONF_FNAME, "r");
- if (f == NULL)
- goto nowrap;
- cp = fgets(buffer, 256, f);
- fclose(f);
- if (cp == NULL)
- goto nowrap;
- len = strlen(cp);
- if (cp[len - 1] == '\n')
- cp[len - 1] = '\0';
- while (strchr(SEPARATORS, *cp) != NULL)
- cp++;
- verstr = cp;
- cp = strpbrk(cp, SEPARATORS);
- if (cp == NULL)
- goto nowrap;
- *cp = '\0';
- for (cp = verstr; *cp != '\0'; cp++)
- if (isdigit(*cp) == 0)
- goto nowrap;
- if (atoi(verstr) < PKG_INSTALL_VERSION)
- goto nowrap;
- cp++;
- while (*cp != '\0' && strchr(SEPARATORS, *cp) != NULL)
- cp++;
- if (*cp == '\0')
- goto nowrap;
- bcopy(cp, buffer, strlen(cp) + 1);
- cp = strpbrk(buffer, SEPARATORS);
- if (cp != NULL)
- *cp = '\0';
- if (!isdir(buffer))
- goto nowrap;
- cp = strrchr(argv[0], '/');
- if (cp == NULL)
- cp = argv[0];
- else
- cp++;
- strlcat(buffer, "/", sizeof(buffer));
- strlcat(buffer, cp, sizeof(buffer));
- setenv("PKG_NOWRAP", "1", 1);
- execve(buffer, argv, environ);
-
-nowrap:
- unsetenv("PKG_NOWRAP");
- return(real_main(argc, argv));
-}
diff --git a/usr.sbin/pkg_install/lib/plist.c b/usr.sbin/pkg_install/lib/plist.c
deleted file mode 100644
index bce6d04..0000000
--- a/usr.sbin/pkg_install/lib/plist.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * General packing list routines.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <md5.h>
-
-/* Add an item to a packing list */
-void
-add_plist(Package *p, plist_t type, const char *arg)
-{
- PackingList tmp;
-
- tmp = new_plist_entry();
- tmp->name = copy_string(arg);
- tmp->type = type;
-
- if (!p->head)
- p->head = p->tail = tmp;
- else {
- tmp->prev = p->tail;
- p->tail->next = tmp;
- p->tail = tmp;
- }
- switch (type) {
- case PLIST_NAME:
- p->name = tmp->name;
- break;
-
- case PLIST_ORIGIN:
- p->origin = tmp->name;
- break;
-
- default:
- break;
- }
-}
-
-void
-add_plist_top(Package *p, plist_t type, const char *arg)
-{
- PackingList tmp;
-
- tmp = new_plist_entry();
- tmp->name = copy_string(arg);
- tmp->type = type;
-
- if (!p->head)
- p->head = p->tail = tmp;
- else {
- tmp->next = p->head;
- p->head->prev = tmp;
- p->head = tmp;
- }
-}
-
-/* Return the last (most recent) entry in a packing list */
-PackingList
-last_plist(Package *p)
-{
- return p->tail;
-}
-
-/* Mark all items in a packing list to prevent iteration over them */
-void
-mark_plist(Package *pkg)
-{
- PackingList p = pkg->head;
-
- while (p) {
- p->marked = TRUE;
- p = p->next;
- }
-}
-
-/* Find a given item in a packing list and, if so, return it (else NULL) */
-PackingList
-find_plist(Package *pkg, plist_t type)
-{
- PackingList p = pkg->head;
-
- while (p) {
- if (p->type == type)
- return p;
- p = p->next;
- }
- return NULL;
-}
-
-/* Look for a specific boolean option argument in the list */
-char *
-find_plist_option(Package *pkg, const char *name)
-{
- PackingList p = pkg->head;
-
- while (p) {
- if (p->type == PLIST_OPTION && !strcmp(p->name, name))
- return p->name;
- p = p->next;
- }
- return NULL;
-}
-
-/*
- * Delete plist item 'type' in the list (if 'name' is non-null, match it
- * too.) If 'all' is set, delete all items, not just the first occurrence.
- */
-void
-delete_plist(Package *pkg, Boolean all, plist_t type, const char *name)
-{
- PackingList p = pkg->head;
-
- while (p) {
- PackingList pnext = p->next;
-
- if (p->type == type && (!name || !strcmp(name, p->name))) {
- free(p->name);
- if (p->prev)
- p->prev->next = pnext;
- else
- pkg->head = pnext;
- if (pnext)
- pnext->prev = p->prev;
- else
- pkg->tail = p->prev;
- free(p);
- if (!all)
- return;
- p = pnext;
- }
- else
- p = p->next;
- }
-}
-
-/* Allocate a new packing list entry */
-PackingList
-new_plist_entry(void)
-{
- PackingList ret;
-
- ret = (PackingList)malloc(sizeof(struct _plist));
- bzero(ret, sizeof(struct _plist));
- return ret;
-}
-
-/* Free an entire packing list */
-void
-free_plist(Package *pkg)
-{
- PackingList p = pkg->head;
-
- while (p) {
- PackingList p1 = p->next;
-
- free(p->name);
- free(p);
- p = p1;
- }
- pkg->head = pkg->tail = NULL;
-}
-
-/*
- * For an ascii string denoting a plist command, return its code and
- * optionally its argument(s)
- */
-int
-plist_cmd(const char *s, char **arg)
-{
- char cmd[FILENAME_MAX + 20]; /* 20 == fudge for max cmd len */
- char *cp;
- const char *sp;
-
- strcpy(cmd, s);
- str_lowercase(cmd);
- cp = cmd;
- sp = s;
- while (*cp) {
- if (isspace(*cp)) {
- *cp = '\0';
- while (isspace(*sp)) /* Never sure if macro, increment later */
- ++sp;
- break;
- }
- ++cp, ++sp;
- }
- if (arg)
- *arg = (char *)sp;
- if (!strcmp(cmd, "cwd"))
- return PLIST_CWD;
- else if (!strcmp(cmd, "srcdir"))
- return PLIST_SRC;
- else if (!strcmp(cmd, "cd"))
- return PLIST_CWD;
- else if (!strcmp(cmd, "exec"))
- return PLIST_CMD;
- else if (!strcmp(cmd, "unexec"))
- return PLIST_UNEXEC;
- else if (!strcmp(cmd, "mode"))
- return PLIST_CHMOD;
- else if (!strcmp(cmd, "owner"))
- return PLIST_CHOWN;
- else if (!strcmp(cmd, "group"))
- return PLIST_CHGRP;
- else if (!strcmp(cmd, "noinst"))
- return PLIST_NOINST;
- else if (!strcmp(cmd, "comment")) {
- if (!strncmp(*arg, "ORIGIN:", 7)) {
- *arg += 7;
- return PLIST_ORIGIN;
- } else if (!strncmp(*arg, "DEPORIGIN:", 10)) {
- *arg += 10;
- return PLIST_DEPORIGIN;
- }
- return PLIST_COMMENT;
- } else if (!strcmp(cmd, "ignore"))
- return PLIST_IGNORE;
- else if (!strcmp(cmd, "ignore_inst"))
- return PLIST_IGNORE_INST;
- else if (!strcmp(cmd, "name"))
- return PLIST_NAME;
- else if (!strcmp(cmd, "display"))
- return PLIST_DISPLAY;
- else if (!strcmp(cmd, "pkgdep"))
- return PLIST_PKGDEP;
- else if (!strcmp(cmd, "conflicts"))
- return PLIST_CONFLICTS;
- else if (!strcmp(cmd, "mtree"))
- return PLIST_MTREE;
- else if (!strcmp(cmd, "dirrm"))
- return PLIST_DIR_RM;
- else if (!strcmp(cmd, "option"))
- return PLIST_OPTION;
- else
- return FAIL;
-}
-
-/* Read a packing list from a file */
-void
-read_plist(Package *pkg, FILE *fp)
-{
- char *cp, pline[FILENAME_MAX];
- int cmd, major, minor;
-
- pkg->fmtver_maj = 1;
- pkg->fmtver_mnr = 0;
- pkg->origin = NULL;
- while (fgets(pline, FILENAME_MAX, fp)) {
- int len = strlen(pline);
-
- while (len && isspace(pline[len - 1]))
- pline[--len] = '\0';
- if (!len)
- continue;
- cp = pline;
- if (pline[0] != CMD_CHAR) {
- cmd = PLIST_FILE;
- goto bottom;
- }
- cmd = plist_cmd(pline + 1, &cp);
- if (cmd == FAIL) {
- warnx("%s: unknown command '%s' (package tools out of date?)",
- __func__, pline);
- goto bottom;
- }
- if (*cp == '\0') {
- cp = NULL;
- if (cmd == PLIST_PKGDEP) {
- warnx("corrupted record for package %s (pkgdep line without "
- "argument), ignoring", pkg->name);
- cmd = FAIL;
- }
- goto bottom;
- }
- if (cmd == PLIST_COMMENT && sscanf(cp, "PKG_FORMAT_REVISION:%d.%d\n",
- &major, &minor) == 2) {
- pkg->fmtver_maj = major;
- pkg->fmtver_mnr = minor;
- if (verscmp(pkg, PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR) <= 0)
- goto bottom;
-
- warnx("plist format revision (%d.%d) is higher than supported"
- "(%d.%d)", pkg->fmtver_maj, pkg->fmtver_mnr,
- PLIST_FMT_VER_MAJOR, PLIST_FMT_VER_MINOR);
- if (pkg->fmtver_maj > PLIST_FMT_VER_MAJOR) {
- cleanup(0);
- exit(2);
- }
- }
-bottom:
- add_plist(pkg, cmd, cp);
- }
-}
-
-/* Write a packing list to a file, converting commands to ascii equivs */
-void
-write_plist(Package *pkg, FILE *fp)
-{
- PackingList plist = pkg->head;
-
- while (plist) {
- switch(plist->type) {
- case PLIST_FILE:
- fprintf(fp, "%s\n", plist->name);
- break;
-
- case PLIST_CWD:
- fprintf(fp, "%ccwd %s\n", CMD_CHAR, (plist->name == NULL) ? "" : plist->name);
- break;
-
- case PLIST_SRC:
- fprintf(fp, "%csrcdir %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_CMD:
- fprintf(fp, "%cexec %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_UNEXEC:
- fprintf(fp, "%cunexec %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_CHMOD:
- fprintf(fp, "%cmode %s\n", CMD_CHAR, plist->name ? plist->name : "");
- break;
-
- case PLIST_CHOWN:
- fprintf(fp, "%cowner %s\n", CMD_CHAR, plist->name ? plist->name : "");
- break;
-
- case PLIST_CHGRP:
- fprintf(fp, "%cgroup %s\n", CMD_CHAR, plist->name ? plist->name : "");
- break;
-
- case PLIST_COMMENT:
- fprintf(fp, "%ccomment %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_NOINST:
- fprintf(fp, "%cnoinst %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_IGNORE:
- case PLIST_IGNORE_INST: /* a one-time non-ignored file */
- fprintf(fp, "%cignore\n", CMD_CHAR);
- break;
-
- case PLIST_NAME:
- fprintf(fp, "%cname %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_DISPLAY:
- fprintf(fp, "%cdisplay %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_PKGDEP:
- fprintf(fp, "%cpkgdep %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_CONFLICTS:
- fprintf(fp, "%cconflicts %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_MTREE:
- fprintf(fp, "%cmtree %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_DIR_RM:
- fprintf(fp, "%cdirrm %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_OPTION:
- fprintf(fp, "%coption %s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_ORIGIN:
- fprintf(fp, "%ccomment ORIGIN:%s\n", CMD_CHAR, plist->name);
- break;
-
- case PLIST_DEPORIGIN:
- fprintf(fp, "%ccomment DEPORIGIN:%s\n", CMD_CHAR, plist->name);
- break;
-
- default:
- cleanup(0);
- errx(2, "%s: unknown command type %d (%s)", __func__,
- plist->type, plist->name);
- break;
- }
- plist = plist->next;
- }
-}
-
-/*
- * Delete the results of a package installation.
- *
- * This is here rather than in the pkg_delete code because pkg_add needs to
- * run it too in cases of failure.
- */
-int
-delete_package(Boolean ign_err, Boolean nukedirs, Package *pkg)
-{
- PackingList p;
- const char *Where = ".", *last_file = "";
- Boolean fail = SUCCESS;
- Boolean preserve;
- char tmp[FILENAME_MAX], *name = NULL;
- char *prefix = NULL;
-
- preserve = find_plist_option(pkg, "preserve") ? TRUE : FALSE;
- for (p = pkg->head; p; p = p->next) {
- switch (p->type) {
- case PLIST_NAME:
- name = p->name;
- break;
-
- case PLIST_IGNORE:
- p = p->next;
- break;
-
- case PLIST_CWD:
- if (!prefix)
- prefix = p->name;
- Where = (p->name == NULL) ? prefix : p->name;
- if (Verbose)
- printf("Change working directory to %s\n", Where);
- break;
-
- case PLIST_UNEXEC:
- format_cmd(tmp, FILENAME_MAX, p->name, Where, last_file);
- if (Verbose)
- printf("Execute '%s'\n", tmp);
- if (!Fake && system(tmp)) {
- warnx("unexec command for '%s' failed", tmp);
- fail = FAIL;
- }
- break;
-
- case PLIST_FILE:
- last_file = p->name;
- if (*p->name == '/')
- strlcpy(tmp, p->name, FILENAME_MAX);
- else
- sprintf(tmp, "%s/%s", Where, p->name);
- if (isdir(tmp) && fexists(tmp) && !issymlink(tmp)) {
- warnx("cannot delete specified file '%s' - it is a directory!\n"
- "this packing list is incorrect - ignoring delete request", tmp);
- }
- else {
- if (p->next && p->next->type == PLIST_COMMENT && !strncmp(p->next->name, "MD5:", 4)) {
- char *cp = NULL, buf[33];
-
- /*
- * For packing lists whose version is 1.1 or greater, the md5
- * hash for a symlink is calculated on the string returned
- * by readlink().
- */
- if (issymlink(tmp) && verscmp(pkg, 1, 0) > 0) {
- int len;
- char linkbuf[FILENAME_MAX];
-
- if ((len = readlink(tmp, linkbuf, FILENAME_MAX)) > 0)
- cp = MD5Data((unsigned char *)linkbuf, len, buf);
- } else if (isfile(tmp) || verscmp(pkg, 1, 1) < 0)
- cp = MD5File(tmp, buf);
-
- if (cp != NULL) {
- /* Mismatch? */
- if (strcmp(cp, p->next->name + 4)) {
- warnx("'%s' fails original MD5 checksum - %s",
- tmp, Force ? "deleted anyway." : "not deleted.");
- if (!Force) {
- fail = FAIL;
- continue;
- }
- }
- }
- }
- if (Verbose)
- printf("Delete file %s\n", tmp);
- if (!Fake) {
- if (delete_hierarchy(tmp, ign_err, nukedirs))
- fail = FAIL;
- if (preserve && name) {
- char tmp2[FILENAME_MAX];
-
- if (make_preserve_name(tmp2, FILENAME_MAX, name, tmp)) {
- if (fexists(tmp2)) {
- if (rename(tmp2, tmp))
- warn("preserve: unable to restore %s as %s",
- tmp2, tmp);
- }
- }
- }
- }
- }
- break;
-
- case PLIST_DIR_RM:
- sprintf(tmp, "%s/%s", Where, p->name);
- if (!isdir(tmp) && fexists(tmp)) {
- warnx("cannot delete specified directory '%s' - it is a file!\n"
- "this packing list is incorrect - ignoring delete request", tmp);
- }
- else {
- if (Verbose)
- printf("Delete directory %s\n", tmp);
- if (!Fake && delete_hierarchy(tmp, ign_err, FALSE)) {
- warnx("unable to completely remove directory '%s'", tmp);
- fail = FAIL;
- }
- }
- last_file = p->name;
- break;
-
- default:
- break;
- }
- }
- return fail;
-}
-
-#ifdef DEBUG
-#define RMDIR(dir) vsystem("%s %s", RMDIR_CMD, dir)
-#define REMOVE(dir,ie) vsystem("%s %s%s", REMOVE_CMD, (ie ? "-f " : ""), dir)
-#else
-#define RMDIR rmdir
-#define REMOVE(file,ie) (remove(file) && !(ie))
-#endif
-
-/* Selectively delete a hierarchy */
-int
-delete_hierarchy(const char *dir, Boolean ign_err, Boolean nukedirs)
-{
- char *cp1, *cp2;
-
- cp1 = cp2 = strdup(dir);
- if (!fexists(dir) && !issymlink(dir)) {
- if (!ign_err)
- warnx("%s '%s' doesn't exist",
- isdir(dir) ? "directory" : "file", dir);
- return !ign_err;
- }
- else if (nukedirs) {
- if (vsystem("%s -r%s %s", REMOVE_CMD, (ign_err ? "f" : ""), dir))
- return 1;
- }
- else if (isdir(dir) && !issymlink(dir)) {
- if (RMDIR(dir) && !ign_err)
- return 1;
- }
- else {
- if (REMOVE(dir, ign_err))
- return 1;
- }
-
- if (!nukedirs)
- return 0;
- while (cp2) {
- if ((cp2 = strrchr(cp1, '/')) != NULL)
- *cp2 = '\0';
- if (!isemptydir(dir))
- return 0;
- if (RMDIR(dir) && !ign_err) {
- if (!fexists(dir))
- warnx("directory '%s' doesn't exist", dir);
- else
- return 1;
- }
- /* back up the pathname one component */
- if (cp2) {
- cp1 = strdup(dir);
- }
- }
- return 0;
-}
diff --git a/usr.sbin/pkg_install/lib/str.c b/usr.sbin/pkg_install/lib/str.c
deleted file mode 100644
index f1a087f..0000000
--- a/usr.sbin/pkg_install/lib/str.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * Miscellaneous string utilities.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-
-char *
-strconcat(const char *s1, const char *s2)
-{
- static char tmp[FILENAME_MAX];
-
- tmp[0] = '\0';
- strncpy(tmp, s1 ? s1 : s2, FILENAME_MAX); /* XXX: what if both are NULL? */
- if (s1 && s2)
- strncat(tmp, s2, FILENAME_MAX - strlen(tmp));
- return tmp;
-}
-
-/* Get a string parameter as a file spec or as a "contents follow -" spec */
-char *
-get_dash_string(char **str)
-{
- char *s = *str;
-
- if (*s == '-')
- *str = copy_string_adds_newline(s + 1);
- else
- *str = fileGetContents(s);
- return *str;
-}
-
-/* Rather Obvious */
-char *
-copy_string(const char *str)
-{
- return (str ? strdup(str) : NULL);
-}
-
-/* Rather Obvious but adds a trailing \n newline */
-char *
-copy_string_adds_newline(const char *str)
-{
- if (str == NULL) {
- return (NULL);
- } else {
- char *copy;
- size_t line_length;
-
- line_length = strlen(str) + 2;
- if ((copy = malloc(line_length)) == NULL)
- return (NULL);
- memcpy(copy, str, line_length - 2);
- copy[line_length - 2] = '\n'; /* Adds trailing \n */
- copy[line_length - 1] = '\0';
-
- return (copy);
- }
-}
-
-/* Return TRUE if 'str' ends in suffix 'suff' */
-Boolean
-suffix(const char *str, const char *suff)
-{
- char *idx;
- Boolean ret = FALSE;
-
- idx = strrchr(str, '.');
- if (idx && !strcmp(idx + 1, suff))
- ret = TRUE;
- return ret;
-}
-
-/* Assuming str has a suffix, brutally murder it! */
-void
-nuke_suffix(char *str)
-{
- char *idx;
-
- idx = strrchr(str, '.');
- if (idx)
- *idx = '\0'; /* Yow! Don't try this on a const! */
-}
-
-/* Lowercase a whole string */
-void
-str_lowercase(char *str)
-{
- while (*str) {
- *str = tolower(*str);
- ++str;
- }
-}
-
-char *
-get_string(char *str, int max, FILE *fp)
-{
- int len;
-
- if (!str)
- return NULL;
- str[0] = '\0';
- while (fgets(str, max, fp)) {
- len = strlen(str);
- while (len && isspace(str[len - 1]))
- str[--len] = '\0';
- if (len)
- return str;
- }
- return NULL;
-}
diff --git a/usr.sbin/pkg_install/lib/url.c b/usr.sbin/pkg_install/lib/url.c
deleted file mode 100644
index 80d306c..0000000
--- a/usr.sbin/pkg_install/lib/url.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jordan K. Hubbard
- * 18 July 1993
- *
- * URL file access utilities.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-#include <fetch.h>
-#include <libgen.h>
-#include <sys/wait.h>
-#include <stdio.h>
-
-/*
- * Try and fetch a file by URL, returning the directory name for where
- * it's unpacked, if successful.
- */
-const char *
-fileGetURL(const char *base, const char *spec, int keep_package)
-{
- const char *rp;
- char *cp, *tmp;
- char fname[FILENAME_MAX];
- char pen[FILENAME_MAX];
- char pkg[FILENAME_MAX];
- char buf[8192];
- FILE *ftp;
- pid_t tpid;
- int pfd[2], pstat, r, w = 0;
- char *hint;
- int fd, pkgfd = 0;
-
- rp = NULL;
- /* Special tip that sysinstall left for us */
- hint = getenv("PKG_ADD_BASE");
- if (!isURL(spec)) {
- if (!base && !hint)
- return NULL;
- /*
- * We've been given an existing URL (that's known-good) and now we need
- * to construct a composite one out of that and the basename we were
- * handed as a dependency.
- */
- if (base) {
- strcpy(fname, base);
- /*
- * Advance back two slashes to get to the root of the package
- * hierarchy
- */
- cp = strrchr(fname, '/');
- if (cp) {
- *cp = '\0'; /* chop name */
- cp = strrchr(fname, '/');
- }
- if (cp) {
- *(cp + 1) = '\0';
- strcat(cp, "All/");
- strcat(cp, spec);
- if (getenv("PACKAGESUFFIX"))
- strcat(cp, getenv("PACKAGESUFFIX"));
- else
- strcat(cp, ".tbz");
- }
- else
- return NULL;
- }
- else {
- /*
- * Otherwise, we've been given an environment variable hinting
- * at the right location from sysinstall
- */
- strcpy(fname, hint);
- strcat(fname, spec);
- if (getenv("PACKAGESUFFIX"))
- strcat(fname, getenv("PACKAGESUFFIX"));
- else
- strcat(fname, ".tbz");
- }
- }
- else
- strcpy(fname, spec);
-
- if (keep_package) {
- tmp = getenv("PKGDIR");
- strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
- tmp = basename(fname);
- strlcat(pkg, "/", sizeof(pkg));
- strlcat(pkg, tmp, sizeof(pkg));
- if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
- printf("Error: Unable to open %s\n", pkg);
- perror("open");
- return NULL;
- }
- }
-
- fetchDebug = (Verbose > 0);
- if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
- printf("Error: Unable to get %s: %s\n",
- fname, fetchLastErrString);
- /* If the fetch fails, yank the package. */
- if (keep_package && unlink(pkg) < 0 && Verbose) {
- warnx("failed to remove partially fetched package: %s", pkg);
- }
- return NULL;
- }
-
- if (isatty(0) || Verbose)
- printf("Fetching %s...", fname), fflush(stdout);
- pen[0] = '\0';
- if ((rp = make_playpen(pen, 0)) == NULL) {
- printf("Error: Unable to construct a new playpen for FTP!\n");
- fclose(ftp);
- return NULL;
- }
- if (pipe(pfd) == -1) {
- warn("pipe()");
- cleanup(0);
- exit(2);
- }
- if ((tpid = fork()) == -1) {
- warn("pipe()");
- cleanup(0);
- exit(2);
- }
- if (!tpid) {
- dup2(pfd[0], 0);
- for (fd = getdtablesize() - 1; fd >= 3; --fd)
- close(fd);
- execl("/usr/bin/tar", "tar",
- Verbose ? "-xpjvf" : "-xpjf",
- "-", (char *)0);
- _exit(2);
- }
- close(pfd[0]);
- for (;;) {
- if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
- break;
- if ((w = write(pfd[1], buf, r)) != r)
- break;
- if (keep_package) {
- if ((w = write(pkgfd, buf, r)) != r)
- break;
- }
- }
- if (ferror(ftp))
- warn("warning: error reading from server");
- fclose(ftp);
- if (keep_package) {
- close(pkgfd);
- }
- close(pfd[1]);
- if (w == -1)
- warn("warning: error writing to tar");
- tpid = waitpid(tpid, &pstat, 0);
- if (Verbose)
- printf("tar command returns %d status\n", WEXITSTATUS(pstat));
- if (rp && (isatty(0) || Verbose))
- printf(" Done.\n");
- return rp;
-}
diff --git a/usr.sbin/pkg_install/lib/version.c b/usr.sbin/pkg_install/lib/version.c
deleted file mode 100644
index c25d272..0000000
--- a/usr.sbin/pkg_install/lib/version.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Maxim Sobolev
- * 31 July 2001
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include <err.h>
-
-/*
- * Routines to assist with PLIST_FMT_VER numbers in the packing
- * lists.
- *
- * Following is the PLIST_FMT_VER history:
- * 1.0 - Initial revision;
- * 1.1 - When recording/checking checksum of symlink use hash of readlink()
- * value instead of the hash of an object this links points to.
- *
- */
-int
-verscmp(Package *pkg, int major, int minor)
-{
- int rval = 0;
-
- if ((pkg->fmtver_maj < major) || (pkg->fmtver_maj == major &&
- pkg->fmtver_mnr < minor))
- rval = -1;
- else if ((pkg->fmtver_maj > major) || (pkg->fmtver_maj == major &&
- pkg->fmtver_mnr > minor))
- rval = 1;
-
- return rval;
-}
-
-/*
- * split_version(pkgname, endname, epoch, revision) returns a pointer to
- * the version portion of a package name and the two special components.
- *
- * Syntax is: ${PORTNAME}-${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
- *
- * Written by Oliver Eikemeier
- * Based on work of Jeremy D. Lea.
- */
-static const char *
-split_version(const char *pkgname, const char **endname, unsigned long *epoch, unsigned long *revision)
-{
- char *ch;
- const char *versionstr;
- const char *endversionstr;
-
- if (pkgname == NULL)
- errx(2, "%s: Passed NULL pkgname.", __func__);
-
- /* Look for the last '-' in the pkgname */
- ch = strrchr(pkgname, '-');
- /* Cheat if we are just passed a version, not a valid package name */
- versionstr = ch ? ch + 1 : pkgname;
-
- /* Look for the last '_' in the version string, advancing the end pointer */
- ch = strrchr(versionstr, '_');
- if (revision != NULL) {
- *revision = ch ? strtoul(ch + 1, NULL, 10) : 0;
- }
- endversionstr = ch;
-
- /* Look for the last ',' in the remaining version string */
- ch = strrchr(endversionstr ? endversionstr + 1 : versionstr, ',');
- if (epoch != NULL) {
- *epoch = ch ? strtoul(ch + 1, NULL, 10) : 0;
- }
- if (ch && !endversionstr)
- endversionstr = ch;
-
- /* set the pointer behind the last character of the version without revision or epoch */
- if (endname)
- *endname = endversionstr ? endversionstr : strrchr(versionstr, '\0');
-
- return versionstr;
-}
-
-/*
- * PORTVERSIONs are composed of components separated by dots. A component
- * consists of a version number, a letter and a patchlevel number. This does
- * not conform to the porter's handbook, but let us formulate rules that
- * fit the current practice and are far simpler than to make decisions
- * based on the order of netters and lumbers. Besides, people use versions
- * like 10b2 in the ports...
- */
-
-typedef struct {
-#ifdef __LONG_LONG_SUPPORTED
- long long n;
- long long pl;
-#else
- long n;
- long pl;
-#endif
- int a;
-} version_component;
-
-/*
- * get_component(position, component) gets the value of the next component
- * (number - letter - number triple) and returns a pointer to the next character
- * after any leading separators
- *
- * - components are separated by dots
- * - characters !~ [a-zA-Z0-9.+*] are treated as separators
- * (1.0:2003.09.16 = 1.0.2003.09.16), this may not be what you expect:
- * 1.0.1:2003.09.16 < 1.0:2003.09.16
- * - consecutive separators are collapsed (10..1 = 10.1)
- * - missing separators are inserted, essentially
- * letter number letter => letter number . letter (10a1b2 = 10a1.b2)
- * - missing components are assumed to be equal to 0 (10 = 10.0 = 10.0.0)
- * - the letter sort order is: [none], a, b, ..., z; numbers without letters
- * sort first (10 < 10a < 10b)
- * - missing version numbers (in components starting with a letter) sort as -1
- * (a < 0, 10.a < 10)
- * - a separator is inserted before the special strings "pl", "alpha", "beta",
- * "pre" and "rc".
- * - "pl" sorts before every other letter, "alpha", "beta", "pre" and "rc"
- * sort as a, b, p and r. (10alpha = 10.a < 10, but 10 < 10a; pl11 < alpha3
- * < 0.1beta2 = 0.1.b2 < 0.1)
- * - other strings use only the first letter for sorting, case is ignored
- * (1.d2 = 1.dev2 = 1.Development2)
- * - The special component `*' is guaranteed to be the smallest possible
- * component (2.* < 2pl1 < 2alpha3 < 2.9f7 < 3.*)
- * - components separated by `+' are handled by version_cmp below
- *
- * Oliver Eikemeier
- */
-
-static const struct {
- const char *name;
- size_t namelen;
- int value;
-} stage[] = {
- { "pl", 2, 0 },
- { "alpha", 5, 'a'-'a'+1 },
- { "beta", 4, 'b'-'a'+1 },
- { "pre", 3, 'p'-'a'+1 },
- { "rc", 2, 'r'-'a'+1 },
- { NULL, 0, -1 }
-};
-
-static const char *
-get_component(const char *position, version_component *component)
-{
- const char *pos = position;
- int hasstage = 0, haspatchlevel = 0;
-
- if (!pos)
- errx(2, "%s: Passed NULL position.", __func__);
-
- /* handle version number */
- if (isdigit(*pos)) {
- char *endptr;
-#ifdef __LONG_LONG_SUPPORTED
- component->n = strtoll(pos, &endptr, 10);
-#else
- component->n = strtol(pos, &endptr, 10);
-#endif
- /* should we test for errno == ERANGE? */
- pos = endptr;
- } else if (*pos == '*') {
- component->n = -2;
- do {
- pos++;
- } while(*pos && *pos != '+');
- } else {
- component->n = -1;
- hasstage = 1;
- }
-
- /* handle letter */
- if (isalpha(*pos)) {
- int c = tolower(*pos);
- haspatchlevel = 1;
- /* handle special suffixes */
- if (isalpha(pos[1])) {
- int i;
- for (i = 0; stage[i].name; i++) {
- if (strncasecmp(pos, stage[i].name, stage[i].namelen) == 0
- && !isalpha(pos[stage[i].namelen])) {
- if (hasstage) {
- /* stage to value */
- component->a = stage[i].value;
- pos += stage[i].namelen;
- } else {
- /* insert dot */
- component->a = 0;
- haspatchlevel = 0;
- }
- c = 0;
- break;
- }
- }
- }
- /* unhandled above */
- if (c) {
- /* use the first letter and skip following */
- component->a = c - 'a' + 1;
- do {
- ++pos;
- } while (isalpha(*pos));
- }
- } else {
- component->a = 0;
- haspatchlevel = 0;
- }
-
- if (haspatchlevel) {
- /* handle patch number */
- if (isdigit(*pos)) {
- char *endptr;
-#ifdef __LONG_LONG_SUPPORTED
- component->pl = strtoll(pos, &endptr, 10);
-#else
- component->pl = strtol(pos, &endptr, 10);
-#endif
- /* should we test for errno == ERANGE? */
- pos = endptr;
- } else {
- component->pl = -1;
- }
- } else {
- component->pl = 0;
- }
-
- /* skip trailing separators */
- while (*pos && !isdigit(*pos) && !isalpha(*pos) && *pos != '+' && *pos != '*') {
- pos++;
- }
-
- return pos;
-}
-
-/*
- * version_cmp(pkg1, pkg2) returns -1, 0 or 1 depending on if the version
- * components of pkg1 is less than, equal to or greater than pkg2. No
- * comparison of the basenames is done.
- *
- * The port version is defined by:
- * ${PORTVERSION}[_${PORTREVISION}][,${PORTEPOCH}]
- * ${PORTEPOCH} supersedes ${PORTVERSION} supersedes ${PORTREVISION}.
- * See the commit log for revision 1.349 of ports/Mk/bsd.port.mk
- * for more information.
- *
- * The epoch and revision are defined to be a single number, while the rest
- * of the version should conform to the porting guidelines. It can contain
- * multiple components, separated by a period, including letters.
- *
- * The tests allow for significantly more latitude in the version numbers
- * than is allowed in the guidelines. No point in enforcing them here.
- * That's what portlint is for.
- *
- * Jeremy D. Lea.
- * reimplemented by Oliver Eikemeier
- */
-int
-version_cmp(const char *pkg1, const char *pkg2)
-{
- const char *v1, *v2, *ve1, *ve2;
- unsigned long e1, e2, r1, r2;
- int result = 0;
-
- v1 = split_version(pkg1, &ve1, &e1, &r1);
- v2 = split_version(pkg2, &ve2, &e2, &r2);
-
- /* Check epoch, port version, and port revision, in that order. */
- if (e1 != e2) {
- result = (e1 < e2 ? -1 : 1);
- }
-
- /* Shortcut check for equality before invoking the parsing routines. */
- if (result == 0 && (ve1 - v1 != ve2 - v2 || strncasecmp(v1, v2, ve1 - v1) != 0)) {
- /* Loop over different components (the parts separated by dots).
- * If any component differs, we have the basis for an inequality. */
- while(result == 0 && (v1 < ve1 || v2 < ve2)) {
- int block_v1 = 0;
- int block_v2 = 0;
- version_component vc1 = {0, 0, 0};
- version_component vc2 = {0, 0, 0};
- if (v1 < ve1 && *v1 != '+') {
- v1 = get_component(v1, &vc1);
- } else {
- block_v1 = 1;
- }
- if (v2 < ve2 && *v2 != '+') {
- v2 = get_component(v2, &vc2);
- } else {
- block_v2 = 1;
- }
- if (block_v1 && block_v2) {
- if (v1 < ve1)
- v1++;
- if (v2 < ve2)
- v2++;
- } else if (vc1.n != vc2.n) {
- result = (vc1.n < vc2.n ? -1 : 1);
- } else if (vc1.a != vc2.a) {
- result = (vc1.a < vc2.a ? -1 : 1);
- } else if (vc1.pl != vc2.pl) {
- result = (vc1.pl < vc2.pl ? -1 : 1);
- }
- }
- }
-
- /* Compare FreeBSD revision numbers. */
- if (result == 0 && r1 != r2) {
- result = (r1 < r2 ? -1 : 1);
- }
- return result;
-}
diff --git a/usr.sbin/pkg_install/tkpkg b/usr.sbin/pkg_install/tkpkg
deleted file mode 100755
index 9c95abf..0000000
--- a/usr.sbin/pkg_install/tkpkg
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/usr/local/bin/wish -f
-#$FreeBSD$
-#
-set pkgname ""
-wm title . "Package Installation"
-#--------------------------------------------------------------
-# The top level main window, consisting of a bar of buttons and a list
-# of packages and a description of the current package.
-#--------------------------------------------------------------
-frame .menu -relief raised -borderwidth 1
-frame .frame -borderwidth 4
-
-scrollbar .frame.scroll -relief sunken -command ".frame.list yview"
-listbox .frame.list -yscroll ".frame.scroll set" -relief sunken -setgrid 1
-pack append .frame .frame.scroll {right filly} \
- .frame.list {left expand fill}
-
-# build the lower window shoing the complete description of a pacage
-frame .f -borderwidth 4
-text .f.t -width 80 -height 20 -yscrollcommand ".f.s set" -relief sunken
-
-# Initially display instructions in this window. Erase the
-# instructions and show the package description when the user clicks
-# on a package.
-#
-.f.t insert end "Double click on a package above to see its
-complete description here."
-scrollbar .f.s -relief sunken -command ".f.t yview"
-pack append .f .f.s {right filly} .f.t {left expand fill}
-
-bind .frame.list <Double-Button-1> \
- {foreach i [selection get] {do_description $i}}
-pack append . .menu {top fill} \
- .f {bottom expand fill} \
- .frame {bottom expand fill}
-
-#----------------------------------------------------------------
-# Make menu bar:
-#----------------------------------------------------------------
-button .menu.inst -text "Install" \
- -command "apply_to_pkg \"pkg_add -v\""
-button .menu.dein -text "Deinstall" \
- -command "apply_to_pkg \"pkg_delete -v\""
-button .menu.installed -text "What is Installed?" \
- -command "list_pkgs \"pkg_info -I -a |tr ' ' ' '\""
-button .menu.available -text "What can I install?" \
- -command "list_pkgs \"pkg_info -I -c [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}] |tr ' ' ' '\""
-button .menu.cont -text "Contents?" \
- -command "apply_to_pkg \"pkg_info -d -v\""
-button .menu.quit -text "Quit" -command "destroy ."
-button .menu.help -text "Help" -command "do_help"
-
-pack append .menu \
- .menu.inst left \
- .menu.dein left \
- .menu.installed left \
- .menu.available left \
- .menu.cont left \
- .menu.quit left \
- .menu.help right
-#-------------------------------------------------------
-# Display the package description.
-#-------------------------------------------------------
-proc list_pkgs {s} {
- set line ""
- set f [eval "open {| sh -c \"$s\" } r"]
- .frame.list delete 0 end
- while {[gets $f line] > 0} {
- .frame.list insert end $line
- }
- close $f
-}
-
-# display the list of available packages
-set archives [glob -nocomplain *.{tgz,tar.z,tar.gz,tar.Z}]
-if {$archives == ""} {
- .frame.list delete 0 end
- .frame.list insert end "Warning: no compressed tar archives files found."
-} else {
- list_pkgs "pkg_info -I -c $archives |tr ' ' ' '"
-}
-
-#-------------------------------------------------------
-# Display the package description.
-#-------------------------------------------------------
-proc do_description {s} {
- global pkgname
- regexp {[^ ]*} $s filename
- set pkgname $filename
- .f.t delete 0.0 end
- set cmd "pkg_info -d $filename |tr -d ' '"
- set f [eval "open {| csh -c \"$cmd\" } r"]
- while {![eof $f]} {
- .f.t insert end [read $f]
- }
-}
-#-------------------------------------------------------
-# package install window.
-#-------------------------------------------------------
-proc do_help {{w .help}} {
- catch {destroy $w}
- toplevel $w
- wm title $w "Help"
- wm iconname $w "Help"
- button $w.ok -text OK -command "destroy $w"
- message $w.t -relief raised -bd 2 \
- -text "You can install, deinstall and list info on the available packages. To select a package and see its complete description, press mouse button 1 over the package name. To install a selected package, press the Install button. To exit, press the \"Quit\" button."
- pack append $w $w.ok {bottom fillx} $w.t {expand fill}
-}
-#-------------------------------------------------------
-# Apply a command to a package.
-#-------------------------------------------------------
-proc apply_to_pkg {s} {
- apply_to_pkg_err $s ""
-}
-#-------------------------------------------------------
-# Apply a command to a package, with error stream redirection instructions.
-#-------------------------------------------------------
-proc apply_to_pkg_err {s errredir} {
- global pkgname
- .f.t delete 0.0 end
- if {$pkgname == ""} {
- .f.t insert end "You must double click on a package name first!"
- } else {
- apply_to_pkg_int "$s $pkgname" "2>&1"
- }
-}
-proc apply_to_pkg_int {s errredir} {
- .f.t delete 0.0 end
- .f.t insert end "Running: $s\n"
- set f [eval "open {| sh -c \"$s $errredir\" } r"]
- while {![eof $f]} {
- .f.t insert end [read $f 64]
- }
-}
-#-------------------------------------------------------
-# Invoke an arbitrary command.
-#-------------------------------------------------------
-proc do_command {s} {
- .f.t delete 0.0 end
- .f.t insert end "Running: $s\n"
- set f [eval "open {| $s} r"]
- while {![eof $f]} {
- .f.t insert end [read $f 64]
- }
-}
-# local variables:
-# mode: csh
-# compile-command: ""
-# comment-start: "# "
-# comment-start-skip: "# "
-# end:
diff --git a/usr.sbin/pkg_install/updating/Makefile b/usr.sbin/pkg_install/updating/Makefile
deleted file mode 100644
index b0d3689..0000000
--- a/usr.sbin/pkg_install/updating/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# $FreeBSD$
-
-PROG= pkg_updating
-SRCS= main.c
-
-CFLAGS+= -I${.CURDIR}/../lib
-
-WFORMAT?= 1
-
-DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
-LDADD= ${LIBINSTALL} -lfetch -lmd
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/updating/Makefile.depend b/usr.sbin/pkg_install/updating/Makefile.depend
deleted file mode 100644
index 9507bb2..0000000
--- a/usr.sbin/pkg_install/updating/Makefile.depend
+++ /dev/null
@@ -1,24 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libfetch \
- lib/libmd \
- lib/libutil \
- secure/lib/libcrypto \
- secure/lib/libssl \
- usr.sbin/pkg_install/lib \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/updating/main.c b/usr.sbin/pkg_install/updating/main.c
deleted file mode 100644
index 4a36e22..0000000
--- a/usr.sbin/pkg_install/updating/main.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*-
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <beat@chruetertee.ch> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Beat Gätzi
- * ----------------------------------------------------------------------------
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-
-#include <sys/param.h>
-#include <stdio.h>
-#include <errno.h>
-#include <fetch.h>
-#include <limits.h>
-#include <sysexits.h>
-#include <getopt.h>
-
-#include "lib.h"
-#include "pathnames.h"
-
-typedef struct installedport {
- struct installedport *next; /* List of installed ports. */
- char name[LINE_MAX]; /* Name of the installed port. */
-} INSTALLEDPORT;
-
-int usage(void);
-
-static char opts[] = "d:f:h";
-static struct option longopts[] = {
- { "date", required_argument, NULL, 'd' },
- { "file", required_argument, NULL, 'f' },
- { "help", no_argument, NULL, 'h' },
- { NULL, 0, NULL, 0 },
-};
-
-/*
- * Parse /usr/port/UPDATING for corresponding entries. If no argument is
- * passed to pkg_updating all entries for all installed ports are displayed.
- * If a list of portnames is passed to pkg_updating only entries for the
- * given portnames are displayed. Use the -d option to define that only newer
- * entries as this date are shown.
- */
-int
-main(int argc, char *argv[])
-{
- /* Keyword for searching portname in UPDATING. */
- const char *affects = "AFFECTS";
- /* Indicate a date -> end of a entry. Will fail on 2100-01-01... */
- const char *end = "20";
- /* Keyword for searching origin portname of installed port. */
- const char *origin = "@comment ORIGIN:";
- const char *pkgdbpath = LOG_DIR; /* Location of pkgdb */
- const char *updatingfile = UPDATING; /* Location of UPDATING */
-
- char *date = NULL; /* Passed -d argument */
- char *dateline = NULL; /* Saved date of an entry */
- /* Tmp lines for parsing file */
- char *tmpline1 = NULL;
- char *tmpline2 = NULL;
-
- char originline[LINE_MAX]; /* Line of +CONTENTS */
- /* Temporary variable to create path to +CONTENTS for installed ports. */
- char tmp_file[MAXPATHLEN];
- char updatingline[LINE_MAX]; /* Line of UPDATING */
-
- int ch; /* Char used by getopt */
- int found = 0; /* Found an entry */
- int linelength; /* Length of parsed line */
- int maxcharperline = LINE_MAX; /* Max chars per line */
- int dflag = 0; /* -d option set */
- /* If pflag = 0 UPDATING will be checked for all installed ports. */
- int pflag = 0;
-
- size_t n; /* Offset to create path */
-
- struct dirent *pkgdbdir; /* pkgdb directory */
- struct stat attribute; /* attribute of pkgdb element */
-
- /* Needed nodes for linked list with installed ports. */
- INSTALLEDPORT *head = (INSTALLEDPORT *) NULL;
- INSTALLEDPORT *curr = (INSTALLEDPORT *) NULL;
-
- DIR *dir;
- FILE *fd;
-
- warnpkgng();
- while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
- switch (ch) {
- case 'd':
- dflag = 1;
- date = optarg;
- break;
- case 'f':
- updatingfile = optarg;
- break;
- case 'h':
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- /* Check if passed date has a correct format. */
- if (dflag == 1) {
- linelength = strlen(date);
- if (linelength != 8)
- exit(EX_DATAERR);
- if (strspn(date, "0123456789") != 8) {
- fprintf(stderr, "unknown date format: %s\n", date);
- exit(EX_DATAERR);
- }
- }
-
- /* Save the list of passed portnames. */
- if (argc != 0) {
- pflag = 1;
- while (*argv) {
- if ((curr = (INSTALLEDPORT *)
- malloc(sizeof(INSTALLEDPORT))) == NULL)
- (void)exit(EXIT_FAILURE);
- strlcpy(curr->name, *argv, strlen(*argv) + 1);
- curr->next = head;
- head = curr;
- (void)*argv++;
- }
- }
-
- /*
- * UPDATING will be parsed for all installed ports
- * if no portname is passed.
- */
- if (pflag == 0) {
- /* Open /var/db/pkg and search for all installed ports. */
- if ((dir = opendir(pkgdbpath)) != NULL) {
- while ((pkgdbdir = readdir(dir)) != NULL) {
- if (strcmp(pkgdbdir->d_name, ".") != 0 &&
- strcmp(pkgdbdir->d_name, "..") != 0) {
-
- /* Create path to +CONTENTS file for each installed port */
- n = strlcpy(tmp_file, pkgdbpath, sizeof(tmp_file));
- n = strlcpy(tmp_file + n, "/", sizeof(tmp_file) - n);
- n = strlcat(tmp_file + n, pkgdbdir->d_name,
- sizeof(tmp_file) - n);
- if (stat(tmp_file, &attribute) == -1) {
- fprintf(stderr, "can't open %s: %s\n",
- tmp_file, strerror(errno));
- return EXIT_FAILURE;
- }
- if (attribute.st_mode & S_IFREG)
- continue;
- (void)strlcat(tmp_file + n, "/",
- sizeof(tmp_file) - n);
- (void)strlcat(tmp_file + n, CONTENTS_FNAME,
- sizeof(tmp_file) - n);
-
- /* Open +CONTENT file */
- fd = fopen(tmp_file, "r");
- if (fd == NULL) {
- fprintf(stderr, "warning: can't open %s: %s\n",
- tmp_file, strerror(errno));
- continue;
- }
-
- /*
- * Parses +CONTENT for ORIGIN line and
- * put element into linked list.
- */
- while (fgets(originline, maxcharperline, fd) != NULL) {
- tmpline1 = strstr(originline, origin);
- if (tmpline1 != NULL) {
- /* Tmp variable to store port name. */
- char *pname;
- pname = strrchr(originline, (int)':');
- pname++;
- if ((curr = (INSTALLEDPORT *)
- malloc(sizeof(INSTALLEDPORT))) == NULL)
- (void)exit(EXIT_FAILURE);
- if (pname[strlen(pname) - 1] == '\n')
- pname[strlen(pname) - 1] = '\0';
- strlcpy (curr->name, pname, sizeof(curr->name));
- curr->next = head;
- head = curr;
- }
- }
-
- if (ferror(fd)) {
- fprintf(stderr, "error reading input\n");
- exit(EX_IOERR);
- }
-
- (void)fclose(fd);
- }
- }
- closedir(dir);
- }
- }
-
- /* Fetch UPDATING file if needed and open file */
- if (isURL(updatingfile)) {
- if ((fd = fetchGetURL(updatingfile, "")) == NULL) {
- fprintf(stderr, "Error: Unable to get %s: %s\n",
- updatingfile, fetchLastErrString);
- exit(EX_UNAVAILABLE);
- }
- }
- else {
- fd = fopen(updatingfile, "r");
- }
- if (fd == NULL) {
- fprintf(stderr, "can't open %s: %s\n",
- updatingfile, strerror(errno));
- exit(EX_UNAVAILABLE);
- }
-
- /* Parse opened UPDATING file. */
- while (fgets(updatingline, maxcharperline, fd) != NULL) {
- /* No entry is found so far */
- if (found == 0) {
- /* Search for AFFECTS line to parse the portname. */
- tmpline1 = strstr(updatingline, affects);
-
- if (tmpline1 != NULL) {
- curr = head;
- while (curr != NULL) {
- tmpline2 = strstr(updatingline, curr->name);
- if (tmpline2 != NULL)
- break;
- curr = curr->next;
- }
- if (tmpline2 != NULL) {
- /* If -d is set, check if entry is newer than the date. */
- if ((dflag == 1) && (strncmp(dateline, date, 8) < 0))
- continue;
- printf("%s", dateline);
- printf("%s", updatingline);
- found = 1;
- }
- }
- }
- /* Search for the end of an entry, if not found print the line. */
- else {
- tmpline1 = strstr(updatingline, end);
- if (tmpline1 == NULL)
- printf("%s", updatingline);
- else {
- linelength = strlen(updatingline);
- if (linelength == 10)
- found = 0;
- else
- printf("%s", updatingline);
- }
- }
- /* Save the actual line, it could be a date. */
- dateline = strdup(updatingline);
- }
-
- if (ferror(fd)) {
- fprintf(stderr, "error reading input\n");
- exit(EX_IOERR);
- }
- (void)fclose(fd);
-
- exit(EX_OK);
-}
-
-int
-usage(void)
-{
- fprintf(stderr,
- "usage: pkg_updating [-h] [-d YYYYMMDD] [-f file] [portname ...]\n");
- exit(EX_USAGE);
-}
-
-void
-cleanup(int sig)
-{
- if (sig)
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/updating/pathnames.h b/usr.sbin/pkg_install/updating/pathnames.h
deleted file mode 100644
index b9a94ed..0000000
--- a/usr.sbin/pkg_install/updating/pathnames.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*-
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <beat@chruetertee.ch> wrote this file. As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return. Beat Gätzi
- * ----------------------------------------------------------------------------
- *
- * $FreeBSD$
- *
- */
-
-/* Where the updating file lives by default */
-#define DEF_UPDATING "/usr/ports/UPDATING"
-/* macro to define location of the UPDATING file */
-#define UPDATING (getenv(PORTSDIR) ? strcat(getenv(PORTSDIR), \
- "/UPDATING") : DEF_UPDATING)
diff --git a/usr.sbin/pkg_install/updating/pkg_updating.1 b/usr.sbin/pkg_install/updating/pkg_updating.1
deleted file mode 100644
index 3fe16fd..0000000
--- a/usr.sbin/pkg_install/updating/pkg_updating.1
+++ /dev/null
@@ -1,97 +0,0 @@
-.\"
-.\" FreeBSD updating - Scan the installed ports and show all UPDATING entries
-.\" that affect one of the installed ports. Alternative a list of portnames
-.\" could be passed to pkg_updating
-.\"
-.\" "THE BEER-WARE LICENSE" (Revision 42):
-.\" <beat@chruetertee.ch> wrote this file. As long as you retain this notice you
-.\" can do whatever you want with this stuff. If we meet some day, and you think
-.\" this stuff is worth it, you can buy me a beer in return. Beat Gätzi
-.\"
-.\" $FreeBSD$
-.\"
-.Dd November 9, 2012
-.Dt PKG_UPDATING 1
-.Os
-.Sh NAME
-.Nm pkg_updating
-.Nd a utility for displaying UPDATING entries of software packages
-.Sh SYNOPSIS
-.Nm
-.Op Fl h
-.Op Fl d Ar date
-.Op Fl f Ar file
-.Op Ar pkg-name ...
-.Nm
-.Sh DESCRIPTION
-The
-.Nm
-command scans the installed ports and show all UPDATING entries that affect one
-of the installed ports. Alternative a list of pkg-names could be passed.
-.Sh OPTIONS
-The following command line options are supported:
-.Bl -tag -width indent
-.It Ar pkg-name ...
-UPDATING entries for the named packages are displayed.
-.It Fl d , -date Ar date
-Only entries newer than
-.Ar date
-are shown. Use a YYYYMMDD date format.
-.It Fl f , -file Ar file
-Defines a alternative location of the UPDATING
-.Ar file .
-.It Fl h , -help
-Print help message.
-.El
-.Sh ENVIRONMENT
-.Bl -tag -width PKG_DBDIR
-.It Ev PKG_DBDIR
-Specifies an alternative location for the installed package database.
-.It Ev PORTSDIR
-Location of the ports tree.
-.El
-.Sh FILES
-.Bl -tag -width /var/db/pkg -compact
-.It Pa /var/db/pkg
-Default location of the installed package database.
-.It Pa /usr/ports
-The default ports directory and default location of the UPDATING file.
-.El
-.Sh EXAMPLES
-Shows all entries of all installed ports:
-.Dl % pkg_updating
-.Pp
-Shows all entries of all installed ports since 2007-01-01:
-.Dl % pkg_updating -d 20070101
-.Pp
-Shows all entries for all apache and mysql ports:
-.Dl % pkg_updating apache mysql
-.Pp
-Shows all apache entries since 2006-01-01:
-.Dl % pkg_updating -d 20060101 apache
-.Pp
-Defines that the UPDATING file is in /tmp and shows all entries of all
-installed ports:
-.Dl % pkg_updating -f /tmp/UPDATING
-.Pp
-Fetch UPDATING file from ftp mirror and show all entries of all
-installed ports:
-.Dl % pkg_updating -f ftp://ftp.freebsd.org/pub/FreeBSD/ports/packages/UPDATING
-.Sh ENVRIOMENT
-.Bl -tag -width indent
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh SEE ALSO
-.Xr pkg_add 1 ,
-.Xr pkg_create 1 ,
-.Xr pkg_delete 1 ,
-.Xr pkg_version 1
-.Sh AUTHORS
-.An Beat G\(:atzi Aq beat@chruetertee.ch
-.Sh CONTRIBUTORS
-.An Martin Tournoij Aq carpetsmoker@xs4all.nl
-.Sh BUGS
-Sure to be some.
diff --git a/usr.sbin/pkg_install/version/Makefile b/usr.sbin/pkg_install/version/Makefile
deleted file mode 100644
index 3e1d7a5..0000000
--- a/usr.sbin/pkg_install/version/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# $FreeBSD$
-
-PROG= pkg_version
-SRCS= main.c perform.c
-
-CFLAGS+= -I${.CURDIR}/../lib
-
-WFORMAT?= 1
-
-DPADD= ${LIBINSTALL} ${LIBFETCH} ${LIBMD}
-LDADD= ${LIBINSTALL} -lfetch -lmd
-
-test:
- sh ${.CURDIR}/test-pkg_version.sh
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg_install/version/Makefile.depend b/usr.sbin/pkg_install/version/Makefile.depend
deleted file mode 100644
index 9507bb2..0000000
--- a/usr.sbin/pkg_install/version/Makefile.depend
+++ /dev/null
@@ -1,24 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libcompiler_rt \
- lib/libfetch \
- lib/libmd \
- lib/libutil \
- secure/lib/libcrypto \
- secure/lib/libssl \
- usr.sbin/pkg_install/lib \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/pkg_install/version/main.c b/usr.sbin/pkg_install/version/main.c
deleted file mode 100644
index dd67e63..0000000
--- a/usr.sbin/pkg_install/version/main.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jeremy D. Lea.
- * 11 May 2002
- *
- * This is the version module. Based on pkg_version.pl by Bruce A. Mah.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-
-#include <getopt.h>
-#include <err.h>
-
-#include "lib.h"
-#include "version.h"
-
-char *LimitChars = NULL;
-char *PreventChars = NULL;
-char *MatchName = NULL;
-char *LookUpOrigin = NULL;
-Boolean RegexExtended = FALSE;
-Boolean UseINDEXOnly = FALSE;
-Boolean ShowOrigin = FALSE;
-
-static void usage(void);
-
-static char opts[] = "dIhl:L:qs:XtTO:ov";
-static struct option longopts[] = {
- { "extended", no_argument, NULL, 'X' },
- { "help", no_argument, NULL, 'h' },
- { "match", required_argument, NULL, 's' },
- { "no-status", required_argument, NULL, 'L' },
- { "origin", required_argument, NULL, 'O' },
- { "quiet", no_argument, NULL, 'q' },
- { "show-origin",no_argument, NULL, 'o' },
- { "status", required_argument, NULL, 'l' },
- { "index-only", no_argument, NULL, 'I' },
- { "verbose", no_argument, NULL, 'v' },
- { NULL, 0, NULL, 0 }
-};
-
-int
-main(int argc, char **argv)
-{
- int ch, cmp = 0;
-
- warnpkgng();
- if (argc == 4 && !strcmp(argv[1], "-t")) {
- cmp = version_cmp(argv[2], argv[3]);
- printf(cmp > 0 ? ">\n" : (cmp < 0 ? "<\n" : "=\n"));
- exit(0);
- }
- else if (argc == 4 && !strcmp(argv[1], "-T")) {
- cmp = version_match(argv[3], argv[2]);
- exit(cmp == 1 ? 0 : 1);
- }
- else while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) {
- switch(ch) {
- case 'v':
- Verbose++;
- break;
-
- case 'I':
- UseINDEXOnly = TRUE;
- break;
-
- case 'l':
- LimitChars = optarg;
- break;
-
- case 'L':
- PreventChars = optarg;
- break;
-
- case 'q':
- Quiet = TRUE;
- break;
-
- case 's':
- MatchName = optarg;
- break;
-
- case 'O':
- LookUpOrigin = optarg;
- break;
-
- case 'o':
- ShowOrigin = TRUE;
- break;
-
- case 't':
- errx(2, "Invalid -t usage.");
- break;
-
- case 'T':
- errx(2, "Invalid -T usage.");
- break;
-
- case 'X':
- RegexExtended = TRUE;
- break;
-
- case 'h':
- default:
- usage();
- break;
- }
- }
-
- argc -= optind;
- argv += optind;
-
- return pkg_perform(argv);
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "%s\n%s\n%s\n",
- "usage: pkg_version [-hIoqv] [-l limchar] [-L limchar] [[-X] -s string] [-O origin] [index]",
- " pkg_version -t v1 v2",
- " pkg_version -T name pattern");
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/version/perform.c b/usr.sbin/pkg_install/version/perform.c
deleted file mode 100644
index 426d979..0000000
--- a/usr.sbin/pkg_install/version/perform.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jeremy D. Lea.
- * 11 May 2002
- *
- * This is the version module. Based on pkg_version.pl by Bruce A. Mah.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "lib.h"
-#include "version.h"
-#include <err.h>
-#include <fetch.h>
-#include <signal.h>
-
-static FILE *IndexFile;
-static char IndexPath[PATH_MAX] = "";
-static struct index_head Index = SLIST_HEAD_INITIALIZER(Index);
-
-static int pkg_do(char *);
-static void show_version(Package, const char *, const char *);
-
-/*
- * This is the traditional pkg_perform, except that the argument is _not_ a
- * list of packages. It is the index file from the command line.
- *
- * We loop over the installed packages, matching them with the -s flag if
- * needed and calling pkg_do(). Beforehand we set up a few things, and after
- * we tear them down...
- *
- * Returns 0 on success, non-zero on failure, corresponding to the number of
- * failed attempts to access the INDEX.
- */
-int
-pkg_perform(char **indexarg)
-{
- char **pkgs, *pat[2], **patterns;
- struct index_entry *ie;
- int i, err_cnt = 0, rel_major_ver;
- int MatchType;
-
- struct utsname u;
-
- if (uname(&u) == -1) {
- warn("%s: failed to determine uname information", __func__);
- return 1;
- } else if ((rel_major_ver = (int) strtol(u.release, NULL, 10)) <= 0) {
- warnx("%s: bad release version specified: %s", __func__, u.release);
- return 1;
- }
-
- /*
- * Try to find and open the INDEX. We only check IndexFile != NULL
- * later, if we actually need the INDEX.
- */
- if (*indexarg == NULL) {
- snprintf(IndexPath, sizeof(IndexPath), "%s/INDEX-%d", PORTS_DIR,
- rel_major_ver);
- } else
- strlcpy(IndexPath, *indexarg, sizeof(IndexPath));
- if (isURL(IndexPath))
- IndexFile = fetchGetURL(IndexPath, "");
- else
- IndexFile = fopen(IndexPath, "r");
-
- /* Get either a list of matching or all packages */
- if (MatchName != NULL) {
- pat[0] = MatchName;
- pat[1] = NULL;
- MatchType = RegexExtended ? MATCH_EREGEX : MATCH_REGEX;
- patterns = pat;
- } else {
- MatchType = MATCH_ALL;
- patterns = NULL;
- }
-
- if (LookUpOrigin != NULL)
- pkgs = matchbyorigin(LookUpOrigin, &err_cnt);
- else
- pkgs = matchinstalled(MatchType, patterns, &err_cnt);
-
- if (err_cnt != 0)
- errx(2, "Unable to find package database directory!");
- if (pkgs == NULL) {
- if (LookUpOrigin != NULL) {
- warnx("no packages recorded with this origin");
- return (1);
- } else {
- switch (MatchType) {
- case MATCH_ALL:
- warnx("no packages installed");
- return (0);
- case MATCH_EREGEX:
- case MATCH_REGEX:
- warnx("no packages match pattern");
- return (1);
- default:
- break;
- }
- }
- }
-
- for (i = 0; pkgs[i] != NULL; i++)
- err_cnt += pkg_do(pkgs[i]);
-
- /* If we opened the INDEX in pkg_do(), clean up. */
- while (!SLIST_EMPTY(&Index)) {
- ie = SLIST_FIRST(&Index);
- SLIST_REMOVE_HEAD(&Index, next);
- if (ie->name != NULL)
- free(ie->name);
- if (ie->origin != NULL)
- free(ie->origin);
- free(ie);
- }
- if (IndexFile != NULL)
- fclose(IndexFile);
-
- return err_cnt;
-}
-
-/*
- * Traditional pkg_do(). We take the package name we are passed and
- * first slurp in the CONTENTS file, getting name and origin, then
- * we look for it's corresponding Makefile. If that fails we pull in
- * the INDEX, and check there.
- */
-static int
-pkg_do(char *pkg)
-{
- char *ch, tmp[PATH_MAX], tmp2[PATH_MAX], *latest = NULL;
- Package plist;
- struct index_entry *ie;
- FILE *fp;
- size_t len;
-
- /* Suck in the contents list. */
- plist.head = plist.tail = NULL;
- plist.name = plist.origin = NULL;
- snprintf(tmp, PATH_MAX, "%s/%s/%s", LOG_DIR, pkg, CONTENTS_FNAME);
- fp = fopen(tmp, "r");
- if (!fp) {
- warnx("the package info for package '%s' is corrupt", pkg);
- return 1;
- }
- read_plist(&plist, fp);
- fclose(fp);
- if (plist.name == NULL) {
- warnx("%s does not appear to be a valid package!", pkg);
- return 1;
- }
-
- /*
- * First we check if the installed package has an origin, and try
- * looking for it's Makefile. If we find the Makefile we get the
- * latest version from there. If we fail, we start looking in the
- * INDEX, first matching the origin and then the package name.
- */
- if (plist.origin != NULL && !UseINDEXOnly) {
- snprintf(tmp, PATH_MAX, "%s/%s", PORTS_DIR, plist.origin);
- if (isdir(tmp) && chdir(tmp) != FAIL && isfile("Makefile")) {
- if ((latest = vpipe("/usr/bin/make -V PKGNAME", tmp)) == NULL)
- warnx("Failed to get PKGNAME from %s/Makefile!", tmp);
- else
- show_version(plist, latest, "port");
- }
- }
- if (latest == NULL) {
- /* Report package as not found in INDEX if the INDEX is not required. */
- if (IndexFile == NULL && !UseINDEXOnly)
- show_version(plist, NULL, plist.origin);
- else {
- /* We only pull in the INDEX once, if needed. */
- if (SLIST_EMPTY(&Index)) {
- if (!IndexFile)
- errx(2, "Unable to open %s in %s.", IndexPath, __func__);
- while ((ch = fgetln(IndexFile, &len)) != NULL) {
- /*
- * Don't use strlcpy() because fgetln() doesn't
- * return a valid C string.
- */
- strncpy(tmp, ch, MIN(len, PATH_MAX));
- tmp[PATH_MAX-1] = '\0';
- /* The INDEX has pkgname|portdir|... */
- if ((ch = strchr(tmp, '|')) != NULL)
- ch[0] = '\0';
- if (ch != NULL && (ch = strchr(&ch[1], '|')) != NULL)
- ch[0] = '\0';
- /* Look backwards for the last two dirs = origin */
- while (ch != NULL && *--ch != '/')
- if (ch[0] == '\0')
- ch = NULL;
- while (ch != NULL && *--ch != '/')
- if (ch[0] == '\0')
- ch = NULL;
- if (ch == NULL)
- errx(2, "The INDEX does not appear to be valid!");
- if ((ie = malloc(sizeof(struct index_entry))) == NULL)
- errx(2, "Unable to allocate memory in %s.", __func__);
- bzero(ie, sizeof(struct index_entry));
- ie->name = strdup(tmp);
- ie->origin = strdup(&ch[1]);
- /* Who really cares if we reverse the index... */
- SLIST_INSERT_HEAD(&Index, ie, next);
- }
- }
- /* Now that we've slurped in the INDEX... */
- SLIST_FOREACH(ie, &Index, next) {
- if (plist.origin != NULL) {
- if (strcmp(plist.origin, ie->origin) == 0)
- latest = strdup(ie->name);
- } else {
- strlcpy(tmp, ie->name, PATH_MAX);
- strlcpy(tmp2, plist.name, PATH_MAX);
- /* Chop off the versions and compare. */
- if ((ch = strrchr(tmp, '-')) == NULL)
- errx(2, "The INDEX does not appear to be valid!");
- ch[0] = '\0';
- if ((ch = strrchr(tmp2, '-')) == NULL)
- warnx("%s is not a valid package!", plist.name);
- else
- ch[0] = '\0';
- if (strcmp(tmp2, tmp) == 0) {
- if (latest != NULL) {
- /* Multiple matches */
- snprintf(tmp, PATH_MAX, "%s|%s", latest, ie->name);
- free(latest);
- latest = strdup(tmp);
- } else
- latest = strdup(ie->name);
- }
- }
- }
- if (latest == NULL)
- show_version(plist, NULL, NULL);
- else
- show_version(plist, latest, "index");
- }
- }
- if (latest != NULL)
- free(latest);
- free_plist(&plist);
- return 0;
-}
-
-#define OUTPUT(c) ((PreventChars != NULL && !strchr(PreventChars, (c))) || \
- (LimitChars != NULL && strchr(LimitChars, (c))) || \
- (PreventChars == NULL && LimitChars == NULL))
-
-/*
- * Do the work of comparing and outputing. Ugly, but well that's what
- * You get when you try to match perl output in C ;-).
- */
-void
-show_version(Package plist, const char *latest, const char *source)
-{
- char *ch, tmp[PATH_MAX];
- const char *ver;
- int cmp = 0;
-
- if (!plist.name || strlen(plist.name) == 0)
- return;
- if (ShowOrigin != FALSE && plist.origin != NULL)
- strlcpy(tmp, plist.origin, PATH_MAX);
- else {
- strlcpy(tmp, plist.name, PATH_MAX);
- if (!Verbose) {
- if ((ch = strrchr(tmp, '-')) != NULL)
- ch[0] = '\0';
- }
- }
- if (latest == NULL) {
- if (source == NULL && OUTPUT('!')) {
- printf("%-34s !", tmp);
- if (Verbose)
- printf(" Comparison failed");
- printf("\n");
- } else if (OUTPUT('?')) {
- printf("%-34s ?", tmp);
- if (Verbose)
- printf(" orphaned: %s", plist.origin);
- printf("\n");
- }
- } else if (strchr(latest,'|') != NULL) {
- if (OUTPUT('*')) {
- printf("%-34s *", tmp);
- if (Verbose) {
- strlcpy(tmp, latest, PATH_MAX);
- ch = strchr(tmp, '|');
- ch[0] = '\0';
-
- ver = strrchr(tmp, '-');
- ver = ver ? &ver[1] : tmp;
- printf(" multiple versions (index has %s", ver);
- do {
- ver = strrchr(&ch[1], '-');
- ver = ver ? &ver[1] : &ch[1];
- if ((ch = strchr(&ch[1], '|')) != NULL)
- ch[0] = '\0';
- printf(", %s", ver);
- } while (ch != NULL);
- printf(")");
- }
- printf("\n");
- }
- } else {
- cmp = version_cmp(plist.name, latest);
- ver = strrchr(latest, '-');
- ver = ver ? &ver[1] : latest;
- if (cmp < 0 && OUTPUT('<')) {
- if (Quiet)
- printf("%s", tmp);
- else {
- printf("%-34s <", tmp);
- if (Verbose)
- printf(" needs updating (%s has %s)", source, ver);
- }
- printf("\n");
- } else if (cmp == 0 && OUTPUT('=')) {
- if (Quiet)
- printf("%s", tmp);
- else {
- printf("%-34s =", tmp);
- if (Verbose)
- printf(" up-to-date with %s", source);
- }
- printf("\n");
- } else if (cmp > 0 && OUTPUT('>')) {
- if (Quiet)
- printf("%s", tmp);
- else {
- printf("%-34s >", tmp);
- if (Verbose)
- printf(" succeeds %s (%s has %s)", source, source, ver);
- }
- printf("\n");
- }
- }
-}
-
-int
-version_match(char *pattern, const char *pkgname)
-{
- int ret = 0;
- int matchstream = 0;
- FILE *fp = NULL;
- Boolean isTMP = FALSE;
-
- if (isURL(pkgname)) {
- fp = fetchGetURL(pkgname, "");
- isTMP = TRUE;
- matchstream = 1;
- if (fp == NULL)
- errx(2, "Unable to open %s.", pkgname);
- } else if (pkgname[0] == '/') {
- fp = fopen(pkgname, "r");
- isTMP = TRUE;
- matchstream = 1;
- if (fp == NULL)
- errx(2, "Unable to open %s.", pkgname);
- } else if (strcmp(pkgname, "-") == 0) {
- fp = stdin;
- matchstream = 1;
- } else if (isURL(pattern)) {
- fp = fetchGetURL(pattern, "");
- isTMP = TRUE;
- matchstream = -1;
- if (fp == NULL)
- errx(2, "Unable to open %s.", pattern);
- } else if (pattern[0] == '/') {
- fp = fopen(pattern, "r");
- isTMP = TRUE;
- matchstream = -1;
- if (fp == NULL)
- errx(2, "Unable to open %s.", pattern);
- } else if (strcmp(pattern, "-") == 0) {
- fp = stdin;
- matchstream = -1;
- } else {
- ret = pattern_match(MATCH_GLOB, pattern, pkgname);
- }
-
- if (fp != NULL) {
- size_t len;
- char *line;
- while ((line = fgetln(fp, &len)) != NULL) {
- int match;
- char *ch, ln[2048];
- size_t lnlen;
- if (len > 0 && line[len-1] == '\n')
- len --;
- lnlen = len;
- if (lnlen > sizeof(ln)-1)
- lnlen = sizeof(ln)-1;
- memcpy(ln, line, lnlen);
- ln[lnlen] = '\0';
- if ((ch = strchr(ln, '|')) != NULL)
- ch[0] = '\0';
- if (matchstream > 0)
- match = pattern_match(MATCH_GLOB, pattern, ln);
- else
- match = pattern_match(MATCH_GLOB, ln, pkgname);
- if (match == 1) {
- ret = 1;
- printf("%.*s\n", (int)len, line);
- }
- }
- if (isTMP)
- fclose(fp);
- }
-
- return ret;
-}
-
-void
-cleanup(int sig)
-{
- if (sig)
- exit(1);
-}
diff --git a/usr.sbin/pkg_install/version/pkg_version.1 b/usr.sbin/pkg_install/version/pkg_version.1
deleted file mode 100644
index 42f4bfc..0000000
--- a/usr.sbin/pkg_install/version/pkg_version.1
+++ /dev/null
@@ -1,263 +0,0 @@
-.\"
-.\" Copyright 1998 Bruce A. Mah
-.\"
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd May 18, 2013
-.Dt PKG_VERSION 1
-.Os
-.Sh NAME
-.Nm pkg_version
-.Nd summarize installed versions of packages
-.Sh SYNOPSIS
-.Nm
-.Op Fl hIoqv
-.Op Fl l Ar limchar
-.Op Fl L Ar limchar
-.Oo
-.Op Fl X
-.Fl s Ar string
-.Oc
-.Op Fl O Ar origin
-.Op Ar index
-.Nm
-.Fl t Ar version1 version2
-.Nm
-.Fl T Ar pkgname pattern
-.Sh DESCRIPTION
-The
-.Nm
-command is used to produce a report of non-base software packages
-installed using the
-.Xr pkg_add 1
-command.
-.Pp
-Each package's version number is checked against one of two sources to
-see if that package may require updating.
-If the package contains
-information about its origin in the
-.Fx
-ports tree, and a version number can be determined from the port's
-.Pa Makefile ,
-then the version number from the
-.Pa Makefile
-will be used to determine whether the installed package is up-to-date
-or requires updating.
-.Pp
-If no origin for a package can be found, or if the port's
-.Pa Makefile
-cannot be located,
-.Nm
-will search for the package in the ports collection index file
-(typically
-.Pa /usr/ports/INDEX-10 ) .
-Any matching version number(s) there will be used to determine whether
-the installed package is up-to-date or requires updating.
-.Pp
-Generally, using the version number from a port's
-.Pa Makefile
-will provide a more accurate result, since, unlike the index file, it
-provides an unambiguous current version number, even when multiple
-versions of a port exist in the ports collection.
-Moreover, the ports collection index file is only updated at
-intervals, meaning that it may not completely reflect the version
-numbers of the software contained in the ports collection.
-.Pp
-Each package name is printed, along with a one-character status flag:
-.Bl -tag -width indent
-.It Li =
-The installed version of the package is current.
-.It Li \&<
-The installed version of the package is older than the current version.
-.It Li \&>
-The installed version of the package is newer than the current version.
-This situation can arise with an out-of-date index file, or when
-testing new ports.
-.It Li \&?
-The installed package does not appear in the index.
-This could be due to an out of date index or a package taken from a PR
-that has not yet been committed.
-.It Li *
-There are multiple versions of a particular software package
-listed in the index file.
-Examples from the
-.Fx
-ports collection are the Tcl toolkit or the
-.Tn EMACS
-editor.
-.It Li \&!
-The installed package exists in the index but for some reason,
-.Nm
-was unable to compare the version number of the installed package
-with the corresponding entry in the index.
-.El
-.Sh OPTIONS
-The
-.Nm
-utility supports several command-line arguments:
-.Bl -tag -width indent
-.It Fl h , -help
-Print help message.
-.It Fl I , -index-only
-Use only the index file for determining if a package is out of date.
-This is much faster than using the version number from a port's
-Makefile, at the expense of potentially giving an incorrect result if
-the index file is out of date.
-.It Fl l , -status Ar limchar
-Limit the output to those packages whose status flag matches the
-character(s) in
-.Ar limchar .
-More than one character can be specified in
-.Ar limchar .
-Note that because some of the status flag characters are also special
-to the shell, it is best to quote
-.Ar limchar
-with single quotes.
-.It Fl L , -no-status Ar limchar
-Limit the output to those packages whose status flag does not match
-.Ar limchar .
-You may specify more than one character to match in
-.Ar limchar .
-Note that because some of the status flag characters are also special
-to the shell, it is best to quote
-.Ar limchar
-with single quotes.
-.It Fl o , -show-origin
-Show the origin recorded on package generation instead of the package
-name.
-.It Fl O , -origin Ar origin
-Only list packages whose registered origin is
-.Ar origin .
-.It Fl q , -quiet
-Enable quiet output.
-Quiet output precludes printing the
-.Ar limchar
-when used with
-.Fl l
-or
-.Fl L .
-This is useful when used as the input to
-.Xr portupgrade 8 .
-.It Fl s , -match Ar string
-Limit the output to those packages whose names match a given
-.Ar string .
-.It Fl X , -extended
-Interpret
-.Ar string
-as a extended regular expression.
-.It Fl t
-Test a pair of version number strings and exit.
-The output consists of one of the single characters
-.Li =
-(equal),
-.Li \&<
-(right-hand number greater), or
-.Li \&>
-(left-hand number greater) on standard output.
-This flag is mostly useful for scripts or for testing.
-.It Fl T
-Test whether
-.Ar pkgname
-is matched by
-.Ar pattern
-and set the exit code accordingly.
-.Fl T
-can also be used in `filter mode':
-When one of the arguments is `-', standard input is used, and lines
-with matching package names/patterns are echoed to standard output.
-.It Fl v
-Enable verbose output.
-Verbose output includes some English-text
-interpretations of the version number comparisons, as well as the
-version numbers compared for each package.
-Non-verbose output is
-probably easier for programs or scripts to parse.
-.It Ar index
-Specify the index to be used as a basis of comparison.
-This index can
-be specified as a filename (in the local file system) or a URL.
-Any
-URL understandable by
-.Xr fetch 1
-can be used here.
-If no
-.Ar index
-file is specified on the command line,
-.Pa /usr/ports/INDEX-10
-is used.
-.El
-.Sh FILES
-.Bl -tag -width /usr/ports/INDEX-10 -compact
-.It Pa /usr/ports/INDEX-10
-Default index file.
-.El
-.Sh EXAMPLES
-The following is a typical invocation of the
-.Nm
-command, which checks the installed packages against the local ports
-index file:
-.Pp
-.Dl % pkg_version -v
-.Pp
-The command below generates a report against
-the version numbers in the on-line ports collection:
-.Pp
-.Dl % pkg_version http://www.FreeBSD.org/ports/INDEX-10
-.Pp
-The following command compares two package version strings:
-.Pp
-.Dl % pkg_version -t 1.5 1.5.1
-.Sh COMPATIBILITY
-The
-.Fl c
-option has been deprecated and is no longer supported.
-.Sh ENVRIOMENT
-.Bl -tag -width indent
-.It Ev PKG_OLD_NOWARN
-If set
-.Nm
-will not warn about its use in the presence of pkgng databases.
-.El
-.Sh SEE ALSO
-.Xr fetch 1 ,
-.Xr pkg_add 1 ,
-.Xr pkg_create 1 ,
-.Xr pkg_delete 1 ,
-.Xr pkg_info 1 ,
-.Xr portupgrade 8
-.Sh AUTHORS
-The
-.Nm
-utility was written by
-.An Jeremy D. Lea Aq reg@FreeBSD.org ,
-partially based on a Perl script written by
-.An Bruce A. Mah Aq bmah@FreeBSD.org .
-.Sh CONTRIBUTORS
-.An Nik Clayton Aq nik@FreeBSD.org ,
-.An Dominic Mitchell Aq dom@palmerharvey.co.uk ,
-.An Mark Ovens Aq marko@FreeBSD.org ,
-.An Doug Barton Aq DougB@gorean.org ,
-.An Akinori MUSHA Aq knu@FreeBSD.org ,
-.An Oliver Eikemeier Aq eik@FreeBSD.org
diff --git a/usr.sbin/pkg_install/version/test-pkg_version.sh b/usr.sbin/pkg_install/version/test-pkg_version.sh
deleted file mode 100755
index 95486c1..0000000
--- a/usr.sbin/pkg_install/version/test-pkg_version.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/sh
-#
-# Copyright 2001 Bruce A. Mah
-#
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# test-pkg_version.sh
-#
-# Regression testing for pkg_version
-# Originally from an idea by "Akinori MUSHA" <knu@iDaemons.org>
-#
-# $FreeBSD$
-#
-
-ECHO=echo
-PKG_VERSION=./pkg_version
-
-test-pv ( ) { \
- setvar v1 $1
- setvar answer $2
- setvar v2 $3
- setvar type $4
- res=`${PKG_VERSION} -t ${v1} ${v2}`
- if [ ${res} != ${answer} ]; then \
- ${ECHO} "${type} test failed (${v1} ${res} ${v2}, should have been ${answer})"; \
- fi
-}
-
-# Test coercion of default PORTREVISION and PORTEPOCH
-test-pv 0.10 "=" 0.10_0 coercion
-test-pv 0.10 "=" 0.10,0 coercion
-test-pv 0.10 "=" 0.10_0,0 coercion
-
-# Test various comparisons
-test-pv 1.0 "=" 1.0 equality
-test-pv 2.15a "=" 2.15a equality
-
-test-pv 0.10 ">" 0.9 inequality
-test-pv 0.9 "<" 0.10 inequality
-
-test-pv 2.3p10 ">" 2.3p9 number/letter
-test-pv 1.6.0 ">" 1.6.0.p3 number/letter
-test-pv 1.0.b ">" 1.0.a3 number/letter
-test-pv 1.0a ">" 1.0 number/letter
-test-pv 1.0a "<" 1.0b number/letter
-test-pv 5.0a ">" 5.0.b number/letter
-
-test-pv 1.5_1 ">" 1.5 portrevision
-test-pv 1.5_2 ">" 1.5_1 portrevision
-test-pv 1.5_1 "<" 1.5.0.1 portrevision
-test-pv 1.5 "<" 1.5.0.1 portrevision
-
-test-pv 00.01.01,1 ">" 99.12.31 portepoch
-test-pv 0.0.1_1,2 ">" 0.0.1,2 portrevision/portepoch
-test-pv 0.0.1_1,3 ">" 0.0.1_2,2 portrevision/portepoch
-
-test-pv 2.0 ">" 2.a2 number/letter
-test-pv 3 "=" 3.0 equality
-test-pv 4a "<" 4a0 letter/zero
-test-pv 10a1b2 "=" 10a1.b2 separator
-
-test-pv 7pl "=" 7.pl patchevel
-test-pv 8.0.a "=" 8.0alpha alpha
-test-pv 9.b3.0 "=" 9beta3 beta
-test-pv 10.pre7 "=" 10pre7.0 pre
-test-pv 11.r "=" 11.rc rc
-
-test-pv 12pl "<" 12alpha alpha/patchevel
-test-pv 13.* "<" 13.pl star/patchevel
-
-test-pv 1.0.0+2003.09.06 "=" 1.0+2003.09.06 plus/multiple
-test-pv 1.0.1+2003.09.06 ">" 1.0+2003.09.06 plus/multiple
-test-pv 1.0.0+2003.09.06 "<" 1.0+2003.09.06_1 plus/portrevision
-test-pv 1.0.1+2003.09.06 ">" 1.0+2003.09.06_1 plus/portrevision
diff --git a/usr.sbin/pkg_install/version/version.h b/usr.sbin/pkg_install/version/version.h
deleted file mode 100644
index 1f265d4..0000000
--- a/usr.sbin/pkg_install/version/version.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * FreeBSD install - a package for the installation and maintenance
- * of non-core utilities.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Jeremy D. Lea.
- * 11 May 2002
- *
- * This is the version module. Based on pkg_version.pl by Bruce A. Mah.
- *
- */
-
-#ifndef _INST_VERSION_H_INCLUDE
-#define _INST_VERSION_H_INCLUDE
-
-struct index_entry {
- SLIST_ENTRY(index_entry) next;
- char *name;
- char *origin;
-};
-SLIST_HEAD(index_head, index_entry);
-
-extern char *LimitChars;
-extern char *PreventChars;
-extern char *MatchName;
-extern char *LookUpOrigin;
-extern Boolean RegexExtended;
-extern Boolean UseINDEXOnly;
-extern Boolean ShowOrigin;
-
-extern int version_match(char *, const char *);
-
-#endif /* _INST_VERSION_H_INCLUDE */
diff --git a/usr.sbin/pmcstat/Makefile b/usr.sbin/pmcstat/Makefile
index c27e56d..b8c8081 100644
--- a/usr.sbin/pmcstat/Makefile
+++ b/usr.sbin/pmcstat/Makefile
@@ -9,6 +9,7 @@ DPADD= ${LIBELF} ${LIBKVM} ${LIBPMC} ${LIBM} ${LIBNCURSES}
LDADD= -lelf -lkvm -lpmc -lm -lncurses
SRCS= pmcstat.c pmcstat.h pmcstat_log.c \
-pmcpl_callgraph.c pmcpl_gprof.c pmcpl_annotate.c pmcpl_calltree.c
+pmcpl_callgraph.c pmcpl_gprof.c pmcpl_annotate.c \
+pmcpl_annotate_cg.c pmcpl_calltree.c
.include <bsd.prog.mk>
diff --git a/usr.sbin/pmcstat/pmcpl_annotate_cg.c b/usr.sbin/pmcstat/pmcpl_annotate_cg.c
new file mode 100644
index 0000000..e90bda1
--- /dev/null
+++ b/usr.sbin/pmcstat/pmcpl_annotate_cg.c
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 2005-2007, Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
+ * Copyright (c) 2014, Adrian Chadd, Netflix Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Transform a hwpmc(4) log into human readable form, and into
+ * gprof(1) compatible profiles.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/gmon.h>
+#include <sys/imgact_aout.h>
+#include <sys/imgact_elf.h>
+#include <sys/mman.h>
+#include <sys/pmc.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <netinet/in.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libgen.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pmc.h>
+#include <pmclog.h>
+#include <sysexits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pmcstat.h"
+#include "pmcstat_log.h"
+#include "pmcpl_annotate_cg.h"
+
+/*
+ * Record a callchain.
+ */
+
+void
+pmcpl_annotate_cg_process(struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
+ uint32_t nsamples, uintfptr_t *cc, int usermode, uint32_t cpu)
+{
+ struct pmcstat_pcmap *map;
+ struct pmcstat_symbol *sym;
+ uintfptr_t newpc;
+ struct pmcstat_image *image;
+ int i;
+ char filename[PATH_MAX], funcname[PATH_MAX];
+ unsigned sline;
+
+ (void) pmcr; (void) nsamples; (void) usermode; (void) cpu;
+
+ for (i = 0; i < (int) nsamples; i++) {
+ map = NULL;
+ sym = NULL;
+ image = NULL;
+ filename[0] = '\0';
+ funcname[0] = '\0';
+ sline = 0;
+
+ map = pmcstat_process_find_map(usermode ? pp : pmcstat_kernproc, cc[i]);
+ if (map != NULL) {
+ assert(cc[i] >= map->ppm_lowpc && cc[i] < map->ppm_highpc);
+ image = map->ppm_image;
+ newpc = cc[i] - (map->ppm_lowpc +
+ (image->pi_vaddr - image->pi_start));
+ sym = pmcstat_symbol_search(image, newpc);
+ }
+
+ if (map != NULL && image != NULL && sym != NULL) {
+ (void) pmcstat_image_addr2line(image, cc[i],
+ filename, sizeof(filename), &sline, funcname, sizeof(funcname));
+ }
+
+ if (map != NULL && sym != NULL) {
+ fprintf(args.pa_graphfile, "%p %s %s:%d\n",
+ (void *)cc[i],
+ funcname,
+ filename,
+ sline);
+ } else {
+ fprintf(args.pa_graphfile, "%p <unknown> ??:0\n",
+ (void *) cc[i]);
+ }
+ }
+ fprintf(args.pa_graphfile, "--\n");
+}
diff --git a/usr.sbin/pkg_install/lib/pkgng.c b/usr.sbin/pmcstat/pmcpl_annotate_cg.h
index 3aba383..bd655f7 100644
--- a/usr.sbin/pkg_install/lib/pkgng.c
+++ b/usr.sbin/pmcstat/pmcpl_annotate_cg.h
@@ -1,7 +1,12 @@
/*-
- * Copyright (c) 2012 Eitan Adler
+ * Copyright (c) 2005-2007, Joseph Koshy
+ * Copyright (c) 2007 The FreeBSD Foundation
+ * Copyright (c) 2014, Adrian Chadd, Netflix Inc.
* All rights reserved.
*
+ * Portions of this software were developed by A. Joseph Koshy under
+ * sponsorship from the FreeBSD Foundation and Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -26,36 +31,12 @@
* $FreeBSD$
*/
-#include <sys/cdefs.h>
-
-#include "lib.h"
-#include <err.h>
-
-static const char message[] = "You appear to be using the newer pkg(1) tool on \
-this system for package management, rather than the legacy package \
-management tools (pkg_*). The legacy tools should no longer be used on \
-this system.";
-
-void warnpkgng(void)
-{
- char pkgngpath[MAXPATHLEN + 1];
- char *pkgngdir;
- char *dontwarn;
- int rc;
-
- dontwarn = getenv("PKG_OLD_NOWARN");
- if (dontwarn != NULL)
- return;
- pkgngdir = getenv("PKG_DBDIR");
- if (pkgngdir == NULL)
- pkgngdir = "/var/db/pkg";
+#ifndef _PMCSTAT_PL_ANNOTATE_CG_H_
+#define _PMCSTAT_PL_ANNOTATE_CG_H_
- rc = snprintf(pkgngpath, sizeof(pkgngpath), "%s/local.sqlite", pkgngdir);
- if ((size_t)rc >= sizeof(pkgngpath)) {
- warnx("path too long: %s/local.sqlite", pkgngdir);
- return;
- }
+/* Function prototypes */
+void pmcpl_annotate_cg_process(
+ struct pmcstat_process *pp, struct pmcstat_pmcrecord *pmcr,
+ uint32_t nsamples, uintfptr_t *cc, int usermode, uint32_t cpu);
- if (access(pkgngpath, F_OK) == 0)
- warnx(message);
-}
+#endif /* _PMCSTAT_PL_ANNOTATE_CG_H_ */
diff --git a/usr.sbin/pmcstat/pmcstat.c b/usr.sbin/pmcstat/pmcstat.c
index cc43b82..3edba3f 100644
--- a/usr.sbin/pmcstat/pmcstat.c
+++ b/usr.sbin/pmcstat/pmcstat.c
@@ -503,6 +503,7 @@ pmcstat_show_usage(void)
"\t -S spec\t allocate a system-wide sampling PMC\n"
"\t -T\t\t start in top mode\n"
"\t -W\t\t (toggle) show counts per context switch\n"
+ "\t -a <file>\t print sampled PCs and callgraph to \"file\"\n"
"\t -c cpu-list\t set cpus for subsequent system-wide PMCs\n"
"\t -d\t\t (toggle) track descendants\n"
"\t -f spec\t pass \"spec\" to as plugin option\n"
@@ -617,8 +618,14 @@ main(int argc, char **argv)
CPU_SET(hcpu, &cpumask);
while ((option = getopt(argc, argv,
- "CD:EF:G:M:NO:P:R:S:TWc:df:gk:m:n:o:p:qr:s:t:vw:z:")) != -1)
+ "CD:EF:G:M:NO:P:R:S:TWa:c:df:gk:m:n:o:p:qr:s:t:vw:z:")) != -1)
switch (option) {
+ case 'a': /* Annotate + callgraph */
+ args.pa_flags |= FLAG_DO_ANNOTATE;
+ args.pa_plugin = PMCSTAT_PL_ANNOTATE_CG;
+ graphfilename = optarg;
+ break;
+
case 'C': /* cumulative values */
use_cumulative_counts = !use_cumulative_counts;
args.pa_required |= FLAG_HAS_COUNTING_PMCS;
@@ -917,7 +924,8 @@ main(int argc, char **argv)
/* -m option is allowed with -R only. */
if (args.pa_flags & FLAG_DO_ANNOTATE && args.pa_inputpath == NULL)
- errx(EX_USAGE, "ERROR: option -m requires an input file");
+ errx(EX_USAGE, "ERROR: option %s requires an input file",
+ args.pa_plugin == PMCSTAT_PL_ANNOTATE ? "-m" : "-a");
/* -m option is not allowed combined with -g or -G. */
if (args.pa_flags & FLAG_DO_ANNOTATE &&
diff --git a/usr.sbin/pmcstat/pmcstat.h b/usr.sbin/pmcstat/pmcstat.h
index 6b64b76..c8ec14d 100644
--- a/usr.sbin/pmcstat/pmcstat.h
+++ b/usr.sbin/pmcstat/pmcstat.h
@@ -91,6 +91,7 @@
#define PMCSTAT_PL_GPROF 2
#define PMCSTAT_PL_ANNOTATE 3
#define PMCSTAT_PL_CALLTREE 4
+#define PMCSTAT_PL_ANNOTATE_CG 5
#define PMCSTAT_TOP_DELTA 0
#define PMCSTAT_TOP_ACCUM 1
diff --git a/usr.sbin/pmcstat/pmcstat_log.c b/usr.sbin/pmcstat/pmcstat_log.c
index fdcf9c4..f0e4939 100644
--- a/usr.sbin/pmcstat/pmcstat_log.c
+++ b/usr.sbin/pmcstat/pmcstat_log.c
@@ -149,6 +149,7 @@ struct pmcstat_process *pmcstat_kernproc; /* kernel 'process' */
#include "pmcpl_gprof.h"
#include "pmcpl_callgraph.h"
#include "pmcpl_annotate.h"
+#include "pmcpl_annotate_cg.h"
#include "pmcpl_calltree.h"
static struct pmc_plugins {
@@ -214,6 +215,11 @@ static struct pmc_plugins {
.pl_topdisplay = pmcpl_ct_topdisplay
},
{
+ .pl_name = "annotate_cg",
+ .pl_process = pmcpl_annotate_cg_process
+ },
+
+ {
.pl_name = NULL
}
};
diff --git a/usr.sbin/portsnap/make_index/Makefile b/usr.sbin/portsnap/make_index/Makefile
index 87768f6..92e9145 100644
--- a/usr.sbin/portsnap/make_index/Makefile
+++ b/usr.sbin/portsnap/make_index/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= make_index
-NO_MAN=
+MAN=
BINDIR= ${LIBEXECDIR}
diff --git a/usr.sbin/portsnap/phttpget/Makefile b/usr.sbin/portsnap/phttpget/Makefile
index 6f003e3..a43672f 100644
--- a/usr.sbin/portsnap/phttpget/Makefile
+++ b/usr.sbin/portsnap/phttpget/Makefile
@@ -1,7 +1,7 @@
# $FreeBSD$
PROG= phttpget
-NO_MAN=
+MAN=
BINDIR= ${LIBEXECDIR}
diff --git a/usr.sbin/portsnap/portsnap/portsnap.8 b/usr.sbin/portsnap/portsnap/portsnap.8
index baa1a57..0e9bd7e 100644
--- a/usr.sbin/portsnap/portsnap/portsnap.8
+++ b/usr.sbin/portsnap/portsnap/portsnap.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 14, 2012
+.Dd October 22, 2013
.Dt PORTSNAP 8
.Os FreeBSD
.Sh NAME
@@ -161,6 +161,18 @@ or
commands.
Again, note that in the parts of the ports tree which are being
updated, any local changes or additions will be removed.
+.It auto
+Run
+.Cm fetch
+or
+.Cm cron
+depending on whether stdin is a terminal; then run
+.Cm update
+or
+.Cm extract
+depending on whether
+.Ar portsdir
+exists.
.El
.Sh TIPS
.Bl -bullet
diff --git a/usr.sbin/portsnap/portsnap/portsnap.sh b/usr.sbin/portsnap/portsnap/portsnap.sh
index 14e5441..cba06d2 100644
--- a/usr.sbin/portsnap/portsnap/portsnap.sh
+++ b/usr.sbin/portsnap/portsnap/portsnap.sh
@@ -61,6 +61,8 @@ Commands:
files and directories.
update -- Update ports tree to match current snapshot, replacing
files and directories which have changed.
+ auto -- Fetch updates, and either extract a new ports tree or
+ update an existing tree.
EOF
exit 0
}
@@ -147,12 +149,15 @@ parse_cmdline() {
if [ ! -z "${SERVERNAME}" ]; then usage; fi
shift; SERVERNAME="$1"
;;
- cron | extract | fetch | update | alfred)
+ cron | extract | fetch | update | auto)
COMMANDS="${COMMANDS} $1"
;;
up)
COMMANDS="${COMMANDS} update"
;;
+ alfred)
+ COMMANDS="${COMMANDS} auto"
+ ;;
*)
if [ $# -gt 1 ]; then usage; fi
if echo ${COMMANDS} | grep -vq extract; then
@@ -362,7 +367,7 @@ fetch_pick_server_init() {
# "$name server selection ..."; we allow either format.
MLIST="_http._tcp.${SERVERNAME}"
host -t srv "${MLIST}" |
- sed -nE "s/${MLIST} (has SRV record|server selection) //p" |
+ sed -nE "s/${MLIST} (has SRV record|server selection) //Ip" |
cut -f 1,2,4 -d ' ' |
sed -e 's/\.$//' |
sort > serverlist_full
@@ -947,7 +952,7 @@ extract_run() {
cat ${WORKDIR}/INDEX
fi | while read FILE HASH; do
echo ${PORTSDIR}/${FILE}
- if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then
+ if ! [ -s "${WORKDIR}/files/${HASH}.gz" ]; then
echo "files/${HASH}.gz not found -- snapshot corrupt."
return 1
fi
@@ -991,7 +996,7 @@ update_run_extract() {
comm -13 ${PORTSDIR}/.portsnap.INDEX - |
while read FILE HASH; do
echo ${PORTSDIR}/${FILE}
- if ! [ -r "${WORKDIR}/files/${HASH}.gz" ]; then
+ if ! [ -s "${WORKDIR}/files/${HASH}.gz" ]; then
echo "files/${HASH}.gz not found -- snapshot corrupt."
return 1
fi
@@ -1104,10 +1109,10 @@ cmd_update() {
update_run || exit 1
}
-# Alfred command. Run 'fetch' or 'cron' depending on
+# Auto command. Run 'fetch' or 'cron' depending on
# whether stdin is a terminal; then run 'update' or
# 'extract' depending on whether ${PORTSDIR} exists.
-cmd_alfred() {
+cmd_auto() {
if [ "${INTERACTIVE}" = "YES" ]; then
cmd_fetch
else
diff --git a/usr.sbin/powerd/powerd.c b/usr.sbin/powerd/powerd.c
index 2c6eac2..3f628f6 100644
--- a/usr.sbin/powerd/powerd.c
+++ b/usr.sbin/powerd/powerd.c
@@ -279,6 +279,7 @@ static void
acline_init(void)
{
acline_mib_len = 4;
+ acline_status = SRC_UNKNOWN;
if (sysctlnametomib(ACPIAC, acline_mib, &acline_mib_len) == 0) {
acline_mode = ac_sysctl;
diff --git a/usr.sbin/ppp/chat.c b/usr.sbin/ppp/chat.c
index 04b2679..daa52cd 100644
--- a/usr.sbin/ppp/chat.c
+++ b/usr.sbin/ppp/chat.c
@@ -154,6 +154,11 @@ chat_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
else {
/* c->state = CHAT_EXPECT; */
c->argptr = &arg_term;
+ /*
+ We have to clear the input buffer, because it contains output
+ from the previous (timed out) command.
+ */
+ c->bufstart = c->bufend;
}
c->TimedOut = 0;
}
diff --git a/usr.sbin/ppp/mppe.c b/usr.sbin/ppp/mppe.c
index 141574f..f1fadc3 100644
--- a/usr.sbin/ppp/mppe.c
+++ b/usr.sbin/ppp/mppe.c
@@ -168,7 +168,7 @@ MPPEOutput(void *v, struct ccp *ccp, struct link *l __unused, int pri __unused,
dictinit = 0;
log_Printf(LogDEBUG, "MPPE: Output: Proto %02x (%d bytes)\n", *proto, ilen);
- if (*proto < 0x21 && *proto > 0xFA) {
+ if (*proto < 0x21 || *proto > 0xFA) {
log_Printf(LogDEBUG, "MPPE: Output: Not encrypting\n");
ccp->compout += ilen;
ccp->uncompout += ilen;
diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8
index 7358a48..c4ebe50 100644
--- a/usr.sbin/ppp/ppp.8
+++ b/usr.sbin/ppp/ppp.8
@@ -1188,7 +1188,6 @@ Use Hardware Handshake (CTS/RTS) for flow control.
.It
Modem should be set to NO echo back (ATE0) and NO results string (ATQ1).
.El
-.Pp
.It
Edit
.Pa /etc/ttys
@@ -1796,7 +1795,6 @@ If no timeout is given, the default timeout (set using
.Ic set timeout
and defaulting to 180 seconds) is used.
.El
-.Pp
.It
Each filter can hold up to 40 rules, starting from rule 0.
The entire rule set is not effective until rule 0 is defined,
@@ -2207,7 +2205,6 @@ ISPs IP number would be:
.Bd -literal -offset indent
set ifaddr 10.0.0.1/0 10.0.0.2/0 0.0.0.0 0.0.0.0
.Ed
-.Pp
.It
In most cases, your ISP will also be your default router.
If this is the case, add the line
@@ -3241,7 +3238,6 @@ not to make any utmp or wtmp entries.
This is usually only necessary if
you require the user to both login and authenticate themselves.
.El
-.Pp
.It add Ns Xo
.Op !\&
.Ar dest Ns Op / Ns Ar nn
@@ -3395,7 +3391,6 @@ When running in multi-link mode, a section can be loaded if it allows
.Em any
of the currently existing line modes.
.El
-.Pp
.It nat Ar command Op Ar args
This command allows the control of the network address translation (also
known as masquerading or IP aliasing) facilities that are built into
@@ -3584,7 +3579,6 @@ are 10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16.
These commands are also discussed in the file
.Pa README.nat
which comes with the source distribution.
-.Pp
.It Oo !\& Oc Ns Xo
.No bg Ar command
.Xc
@@ -3890,7 +3884,6 @@ mode, all interface addresses are deleted.
.Pp
If the INET or INET6 arguments are used, only addresses for that address
family are cleared.
-.Pp
.It iface delete Ns Xo
.Op !\& Ns
.No |rm Ns Op !\&
@@ -4392,7 +4385,6 @@ the connection.
This is required (in addition to one or more other callback
options) if you wish callback to be optional.
.El
-.Pp
.It set cbcp Oo
.No *| Ns Ar number Ns Oo
.No , Ns Ar number Ns ...\& Oc
@@ -5441,7 +5433,6 @@ This also applies for RADIUS routes that do not {include} the
or
.Dv HISADDR
keywords.
-.Pp
.It RAD_FRAMED_IPV6_PREFIX
If this attribute is supplied, the value is substituted for IPV6PREFIX
in a command.
@@ -5493,7 +5484,6 @@ also applies for RADIUS IPv6 routes that do not {include} the
or
.Dv HISADDR6
keywords.
-.Pp
.It RAD_SESSION_TIMEOUT
If supplied, the client connection is closed after the given number of
seconds.
@@ -5853,7 +5843,6 @@ and
.Ar 16
inclusive.
.El
-.Pp
.It shell|! Op Ar command
If
.Ar command
@@ -5933,7 +5922,6 @@ Show the active alarm timers.
Show the current version number of
.Nm .
.El
-.Pp
.It term
Go into terminal mode.
Characters typed at the keyboard are sent to the device.
@@ -5966,7 +5954,6 @@ http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/faq/ppp.html
.It
http://www.FreeBSD.org/doc/handbook/userppp.html
.El
-.Pp
.El
.Sh FILES
.Nm
diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c
index e7db97e..758b403 100644
--- a/usr.sbin/ppp/route.c
+++ b/usr.sbin/ppp/route.c
@@ -158,26 +158,16 @@ static struct bits {
{ RTF_MODIFIED, 'M' },
{ RTF_DONE, 'd' },
{ RTF_XRESOLVE, 'X' },
-#ifdef RTF_CLONING
- { RTF_CLONING, 'C' },
-#endif
{ RTF_STATIC, 'S' },
{ RTF_PROTO1, '1' },
{ RTF_PROTO2, '2' },
{ RTF_BLACKHOLE, 'B' },
-
#ifdef RTF_LLINFO
{ RTF_LLINFO, 'L' },
#endif
#ifdef RTF_CLONING
{ RTF_CLONING, 'C' },
#endif
-#ifdef RTF_WASCLONED
- { RTF_WASCLONED, 'W' },
-#endif
-#ifdef RTF_PRCLONING
- { RTF_PRCLONING, 'c' },
-#endif
#ifdef RTF_PROTO3
{ RTF_PROTO3, '3' },
#endif
@@ -187,10 +177,6 @@ static struct bits {
{ 0, '\0' }
};
-#ifndef RTF_WASCLONED
-#define RTF_WASCLONED (0)
-#endif
-
static void
p_flags(struct prompt *prompt, u_int32_t f, unsigned max)
{
@@ -434,7 +420,7 @@ route_IfDelete(struct bundle *bundle, int all)
* route X was cloned from route Y (and is no longer there 'cos it
* may have gone with route Y).
*/
- if (RTF_WASCLONED == 0 && pass == 0)
+ if (pass == 0)
/* So we can't tell ! */
continue;
for (cp = sp; cp < ep; cp += rtm->rtm_msglen) {
@@ -461,8 +447,7 @@ route_IfDelete(struct bundle *bundle, int all)
sa[RTAX_GATEWAY]->sa_family == AF_INET6 ||
#endif
sa[RTAX_GATEWAY]->sa_family == AF_LINK) {
- if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) ||
- (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) {
+ if (pass == 1) {
ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]);
rt_Set(bundle, RTM_DELETE, &range, NULL, 0, 0);
} else
diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h
index 1ff69a6..a1ed0c4 100644
--- a/usr.sbin/pw/pw.h
+++ b/usr.sbin/pw/pw.h
@@ -26,6 +26,7 @@
* $FreeBSD$
*/
+#define _WITH_GETLINE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/usr.sbin/pw/pw_conf.c b/usr.sbin/pw/pw_conf.c
index edeb015..1289b3e 100644
--- a/usr.sbin/pw/pw_conf.c
+++ b/usr.sbin/pw/pw_conf.c
@@ -226,35 +226,21 @@ newstr(char const * p)
struct userconf *
read_userconfig(char const * file)
{
- FILE *fp;
+ FILE *fp;
+ char *buf, *p;
+ size_t linecap;
+ ssize_t linelen;
+
+ buf = NULL;
+ linecap = 0;
extendarray(&config.groups, &config.numgroups, 200);
memset(config.groups, 0, config.numgroups * sizeof(char *));
if (file == NULL)
file = _PATH_PW_CONF;
- if ((fp = fopen(file, "r")) != NULL) {
- int buflen = LNBUFSZ;
- char *buf = malloc(buflen);
-
- nextline:
- while (fgets(buf, buflen, fp) != NULL) {
- char *p;
-
- while ((p = strchr(buf, '\n')) == NULL) {
- int l;
- if (extendline(&buf, &buflen, buflen + LNBUFSZ) == -1) {
- int ch;
- while ((ch = fgetc(fp)) != '\n' && ch != EOF);
- goto nextline; /* Ignore it */
- }
- l = strlen(buf);
- if (fgets(buf + l, buflen - l, fp) == NULL)
- break; /* Unterminated last line */
- }
-
- if (p != NULL)
- *p = '\0';
+ if ((fp = fopen(file, "r")) != NULL) {
+ while ((linelen = getline(&buf, &linecap, fp)) > 0) {
if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') {
static char const toks[] = " \t\r\n,=";
char *q = strtok(NULL, toks);
@@ -368,7 +354,8 @@ read_userconfig(char const * file)
}
}
}
- free(buf);
+ if (linecap > 0)
+ free(buf);
fclose(fp);
}
return &config;
diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c
index 3259412..391e477 100644
--- a/usr.sbin/pw/pw_group.c
+++ b/usr.sbin/pw/pw_group.c
@@ -227,10 +227,12 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
else if (arg->ch == 'm') {
int k = 0;
- while (grp->gr_mem[k] != NULL) {
- if (extendarray(&members, &grmembers, i + 2) != -1)
- members[i++] = grp->gr_mem[k];
- k++;
+ if (grp->gr_mem != NULL) {
+ while (grp->gr_mem[k] != NULL) {
+ if (extendarray(&members, &grmembers, i + 2) != -1)
+ members[i++] = grp->gr_mem[k];
+ k++;
+ }
}
}
@@ -311,6 +313,9 @@ delete_members(char ***members, int *grmembers, int *i, struct carg *arg,
int k;
struct passwd *pwd;
+ if (grp->gr_mem == NULL)
+ return;
+
k = 0;
while (grp->gr_mem[k] != NULL) {
matchFound = false;
@@ -415,8 +420,10 @@ print_group(struct group * grp, int pretty)
printf("Group Name: %-15s #%lu\n"
" Members: ",
grp->gr_name, (long) grp->gr_gid);
- for (i = 0; grp->gr_mem[i]; i++)
- printf("%s%s", i ? "," : "", grp->gr_mem[i]);
+ if (grp->gr_mem != NULL) {
+ for (i = 0; grp->gr_mem[i]; i++)
+ printf("%s%s", i ? "," : "", grp->gr_mem[i]);
+ }
fputs("\n\n", stdout);
}
return EXIT_SUCCESS;
diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c
index def238c..4b3f550 100644
--- a/usr.sbin/pw/pw_user.c
+++ b/usr.sbin/pw/pw_user.c
@@ -380,6 +380,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
char file[MAXPATHLEN];
char home[MAXPATHLEN];
uid_t uid = pwd->pw_uid;
+ struct group *gr;
+ char grname[LOGNAMESIZE];
if (strcmp(pwd->pw_name, "root") == 0)
errx(EX_DATAERR, "cannot remove user 'root'");
@@ -406,6 +408,11 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
*/
sprintf(file, "%s/%s", _PATH_MAILDIR, pwd->pw_name);
strlcpy(home, pwd->pw_dir, sizeof(home));
+ gr = GETGRGID(pwd->pw_gid);
+ if (gr != NULL)
+ strlcpy(grname, gr->gr_name, LOGNAMESIZE);
+ else
+ grname[0] = '\0';
rc = delpwent(pwd);
if (rc == -1)
@@ -425,19 +432,23 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
}
grp = GETGRNAM(a_name->val);
- if (grp != NULL && *grp->gr_mem == NULL)
+ if (grp != NULL &&
+ (grp->gr_mem == NULL || *grp->gr_mem == NULL) &&
+ strcmp(a_name->val, grname) == 0)
delgrent(GETGRNAM(a_name->val));
SETGRENT();
while ((grp = GETGRENT()) != NULL) {
int i;
char group[MAXLOGNAME];
- for (i = 0; grp->gr_mem[i] != NULL; i++) {
- if (!strcmp(grp->gr_mem[i], a_name->val)) {
- while (grp->gr_mem[i] != NULL) {
- grp->gr_mem[i] = grp->gr_mem[i+1];
- }
- strlcpy(group, grp->gr_name, MAXLOGNAME);
- chggrent(group, grp);
+ if (grp->gr_mem != NULL) {
+ for (i = 0; grp->gr_mem[i] != NULL; i++) {
+ if (!strcmp(grp->gr_mem[i], a_name->val)) {
+ while (grp->gr_mem[i] != NULL) {
+ grp->gr_mem[i] = grp->gr_mem[i+1];
+ }
+ strlcpy(group, grp->gr_name, MAXLOGNAME);
+ chggrent(group, grp);
+ }
}
}
}
@@ -908,7 +919,8 @@ pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer
errx(EX_NOUSER, "group `%s' is not defined", a_gid->val);
}
gid = grp->gr_gid;
- } else if ((grp = GETGRNAM(nam)) != NULL && grp->gr_mem[0] == NULL) {
+ } else if ((grp = GETGRNAM(nam)) != NULL &&
+ (grp->gr_mem == NULL || grp->gr_mem[0] == NULL)) {
gid = grp->gr_gid; /* Already created? Use it anyway... */
} else {
struct cargs grpargs;
@@ -1182,14 +1194,16 @@ print_user(struct passwd * pwd, int pretty, int v7)
while ((grp=GETGRENT()) != NULL)
{
int i = 0;
- while (grp->gr_mem[i] != NULL)
- {
- if (strcmp(grp->gr_mem[i], pwd->pw_name)==0)
+ if (grp->gr_mem != NULL) {
+ while (grp->gr_mem[i] != NULL)
{
- printf(j++ == 0 ? " Groups: %s" : ",%s", grp->gr_name);
- break;
+ if (strcmp(grp->gr_mem[i], pwd->pw_name)==0)
+ {
+ printf(j++ == 0 ? " Groups: %s" : ",%s", grp->gr_name);
+ break;
+ }
+ ++i;
}
- ++i;
}
}
ENDGRENT();
diff --git a/usr.sbin/pwd_mkdb/pwd_mkdb.8 b/usr.sbin/pwd_mkdb/pwd_mkdb.8
index 1265c59..209f06e 100644
--- a/usr.sbin/pwd_mkdb/pwd_mkdb.8
+++ b/usr.sbin/pwd_mkdb/pwd_mkdb.8
@@ -28,7 +28,7 @@
.\" @(#)pwd_mkdb.8 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
-.Dd February 28, 2005
+.Dd February 5, 2014
.Dt PWD_MKDB 8
.Os
.Sh NAME
@@ -143,6 +143,12 @@ The current password file.
.It Pa /etc/passwd
A Version 7 format password file.
.El
+.Sh EXAMPLES
+Regenerate the password database after manually editing or replacing
+the password file:
+.Bd -literal -offset -indent
+/usr/sbin/pwd_mkdb -p /etc/master.passwd
+.Ed
.Sh COMPATIBILITY
Previous versions of the system had a program similar to
.Nm ,
diff --git a/usr.sbin/route6d/route6d.c b/usr.sbin/route6d/route6d.c
index 421ac1a..fc45615 100644
--- a/usr.sbin/route6d/route6d.c
+++ b/usr.sbin/route6d/route6d.c
@@ -64,9 +64,7 @@ static const char _rcsid[] = "$KAME: route6d.c,v 1.104 2003/10/31 00:30:20 itoju
#include <sys/uio.h>
#include <net/if.h>
#include <net/if_var.h>
-#define _KERNEL 1
#include <net/route.h>
-#undef _KERNEL
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netinet/ip6.h>
@@ -1901,10 +1899,6 @@ rtrecv(void)
if (!rt_deladdr(ifcp, rta[RTAX_IFA], rta[RTAX_NETMASK]))
iface++;
break;
- case RTM_OLDADD:
- case RTM_OLDDEL:
- trace(1, "\tnot supported yet, ignored\n");
- break;
}
}
@@ -2467,17 +2461,9 @@ do { \
RTTYPE("REDIRECT", RTM_REDIRECT);
RTTYPE("MISS", RTM_MISS);
RTTYPE("LOCK", RTM_LOCK);
- RTTYPE("OLDADD", RTM_OLDADD);
- RTTYPE("OLDDEL", RTM_OLDDEL);
RTTYPE("NEWADDR", RTM_NEWADDR);
RTTYPE("DELADDR", RTM_DELADDR);
RTTYPE("IFINFO", RTM_IFINFO);
-#ifdef RTM_OLDADD
- RTTYPE("OLDADD", RTM_OLDADD);
-#endif
-#ifdef RTM_OLDDEL
- RTTYPE("OLDDEL", RTM_OLDDEL);
-#endif
#ifdef RTM_OIFINFO
RTTYPE("OIFINFO", RTM_OIFINFO);
#endif
@@ -2518,18 +2504,9 @@ do { \
#ifdef RTF_MASK
RTFLAG("m", RTF_MASK);
#endif
-#ifdef RTF_CLONING
- RTFLAG("C", RTF_CLONING);
-#endif
#ifdef RTF_CLONED
RTFLAG("c", RTF_CLONED);
#endif
-#ifdef RTF_PRCLONING
- RTFLAG("c", RTF_PRCLONING);
-#endif
-#ifdef RTF_WASCLONED
- RTFLAG("W", RTF_WASCLONED);
-#endif
RTFLAG("X", RTF_XRESOLVE);
#ifdef RTF_LLINFO
RTFLAG("L", RTF_LLINFO);
@@ -2585,9 +2562,6 @@ do { \
#ifdef IFF_NOTRAILERS
IFFLAG("NOTRAILERS", IFF_NOTRAILERS);
#endif
-#ifdef IFF_SMART
- IFFLAG("SMART", IFF_SMART);
-#endif
IFFLAG("RUNNING", IFF_RUNNING);
IFFLAG("NOARP", IFF_NOARP);
IFFLAG("PROMISC", IFF_PROMISC);
diff --git a/usr.sbin/rpc.lockd/kern.c b/usr.sbin/rpc.lockd/kern.c
index 4775ab6..759e147 100644
--- a/usr.sbin/rpc.lockd/kern.c
+++ b/usr.sbin/rpc.lockd/kern.c
@@ -97,8 +97,7 @@ nfslockdans(int vers, struct lockd_ans *ansp)
#define d_args (debug_level > 2)
static const char *
-from_addr(saddr)
- struct sockaddr *saddr;
+from_addr(struct sockaddr *saddr)
{
static char inet_buf[INET6_ADDRSTRLEN];
@@ -231,9 +230,7 @@ err:
}
void
-set_auth(cl, xucred)
- CLIENT *cl;
- struct xucred *xucred;
+set_auth(CLIENT *cl, struct xucred *xucred)
{
int ngroups;
diff --git a/usr.sbin/rpc.lockd/lock_proc.c b/usr.sbin/rpc.lockd/lock_proc.c
index 0449664..8884ad9 100644
--- a/usr.sbin/rpc.lockd/lock_proc.c
+++ b/usr.sbin/rpc.lockd/lock_proc.c
@@ -76,9 +76,7 @@ static int addrcmp(struct sockaddr *, struct sockaddr *);
* passed in as part of the called procedure specification
*/
static void
-log_from_addr(fun_name, req)
- const char *fun_name;
- struct svc_req *req;
+log_from_addr(const char *fun_name, struct svc_req *req)
{
struct sockaddr *addr;
char hostname_buf[NI_MAXHOST];
@@ -99,8 +97,7 @@ log_from_addr(fun_name, req)
* a debug subsystem.
*/
static void
-log_netobj(obj)
- netobj *obj;
+log_netobj(netobj *obj)
{
char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2];
char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1];
@@ -161,9 +158,7 @@ static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE];
static int clnt_cache_next_to_use = 0;
static int
-addrcmp(sa1, sa2)
- struct sockaddr *sa1;
- struct sockaddr *sa2;
+addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
{
int len;
void *p1, *p2;
@@ -190,9 +185,7 @@ addrcmp(sa1, sa2)
}
CLIENT *
-get_client(host_addr, vers)
- struct sockaddr *host_addr;
- rpcvers_t vers;
+get_client(struct sockaddr *host_addr, rpcvers_t vers)
{
CLIENT *client;
struct timeval retry_time, time_now;
@@ -327,10 +320,7 @@ get_client(host_addr, vers)
* without expecting a result
*/
void
-transmit_result(opcode, result, addr)
- int opcode;
- nlm_res *result;
- struct sockaddr *addr;
+transmit_result(int opcode, nlm_res *result, struct sockaddr *addr)
{
static char dummy;
CLIENT *cli;
@@ -358,10 +348,7 @@ transmit_result(opcode, result, addr)
* without expecting a result
*/
void
-transmit4_result(opcode, result, addr)
- int opcode;
- nlm4_res *result;
- struct sockaddr *addr;
+transmit4_result(int opcode, nlm4_res *result, struct sockaddr *addr)
{
static char dummy;
CLIENT *cli;
@@ -385,11 +372,8 @@ transmit4_result(opcode, result, addr)
/*
* converts a struct nlm_lock to struct nlm4_lock
*/
-static void nlmtonlm4(struct nlm_lock *, struct nlm4_lock *);
static void
-nlmtonlm4(arg, arg4)
- struct nlm_lock *arg;
- struct nlm4_lock *arg4;
+nlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4)
{
arg4->caller_name = arg->caller_name;
arg4->fh = arg->fh;
@@ -432,9 +416,7 @@ nlmtonlm4(arg, arg4)
* Notes:
*/
nlm_testres *
-nlm_test_1_svc(arg, rqstp)
- nlm_testargs *arg;
- struct svc_req *rqstp;
+nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
{
static nlm_testres res;
struct nlm4_lock arg4;
@@ -466,9 +448,7 @@ nlm_test_1_svc(arg, rqstp)
}
void *
-nlm_test_msg_1_svc(arg, rqstp)
- nlm_testargs *arg;
- struct svc_req *rqstp;
+nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
{
nlm_testres res;
static char dummy;
@@ -523,9 +503,7 @@ nlm_test_msg_1_svc(arg, rqstp)
* Notes: *** grace period support missing
*/
nlm_res *
-nlm_lock_1_svc(arg, rqstp)
- nlm_lockargs *arg;
- struct svc_req *rqstp;
+nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
struct nlm4_lockargs arg4;
@@ -547,9 +525,7 @@ nlm_lock_1_svc(arg, rqstp)
}
void *
-nlm_lock_msg_1_svc(arg, rqstp)
- nlm_lockargs *arg;
- struct svc_req *rqstp;
+nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
struct nlm4_lockargs arg4;
@@ -578,9 +554,7 @@ nlm_lock_msg_1_svc(arg, rqstp)
* Notes:
*/
nlm_res *
-nlm_cancel_1_svc(arg, rqstp)
- nlm_cancargs *arg;
- struct svc_req *rqstp;
+nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
struct nlm4_lock arg4;
@@ -602,9 +576,7 @@ nlm_cancel_1_svc(arg, rqstp)
}
void *
-nlm_cancel_msg_1_svc(arg, rqstp)
- nlm_cancargs *arg;
- struct svc_req *rqstp;
+nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
struct nlm4_lock arg4;
@@ -633,9 +605,7 @@ nlm_cancel_msg_1_svc(arg, rqstp)
* re-try an unlock that has already succeeded.
*/
nlm_res *
-nlm_unlock_1_svc(arg, rqstp)
- nlm_unlockargs *arg;
- struct svc_req *rqstp;
+nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
struct nlm4_lock arg4;
@@ -652,9 +622,7 @@ nlm_unlock_1_svc(arg, rqstp)
}
void *
-nlm_unlock_msg_1_svc(arg, rqstp)
- nlm_unlockargs *arg;
- struct svc_req *rqstp;
+nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
struct nlm4_lock arg4;
@@ -690,9 +658,7 @@ nlm_unlock_msg_1_svc(arg, rqstp)
* Notes:
*/
nlm_res *
-nlm_granted_1_svc(arg, rqstp)
- nlm_testargs *arg;
- struct svc_req *rqstp;
+nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
@@ -710,9 +676,7 @@ nlm_granted_1_svc(arg, rqstp)
}
void *
-nlm_granted_msg_1_svc(arg, rqstp)
- nlm_testargs *arg;
- struct svc_req *rqstp;
+nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
@@ -734,9 +698,7 @@ nlm_granted_msg_1_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm_test_res_1_svc(arg, rqstp)
- nlm_testres *arg;
- struct svc_req *rqstp;
+nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm_test_res", rqstp);
@@ -751,9 +713,7 @@ nlm_test_res_1_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm_lock_res_1_svc(arg, rqstp)
- nlm_res *arg;
- struct svc_req *rqstp;
+nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm_lock_res", rqstp);
@@ -769,9 +729,7 @@ nlm_lock_res_1_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm_cancel_res_1_svc(arg, rqstp)
- nlm_res *arg __unused;
- struct svc_req *rqstp;
+nlm_cancel_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm_cancel_res", rqstp);
@@ -784,9 +742,7 @@ nlm_cancel_res_1_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm_unlock_res_1_svc(arg, rqstp)
- nlm_res *arg;
- struct svc_req *rqstp;
+nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm_unlock_res", rqstp);
@@ -802,9 +758,7 @@ nlm_unlock_res_1_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm_granted_res_1_svc(arg, rqstp)
- nlm_res *arg __unused;
- struct svc_req *rqstp;
+nlm_granted_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm_granted_res", rqstp);
@@ -827,9 +781,7 @@ nlm_granted_res_1_svc(arg, rqstp)
* to retry if required.
*/
nlm_shareres *
-nlm_share_3_svc(arg, rqstp)
- nlm_shareargs *arg;
- struct svc_req *rqstp;
+nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
{
static nlm_shareres res;
@@ -849,9 +801,7 @@ nlm_share_3_svc(arg, rqstp)
* Notes:
*/
nlm_shareres *
-nlm_unshare_3_svc(arg, rqstp)
- nlm_shareargs *arg;
- struct svc_req *rqstp;
+nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
{
static nlm_shareres res;
@@ -875,9 +825,7 @@ nlm_unshare_3_svc(arg, rqstp)
* respond to the statd protocol.
*/
nlm_res *
-nlm_nm_lock_3_svc(arg, rqstp)
- nlm_lockargs *arg;
- struct svc_req *rqstp;
+nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
{
static nlm_res res;
@@ -901,9 +849,7 @@ nlm_nm_lock_3_svc(arg, rqstp)
* using monitored locks.
*/
void *
-nlm_free_all_3_svc(arg, rqstp)
- nlm_notify *arg __unused;
- struct svc_req *rqstp;
+nlm_free_all_3_svc(nlm_notify *arg __unused, struct svc_req *rqstp)
{
static char dummy;
@@ -920,9 +866,7 @@ nlm_free_all_3_svc(arg, rqstp)
* Notes:
*/
nlm4_testres *
-nlm4_test_4_svc(arg, rqstp)
- nlm4_testargs *arg;
- struct svc_req *rqstp;
+nlm4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
{
static nlm4_testres res;
struct nlm4_holder *holder;
@@ -968,9 +912,7 @@ nlm4_test_4_svc(arg, rqstp)
}
void *
-nlm4_test_msg_4_svc(arg, rqstp)
- nlm4_testargs *arg;
- struct svc_req *rqstp;
+nlm4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
{
nlm4_testres res;
static char dummy;
@@ -1020,9 +962,7 @@ nlm4_test_msg_4_svc(arg, rqstp)
* Notes: *** grace period support missing
*/
nlm4_res *
-nlm4_lock_4_svc(arg, rqstp)
- nlm4_lockargs *arg;
- struct svc_req *rqstp;
+nlm4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1056,9 +996,7 @@ nlm4_lock_4_svc(arg, rqstp)
}
void *
-nlm4_lock_msg_4_svc(arg, rqstp)
- nlm4_lockargs *arg;
- struct svc_req *rqstp;
+nlm4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1079,9 +1017,7 @@ nlm4_lock_msg_4_svc(arg, rqstp)
* Notes:
*/
nlm4_res *
-nlm4_cancel_4_svc(arg, rqstp)
- nlm4_cancargs *arg;
- struct svc_req *rqstp;
+nlm4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1100,9 +1036,7 @@ nlm4_cancel_4_svc(arg, rqstp)
}
void *
-nlm4_cancel_msg_4_svc(arg, rqstp)
- nlm4_cancargs *arg;
- struct svc_req *rqstp;
+nlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1128,9 +1062,7 @@ nlm4_cancel_msg_4_svc(arg, rqstp)
* re-try an unlock that has already succeeded.
*/
nlm4_res *
-nlm4_unlock_4_svc(arg, rqstp)
- nlm4_unlockargs *arg;
- struct svc_req *rqstp;
+nlm4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1144,9 +1076,7 @@ nlm4_unlock_4_svc(arg, rqstp)
}
void *
-nlm4_unlock_msg_4_svc(arg, rqstp)
- nlm4_unlockargs *arg;
- struct svc_req *rqstp;
+nlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1179,9 +1109,7 @@ nlm4_unlock_msg_4_svc(arg, rqstp)
* Notes:
*/
nlm4_res *
-nlm4_granted_4_svc(arg, rqstp)
- nlm4_testargs *arg;
- struct svc_req *rqstp;
+nlm4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1199,9 +1127,7 @@ nlm4_granted_4_svc(arg, rqstp)
}
void *
-nlm4_granted_msg_4_svc(arg, rqstp)
- nlm4_testargs *arg;
- struct svc_req *rqstp;
+nlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1222,9 +1148,7 @@ nlm4_granted_msg_4_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm4_test_res_4_svc(arg, rqstp)
- nlm4_testres *arg;
- struct svc_req *rqstp;
+nlm4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm4_test_res", rqstp);
@@ -1241,9 +1165,7 @@ nlm4_test_res_4_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm4_lock_res_4_svc(arg, rqstp)
- nlm4_res *arg;
- struct svc_req *rqstp;
+nlm4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm4_lock_res", rqstp);
@@ -1259,9 +1181,7 @@ nlm4_lock_res_4_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm4_cancel_res_4_svc(arg, rqstp)
- nlm4_res *arg __unused;
- struct svc_req *rqstp;
+nlm4_cancel_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm4_cancel_res", rqstp);
@@ -1274,9 +1194,7 @@ nlm4_cancel_res_4_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm4_unlock_res_4_svc(arg, rqstp)
- nlm4_res *arg __unused;
- struct svc_req *rqstp;
+nlm4_unlock_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm4_unlock_res", rqstp);
@@ -1289,9 +1207,7 @@ nlm4_unlock_res_4_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm4_granted_res_4_svc(arg, rqstp)
- nlm4_res *arg __unused;
- struct svc_req *rqstp;
+nlm4_granted_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
{
if (debug_level)
log_from_addr("nlm4_granted_res", rqstp);
@@ -1314,9 +1230,7 @@ nlm4_granted_res_4_svc(arg, rqstp)
* to retry if required.
*/
nlm4_shareres *
-nlm4_share_4_svc(arg, rqstp)
- nlm4_shareargs *arg;
- struct svc_req *rqstp;
+nlm4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
{
static nlm4_shareres res;
@@ -1336,9 +1250,7 @@ nlm4_share_4_svc(arg, rqstp)
* Notes:
*/
nlm4_shareres *
-nlm4_unshare_4_svc(arg, rqstp)
- nlm4_shareargs *arg;
- struct svc_req *rqstp;
+nlm4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
{
static nlm4_shareres res;
@@ -1362,9 +1274,7 @@ nlm4_unshare_4_svc(arg, rqstp)
* respond to the statd protocol.
*/
nlm4_res *
-nlm4_nm_lock_4_svc(arg, rqstp)
- nlm4_lockargs *arg;
- struct svc_req *rqstp;
+nlm4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
{
static nlm4_res res;
@@ -1388,9 +1298,7 @@ nlm4_nm_lock_4_svc(arg, rqstp)
* using monitored locks.
*/
void *
-nlm4_free_all_4_svc(arg, rqstp)
- struct nlm4_notify *arg __unused;
- struct svc_req *rqstp;
+nlm4_free_all_4_svc(struct nlm4_notify *arg __unused, struct svc_req *rqstp)
{
static char dummy;
@@ -1405,9 +1313,7 @@ nlm4_free_all_4_svc(arg, rqstp)
* Returns: Nothing
*/
void *
-nlm_sm_notify_0_svc(arg, rqstp)
- struct nlm_sm_status *arg;
- struct svc_req *rqstp __unused;
+nlm_sm_notify_0_svc(struct nlm_sm_status *arg, struct svc_req *rqstp __unused)
{
static char dummy;
notify(arg->mon_name, arg->state);
diff --git a/usr.sbin/rpc.lockd/lockd.c b/usr.sbin/rpc.lockd/lockd.c
index b3402ff..2974acb 100644
--- a/usr.sbin/rpc.lockd/lockd.c
+++ b/usr.sbin/rpc.lockd/lockd.c
@@ -101,10 +101,6 @@ static void complete_service(struct netconfig *nconf, char *port_str);
static void clearout_service(void);
void lookup_addresses(struct netconfig *nconf);
void init_nsm(void);
-void nlm_prog_0(struct svc_req *, SVCXPRT *);
-void nlm_prog_1(struct svc_req *, SVCXPRT *);
-void nlm_prog_3(struct svc_req *, SVCXPRT *);
-void nlm_prog_4(struct svc_req *, SVCXPRT *);
void out_of_mem(void);
void usage(void);
@@ -228,7 +224,7 @@ main(int argc, char **argv)
if (hosts == NULL)
out_of_mem();
- hosts[0] = "*";
+ hosts[0] = strdup("*");
nhosts = 1;
} else {
hosts_bak = hosts;
@@ -244,7 +240,7 @@ main(int argc, char **argv)
hosts = hosts_bak;
nhosts += 2;
- hosts[nhosts - 2] = "::1";
+ hosts[nhosts - 2] = strdup("::1");
} else {
hosts_bak = realloc(hosts, (nhosts + 1) * sizeof(char *));
if (hosts_bak == NULL) {
@@ -258,7 +254,7 @@ main(int argc, char **argv)
hosts = hosts_bak;
}
}
- hosts[nhosts - 1] = "127.0.0.1";
+ hosts[nhosts - 1] = strdup("127.0.0.1");
}
if (kernel_lockd) {
diff --git a/usr.sbin/rpc.lockd/rpc.lockd.8 b/usr.sbin/rpc.lockd/rpc.lockd.8
index 4fabe5d..763a163 100644
--- a/usr.sbin/rpc.lockd/rpc.lockd.8
+++ b/usr.sbin/rpc.lockd/rpc.lockd.8
@@ -11,11 +11,7 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
diff --git a/usr.sbin/rpc.statd/rpc.statd.8 b/usr.sbin/rpc.statd/rpc.statd.8
index 5b53ff1..32559ad 100644
--- a/usr.sbin/rpc.statd/rpc.statd.8
+++ b/usr.sbin/rpc.statd/rpc.statd.8
@@ -11,11 +11,7 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
diff --git a/usr.sbin/rpc.ypupdated/Makefile b/usr.sbin/rpc.ypupdated/Makefile
index ffef7d4..03c1142 100644
--- a/usr.sbin/rpc.ypupdated/Makefile
+++ b/usr.sbin/rpc.ypupdated/Makefile
@@ -3,7 +3,7 @@
.PATH: ${.CURDIR}/../ypserv ${.CURDIR}/../../libexec/ypxfr
PROG= rpc.ypupdated
-NO_MAN=
+MAN=
SRCS= ypupdate_prot_svc.c ypupdate_prot.h ypupdated_main.c \
yp_error.c update.c ypupdated_server.c \
yp_dblookup.c yp_dbwrite.c yp_dbdelete.c yp_dbupdate.c
diff --git a/usr.sbin/rpcbind/check_bound.c b/usr.sbin/rpcbind/check_bound.c
index 35e0a5a..3691f5f 100644
--- a/usr.sbin/rpcbind/check_bound.c
+++ b/usr.sbin/rpcbind/check_bound.c
@@ -1,33 +1,32 @@
/* $NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $ */
/* $FreeBSD$ */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
diff --git a/usr.sbin/rpcbind/pmap_svc.c b/usr.sbin/rpcbind/pmap_svc.c
index 5df3097..d20f18f 100644
--- a/usr.sbin/rpcbind/pmap_svc.c
+++ b/usr.sbin/rpcbind/pmap_svc.c
@@ -1,33 +1,32 @@
/* $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ */
/* $FreeBSD$ */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
diff --git a/usr.sbin/rpcbind/rpcb_stat.c b/usr.sbin/rpcbind/rpcb_stat.c
index 3061754..fd92d78 100644
--- a/usr.sbin/rpcbind/rpcb_stat.c
+++ b/usr.sbin/rpcbind/rpcb_stat.c
@@ -2,33 +2,32 @@
* $NetBSD: rpcb_stat.c,v 1.2 2000/07/04 20:27:40 matt Exp $
* $FreeBSD$
*/
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/* #pragma ident "@(#)rpcb_stat.c 1.7 94/04/25 SMI" */
diff --git a/usr.sbin/rpcbind/rpcb_svc.c b/usr.sbin/rpcbind/rpcb_svc.c
index 9ed05347..7aa5393 100644
--- a/usr.sbin/rpcbind/rpcb_svc.c
+++ b/usr.sbin/rpcbind/rpcb_svc.c
@@ -1,33 +1,32 @@
/* $NetBSD: rpcb_svc.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $ */
/* $FreeBSD$ */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
diff --git a/usr.sbin/rpcbind/rpcb_svc_4.c b/usr.sbin/rpcbind/rpcb_svc_4.c
index 86bfc08..852abaf 100644
--- a/usr.sbin/rpcbind/rpcb_svc_4.c
+++ b/usr.sbin/rpcbind/rpcb_svc_4.c
@@ -3,33 +3,32 @@
* $FreeBSD$
*/
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
diff --git a/usr.sbin/rpcbind/rpcb_svc_com.c b/usr.sbin/rpcbind/rpcb_svc_com.c
index f90dc59..a362c85 100644
--- a/usr.sbin/rpcbind/rpcb_svc_com.c
+++ b/usr.sbin/rpcbind/rpcb_svc_com.c
@@ -1,33 +1,32 @@
/* $NetBSD: rpcb_svc_com.c,v 1.9 2002/11/08 00:16:39 fvdl Exp $ */
/* $FreeBSD$ */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
diff --git a/usr.sbin/rpcbind/rpcbind.8 b/usr.sbin/rpcbind/rpcbind.8
index 0ecf895..0df1fd0 100644
--- a/usr.sbin/rpcbind/rpcbind.8
+++ b/usr.sbin/rpcbind/rpcbind.8
@@ -2,7 +2,7 @@
.\" Copyright 1989 AT&T
.\" Copyright 1991 Sun Microsystems, Inc.
.\" $FreeBSD$
-.Dd April 23, 2007
+.Dd March 6, 2014
.Dt RPCBIND 8
.Os
.Sh NAME
@@ -133,6 +133,8 @@ to use non-privileged ports for outgoing connections, preventing non-privileged
clients from using
.Nm
to connect to services from a privileged port.
+.It Fl W
+Enable libwrap (TCP wrappers) support.
.El
.Sh NOTES
All RPC servers must be restarted if
diff --git a/usr.sbin/rpcbind/rpcbind.c b/usr.sbin/rpcbind/rpcbind.c
index fb6c99d..67c7f7b 100644
--- a/usr.sbin/rpcbind/rpcbind.c
+++ b/usr.sbin/rpcbind/rpcbind.c
@@ -1,33 +1,32 @@
/* $NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $ */
/* $FreeBSD$ */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
@@ -89,6 +88,9 @@ rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
int runasdaemon = 0;
int insecure = 0;
int oldstyle_local = 0;
+#ifdef LIBWRAP
+int libwrap = 0;
+#endif
int verboselog = 0;
char **hosts = NULL;
@@ -786,7 +788,12 @@ parseargs(int argc, char *argv[])
#else
#define WSOP ""
#endif
- while ((c = getopt(argc, argv, "6adh:iLls" WSOP)) != -1) {
+#ifdef LIBWRAP
+#define WRAPOP "W"
+#else
+#define WRAPOP ""
+#endif
+ while ((c = getopt(argc, argv, "6adh:iLls" WRAPOP WSOP)) != -1) {
switch (c) {
case '6':
ipv6_only = 1;
@@ -819,6 +826,11 @@ parseargs(int argc, char *argv[])
case 's':
runasdaemon = 1;
break;
+#ifdef LIBWRAP
+ case 'W':
+ libwrap = 1;
+ break;
+#endif
#ifdef WARMSTART
case 'w':
warmstart = 1;
@@ -826,8 +838,8 @@ parseargs(int argc, char *argv[])
#endif
default: /* error */
fprintf(stderr,
- "usage: rpcbind [-6adiLls%s] [-h bindip]\n",
- WSOP);
+ "usage: rpcbind [-6adiLls%s%s] [-h bindip]\n",
+ WRAPOP, WSOP);
exit (1);
}
}
diff --git a/usr.sbin/rpcbind/rpcbind.h b/usr.sbin/rpcbind/rpcbind.h
index 717bb3b..4aba420 100644
--- a/usr.sbin/rpcbind/rpcbind.h
+++ b/usr.sbin/rpcbind/rpcbind.h
@@ -1,33 +1,32 @@
/* $NetBSD: rpcbind.h,v 1.1 2000/06/03 00:47:21 fvdl Exp $ */
/* $FreeBSD$ */
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
@@ -67,6 +66,9 @@ struct r_rmtcall_args {
extern int debugging;
extern int doabort;
+#ifdef LIBWRAP
+extern int libwrap;
+#endif
extern int verboselog;
extern int insecure;
extern int oldstyle_local;
diff --git a/usr.sbin/rpcbind/security.c b/usr.sbin/rpcbind/security.c
index 8657247..2cff10a 100644
--- a/usr.sbin/rpcbind/security.c
+++ b/usr.sbin/rpcbind/security.c
@@ -108,13 +108,15 @@ check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, unsigned int rpcbvers)
}
#ifdef LIBWRAP
- if (addr->sa_family == AF_LOCAL)
- return 1;
- request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
- sock_methods(&req);
- if(!hosts_access(&req)) {
- logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
- return 0;
+ if (libwrap && addr->sa_family != AF_LOCAL) {
+ request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr,
+ 0);
+ sock_methods(&req);
+ if(!hosts_access(&req)) {
+ logit(deny_severity, addr, proc, prog,
+ ": request from unauthorized host");
+ return 0;
+ }
}
#endif
if (verboselog)
diff --git a/usr.sbin/rpcbind/warmstart.c b/usr.sbin/rpcbind/warmstart.c
index fc0956f..473b6f7 100644
--- a/usr.sbin/rpcbind/warmstart.c
+++ b/usr.sbin/rpcbind/warmstart.c
@@ -1,30 +1,29 @@
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
/*
* warmstart.c
diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c
index 87a4166..30a4ae8 100644
--- a/usr.sbin/rwhod/rwhod.c
+++ b/usr.sbin/rwhod/rwhod.c
@@ -43,7 +43,7 @@ static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/capability.h>
+#include <sys/capsicum.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
@@ -281,7 +281,7 @@ main(int argc, char *argv[])
} else if (pid_child_receiver == -1) {
if (errno == ENOSYS) {
syslog(LOG_ERR,
- "The pdfork(2) system call is not available; recompile the kernel with options PROCDESC");
+ "The pdfork(2) system call is not available - kernel too old.");
} else {
syslog(LOG_ERR, "pdfork: %m");
}
diff --git a/usr.sbin/sa/Makefile b/usr.sbin/sa/Makefile
index 0adf1f8..23f9bf2 100644
--- a/usr.sbin/sa/Makefile
+++ b/usr.sbin/sa/Makefile
@@ -1,9 +1,15 @@
# $FreeBSD$
+.include <bsd.own.mk>
+
.PATH: ${.CURDIR}/../../usr.bin/lastcomm
PROG= sa
MAN= sa.8
SRCS= main.c db.c pdb.c usrdb.c readrec.c
+.if ${MK_TESTS} != "no"
+SUBDIR+= tests
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/sa/tests/Makefile b/usr.sbin/sa/tests/Makefile
new file mode 100644
index 0000000..204b510
--- /dev/null
+++ b/usr.sbin/sa/tests/Makefile
@@ -0,0 +1,33 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/usr.sbin/sa
+
+TAP_TESTS_SH= legacy_test
+
+FILESDIR= ${TESTSDIR}
+FILES= v1-amd64-sav.in
+FILES+= v1-amd64-sav.out
+FILES+= v1-amd64-u.out
+FILES+= v1-amd64-usr.in
+FILES+= v1-amd64-usr.out
+FILES+= v1-i386-sav.in
+FILES+= v1-i386-sav.out
+FILES+= v1-i386-u.out
+FILES+= v1-i386-usr.in
+FILES+= v1-i386-usr.out
+FILES+= v1-sparc64-sav.in
+FILES+= v1-sparc64-sav.out
+FILES+= v1-sparc64-u.out
+FILES+= v1-sparc64-usr.in
+FILES+= v1-sparc64-usr.out
+FILES+= v2-amd64-sav.in
+FILES+= v2-amd64-u.out
+FILES+= v2-amd64-usr.in
+FILES+= v2-i386-sav.in
+FILES+= v2-i386-u.out
+FILES+= v2-i386-usr.in
+FILES+= v2-sparc64-sav.in
+FILES+= v2-sparc64-u.out
+FILES+= v2-sparc64-usr.in
+
+.include <bsd.test.mk>
diff --git a/usr.sbin/sa/tests/legacy_test.sh b/usr.sbin/sa/tests/legacy_test.sh
new file mode 100644
index 0000000..d0d8f42
--- /dev/null
+++ b/usr.sbin/sa/tests/legacy_test.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+DIR=`dirname $0`
+LCDIR=`dirname $0`/../../usr.bin/lastcomm
+ARCH=`uname -m`
+
+collapse_whitespace()
+{
+ sed -E 's,[ ]+, ,g'
+}
+
+check()
+{
+ NUM=$1
+ shift
+ collapse_whitespace | \
+ if diff -q - $1
+ then
+ echo "ok $NUM"
+ else
+ echo "not ok $NUM"
+ fi
+}
+
+install -c -m 644 $LCDIR/v1-$ARCH-acct.in v1-$ARCH-acct.in
+install -c -m 644 $LCDIR/v2-$ARCH-acct.in v2-$ARCH-acct.in
+
+echo 1..13
+
+# Command listings of the two acct versions
+sa -u v1-$ARCH-acct.in | check 1 $DIR/v1-$ARCH-u.out
+sa -u v2-$ARCH-acct.in | check 2 $DIR/v2-$ARCH-u.out
+
+# Plain summaries of user/process
+sa -i v1-$ARCH-acct.in | check 3 $DIR/v1-$ARCH-sav.out
+sa -im v1-$ARCH-acct.in | check 4 $DIR/v1-$ARCH-usr.out
+
+# Backward compatibility of v1 summary files
+sa -P $DIR/v1-$ARCH-sav.in -U $DIR/v1-$ARCH-usr.in /dev/null |
+ check 5 $DIR/v1-$ARCH-sav.out
+sa -m -P $DIR/v1-$ARCH-sav.in -U $DIR/v1-$ARCH-usr.in /dev/null |
+ check 6 $DIR/v1-$ARCH-usr.out
+
+# Convert old summary format to new
+install -c -m 644 $DIR/v1-$ARCH-sav.in v2c-$ARCH-sav.in
+install -c -m 644 $DIR/v1-$ARCH-usr.in v2c-$ARCH-usr.in
+sa -s -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in /dev/null >/dev/null
+sa -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in /dev/null |
+ check 7 $DIR/v1-$ARCH-sav.out
+sa -m -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in /dev/null |
+ check 8 $DIR/v1-$ARCH-usr.out
+
+# Reading v2 summary files
+sa -P $DIR/v2-$ARCH-sav.in -U $DIR/v2-$ARCH-usr.in /dev/null |
+ check 9 $DIR/v1-$ARCH-sav.out
+sa -m -P $DIR/v2-$ARCH-sav.in -U $DIR/v2-$ARCH-usr.in /dev/null |
+ check 10 $DIR/v1-$ARCH-usr.out
+
+# Summarize
+sa -is -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in v1-$ARCH-acct.in >/dev/null
+sa -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in /dev/null |
+ check 11 $DIR/v1-$ARCH-sav.out
+sa -m -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in /dev/null |
+ check 12 $DIR/v1-$ARCH-usr.out
+
+# Accumulate
+install -c -m 644 $LCDIR/v1-$ARCH-acct.in v1-$ARCH-acct.in
+sa -is -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in v1-$ARCH-acct.in >/dev/null
+install -c -m 644 $LCDIR/v1-$ARCH-acct.in v1-$ARCH-acct.in
+sa -s -P v2c-$ARCH-sav.in -U v2c-$ARCH-usr.in v1-$ARCH-acct.in \
+ | collapse_whitespace >double
+cp $LCDIR/v1-$ARCH-acct.in v1-$ARCH-acct.in
+sa -i v1-$ARCH-acct.in v1-$ARCH-acct.in | check 13 double
+
+exit 0
diff --git a/usr.sbin/sa/tests/prime.sh b/usr.sbin/sa/tests/prime.sh
new file mode 100755
index 0000000..6992f45
--- /dev/null
+++ b/usr.sbin/sa/tests/prime.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Configure and run this script to create the files for regression testing
+# for a new architecture/configuration.
+#
+# $FreeBSD$
+#
+
+TZ=UTC; export TZ
+
+# Set this to the path of the current sa command
+SANEW=/usr/sbin/sa
+
+# Set this to the path of the sa as of 2007-05-19.
+# You can obtain it with a command like:
+# cvs co -D '2007-05-19' sa
+# To compile it you will also need sys/acct.h from that date
+# and sa configured to use that file, instead of the current version.
+SAOLD=/$HOME/src/sa/sa
+
+# Machine architecture
+ARCH=`uname -m`
+
+# Location of lastcomm regression files
+LCDIR=../../usr.bin/lastcomm
+
+$SANEW -u $LCDIR/v1-$ARCH-acct.in >v1-$ARCH-u.out
+$SANEW -u $LCDIR/v2-$ARCH-acct.in >v2-$ARCH-u.out
+$SANEW -i $LCDIR/v1-$ARCH-acct.in >v1-$ARCH-sav.out
+$SANEW -im $LCDIR/v1-$ARCH-acct.in >v1-$ARCH-usr.out
+cp $LCDIR/v1-$ARCH-acct.in acct.in
+rm -f v1-$ARCH-sav.in v1-$ARCH-usr.in
+$SAOLD -s -P v1-$ARCH-sav.in -U v1-$ARCH-usr.in acct.in >/dev/null
+cp $LCDIR/v1-$ARCH-acct.in acct.in
+rm -f v2-$ARCH-sav.in v2-$ARCH-usr.in
+$SANEW -s -P v2-$ARCH-sav.in -U v2-$ARCH-usr.in acct.in >/dev/null
+rm acct.in
diff --git a/usr.sbin/sa/tests/v1-amd64-sav.in b/usr.sbin/sa/tests/v1-amd64-sav.in
new file mode 100644
index 0000000..adc38dd
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-amd64-sav.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v1-amd64-sav.out b/usr.sbin/sa/tests/v1-amd64-sav.out
new file mode 100644
index 0000000..a2289ee
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-amd64-sav.out
@@ -0,0 +1,5 @@
+ 28 0.282re 0.06cp 40avio 957k
+ 13 0.141re 0.06cp 87avio 903k ***other
+ 3 0.000re 0.00cp 0avio 0k ln
+ 9 0.141re 0.00cp 0avio 19700k time
+ 3 0.000re 0.00cp 0avio 0k time*
diff --git a/usr.sbin/sa/tests/v1-amd64-u.out b/usr.sbin/sa/tests/v1-amd64-u.out
new file mode 100644
index 0000000..4c13b76
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-amd64-u.out
@@ -0,0 +1,28 @@
+ 0 0.000 cpu 0k mem 0 io accton
+ 0 0.172 cpu 41k mem 0 io awk
+ 0 0.000 cpu 140k mem 0 io time
+ 0 3.031 cpu 45k mem 1 io egrep
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.250 cpu 42k mem 1087 io find
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io sleep
+ 0 0.000 cpu 57k mem 0 io time
+ 0 0.016 cpu 31k mem 16 io dd
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.203 cpu 1976k mem 0 io diff
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io ln
+ 0 0.000 cpu 0k mem 0 io time*
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io ln
+ 0 0.000 cpu 0k mem 0 io time*
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io ln
+ 0 0.000 cpu 0k mem 0 io time*
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 713k mem 0 io cc1
+ 0 0.000 cpu 0k mem 0 io as
+ 0 0.000 cpu 228k mem 1 io ld
+ 0 0.000 cpu 196k mem 9 io cc
+ 0 0.000 cpu 45k mem 7 io core
+ 0 0.000 cpu 0k mem 9 io core*
diff --git a/usr.sbin/sa/tests/v1-amd64-usr.in b/usr.sbin/sa/tests/v1-amd64-usr.in
new file mode 100644
index 0000000..6896d32
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-amd64-usr.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v1-amd64-usr.out b/usr.sbin/sa/tests/v1-amd64-usr.out
new file mode 100644
index 0000000..2282808
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-amd64-usr.out
@@ -0,0 +1 @@
+root 28 0.06cpu 1130tio 3514k*sec
diff --git a/usr.sbin/sa/tests/v1-i386-sav.in b/usr.sbin/sa/tests/v1-i386-sav.in
new file mode 100644
index 0000000..4ed7aef
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-i386-sav.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v1-i386-sav.out b/usr.sbin/sa/tests/v1-i386-sav.out
new file mode 100644
index 0000000..a8d68b1
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-i386-sav.out
@@ -0,0 +1,5 @@
+ 28 0.425re 0.10cp 143avio 477k
+ 14 0.220re 0.10cp 286avio 411k ***other
+ 2 0.000re 0.00cp 0avio 0k 1234567890123456
+ 3 0.000re 0.00cp 0avio 0k ln
+ 9 0.205re 0.00cp 0avio 40400k time
diff --git a/usr.sbin/sa/tests/v1-i386-u.out b/usr.sbin/sa/tests/v1-i386-u.out
new file mode 100644
index 0000000..17c28be
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-i386-u.out
@@ -0,0 +1,28 @@
+ 0 0.000 cpu 264k mem 0 io accton
+ 0 0.453 cpu 41k mem 0 io awk
+ 0 0.000 cpu 0k mem 0 io time
+ 0 4.984 cpu 41k mem 28 io egrep
+ 0 0.000 cpu 140k mem 0 io time
+ 0 0.266 cpu 36k mem 3921 io find
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io sleep
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.016 cpu 25k mem 16 io dd
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.312 cpu 1361k mem 0 io diff
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io ln
+ 0 0.000 cpu 0k mem 0 io 123456789012345
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io ln
+ 0 0.000 cpu 0k mem 0 io 1234567890123456
+ 0 0.000 cpu 264k mem 0 io time
+ 0 0.000 cpu 0k mem 0 io ln
+ 0 0.000 cpu 0k mem 0 io 1234567890123456
+ 0 0.000 cpu 0k mem 0 io time
+ 0 0.016 cpu 233k mem 1 io cc1
+ 0 0.000 cpu 482k mem 1 io as
+ 0 0.000 cpu 0k mem 11 io ld
+ 0 0.000 cpu 0k mem 6 io cc
+ 0 0.000 cpu 0k mem 12 io core
+ 0 0.000 cpu 0k mem 7 io core*
diff --git a/usr.sbin/sa/tests/v1-i386-usr.in b/usr.sbin/sa/tests/v1-i386-usr.in
new file mode 100644
index 0000000..791b6ed
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-i386-usr.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v1-i386-usr.out b/usr.sbin/sa/tests/v1-i386-usr.out
new file mode 100644
index 0000000..cf9e7bd
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-i386-usr.out
@@ -0,0 +1 @@
+root 28 0.10cpu 4003tio 2887k*sec
diff --git a/usr.sbin/sa/tests/v1-sparc64-sav.in b/usr.sbin/sa/tests/v1-sparc64-sav.in
new file mode 100644
index 0000000..d6911cf
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-sparc64-sav.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v1-sparc64-sav.out b/usr.sbin/sa/tests/v1-sparc64-sav.out
new file mode 100644
index 0000000..1905420
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-sparc64-sav.out
@@ -0,0 +1,5 @@
+ 28 1.839re 0.66cp 161avio 252k
+ 14 0.930re 0.66cp 322avio 197k ***other
+ 9 0.908re 0.00cp 0avio 10190k time
+ 3 0.001re 0.00cp 0avio 16256k ln
+ 2 0.001re 0.00cp 0avio 27900k 1234567890123456
diff --git a/usr.sbin/sa/tests/v1-sparc64-u.out b/usr.sbin/sa/tests/v1-sparc64-u.out
new file mode 100644
index 0000000..d0ecb51
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-sparc64-u.out
@@ -0,0 +1,28 @@
+ 0 0.016 cpu 162k mem 0 io accton
+ 0 1.609 cpu 273k mem 0 io awk
+ 0 0.016 cpu 174k mem 0 io time
+ 0 29.750 cpu 233k mem 26 io egrep
+ 0 0.016 cpu 161k mem 0 io time
+ 0 5.516 cpu 184k mem 4437 io find
+ 0 0.016 cpu 156k mem 0 io time
+ 0 0.000 cpu 136k mem 0 io sleep
+ 0 0.016 cpu 152k mem 0 io time
+ 0 0.562 cpu 161k mem 16 io dd
+ 0 0.016 cpu 156k mem 0 io time
+ 0 1.641 cpu 193k mem 0 io diff
+ 0 0.016 cpu 156k mem 0 io time
+ 0 0.000 cpu 169k mem 0 io ln
+ 0 0.000 cpu 144k mem 0 io 123456789012345
+ 0 0.016 cpu 166k mem 0 io time
+ 0 0.016 cpu 170k mem 0 io ln
+ 0 0.000 cpu 144k mem 0 io 1234567890123456
+ 0 0.016 cpu 156k mem 0 io time
+ 0 0.016 cpu 169k mem 0 io ln
+ 0 0.000 cpu 135k mem 0 io 1234567890123456
+ 0 0.016 cpu 156k mem 0 io time
+ 0 0.094 cpu 3462k mem 2 io cc1
+ 0 0.016 cpu 1047k mem 1 io as
+ 0 0.094 cpu 1118k mem 10 io ld
+ 0 0.016 cpu 361k mem 5 io cc
+ 0 0.031 cpu 165k mem 7 io core
+ 0 0.000 cpu 112k mem 4 io core*
diff --git a/usr.sbin/sa/tests/v1-sparc64-usr.in b/usr.sbin/sa/tests/v1-sparc64-usr.in
new file mode 100644
index 0000000..08d795b
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-sparc64-usr.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v1-sparc64-usr.out b/usr.sbin/sa/tests/v1-sparc64-usr.out
new file mode 100644
index 0000000..cab001f
--- /dev/null
+++ b/usr.sbin/sa/tests/v1-sparc64-usr.out
@@ -0,0 +1 @@
+root 28 0.66cpu 4508tio 9971k*sec
diff --git a/usr.sbin/sa/tests/v2-amd64-sav.in b/usr.sbin/sa/tests/v2-amd64-sav.in
new file mode 100644
index 0000000..24f863b
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-amd64-sav.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v2-amd64-u.out b/usr.sbin/sa/tests/v2-amd64-u.out
new file mode 100644
index 0000000..4196f4a
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-amd64-u.out
@@ -0,0 +1,28 @@
+ 0 0.002 cpu 68k mem 0 io accton
+ 0 0.163 cpu 35k mem 0 io awk
+ 0 0.003 cpu 0k mem 0 io time
+ 0 3.247 cpu 29k mem 26 io egrep
+ 0 0.003 cpu 93k mem 0 io time
+ 0 0.822 cpu 19k mem 4472 io find
+ 0 0.003 cpu 0k mem 0 io time
+ 0 0.002 cpu 0k mem 0 io sleep
+ 0 0.004 cpu 88k mem 0 io time
+ 0 0.076 cpu 18k mem 16 io dd
+ 0 0.003 cpu 0k mem 0 io time
+ 0 0.223 cpu 24k mem 0 io diff
+ 0 0.003 cpu 0k mem 0 io time
+ 0 0.003 cpu 0k mem 0 io ln
+ 0 0.002 cpu 0k mem 0 io 123456789012345
+ 0 0.003 cpu 0k mem 0 io time
+ 0 0.002 cpu 0k mem 0 io ln
+ 0 0.002 cpu 0k mem 0 io 1234567890123456
+ 0 0.003 cpu 0k mem 0 io time
+ 0 0.002 cpu 0k mem 0 io ln
+ 0 0.002 cpu 70k mem 0 io 1234567890123456
+ 0 0.003 cpu 0k mem 0 io time
+ 0 0.024 cpu 661k mem 2 io cc1
+ 0 0.005 cpu 0k mem 1 io as
+ 0 0.014 cpu 192k mem 9 io ld
+ 0 0.005 cpu 162k mem 5 io cc
+ 0 0.005 cpu 0k mem 13 io core
+ 0 0.002 cpu 0k mem 7 io core*
diff --git a/usr.sbin/sa/tests/v2-amd64-usr.in b/usr.sbin/sa/tests/v2-amd64-usr.in
new file mode 100644
index 0000000..4c3b136
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-amd64-usr.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v2-i386-sav.in b/usr.sbin/sa/tests/v2-i386-sav.in
new file mode 100644
index 0000000..d3172db
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-i386-sav.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v2-i386-u.out b/usr.sbin/sa/tests/v2-i386-u.out
new file mode 100644
index 0000000..b553eb8
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-i386-u.out
@@ -0,0 +1,28 @@
+ 0 0.001 cpu 0k mem 0 io accton
+ 0 0.448 cpu 112k mem 0 io awk
+ 0 0.001 cpu 0k mem 0 io time
+ 0 6.680 cpu 110k mem 0 io egrep
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.248 cpu 108k mem 0 io find
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.001 cpu 0k mem 0 io sleep
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.025 cpu 103k mem 16 io dd
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.423 cpu 110k mem 0 io diff
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.001 cpu 0k mem 0 io ln
+ 0 0.001 cpu 0k mem 0 io 123456789012345
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.001 cpu 0k mem 0 io ln
+ 0 0.001 cpu 0k mem 0 io 1234567890123456
+ 0 0.001 cpu 140k mem 0 io time
+ 0 0.001 cpu 0k mem 0 io ln
+ 0 0.001 cpu 0k mem 0 io 1234567890123456
+ 0 0.001 cpu 0k mem 0 io time
+ 0 0.016 cpu 620k mem 0 io cc1
+ 0 0.002 cpu 432k mem 0 io as
+ 0 0.028 cpu 96k mem 0 io ld
+ 0 0.002 cpu 0k mem 0 io cc
+ 0 0.002 cpu 68k mem 12 io core
+ 0 0.000 cpu 0k mem 7 io core*
diff --git a/usr.sbin/sa/tests/v2-i386-usr.in b/usr.sbin/sa/tests/v2-i386-usr.in
new file mode 100644
index 0000000..465fdb4
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-i386-usr.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v2-sparc64-sav.in b/usr.sbin/sa/tests/v2-sparc64-sav.in
new file mode 100644
index 0000000..b6d836a
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-sparc64-sav.in
Binary files differ
diff --git a/usr.sbin/sa/tests/v2-sparc64-u.out b/usr.sbin/sa/tests/v2-sparc64-u.out
new file mode 100644
index 0000000..9339238
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-sparc64-u.out
@@ -0,0 +1,36 @@
+ 0 0.019 cpu 163k mem 0 io accton
+ 0 1.644 cpu 272k mem 0 io awk
+ 0 0.029 cpu 175k mem 0 io time
+ 0 0.019 cpu 163k mem 0 io sleep
+ 0 0.032 cpu 214k mem 35 io fsck_ufs
+ 0 0.028 cpu 213k mem 10 io fsck_ufs
+ 0 0.028 cpu 189k mem 8 io fsck_ufs
+ 0 0.028 cpu 196k mem 7 io fsck_ufs
+ 0 0.055 cpu 168k mem 0 io fsck
+ 0 0.008 cpu 204k mem 0 io sh*
+ 0 0.023 cpu 179k mem 0 io logger
+ 0 26.715 cpu 233k mem 25 io egrep
+ 0 0.029 cpu 162k mem 0 io time
+ 0 5.703 cpu 184k mem 4444 io find
+ 0 0.029 cpu 166k mem 0 io time
+ 0 0.018 cpu 136k mem 0 io sleep
+ 0 0.028 cpu 157k mem 0 io time
+ 0 0.588 cpu 160k mem 16 io dd
+ 0 0.027 cpu 162k mem 0 io time
+ 0 1.636 cpu 193k mem 0 io diff
+ 0 0.029 cpu 172k mem 0 io time
+ 0 0.020 cpu 170k mem 0 io ln
+ 0 0.018 cpu 135k mem 0 io 123456789012345
+ 0 0.029 cpu 167k mem 0 io time
+ 0 0.019 cpu 163k mem 0 io ln
+ 0 0.017 cpu 135k mem 0 io 1234567890123456
+ 0 0.029 cpu 157k mem 0 io time
+ 0 0.019 cpu 163k mem 0 io ln
+ 0 0.017 cpu 135k mem 0 io 1234567890123456
+ 0 0.029 cpu 162k mem 0 io time
+ 0 0.105 cpu 3358k mem 2 io cc1
+ 0 0.030 cpu 996k mem 1 io as
+ 0 0.186 cpu 1114k mem 11 io ld
+ 0 0.033 cpu 386k mem 6 io cc
+ 0 0.037 cpu 158k mem 12 io core
+ 0 0.010 cpu 129k mem 7 io core*
diff --git a/usr.sbin/sa/tests/v2-sparc64-usr.in b/usr.sbin/sa/tests/v2-sparc64-usr.in
new file mode 100644
index 0000000..01a1bdc
--- /dev/null
+++ b/usr.sbin/sa/tests/v2-sparc64-usr.in
Binary files differ
diff --git a/usr.sbin/service/service.sh b/usr.sbin/service/service.sh
index cf181fa..8c12b89 100755
--- a/usr.sbin/service/service.sh
+++ b/usr.sbin/service/service.sh
@@ -145,5 +145,5 @@ done
# If the script was not found
echo "$script does not exist in /etc/rc.d or the local startup"
-echo "directories (${local_startup})"
+echo "directories (${local_startup}), or is not executable"
exit 1
diff --git a/usr.sbin/services_mkdb/extern.h b/usr.sbin/services_mkdb/extern.h
index 94e31d3..b973972 100644
--- a/usr.sbin/services_mkdb/extern.h
+++ b/usr.sbin/services_mkdb/extern.h
@@ -29,6 +29,6 @@
* $FreeBSD$
*/
-extern const HASHINFO hinfo;
+extern HASHINFO hinfo;
void uniq(const char *);
diff --git a/usr.sbin/services_mkdb/services_mkdb.8 b/usr.sbin/services_mkdb/services_mkdb.8
index 834423a..e3b70e2 100644
--- a/usr.sbin/services_mkdb/services_mkdb.8
+++ b/usr.sbin/services_mkdb/services_mkdb.8
@@ -37,6 +37,7 @@
.Nd generate the services database
.Sh SYNOPSIS
.Nm
+.Op Fl b | l
.Op Fl q
.Op Fl o Ar database
.Op Ar file
@@ -61,6 +62,10 @@ The file must be in the correct format (see
.Pp
The options are as follows:
.Bl -tag -width indent
+.It Fl b
+Use big-endian byte order for database metadata.
+.It Fl l
+Use little-endian byte order for database metadata.
.It Fl o Ar database
Put the output databases in the named file.
.It Fl q
@@ -70,6 +75,13 @@ Print the services file to stdout, omitting duplicate entries and comments.
.El
.Pp
The databases are used by the C library services routines (see
+.Pp
+The
+.Fl b
+and
+.Fl l
+flags are mutually exclusive.
+The default byte ordering is the current host order.
.Xr getservent 3 ) .
.Sh FILES
.Bl -tag -width ".Pa /var/db/services.db.tmp" -compact
diff --git a/usr.sbin/services_mkdb/services_mkdb.c b/usr.sbin/services_mkdb/services_mkdb.c
index 7f5316c..a91340e 100644
--- a/usr.sbin/services_mkdb/services_mkdb.c
+++ b/usr.sbin/services_mkdb/services_mkdb.c
@@ -67,7 +67,7 @@ static const char *getprotostr(StringList *, size_t);
static const char *mkaliases(StringList *, char *, size_t);
static void usage(void);
-const HASHINFO hinfo = {
+HASHINFO hinfo = {
.bsize = 256,
.ffactor = 4,
.nelem = 32768,
@@ -87,14 +87,21 @@ main(int argc, char *argv[])
int warndup = 1;
int unique = 0;
int otherflag = 0;
+ int byteorder = 0;
size_t cnt = 0;
StringList *sl, ***svc;
size_t port, proto;
setprogname(argv[0]);
- while ((ch = getopt(argc, argv, "qo:u")) != -1)
+ while ((ch = getopt(argc, argv, "blo:qu")) != -1)
switch (ch) {
+ case 'b':
+ case 'l':
+ if (byteorder != 0)
+ usage();
+ byteorder = ch == 'b' ? 4321 : 1234;
+ break;
case 'q':
otherflag = 1;
warndup = 0;
@@ -119,6 +126,9 @@ main(int argc, char *argv[])
if (argc == 1)
fname = argv[0];
+ /* Set byte order. */
+ hinfo.lorder = byteorder;
+
if (unique)
uniq(fname);
@@ -423,7 +433,8 @@ out:
static void
usage(void)
{
- (void)fprintf(stderr, "Usage:\t%s [-q] [-o <db>] [<servicefile>]\n"
+ (void)fprintf(stderr,
+ "Usage:\t%s [-b | -l] [-q] [-o <db>] [<servicefile>]\n"
"\t%s -u [<servicefile>]\n", getprogname(), getprogname());
exit(1);
}
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 8fc2678..60c74d1 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$");
#define DEFSPRI (LOG_KERN|LOG_CRIT)
#define TIMERINTVL 30 /* interval for checking flush, mark */
#define TTYMSGTIME 1 /* timeout passed to ttymsg */
+#define RCVBUF_MINSIZE (80 * 1024) /* minimum size of dgram rcv buffer */
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -336,7 +337,7 @@ static void unmapped(struct sockaddr *);
static void wallmsg(struct filed *, struct iovec *, const int iovlen);
static int waitdaemon(int, int, int);
static void timedout(int);
-static void double_rbuf(int);
+static void increase_rcvbuf(int);
int
main(int argc, char *argv[])
@@ -547,8 +548,8 @@ main(int argc, char *argv[])
STAILQ_REMOVE(&funixes, fx, funix, next);
continue;
}
- double_rbuf(fx->s);
}
+ increase_rcvbuf(fx->s);
}
if (SecureMode <= 1)
finet = socksetup(family, bindhostname);
@@ -1241,8 +1242,10 @@ fprintlog(struct filed *f, int flags, const char *msg)
switch (errno) {
case ENOBUFS:
case ENETDOWN:
+ case ENETUNREACH:
case EHOSTUNREACH:
case EHOSTDOWN:
+ case EADDRNOTAVAIL:
break;
/* case EBADF: */
/* case EACCES: */
@@ -1253,7 +1256,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
/* case ENOBUFS: */
/* case ECONNREFUSED: */
default:
- dprintf("removing entry\n");
+ dprintf("removing entry: errno=%d\n", e);
f->f_type = F_UNUSED;
break;
}
@@ -2720,7 +2723,7 @@ socksetup(int af, char *bindhostname)
}
if (!SecureMode)
- double_rbuf(*s);
+ increase_rcvbuf(*s);
}
(*socks)++;
@@ -2741,12 +2744,16 @@ socksetup(int af, char *bindhostname)
}
static void
-double_rbuf(int fd)
+increase_rcvbuf(int fd)
{
- socklen_t slen, len;
+ socklen_t len, slen;
+
+ slen = sizeof(len);
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, &slen) == 0) {
- len *= 2;
- setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, slen);
+ if (len < RCVBUF_MINSIZE) {
+ len = RCVBUF_MINSIZE;
+ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
+ }
}
}
diff --git a/usr.sbin/sysrc/sysrc b/usr.sbin/sysrc/sysrc
index 7e1ddcb..bc603b1 100644
--- a/usr.sbin/sysrc/sysrc
+++ b/usr.sbin/sysrc/sysrc
@@ -28,6 +28,9 @@
#
############################################################ INCLUDES
+# Prevent `-d' from being interpreted as a debug flag by common.subr
+DEBUG_SELF_INITIALIZE=
+
BSDCFG_SHARE="/usr/share/bsdconfig"
[ "$_COMMON_SUBR" ] || . $BSDCFG_SHARE/common.subr || exit 1
[ "$_SYSRC_SUBR" ] || f_include $BSDCFG_SHARE/sysrc.subr
@@ -35,8 +38,14 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
############################################################ GLOBALS
#
+# Version information
+#
+SYSRC_VERSION="6.0 Nov-07,2013"
+
+#
# Options
#
+CHECK_ONLY=
DELETE=
DESCRIBE=
IGNORE_UNKNOWNS=
@@ -92,6 +101,8 @@ help()
"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" "-c" \
+ "Check. Return success if no changes needed, else error."
f_err "$optfmt" "-d" \
"Print a description of the given variable."
f_err "$optfmt" "-D" \
@@ -130,6 +141,8 @@ help()
"Verbose. Print the pathname of the specific rc.conf(5)"
f_err "$optfmt" "" \
"file where the directive was found."
+ f_err "$optfmt" "--version" \
+ "Print version information to stdout and exit."
f_err "$optfmt" "-x" \
"Remove variable(s) from specified file(s)."
f_err "\n"
@@ -179,6 +192,7 @@ jail_depend()
#
# Print include dependencies
#
+ echo DEBUG_SELF_INITIALIZE=
cat $BSDCFG_SHARE/common.subr
cat $BSDCFG_SHARE/sysrc.subr
}
@@ -191,27 +205,31 @@ jail_depend()
[ $# -gt 0 ] || usage
#
-# Check for `--help' command-line option
+# Check for `--help' and `--version' command-line option
#
( # Operate in sub-shell to protect $@ in parent
while [ $# -gt 0 ]; do
case "$1" in
- --help) exit 1;;
+ --help) help ;;
+ --version) # see GLOBALS
+ echo "$SYSRC_VERSION"
+ exit 1 ;;
-[fRj]) # These flags take an argument
- shift 1;;
+ shift 1 ;;
esac
shift 1
done
exit 0
-) || help
+) || die
#
# Process command-line flags
#
-while getopts aAdDef:Fhij:nNqR:vxX flag; do
+while getopts aAcdDef:Fhij:nNqR:vxX flag; do
case "$flag" in
a) SHOW_ALL=${SHOW_ALL:-1};;
A) SHOW_ALL=2;;
+ c) CHECK_ONLY=1;;
d) DESCRIBE=1;;
D) RC_CONFS=;;
e) SHOW_EQUALS=1;;
@@ -273,16 +291,23 @@ if [ "$DELETE" -a "$SHOW_ALL" ]; then
fi
#
+# Pre-flight for `-c' command-line option
+#
+[ "$CHECK_ONLY" -a "$SHOW_ALL" ] &&
+ die "$pgm: \`-c' option incompatible with \`-a'/\`-A' options"
+
+#
# Process `-e', `-n', and `-N' command-line options
#
SEP=': '
-[ "$SHOW_EQUALS" ] && SEP='="'
+[ "$SHOW_FILE" ] && SHOW_EQUALS=
[ "$SHOW_NAME" ] || SHOW_EQUALS=
[ "$SYSRC_VERBOSE" = "0" ] && SYSRC_VERBOSE=
if [ ! "$SHOW_VALUE" ]; then
SHOW_NAME=1
SHOW_EQUALS=
fi
+[ "$SHOW_EQUALS" ] && SEP='="'
#
# Process `-j jail' and `-R dir' command-line options
@@ -298,6 +323,7 @@ if [ "$JAIL" -o "$ROOTDIR" ]; then
$( [ "$DELETE" = "2" ] && echo \ -X )
$( [ "$SHOW_ALL" = "1" ] && echo \ -a )
$( [ "$SHOW_ALL" = "2" ] && echo \ -A )
+ ${CHECK_ONLY:+-c}
${DESCRIBE:+-d}
${SHOW_EQUALS:+-e}
${IGNORE_UNKNOWNS:+-i}
@@ -408,7 +434,7 @@ if [ "$SHOW_ALL" ]; then
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|pgm|SUCCESS|FAILURE|CHECK_ONLY"
EXCEPT="$EXCEPT|f_sysrc_desc_awk|f_sysrc_delete_awk"
#
@@ -501,6 +527,7 @@ fi
#
# Process command-line arguments
#
+costatus=$SUCCESS
while [ $# -gt 0 ]; do
NAME="${1%%=*}"
@@ -511,14 +538,19 @@ while [ $# -gt 0 ]; do
*=*)
#
# Like sysctl(8), if both `-d' AND "name=value" is passed,
- # first describe, then attempt to set
+ # first describe (done above), then attempt to set
#
- if [ "$SYSRC_VERBOSE" ]; then
+ # If verbose, prefix line with where the directive lives
+ if [ "$SYSRC_VERBOSE" -a ! "$CHECK_ONLY" ]; then
file=$( f_sysrc_find "$NAME" )
[ "$file" = "$RC_DEFAULTS" -o ! "$file" ] && \
file=$( f_sysrc_get 'rc_conf_files%%[$IFS]*' )
- echo -n "$file: "
+ if [ "$SHOW_EQUALS" ]; then
+ echo -n ": $file; "
+ else
+ echo -n "$file: "
+ fi
fi
#
@@ -532,6 +564,20 @@ while [ $# -gt 0 ]; do
fi
#
+ # If `-c' is passed, simply compare and move on
+ #
+ if [ "$CHECK_ONLY" ]; then
+ if ! IGNORED=$( f_sysrc_get "$NAME?" ); then
+ costatus=$FAILURE
+ else
+ value=$( f_sysrc_get "$NAME" )
+ [ "$value" = "${1#*=}" ] || costatus=$FAILURE
+ fi
+ shift 1
+ continue
+ fi
+
+ #
# If `-N' is passed, simplify the output
#
if [ ! "$SHOW_VALUE" ]; then
@@ -546,28 +592,34 @@ while [ $# -gt 0 ]; do
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
+ echo -n "${SHOW_NAME:+$NAME$SEP}"
+ echo -n "$before${SHOW_EQUALS:+\" #}"
+ echo -n " -> ${SHOW_EQUALS:+\"}$after"
+ echo "${SHOW_EQUALS:+\"}"
fi
fi
;;
*)
- if ! IGNORED="$( f_sysrc_get "$NAME?" )"; then
- [ "$IGNORE_UNKNOWNS" ] \
- || echo "$pgm: unknown variable '$NAME'"
+ if ! IGNORED=$( f_sysrc_get "$NAME?" ); then
+ [ "$IGNORE_UNKNOWNS" ] ||
+ echo "$pgm: unknown variable '$NAME'"
+ shift 1
+ costatus=$FAILURE
+ continue
+ fi
+
+ # The above check told us what we needed for `-c'
+ if [ "$CHECK_ONLY" ]; then
shift 1
continue
fi
#
- # Like sysctl(8), when `-d' is passed,
- # desribe it rather than expanding it
+ # Like sysctl(8), when `-d' is passed, desribe it
+ # (already done above) rather than expanding it
#
if [ "$DESCRIBE" ]; then
@@ -594,8 +646,13 @@ while [ $# -gt 0 ]; do
continue
fi
- [ "$SYSRC_VERBOSE" ] && \
- echo -n "$( f_sysrc_find "$NAME" ): "
+ if [ "$SYSRC_VERBOSE" ]; then
+ if [ "$SHOW_EQUALS" ]; then
+ echo -n ": $( f_sysrc_find "$NAME" ); "
+ else
+ echo -n "$( f_sysrc_find "$NAME" ): "
+ fi
+ fi
#
# If `-N' is passed, simplify the output
@@ -609,3 +666,9 @@ while [ $# -gt 0 ]; do
esac
shift 1
done
+
+[ ! "$CHECK_ONLY" ] || exit $costatus
+
+################################################################################
+# END
+################################################################################
diff --git a/usr.sbin/sysrc/sysrc.8 b/usr.sbin/sysrc/sysrc.8
index b5671a0..e3b873f 100644
--- a/usr.sbin/sysrc/sysrc.8
+++ b/usr.sbin/sysrc/sysrc.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd Jul 5, 2013
+.Dd Nov 20, 2013
.Dt SYSRC 8
.Os
.Sh NAME
@@ -32,13 +32,13 @@
.Nd safely edit system rc files
.Sh SYNOPSIS
.Nm
-.Op Fl dDeFhinNqvx
+.Op Fl cdDeFhinNqvx
.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 cdDeFhinNqvx
.Op Fl f Ar file
.Op Fl j Ar jail | Fl R Ar dir
.Fl a | A
@@ -57,6 +57,12 @@ Dump a list of all non-default configuration variables.
.It Fl A
Dump a list of all configuration variables
.Pq incl. defaults .
+.It Fl c
+Check if the value will change when assigning a new value.
+If verbose
+.Pq see Dq Fl v
+prints a message stating whether a change would occur.
+Exits with success if no change is necessary, else returns error status.
.It Fl d
Print a description of the given variable.
.It Fl D
@@ -64,10 +70,13 @@ 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
+.Xr sh 1
+compatible syntax
+.Pq for example, Ql var=value .
+Ignored if either
+.Ql Fl n
+or
+.Ql Fl F
is specified.
.It Fl f Ar file
Operate on the specified file(s) instead of the files obtained by reading the
@@ -112,6 +121,8 @@ Verbose.
Print the pathname of the specific
.Xr rc.conf 5
file where the directive was found.
+.It Fl -version
+Print version information to stdout and exit.
.It Fl x
Remove variable(s) from specified file(s).
.El
diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile
index fe2a001..ac7636ac 100644
--- a/usr.sbin/tcpdump/tcpdump/Makefile
+++ b/usr.sbin/tcpdump/tcpdump/Makefile
@@ -89,7 +89,6 @@ SRCS= addrtoname.c \
print-olsr.c \
print-ospf.c \
print-otv.c \
- print-pfsync.c \
print-pgm.c \
print-pim.c \
print-ppi.c \
@@ -163,6 +162,11 @@ CFLAGS+= -DLBL_ALIGN
DPADD= ${LIBL} ${LIBPCAP}
LDADD= -ll -lpcap
+.if ${MK_CASPER} != "no"
+DPADD+= ${LIBCAPSICUM} ${LIBNV}
+LDADD+= -lcapsicum -lnv
+CFLAGS+=-DHAVE_LIBCAPSICUM
+.endif
.if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH)
DPADD+= ${LIBCRYPTO}
LDADD+= -lcrypto
@@ -171,7 +175,8 @@ CFLAGS+= -DHAVE_LIBCRYPTO -DHAVE_OPENSSL_EVP_H
.endif
.if ${MK_PF} != "no"
-SRCS+= print-pflog.c
+SRCS+= print-pflog.c \
+ print-pfsync.c
CFLAGS+= -DHAVE_NET_PFVAR_H
.endif
diff --git a/usr.sbin/tests/Makefile b/usr.sbin/tests/Makefile
new file mode 100644
index 0000000..a7e9c71
--- /dev/null
+++ b/usr.sbin/tests/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+TESTSDIR= ${TESTSBASE}/usr.sbin
+
+.PATH: ${.CURDIR:H:H}/tests
+KYUAFILE= yes
+
+.include <bsd.test.mk>
diff --git a/usr.sbin/tzsetup/Makefile b/usr.sbin/tzsetup/Makefile
index 4ef6533..5c80a48 100644
--- a/usr.sbin/tzsetup/Makefile
+++ b/usr.sbin/tzsetup/Makefile
@@ -7,7 +7,17 @@ CFLAGS+= -I${.CURDIR}/../../contrib/dialog -I.
WARNS?= 3
-DPADD= ${LIBDIALOG} ${LIBNCURSESW} ${LIBM}
-LDADD= -ldialog -lncursesw -lm
+DPADD= ${LIBDIALOG} ${LIBM}
+LDADD= -ldialog -lm
+
+.include <bsd.own.mk>
+
+.if ${MK_NCURSESW} == "no"
+DPADD+= ${LIBNCURSES}
+LDADD+= -lncurses
+.else
+DPADD+= ${LIBNCURSESW}
+LDADD+= -lncursesw
+.endif
.include <bsd.prog.mk>
diff --git a/usr.sbin/usbdump/usbdump.c b/usr.sbin/usbdump/usbdump.c
index 7e7eae9..43fde90 100644
--- a/usr.sbin/usbdump/usbdump.c
+++ b/usr.sbin/usbdump/usbdump.c
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/sysctl.h>
#include <sys/utsname.h>
#include <sys/queue.h>
#include <net/if.h>
@@ -780,6 +781,23 @@ usage(void)
exit(EX_USAGE);
}
+static void
+check_usb_pf_sysctl(void)
+{
+ int error;
+ int no_pf_val = 0;
+ size_t no_pf_len = sizeof(int);
+
+ /* check "hw.usb.no_pf" sysctl for 8- and 9- stable */
+
+ error = sysctlbyname("hw.usb.no_pf", &no_pf_val,
+ &no_pf_len, NULL, 0);
+ if (error == 0 && no_pf_val != 0) {
+ warnx("The USB packet filter might be disabled.");
+ warnx("See the \"hw.usb.no_pf\" sysctl for more information.");
+ }
+}
+
int
main(int argc, char *argv[])
{
@@ -872,6 +890,8 @@ main(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
+ check_usb_pf_sysctl();
+
p->fd = fd = open("/dev/bpf", O_RDONLY);
if (p->fd < 0)
err(EXIT_FAILURE, "Could not open BPF device");
diff --git a/usr.sbin/utx/Makefile b/usr.sbin/utx/Makefile
index a70c71c..78c4f90 100644
--- a/usr.sbin/utx/Makefile
+++ b/usr.sbin/utx/Makefile
@@ -3,7 +3,4 @@
PROG= utx
MAN= utx.8
-LINKS= ${BINDIR}/utx ${BINDIR}/utxrm
-MLINKS= utx.8 utxrm.8
-
.include <bsd.prog.mk>
diff --git a/usr.sbin/utx/utx.8 b/usr.sbin/utx/utx.8
index c3e71e2..363a46a 100644
--- a/usr.sbin/utx/utx.8
+++ b/usr.sbin/utx/utx.8
@@ -24,12 +24,11 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 11, 2012
+.Dd November 3, 2013
.Dt UTX 8
.Os
.Sh NAME
-.Nm utx ,
-.Nm utxrm
+.Nm utx
.Nd manage the user accounting database
.Sh SYNOPSIS
.Nm
@@ -40,9 +39,6 @@
.Cm rm
.Ar identifier
.Ar ...
-.Nm utxrm
-.Ar identifier
-.Ar ...
.Sh DESCRIPTION
The
.Nm
@@ -82,11 +78,6 @@ accounting database's active session table, including its identifiers:
Identifiers can either be supplied in hexadecimal form as displayed by
.Xr getent 1 ,
or as a string if the identifier allows such a representation.
-.Pp
-To remain backward compatible, this action can also be invoked directly
-by using the
-.Nm utxrm
-command.
.El
.Pp
Because this utility requires write-access to the user accounting
diff --git a/usr.sbin/utx/utx.c b/usr.sbin/utx/utx.c
index 99d9591..59edf3b 100644
--- a/usr.sbin/utx/utx.c
+++ b/usr.sbin/utx/utx.c
@@ -95,10 +95,7 @@ int
main(int argc, char *argv[])
{
- if (argc >= 2 && strcmp(getprogname(), "utxrm") == 0)
- /* For compatibility. */
- return (rm(&argv[1]));
- else if (argc == 2 && strcmp(argv[1], "boot") == 0)
+ if (argc == 2 && strcmp(argv[1], "boot") == 0)
return (boot(BOOT_TIME));
else if (argc == 2 && strcmp(argv[1], "shutdown") == 0)
return (boot(SHUTDOWN_TIME));
@@ -108,7 +105,6 @@ main(int argc, char *argv[])
fprintf(stderr,
"usage: utx boot\n"
" utx shutdown\n"
- " utx rm identifier ...\n"
- " utxrm identifier ...\n");
+ " utx rm identifier ...\n");
exit(1);
}
diff --git a/usr.sbin/watchdogd/watchdogd.8 b/usr.sbin/watchdogd/watchdogd.8
index 6176a20..d50a964 100644
--- a/usr.sbin/watchdogd/watchdogd.8
+++ b/usr.sbin/watchdogd/watchdogd.8
@@ -125,42 +125,35 @@ Do not fork.
When this option is specified,
.Nm
will not fork into the background at startup.
-.Pp
.It Fl S
Do not send a message to the system logger when the watchdog command takes
longer than expected to execute.
The default behaviour is to log a warning via the system logger with the
LOG_DAEMON facility, and to output a warning to standard error.
-.Pp
.It Fl w
Complain when the watchdog script takes too long.
This flag will cause watchdogd to complain when the amount of time to
execute the watchdog script exceeds the threshold of 'sleep' option.
-.Pp
.It Fl -pretimeout Ar timeout
Set a "pretimeout" watchdog.
At "timeout" seconds before the watchdog will fire attempt an action.
The action is set by the --pretimeout-action flag.
The default is just to log a message (WD_SOFT_LOG) via
.Xr log 9 .
-.Pp
.It Fl -pretimeout-action Ar action
Set the timeout action for the pretimeout.
See the section
.Sx Timeout Actions .
-.Pp
.It Fl -softtimeout
Instead of arming the various hardware watchdogs, only use a basic software
watchdog.
The default action is just to
.Xr log 9
a message (WD_SOFT_LOG).
-.Pp
.It Fl -softtimeout-action Ar action
Set the timeout action for the softtimeout.
See the section
.Sx Timeout Actions .
-.Pp
.El
.Sh Timeout Actions
The following timeout actions are available via the
@@ -173,25 +166,22 @@ flags:
Call
.Xr panic 9
when the timeout is reached.
-.Pp
.It Ar ddb
Enter the kernel debugger via
.Xr kdb_enter 9
when the timeout is reached.
-.Pp
.It Ar log
Log a message using
.Xr log 9
when the timeout is reached.
-.Pp
.It Ar printf
call the kernel
.Xr printf 9
to display a message to the console and
.Xr dmesg 8
buffer.
-.Pp
.El
+.Pp
Actions can be combined in a comma separated list as so:
.Ar log,printf
which would both
diff --git a/usr.sbin/wlandebug/wlandebug.8 b/usr.sbin/wlandebug/wlandebug.8
index 3049000..8c8122c 100644
--- a/usr.sbin/wlandebug/wlandebug.8
+++ b/usr.sbin/wlandebug/wlandebug.8
@@ -153,10 +153,10 @@ The following might be used to debug basic station mode operation:
it enables debug messages while scanning, authenticating to
an access point, and associating to an access point.
.Sh SEE ALSO
-.Xr ifconfig 8 ,
-.Xr wlanstats 8 ,
.Xr athdebug 8 ,
-.Xr athstats 8 .
+.Xr athstats 8 ,
+.Xr ifconfig 8 ,
+.Xr wlanstats 8
.Sh NOTES
Different wireless drivers support different debugging messages.
Drivers such as
diff --git a/usr.sbin/wpa/ndis_events/ndis_events.8 b/usr.sbin/wpa/ndis_events/ndis_events.8
index 9cc2bcd..44ce6b9 100644
--- a/usr.sbin/wpa/ndis_events/ndis_events.8
+++ b/usr.sbin/wpa/ndis_events/ndis_events.8
@@ -81,7 +81,7 @@ The
version performs the same functions as the
.Tn Windows\[rg]
one, except that it uses an
-.Xr ioctl 4
+.Xr ioctl 2
and routing socket interface instead of WMI.
.Pp
Note that a single instance of
diff --git a/usr.sbin/ypbind/yp_ping.c b/usr.sbin/ypbind/yp_ping.c
index 1453126..4e445ea 100644
--- a/usr.sbin/ypbind/yp_ping.c
+++ b/usr.sbin/ypbind/yp_ping.c
@@ -30,35 +30,33 @@
* SUCH DAMAGE.
*/
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
+/*-
+ * Copyright (c) 2009, Sun Microsystems, Inc.
+ * All rights reserved.
*
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * - Neither the name of Sun Microsystems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
*/
-
#if 0
#ifndef lint
static char *sccsid = "@(#)from: clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
diff --git a/usr.sbin/ypset/ypset.c b/usr.sbin/ypset/ypset.c
index b63578a..d77909e 100644
--- a/usr.sbin/ypset/ypset.c
+++ b/usr.sbin/ypset/ypset.c
@@ -75,7 +75,7 @@ bind_tohost(struct sockaddr_in *sin, char *dom, char *server)
bcopy (hp->h_addr_list[0],
(u_long *)&ypsd.ypsetdom_binding.ypbind_binding_addr,
sizeof (unsigned long));
- } else if ((long)(server_addr = inet_addr (server)) == -1) {
+ } else if ((server_addr = inet_addr(server)) == INADDR_NONE) {
errx(1, "can't find address for %s", server);
} else
bcopy (&server_addr,
@@ -129,7 +129,8 @@ main(int argc, char *argv[])
domainname = optarg;
break;
case 'h':
- if ((sin.sin_addr.s_addr = inet_addr(optarg)) == -1) {
+ if ((sin.sin_addr.s_addr = inet_addr(optarg)) ==
+ INADDR_NONE) {
hent = gethostbyname(optarg);
if (hent == NULL)
errx(1, "host %s unknown", optarg);
OpenPOWER on IntegriCloud