summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2013-04-12 20:48:55 +0000
committersjg <sjg@FreeBSD.org>2013-04-12 20:48:55 +0000
commit97d8b9495668afa398ab17c8c5f7e223b5fd2e89 (patch)
tree54038c9ac32a45f8741dcc23fb9a8ffc0e15ff89 /usr.sbin
parent5ee3bfdb338e7c80af29a67f4425c4be24c7b866 (diff)
parent086d73aef6d0ab7d21daa2076fdc8d25961f9b05 (diff)
downloadFreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.zip
FreeBSD-src-97d8b9495668afa398ab17c8c5f7e223b5fd2e89.tar.gz
sync from head
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/Makefile1
-rw-r--r--usr.sbin/ac/ac.820
-rw-r--r--usr.sbin/acpi/acpidb/Makefile13
-rw-r--r--usr.sbin/acpi/iasl/Makefile29
-rw-r--r--usr.sbin/bhyve/Makefile2
-rw-r--r--usr.sbin/bhyve/acpi.c26
-rw-r--r--usr.sbin/bhyve/bhyverun.c53
-rw-r--r--usr.sbin/bhyve/bhyverun.h4
-rw-r--r--usr.sbin/bhyve/consport.c1
-rw-r--r--usr.sbin/bhyve/dbgport.c1
-rw-r--r--usr.sbin/bhyve/inout.c56
-rw-r--r--usr.sbin/bhyve/inout.h4
-rw-r--r--usr.sbin/bhyve/mem.c105
-rw-r--r--usr.sbin/bhyve/mem.h2
-rw-r--r--usr.sbin/bhyve/mptbl.c11
-rw-r--r--usr.sbin/bhyve/pci_emul.c337
-rw-r--r--usr.sbin/bhyve/pci_emul.h36
-rw-r--r--usr.sbin/bhyve/pci_hostbridge.c2
-rw-r--r--usr.sbin/bhyve/pci_passthru.c3
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c53
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c33
-rw-r--r--usr.sbin/bhyve/pmtmr.c101
-rw-r--r--usr.sbin/bhyve/uart.c60
-rw-r--r--usr.sbin/bhyve/virtio.h15
-rw-r--r--usr.sbin/bhyvectl/bhyvectl.c65
-rw-r--r--usr.sbin/bhyveload/bhyveload.833
-rw-r--r--usr.sbin/bhyveload/bhyveload.c57
-rw-r--r--usr.sbin/bluetooth/ath3kfw/ath3kfw.c18
-rw-r--r--usr.sbin/bluetooth/l2ping/l2ping.82
-rw-r--r--usr.sbin/bsdconfig/include/Makefile3
-rw-r--r--usr.sbin/bsdconfig/include/media.hlp48
-rw-r--r--usr.sbin/bsdconfig/include/messages.subr214
-rw-r--r--usr.sbin/bsdconfig/include/network_device.hlp58
-rw-r--r--usr.sbin/bsdconfig/include/options.hlp98
-rw-r--r--usr.sbin/bsdconfig/include/tcp.hlp (renamed from usr.sbin/bsdconfig/networking/include/tcp.hlp)0
-rwxr-xr-xusr.sbin/bsdconfig/networking/devices3
-rw-r--r--usr.sbin/bsdconfig/networking/include/Makefile2
-rw-r--r--usr.sbin/bsdconfig/networking/share/common.subr13
-rw-r--r--usr.sbin/bsdconfig/networking/share/device.subr133
-rw-r--r--usr.sbin/bsdconfig/networking/share/hostname.subr59
-rw-r--r--usr.sbin/bsdconfig/networking/share/ipaddr.subr204
-rw-r--r--usr.sbin/bsdconfig/networking/share/netmask.subr83
-rw-r--r--usr.sbin/bsdconfig/networking/share/resolv.subr27
-rw-r--r--usr.sbin/bsdconfig/networking/share/routing.subr22
-rw-r--r--usr.sbin/bsdconfig/share/Makefile6
-rw-r--r--usr.sbin/bsdconfig/share/common.subr42
-rw-r--r--usr.sbin/bsdconfig/share/device.subr795
-rw-r--r--usr.sbin/bsdconfig/share/media/Makefile13
-rw-r--r--usr.sbin/bsdconfig/share/media/any.subr152
-rw-r--r--usr.sbin/bsdconfig/share/media/cdrom.subr210
-rw-r--r--usr.sbin/bsdconfig/share/media/common.subr109
-rw-r--r--usr.sbin/bsdconfig/share/media/directory.subr146
-rw-r--r--usr.sbin/bsdconfig/share/media/dos.subr164
-rw-r--r--usr.sbin/bsdconfig/share/media/floppy.subr214
-rw-r--r--usr.sbin/bsdconfig/share/media/ftp.subr893
-rw-r--r--usr.sbin/bsdconfig/share/media/httpproxy.subr433
-rw-r--r--usr.sbin/bsdconfig/share/media/network.subr182
-rw-r--r--usr.sbin/bsdconfig/share/media/nfs.subr251
-rw-r--r--usr.sbin/bsdconfig/share/media/options.subr308
-rw-r--r--usr.sbin/bsdconfig/share/media/tcpip.subr1688
-rw-r--r--usr.sbin/bsdconfig/share/media/ufs.subr193
-rw-r--r--usr.sbin/bsdconfig/share/media/usb.subr174
-rw-r--r--usr.sbin/bsdconfig/share/script.subr33
-rw-r--r--usr.sbin/bsdconfig/share/strings.subr68
-rw-r--r--usr.sbin/bsdconfig/share/struct.subr206
-rw-r--r--usr.sbin/bsdconfig/share/variable.subr68
-rwxr-xr-xusr.sbin/bsdconfig/startup/rcvar4
-rw-r--r--usr.sbin/bsdinstall/distextract/distextract.c4
-rw-r--r--usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c32
-rw-r--r--usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.18
-rw-r--r--usr.sbin/burncd/Makefile6
-rw-r--r--usr.sbin/burncd/Makefile.depend19
-rw-r--r--usr.sbin/burncd/burncd.8249
-rw-r--r--usr.sbin/burncd/burncd.c748
-rw-r--r--usr.sbin/config/main.c12
-rw-r--r--usr.sbin/ctladm/ctladm.85
-rw-r--r--usr.sbin/ctladm/ctladm.c10
-rw-r--r--usr.sbin/extattr/rmextattr.c61
-rw-r--r--usr.sbin/jail/command.c24
-rw-r--r--usr.sbin/jail/config.c8
-rw-r--r--usr.sbin/jail/jailp.h1
-rw-r--r--usr.sbin/kgmon/kgmon.c62
-rw-r--r--usr.sbin/makefs/makefs.86
-rw-r--r--usr.sbin/makefs/makefs.c7
-rw-r--r--usr.sbin/makefs/makefs.h3
-rw-r--r--usr.sbin/makefs/mtree.c58
-rw-r--r--usr.sbin/makefs/walk.c3
-rw-r--r--usr.sbin/mfiutil/Makefile4
-rw-r--r--usr.sbin/mfiutil/mfi_bbu.c249
-rw-r--r--usr.sbin/mfiutil/mfi_show.c29
-rw-r--r--usr.sbin/mfiutil/mfi_volume.c3
-rw-r--r--usr.sbin/mfiutil/mfiutil.833
-rw-r--r--usr.sbin/mfiutil/mfiutil.c2
-rw-r--r--usr.sbin/mfiutil/mfiutil.h7
-rw-r--r--usr.sbin/mount_nwfs/Makefile15
-rw-r--r--usr.sbin/mount_nwfs/Makefile.depend20
-rw-r--r--usr.sbin/mount_nwfs/mount_nwfs.8230
-rw-r--r--usr.sbin/mount_nwfs/mount_nwfs.c369
-rw-r--r--usr.sbin/mount_portalfs/Makefile15
-rw-r--r--usr.sbin/mount_portalfs/Makefile.depend20
-rw-r--r--usr.sbin/mount_portalfs/activate.c195
-rw-r--r--usr.sbin/mount_portalfs/conf.c318
-rw-r--r--usr.sbin/mount_portalfs/cred.c75
-rw-r--r--usr.sbin/mount_portalfs/mount_portalfs.8216
-rw-r--r--usr.sbin/mount_portalfs/mount_portalfs.c281
-rw-r--r--usr.sbin/mount_portalfs/portal.conf7
-rw-r--r--usr.sbin/mount_portalfs/portald.h86
-rw-r--r--usr.sbin/mount_portalfs/pt_conf.c50
-rw-r--r--usr.sbin/mount_portalfs/pt_exec.c50
-rw-r--r--usr.sbin/mount_portalfs/pt_file.c91
-rw-r--r--usr.sbin/mount_portalfs/pt_pipe.c229
-rw-r--r--usr.sbin/mount_portalfs/pt_tcp.c157
-rw-r--r--usr.sbin/mount_portalfs/pt_tcplisten.c201
-rw-r--r--usr.sbin/mountd/mountd.c2
-rw-r--r--usr.sbin/moused/moused.c1
-rw-r--r--usr.sbin/mptutil/mptutil.84
-rw-r--r--usr.sbin/named/Makefile2
-rw-r--r--usr.sbin/newsyslog/newsyslog.c192
-rw-r--r--usr.sbin/nfsd/nfsd.c123
-rw-r--r--usr.sbin/nmtree/Makefile2
-rwxr-xr-xusr.sbin/pc-sysinstall/backend-query/disk-list.sh9
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh13
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-disk.sh1
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-extractimage.sh143
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-installpackages.sh131
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-mountdisk.sh8
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-newfs.sh44
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-packages.sh137
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions-parse.sh2
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/functions.sh6
-rwxr-xr-xusr.sbin/pc-sysinstall/backend/parseconfig.sh2
-rw-r--r--usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf8
-rw-r--r--usr.sbin/pc-sysinstall/examples/README11
-rw-r--r--usr.sbin/pciconf/pciconf.c2
-rw-r--r--usr.sbin/pkg/Makefile6
-rw-r--r--usr.sbin/pkg/config.c428
-rw-r--r--usr.sbin/pkg/config.h (renamed from usr.sbin/mount_portalfs/pathnames.h)44
-rw-r--r--usr.sbin/pkg/pkg.c192
-rw-r--r--usr.sbin/pmcannotate/pmcannotate.86
-rw-r--r--usr.sbin/rarpd/rarpd.c22
-rw-r--r--usr.sbin/rtadvd/rtadvd.816
-rw-r--r--usr.sbin/rtadvd/rtadvd.c22
-rw-r--r--usr.sbin/sendmail/Makefile5
-rw-r--r--usr.sbin/services_mkdb/services_mkdb.82
-rw-r--r--usr.sbin/tzsetup/tzsetup.c5
-rw-r--r--usr.sbin/usbconfig/dump.c8
-rw-r--r--usr.sbin/usbconfig/usbconfig.c1
-rw-r--r--usr.sbin/watchdogd/watchdogd.8114
-rw-r--r--usr.sbin/watchdogd/watchdogd.c344
149 files changed, 9575 insertions, 5223 deletions
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index 532595b..02e590e 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -6,7 +6,6 @@
SUBDIR= adduser \
arp \
bootparamd \
- burncd \
bsdinstall \
cdcontrol \
chkgrp \
diff --git a/usr.sbin/ac/ac.8 b/usr.sbin/ac/ac.8
index 26667d8..954d9f7 100644
--- a/usr.sbin/ac/ac.8
+++ b/usr.sbin/ac/ac.8
@@ -105,17 +105,6 @@ hand.
No login or connect time accounting is performed if
.Pa /var/log/utx.log
does not exist.
-.Pp
-For example,
-.Bd -literal -offset indent
-ac -p -t "ttyd*" > modems
-ac -p -t "!ttyd*" > other
-.Ed
-.Pp
-allows times recorded in
-.Pa modems
-to be charged out at a different rate than
-.Pa other .
.Sh FILES
.Bl -tag -width /var/log/utx.log -compact
.It Pa /var/log/utx.log
@@ -123,6 +112,15 @@ connect time accounting file
.El
.Sh EXIT STATUS
.Ex -std
+.Sh EXAMPLES
+Allow times recorded in
+.Pa modems
+to be charged out at a different rate than
+.Pa other :
+.Bd -literal -offset indent
+ac -p -t "ttyd*" > modems
+ac -p -t "!ttyd*" > other
+.Ed
.Sh SEE ALSO
.Xr login 1 ,
.Xr getutxent 3 ,
diff --git a/usr.sbin/acpi/acpidb/Makefile b/usr.sbin/acpi/acpidb/Makefile
index 9eccb4d..5ee3d47 100644
--- a/usr.sbin/acpi/acpidb/Makefile
+++ b/usr.sbin/acpi/acpidb/Makefile
@@ -35,10 +35,10 @@ SRCS+= hwacpi.c hwesleep.c hwgpe.c hwpci.c hwregs.c hwsleep.c \
hwvalid.c hwxface.c hwxfsleep.c
# components/namespace
-SRCS+= nsaccess.c nsalloc.c nsdump.c nseval.c nsinit.c \
- nsload.c nsnames.c nsobject.c nsparse.c nspredef.c \
- nsprepkg.c nsrepair.c nsrepair2.c nssearch.c nsutils.c \
- nswalk.c nsxfeval.c nsxfname.c nsxfobj.c
+SRCS+= nsaccess.c nsalloc.c nsconvert.c nsdump.c nseval.c \
+ nsinit.c nsload.c nsnames.c nsobject.c nsparse.c \
+ nspredef.c nsprepkg.c nsrepair.c nsrepair2.c nssearch.c \
+ nsutils.c nswalk.c nsxfeval.c nsxfname.c nsxfobj.c
# components/parser
SRCS+= psargs.c psloop.c psobject.c psopcode.c psopinfo.c \
@@ -61,8 +61,9 @@ SRCS+= tbfadt.c tbfind.c tbinstal.c tbutils.c tbxface.c \
SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c \
utdecode.c utdelete.c uteval.c utexcep.c utglobal.c \
utids.c utinit.c utlock.c utmath.c utmisc.c utmutex.c \
- utobject.c utosi.c utownerid.c utresrc.c utstate.c \
- utstring.c uttrack.c utxface.c utxferror.c utxfinit.c
+ utobject.c utosi.c utownerid.c utpredef.c utresrc.c \
+ utstate.c utstring.c uttrack.c utxface.c utxferror.c \
+ utxfinit.c
MAN= acpidb.8
WARNS?= 2
diff --git a/usr.sbin/acpi/iasl/Makefile b/usr.sbin/acpi/iasl/Makefile
index b348141..973b63d 100644
--- a/usr.sbin/acpi/iasl/Makefile
+++ b/usr.sbin/acpi/iasl/Makefile
@@ -11,18 +11,19 @@ SRCS+= ahpredef.c dmextern.c dmrestag.c dmtable.c dmtbdump.c \
SRCS+= aslanalyze.c aslbtypes.c aslcodegen.c aslcompile.c \
aslcompiler.y.h aslcompilerlex.c aslcompilerparse.c \
aslerror.c aslfileio.c aslfiles.c aslfold.c aslhex.c \
- asllength.c asllisting.c aslload.c asllookup.c \
- aslmain.c aslmap.c aslmethod.c aslnamesp.c aslopcodes.c \
- asloperands.c aslopt.c aslpredef.c aslresource.c \
- aslrestype1.c aslrestype1i.c aslrestype2.c \
- aslrestype2d.c aslrestype2e.c aslrestype2q.c \
- aslrestype2s.c aslrestype2w.c aslstartup.c aslstubs.c \
- asltransform.c asltree.c aslutils.c asluuid.c \
- aslwalks.c aslxref.c dtcompile.c dtexpress.c dtfield.c \
- dtio.c dtparser.y.h dtparserlex.c dtparserparse.c \
- dtsubtable.c dttable.c dttemplate.c dtutils.c \
- prexpress.c prmacros.c prparser.y.h prparserlex.c \
- prparserparse.c prscan.c prutils.c
+ asllength.c asllisting.c asllistsup.c aslload.c \
+ asllookup.c aslmain.c aslmap.c aslmethod.c aslnamesp.c \
+ asloffset.c aslopcodes.c asloperands.c aslopt.c \
+ aslpredef.c aslprepkg.c aslresource.c aslrestype1.c \
+ aslrestype1i.c aslrestype2.c aslrestype2d.c \
+ aslrestype2e.c aslrestype2q.c aslrestype2s.c \
+ aslrestype2w.c aslstartup.c aslstubs.c asltransform.c \
+ asltree.c aslutils.c asluuid.c aslwalks.c aslxref.c \
+ dtcompile.c dtexpress.c dtfield.c dtio.c dtparser.y.h \
+ dtparserlex.c dtparserparse.c dtsubtable.c dttable.c \
+ dttemplate.c dtutils.c prexpress.c prmacros.c \
+ prparser.y.h prparserlex.c prparserparse.c prscan.c \
+ prutils.c
# components/debugger
SRCS+= dbfileio.c
@@ -57,8 +58,8 @@ SRCS+= tbfadt.c tbinstal.c tbutils.c tbxface.c
SRCS+= utaddress.c utalloc.c utcache.c utcopy.c utdebug.c \
utdecode.c utdelete.c utexcep.c utglobal.c utinit.c \
utlock.c utmath.c utmisc.c utmutex.c utobject.c \
- utownerid.c utresrc.c utstate.c utstring.c utxface.c \
- utxferror.c
+ utownerid.c utpredef.c utresrc.c utstate.c utstring.c \
+ utxface.c utxferror.c
# os_specific/service_layers
SRCS+= osunixxf.c
diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile
index ef39079..e6aa8b2 100644
--- a/usr.sbin/bhyve/Makefile
+++ b/usr.sbin/bhyve/Makefile
@@ -9,7 +9,7 @@ DEBUG_FLAGS= -g -O0
SRCS= acpi.c atpic.c bhyverun.c consport.c dbgport.c elcr.c inout.c
SRCS+= ioapic.c mem.c mevent.c mptbl.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 uart.c
+SRCS+= pci_virtio_net.c pci_uart.c pit_8254.c pmtmr.c post.c rtc.c
SRCS+= xmsr.c spinup_ap.c
.PATH: ${.CURDIR}/../../sys/amd64/vmm
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
index 32effdc..ed0c545 100644
--- a/usr.sbin/bhyve/acpi.c
+++ b/usr.sbin/bhyve/acpi.c
@@ -680,22 +680,26 @@ basl_end(struct basl_fio *in, struct basl_fio *out)
}
static int
-basl_load(int fd, uint64_t off)
+basl_load(struct vmctx *ctx, int fd, uint64_t off)
{
- struct stat sb;
- int err;
+ struct stat sb;
+ void *gaddr;
- err = 0;
+ if (fstat(fd, &sb) < 0)
+ return (errno);
+
+ gaddr = paddr_guest2host(ctx, basl_acpi_base + off, sb.st_size);
+ if (gaddr == NULL)
+ return (EFAULT);
- if (fstat(fd, &sb) < 0 ||
- read(fd, paddr_guest2host(basl_acpi_base + off), sb.st_size) < 0)
- err = errno;
+ if (read(fd, gaddr, sb.st_size) < 0)
+ return (errno);
- return (err);
+ return (0);
}
static int
-basl_compile(int (*fwrite_section)(FILE *fp), uint64_t offset)
+basl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *), uint64_t offset)
{
struct basl_fio io[2];
static char iaslbuf[3*MAXPATHLEN + 10];
@@ -729,7 +733,7 @@ basl_compile(int (*fwrite_section)(FILE *fp), uint64_t offset)
* Copy the aml output file into guest
* memory at the specified location
*/
- err = basl_load(io[1].fd, offset);
+ err = basl_load(ctx, io[1].fd, offset);
}
}
basl_end(&io[0], &io[1]);
@@ -835,7 +839,7 @@ acpi_build(struct vmctx *ctx, int ncpu, int ioapic)
* copying them into guest memory
*/
while (!err && basl_ftables[i].wsect != NULL) {
- err = basl_compile(basl_ftables[i].wsect,
+ err = basl_compile(ctx, basl_ftables[i].wsect,
basl_ftables[i].offset);
i++;
}
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index 8d03649..3218ca4 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -80,9 +80,6 @@ int guest_tslice = DEFAULT_GUEST_TSLICE;
int guest_hz = DEFAULT_GUEST_HZ;
char *vmname;
-u_long lomem_sz;
-u_long himem_sz;
-
int guest_ncpus;
static int pincpu = -1;
@@ -95,9 +92,6 @@ static int strictio;
static int acpi;
-static char *lomem_addr;
-static char *himem_addr;
-
static char *progname;
static const int BSP = 0;
@@ -147,8 +141,7 @@ usage(int code)
" -z: guest hz (default is %d)\n"
" -s: <slot,driver,configinfo> PCI slot config\n"
" -S: <slot,driver,configinfo> legacy PCI slot config\n"
- " -m: lowmem in MB\n"
- " -M: highmem in MB\n"
+ " -m: memory size in MB\n"
" -x: mux vcpus to 1 hcpu\n"
" -t: mux vcpu timeslice hz (default %d)\n",
progname, DEFAULT_GDB_PORT, DEFAULT_GUEST_HZ,
@@ -157,17 +150,10 @@ usage(int code)
}
void *
-paddr_guest2host(uintptr_t gaddr)
+paddr_guest2host(struct vmctx *ctx, uintptr_t gaddr, size_t len)
{
- if (lomem_sz == 0)
- return (NULL);
-
- if (gaddr < lomem_sz) {
- return ((void *)(lomem_addr + gaddr));
- } else if (gaddr >= 4*GB && gaddr < (4*GB + himem_sz)) {
- return ((void *)(himem_addr + gaddr - 4*GB));
- } else
- return (NULL);
+
+ return (vm_map_gpa(ctx, gaddr, len));
}
int
@@ -520,13 +506,17 @@ static vmexit_handler_t handler[VM_EXITCODE_MAX] = {
static void
vm_loop(struct vmctx *ctx, int vcpu, uint64_t rip)
{
+ cpuset_t mask;
int error, rc, prevcpu;
if (guest_vcpu_mux)
setup_timeslice();
if (pincpu >= 0) {
- error = vm_set_pinning(ctx, vcpu, pincpu + vcpu);
+ CPU_ZERO(&mask);
+ CPU_SET(pincpu + vcpu, &mask);
+ error = pthread_setaffinity_np(pthread_self(),
+ sizeof(mask), &mask);
assert(error == 0);
}
@@ -598,6 +588,7 @@ main(int argc, char *argv[])
int max_vcpus;
struct vmctx *ctx;
uint64_t rip;
+ size_t memsize;
bvmcons = 0;
inject_bkpt = 0;
@@ -605,8 +596,9 @@ main(int argc, char *argv[])
gdb_port = DEFAULT_GDB_PORT;
guest_ncpus = 1;
ioapic = 0;
+ memsize = 256 * MB;
- while ((c = getopt(argc, argv, "abehABHIPxp:g:c:z:s:S:n:m:M:")) != -1) {
+ while ((c = getopt(argc, argv, "abehABHIPxp:g:c:z:s:S:n:m:")) != -1) {
switch (c) {
case 'a':
disable_x2apic = 1;
@@ -645,10 +637,7 @@ main(int argc, char *argv[])
pci_parse_slot(optarg, 1);
break;
case 'm':
- lomem_sz = strtoul(optarg, NULL, 0) * MB;
- break;
- case 'M':
- himem_sz = strtoul(optarg, NULL, 0) * MB;
+ memsize = strtoul(optarg, NULL, 0) * MB;
break;
case 'H':
guest_vmexit_on_hlt = 1;
@@ -733,19 +722,13 @@ main(int argc, char *argv[])
exit(1);
}
- if (lomem_sz != 0) {
- lomem_addr = vm_map_memory(ctx, 0, lomem_sz);
- if (lomem_addr == (char *) MAP_FAILED) {
- lomem_sz = 0;
- } else if (himem_sz != 0) {
- himem_addr = vm_map_memory(ctx, 4*GB, himem_sz);
- if (himem_addr == (char *) MAP_FAILED) {
- lomem_sz = 0;
- himem_sz = 0;
- }
- }
+ err = vm_setup_memory(ctx, memsize, VM_MMAP_ALL);
+ if (err) {
+ fprintf(stderr, "Unable to setup memory (%d)\n", err);
+ exit(1);
}
+ init_mem();
init_inout();
init_pci(ctx);
if (ioapic)
diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h
index 45033b8..ffe3018 100644
--- a/usr.sbin/bhyve/bhyverun.h
+++ b/usr.sbin/bhyve/bhyverun.h
@@ -41,9 +41,7 @@ extern int guest_tslice;
extern int guest_ncpus;
extern char *vmname;
-extern u_long lomem_sz, himem_sz;
-
-void *paddr_guest2host(uintptr_t);
+void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);
void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip);
int fbsdrun_muxed(void);
diff --git a/usr.sbin/bhyve/consport.c b/usr.sbin/bhyve/consport.c
index 3915b6d..a31038a 100644
--- a/usr.sbin/bhyve/consport.c
+++ b/usr.sbin/bhyve/consport.c
@@ -128,6 +128,7 @@ console_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
static struct inout_port consport = {
"bvmcons",
BVM_CONSOLE_PORT,
+ 1,
IOPORT_F_INOUT,
console_handler
};
diff --git a/usr.sbin/bhyve/dbgport.c b/usr.sbin/bhyve/dbgport.c
index 034531c..97a86ef 100644
--- a/usr.sbin/bhyve/dbgport.c
+++ b/usr.sbin/bhyve/dbgport.c
@@ -105,6 +105,7 @@ again:
static struct inout_port dbgport = {
"bvmdbg",
BVM_DBG_PORT,
+ 1,
IOPORT_F_INOUT,
dbg_handler
};
diff --git a/usr.sbin/bhyve/inout.c b/usr.sbin/bhyve/inout.c
index 5f47a89f..29d9f17 100644
--- a/usr.sbin/bhyve/inout.c
+++ b/usr.sbin/bhyve/inout.c
@@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker_set.h>
#include <stdio.h>
+#include <string.h>
#include <assert.h>
#include "inout.h"
@@ -41,6 +42,9 @@ SET_DECLARE(inout_port_set, struct inout_port);
#define MAX_IOPORTS (1 << 16)
+#define VERIFY_IOPORT(port, size) \
+ assert((port) >= 0 && (size) > 0 && ((port) + (size)) <= MAX_IOPORTS)
+
static struct {
const char *name;
int flags;
@@ -69,6 +73,23 @@ default_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
return (0);
}
+static void
+register_default_iohandler(int start, int size)
+{
+ struct inout_port iop;
+
+ VERIFY_IOPORT(start, size);
+
+ bzero(&iop, sizeof(iop));
+ iop.name = "default";
+ iop.port = start;
+ iop.size = size;
+ iop.flags = IOPORT_F_INOUT;
+ iop.handler = default_inout;
+
+ register_inout(&iop);
+}
+
int
emulate_inout(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, int strict)
@@ -113,17 +134,11 @@ void
init_inout(void)
{
struct inout_port **iopp, *iop;
- int i;
/*
* Set up the default handler for all ports
*/
- for (i = 0; i < MAX_IOPORTS; i++) {
- inout_handlers[i].name = "default";
- inout_handlers[i].flags = IOPORT_F_IN | IOPORT_F_OUT;
- inout_handlers[i].handler = default_inout;
- inout_handlers[i].arg = NULL;
- }
+ register_default_iohandler(0, MAX_IOPORTS);
/*
* Overwrite with specified handlers
@@ -141,11 +156,28 @@ init_inout(void)
int
register_inout(struct inout_port *iop)
{
- assert(iop->port < MAX_IOPORTS);
- inout_handlers[iop->port].name = iop->name;
- inout_handlers[iop->port].flags = iop->flags;
- inout_handlers[iop->port].handler = iop->handler;
- inout_handlers[iop->port].arg = iop->arg;
+ int i;
+
+ VERIFY_IOPORT(iop->port, iop->size);
+
+ for (i = iop->port; i < iop->port + iop->size; i++) {
+ inout_handlers[i].name = iop->name;
+ inout_handlers[i].flags = iop->flags;
+ inout_handlers[i].handler = iop->handler;
+ inout_handlers[i].arg = iop->arg;
+ }
+
+ return (0);
+}
+
+int
+unregister_inout(struct inout_port *iop)
+{
+
+ VERIFY_IOPORT(iop->port, iop->size);
+ assert(inout_handlers[iop->port].name == iop->name);
+
+ register_default_iohandler(iop->port, iop->size);
return (0);
}
diff --git a/usr.sbin/bhyve/inout.h b/usr.sbin/bhyve/inout.h
index a73b78d..4de58d1 100644
--- a/usr.sbin/bhyve/inout.h
+++ b/usr.sbin/bhyve/inout.h
@@ -39,6 +39,7 @@ typedef int (*inout_func_t)(struct vmctx *ctx, int vcpu, int in, int port,
struct inout_port {
const char *name;
int port;
+ int size;
int flags;
inout_func_t handler;
void *arg;
@@ -51,6 +52,7 @@ struct inout_port {
static struct inout_port __CONCAT(__inout_port, __LINE__) = { \
#name, \
(port), \
+ 1, \
(flags), \
(handler), \
0 \
@@ -61,7 +63,7 @@ void init_inout(void);
int emulate_inout(struct vmctx *, int vcpu, int in, int port, int bytes,
uint32_t *eax, int strict);
int register_inout(struct inout_port *iop);
-
+int unregister_inout(struct inout_port *iop);
void init_bvmcons(void);
#endif /* _INOUT_H_ */
diff --git a/usr.sbin/bhyve/mem.c b/usr.sbin/bhyve/mem.c
index 27f4782..d5c7935 100644
--- a/usr.sbin/bhyve/mem.c
+++ b/usr.sbin/bhyve/mem.c
@@ -30,12 +30,6 @@
* Memory ranges are represented with an RB tree. On insertion, the range
* is checked for overlaps. On lookup, the key has the same base and limit
* so it can be searched within the range.
- *
- * It is assumed that all setup of ranges takes place in single-threaded
- * mode before vCPUs have been started. As such, no locks are used on the
- * RB tree. If this is no longer the case, then a r/w lock could be used,
- * with readers on the lookup and a writer if the tree needs to be changed
- * (and per vCPU caches flushed)
*/
#include <sys/cdefs.h>
@@ -49,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <pthread.h>
#include "mem.h"
@@ -62,7 +57,7 @@ struct mmio_rb_range {
struct mmio_rb_tree;
RB_PROTOTYPE(mmio_rb_tree, mmio_rb_range, mr_link, mmio_rb_range_compare);
-RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rbroot;
+RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rb_root, mmio_rb_fallback;
/*
* Per-vCPU cache. Since most accesses from a vCPU will be to
@@ -71,6 +66,8 @@ RB_HEAD(mmio_rb_tree, mmio_rb_range) mmio_rbroot;
*/
static struct mmio_rb_range *mmio_hint[VM_MAXCPU];
+static pthread_rwlock_t mmio_rwlock;
+
static int
mmio_rb_range_compare(struct mmio_rb_range *a, struct mmio_rb_range *b)
{
@@ -82,13 +79,14 @@ mmio_rb_range_compare(struct mmio_rb_range *a, struct mmio_rb_range *b)
}
static int
-mmio_rb_lookup(uint64_t addr, struct mmio_rb_range **entry)
+mmio_rb_lookup(struct mmio_rb_tree *rbt, uint64_t addr,
+ struct mmio_rb_range **entry)
{
struct mmio_rb_range find, *res;
find.mr_base = find.mr_end = addr;
- res = RB_FIND(mmio_rb_tree, &mmio_rbroot, &find);
+ res = RB_FIND(mmio_rb_tree, rbt, &find);
if (res != NULL) {
*entry = res;
@@ -99,11 +97,11 @@ mmio_rb_lookup(uint64_t addr, struct mmio_rb_range **entry)
}
static int
-mmio_rb_add(struct mmio_rb_range *new)
+mmio_rb_add(struct mmio_rb_tree *rbt, struct mmio_rb_range *new)
{
struct mmio_rb_range *overlap;
- overlap = RB_INSERT(mmio_rb_tree, &mmio_rbroot, new);
+ overlap = RB_INSERT(mmio_rb_tree, rbt, new);
if (overlap != NULL) {
#ifdef RB_DEBUG
@@ -120,14 +118,16 @@ mmio_rb_add(struct mmio_rb_range *new)
#if 0
static void
-mmio_rb_dump(void)
+mmio_rb_dump(struct mmio_rb_tree *rbt)
{
struct mmio_rb_range *np;
- RB_FOREACH(np, mmio_rb_tree, &mmio_rbroot) {
+ pthread_rwlock_rdlock(&mmio_rwlock);
+ RB_FOREACH(np, mmio_rb_tree, rbt) {
printf(" %lx:%lx, %s\n", np->mr_base, np->mr_end,
np->mr_param.name);
}
+ pthread_rwlock_unlock(&mmio_rwlock);
}
#endif
@@ -160,7 +160,8 @@ emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie)
{
struct mmio_rb_range *entry;
int err;
-
+
+ pthread_rwlock_rdlock(&mmio_rwlock);
/*
* First check the per-vCPU cache
*/
@@ -172,36 +173,41 @@ emulate_mem(struct vmctx *ctx, int vcpu, uint64_t paddr, struct vie *vie)
entry = NULL;
if (entry == NULL) {
- if (mmio_rb_lookup(paddr, &entry))
+ if (mmio_rb_lookup(&mmio_rb_root, paddr, &entry) == 0) {
+ /* Update the per-vCPU cache */
+ mmio_hint[vcpu] = entry;
+ } else if (mmio_rb_lookup(&mmio_rb_fallback, paddr, &entry)) {
+ pthread_rwlock_unlock(&mmio_rwlock);
return (ESRCH);
-
- /* Update the per-vCPU cache */
- mmio_hint[vcpu] = entry;
+ }
}
- assert(entry != NULL && entry == mmio_hint[vcpu]);
-
+ assert(entry != NULL);
err = vmm_emulate_instruction(ctx, vcpu, paddr, vie,
mem_read, mem_write, &entry->mr_param);
+ pthread_rwlock_unlock(&mmio_rwlock);
+
return (err);
}
-int
-register_mem(struct mem_range *memp)
+static int
+register_mem_int(struct mmio_rb_tree *rbt, struct mem_range *memp)
{
- struct mmio_rb_range *mrp;
+ struct mmio_rb_range *entry, *mrp;
int err;
err = 0;
mrp = malloc(sizeof(struct mmio_rb_range));
-
+
if (mrp != NULL) {
mrp->mr_param = *memp;
mrp->mr_base = memp->base;
mrp->mr_end = memp->base + memp->size - 1;
-
- err = mmio_rb_add(mrp);
+ pthread_rwlock_wrlock(&mmio_rwlock);
+ if (mmio_rb_lookup(rbt, memp->base, &entry) != 0)
+ err = mmio_rb_add(rbt, mrp);
+ pthread_rwlock_unlock(&mmio_rwlock);
if (err)
free(mrp);
} else
@@ -210,9 +216,54 @@ register_mem(struct mem_range *memp)
return (err);
}
+int
+register_mem(struct mem_range *memp)
+{
+
+ return (register_mem_int(&mmio_rb_root, memp));
+}
+
+int
+register_mem_fallback(struct mem_range *memp)
+{
+
+ return (register_mem_int(&mmio_rb_fallback, memp));
+}
+
+int
+unregister_mem(struct mem_range *memp)
+{
+ struct mem_range *mr;
+ struct mmio_rb_range *entry = NULL;
+ int err, i;
+
+ pthread_rwlock_wrlock(&mmio_rwlock);
+ err = mmio_rb_lookup(&mmio_rb_root, memp->base, &entry);
+ if (err == 0) {
+ mr = &entry->mr_param;
+ assert(mr->name == memp->name);
+ assert(mr->base == memp->base && mr->size == memp->size);
+ RB_REMOVE(mmio_rb_tree, &mmio_rb_root, entry);
+
+ /* flush Per-vCPU cache */
+ for (i=0; i < VM_MAXCPU; i++) {
+ if (mmio_hint[i] == entry)
+ mmio_hint[i] = NULL;
+ }
+ }
+ pthread_rwlock_unlock(&mmio_rwlock);
+
+ if (entry)
+ free(entry);
+
+ return (err);
+}
+
void
init_mem(void)
{
- RB_INIT(&mmio_rbroot);
+ RB_INIT(&mmio_rb_root);
+ RB_INIT(&mmio_rb_fallback);
+ pthread_rwlock_init(&mmio_rwlock, NULL);
}
diff --git a/usr.sbin/bhyve/mem.h b/usr.sbin/bhyve/mem.h
index 88fafe1..264bff9 100644
--- a/usr.sbin/bhyve/mem.h
+++ b/usr.sbin/bhyve/mem.h
@@ -53,5 +53,7 @@ void init_mem(void);
int emulate_mem(struct vmctx *, int vcpu, uint64_t paddr, struct vie *vie);
int register_mem(struct mem_range *memp);
+int register_mem_fallback(struct mem_range *memp);
+int unregister_mem(struct mem_range *memp);
#endif /* _MEM_H_ */
diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c
index 52790f3..74db2ea 100644
--- a/usr.sbin/bhyve/mptbl.c
+++ b/usr.sbin/bhyve/mptbl.c
@@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
#define MPTABLE_BASE 0xF0000
+/* floating pointer length + maximum length of configuration table */
+#define MPTABLE_MAX_LENGTH (65536 + 16)
+
#define LAPIC_PADDR 0xFEE00000
#define LAPIC_VERSION 16
@@ -346,13 +349,13 @@ mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
char *curraddr;
char *startaddr;
- if (paddr_guest2host(0) == NULL) {
+ startaddr = paddr_guest2host(ctx, MPTABLE_BASE, MPTABLE_MAX_LENGTH);
+ if (startaddr == NULL) {
printf("mptable requires mapped mem\n");
return (ENOMEM);
}
- startaddr = curraddr = paddr_guest2host(MPTABLE_BASE);
-
+ curraddr = startaddr;
mpfp = (mpfps_t)curraddr;
mpt_build_mpfp(mpfp, MPTABLE_BASE);
curraddr += sizeof(*mpfp);
@@ -392,7 +395,7 @@ mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
}
mpch->base_table_length = curraddr - (char *)mpch;
- mpch->checksum = mpt_compute_checksum(mpch, sizeof(*mpch));
+ mpch->checksum = mpt_compute_checksum(mpch, mpch->base_table_length);
return (0);
}
diff --git a/usr.sbin/bhyve/pci_emul.c b/usr.sbin/bhyve/pci_emul.c
index 32a3deb..713e197 100644
--- a/usr.sbin/bhyve/pci_emul.c
+++ b/usr.sbin/bhyve/pci_emul.c
@@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/linker_set.h>
+#include <sys/errno.h>
#include <ctype.h>
#include <stdio.h>
@@ -38,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <strings.h>
#include <assert.h>
+#include <stdbool.h>
#include <machine/vmm.h>
#include <vmmapi.h>
@@ -86,6 +88,8 @@ static struct lirqinfo {
SET_DECLARE(pci_devemu_set, struct pci_devemu);
+static uint32_t pci_hole_startaddr;
+
static uint64_t pci_emul_iobase;
static uint64_t pci_emul_membase32;
static uint64_t pci_emul_membase64;
@@ -93,7 +97,6 @@ static uint64_t pci_emul_membase64;
#define PCI_EMUL_IOBASE 0x2000
#define PCI_EMUL_IOLIMIT 0x10000
-#define PCI_EMUL_MEMBASE32 (lomem_sz)
#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */
#define PCI_EMUL_MEMBASE64 0xD000000000UL
@@ -352,20 +355,150 @@ pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, enum pcibar_type type,
return (pci_emul_alloc_pbar(pdi, idx, 0, type, size));
}
+/*
+ * Register (or unregister) the MMIO or I/O region associated with the BAR
+ * register 'idx' of an emulated pci device.
+ */
+static void
+modify_bar_registration(struct pci_devinst *pi, int idx, int registration)
+{
+ int error;
+ struct inout_port iop;
+ struct mem_range mr;
+
+ switch (pi->pi_bar[idx].type) {
+ case PCIBAR_IO:
+ bzero(&iop, sizeof(struct inout_port));
+ iop.name = pi->pi_name;
+ iop.port = pi->pi_bar[idx].addr;
+ iop.size = pi->pi_bar[idx].size;
+ if (registration) {
+ iop.flags = IOPORT_F_INOUT;
+ iop.handler = pci_emul_io_handler;
+ iop.arg = pi;
+ error = register_inout(&iop);
+ } else
+ error = unregister_inout(&iop);
+ break;
+ case PCIBAR_MEM32:
+ case PCIBAR_MEM64:
+ bzero(&mr, sizeof(struct mem_range));
+ mr.name = pi->pi_name;
+ mr.base = pi->pi_bar[idx].addr;
+ mr.size = pi->pi_bar[idx].size;
+ if (registration) {
+ mr.flags = MEM_F_RW;
+ mr.handler = pci_emul_mem_handler;
+ mr.arg1 = pi;
+ mr.arg2 = idx;
+ error = register_mem(&mr);
+ } else
+ error = unregister_mem(&mr);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ assert(error == 0);
+}
+
+static void
+unregister_bar(struct pci_devinst *pi, int idx)
+{
+
+ modify_bar_registration(pi, idx, 0);
+}
+
+static void
+register_bar(struct pci_devinst *pi, int idx)
+{
+
+ modify_bar_registration(pi, idx, 1);
+}
+
+/* Are we decoding i/o port accesses for the emulated pci device? */
+static int
+porten(struct pci_devinst *pi)
+{
+ uint16_t cmd;
+
+ cmd = pci_get_cfgdata16(pi, PCIR_COMMAND);
+
+ return (cmd & PCIM_CMD_PORTEN);
+}
+
+/* Are we decoding memory accesses for the emulated pci device? */
+static int
+memen(struct pci_devinst *pi)
+{
+ uint16_t cmd;
+
+ cmd = pci_get_cfgdata16(pi, PCIR_COMMAND);
+
+ return (cmd & PCIM_CMD_MEMEN);
+}
+
+/*
+ * Update the MMIO or I/O address that is decoded by the BAR register.
+ *
+ * If the pci device has enabled the address space decoding then intercept
+ * the address range decoded by the BAR register.
+ */
+static void
+update_bar_address(struct pci_devinst *pi, uint64_t addr, int idx, int type)
+{
+ int decode;
+
+ if (pi->pi_bar[idx].type == PCIBAR_IO)
+ decode = porten(pi);
+ else
+ decode = memen(pi);
+
+ if (decode)
+ unregister_bar(pi, idx);
+
+ switch (type) {
+ case PCIBAR_IO:
+ case PCIBAR_MEM32:
+ pi->pi_bar[idx].addr = addr;
+ break;
+ case PCIBAR_MEM64:
+ pi->pi_bar[idx].addr &= ~0xffffffffUL;
+ pi->pi_bar[idx].addr |= addr;
+ break;
+ case PCIBAR_MEMHI64:
+ pi->pi_bar[idx].addr &= 0xffffffff;
+ pi->pi_bar[idx].addr |= addr;
+ break;
+ default:
+ assert(0);
+ }
+
+ if (decode)
+ register_bar(pi, idx);
+}
+
int
pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
enum pcibar_type type, uint64_t size)
{
- int i, error;
+ int error;
uint64_t *baseptr, limit, addr, mask, lobits, bar;
- struct inout_port iop;
- struct mem_range memp;
assert(idx >= 0 && idx <= PCI_BARMAX);
if ((size & (size - 1)) != 0)
size = 1UL << flsl(size); /* round up to a power of 2 */
+ /* Enforce minimum BAR sizes required by the PCI standard */
+ if (type == PCIBAR_IO) {
+ if (size < 4)
+ size = 4;
+ } else {
+ if (size < 16)
+ size = 16;
+ }
+
switch (type) {
case PCIBAR_NONE:
baseptr = NULL;
@@ -442,30 +575,7 @@ pci_emul_alloc_pbar(struct pci_devinst *pdi, int idx, uint64_t hostbase,
pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32);
}
- /* add a handler to intercept accesses to the I/O bar */
- if (type == PCIBAR_IO) {
- iop.name = pdi->pi_name;
- iop.flags = IOPORT_F_INOUT;
- iop.handler = pci_emul_io_handler;
- iop.arg = pdi;
-
- for (i = 0; i < size; i++) {
- iop.port = addr + i;
- register_inout(&iop);
- }
- } else if (type == PCIBAR_MEM32 || type == PCIBAR_MEM64) {
- /* add memory bar intercept handler */
- memp.name = pdi->pi_name;
- memp.flags = MEM_F_RW;
- memp.base = addr;
- memp.size = size;
- memp.handler = pci_emul_mem_handler;
- memp.arg1 = pdi;
- memp.arg2 = idx;
-
- error = register_mem(&memp);
- assert(error == 0);
- }
+ register_bar(pdi, idx);
return (0);
}
@@ -740,6 +850,38 @@ msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
CFGWRITE(pi, offset, val, bytes);
}
+void
+pciecap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
+ int bytes, uint32_t val)
+{
+
+ /* XXX don't write to the readonly parts */
+ CFGWRITE(pi, offset, val, bytes);
+}
+
+#define PCIECAP_VERSION 0x2
+int
+pci_emul_add_pciecap(struct pci_devinst *pi, int type)
+{
+ int err;
+ struct pciecap pciecap;
+
+ CTASSERT(sizeof(struct pciecap) == 60);
+
+ if (type != PCIEM_TYPE_ROOT_PORT)
+ return (-1);
+
+ bzero(&pciecap, sizeof(pciecap));
+
+ pciecap.capid = PCIY_EXPRESS;
+ pciecap.pcie_capabilities = PCIECAP_VERSION | PCIEM_TYPE_ROOT_PORT;
+ pciecap.link_capabilities = 0x411; /* gen1, x1 */
+ pciecap.link_status = 0x11; /* gen1, x1 */
+
+ err = pci_emul_add_capability(pi, (u_char *)&pciecap, sizeof(pciecap));
+ return (err);
+}
+
/*
* This function assumes that 'coff' is in the capabilities region of the
* config space.
@@ -782,6 +924,9 @@ pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val)
case PCIY_MSIX:
msixcap_cfgwrite(pi, capoff, offset, bytes, val);
break;
+ case PCIY_EXPRESS:
+ pciecap_cfgwrite(pi, capoff, offset, bytes, val);
+ break;
default:
break;
}
@@ -811,15 +956,34 @@ pci_emul_iscap(struct pci_devinst *pi, int offset)
return (found);
}
+static int
+pci_emul_fallback_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr,
+ int size, uint64_t *val, void *arg1, long arg2)
+{
+ /*
+ * Ignore writes; return 0xff's for reads. The mem read code
+ * will take care of truncating to the correct size.
+ */
+ if (dir == MEM_F_READ) {
+ *val = 0xffffffffffffffff;
+ }
+
+ return (0);
+}
+
void
init_pci(struct vmctx *ctx)
{
+ struct mem_range memp;
struct pci_devemu *pde;
struct slotinfo *si;
int slot, func;
+ int error;
+
+ pci_hole_startaddr = vm_get_lowmem_limit(ctx);
pci_emul_iobase = PCI_EMUL_IOBASE;
- pci_emul_membase32 = PCI_EMUL_MEMBASE32;
+ pci_emul_membase32 = pci_hole_startaddr;
pci_emul_membase64 = PCI_EMUL_MEMBASE64;
for (slot = 0; slot < MAXSLOTS; slot++) {
@@ -844,6 +1008,20 @@ init_pci(struct vmctx *ctx)
lirq[11].li_generic = 1;
lirq[12].li_generic = 1;
lirq[15].li_generic = 1;
+
+ /*
+ * Setup the PCI hole to return 0xff's when accessed in a region
+ * with no devices
+ */
+ memset(&memp, 0, sizeof(struct mem_range));
+ memp.name = "PCI hole";
+ memp.flags = MEM_F_RW;
+ memp.base = pci_hole_startaddr;
+ memp.size = (4ULL * 1024 * 1024 * 1024) - pci_hole_startaddr;
+ memp.handler = pci_emul_fallback_handler;
+
+ error = register_mem_fallback(&memp);
+ assert(error == 0);
}
int
@@ -1032,6 +1210,62 @@ pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
}
INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_OUT, pci_emul_cfgaddr);
+static uint32_t
+bits_changed(uint32_t old, uint32_t new, uint32_t mask)
+{
+
+ return ((old ^ new) & mask);
+}
+
+static void
+pci_emul_cmdwrite(struct pci_devinst *pi, uint32_t new, int bytes)
+{
+ int i;
+ uint16_t old;
+
+ /*
+ * The command register is at an offset of 4 bytes and thus the
+ * guest could write 1, 2 or 4 bytes starting at this offset.
+ */
+
+ old = pci_get_cfgdata16(pi, PCIR_COMMAND); /* stash old value */
+ CFGWRITE(pi, PCIR_COMMAND, new, bytes); /* update config */
+ new = pci_get_cfgdata16(pi, PCIR_COMMAND); /* get updated value */
+
+ /*
+ * 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++) {
+ switch (pi->pi_bar[i].type) {
+ case PCIBAR_NONE:
+ case PCIBAR_MEMHI64:
+ break;
+ case PCIBAR_IO:
+ /* I/O address space decoding changed? */
+ if (bits_changed(old, new, PCIM_CMD_PORTEN)) {
+ if (porten(pi))
+ register_bar(pi, i);
+ else
+ unregister_bar(pi, i);
+ }
+ break;
+ case PCIBAR_MEM32:
+ case PCIBAR_MEM64:
+ /* MMIO address space decoding changed? */
+ if (bits_changed(old, new, PCIM_CMD_MEMEN)) {
+ if (memen(pi))
+ register_bar(pi, i);
+ else
+ unregister_bar(pi, i);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ }
+}
+
static int
pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
uint32_t *eax, void *arg)
@@ -1039,7 +1273,7 @@ pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
struct pci_devinst *pi;
struct pci_devemu *pe;
int coff, idx, needcfg;
- uint64_t mask, bar;
+ uint64_t addr, bar, mask;
assert(bytes == 1 || bytes == 2 || bytes == 4);
@@ -1106,33 +1340,48 @@ pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
if (bytes != 4 || (coff & 0x3) != 0)
return (0);
idx = (coff - PCIR_BAR(0)) / 4;
+ mask = ~(pi->pi_bar[idx].size - 1);
switch (pi->pi_bar[idx].type) {
case PCIBAR_NONE:
- bar = 0;
+ pi->pi_bar[idx].addr = bar = 0;
break;
case PCIBAR_IO:
- mask = ~(pi->pi_bar[idx].size - 1);
- mask &= PCIM_BAR_IO_BASE;
- bar = (*eax & mask) | PCIM_BAR_IO_SPACE;
+ addr = *eax & mask;
+ addr &= 0xffff;
+ bar = addr | PCIM_BAR_IO_SPACE;
+ /*
+ * Register the new BAR value for interception
+ */
+ if (addr != pi->pi_bar[idx].addr) {
+ update_bar_address(pi, addr, idx,
+ PCIBAR_IO);
+ }
break;
case PCIBAR_MEM32:
- mask = ~(pi->pi_bar[idx].size - 1);
- mask &= PCIM_BAR_MEM_BASE;
- bar = *eax & mask;
+ addr = bar = *eax & mask;
bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32;
+ if (addr != pi->pi_bar[idx].addr) {
+ update_bar_address(pi, addr, idx,
+ PCIBAR_MEM32);
+ }
break;
case PCIBAR_MEM64:
- mask = ~(pi->pi_bar[idx].size - 1);
- mask &= PCIM_BAR_MEM_BASE;
- bar = *eax & mask;
+ addr = bar = *eax & mask;
bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 |
PCIM_BAR_MEM_PREFETCH;
+ if (addr != (uint32_t)pi->pi_bar[idx].addr) {
+ update_bar_address(pi, addr, idx,
+ PCIBAR_MEM64);
+ }
break;
case PCIBAR_MEMHI64:
mask = ~(pi->pi_bar[idx - 1].size - 1);
- mask &= PCIM_BAR_MEM_BASE;
- bar = ((uint64_t)*eax << 32) & mask;
- bar = bar >> 32;
+ addr = ((uint64_t)*eax << 32) & mask;
+ bar = addr >> 32;
+ if (bar != pi->pi_bar[idx - 1].addr >> 32) {
+ update_bar_address(pi, addr, idx - 1,
+ PCIBAR_MEMHI64);
+ }
break;
default:
assert(0);
@@ -1141,6 +1390,8 @@ pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
} else if (pci_emul_iscap(pi, coff)) {
pci_emul_capwrite(pi, coff, bytes, *eax);
+ } else if (coff == PCIR_COMMAND) {
+ pci_emul_cmdwrite(pi, *eax, bytes);
} else {
CFGWRITE(pi, coff, *eax, bytes);
}
diff --git a/usr.sbin/bhyve/pci_emul.h b/usr.sbin/bhyve/pci_emul.h
index 8c6260c..db218bb 100644
--- a/usr.sbin/bhyve/pci_emul.h
+++ b/usr.sbin/bhyve/pci_emul.h
@@ -105,7 +105,6 @@ struct pci_devinst {
uint8_t pi_bus, pi_slot, pi_func;
uint8_t pi_lintr_pin;
char pi_name[PI_NAMESZ];
- uint16_t pi_iobase;
int pi_bar_getsize;
struct {
@@ -150,6 +149,40 @@ struct msixcap {
uint32_t pba_info; /* bar index and offset within it */
} __packed;
+struct pciecap {
+ uint8_t capid;
+ uint8_t nextptr;
+ uint16_t pcie_capabilities;
+
+ uint32_t dev_capabilities; /* all devices */
+ uint16_t dev_control;
+ uint16_t dev_status;
+
+ uint32_t link_capabilities; /* devices with links */
+ uint16_t link_control;
+ uint16_t link_status;
+
+ uint32_t slot_capabilities; /* ports with slots */
+ uint16_t slot_control;
+ uint16_t slot_status;
+
+ uint16_t root_control; /* root ports */
+ uint16_t root_capabilities;
+ uint32_t root_status;
+
+ uint32_t dev_capabilities2; /* all devices */
+ uint16_t dev_control2;
+ uint16_t dev_status2;
+
+ uint32_t link_capabilities2; /* devices with links */
+ uint16_t link_control2;
+ uint16_t link_status2;
+
+ uint32_t slot_capabilities2; /* ports with slots */
+ uint16_t slot_control2;
+ uint16_t slot_status2;
+} __packed;
+
void init_pci(struct vmctx *ctx);
void msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset,
int bytes, uint32_t val);
@@ -161,6 +194,7 @@ int pci_emul_alloc_bar(struct pci_devinst *pdi, int idx,
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);
diff --git a/usr.sbin/bhyve/pci_hostbridge.c b/usr.sbin/bhyve/pci_hostbridge.c
index c77762d..dee0a47 100644
--- a/usr.sbin/bhyve/pci_hostbridge.c
+++ b/usr.sbin/bhyve/pci_hostbridge.c
@@ -42,6 +42,8 @@ pci_hostbridge_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE);
pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_HOST);
+ pci_emul_add_pciecap(pi, PCIEM_TYPE_ROOT_PORT);
+
return (0);
}
diff --git a/usr.sbin/bhyve/pci_passthru.c b/usr.sbin/bhyve/pci_passthru.c
index 08a9a58..43c542d 100644
--- a/usr.sbin/bhyve/pci_passthru.c
+++ b/usr.sbin/bhyve/pci_passthru.c
@@ -279,6 +279,7 @@ msix_table_read(struct passthru_softc *sc, uint64_t offset, int size)
int index;
pi = sc->psc_pi;
+ offset -= pi->pi_msix.table_offset;
index = offset / MSIX_TABLE_ENTRY_SIZE;
if (index >= pi->pi_msix.table_count)
@@ -323,6 +324,8 @@ 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;
+
index = offset / MSIX_TABLE_ENTRY_SIZE;
if (index >= pi->pi_msix.table_count)
return;
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
index c8fc914..a325e97 100644
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -110,8 +110,9 @@ CTASSERT(sizeof(struct vtblk_config) == VTBLK_CFGSZ);
* Fixed-size block header
*/
struct virtio_blk_hdr {
-#define VBH_OP_READ 0
-#define VBH_OP_WRITE 1
+#define VBH_OP_READ 0
+#define VBH_OP_WRITE 1
+#define VBH_FLAG_BARRIER 0x80000000 /* OR'ed into vbh_type */
uint32_t vbh_type;
uint32_t vbh_ioprio;
uint64_t vbh_sector;
@@ -140,6 +141,7 @@ struct pci_vtblk_softc {
uint16_t msix_table_idx_req;
uint16_t msix_table_idx_cfg;
};
+#define vtblk_ctx(sc) ((sc)->vbsc_pi->pi_vmctx)
/*
* Return the size of IO BAR that maps virtio header and device specific
@@ -163,14 +165,19 @@ pci_vtblk_iosize(struct pci_devinst *pi)
static int
hq_num_avail(struct vring_hqueue *hq)
{
- int ndesc;
+ uint16_t ndesc;
- if (*hq->hq_avail_idx >= hq->hq_cur_aidx)
- ndesc = *hq->hq_avail_idx - hq->hq_cur_aidx;
- else
- ndesc = UINT16_MAX - hq->hq_cur_aidx + *hq->hq_avail_idx + 1;
+ /*
+ * We're just computing (a-b) in GF(216).
+ *
+ * The only glitch here is that in standard C,
+ * uint16_t promotes to (signed) int when int has
+ * more than 16 bits (pretty much always now), so
+ * we have to force it back to unsigned.
+ */
+ ndesc = (unsigned)*hq->hq_avail_idx - (unsigned)hq->hq_cur_aidx;
- assert(ndesc >= 0 && ndesc <= hq->hq_size);
+ assert(ndesc <= hq->hq_size);
return (ndesc);
}
@@ -198,7 +205,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
int iolen;
int nsegs;
int uidx, aidx, didx;
- int writeop;
+ int writeop, type;
off_t offset;
uidx = *hq->hq_used_idx;
@@ -221,18 +228,25 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
assert(nsegs >= 3);
assert(nsegs < VTBLK_MAXSEGS + 2);
- vid = paddr_guest2host(vd->vd_addr);
+ vid = paddr_guest2host(vtblk_ctx(sc), vd->vd_addr, vd->vd_len);
assert((vid->vd_flags & VRING_DESC_F_INDIRECT) == 0);
/*
* The first descriptor will be the read-only fixed header
*/
- vbh = paddr_guest2host(vid[0].vd_addr);
+ vbh = paddr_guest2host(vtblk_ctx(sc), vid[0].vd_addr,
+ sizeof(struct virtio_blk_hdr));
assert(vid[0].vd_len == sizeof(struct virtio_blk_hdr));
assert(vid[0].vd_flags & VRING_DESC_F_NEXT);
assert((vid[0].vd_flags & VRING_DESC_F_WRITE) == 0);
- writeop = (vbh->vbh_type == VBH_OP_WRITE);
+ /*
+ * XXX
+ * The guest should not be setting the BARRIER flag because
+ * we don't advertise the capability.
+ */
+ type = vbh->vbh_type & ~VBH_FLAG_BARRIER;
+ writeop = (type == VBH_OP_WRITE);
offset = vbh->vbh_sector * DEV_BSIZE;
@@ -240,7 +254,8 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
* Build up the iovec based on the guest's data descriptors
*/
for (i = 1, iolen = 0; i < nsegs - 1; i++) {
- iov[i-1].iov_base = paddr_guest2host(vid[i].vd_addr);
+ iov[i-1].iov_base = paddr_guest2host(vtblk_ctx(sc),
+ vid[i].vd_addr, vid[i].vd_len);
iov[i-1].iov_len = vid[i].vd_len;
iolen += vid[i].vd_len;
@@ -258,7 +273,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
}
/* Lastly, get the address of the status byte */
- status = paddr_guest2host(vid[nsegs - 1].vd_addr);
+ status = paddr_guest2host(vtblk_ctx(sc), vid[nsegs - 1].vd_addr, 1);
assert(vid[nsegs - 1].vd_len == 1);
assert((vid[nsegs - 1].vd_flags & VRING_DESC_F_NEXT) == 0);
assert(vid[nsegs - 1].vd_flags & VRING_DESC_F_WRITE);
@@ -334,7 +349,8 @@ pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
hq = &sc->vbsc_q;
hq->hq_size = VTBLK_RINGSZ;
- hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
+ hq->hq_dtable = paddr_guest2host(vtblk_ctx(sc), pfn << VRING_PFN,
+ vring_size(VTBLK_RINGSZ));
hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
hq->hq_avail_idx = hq->hq_avail_flags + 1;
hq->hq_avail_ring = hq->hq_avail_flags + 2;
@@ -365,13 +381,6 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
}
/*
- * Access to guest memory is required. Fail if
- * memory not mapped
- */
- if (paddr_guest2host(0) == NULL)
- return (1);
-
- /*
* The supplied backing file has to exist
*/
fd = open(opts, O_RDWR);
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
index 327ebf7..783c45e 100644
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -148,6 +148,7 @@ struct pci_vtnet_softc {
struct vring_hqueue vsc_hq[VTNET_MAXQ];
uint16_t vsc_msix_table_idx[VTNET_MAXQ];
};
+#define vtnet_ctx(sc) ((sc)->vsc_pi->pi_vmctx)
/*
* Return the size of IO BAR that maps virtio header and device specific
@@ -170,14 +171,19 @@ pci_vtnet_iosize(struct pci_devinst *pi)
static int
hq_num_avail(struct vring_hqueue *hq)
{
- int ndesc;
+ uint16_t ndesc;
- if (*hq->hq_avail_idx >= hq->hq_cur_aidx)
- ndesc = *hq->hq_avail_idx - hq->hq_cur_aidx;
- else
- ndesc = UINT16_MAX - hq->hq_cur_aidx + *hq->hq_avail_idx + 1;
+ /*
+ * We're just computing (a-b) in GF(216).
+ *
+ * The only glitch here is that in standard C,
+ * uint16_t promotes to (signed) int when int has
+ * more than 16 bits (pretty much always now), so
+ * we have to force it back to unsigned.
+ */
+ ndesc = (unsigned)*hq->hq_avail_idx - (unsigned)hq->hq_cur_aidx;
- assert(ndesc >= 0 && ndesc <= hq->hq_size);
+ assert(ndesc <= hq->hq_size);
return (ndesc);
}
@@ -326,7 +332,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc *sc)
* Get a pointer to the rx header, and use the
* data immediately following it for the packet buffer.
*/
- vrx = (struct virtio_net_rxhdr *)paddr_guest2host(vd->vd_addr);
+ vrx = paddr_guest2host(vtnet_ctx(sc), vd->vd_addr, vd->vd_len);
buf = (uint8_t *)(vrx + 1);
len = read(sc->vsc_tapfd, buf,
@@ -434,7 +440,8 @@ pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vring_hqueue *hq)
for (i = 0, plen = 0;
i < VTNET_MAXSEGS;
i++, vd = &hq->hq_dtable[vd->vd_next]) {
- iov[i].iov_base = paddr_guest2host(vd->vd_addr);
+ iov[i].iov_base = paddr_guest2host(vtnet_ctx(sc),
+ vd->vd_addr, vd->vd_len);
iov[i].iov_len = vd->vd_len;
plen += vd->vd_len;
tlen += vd->vd_len;
@@ -517,7 +524,8 @@ pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn)
hq = &sc->vsc_hq[qnum];
hq->hq_size = pci_vtnet_qsize(qnum);
- hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
+ hq->hq_dtable = paddr_guest2host(vtnet_ctx(sc), pfn << VRING_PFN,
+ vring_size(hq->hq_size));
hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
hq->hq_avail_idx = hq->hq_avail_flags + 1;
hq->hq_avail_ring = hq->hq_avail_flags + 2;
@@ -541,13 +549,6 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
struct pci_vtnet_softc *sc;
const char *env_msi;
- /*
- * Access to guest memory is required. Fail if
- * memory not mapped
- */
- if (paddr_guest2host(0) == NULL)
- return (1);
-
sc = malloc(sizeof(struct pci_vtnet_softc));
memset(sc, 0, sizeof(struct pci_vtnet_softc));
diff --git a/usr.sbin/bhyve/pmtmr.c b/usr.sbin/bhyve/pmtmr.c
index b85b0a7..c8fbd62 100644
--- a/usr.sbin/bhyve/pmtmr.c
+++ b/usr.sbin/bhyve/pmtmr.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpufunc.h>
#include <stdio.h>
+#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <pthread.h>
@@ -53,35 +54,108 @@ __FBSDID("$FreeBSD$");
#define PMTMR_FREQ 3579545 /* 3.579545MHz */
static pthread_mutex_t pmtmr_mtx;
-static uint64_t pmtmr_tscf;
+
static uint64_t pmtmr_old;
+
+static uint64_t pmtmr_tscf;
static uint64_t pmtmr_tsc_old;
+static clockid_t clockid = CLOCK_UPTIME_FAST;
+static struct timespec pmtmr_uptime_old;
+
+#define timespecsub(vvp, uvp) \
+ do { \
+ (vvp)->tv_sec -= (uvp)->tv_sec; \
+ (vvp)->tv_nsec -= (uvp)->tv_nsec; \
+ if ((vvp)->tv_nsec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_nsec += 1000000000; \
+ } \
+ } while (0)
+
+static uint64_t
+timespec_to_pmtmr(const struct timespec *tsnew, const struct timespec *tsold)
+{
+ struct timespec tsdiff;
+ int64_t nsecs;
+
+ tsdiff = *tsnew;
+ timespecsub(&tsdiff, tsold);
+ nsecs = tsdiff.tv_sec * 1000000000 + tsdiff.tv_nsec;
+ assert(nsecs >= 0);
+
+ return (nsecs * PMTMR_FREQ / 1000000000 + pmtmr_old);
+}
+
+static uint64_t
+tsc_to_pmtmr(uint64_t tsc_new, uint64_t tsc_old)
+{
+
+ return ((tsc_new - tsc_old) * PMTMR_FREQ / pmtmr_tscf + pmtmr_old);
+}
+
+static void
+pmtmr_init(void)
+{
+ size_t len;
+ int smp_tsc, err;
+ struct timespec tsnew, tsold = { 0 };
+
+ len = sizeof(smp_tsc);
+ err = sysctlbyname("kern.timecounter.smp_tsc", &smp_tsc, &len, NULL, 0);
+ assert(err == 0);
+
+ if (smp_tsc) {
+ len = sizeof(pmtmr_tscf);
+ err = sysctlbyname("machdep.tsc_freq", &pmtmr_tscf, &len,
+ NULL, 0);
+ assert(err == 0);
+
+ pmtmr_tsc_old = rdtsc();
+ pmtmr_old = tsc_to_pmtmr(pmtmr_tsc_old, 0);
+ } else {
+ if (getenv("BHYVE_PMTMR_PRECISE") != NULL)
+ clockid = CLOCK_UPTIME;
+
+ err = clock_gettime(clockid, &tsnew);
+ assert(err == 0);
+
+ pmtmr_uptime_old = tsnew;
+ pmtmr_old = timespec_to_pmtmr(&tsnew, &tsold);
+ }
+}
+
static uint32_t
pmtmr_val(void)
{
+ struct timespec tsnew;
uint64_t pmtmr_tsc_new;
uint64_t pmtmr_new;
+ int error;
+
static int inited = 0;
if (!inited) {
- size_t len;
-
- inited = 1;
pthread_mutex_init(&pmtmr_mtx, NULL);
- len = sizeof(pmtmr_tscf);
- sysctlbyname("machdep.tsc_freq", &pmtmr_tscf, &len,
- NULL, 0);
- pmtmr_tsc_old = rdtsc();
- pmtmr_old = pmtmr_tsc_old / pmtmr_tscf * PMTMR_FREQ;
+ pmtmr_init();
+ inited = 1;
}
pthread_mutex_lock(&pmtmr_mtx);
- pmtmr_tsc_new = rdtsc();
- pmtmr_new = (pmtmr_tsc_new - pmtmr_tsc_old) * PMTMR_FREQ / pmtmr_tscf +
- pmtmr_old;
+
+ if (pmtmr_tscf) {
+ pmtmr_tsc_new = rdtsc();
+ pmtmr_new = tsc_to_pmtmr(pmtmr_tsc_new, pmtmr_tsc_old);
+ pmtmr_tsc_old = pmtmr_tsc_new;
+ } else {
+ error = clock_gettime(clockid, &tsnew);
+ assert(error == 0);
+
+ pmtmr_new = timespec_to_pmtmr(&tsnew, &pmtmr_uptime_old);
+ pmtmr_uptime_old = tsnew;
+ }
pmtmr_old = pmtmr_new;
- pmtmr_tsc_old = pmtmr_tsc_new;
+
pthread_mutex_unlock(&pmtmr_mtx);
return (pmtmr_new);
@@ -102,4 +176,3 @@ pmtmr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
}
INOUT_PORT(pmtmr, IO_PMTMR, IOPORT_F_IN, pmtmr_handler);
-
diff --git a/usr.sbin/bhyve/uart.c b/usr.sbin/bhyve/uart.c
deleted file mode 100644
index 640f3bf..0000000
--- a/usr.sbin/bhyve/uart.c
+++ /dev/null
@@ -1,60 +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 <assert.h>
-
-#include "inout.h"
-
-#define COM1 0x3F8
-#define COM2 0x2F8
-
-#define REG_IIR 2
-
-static int
-com_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
- uint32_t *eax, void *arg)
-{
- assert(in);
-
- if (bytes != 1)
- return (-1);
-
- /*
- * COM port is not implemented so we return 0xFF for all registers
- */
- *eax = 0xFF;
-
- return (0);
-}
-
-INOUT_PORT(uart, COM1 + REG_IIR, IOPORT_F_IN, com_handler);
-INOUT_PORT(uart, COM2 + REG_IIR, IOPORT_F_IN, com_handler);
diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h
index 04ef586..fe6fb1a 100644
--- a/usr.sbin/bhyve/virtio.h
+++ b/usr.sbin/bhyve/virtio.h
@@ -85,4 +85,19 @@ struct virtio_used {
#define VTCFG_R_CFG1 24 /* With MSI-X */
#define VTCFG_R_MSIX 20
+/* From section 2.3, "Virtqueue Configuration", of the virtio specification */
+static inline u_int
+vring_size(u_int qsz)
+{
+ u_int size;
+
+ size = sizeof(struct virtio_desc) * qsz + sizeof(uint16_t) * (3 + qsz);
+ size = roundup2(size, VRING_ALIGN);
+
+ size += sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz;
+ size = roundup2(size, VRING_ALIGN);
+
+ return (size);
+}
+
#endif /* _VIRTIO_H_ */
diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c
index 35e1388..438d01c 100644
--- a/usr.sbin/bhyvectl/bhyvectl.c
+++ b/usr.sbin/bhyvectl/bhyvectl.c
@@ -183,13 +183,11 @@ usage(void)
" [--get-vmcs-exit-interruption-info]\n"
" [--get-vmcs-exit-interruption-error]\n"
" [--get-vmcs-interruptibility]\n"
- " [--set-pinning=<host_cpuid>]\n"
- " [--get-pinning]\n"
" [--set-x2apic-state=<state>]\n"
" [--get-x2apic-state]\n"
- " [--set-lowmem=<memory below 4GB in units of MB>]\n"
+ " [--unassign-pptdev=<bus/slot/func>]\n"
+ " [--set-mem=<memory in units of MB>]\n"
" [--get-lowmem]\n"
- " [--set-highmem=<memory above 4GB in units of MB>]\n"
" [--get-highmem]\n",
progname);
exit(1);
@@ -198,7 +196,7 @@ usage(void)
static int get_stats, getcap, setcap, capval;
static const char *capname;
static int create, destroy, get_lowmem, get_highmem;
-static uint64_t lowmem, highmem;
+static uint64_t memsize;
static int set_cr0, get_cr0, set_cr3, get_cr3, set_cr4, get_cr4;
static int set_efer, get_efer;
static int set_dr7, get_dr7;
@@ -218,9 +216,9 @@ static int set_desc_tr, get_desc_tr;
static int set_desc_ldtr, get_desc_ldtr;
static int set_cs, set_ds, set_es, set_fs, set_gs, set_ss, set_tr, set_ldtr;
static int get_cs, get_ds, get_es, get_fs, get_gs, get_ss, get_tr, get_ldtr;
-static int set_pinning, get_pinning, pincpu;
static int set_x2apic_state, get_x2apic_state;
enum x2apic_state x2apic_state;
+static int unassign_pptdev, bus, slot, func;
static int run;
/*
@@ -352,8 +350,7 @@ vm_set_vmcs_field(struct vmctx *ctx, int vcpu, int field, uint64_t val)
enum {
VMNAME = 1000, /* avoid collision with return values from getopt */
VCPU,
- SET_LOWMEM,
- SET_HIGHMEM,
+ SET_MEM,
SET_EFER,
SET_CR0,
SET_CR3,
@@ -374,12 +371,12 @@ enum {
SET_SS,
SET_TR,
SET_LDTR,
- SET_PINNING,
SET_X2APIC_STATE,
SET_VMCS_EXCEPTION_BITMAP,
SET_VMCS_ENTRY_INTERRUPTION_INFO,
SET_CAP,
CAPNAME,
+ UNASSIGN_PPTDEV,
};
int
@@ -401,8 +398,7 @@ main(int argc, char *argv[])
struct option opts[] = {
{ "vm", REQ_ARG, 0, VMNAME },
{ "cpu", REQ_ARG, 0, VCPU },
- { "set-lowmem", REQ_ARG, 0, SET_LOWMEM },
- { "set-highmem",REQ_ARG, 0, SET_HIGHMEM },
+ { "set-mem", REQ_ARG, 0, SET_MEM },
{ "set-efer", REQ_ARG, 0, SET_EFER },
{ "set-cr0", REQ_ARG, 0, SET_CR0 },
{ "set-cr3", REQ_ARG, 0, SET_CR3 },
@@ -423,13 +419,13 @@ main(int argc, char *argv[])
{ "set-ss", REQ_ARG, 0, SET_SS },
{ "set-tr", REQ_ARG, 0, SET_TR },
{ "set-ldtr", REQ_ARG, 0, SET_LDTR },
- { "set-pinning",REQ_ARG, 0, SET_PINNING },
{ "set-x2apic-state",REQ_ARG, 0, SET_X2APIC_STATE },
{ "set-vmcs-exception-bitmap",
REQ_ARG, 0, SET_VMCS_EXCEPTION_BITMAP },
{ "set-vmcs-entry-interruption-info",
REQ_ARG, 0, SET_VMCS_ENTRY_INTERRUPTION_INFO },
{ "capname", REQ_ARG, 0, CAPNAME },
+ { "unassign-pptdev", REQ_ARG, 0, UNASSIGN_PPTDEV },
{ "setcap", REQ_ARG, 0, SET_CAP },
{ "getcap", NO_ARG, &getcap, 1 },
{ "get-stats", NO_ARG, &get_stats, 1 },
@@ -552,7 +548,6 @@ main(int argc, char *argv[])
NO_ARG, &get_vmcs_exit_interruption_error, 1},
{ "get-vmcs-interruptibility",
NO_ARG, &get_vmcs_interruptibility, 1 },
- { "get-pinning",NO_ARG, &get_pinning, 1 },
{ "get-x2apic-state",NO_ARG, &get_x2apic_state, 1 },
{ "get-all", NO_ARG, &get_all, 1 },
{ "run", NO_ARG, &run, 1 },
@@ -574,13 +569,9 @@ main(int argc, char *argv[])
case VCPU:
vcpu = atoi(optarg);
break;
- case SET_LOWMEM:
- lowmem = atoi(optarg) * MB;
- lowmem = roundup(lowmem, 2 * MB);
- break;
- case SET_HIGHMEM:
- highmem = atoi(optarg) * MB;
- highmem = roundup(highmem, 2 * MB);
+ case SET_MEM:
+ memsize = atoi(optarg) * MB;
+ memsize = roundup(memsize, 2 * MB);
break;
case SET_EFER:
efer = strtoul(optarg, NULL, 0);
@@ -659,10 +650,6 @@ main(int argc, char *argv[])
ldtr = strtoul(optarg, NULL, 0);
set_ldtr = 1;
break;
- case SET_PINNING:
- pincpu = strtol(optarg, NULL, 0);
- set_pinning = 1;
- break;
case SET_X2APIC_STATE:
x2apic_state = strtol(optarg, NULL, 0);
set_x2apic_state = 1;
@@ -682,6 +669,11 @@ main(int argc, char *argv[])
case CAPNAME:
capname = optarg;
break;
+ case UNASSIGN_PPTDEV:
+ unassign_pptdev = 1;
+ if (sscanf(optarg, "%d/%d/%d", &bus, &slot, &func) != 3)
+ usage();
+ break;
default:
usage();
}
@@ -703,11 +695,8 @@ main(int argc, char *argv[])
error = -1;
}
- if (!error && lowmem)
- error = vm_setup_memory(ctx, 0, lowmem, NULL);
-
- if (!error && highmem)
- error = vm_setup_memory(ctx, 4 * GB, highmem, NULL);
+ if (!error && memsize)
+ error = vm_setup_memory(ctx, memsize, VM_MMAP_NONE);
if (!error && set_efer)
error = vm_set_register(ctx, vcpu, VM_REG_GUEST_EFER, efer);
@@ -812,12 +801,12 @@ main(int argc, char *argv[])
if (!error && set_ldtr)
error = vm_set_register(ctx, vcpu, VM_REG_GUEST_LDTR, ldtr);
- if (!error && set_pinning)
- error = vm_set_pinning(ctx, vcpu, pincpu);
-
if (!error && set_x2apic_state)
error = vm_set_x2apic_state(ctx, vcpu, x2apic_state);
+ if (!error && unassign_pptdev)
+ error = vm_unassign_pptdev(ctx, bus, slot, func);
+
if (!error && set_exception_bitmap) {
error = vm_set_vmcs_field(ctx, vcpu, VMCS_EXCEPTION_BITMAP,
exception_bitmap);
@@ -992,7 +981,7 @@ main(int argc, char *argv[])
printf("vcpu%d\n", vcpu);
for (i = 0; i < num_stats; i++) {
desc = vm_get_stat_desc(ctx, i);
- printf("%-32s\t%ld\n", desc, stats[i]);
+ printf("%-40s\t%ld\n", desc, stats[i]);
}
}
}
@@ -1135,16 +1124,6 @@ main(int argc, char *argv[])
printf("ldtr[%d]\t\t0x%04lx\n", vcpu, ldtr);
}
- if (!error && (get_pinning || get_all)) {
- error = vm_get_pinning(ctx, vcpu, &pincpu);
- if (error == 0) {
- if (pincpu < 0)
- printf("pincpu[%d]\tunpinned\n", vcpu);
- else
- printf("pincpu[%d]\t%d\n", vcpu, pincpu);
- }
- }
-
if (!error && (get_x2apic_state || get_all)) {
error = vm_get_x2apic_state(ctx, vcpu, &x2apic_state);
if (error == 0)
diff --git a/usr.sbin/bhyveload/bhyveload.8 b/usr.sbin/bhyveload/bhyveload.8
index 4a05116..f2e5e35 100644
--- a/usr.sbin/bhyveload/bhyveload.8
+++ b/usr.sbin/bhyveload/bhyveload.8
@@ -35,8 +35,7 @@
guest inside a bhyve virtual machine
.Sh SYNOPSIS
.Nm
-.Op Fl m Ar lowmem
-.Op Fl M Ar highmem
+.Op Fl m Ar mem-size
.Op Fl d Ar disk-path
.Op Fl h Ar host-path
.Ar vmname
@@ -61,22 +60,13 @@ and will be created if it does not already exist.
.Sh OPTIONS
The following options are available:
.Bl -tag -width indent
-.It Fl m Ar lowmem
-.Ar lowmem
-is the amount of memory allocated below 4GB in the guest's physical address
-space.
+.It Fl m Ar mem-size
+.Ar mem-size
+is the amount of memory allocated to the guest in units of megabytes.
.Pp
The default value of
-.Ar lowmem
-is 256MB.
-.It Fl M Ar highmem
-.Ar highmem
-is the amount of memory allocated above 4GB in the guest's physical address
-space.
-.Pp
-The default value of
-.Ar highmem
-is 0MB.
+.Ar mem-size
+is 256.
.It Fl d Ar disk-path
The
.Ar disk-path
@@ -93,16 +83,7 @@ that boots off the ISO image
.Pa /freebsd/release.iso
and has 1GB memory allocated to it:
.Pp
-.Dl "bhyveload -m 256 -M 768 -d /freebsd/release.iso freebsd-vm"
-.Pp
-In the example above the 1GB allocation is split in two segments:
-.Pp
-.Bl -dash -compact
-.It
-256MB below the 4GB boundary (0MB - 256MB)
-.It
-768MB above the 4GB boundary (4096MB - 4864MB)
-.El
+.Dl "bhyveload -m 1024 -d /freebsd/release.iso freebsd-vm"
.Sh SEE ALSO
.Xr bhyve 4 ,
.Xr bhyve 8 ,
diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c
index ef12d9f..4cd280c 100644
--- a/usr.sbin/bhyveload/bhyveload.c
+++ b/usr.sbin/bhyveload/bhyveload.c
@@ -88,8 +88,7 @@ static char *host_base = "/";
static struct termios term, oldterm;
static int disk_fd = -1;
-static char *vmname, *progname, *membase;
-static uint64_t lowmem, highmem;
+static char *vmname, *progname;
static struct vmctx *ctx;
static uint64_t gdtbase, cr3, rsp;
@@ -323,30 +322,30 @@ cb_diskioctl(void *arg, int unit, u_long cmd, void *data)
static int
cb_copyin(void *arg, const void *from, uint64_t to, size_t size)
{
+ char *ptr;
to &= 0x7fffffff;
- if (to > lowmem)
- return (EFAULT);
- if (to + size > lowmem)
- size = lowmem - to;
- memcpy(&membase[to], from, size);
+ ptr = vm_map_gpa(ctx, to, size);
+ if (ptr == NULL)
+ return (EFAULT);
+ memcpy(ptr, from, size);
return (0);
}
static int
cb_copyout(void *arg, uint64_t from, void *to, size_t size)
{
+ char *ptr;
from &= 0x7fffffff;
- if (from > lowmem)
- return (EFAULT);
- if (from + size > lowmem)
- size = lowmem - from;
- memcpy(to, &membase[from], size);
+ ptr = vm_map_gpa(ctx, from, size);
+ if (ptr == NULL)
+ return (EFAULT);
+ memcpy(to, ptr, size);
return (0);
}
@@ -493,8 +492,8 @@ static void
cb_getmem(void *arg, uint64_t *ret_lowmem, uint64_t *ret_highmem)
{
- *ret_lowmem = lowmem;
- *ret_highmem = highmem;
+ vm_get_memory_seg(ctx, 0, ret_lowmem);
+ vm_get_memory_seg(ctx, 4 * GB, ret_highmem);
}
static const char *
@@ -551,9 +550,9 @@ static void
usage(void)
{
- printf("usage: %s [-d <disk image path>] [-h <host filesystem path>] "
- "[-m <lowmem>][-M <highmem>] "
- "<vmname>\n", progname);
+ fprintf(stderr,
+ "usage: %s [-m mem-size][-d <disk-path>] [-h <host-path>] "
+ "<vmname>\n", progname);
exit(1);
}
@@ -562,16 +561,16 @@ main(int argc, char** argv)
{
void *h;
void (*func)(struct loader_callbacks *, void *, int, int);
+ uint64_t mem_size;
int opt, error;
char *disk_image;
progname = argv[0];
- lowmem = 128 * MB;
- highmem = 0;
+ mem_size = 256 * MB;
disk_image = NULL;
- while ((opt = getopt(argc, argv, "d:h:m:M:")) != -1) {
+ while ((opt = getopt(argc, argv, "d:h:m:")) != -1) {
switch (opt) {
case 'd':
disk_image = optarg;
@@ -582,13 +581,9 @@ main(int argc, char** argv)
break;
case 'm':
- lowmem = strtoul(optarg, NULL, 0) * MB;
+ mem_size = strtoul(optarg, NULL, 0) * MB;
break;
- case 'M':
- highmem = strtoul(optarg, NULL, 0) * MB;
- break;
-
case '?':
usage();
}
@@ -615,20 +610,12 @@ main(int argc, char** argv)
exit(1);
}
- error = vm_setup_memory(ctx, 0, lowmem, &membase);
+ error = vm_setup_memory(ctx, mem_size, VM_MMAP_ALL);
if (error) {
- perror("vm_setup_memory(lowmem)");
+ perror("vm_setup_memory");
exit(1);
}
- if (highmem != 0) {
- error = vm_setup_memory(ctx, 4 * GB, highmem, NULL);
- if (error) {
- perror("vm_setup_memory(highmem)");
- exit(1);
- }
- }
-
tcgetattr(0, &term);
oldterm = term;
term.c_lflag &= ~(ICANON|ECHO);
diff --git a/usr.sbin/bluetooth/ath3kfw/ath3kfw.c b/usr.sbin/bluetooth/ath3kfw/ath3kfw.c
index 02d4501..37191d1 100644
--- a/usr.sbin/bluetooth/ath3kfw/ath3kfw.c
+++ b/usr.sbin/bluetooth/ath3kfw/ath3kfw.c
@@ -59,6 +59,9 @@ static int download_firmware (struct libusb20_device *dev,
char const *firmware);
static void usage (void);
+static int vendor_id = ATH3KFW_VENDOR_ID;
+static int product_id = ATH3KFW_PRODUCT_ID;
+
/*
* Firmware downloader for Atheros AR3011 based USB Bluetooth devices
*/
@@ -78,7 +81,7 @@ main(int argc, char **argv)
addr = 0;
firmware = ATH3KFW_FW;
- while ((n = getopt(argc, argv, "d:f:h")) != -1) {
+ while ((n = getopt(argc, argv, "d:f:hp:v:")) != -1) {
switch (n) {
case 'd': /* ugen device name */
if (parse_ugen_name(optarg, &bus, &addr) < 0)
@@ -88,7 +91,12 @@ main(int argc, char **argv)
case 'f': /* firmware file */
firmware = optarg;
break;
-
+ case 'p': /* product id */
+ product_id = strtol(optarg, NULL, 0);
+ break;
+ case 'v': /* vendor id */
+ vendor_id = strtol(optarg, NULL, 0);
+ break;
case 'h':
default:
usage();
@@ -166,8 +174,8 @@ find_device(struct libusb20_backend *be, uint8_t bus, uint8_t addr,
if (desc == NULL)
continue;
- if (desc->idVendor != ATH3KFW_VENDOR_ID ||
- desc->idProduct != ATH3KFW_PRODUCT_ID)
+ if (desc->idVendor != vendor_id ||
+ desc->idProduct != product_id)
continue;
break;
@@ -280,6 +288,8 @@ usage(void)
"Where:\n" \
"\t-d ugenX.Y ugen device name\n" \
"\t-f firmware image firmware image file name for download\n" \
+"\t-v vendor_id vendor id\n" \
+"\t-p vendor_id product id\n" \
"\t-h display this message\n", ATH3KFW, ATH3KFW);
exit(255);
diff --git a/usr.sbin/bluetooth/l2ping/l2ping.8 b/usr.sbin/bluetooth/l2ping/l2ping.8
index 703b0bd..73774ec 100644
--- a/usr.sbin/bluetooth/l2ping/l2ping.8
+++ b/usr.sbin/bluetooth/l2ping/l2ping.8
@@ -63,7 +63,7 @@ If this option is not specified,
.Nm
will operate until interrupted.
.It Fl f
-Don't wait between sending each packet.
+Do not wait between sending each packet.
.It Fl h
Display usage message and exit.
.It Fl i Ar wait
diff --git a/usr.sbin/bsdconfig/include/Makefile b/usr.sbin/bsdconfig/include/Makefile
index cb4b1b6..ee21cec 100644
--- a/usr.sbin/bsdconfig/include/Makefile
+++ b/usr.sbin/bsdconfig/include/Makefile
@@ -3,7 +3,8 @@
NO_OBJ=
FILESDIR= ${LIBEXECDIR}/bsdconfig/include
-FILES= bsdconfig.hlp messages.subr usage.hlp
+FILES= bsdconfig.hlp media.hlp messages.subr network_device.hlp \
+ options.hlp tcp.hlp usage.hlp
beforeinstall:
mkdir -p ${DESTDIR}${FILESDIR}
diff --git a/usr.sbin/bsdconfig/include/media.hlp b/usr.sbin/bsdconfig/include/media.hlp
new file mode 100644
index 0000000..6df5b03
--- /dev/null
+++ b/usr.sbin/bsdconfig/include/media.hlp
@@ -0,0 +1,48 @@
+You can install from the following types of media:
+
+ CDROM requires one of the following supported CDROM drives:
+ ATAPI - Any standard ATAPI CDROM drive hooked to
+ a supported controller (see Hardware Guide).
+ SCSI - Any standard SCSI CDROM drive hooked to
+ a supported controller (see Hardware Guide).
+
+
+ DOS A DOS primary partition with the required FreeBSD
+ distribution files copied onto it (e.g. C:\FREEBSD\)
+
+
+ UFS Assuming a disk or partition with an existing
+ FreeBSD file system and distribution set on it,
+ get the distribution files from there.
+
+
+ Floppy Get distribution files from one or more DOS or UFS
+ formatted floppies. Such floppies are assumed to
+ contain the appropriate distribution pieces - see
+ ABOUT.TXT for more information about making floppy
+ distribution media.
+
+
+ FTP Get the distribution files from an anonymous ftp server
+ (you will be presented with a list). Please note that
+ you may invoke FTP in "Active" mode, "Passive" mode, or
+ via an HTTP proxy.
+
+ Active mode is the standard way of fetching files and
+ Passive mode is for use when you're behind a firewall or
+ some other security mechanism that blocks active FTP
+ connections. Using an HTTP proxy is sometimes necessary
+ for firewalls which block all FTP connections.
+
+ If you chose to enter your own URL in the FTP menu, please
+ note that all paths are *relative* to the home directory
+ of the user being logged in as. By default, this is the
+ user "ftp" (anonymous ftp) but you may change this in the
+ Options screen.
+
+
+ NFS Get the distribution files from an NFS server somewhere
+ (make sure that permissions on the server allow this!).
+ If this install method hangs on you or refuses to work
+ properly, you may need to set some special options for
+ your NFS server. See the Options screen for more details.
diff --git a/usr.sbin/bsdconfig/include/messages.subr b/usr.sbin/bsdconfig/include/messages.subr
index dc7c246..82afb6d 100644
--- a/usr.sbin/bsdconfig/include/messages.subr
+++ b/usr.sbin/bsdconfig/include/messages.subr
@@ -1,5 +1,5 @@
# Copyright (c) 2012 Ron McDowell
-# Copyright (c) 2012 Devin Teske
+# Copyright (c) 2012-2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -27,39 +27,251 @@
field_username="Username:"
field_password="Password:"
+hline_alnum_arrows_punc_tab_enter="Use alnum, arrows, punctuation, TAB or ENTER"
hline_alnum_punc_tab_enter="Use alpha-numeric, punctuation, TAB or ENTER"
hline_arrows_tab_enter="Press arrows, TAB or ENTER"
+hline_choose_help_for_more_information_on_media_types="Choose Help for more information on the various media types"
+msg_accept_continue="Accept/Continue"
msg_always_try_sudo_when_run_as="Always try sudo(8) when run as %s"
+msg_argentina="Argentina"
+msg_assume_network_is_already_configured="Running multi-user, assume that the network is already configured?"
+msg_attempt_automatic_dhcp_configuration="Attempt automatic DHCP configuration of interfaces"
+msg_attempt_ipv6_configuration_of_interfaces="Attempt IPv6 configuration of interfaces"
+msg_australia="Australia"
+msg_austria="Austria"
msg_becoming_root_via_sudo="Becoming root via sudo(8)..."
+msg_brazil="Brazil"
+msg_canada="Canada"
msg_cancel="Cancel"
msg_cancel_exit="Cancel/Exit"
msg_cannot_create_permission_denied="%s: cannot create %s: Permission denied"
+msg_cannot_resolve_hostname="Cannot resolve \`%s'! Are you sure that your\nname server, gateway and network interface are correctly configured?"
+msg_cant_find_distribution="Warning: Can't find the \`%s' distribution on this\nFTP server. You may need to visit a different server for\nthe release you are trying to fetch or go to the Options\nmenu and set the release name to explicitly match what's\navailable on %s (or set to \"any\").\n\nWould you like to select another FTP server?"
+msg_cant_seem_to_write_out_resolv_conf="Can't seem to write out %s. Net cannot be used."
+msg_cd_dvd="CD/DVD"
+msg_cdrom="CDROM"
+msg_checking_access_to="Checking access to\n %s"
+msg_china="China"
+msg_choose_a_cd_dvd_type="Choose a CD/DVD type"
+msg_choose_a_dos_partition="Choose a DOS partition"
+msg_choose_a_floppy_drive="Choose a Floppy drive"
+msg_choose_a_ufs_partition="Choose a UFS partition"
+msg_choose_a_usb_partition="Choose a USB drive"
+msg_choose_installation_media="Choose Installation Media"
+msg_choose_installation_media_description="FreeBSD can be installed from a variety of different installation\nmedia, ranging from floppies to an Internet FTP server. If you're\ninstalling FreeBSD from a supported CD/DVD drive then this is generally\nthe best media to use if you have no overriding reason for using other\nmedia."
+msg_client_error="Client error, you could try an other server"
msg_command_failed_rest_of_script_aborted="Command \`%s' failed - rest of script aborted."
+msg_configuration_for_interface="Configuration for Interface"
+msg_could_not_unmount_the_cdrom_dvd="Could not unmount the CDROM/DVD from %s: %s"
+msg_could_not_unmount_the_dos_partition="Could not unmount the DOS partition from %s: %s"
+msg_could_not_unmount_the_nfs_partition="Could not unmount the NFS partition from %s: %s"
+msg_could_not_unmount_the_ufs_partition="Could not unmount the UFS partition from %s: %s"
+msg_couldnt_connect_to_proxy="Couldn't connect to proxy"
+msg_couldnt_connect_to_ftp_server="Couldn't connect to FTP server"
+msg_couldnt_open_ftp_connection="Couldn't open FTP connection to %s:\n %s."
msg_created_path="Created %s"
+msg_croatia="Croatia"
+msg_czech_republic="Czech Republic"
+msg_debugging="Debugging"
+msg_denmark="Denmark"
+msg_device_is_not_configured="The %s device is not configured. You will need to do so\nin the Networking configuration menu before proceeding."
+msg_dhcp="DHCP"
+msg_dialog_mixedform_navigation_help="Use <up>/<down> arrows to navigate between fields, TAB to focus buttons, and Enter for OK/Cancel."
+msg_directory="Directory"
msg_directory_not_found="%s: Directory not found."
+msg_done="Done"
+msg_dos="DOS"
+msg_editor="Editor"
+msg_emit_extra_debugging_output="Emit extra debugging output"
+msg_enter_a_fully_qualified_pathname_for_the_directory="Enter a fully qualified pathname for the directory\ncontaining the FreeBSD distribution files:"
+msg_enter_the_device_name_of_a_ufs_formatted_partition="Enter the device-name of a UFS formatted partition"
+msg_error="Error"
+msg_error_mounting_device="Error mounting %s on %s: %s"
+msg_error_mounting_floppy_device="Error mounting floppy %s (%s) on %s: %s"
+msg_error_mounting_usb_drive="Error mounting USB drive %s on %s: %s"
+msg_error_when_requesting_url="Error when requesting %s, you could try an other server"
+msg_estonia="Estonia"
msg_exit="Exit"
msg_exit_bsdconfig="Exit bsdconfig"
+msg_extra_options_to_ifconfig="Extra options to ifconfig (usually empty):"
+msg_failed_to_add_default_route="Failed to add a default route; please check your network configuration"
+msg_file_system="File System"
+msg_finland="Finland"
+msg_floppy="Floppy"
+msg_france="France"
+msg_ftp="FTP"
+msg_ftp_passive="FTP Passive"
+msg_ftp_username="FTP username"
+msg_germany="Germany"
+msg_greece="Greece"
+msg_help="Help"
+msg_host_name_including_domain="Host name (including domain)"
+msg_hostname_variable_not_set="WARNING: hostname variable not set and is a non-optional\nparameter. Please add this to your installation script\nor set the netInteractive variable (see bsdconfig man page)"
+msg_http="HTTP"
+msg_http_proxy="HTTP Proxy"
+msg_hungary="Hungary"
+msg_iceland="Iceland"
+msg_install_from_a_dos_partition="Install from a DOS partition"
+msg_install_from_a_floppy_disk_set="Install from a floppy disk set"
+msg_install_from_a_freebsd_cd_dvd="Install from a FreeBSD CD/DVD"
+msg_install_from_a_usb_drive="Install from a USB drive"
+msg_install_from_a_ufs_partition="Install from a UFS partition"
+msg_install_from_an_ftp_server="Install from an FTP server"
+msg_install_from_an_ftp_server_thru_firewall="Install from an FTP server through a firewall"
+msg_install_from_an_ftp_server_thru_proxy="Install from an FTP server through an HTTP proxy"
+msg_install_from_the_existing_filesystem="Install from the existing filesystem"
+msg_install_over_nfs="Install over NFS"
+msg_invalid_gateway_ipv4_address_specified="Invalid gateway IPv4 address specified"
+msg_invalid_hostname_value="Invalid hostname value"
+msg_invalid_ipv4_address="Invalid IPv4 address"
+msg_invalid_name_server_ip_address_specified="Invalid name server IP address specified"
+msg_invalid_netmask_value="Invalid netmask value"
+msg_invalid_nfs_path_specification="Invalid NFS path specification. Must be of the form:\nhost:/full/pathname/to/FreeBSD/distdir"
+msg_ipv4_address="IPv4 Address"
+msg_ipv4_gateway="IPv4 Gateway"
+msg_ipv6="IPv6"
+msg_ipv6_ready="IPv6 ready"
+msg_ireland="Ireland"
+msg_israel="Israel"
+msg_italy="Italy"
+msg_japan="Japan"
+msg_korea="Korea"
+msg_lithuania="Lithuania"
+msg_length_of_specified_url_is_too_long="Length of specified URL is %u characters. Allowable maximum is %u."
+msg_logging_in_to_user_at_host="Logging in to %s@%s.."
+msg_looking_up_host="Looking up host %s"
msg_main_menu="Main Menu"
+msg_main_site="Main Site"
+msg_media_timeout="Media Timeout"
+msg_media_type="Media Type"
msg_menu_text="If you've already installed FreeBSD, you may use\nthis menu to customize it somewhat to suit your\nparticular configuration. Most importantly, you\ncan use the Packages utility to load extra '3rd\nparty' software not provided in the base\ndistributions."
+msg_missing_ftp_host_or_directory="Missing FTP host or directory specification. FTP media not initialized."
msg_must_be_root_to_execute="%s: must be root to execute"
+msg_must_specify_a_host_name_of_some_sort="Must specify a host name of some sort!"
+msg_name_server="Name server"
+msg_net_device_init_failed="Net device init failed."
+msg_netmask="Netmask"
+msg_netherlands="Netherlands"
+msg_network_configuration="Network Configuration"
+msg_network_interface_information_required="Network interface information required"
msg_nfailed_attempts="%u incorrect password attempts"
+msg_nfs="NFS"
+msg_nfs_secure="NFS Secure"
+msg_nfs_server_talks_only_on_a_secure_port="NFS server talks only on a secure port"
+msg_nfs_slow="NFS Slow"
+msg_nfs_tcp="NFS TCP"
+msg_nfs_version_3="NFS version 3"
msg_no="No"
+msg_no_cd_dvd_devices_found="No CD/DVD devices found! Please check that your system's\nconfiguration is correct and that the CD/DVD drive is of a\nsupported type. For more information, consult the hardware\nguide in the Doc menu."
+msg_no_dos_primary_partitions_found="No DOS primary partitions found! This installation method is unavailable"
+msg_no_floppy_devices_found="No floppy devices found! Please check that your system's configuration\nis correct. For more information, consult the hardware guide in the Doc\nmenu."
+msg_no_gateway_has_been_set="No gateway has been set. You will be unable to access hosts\nnot on your local network"
+msg_no_network_devices="No network devices available!"
msg_no_such_file_or_directory="%s: %s: No such file or directory"
+msg_no_usb_devices_found="No USB devices found (try Options/Re-scan Devices)"
msg_no_username="No username provided!"
+msg_norway="Norway"
+msg_not_a_directory="%s: %s: Not a directory"
msg_not_found="not found"
+msg_not_yet_set="not yet set"
msg_ok="OK"
+msg_options="Options"
+msg_options_editor="Options Editor"
+msg_other="other"
msg_permission_denied="%s: %s: Permission denied"
+msg_please_check_the_url_and_try_again="No such directory: %s\nplease check the URL and try again."
msg_please_enter_password="Please enter your password for sudo(8):"
msg_please_enter_username_password="Please enter a username and password for sudo(8):"
+msg_please_enter_the_address_of_the_http_proxy="Please enter the address of the HTTP proxy in this format:\n hostname:port (the ':port' is optional, default is 3128)"
+msg_please_enter_the_full_nfs_file_specification="Please enter the full NFS file specification for the remote\nhost and directory containing the FreeBSD distribution files.\nThis should be in the format: hostname:/some/freebsd/dir"
+msg_please_enter_the_password_for_this_user="Please enter the password for this user:"
+msg_please_enter_the_username_you_wish_to_login_as="Please enter the username you wish to login as:"
+msg_please_insert_floppy_in_drive="Please insert floppy in %s"
+msg_please_insert_floppy_containing="Please insert floppy containing %s in %s"
+msg_please_select_a_cd_dvd_drive="FreeBSD can be installed directly from a CD/DVD containing a valid\nFreeBSD distribution. If you are seeing this menu it is because\nmore than one CD/DVD drive was found on your system. Please select\none of the following CD/DVD drives as your installation drive."
+msg_please_select_a_floppy_drive="You have more than one floppy drive. Please choose which drive\nyou would like to use."
+msg_please_select_a_freebsd_ftp_distribution_site="Please select a FreeBSD FTP distribution site"
+msg_please_select_dos_partition="FreeBSD can be installed directly from a DOS partition assuming,\nof course, that you have copied the relevant distributions into\nyour DOS partition before starting this installation. If this is\nnot the case then you should reboot DOS at this time and copy the\ndistributions you wish to install into a \"FREEBSD\" subdirectory\non one of your DOS partitions. Otherwise, please select the DOS\npartition containing the FreeBSD distribution files."
+msg_please_select_ufs_partition="FreeBSD can be installed directly from another FreeBSD partition\nthat is UFS formatted assuming, of course, that you have copied\nthe relevant distributions into said partition before starting\ninstallation."
+msg_please_select_a_usb_drive="You have more than one USB drive. Please choose which drive\nyou would like to use."
+msg_please_select_ethernet_device_to_configure="Please select the ethernet or PLIP device to configure."
+msg_please_select_the_site_closest_to_you_or_other="Please select the site closest to you or \"other\" if you'd like to\nspecify a different choice. Also note that not every site listed here\ncarries more than the base distribution kits. Only Primary sites are\nguaranteed to carry the full range of possible distributions."
+msg_please_specify_the_name_of_the_text_editor="Please specify the name of the text editor you wish to use:"
+msg_please_specify_the_number_of_seconds_to_wait="Please specify the number of seconds to wait for slow media:"
+msg_please_specify_the_release_you_wish_to_load="Please specify the release you wish to load or\n\"any\" for a generic release install:"
+msg_please_specify_url_of_a_freebsd_distribution="Please specify the URL of a FreeBSD distribution on a\nremote ftp site. This site must accept either anonymous\nftp or you should have set an ftp username and password\nin the Options screen.\n\nA URL looks like this: ftp://<hostname>/<path>\nWhere <path> is relative to the anonymous ftp directory or the\nhome directory of the user being logged in as."
+msg_poland="Poland"
+msg_portugal="Portugal"
msg_previous_syntax_errors="%s: Not overwriting \`%s' due to previous syntax errors"
+msg_primary="Primary"
+msg_probing_devices_please_wait_this_can_take_a_while="Probing devices, please wait (this can take a while)..."
msg_quick_start_how_to_use_this_menu_system="Quick start - How to use this menu system"
+msg_release_name="Release Name"
+msg_rerun_bsdconfig_initial_device_probe="Re-run bsdconfig initial device probe"
+msg_rescan_devices="Re-scan Devices"
+msg_reset="RESET!"
+msg_reset_all_values_to_startup_defaults="Reset all values to startup defaults"
+msg_reuse_old_ftp_site_selection_values="Re-use old FTP site selection values?"
+msg_romania="Romania"
+msg_russia="Russia"
+msg_scanning_for_dhcp_servers="Scanning for DHCP servers..."
+msg_scanning_for_ra_servers="Scanning for RA servers..."
msg_secure_mode_requires_x11="Secure-mode requires X11 (use \`-X')!"
msg_secure_mode_requires_root="Secure-mode requires root-access!"
+msg_select_a_site_thats_close="Select a site that's close!"
+msg_server_error_when_requesting_url="Server error when requesting %s, you could try an other server"
+msg_singapore="Singapore"
+msg_slovak_republic="Slovak Republic"
+msg_slovenia="Slovenia"
+msg_snapshots_server_japan="Snapshots Server Japan"
+msg_snapshots_server_sweden="Snapshots Server Sweden"
+msg_sorry_invalid_url="Sorry, %s is an invalid URL!"
msg_sorry_try_again="Sorry, try again."
+msg_south_africa="South Africa"
+msg_spain="Spain"
+msg_specify_some_other_ftp_site="Specify some other ftp site by URL"
+msg_sweden="Sweden"
+msg_switzerland="Switzerland"
+msg_taiwan="Taiwan"
+msg_the_current_installation_media_type="The current installation media type."
+msg_timeout_value_in_seconds_for_slow_media="Timeout value in seconds for slow media."
+msg_try_dhcp_configuration="Do you want to try DHCP configuration of the interface?"
+msg_try_ipv6_configuration="Do you want to try IPv6 configuration of the interface?"
msg_try_sudo_only_this_once="Try sudo(8) only this once"
+msg_turkey="Turkey"
+msg_ufs="UFS"
+msg_uk="UK"
+msg_ukraine="Ukraine"
+msg_unable_to_configure_device="Unable to configure the %s interface!\nThis installation method cannot be used."
+msg_unable_to_get_proper_ftp_path="Unable to get proper FTP path. FTP media not initialized."
+msg_unable_to_make_directory_mountpoint="Unable to make %s directory mountpoint for %s!"
msg_unable_to_open="Unable to open %s"
+msg_unknown="unknown"
msg_unknown_user="Unknown user: %s"
+msg_url_was_not_found="%s was not found, maybe directory or release-version are wrong?"
+msg_usa="USA"
msg_usage="Usage"
+msg_usb="USB"
+msg_use_defaults="Use Defaults"
+msg_use_nfs_version_3="Use NFS version 3"
+msg_use_tcp_protocol_for_nfs="Use TCP protocol for NFS"
msg_user_disallowed="User disallowed: %s"
+msg_user_is_using_a_slow_pc_or_ethernet_card="User is using a slow PC or Ethernet card"
+msg_username_and_password_to_use="Username and password to use instead of anonymous"
+msg_using_interface="Using interface %s"
+msg_using_usb_device="Using USB device: %s"
+msg_view_set_various_media_options="View/Set various media options"
+msg_which_release_to_attempt_to_load="Which release to attempt to load from installation media"
+msg_which_text_editor_to_use="Which text editor to use during installation"
+msg_would_you_like_to_bring_interface_up="Would you like to bring the %s interface up right now?"
msg_yes="Yes"
msg_you_are_not_root_but="You are not root but %s can use sudo(8).\nWhat would you like to do?"
+msg_you_may_remove_the_floppy="You may remove the floppy from %s"
+msg_youve_already_done_the_network_configuration="You've already done the network configuration once,\nwould you like to skip over it now?"
+tcplayout_extras_help="Any interface-specific options to ifconfig you would like to add"
+tcplayout_extras_help_for_plip="For PLIP configuration, you must enter the peer's IP address here."
+tcplayout_gateway_help="IPv4 address of host forwarding packets to non-local destinations"
+tcplayout_hostname_help="Your fully-qualified hostname, e.g. foo.example.com"
+tcplayout_ipaddr_help="The IPv4 address to be used for this interface"
+tcplayout_nameserver_help="IPv4 or IPv6 address of your local DNS server"
+tcplayout_netmask_help="The netmask for this interface, e.g. 255.255.255.0 for a class C network"
diff --git a/usr.sbin/bsdconfig/include/network_device.hlp b/usr.sbin/bsdconfig/include/network_device.hlp
new file mode 100644
index 0000000..affa86a
--- /dev/null
+++ b/usr.sbin/bsdconfig/include/network_device.hlp
@@ -0,0 +1,58 @@
+You can do network installations over 3 types of communications links:
+
+ Serial port: SLIP / PPP
+ Parallel port: PLIP (laplink cable)
+ Ethernet: A standard Ethernet controller (includes some
+ PCMCIA networking cards).
+
+SLIP support is rather primitive and limited primarily to directly
+connected links, such as a serial cable running between a laptop
+computer and another PC. The link must be hard-wired as the SLIP
+installation doesn't currently offer a dialing capability (that
+facility is offered by the PPP utility, which should be used in
+preference to SLIP whenever possible). When you choose the SLIP
+option, you'll be given the option of later editing the slattach
+command before it's run on the serial line. It is expected that
+you'll run slattach (or some equivalent command) on the other end of
+the link at that time and bring up the line. FreeBSD will then
+install itself at serial speeds of up to 115.2K/baud (the recommended
+speed for a hardwired cable).
+
+If you're using a modem then PPP is almost certainly your only choice.
+Make sure that you have your service provider's information handy as
+you'll need to know it fairly early in the installation process. You
+will need to know your service provider's IP address, the IP address
+of your provider's DNS server, and possibly your own IP address unless
+your ISP supports dynamic negotiation, most do. If you do not choose
+a PAP or CHAP login you will also need to know how to use the various
+"AT commands" to dial the ISP with your particular brand of modem as
+the PPP dialer provides only a very simple terminal emulator and has no
+"modem capabilities database". If you choose a PAP or CHAP login you
+can simply enter `dial' (without the quotes) at the ppp prompt if your
+modem uses the Hayes compatible AT command set.
+
+If a hard-wired connection to another FreeBSD (2.0R or later) machine
+is available, you might also consider installing over a "laplink"
+parallel port cable. The data rate over the parallel port is much
+higher than what is typically possible over a serial line, and speeds
+of over 50KB/sec are not uncommon.
+
+Finally, for the fastest possible network installation, an Ethernet
+adaptor is always a good choice! FreeBSD supports most common PC
+Ethernet cards, a table of which is provided in the FreeBSD Hardware
+Guide (see the `Documentation' entry in the main menu). If you are
+using one of the supported PCMCIA Ethernet cards, also be sure that
+it's plugged in BEFORE the laptop is powered on! Sysinstall does not,
+unfortunately, currently support "hot insertion" of PCMCIA cards.
+
+You will also need to know your IP address on the network, the
+"netmask" value for your address class, and the name of your machine.
+Your system administrator can tell you which values to use for your
+particular network setup. If you will be referring to other hosts by
+name rather than IP address, you'll also need a name server and
+possibly the address of a gateway (if you're using PPP, it's your
+provider's IP address) to use in talking to it. If you do not know
+the answers to all or most of these questions then you should really
+probably talk to your system administrator FIRST before trying this
+type of installation! Choosing the wrong IP address on a busy network
+will NOT make you popular with your systems administrator! :-)
diff --git a/usr.sbin/bsdconfig/include/options.hlp b/usr.sbin/bsdconfig/include/options.hlp
new file mode 100644
index 0000000..674e48d
--- /dev/null
+++ b/usr.sbin/bsdconfig/include/options.hlp
@@ -0,0 +1,98 @@
+The following options may be set from this screen.
+
+NFS Secure: NFS server talks only on a secure port
+
+ This is most commonly used when talking to Sun workstations, which
+ will not talk NFS over "non privileged" ports.
+
+
+NFS Slow: User is using a slow PC or Ethernet card
+
+ Use this option if you have a slow PC (386) or an Ethernet card
+ with poor performance being "fed" by NFS on a higher-performance
+ workstation. This will throttle the workstation back to prevent
+ the PC from becoming swamped with data.
+
+
+NFS TCP: Use TCP for the NFS mount
+
+ This option can be used if your NFS server supports TCP
+ connections; not all do! This may be useful if your NFS server
+ is at a remote site in which case it may offer some additional
+ stability.
+
+
+NFS version 3: Use NFS version 3
+
+ This option forces the use of NFS version 3 and is on by default.
+ If your NFS server only supports NFS version 2, disable this option.
+
+
+Debugging: Turn on the extra debugging flag
+
+ This turns on a lot of extra noise in between dialogs (unless
+ debugFile has been set, sending the data to a logfile instead).
+ Optionally, if debugFile begins with a plus sign (`+'), output will
+ occur both on standard output and to debugFile (minus leading plus).
+ If your installation should fail for any reason, PLEASE turn this
+ flag on when attempting to reproduce the problem. It will provide a
+ lot of extra debugging at the failure point and may be very helpful
+ to the developers in tracking such problems down!
+
+
+DHCP: Enable DHCP configuration of interfaces
+
+ This option specifies whether DHCP configuration of interfaces
+ may be attempted. The default setting is to interactively ask
+ the user.
+
+
+IPv6: Enable IPv6 router solicitation configuration
+
+ This option specifies whether automatic configuration of IPv6
+ interfaces may be attempted. This uses the router solicitation
+ method of automatic configuration. The default setting is to
+ interactively ask the user.
+
+
+FTP username: Specify username and password instead of anonymous.
+
+ By default, the installation attempts to log in as the
+ anonymous user. If you wish to log in as someone else,
+ specify the username and password with this option.
+
+
+Editor: Specify which screen editor to use.
+
+ At various points during the installation it may be necessary
+ to customize some text file, at which point the user will be
+ thrown unceremoniously into a screen editor. A relatively
+ simplistic editor which shows its command set on-screen is
+ selected by default, but UNIX purists may wish to change this
+ setting to `/usr/bin/vi'.
+
+
+Release Name: Which release to attempt to load from installation media.
+
+ You should only change this option if you're really sure you know
+ what you are doing! This will change the release name used by
+ bsdconfig when fetching components of any distributions, and
+ is a useful way of using a more recent installation boot floppy
+ with an older release (say, on CDROM).
+
+
+Media Type: Which media type is being used.
+
+ This is mostly informational and indicates which media type (if any)
+ was last selected in the Media menu. It's also a convenient short-cut
+ to the media menu itself.
+
+
+Re-scan Devices:
+
+ Reprobe the system for devices.
+
+
+Use Defaults: Use default values.
+
+ Reset all options back to their default values.
diff --git a/usr.sbin/bsdconfig/networking/include/tcp.hlp b/usr.sbin/bsdconfig/include/tcp.hlp
index 6d0ba10..6d0ba10 100644
--- a/usr.sbin/bsdconfig/networking/include/tcp.hlp
+++ b/usr.sbin/bsdconfig/include/tcp.hlp
diff --git a/usr.sbin/bsdconfig/networking/devices b/usr.sbin/bsdconfig/networking/devices
index 443294f..f9c27b4 100755
--- a/usr.sbin/bsdconfig/networking/devices
+++ b/usr.sbin/bsdconfig/networking/devices
@@ -1,6 +1,6 @@
#!/bin/sh
#-
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,7 @@ f_dprintf "%s: loading includes..." "$0"
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/mustberoot.subr
f_include $BSDCFG_SHARE/sysrc.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
f_include $BSDCFG_SHARE/networking/device.subr
f_include $BSDCFG_SHARE/networking/ipaddr.subr
f_include $BSDCFG_SHARE/networking/media.subr
diff --git a/usr.sbin/bsdconfig/networking/include/Makefile b/usr.sbin/bsdconfig/networking/include/Makefile
index be6cacb..c93d486 100644
--- a/usr.sbin/bsdconfig/networking/include/Makefile
+++ b/usr.sbin/bsdconfig/networking/include/Makefile
@@ -3,7 +3,7 @@
NO_OBJ=
FILESDIR= ${LIBEXECDIR}/bsdconfig/120.networking/include
-FILES= messages.subr tcp.hlp
+FILES= messages.subr
beforeinstall:
mkdir -p ${DESTDIR}${FILESDIR}
diff --git a/usr.sbin/bsdconfig/networking/share/common.subr b/usr.sbin/bsdconfig/networking/share/common.subr
index e501a9c..1a37a9c 100644
--- a/usr.sbin/bsdconfig/networking/share/common.subr
+++ b/usr.sbin/bsdconfig/networking/share/common.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_COMMON_SUBR" ]; then _NETWORKING_COMMON_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,17 +33,6 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
############################################################ FUNCTIONS
-# f_mounted $local_directory
-#
-# Return success if a filesystem is mounted on a particular directory.
-#
-f_mounted()
-{
- local dir="$1"
- [ -d "$dir" ] || return $FAILURE
- mount | grep -Eq " on $dir \([^)]+\)$"
-}
-
# f_jailed
#
# Returns true if the current process is jail(8)ed.
diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr
index 23ac83b..cac8ef5 100644
--- a/usr.sbin/bsdconfig/networking/share/device.subr
+++ b/usr.sbin/bsdconfig/networking/share/device.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -31,8 +31,10 @@ if [ ! "$_NETWORKING_DEVICE_SUBR" ]; then _NETWORKING_DEVICE_SUBR=1
BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." networking/device.subr
+f_include $BSDCFG_SHARE/device.subr
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/sysrc.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
f_include $BSDCFG_SHARE/networking/common.subr
f_include $BSDCFG_SHARE/networking/ipaddr.subr
f_include $BSDCFG_SHARE/networking/media.subr
@@ -43,8 +45,6 @@ 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
-TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp
-
############################################################ GLOBALS
#
@@ -55,133 +55,6 @@ TCP_HELPFILE=$BSDCFG_LIBE/$APP_DIR/include/tcp.hlp
############################################################ FUNCTIONS
-# f_device_desc $device_name
-#
-# Print a description for a device name (eg., `fxp0').
-#
-f_device_desc()
-{
- local device="$1" d="[1234567890]" desc=""
-
- # Check variables
- [ "$device" ] || return $SUCCESS
-
- #
- # Return sysctl MIB dev.NAME.UNIT.%desc if it exists,
- # otherwise fall through to below static list.
- #
- if f_have sysctl; then
- local devname devunit
- devname="${device%%$d*}"
- devunit="${device#$devname}"
- devunit="${devunit%%[a-zA-Z_]*}"
- sysctl -n "dev.$devname.$devunit.%desc" 2> /dev/null &&
- return $SUCCESS
- fi
-
- case "$device" in
- # Network devices
- ae$d) desc="Attansic/Atheros L2 Fast Ethernet";;
- age$d) desc="Attansic/Atheros L1 Gigabit Ethernet";;
- alc$d) desc="Atheros AR8131/AR8132 PCIe Ethernet";;
- ale$d) desc="Atheros AR8121/AR8113/AR8114 PCIe Ethernet";;
- an$d) desc="Aironet 4500/4800 802.11 wireless adapter";;
- ath$d) desc="Atheros IEEE 802.11 wireless adapter";;
- aue$d) desc="ADMtek USB Ethernet adapter";;
- axe$d) desc="ASIX Electronics USB Ethernet adapter";;
- bce$d) desc="Broadcom NetXtreme II Gigabit Ethernet card";;
- bfe$d) desc="Broadcom BCM440x PCI Ethernet card";;
- bge$d) desc="Broadcom BCM570x PCI Gigabit Ethernet card";;
- bm$d) desc="Apple BMAC Built-in Ethernet";;
- bwn$d) desc="Broadcom BCM43xx IEEE 802.11 wireless adapter";;
- cas$d) desc="Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet";;
- cc3i$d) desc="SDL HSSI sync serial PCI card";;
- cue$d) desc="CATC USB Ethernet adapter";;
- cxgb$d) desc="Chelsio T3 10Gb Ethernet card";;
- dc$d) desc="DEC/Intel 21143 (and clones) PCI Fast Ethernet card";;
- de$d) desc="DEC DE435 PCI NIC or other DC21040-AA based card";;
- disc$d) desc="Software discard network interface";;
- ed$d) desc="Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA";;
- el$d) desc="3Com 3C501 Ethernet card";;
- em$d) desc="Intel(R) PRO/1000 Ethernet card";;
- en$d) desc="Efficient Networks ATM PCI card";;
- ep$d) desc="3Com 3C509 Ethernet card/3C589 PCMCIA";;
- et$d) desc="Agere ET1310 based PCI Express Gigabit Ethernet card";;
- ex$d) desc="Intel EtherExpress Pro/10 Ethernet card";;
- fe$d) desc="Fujitsu MB86960A/MB86965A Ethernet card";;
- fpa$d) desc="DEC DEFPA PCI FDDI card";;
- fwe$d) desc="FireWire Ethernet emulation";;
- fwip$d) desc="IP over FireWire";;
- fxp$d) desc="Intel EtherExpress Pro/100B PCI Fast Ethernet card";;
- gem$d) desc="Apple GMAC or Sun ERI/GEM Ethernet adapter";;
- hme$d) desc="Sun HME (Happy Meal Ethernet) Ethernet adapter";;
- ie$d) desc="AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210";;
- igb$d) desc="Intel(R) PRO/1000 PCI Express Gigabit Ethernet card";;
- ipw$d) desc="Intel PRO/Wireless 2100 IEEE 802.11 adapter";;
- iwi$d) desc="Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter";;
- iwn$d) desc="Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter";;
- ix$d) desc="Intel Etherexpress Ethernet card";;
- ixgb$d) desc="Intel(R) PRO/10Gb Ethernet card";;
- ixgbe$d) desc="Intel(R) PRO/10Gb Ethernet card";;
- jme$d) desc="JMicron JMC250 Gigabit/JMC260 Fast Ethernet";;
- kue$d) desc="Kawasaki LSI USB Ethernet adapter";;
- le$d) desc="AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter";;
- lge$d) desc="Level 1 LXT1001 Gigabit Ethernet card";;
- lnc$d) desc="Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet";;
- lp$d) desc="Parallel Port IP (PLIP) peer connection";;
- lo$d) desc="Loop-back (local) network interface";;
- malo$d) desc="Marvell Libertas 88W8335 802.11 wireless adapter";;
- msk$d) desc="Marvell/SysKonnect Yukon II Gigabit Ethernet";;
- mxge$d) desc="Myricom Myri10GE 10Gb Ethernet card";;
- nfe$d) desc="NVIDIA nForce MCP Ethernet";;
- ng${d}_*|ng$d${d}_*|ng$d$d${d}_*|ng$d$d$d${d}_*|ng$d$d$d$d${d}_*)
- desc="Vimage netgraph(4) bridged Ethernet device";;
- nge$d) desc="NatSemi PCI Gigabit Ethernet card";;
- nve$d) desc="NVIDIA nForce MCP Ethernet";;
- nxge$d) desc="Neterion Xframe 10GbE Server/Storage adapter";;
- pcn$d) desc="AMD Am79c79x PCI Ethernet card";;
- plip$d) desc="Parallel Port IP (PLIP) peer connection";;
- ral$d) desc="Ralink Technology IEEE 802.11 wireless adapter";;
- ray$d) desc="Raytheon Raylink 802.11 wireless adapter";;
- re$d) desc="RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter";;
- rl$d) desc="RealTek 8129/8139 PCI Ethernet card";;
- rue$d) desc="RealTek USB Ethernet card";;
- rum$d) desc="Ralink Technology USB IEEE 802.11 wireless adapter";;
- sf$d) desc="Adaptec AIC-6915 PCI Ethernet card";;
- sge$d) desc="Silicon Integrated Systems SiS190/191 Ethernet";;
- sis$d) desc="SiS 900/SiS 7016 PCI Ethernet card";;
- sk$d) desc="SysKonnect PCI Gigabit Ethernet card";;
- sn$d) desc="SMC/Megahertz Ethernet card";;
- snc$d) desc="SONIC Ethernet card";;
- sr$d) desc="SDL T1/E1 sync serial PCI card";;
- ste$d) desc="Sundance ST201 PCI Ethernet card";;
- stge$d) desc="Sundance/Tamarack TC9021 Gigabit Ethernet";;
- ti$d) desc="Alteon Networks PCI Gigabit Ethernet card";;
- tl$d) desc="Texas Instruments ThunderLAN PCI Ethernet card";;
- tx$d) desc="SMC 9432TX Ethernet card";;
- txp$d) desc="3Com 3cR990 Ethernet card";;
- uath$d) desc="Atheros AR5005UG and AR5005UX USB wireless adapter";;
- upgt$d) desc="Conexant/Intersil PrismGT USB wireless adapter";;
- ural$d) desc="Ralink Technology RT2500USB 802.11 wireless adapter";;
- urtw$d) desc="Realtek 8187L USB wireless adapter";;
- vge$d) desc="VIA VT612x PCI Gigabit Ethernet card";;
- vlan$d|vlan$d$d|vlan$d$d$d|vlan$d$d$d$d|vlan$d$d$d$d$d)
- desc="IEEE 802.1Q VLAN network interface";;
- vr$d) desc="VIA VT3043/VT86C100A Rhine PCI Ethernet card";;
- vx$d) desc="3COM 3c590 / 3c595 Ethernet card";;
- wb$d) desc="Winbond W89C840F PCI Ethernet card";;
- wi$d) desc="Lucent WaveLAN/IEEE 802.11 wireless adapter";;
- wpi$d) desc="Intel 3945ABG IEEE 802.11 wireless adapter";;
- wx$d) desc="Intel Gigabit Ethernet (82452) card";;
- xe$d) desc="Xircom/Intel EtherExpress Pro100/16 Ethernet card";;
- xl$d) desc="3COM 3c90x / 3c90xB PCI Ethernet card";;
- zyd$d) desc="ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter";;
- # Unknown device
- *) desc="<unknown network interface type>";;
- esac
- printf "%s\n" "$desc"
-}
-
# f_dialog_menu_netdev
#
# Display a list of network devices with descriptions.
diff --git a/usr.sbin/bsdconfig/networking/share/hostname.subr b/usr.sbin/bsdconfig/networking/share/hostname.subr
index b276059..61df2b4 100644
--- a/usr.sbin/bsdconfig/networking/share/hostname.subr
+++ b/usr.sbin/bsdconfig/networking/share/hostname.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_HOSTNAME_SUBR" ]; then _NETWORKING_HOSTNAME_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -41,63 +41,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
############################################################ FUNCTIONS
-# f_validate_hostname $hostname
-#
-# Returns zero if the given argument (a fully-qualified hostname) is compliant
-# with standards set-forth in RFC's 952 and 1123 of the Network Working Group:
-#
-# RFC 952 - DoD Internet host table specification
-# http://tools.ietf.org/html/rfc952
-#
-# RFC 1123 - Requirements for Internet Hosts - Application and Support
-# http://tools.ietf.org/html/rfc1123
-#
-# See http://en.wikipedia.org/wiki/Hostname for a brief overview.
-#
-# The return status for invalid hostnames is one of:
-# 255 Entire hostname exceeds the maximum length of 255 characters.
-# 63 One or more individual labels within the hostname (separated by
-# dots) exceeds the maximum of 63 characters.
-# 1 One or more individual labels within the hostname contains one
-# or more invalid characters.
-# 2 One or more individual labels within the hostname starts or
-# ends with a hyphen (hyphens are allowed, but a label cannot
-# begin or end with a hyphen).
-# 3 One or more individual labels within the hostname are null.
-#
-# If the hostname is determined to be invalid, the appropriate error will be
-# displayed using the f_show_msg function.
-#
-f_validate_hostname()
-{
- local fqhn="$1"
-
- ( # Operate within a sub-shell to protect the parent environment
-
- # Return error if the hostname exceeds 255 characters
- [ ${#fqhn} -gt 255 ] && exit 255
-
- IFS="." # Split on `dot'
- for label in $fqhn; do
-
- # Return error if the label exceeds 63 characters
- [ ${#label} -gt 63 ] && exit 63
-
- # Return error if the label is null
- [ "$label" ] || exit 3
-
- # Return error if label begins/ends with dash
- case "$label" in
- -*|*-) exit 2
- esac
-
- # Return error if the label contains any invalid chars
- echo "$label" | grep -q '^[[:alnum:]-]*$' || exit 1
-
- done
- )
-}
-
# f_dialog_hnerror $error $hostname
#
# Display a msgbox with the appropriate error message for an error returned by
diff --git a/usr.sbin/bsdconfig/networking/share/ipaddr.subr b/usr.sbin/bsdconfig/networking/share/ipaddr.subr
index d5398e5..4b39dd2 100644
--- a/usr.sbin/bsdconfig/networking/share/ipaddr.subr
+++ b/usr.sbin/bsdconfig/networking/share/ipaddr.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -40,75 +40,10 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
############################################################ FUNCTIONS
-# f_ifconfig_inet $interface
-#
-# Returns the IPv4 address associated with $interface.
-#
-f_ifconfig_inet()
-{
- local interface="$1"
- ifconfig "$interface" 2> /dev/null | awk \
- '
- BEGIN { found = 0 }
- ( $1 == "inet" ) \
- {
- print $2
- found = 1
- exit
- }
- END { exit ! found }
- '
-}
-
-# f_validate_ipaddr $ipaddr
-#
-# Returns zero if the given argument (an IP address) is of the proper format.
-#
-# The return status for invalid IP address is one of:
-# 1 One or more individual octets within the IP address (separated
-# by dots) contains one or more invalid characters.
-# 2 One or more individual octets within the IP address are null
-# and/or missing.
-# 3 One or more individual octets within the IP address exceeds the
-# maximum of 255 (or 2^8, being an octet comprised of 8 bits).
-# 4 The IP address has either too few or too many octets.
-#
-f_validate_ipaddr()
-{
- local ip="$1"
-
- ( # Operate within a sub-shell to protect the parent environment
-
- # Track number of octets for error checking
- noctets=0
-
- IFS="." # Split on `dot'
- for octet in $ip; do
-
- # Return error if the octet is null
- [ "$octet" ] || exit 2
-
- # Return error if not a whole integer
- f_isinteger "$octet" || exit 1
-
- # Return error if not a positive integer
- [ $octet -ge 0 ] || exit 1
-
- # Return error if the octet exceeds 255
- [ $octet -gt 255 ] && exit 3
-
- noctets=$(( $noctets + 1 ))
-
- done
-
- [ $noctets -eq 4 ] || exit 4
- )
-}
-
# f_dialog_iperror $error $ipaddr
#
# Display a msgbox with the appropriate error message for an error returned by
-# the f_validate_ipaddr function above.
+# the f_validate_ipaddr function.
#
f_dialog_iperror()
{
@@ -144,141 +79,6 @@ f_dialog_validate_ipaddr()
return $retval
}
-# f_validate_ipaddr6 $ipv6_addr
-#
-# Returns zero if the given argument (an IPv6 address) is of the proper format.
-#
-# The return status for invalid IP address is one of:
-# 1 One or more individual segments within the IP address
-# (separated by colons) contains one or more invalid characters.
-# Segments must contain only combinations of the characters 0-9,
-# A-F, or a-f.
-# 2 Too many/incorrect null segments. A single null segment is
-# allowed within the IP address (separated by colons) but not
-# allowed at the beginning or end (unless a double-null segment;
-# i.e., "::*" or "*::").
-# 3 One or more individual segments within the IP address
-# (separated by colons) exceeds the length of 4 hex-digits.
-# 4 The IP address entered has either too few (less than 3), too
-# many (more than 8), or not enough segments, separated by
-# colons.
-# 5* The IPv4 address at the end of the IPv6 address is invalid.
-# * When there is an error with the dotted-quad IPv4 address at the
-# end of the IPv6 address, the return value of 5 is OR'd with a
-# bit-shifted (<< 4) return of f_validate_ipaddr.
-#
-f_validate_ipaddr6()
-{
- local ip="$1"
-
- ( # Operate within a sub-shell to protect the parent environment
-
- IFS=":" # Split on `colon'
- set -- $ip:
-
- # Return error if too many or too few segments
- # Using 9 as max in case of leading or trailing null spanner
- [ $# -gt 9 -o $# -lt 3 ] && exit 4
-
- h="[0-9A-Fa-f]"
- nulls=0
- nsegments=$#
- contains_ipv4_segment=
-
- while [ $# -gt 0 ]; do
-
- segment="${1%:}"
- shift
-
- #
- # Return error if this segment makes one null too-many.
- # A single null segment is allowed anywhere in the
- # middle as well as double null segments are allowed at
- # the beginning or end (but not both).
- #
- if [ ! "$segment" ]; then
- nulls=$(( $nulls + 1 ))
- if [ $nulls -eq 3 ]; then
- # Only valid syntax for 3 nulls is `::'
- [ "$ip" = "::" ] || exit 2
- elif [ $nulls -eq 2 ]; then
- # Only valid if begins/ends with `::'
- case "$ip" in
- ::*|*::) : fall thru ;;
- *) exit 2
- esac
- fi
- continue
- fi
-
- #
- # Return error if not a valid hexadecimal short
- #
- case "$segment" in
- $h|$h$h|$h$h$h|$h$h$h$h)
- : valid segment of 1-4 hexadecimal digits
- ;;
- *[!0-9A-Fa-f]*)
- # Segment contains at least one invalid char
-
- # Return error immediately if not last segment
- [ $# -eq 0 ] || exit 1
-
- # Otherwise, check for legacy IPv4 notation
- case "$segment" in
- *[!0-9.]*)
- # Segment contains at least one invalid
- # character even for an IPv4 address
- exit 1
- esac
-
- # Return error if not enough segments
- if [ $nulls -eq 0 ]; then
- [ $nsegments -eq 7 ] || exit 4
- fi
-
- contains_ipv4_segment=1
-
- # Validate the IPv4 address
- f_validate_ipaddr "$segment" ||
- exit $(( 5 | $? << 4 ))
- ;;
- *)
- # Segment characters are all valid but too many
- exit 3
- esac
-
- done
-
- if [ $nulls -eq 1 ]; then
- # Single null segment cannot be at beginning/end
- case "$ip" in
- :*|*:) exit 2
- esac
- fi
-
- #
- # A legacy IPv4 address can span the last two 16-bit segments,
- # reducing the amount of maximum allowable segments by-one.
- #
- maxsegments=8
- if [ "$contains_ipv4_segment" ]; then
- maxsegments=7
- fi
-
- case $nulls in
- # Return error if missing segments with no null spanner
- 0) [ $nsegments -eq $maxsegments ] || exit 4 ;;
- # Return error if null spanner with too many segments
- 1) [ $nsegments -le $maxsegments ] || exit 4 ;;
- # Return error if leading/trailing `::' with too many segments
- 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || exit 4 ;;
- esac
-
- exit $SUCCESS
- )
-}
-
# f_dialog_ip6error $error $ipv6_addr
#
# Display a msgbox with the appropriate error message for an error returned by
diff --git a/usr.sbin/bsdconfig/networking/share/netmask.subr b/usr.sbin/bsdconfig/networking/share/netmask.subr
index 3a8665d..e6838e5 100644
--- a/usr.sbin/bsdconfig/networking/share/netmask.subr
+++ b/usr.sbin/bsdconfig/networking/share/netmask.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_NETMASK_SUBR" ]; then _NETWORKING_NETMASK_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -40,87 +40,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
############################################################ FUNCTIONS
-# f_ifconfig_netmask $interface
-#
-# Returns the IPv4 subnet mask associated with $interface.
-#
-f_ifconfig_netmask()
-{
- local interface="$1" octets
- octets=$( ifconfig "$interface" 2> /dev/null | awk \
- '
- BEGIN { found = 0 }
- ( $1 == "inet" ) \
- {
- printf "%s %s %s %s\n",
- substr($4,3,2),
- substr($4,5,2),
- substr($4,7,2),
- substr($4,9,2)
- found = 1
- exit
- }
- END { exit ! found }
- ' ) || return $FAILURE
-
- local octet netmask=
- for octet in $octets; do
- netmask="$netmask${netmask:+.}$( printf "%u" "0x$octet" )"
- done
- echo $netmask
-}
-
-# f_validate_netmask $netmask
-#
-# Returns zero if the given argument (a subnet mask) is of the proper format.
-#
-# The return status for invalid IP address is one of:
-# 1 One or more individual fields within the subnet mask (separated
-# by dots) contains one or more invalid characters.
-# 2 One or more individual fields within the subnet mask are null
-# and/or missing.
-# 3 One or more individual fields within the subnet mask exceeds
-# the maximum of 255 (a full 8-bit register).
-# 4 The subnet mask has either too few or too many fields.
-# 5 One or more individual fields within the subnet mask is an
-# invalid integer (only 0,128,192,224,240,248,252,254,255 are
-# valid integers).
-#
-f_validate_netmask()
-{
- local mask="$1"
-
- ( # Operate within a sub-shell to protect the parent environment
-
- # Track number of fields for error checking
- nfields=0
-
- IFS="." # Split on `dot'
- for field in $mask; do
-
- # Return error if the field is null
- [ "$field" ] || exit 2
-
- # Return error if not a whole positive integer
- f_isinteger "$field" || exit 1
-
- # Return error if the field exceeds 255
- [ $field -gt 255 ] && exit 3
-
- # Return error if the field is an invalid integer
- case "$field" in
- 0|128|192|224|240|248|252|254|255) :;;
- *) exit 5;;
- esac
-
- nfields=$(( $nfields + 1 ))
-
- done
-
- [ $nfields -eq 4 ] || exit 4
- )
-}
-
# f_dialog_maskerror $error $netmask
#
# Display a msgbox with the appropriate error message for an error returned by
diff --git a/usr.sbin/bsdconfig/networking/share/resolv.subr b/usr.sbin/bsdconfig/networking/share/resolv.subr
index 7d9af3b..b525a4d 100644
--- a/usr.sbin/bsdconfig/networking/share/resolv.subr
+++ b/usr.sbin/bsdconfig/networking/share/resolv.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." networking/resolv.subr
f_include $BSDCFG_SHARE/dialog.subr
f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
f_include $BSDCFG_SHARE/networking/common.subr
f_include $BSDCFG_SHARE/networking/ipaddr.subr
@@ -42,11 +43,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
############################################################ CONFIGURATION
#
-# Path to resolv.conf(5).
-#
-: ${RESOLV_CONF:="/etc/resolv.conf"}
-
-#
# When updating resolv.conf(5), should we populate the `search' directive with
# all possible sub-domains? In example, if the domain is "sub.domain.com", when
# the below option is set to 1, include both "sub.domain.com" and "domain.com"
@@ -103,25 +99,6 @@ f_resolv_conf_search()
'
}
-# f_resolv_conf_nameservers
-#
-# Returns nameserver(s) configured in resolv.conf(5).
-#
-f_resolv_conf_nameservers()
-{
- awk \
- '
- BEGIN { found = 0 }
- ( $1 == "nameserver" ) \
- {
- print $2
- found = 1
- }
- END { exit ! found }
- ' \
- "$RESOLV_CONF" 2> /dev/null
-}
-
# f_dialog_resolv_conf_update $hostname
#
# Updates the search/domain directives in resolv.conf(5) given a valid fully-
diff --git a/usr.sbin/bsdconfig/networking/share/routing.subr b/usr.sbin/bsdconfig/networking/share/routing.subr
index 4207ab2..2d8cafc 100644
--- a/usr.sbin/bsdconfig/networking/share/routing.subr
+++ b/usr.sbin/bsdconfig/networking/share/routing.subr
@@ -1,6 +1,6 @@
if [ ! "$_NETWORKING_ROUTING_SUBR" ]; then _NETWORKING_ROUTING_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -33,6 +33,7 @@ BSDCFG_SHARE="/usr/share/bsdconfig"
f_dprintf "%s: loading includes..." networking/routing.subr
f_include $BSDCFG_SHARE/sysrc.subr
f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
f_include $BSDCFG_SHARE/networking/common.subr
f_include $BSDCFG_SHARE/networking/ipaddr.subr
@@ -41,25 +42,6 @@ f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
############################################################ FUNCTIONS
-# f_route_get_default
-#
-# Returns the IP address of the currently active default router.
-#
-f_route_get_default()
-{
- route -n get default 2> /dev/null | awk \
- '
- BEGIN { found = 0 }
- ( $1 == "gateway:" ) \
- {
- print $2
- found = 1
- exit
- }
- END { exit ! found }
- '
-}
-
# f_dialog_input_defaultrouter
#
# Edits the default router.
diff --git a/usr.sbin/bsdconfig/share/Makefile b/usr.sbin/bsdconfig/share/Makefile
index cd56dfc..4c20c2b 100644
--- a/usr.sbin/bsdconfig/share/Makefile
+++ b/usr.sbin/bsdconfig/share/Makefile
@@ -2,9 +2,11 @@
NO_OBJ=
+SUBDIR= media
+
FILESDIR= ${SHAREDIR}/bsdconfig
-FILES= common.subr dialog.subr mustberoot.subr script.subr \
- strings.subr sysrc.subr variable.subr
+FILES= common.subr device.subr dialog.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 c66a54f..cb9096f 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 Devin Teske
+# Copyright (c) 2012-2013 Devin Teske
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -127,15 +127,15 @@ f_have()
#
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=$?
+ local __var_to_get="$1" __var_to_set="$2"
+ [ "$__var_to_set" ] || local value
+ eval ${__var_to_set:-value}=\"\${$__var_to_get}\"
+ eval [ \"\${$__var_to_get+set}\" ]
+ local __retval=$?
eval f_dprintf '"f_getvar: var=[%s] value=[%s] r=%u"' \
- \"\$var_to_get\" \"\$${var_to_set:-value}\" \$retval
- [ "$var_to_set" ] || { [ "$value" ] && echo "$value"; }
- return $retval
+ \"\$__var_to_get\" \"\$${__var_to_set:-value}\" \$__retval
+ [ "$__var_to_set" ] || { [ "$value" ] && echo "$value"; }
+ return $__retval
}
# f_die [ $status [ $fmt [ $opts ... ]]]
@@ -574,6 +574,30 @@ f_index_menusel_command()
echo "$command"
}
+# f_running_as_init
+#
+# Returns true if running as init(1).
+#
+f_running_as_init()
+{
+ #
+ # When a custom init(8) performs an exec(3) to invoke a shell script,
+ # PID 1 becomes sh(1) and $PPID is set to 1 in the executed script.
+ #
+ [ ${PPID:-0} -eq 1 ] # Return status
+}
+
+# f_mounted $local_directory
+#
+# Return success if a filesystem is mounted on a particular directory.
+#
+f_mounted()
+{
+ local dir="$1"
+ [ -d "$dir" ] || return $FAILURE
+ mount | grep -Eq " on $dir \([^)]+\)$"
+}
+
############################################################ MAIN
#
diff --git a/usr.sbin/bsdconfig/share/device.subr b/usr.sbin/bsdconfig/share/device.subr
new file mode 100644
index 0000000..07b3f87
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/device.subr
@@ -0,0 +1,795 @@
+if [ ! "$_DEVICE_SUBR" ]; then _DEVICE_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/struct.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+DEVICES=
+DEVICE_NAMES=
+
+# A "device" from sysinstall's point of view
+f_struct_define DEVICE \
+ name \
+ desc \
+ devname \
+ type \
+ enabled \
+ init \
+ get \
+ shutdown \
+ flags \
+ private \
+ volume
+
+# Network devices have their `private' property set to this
+f_struct_define DEVICE_INFO \
+ use_rtsol use_dhcp ipaddr ipv6addr netmask extras
+
+setvar DEVICE_TYPE_NONE 1
+setvar DEVICE_TYPE_DISK 2
+setvar DEVICE_TYPE_FLOPPY 3
+setvar DEVICE_TYPE_FTP 4
+setvar DEVICE_TYPE_NETWORK 5
+setvar DEVICE_TYPE_CDROM 6
+setvar DEVICE_TYPE_USB 7
+setvar DEVICE_TYPE_DOS 8
+setvar DEVICE_TYPE_UFS 9
+setvar DEVICE_TYPE_NFS 10
+setvar DEVICE_TYPE_ANY 11
+setvar DEVICE_TYPE_HTTP_PROXY 12
+
+#
+# Default behavior is to call f_device_get_all() automatically when loaded.
+#
+: ${DEVICE_SELF_SCAN_ALL=1}
+
+############################################################ FUNCTIONS
+
+# f_device_try $name [$i [$var_path]]
+#
+# Test a particular device. If $i is given, then $name is expected to contain a
+# single "%d" where $i will be inserted using printf. If $var_path is given,
+# it is used as a variable name to provide the caller the device pathname.
+#
+# Returns success if the device path exists and is a cdev.
+#
+f_device_try()
+{
+ local name="$1" i="$2" var_path="$3" unit
+ if [ "$i" ]; then
+ unit=$( printf "$name" "$i" )
+ else
+ unit="$name"
+ fi
+ case "$unit" in
+ /dev/*) : good ;; # already qualified
+ *) unit="/dev/$unit" ;;
+ esac
+ [ "$var_path" ] && setvar "$var_path" "$unit"
+ f_dprintf "f_device_try: making sure %s is a device node" "$unit"
+ if [ -c "$unit" ]; then
+ f_dprintf "f_device_try: %s is a cdev [good]" "$unit"
+ return $SUCCESS
+ else
+ f_dprintf "f_device_try: %s is not a cdev [skip]" "$unit"
+ return $FAILURE
+ fi
+}
+
+# f_device_register $name $desc $devname $type $enabled $init_function \
+# $get_function $shutdown_function $private
+#
+# Register a device. A `structure' (see struct.subr) is created with the name
+# device_$name (so make sure $name contains only alpha-numeric characters or
+# the underscore, `_'). The remaining arguments after $name correspond to the
+# properties of the `DEVICE' structure-type (defined above).
+#
+# If not already registered, the device is then appended to the DEVICES
+# environment variable, a space-separated list of all registered devices.
+#
+f_device_register()
+{
+ local name="$1" desc="$2" devname="$3" type="$4" enabled="$5"
+ local init_func="$6" get_func="$7" shutdown_func="$8" private="$9"
+
+ f_struct_new DEVICE "device_$name" || return $FAILURE
+ device_$name set name "$name"
+ device_$name set desc "$desc"
+ device_$name set devname "$devname"
+ device_$name set type "$type"
+ device_$name set enabled "$enabled"
+ device_$name set init "$init_func"
+ device_$name set get "$get_func"
+ device_$name set shutdown "$shutdown_func"
+ device_$name set private "$private"
+
+ # Scan our global register to see if it needs ammending
+ local dev found=
+ for dev in $DEVICES; do
+ [ "$dev" = "$name" ] || continue
+ found=1 && break
+ done
+ [ "$found" ] || DEVICES="$DEVICES $name"
+
+ return $SUCCESS
+}
+
+# f_device_reset
+#
+# Reset the registered device chain.
+#
+f_device_reset()
+{
+ local dev
+ for dev in $DEVICES; do
+ f_device_shutdown $dev
+
+ #
+ # XXX this potentially leaks $dev->private if it's being
+ # used to point to something dynamic, but you're not supposed
+ # to call this routine at such times that some open instance
+ # has its private member pointing somewhere anyway. XXX
+ #
+ f_struct_free device_$dev
+ done
+ DEVICES=
+}
+
+# f_device_get_all
+#
+# Get all device information for devices we have attached.
+#
+f_device_get_all()
+{
+ local devname desc
+
+ f_dprintf "f_device_get_all: Probing devices..."
+ f_dialog_info "$msg_probing_devices_please_wait_this_can_take_a_while"
+
+ # First go for the network interfaces
+ for devname in $( ifconfig -l ); do
+ # Eliminate network devices that don't make sense
+ case "$devname" in
+ lo*) continue ;;
+ esac
+
+ # Try and find its description
+ f_device_desc "$devname" $DEVICE_TYPE_NETWORK desc
+
+ f_dprintf "Found a network device named %s" "$devname"
+ f_device_register $devname \
+ "$desc" "$devname" $DEVICE_TYPE_NETWORK 1 \
+ f_media_init_network "" f_media_shutdown_network ""
+ done
+
+ # Next, try to find all the types of devices one might use
+ # as a media source for content
+ #
+
+ local dev desc type max n=0
+ for dev in $DEVICE_NAMES; do
+ n=$(( $n + 1 ))
+ # Get the desc, type, and max (with debugging disabled)
+ # NOTE: Bypassing f_device_name_get() for efficiency
+ debug= f_getvar _device_desc$n desc
+ debug= f_getvar _device_type$n type
+ debug= f_getvar _device_max$n max
+
+ local k=0
+ while [ $k -lt ${max:-0} ]; do
+ i=$k k=$(( $k + 1 ))
+ devname=""
+ case "$type" in
+ $DEVICE_TYPE_CDROM)
+ f_device_try "$dev" "$i" devname || continue
+ f_device_register "${devname##*/}" "$desc" \
+ "$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom ""
+ f_dprintf "Found a CDROM device for %s" \
+ "$devname"
+ ;;
+ $DEVICE_TYPE_FLOPPY)
+ f_device_try "$dev" "$i" devname || continue
+ f_device_register "${devname##*/}" "$desc" \
+ "$devname" $DEVICE_TYPE_FLOPPY 1 \
+ f_media_init_floppy \
+ f_media_get_floppy \
+ f_media_shutdown_floppy ""
+ f_dprintf "Found a floppy device for %s" \
+ "$devname"
+ ;;
+ $DEVICE_TYPE_USB)
+ f_device_try "$dev" "$i" devname || continue
+ f_device_register "${devname##*/}" "$desc" \
+ "$devname" $DEVICE_TYPE_USB 1 \
+ f_media_init_usb f_media_get_usb \
+ f_media_shutdown_usb ""
+ f_dprintf "Found a USB disk for %s" "$devname"
+ ;;
+ esac
+ done
+ done
+
+ # Register ISO9660 providers as CDROM devices
+ for devname in /dev/iso9660/*; do
+ f_device_try "$devname" || continue
+ f_device_register "${devname##*/}" "ISO9660 file system" \
+ "$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom ""
+ f_dprintf "Found a CDROM device for %s" "$devname"
+ done
+
+ # Scan for mdconfig(8)-created md(4) devices
+ local filename
+ for devname in /dev/md[0-9] /dev/md[0-9][0-9]; do
+ f_device_try "$devname" || continue
+
+ # See if the md(4) device is a vnode type backed by a file
+ filename=$( sysctl kern.geom.conftxt |
+ awk -v devname="${devname##*/}" \
+ '
+ ( $2 == "MD" ) && \
+ ( $3 == devname ) && \
+ ( $(NF-2) == "vnode" ) && \
+ ( $(NF-1) == "file" ) \
+ {
+ print $NF
+ }
+ ' )
+ case "$filename" in
+ *.iso) # Register the device as an ISO9660 provider
+ f_device_register "${devname##*/}" \
+ "md(4) vnode file system" \
+ "$devname" $DEVICE_TYPE_CDROM 1 \
+ f_media_init_cdrom f_media_get_cdrom \
+ f_media_shutdown_cdrom ""
+ f_dprintf "Found a CDROM device for %s" "$devname"
+ ;;
+ esac
+ done
+
+ # Finally go get the disks and look for partitions to register
+ local diskname slices index type rest slice part
+ for diskname in $( sysctl -n kern.disks ); do
+
+ case "$diskname" in
+ cd*)
+ # XXX
+ # Due to unknown reasons, kern.disks returns SCSI
+ # CDROM as a valid disk. This will prevent bsdconfig
+ # from presenting SCSI CDROMs as available disks in
+ # various menus. Why GEOM treats SCSI CDROM as a disk
+ # is beyond me and that should be investigated.
+ # For temporary workaround, ignore SCSI CDROM device.
+ #
+ continue ;;
+ esac
+
+ # Try to create a list of partitions and their types,
+ # consisting of "N,typeN ..." (e.g., "1,0xa5 2,0x06").
+ if ! slices=$( fdisk -p "$diskname" 2> /dev/null |
+ awk '( $1 == "p" ) { print $2","$3 }' )
+ then
+ f_dprintf "Unable to open disk %s" "$diskname"
+ continue
+ fi
+
+ f_device_register "$diskname" "" \
+ "/dev/$diskname" $DEVICE_TYPE_DISK 0
+ f_dprintf "Found a disk device named %s" "$diskname"
+
+ # Look for existing partitions to register
+ for slice in $slices; do
+ index="${slice%%,*}" type="${slice#*,}"
+ slice=${diskname}s$index
+ case "$type" in
+ 0x01|0x04|0x06|0x0b|0x0c|0x0e|0xef)
+ # DOS partitions to add as "DOS media devices"
+ f_device_register "$slice" "" \
+ "/dev/$slice" $DEVICE_TYPE_DOS 1 \
+ f_media_init_dos f_media_get_dos \
+ f_media_shutdown_dos ""
+ f_dprintf "Found a DOS partition %s" "$slice"
+ ;;
+ 0xa5) # FreeBSD partition
+ for part in $(
+ bsdlabel -r $slice 2> /dev/null |
+ awk -v slice="$slice" '
+ ( $1 ~ /[abdefgh]:/ ) {
+ printf "%s%s\n",
+ slice,
+ substr($1,1,1)
+ }'
+ ); do
+ f_quietly dumpfs -m /dev/$part ||
+ continue
+ f_device_register \
+ "$part" "" "/dev/$part" \
+ $DEVICE_TYPE_UFS 1 \
+ f_media_init_ufs \
+ f_media_get_ufs \
+ f_media_shutdown_ufs ""
+ f_dprintf "Found a UFS partition %s" \
+ "$part"
+ done # parts
+ ;;
+ esac
+ done # slices
+
+ done # disks
+}
+
+# f_device_name_get $type $name type|desc|max [$var_to_set]
+#
+# Fetch the device type (type), description (desc), or maximum number of
+# devices to scan for (max) associated with device $name and $type. If $type is
+# either NULL, missing, or set to $DEVICE_TYPE_ANY then only $name is used.
+# Returns success if a match was found, otherwise failure.
+#
+# If $var_to_set is missing or NULL, the device name is printed to standard out
+# for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example, when called in a loop).
+#
+f_device_name_get()
+{
+ local __type="$1" __name="$2" __prop="$3" __var_to_set="$4"
+ local __dev __devtype __n=0
+
+ # Return failure if no $name or $prop is an unknown property
+ [ "$__name" ] || return $FAILURE
+ case "$__prop" in type|desc|max) : good ;;
+ *) return $FAILURE; esac
+
+ [ "$__type" = "$DEVICE_TYPE_ANY" ] && __type=
+ for __dev in $DEVICE_NAMES; do
+ __n=$(( $__n + 1 ))
+ [ "$__dev" = "$__name" ] || continue
+ f_getvar _device_type$__n __devtype
+ [ "${__type:-$__devtype}" = "$__devtype" ] || continue
+ f_getvar _device_$__prop$__n $__var_to_set
+ return $?
+ done
+ return $FAILURE
+}
+
+# f_device_name_set $type $name $desc [$max]
+#
+# Store a description (desc) and [optionally] maximum number of devices to scan
+# for (max) in-association with device $type and $name. Returns success. Use
+# the f_device_name_get() routine with the same $name and [optionally] $type to
+# retrieve one of type, desc, or max properties.
+#
+f_device_name_set()
+{
+ local type="$1" name="$2" desc="$3" max="$4"
+ local dev devtype n=0 found=
+ [ "$name" ] || return $FAILURE
+ for dev in $DEVICE_NAMES; do
+ n=$(( $n + 1 ))
+ [ "$dev" = "$name" ] || continue
+ if f_getvar _device_type$n devtype; then
+ # Allow multiple entries with same name but diff type
+ [ "$devtype" = "$type" ] || continue
+ fi
+ found=1 && break
+ done
+ if [ ! "$found" ]; then
+ DEVICE_NAMES="$DEVICE_NAMES $name"
+ n=$(( $n + 1 ))
+ fi
+ setvar _device_type$n "$type"
+ setvar _device_desc$n "$desc"
+ [ "${4+set}" ] && setvar _device_max$n "$max"
+ return $SUCCESS
+}
+
+# f_device_desc $device_name $device_type [$var_to_set]
+#
+# Print a description for a device name (eg., `fxp0') given a specific device
+# type/class.
+#
+# If $var_to_set is missing or NULL, the device description is printed to
+# standard out for capturing in a sub-shell (which is less-recommended because
+# of performance degredation; for example, when called in a loop).
+#
+f_device_desc()
+{
+ local __name="$1" __type="$2" __var_to_set="$3"
+ local __devname __devunit __cp
+
+ # Check variables
+ [ "$__name" ] || return $SUCCESS
+ [ "$__type" = "$DEVICE_TYPE_ANY" ] && type=
+ [ "$__var_to_set" ] && { setvar "$__var_to_set" "" || return; }
+
+ #
+ # Return sysctl MIB dev.NAME.UNIT.%desc if it exists,
+ # otherwise fall through to below static list.
+ #
+ if f_have sysctl; then
+ __devname="${__name%%[0-9]*}"
+ __devunit="${__name#$__devname}"
+ __devunit="${__devunit%%[!0-9]*}"
+ if [ "$__var_to_set" ]; then
+ if __cp=$(
+ sysctl -n "dev.$__devname.$__devunit.%desc" \
+ 2> /dev/null
+ ); then
+ setvar "$__var_to_set" "$__cp" &&
+ return $SUCCESS
+ fi
+ else
+ sysctl -n "dev.$__devname.$__devunit.%desc" \
+ 2> /dev/null && return $SUCCESS
+ fi
+ fi
+
+ local __dev __devtype __n=0
+ for __dev in $DEVICE_NAMES; do
+ __n=$(( $__n + 1 ))
+ debug= f_getvar _device_type$__n __devtype
+ [ "${__type:-$__devtype}" = "$__devtype" ] || continue
+ if [ "$__devtype" = "$DEVICE_TYPE_NETWORK" ]; then
+ __devname=$( f_substr "$__name" 0 ${#__dev} )
+ [ "$__devname" = "$__dev" ] || continue
+ else
+ __devname="${__name%%[0-9]*}"
+ __devunit="${__name#$__devname}"
+ __devunit="${__devunit%%[!0-9]*}"
+ __devname=$( printf "$__dev" $__devunit )
+ [ "$__devname" = "$__name" ] || continue
+ fi
+ debug= f_getvar _device_desc$__n $__var_to_set
+ return $?
+ done
+
+ #
+ # Sensible fall-backs for specific types
+ #
+ case "$__type" in
+ $DEVICE_TYPE_CDROM) __cp="<unknown cdrom device type>";;
+ $DEVICE_TYPE_DISK) __cp="<unknown disk device type>";;
+ $DEVICE_TYPE_FLOPPY) __cp="<unknown floppy device type>";;
+ $DEVICE_TYPE_USB) __cp="<unknown usb storage device type>";;
+ $DEVICE_TYPE_NETWORK) __cp="<unknown network interface type>";;
+ *)
+ __cp="<unknown device type>"
+ esac
+
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__cp"
+ else
+ echo "$__cp"
+ fi
+
+ return $FAILURE
+}
+
+# f_device_rescan
+#
+# Rescan all devices, after closing previous set - convenience function.
+#
+f_device_rescan()
+{
+ f_device_reset
+ f_device_get_all
+}
+
+# f_device_find $name [$type [$var_to_set]]
+#
+# Find one or more registered devices by name, type, or both. Returns a space-
+# separated list of devices matching the search criterion.
+#
+# If $var_to_set is missing or NULL, the device name(s) are printed to standard
+# out for capturing in a sub-shell (which is less-recommended because of
+# performance degredation; for example, when called in a loop).
+#
+f_device_find()
+{
+ local __name="$1" __type="${2:-$DEVICE_TYPE_ANY}" __var_to_set="$3"
+ local __dev __devname __devtype __found=
+ for __dev in $DEVICES; do
+ device_$__dev get name __devname
+ device_$__dev get type __devtype
+ if [ "$__name" = "$__devname" -o ! "$__name" ] &&
+ [ "$__type" = "$DEVICE_TYPE_ANY" -o \
+ "$__type" = "$__devtype" ]
+ then
+ __found="$__found $__dev"
+ fi
+ done
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "${__found# }"
+ else
+ echo $__found
+ fi
+ [ "$__found" ] # Return status
+}
+
+# f_device_init $name
+#
+# Initialize a device by evaluating its `init' function.
+#
+f_device_init()
+{
+ local name="$1" init_func
+ device_$name get init init_func || return
+ ${init_func:-:} $name
+}
+
+# f_device_get $name $file [$probe]
+#
+# Read $file by evaluating the device's `get' function. The file is commonly
+# produced on standard output (but it truly depends on the function called).
+#
+f_device_get()
+{
+ local name="$1" file="$2" probe="$3" get_func
+ device_$name get get get_func || return
+ ${get_func:-:} $name "$file" ${3+"$probe"}
+}
+
+# f_device_shutdown $name
+#
+# Shutdown a device by evaluating its `shutdown' function.
+#
+f_device_shutdown()
+{
+ local name="$1" shutdown_func
+ device_$name get shutdown shutdown_func || return
+ ${shutdown_func:-:} $name
+}
+
+# f_device_menu $title $prompt $hline $device_type [$helpfile]
+#
+# Display a menu listing all the devices of a certain type in the system.
+#
+f_device_menu()
+{
+ f_dialog_title "$1"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+
+ local prompt="$2" hline="$3" type="$4" helpfile="$5"
+
+ local dev devtype devs=
+ for dev in $DEVICES; do
+ device_$dev get type devtype || continue
+ [ "$devtype" = "$type" ] || continue
+ devs="$devs $dev"
+ done
+ [ "$devs" ] || return $FAILURE
+
+ local sanitize_awk="{ gsub(/'/, \"'\\\\''\"); print }"
+
+ local desc menu_list=
+ for dev in $devs; do
+ device_$dev get desc desc
+ desc=$( echo "$desc" | awk "$sanitize_awk" )
+ menu_list="$menu_list '$dev' '$desc'"
+ done
+
+ local size mtag
+ size=$( eval f_dialog_menu_size \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list )
+
+ local errexit=
+ case $- in *e*) errexit=1; esac
+ set +e
+
+ while :; do
+ mtag=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ ${helpfile:+ \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ } \
+ --menu \"\$prompt\" $size \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+
+ [ $retval -ne 2 ] && break
+ # Otherwise, the Help button was pressed
+ f_show_help "$helpfile"
+ # Loop back to menu
+ done
+ f_dprintf "retval=%u mtag=[%s]" $retval "$mtag"
+
+ [ "$errexit" ] && set -e
+
+ [ $retval -eq 0 ] && echo "$mtag" >&2
+
+ return $retval
+}
+
+#
+# Short-hand
+#
+f_cdrom() { f_device_name_set $DEVICE_TYPE_CDROM "$1" "$2" "$3"; }
+f_disk() { f_device_name_set $DEVICE_TYPE_DISK "$1" "$2" "$3"; }
+f_floppy() { f_device_name_set $DEVICE_TYPE_FLOPPY "$1" "$2" "$3"; }
+f_serial() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2" "$3"; }
+f_usb() { f_device_name_set $DEVICE_TYPE_USB "$1" "$2" "$3"; }
+f_network() { f_device_name_set $DEVICE_TYPE_NETWORK "$1" "$2"; }
+
+############################################################ MAIN
+
+# CDROM, Disk, Floppy, Serial, and USB devices/names
+f_cdrom "cd%d" "SCSI CDROM drive" 4
+f_cdrom "mcd%d" "Mitsumi (old model) CDROM drive" 4
+f_cdrom "scd%d" "Sony CDROM drive - CDU31/33A type" 4
+f_disk "aacd%d" "Adaptec FSA RAID array" 4
+f_disk "ada%d" "ATA/SATA disk device" 16
+f_disk "amrd%d" "AMI MegaRAID drive" 4
+f_disk "da%d" "SCSI disk device" 16
+f_disk "idad%d" "Compaq RAID array" 4
+f_disk "ipsd%d" "IBM ServeRAID RAID array" 4
+f_disk "mfid%d" "LSI MegaRAID SAS array" 4
+f_disk "mlxd%d" "Mylex RAID disk" 4
+f_disk "twed%d" "3ware ATA RAID array" 4
+f_floppy "fd%d" "Floppy Drive unit A" 4
+f_serial "cuau%d" "%s on device %s (COM%d)" 16
+f_usb "da%da" "USB Mass Storage Device" 16
+
+# Network interfaces/names
+f_network "ae" "Attansic/Atheros L2 Fast Ethernet"
+f_network "age" "Attansic/Atheros L1 Gigabit Ethernet"
+f_network "alc" "Atheros AR8131/AR8132 PCIe Ethernet"
+f_network "ale" "Atheros AR8121/AR8113/AR8114 PCIe Ethernet"
+f_network "an" "Aironet 4500/4800 802.11 wireless adapter"
+f_network "ath" "Atheros IEEE 802.11 wireless adapter"
+f_network "aue" "ADMtek USB Ethernet adapter"
+f_network "axe" "ASIX Electronics USB Ethernet adapter"
+f_network "bce" "Broadcom NetXtreme II Gigabit Ethernet card"
+f_network "bfe" "Broadcom BCM440x PCI Ethernet card"
+f_network "bge" "Broadcom BCM570x PCI Gigabit Ethernet card"
+f_network "bm" "Apple BMAC Built-in Ethernet"
+f_network "bwn" "Broadcom BCM43xx IEEE 802.11 wireless adapter"
+f_network "cas" "Sun Cassini/Cassini+ or NS DP83065 Saturn Ethernet"
+f_network "cc3i" "SDL HSSI sync serial PCI card"
+f_network "cue" "CATC USB Ethernet adapter"
+f_network "cxgb" "Chelsio T3 10Gb Ethernet card"
+f_network "dc" "DEC/Intel 21143 (and clones) PCI Fast Ethernet card"
+f_network "de" "DEC DE435 PCI NIC or other DC21040-AA based card"
+f_network "disc" "Software discard network interface"
+f_network "ed" "Novell NE1000/2000; 3C503; NE2000-compatible PCMCIA"
+f_network "el" "3Com 3C501 Ethernet card"
+f_network "em" "Intel(R) PRO/1000 Ethernet card"
+f_network "en" "Efficient Networks ATM PCI card"
+f_network "ep" "3Com 3C509 Ethernet card/3C589 PCMCIA"
+f_network "et" "Agere ET1310 based PCI Express Gigabit Ethernet card"
+f_network "ex" "Intel EtherExpress Pro/10 Ethernet card"
+f_network "fe" "Fujitsu MB86960A/MB86965A Ethernet card"
+f_network "fpa" "DEC DEFPA PCI FDDI card"
+f_network "fwe" "FireWire Ethernet emulation"
+f_network "fwip" "IP over FireWire"
+f_network "fxp" "Intel EtherExpress Pro/100B PCI Fast Ethernet card"
+f_network "gem" "Apple GMAC or Sun ERI/GEM Ethernet adapter"
+f_network "hme" "Sun HME (Happy Meal Ethernet) Ethernet adapter"
+f_network "ie" "AT&T StarLAN 10 and EN100; 3Com 3C507; NI5210"
+f_network "igb" "Intel(R) PRO/1000 PCI Express Gigabit Ethernet card"
+f_network "ipw" "Intel PRO/Wireless 2100 IEEE 802.11 adapter"
+f_network "iwi" "Intel PRO/Wireless 2200BG/2225BG/2915ABG adapter"
+f_network "iwn" "Intel Wireless WiFi Link 4965AGN IEEE 802.11n adapter"
+f_network "ixgbe" "Intel(R) PRO/10Gb Ethernet card"
+f_network "ixgb" "Intel(R) PRO/10Gb Ethernet card"
+f_network "ix" "Intel Etherexpress Ethernet card"
+ # Maintain sequential order of above(3): ixgbe ixgb ix
+f_network "jme" "JMicron JMC250 Gigabit/JMC260 Fast Ethernet"
+f_network "kue" "Kawasaki LSI USB Ethernet adapter"
+f_network "le" "AMD Am7900 LANCE or Am79C9xx PCnet Ethernet adapter"
+f_network "lge" "Level 1 LXT1001 Gigabit Ethernet card"
+f_network "lnc" "Lance/PCnet (Isolan/Novell NE2100/NE32-VL) Ethernet"
+f_network "lo" "Loop-back (local) network interface"
+f_network "lp" "Parallel Port IP (PLIP) peer connection"
+f_network "malo" "Marvell Libertas 88W8335 802.11 wireless adapter"
+f_network "msk" "Marvell/SysKonnect Yukon II Gigabit Ethernet"
+f_network "mxge" "Myricom Myri10GE 10Gb Ethernet card"
+f_network "nfe" "NVIDIA nForce MCP Ethernet"
+f_network "nge" "NatSemi PCI Gigabit Ethernet card"
+f_network "ng" "Vimage netgraph(4) bridged Ethernet device"
+ # Maintain sequential order of above(2): nge ng
+f_network "nve" "NVIDIA nForce MCP Ethernet"
+f_network "nxge" "Neterion Xframe 10GbE Server/Storage adapter"
+f_network "pcn" "AMD Am79c79x PCI Ethernet card"
+f_network "plip" "Parallel Port IP (PLIP) peer connection"
+f_network "ral" "Ralink Technology IEEE 802.11 wireless adapter"
+f_network "ray" "Raytheon Raylink 802.11 wireless adapter"
+f_network "re" "RealTek 8139C+/8169/8169S/8110S PCI Ethernet adapter"
+f_network "rl" "RealTek 8129/8139 PCI Ethernet card"
+f_network "rue" "RealTek USB Ethernet card"
+f_network "rum" "Ralink Technology USB IEEE 802.11 wireless adapter"
+f_network "sf" "Adaptec AIC-6915 PCI Ethernet card"
+f_network "sge" "Silicon Integrated Systems SiS190/191 Ethernet"
+f_network "sis" "SiS 900/SiS 7016 PCI Ethernet card"
+f_network "sk" "SysKonnect PCI Gigabit Ethernet card"
+f_network "snc" "SONIC Ethernet card"
+f_network "sn" "SMC/Megahertz Ethernet card"
+ # Maintain sequential order of above(2): snc sn
+f_network "sr" "SDL T1/E1 sync serial PCI card"
+f_network "ste" "Sundance ST201 PCI Ethernet card"
+f_network "stge" "Sundance/Tamarack TC9021 Gigabit Ethernet"
+f_network "ti" "Alteon Networks PCI Gigabit Ethernet card"
+f_network "tl" "Texas Instruments ThunderLAN PCI Ethernet card"
+f_network "txp" "3Com 3cR990 Ethernet card"
+f_network "tx" "SMC 9432TX Ethernet card"
+ # Maintain sequential order of above(2): txp tx
+f_network "uath" "Atheros AR5005UG and AR5005UX USB wireless adapter"
+f_network "upgt" "Conexant/Intersil PrismGT USB wireless adapter"
+f_network "ural" "Ralink Technology RT2500USB 802.11 wireless adapter"
+f_network "urtw" "Realtek 8187L USB wireless adapter"
+f_network "vge" "VIA VT612x PCI Gigabit Ethernet card"
+f_network "vlan" "IEEE 802.1Q VLAN network interface"
+f_network "vr" "VIA VT3043/VT86C100A Rhine PCI Ethernet card"
+f_network "vx" "3COM 3c590 / 3c595 Ethernet card"
+f_network "wb" "Winbond W89C840F PCI Ethernet card"
+f_network "wi" "Lucent WaveLAN/IEEE 802.11 wireless adapter"
+f_network "wpi" "Intel 3945ABG IEEE 802.11 wireless adapter"
+f_network "wx" "Intel Gigabit Ethernet (82452) card"
+f_network "xe" "Xircom/Intel EtherExpress Pro100/16 Ethernet card"
+f_network "xl" "3COM 3c90x / 3c90xB PCI Ethernet card"
+f_network "zyd" "ZyDAS ZD1211/ZD1211B USB 802.11 wireless adapter"
+
+f_dprintf "%s: Initialized %u known device names/descriptions." device.subr \
+ "$( set -- $DEVICE_NAMES; echo $# )"
+
+#
+# Scan for the above devices unless requeted otherwise
+#
+f_dprintf "%s: DEVICE_SELF_SCAN_ALL=[%s]" device.subr "$DEVICE_SELF_SCAN_ALL"
+case "$DEVICE_SELF_SCAN_ALL" in
+""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
+*) f_device_get_all
+esac
+
+f_dprintf "%s: Successfully loaded." device.subr
+
+fi # ! $_DEVICE_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/Makefile b/usr.sbin/bsdconfig/share/media/Makefile
new file mode 100644
index 0000000..ebd7c96
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+NO_OBJ=
+
+FILESDIR= ${SHAREDIR}/bsdconfig/media
+FILES= any.subr cdrom.subr common.subr directory.subr dos.subr \
+ floppy.subr ftp.subr httpproxy.subr network.subr nfs.subr \
+ options.subr tcpip.subr ufs.subr usb.subr
+
+beforeinstall:
+ mkdir -p ${DESTDIR}${FILESDIR}
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/bsdconfig/share/media/any.subr b/usr.sbin/bsdconfig/share/media/any.subr
new file mode 100644
index 0000000..f64710f
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/any.subr
@@ -0,0 +1,152 @@
+if [ ! "$_MEDIA_ANY_SUBR" ]; then _MEDIA_ANY_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/any.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/media/cdrom.subr
+f_include $BSDCFG_SHARE/media/directory.subr
+f_include $BSDCFG_SHARE/media/dos.subr
+f_include $BSDCFG_SHARE/media/floppy.subr
+f_include $BSDCFG_SHARE/media/ftp.subr
+f_include $BSDCFG_SHARE/media/httpproxy.subr
+f_include $BSDCFG_SHARE/media/nfs.subr
+f_include $BSDCFG_SHARE/media/options.subr
+f_include $BSDCFG_SHARE/media/ufs.subr
+f_include $BSDCFG_SHARE/media/usb.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+MEDIA_HELPFILE=$BSDCFG_LIBE/include/media.hlp
+
+############################################################ FUNCTIONS
+
+# f_media_get_type
+#
+# Prompt the user to select amongst the known media types (included above).
+#
+# If the user does not cancel or press Esc, invokes the f_media_set_* function
+# associated with the chosen media type. If after all that we have a struct
+# named `device_media' then success is returned, otherwise failure.
+#
+# NOTE: The f_media_set_* function should create the `device_media' struct.
+# See `struct.subr' and the above `media/*.subr' includes for more details.
+#
+f_media_get_type()
+{
+ f_dialog_title "$msg_choose_installation_media"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local prompt="$msg_choose_installation_media_description"
+ local hline="$hline_choose_help_for_more_information_on_media_types"
+ local menu_list size
+
+ menu_list="
+ '1 $msg_cd_dvd' '$msg_install_from_a_freebsd_cd_dvd'
+ '2 $msg_ftp' '$msg_install_from_an_ftp_server'
+ '3 $msg_ftp_passive'
+ '$msg_install_from_an_ftp_server_thru_firewall'
+ '4 $msg_http' '$msg_install_from_an_ftp_server_thru_proxy'
+ '5 $msg_directory' '$msg_install_from_the_existing_filesystem'
+ '6 $msg_nfs' '$msg_install_over_nfs'
+ '7 $msg_dos' '$msg_install_from_a_dos_partition'
+ '8 $msg_ufs' '$msg_install_from_a_ufs_partition'
+ '9 $msg_floppy' '$msg_install_from_a_floppy_disk_set'
+ 'A $msg_usb' '$msg_install_from_a_usb_drive'
+ 'X $msg_options' '$msg_view_set_various_media_options'
+ " # END-QUOTE
+
+ size=$( eval f_dialog_menu_size \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list )
+
+ local dialog_menu
+
+ while :; do
+ dialog_menu=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --menu \"\$prompt\" $size $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ setvar DIALOG_MENU_$$ "$dialog_menu"
+
+ local mtag
+ mtag=$( f_dialog_menutag )
+ f_dprintf "retval=%s mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq 2 ]; then
+ # The Help button was pressed
+ f_show_help "$MEDIA_HELPFILE"
+ continue
+ elif [ $retval -ne 0 ]; then
+ return $FAILURE
+ fi
+
+ case "$mtag" in
+ ?" $msg_cd_dvd") f_media_set_cdrom ;;
+ ?" $msg_ftp") f_media_set_ftp_active ;;
+ ?" $msg_ftp_passive") f_media_set_ftp_passive ;;
+ ?" $msg_http") f_media_set_http_proxy ;;
+ ?" $msg_directory") f_media_set_directory ;;
+ ?" $msg_dos") f_media_set_dos ;;
+ ?" $msg_nfs") f_media_set_nfs ;;
+ ?" $msg_ufs") f_media_set_ufs ;;
+ ?" $msg_floppy") f_media_set_floppy ;;
+ ?" $msg_usb") f_media_set_usb ;;
+ ?" $msg_options")
+ f_media_options_menu
+ continue
+ ;;
+ esac
+ break
+ done
+
+ f_struct device_media || return $FAILURE
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/any.subr
+
+fi # ! $_MEDIA_ANY_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/cdrom.subr b/usr.sbin/bsdconfig/share/media/cdrom.subr
new file mode 100644
index 0000000..f22ebd2
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/cdrom.subr
@@ -0,0 +1,210 @@
+if [ ! "$_MEDIA_CDROM_SUBR" ]; then _MEDIA_CDROM_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/cdrom.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+CDROM_MOUNTED=
+CDROM_PREVIOUSLY_MOUNTED=
+CDROM_INIT_QUIET=
+
+############################################################ FUNCTIONS
+
+# f_media_set_cdrom
+#
+# Return success if we both found and set the media type to be a CD.
+#
+f_media_set_cdrom()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_CDROM devs
+ ndevs=$( set -- $devs; echo $# )
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_interactive && f_dialog_msgbox "$msg_no_cd_dvd_devices_found"
+ return $FAILURE
+ elif [ $ndevs -gt 1 ]; then
+ local title="$msg_choose_a_cd_dvd_type"
+ local prompt="$msg_please_select_a_cd_dvd_drive"
+ local hline=""
+
+ local dev retval
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_CDROM \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ retval=$?
+ [ "$dev" ] || return $FAILURE
+
+ f_device_find "$dev" $DEVICE_TYPE_CDROM devs
+ [ "$devs" ] || return $FAILURE
+ dev="${devs%%[$IFS]*}"
+
+ f_struct_copy device_$dev device_media
+ [ $retval -eq $SUCCESS ] || return $FAILURE
+ else
+ f_struct_copy device_$devs device_media
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_cdrom $device
+#
+# Initializes the CDROM media device. Returns success if able to mount the CD
+# device using mount_cd9660(8).
+#
+f_media_init_cdrom()
+{
+ local dev="$1" devname err
+
+ device_$dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for CDROM device. devname=[%s]" \
+ "$devname"
+
+ if [ "$CDROM_MOUNTED" ]; then
+ f_dprintf "CDROM device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ] &&
+ ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
+ then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+
+ if ! err=$( mount_cd9660 "$devname" "$MOUNTPOINT" 2>&1 )
+ then
+ err="${err#mount_cd9660: }"; err="${err#$devname: }"
+ case "$err" in
+ "Device busy")
+ # Perhaps the CDROM drive is already mounted as /cdrom
+ if f_mounted /cdrom; then
+ CDROM_PREVIOUSLY_MOUNTED=1
+ MOUNTPOINT=/cdrom
+ err=
+ fi
+ ;;
+ esac
+ case "$err" in
+ "") : good ;; # no error
+ *)
+ [ "$CDROM_INIT_QUIET" ] ||
+ f_show_msg "$msg_error_mounting_device" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+ esac
+ fi
+ CDROM_MOUNTED=1
+
+ : xxx # /cdrom.inf has been deprecated since 9.0-R
+
+ # No other CDROM media validation at this time
+
+ return $SUCCESS
+}
+
+# f_media_get_cdrom $device $file [$probe_only]
+#
+# Returns data from $file on a mounted CDROM device. Similar to cat(1).
+# $probe_only is currently unused by this media type.
+#
+f_media_get_cdrom()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_cdrom: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ f_media_generic_get "$MOUNTPOINT" "$file"
+}
+
+# f_media_shutdown_cdrom $device
+#
+# Shuts down the CDROM device and ejects the media using f_media_eject_cdrom(),
+# below. Return status should be ignored.
+#
+f_media_shutdown_cdrom()
+{
+ local dev="$1" err
+
+ [ "$CDROM_MOUNTED" ] || return
+
+ if [ "$CDROM_PREVIOUSLY_MOUNTED" ]; then
+ CDROM_MOUNTED=
+ return $SUCCESS
+ fi
+
+ if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_cdrom_dvd" \
+ "$MOUNTPOINT" "$err"
+ else
+ CDROM_MOUNTED=
+ fi
+
+ f_media_eject_cdrom "$dev"
+}
+
+# f_media_eject_cdrom $device
+#
+# Eject the media from the CDROM device. Returns success.
+#
+f_media_eject_cdrom()
+{
+ local dev="$1" devname err
+ device_$dev get name devname || return $SUCCESS
+ case "$devname" in /dev/iso9660/*) return $SUCCESS; esac
+ f_dprintf "Ejecting CDROM/DVD at %s" "$devname"
+ if ! err=$( cdcontrol -f "$devname" eject 2>&1 ); then
+ f_dprintf "Could not eject the CDROM/DVD from %s: %s" \
+ "$devname" "${err#cdcontrol: }"
+ fi
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/cdrom.subr
+
+fi # ! $_MEDIA_CDROM_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/common.subr b/usr.sbin/bsdconfig/share/media/common.subr
new file mode 100644
index 0000000..589bbdc
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/common.subr
@@ -0,0 +1,109 @@
+if [ ! "$_MEDIA_COMMON_SUBR" ]; then _MEDIA_COMMON_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/common.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+
+############################################################ GLOBALS
+
+#
+# Where to mount media
+#
+MOUNTPOINT=/dist
+
+############################################################ FUNCTIONS
+
+# f_media_open
+#
+# Returms success if able to initialize the media device.
+#
+f_media_open()
+{
+ { # Verify and initialize device media if-defined
+ f_struct device_media &&
+ f_media_verify &&
+ f_device_init media
+ } || return $FAILURE
+}
+
+# f_media_close
+#
+# Shuts down the media device, see f_device_shutdown() from device.subr for
+# more details.
+#
+f_media_close()
+{
+ f_struct device_media &&
+ f_device_shutdown media
+ f_struct_free device_media
+}
+
+# f_media_verify
+#
+# Returns success if the media device is available, and if not, prompts the
+# user to select a media type. See f_media_get_type() from media/any.subr for
+# more details.
+#
+f_media_verify()
+{
+ f_struct device_media || f_media_get_type
+}
+
+# f_media_generic_get $base $file
+#
+# A generic open which follows a well-known "path" of places to look.
+#
+f_media_generic_get()
+{
+ local base="$1" file="$2" rel path
+
+ f_getvar $VAR_RELNAME rel
+ for path in \
+ "$base/$file" \
+ "$base/FreeBSD/$file" \
+ "$base/releases/$file" \
+ "$base/$rel/$file" \
+ ; do
+ if [ -f "$path" -a -r "$path" ]; then
+ cat "$path"
+ return
+ fi
+ done
+ cat "$base/releases/$rel/$file" # Final path to try
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/common.subr
+
+fi # ! $_MEDIA_COMMON_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/directory.subr b/usr.sbin/bsdconfig/share/media/directory.subr
new file mode 100644
index 0000000..3831140
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/directory.subr
@@ -0,0 +1,146 @@
+if [ ! "$_MEDIA_DIRECTORY_SUBR" ]; then _MEDIA_DIRECTORY_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/directory.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+DIRECTORY_CHECKED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_directory
+#
+# Return success if we both found and set the media type to be a local
+# directory.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_DIRECTORY_PATH
+# Path to an existing directory containing the FreeBSD
+# distribution files.
+#
+f_media_set_directory()
+{
+ local path
+
+ f_media_close
+
+ f_variable_get_value $VAR_DIRECTORY_PATH \
+ "$msg_enter_a_fully_qualified_pathname_for_the_directory"
+ f_getvar $VAR_DIRECTORY_PATH path
+ [ "$path" ] || return $FAILURE
+
+ f_struct_new DEVICE device_directory
+ device_directory set get f_media_get_directory
+ device_directory set init f_media_init_directory
+ device_directory set shutdown f_media_shutdown_directory
+ device_directory set private "$path"
+
+ f_struct_copy device_directory device_media
+ f_struct_free device_directory
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_directory $device
+#
+# Initializes the Directory media device. Returns success if the directory path
+# both exists and is a directory.
+#
+f_media_init_directory()
+{
+ local dev="$1" path
+
+ device_$dev get private path || return $FAILURE
+ f_dprintf "Init routine called for Directory device. path=[%s]" \
+ "$path"
+
+ # Track whether we've been through here before (for remote filesystems
+ # mounted in the directory path, not repeating these queries saves us
+ # valuable time for slow/uncooperative links).
+ if [ "$DIRECTORY_CHECKED" ]; then
+ f_dprintf "Directory device already checked."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$path" ]; then
+ f_show_msg "$msg_no_such_file_or_directory" \
+ "f_media_init_directory" "$path"
+ return $FAILURE
+ elif [ ! -d "$path" ]; then
+ f_show_msg "$msg_not_a_directory" \
+ "f_media_init_directory" "$path"
+ return $FAILURE
+ fi
+ DIRECTORY_CHECKED=1
+ return $SUCCESS
+}
+
+# f_media_get_directory $device $file [$probe_only]
+#
+# Returns data from $file in the existing/current filesystem. Similar to
+# cat(1). $probe_only is currently unused by this media type.
+#
+f_media_get_directory()
+{
+ local dev="$1" file="$2" probe_only="$3" path
+
+ f_dprintf "f_media_get_directory: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ device_$dev get private path
+ f_media_generic_get "$path" "$file"
+}
+
+# f_media_shutdown_directory $device
+#
+# Shuts down the Directory device. Return status should be ignored.
+#
+f_media_shutdown_directory()
+{
+ DIRECTORY_CHECKED=
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/directory.subr
+
+fi # ! $_MEDIA_DIRECTORY_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/dos.subr b/usr.sbin/bsdconfig/share/media/dos.subr
new file mode 100644
index 0000000..3e59fb6
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/dos.subr
@@ -0,0 +1,164 @@
+if [ ! "$_MEDIA_DOS_SUBR" ]; then _MEDIA_DOS_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/dos.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+DOS_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_dos
+#
+# Return success if we both found and set the media type to be a DOS partition.
+#
+f_media_set_dos()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_DOS devs
+ ndevs=$( set -- $devs; echo $# )
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_dialog_msgbox "$msg_no_dos_primary_partitions_found"
+ return $FAILURE
+ elif [ $ndevs -gt 1 ]; then
+ local title="$msg_choose_a_dos_partition"
+ local prompt="$msg_please_select_dos_partition"
+ local hline=""
+
+ local dev retval
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_DOS \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ retval=$?
+ [ "$dev" ] || return $FAILURE
+
+ f_device_find "$dev" $DEVICE_TYPE_DOS devs
+ [ "$devs" ] || return $FAILURE
+ dev="${devs%%[$IFS]*}"
+
+ f_struct_copy device_$dev device_media
+ [ $retval -eq $SUCCESS ] || return $FAILURE
+ else
+ f_struct_copy device_$devs device_media
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_dos $device
+#
+# Initializes the DOS media device. Returns success if able to mount the DOS
+# partition device using mount_msdosfs(8).
+#
+f_media_init_dos()
+{
+ local dev="$1" devname err
+
+ device_$dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for DOS device. devname=[%s]" \
+ "$devname"
+
+ if [ "$DOS_MOUNTED" ]; then
+ f_dprintf "DOS device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ] &&
+ ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
+ then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+
+ if ! err=$( mount_msdosfs "$devname" "$MOUNTPOINT" 2>&1 )
+ then
+ err="${err#mount_msdosfs: }"; err="${err#$devname: }"
+ f_show_msg "$msg_error_mounting_device" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+ fi
+ DOS_MOUNTED=1
+ return $SUCCESS
+}
+
+# f_media_get_dos $device $file [$probe_only]
+#
+# Returns data from $file on a mounted DOS partition device. Similar to cat(1).
+# $probe_only is currently unused by this media type.
+#
+f_media_get_dos()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_dos: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ f_media_generic_get "$MOUNTPOINT" "$file"
+}
+
+# f_media_shutdown_dos $device
+#
+# Shuts down the DOS partition device using umount(8). Return status should be
+# ignored.
+#
+f_media_shutdown_dos()
+{
+ local dev="$1" err
+
+ [ "$DOS_MOUNTED" ] || return
+
+ if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_dos_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ DOS_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/dos.subr
+
+fi # ! $_MEDIA_DOS_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/floppy.subr b/usr.sbin/bsdconfig/share/media/floppy.subr
new file mode 100644
index 0000000..c874c61
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/floppy.subr
@@ -0,0 +1,214 @@
+if [ ! "$_MEDIA_FLOPPY_SUBR" ]; then _MEDIA_FLOPPY_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/floppy.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+FLOPPY_MOUNTED=
+FLOPPY_DISTWANTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_floppy
+#
+# Return success if we both found and set the media type to be a floppy.
+#
+f_media_set_floppy()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_FLOPPY devs
+ ndevs=$( set -- $devs; echo $# )
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_interactive && f_dialog_msgbox "$msg_no_floppy_devices_found"
+ return $FAILURE
+ elif [ $ndevs -gt 1 ]; then
+ local title="$msg_choose_a_floppy_drive"
+ local prompt="$msg_please_select_a_floppy_drive"
+ local hline=""
+
+ local dev retval
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_FLOPPY \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ retval=$?
+ [ "$dev" ] || return $FAILURE
+
+ f_device_find "$dev" $DEVICE_TYPE_FLOPPY devs
+ [ "$devs" ] || return $FAILURE
+ dev="${devs%%[$IFS]*}"
+
+ f_struct_copy device_$dev device_media
+ [ $retval -eq $SUCCESS ] || return $FAILURE
+ else
+ f_struct_copy device_$devs device_media
+ fi
+
+ f_struct device_media &&
+ device_media unset private
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_floppy $device
+#
+# Initializes the Floppy media device. Returns success if able to mount the
+# Floppy disk device using either mount_msdosfs(8) or mount(8) (tried in that
+# order).
+#
+f_media_init_floppy()
+{
+ local dev="$1" devname err
+
+ device_$dev get devname devname || return $FAILURE
+ f_dprintf "Init floppy called for %s distribution. devname=[%s]" \
+ "${FLOPPY_DISTWANTED:-some}" "$devname"
+
+ if [ "$FLOPPY_MOUNTED" ]; then
+ f_dprintf "Floppy device already mounted."
+ return $SUCCESS
+ fi
+
+ local mp
+ device_$dev get private mp
+ if [ ! -e "${mp:=$MOUNTPOINT}" ] && ! f_quietly mkdir -p "$mp"; then
+ f_show_msg "$msg_unable_to_make_directory_mountpoint" \
+ "$mp" "$devname"
+ return $FAILURE
+ fi
+
+ if f_interactive; then
+ local desc
+ device_$dev get desc desc
+ if [ "$FLOPPY_DISTWANTED" ]; then
+ f_show_msg "$msg_please_insert_floppy_in_drive" "$desc"
+ else
+ f_show_msg "$msg_please_insert_floppy_containing" \
+ "$FLOPPY_DISTWANTED" "$desc"
+ fi
+ fi
+
+ if ! {
+ f_quietly mount_msdosfs -o ro -m 0777 -u 0 -g 0 "$devname" "$mp" ||
+ err=$( mount -o ro "$devname" "$mp" 2>&1 )
+ }; then
+ err="${err#mount: }"; err="${err#*: }"
+ local name
+ device_$dev get name name
+ f_show_msg "$msg_error_mounting_floppy_device" \
+ "$name" "$devname" "$mp" "$err"
+ return $FAILURE
+ fi
+ FLOPPY_MOUNTED=1
+ FLOPPY_DISTWANTED=
+ return $SUCCESS
+}
+
+# f_media_get_floppy $device $file [$probe_only]
+#
+# Returns data from $file on a mounted Floppy disk device. Similar to cat(1).
+# If $probe_only is present and non-null, limits retries to zero.
+#
+f_media_get_floppy()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_floppy: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ #
+ # floppies don't use f_media_generic_get() because it's too expensive
+ # to speculatively open files on a floppy disk. Make user get it
+ # right or give up with floppies.
+ #
+ local mp
+ device_$dev get private mp
+ local fp="${mp:=$MOUNTPOINT}/$file"
+ if ! [ -f "$fp" -a -r "$fp" ]; then
+ local nretries=4
+ [ "$probe_only" ] && return $FAILURE
+ while ! [ -f "$fp" -a -r "$fp" ]; do
+ if [ $nretries -eq 0 ]; then
+ f_show_msg "$msg_failed_to_get_floppy_file" \
+ "$fp"
+ return $FAILURE
+ fi
+ FLOPPY_DISTWANTED="$fp"
+ f_media_shutdown_floppy "$dev"
+ f_media_init_floppy "$dev" || return $FAILURE
+ nretries=$(( $nretries - 1 ))
+ done
+ fi
+ cat "$fp"
+}
+
+# f_media_shutdown_floppy $device
+#
+# Shuts down the Floppy disk device using umount(8). Return status should be
+# ignored.
+#
+f_media_shutdown_floppy()
+{
+ local dev="$1" err mp
+
+ [ "$FLOPPY_MOUNTED" ] || return
+
+ device_$dev get private mp
+ if ! err=$( umount -f "${mp:=$MOUNTPOINT}" 2>&1 ); then
+ err="${err#umount: }"; err="${err#*:}"
+ f_dprintf "Umount of floppy on %s failed: %s" "$mp" "$err"
+ else
+ FLOPPY_MOUNTED=
+ if f_interactive && [ "$_systemState" != "fixit" ]; then
+ local desc
+ device_$dev get desc desc
+ f_show_msg "$msg_you_may_remove_the_floppy" "$desc"
+ fi
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/floppy.subr
+
+fi # ! $_MEDIA_FLOPPY_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/ftp.subr b/usr.sbin/bsdconfig/share/media/ftp.subr
new file mode 100644
index 0000000..ecc7724
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/ftp.subr
@@ -0,0 +1,893 @@
+if [ ! "$_MEDIA_FTP_SUBR" ]; then _MEDIA_FTP_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/ftp.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/strings.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/media/network.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+FTP_SKIP_RESOLV=
+
+URL_MAX=261261 # according to actual fetch(1) test-results
+
+FTP_DIRS="
+ .
+ releases/$UNAME_P
+ snapshots/$UNAME_P
+ pub/FreeBSD
+ pub/FreeBSD/releases/$UNAME_P
+ pub/FreeBSD/snapshots/$UNAME_P
+ pub/FreeBSD-Archive/old-releases/$UNAME_P
+" # END-QUOTE
+
+############################################################ FUNCTIONS
+
+# f_dialog_menu_media_ftp
+#
+# Prompt the user to select from a range of ``built-in'' FTP servers or specify
+# their own. If the user makes a choice and doesn't cancel or press Esc, stores
+# the user's choice in VAR_FTP_PATH (see variables.subr) and returns success.
+#
+f_dialog_menu_media_ftp()
+{
+ f_dialog_title "$msg_please_select_a_freebsd_ftp_distribution_site"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+
+ local prompt="$msg_please_select_the_site_closest_to_you_or_other"
+ local hline="$msg_select_a_site_thats_close"
+ local menu_list="
+ '$msg_main_site' 'ftp.freebsd.org'
+ 'URL' '$msg_specify_some_other_ftp_site'
+ '$msg_snapshots_server_japan'
+ 'snapshots.jp.freebsd.org'
+ '$msg_snapshots_server_sweden'
+ 'snapshots.se.freebsd.org'
+ 'IPv6 $msg_main_site' 'ftp.freebsd.org'
+ ' IPv6 $msg_ireland' 'ftp3.ie.freebsd.org'
+ ' IPv6 $msg_israel' 'ftp.il.freebsd.org'
+ ' IPv6 $msg_japan' 'ftp2.jp.freebsd.org'
+ ' IPv6 $msg_usa' 'ftp4.us.freebsd.org'
+ ' IPv6 $msg_turkey' 'ftp2.tr.freebsd.org'
+ '$msg_primary' 'ftp1.freebsd.org'
+ ' $msg_primary #2' 'ftp2.freebsd.org'
+ ' $msg_primary #3' 'ftp3.freebsd.org'
+ ' $msg_primary #4' 'ftp4.freebsd.org'
+ ' $msg_primary #5' 'ftp5.freebsd.org'
+ ' $msg_primary #6' 'ftp6.freebsd.org'
+ ' $msg_primary #7' 'ftp7.freebsd.org'
+ ' $msg_primary #8' 'ftp8.freebsd.org'
+ ' $msg_primary #9' 'ftp9.freebsd.org'
+ ' $msg_primary #10' 'ftp10.freebsd.org'
+ ' $msg_primary #11' 'ftp11.freebsd.org'
+ ' $msg_primary #12' 'ftp12.freebsd.org'
+ ' $msg_primary #13' 'ftp13.freebsd.org'
+ ' $msg_primary #14' 'ftp14.freebsd.org'
+ '$msg_argentina' 'ftp.ar.freebsd.org'
+ '$msg_australia' 'ftp.au.freebsd.org'
+ ' $msg_australia #2' 'ftp2.au.freebsd.org'
+ ' $msg_australia #3' 'ftp3.au.freebsd.org'
+ '$msg_austria' 'ftp.at.freebsd.org'
+ ' $msg_austria #2' 'ftp2.at.freebsd.org'
+ '$msg_brazil' 'ftp.br.freebsd.org'
+ ' $msg_brazil #2' 'ftp2.br.freebsd.org'
+ ' $msg_brazil #3' 'ftp3.br.freebsd.org'
+ ' $msg_brazil #4' 'ftp4.br.freebsd.org'
+ ' $msg_brazil #5' 'ftp5.br.freebsd.org'
+ ' $msg_brazil #6' 'ftp6.br.freebsd.org'
+ ' $msg_brazil #7' 'ftp7.br.freebsd.org'
+ '$msg_canada' 'ftp.ca.freebsd.org'
+ '$msg_china' 'ftp.cn.freebsd.org'
+ ' $msg_china #2' 'ftp2.cn.freebsd.org'
+ '$msg_croatia' 'ftp.hr.freebsd.org'
+ '$msg_czech_republic' 'ftp.cz.freebsd.org'
+ '$msg_denmark' 'ftp.dk.freebsd.org'
+ ' $msg_denmark #2' 'ftp2.dk.freebsd.org'
+ '$msg_estonia' 'ftp.ee.freebsd.org'
+ '$msg_finland' 'ftp.fi.freebsd.org'
+ '$msg_france' 'ftp.fr.freebsd.org'
+ ' $msg_france #2' 'ftp2.fr.freebsd.org'
+ ' $msg_france #3' 'ftp3.fr.freebsd.org'
+ ' $msg_france #5' 'ftp5.fr.freebsd.org'
+ ' $msg_france #6' 'ftp6.fr.freebsd.org'
+ ' $msg_france #8' 'ftp8.fr.freebsd.org'
+ '$msg_germany' 'ftp.de.freebsd.org'
+ ' $msg_germany #2' 'ftp2.de.freebsd.org'
+ ' $msg_germany #3' 'ftp3.de.freebsd.org'
+ ' $msg_germany #4' 'ftp4.de.freebsd.org'
+ ' $msg_germany #5' 'ftp5.de.freebsd.org'
+ ' $msg_germany #6' 'ftp6.de.freebsd.org'
+ ' $msg_germany #7' 'ftp7.de.freebsd.org'
+ ' $msg_germany #8' 'ftp8.de.freebsd.org'
+ '$msg_greece' 'ftp.gr.freebsd.org'
+ ' $msg_greece #2' 'ftp2.gr.freebsd.org'
+ '$msg_hungary' 'ftp.hu.freebsd.org'
+ '$msg_iceland' 'ftp.is.freebsd.org'
+ '$msg_ireland' 'ftp.ie.freebsd.org'
+ ' $msg_ireland #2' 'ftp2.ie.freebsd.org'
+ ' $msg_ireland #3' 'ftp3.ie.freebsd.org'
+ '$msg_israel' 'ftp.il.freebsd.org'
+ '$msg_italy' 'ftp.it.freebsd.org'
+ '$msg_japan' 'ftp.jp.freebsd.org'
+ ' $msg_japan #2' 'ftp2.jp.freebsd.org'
+ ' $msg_japan #3' 'ftp3.jp.freebsd.org'
+ ' $msg_japan #4' 'ftp4.jp.freebsd.org'
+ ' $msg_japan #5' 'ftp5.jp.freebsd.org'
+ ' $msg_japan #6' 'ftp6.jp.freebsd.org'
+ ' $msg_japan #7' 'ftp7.jp.freebsd.org'
+ ' $msg_japan #8' 'ftp8.jp.freebsd.org'
+ ' $msg_japan #9' 'ftp9.jp.freebsd.org'
+ '$msg_korea' 'ftp.kr.freebsd.org'
+ ' $msg_korea #2' 'ftp2.kr.freebsd.org'
+ '$msg_lithuania' 'ftp.lt.freebsd.org'
+ '$msg_netherlands' 'ftp.nl.freebsd.org'
+ ' $msg_netherlands #2' 'ftp2.nl.freebsd.org'
+ '$msg_norway' 'ftp.no.freebsd.org'
+ ' $msg_norway #3' 'ftp3.no.freebsd.org'
+ '$msg_poland' 'ftp.pl.freebsd.org'
+ ' $msg_poland #2' 'ftp2.pl.freebsd.org'
+ ' $msg_poland #5' 'ftp5.pl.freebsd.org'
+ '$msg_portugal' 'ftp.pt.freebsd.org'
+ ' $msg_portugal #2' 'ftp2.pt.freebsd.org'
+ ' $msg_portugal #4' 'ftp4.pt.freebsd.org'
+ '$msg_romania' 'ftp.ro.freebsd.org'
+ '$msg_russia' 'ftp.ru.freebsd.org'
+ ' $msg_russia #2' 'ftp2.ru.freebsd.org'
+ ' $msg_russia #3' 'ftp3.ru.freebsd.org'
+ ' $msg_russia #4' 'ftp4.ru.freebsd.org'
+ '$msg_singapore' 'ftp.sg.freebsd.org'
+ '$msg_slovak_republic' 'ftp.sk.freebsd.org'
+ '$msg_slovenia' 'ftp.si.freebsd.org'
+ ' $msg_slovenia #2' 'ftp2.si.freebsd.org'
+ '$msg_south_africa' 'ftp.za.freebsd.org'
+ ' $msg_south_africa #2' 'ftp2.za.freebsd.org'
+ ' $msg_south_africa #3' 'ftp3.za.freebsd.org'
+ ' $msg_south_africa #4' 'ftp4.za.freebsd.org'
+ '$msg_spain' 'ftp.es.freebsd.org'
+ ' $msg_spain #2' 'ftp2.es.freebsd.org'
+ ' $msg_spain #3' 'ftp3.es.freebsd.org'
+ '$msg_sweden' 'ftp.se.freebsd.org'
+ ' $msg_sweden #2' 'ftp2.se.freebsd.org'
+ ' $msg_sweden #3' 'ftp3.se.freebsd.org'
+ ' $msg_sweden #4' 'ftp4.se.freebsd.org'
+ ' $msg_sweden #5' 'ftp5.se.freebsd.org'
+ '$msg_switzerland' 'ftp.ch.freebsd.org'
+ ' $msg_switzerland #2' 'ftp2.ch.freebsd.org'
+ '$msg_taiwan' 'ftp.tw.freebsd.org'
+ ' $msg_taiwan #2' 'ftp2.tw.freebsd.org'
+ ' $msg_taiwan #3' 'ftp3.tw.freebsd.org'
+ ' $msg_taiwan #4' 'ftp4.tw.freebsd.org'
+ ' $msg_taiwan #6' 'ftp6.tw.freebsd.org'
+ ' $msg_taiwan #11' 'ftp11.tw.freebsd.org'
+ '$msg_turkey' 'ftp.tr.freebsd.org'
+ ' $msg_turkey #2' 'ftp2.tr.freebsd.org'
+ '$msg_uk' 'ftp.uk.freebsd.org'
+ ' $msg_uk #2' 'ftp2.uk.freebsd.org'
+ ' $msg_uk #3' 'ftp3.uk.freebsd.org'
+ ' $msg_uk #4' 'ftp4.uk.freebsd.org'
+ ' $msg_uk #5' 'ftp5.uk.freebsd.org'
+ ' $msg_uk #6' 'ftp6.uk.freebsd.org'
+ '$msg_ukraine' 'ftp.ua.freebsd.org'
+ ' $msg_ukraine #2' 'ftp2.ua.freebsd.org'
+ ' $msg_ukraine #5' 'ftp5.ua.freebsd.org'
+ ' $msg_ukraine #6' 'ftp6.ua.freebsd.org'
+ ' $msg_ukraine #7' 'ftp7.ua.freebsd.org'
+ ' $msg_ukraine #8' 'ftp8.ua.freebsd.org'
+ '$msg_usa #1' 'ftp1.us.freebsd.org'
+ ' $msg_usa #2' 'ftp2.us.freebsd.org'
+ ' $msg_usa #3' 'ftp3.us.freebsd.org'
+ ' $msg_usa #4' 'ftp4.us.freebsd.org'
+ ' $msg_usa #5' 'ftp5.us.freebsd.org'
+ ' $msg_usa #6' 'ftp6.us.freebsd.org'
+ ' $msg_usa #7' 'ftp7.us.freebsd.org'
+ ' $msg_usa #8' 'ftp8.us.freebsd.org'
+ ' $msg_usa #9' 'ftp9.us.freebsd.org'
+ ' $msg_usa #10' 'ftp10.us.freebsd.org'
+ ' $msg_usa #11' 'ftp11.us.freebsd.org'
+ ' $msg_usa #12' 'ftp12.us.freebsd.org'
+ ' $msg_usa #13' 'ftp13.us.freebsd.org'
+ ' $msg_usa #14' 'ftp14.us.freebsd.org'
+ ' $msg_usa #15' 'ftp15.us.freebsd.org'
+ " # END-QUOTE
+
+ local size
+ size=$( eval f_dialog_menu_size \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list )
+
+ local dialog_menu retval mtag value
+ dialog_menu=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_cancel\" \
+ --menu \"\$prompt\" $size \
+ $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ retval=$?
+ setvar DIALOG_MENU_$$ "$dialog_menu"
+ mtag=$( f_dialog_menutag )
+
+ [ $retval -eq 0 ] || return $FAILURE
+
+ case "$mtag" in
+ URL) setvar $VAR_FTP_PATH "other" ;;
+ *)
+ value=$( eval f_dialog_menutag2item \"\$mtag\" $menu_list )
+ setvar $VAR_FTP_PATH "ftp://$value"
+ esac
+
+ return $SUCCESS
+}
+
+# f_media_set_ftp
+#
+# Return success if we both found and set the media type to be an FTP server.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_FTP_PATH
+# Can be a URL (including "ftp://" protocol-prefix) or "other"
+# (user is prompted to enter FTP URL). If a URL, can optionally
+# contain directory prefix after hostname/port. Valid examples
+# include:
+# ftp://myhost
+# ftp://somename:21/pub/
+# ftp://192.168.2.3/pub/
+# ftp://[::1]:21/
+# The default port if not specified is 21.
+# VAR_NAMESERVER [Optional]
+# If set, overrides resolv.conf(5) and sets the nameserver that
+# is used to convert names into addresses (when a name converts
+# into multiple addresses, the first address to successfully
+# connect is used).
+#
+# Meanwhile, the following variables from variable.subr are set after
+# successful execution:
+#
+# VAR_FTP_HOST
+# The FTP host to connect to, parsed from VAR_FTP_PATH. In the
+# example case of IPv6 where VAR_FTP_PATH is a "ftp://[::1]" this
+# variable will be set to "::1" (the outer brackets are removed).
+# VAR_FTP_PORT
+# The TCP port to connect to, parsed from VAR_FTP_PATH. Usually
+# 21 unless VAR_FTP_PATH was of one of the following forms:
+# ftp://hostname:OTHER_PORT
+# ftp://hostname:OTHER_PORT/*
+# ftp://ip:OTHER_PORT
+# ftp://ip:OTHER_PORT/*
+# ftp://[ip6]:OTHER_PORT
+# ftp://[ip6]:OTHER_PORT/*
+# VAR_FTP_DIR
+# If VAR_FTP_PATH contained a directory element (e.g.,
+# "ftp://localhost/pub") this variable contains only the
+# directory element (e.g., "/pub").
+#
+f_media_set_ftp()
+{
+ f_media_close
+
+ local url
+ f_getvar $VAR_FTP_PATH url
+
+ # If we've been through here before ...
+ if f_struct device_network && [ "${url#$msg_other}" ]; then
+ f_dialog_yesno "$msg_reuse_old_ftp_site_selection_values" ||
+ url=
+ fi
+
+ if [ ! "$url" ]; then
+ f_dialog_menu_media_ftp || return $FAILURE
+ f_getvar $VAR_FTP_PATH url
+ fi
+ [ "$url" ] || return $FAILURE
+
+ case "$url" in
+ other)
+ setvar $VAR_FTP_PATH "ftp://"
+ f_variable_get_value $VAR_FTP_PATH \
+ "$msg_please_specify_url_of_a_freebsd_distribution"
+ f_getvar $VAR_FTP_PATH url
+ if [ ! "${url#ftp://}" ]; then
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ if [ ${#url} -gt ${URL_MAX:-261261} ]; then
+ f_show_msg "$msg_length_of_specified_url_is_too_long" \
+ ${#url} ${URL_MAX:-261261}
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ case "$url" in
+ ftp://*) : valid URL ;;
+ *)
+ f_show_msg "$msg_sorry_invalid_url" "$url"
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ esac
+ esac
+ case "$url" in
+ ftp://*) : valid URL ;;
+ *)
+ f_show_msg "$msg_sorry_invalid_url" "$url"
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ esac
+
+ # Set the name of the FTP device to the URL
+ f_struct_new DEVICE device_ftp
+ device_ftp set name "$url"
+
+ if ! f_struct device_network ||
+ ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
+ then
+ f_struct device_network &&
+ f_device_shutdown network
+ if ! f_device_select_tcp; then
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ local dev
+ f_getvar $VAR_NETWORK_DEVICE dev
+ f_struct_copy "device_$dev" device_network
+ fi
+ if ! f_device_init network; then
+ f_dprintf "f_media_set_ftp: %s" "$msg_net_device_init_failed"
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+
+ local hostname="${url#*://}" port=21 dir=/
+ case "$hostname" in
+ "["*"]")
+ hostname="${hostname#\[}"
+ hostname="${hostname%%\]*}"
+ ;;
+ "["*"]/"*)
+ hostname="${hostname#\[}"
+ dir="/${hostname#*/}"
+ hostname="${hostname%%\]*}"
+ ;;
+ *"/"*)
+ dir="/${hostname#*/}"
+ hostname="${hostname%%/*}"
+ ;;
+ "["*"]:"*)
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ *)
+ hostname="${hostname%%/*}"
+ esac
+
+ f_dprintf "hostname = \`%s'" "$hostname"
+ f_dprintf "dir = \`%s'" "$dir"
+ f_dprintf "port \# = \`%d'" "$port"
+
+ local ns
+ f_getvar $VAR_NAMESERVER ns
+ [ "$ns" ] || f_resolv_conf_nameservers ns
+ if [ "$ns" -a ! "$FTP_SKIP_RESOLV" ] && ! {
+ f_validate_ipaddr "$hostname" ||
+ f_validate_ipaddr6 "$hostname"
+ }; then
+ f_show_info "$msg_looking_up_host" "$hostname"
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_set_ftp" "$hostname"
+ if ! f_quietly f_host_lookup "$hostname"; then
+ f_show_msg "$msg_cannot_resolve_hostname" "$hostname"
+ f_struct device_network &&
+ f_device_shutdown network
+ f_struct_free device_network
+ unset $VAR_FTP_PATH
+ return $FAILURE
+ fi
+ f_dprintf "Found DNS entry for %s successfully." "$hostname"
+ fi
+
+ setvar $VAR_FTP_HOST "$hostname"
+ setvar $VAR_FTP_PORT "$port"
+ setvar $VAR_FTP_DIR "$dir"
+
+ device_ftp set type $DEVICE_TYPE_FTP
+ device_ftp set init f_media_init_ftp
+ device_ftp set get f_media_get_ftp
+ device_ftp set shutdown f_media_shutdown_ftp
+ device_ftp set private network
+ f_struct_copy device_ftp device_media
+ f_struct_free device_ftp
+
+ return $SUCCESS
+}
+
+# f_media_set_ftp_active
+#
+# Wrapper to f_media_set_ftp to access FTP servers actively.
+#
+f_media_set_ftp_active()
+{
+ setvar $VAR_FTP_STATE "active"
+ f_media_set_ftp
+}
+
+# f_media_set_ftp_passive
+#
+# Wrapper to f_media_set_ftp to access FTP servers passively.
+#
+f_media_set_ftp_passive()
+{
+ setvar $VAR_FTP_STATE "passive"
+ f_media_set_ftp
+}
+
+# f_media_set_ftp_userpass
+#
+# Prompt the user to enter/confirm the username/password variables that will
+# be used to communicate with the FTP servers. Returns success if the user does
+# not cancel or press Esc to either username or password.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_FTP_USER
+# The username to send via ftp(1) when connecting to an FTP
+# server.
+# VAR_FTP_PASS
+# The password to send with the above username.
+#
+# Does not prompt for confirmation of values if VAR_NONINTERACTIVE is set (see
+# variable.subr for more information).
+#
+f_media_set_ftp_userpass()
+{
+ local user pass
+ f_variable_get_value $VAR_FTP_USER \
+ "$msg_please_enter_the_username_you_wish_to_login_as"
+ f_getvar $VAR_FTP_USER user
+ if [ "$user" ]; then
+ f_variable_get_value $VAR_FTP_PASS \
+ "$msg_please_enter_the_password_for_this_user"
+ f_getvar $VAR_FTP_PASS pass
+ else
+ pass=
+ fi
+ [ "$pass" ] # Return status
+}
+
+# f_device_network_up $device
+#
+# Brings up attached network device, if any - takes FTP device as arg.
+#
+f_device_network_up()
+{
+ local dev="$1" netDev
+ device_$dev get private netDev || return $SUCCESS # No net == happy net
+ f_device_init $netDev
+}
+
+# f_device_network_down $device
+#
+# Brings down attached network device, if any - takes FTP device as arg.
+#
+f_device_network_down()
+{
+ local dev="$1" netDev
+ device_$dev get private netDev || return $SUCCESS
+ f_device_shutdown $netDev
+}
+
+# f_media_init_ftp $device
+#
+# Initializes the FTP media device. Returns success if both able to log into
+# the FTP server and confirm the existence of at least one known release path
+# using ftp(1).
+#
+# Variables from variable.subr used to initialize the connection are as follows
+# (all of which are configured by f_media_set_ftp above):
+#
+# VAR_FTP_PATH
+# The unparsed FTP URL representing the server to contact.
+# Usually "ftp://server" for example. Can contain TCP port number
+# and/or directory path (but should not contain username/password
+# info).
+# VAR_FTP_HOST
+# The FTP host to connect to. Can be an IPv4 address (e.g.,
+# 127.0.0.1), IPv6 address (e.g., ::1), or DNS hostname. Usually
+# set automatically in f_media_set_ftp() by parsing VAR_FTP_PATH.
+# VAR_FTP_PORT
+# The TCP port to connect to. Usually set automatically in
+# f_media_set_ftp() by parsing VAR_FTP_PATH.
+# VAR_FTP_DIR
+# The base FTP directory to use when downloading files from the
+# FTP server. Usually set automatically in f_media_set_ftp() by
+# parsing VAR_FTP_PATH.
+# VAR_FTP_USER [Optional]
+# If unset, defaults to using anonymous access.
+# VAR_FTP_PASS [Optional]
+# If unset, defaults to a sensible value.
+#
+# In addition, the following (managed either manually or by f_media_set_ftp_*):
+#
+# VAR_FTP_STATE
+# Sets FTPMODE for ftp(1) and can be one of:
+# active active mode FTP only
+# auto automatic determination of passive or active
+# (this is the default)
+# gate gate-ftp mode
+# passive passive mode FTP only
+# See ftp(1) for additional information.
+#
+# And last, but not least (managed automatically or manually):
+#
+# VAR_RELNAME
+# Defaults to being set to $(uname -r) but can be overridden.
+# This sets the name of a release to look for as part of a well
+# known set of paths to search for release data once connected
+# via FTP. If set to "__RELEASE" or "any" then the VAR_FTP_DIR is
+# taken as the absolute path to the release and no further
+# searching is done (see FTP_DIRS above in the GLOBALS section
+# for a list of well known paths that are used when searching for
+# a VAR_RELNAME sub-directory).
+#
+f_media_init_ftp()
+{
+ local dev="$1"
+
+ local url
+ device_$dev get name url
+ f_dprintf "Init routine called for FTP device. url=[%s]" "$url"
+
+ if [ "$FTP_INITIALIZED" ]; then
+ f_dprintf "FTP device already initialized."
+ return $SUCCESS
+ fi
+
+ # If we can't initialize the network, bag it!
+ f_device_network_up $dev || return $FAILURE
+
+ local cp
+ while :; do
+ f_getvar $VAR_FTP_PATH cp
+ if [ ! "$cp" ]; then
+ if ! f_media_set_ftp ||
+ ! f_getvar $VAR_FTP_PATH cp ||
+ [ ! "$cp" ]
+ then
+ f_dialog_msgbox \
+ "$msg_unable_to_get_proper_ftp_path"
+ f_device_network_down $dev
+ return $FAILURE
+ fi
+ fi
+
+ local ftp_host ftp_dir
+ if ! {
+ f_getvar $VAR_FTP_HOST ftp_host &&
+ f_getvar $VAR_FTP_DIR ftp_dir
+ }; then
+ f_dialog_msgbox "$msg_missing_ftp_host_or_directory"
+ f_device_network_down $dev
+ return $FAILURE
+ fi
+
+ local ftp_port
+ f_getvar $VAR_FTP_PORT ftp_port
+ local host="$ftp_host" port="${ftp_port:+:$ftp_port}"
+ case "$host" in *:*) host="[$host]"; esac
+
+ local user pass use_anon=""
+ f_getvar $VAR_FTP_USER user
+ if [ ! "$user" ]; then
+ user="anonymous"
+ use_anon=1
+ fi
+ if ! f_getvar $VAR_FTP_PASS pass; then
+ f_getvar $VAR_HOSTNAME cp
+ if f_running_as_init; then
+ pass="installer@$cp"
+ else
+ local name="$( id -un 2> /dev/null )"
+ pass="${name:-ftp}@$cp"
+ fi
+ fi
+
+ f_show_info "$msg_logging_in_to_user_at_host" \
+ "$user" "$ftp_host"
+
+ local userpass=""
+ if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then
+ userpass="$user${pass:+:$( f_uriencode "$pass" )}"
+ userpass="$userpass${userpass:+@}"
+ fi
+
+ local mode rx
+ f_getvar $VAR_FTP_STATE mode
+
+ if [ "$ftp_dir" ]; then
+ if ! rx=$(
+ printf 'cd "%s"\npwd\n' "$ftp_dir" | eval \
+ FTPMODE=\"\$mode\" \
+ ${use_anon:+FTPANONPASS=\"\$pass\"} \
+ ftp -V ${use_anon:+-a} \
+ \"ftp://\$userpass\$host\$port\" \
+ 2>&1
+ ); then
+ f_show_msg "$msg_couldnt_open_ftp_connection" \
+ "$ftp_host" "$rx"
+ break # to failure
+ fi
+ if echo "$rx" | awk -v dir="/${ftp_dir#/}" '
+ BEGIN { found = 0 }
+ /^Remote directory: / {
+ sub(/^[^:]*:[[:space:]]*/, "")
+ if ($0 != dir) next
+ found = 1; exit
+ }
+ END { exit ! found }
+ '; then
+ setvar $VAR_FTP_DIR "$ftp_dir"
+ setvar $VAR_FTP_PATH \
+ "ftp://$ftp_host/${ftp_dir#/}"
+ else
+ f_show_msg \
+ "$msg_please_check_the_url_and_try_again" \
+ "ftp://$ftp_host/${ftp_dir#/}"
+ break # to failure
+ fi
+ fi
+
+ #
+ # Now that we've verified that the path we're given is ok,
+ # let's try to be a bit intelligent in locating the release we
+ # are looking for. First off, if the release is specified as
+ # "__RELEASE" or "any", then just assume that the current
+ # directory is the one we want and give up.
+ #
+ local rel
+ f_getvar $VAR_RELNAME rel
+ f_dprintf "f_media_init_ftp: rel=[%s]" "$rel"
+
+ case "$rel" in
+ __RELEASE|any)
+ FTP_INITIALIZED=YES
+ return $SUCCESS
+ ;;
+ *)
+ #
+ # Ok, since we have a release variable, let's walk
+ # through the list of directories looking for a release
+ # directory. First successful CWD wins.
+ #
+ if ! rx=$(
+ for dir in $FTP_DIRS; do
+ # Avoid confusing some servers
+ [ "$dir" = "." ] && continue
+ printf 'cd "/%s/%s"\npwd\n' \
+ "$dir" "$rel"
+ done | eval \
+ FTPMODE=\"\$mode\" \
+ ${use_anon:+FTPANONPASS=\"\$pass\"} \
+ ftp -V ${use_anon:+-a} \
+ \"ftp://\$userpass\$host\$port\" \
+ 2>&1
+ ); then
+ f_show_msg "$msg_couldnt_open_ftp_connection" \
+ "$ftp_host" "$rx"
+ break # to failure
+ fi
+
+ local fdir
+ if fdir=$( echo "$rx" | awk '
+ BEGIN { found = 0 }
+ /^Remote directory: / {
+ sub(/^[^:]*:[[:space:]]*/, "")
+ if ($0 == "/") next
+ # Exit after the first dir
+ found++; print; exit
+ }
+ END { exit ! found }
+ ' ); then
+ setvar $VAR_FTP_DIR "$fdir"
+ setvar $VAR_FTP_PATH "ftp://$ftp_host$fdir"
+ FTP_INITIALIZED=YES
+ return $SUCCESS
+ else
+ f_yesno "$msg_cant_find_distribution" \
+ "$rel" "$ftp_host"
+ if [ $? -eq $SUCCESS ]; then
+ unset $VAR_FTP_PATH
+ f_media_set_ftp && continue
+ fi
+ fi
+ esac
+ break # to failure
+ done
+
+ unset FTP_INITIALIZED $VAR_FTP_PATH
+ f_device_network_down $dev
+ return $FAILURE
+}
+
+# f_media_get_ftp $device $file [$probe_only]
+#
+# Returns data from $file on an FTP server using ftp(1). Please note that
+# $device is unused but must be present (even if null). Information is instead
+# gathered from the environment. $probe_only is currently unused by this media
+# type.
+#
+# Variables from variable.subr used to configure the connection are as follows
+# (all of which are configured by f_media_set_ftp above):
+#
+# VAR_FTP_HOST
+# FTP host to connect to. Can be an IPv4 address, IPv6 address,
+# or DNS hostname of your choice.
+# VAR_FTP_PORT
+# TCP port to connect on; see f_media_set_ftp() above.
+# VAR_FTP_USER [Optional]
+# If unset, defaults to using anonymous access.
+# VAR_FTP_PASS [Optional]
+# If unset, defaults to a sensible value.
+#
+# In addition, the following (managed either manually or by f_media_set_ftp_*):
+#
+# VAR_FTP_STATE
+# Sets FTPMODE for ftp(1) and can be one of:
+# active active mode FTP only
+# auto automatic determination of passive or active
+# (this is the default)
+# gate gate-ftp mode
+# passive passive mode FTP only
+# See ftp(1) for additional information.
+#
+# See variable.subr for additional information.
+#
+# Example usage:
+# f_media_set_ftp
+# f_media_get_ftp media $file
+#
+f_media_get_ftp()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_ftp: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ local ftp_host ftp_port
+ f_getvar $VAR_FTP_HOST ftp_host
+ f_getvar $VAR_FTP_PORT ftp_port
+
+ if [ ! "$FTP_INITIALIZED" ]; then
+ f_dprintf "No FTP connection open, can't get file %s" "$file"
+ return $FAILURE
+ fi
+
+ if ! {
+ f_validate_ipaddr "$ftp_host" ||
+ f_validate_ipaddr6 "$ftp_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_get_ftp" "$ftp_host"
+ f_host_lookup "$ftp_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$ftp_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$ftp_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_ftp_server %s:%s" \
+ "$ftp_host" "$ftp_port"
+ return $FAILURE
+ fi
+
+ local user pass use_anon=""
+ f_getvar $VAR_FTP_USER user
+ if [ ! "$user" ]; then
+ user="anonymous"
+ use_anon=1
+ fi
+ if ! f_getvar $VAR_FTP_PASS pass; then
+ f_getvar $VAR_HOSTNAME cp
+ if f_running_as_init; then
+ pass="installer@$cp"
+ else
+ local name="$( id -un 2> /dev/null )"
+ pass="${name:-ftp}@$cp"
+ fi
+ fi
+
+ local userpass=""
+ if [ ! "$use_anon" ] && [ "$user" -o "$pass" ]; then
+ userpass="$user${pass:+:$( f_uriencode "$pass" )}"
+ userpass="$userpass${userpass:+@}"
+ fi
+
+ local ftp_dir mode rx
+ f_getvar $VAR_FTP_DIR ftp_dir
+ f_getvar $VAR_FTP_STATE mode
+
+ local dir="${ftp_dir#/}"
+ local port="${ftp_port:+:$ftp_port}"
+ case "$host" in *:*) host="[$host]"; esac
+
+ f_dprintf "sending ftp request for: %s" "ftp://$host$port/$dir/$file"
+
+ eval FTPMODE=\"\$mode\" ${use_anon:+FTPANONPASS=\"\$pass\"} \
+ ftp -V ${use_anon:+-a} -o - \
+ \"ftp://\$userpass\$host\$port/\$dir/\$file\" 2> /dev/null
+ local retval=$?
+
+ [ $retval -eq $SUCCESS ] || f_dprintf "request failed!"
+ return $retval
+}
+
+# f_media_shutdown_ftp $device
+#
+# Shuts down the FTP device. Return status should be ignored. Note that since
+# we don't maintain an open connection to the FTP server there's nothing to do.
+#
+f_media_shutdown_ftp()
+{
+ [ "$FTP_INITIALIZED" ] || return $SUCCESS
+
+ unset FTP_INITIALIZED
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/ftp.subr
+
+fi # ! $_MEDIA_FTP_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/httpproxy.subr b/usr.sbin/bsdconfig/share/media/httpproxy.subr
new file mode 100644
index 0000000..fad1007
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/httpproxy.subr
@@ -0,0 +1,433 @@
+if [ ! "$_MEDIA_HTTPPROXY_SUBR" ]; then _MEDIA_HTTPPROXY_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/httpproxy.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/ftp.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ FUNCTIONS
+
+# f_media_set_http_proxy
+#
+# Return success if we both found and set the media type to be an ftp server,
+# accessed via http proxy.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_PROXY
+# HTTP Proxy server to use. Valid examples include:
+# myhost
+# somename:3128
+# 192.168.2.3
+# [::1]:8080
+# The default port if not specified is 3128.
+#
+# Variables from variable.subr that are set after successful execution include
+# the following:
+#
+# VAR_HTTP_PROXY_HOST The host portion of VAR_HTTP_PROXY.
+# VAR_HTTP_PROXY_PORT The TCP port parsed from VAR_HTTP_PROXY.
+#
+# See also f_media_set_ftp() for additional variables.
+#
+f_media_set_http_proxy()
+{
+ FTP_SKIP_RESOLV=1 f_media_set_ftp || return $FAILURE
+
+ f_variable_get_value $VAR_HTTP_PROXY \
+ "$msg_please_enter_the_address_of_the_http_proxy"
+
+ local proxy
+ f_getvar $VAR_HTTP_PROXY proxy
+ [ "$proxy" ] || return $FAILURE
+
+ local hostname="$proxy" port=3128
+ case "$hostname" in
+ "["*"]")
+ hostname="${hostname#\[}"
+ hostname="${hostname%\]}"
+ ;;
+ "["*"]:")
+ hostname="${hostname#\[}"
+ port="${hostname#*\]:}"
+ port="${port%%[!0-9]*}"
+ hostname="${hostname%%\]:*}"
+ ;;
+ *":"*)
+ port="${hostname#*:}"
+ hostname="${hostname%%:*}"
+ esac
+
+ setvar $VAR_HTTP_PROXY_HOST "$hostname"
+ setvar $VAR_HTTP_PROXY_PORT "$port"
+
+ if f_debugging; then
+ f_dprintf "VAR_FTP_PATH : %s" "$( f_getvar $VAR_FTP_PATH )"
+ f_dprintf "VAR_HTTP_PROXY_HOST, _PORT: %s:%s" \
+ "$( f_getvar $VAR_HTTP_PROXY_HOST )" \
+ "$( f_getvar $VAR_HTTP_PROXY_PORT )"
+ fi
+
+ # media device has been set by f_media_set_ftp(), overwrite partly:
+ device_media set type $DEVICE_TYPE_HTTP_PROXY
+ device_media set init f_media_init_http_proxy
+ device_media set get f_media_get_http_proxy
+ device_media unset shutdown
+
+ return $SUCCESS
+}
+
+# f_http_proxy_check_access [$connect_only]
+#
+# Return success if able list a remote FTP directory via HTTP proxy. If
+# $connect_only is present and non-null, then returns success if a connection
+# can be made. Variables from variable.subr that can be used to script user
+# input:
+#
+# VAR_HTTP_PROXY_HOST
+# The HTTP proxy server host name, IPv4 address or IPv6 address.
+# Valid examples include:
+# myhost
+# 192.168.2.3
+# ::1
+# VAR_HTTP_PROXY_PORT
+# The TCP port to connect to when communicating with the HTTP
+# proxy server.
+# VAR_HTTP_PROXY_PATH
+# The FTP URL sent to the HTTP proxy server. Unused if
+# $connect_only is present and non-NULL.
+#
+f_http_proxy_check_access()
+{
+ local connect_only="$1" hosts=""
+
+ local proxy_host proxy_port
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ f_getvar $VAR_HTTP_PROXY_PORT proxy_port
+
+ if ! {
+ f_validate_ipaddr "$proxy_host" ||
+ f_validate_ipaddr6 "$proxy_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_http_proxy_check_access" "$proxy_host"
+ f_host_lookup "$proxy_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ unset $VAR_HTTP_PROXY_HOST
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$proxy_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$proxy_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \
+ "$proxy_host" "$proxy_port"
+ unset $VAR_HTTP_PROXY_HOST
+ return $FAILURE
+ fi
+ [ "$connect_only" ] && return $SUCCESS
+
+ #
+ # Some proxies fetch files with certain extensions in "ascii mode"
+ # instead of "binary mode" for FTP. The FTP server then translates all
+ # LF to CRLF.
+ #
+ # You can force Squid to use binary mode by appending ";type=i" to the
+ # URL, which is what sysinstall(8) has traditionally done.
+ #
+
+ local proxy_path
+ f_getvar $VAR_HTTP_PROXY_PATH proxy_path
+ f_show_info "$msg_checking_access_to" "$proxy_path"
+
+ local rx
+ if ! rx=$(
+ printf "GET %s/ HTTP/1.0\r\n\r\n" "${proxy_path%/}" |
+ nc -n "$host" "$proxy_port"
+ ); then
+ f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \
+ "$proxy_host" "$proxy_port"
+ unset $VAR_HTTP_PROXY_HOST
+ return $FAILURE
+ fi
+
+ local hdr
+ hdr=$( echo "$rx" | awk '/^\r$/{exit}{print}' )
+
+ local http_found=$FAILURE
+ if echo "$hdr" | awk '
+ BEGIN { found = 0 }
+ /^HTTP.... 200 / {
+ found = 1
+ exit
+ }
+ END { exit ! found }
+ '; then
+ http_found=$SUCCESS
+ fi
+
+ #
+ # Scan the headers of the response
+ # this is extremely quick'n dity
+ #
+
+ unset $VAR_HTTP_FTP_MODE
+ if echo "$hdr" | awk '
+ BEGIN { found = 0 }
+ {
+ if (!match($0, /^Server: /)) next
+ found = ( substr($0, 9, 5) ~ /[Ss]quid/ )
+ }
+ END { exit ! found }
+ '; then
+ setvar $VAR_HTTP_FTP_MODE ";type=i"
+ else
+ setvar $VAR_HTTP_FTP_MODE ""
+ fi
+
+ return $http_found
+}
+
+# f_media_init_http_proxy $device
+#
+# Initializes the HTTP Proxy media device. Returns success if able to confirm
+# the existence of at least one known FTP server release path via HTTP proxy
+# using f_http_proxy_check_access(), above.
+#
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_HTTP_PROXY_HOST
+# The HTTP proxy server to connect to. Usually set by having
+# f_media_set_http_proxy() parse VAR_HTTP_PROXY. Must be set.
+# Also see f_http_proxy_check_access() for additional variables.
+# VAR_RELNAME
+# Usually set to `uname -r' but can be overridden.
+# VAR_FTP_PATH
+# The FTP URL to send to the HTTP proxy server. Usually set by
+# calling f_media_set_ftp().
+#
+# Meanwhile, after successful execution, the following variables (also from
+# variable.subr) are set:
+#
+# VAR_HTTP_PROXY_PATH
+# The [possibly] adjusted VAR_FTP_PATH that was found to contain
+# a valid FreeBSD repository.
+#
+f_media_init_http_proxy()
+{
+ local dev="$1"
+ f_dprintf "Init routine called for HTTP Proxy device. dev=[%s]" "$dev"
+
+ #
+ # First verify access
+ #
+ local connect_only=1
+ f_http_proxy_check_access $connect_only
+
+ local proxy_host
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ while [ ! "$proxy_host" ]; do
+ f_media_set_http_proxy || return $FAILURE
+ f_http_proxy_check_access $connect_only
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ done
+
+ local rel proxy_path http_found=$FAILURE
+ while :; do
+ #
+ # If the release is specified as "__RELEASE" or "any", then
+ # just assume that the path the user gave is ok.
+ #
+ f_getvar $VAR_RELNAME rel
+ f_dprintf "f_media_init_http_proxy: rel=[%s]" "$rel"
+
+ case "$rel" in
+ __RELEASE|any)
+ f_getvar $VAR_FTP_PATH $VAR_HTTP_PROXY_PATH
+ f_http_proxy_check_access
+ http_found=$?
+ ;;
+ *)
+ local fdir fp
+ f_getvar $VAR_FTP_PATH fp
+ for fdir in $FTP_DIRS; do
+ setvar $VAR_HTTP_PROXY_PATH "$fp/$fdir/$rel"
+ if f_http_proxy_check_access; then
+ http_found=$SUCCESS
+ break
+ fi
+ done
+ esac
+
+ [ $http_found -eq $SUCCESS ] && break
+
+ f_getvar $VAR_HTTP_PROXY_PATH proxy_path
+ f_show_msg "$msg_please_check_the_url_and_try_again" \
+ "$proxy_path"
+
+ unset $VAR_HTTP_PROXY_PATH
+ f_media_set_http_proxy || break
+ done
+
+ return $http_found
+}
+
+# f_media_get_http_proxy $device $file [$probe_only]
+#
+# Returns data from $file on an FTP server via HTTP proxy using nc(1). Please
+# note that $device is unused but must be present (even if null). Information
+# is instead gathered from the environment. $probe_only is currently unused by
+# this media type.
+#
+# The variables used to configure the connection are as follows (all of which
+# are configured by f_media_set_http_proxy above):
+#
+# VAR_HTTP_PROXY_HOST
+# HTTP proxy host to connect. Can be an IPv4 address, IPv6
+# address, or DNS hostname of your choice.
+# VAR_HTTP_PROXY_PORT
+# TCP port to connect on; see f_media_set_http_proxy above.
+# VAR_HTTP_PROXY_PATH
+# URL (including "ftp://" protocol-prefix) of FTP directory to
+# use as a prefix when requesting $file via HTTP proxy.
+#
+# See variable.subr for additional information.
+#
+# Example usage:
+# f_media_set_http_proxy
+# f_media_get_http_proxy media $file
+#
+f_media_get_http_proxy()
+{
+ local dev="$1" file="$2" probe_only="$3" hosts=
+
+ f_dprintf "f_media_get_http_proxy: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ local proxy_host proxy_port
+ f_getvar $VAR_HTTP_PROXY_HOST proxy_host
+ f_getvar $VAR_HTTP_PROXY_PORT proxy_port
+
+ if ! {
+ f_validate_ipaddr "$proxy_host" ||
+ f_validate_ipaddr6 "$proxy_host" ||
+ {
+ f_dprintf "%s: Looking up hostname, %s, using host(1)" \
+ "f_media_get_http_proxy" "$proxy_host"
+ f_host_lookup "$proxy_host" hosts
+ }
+ }; then
+ # All the above validations failed
+ [ "$hosts" ] && f_dialog_msgbox "$hosts"
+ return $FAILURE
+ elif [ ! "$hosts" ]; then
+ # One of the first two validations passed
+ hosts="$proxy_host"
+ fi
+
+ local host connected=
+ for host in $hosts; do
+ f_quietly nc -nz "$host" "$proxy_port" || continue
+ connected=1; break
+ done
+ if [ ! "$connected" ]; then
+ f_show_msg "$msg_couldnt_connect_to_proxy %s:%s" \
+ "$proxy_host" "$proxy_port"
+ return $FAILURE
+ fi
+
+ local proxy_path mode
+ f_getvar $VAR_HTTP_PROXY_PATH proxy_path
+ f_getvar $VAR_HTTP_FTP_MODE mode
+ local url="${proxy_path%/}/$file$mode" rx
+
+ f_dprintf "sending http request for: %s" "$url"
+ printf "GET %s HTTP/1.0\r\n\r\n" "$url" | nc -n "$host" "$proxy_port" |
+ (
+ #
+ # scan the headers of the response
+ # this is extremely quick'n dirty
+ #
+
+ rv=0
+ while read LINE; do
+ case "$LINE" in
+ HTTP*)
+ f_dprintf "received response: %s" "$LINE"
+ set -- $LINE; rv=$2
+ f_isinteger "$rv" || rv=0
+ ;;
+ *)
+ [ "${LINE% }" ] || break # End of headers
+ esac
+ done
+
+ [ $rv -ge 500 ] && exit 5
+ [ $rv -eq 404 ] && exit 44
+ [ $rv -ge 400 ] && exit 4
+ [ $rv -ge 300 ] && exit 3
+ [ $rv -eq 200 ] || exit $FAILURE
+
+ cat # output the rest ``as-is''
+ exit 200
+ )
+ local retval=$?
+ [ $retval -eq 200 ] && return $SUCCESS
+
+ case "$retval" in
+ 5) f_show_msg "$msg_server_error_when_requesting_url" "$url" ;;
+ 44) f_show_msg "$msg_url_was_not_found" "$url" ;;
+ 4) f_show_msg "$msg_client_error" ;;
+ *) f_show_msg "$msg_error_when_requesting_url" "$url" ;;
+ esac
+ return $FAILURE
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/httpproxy.subr
+
+fi # ! $_MEDIA_HTTPPROXY_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/network.subr b/usr.sbin/bsdconfig/share/media/network.subr
new file mode 100644
index 0000000..d9fe8e6
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/network.subr
@@ -0,0 +1,182 @@
+if [ ! "$_MEDIA_NETWORK_SUBR" ]; then _MEDIA_NETWORK_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/network.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+NETWORK_INITIALIZED=
+
+############################################################ FUNCTIONS
+
+# f_media_init_network $device
+#
+# Initialize a network device (such as `fxp0', `em0', etc.). Returns success if
+# able to successfully initialize the device. If not running as init (basically
+# from the FreeBSD install media) then assume that the network has already been
+# initialized and returns success.
+#
+# The variables (from variable.subr) used to initialize the network are as
+# follows (all of which are configured either automatically or manaully):
+#
+# VAR_IFCONFIG + device_name (e.g., `ifconfig_em0')
+# Automatically populated but can be overridden in a script. This
+# defines the ifconfig(8) properties specific to a chosen network
+# interface device. Optional if VAR_IPV6ADDR is set.
+# VAR_IPV6ADDR [Optional]
+# If not running as init (and setting up RTSOL connections for
+# the interface), then must be set manually. If set, used as the
+# IPv6 configuration for the given network interface device.
+# VAR_GATEWAY [Optional]
+# If not running as init (and setting up a static connection for
+# the interface) then must be set (usually via rc.conf(5), but
+# can be set manually to override). If unset, the user is warned
+# but not prevented from proceeding (as most connections need a
+# default route but not everyone).
+#
+f_media_init_network()
+{
+ local dev="$1"
+
+ f_dprintf "Init routine called for network device \`%s'." "$dev"
+ if [ "$NETWORK_INITIALIZED" ]; then
+ f_dprintf "Network already initialized."
+ return $SUCCESS
+ elif ! f_running_as_init; then
+ f_dprintf "Not running as init -- calling the deed done."
+ NETWORK_INITIALIZED=1
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$RESOLV_CONF" ]; then
+ if ! f_config_resolv; then
+ f_show_msg "$msg_cant_seem_to_write_out_resolv_conf" \
+ "$RESOLV_CONF"
+ return $FAILURE
+ fi
+ fi
+
+ local cp
+ if f_getvar $VAR_IFCONFIG$dev cp; then
+ #
+ # If this interface isn't a DHCP one, bring it up.
+ # If it is, then it's already up.
+ #
+ case "$cp" in
+ *DHCP*)
+ f_dprintf "A DHCP interface. Should already be up."
+ ;;
+ *)
+ f_dprintf "Not a DHCP interface."
+ if ! f_quietly ifconfig "$dev" $cp; then
+ f_show_msg "$msg_unable_to_configure_device" \
+ "$dev"
+ return $FAILURE
+ fi
+ local rp
+ f_getvar $VAR_GATEWAY rp
+ if [ ! "$rp" ]; then
+ f_dialog_msgbox "$msg_no_gateway_has_been_set"
+ else
+ #
+ # Explicitly flush all routes to get back to a
+ # known sane state. We don't need to check this
+ # exit code because if anything fails it will
+ # show up in the route add below.
+ #
+ f_quietly route -n flush
+ f_dprintf "Adding default route to %s." "$rp"
+ if ! f_quietly route -n add default "$rp"; then
+ f_dialog_msgbox \
+ "$msg_failed_to_add_default_route"
+ return $FAILURE
+ fi
+ fi
+ esac
+ elif ! { f_getvar $VAR_IPV6ADDR cp && [ "$cp" ]; }; then
+ f_show_msg "$msg_device_is_not_configured" "$dev"
+ return $FAILURE
+ fi
+
+ f_dprintf "Network initialized successfully."
+ NETWORK_INITIALIZED=1
+ return $SUCCESS
+}
+
+# f_media_shutdown_network $device
+#
+# Shuts down the configured network device (e.g., `fxp0', `em0', etc.) and
+# deletes the default route (if configured). Returns failure if the device
+# passed has not been configured. If not running as init (basically from the
+# FreeBSD install media) then does nothing and returns success.
+#
+f_media_shutdown_network()
+{
+ local dev="$1" cp
+
+ f_dprintf "Shutdown called for network device %s" "$dev"
+ if [ ! "$NETWORK_INITIALIZED" ]; then
+ f_dprintf "Network not initialized -- nothing to do."
+ return $SUCCESS
+ fi
+
+ unset NETWORK_INITIALIZED
+ unset $VAR_NETWORK_DEVICE
+
+ if ! f_running_as_init; then
+ f_dprintf "Not running as init -- calling the deed done."
+ return $SUCCESS
+ fi
+
+ f_getvar $VAR_IFCONFIG$dev cp || return $FAILURE
+ f_dprintf "ifconfig %s down" "$dev"
+ f_quietly ifconfig $dev down ||
+ f_show_msg "$msg_unable_to_down_the_interface_properly" "$dev"
+
+ if f_getvar $VAR_GATEWAY cp; then
+ f_dprintf "Deleting default route."
+ f_quietly route -n delete default
+ fi
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/network.subr
+
+fi # ! $_MEDIA_NETWORK_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/nfs.subr b/usr.sbin/bsdconfig/share/media/nfs.subr
new file mode 100644
index 0000000..461db1c
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/nfs.subr
@@ -0,0 +1,251 @@
+if [ ! "$_MEDIA_NFS_SUBR" ]; then _MEDIA_NFS_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/nfs.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
+f_include $BSDCFG_SHARE/media/network.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+NFS_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_nfs
+#
+# Return success if we both found and set the media type to be an NFS server.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_NFS_PATH
+# The NFS path specification (host:path) to use when mounting the
+# remote repository.
+# VAR_NAMESERVER [Optional]
+# Automatically populated from resolv.conf(5) but can be
+# overridden. If set, the host portion of VAR_NFS_PATH is
+# looked up using f_host_lookup() from `tcpip.subr'.
+#
+# Meanwhile, the following variables from variable.subr are set after
+# successful execution:
+#
+# VAR_NFS_HOST
+# The host portion of the NFS path specification, parsed from
+# VAR_NFS_PATH.
+#
+f_media_set_nfs()
+{
+ local nfs
+
+ f_media_close
+
+ f_variable_get_value $VAR_NFS_PATH \
+ "$msg_please_enter_the_full_nfs_file_specification"
+ f_getvar $VAR_NFS_PATH nfs
+ [ "$nfs" ] || return $FAILURE
+
+ case "$nfs" in
+ *:*) : valid NFS path ;;
+ *)
+ f_dialog_msgbox "$msg_invalid_nfs_path_specification"
+ return $FAILURE
+ esac
+
+ f_struct_new DEVICE device_nfs
+ device_nfs set name "$nfs"
+
+ if ! f_struct device_network ||
+ ! f_dialog_yesno "$msg_youve_already_done_the_network_configuration"
+ then
+ f_struct device_network &&
+ f_device_shutdown network
+ f_device_select_tcp || return $FAILURE
+ local dev
+ f_getvar $VAR_NETWORK_DEVICE dev
+ f_struct_copy "device_$dev" device_network
+ fi
+ f_device_init network ||
+ f_dprintf "%s: $msg_net_device_init_failed\n" f_media_set_nfs
+
+ local hostname="${nfs%%:*}"
+ if f_quietly f_getvar $VAR_NAMESERVER && ! {
+ f_validate_ipaddr "$hostname" ||
+ f_validate_ipaddr6 "$hostname"
+ }; then
+ f_show_info "$msg_looking_up_host" "$hostname"
+ f_dprintf "%s Looking up hostname, %s, using host(1)" \
+ "f_media_set_nfs" "$hostname"
+ if ! f_quietly f_host_lookup "$hostname"; then
+ f_show_msg "$msg_cannot_resolve_hostname" "$hostname"
+ f_struct device_network &&
+ f_device_shutdown network
+ f_struct_free device_network
+ unset $VAR_NFS_PATH
+ return $FAILURE
+ fi
+ f_dprintf "Found DNS entry for %s successfully." "$hostname"
+ fi
+
+ setvar $VAR_NFS_HOST "$hostname"
+
+ device_nfs set type $DEVICE_TYPE_NFS
+ device_nfs set init f_media_init_nfs
+ device_nfs set get f_media_get_nfs
+ device_nfs set shutdown f_media_shutdown_nfs
+ device_nfs set private device_network # in name only (deref'd later)
+
+ f_struct_copy device_nfs device_media
+ f_struct_free device_nfs
+
+ return $SUCCESS
+}
+
+# f_media_init_nfs $device
+#
+# Initializes the NFS media device. Returns success if able to mount the NFS
+# device using mount_nfs(1).
+#
+# The variables (from variable.subr) used to initialize the NFS mount are as
+# follows (all of which are configured manually/optionally from the options
+# menu):
+#
+# VAR_NFS_TCP [Optional]
+# If non-NULL, adds the "tcp" option via `-o' to mount_nfs(8).
+# VAR_NFS_V3 [Optional]
+# If non-NULL, adds the "nfsv3" option via `-o' to mount_nfs(8).
+# VAR_NFS_SECURE [Optional]
+# If non-NULL, adds the "-P" flag to mount_nfs(8).
+# VAR_SLOW_ETHER [Optional]
+# If non-NULL, adjusts the read/write size to avoid timeouts.
+#
+f_media_init_nfs()
+{
+ local dev="$1" name err
+
+ device_$dev get name name || return $FAILURE
+ f_dprintf "Init routine called for NFS device. name=[%s]" \
+ "$name"
+
+ if [ "$NFS_MOUNTED" ]; then
+ f_dprintf "NFS device already mounted."
+ return $SUCCESS
+ fi
+
+ if ! f_device_init network; then
+ f_dprintf "f_media_init_nfs: %s" "$msg_net_device_init_failed"
+ return $FAILURE
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ] &&
+ ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
+ then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+
+ local cp tcp="" use3="" secure="" readsize=4096 writesize=4096
+ f_getvar $VAR_NFS_TCP cp
+ [ "$cp" = "YES" ] && tcp=1
+ f_getvar $VAR_NFS_V3 cp
+ [ "$cp" = "YES" ] && use3=1
+ f_getvar $VAR_NFS_SECURE cp
+ [ "$cp" = "YES" ] && secure=1
+ f_getvar $VAR_SLOW_ETHER cp
+ [ "$cp" = "YES" ] && readsize=1024 writesize=1024
+
+ local options="rsize=$readsize,wsize=$writesize"
+ [ "$use3" ] && options="$options,nfsv3"
+ [ "$tcp" ] && options="$options,tcp"
+
+ if ! err=$( mount_nfs \
+ ${secure:+-P} -o "$options" "$name" "$MOUNTPOINT" 2>&1 )
+ then
+ err="${err#mount_nfs: }"
+ f_show_msg "$msg_error_mounting_device" \
+ "$name" "$MOUNTPOINT" "$err"
+ f_struct device_network &&
+ f_device_shutdown network
+ return $FAILURE
+ fi
+ NFS_MOUNTED=1
+
+ f_dprintf "Mounted NFS device %s onto %s" "$name" "$MOUNTPOINT"
+
+ return $SUCCESS
+}
+
+# f_media_get_nfs $device $file [$probe_only]
+#
+# Returns data from $file on a mounted NFS device. Similar to cat(1).
+# $probe_only is currently unused by this media type.
+#
+f_media_get_nfs()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_nfs: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ f_media_generic_get "$MOUNTPOINT" "$file"
+}
+
+# f_media_shutdown_nfs $device
+#
+# Shuts down the NFS device using umount(8). Return status should be ignored.
+#
+f_media_shutdown_nfs()
+{
+ local dev="$1" err
+
+ [ "$NFS_MOUNTED" ] || return
+
+ f_dprintf "Unmounting NFS partition on %s" "$MOUNTPOINT"
+ if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_nfs_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ NFS_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/nfs.subr
+
+fi # ! $_MEDIA_NFS_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/options.subr b/usr.sbin/bsdconfig/share/media/options.subr
new file mode 100644
index 0000000..c32bec5
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/options.subr
@@ -0,0 +1,308 @@
+if [ ! "$_MEDIA_OPTIONS_SUBR" ]; then _MEDIA_OPTIONS_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/options.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/any.subr
+f_include $BSDCFG_SHARE/media/ftp.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+OPTIONS_HELPFILE=$BSDCFG_LIBE/include/options.hlp
+
+############################################################ FUNCTIONS
+
+# f_media_options_menu
+#
+# Prompt the user to confirm/edit various media settings. Returns success.
+#
+f_media_options_menu()
+{
+ f_dialog_title "$msg_options_editor"
+ local title="$DIALOG_TITLE" btitle="$DIALOG_BACKTITLE"
+ f_dialog_title_restore
+ local prompt=""
+ local hline="$hline_arrows_tab_enter"
+ local menu_list size cp
+
+ #
+ # A hack so that the dialogs below are always interactive in a script
+ #
+ local old_interactive=
+ if ! f_interactive; then
+ f_getvar $VAR_NONINTERACTIVE old_interactive
+ unset $VAR_NONINTERACTIVE
+ fi
+
+ while :; do
+ menu_list=""
+
+ f_getvar $VAR_NFS_SECURE cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_secure' 'YES'
+ '$msg_nfs_server_talks_only_on_a_secure_port'"
+ else menu_list="$menu_list
+ ' $msg_nfs_secure' 'NO'
+ '$msg_nfs_server_talks_only_on_a_secure_port'"
+ fi
+
+ f_getvar $VAR_SLOW_ETHER cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_slow' 'YES'
+ '$msg_user_is_using_a_slow_pc_or_ethernet_card'"
+ else menu_list="$menu_list
+ ' $msg_nfs_slow' 'NO'
+ '$msg_user_is_using_a_slow_pc_or_ethernet_card'"
+ fi
+
+ f_getvar $VAR_NFS_TCP cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_tcp' 'YES' '$msg_use_tcp_protocol_for_nfs'"
+ else menu_list="$menu_list
+ ' $msg_nfs_tcp' 'NO' '$msg_use_tcp_protocol_for_nfs'"
+ fi
+
+ f_getvar $VAR_NFS_V3 cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_nfs_version_3' 'YES' '$msg_use_nfs_version_3'"
+ else menu_list="$menu_list
+ ' $msg_nfs_version_3' 'NO' '$msg_use_nfs_version_3'"
+ fi
+
+ f_getvar $VAR_DEBUG cp
+ if [ "$cp" ]; then menu_list="$menu_list
+ ' $msg_debugging' 'YES'
+ '$msg_emit_extra_debugging_output'"
+ else menu_list="$menu_list
+ ' $msg_debugging' 'NO'
+ '$msg_emit_extra_debugging_output'"
+ fi
+
+ f_getvar $VAR_TRY_DHCP cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_dhcp' 'YES'
+ '$msg_attempt_automatic_dhcp_configuration'"
+ else menu_list="$menu_list
+ ' $msg_dhcp' 'NO'
+ '$msg_attempt_automatic_dhcp_configuration'"
+ fi
+
+ f_getvar $VAR_TRY_RTSOL cp
+ if [ "$cp" = "YES" ]; then menu_list="$menu_list
+ ' $msg_ipv6' 'YES'
+ '$msg_attempt_ipv6_configuration_of_interfaces'"
+ else menu_list="$menu_list
+ ' $msg_ipv6' 'NO'
+ '$msg_attempt_ipv6_configuration_of_interfaces'"
+ fi
+
+ f_getvar $VAR_FTP_USER cp
+ menu_list="$menu_list
+ ' $msg_ftp_username' '$cp'
+ '$msg_username_and_password_to_use'"
+
+ f_getvar $VAR_EDITOR cp
+ menu_list="$menu_list
+ ' $msg_editor' '$cp' '$msg_which_text_editor_to_use'"
+
+ f_getvar $VAR_RELNAME cp
+ menu_list="$menu_list
+ ' $msg_release_name' '$cp'
+ '$msg_which_release_to_attempt_to_load'"
+
+ if f_struct device_media; then
+ device_media get type cp
+ case "$cp" in
+ $DEVICE_TYPE_UFS|$DEVICE_TYPE_DISK)
+ cp="$msg_file_system";;
+ $DEVICE_TYPE_DIRECTORY)
+ cp="$msg_directory";;
+ $DEVICE_TYPE_FLOPPY)
+ cp="$msg_floppy";;
+ $DEVICE_TYPE_FTP)
+ cp="$msg_ftp";;
+ $DEVICE_TYPE_HTTP_PROXY)
+ cp="$msg_http_proxy";;
+ $DEVICE_TYPE_CDROM)
+ cp="$msg_cdrom";;
+ $DEVICE_TYPE_USB)
+ cp="$msg_usb";;
+ $DEVICE_TYPE_DOS)
+ cp="$msg_dos";;
+ $DEVICE_TYPE_NFS)
+ cp="$msg_nfs";;
+ *)
+ cp="<$msg_unknown>"
+ esac
+ else
+ cp="<$msg_not_yet_set>"
+ fi
+ menu_list="$menu_list
+ ' $msg_media_type' '$cp'
+ '$msg_the_current_installation_media_type'"
+
+ f_getvar $VAR_MEDIA_TIMEOUT cp
+ menu_list="$menu_list
+ ' $msg_media_timeout' '$cp'
+ '$msg_timeout_value_in_seconds_for_slow_media'"
+
+ menu_list="$menu_list
+ ' $msg_rescan_devices' '<*>'
+ '$msg_rerun_bsdconfig_initial_device_probe'
+ ' $msg_use_defaults' '[${msg_reset}]'
+ '$msg_reset_all_values_to_startup_defaults'
+ " # END-QUOTE
+
+ size=$( eval f_dialog_menu_with_help_size \
+ \"\$title\" \
+ \"\$btitle\" \
+ \"\$prompt\" \
+ \"\$hline\" \
+ $menu_list )
+
+ local dialog_menu
+
+ dialog_menu=$( eval $DIALOG \
+ --title \"\$title\" \
+ --backtitle \"\$btitle\" \
+ --hline \"\$hline\" \
+ --item-help \
+ --ok-label \"\$msg_ok\" \
+ --cancel-label \"\$msg_done\" \
+ --help-button \
+ --help-label \"\$msg_help\" \
+ ${USE_XDIALOG:+--help \"\"} \
+ --menu \"\$prompt\" $size $menu_list \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ setvar DIALOG_MENU_$$ "$dialog_menu"
+
+ local mtag
+ mtag=$( f_dialog_menutag )
+ f_dprintf "retval=%s mtag=[%s]" $retval "$mtag"
+
+ if [ $retval -eq 2 ]; then
+ # The Help button was pressed
+ f_show_help "$OPTIONS_HELPFILE"
+ continue
+ elif [ $retval -ne 0 ]; then
+ break # to success
+ fi
+
+ case "$mtag" in
+ " $msg_nfs_secure")
+ f_getvar $VAR_NFS_SECURE cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_NFS_SECURE="NO"
+ else
+ export $VAR_NFS_SECURE="YES"
+ fi ;;
+ " $msg_nfs_slow")
+ f_getvar $VAR_SLOW_ETHER cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_SLOW_ETHER="NO"
+ else
+ export $VAR_SLOW_ETHER="YES"
+ fi ;;
+ " $msg_nfs_tcp")
+ f_getvar $VAR_NFS_TCP cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_NFS_TCP="NO"
+ else
+ export $VAR_NFS_TCP="YES"
+ fi ;;
+ " $msg_nfs_version_3")
+ f_getvar $VAR_NFS_V3 cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_NFS_V3="NO"
+ else
+ export $VAR_NFS_V3="YES"
+ fi ;;
+ " $msg_debugging")
+ if f_getvar $VAR_DEBUG cp && [ "$cp" ]; then
+ unset $VAR_DEBUG
+ else
+ export $VAR_DEBUG=1
+ fi ;;
+ " $msg_dhcp")
+ f_getvar $VAR_TRY_DHCP cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_TRY_DHCP="NO"
+ else
+ export $VAR_TRY_DHCP="YES"
+ fi ;;
+ " $msg_ipv6")
+ f_getvar $VAR_TRY_RTSOL cp
+ if [ "$cp" = "YES" ]; then
+ export $VAR_TRY_RTSOL="NO"
+ else
+ export $VAR_TRY_RTSOL="YES"
+ fi ;;
+ " $msg_ftp_username")
+ f_media_set_ftp_userpass ;;
+ " $msg_editor")
+ f_variable_get_value $VAR_EDITOR \
+ "$msg_please_specify_the_name_of_the_text_editor"
+ ;;
+ " $msg_release_name")
+ f_variable_get_value $VAR_RELNAME \
+ "$msg_please_specify_the_release_you_wish_to_load"
+ ;;
+ " $msg_media_type")
+ f_media_get_type ;;
+ " $msg_media_timeout")
+ f_variable_get_value $VAR_MEDIA_TIMEOUT \
+ "$msg_please_specify_the_number_of_seconds_to_wait"
+ ;;
+ " $msg_rescan_devices")
+ f_device_rescan ;;
+ " $msg_use_defaults")
+ f_variable_set_defaults ;;
+ esac
+ done
+
+ # Restore old VAR_NONINTERACTIVE if needed.
+ [ "$old_interactive" ] &&
+ setvar $VAR_NONINTERACTIVE "$old_interactive"
+
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/options.subr
+
+fi # ! $_MEDIA_OPTIONS_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/tcpip.subr b/usr.sbin/bsdconfig/share/media/tcpip.subr
new file mode 100644
index 0000000..0bf0487
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/tcpip.subr
@@ -0,0 +1,1688 @@
+if [ ! "$_MEDIA_TCPIP_SUBR" ]; then _MEDIA_TCPIP_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/tcpip.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+TCP_HELPFILE=$BSDCFG_LIBE/include/tcp.hlp
+NETWORK_DEVICE_HELPFILE=$BSDCFG_LIBE/include/network_device.hlp
+
+############################################################ GLOBALS
+
+#
+# Path to resolv.conf(5).
+#
+: ${RESOLV_CONF:="/etc/resolv.conf"}
+
+#
+# Path to nsswitch.conf(5).
+#
+: ${NSSWITCH_CONF:="/etc/nsswitch.conf"}
+
+#
+# Path to hosts(5)
+#
+: ${ETC_HOSTS:="/etc/hosts"}
+
+#
+# Structure of dhclient.leases(5) lease { ... } entry
+#
+f_struct_define DHCP_LEASE \
+ interface \
+ fixed_address \
+ filename \
+ server_name \
+ script \
+ medium \
+ host_name \
+ subnet_mask \
+ routers \
+ domain_name_servers \
+ domain_name \
+ broadcast_address \
+ dhcp_lease_time \
+ dhcp_message_type \
+ dhcp_server_identifier \
+ dhcp_renewal_time \
+ dhcp_rebinding_time \
+ renew \
+ rebind \
+ expire
+
+############################################################ FUNCTIONS
+
+# f_validate_hostname $hostname
+#
+# Returns zero if the given argument (a fully-qualified hostname) is compliant
+# with standards set-forth in RFC's 952 and 1123 of the Network Working Group:
+#
+# RFC 952 - DoD Internet host table specification
+# http://tools.ietf.org/html/rfc952
+#
+# RFC 1123 - Requirements for Internet Hosts - Application and Support
+# http://tools.ietf.org/html/rfc1123
+#
+# See http://en.wikipedia.org/wiki/Hostname for a brief overview.
+#
+# The return status for invalid hostnames is one of:
+# 255 Entire hostname exceeds the maximum length of 255 characters.
+# 63 One or more individual labels within the hostname (separated by
+# dots) exceeds the maximum of 63 characters.
+# 1 One or more individual labels within the hostname contains one
+# or more invalid characters.
+# 2 One or more individual labels within the hostname starts or
+# ends with a hyphen (hyphens are allowed, but a label cannot
+# begin or end with a hyphen).
+# 3 One or more individual labels within the hostname are null.
+#
+# f_dialog_validate_hostname $hostname
+#
+# If the hostname is determined to be invalid, the appropriate error will be
+# displayed using the f_show_msg function.
+#
+f_validate_hostname()
+{
+ local fqhn="$1"
+
+ # Return error if the hostname exceeds 255 characters
+ [ ${#fqhn} -gt 255 ] && return 255
+
+ local IFS="." # Split on `dot'
+ for label in $fqhn; do
+ # Return error if the label exceeds 63 characters
+ [ ${#label} -gt 63 ] && return 63
+
+ # Return error if the label is null
+ [ "$label" ] || return 3
+
+ # Return error if label begins/ends with dash
+ case "$label" in -*|*-) return 2; esac
+
+ # Return error if the label contains any invalid chars
+ case "$label" in *[!0-9a-zA-Z-]*) return 1; esac
+ done
+
+ return $SUCCESS
+}
+
+# f_inet_atoi $ipv4_address [$var_to_set]
+#
+# Convert an IPv4 address or mask from dotted-quad notation (e.g., `127.0.0.1'
+# or `255.255.255.0') to a 32-bit unsigned integer for the purpose of network
+# and broadcast calculations. For example, one can validate that two addresses
+# are on the same network:
+#
+# f_inet_atoi 1.2.3.4 ip1num
+# f_inet_atoi 1.2.4.5 ip2num
+# f_inet_atoi 255.255.0.0 masknum
+# if [ $(( $ip1num & $masknum )) -eq \
+# $(( $ip2num & $masknum )) ]
+# then
+# : IP addresses are on same network
+# fi
+#
+# See f_validate_ipaddr() below for an additional example usage, on calculating
+# network and broadcast addresses.
+#
+# If $var_to_set is missing or NULL, the converted IP address is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+f_inet_atoi()
+{
+ local __addr="$1" __var_to_set="$2" __num=0
+ if f_validate_ipaddr "$__addr"; then
+ __num=$( IFS=.; set -- $__addr; \
+ echo $(( ($1 << 24) + ($2 << 16) + ($3 << 8) + $4 )) )
+ fi
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" $__num
+ else
+ echo $__num
+ fi
+}
+
+# f_validate_ipaddr $ipaddr [$netmask]
+#
+# Returns zero if the given argument (an IP address) is of the proper format.
+#
+# The return status for invalid IP address is one of:
+# 1 One or more individual octets within the IP address (separated
+# by dots) contains one or more invalid characters.
+# 2 One or more individual octets within the IP address are null
+# and/or missing.
+# 3 One or more individual octets within the IP address exceeds the
+# maximum of 255 (or 2^8, being an octet comprised of 8 bits).
+# 4 The IP address has either too few or too many octets.
+#
+# If a netmask is provided, the IP address is checked further:
+#
+# 5 The IP address must not be the network or broadcast address.
+#
+f_validate_ipaddr()
+{
+ local ip="$1" mask="$2"
+
+ # Track number of octets for error checking
+ local noctets=0
+
+ local oldIFS="$IFS"
+ local IFS="." # Split on `dot'
+ for octet in $ip; do
+ # Return error if the octet is null
+ [ "$octet" ] || return 2
+
+ # Return error if not a whole integer
+ f_isinteger "$octet" || return 1
+
+ # Return error if not a positive integer
+ [ $octet -ge 0 ] || return 1
+
+ # Return error if the octet exceeds 255
+ [ $octet -gt 255 ] && return 3
+
+ noctets=$(( $noctets + 1 ))
+ done
+ IFS="$oldIFS"
+
+ [ $noctets -eq 4 ] || return 4
+
+ #
+ # The IP address must not be network or broadcast address.
+ #
+ if [ "$mask" ]; then
+ local ipnum masknum netnum bcastnum
+ local max_addr=4294967295 # 255.255.255.255
+
+ f_inet_atoi $ip ipnum
+ f_inet_atoi $mask masknum
+
+ netnum=$(( $ipnum & $masknum ))
+ bcastnum=$(( ($ipnum & $masknum)+$max_addr-$masknum ))
+
+ if [ "$masknum" ] &&
+ [ $ipnum -eq $netnum -o $ipnum -eq $bcastnum ]
+ then
+ return 5
+ fi
+ fi
+
+ return $SUCCESS
+}
+
+# f_validate_ipaddr6 $ipv6_addr
+#
+# Returns zero if the given argument (an IPv6 address) is of the proper format.
+#
+# The return status for invalid IP address is one of:
+# 1 One or more individual segments within the IP address
+# (separated by colons) contains one or more invalid characters.
+# Segments must contain only combinations of the characters 0-9,
+# A-F, or a-f.
+# 2 Too many/incorrect null segments. A single null segment is
+# allowed within the IP address (separated by colons) but not
+# allowed at the beginning or end (unless a double-null segment;
+# i.e., "::*" or "*::").
+# 3 One or more individual segments within the IP address
+# (separated by colons) exceeds the length of 4 hex-digits.
+# 4 The IP address entered has either too few (less than 3), too
+# many (more than 8), or not enough segments, separated by
+# colons.
+# 5* The IPv4 address at the end of the IPv6 address is invalid.
+# * When there is an error with the dotted-quad IPv4 address at the
+# end of the IPv6 address, the return value of 5 is OR'd with a
+# bit-shifted (<< 4) return of f_validate_ipaddr.
+#
+f_validate_ipaddr6()
+{
+ local ip="${1%\%*}" # removing the interface specification if-present
+
+ local IFS=":" # Split on `colon'
+ set -- $ip:
+
+ # Return error if too many or too few segments
+ # Using 9 as max in case of leading or trailing null spanner
+ [ $# -gt 9 -o $# -lt 3 ] && return 4
+
+ local h="[0-9A-Fa-f]"
+ local nulls=0 nsegments=$# contains_ipv4_segment=
+
+ while [ $# -gt 0 ]; do
+
+ segment="${1%:}"
+ shift
+
+ #
+ # Return error if this segment makes one null too-many. A
+ # single null segment is allowed anywhere in the middle as well
+ # as double null segments are allowed at the beginning or end
+ # (but not both).
+ #
+ if [ ! "$segment" ]; then
+ nulls=$(( $nulls + 1 ))
+ if [ $nulls -eq 3 ]; then
+ # Only valid syntax for 3 nulls is `::'
+ [ "$ip" = "::" ] || return 2
+ elif [ $nulls -eq 2 ]; then
+ # Only valid if begins/ends with `::'
+ case "$ip" in
+ ::*|*::) : fall thru ;;
+ *) return 2
+ esac
+ fi
+ continue
+ fi
+
+ #
+ # Return error if not a valid hexadecimal short
+ #
+ case "$segment" in
+ $h|$h$h|$h$h$h|$h$h$h$h)
+ : valid segment of 1-4 hexadecimal digits
+ ;;
+ *[!0-9A-Fa-f]*)
+ # Segment contains at least one invalid char
+
+ # Return error immediately if not last segment
+ [ $# -eq 0 ] || return 1
+
+ # Otherwise, check for legacy IPv4 notation
+ case "$segment" in
+ *[!0-9.]*)
+ # Segment contains at least one invalid
+ # character even for an IPv4 address
+ return 1
+ esac
+
+ # Return error if not enough segments
+ if [ $nulls -eq 0 ]; then
+ [ $nsegments -eq 7 ] || return 4
+ fi
+
+ contains_ipv4_segment=1
+
+ # Validate the IPv4 address
+ f_validate_ipaddr "$segment" ||
+ return $(( 5 | $? << 4 ))
+ ;;
+ *)
+ # Segment characters are all valid but too many
+ return 3
+ esac
+
+ done
+
+ if [ $nulls -eq 1 ]; then
+ # Single null segment cannot be at beginning/end
+ case "$ip" in
+ :*|*:) return 2
+ esac
+ fi
+
+ #
+ # A legacy IPv4 address can span the last two 16-bit segments,
+ # reducing the amount of maximum allowable segments by-one.
+ #
+ maxsegments=8
+ if [ "$contains_ipv4_segment" ]; then
+ maxsegments=7
+ fi
+
+ case $nulls in
+ # Return error if missing segments with no null spanner
+ 0) [ $nsegments -eq $maxsegments ] || return 4 ;;
+ # Return error if null spanner with too many segments
+ 1) [ $nsegments -le $maxsegments ] || return 4 ;;
+ # Return error if leading/trailing `::' with too many segments
+ 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || return 4 ;;
+ esac
+
+ return $SUCCESS
+}
+
+# f_validate_netmask $netmask
+#
+# Returns zero if the given argument (a subnet mask) is of the proper format.
+#
+# The return status for invalid netmask is one of:
+# 1 One or more individual fields within the subnet mask (separated
+# by dots) contains one or more invalid characters.
+# 2 One or more individual fields within the subnet mask are null
+# and/or missing.
+# 3 One or more individual fields within the subnet mask exceeds
+# the maximum of 255 (a full 8-bit register).
+# 4 The subnet mask has either too few or too many fields.
+# 5 One or more individual fields within the subnet mask is an
+# invalid integer (only 0,128,192,224,240,248,252,254,255 are
+# valid integers).
+#
+f_validate_netmask()
+{
+ local mask="$1"
+
+ # Track number of fields for error checking
+ local nfields=0
+
+ local IFS="." # Split on `dot'
+ for field in $mask; do
+ # Return error if the field is null
+ [ "$field" ] || return 2
+
+ # Return error if not a whole positive integer
+ f_isinteger "$field" || return 1
+
+ # Return error if the field exceeds 255
+ [ $field -gt 255 ] && return 3
+
+ # Return error if the field is an invalid integer
+ case "$field" in
+ 0|128|192|224|240|248|252|254|255) :;;
+ *) return 5;;
+ esac
+
+ nfields=$(( $nfields + 1 ))
+ done
+
+ [ $nfields -eq 4 ] || return 4
+}
+
+# f_validate_gateway $gateway $ipaddr $netmask
+#
+# Validate an IPv4 default gateway (aka router) address for a given IP address
+# making sure the two are in the same network (able to ``talk'' to each other).
+# Returns success if $ipaddr and $gateway are in the same network given subnet
+# mask $netmask.
+#
+f_validate_gateway()
+{
+ local gateway="$1" ipaddr="$2" netmask="$3"
+ local gwnum ipnum masknum
+
+ f_validate_ipaddr "$gateway" "$netmask" || return $FAILURE
+
+ f_inet_atoi "$netmask" masknum
+ f_inet_atoi "$ipaddr" ipnum
+ f_inet_atoi "$gateway" gwnum
+
+ # Gateway must be within set of IPs reachable through interface
+ [ $(( $ipnum & $masknum )) -eq \
+ $(( $gwnum & $masknum )) ] # Return status
+}
+
+# f_dialog_validate_tcpip $hostname $gateway $nameserver $ipaddr $netmask
+#
+# Returns success if the arguments provided are valid for accessing a TCP/IP
+# network, otherwise returns failure.
+#
+f_dialog_validate_tcpip()
+{
+ local hostname="$1" gateway="$2" nameserver="$3"
+ local ipaddr="$4" netmask="$5"
+ local ipnum masknum
+
+ if [ ! "$hostname" ]; then
+ f_dialog_msgbox "$msg_must_specify_a_host_name_of_some_sort"
+ elif ! f_validate_hostname "$hostname"; then
+ f_dialog_msgbox "$msg_invalid_hostname_value"
+ elif [ "$netmask" ] && ! f_validate_netmask "$netmask"; then
+ f_dialog_msgbox "$msg_invalid_netmask_value"
+ elif [ "$nameserver" ] &&
+ ! f_validate_ipaddr "$nameserver" &&
+ ! f_validate_ipaddr6 "$nameserver"; then
+ f_dialog_msgbox "$msg_invalid_name_server_ip_address_specified"
+ elif [ "$ipaddr" ] && ! f_validate_ipaddr "$ipaddr" "$netmask"; then
+ f_dialog_msgbox "$msg_invalid_ipv4_address"
+ elif [ "$gateway" -a "$gateway" != "NO" ] &&
+ ! f_validate_gateway "$gateway" "$ipaddr" "$netmask"; then
+ f_dialog_msgbox "$msg_invalid_gateway_ipv4_address_specified"
+ else
+ return $SUCCESS
+ fi
+
+ return $FAILURE
+}
+
+# f_ifconfig_inet $interface [$var_to_set]
+#
+# Returns the IPv4 address associated with $interface. If $var_to_set is
+# missing or NULL, the IP address is printed to standard output for capturing
+# in a sub-shell (which is less-recommended because of performance degredation;
+# for example, when called in a loop).
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_ifconfig_inet_awk='
+BEGIN { found = 0 }
+( $1 == "inet" ) \
+{
+ print $2
+ found = 1
+ exit
+}
+END { exit ! found }
+'
+f_ifconfig_inet()
+{
+ local __interface="$1" __var_to_set="$2"
+ if [ "$__var_to_set" ]; then
+ local __ip
+ __ip=$( ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet_awk" )
+ setvar "$__var_to_set" "$__ip"
+ else
+ ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet_awk"
+ fi
+}
+
+# f_ifconfig_inet6 $interface [$var_to_set]
+#
+# Returns the IPv6 address associated with $interface. If $var_to_set is
+# missing or NULL, the IP address is printed to standard output for capturing
+# in a sub-shell (which is less-recommended because of performance degredation;
+# for example, when called in a loop).
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_ifconfig_inet6_awk='
+BEGIN { found = 0 }
+( $1 == "inet6" ) \
+{
+ print $2
+ found = 1
+ exit
+}
+END { exit ! found }
+'
+f_ifconfig_inet6()
+{
+ local __interface="$1" __var_to_set="$2"
+ if [ "$__var_to_set" ]; then
+ local __ip6
+ __ip6=$( ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet6_awk" )
+ setvar "$__var_to_set" "$__ip6"
+ else
+ ifconfig "$__interface" 2> /dev/null |
+ awk "$f_ifconfig_inet6_awk"
+ fi
+}
+
+# f_ifconfig_netmask $interface [$var_to_set]
+#
+# Returns the IPv4 subnet mask associated with $interface. If $var_to_set is
+# missing or NULL, the netmask is printed to standard output for capturing in a
+# sub-shell (which is less-recommended because of performance degredation; for
+# example, when called in a loop).
+#
+f_ifconfig_netmask()
+{
+ local __interface="$1" __var_to_set="$2" __octets
+ __octets=$( ifconfig "$__interface" 2> /dev/null | awk \
+ '
+ BEGIN { found = 0 }
+ ( $1 == "inet" ) \
+ {
+ printf "%s %s %s %s\n",
+ substr($4,3,2),
+ substr($4,5,2),
+ substr($4,7,2),
+ substr($4,9,2)
+ found = 1
+ exit
+ }
+ END { exit ! found }
+ ' ) || return $FAILURE
+
+ local __octet __netmask=
+ for __octet in $__octets; do
+ __netmask="$__netmask.$( printf "%u" "0x$__octet" )"
+ done
+ __netmask="${__netmask#.}"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__netmask"
+ else
+ echo $__netmask
+ fi
+}
+
+# f_route_get_default [$var_to_set]
+#
+# Returns the IP address of the currently active default router. If $var_to_set
+# is missing or NULL, the IP address is printed to standard output for
+# capturing in a sub-shell (which is less-recommended because of performance
+# degredation; for example, when called in a loop).
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_route_get_default='
+BEGIN { found = 0 }
+( $1 == "gateway:" ) \
+{
+ print $2
+ found = 1
+ exit
+}
+END { exit ! found }
+'
+f_route_get_default()
+{
+ local __var_to_set="$1"
+ if [ "$__var_to_set" ]; then
+ local __ip
+ __ip=$( route -n get default 2> /dev/null |
+ awk "$f_route_get_default_awk" )
+ setvar "$__var_to_set" "$__ip"
+ else
+ route -n get default 2> /dev/null |
+ awk "$f_route_get_default_awk"
+ fi
+}
+
+# f_resolv_conf_nameservers [$var_to_set]
+#
+# Returns nameserver(s) configured in resolv.conf(5). If $var_to_set is missing
+# or NULL, the list of nameservers is printed to standard output for capturing
+# in a sub-shell (which is less-recommended because of performance degredation;
+# for example, when called in a loop).
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_resolv_conf_nameservers_awk='
+BEGIN { found = 0 }
+( $1 == "nameserver" ) \
+{
+ print $2
+ found = 1
+}
+END { exit ! found }
+'
+f_resolv_conf_nameservers()
+{
+ local __var_to_set="$1"
+ if [ "$__var_to_set" ]; then
+ local __ns
+ __ns=$( awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \
+ 2> /dev/null )
+ setvar "$__var_to_set" "$__ns"
+ else
+ awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \
+ 2> /dev/null
+ fi
+}
+
+# f_config_resolv
+#
+# Attempts to configure resolv.conf(5) and ilk. Returns success if able to
+# write the file(s), otherwise returns error status.
+#
+# Variables from variable.subr that are used in configuring resolv.conf(5) are
+# as follows (all of which can be configured automatically through functions
+# like f_dhcp_get_info() or manually):
+#
+# VAR_NAMESERVER
+# The nameserver to add in resolv.conf(5).
+# VAR_DOMAINNAME
+# The domain to configure in resolv.conf(5). Also used in the
+# configuration of hosts(5).
+# VAR_IPADDR
+# The IPv4 address to configure in hosts(5).
+# VAR_IPV6ADDR
+# The IPv6 address to configure in hosts(5).
+# VAR_HOSTNAME
+# The hostname to associate with the IPv4 and/or IPv6 address in
+# hosts(5).
+#
+f_config_resolv()
+{
+ local cp c6p dp hp
+
+ f_getvar $VAR_NAMESERVER cp
+ if [ "$cp" ]; then
+ case "$RESOLV_CONF" in
+ */*) f_quietly mkdir -p "${RESOLV_CONF%/*}" ;;
+ esac
+
+ # Attempt to create/truncate the file
+ ( :> "$RESOLV_CONF" ) 2> /dev/null || return $FAILURE
+
+ f_getvar $VAR_DOMAINNAME dp &&
+ printf "domain\t%s\n" "$dp" >> "$RESOLV_CONF"
+ printf "nameserver\t%s\n" "$cp" >> "$RESOLV_CONF"
+
+ f_dprintf "Wrote out %s" "$RESOLV_CONF"
+ fi
+
+ f_getvar $VAR_DOMAINNAME dp
+ f_getvar $VAR_IPADDR cp
+ f_getvar $VAR_IPV6ADDR c6p
+ f_getvar $VAR_HOSTNAME hp
+
+ # Attempt to create the file if it doesn't already exist
+ if [ ! -e "$ETC_HOSTS" ]; then
+ case "$ETC_HOSTS" in
+ */*) f_quietly mkdir -p "${ETC_HOSTS%/*}" ;;
+ esac
+
+ ( :> "$ETC_HOSTS" ) 2> /dev/null || return $FAILURE
+ fi
+
+ # Scan the file and add ourselves if not already configured
+ awk -v dn="$dp" -v ip4="$cp" -v ip6="$c6p" -v hn="$hp" '
+ BEGIN {
+ local4found = local6found = 0
+ hn4found = hn6found = h4found = h6found = 0
+ h = ( match(hn, /\./) ? substr(hn, 0, RSTART-1) : "" )
+ }
+ ($1 == "127.0.0.1") { local4found = 1 }
+ ($1 == "::1") { local6found = 1 }
+ {
+ for (n = 2; n <= NF; n++)
+ {
+ if ( $1 == ip4 ) {
+ if ( $n == h ) h4found = 1
+ if ( $n == hn ) hn4found = 1
+ if ( $n == hn "." ) hn4found = 1
+ }
+ if ( $1 == ip6 ) {
+ if ( $n == h ) h6found = 1
+ if ( $n == hn ) hn6found = 1
+ if ( $n == hn "." ) hn6found = 1
+ }
+ }
+ }
+ END {
+ hosts = FILENAME
+
+ if ( ! local6found )
+ printf "::1\t\t\tlocalhost%s\n",
+ ( dn ? " localhost." dn : "" ) >> hosts
+ if ( ! local4found )
+ printf "127.0.0.1\t\tlocalhost%s\n",
+ ( dn ? " localhost." dn : "" ) >> hosts
+
+ if ( ip6 && ! (h6found && hn6found))
+ {
+ printf "%s\t%s %s\n", ip6, hn, h >> hosts
+ printf "%s\t%s.\n", ip6, hn >> hosts
+ }
+ else if ( ip6 )
+ {
+ if ( ! h6found )
+ printf "%s\t%s.\n", ip6, h >> hosts
+ if ( ! hn6found )
+ printf "%s\t%s\n", ip6, hn >> hosts
+ }
+
+ if ( ip4 && ! (h4found && hn4found))
+ {
+ printf "%s\t\t%s %s\n", ip4, hn, h >> hosts
+ printf "%s\t\t%s.\n", ip4, hn >> hosts
+ }
+ else if ( ip4 )
+ {
+ if ( ! h4found )
+ printf "%s\t\t%s.\n", ip4, h >> hosts
+ if ( ! hn4found )
+ printf "%s\t\t%s\n", ip4, hn >> hosts
+ }
+ }
+ ' "$ETC_HOSTS" 2> /dev/null || return $FAILURE
+
+ f_dprintf "Wrote out %s" "$ETC_HOSTS"
+ return $SUCCESS
+}
+
+# f_dhcp_parse_leases $leasefile struct_name
+#
+# Parse $leasefile and store the information for the most recent lease in a
+# struct (see struct.subr for additional details) named `struct_name'. See
+# DHCP_LEASE struct definition in the GLOBALS section above.
+#
+f_dhcp_parse_leases()
+{
+ local leasefile="$1" struct_name="$2"
+
+ [ "$struct_name" ] || return $FAILURE
+
+ if [ ! -e "$leasefile" ]; then
+ f_dprintf "%s: No such file or directory" "$leasefile"
+ return $FAILURE
+ fi
+
+ f_struct "$struct_name" && f_struct_free "$struct_name"
+ f_struct_new DHCP_LEASE "$struct_name"
+
+ eval "$( awk -v struct="$struct_name" '
+ BEGIN {
+ lease_found = 0
+ keyword_list = " \
+ interface \
+ fixed-address \
+ filename \
+ server-name \
+ script \
+ medium \
+ "
+ split(keyword_list, keywords, FS)
+
+ time_list = "renew rebind expire"
+ split(time_list, times, FS)
+
+ option_list = " \
+ host-name \
+ subnet-mask \
+ routers \
+ domain-name-servers \
+ domain-name \
+ broadcast-address \
+ dhcp-lease-time \
+ dhcp-message-type \
+ dhcp-server-identifier \
+ dhcp-renewal-time \
+ dhcp-rebinding-time \
+ "
+ split(option_list, options, FS)
+ }
+ function set_value(prop,value)
+ {
+ lease_found = 1
+ gsub(/[^[:alnum:]_]/, "_", prop)
+ sub(/;$/, "", value)
+ sub(/^"/, "", value)
+ sub(/"$/, "", value)
+ sub(/,.*/, "", value)
+ printf "%s set %s \"%s\"\n", struct, prop, value
+ }
+ /^lease {$/, /^}$/ \
+ {
+ if ( $0 ~ /^lease {$/ ) next
+ if ( $0 ~ /^}$/ ) exit
+
+ for (k in keywords)
+ {
+ keyword = keywords[k]
+ if ( $1 == keyword )
+ {
+ set_value(keyword, $2)
+ next
+ }
+ }
+
+ for (t in times)
+ {
+ time = times[t]
+ if ( $1 == time )
+ {
+ set_value(time, $2 " " $3 " " $4)
+ next
+ }
+ }
+
+ if ( $1 != "option" ) next
+ for (o in options)
+ {
+ option = options[o]
+ if ( $2 == option )
+ {
+ set_value(option, $3)
+ next
+ }
+ }
+ }
+ EXIT {
+ if ( ! lease_found )
+ {
+ printf "f_struct_free \"%s\"\n", struct
+ print "return $FAILURE"
+ }
+ }
+ ' "$leasefile" )"
+}
+
+# f_dhcp_get_info $interface
+#
+# Parse the dhclient(8) lease database for $interface to obtain all the
+# necessary IPv4 details necessary to communicate on the network. The retrieved
+# information is stored in VAR_IPADDR, VAR_NETMASK, VAR_GATEWAY, and
+# VAR_NAMESERVER.
+#
+# If reading the lease database fails, values are obtained from ifconfig(8) and
+# route(8). If the DHCP lease did not provide a nameserver (or likewise, we
+# were unable to parse the lease database), fall-back to resolv.conf(5) for
+# obtaining the nameserver. Always returns success.
+#
+f_dhcp_get_info()
+{
+ local interface="$1" cp
+ local leasefile="/var/db/dhclient.leases.$interface"
+
+ # If it fails, do it the old-fashioned way
+ if f_dhcp_parse_leases "$leasefile" lease; then
+ lease get fixed_address $VAR_IPADDR
+ lease get subnet_mask $VAR_NETMASK
+ lease get routers cp
+ setvar $VAR_GATEWAY "${cp%%,*}"
+ lease get domain_name_servers cp
+ setvar $VAR_NAMESERVER "${cp%%,*}"
+ lease get host_name cp &&
+ setvar $VAR_HOSTNAME "$cp"
+ f_struct_free lease
+ else
+ # Bah, now we have to get the information from ifconfig
+ if f_debugging; then
+ f_dprintf "DHCP configured interface returns %s" \
+ "$( ifconfig "$interface" )"
+ fi
+ f_ifconfig_inet "$interface" $VAR_IPADDR
+ f_ifconfig_netmask "$interface" $VAR_NETMASK
+ f_route_get_default $VAR_GATEWAY
+ fi
+
+ # If we didn't get a name server value, hunt for it in resolv.conf
+ local ns
+ if [ -r "$RESOLV_CONF" ] && ! {
+ f_getvar $VAR_NAMESERVER ns || [ "$ns" ]
+ }; then
+ f_resolv_conf_nameservers cp &&
+ setvar $VAR_NAMESERVER ${cp%%[$IFS]*}
+ fi
+
+ return $SUCCESS
+}
+
+# f_rtsol_get_info $interface
+#
+# Returns the rtsol-provided IPv6 address associated with $interface. The
+# retrieved IP address is stored in VAR_IPV6ADDR. Always returns success.
+#
+f_rtsol_get_info()
+{
+ local interface="$1" cp
+ cp=$( ifconfig "$interface" 2> /dev/null | awk \
+ '
+ BEGIN { found = 0 }
+ ( $1 == "inet6" ) && ( $2 ~ /^fe80:/ ) \
+ {
+ print $2
+ found = 1
+ exit
+ }
+ END { exit ! found }
+ ' ) && setvar $VAR_IPV6ADDR "$cp"
+}
+
+# f_host_lookup $host [$var_to_set]
+#
+# Use host(1) to lookup (or reverse) an Internet number from (or to) a name.
+# Multiple answers are returned separated by a single space. If host(1) does
+# not exit cleanly, its full output is provided and the return status is 1.
+#
+# If nsswitch.conf(5) has been configured to query local access first for the
+# `hosts' database, we'll manually check hosts(5) first (preventing host(1)
+# from hanging in the event that DNS goes awry).
+#
+# If $var_to_set is missing or NULL, the list of IP addresses is printed to
+# standard output for capturing in a sub-shell (which is less-recommended
+# because of performance degredation; for example, when called in a loop).
+#
+# The variables from variable.subr used in looking up the host are as follows
+# (which are set manually):
+#
+# VAR_IPV6_ENABLE [Optional]
+# If set to "YES", enables the lookup of IPv6 addresses and IPv4
+# address. IPv6 addresses, if any, will come before IPv4. Note
+# that if nsswitch.conf(5) shows an affinity for "files" for the
+# "host" database and there is a valid entry in hosts(5) for
+# $host, this setting currently has no effect (an IPv4 address
+# can supersede an IPv6 address). By design, hosts(5) overrides
+# any preferential treatment. Otherwise, if this variable is not
+# set, IPv6 addresses will not be used (IPv4 addresses will
+# specifically be requested from DNS).
+#
+# This function is a two-parter. Below is the awk(1) portion of the function,
+# afterward is the sh(1) function which utilizes the below awk script.
+#
+f_host_lookup_awk='
+BEGIN{ addrs = "" }
+!/^[[:space:]]*(#|$)/ \
+{
+ for (n=1; n++ < NF;) if ($n == name)
+ addrs = addrs (addrs ? " " : "") $1
+}
+END {
+ if (addrs) print addrs
+ exit !addrs
+}
+'
+f_host_lookup()
+{
+ local __host="$1" __var_to_set="$2"
+ f_dprintf "f_host_lookup: host=[%s]" "$__host"
+
+ # If we're configured to look at local files first, do that
+ if awk '/^hosts:/{exit !($2=="files")}' "$NSSWITCH_CONF"; then
+ if [ "$__var_to_set" ]; then
+ local __cp
+ if __cp=$( awk -v name="$__host" \
+ "$f_host_lookup_awk" "$ETC_HOSTS" )
+ then
+ setvar "$__var_to_set" "$__cp"
+ return $SUCCESS
+ fi
+ else
+ awk -v name="$__host" \
+ "$f_host_lookup_awk" "$ETC_HOSTS" &&
+ return $SUCCESS
+ fi
+ fi
+
+ #
+ # Fall back to host(1) -- which is further governed by nsswitch.conf(5)
+ #
+
+ local __output __ip6 __addrs="" __wait=""
+ f_getvar $VAR_MEDIA_TIMEOUT __wait
+ [ "$__wait" ] && __wait="-W $(( $__wait / 2 ))"
+ f_getvar $VAR_IPV6_ENABLE __ip6
+ if [ "$__ip6" = "YES" ]; then
+ if ! __output=$( host -t AAAA $__wait -- "$__host" 2>&1 ); then
+ # An error occurred, display in-full and return error
+ [ "$__var_to_set" ] &&
+ setvar "$__var_to_set" "$__output"
+ return $FAILURE
+ fi
+ __addrs=$( echo "$__output" | awk '/ address /{print $NF}' )
+ fi
+ if ! __output=$( host -t A $__wait -- "$__host" 2>&1 ); then
+ # An error occurred, display it in-full and return error
+ [ "$__var_to_set" ] && setvar "$__var_to_set" "$__output"
+ return $FAILURE
+ fi
+ __addrs="$__addrs${__addrs:+ }$(
+ echo "$__output" | awk '/ address /{print $NF}' )"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__addrs"
+ else
+ echo $__addrs
+ fi
+}
+
+# f_device_dialog_tcp $device
+#
+# This is it - how to get TCP setup values. Prompt the user to edit/confirm the
+# interface, gateway, nameserver, and hostname settings -- all required for
+# general TCP/IP access.
+#
+# Variables from variable.subr that can be used to sript user input:
+#
+# VAR_NO_INET6
+# If set, prevents asking the user if they would like to use
+# rtsol(8) to check for an IPv6 router.
+# VAR_TRY_RTSOL
+# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the
+# user if they would like to try the IPv6 RouTer SOLicitation
+# utility (rtsol(8)) to get IPv6 information. Ignored if
+# VAR_NO_INET6 is set.
+# VAR_TRY_DHCP
+# If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the
+# user if they would like to try to acquire IPv4 connection
+# settings from a DHCP server using dhclient(8).
+#
+# VAR_GATEWAY Default gateway to use.
+# VAR_IPADDR Interface address to assign.
+# VAR_NETMASK Interface subnet mask.
+# VAR_EXTRAS Extra interface options to ifconfig(8).
+# VAR_HOSTNAME Hostname to set.
+# VAR_DOMAINNAME Domain name to use.
+# VAR_NAMESERVER DNS nameserver to use when making lookups.
+# VAR_IPV6ADDR IPv6 interface address.
+#
+# In addition, the following variables are used in acquiring network settings
+# from the user:
+#
+# VAR_NONINTERACTIVE
+# If set (such as when running in a script), prevents asking the
+# user questions or displaying the usual prompts, etc.
+# VAR_NETINTERACTIVE
+# The one exception to VAR_NONINTERACTIVE is VAR_NETINTERACTIVE,
+# which if set will prompt the user to try RTSOL (unless
+# VAR_TRY_RTSOL has been set), try DHCP (unless VAR_TRY_DHCP has
+# been set), and display the network verification dialog. This
+# allows you to have a mostly non-interactive script that still
+# prompts for network setup/confirmation.
+#
+# After successfull execution, the following variables are set:
+#
+# VAR_IFCONFIG + $device (e.g., `ifconfig_em0')
+# Defines the ifconfig(8) properties specific to $device.
+#
+f_device_dialog_tcp()
+{
+ local dev="$1" cp n
+ local use_dhcp="" use_rtsol=""
+ local _ipaddr _netmask _extras
+
+ [ "$dev" ] || return $FAILURE
+
+ # Initialize vars from previous device values
+ local private
+ device_$dev get private private
+ if [ "$private" ] && f_struct "$private"; then
+ $private get ipaddr _ipaddr
+ $private get netmask _netmask
+ $private get extras _extras
+ $private get use_dhcp use_dhcp
+ $private get use_rtsol use_rtsol
+ else # See if there are any defaults
+
+ #
+ # This is a hack so that the dialogs below are interactive in a
+ # script if we have requested interactive behavior.
+ #
+ local old_interactive=
+ if ! f_interactive && f_netinteractive; then
+ f_getvar $VAR_NONINTERACTIVE old_interactive
+ unset $VAR_NONINTERACTIVE
+ fi
+
+
+ #
+ # Try a RTSOL scan if such behavior is desired.
+ # If the variable was configured and is YES, do it.
+ # If it was configured to anything else, treat it as NO.
+ # Otherwise, ask the question interactively.
+ #
+ local try6
+ if ! f_quietly f_getvar $VAR_NO_INET6 && {
+ { f_getvar $VAR_TRY_RTSOL try6 && [ "$try6" = "YES" ]; } ||
+ {
+ ! f_quietly f_getvar $VAR_TRY_RTSOL &&
+ f_dialog_noyes "$msg_try_ipv6_configuration"
+ }
+ }; then
+ local i
+
+ f_quietly sysctl net.inet6.ip6.forwarding=0
+ f_quietly sysctl net.inet6.ip6.accept_rtadv=1
+ f_quietly ifconfig $dev up
+
+ i=$( sysctl -n net.inet6.ip6.dad_count )
+ sleep $(( $i + 1 ))
+
+ f_quietly mkdir -p /var/run
+ f_dialog_info "$msg_scanning_for_ra_servers"
+ if f_quietly rtsol $dev; then
+ i=$( sysctl -n net.inet6.ip6.dad_count )
+ sleep $(( $i + 1 ))
+ f_rtsol_get_info $dev
+ use_rtsol=1
+ else
+ use_rtsol=
+ fi
+ fi
+
+ #
+ # Try a DHCP scan if such behavior is desired.
+ # If the variable was configured and is YES, do it.
+ # If it was configured to anything else, treat it as NO.
+ # Otherwise, ask the question interactively.
+ #
+ local try4
+ if { f_getvar $VAR_TRY_DHCP try4 && [ "$try4" = "YES" ]; } || {
+ ! f_quietly f_getvar $VAR_TRY_DHCP &&
+ f_dialog_noyes "$msg_try_dhcp_configuration"
+ }; then
+ f_quietly ifconfig $dev delete
+ f_quietly mkdir -p /var/db
+ f_quietly mkdir -p /var/run
+ f_quietly mkdir -p /tmp
+
+ local msg="$msg_scanning_for_dhcp_servers"
+ trap - SIGINT
+ ( # Execute in sub-shell to allow/catch Ctrl-C
+ trap 'exit $FAILURE' SIGINT
+ if [ "$USE_XDIALOG" ]; then
+ f_quietly dhclient $dev |
+ f_xdialog_info "$msg"
+ else
+ f_dialog_info "$msg"
+ f_quietly dhclient $dev
+ fi
+ )
+ local retval=$?
+ trap 'f_interrupt' SIGINT
+ if [ $retval -eq $SUCCESS ]; then
+ f_dhcp_get_info $dev
+ use_dhcp=1
+ else
+ use_dhcp=
+ fi
+ fi
+
+ # Restore old VAR_NONINTERACTIVE if needed.
+ [ "$old_interactive" ] &&
+ setvar $VAR_NONINTERACTIVE "$old_interactive"
+
+ # Special hack so it doesn't show up oddly in the menu
+ local gw
+ if f_getvar $VAR_GATEWAY gw && [ "$gw" = "NO" ]; then
+ setvar $VAR_GATEWAY ""
+ fi
+
+ # Get old IP address from variable space, if available
+ if [ ! "$_ipaddr" ]; then
+ if f_getvar $VAR_IPADDR cp; then
+ _ipaddr="$cp"
+ elif f_getvar ${dev}_$VAR_IPADDR cp; then
+ _ipaddr="$cp"
+ fi
+ fi
+
+ # Get old netmask from variable space, if available
+ if [ ! "$_netmask" ]; then
+ if f_getvar $VAR_NETMASK cp; then
+ _netmask="$cp"
+ elif f_getvar ${dev}_$VAR_NETMASK cp; then
+ _netmask="$cp"
+ fi
+ fi
+
+ # Get old extras string from variable space, if available
+ if [ ! "$_extras" ]; then
+ if f_getvar $VAR_EXTRAS cp; then
+ _extras="$cp"
+ elif f_getvar ${dev}_$VAR_EXTRAS cp; then
+ _extras="$cp"
+ fi
+ fi
+ fi
+
+ # Look up values already recorded with the system, or blank the string
+ # variables ready to accept some new data
+ local _hostname _gateway _nameserver
+ f_getvar $VAR_HOSTNAME _hostname
+ case "$_hostname" in
+ *.*) : do nothing ;; # Already fully-qualified
+ *)
+ f_getvar $VAR_DOMAINNAME cp
+ [ "$cp" ] && _hostname="$_hostname.$cp"
+ esac
+ f_getvar $VAR_GATEWAY _gateway
+ f_getvar $VAR_NAMESERVER _nameserver
+
+ # Re-check variables for initial inheritance before heading into dialog
+ [ "$_hostname" ] || _hostname="${HOSTNAME:-$( hostname )}"
+ [ "$_gateway" ] || f_route_get_default _gateway
+ [ ! "$_nameserver" ] &&
+ f_resolv_conf_nameservers cp && _nameserver=${cp%%[$IFS]*}
+ [ "$_ipaddr" ] || f_ifconfig_inet $dev _ipaddr
+ [ "$_netmask" ] || f_ifconfig_netmask $dev _netmask
+
+ # If non-interactive, jump over dialog section and into config section
+ if f_netinteractive || f_interactive || [ ! "$_hostname" ]
+ then
+ [ ! "$_hostname" ] && f_interactive &&
+ f_dialog_msgbox "$msg_hostname_variable_not_set"
+
+ local title=" $msg_network_configuration "
+ local hline="$hline_alnum_arrows_punc_tab_enter"
+ local extras_help="$tcplayout_extras_help"
+
+ # Modify the help line for PLIP config
+ [ "${dev#plip}" != "$dev" ] &&
+ extras_help="$tcplayout_extras_help_for_plip"
+
+ f_getvar $VAR_IPV6ADDR cp && [ "$cp" ] &&
+ title="$title($msg_ipv6_ready) "
+
+ if [ ! "$USE_XDIALOG" ]; then
+ local prompt="$msg_dialog_mixedform_navigation_help"
+ # Calculate center position for displaying device label
+ local devlabel="$msg_configuration_for_interface $dev"
+ local width=54
+ local n=$(( $width/2 - (${#devlabel} + 4)/2 - 2 ))
+
+ while :; do
+ cp=$( $DIALOG \
+ --title "$title" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --item-help \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --help-button \
+ --help-label "$msg_help" \
+ --mixedform "$prompt" 16 $width 9 \
+ "$msg_host_name_including_domain:" 1 2 \
+ "$_hostname" 2 3 45 255 0 \
+ "$tcplayout_hostname_help" \
+ "$msg_ipv4_gateway:" 3 2 \
+ "$_gateway" 4 3 16 15 0 \
+ "$tcplayout_gateway_help" \
+ "$msg_name_server:" 3 31 \
+ "$_nameserver" 4 32 16 15 0 \
+ "$tcplayout_nameserver_help" \
+ "- $devlabel -" 5 $n "" 0 0 0 0 3 "" \
+ "$msg_ipv4_address:" 6 6 \
+ "$_ipaddr" 7 7 16 15 0 \
+ "$tcplayout_ipaddr_help" \
+ "$msg_netmask:" 6 31 \
+ "$_netmask" 7 32 16 15 0 \
+ "$tcplayout_netmask_help" \
+ "$msg_extra_options_to_ifconfig" 8 6 \
+ "$_extras" 9 7 41 2048 0 \
+ "$extras_help" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+
+ # --mixed-form always returns 0, we have to
+ # use the returned data to determine button
+ if [ ! "$cp" ]; then
+ # User either chose "Cancel", pressed
+ # ESC, or blanked every form field
+ return $FAILURE
+ else
+ n=$( echo "$cp" | f_number_of_lines )
+ [ $n -eq 1 ] && case "$cp" in HELP*)
+ # User chose "Help"
+ f_show_help "$TCP_HELPFILE"
+ continue
+ esac
+ fi
+
+ # Turn mixed-form results into env variables
+ eval "$( echo "$cp" | awk '
+ BEGIN {
+ n = 0
+ field[++n] = "_hostname"
+ field[++n] = "_gateway"
+ field[++n] = "_nameserver"
+ field[++n] = "_ipaddr"
+ field[++n] = "_netmask"
+ field[++n] = "_extras"
+ nfields = n
+ n = 0
+ }
+ {
+ gsub(/'\''/, "'\'\\\\\'\''")
+ sub(/[[:space:]]*$/, "")
+ value[field[++n]] = $0
+ }
+ END {
+ for ( n = 1; n <= nfields; n++ )
+ {
+ printf "%s='\''%s'\'';\n",
+ field[n],
+ value[field[n]]
+ }
+ }' )"
+
+ f_dialog_validate_tcpip \
+ "$_hostname" \
+ "$_gateway" \
+ "$_nameserver" \
+ "$_ipaddr" \
+ "$_netmask" \
+ && break
+ done
+ else
+ # Xdialog(1) does not support --mixed-form
+ # Create a persistent menu instead
+
+ f_dialog_title "$msg_network_configuration"
+ local prompt=""
+
+ while :; do
+ cp=$( $DIALOG \
+ --title "$DIALOG_TITLE" \
+ --backtitle "$DIALOG_BACKTITLE" \
+ --hline "$hline" \
+ --item-help \
+ --ok-label "$msg_ok" \
+ --cancel-label "$msg_cancel" \
+ --help "" \
+ --menu "$prompt" 21 60 8 \
+ "$msg_accept_continue" "" \
+ "$tcplayout_accept_cont_help" \
+ "$msg_host_name_including_domain:" \
+ "$_hostname" \
+ "$tcplayout_hostname_help" \
+ "$msg_ipv4_gateway:" "$_gateway" \
+ "$tcplayout_gateway_help" \
+ "$msg_name_server:" "$_nameserver" \
+ "$tcplayout_nameserver_help" \
+ "$msg_ipv4_address:" "$_ipaddr" \
+ "$tcplayout_ipaddr_help" \
+ "$msg_netmask:" "$_netmask" \
+ "$tcplayout_netmask_help" \
+ "$msg_extra_options_to_ifconfig" \
+ "$_extras" "$extras_help" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
+ )
+ local retval=$?
+ f_dprintf "retval=%u mtag=[%s]" $retval "$cp"
+
+ if [ $retval -eq 2 ]; then
+ # The Help button was pressed
+ f_show_help "$TCP_HELPFILE"
+ continue
+ elif [ $retval -ne 0 ]; then
+ # User chose "Cancel" or pressed ESC
+ f_dialog_title_restore
+ return $FAILURE
+ fi
+
+ case "$cp" in
+ "$msg_accept_continue")
+ f_dialog_validate_tcpip \
+ "$_hostname" \
+ "$_gateway" \
+ "$_nameserver" \
+ "$_ipaddr" \
+ "$_netmask" \
+ && break ;;
+ "$msg_host_name_including_domain:")
+ cp=$( f_dialog_input "$cp" \
+ "$_hostname"
+ ) && _hostname="$cp" ;;
+ "$msg_ipv4_gateway:")
+ cp=$( f_dialog_input "$cp" \
+ "$_gateway"
+ ) && _gateway="$cp" ;;
+ "$msg_name_server:")
+ cp=$( f_dialog_input "$cp" \
+ "$_nameserver"
+ ) && _nameserver="$cp" ;;
+ "$msg_ipv4_address:")
+ cp=$( f_dialog_input "$cp" \
+ "$_ipaddr"
+ ) && _ipaddr="$cp" ;;
+ "$msg_netmask:")
+ cp=$( f_dialog_input "$cp" \
+ "$_netmask"
+ ) && _netmask="$cp" ;;
+ "$msg_extra_options_to_ifconfig")
+ cp=$( f_dialog_input "$cp" \
+ "$_extras"
+ ) && _extras="$cp" ;;
+ esac
+ done
+
+ f_dialog_title_restore
+
+ fi # XDIALOG
+
+ fi # interactive
+
+ # We actually need to inform the rest of bsdconfig about this
+ # data now if the user hasn't selected cancel.
+
+ if [ "$_hostname" ]; then
+ setvar $VAR_HOSTNAME "$_hostname"
+ f_quietly hostname "$_hostname"
+ case "$_hostname" in
+ *.*) setvar $VAR_DOMAINNAME "${_hostname#*.}" ;;
+ esac
+ fi
+ [ "$_gateway" ] && setvar $VAR_GATEWAY "$_gateway"
+ [ "$_nameserver" ] && setvar $VAR_NAMESERVER "$_nameserver"
+ [ "$_ipaddr" ] && setvar $VAR_IPADDR "$_ipaddr"
+ [ "$_netmask" ] && setvar $VAR_NETMASK "$_netmask"
+ [ "$_extras" ] && setvar $VAR_EXTRAS "$_extras"
+
+ f_dprintf "Creating struct DEVICE_INFO devinfo_%s" "$dev"
+ f_struct_new DEVICE_INFO devinfo_$dev
+ device_$dev set private devinfo_$dev
+
+ devinfo_$dev set ipaddr $_ipaddr
+ devinfo_$dev set netmask $_netmask
+ devinfo_$dev set extras $_extras
+ devinfo_$dev set use_rtsol $use_rtsol
+ devinfo_$dev set use_dhcp $use_dhcp
+
+ if [ "$use_dhcp" -o "$_ipaddr" ]; then
+ if [ "$use_dhcp" ]; then
+ cp="DHCP${extras:+ $extras}"
+ else
+ cp="inet $_ipaddr netmask $_netmask${extras:+ $extras}"
+ fi
+ setvar $VAR_IFCONFIG$dev "$cp"
+ fi
+ [ "$use_rtsol" ] &&
+ setvar $VAR_IPV6_ENABLE "YES"
+
+ [ "$use_dhcp" ] ||
+ f_config_resolv # XXX this will do it on the MFS copy
+
+ return $SUCCESS
+}
+
+# f_device_scan_tcp [$var_to_set]
+#
+# Scan for the first active/configured TCP/IP device. The name of the interface
+# is printed to stderr like other dialog(1)-based functions (stdout is reserved
+# for dialog(1) interaction) if $var_to_set is missing or NULL. Returns failure
+# if no active/configured interface
+#
+f_device_scan_tcp()
+{
+ local __var_to_set="$1" __iface
+ for __iface in $( ifconfig -l ); do
+ if ifconfig $__iface | awk '
+ BEGIN {
+ has_inet = has_inet6 = is_ethernet = 0
+ is_usable = 1
+ }
+ ( $1 == "status:" && $2 != "active" ) { is_usable = 0; exit }
+ ( $1 == "inet" ) {
+ if ($2 == "0.0.0.0") { is_usable = 0; exit }
+ has_inet++
+ }
+ ( $1 == "inet6") { has_inet6++ }
+ ( $1 == "media:" ) {
+ if ($2 != "Ethernet") { is_usable = 0; exit }
+ is_ethernet = 1
+ }
+ END {
+ if (!(is_ethernet && (has_inet || has_inet6)))
+ is_usable = 0
+ exit ! is_usable
+ }'; then
+ f_interactive &&
+ f_show_msg "$msg_using_interface" "$__iface"
+ f_dprintf "f_device_scan_tcp found %s" "$__iface"
+ if [ "$__var_to_set" ]; then
+ setvar "$__var_to_set" "$__iface"
+ else
+ echo "$__iface" >&2
+ fi
+ return $SUCCESS
+ fi
+ done
+
+ return $FAILURE
+}
+
+# f_device_select_tcp
+#
+# Prompt the user to select network interface to use for TCP/IP access.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_NETWORK_DEVICE [Optional]
+# Either a comma-separated list of network interfaces to try when
+# setting up network access (e.g., "fxp0,em0") or "ANY" (case-
+# sensitive) to indicate that the first active and configured
+# interface is acceptable. If unset, the user is presented with a
+# menu of all available network interfaces.
+#
+# Returns success if a valid network interface has been selected.
+#
+f_device_select_tcp()
+{
+ local devs dev cnt network_dev
+ f_getvar $VAR_NETWORK_DEVICE network_dev
+
+ f_dprintf "f_device_select_tcp: %s=[%s]" \
+ VAR_NETWORK_DEVICE "$network_dev"
+
+ if [ "$network_dev" ]; then
+ #
+ # This can be set to several types of values. If set to ANY,
+ # scan all network devices looking for a valid link, and go
+ # with the first device found. Can also be specified as a
+ # comma delimited list, with each network device tried in
+ # order. Can also be set to a single network device.
+ #
+ [ "$network_dev" = "ANY" ] && f_device_scan_tcp network_dev
+
+ while [ "$network_dev" ]; do
+ case "$network_dev" in
+ *,*) dev="${network_dev%%,*}"
+ network_dev="${network_dev#*,}"
+ ;;
+ *) dev="$network_dev"
+ network_dev=
+ esac
+
+ f_device_find "$dev" $DEVICE_TYPE_NETWORK devs
+ cnt=$( set -- $devs; echo $# )
+
+ if [ ${cnt:=0} -gt 0 ]; then
+ dev="${devs%%[$IFS]*}"
+ f_device_dialog_tcp $dev
+ if [ $? -eq $SUCCESS ]; then
+ setvar $VAR_NETWORK_DEVICE $dev
+ return $SUCCESS
+ fi
+ fi
+ done
+
+ f_interactive && f_dialog_msgbox "$msg_no_network_devices"
+ return $FAILURE
+
+ fi # $network_dev
+
+ f_device_find "" $DEVICE_TYPE_NETWORK devs
+ cnt=$( set -- $devs; echo $# )
+ dev="${devs%%[$IFS]*}"
+
+ f_quietly f_getvar NETWORK_CONFIGURED # for debugging info
+ if ! f_running_as_init &&
+ ! [ "${NETWORK_CONFIGURED+set}" -a "$NETWORK_CONFIGURED" = "NO" ]
+ then
+ trap 'f_interrupt' SIGINT
+ if f_dialog_yesno "$msg_assume_network_is_already_configured"
+ then
+ setvar $VAR_NETWORK_DEVICE $dev
+ return $SUCCESS
+ fi
+ fi
+
+ local retval=$SUCCESS
+ if [ ${cnt:=0} -eq 0 ]; then
+ f_dialog_msgbox "$msg_no_network_devices"
+ retval=$FAILURE
+ elif [ $cnt -eq 1 ]; then
+ f_device_dialog_tcp $dev
+ retval=$?
+ [ $retval -eq $SUCCESS ] && setvar $VAR_NETWORK_DEVICE $dev
+ else
+ local title="$msg_network_interface_information_required"
+ local prompt="$msg_please_select_ethernet_device_to_configure"
+ local hline="$hline_arrows_tab_enter"
+
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_NETWORK \
+ "$NETWORK_DEVICE_HELPFILE" \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ retval=$?
+ [ "$dev" ] || return $FAILURE
+
+ f_device_find "$dev" $DEVICE_TYPE_NETWORK devs
+ [ "$devs" ] || return $FAILURE
+ dev="${devs%%[$IFS]*}"
+
+ f_device_dialog_tcp $dev
+ retval=$?
+ if [ $retval -eq $SUCCESS ]; then
+ f_struct_copy device_$dev device_network
+ setvar $VAR_NETWORK_DEVICE network
+ else
+ f_struct_free device_network
+ fi
+ fi
+
+ return $retval
+}
+
+# f_dialog_menu_select_tcp
+#
+# Like f_dialog_select_tcp() above, but do it from a menu that doesn't care
+# about status. In other words, where f_dialog_select_tcp() will not display a
+# menu if scripted, this function will always display the menu of available
+# network interfaces.
+#
+f_dialog_menu_select_tcp()
+{
+ local private use_dhcp name
+ NETWORK_CONFIGURED=NO f_device_select_tcp
+ if f_struct device_network &&
+ device_network get private private &&
+ f_struct_copy "$private" di &&
+ di get use_dhcp use_dhcp &&
+ [ ! "$use_dhcp" ] &&
+ device_network get name name &&
+ f_yesno "$msg_would_you_like_to_bring_interface_up" "$name"
+ then
+ if ! f_device_init network; then
+ f_show_msg "$msg_initialization_of_device_failed" \
+ "$name"
+ fi
+ fi
+ return $SUCCESS
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/tcpip.subr
+
+fi # ! $_MEDIA_TCPIP_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/ufs.subr b/usr.sbin/bsdconfig/share/media/ufs.subr
new file mode 100644
index 0000000..0b70f09
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/ufs.subr
@@ -0,0 +1,193 @@
+if [ ! "$_MEDIA_UFS_SUBR" ]; then _MEDIA_UFS_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/ufs.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+UFS_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_ufs
+#
+# Return success if we both found and set the media type to be a UFS partition.
+# Variables from variable.subr that can be used to script user input:
+#
+# VAR_UFS_PATH
+# Path to a UFS character device node to be used with mount(8) in
+# mounting a UFS formatted partition. Valid examples include:
+# /dev/da0s1a
+# /dev/ad4s1e
+# However, other forms may be valid (see mount(8) for additional
+# information).
+#
+f_media_set_ufs()
+{
+ local ufs
+
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_UFS devs
+ ndevs=$( set -- $devs; echo $# )
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_variable_get_value $VAR_UFS_PATH \
+ "$msg_enter_the_device_name_of_a_ufs_formatted_partition"
+ f_getvar $VAR_UFS_PATH ufs
+ [ "$ufs" ] || return $FAILURE
+
+ local fstype
+ fstype=$( df -nT $ufs 2> /dev/null |
+ awk '!/Type/{print $2;exit}' )
+
+ f_struct_new DEVICE device_ufs
+ device_ufs set name ${fstype:-ufs}
+ device_ufs set devname "$ufs"
+ device_ufs set get f_media_get_ufs
+ device_ufs set init f_media_init_ufs
+ device_ufs set shutdown f_media_shutdown_ufs
+ device_ufs unset private
+
+ f_struct_copy device_ufs device_media
+ f_struct_free device_ufs
+ elif [ $ndevs -gt 1 ]; then
+ local title="$msg_choose_a_ufs_partition"
+ local prompt="$msg_please_select_ufs_partition"
+ local hline=""
+
+ local dev retval
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_UFS \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ retval=$?
+ [ "$dev" ] || return $FAILURE
+
+ f_struct_copy device_$dev device_media
+ [ $retval -eq $SUCCESS ] || return $FAILURE
+ else
+ f_struct_copy device_$devs device_media
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_ufs $device
+#
+# Initializes the UFS media device. Returns success if able to mount the UFS
+# partition device using mount(1).
+#
+f_media_init_ufs()
+{
+ local dev="$1" devname err
+
+ device_$dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for UFS device. devname=[%s]" \
+ "$devname"
+
+ if [ "$UFS_MOUNTED" ]; then
+ f_dprintf "UFS device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$devname" ]; then
+ f_show_msg "$msg_no_such_file_or_directory" \
+ "f_media_init_ufs" "$devname"
+ return $FAILURE
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ] &&
+ ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
+ then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+
+ if ! err=$( mount "$devname" "$MOUNTPOINT" 2>&1 )
+ then
+ err="${err#mount: }"; err="${err#$devname : }"
+ f_show_msg "$msg_error_mounting_device" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+ fi
+ UFS_MOUNTED=1
+ return $SUCCESS
+}
+
+# f_media_get_ufs $device $file [$probe_only]
+#
+# Returns data from $file on a mounted UFS partition device. Similar to cat(1).
+# $probe_only is currently unused by this media type.
+#
+f_media_get_ufs()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_ufs: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ f_media_generic_get "$MOUNTPOINT" "$file"
+}
+
+# f_media_shutdown_ufs $device
+#
+# Shuts down the UFS device using umount(8). Return status should be ignored.
+#
+f_media_shutdown_ufs()
+{
+ local dev="$1" err
+
+ [ "$UFS_MOUNTED" ] || return
+
+ if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_ufs_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ UFS_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/ufs.subr
+
+fi # ! $_MEDIA_UFS_SUBR
diff --git a/usr.sbin/bsdconfig/share/media/usb.subr b/usr.sbin/bsdconfig/share/media/usb.subr
new file mode 100644
index 0000000..c7fc973
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/media/usb.subr
@@ -0,0 +1,174 @@
+if [ ! "$_MEDIA_USB_SUBR" ]; then _MEDIA_USB_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+f_dprintf "%s: loading includes..." media/usb.subr
+f_include $BSDCFG_SHARE/struct.subr
+f_include $BSDCFG_SHARE/device.subr
+f_include $BSDCFG_SHARE/dialog.subr
+f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/common.subr
+
+BSDCFG_LIBE="/usr/libexec/bsdconfig"
+f_include_lang $BSDCFG_LIBE/include/messages.subr
+
+############################################################ GLOBALS
+
+USB_MOUNTED=
+
+############################################################ FUNCTIONS
+
+# f_media_set_usb
+#
+# Attempt to use USB as the media type. Return success if we both found and set
+# the media type to be a USB drive.
+#
+f_media_set_usb()
+{
+ f_media_close
+
+ local devs ndevs
+ f_device_find "" $DEVICE_TYPE_USB devs
+ ndevs=$( set -- $devs; echo $# )
+
+ if [ ${ndevs:=0} -eq 0 ]; then
+ f_dialog_msgbox "$msg_no_usb_devices_found"
+ return $FAILURE
+ elif [ $ndevs -gt 1 ]; then
+ local title="$msg_choose_a_usb_drive"
+ local prompt="$msg_please_select_a_usb_drive"
+ local hline=""
+
+ local dev retval
+ dev=$( f_device_menu \
+ "$title" "$prompt" "$hline" $DEVICE_TYPE_USB \
+ 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
+ retval=$?
+ [ "$dev" ] || return $FAILURE
+
+ f_device_find "$dev" $DEVICE_TYPE_USB devs
+ [ "$devs" ] || return $FAILURE
+ dev="${devs%%[$IFS]*}"
+
+ f_struct_copy device_$dev device_media
+ [ $retval -eq $SUCCESS ] || return $FAILURE
+ else
+ f_struct_copy device_$devs device_media
+ fi
+
+ f_struct device_media &&
+ device_media unset private
+
+ if f_interactive; then
+ local name
+ f_struct device_media get name name
+ f_show_msg "$msg_using_usb_device" "$name"
+ fi
+
+ f_struct device_media || return $FAILURE
+}
+
+# f_media_init_usb $device
+#
+# Initializes the USB media device. Returns success if able to mount the USB
+# disk device using mount(8).
+#
+f_media_init_usb()
+{
+ local dev="$1" devname err
+
+ device_$dev get devname devname || return $FAILURE
+ f_dprintf "Init routine called for USB device. devname=[%s]" \
+ "$devname"
+
+ if [ "$USB_MOUNTED" ]; then
+ f_dprintf "USB device already mounted."
+ return $SUCCESS
+ fi
+
+ if [ ! -e "$MOUNTPOINT" ] &&
+ ! err=$( mkdir -p "$MOUNTPOINT" 2>&1 )
+ then
+ f_dialog_msgbox "$err"
+ return $FAILURE
+ fi
+
+ if err=$( mount "$devname" "$MOUNTPOINT" 2>&1 ); then
+ USB_MOUNTED=1
+ return $SUCCESS
+ fi
+
+ err="${err#mount: }"; err="${err#$devname: }"
+ f_show_msg "$msg_error_mounting_usb_drive" \
+ "$devname" "$MOUNTPOINT" "$err"
+ return $FAILURE
+}
+
+# f_media_get_usb $device $file [$probe_only]
+#
+# Returns data from $file on a mounted USB disk device. Similar to cat(1).
+# $probe_only is currently unused by this media type.
+#
+f_media_get_usb()
+{
+ local dev="$1" file="$2" probe_only="$3"
+
+ f_dprintf "f_media_get_usb: dev=[%s] file=[%s] probe_only=%s" \
+ "$dev" "$file" "$probe_only"
+
+ f_media_generic_get "$MOUNTPOINT" "$file"
+}
+
+# f_media_shutdown_usb $device
+#
+# Shuts down the USB disk device using umount(8). Return status should be
+# ignored.
+#
+f_media_shutdown_usb()
+{
+ local dev="$1" err
+
+ [ "$USB_MOUNTED" ] || return
+
+ if ! err=$( umount -f "$MOUNTPOINT" 2>&1 ); then
+ err="${err#umount: }"; err="${err#*: }"
+ f_show_msg "$msg_could_not_unmount_the_ufs_partition" \
+ "$MOUNTPOINT" "$err"
+ else
+ USB_MOUNTED=
+ fi
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." media/usb.subr
+
+fi # ! $_MEDIA_USB_SUBR
diff --git a/usr.sbin/bsdconfig/share/script.subr b/usr.sbin/bsdconfig/share/script.subr
index 84d1cab..3ea5dd5 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 Devin Teske
+# Copyright (c) 2012-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,10 @@ if [ ! "$_SCRIPT_SUBR" ]; then _SCRIPT_SUBR=1
BSDCFG_SHARE="/usr/share/bsdconfig"
. $BSDCFG_SHARE/common.subr || exit 1
f_dprintf "%s: loading includes..." script.subr
+f_include $BSDCFG_SHARE/device.subr
f_include $BSDCFG_SHARE/variable.subr
+f_include $BSDCFG_SHARE/media/any.subr
+f_include $BSDCFG_SHARE/media/tcpip.subr
############################################################ GLOBALS
@@ -75,11 +78,13 @@ f_dispatch()
local func="$1" resword="${2:-$1}"
f_dprintf "f_dispatch: calling resword \`%s'" "$resword"
eval $func
- local retval=$? _ignore_this_error
- f_getvar $VAR_NO_ERROR _ignore_this_error
- [ $retval -eq $SUCCESS ] ||
+ local retval=$?
+ if [ $retval -ne $SUCCESS ]; then
+ local _ignore_this_error
+ f_getvar $VAR_NO_ERROR _ignore_this_error
[ "$_ignore_this_error" ] || f_die $retval \
- "$msg_command_failed_rest_of_script_aborted" "$resword"
+ "$msg_command_failed_rest_of_script_aborted" "$resword"
+ fi
unset $VAR_NO_ERROR
}
@@ -146,8 +151,26 @@ f_script_load()
#
# Reserved words meant for scripting
#
+f_resword_new deviceRescan f_device_rescan
f_resword_new dumpVariables f_dump_variables
f_resword_new loadConfig f_script_load
+f_resword_new mediaClose f_media_close
+f_resword_new mediaGetType f_media_get_type
+f_resword_new mediaOpen f_media_open
+f_resword_new mediaSetCDROM f_media_set_cdrom
+f_resword_new mediaSetDOS f_media_set_dos
+f_resword_new mediaSetFTP f_media_set_ftp
+f_resword_new mediaSetFTPActive f_media_set_ftp_active
+f_resword_new mediaSetFTPPassive f_media_set_ftp_passive
+f_resword_new mediaSetFTPUserPass f_media_set_ftp_userpass
+f_resword_new mediaSetFloppy f_media_set_floppy
+f_resword_new mediaSetHTTP f_media_set_http_proxy
+f_resword_new mediaSetHTTPProxy f_media_set_http_proxy
+f_resword_new mediaSetNFS f_media_set_nfs
+f_resword_new mediaSetUFS f_media_set_ufs
+f_resword_new mediaSetUSB f_media_set_usb
+f_resword_new optionsEditor f_media_options_menu
+f_resword_new tcpMenuSelect f_dialog_menu_select_tcp
f_dprintf "%s: Successfully loaded." script.subr
diff --git a/usr.sbin/bsdconfig/share/strings.subr b/usr.sbin/bsdconfig/share/strings.subr
index 6fe0f32..5b9f51e 100644
--- a/usr.sbin/bsdconfig/share/strings.subr
+++ b/usr.sbin/bsdconfig/share/strings.subr
@@ -1,6 +1,6 @@
if [ ! "$_STRINGS_SUBR" ]; then _STRINGS_SUBR=1
#
-# Copyright (c) 2006-2012 Devin Teske
+# Copyright (c) 2006-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -101,6 +101,72 @@ f_isinteger()
( : $((0/$arg)) ) > /dev/null 2>&1
}
+# f_uriencode [$text]
+#
+# Encode $text for the purpose of embedding safely into a URL. Non-alphanumeric
+# characters are converted to `%XX' sequence where XX represents the hexa-
+# decimal ordinal of the non-alphanumeric character. If $text is missing, data
+# is instead read from standard input.
+#
+f_uriencode_awk='
+BEGIN {
+ output = ""
+ for (n = 0; n < 256; n++) pack[sprintf("%c", n)] = sprintf("%%%02x", n)
+}
+{
+ sline = ""
+ slen = length($0)
+ for (n = 1; n <= slen; n++) {
+ char = substr($0, n, 1)
+ if ( char !~ /^[[:alnum:]_]$/ ) char = pack[char]
+ sline = sline char
+ }
+ output = output ( output ? "%0a" : "" ) sline
+}
+END { print output }
+'
+f_uriencode()
+{
+ if [ $# -gt 0 ]; then
+ echo "$1" | awk "$f_uriencode_awk"
+ else
+ awk "$f_uriencode_awk"
+ fi
+}
+
+# f_uridecode [$text]
+#
+# Decode $text from a URI. Encoded characters are converted from their `%XX'
+# sequence into original unencoded ASCII sequences. If $text is missing, data
+# is instead read from standard input.
+#
+f_uridecode_awk='
+BEGIN { for (n = 0; n < 256; n++) chr[n] = sprintf("%c", n) }
+{
+ sline = ""
+ slen = length($0)
+ for (n = 1; n <= slen; n++)
+ {
+ seq = substr($0, n, 3)
+ if ( seq ~ /^%[[:xdigit:]][[:xdigit:]]$/ ) {
+ hex = substr(seq, 2, 2)
+ sline = sline chr[sprintf("%u", "0x"hex)]
+ n += 2
+ } else
+ sline = sline substr(seq, 1, 1)
+ }
+ print sline
+}
+'
+f_uridecode()
+{
+ if [ $# -gt 0 ]; then
+ echo "$1" | awk "$f_uridecode_awk"
+ else
+ awk "$f_uridecode_awk"
+ fi
+}
+
f_dprintf "%s: Successfully loaded." strings.subr
fi # ! $_STRINGS_SUBR
diff --git a/usr.sbin/bsdconfig/share/struct.subr b/usr.sbin/bsdconfig/share/struct.subr
new file mode 100644
index 0000000..3c6f90f
--- /dev/null
+++ b/usr.sbin/bsdconfig/share/struct.subr
@@ -0,0 +1,206 @@
+if [ ! "$_STRUCT_SUBR" ]; then _STRUCT_SUBR=1
+#
+# Copyright (c) 2012-2013 Devin Teske
+# All Rights Reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+############################################################ INCLUDES
+
+BSDCFG_SHARE="/usr/share/bsdconfig"
+. $BSDCFG_SHARE/common.subr || exit 1
+
+############################################################ FUNCTIONS
+
+# f_struct_define $type $member_name1 ...
+#
+# Define a new `structure' type $type made up of the properties $member_name1
+# $member_name2 and so-on. Properties are not typed and can hold any type of
+# data (including names of other structs).
+#
+# Before creating instances of a struct (using f_struct_new $type $name) you
+# should use this function to define $type.
+#
+# Both $type and member names should consist only of alpha-numeric letters or
+# the underscore.
+#
+f_struct_define()
+{
+ local type="$1"
+ [ "$type" ] || return $FAILURE
+ shift
+ setvar "_struct_typedef_$type" "$*"
+}
+
+# f_struct_new $type $name
+#
+# Create a new `structure' named $name of type $type. There are two ways to
+# access properties of a struct, but they are not equal (each method has its
+# own unique benefits, discussed below).
+#
+# The primary method of accessing (both setting and getting) properties of any
+# struct is through the f_struct() function below.
+#
+# The secondary method of accessing data is by using $name as a function.
+#
+# Both access methods are cross-platform compatible with any version of sh(1).
+# Below is an example of the primary access method:
+#
+# f_struct_new MY_STRUCT_TYPE my_struct
+# f_struct my_struct set abc 123
+# f_struct my_struct get abc # prints 123 to stdout
+# f_struct my_struct get abc abc # sets local variable $abc to 123
+#
+# Alternatively, the secondary access method (details below):
+#
+# f_struct_new MY_STRUCT_TYPE my_struct
+# my_struct set abc 123
+# my_struct get abc # prints 123 to stdout
+# my_struct get abc abc # sets local variable $abc to 123
+#
+# The secondary form should only be used if/when:
+# + You are certain that the structure already exists
+# + You want a syntax error if/when the struct does not exist
+#
+# The primary benefit to the secondary form is syntax cleanliness and read-
+# ability. If you are unsure if a given struct exists (which would cause a
+# syntax error when using this form), you can use the primary access method to
+# first test for the existence of the struct. For example:
+#
+# if f_struct my_struct; then
+# my_struct get abc # only executed if my_struct exists
+# fi
+#
+# For more information, see the f_struct() function.
+#
+f_struct_new()
+{
+ local type="$1" name="$2"
+ f_dprintf "f_struct_new: type=[%s] name=[%s]" "$type" "$name"
+ [ "$name" ] || return $FAILURE
+ setvar "_struct_type_$name" "$type" || return $FAILURE
+ # OK to use bare $name at this point
+ eval $name\(\){ f_struct $name \"\$@\"\; }
+}
+
+# f_struct $name
+# f_struct $name get $property [$var_to_set]
+# f_struct $name set $property $new_value
+# f_struct $name unset $property
+#
+# Access routine for getting, setting, unsetting, and testing properties of
+# `structures'.
+#
+# If only given $name, returns success if struct $name has been created (using
+# the f_struct_new() function above).
+#
+# For getting properties of a struct (versus setting) there are two methods of
+# access. If $var_to_set is missing or NULL, the value of the property is
+# printed to standard output for capturing in a sub-shell (which is less-
+# recommended because of performance degredation; for example, when called in a
+# loop). Returns success unless the property is unset.
+#
+# For setting properties of a struct, sets the value of $property to $new_value
+# and returns success.
+#
+# For unsetting, the underlying environment variable associated with the given
+# $property is unset.
+#
+f_struct()
+{
+ local __name="$1" __action="$2" __property="$3"
+ case $# in
+ 0) return $FAILURE ;;
+ 1) f_have $__name ;;
+ *) case "$__action" in
+ get) local __var_to_set="$4"
+ f_getvar "_struct_value_${__name}_$__property" "$__var_to_set"
+ ;;
+ set) local new_value="$4"
+ setvar "_struct_value_${__name}_$__property" "$new_value" ;;
+ unset) unset "_struct_value_${__name}_$__property" ;;
+ esac
+ esac
+ # Return the status of the last command above
+}
+
+# f_struct_free $name
+#
+# Unset the collection of environment variables and accessor-function
+# associated with struct $name.
+#
+f_struct_free()
+{
+ local name="$1" type member members
+ f_getvar "_struct_type_$name" type
+ f_dprintf "f_struct_free: name=[%s] type=[%s]" "$name" "$type"
+ [ "$name" ] || return $FAILURE
+ f_getvar "_struct_typedef_$type" members
+ for member in $members; do
+ f_struct "$name" unset $member
+ done
+ unset -f "$name"
+ unset "_struct_type_$name"
+}
+
+# f_struct_copy $from_name $to_name
+#
+# Copy the properties of one struct to another. If struct $to_name does not
+# exist, it is created. If struct $from_name does not exist, nothing is done
+# and struct $to_name remains unmodified.
+#
+# Returns success unless struct $to_name did not exist and f_struct_new() was
+# unable to create it.
+#
+f_struct_copy()
+{
+ local from_name="$1" to_name="$2" type
+ f_dprintf "f_struct_copy: from_name=[%s] to_name=[%s]" \
+ "$from_name" "$to_name"
+ f_getvar "_struct_type_$from_name" type
+ f_struct "$to_name" ||
+ f_struct_new "$type" "$to_name" || return $FAILURE
+ f_struct "$from_name" || return $SUCCESS
+ f_dprintf "f_struct_copy: copying properties from %s to %s" \
+ "$from_name" "$to_name"
+ local property properties from_value n=0 k=0
+ f_getvar "_struct_typedef_$type" properties
+ for property in $properties; do
+ k=$(( $k + 1 ))
+ if f_struct "$from_name" get $property from_value; then
+ f_struct "$to_name" set $property "$from_value"
+ n=$(( $n + 1 ))
+ else
+ f_struct "$to_name" unset $property
+ fi
+ done
+ f_dprintf "f_struct_copy: copied %u of %u properties from %s to %s" \
+ "$n" "$k" "$from_name" "$to_name"
+}
+
+############################################################ MAIN
+
+f_dprintf "%s: Successfully loaded." struct.subr
+
+fi # ! $_STRUCT_SUBR
diff --git a/usr.sbin/bsdconfig/share/variable.subr b/usr.sbin/bsdconfig/share/variable.subr
index 235f6dc..7a066421 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 Devin Teske
+# Copyright (c) 2012-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -109,7 +109,15 @@ f_variable_set_defaults()
#
# Initialize various user-edittable values to their defaults
#
- setvar $VAR_RELNAME "$UNAME_R"
+ setvar $VAR_EDITOR "${EDITOR:-/usr/bin/ee}"
+ setvar $VAR_FTP_STATE "passive"
+ setvar $VAR_FTP_USER "ftp"
+ setvar $VAR_HOSTNAME "$( hostname )"
+ setvar $VAR_MEDIA_TIMEOUT "300"
+ setvar $VAR_NFS_SECURE "NO"
+ setvar $VAR_NFS_TCP "NO"
+ setvar $VAR_NFS_V3 "YES"
+ setvar $VAR_RELNAME "$UNAME_R"
f_dprintf "f_variable_set_defaults: Defaults initialized."
}
@@ -158,17 +166,71 @@ f_interactive()
! f_getvar $VAR_NONINTERACTIVE value || [ ! "$value" ]
}
+# f_netinteractive()
+#
+# Has the user specifically requested the network-portion of configuration and
+# setup to be performed interactively? Returns success if the user has asked
+# for the network configuration to be done interactively even if perhaps over-
+# all non-interactive mode has been requested (by setting nonInteractive).
+#
+# Returns success if $netInteractive is set and non-NULL.
+#
+f_netinteractive()
+{
+ local value
+ f_getvar $VAR_NETINTERACTIVE value && [ "$value" ]
+}
+
############################################################ MAIN
#
# Variables that can be tweaked from config files
#
+# Handle Variable Name
f_variable_new VAR_CONFIG_FILE configFile
f_variable_new VAR_DEBUG debug
f_variable_new VAR_DEBUG_FILE debugFile
-f_variable_new VAR_NO_ERROR noError
+f_variable_new VAR_DIRECTORY_PATH _directoryPath
+f_variable_new VAR_DOMAINNAME domainname
+f_variable_new VAR_EDITOR editor
+f_variable_new VAR_EXTRAS ifconfig_
+f_variable_new VAR_FTP_DIR ftpDirectory
+f_variable_new VAR_FTP_HOST ftpHost
+f_variable_new VAR_FTP_PASS ftpPass
+f_variable_new VAR_FTP_PATH _ftpPath
+f_variable_new VAR_FTP_PORT ftpPort
+f_variable_new VAR_FTP_STATE ftpState
+f_variable_new VAR_FTP_USER ftpUser
+f_variable_new VAR_GATEWAY defaultrouter
+f_variable_new VAR_HOSTNAME hostname
+f_variable_new VAR_HTTP_FTP_MODE httpFtpMode
+f_variable_new VAR_HTTP_PROXY httpProxy
+f_variable_new VAR_HTTP_PROXY_HOST httpProxyHost
+f_variable_new VAR_HTTP_PROXY_PATH _httpProxyPath
+f_variable_new VAR_HTTP_PROXY_PORT httpProxyPort
+f_variable_new VAR_IFCONFIG ifconfig_
+f_variable_new VAR_IPADDR ipaddr
+f_variable_new VAR_IPV6ADDR ipv6addr
+f_variable_new VAR_IPV6_ENABLE ipv6_activate_all_interfaces
+f_variable_new VAR_MEDIA_TIMEOUT MEDIA_TIMEOUT
+f_variable_new VAR_MEDIA_TYPE mediaType
+f_variable_new VAR_NAMESERVER nameserver
+f_variable_new VAR_NETINTERACTIVE netInteractive
+f_variable_new VAR_NETMASK netmask
+f_variable_new VAR_NETWORK_DEVICE netDev
+f_variable_new VAR_NFS_HOST nfsHost
+f_variable_new VAR_NFS_PATH nfsPath
+f_variable_new VAR_NFS_SECURE nfs_reserved_port_only
+f_variable_new VAR_NFS_TCP nfs_use_tcp
+f_variable_new VAR_NFS_V3 nfs_use_v3
f_variable_new VAR_NONINTERACTIVE nonInteractive
+f_variable_new VAR_NO_ERROR noError
+f_variable_new VAR_NO_INET6 noInet6
f_variable_new VAR_RELNAME releaseName
+f_variable_new VAR_SLOW_ETHER slowEthernetCard
+f_variable_new VAR_TRY_DHCP tryDHCP
+f_variable_new VAR_TRY_RTSOL tryRTSOL
+f_variable_new VAR_UFS_PATH ufs
#
# Self-initialize unless requested otherwise
diff --git a/usr.sbin/bsdconfig/startup/rcvar b/usr.sbin/bsdconfig/startup/rcvar
index d7ced9e..d655e61 100755
--- a/usr.sbin/bsdconfig/startup/rcvar
+++ b/usr.sbin/bsdconfig/startup/rcvar
@@ -1,6 +1,6 @@
#!/bin/sh
#-
-# Copyright (c) 2012 Devin Teske
+# Copyright (c) 2012-2013 Devin Teske
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -75,7 +75,7 @@ dialog_menu_main()
" # END-QUOTE
if [ ! "$_RCVAR_MAP" ]; then
- # Genreate RCVAR_MAP of `rcvar dflt script desc ...' per-line
+ # Generate RCVAR_MAP of `rcvar dflt script desc ...' per-line
f_dialog_info "$msg_creating_rcvar_map"
RCVAR_MAP=$( f_startup_rcvar_map )
export RCVAR_MAP
diff --git a/usr.sbin/bsdinstall/distextract/distextract.c b/usr.sbin/bsdinstall/distextract/distextract.c
index 0afe761..a35dbd6 100644
--- a/usr.sbin/bsdinstall/distextract/distextract.c
+++ b/usr.sbin/bsdinstall/distextract/distextract.c
@@ -126,7 +126,7 @@ count_files(const char *file)
/* Either we didn't have a manifest, or this archive wasn't there */
archive = archive_read_new();
archive_read_support_format_all(archive);
- archive_read_support_compression_all(archive);
+ archive_read_support_filter_all(archive);
sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), file);
err = archive_read_open_filename(archive, path, 4096);
if (err != ARCHIVE_OK) {
@@ -188,7 +188,7 @@ extract_files(int nfiles, const char **files)
for (i = 0; i < nfiles; i++) {
archive = archive_read_new();
archive_read_support_format_all(archive);
- archive_read_support_compression_all(archive);
+ archive_read_support_filter_all(archive);
sprintf(path, "%s/%s", getenv("BSDINSTALL_DISTDIR"), files[i]);
err = archive_read_open_filename(archive, path, 4096);
diff --git a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c
index ee8bdcc..ced7e8d 100644
--- a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c
+++ b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_storage_tbl.c
@@ -442,10 +442,9 @@ static void
storage_OS_get_fs(void)
{
struct storage_entry *entry;
- uint64_t used_blocks_count = 0;
+ uint64_t size, used;
+ int i, mounted_fs_count, units;
char fs_string[SE_DESC_MLEN];
- int mounted_fs_count;
- int i = 0;
if ((mounted_fs_count = getfsstat(NULL, 0, MNT_NOWAIT)) < 0) {
syslog(LOG_ERR, "hrStorageTable: getfsstat() failed: %m");
@@ -488,22 +487,17 @@ storage_OS_get_fs(void)
entry->flags |= HR_STORAGE_FOUND;
entry->type = fs_get_type(&fs_buf[i]); /*XXX - This is wrong*/
- if (fs_buf[i].f_bsize > INT_MAX)
- entry->allocationUnits = INT_MAX;
- else
- entry->allocationUnits = fs_buf[i].f_bsize;
-
- if (fs_buf[i].f_blocks > INT_MAX)
- entry->size = INT_MAX;
- else
- entry->size = fs_buf[i].f_blocks;
-
- used_blocks_count = fs_buf[i].f_blocks - fs_buf[i].f_bfree;
-
- if (used_blocks_count > INT_MAX)
- entry->used = INT_MAX;
- else
- entry->used = used_blocks_count;
+ units = fs_buf[i].f_bsize;
+ size = fs_buf[i].f_blocks;
+ used = fs_buf[i].f_blocks - fs_buf[i].f_bfree;
+ while (size > INT_MAX) {
+ units <<= 1;
+ size >>= 1;
+ used >>= 1;
+ }
+ entry->allocationUnits = units;
+ entry->size = size;
+ entry->used = used;
entry->allocationFailures = 0;
diff --git a/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1 b/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
index 57a85d6..16eec25 100644
--- a/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
+++ b/usr.sbin/bsnmpd/tools/bsnmptools/bsnmpget.1
@@ -108,7 +108,7 @@ Depending on the options
.Nm bsnmpget
constructs either a SMNP GetRequest, GetNextRequest
or a GetBulkRequest packet, fills in the object identifiers (OIDs) of the
-objects whose values will be retrived, waits for a response and prints it if
+objects whose values will be retrieved, waits for a response and prints it if
received successfully.
.Pp
.Nm Bsnmpwalk
@@ -259,7 +259,7 @@ for
and getnext for
.Nm bsnmpwalk .
Getbulk allows executing the so called SNMP "bulkwalks" allowing the values of
-multiple columns to be retrived in a single PDU by
+multiple columns to be retrieved in a single PDU by
.Nm bsnmpwalk .
.It Fl r Ar retries
Number of resends of request packets before giving up if the agent does
@@ -332,7 +332,7 @@ 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.
.It OID
-The object identifier whose value to retrive.
+The object identifier whose value to retrieve.
At least one OID should be provided for
.Nm bsnmpget
to be able to send a request.
@@ -340,7 +340,7 @@ to be able to send a request.
For
.Nm bsnmpwalk
this is the root object identifier of the subtree whose values are to be
-retrived.
+retrieved.
If no OID is provided
.Nm bsnmpwalk
will walk the mib2 subtree rooted
diff --git a/usr.sbin/burncd/Makefile b/usr.sbin/burncd/Makefile
deleted file mode 100644
index 11e07c7..0000000
--- a/usr.sbin/burncd/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# $FreeBSD$
-
-PROG= burncd
-MAN= burncd.8
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/burncd/Makefile.depend b/usr.sbin/burncd/Makefile.depend
deleted file mode 100644
index 26cf195..0000000
--- a/usr.sbin/burncd/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/burncd/burncd.8 b/usr.sbin/burncd/burncd.8
deleted file mode 100644
index ae9ffd9..0000000
--- a/usr.sbin/burncd/burncd.8
+++ /dev/null
@@ -1,249 +0,0 @@
-.\"
-.\" Copyright (c) 2000,2001,2002 Søren Schmidt <sos@FreeBSD.org>
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer,
-.\" without modification, immediately at the beginning of the file.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. The name of the author may not be used to endorse or promote products
-.\" derived from this software without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd October 9, 2011
-.Dt BURNCD 8
-.Os
-.Sh NAME
-.Nm burncd
-.Nd control the ATAPI CD-R/RW driver
-.Pp
-This utility was
-.Em deprecated
-in
-.Fx 9.0 .
-See
-.Sx NOTES .
-.Sh SYNOPSIS
-.Nm
-.Op Fl deFlmnpqtv
-.Op Fl f Ar device
-.Op Fl s Ar speed
-.Op Ar command
-.Op Ar command Ar
-.Sh DESCRIPTION
-The
-.Nm
-utility is used to burn CD-R/RW media using the ATAPI cd driver.
-.Pp
-Available options and operands:
-.Bl -tag -width XXXXXXXXXXXX
-.It Fl d
-burn the CD-R/RW in DAO (disk at once) mode.
-.It Fl e
-eject the medium when done.
-.It Fl f Ar device
-set the device to use for the burning process.
-.It Fl F
-force operation regardless of warnings.
-.It Fl l
-read a list of image files from filename.
-.It Fl m
-close disk in multisession mode (otherwise disk is closed as singlesession).
-.It Fl n
-do not write gaps between data tracks in DAO mode.
-.It Fl p
-use preemphasis on audio tracks.
-.It Fl q
-quiet, do not print progress messages.
-.It Fl s Ar speed
-set the speed of the burner device.
-Defaults to 4.
-Specify
-.Dq Li max
-to use the drive's fastest speed.
-.It Fl t
-test write, do not actually write on the media.
-.It Fl v
-verbose, print extra progress messages.
-.El
-.Pp
-.Ar command
-may be one of:
-.Bl -tag -width XXXXXXXXXXXX
-.It Cm msinfo
-Show the first LBA of the last track on the media
-and the next writeable address on the media for use with the
-.Xr mkisofs 8 Ns 's Pq Pa ports/sysutils/cdrtools
-.Fl C
-switch when adding additional data to ISO file systems with extra sessions.
-.It Cm blank
-Blank a CD-RW medium.
-This uses the fast blanking method, so data are not physically overwritten,
-only those areas that make the media appear blank for further usage are erased.
-.It Cm eject
-Eject the medium when done.
-This is equivalent to the
-.Fl e
-option.
-.It Cm erase
-Erase a CD-RW medium.
-This erases the entire media.
-Can take up to 1 hour to finish.
-.It Cm format Brq Cm dvd+rw | dvd-rw
-Formats a DVD+RW or DVD-RW media to the default max size and 2048 byte blocks.
-This operation can take a long time to finish.
-Progress reporting is done during the process.
-.It Cm fixate
-Fixate the medium so that the TOC is generated and the media can be used
-in an ordinary CD drive.
-The driver defaults to creating singlesession media (see
-.Fl m
-option).
-Ignored in DAO mode (see
-.Fl d
-option).
-.It Cm raw | audio
-Set the write mode to produce audio (raw mode) tracks for the following
-images on the command line.
-.It Cm data | mode1
-Set the write mode to produce data (mode1) tracks for the following
-image files
-on the command line.
-.It Cm mode2
-Set the write mode to produce data (mode2) tracks for the following
-image files
-on the command line.
-.It Cm XAmode1
-Set the write mode to produce data (XAmode1) tracks for the following image
-files on the command line.
-.It Cm XAmode2
-Set the write mode to produce data (XAmode2) tracks for the following image
-files on the command line.
-.It Cm vcd
-Set the write mode to produce VCD/SVCD tracks for the following image files
-on the command line.
-This automatically sets DAO
-.Pq Fl d
-and
-.Dq "no gaps"
-.Pq Fl n
-modes.
-.It Cm dvdrw
-Set the write mode to write a DVD+RW from the following image.
-DVDs only have one track.
-.It Ar file
-All other arguments are treated as filenames of images to write to the media,
-or in case the
-.Fl l
-option is used as files containing lists of images.
-.El
-.Pp
-Files whose length are not a multiple of the current media blocksize are
-quietly zero padded to fit the blocksize requirement.
-The conventional filename
-.Fl
-refers to stdin, and can only be used once.
-.Sh ENVIRONMENT
-The following environment variables affect the execution of
-.Nm :
-.Bl -tag -width ".Ev BURNCD_SPEED"
-.It Ev BURNCD_SPEED
-The write speed to use if one is not specified with the
-.Fl s
-flag.
-.It Ev CDROM
-The CD device to use if one is not specified with the
-.Fl f
-flag.
-.El
-.Sh FILES
-.Bl -tag -width ".Pa /dev/acd0"
-.It Pa /dev/acd0
-The default device, if not overridden by the
-.Ev CDROM
-environment variable or the
-.Fl f
-option.
-.El
-.Sh EXAMPLES
-The typical usage for burning a data CD-R:
-.Pp
-.Dl "burncd -f /dev/acd0 data file1 fixate"
-.Pp
-The typical usage for burning an audio CD-R:
-.Pp
-.Dl "burncd -f /dev/acd0 audio file1 file2 file3 fixate"
-.Pp
-The typical usage for burning an audio CD-R in DAO mode:
-.Pp
-.Dl "burncd -f /dev/acd0 -d audio file1 file2 file3"
-.Pp
-The typical usage for burning a mixed mode CD-R:
-.Pp
-.Dl "burncd -f /dev/acd0 data file1 audio file2 file3 fixate"
-.Pp
-The typical usage for burning from a compressed image file on stdin:
-.Pp
-.Dl "gunzip -c file.iso.gz | burncd -f /dev/acd0 data - fixate"
-.Pp
-In the examples above, the files burned to data CD-Rs are assumed to
-be ISO9660 file systems.
-.Xr mkisofs 8 ,
-available in the
-.Fx
-Ports Collection,
-as part of the
-.Pa sysutils/cdrtools
-port, is commonly used to create ISO9660 file system images
-from a given directory tree.
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Fx 4.0 .
-.Pp
-.Nm
-was deprecated in
-.Fx 9.0 .
-.Sh AUTHORS
-The
-.Nm
-utility and this manpage was contributed by
-.An S\(/oren Schmidt ,
-Denmark
-.Aq sos@FreeBSD.org .
-.Sh BUGS
-Probably, please report when found.
-.Sh NOTES
-When
-.Bd -ragged -offset indent
-.Cd "options ATA_CAM"
-.Ed
-.Pp
-is compiled into the kernel, then
-.Xr cdrecord 1 ,
-available in the
-.Fx
-Ports Collection as part of the
-.Pa sysutils/cdrtools
-port, must be used instead.
-Refer to:
-.Pp
-http://www.freebsd.org/doc/handbook/creating-cds.html#CDRECORD
diff --git a/usr.sbin/burncd/burncd.c b/usr.sbin/burncd/burncd.c
deleted file mode 100644
index c8b22ac..0000000
--- a/usr.sbin/burncd/burncd.c
+++ /dev/null
@@ -1,748 +0,0 @@
-/*-
- * Copyright (c) 2000,2001,2002 Søren Schmidt <sos@freebsd.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer,
- * without modification, immediately at the beginning of the file.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#include <unistd.h>
-#include <signal.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <err.h>
-#include <sysexits.h>
-#include <fcntl.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/cdio.h>
-#include <sys/cdrio.h>
-#include <sys/dvdio.h>
-#include <sys/param.h>
-#include <arpa/inet.h>
-
-#define BLOCKS 16
-
-struct track_info {
- int file;
- char file_name[MAXPATHLEN + 1];
- off_t file_size;
- int block_size;
- int block_type;
- int pregap;
- int addr;
-};
-static struct track_info tracks[100];
-static int quiet, verbose, saved_block_size, notracks;
-static volatile sig_atomic_t global_fd_for_cleanup;
-
-void add_track(char *, int, int, int);
-void do_DAO(int fd, int, int);
-void do_TAO(int fd, int, int, int);
-void do_format(int, int, char *);
-int write_file(int fd, struct track_info *);
-int roundup_blocks(struct track_info *);
-void cue_ent(struct cdr_cue_entry *, int, int, int, int, int, int, int);
-void cleanup(int);
-void cleanup_flush(void);
-void cleanup_signal(int);
-void usage(void);
-
-int
-main(int argc, char **argv)
-{
- int arg, addr, ch, fd;
- int dao = 0, eject = 0, fixate = 0, list = 0, multi = 0, preemp = 0;
- int nogap = 0, speed = 4 * 177, test_write = 0, force = 0;
- int block_size = 0, block_type = 0, cdopen = 0, dvdrw = 0;
- const char *dev, *env_speed;
-
- if (feature_present("ata_cam")) {
- errx(1, "\nATA_CAM option is enabled in kernel.\n"
- "Install the sysutils/cdrtools port and use cdrecord instead.\n\n"
- "Please refer to:\n"
- "http://www.freebsd.org/doc/handbook/creating-cds.html#CDRECORD");
- }
-
- if ((dev = getenv("CDROM")) == NULL)
- dev = "/dev/acd0";
-
- env_speed = getenv("BURNCD_SPEED");
-
- while ((ch = getopt(argc, argv, "def:Flmnpqs:tv")) != -1) {
- switch (ch) {
- case 'd':
- dao = 1;
- break;
-
- case 'e':
- eject = 1;
- break;
-
- case 'f':
- dev = optarg;
- break;
-
- case 'F':
- force = 1;
- break;
-
- case 'l':
- list = 1;
- break;
-
- case 'm':
- multi = 1;
- break;
-
- case 'n':
- nogap = 1;
- break;
-
- case 'p':
- preemp = 1;
- break;
-
- case 'q':
- quiet = 1;
- break;
-
- case 's':
- env_speed = optarg;
- break;
-
- case 't':
- test_write = 1;
- break;
-
- case 'v':
- verbose = 1;
- break;
-
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (env_speed == NULL)
- ;
- else if (strcasecmp("max", env_speed) == 0)
- speed = CDR_MAX_SPEED;
- else
- speed = atoi(env_speed) * 177;
- if (speed <= 0)
- errx(EX_USAGE, "Invalid speed: %s", env_speed);
-
- if (argc == 0)
- usage();
-
- if ((fd = open(dev, O_RDWR, 0)) < 0)
- err(EX_NOINPUT, "open(%s)", dev);
-
- if (ioctl(fd, CDRIOCGETBLOCKSIZE, &saved_block_size) < 0)
- err(EX_IOERR, "ioctl(CDRIOCGETBLOCKSIZE)");
-
- if (ioctl(fd, CDRIOCWRITESPEED, &speed) < 0)
- err(EX_IOERR, "ioctl(CDRIOCWRITESPEED)");
-
- global_fd_for_cleanup = fd;
- err_set_exit(cleanup);
- signal(SIGHUP, cleanup_signal);
- signal(SIGINT, cleanup_signal);
- signal(SIGTERM, cleanup_signal);
-
- for (arg = 0; arg < argc; arg++) {
- if (!strcasecmp(argv[arg], "fixate")) {
- fixate = 1;
- continue;
- }
- if (!strcasecmp(argv[arg], "eject")) {
- eject = 1;
- break;
- }
- if (!strcasecmp(argv[arg], "msinfo")) {
- struct ioc_read_toc_single_entry entry;
- struct ioc_toc_header header;
-
- if (ioctl(fd, CDIOREADTOCHEADER, &header) < 0)
- err(EX_IOERR, "ioctl(CDIOREADTOCHEADER)");
- bzero(&entry, sizeof(struct ioc_read_toc_single_entry));
- entry.address_format = CD_LBA_FORMAT;
- entry.track = header.ending_track;
- if (ioctl(fd, CDIOREADTOCENTRY, &entry) < 0)
- err(EX_IOERR, "ioctl(CDIOREADTOCENTRY)");
- if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &addr) < 0)
- err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
- fprintf(stdout, "%d,%d\n",
- ntohl(entry.entry.addr.lba), addr);
-
- break;
- }
- if ((!strcasecmp(argv[arg], "erase") ||
- !strcasecmp(argv[arg], "blank")) && !test_write) {
- int blank, pct, last = 0;
-
- if (!strcasecmp(argv[arg], "erase"))
- blank = CDR_B_ALL;
- else
- blank = CDR_B_MIN;
- if (!quiet)
- fprintf(stderr, "%sing CD, please wait..\r",
- blank == CDR_B_ALL ? "eras" : "blank");
-
- if (ioctl(fd, CDRIOCBLANK, &blank) < 0)
- err(EX_IOERR, "ioctl(CDRIOCBLANK)");
- while (1) {
- sleep(1);
- if (ioctl(fd, CDRIOCGETPROGRESS, &pct) == -1)
- err(EX_IOERR,"ioctl(CDRIOGETPROGRESS)");
- if (pct > 0 && !quiet)
- fprintf(stderr,
- "%sing CD - %d %% done \r",
- blank == CDR_B_ALL ?
- "eras" : "blank", pct);
- if (pct == 100 || (pct == 0 && last > 90))
- break;
- last = pct;
- }
- if (!quiet)
- printf("\n");
- continue;
- }
- if (!strcasecmp(argv[arg], "format") && !test_write) {
- if (arg + 1 < argc &&
- (!strcasecmp(argv[arg + 1], "dvd+rw") ||
- !strcasecmp(argv[arg + 1], "dvd-rw")))
- do_format(fd, force, argv[arg + 1]);
- else
- errx(EX_NOINPUT, "format media type invalid");
- arg++;
- continue;
- }
- if (!strcasecmp(argv[arg], "audio") || !strcasecmp(argv[arg], "raw")) {
- block_type = CDR_DB_RAW;
- block_size = 2352;
- continue;
- }
- if (!strcasecmp(argv[arg], "data") || !strcasecmp(argv[arg], "mode1")) {
- block_type = CDR_DB_ROM_MODE1;
- block_size = 2048;
- continue;
- }
- if (!strcasecmp(argv[arg], "mode2")) {
- block_type = CDR_DB_ROM_MODE2;
- block_size = 2336;
- continue;
- }
- if (!strcasecmp(argv[arg], "xamode1")) {
- block_type = CDR_DB_XA_MODE1;
- block_size = 2048;
- continue;
- }
- if (!strcasecmp(argv[arg], "xamode2")) {
- block_type = CDR_DB_XA_MODE2_F2;
- block_size = 2324;
- continue;
- }
- if (!strcasecmp(argv[arg], "vcd")) {
- block_type = CDR_DB_XA_MODE2_F2;
- block_size = 2352;
- dao = 1;
- nogap = 1;
- continue;
- }
- if (!strcasecmp(argv[arg], "dvdrw")) {
- block_type = CDR_DB_ROM_MODE1;
- block_size = 2048;
- dvdrw = 1;
- continue;
- }
-
- if (!block_size)
- errx(EX_NOINPUT, "no data format selected");
- if (list) {
- char file_buf[MAXPATHLEN + 1], *eol;
- FILE *fp;
-
- if ((fp = fopen(argv[arg], "r")) == NULL)
- err(EX_NOINPUT, "fopen(%s)", argv[arg]);
-
- while (fgets(file_buf, sizeof(file_buf), fp) != NULL) {
- if (*file_buf == '#' || *file_buf == '\n')
- continue;
- if ((eol = strchr(file_buf, '\n')))
- *eol = '\0';
- add_track(file_buf, block_size, block_type, nogap);
- }
- if (feof(fp))
- fclose(fp);
- else
- err(EX_IOERR, "fgets(%s)", file_buf);
- }
- else
- add_track(argv[arg], block_size, block_type, nogap);
- }
- if (notracks) {
- if (dvdrw && notracks > 1)
- errx(EX_USAGE, "DVD's only have 1 track");
- if (ioctl(fd, CDIOCSTART, 0) < 0)
- err(EX_IOERR, "ioctl(CDIOCSTART)");
- if (!cdopen) {
- if (ioctl(fd, CDRIOCINITWRITER, &test_write) < 0)
- err(EX_IOERR, "ioctl(CDRIOCINITWRITER)");
- cdopen = 1;
- }
- if (dao)
- do_DAO(fd, test_write, multi);
- else
- do_TAO(fd, test_write, preemp, dvdrw);
- }
- if (!test_write && fixate && !dao && !dvdrw) {
- if (!quiet)
- fprintf(stderr, "fixating CD, please wait..\n");
- if (ioctl(fd, CDRIOCFIXATE, &multi) < 0)
- err(EX_IOERR, "ioctl(CDRIOCFIXATE)");
- }
-
- if (ioctl(fd, CDRIOCSETBLOCKSIZE, &saved_block_size) < 0) {
- err_set_exit(NULL);
- err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
- }
-
- if (eject)
- if (ioctl(fd, CDIOCEJECT) < 0)
- err(EX_IOERR, "ioctl(CDIOCEJECT)");
-
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- close(fd);
- exit(EX_OK);
-}
-
-void
-add_track(char *name, int block_size, int block_type, int nogap)
-{
- struct stat sb;
- int file;
- static int done_stdin = 0;
-
- if (!strcmp(name, "-")) {
- if (done_stdin) {
- warn("skipping multiple usages of stdin");
- return;
- }
- file = STDIN_FILENO;
- done_stdin = 1;
- }
- else if ((file = open(name, O_RDONLY, 0)) < 0)
- err(EX_NOINPUT, "open(%s)", name);
- if (fstat(file, &sb) < 0)
- err(EX_IOERR, "fstat(%s)", name);
- tracks[notracks].file = file;
- strncpy(tracks[notracks].file_name, name, MAXPATHLEN);
- if (file == STDIN_FILENO)
- tracks[notracks].file_size = -1;
- else
- tracks[notracks].file_size = sb.st_size;
- tracks[notracks].block_size = block_size;
- tracks[notracks].block_type = block_type;
-
- if (nogap && notracks)
- tracks[notracks].pregap = 0;
- else {
- if (tracks[notracks - (notracks > 0)].block_type == block_type)
- tracks[notracks].pregap = 150;
- else
- tracks[notracks].pregap = 255;
- }
-
- if (verbose) {
- int pad = 0;
-
- if (tracks[notracks].file_size / tracks[notracks].block_size !=
- roundup_blocks(&tracks[notracks]))
- pad = 1;
- fprintf(stderr,
- "adding type 0x%02x file %s size %jd KB %d blocks %s\n",
- tracks[notracks].block_type, name,
- (intmax_t)sb.st_size/1024,
- roundup_blocks(&tracks[notracks]),
- pad ? "(0 padded)" : "");
- }
- notracks++;
-}
-
-void
-do_DAO(int fd, int test_write, int multi)
-{
- struct cdr_cuesheet sheet;
- struct cdr_cue_entry cue[100];
- int format = CDR_SESS_CDROM;
- int addr, i, j = 0;
-
- int bt2ctl[16] = { 0x0, -1, -1, -1, -1, -1, -1, -1,
- 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, -1, -1 };
-
- int bt2df[16] = { 0x0, -1, -1, -1, -1, -1, -1, -1,
- 0x10, 0x30, 0x20, -1, 0x21, -1, -1, -1 };
-
- if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR, &addr) < 0)
- err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
- if (verbose)
- fprintf(stderr, "next writeable LBA %d\n", addr);
-
- cue_ent(&cue[j++], bt2ctl[tracks[0].block_type], 0x01, 0x00, 0x0,
- (bt2df[tracks[0].block_type] & 0xf0) |
- (tracks[0].block_type < 8 ? 0x01 : 0x04), 0x00, addr);
-
- for (i = 0; i < notracks; i++) {
- if (bt2ctl[tracks[i].block_type] < 0 ||
- bt2df[tracks[i].block_type] < 0)
- errx(EX_IOERR, "track type not supported in DAO mode");
-
- if (tracks[i].block_type >= CDR_DB_XA_MODE1)
- format = CDR_SESS_CDROM_XA;
-
- if (i == 0) {
- addr += tracks[i].pregap;
- tracks[i].addr = addr;
-
- cue_ent(&cue[j++], bt2ctl[tracks[i].block_type],
- 0x01, i+1, 0x1, bt2df[tracks[i].block_type],
- 0x00, addr);
-
- }
- else {
- if (tracks[i].pregap) {
- if (tracks[i].block_type > 0x7) {
- cue_ent(&cue[j++],bt2ctl[tracks[i].block_type],
- 0x01, i+1, 0x0,
- (bt2df[tracks[i].block_type] & 0xf0) |
- (tracks[i].block_type < 8 ? 0x01 :0x04),
- 0x00, addr);
- }
- else
- cue_ent(&cue[j++],bt2ctl[tracks[i].block_type],
- 0x01, i+1, 0x0,
- bt2df[tracks[i].block_type],
- 0x00, addr);
- }
- tracks[i].addr = tracks[i - 1].addr +
- roundup_blocks(&tracks[i - 1]);
-
- cue_ent(&cue[j++], bt2ctl[tracks[i].block_type],
- 0x01, i+1, 0x1, bt2df[tracks[i].block_type],
- 0x00, addr + tracks[i].pregap);
-
- if (tracks[i].block_type > 0x7)
- addr += tracks[i].pregap;
- }
- addr += roundup_blocks(&tracks[i]);
- }
-
- cue_ent(&cue[j++], bt2ctl[tracks[i - 1].block_type], 0x01, 0xaa, 0x01,
- (bt2df[tracks[i - 1].block_type] & 0xf0) |
- (tracks[i - 1].block_type < 8 ? 0x01 : 0x04), 0x00, addr);
-
- sheet.len = j * 8;
- sheet.entries = cue;
- sheet.test_write = test_write;
- sheet.session_type = multi ? CDR_SESS_MULTI : CDR_SESS_NONE;
- sheet.session_format = format;
- if (verbose) {
- u_int8_t *ptr = (u_int8_t *)sheet.entries;
-
- fprintf(stderr,"CUE sheet:");
- for (i = 0; i < sheet.len; i++)
- if (i % 8)
- fprintf(stderr," %02x", ptr[i]);
- else
- fprintf(stderr,"\n%02x", ptr[i]);
- fprintf(stderr,"\n");
- }
-
- if (ioctl(fd, CDRIOCSENDCUE, &sheet) < 0)
- err(EX_IOERR, "ioctl(CDRIOCSENDCUE)");
-
- for (i = 0; i < notracks; i++) {
- if (write_file(fd, &tracks[i])) {
- cleanup_flush();
- err(EX_IOERR, "write_file");
- }
- }
-
- ioctl(fd, CDRIOCFLUSH);
-}
-
-void
-do_TAO(int fd, int test_write, int preemp, int dvdrw)
-{
- struct cdr_track track;
- int i;
-
- for (i = 0; i < notracks; i++) {
- track.test_write = test_write;
- track.datablock_type = tracks[i].block_type;
- track.preemp = preemp;
- if (ioctl(fd, CDRIOCINITTRACK, &track) < 0)
- err(EX_IOERR, "ioctl(CDRIOCINITTRACK)");
-
- if (dvdrw)
- tracks[i].addr = 0;
- else
- if (ioctl(fd, CDRIOCNEXTWRITEABLEADDR,
- &tracks[i].addr) < 0)
- err(EX_IOERR, "ioctl(CDRIOCNEXTWRITEABLEADDR)");
-
- if (!quiet)
- fprintf(stderr, "next writeable LBA %d\n",
- tracks[i].addr);
- if (write_file(fd, &tracks[i])) {
- cleanup_flush();
- err(EX_IOERR, "write_file");
- }
- if (ioctl(fd, CDRIOCFLUSH) < 0)
- err(EX_IOERR, "ioctl(CDRIOCFLUSH)");
- }
-}
-
-#define NTOH3B(x) ((x&0x0000ff)<<16) | (x&0x00ff00) | ((x&0xff0000)>>16)
-
-void
-do_format(int the_fd, int force, char *type)
-{
- struct cdr_format_capacities capacities;
- struct cdr_format_params format_params;
- int count, i, pct, last = 0;
-
- if (ioctl(the_fd, CDRIOCREADFORMATCAPS, &capacities) == -1)
- err(EX_IOERR, "ioctl(CDRIOCREADFORMATCAPS)");
-
- if (verbose) {
- fprintf(stderr, "format list entries=%zd\n",
- capacities.length / sizeof(struct cdr_format_capacity));
- fprintf(stderr, "current format: blocks=%u type=0x%x block_size=%u\n",
- ntohl(capacities.blocks), capacities.type,
- NTOH3B(capacities.block_size));
- }
-
- count = capacities.length / sizeof(struct cdr_format_capacity);
- if (verbose) {
- for (i = 0; i < count; ++i)
- fprintf(stderr,
- "format %d: blocks=%u type=0x%x param=%u\n",
- i, ntohl(capacities.format[i].blocks),
- capacities.format[i].type,
- NTOH3B(capacities.format[i].param));
- }
-
- for (i = 0; i < count; ++i) {
- if (!strcasecmp(type, "dvd+rw")) {
- if (capacities.format[i].type == 0x26) {
- break;
- }
- }
- if (!strcasecmp(type, "dvd-rw")) {
- if (capacities.format[i].type == 0x0) {
- break;
- }
- }
- }
- if (i == count)
- errx(EX_IOERR, "could not find a valid format capacity");
-
- if (!quiet)
- fprintf(stderr,"formatting with blocks=%u type=0x%x param=%u\n",
- ntohl(capacities.format[i].blocks),
- capacities.format[i].type,
- NTOH3B(capacities.format[i].param));
-
- if (!force && capacities.type == 2)
- errx(EX_IOERR, "media already formatted (use -F to override)");
-
- memset(&format_params, 0, sizeof(struct cdr_format_params));
- format_params.fov = 1;
- format_params.immed = 1;
- format_params.length = ntohs(sizeof(struct cdr_format_capacity));
- memcpy(&format_params.format, &capacities.format[i],
- sizeof(struct cdr_format_capacity));
-
- if(ioctl(the_fd, CDRIOCFORMAT, &format_params) == -1)
- err(EX_IOERR, "ioctl(CDRIOCFORMAT)");
-
- while (1) {
- sleep(1);
- if (ioctl(the_fd, CDRIOCGETPROGRESS, &pct) == -1)
- err(EX_IOERR, "ioctl(CDRIOGETPROGRESS)");
- if (pct > 0 && !quiet)
- fprintf(stderr, "formatting DVD - %d %% done \r",
- pct);
- if (pct == 100 || (pct == 0 && last > 90))
- break;
- last = pct;
- }
- if (!quiet)
- fprintf(stderr, "\n");
-}
-
-int
-write_file(int fd, struct track_info *track_info)
-{
- off_t size, count, filesize;
- char buf[2352*BLOCKS];
- static off_t tot_size = 0;
-
- filesize = track_info->file_size / 1024;
-
- if (ioctl(fd, CDRIOCSETBLOCKSIZE, &track_info->block_size) < 0)
- err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
-
- if (track_info->addr >= 0)
- lseek(fd, track_info->addr * track_info->block_size, SEEK_SET);
-
- if (verbose)
- fprintf(stderr, "addr = %d size = %jd blocks = %d\n",
- track_info->addr, (intmax_t)track_info->file_size,
- roundup_blocks(track_info));
-
- if (!quiet) {
- if (track_info->file == STDIN_FILENO)
- fprintf(stderr, "writing from stdin\n");
- else
- fprintf(stderr,
- "writing from file %s size %jd KB\n",
- track_info->file_name, (intmax_t)filesize);
- }
- size = 0;
-
- while ((count = read(track_info->file, buf,
- track_info->file_size == -1
- ? track_info->block_size * BLOCKS
- : MIN((track_info->file_size - size),
- track_info->block_size * BLOCKS))) > 0) {
- int res;
-
- if (count % track_info->block_size) {
- /* pad file to % block_size */
- bzero(&buf[count],
- (track_info->block_size * BLOCKS) - count);
- count = ((count / track_info->block_size) + 1) *
- track_info->block_size;
- }
- if ((res = write(fd, buf, count)) != count) {
- if (res == -1) {
- fprintf(stderr, "\n");
- close(track_info->file);
- return errno;
- } else
- fprintf(stderr, "\nonly wrote %d of %jd"
- " bytes\n", res, (intmax_t)count);
- break;
- }
- size += count;
- tot_size += count;
- if (!quiet) {
- int pct;
-
- fprintf(stderr, "written this track %jd KB",
- (intmax_t)size/1024);
- if (track_info->file != STDIN_FILENO && filesize) {
- pct = (size / 1024) * 100 / filesize;
- fprintf(stderr, " (%d%%)", pct);
- }
- fprintf(stderr, " total %jd KB\r",
- (intmax_t)tot_size / 1024);
- }
- if (track_info->file_size != -1
- && size >= track_info->file_size)
- break;
- }
-
- if (!quiet)
- fprintf(stderr, "\n");
- close(track_info->file);
- return 0;
-}
-
-int
-roundup_blocks(struct track_info *track)
-{
- return ((track->file_size + track->block_size - 1) / track->block_size);
-}
-
-void
-cue_ent(struct cdr_cue_entry *cue, int ctl, int adr, int track, int idx,
- int dataform, int scms, int lba)
-{
- cue->adr = adr;
- cue->ctl = ctl;
- cue->track = track;
- cue->index = idx;
- cue->dataform = dataform;
- cue->scms = scms;
- lba += 150;
- cue->min = lba / (60*75);
- cue->sec = (lba % (60*75)) / 75;
- cue->frame = (lba % (60*75)) % 75;
-}
-
-void
-cleanup(int dummy __unused)
-{
- if (ioctl(global_fd_for_cleanup, CDRIOCSETBLOCKSIZE,
- &saved_block_size) < 0)
- err(EX_IOERR, "ioctl(CDRIOCSETBLOCKSIZE)");
-}
-
-void
-cleanup_flush(void)
-{
- if (ioctl(global_fd_for_cleanup, CDRIOCFLUSH) < 0)
- err(EX_IOERR, "ioctl(CDRIOCFLUSH)");
-}
-
-void
-cleanup_signal(int sig)
-{
- signal(sig, SIG_IGN);
- ioctl(global_fd_for_cleanup, CDRIOCFLUSH);
- write(STDERR_FILENO, "\nAborted\n", 10);
- _exit(EXIT_FAILURE);
-}
-
-void
-usage(void)
-{
- fprintf(stderr,
- "usage: %s [-deFlmnpqtv] [-f device] [-s speed] [command]"
- " [command file ...]\n", getprogname());
- exit(EX_USAGE);
-}
diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c
index 14061c2..3ed5495 100644
--- a/usr.sbin/config/main.c
+++ b/usr.sbin/config/main.c
@@ -351,16 +351,24 @@ begin:
if (ch == '"' || ch == '\'') {
int quote = ch;
+ escaped_nl = 0;
while ((ch = getc(fp)) != EOF) {
- if (ch == quote)
+ if (ch == quote && !escaped_nl)
break;
- if (ch == '\n') {
+ if (ch == '\n' && !escaped_nl) {
*cp = 0;
printf("config: missing quote reading `%s'\n",
line);
exit(2);
}
+ if (ch == '\\' && !escaped_nl) {
+ escaped_nl = 1;
+ continue;
+ }
+ if (ch != quote && escaped_nl)
+ *cp++ = '\\';
*cp++ = ch;
+ escaped_nl = 0;
}
} else {
*cp++ = ch;
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index 2e73aeb..68e79ff 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 March 6, 2012
+.Dd April 2, 2013
.Dt CTLADM 8
.Os
.Sh NAME
@@ -487,7 +487,7 @@ cache for the entire LUN.
.It Fl r
Specify relative addressing for the starting LBA. CTL does not support
relative addressing, since it only works for linked commands, and CTL
-doesn't support linked commands.
+does not support linked commands.
.It Fl i
Tell the target to return status immediately after issuing the SYHCHRONIZE CACHE
command rather than waiting for the cache to finish syncing. CTL does not
@@ -975,6 +975,7 @@ This will result in a sense key of NOT READY (0x02), and an ASC/ASCQ of
.Xr cam 3 ,
.Xr cam_cdbparse 3 ,
.Xr cam 4 ,
+.Xr ctl 4 ,
.Xr xpt 4 ,
.Xr camcontrol 8
.Sh HISTORY
diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c
index 2a743da..bfbedc7 100644
--- a/usr.sbin/ctladm/ctladm.c
+++ b/usr.sbin/ctladm/ctladm.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/linker.h>
#include <sys/queue.h>
#include <sys/callout.h>
#include <sys/sbuf.h>
@@ -3814,6 +3815,7 @@ main(int argc, char **argv)
int retval, fd;
int retries;
int initid;
+ int saved_errno;
retval = 0;
cmdargs = CTLADM_ARG_NONE;
@@ -3963,6 +3965,14 @@ main(int argc, char **argv)
if ((cmdargs & CTLADM_ARG_DEVICE)
&& (command != CTLADM_CMD_HELP)) {
fd = open(device, O_RDWR);
+ if (fd == -1 && errno == ENOENT) {
+ saved_errno = errno;
+ retval = kldload("ctl");
+ if (retval != -1)
+ fd = open(device, O_RDWR);
+ else
+ errno = saved_errno;
+ }
if (fd == -1) {
fprintf(stderr, "%s: error opening %s: %s\n",
argv[0], device, strerror(errno));
diff --git a/usr.sbin/extattr/rmextattr.c b/usr.sbin/extattr/rmextattr.c
index db7df1a..c061943 100644
--- a/usr.sbin/extattr/rmextattr.c
+++ b/usr.sbin/extattr/rmextattr.c
@@ -102,6 +102,8 @@ main(int argc, char *argv[])
char *buf, *visbuf, *p;
const char *options, *attrname;
+ size_t len;
+ ssize_t ret;
int buflen, visbuflen, ch, error, i, arg_counter, attrnamespace,
minargc;
@@ -200,79 +202,84 @@ main(int argc, char *argv[])
continue;
break;
case EASET:
+ len = strlen(buf) + flag_null;
if (flag_nofollow)
- error = extattr_set_link(argv[arg_counter],
- attrnamespace, attrname, buf,
- strlen(buf) + flag_null);
+ ret = extattr_set_link(argv[arg_counter],
+ attrnamespace, attrname, buf, len);
else
- error = extattr_set_file(argv[arg_counter],
- attrnamespace, attrname, buf,
- strlen(buf) + flag_null);
- if (error >= 0)
+ ret = extattr_set_file(argv[arg_counter],
+ attrnamespace, attrname, buf, len);
+ if (ret >= 0) {
+ if ((size_t)ret != len && !flag_quiet) {
+ warnx("Set %zd bytes of %zu for %s",
+ ret, len, attrname);
+ }
continue;
+ }
break;
case EALS:
if (flag_nofollow)
- error = extattr_list_link(argv[arg_counter],
+ ret = extattr_list_link(argv[arg_counter],
attrnamespace, NULL, 0);
else
- error = extattr_list_file(argv[arg_counter],
+ ret = extattr_list_file(argv[arg_counter],
attrnamespace, NULL, 0);
- if (error < 0)
+ if (ret < 0)
break;
- mkbuf(&buf, &buflen, error);
+ mkbuf(&buf, &buflen, ret);
if (flag_nofollow)
- error = extattr_list_link(argv[arg_counter],
+ ret = extattr_list_link(argv[arg_counter],
attrnamespace, buf, buflen);
else
- error = extattr_list_file(argv[arg_counter],
+ ret = extattr_list_file(argv[arg_counter],
attrnamespace, buf, buflen);
- if (error < 0)
+ if (ret < 0)
break;
if (!flag_quiet)
printf("%s\t", argv[arg_counter]);
- for (i = 0; i < error; i += ch + 1) {
+ for (i = 0; i < ret; i += ch + 1) {
/* The attribute name length is unsigned. */
ch = (unsigned char)buf[i];
printf("%s%*.*s", i ? "\t" : "",
ch, ch, buf + i + 1);
}
- printf("\n");
+ if (!flag_quiet || ret > 0)
+ printf("\n");
continue;
case EAGET:
if (flag_nofollow)
- error = extattr_get_link(argv[arg_counter],
+ ret = extattr_get_link(argv[arg_counter],
attrnamespace, attrname, NULL, 0);
else
- error = extattr_get_file(argv[arg_counter],
+ ret = extattr_get_file(argv[arg_counter],
attrnamespace, attrname, NULL, 0);
- if (error < 0)
+ if (ret < 0)
break;
- mkbuf(&buf, &buflen, error);
+ mkbuf(&buf, &buflen, ret);
if (flag_nofollow)
- error = extattr_get_link(argv[arg_counter],
+ ret = extattr_get_link(argv[arg_counter],
attrnamespace, attrname, buf, buflen);
else
- error = extattr_get_file(argv[arg_counter],
+ ret = extattr_get_file(argv[arg_counter],
attrnamespace, attrname, buf, buflen);
- if (error < 0)
+ if (ret < 0)
break;
if (!flag_quiet)
printf("%s\t", argv[arg_counter]);
if (flag_string) {
- mkbuf(&visbuf, &visbuflen, error * 4 + 1);
- strvisx(visbuf, buf, error,
+ mkbuf(&visbuf, &visbuflen, ret * 4 + 1);
+ strvisx(visbuf, buf, ret,
VIS_SAFE | VIS_WHITE);
printf("\"%s\"\n", visbuf);
continue;
} else if (flag_hex) {
- for (i = 0; i < error; i++)
+ for (i = 0; i < ret; i++)
printf("%s%02x", i ? " " : "",
buf[i]);
printf("\n");
continue;
} else {
- fwrite(buf, error, 1, stdout);
+ fwrite(buf, ret, 1, stdout);
printf("\n");
continue;
}
diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c
index b7d5168..452a079 100644
--- a/usr.sbin/jail/command.c
+++ b/usr.sbin/jail/command.c
@@ -66,7 +66,7 @@ int paralimit = -1;
extern char **environ;
static int run_command(struct cfjail *j);
-static void add_proc(struct cfjail *j, pid_t pid);
+static int add_proc(struct cfjail *j, pid_t pid);
static void clear_procs(struct cfjail *j);
static struct cfjail *find_proc(pid_t pid);
static int term_procs(struct cfjail *j);
@@ -88,13 +88,14 @@ int
next_command(struct cfjail *j)
{
enum intparam comparam;
- int create_failed;
+ int create_failed, stopping;
if (paralimit == 0) {
requeue(j, &runnable);
return 1;
}
create_failed = (j->flags & (JF_STOP | JF_FAILED)) == JF_FAILED;
+ stopping = (j->flags & JF_STOP) != 0;
comparam = *j->comparam;
for (;;) {
if (j->comstring == NULL) {
@@ -113,14 +114,16 @@ next_command(struct cfjail *j)
default:
if (j->intparams[comparam] == NULL)
continue;
- j->comstring = create_failed
+ j->comstring = create_failed || (stopping &&
+ (j->intparams[comparam]->flags & PF_REV))
? TAILQ_LAST(&j->intparams[comparam]->val,
cfstrings)
: TAILQ_FIRST(&j->intparams[comparam]->val);
}
} else {
j->comstring = j->comstring == &dummystring ? NULL :
- create_failed
+ create_failed || (stopping &&
+ (j->intparams[comparam]->flags & PF_REV))
? TAILQ_PREV(j->comstring, cfstrings, tq)
: TAILQ_NEXT(j->comstring, tq);
}
@@ -542,13 +545,12 @@ run_command(struct cfjail *j)
if (pid < 0)
err(1, "fork");
if (pid > 0) {
- if (bg) {
+ if (bg || !add_proc(j, pid)) {
free(j->comline);
j->comline = NULL;
return 0;
} else {
paralimit--;
- add_proc(j, pid);
return 1;
}
}
@@ -622,7 +624,7 @@ run_command(struct cfjail *j)
/*
* Add a process to the hash, tied to a jail.
*/
-static void
+static int
add_proc(struct cfjail *j, pid_t pid)
{
struct kevent ke;
@@ -632,8 +634,11 @@ add_proc(struct cfjail *j, pid_t pid)
if (!kq && (kq = kqueue()) < 0)
err(1, "kqueue");
EV_SET(&ke, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
- if (kevent(kq, &ke, 1, NULL, 0, NULL) < 0)
+ if (kevent(kq, &ke, 1, NULL, 0, NULL) < 0) {
+ if (errno == ESRCH)
+ return 0;
err(1, "kevent");
+ }
ph = emalloc(sizeof(struct phash));
ph->j = j;
ph->pid = pid;
@@ -658,6 +663,7 @@ add_proc(struct cfjail *j, pid_t pid)
TAILQ_INSERT_TAIL(&sleeping, j, tq);
j->queue = &sleeping;
}
+ return 1;
}
/*
@@ -730,7 +736,7 @@ term_procs(struct cfjail *j)
for (i = 0; i < pcnt; i++)
if (ki[i].ki_jid == j->jid &&
kill(ki[i].ki_pid, SIGTERM) == 0) {
- add_proc(j, ki[i].ki_pid);
+ (void)add_proc(j, ki[i].ki_pid);
if (verbose > 0) {
if (!noted) {
noted = 1;
diff --git a/usr.sbin/jail/config.c b/usr.sbin/jail/config.c
index d0b7d26..a201f31 100644
--- a/usr.sbin/jail/config.c
+++ b/usr.sbin/jail/config.c
@@ -81,18 +81,18 @@ static const struct ipspec intparams[] = {
[IP_INTERFACE] = {"interface", PF_INTERNAL},
[IP_IP_HOSTNAME] = {"ip_hostname", PF_INTERNAL | PF_BOOL},
#endif
- [IP_MOUNT] = {"mount", PF_INTERNAL},
+ [IP_MOUNT] = {"mount", PF_INTERNAL | PF_REV},
[IP_MOUNT_DEVFS] = {"mount.devfs", PF_INTERNAL | PF_BOOL},
[IP_MOUNT_FSTAB] = {"mount.fstab", PF_INTERNAL},
[IP_STOP_TIMEOUT] = {"stop.timeout", PF_INTERNAL | PF_INT},
[IP_VNET_INTERFACE] = {"vnet.interface", PF_INTERNAL},
#ifdef INET
- [IP__IP4_IFADDR] = {"ip4.addr", PF_INTERNAL | PF_CONV},
+ [IP__IP4_IFADDR] = {"ip4.addr", PF_INTERNAL | PF_CONV | PF_REV},
#endif
#ifdef INET6
- [IP__IP6_IFADDR] = {"ip6.addr", PF_INTERNAL | PF_CONV},
+ [IP__IP6_IFADDR] = {"ip6.addr", PF_INTERNAL | PF_CONV | PF_REV},
#endif
- [IP__MOUNT_FROM_FSTAB] = {"mount.fstab", PF_INTERNAL | PF_CONV},
+ [IP__MOUNT_FROM_FSTAB] = {"mount.fstab", PF_INTERNAL | PF_CONV | PF_REV},
[IP__OP] = {NULL, PF_CONV},
[KP_ALLOW_CHFLAGS] = {"allow.chflags", 0},
[KP_ALLOW_MOUNT] = {"allow.mount", 0},
diff --git a/usr.sbin/jail/jailp.h b/usr.sbin/jail/jailp.h
index ffd35cc..63995b2 100644
--- a/usr.sbin/jail/jailp.h
+++ b/usr.sbin/jail/jailp.h
@@ -50,6 +50,7 @@
#define PF_BOOL 0x10 /* Boolean parameter */
#define PF_INT 0x20 /* Integer parameter */
#define PF_CONV 0x40 /* Parameter duplicated in converted form */
+#define PF_REV 0x80 /* Run commands in reverse order on stopping */
#define JF_START 0x0001 /* -c */
#define JF_SET 0x0002 /* -m */
diff --git a/usr.sbin/kgmon/kgmon.c b/usr.sbin/kgmon/kgmon.c
index c691d6e..3bc5351 100644
--- a/usr.sbin/kgmon/kgmon.c
+++ b/usr.sbin/kgmon/kgmon.c
@@ -37,10 +37,11 @@ static const char copyright[] =
#if 0
static char sccsid[] = "@(#)kgmon.c 8.1 (Berkeley) 6/6/93";
#endif
-static const char rcsid[] =
- "$FreeBSD$";
#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/file.h>
#include <sys/time.h>
@@ -77,7 +78,7 @@ int debug = 0;
int getprof(struct kvmvars *);
int getprofhz(struct kvmvars *);
void kern_readonly(int);
-int openfiles(char *, char *, struct kvmvars *);
+int openfiles(const char *, char *, struct kvmvars *);
void setprof(struct kvmvars *kvp, int state);
void dumpstate(struct kvmvars *kvp);
void reset(struct kvmvars *kvp);
@@ -88,13 +89,14 @@ main(int argc, char **argv)
{
int ch, mode, disp, accessmode;
struct kvmvars kvmvars;
- char *system, *kmemf;
+ const char *systemname;
+ char *kmemf;
if (seteuid(getuid()) != 0) {
err(1, "seteuid failed\n");
}
kmemf = NULL;
- system = NULL;
+ systemname = NULL;
while ((ch = getopt(argc, argv, "M:N:Bbhpr")) != -1) {
switch((char)ch) {
@@ -104,7 +106,7 @@ main(int argc, char **argv)
break;
case 'N':
- system = optarg;
+ systemname = optarg;
break;
case 'B':
@@ -137,16 +139,16 @@ main(int argc, char **argv)
#define BACKWARD_COMPATIBILITY
#ifdef BACKWARD_COMPATIBILITY
if (*argv) {
- system = *argv;
+ systemname = *argv;
if (*++argv) {
kmemf = *argv;
++kflag;
}
}
#endif
- if (system == NULL)
- system = (char *)getbootfile();
- accessmode = openfiles(system, kmemf, &kvmvars);
+ if (systemname == NULL)
+ systemname = getbootfile();
+ accessmode = openfiles(systemname, kmemf, &kvmvars);
mode = getprof(&kvmvars);
if (hflag)
disp = GMON_PROF_OFF;
@@ -173,7 +175,7 @@ main(int argc, char **argv)
}
static void
-usage()
+usage(void)
{
fprintf(stderr, "usage: kgmon [-Bbhrp] [-M core] [-N system]\n");
exit(1);
@@ -183,10 +185,7 @@ usage()
* Check that profiling is enabled and open any necessary files.
*/
int
-openfiles(system, kmemf, kvp)
- char *system;
- char *kmemf;
- struct kvmvars *kvp;
+openfiles(const char *systemname, char *kmemf, struct kvmvars *kvp)
{
size_t size;
int mib[3], state, openmode;
@@ -212,11 +211,11 @@ openfiles(system, kmemf, kvp)
}
openmode = (Bflag || bflag || hflag || pflag || rflag)
? O_RDWR : O_RDONLY;
- kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf);
+ kvp->kd = kvm_openfiles(systemname, kmemf, NULL, openmode, errbuf);
if (kvp->kd == NULL) {
if (openmode == O_RDWR) {
openmode = O_RDONLY;
- kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY,
+ kvp->kd = kvm_openfiles(systemname, kmemf, NULL, O_RDONLY,
errbuf);
}
if (kvp->kd == NULL)
@@ -224,7 +223,7 @@ openfiles(system, kmemf, kvp)
kern_readonly(GMON_PROF_ON);
}
if (kvm_nlist(kvp->kd, nl) < 0)
- errx(3, "%s: no namelist", system);
+ errx(3, "%s: no namelist", systemname);
if (!nl[N_GMONPARAM].n_value)
errx(20, "profiling not defined in kernel");
return (openmode);
@@ -234,8 +233,7 @@ openfiles(system, kmemf, kvp)
* Suppress options that require a writable kernel.
*/
void
-kern_readonly(mode)
- int mode;
+kern_readonly(int mode)
{
(void)fprintf(stderr, "kgmon: kernel read-only: ");
@@ -256,8 +254,7 @@ kern_readonly(mode)
* Get the state of kernel profiling.
*/
int
-getprof(kvp)
- struct kvmvars *kvp;
+getprof(struct kvmvars *kvp)
{
size_t size;
int mib[3];
@@ -311,9 +308,7 @@ getprof(kvp)
* Enable or disable kernel profiling according to the state variable.
*/
void
-setprof(kvp, state)
- struct kvmvars *kvp;
- int state;
+setprof(struct kvmvars *kvp, int state)
{
struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;
size_t sz;
@@ -335,7 +330,7 @@ setprof(kvp, state)
}
(void)seteuid(getuid());
} else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz)
- == sz)
+ == (ssize_t)sz)
return;
bad:
warnx("warning: cannot turn profiling %s",
@@ -346,8 +341,7 @@ bad:
* Build the gmon.out file.
*/
void
-dumpstate(kvp)
- struct kvmvars *kvp;
+dumpstate(struct kvmvars *kvp)
{
register FILE *fp;
struct rawarc rawarc;
@@ -463,8 +457,7 @@ dumpstate(kvp)
* Get the profiling rate.
*/
int
-getprofhz(kvp)
- struct kvmvars *kvp;
+getprofhz(struct kvmvars *kvp)
{
size_t size;
int mib[2], profrate;
@@ -490,8 +483,7 @@ getprofhz(kvp)
* Reset the kernel profiling date structures.
*/
void
-reset(kvp)
- struct kvmvars *kvp;
+reset(struct kvmvars *kvp)
{
char *zbuf;
u_long biggest;
@@ -509,13 +501,13 @@ reset(kvp)
bzero(zbuf, biggest);
if (kflag) {
if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,
- kvp->gpm.kcountsize) != kvp->gpm.kcountsize)
+ kvp->gpm.kcountsize) != (ssize_t)kvp->gpm.kcountsize)
errx(13, "tickbuf zero: %s", kvm_geterr(kvp->kd));
if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,
- kvp->gpm.fromssize) != kvp->gpm.fromssize)
+ kvp->gpm.fromssize) != (ssize_t)kvp->gpm.fromssize)
errx(14, "froms zero: %s", kvm_geterr(kvp->kd));
if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,
- kvp->gpm.tossize) != kvp->gpm.tossize)
+ kvp->gpm.tossize) != (ssize_t)kvp->gpm.tossize)
errx(15, "tos zero: %s", kvm_geterr(kvp->kd));
return;
}
diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8
index b1a5751..4d81e45 100644
--- a/usr.sbin/makefs/makefs.8
+++ b/usr.sbin/makefs/makefs.8
@@ -43,7 +43,7 @@
.Nd create a file system image from a directory tree or a mtree manifest
.Sh SYNOPSIS
.Nm
-.Op Fl px
+.Op Fl Dpx
.Op Fl B Ar byte-order
.Op Fl b Ar free-blocks
.Op Fl d Ar debug-mask
@@ -106,6 +106,8 @@ An optional
suffix may be provided to indicate that
.Ar free-blocks
indicates a percentage of the calculated image size.
+.It Fl D
+Treat duplicate paths in an mtree manifest as warnings not error.
.It Fl d Ar debug-mask
Enable various levels of debugging, depending upon which bits are
set in
@@ -323,7 +325,7 @@ Load a generic boot image into the first 32K of the cd9660 image.
.It Sy hard-disk-boot
Boot image is a hard disk image.
.It Sy keep-bad-images
-Don't throw away images whose write was aborted due to an error.
+Do not throw away images whose write was aborted due to an error.
For debugging purposes.
.It Sy label
Label name of the image.
diff --git a/usr.sbin/makefs/makefs.c b/usr.sbin/makefs/makefs.c
index b2da82b..03ff1ac 100644
--- a/usr.sbin/makefs/makefs.c
+++ b/usr.sbin/makefs/makefs.c
@@ -73,6 +73,7 @@ static fstype_t fstypes[] = {
};
u_int debug;
+int dupsok;
struct timespec start_time;
static fstype_t *get_fstype(const char *);
@@ -112,7 +113,7 @@ main(int argc, char *argv[])
start_time.tv_sec = start.tv_sec;
start_time.tv_nsec = start.tv_usec * 1000;
- while ((ch = getopt(argc, argv, "B:b:d:f:F:M:m:N:o:ps:S:t:x")) != -1) {
+ while ((ch = getopt(argc, argv, "B:b:Dd:f:F:M:m:N:o:ps:S:t:x")) != -1) {
switch (ch) {
case 'B':
@@ -148,6 +149,10 @@ main(int argc, char *argv[])
}
break;
+ case 'D':
+ dupsok = 1;
+ break;
+
case 'd':
debug = strtoll(optarg, NULL, 0);
break;
diff --git a/usr.sbin/makefs/makefs.h b/usr.sbin/makefs/makefs.h
index 483ccff..c6707d9 100644
--- a/usr.sbin/makefs/makefs.h
+++ b/usr.sbin/makefs/makefs.h
@@ -169,6 +169,7 @@ void cd9660_makefs(const char *, const char *, fsnode *, fsinfo_t *);
extern u_int debug;
+extern int dupsok;
extern struct timespec start_time;
/*
@@ -279,6 +280,8 @@ extern struct timespec start_time;
struct fs;
void ffs_fragacct_swap(struct fs *, int, int32_t [], int, int);
+fsinode *link_check(fsinode *);
+
/*
* Declarations for compat routines.
*/
diff --git a/usr.sbin/makefs/mtree.c b/usr.sbin/makefs/mtree.c
index 836e766..c90c974 100644
--- a/usr.sbin/makefs/mtree.c
+++ b/usr.sbin/makefs/mtree.c
@@ -508,8 +508,8 @@ read_mtree_keywords(FILE *fp, fsnode *node)
{
char keyword[PATH_MAX];
char *name, *p, *value;
- struct group *grent;
- struct passwd *pwent;
+ gid_t gid;
+ uid_t uid;
struct stat *st, sb;
intmax_t num;
u_long flset, flclr;
@@ -585,11 +585,10 @@ read_mtree_keywords(FILE *fp, fsnode *node)
error = ENOATTR;
break;
}
- grent = getgrnam(value);
- if (grent != NULL)
- st->st_gid = grent->gr_gid;
+ if (gid_from_group(value, &gid) == 0)
+ st->st_gid = gid;
else
- error = errno;
+ error = EINVAL;
} else
error = ENOSYS;
break;
@@ -698,11 +697,10 @@ read_mtree_keywords(FILE *fp, fsnode *node)
error = ENOATTR;
break;
}
- pwent = getpwnam(value);
- if (pwent != NULL)
- st->st_uid = pwent->pw_uid;
+ if (uid_from_user(value, &uid) == 0)
+ st->st_uid = uid;
else
- error = errno;
+ error = EINVAL;
} else
error = ENOSYS;
break;
@@ -781,6 +779,24 @@ read_mtree_keywords(FILE *fp, fsnode *node)
return (0);
}
+ /*
+ * Check for hardlinks. If the contents key is used, then the check
+ * will only trigger if the contents file is a link even if it is used
+ * by more than one file
+ */
+ if (sb.st_nlink > 1) {
+ fsinode *curino;
+
+ st->st_ino = sb.st_ino;
+ st->st_dev = sb.st_dev;
+ curino = link_check(node->inode);
+ if (curino != NULL) {
+ free(node->inode);
+ node->inode = curino;
+ node->inode->nlink++;
+ }
+ }
+
free(node->contents);
node->contents = name;
st->st_size = sb.st_size;
@@ -881,8 +897,14 @@ read_mtree_spec1(FILE *fp, bool def, const char *name)
if (strcmp(name, node->name) == 0) {
if (def == true) {
- mtree_error("duplicate definition of %s",
- name);
+ if (!dupsok)
+ mtree_error(
+ "duplicate definition of %s",
+ name);
+ else
+ mtree_warning(
+ "duplicate definition of %s",
+ name);
return (0);
}
@@ -970,15 +992,15 @@ read_mtree_spec(FILE *fp)
do {
*cp++ = '\0';
- /* Disallow '.' and '..' as components. */
- if (IS_DOT(pathspec) || IS_DOTDOT(pathspec)) {
- mtree_error("absolute path cannot contain . "
- "or .. components");
+ /* Disallow '..' as a component. */
+ if (IS_DOTDOT(pathspec)) {
+ mtree_error("absolute path cannot contain "
+ ".. component");
goto out;
}
- /* Ignore multiple adjacent slashes. */
- if (pathspec[0] != '\0')
+ /* Ignore multiple adjacent slashes and '.'. */
+ if (pathspec[0] != '\0' && !IS_DOT(pathspec))
error = read_mtree_spec1(fp, false, pathspec);
memmove(pathspec, cp, strlen(cp) + 1);
cp = strchr(pathspec, '/');
diff --git a/usr.sbin/makefs/walk.c b/usr.sbin/makefs/walk.c
index 0664c84..7af92bb 100644
--- a/usr.sbin/makefs/walk.c
+++ b/usr.sbin/makefs/walk.c
@@ -59,7 +59,6 @@ static void apply_specdir(const char *, NODE *, fsnode *, int);
static void apply_specentry(const char *, NODE *, fsnode *);
static fsnode *create_fsnode(const char *, const char *, const char *,
struct stat *);
-static fsinode *link_check(fsinode *);
/*
@@ -644,7 +643,7 @@ inode_type(mode_t mode)
/* This was borrowed from du.c and tweaked to keep an fsnode
* pointer instead. -- dbj@netbsd.org
*/
-static fsinode *
+fsinode *
link_check(fsinode *entry)
{
static struct entry {
diff --git a/usr.sbin/mfiutil/Makefile b/usr.sbin/mfiutil/Makefile
index e100358..c460b3f 100644
--- a/usr.sbin/mfiutil/Makefile
+++ b/usr.sbin/mfiutil/Makefile
@@ -1,8 +1,8 @@
# $FreeBSD$
PROG= mfiutil
-SRCS= mfiutil.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
+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
MAN8= mfiutil.8
CFLAGS+= -fno-builtin-strftime
diff --git a/usr.sbin/mfiutil/mfi_bbu.c b/usr.sbin/mfiutil/mfi_bbu.c
new file mode 100644
index 0000000..db16367
--- /dev/null
+++ b/usr.sbin/mfiutil/mfi_bbu.c
@@ -0,0 +1,249 @@
+/*-
+ * Copyright (c) 2013 Sandvine 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/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include "mfiutil.h"
+
+/* The autolearn period is given in seconds. */
+void
+mfi_autolearn_period(uint32_t period, char *buf, size_t sz)
+{
+ unsigned int d, h;
+ char *tmp;
+
+ d = period / (24 * 3600);
+ h = (period % (24 * 3600)) / 3600;
+
+ tmp = buf;
+ if (d != 0) {
+ tmp += snprintf(buf, sz, "%u day%s", d, d == 1 ? "" : "s");
+ sz -= tmp - buf;
+ if (h != 0) {
+ tmp += snprintf(tmp, sz, ", ");
+ sz -= 2;
+ }
+ }
+ if (h != 0)
+ snprintf(tmp, sz, "%u hour%s", h, h == 1 ? "" : "s");
+
+ if (d == 0 && h == 0)
+ snprintf(tmp, sz, "less than 1 hour");
+}
+
+/* The time to the next relearn is given in seconds since 1/1/2000. */
+void
+mfi_next_learn_time(uint32_t next_learn_time, char *buf, size_t sz)
+{
+ time_t basetime;
+ struct tm tm;
+ size_t len;
+
+ memset(&tm, 0, sizeof(tm));
+ tm.tm_year = 100;
+ basetime = timegm(&tm);
+ basetime += (time_t)next_learn_time;
+ len = snprintf(buf, sz, "%s", ctime(&basetime));
+ if (len > 0)
+ /* Get rid of the newline added by ctime(3). */
+ buf[len - 1] = '\0';
+}
+
+void
+mfi_autolearn_mode(uint8_t mode, char *buf, size_t sz)
+{
+
+ switch (mode) {
+ case 0:
+ snprintf(buf, sz, "enabled");
+ break;
+ case 1:
+ snprintf(buf, sz, "disabled");
+ break;
+ case 2:
+ snprintf(buf, sz, "warn via event");
+ break;
+ default:
+ snprintf(buf, sz, "mode 0x%02x", mode);
+ break;
+ }
+}
+
+int
+mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props, uint8_t *statusp)
+{
+
+ return (mfi_dcmd_command(fd, MFI_DCMD_BBU_GET_PROP, props,
+ sizeof(*props), NULL, 0, statusp));
+}
+
+int
+mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props, uint8_t *statusp)
+{
+
+ return (mfi_dcmd_command(fd, MFI_DCMD_BBU_SET_PROP, props,
+ sizeof(*props), NULL, 0, statusp));
+}
+
+static int
+start_bbu_learn(int ac, char **av __unused)
+{
+ uint8_t status;
+ int error, fd;
+
+ status = MFI_STAT_OK;
+ error = 0;
+
+ if (ac != 1) {
+ warnx("start learn: unexpected arguments");
+ return (EINVAL);
+ }
+
+ fd = mfi_open(mfi_unit, O_RDWR);
+ if (fd < 0) {
+ error = errno;
+ warn("mfi_open");
+ return (error);
+ }
+
+ if (mfi_dcmd_command(fd, MFI_DCMD_BBU_START_LEARN, NULL, 0, NULL, 0,
+ &status) < 0) {
+ error = errno;
+ warn("Failed to start BBU learn");
+ } else if (status != MFI_STAT_OK) {
+ warnx("Failed to start BBU learn: %s", mfi_status(status));
+ error = EIO;
+ }
+
+ return (error);
+}
+MFI_COMMAND(start, learn, start_bbu_learn);
+
+static int
+update_bbu_props(int ac, char **av)
+{
+ struct mfi_bbu_properties props;
+ unsigned long delay;
+ uint8_t status;
+ int error, fd;
+ char *mode, *endptr;
+
+ status = MFI_STAT_OK;
+ error = 0;
+
+ if (ac != 3) {
+ warnx("bbu: property and value required");
+ return (EINVAL);
+ }
+
+ fd = mfi_open(mfi_unit, O_RDWR);
+ if (fd < 0) {
+ error = errno;
+ warn("mfi_open");
+ return (error);
+ }
+
+ if (mfi_bbu_get_props(fd, &props, &status) < 0) {
+ error = errno;
+ warn("Failed to get BBU properties");
+ goto done;
+ } else if (status != MFI_STAT_OK) {
+ warnx("Failed to get BBU properties: %s", mfi_status(status));
+ error = EIO;
+ goto done;
+ }
+
+ if (strcmp(av[1], "learn-delay") == 0) {
+ delay = strtoul(av[2], &endptr, 10);
+ if (strlen(av[2]) == 0 || *endptr != '\0' || delay > 255) {
+ warnx("Invalid learn delay '%s'", av[2]);
+ error = EINVAL;
+ goto done;
+ }
+
+ props.learn_delay_interval = delay;
+ } else if (strcmp(av[1], "autolearn-mode") == 0) {
+ mode = av[2];
+
+ if (strcmp(av[2], "enable") == 0)
+ props.auto_learn_mode = 0;
+ else if (strcmp(av[2], "disable") == 0)
+ props.auto_learn_mode = 1;
+ else if (mode[0] >= '0' && mode[0] <= '2' && mode[1] == '\0')
+ props.auto_learn_mode = mode[0] - '0';
+ else {
+ warnx("Invalid mode '%s'", mode);
+ error = EINVAL;
+ goto done;
+ }
+ } else if (strcmp(av[1], "bbu-mode") == 0) {
+ if (props.bbu_mode == 0) {
+ warnx("This BBU does not implement different modes");
+ error = EINVAL;
+ goto done;
+ }
+
+ /* The mode must be an integer between 1 and 5. */
+ mode = av[2];
+ if (mode[0] < '1' || mode[0] > '5' || mode[1] != '\0') {
+ warnx("Invalid mode '%s'", mode);
+ error = EINVAL;
+ goto done;
+ }
+
+ props.bbu_mode = mode[0] - '0';
+ } else {
+ warnx("bbu: Invalid command '%s'", av[1]);
+ error = EINVAL;
+ goto done;
+ }
+
+ if (mfi_bbu_set_props(fd, &props, &status) < 0) {
+ error = errno;
+ warn("Failed to set BBU properties");
+ goto done;
+ } else if (status != MFI_STAT_OK) {
+ warnx("Failed to set BBU properties: %s", mfi_status(status));
+ error = EIO;
+ goto done;
+ }
+
+done:
+ close(fd);
+
+ return (error);
+}
+MFI_COMMAND(top, bbu, update_bbu_props);
diff --git a/usr.sbin/mfiutil/mfi_show.c b/usr.sbin/mfiutil/mfi_show.c
index be395bb..06721c2 100644
--- a/usr.sbin/mfiutil/mfi_show.c
+++ b/usr.sbin/mfiutil/mfi_show.c
@@ -140,9 +140,11 @@ show_battery(int ac, char **av __unused)
{
struct mfi_bbu_capacity_info cap;
struct mfi_bbu_design_info design;
+ struct mfi_bbu_properties props;
struct mfi_bbu_status stat;
uint8_t status;
- int comma, error, fd, show_capacity;
+ int comma, error, fd, show_capacity, show_props;
+ char buf[32];
if (ac != 1) {
warnx("show battery: extra arguments");
@@ -186,6 +188,14 @@ show_battery(int ac, char **av __unused)
return (error);
}
+ if (mfi_bbu_get_props(fd, &props, &status) < 0) {
+ error = errno;
+ warn("Failed to get properties");
+ close(fd);
+ return (error);
+ }
+ show_props = (status == MFI_STAT_OK);
+
printf("mfi%d: Battery State:\n", mfi_unit);
printf(" Manufacture Date: %d/%d/%d\n", design.mfg_date >> 5 & 0x0f,
design.mfg_date & 0x1f, design.mfg_date >> 9 & 0xffff);
@@ -205,6 +215,23 @@ show_battery(int ac, char **av __unused)
printf(" Design Voltage: %d mV\n", design.design_voltage);
printf(" Current Voltage: %d mV\n", stat.voltage);
printf(" Temperature: %d C\n", stat.temperature);
+ if (show_props) {
+ mfi_autolearn_period(props.auto_learn_period, buf, sizeof(buf));
+ printf(" Autolearn period: %s\n", buf);
+ if (props.auto_learn_mode != 0)
+ snprintf(buf, sizeof(buf), "never");
+ else
+ mfi_next_learn_time(props.next_learn_time, buf,
+ sizeof(buf));
+ printf(" Next learn time: %s\n", buf);
+ printf(" Learn delay interval: %u hour%s\n",
+ props.learn_delay_interval,
+ props.learn_delay_interval != 1 ? "s" : "");
+ mfi_autolearn_mode(props.auto_learn_mode, buf, sizeof(buf));
+ printf(" Autolearn mode: %s\n", buf);
+ if (props.bbu_mode != 0)
+ printf(" BBU Mode: %d\n", props.bbu_mode);
+ }
printf(" Status:");
comma = 0;
if (stat.fw_status & MFI_BBU_STATE_PACK_MISSING) {
diff --git a/usr.sbin/mfiutil/mfi_volume.c b/usr.sbin/mfiutil/mfi_volume.c
index 49417d0..2306256 100644
--- a/usr.sbin/mfiutil/mfi_volume.c
+++ b/usr.sbin/mfiutil/mfi_volume.c
@@ -363,7 +363,8 @@ volume_cache(int ac, char **av)
break;
}
if (props.default_cache_policy != props.current_cache_policy)
- printf("Cache Disabled Due to Dead Battery\n");
+ printf(
+ "Cache disabled due to dead battery or ongoing battery relearn\n");
error = 0;
} else {
new = props;
diff --git a/usr.sbin/mfiutil/mfiutil.8 b/usr.sbin/mfiutil/mfiutil.8
index b1be5d9..5468617 100644
--- a/usr.sbin/mfiutil/mfiutil.8
+++ b/usr.sbin/mfiutil/mfiutil.8
@@ -141,6 +141,12 @@
.Nm
.Op Fl u Ar unit
.Cm flash Ar file
+.Nm
+.Op Fl u Ar unit
+.Cm start learn
+.Nm
+.Op Fl u Ar unit
+.Cm bbu Ar setting Ar value
.Sh DESCRIPTION
The
.Nm
@@ -565,6 +571,33 @@ Stop a currently running patrol read operation.
Updates the flash on the controller with the firmware stored in
.Ar file .
A reboot is required for the new firmware to take effect.
+.It Cm start learn
+Start a battery relearn.
+.It Cm bbu Ar setting Ar value
+Update battery backup unit (BBU) properties related to battery relearning.
+The following settings are configurable:
+.Bl -tag -width indent
+.It Cm learn-delay
+Add a delay to the next scheduled battery relearn event. This setting is
+given in hours and must lie in the range of 0 to 255.
+.It Cm autolearn-mode
+Enable or disable automatic periodic battery relearning.
+The setting may be set to
+.Dq enable
+or
+.Dq disable
+to respectively enable or disable the relearn cycle.
+Alternatively, a mode of 0, 1 or 2 may be given.
+Mode 0 enables periodic relearning, mode 1 disables it, and mode 2 disables
+it and logs a warning to the event log when it detects that a battery relearn
+should be performed.
+.It Cm bbu-mode
+Set the BBU's mode of operation. This setting is not supported by all BBUs.
+Where it is supported, the possible values are the integers between 1 and 5
+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
.El
.Sh EXAMPLES
Configure the cache for volume mfid0 to cache only writes:
diff --git a/usr.sbin/mfiutil/mfiutil.c b/usr.sbin/mfiutil/mfiutil.c
index 79c6a4b..7488e24 100644
--- a/usr.sbin/mfiutil/mfiutil.c
+++ b/usr.sbin/mfiutil/mfiutil.c
@@ -84,6 +84,8 @@ usage(void)
fprintf(stderr, " start patrol - start a patrol read\n");
fprintf(stderr, " stop patrol - stop a patrol read\n");
fprintf(stderr, " flash <firmware>\n");
+ fprintf(stderr, " start learn - start a BBU relearn\n");
+ fprintf(stderr, " bbu <setting> <value> - set BBU properties\n");
#ifdef DEBUG
fprintf(stderr, " debug - debug 'show config'\n");
fprintf(stderr, " dump - display 'saved' config\n");
diff --git a/usr.sbin/mfiutil/mfiutil.h b/usr.sbin/mfiutil/mfiutil.h
index 687bdd9..8a544c2 100644
--- a/usr.sbin/mfiutil/mfiutil.h
+++ b/usr.sbin/mfiutil/mfiutil.h
@@ -152,6 +152,13 @@ int mfi_reconfig_supported(void);
const char *mfi_status(u_int status_code);
const char *mfi_drive_name(struct mfi_pd_info *pinfo, uint16_t device_id,
uint32_t def);
+int mfi_bbu_get_props(int fd, struct mfi_bbu_properties *props,
+ uint8_t *statusp);
+int mfi_bbu_set_props(int fd, struct mfi_bbu_properties *props,
+ uint8_t *statusp);
+void mfi_autolearn_period(uint32_t, char *, size_t);
+void mfi_next_learn_time(uint32_t, char *, size_t);
+void mfi_autolearn_mode(uint8_t, char *, size_t);
void scan_firmware(struct mfi_info_component *comp);
void display_firmware(struct mfi_info_component *comp, const char *tag);
diff --git a/usr.sbin/mount_nwfs/Makefile b/usr.sbin/mount_nwfs/Makefile
deleted file mode 100644
index 8f46581..0000000
--- a/usr.sbin/mount_nwfs/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# $FreeBSD$
-
-PROG= mount_nwfs
-SRCS= mount_nwfs.c getmntopts.c
-MAN= mount_nwfs.8
-
-MOUNT= ${.CURDIR}/../../sbin/mount
-CFLAGS+= -DNWFS -I${MOUNT}
-
-.PATH: ${MOUNT}
-
-DPADD= ${LIBNCP} ${LIBIPX}
-LDADD= -lncp -lipx
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/mount_nwfs/Makefile.depend b/usr.sbin/mount_nwfs/Makefile.depend
deleted file mode 100644
index bfecf09..0000000
--- a/usr.sbin/mount_nwfs/Makefile.depend
+++ /dev/null
@@ -1,20 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DEP_MACHINE := ${.PARSEFILE:E}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
- lib/libipx \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/mount_nwfs/mount_nwfs.8 b/usr.sbin/mount_nwfs/mount_nwfs.8
deleted file mode 100644
index 3946f71..0000000
--- a/usr.sbin/mount_nwfs/mount_nwfs.8
+++ /dev/null
@@ -1,230 +0,0 @@
-.\" $FreeBSD$
-.Dd October 14, 1999
-.Dt MOUNT_NWFS 8
-.Os
-.Sh NAME
-.Nm mount_nwfs
-.Nd mount NetWare volume from a NetWare file server
-.Sh SYNOPSIS
-.Nm
-.Op Fl Chv
-.Fl S Ar server
-.Fl U Ar user
-.Op Fl connection\ options
-.Fl V Ar volume
-.Op Fl M Ar mode
-.Op Fl c Ar case
-.Op Fl d Ar mode
-.Op Fl f Ar mode
-.Op Fl g Ar gid
-.Op Fl l Ar locale
-.Op Fl n Ar os2
-.Op Fl u Ar uid
-.Op Fl w Ar scheme
-.Ar node
-.Nm
-.Op Fl options
-.Ar /server:user/volume[/path]
-.Ar node
-.Sh DESCRIPTION
-The
-.Nm
-utility allows to mount volume from a NetWare server.
-It may use either
-existing connection or create new: if no usable connection was found
-it will try to establish a new one.
-Connection has count of references to it,
-so when last mount will be dismounted connection will be closed.
-It is
-possible to create connection without any mounts (but use it for them) with
-.Xr ncplogin 1 .
-.Pp
-Note two forms of command line.
-In the first form, server and user specified
-via
-.Fl S
-and
-.Fl U
-options respectively.
-In the second form server and user specified in
-.Ar special
-part of
-.Xr mount 8
-command line arguments (the
-.Fl S ,
-.Fl U
-and
-.Fl V
-options are not used in this case).
-This allows use of
-.Xr fstab 5
-file (see
-.Sx EXAMPLES
-below).
-.Pp
-The options are:
-.Bl -tag -width indent
-.It Fl S Ar server
-Name of NetWare server to connect.
-For native IP you will need also
-.Fl A
-option.
-.It Fl U Ar user
-Name of user used in login sequence.
-.It Fl connection\ options
-See
-.Xr ncplogin 1
-for details.
-.It Fl V Ar volume
-Volume name to mount.
-Volume name can also be specified after all options and
-before
-.Ar mount-point .
-.It Ar node
-Path to mount volume.
-.It Fl c Ar case
-Select a
-.Ar case
-option which affects on name representation.
-.Ar Case
-can be one of the following:
-.Bl -tag -width "ValueXX"
-.It Em Value
-.Em Meaning
-.It l
-All existing file names converted to lower case.
-Newly created file gets a lower case under OS2 name space.
-This is the default when mounting volumes with DOS name space.
-.It L
-Same as 'l' but file system tries to be case insensitive.
-May not work well.
-.It n
-No case conversion is performed.
-.Em Warning !
-Use this option with DOS name space only as a last resort,
-because creating a lower case name in the DOS name space
-can lead to unpredictable results.
-This is the default when mounting volumes with OS2 name space.
-.It u
-All existing file names converted to upper case.
-Newly created file gets an upper case under OS2 name space.
-.It U
-Same as 'u' but file system tries to be case insensitive.
-May not work well.
-.El
-.It Fl f Ar mode , Fl d Ar mode
-Specify permissions that should be assigned to files and directories.
-The values must be specified as octal numbers.
-Default value for the file mode
-is taken from mount point, default value for the dir mode adds execute
-permission where the file mode gives read permission.
-.Pp
-Note that these permissions can differ from the rights granted by NetWare
-server.
-.It Fl n Ar namespace
-Do not use
-.Ar namespace .
-Currently only
-.Ar OS2
-can be here.
-.It Fl v
-Print version number.
-.It Fl u Ar uid , Fl g Ar gid
-User id and group id assigned to files.
-The default is owner and group id from
-directory where volume is mounted.
-.It Fl l Ar locale
-Set the locale for case conversion.
-By default
-.Nm
-tries to use an environment variable
-.Ev LC_* .
-.It Fl w Ar scheme
-Select a
-.Ar scheme
-used to convert file names between NetWare and
-.Fx .
-Supported conversion schemes are:
-.Bl -tag -width ".Cm koi2cp866"
-.It Cm asis
-Characters passed as is without any alteration.
-.It Cm koi2cp866
-koi8-r <-> CP866
-.It Cm se
-Suits for setups used in Sweden.
-.El
-.It Fl M Ar mode
-See
-.Xr ncplogin 1
-for details.
-If this option is omitted, connection permissions
-assumed the same as directory mode
-.Pq Fl d
-option.
-.El
-.Sh FILES
-.Bl -tag -width /var/log/wtmp -compact
-.It Pa ~/.nwfsrc
-keeps static parameters for connections and other information.
-See
-.Pa /usr/share/examples/nwclient/dot.nwfsrc
-for details.
-.El
-.Sh NOTES
-Before any NCP connection can be established kernel must be configured
-for IPX support, IPXrouted and KLD nwfs.ko should be loaded.
-.Sh EXAMPLES
-Next examples illustrates how to connect to NetWare server
-.Em nwserv
-as user
-.Em GUEST
-and mount volumes
-.Em SYS
-and
-.Em VOL1 :
-.Bd -literal -offset indent
-mount_nwfs -S nwserv -U guest -V sys /nw/s1/sys
-mount_nwfs /nwserv:guest/sys /nw/s1/sys
-mount -t nwfs /nwserv:guest/vol1 /nw/s1/vol1
-mount -t nwfs /nwserv:boris/sys/home/boris /home/boris/nw/home
-.Ed
-.Pp
-The last example mounts only subdirectory on a volume and equivalent
-to NetWare 'map root' command.
-.Pp
-It is possible to use
-.Xr fstab 5
-for nwfs mounts:
-.Bd -literal -offset indent
-/nwserv:guest/sys /nw/s1/sys nwfs rw,noauto 0 0
-/nwserv:guest/vol1 /nw/s1/vol2 nwfs rw,noauto 0 0
-.Ed
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Fx 4.0 .
-.Sh CREDITS
-In development of NetWare client for
-.Fx ,
-the following sources were used:
-.Pp
-Documentation from NetWare NDK.
-.Pp
-Ncpfs for Linux - written by
-.An Volker Lendecke Aq lendecke@math.uni\-goettingen.de .
-He granted me permission to publish parts of his code under
-.Bx Ns -style
-license,
-.Pp
-"Interrupt List" from
-.An Ralf Brown ,
-.Pp
-Many files from
-.Pa /sys
-directory.
-.Sh AUTHORS
-.An Boris Popov Aq bp@butya.kz ,
-.Aq rbp@chat.ru
-.Sh BUGS
-to number a few
diff --git a/usr.sbin/mount_nwfs/mount_nwfs.c b/usr.sbin/mount_nwfs/mount_nwfs.c
deleted file mode 100644
index 5f5f19a..0000000
--- a/usr.sbin/mount_nwfs/mount_nwfs.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 1999, Boris Popov
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Boris Popov.
- * 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 THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-#include <sys/mount.h>
-#include <sys/sysctl.h>
-#include <machine/cpu.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <pwd.h>
-#include <grp.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <err.h>
-#include <sysexits.h>
-#include <time.h>
-
-#include <netncp/ncp_lib.h>
-#include <netncp/ncp_rcfile.h>
-#include <fs/nwfs/nwfs_mount.h>
-#include "mntopts.h"
-
-#define NWFS_VFSNAME "nwfs"
-
-static char mount_point[MAXPATHLEN + 1];
-static void usage(void);
-static int parsercfile(struct ncp_conn_loginfo *li, struct nwfs_args *mdata);
-
-static struct mntopt mopts[] = {
- MOPT_STDOPTS,
- MOPT_END
-};
-
-static int
-parsercfile(struct ncp_conn_loginfo *li __unused,
- struct nwfs_args *mdata __unused)
-{
- return 0;
-}
-
-int
-main(int argc, char *argv[])
-{
- NWCONN_HANDLE connHandle;
- struct nwfs_args mdata;
- struct ncp_conn_loginfo li;
- struct stat st;
- struct nw_entry_info einfo;
- struct tm *tm;
- time_t ltime;
- int opt, error, mntflags, nlsopt, wall_clock;
- int uid_set, gid_set;
- size_t len;
- char *p, *p1, tmp[1024];
- u_char *pv;
-
- if (argc < 2)
- usage();
- if (argc == 2) {
- if (strcmp(argv[1], "-h") == 0) {
- usage();
- } else if (strcmp(argv[1], "-v") == 0) {
- errx(EX_OK, "version %d.%d.%d", NWFS_VERSION / 100000,
- (NWFS_VERSION % 10000) / 1000,
- (NWFS_VERSION % 1000) / 100);
- }
- }
-
- if(ncp_initlib()) exit(1);
-
- mntflags = error = 0;
- bzero(&mdata,sizeof(mdata));
- gid_set = uid_set = 0;
- nlsopt = 0;
-
- if (ncp_li_init(&li, argc, argv)) return 1;
- /*
- * A little bit weird, but I should figure out which server/user to use
- * _before_ reading .rc file
- */
- if (argc >= 3 && argv[argc-1][0] != '-' && argv[argc-2][0] != '-' &&
- argv[argc-2][0] == '/') {
- p = argv[argc-2];
- error = 1;
- do {
- if (*p++ != '/') break;
- p1 = tmp;
- while (*p != ':' && *p != 0) *p1++ = *p++;
- if (*p++ == 0) break;
- *p1 = 0;
- if (ncp_li_setserver(&li, tmp)) break;
- p1 = tmp;
- while (*p != '/' && *p != 0) *p1++ = *p++;
- if (*p++ == 0) break;
- *p1 = 0;
- if (ncp_li_setuser(&li, tmp)) break;
- p1 = tmp;
- while (*p != '/' && *p != 0) *p1++ = *p++;
- *p1 = 0;
- if (strlen(tmp) > NCP_VOLNAME_LEN) {
- warnx("volume name too long: %s", tmp);
- break;
- }
- ncp_str_upper(strcpy(mdata.mounted_vol,tmp));
- if (*p == '/')
- p++;
- p1 = mdata.root_path + 2;
- pv = mdata.root_path + 1;
- for(;*p;) {
- *pv = 0;
- while (*p != '/' && *p) {
- *p1++ = *p++;
- (*pv)++;
- }
- if (*pv) {
- ncp_nls_mem_u2n(pv + 1, pv + 1, *pv);
- pv += (*pv) + 1;
- mdata.root_path[0]++;
- }
- if (*p++ == 0) break;
- p1++;
- }
- error = 0;
- } while(0);
- if (error)
- errx(EX_DATAERR,
- "an error occurred while parsing '%s'",
- argv[argc - 2]);
- }
- if (ncp_li_readrc(&li)) return 1;
- if (ncp_rc) {
- parsercfile(&li,&mdata);
- rc_close(ncp_rc);
- }
- while ((opt = getopt(argc, argv, STDPARAM_OPT"V:c:d:f:g:l:n:o:u:w:")) != -1) {
- switch (opt) {
- case STDPARAM_ARGS:
- if (ncp_li_arg(&li, opt, optarg)) {
- return 1;
- }
- break;
- case 'V':
- if (strlen(optarg) > NCP_VOLNAME_LEN)
- errx(EX_DATAERR, "volume too long: %s", optarg);
- ncp_str_upper(strcpy(mdata.mounted_vol,optarg));
- break;
- case 'u': {
- struct passwd *pwd;
-
- pwd = isdigit(optarg[0]) ?
- getpwuid(atoi(optarg)) : getpwnam(optarg);
- if (pwd == NULL)
- errx(EX_NOUSER, "unknown user '%s'", optarg);
- mdata.uid = pwd->pw_uid;
- uid_set = 1;
- break;
- }
- case 'g': {
- struct group *grp;
-
- grp = isdigit(optarg[0]) ?
- getgrgid(atoi(optarg)) : getgrnam(optarg);
- if (grp == NULL)
- errx(EX_NOUSER, "unknown group '%s'", optarg);
- mdata.gid = grp->gr_gid;
- gid_set = 1;
- break;
- }
- case 'd':
- errno = 0;
- mdata.dir_mode = strtol(optarg, &p, 8);
- if (errno || *p != 0)
- errx(EX_DATAERR, "invalid value for directory mode");
- break;
- case 'f':
- errno = 0;
- mdata.file_mode = strtol(optarg, &p, 8);
- if (errno || *p != 0)
- errx(EX_DATAERR, "invalid value for file mode");
- break;
- case '?':
- usage();
- /*NOTREACHED*/
- case 'n': {
- char *inp, *nsp;
-
- nsp = inp = optarg;
- while ((nsp = strsep(&inp, ",;:")) != NULL) {
- if (strcasecmp(nsp, "OS2") == 0)
- mdata.flags |= NWFS_MOUNT_NO_OS2;
- else if (strcasecmp(nsp, "LONG") == 0)
- mdata.flags |= NWFS_MOUNT_NO_LONG;
- else if (strcasecmp(nsp, "NFS") == 0)
- mdata.flags |= NWFS_MOUNT_NO_NFS;
- else
- errx(EX_DATAERR, "unknown namespace '%s'", nsp);
- }
- break;
- };
- case 'l':
- if (ncp_nls_setlocale(optarg) != 0) return 1;
- mdata.flags |= NWFS_MOUNT_HAVE_NLS;
- break;
- case 'o':
- getmntopts(optarg, mopts, &mntflags, 0);
- break;
- case 'c':
- switch (optarg[0]) {
- case 'l':
- nlsopt |= NWHP_LOWER;
- break;
- case 'u':
- nlsopt |= NWHP_UPPER;
- break;
- case 'n':
- nlsopt |= NWHP_LOWER | NWHP_UPPER;
- break;
- case 'L':
- nlsopt |= NWHP_LOWER | NWHP_NOSTRICT;
- break;
- case 'U':
- nlsopt |= NWHP_UPPER | NWHP_NOSTRICT;
- break;
- default:
- errx(EX_DATAERR, "invalid suboption '%c' for -c",
- optarg[0]);
- }
- break;
- case 'w':
- if (ncp_nls_setrecodebyname(optarg) != 0)
- return 1;
- mdata.flags |= NWFS_MOUNT_HAVE_NLS;
- break;
- default:
- usage();
- }
- }
-
- if (optind == argc - 2) {
- optind++;
- } else if (mdata.mounted_vol[0] == 0)
- errx(EX_USAGE, "volume name should be specified");
-
- if (optind != argc - 1)
- usage();
- realpath(argv[optind], mount_point);
-
- if (stat(mount_point, &st) == -1)
- err(EX_OSERR, "could not find mount point %s", mount_point);
- if (!S_ISDIR(st.st_mode)) {
- errno = ENOTDIR;
- err(EX_OSERR, "can't mount on %s", mount_point);
- }
- if (ncp_geteinfo(mount_point, &einfo) == 0)
- errx(EX_OSERR, "can't mount on %s twice", mount_point);
-
- if (uid_set == 0) {
- mdata.uid = st.st_uid;
- }
- if (gid_set == 0) {
- mdata.gid = st.st_gid;
- }
- if (mdata.file_mode == 0 ) {
- mdata.file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
- }
- if (mdata.dir_mode == 0) {
- mdata.dir_mode = mdata.file_mode;
- if ((mdata.dir_mode & S_IRUSR) != 0)
- mdata.dir_mode |= S_IXUSR;
- if ((mdata.dir_mode & S_IRGRP) != 0)
- mdata.dir_mode |= S_IXGRP;
- if ((mdata.dir_mode & S_IROTH) != 0)
- mdata.dir_mode |= S_IXOTH;
- }
- if (li.access_mode == 0) {
- li.access_mode = mdata.dir_mode;
- }
-/* if (mdata.flags & NWFS_MOUNT_HAVE_NLS) {*/
- mdata.nls = ncp_nls;
-/* }*/
- mdata.nls.opt = nlsopt;
-
- len = sizeof(wall_clock);
- if (sysctlbyname("machdep.wall_cmos_clock", &wall_clock, &len, NULL, 0) == -1)
- err(EX_OSERR, "get wall_clock");
- if (wall_clock == 0) {
- time(&ltime);
- tm = localtime(&ltime);
- mdata.tz = -(tm->tm_gmtoff / 60);
- }
-
- error = ncp_li_check(&li);
- if (error)
- return 1;
- li.opt |= NCP_OPT_WDOG;
- /* well, now we can try to login, or use already established connection */
- error = ncp_li_login(&li, &connHandle);
- if (error) {
- ncp_error("cannot login to server %s", error, li.server);
- exit(1);
- }
- error = ncp_conn2ref(connHandle, &mdata.connRef);
- if (error) {
- ncp_error("could not convert handle to reference", error);
- ncp_disconnect(connHandle);
- exit(1);
- }
- strcpy(mdata.mount_point,mount_point);
- mdata.version = NWFS_VERSION;
- error = mount(NWFS_VFSNAME, mdata.mount_point, mntflags, (void*)&mdata);
- if (error) {
- ncp_error("mount error: %s", error, mdata.mount_point);
- ncp_disconnect(connHandle);
- exit(1);
- }
- /*
- * I'm leave along my handle, but kernel should keep own ...
- */
- ncp_disconnect(connHandle);
- /* we are done ?, impossible ... */
- return 0;
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
- "usage: mount_nwfs [-Chv] -S server -U user [-connection options]",
- " -V volume [-M mode] [-c case] [-d mode] [-f mode]",
- " [-g gid] [-l locale] [-n os2] [-u uid] [-w scheme]",
- " node",
- " mount_nwfs [-options] /server:user/volume[/path] node");
-
- exit (1);
-}
diff --git a/usr.sbin/mount_portalfs/Makefile b/usr.sbin/mount_portalfs/Makefile
deleted file mode 100644
index 991a36f..0000000
--- a/usr.sbin/mount_portalfs/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# From: @(#)Makefile 8.3 (Berkeley) 3/27/94
-# $FreeBSD$
-
-PROG= mount_portalfs
-SRCS= mount_portalfs.c activate.c conf.c cred.c getmntopts.c pt_conf.c \
- pt_exec.c pt_file.c pt_pipe.c pt_tcp.c pt_tcplisten.c
-MAN= mount_portalfs.8
-
-MOUNT= ${.CURDIR}/../../sbin/mount
-CFLAGS+=-I${MOUNT}
-WARNS?= 3
-
-.PATH: ${MOUNT}
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/mount_portalfs/Makefile.depend b/usr.sbin/mount_portalfs/Makefile.depend
deleted file mode 100644
index 16b5e42..0000000
--- a/usr.sbin/mount_portalfs/Makefile.depend
+++ /dev/null
@@ -1,20 +0,0 @@
-# Autogenerated - do NOT edit!
-
-DEP_RELDIR := ${_PARSEDIR:S,${SRCTOP}/,,}
-
-DEP_MACHINE := ${.PARSEFILE:E}
-
-DIRDEPS = \
- gnu/lib/libgcc \
- include \
- include/arpa \
- include/xlocale \
- lib/${CSU_DIR} \
- lib/libc \
-
-
-.include <dirdeps.mk>
-
-.if ${DEP_RELDIR} == ${_DEP_RELDIR}
-# local dependencies - needed for -jN in clean tree
-.endif
diff --git a/usr.sbin/mount_portalfs/activate.c b/usr.sbin/mount_portalfs/activate.c
deleted file mode 100644
index 7d35d48..0000000
--- a/usr.sbin/mount_portalfs/activate.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)activate.c 8.3 (Berkeley) 4/28/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/syslog.h>
-#include <sys/uio.h>
-
-#include "portald.h"
-
-/*
- * Scan the providers list and call the
- * appropriate function.
- */
-static int activate_argv(struct portal_cred *pcr, char *key, char **v, int so,
- int *fdp)
-{
- provider *pr;
-
- for (pr = providers; pr->pr_match; pr++)
- if (strcmp(v[0], pr->pr_match) == 0)
- return ((*pr->pr_func)(pcr, key, v, so, fdp));
-
- return (ENOENT);
-}
-
-static int get_request(int so, struct portal_cred *pcr, char *key, int klen)
-{
- struct iovec iov[2];
- struct msghdr msg;
- int n;
-
- iov[0].iov_base = (caddr_t) pcr;
- iov[0].iov_len = sizeof(*pcr);
- iov[1].iov_base = key;
- iov[1].iov_len = klen;
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = iov;
- msg.msg_iovlen = 2;
-
- n = recvmsg(so, &msg, 0);
- if (n < 0)
- return (errno);
-
- if (n <= (int)sizeof(*pcr))
- return (EINVAL);
-
- n -= sizeof(*pcr);
- key[n] = '\0';
-
- return (0);
-}
-
-static void send_reply(int so, int fd, int error)
-{
- int n;
- struct iovec iov;
- struct msghdr msg;
- union {
- struct cmsghdr cmsg;
- char control[CMSG_SPACE(sizeof(int))];
- } ctl;
-
- /*
- * Line up error code. Don't worry about byte ordering
- * because we must be sending to the local machine.
- */
- iov.iov_base = (caddr_t) &error;
- iov.iov_len = sizeof(error);
-
- /*
- * Build a msghdr
- */
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- /*
- * If there is a file descriptor to send then
- * construct a suitable rights control message.
- */
- if (fd >= 0) {
- ctl.cmsg.cmsg_len = CMSG_LEN(sizeof(int));
- ctl.cmsg.cmsg_level = SOL_SOCKET;
- ctl.cmsg.cmsg_type = SCM_RIGHTS;
- *((int *)CMSG_DATA(&ctl.cmsg)) = fd;
- msg.msg_control = (caddr_t) &ctl;
- msg.msg_controllen = ctl.cmsg.cmsg_len;
- }
-
- /*
- * Send to kernel...
- */
- if ((n = sendmsg(so, &msg, 0)) < 0)
- syslog(LOG_ERR, "send: %s", strerror(errno));
-#ifdef DEBUG
- fprintf(stderr, "sent %d bytes\n", n);
-#endif
- sleep(1); /*XXX*/
-#ifdef notdef
- if (shutdown(so, SHUT_RDWR) < 0)
- syslog(LOG_ERR, "shutdown: %s", strerror(errno));
-#endif
- /*
- * Throw away the open file descriptor
- */
- (void) close(fd);
-}
-
-void activate(qelem *q, int so)
-{
- struct portal_cred pcred;
- char key[MAXPATHLEN+1];
- int error;
- char **v;
- int fd = -1;
-
- /*
- * Read the key from the socket
- */
- error = get_request(so, &pcred, key, sizeof(key));
- if (error) {
- syslog(LOG_ERR, "activate: recvmsg: %s", strerror(error));
- goto drop;
- }
-
-#ifdef DEBUG
- fprintf(stderr, "lookup key %s\n", key);
-#endif
-
- /*
- * Find a match in the configuration file
- */
- v = conf_match(q, key);
-
- /*
- * If a match existed, then find an appropriate portal
- * otherwise simply return ENOENT.
- */
- if (v) {
- error = activate_argv(&pcred, key, v, so, &fd);
- if (error)
- fd = -1;
- else if (fd < 0)
- error = -1;
- } else {
- error = ENOENT;
- }
-
- if (error >= 0)
- send_reply(so, fd, error);
-
-drop:;
- close(so);
-}
diff --git a/usr.sbin/mount_portalfs/conf.c b/usr.sbin/mount_portalfs/conf.c
deleted file mode 100644
index f6b34bd..0000000
--- a/usr.sbin/mount_portalfs/conf.c
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)conf.c 8.2 (Berkeley) 3/27/94
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <regex.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-
-#include "portald.h"
-
-#define ALLOC(ty) (xmalloc(sizeof(ty)))
-
-typedef struct path path;
-struct path {
- qelem p_q; /* 2-way linked list */
- int p_lno; /* Line number of this record */
- char *p_args; /* copy of arg string (malloc) */
- char *p_key; /* Pathname to match (also p_argv[0]) */
- regex_t p_rx; /* RE to match against pathname () */
- int p_rxvalid; /* non-zero if valid regular expression */
- int p_argc; /* number of elements in arg string */
- char **p_argv; /* argv[] pointers into arg string (malloc) */
-};
-
-static char *conf_file; /* XXX for regerror */
-static path *curp; /* XXX for regerror */
-
-/*
- * Add an element to a 2-way list,
- * just after (pred)
- */
-static void ins_que(qelem *elem, qelem *pred)
-{
- qelem *p = pred->q_forw;
- elem->q_back = pred;
- elem->q_forw = p;
- pred->q_forw = elem;
- p->q_back = elem;
-}
-
-/*
- * Remove an element from a 2-way list
- */
-static void rem_que(qelem *elem)
-{
- qelem *p = elem->q_forw;
- qelem *p2 = elem->q_back;
- p2->q_forw = p;
- p->q_back = p2;
-}
-
-/*
- * Error checking malloc
- */
-static void *xmalloc(unsigned siz)
-{
- void *p = malloc(siz);
- if (p)
- return (p);
- syslog(LOG_ALERT, "malloc: failed to get %d bytes", siz);
- exit(1);
-}
-
-/*
- * Insert the path in the list.
- * If there is already an element with the same key then
- * the *second* one is ignored (return 0). If the key is
- * not found then the path is added to the end of the list
- * and 1 is returned.
- */
-static int pinsert(path *p0, qelem *q0)
-{
- qelem *q;
-
- if (p0->p_argc == 0)
- return (0);
-
- for (q = q0->q_forw; q != q0; q = q->q_forw) {
- path *p = (path *) q;
- if (strcmp(p->p_key, p0->p_key) == 0)
- return (0);
- }
- ins_que(&p0->p_q, q0->q_back);
- return (1);
-
-}
-
-static path *palloc(char *cline, int lno)
-{
- int c;
- char *s;
- char *key;
- path *p;
- char **ap;
-
- /*
- * Implement comment chars
- */
- s = strchr(cline, '#');
- if (s)
- *s = 0;
-
- /*
- * Do a pass through the string to count the number
- * of arguments
- */
- c = 0;
- key = strdup(cline);
- for (s = key; s != NULL; ) {
- char *val;
- while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
- ;
- if (val)
- c++;
- }
- c++;
- free(key);
-
- if (c <= 1)
- return (0);
-
- /*
- * Now do another pass and generate a new path structure
- */
- p = ALLOC(path);
- p->p_argc = 0;
- p->p_argv = xmalloc(c * sizeof(char *));
- p->p_args = strdup(cline);
- ap = p->p_argv;
- for (s = p->p_args; s != NULL; ) {
- char *val;
- while ((val = strsep(&s, " \t\n")) != NULL && *val == '\0')
- ;
- if (val) {
- *ap++ = val;
- p->p_argc++;
- }
- }
- *ap = 0;
-
-#ifdef DEBUG
- for (c = 0; c < p->p_argc; c++)
- printf("%sv[%d] = %s\n", c?"\t":"", c, p->p_argv[c]);
-#endif
-
- p->p_key = p->p_argv[0];
- if (strpbrk(p->p_key, RE_CHARS)) {
- int val;
-
- curp = p; /* XXX */
- val = regcomp(&p->p_rx, p->p_key, REG_EXTENDED | REG_NOSUB);
- if (val) {
- char errbuf[_POSIX2_LINE_MAX];
- regerror(val, &p->p_rx, errbuf, sizeof errbuf);
- syslog(LOG_ERR, "%s:%d: regcomp %s: %s",
- conf_file, curp->p_lno, curp->p_key, errbuf);
- regfree(&p->p_rx);
- p->p_rxvalid = 0;
- } else {
- p->p_rxvalid = 1;
- }
- curp = 0; /* XXX */
- } else {
- p->p_rxvalid = 0;
- }
- p->p_lno = lno;
-
- return (p);
-}
-
-/*
- * Free a path structure
- */
-static void pfree(path *p)
-{
- free(p->p_args);
- if (p->p_rxvalid) {
- regfree(&p->p_rx);
- }
- free((char *) p->p_argv);
- free((char *) p);
-}
-
-/*
- * Discard all currently held path structures on q0.
- * and add all the ones on xq.
- */
-static void preplace(qelem *q0, qelem *xq)
-{
- /*
- * While the list is not empty,
- * take the first element off the list
- * and free it.
- */
- while (q0->q_forw != q0) {
- qelem *q = q0->q_forw;
- rem_que(q);
- pfree((path *) q);
- }
- while (xq->q_forw != xq) {
- qelem *q = xq->q_forw;
- rem_que(q);
- ins_que(q, q0);
- }
-}
-
-/*
- * Read the lines from the configuration file and
- * add them to the list of paths.
- */
-static void readfp(qelem *q0, FILE *fp)
-{
- char cline[LINE_MAX];
- int nread = 0;
- qelem q;
-
- /*
- * Make a new empty list.
- */
- q.q_forw = q.q_back = &q;
-
- /*
- * Read the lines from the configuration file.
- */
- while (fgets(cline, sizeof(cline), fp)) {
- path *p = palloc(cline, nread+1);
- if (p && !pinsert(p, &q))
- pfree(p);
- nread++;
- }
-
- /*
- * If some records were read, then throw
- * away the old list and replace with the
- * new one.
- */
- if (nread)
- preplace(q0, &q);
-}
-
-/*
- * Read the configuration file (conf) and replace
- * the existing path list with the new version.
- * If the file is not readable, then no changes take place
- */
-void conf_read(qelem *q, char *conf)
-{
- FILE *fp = fopen(conf, "r");
- if (fp) {
- conf_file = conf; /* XXX */
- readfp(q, fp);
- conf_file = 0; /* XXX */
- (void) fclose(fp);
- } else {
- syslog(LOG_ERR, "open config file \"%s\": %s", conf, strerror(errno));
- }
-}
-
-
-char **conf_match(qelem *q0, char *key)
-{
- qelem *q;
-
- for (q = q0->q_forw; q != q0; q = q->q_forw) {
- path *p = (path *) q;
- if (p->p_rxvalid) {
- if (!regexec(&p->p_rx, key, 0, 0, 0)) {
- return p->p_argv + 1;
- }
- } else {
- if (strncmp(p->p_key, key, strlen(p->p_key)) == 0)
- return (p->p_argv+1);
- }
- }
-
- return (0);
-}
diff --git a/usr.sbin/mount_portalfs/cred.c b/usr.sbin/mount_portalfs/cred.c
deleted file mode 100644
index 2bd3623..0000000
--- a/usr.sbin/mount_portalfs/cred.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*-
- * Copyright (C) 2005 Diomidis Spinellis. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-
-#include "portald.h"
-
-/*
- * Set the process's credentials to those specified in user,
- * saving the existing ones in save.
- * Return 0 on success, -1 (with errno set) on error.
- */
-int
-set_user_credentials(struct portal_cred *user, struct portal_cred *save)
-{
- save->pcr_uid = geteuid();
- if ((save->pcr_ngroups = getgroups(NGROUPS_MAX, save->pcr_groups)) < 0)
- return (-1);
- if (setgroups(user->pcr_ngroups, user->pcr_groups) < 0)
- return (-1);
- if (seteuid(user->pcr_uid) < 0)
- return (-1);
- return (0);
-}
-
-/*
- * Restore the process's credentials to the ones specified in save.
- * Log failures using LOG_ERR.
- * Return 0 on success, -1 (with errno set) on error.
- */
-int
-restore_credentials(struct portal_cred *save)
-{
- if (seteuid(save->pcr_uid) < 0) {
- syslog(LOG_ERR, "seteuid: %m");
- return (-1);
- }
- if (setgroups(save->pcr_ngroups, save->pcr_groups) < 0) {
- syslog(LOG_ERR, "setgroups: %m");
- return (-1);
- }
- return (0);
-}
diff --git a/usr.sbin/mount_portalfs/mount_portalfs.8 b/usr.sbin/mount_portalfs/mount_portalfs.8
deleted file mode 100644
index b6ca9cc..0000000
--- a/usr.sbin/mount_portalfs/mount_portalfs.8
+++ /dev/null
@@ -1,216 +0,0 @@
-.\"
-.\" Copyright (c) 1993, 1994
-.\" The Regents of the University of California. All rights reserved.
-.\" All rights reserved.
-.\"
-.\" This code is derived from software donated to Berkeley by
-.\" Jan-Simon Pendry.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 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.
-.\"
-.\" @(#)mount_portal.8 8.3 (Berkeley) 3/27/94
-.\" $FreeBSD$
-.\"
-.Dd March 11, 2005
-.Dt MOUNT_PORTALFS 8
-.Os
-.Sh NAME
-.Nm mount_portalfs
-.Nd mount the portal daemon
-.Sh SYNOPSIS
-.Nm
-.Op Fl o Ar options
-.Ar /etc/portal.conf
-.Ar mount_point
-.Sh DESCRIPTION
-The
-.Nm
-utility attaches an instance of the portal daemon
-to the global file system namespace.
-The conventional mount point is
-.Pa /p .
-.\" .PA /dev .
-This command is normally executed by
-.Xr mount 8
-at boot time.
-.Pp
-The options are as follows:
-.Bl -tag -width indent
-.It Fl o
-Options are specified with a
-.Fl o
-flag followed by a comma separated string of options.
-See the
-.Xr mount 8
-man page for possible options and their meanings.
-.El
-.Pp
-The portal daemon provides an
-.Em open
-service.
-Objects opened under the portal mount point are
-dynamically created by the portal daemon according
-to rules specified in the named configuration file.
-Using this mechanism allows descriptors such as sockets
-to be made available in the file system namespace.
-.Pp
-The portal daemon works by being passed the full pathname
-of the object being opened.
-The daemon creates an appropriate descriptor according
-to the rules in the configuration file, and then passes the descriptor back
-to the calling process as the result of the open system call.
-.Sh NAMESPACE
-By convention, the portal daemon divides the namespace into sub-namespaces,
-each of which handles objects of a particular type.
-.Pp
-The following sub-namespaces are currently implemented:
-.Pa fs ,
-.Pa pipe ,
-.Pa tcp ,
-and
-.Pa tcplisten .
-.Pp
-The
-.Pa fs
-namespace opens the named file, starting back at the root directory.
-This can be used to provide a controlled escape path from
-a chrooted environment.
-.Pp
-The
-.Pa pipe
-namespace executes the named command, starting back at the root directory.
-The command's arguments can be provided after the command's name,
-by separating them with spaces or tabs.
-Files opened for reading in the
-.Pa pipe
-namespace will receive their input from the command's standard output;
-files opened for writing will send the data of write operations
-to the command's standard input.
-.Pp
-The
-.Pa tcp
-namespace takes a slash separated hostname and a port and
-creates an open TCP/IP connection.
-.Pp
-The
-.Pa tcplisten
-namespace takes a slash separated hostname and port and creates a TCP/IP
-socket bound to the given hostname-port pair.
-The hostname may be
-specified as "ANY" to allow any other host to connect to the socket.
-A
-port number of 0 will dynamically allocate a port, this can be
-discovered by calling
-.Xr getsockname 2
-with the returned file descriptor.
-Privileged ports can only be bound to
-by the super-user.
-.Sh "CONFIGURATION FILE"
-The configuration file contains a list of rules.
-Each rule takes one line and consists of two or more
-whitespace separated fields.
-A hash (``#'') character causes the remainder of a line to
-be ignored.
-Blank lines are ignored.
-.Pp
-The first field is a pathname prefix to match
-against the requested pathname.
-If a match is found, the second field
-tells the daemon what type of object to create.
-Subsequent fields are passed to the creation function.
-.Bd -literal
-# @(#)portal.conf 5.1 (Berkeley) 7/13/92
-tcplisten/ tcplisten tcplisten/
-tcp/ tcp tcp/
-fs/ file fs/
-pipe/ pipe pipe/
-.Ed
-.Sh FILES
-.Bl -tag -width /p/* -compact
-.It Pa /p/*
-.El
-.Sh EXAMPLES
-Display the greeting of the
-.Fx
-.Tn SMTP
-server.
-.Pp
-.Dl "head -1 /p/tcp/mx1.freebsd.org/smtp"
-.Pp
-Implement a (single-threaded) echo server:
-.Bd -literal -offset indent
-while :
-do
- (exec 3<>/p/tcplisten/ANY/echo && cat -u <&3 >&3)
-done
-.Ed
-.Pp
-Gather data from two sources.
-Verify that two remote files are identical:
-.Bd -literal -offset indent
-diff -q '/p/pipe/usr/bin/fetch -o - \\
- ftp://ftp1.freebsd.org/pub/FreeBSD/README.TXT' \\
- '/p/pipe/usr/bin/fetch -o - \\
- ftp://ftp2.freebsd.org/pub/FreeBSD/README.TXT'
-.Ed
-.Pp
-Scatter data to two sinks.
-Record a remote
-.Tn CD
-.Tn ISO
-image and calculate its checksum:
-.Bd -literal -offset indent
-fetch -o - ftp://ftp5.freebsd.org/.../disc.iso |
-tee '/p/pipe/usr/local/bin/cdrecord -' |
-md5
-.Ed
-.Pp
-Create an
-.Tn XML
-view of the password file:
-.Bd -literal -offset indent
-ln -s '/p/pipe/usr/local/bin/passwd2xml /etc/passwd' \\
- /etc/passwd.xml"
-.Ed
-.Sh SEE ALSO
-.Xr mount 2 ,
-.Xr unmount 2 ,
-.Xr fstab 5 ,
-.Xr mount 8
-.Rs
-.%A "W. Richard Stevens"
-.%A "Jan-Simon Pendry"
-.%T "Portals in 4.4BSD"
-.%B "USENIX 1995 Technical Conference Proceedings"
-.%O "Berkeley, CA"
-.%I "Peter Honeyman"
-.Re
-.Sh HISTORY
-The
-.Nm
-utility first appeared in
-.Bx 4.4 .
-.Sh CAVEATS
-This file system may not be NFS-exported.
diff --git a/usr.sbin/mount_portalfs/mount_portalfs.c b/usr.sbin/mount_portalfs/mount_portalfs.c
deleted file mode 100644
index 3bffbb1..0000000
--- a/usr.sbin/mount_portalfs/mount_portalfs.c
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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
-static const char copyright[] =
-"@(#) Copyright (c) 1992, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#if 0
-static char sccsid[] = "@(#)mount_portal.c 8.6 (Berkeley) 4/26/95";
-#endif
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/stat.h>
-#include <sys/syslog.h>
-#include <sys/mount.h>
-
-#include <err.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sysexits.h>
-#include <unistd.h>
-
-#include "mntopts.h"
-#include "pathnames.h"
-#include "portald.h"
-
-struct mntopt mopts[] = {
- MOPT_STDOPTS,
- MOPT_END
-};
-
-static void usage(void) __dead2;
-
-static volatile sig_atomic_t readcf; /* Set when SIGHUP received */
-
-static void sighup(int sig __unused)
-{
- readcf ++;
-}
-
-static void sigchld(int sig __unused)
-{
- pid_t pid;
-
- while ((pid = waitpid((pid_t) -1, (int *) 0, WNOHANG)) > 0)
- ;
- /* wrtp - waitpid _doesn't_ return 0 when no children! */
-#ifdef notdef
- if (pid < 0 && errno != ECHILD)
- syslog(LOG_WARNING, "waitpid: %s", strerror(errno));
-#endif
-}
-
-int
-main(int argc, char *argv[])
-{
- struct portal_args args;
- struct sockaddr_un un;
- char *conf;
- char mountpt[MAXPATHLEN];
- int mntflags = 0;
- char tag[32];
- mode_t um;
-
- qelem q;
- int rc;
- int so;
- int error = 0;
-
- /*
- * Crack command line args
- */
- int ch;
-
- while ((ch = getopt(argc, argv, "o:")) != -1) {
- switch (ch) {
- case 'o':
- getmntopts(optarg, mopts, &mntflags, 0);
- break;
- default:
- error = 1;
- break;
- }
- }
-
- if (optind != (argc - 2))
- error = 1;
-
- if (error)
- usage();
-
- /*
- * Get config file and mount point
- */
- conf = argv[optind];
- if (conf[0] != '/') {
- (void)fprintf(stderr,
- "The configuration file must be specified"
- "through an absolute file path.\n");
- exit(EX_USAGE);
- }
-
- /* resolve the mountpoint with realpath(3) */
- if (checkpath(argv[optind+1], mountpt) != 0)
- err(EX_USAGE, "%s", mountpt);
-
- /*
- * Construct the listening socket
- */
- un.sun_family = AF_UNIX;
- if (sizeof(_PATH_TMPPORTAL) >= sizeof(un.sun_path)) {
- errx(EX_SOFTWARE, "portal socket name too long");
- }
- strcpy(un.sun_path, _PATH_TMPPORTAL);
- mktemp(un.sun_path);
- un.sun_len = strlen(un.sun_path);
-
- so = socket(AF_UNIX, SOCK_STREAM, 0);
- if (so < 0) {
- err(EX_OSERR, "socket");
- }
- um = umask(077);
- (void) unlink(un.sun_path);
- if (bind(so, (struct sockaddr *) &un, sizeof(un)) < 0)
- err(1, NULL);
-
- (void) unlink(un.sun_path);
- (void) umask(um);
-
- (void) listen(so, 5);
-
- args.pa_socket = so;
- sprintf(tag, "portal:%d", getpid());
- args.pa_config = tag;
-
- rc = mount("portalfs", mountpt, mntflags, &args);
- if (rc < 0)
- err(1, NULL);
-
- /*
- * Everything is ready to go - now is a good time to fork
- */
-#ifndef DEBUG
- daemon(0, 0);
-#endif
-
- /*
- * Start logging (and change name)
- */
- openlog("portald", LOG_CONS|LOG_PID, LOG_DAEMON);
-
- q.q_forw = q.q_back = &q;
- readcf = 1;
-
- signal(SIGCHLD, sigchld);
- signal(SIGHUP, sighup);
-
- /*
- * Just loop waiting for new connections and activating them
- */
- for (;;) {
- struct sockaddr_un un2;
- int len2 = sizeof(un2);
- int so2;
- pid_t pid;
- fd_set fdset;
-
- /*
- * Check whether we need to re-read the configuration file
- */
- if (readcf) {
-#ifdef DEBUG
- printf ("re-reading configuration file\n");
-#endif
- readcf = 0;
- conf_read(&q, conf);
- continue;
- }
-
- /*
- * Accept a new connection
- * Will get EINTR if a signal has arrived, so just
- * ignore that error code
- */
- FD_ZERO(&fdset);
- FD_SET(so, &fdset);
- rc = select(so+1, &fdset, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);
- if (rc < 0) {
- if (errno == EINTR)
- continue;
- syslog(LOG_ERR, "select: %s", strerror(errno));
- exit(EX_OSERR);
- }
- if (rc == 0)
- break;
- so2 = accept(so, (struct sockaddr *) &un2, &len2);
- if (so2 < 0) {
- /*
- * The unmount function does a shutdown on the socket
- * which will generated ECONNABORTED on the accept.
- */
- if (errno == ECONNABORTED)
- break;
- if (errno != EINTR) {
- syslog(LOG_ERR, "accept: %s", strerror(errno));
- exit(EX_OSERR);
- }
- continue;
- }
-
- /*
- * Now fork a new child to deal with the connection
- */
- eagain:;
- switch (pid = fork()) {
- case -1:
- if (errno == EAGAIN) {
- sleep(1);
- goto eagain;
- }
- syslog(LOG_ERR, "fork: %s", strerror(errno));
- break;
- case 0:
- (void) close(so);
- activate(&q, so2);
- exit(0);
- default:
- (void) close(so2);
- break;
- }
- }
- syslog(LOG_INFO, "%s unmounted", mountpt);
- exit(0);
-}
-
-static void
-usage(void)
-{
- (void)fprintf(stderr,
- "usage: mount_portalfs [-o options] config mount-point\n");
- exit(EX_USAGE);
-}
diff --git a/usr.sbin/mount_portalfs/portal.conf b/usr.sbin/mount_portalfs/portal.conf
deleted file mode 100644
index 398cfb2..0000000
--- a/usr.sbin/mount_portalfs/portal.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-# @(#)portal.conf 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-tcplisten/ tcplisten tcplisten/
-tcp/ tcp tcp/
-fs/ file fs/
-pipe/ pipe pipe/
-foo/ exec ./bar bar baz
diff --git a/usr.sbin/mount_portalfs/portald.h b/usr.sbin/mount_portalfs/portald.h
deleted file mode 100644
index 99cd5d7..0000000
--- a/usr.sbin/mount_portalfs/portald.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)portald.h 8.1 (Berkeley) 6/5/93
- *
- * $FreeBSD$
- */
-
-#include <sys/cdefs.h>
-#include <sys/ucred.h>
-#include <fs/portalfs/portal.h>
-
-/*
- * Meta-chars in an RE. Paths in the config file containing
- * any of these characters will be matched using regexec, other
- * paths will be prefix-matched.
- */
-#define RE_CHARS ".|()[]*+?\\^$"
-
-typedef struct qelem qelem;
-
-struct qelem {
- qelem *q_forw;
- qelem *q_back;
-};
-
-typedef struct provider provider;
-struct provider {
- const char *pr_match;
- int (*pr_func)(struct portal_cred *,
- char *key, char **v, int so, int *fdp);
-};
-extern provider providers[];
-
-/*
- * Portal providers
- */
-extern int portal_exec(struct portal_cred *,
- char *key, char **v, int so, int *fdp);
-extern int portal_file(struct portal_cred *,
- char *key, char **v, int so, int *fdp);
-extern int portal_pipe(struct portal_cred *,
- char *key, char **v, int so, int *fdp);
-extern int portal_tcp(struct portal_cred *,
- char *key, char **v, int so, int *fdp);
-extern int portal_tcplisten(struct portal_cred *,
- char *key, char **v, int so, int *fdp);
-
-/*
- * Global functions
- */
-extern void activate(qelem *q, int so);
-extern char **conf_match(qelem *q, char *key);
-extern void conf_read(qelem *q, char *conf);
-extern int set_user_credentials(struct portal_cred *user,
- struct portal_cred *save_area);
-extern int restore_credentials(struct portal_cred *save_area);
diff --git a/usr.sbin/mount_portalfs/pt_conf.c b/usr.sbin/mount_portalfs/pt_conf.c
deleted file mode 100644
index 7f1e817..0000000
--- a/usr.sbin/mount_portalfs/pt_conf.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)pt_conf.c 8.1 (Berkeley) 6/5/93
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include "portald.h"
-
-provider providers[] = {
- { "exec", portal_exec },
- { "file", portal_file },
- { "pipe", portal_pipe },
- { "tcp", portal_tcp },
- { "tcplisten", portal_tcplisten },
- { 0, 0 }
-};
diff --git a/usr.sbin/mount_portalfs/pt_exec.c b/usr.sbin/mount_portalfs/pt_exec.c
deleted file mode 100644
index 86a47e9..0000000
--- a/usr.sbin/mount_portalfs/pt_exec.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)pt_exec.c 8.1 (Berkeley) 6/5/93
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-
-#include "portald.h"
-
-int portal_exec(struct portal_cred *pcr __unused, char *key __unused,
- char **v __unused, int so __unused, int *fdp __unused)
-{
- return (ENOEXEC);
-}
-
diff --git a/usr.sbin/mount_portalfs/pt_file.c b/usr.sbin/mount_portalfs/pt_file.c
deleted file mode 100644
index 270f812..0000000
--- a/usr.sbin/mount_portalfs/pt_file.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)pt_file.c 8.3 (Berkeley) 7/3/94
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-
-#include "portald.h"
-
-int portal_file(struct portal_cred *pcr,
- char *key, char **v, int so __unused, int *fdp)
-{
- int fd;
- char pbuf[MAXPATHLEN];
- int error;
- struct portal_cred save_area;
-
- pbuf[0] = '/';
- strcpy(pbuf+1, key + (v[1] ? strlen(v[1]) : 0));
-
-#ifdef DEBUG
- printf("path = %s, uid = %d, gid = %d\n", pbuf, pcr->pcr_uid, pcr->pcr_groups[0]);
- printf ("fflag = %x, oflag = %x\n", pcr->pcr_flag, (pcr->pcr_flag)-1);
-#endif
-
- if (set_user_credentials(pcr, &save_area) < 0)
- return (errno);
-
- /* dmb convert kernel flags to oflags, see <fcntl.h> */
- fd = open(pbuf, (pcr->pcr_flag)-1, 0777);
- if (fd < 0)
- error = errno;
- else
- error = 0;
-
- if (restore_credentials(&save_area) < 0) {
- error = errno;
- if (fd >= 0) {
- (void) close(fd);
- fd = -1;
- }
- }
-
- if (error == 0)
- *fdp = fd;
-
-#ifdef DEBUG
- fprintf(stderr, "pt_file returns *fdp = %d, error = %d\n", *fdp, error);
-#endif
-
- return (error);
-}
diff --git a/usr.sbin/mount_portalfs/pt_pipe.c b/usr.sbin/mount_portalfs/pt_pipe.c
deleted file mode 100644
index 84ee6e4..0000000
--- a/usr.sbin/mount_portalfs/pt_pipe.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*-
- * Copyright (C) 2005 Diomidis Spinellis. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-
-#include "portald.h"
-
-/* Usage conventions for the pipe's endpoints. */
-#define READ_END 0
-#define WRITE_END 1
-
-static int errlog(void);
-static int parse_argv(char *args, char **argv);
-
-int portal_pipe(struct portal_cred *pcr, char *key, char **v,
- int kso __unused, int *fdp)
-{
- int fd[2]; /* Pipe endpoints. */
- int caller_end; /* The pipe end we will use. */
- int process_end; /* The pipe end the spawned process will use. */
- int redirect_fd; /* The fd to redirect on the spawned process. */
- char pbuf[MAXPATHLEN];
- int error = 0;
- int i;
- char **argv;
- int argc;
- struct portal_cred save_area;
-
- /* Validate open mode, and assign roles. */
- if ((pcr->pcr_flag & FWRITE) && (pcr->pcr_flag & FREAD))
- /* Don't allow both on a single fd. */
- return (EINVAL);
- else if (pcr->pcr_flag & FREAD) {
- /*
- * The caller reads from the pipe,
- * the spawned process writes to it.
- */
- caller_end = READ_END;
- process_end = WRITE_END;
- redirect_fd = STDOUT_FILENO;
- } else if (pcr->pcr_flag & FWRITE) {
- /*
- * The caller writes to the pipe,
- * the spawned process reads from it.
- */
- caller_end = WRITE_END;
- process_end = READ_END;
- redirect_fd = STDIN_FILENO;
- } else
- return (EINVAL);
-
- /* Get and check command line. */
- pbuf[0] = '/';
- strcpy(pbuf+1, key + (v[1] ? strlen(v[1]) : 0));
- argc = parse_argv(pbuf, NULL);
- if (argc == 0)
- return (ENOENT);
-
- /* Swap privileges. */
- if (set_user_credentials(pcr, &save_area) < 0)
- return (errno);
-
- /* Redirect and spawn the specified process. */
- fd[READ_END] = fd[WRITE_END] = -1;
- if (pipe(fd) < 0) {
- error = errno;
- goto done;
- }
- switch (fork()) {
- case -1: /* Error */
- error = errno;
- break;
- default: /* Parent */
- (void)close(fd[process_end]);
- break;
- case 0: /* Child */
- argv = (char **)malloc((argc + 1) * sizeof(char *));
- if (argv == 0) {
- syslog(LOG_ALERT,
- "malloc: failed to get space for %d pointers",
- argc + 1);
- exit(EXIT_FAILURE);
- }
- parse_argv(pbuf, argv);
-
- if (dup2(fd[process_end], redirect_fd) < 0) {
- syslog(LOG_ERR, "dup2: %m");
- exit(EXIT_FAILURE);
- }
- (void)close(fd[caller_end]);
- (void)close(fd[process_end]);
- if (errlog() < 0) {
- syslog(LOG_ERR, "errlog: %m");
- exit(EXIT_FAILURE);
- }
- if (execv(argv[0], argv) < 0) {
- syslog(LOG_ERR, "execv(%s): %m", argv[0]);
- exit(EXIT_FAILURE);
- }
- /* NOTREACHED */
- }
-
-done:
- /* Re-establish our privileges. */
- if (restore_credentials(&save_area) < 0)
- error = errno;
-
- /* Set return fd value. */
- if (error == 0)
- *fdp = fd[caller_end];
- else {
- for (i = 0; i < 2; i++)
- if (fd[i] >= 0)
- (void)close(fd[i]);
- *fdp = -1;
- }
-
- return (error);
-}
-
-/*
- * Redirect stderr to the system log.
- * Return 0 if ok.
- * Return -1 with errno set on error.
- */
-static int
-errlog(void)
-{
- int fd[2];
- char buff[1024];
- FILE *f;
- int ret = 0;
-
- if (pipe(fd) < 0)
- return (-1);
- switch (fork()) {
- case -1: /* Error */
- return (-1);
- case 0: /* Child */
- if ((f = fdopen(fd[READ_END], "r")) == NULL) {
- syslog(LOG_ERR, "fdopen: %m");
- exit(EXIT_FAILURE);
- }
- (void)close(fd[WRITE_END]);
- while (fgets(buff, sizeof(buff), f) != NULL)
- syslog(LOG_ERR, "exec: %s", buff);
- exit(EXIT_SUCCESS);
- /* NOTREACHED */
- default: /* Parent */
- if (dup2(fd[WRITE_END], STDERR_FILENO) < 0)
- ret = -1;
- (void)close(fd[READ_END]);
- (void)close(fd[WRITE_END]);
- break;
- }
- return (ret);
-}
-
-/*
- * Parse the args string as a space-separated argument vector.
- * If argv is not NULL, split the string into its constituent
- * components, and set argv to point to the beginning of each
- * string component; NULL-terminating argv.
- * Return the number of string components.
- */
-static int
-parse_argv(char *args, char **argv)
-{
- int count = 0;
- char *p;
- enum {WORD, SPACE} state = SPACE;
-
- for (p = args; *p; p++)
- switch (state) {
- case WORD:
- if (isspace(*p)) {
- if (argv)
- *p = '\0';
- state = SPACE;
- }
- break;
- case SPACE:
- if (!isspace(*p)) {
- if (argv)
- argv[count] = p;
- count++;
- state = WORD;
- }
- }
- if (argv)
- argv[count] = NULL;
- return (count);
-}
diff --git a/usr.sbin/mount_portalfs/pt_tcp.c b/usr.sbin/mount_portalfs/pt_tcp.c
deleted file mode 100644
index d9a2a1e..0000000
--- a/usr.sbin/mount_portalfs/pt_tcp.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 1992, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)pt_tcp.c 8.5 (Berkeley) 4/28/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include "portald.h"
-
-/*
- * Key will be tcp/host/port[/"priv"]
- * Create a TCP socket connected to the
- * requested host and port.
- * Some trailing suffix values have special meanings.
- * An unrecognized suffix is an error.
- */
-int portal_tcp(struct portal_cred *pcr, char *key, char **v,
- int kso __unused, int *fdp)
-{
- char host[MAXHOSTNAMELEN];
- char port[MAXHOSTNAMELEN];
- char *p = key + (v[1] ? strlen(v[1]) : 0);
- char *q;
- struct hostent *hp;
- struct servent *sp;
- struct in_addr **ipp;
- struct in_addr *ip[2];
- struct in_addr ina;
- u_short s_port;
- int priv = 0;
- struct sockaddr_in sain;
-
- q = strchr(p, '/');
- if (q == 0 || q - p >= (int)sizeof(host))
- return (EINVAL);
- *q = '\0';
- strcpy(host, p);
- p = q + 1;
-
- q = strchr(p, '/');
- if (q)
- *q = '\0';
- if (strlen(p) >= sizeof(port))
- return (EINVAL);
- strcpy(port, p);
- if (q) {
- p = q + 1;
- if (strcmp(p, "priv") == 0) {
- if (pcr->pcr_uid == 0)
- priv = 1;
- else
- return (EPERM);
- } else {
- return (EINVAL);
- }
- }
-
- hp = gethostbyname(host);
- if (hp != 0) {
- ipp = (struct in_addr **) hp->h_addr_list;
- } else {
- ina.s_addr = inet_addr(host);
- if (ina.s_addr == INADDR_NONE)
- return (EINVAL);
- ip[0] = &ina;
- ip[1] = 0;
- ipp = ip;
- }
-#ifdef DEBUG
- printf ("inet address for %s is %s\n", host, inet_ntoa(*ipp[0]));
-#endif
-
- sp = getservbyname(port, "tcp");
- if (sp != NULL) {
- s_port = (u_short)sp->s_port;
- } else {
- s_port = strtoul(port, &p, 0);
- if (s_port == 0 || *p != '\0')
- return (EINVAL);
- s_port = htons(s_port);
- }
-#ifdef DEBUG
- printf ("port number for %s is %d\n", port, (int)ntohs(s_port));
-#endif
-
- memset(&sain, 0, sizeof(sain));
- sain.sin_len = sizeof(sain);
- sain.sin_family = AF_INET;
- sain.sin_port = s_port;
-
- while (ipp[0]) {
- int so;
-
- if (priv)
- so = rresvport((int *) 0);
- else
- so = socket(AF_INET, SOCK_STREAM, 0);
- if (so < 0) {
- syslog(LOG_ERR, "socket: %m");
- return (errno);
- }
-
- sain.sin_addr = *ipp[0];
- if (connect(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
- *fdp = so;
- return (0);
- }
- (void) close(so);
-
- ipp++;
- }
-
- return (errno);
-}
diff --git a/usr.sbin/mount_portalfs/pt_tcplisten.c b/usr.sbin/mount_portalfs/pt_tcplisten.c
deleted file mode 100644
index 3bd29c1..0000000
--- a/usr.sbin/mount_portalfs/pt_tcplisten.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- * All rights reserved.
- *
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
- * Modified by Duncan Barclay.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must 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.
- *
- * @(#)pt_tcp.c 8.3 (Berkeley) 3/27/94
- *
- * pt_tcp.c,v 1.1.1.1 1994/05/26 06:34:34 rgrimes Exp
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/syslog.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include "portald.h"
-
-/*
- * Key will be tcplisten/host/port
- *
- * Create a TCP socket bound to the requested host and port.
- * If the host is "ANY" the receiving address will be set to INADDR_ANY.
- * If the port is 0 the caller must find out the returned port number
- * using a call to getsockname.
- *
- * XXX! The owner of the socket will be root rather then the user. This
- * may cause remote auth (identd) to return unexpected results.
- *
- */
-int portal_tcplisten(struct portal_cred *pcr, char *key, char **v,
- int kso __unused, int *fdp)
-{
- char host[MAXHOSTNAMELEN];
- char port[MAXHOSTNAMELEN];
- char *p = key + (v[1] ? strlen(v[1]) : 0);
- char *q;
- struct hostent *hp;
- struct servent *sp;
- struct in_addr **ipp = NULL;
- struct in_addr *ip[2];
- struct in_addr ina;
- u_short s_port;
- int any = 0;
- struct sockaddr_in sain;
-
- q = strchr(p, '/');
- if (q == 0 || q - p >= (int)sizeof(host))
- return (EINVAL);
- *q = '\0';
- snprintf(host, sizeof(host), "%s", p);
- p = q + 1;
-
- q = strchr(p, '/');
- if (q)
- *q = '\0';
- if (strlen(p) >= sizeof(port))
- return (EINVAL);
- snprintf(port, sizeof(port), "%s", p);
-
- if (strcmp(host, "ANY") == 0) {
- any = 1;
- } else {
- hp = gethostbyname(host);
- if (hp != 0) {
- ipp = (struct in_addr **) hp->h_addr_list;
- } else {
- ina.s_addr = inet_addr(host);
- if (ina.s_addr == INADDR_NONE)
- return (EINVAL);
- ip[0] = &ina;
- ip[1] = 0;
- ipp = ip;
- }
- }
-#ifdef DEBUG
- if (any)
- printf("INADDR_ANY to be used for hostname\n");
- else
- printf("inet address for %s is %s\n", host, inet_ntoa(*ipp[0]));
-#endif
-
- sp = getservbyname(port, "tcp");
- if (sp != NULL) {
- s_port = (u_short) sp->s_port;
- } else {
- s_port = strtoul(port, &p, 0);
- if (*p != '\0')
- return (EINVAL);
- s_port = htons(s_port);
- }
- if ((ntohs(s_port) != 0) &&
- (ntohs(s_port) <= IPPORT_RESERVED) &&
- (pcr->pcr_uid != 0))
- return (EPERM);
-#ifdef DEBUG
- printf("port number for %s is %d\n", port, ntohs(s_port));
-#endif
-
- memset(&sain, 0, sizeof(sain));
- sain.sin_len = sizeof(sain);
- sain.sin_family = AF_INET;
- sain.sin_port = s_port;
-
- if (any) {
- int so;
- int sock;
-
- so = socket(AF_INET, SOCK_STREAM, 0);
- if (so < 0) {
- syslog(LOG_ERR, "socket: %m");
- return (errno);
- }
-
- sain.sin_addr.s_addr = INADDR_ANY;
- if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
- listen(so, 1);
- if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) {
- syslog(LOG_ERR, "accept: %m");
- (void) close(so);
- return (errno);
- }
- *fdp = sock;
- (void) close(so);
- return (0);
- }
- syslog(LOG_ERR, "bind: %m");
- (void) close(so);
- return (errno);
- }
-
- while (ipp[0]) {
- int so;
- int sock;
-
- so = socket(AF_INET, SOCK_STREAM, 0);
- if (so < 0) {
- syslog(LOG_ERR, "socket: %m");
- return (errno);
- }
-
- sain.sin_addr = *ipp[0];
- if (bind(so, (struct sockaddr *) &sain, sizeof(sain)) == 0) {
- listen(so, 1);
- if ((sock = accept(so, (struct sockaddr *)0, (int *)0)) == -1) {
- syslog(LOG_ERR, "accept: %m");
- (void) close(so);
- return (errno);
- }
- *fdp = sock;
- (void) close(so);
- return (0);
- }
- (void) close(so);
-
- ipp++;
- }
-
- syslog(LOG_ERR, "bind: %m");
- return (errno);
-
-}
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index bc290d6..1913410 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -2235,7 +2235,7 @@ do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp,
ep->ex_indexfile = strdup(cpoptarg);
} else if (!strcmp(cpopt, "quiet")) {
opt_flags |= OP_QUIET;
- } else if (!strcmp(cpopt, "sec")) {
+ } else if (cpoptarg && !strcmp(cpopt, "sec")) {
if (parsesec(cpoptarg, ep))
return (1);
opt_flags |= OP_SEC;
diff --git a/usr.sbin/moused/moused.c b/usr.sbin/moused/moused.c
index 93eec99..0e278c4 100644
--- a/usr.sbin/moused/moused.c
+++ b/usr.sbin/moused/moused.c
@@ -245,6 +245,7 @@ static symtab_t rmodels[] = {
{ "4D Mouse", MOUSE_MODEL_4D, 0 },
{ "4D+ Mouse", MOUSE_MODEL_4DPLUS, 0 },
{ "Synaptics Touchpad", MOUSE_MODEL_SYNAPTICS, 0 },
+ { "TrackPoint", MOUSE_MODEL_TRACKPOINT, 0 },
{ "generic", MOUSE_MODEL_GENERIC, 0 },
{ NULL, MOUSE_MODEL_UNKNOWN, 0 },
};
diff --git a/usr.sbin/mptutil/mptutil.8 b/usr.sbin/mptutil/mptutil.8
index bd76ce8..e8b617f 100644
--- a/usr.sbin/mptutil/mptutil.8
+++ b/usr.sbin/mptutil/mptutil.8
@@ -196,7 +196,7 @@ If any hot spare drives are configured, then they are listed as well.
Lists all of the physical drives attached to the controller.
.It Cm show events
Display all the entries from the controller's event log.
-Due to lack of documentation this command isn't very useful currently and
+Due to lack of documentation this command is not very useful currently and
just dumps each log entry in hex.
.It Cm show volumes
Lists all of the logical volumes managed by the controller.
@@ -388,7 +388,7 @@ The mpt version 1 API that is used by
.Nm
and
.Xr mpt 4
-doesn't support volumes above two terabytes.
+does not support volumes above two terabytes.
This is a limitation of the API.
If you are using this adapter with volumes larger than two terabytes, use the adapter in JBOD mode.
Utilize
diff --git a/usr.sbin/named/Makefile b/usr.sbin/named/Makefile
index 1200c7e..4743a7b 100644
--- a/usr.sbin/named/Makefile
+++ b/usr.sbin/named/Makefile
@@ -48,7 +48,7 @@ CFLAGS+= -I${SRCDIR}/unix/include -I${SRCDIR}/include -I${LIB_BIND_DIR}
CFLAGS+= -I${BIND_DIR}/lib/isc/${ISC_ATOMIC_ARCH}/include
# Remove the date stamp to make it more obvious when real changes happen
-CFLAGS+= -U__DATE__
+CFLAGS+= -DNO_VERSION_DATE
WARNS?= 0
diff --git a/usr.sbin/newsyslog/newsyslog.c b/usr.sbin/newsyslog/newsyslog.c
index d0ef3d3..08598ac 100644
--- a/usr.sbin/newsyslog/newsyslog.c
+++ b/usr.sbin/newsyslog/newsyslog.c
@@ -276,7 +276,7 @@ static void parse_args(int argc, char **argv);
static int parse_doption(const char *doption);
static void usage(void);
static int log_trim(const char *logname, const struct conf_entry *log_ent);
-static int age_old_log(char *file);
+static int age_old_log(const char *file);
static void savelog(char *from, char *to);
static void createdir(const struct conf_entry *ent, char *dirpart);
static void createlog(const struct conf_entry *ent);
@@ -1447,20 +1447,78 @@ oldlog_entry_compare(const void *a, const void *b)
}
/*
+ * Check whether the file corresponding to dp is an archive of the logfile
+ * logfname, based on the timefnamefmt format string. Return true and fill out
+ * tm if this is the case; otherwise return false.
+ */
+static int
+validate_old_timelog(const struct dirent *dp, const char *logfname, struct tm *tm)
+{
+ size_t logfname_len;
+ char *s;
+ int c;
+
+ logfname_len = strlen(logfname);
+
+ if (dp->d_type != DT_REG)
+ return (0);
+ /* Ignore everything but files with our logfile prefix. */
+ if (strncmp(dp->d_name, logfname, logfname_len) != 0)
+ return (0);
+ /* Ignore the actual non-rotated logfile. */
+ if (dp->d_namlen == logfname_len)
+ return (0);
+
+ /*
+ * Make sure we created have found a logfile, so the
+ * postfix is valid, IE format is: '.<time>(.[bgx]z)?'.
+ */
+ if (dp->d_name[logfname_len] != '.') {
+ if (verbose)
+ printf("Ignoring %s which has unexpected "
+ "extension '%s'\n", dp->d_name,
+ &dp->d_name[logfname_len]);
+ return (0);
+ }
+ if ((s = strptime(&dp->d_name[logfname_len + 1],
+ timefnamefmt, tm)) == NULL) {
+ /*
+ * We could special case "old" sequentially named logfiles here,
+ * but we do not as that would require special handling to
+ * decide which one was the oldest compared to "new" time based
+ * logfiles.
+ */
+ if (verbose)
+ printf("Ignoring %s which does not "
+ "match time format\n", dp->d_name);
+ return (0);
+ }
+
+ for (c = 0; c < COMPRESS_TYPES; c++)
+ if (strcmp(s, compress_type[c].suffix) == 0)
+ /* We're done. */
+ return (1);
+
+ if (verbose)
+ printf("Ignoring %s which has unexpected extension '%s'\n",
+ dp->d_name, s);
+
+ return (0);
+}
+
+/*
* Delete the oldest logfiles, when using time based filenames.
*/
static void
delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
{
char *logfname, *s, *dir, errbuf[80];
- int dir_fd, i, logcnt, max_logcnt, valid;
+ int dir_fd, i, logcnt, max_logcnt;
struct oldlog_entry *oldlogs;
- size_t logfname_len;
struct dirent *dp;
const char *cdir;
struct tm tm;
DIR *dirp;
- int c;
oldlogs = malloc(MAX_OLDLOGS * sizeof(struct oldlog_entry));
max_logcnt = MAX_OLDLOGS;
@@ -1478,7 +1536,6 @@ delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
err(1, "basename()");
if ((logfname = strdup(s)) == NULL)
err(1, "strdup()");
- logfname_len = strlen(logfname);
if (strcmp(logfname, "/") == 0)
errx(1, "Invalid log filename - became '/'");
@@ -1490,50 +1547,8 @@ delete_oldest_timelog(const struct conf_entry *ent, const char *archive_dir)
err(1, "Cannot open log directory '%s'", dir);
dir_fd = dirfd(dirp);
while ((dp = readdir(dirp)) != NULL) {
- if (dp->d_type != DT_REG)
- continue;
-
- /* Ignore everything but files with our logfile prefix */
- if (strncmp(dp->d_name, logfname, logfname_len) != 0)
- continue;
- /* Ignore the actual non-rotated logfile */
- if (dp->d_namlen == logfname_len)
- continue;
- /*
- * Make sure we created have found a logfile, so the
- * postfix is valid, IE format is: '.<time>(.[bg]z)?'.
- */
- if (dp->d_name[logfname_len] != '.') {
- if (verbose)
- printf("Ignoring %s which has unexpected "
- "extension '%s'\n", dp->d_name,
- &dp->d_name[logfname_len]);
+ if (validate_old_timelog(dp, logfname, &tm) == 0)
continue;
- }
- if ((s = strptime(&dp->d_name[logfname_len + 1],
- timefnamefmt, &tm)) == NULL) {
- /*
- * We could special case "old" sequentially
- * named logfiles here, but we do not as that
- * would require special handling to decide
- * which one was the oldest compared to "new"
- * time based logfiles.
- */
- if (verbose)
- printf("Ignoring %s which does not "
- "match time format\n", dp->d_name);
- continue;
- }
-
- for (c = 0; c < COMPRESS_TYPES; c++)
- if (strcmp(s, compress_type[c].suffix) == 0)
- valid = 1;
- if (valid != 1) {
- if (verbose)
- printf("Ignoring %s which has unexpected "
- "extension '%s'\n", dp->d_name, s);
- continue;
- }
/*
* We should now have old an old rotated logfile, so
@@ -2260,13 +2275,66 @@ sizefile(const char *file)
return (kbytes(dbtob(sb.st_blocks)));
}
-/* Return the age of old log file (file.0) */
+/*
+ * Return the mtime of the most recent archive of the logfile, using timestamp
+ * based filenames.
+ */
+static time_t
+mtime_old_timelog(const char *file)
+{
+ struct stat sb;
+ struct tm tm;
+ int dir_fd;
+ time_t t;
+ struct dirent *dp;
+ DIR *dirp;
+ char *s, *logfname, *dir;
+
+ t = -1;
+
+ if ((dir = dirname(file)) == NULL) {
+ warn("dirname() of '%s'", file);
+ return (t);
+ }
+ if ((s = basename(file)) == NULL) {
+ warn("basename() of '%s'", file);
+ return (t);
+ } else if (s[0] == '/') {
+ warnx("Invalid log filename '%s'", s);
+ return (t);
+ } else if ((logfname = strdup(s)) == NULL)
+ err(1, "strdup()");
+
+ if ((dirp = opendir(dir)) == NULL) {
+ warn("Cannot open log directory '%s'", dir);
+ return (t);
+ }
+ dir_fd = dirfd(dirp);
+ /* Open the archive dir and find the most recent archive of logfname. */
+ while ((dp = readdir(dirp)) != NULL) {
+ if (validate_old_timelog(dp, logfname, &tm) == 0)
+ continue;
+
+ if (fstatat(dir_fd, logfname, &sb, 0) == -1) {
+ warn("Cannot stat '%s'", file);
+ continue;
+ }
+ if (t < sb.st_mtime)
+ t = sb.st_mtime;
+ }
+ closedir(dirp);
+
+ return (t);
+}
+
+/* Return the age in hours of the most recent archive of the logfile. */
static int
-age_old_log(char *file)
+age_old_log(const char *file)
{
struct stat sb;
const char *logfile_suffix;
char tmp[MAXPATHLEN + sizeof(".0") + COMPRESS_SUFFIX_MAXLEN + 1];
+ time_t mtime;
if (archtodir) {
char *p;
@@ -2295,14 +2363,22 @@ age_old_log(char *file)
(void) strlcpy(tmp, file, sizeof(tmp));
}
- strlcat(tmp, ".0", sizeof(tmp));
- logfile_suffix = get_logfile_suffix(tmp);
- if (logfile_suffix == NULL)
- return (-1);
- (void) strlcat(tmp, logfile_suffix, sizeof(tmp));
- if (stat(tmp, &sb) < 0)
- return (-1);
- return ((int)(ptimeget_secs(timenow) - sb.st_mtime + 1800) / 3600);
+ if (timefnamefmt != NULL) {
+ mtime = mtime_old_timelog(tmp);
+ if (mtime == -1)
+ return (-1);
+ } else {
+ strlcat(tmp, ".0", sizeof(tmp));
+ logfile_suffix = get_logfile_suffix(tmp);
+ if (logfile_suffix == NULL)
+ return (-1);
+ (void) strlcat(tmp, logfile_suffix, sizeof(tmp));
+ if (stat(tmp, &sb) < 0)
+ return (-1);
+ mtime = sb.st_mtime;
+ }
+
+ return ((int)(ptimeget_secs(timenow) - mtime + 1800) / 3600);
}
/* Skip Over Blanks */
diff --git a/usr.sbin/nfsd/nfsd.c b/usr.sbin/nfsd/nfsd.c
index 0e39138..b114ba6 100644
--- a/usr.sbin/nfsd/nfsd.c
+++ b/usr.sbin/nfsd/nfsd.c
@@ -105,20 +105,21 @@ static struct option longopts[] = {
{ NULL, 0, NULL, 0}
};
-void cleanup(int);
-void child_cleanup(int);
-void killchildren(void);
-void nfsd_exit(int);
-void nonfs(int);
-void reapchild(int);
-int setbindhost(struct addrinfo **ia, const char *bindhost,
- struct addrinfo hints);
-void start_server(int);
-void unregistration(void);
-void usage(void);
-void open_stable(int *, int *);
-void copy_stable(int, int);
-void backup_stable(int);
+static void cleanup(int);
+static void child_cleanup(int);
+static void killchildren(void);
+static void nfsd_exit(int);
+static void nonfs(int);
+static void reapchild(int);
+static int setbindhost(struct addrinfo **ia, const char *bindhost,
+ struct addrinfo hints);
+static void start_server(int);
+static void unregistration(void);
+static void usage(void);
+static void open_stable(int *, int *);
+static void copy_stable(int, int);
+static void backup_stable(int);
+static void set_nfsdcnt(int);
/*
* Nfs server daemon mostly just a user context for nfssvc()
@@ -178,8 +179,7 @@ main(int argc, char **argv)
bindanyflag = 1;
break;
case 'n':
- nfsdcnt_set = 1;
- nfsdcnt = atoi(optarg);
+ set_nfsdcnt(atoi(optarg));
break;
case 'h':
bindhostc++;
@@ -235,15 +235,8 @@ main(int argc, char **argv)
*/
if (argc > 1)
usage();
- if (argc == 1) {
- nfsdcnt_set = 1;
- nfsdcnt = atoi(argv[0]);
- if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) {
- warnx("nfsd count %d; reset to %d", nfsdcnt,
- DEFNFSDCNT);
- nfsdcnt = DEFNFSDCNT;
- }
- }
+ if (argc == 1)
+ set_nfsdcnt(atoi(argv[0]));
/*
* Unless the "-o" option was specified, try and run "nfsd".
@@ -429,16 +422,6 @@ main(int argc, char **argv)
}
if (!new_syscall) {
- if (nfsdcnt < 1) {
- warnx("nfsd count too low %d; reset to %d", nfsdcnt,
- DEFNFSDCNT);
- nfsdcnt = DEFNFSDCNT;
- }
- if (nfsdcnt > MAXNFSDCNT) {
- warnx("nfsd count too high %d; reset to %d", nfsdcnt,
- DEFNFSDCNT);
- nfsdcnt = MAXNFSDCNT;
- }
/* If we use UDP only, we start the last server below. */
srvcnt = tcpflag ? nfsdcnt : nfsdcnt - 1;
for (i = 0; i < srvcnt; i++) {
@@ -844,7 +827,7 @@ main(int argc, char **argv)
}
}
-int
+static int
setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
{
int ecode;
@@ -890,20 +873,37 @@ setbindhost(struct addrinfo **ai, const char *bindhost, struct addrinfo hints)
return (0);
}
-void
+static void
+set_nfsdcnt(int proposed)
+{
+
+ if (proposed < 1) {
+ warnx("nfsd count too low %d; reset to %d", proposed,
+ DEFNFSDCNT);
+ nfsdcnt = DEFNFSDCNT;
+ } else if (proposed > MAXNFSDCNT) {
+ warnx("nfsd count too high %d; truncated to %d", proposed,
+ MAXNFSDCNT);
+ nfsdcnt = MAXNFSDCNT;
+ } else
+ nfsdcnt = proposed;
+ nfsdcnt_set = 1;
+}
+
+static void
usage(void)
{
(void)fprintf(stderr, "%s", getopt_usage);
exit(1);
}
-void
+static void
nonfs(__unused int signo)
{
syslog(LOG_ERR, "missing system call: NFS not available");
}
-void
+static void
reapchild(__unused int signo)
{
pid_t pid;
@@ -916,7 +916,7 @@ reapchild(__unused int signo)
}
}
-void
+static void
unregistration(void)
{
if ((!rpcb_unset(NFS_PROGRAM, 2, NULL)) ||
@@ -924,7 +924,7 @@ unregistration(void)
syslog(LOG_ERR, "rpcb_unset failed");
}
-void
+static void
killchildren(void)
{
int i;
@@ -938,7 +938,7 @@ killchildren(void)
/*
* Cleanup master after SIGUSR1.
*/
-void
+static void
cleanup(__unused int signo)
{
nfsd_exit(0);
@@ -947,13 +947,13 @@ cleanup(__unused int signo)
/*
* Cleanup child after SIGUSR1.
*/
-void
+static void
child_cleanup(__unused int signo)
{
exit(0);
}
-void
+static void
nfsd_exit(int status)
{
killchildren();
@@ -984,7 +984,7 @@ get_tuned_nfsdcount(void)
return tuned_nfsdcnt;
}
-void
+static void
start_server(int master)
{
char principal[MAXHOSTNAMELEN + 5];
@@ -1014,26 +1014,13 @@ start_server(int master)
}
nfsdargs.principal = principal;
- if (minthreads_set) {
- nfsdargs.minthreads = minthreads;
- if (!maxthreads_set)
- nfsdargs.maxthreads = minthreads;
- }
- if (maxthreads_set) {
- nfsdargs.maxthreads = maxthreads;
- if (!minthreads_set)
- nfsdargs.minthreads = maxthreads;
- }
- if (nfsdcnt_set) {
- nfsdargs.minthreads = nfsdcnt;
- nfsdargs.maxthreads = nfsdcnt;
- }
- if (!minthreads_set && !maxthreads_set && !nfsdcnt_set) {
- int tuned_nfsdcnt;
-
- tuned_nfsdcnt = get_tuned_nfsdcount();
- nfsdargs.minthreads = tuned_nfsdcnt;
- nfsdargs.maxthreads = tuned_nfsdcnt;
+ if (nfsdcnt_set)
+ nfsdargs.minthreads = nfsdargs.maxthreads = nfsdcnt;
+ else {
+ nfsdargs.minthreads = minthreads_set ? minthreads : get_tuned_nfsdcount();
+ nfsdargs.maxthreads = maxthreads_set ? maxthreads : nfsdargs.minthreads;
+ if (nfsdargs.maxthreads < nfsdargs.minthreads)
+ nfsdargs.maxthreads = nfsdargs.minthreads;
}
error = nfssvc(nfssvc_nfsd, &nfsdargs);
if (error < 0 && errno == EAUTH) {
@@ -1066,7 +1053,7 @@ start_server(int master)
/*
* Open the stable restart file and return the file descriptor for it.
*/
-void
+static void
open_stable(int *stable_fdp, int *backup_fdp)
{
int stable_fd, backup_fd = -1, ret;
@@ -1118,7 +1105,7 @@ open_stable(int *stable_fdp, int *backup_fdp)
/*
* Copy the stable restart file to the backup or vice versa.
*/
-void
+static void
copy_stable(int from_fd, int to_fd)
{
int cnt, ret;
@@ -1146,7 +1133,7 @@ copy_stable(int from_fd, int to_fd)
/*
* Back up the stable restart file when indicated by the kernel.
*/
-void
+static void
backup_stable(__unused int signo)
{
diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile
index 1b8cc01..138e28d 100644
--- a/usr.sbin/nmtree/Makefile
+++ b/usr.sbin/nmtree/Makefile
@@ -7,7 +7,7 @@
PROG= nmtree
MAN= nmtree.8
SRCS= compare.c crc.c create.c excludes.c getid.c misc.c mtree.c \
- spec.c specspec.c verify.c
+ only.c spec.c specspec.c verify.c
LDADD+= -lmd -lutil
CFLAGS+= -I${.CURDIR}/../../contrib/mknod
diff --git a/usr.sbin/pc-sysinstall/backend-query/disk-list.sh b/usr.sbin/pc-sysinstall/backend-query/disk-list.sh
index d390cbb..2616ef9 100755
--- a/usr.sbin/pc-sysinstall/backend-query/disk-list.sh
+++ b/usr.sbin/pc-sysinstall/backend-query/disk-list.sh
@@ -82,15 +82,10 @@ do
esac
fi
- # Try and find some identification information with camcontrol or atacontrol
+ # Try and find some identification information with camcontrol
NEWLINE=$(camcontrol identify $DEV 2>/dev/null | sed -ne 's/^device model *//p')
if [ -z "$NEWLINE" ]; then
- # Now try atacontrol
- NEWLINE=$(atacontrol list 2>/dev/null | sed -n "s|^.*$DEV <\(.*\)>.*|\1|p")
-
- if [ -z "$NEWLINE" ]; then
- NEWLINE=" <Unknown Device>"
- fi
+ NEWLINE=" <Unknown Device>"
fi
if [ -n "${FLAGS_MD}" ] && echo "${DEV}" | grep -E '^md[0-9]+' >/dev/null 2>/dev/null
diff --git a/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh b/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh
index 0eedfad..37353d7 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-bsdlabel.sh
@@ -62,7 +62,18 @@ get_fs_line_xvars()
echo $ZFSVARS | grep -qE "^(disk|file|mirror|raidz(1|2|3)?|spare|log|cache):" 2>/dev/null
if [ $? -eq 0 ] ; then
ZTYPE=`echo $ZFSVARS | cut -f1 -d:`
- ZFSVARS=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"`
+ tmpVars=`echo $ZFSVARS | sed "s|$ZTYPE: ||g" | sed "s|$ZTYPE:||g"`
+ ZFSVARS=""
+ # make sure we have a '/dev' in front of the extra devices
+ for i in $tmpVars
+ do
+ echo $i | grep -q '/dev/'
+ if [ $? -ne 0 ] ; then
+ ZFSVARS="$ZFSVARS /dev/${i}"
+ else
+ ZFSVARS="$ZFSVARS $i"
+ fi
+ done
fi
# Return the ZFS options
diff --git a/usr.sbin/pc-sysinstall/backend/functions-disk.sh b/usr.sbin/pc-sysinstall/backend/functions-disk.sh
index b1b815d..eac10d9 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-disk.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-disk.sh
@@ -33,6 +33,7 @@ is_disk()
for _dsk in `sysctl -n kern.disks`
do
[ "$_dsk" = "${1}" ] && return 0
+ [ "/dev/$_dsk" = "${1}" ] && return 0
done
return 1
diff --git a/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh b/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh
index 5d32466..fd6556d 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-extractimage.sh
@@ -29,23 +29,60 @@
. ${BACKEND}/functions-mountoptical.sh
+# Performs the extraction of data to disk from FreeBSD dist files
+start_extract_dist()
+{
+ if [ -z "$1" ] ; then exit_err "Called dist extraction with no directory set!"; fi
+ if [ -z "$INSFILE" ]; then exit_err "Called extraction with no install file set!"; fi
+ local DDIR="$1"
+
+ # Check if we are doing an upgrade, and if so use our exclude list
+ if [ "${INSTALLMODE}" = "upgrade" ]; then
+ TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade"
+ else
+ TAROPTS=""
+ fi
+
+ # Loop though and extract dist files
+ for di in $INSFILE
+ do
+ # Check the MANIFEST see if we have an archive size / count
+ if [ -e "${DDIR}/MANIFEST" ]; then
+ count=`grep "^${di}.txz" ${DDIR}/MANIFEST | awk '{print $3}'`
+ if [ ! -z "$count" ] ; then
+ echo "INSTALLCOUNT: $count"
+ fi
+ fi
+ echo_log "pc-sysinstall: Starting Extraction (${di})"
+ tar -xpv -C ${FSMNT} -f ${DDIR}/${di}.txz ${TAROPTS} >&1 2>&1
+ if [ $? -ne 0 ]; then
+ exit_err "ERROR: Failed extracting the dist file: $di"
+ fi
+ done
+
+ # Check if this was a FTP download and clean it up now
+ if [ "${INSTALLMEDIUM}" = "ftp" ]; then
+ echo_log "Cleaning up downloaded archives"
+ rm -rf ${DDIR}
+ fi
+
+ echo_log "pc-sysinstall: Extraction Finished"
+}
+
# Performs the extraction of data to disk from a uzip or tar archive
start_extract_uzip_tar()
{
- if [ -z "$INSFILE" ]
- then
+ if [ -z "$INSFILE" ]; then
exit_err "ERROR: Called extraction with no install file set!"
fi
# Check if we have a .count file, and echo it out for a front-end to use in progress bars
- if [ -e "${INSFILE}.count" ]
- then
+ if [ -e "${INSFILE}.count" ]; then
echo "INSTALLCOUNT: `cat ${INSFILE}.count`"
fi
# Check if we are doing an upgrade, and if so use our exclude list
- if [ "${INSTALLMODE}" = "upgrade" ]
- then
+ if [ "${INSTALLMODE}" = "upgrade" ]; then
TAROPTS="-X ${PROGDIR}/conf/exclude-from-upgrade"
else
TAROPTS=""
@@ -87,9 +124,8 @@ start_extract_uzip_tar()
mdconfig -d -u ${MDDEVICE}
;;
tar)
- tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1
- if [ $? -ne 0 ]
- then
+ tar -xpv -C ${FSMNT} -f ${INSFILE} ${TAROPTS} >&1 2>&1
+ if [ $? -ne 0 ]; then
exit_err "ERROR: Failed extracting the tar image"
fi
;;
@@ -176,6 +212,38 @@ start_extract_split()
echo_log "pc-sysinstall: Extraction Finished"
};
+# Function which will attempt to fetch the dist file(s) before we start
+fetch_dist_file()
+{
+ get_value_from_cfg ftpPath
+ if [ -z "$VAL" ]
+ then
+ exit_err "ERROR: Install medium was set to ftp, but no ftpPath was provided!"
+ fi
+
+ FTPPATH="${VAL}"
+
+ # Check if we have a /usr partition to save the download
+ if [ -d "${FSMNT}/usr" ]
+ then
+ DLDIR="${FSMNT}/usr/.fetch.$$"
+ else
+ DLDIR="${FSMNT}/.fetch.$$"
+ fi
+ mkdir -p ${DLDIR}
+
+ # Do the fetch of the dist archive(s) now
+ for di in $INSFILE
+ do
+ fetch_file "${FTPPATH}/${di}.txz" "${DLDIR}/${di}.txz" "1"
+ done
+
+ # Check to see if there is a MANIFEST file for this install
+ fetch_file "${FTPPATH}/MANIFEST" "${DLDIR}/MANIFEST" "0"
+
+ export DLDIR
+};
+
# Function which will attempt to fetch the install file before we start
# the install
fetch_install_file()
@@ -390,6 +458,13 @@ init_extraction()
case $PACKAGETYPE in
uzip) INSFILE="${FBSD_UZIP_FILE}" ;;
tar) INSFILE="${FBSD_TAR_FILE}" ;;
+ dist)
+ get_value_from_cfg_with_spaces distFiles
+ if [ -z "$VAL" ] ; then
+ exit_err "No dist files specified!"
+ fi
+ INSFILE="${VAL}"
+ ;;
split)
INSDIR="${FBSD_BRANCH_DIR}"
@@ -401,6 +476,13 @@ init_extraction()
case $PACKAGETYPE in
uzip) INSFILE="${UZIP_FILE}" ;;
tar) INSFILE="${TAR_FILE}" ;;
+ dist)
+ get_value_from_cfg_with_spaces distFiles
+ if [ -z "$VAL" ] ; then
+ exit_err "No dist files specified!"
+ fi
+ INSFILE="${VAL}"
+ ;;
esac
fi
export INSFILE
@@ -417,22 +499,32 @@ init_extraction()
start_extract_split
else
- INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE
- start_extract_uzip_tar
+ if [ "$PACKAGETYPE" = "dist" ] ; then
+ start_extract_dist "${CDMNT}/usr/freebsd-dist"
+ else
+ INSFILE="${CDMNT}/${INSFILE}" ; export INSFILE
+ start_extract_uzip_tar
+ fi
fi
;;
ftp)
- if [ "$PACKAGETYPE" = "split" ]
- then
- fetch_split_files
-
- INSDIR="${INSFILE}" ; export INSDIR
- start_extract_split
- else
- fetch_install_file
- start_extract_uzip_tar
- fi
+ case $PACKAGETYPE in
+ split)
+ fetch_split_files
+
+ INSDIR="${INSFILE}" ; export INSDIR
+ start_extract_split
+ ;;
+ dist)
+ fetch_dist_file
+ start_extract_dist "$DLDIR"
+ ;;
+ *)
+ fetch_install_file
+ start_extract_uzip_tar
+ ;;
+ esac
;;
sftp) ;;
@@ -446,8 +538,13 @@ init_extraction()
exit_err "Install medium was set to local, but no localPath was provided!"
fi
LOCALPATH=$VAL
- INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE
- start_extract_uzip_tar
+ if [ "$PACKAGETYPE" = "dist" ] ; then
+ INSFILE="${INSFILE}" ; export INSFILE
+ start_extract_dist "$LOCALPATH"
+ else
+ INSFILE="${LOCALPATH}/${INSFILE}" ; export INSFILE
+ start_extract_uzip_tar
+ fi
;;
*) exit_err "ERROR: Unknown install medium" ;;
esac
diff --git a/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh b/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh
index 7572efb..c1a879a 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-installpackages.sh
@@ -76,50 +76,113 @@ fetch_package_dependencies()
# Check for any packages specified, and begin loading them
install_packages()
{
+ echo "Checking for packages to install..."
+ sleep 2
+
# First, lets check and see if we even have any packages to install
get_value_from_cfg installPackages
- if [ -n "${VAL}" ]
- then
- HERE=`pwd`
- rc_nohalt "mkdir -p ${FSMNT}/${PKGTMPDIR}"
- rc_nohalt "cd ${FSMNT}/${PKGTMPDIR}"
- if [ ! -f "${CONFDIR}/INDEX" ]
+ # Nothing to do?
+ if [ -z "${VAL}" ]; then return; fi
+
+ echo "Installing packages..."
+ sleep 3
+
+ local PKGPTH
+
+ HERE=`pwd`
+ rc_halt "mkdir -p ${FSMNT}${PKGTMPDIR}"
+
+ # Determine the directory we will install packages from
+ get_package_location
+ rc_halt "cd ${PKGDLDIR}"
+
+ # Set the location of the INDEXFILE
+ INDEXFILE="${TMPDIR}/INDEX"
+
+ if [ ! -f "${INDEXFILE}" ]; then
+ get_package_index
+ fi
+
+ if [ ! -f "${TMPDIR}/INDEX.parsed" -a "$INSTALLMEDIUM" = "ftp" ]; then
+ parse_package_index
+ fi
+
+ # What extension are we using for pkgs?
+ PKGEXT="txz"
+ get_value_from_cfg pkgExt
+ if [ -n "${VAL}" ]; then
+ strip_white_space ${VAL}
+ PKGEXT="$VAL"
+ fi
+ export PKGEXT
+
+ # We dont want to be bothered with scripts asking questions
+ PACKAGE_BUILDING=yes
+ export PACKAGE_BUILDING
+
+ # Lets start by cleaning up the string and getting it ready to parse
+ get_value_from_cfg_with_spaces installPackages
+ PACKAGES="${VAL}"
+ echo_log "Packages to install: `echo $PACKAGES | wc -w | awk '{print $1}'`"
+ for i in $PACKAGES
+ do
+ if ! get_package_name "${i}"
then
- get_package_index
+ echo_log "Unable to locate package ${i}"
+ continue
fi
- if [ ! -f "${CONFDIR}/INDEX.parsed" ]
- then
- parse_package_index
+ PKGNAME="${VAL}"
+
+ # Fetch package + deps, but skip if installing from local media
+ if [ "${INSTALLMEDIUM}" = "ftp" ] ; then
+ DEPFILE="${FSMNT}/${PKGTMPDIR}/.${PKGNAME}.deps"
+ rc_nohalt "touch ${DEPFILE}"
+ determine_package_dependencies "${PKGNAME}" "${DEPFILE}"
+ fetch_package_dependencies "${DEPFILE}" "${FSMNT}/${PKGTMPDIR}"
fi
- # Lets start by cleaning up the string and getting it ready to parse
- strip_white_space ${VAL}
- PACKAGES=`echo ${VAL} | sed -e "s|,| |g"`
- for i in $PACKAGES
- do
- if get_package_name "${i}"
- then
- PKGNAME="${VAL}"
- DEPFILE="${FSMNT}/${PKGTMPDIR}/.${PKGNAME}.deps"
-
- rc_nohalt "touch ${DEPFILE}"
- determine_package_dependencies "${PKGNAME}" "${DEPFILE}"
- fetch_package_dependencies "${DEPFILE}" "${FSMNT}/${PKGTMPDIR}"
-
- # If the package is not already installed, install it!
- if ! run_chroot_cmd "pkg_info -e ${PKGNAME}"
- then
- rc_nohalt "pkg_add -C ${FSMNT} ${PKGTMPDIR}/${PKGNAME}.tbz"
- fi
-
- rc_nohalt "rm ${DEPFILE}"
+ # Set package location
+ case "${INSTALLMEDIUM}" in
+ usb|dvd|local) PKGPTH="${PKGTMPDIR}/All/${PKGNAME}" ;;
+ *) PKGPTH="${PKGTMPDIR}/${PKGNAME}" ;;
+ esac
+
+ # See if we need to determine the package format we are working with
+ if [ -z "${PKGINFO}" ] ; then
+ tar tqf "${FSMNT}${PKGPTH}" '+MANIFEST' >/dev/null 2>/dev/null
+ if [ $? -ne 0 ] ; then
+ PKGADD="pkg_add -C ${FSMNT}"
+ PKGINFO="pkg_info"
+ else
+ PKGADD="pkg -c ${FSMNT} add"
+ PKGINFO="pkg info"
+ bootstrap_pkgng
fi
+ fi
- rc_nohalt "cd ${HERE}"
- done
+ # If the package is not already installed, install it!
+ if ! run_chroot_cmd "${PKGINFO} -e ${PKGNAME}" >/dev/null 2>/dev/null
+ then
+ echo_log "Installing package: ${PKGNAME}"
+ rc_nohalt "${PKGADD} ${PKGPTH}"
+ fi
+
+ if [ "${INSTALLMEDIUM}" = "ftp" ] ; then
+ rc_nohalt "rm ${DEPFILE}"
+ fi
+
+ done
+
+ echo_log "Package installation complete!"
- rm -rf "${FSMNT}/${PKGTMPDIR}"
+ # Cleanup after ourselves
+ rc_halt "cd ${HERE}"
+ if [ "${INSTALLMEDIUM}" = "ftp" ] ; then
+ rc_halt "rm -rf ${FSMNT}${PKGTMPDIR}" >/dev/null 2>/dev/null
+ else
+ rc_halt "umount ${FSMNT}${PKGTMPDIR}" >/dev/null 2>/dev/null
+ rc_halt "rmdir ${FSMNT}${PKGTMPDIR}" >/dev/null 2>/dev/null
fi
};
diff --git a/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh b/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh
index c90c058..e9eb148 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-mountdisk.sh
@@ -149,12 +149,12 @@ mount_all_filesystems()
for PART in `ls ${PARTDIR}`
do
PARTDEV=`echo $PART | sed 's|-|/|g'`
- if [ ! -e "${PARTDEV}" ]
+ PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
+ if [ ! -e "${PARTDEV}" -a "${PARTFS}" != "ZFS" ]
then
exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?"
fi
- PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`"
PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`"
@@ -186,12 +186,12 @@ mount_all_filesystems()
for PART in `ls ${PARTDIR}`
do
PARTDEV=`echo $PART | sed 's|-|/|g'`
- if [ ! -e "${PARTDEV}" ]
+ PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
+ if [ ! -e "${PARTDEV}" -a "${PARTFS}" != "ZFS" ]
then
exit_err "ERROR: The partition ${PARTDEV} does not exist. Failure in bsdlabel?"
fi
- PARTFS="`cat ${PARTDIR}/${PART} | cut -d '#' -f 1`"
PARTMNT="`cat ${PARTDIR}/${PART} | cut -d '#' -f 2`"
PARTENC="`cat ${PARTDIR}/${PART} | cut -d '#' -f 3`"
diff --git a/usr.sbin/pc-sysinstall/backend/functions-newfs.sh b/usr.sbin/pc-sysinstall/backend/functions-newfs.sh
index 2ab4a83..f8664f0 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-newfs.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-newfs.sh
@@ -60,18 +60,56 @@ setup_zfs_filesystem()
fi
done
-
# Check if we have some custom zpool arguments and use them if so
if [ ! -z "${ZPOOLOPTS}" ] ; then
- rc_halt "zpool create -m none -f ${ZPOOLNAME} ${ZPOOLOPTS}"
+ # Sort through devices and run gnop on them
+ local gnopDev=""
+ local newOpts=""
+ for i in $ZPOOLOPTS
+ do
+ echo "$i" | grep -q '/dev/'
+ if [ $? -eq 0 ] ; then
+ rc_halt "gnop create -S 4096 ${i}"
+ gnopDev="$gnopDev $i"
+ newOpts="$newOpts ${i}.nop"
+ else
+ newOpts="$newOpts $i"
+ fi
+ done
+
+ echo_log "Creating zpool ${ZPOOLNAME} with $newOpts"
+ rc_halt "zpool create -m none -f ${ZPOOLNAME} ${newOpts}"
+
+ # Export the pool
+ rc_halt "zpool export ${ZPOOLNAME}"
+
+ # Destroy the gnop devices
+ for i in $gnopDev
+ do
+ rc_halt "gnop destroy ${i}.nop"
+ done
+
+ # And lastly re-import the pool
+ rc_halt "zpool import ${ZPOOLNAME}"
else
+ # Lets do our pseudo-4k drive
+ rc_halt "gnop create -S 4096 ${PART}${EXT}"
+
# No zpool options, create pool on single device
- rc_halt "zpool create -m none -f ${ZPOOLNAME} ${PART}${EXT}"
+ echo_log "Creating zpool ${ZPOOLNAME} on ${PART}${EXT}"
+ rc_halt "zpool create -m none -f ${ZPOOLNAME} ${PART}${EXT}.nop"
+
+ # Finish up the gnop 4k trickery
+ rc_halt "zpool export ${ZPOOLNAME}"
+ rc_halt "gnop destroy ${PART}${EXT}.nop"
+ rc_halt "zpool import ${ZPOOLNAME}"
fi
# Disable atime for this zfs partition, speed increase
rc_nohalt "zfs set atime=off ${ZPOOLNAME}"
+
+
};
# Runs newfs on all the partiions which we've setup with bsdlabel
diff --git a/usr.sbin/pc-sysinstall/backend/functions-packages.sh b/usr.sbin/pc-sysinstall/backend/functions-packages.sh
index c426778..ee41928 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-packages.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-packages.sh
@@ -45,9 +45,11 @@ get_package_index_by_ftp()
then
INDEX_FILE="${INDEX_FILE}.bz2"
USE_BZIP2=1
+ INDEX_PATH="${INDEXFILE}.bz2"
+ else
+ INDEX_PATH="${INDEXFILE}"
fi
- INDEX_PATH="${CONFDIR}/${INDEX_FILE}"
fetch_file "${FTP_SERVER}/${INDEX_FILE}" "${INDEX_PATH}" "1"
if [ -f "${INDEX_PATH}" ] && [ "${USE_BZIP2}" -eq "1" ]
then
@@ -57,17 +59,18 @@ get_package_index_by_ftp()
get_package_index_by_fs()
{
- local INDEX_FILE
-
- INDEX_FILE="${CDMNT}/packages/INDEX"
- fetch_file "${INDEX_FILE}" "${CONFDIR}/" "0"
+ if [ "$INSTALLMEDIUM" = "local" ] ; then
+ INDEXFILE="${LOCALPATH}/packages/INDEX"
+ else
+ INDEXFILE="${CDMNT}/packages/INDEX"
+ fi
};
get_package_index_size()
{
- if [ -f "${CONFDIR}/INDEX" ]
+ if [ -f "${INDEXFILE}" ]
then
- SIZE=`ls -l ${CONFDIR}/INDEX | awk '{ print $5 }'`
+ SIZE=`ls -l ${INDEXFILE} | awk '{ print $5 }'`
else
get_ftp_mirror
FTPHOST="${VAL}"
@@ -94,28 +97,24 @@ get_package_index()
get_package_index_by_ftp "${FTPPATH}"
else
- get_value_from_cfg ftpHost
- if [ -z "$VAL" ]
- then
- exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!"
- fi
-
- FTPHOST="${VAL}"
-
- get_value_from_cfg ftpDir
- if [ -z "$VAL" ]
- then
- exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!"
- fi
-
- FTPDIR="${VAL}"
- FTPPATH="ftp://${FTPHOST}${FTPDIR}"
case "${INSTALLMEDIUM}" in
- usb|dvd) get_package_index_by_fs ;;
- ftp) get_package_index_by_ftp "${FTPPATH}" ;;
- sftp) ;;
- *) RES=1 ;;
+ usb|dvd|local) get_package_index_by_fs ;;
+ ftp) get_value_from_cfg ftpHost
+ if [ -z "$VAL" ]; then
+ exit_err "ERROR: Install medium was set to ftp, but no ftpHost was provided!"
+ fi
+ FTPHOST="${VAL}"
+
+ get_value_from_cfg ftpDir
+ if [ -z "$VAL" ]; then
+ exit_err "ERROR: Install medium was set to ftp, but no ftpDir was provided!"
+ fi
+ FTPDIR="${VAL}"
+ FTPPATH="ftp://${FTPHOST}${FTPDIR}"
+ get_package_index_by_ftp "${FTPPATH}" ;;
+ sftp) ;;
+ *) RES=1 ;;
esac
fi
@@ -125,10 +124,11 @@ get_package_index()
parse_package_index()
{
+ echo_log "Building package dep list.. Please wait.."
INDEX_FILE="${PKGDIR}/INDEX"
exec 3<&0
- exec 0<"${INDEX_FILE}"
+ exec 0<"${INDEXFILE}"
while read -r line
do
@@ -257,20 +257,38 @@ get_package_name()
{
PACKAGE="${1}"
RES=0
+ local PKGPTH
- INDEX_FILE="${PKGDIR}/INDEX.deps"
- REGEX="^${PACKAGE}|"
+ # If we are on a local medium, we can parse the Latest/ directory
+ if [ "${INSTALLMEDIUM}" != "ftp" ] ; then
+ case "${INSTALLMEDIUM}" in
+ usb|dvd) PKGPTH="${CDMNT}/packages" ;;
+ *) PKGPTH="${LOCALPATH}/packages" ;;
+ esac
+
+ # Check the /Latest dir for generic names, then look for specific version in All/
+ if [ -e "${PKGPTH}/Latest/${PACKAGE}.${PKGEXT}" ] ; then
+ NAME=`ls -al ${PKGPTH}/Latest/${PACKAGE}.${PKGEXT} 2>/dev/null | cut -d '>' -f 2 | rev | cut -f1 -d'/' | rev | tr -s ' '`
+ else
+ NAME=`ls -al ${PKGPTH}/All/${PACKAGE}.${PKGEXT} 2>/dev/null | cut -d '>' -f 2 | rev | cut -f1 -d'/' | rev | tr -s ' '`
+ fi
+ export VAL="${NAME}"
+ else
+ # Doing remote fetch, we we will look up, but some generic names like
+ # "perl" wont work, since we don't know the default version
+ INDEX_FILE="${PKGDIR}/INDEX.deps"
+ REGEX="^${PACKAGE}|"
- LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null`
- NAME=`echo "${LINE}"|cut -f2 -d'|'`
+ LINE=`grep "${REGEX}" "${INDEX_FILE}" 2>/dev/null`
+ NAME=`echo "${LINE}"|cut -f2 -d'|'`
- export VAL="${NAME}"
+ export VAL="${NAME}"
+ fi
if [ -z "${VAL}" ]
then
RES=1
fi
-
return ${RES}
};
@@ -334,7 +352,7 @@ fetch_package_by_ftp()
fi
FTPDIR="${VAL}"
- PACKAGE="${PACKAGE}.tbz"
+ PACKAGE="${PACKAGE}.${PKGEXT}"
FTP_SERVER="ftp://${FTPHOST}${FTPDIR}"
if [ ! -f "${SAVEDIR}/${PACKAGE}" ]
@@ -345,28 +363,49 @@ fetch_package_by_ftp()
fi
};
-fetch_package_by_fs()
-{
- CATEGORY="${1}"
- PACKAGE="${2}"
- SAVEDIR="${3}"
-
- PACKAGE="${PACKAGE}.tbz"
- if [ ! -f "${SAVEDIR}/${PACKAGE}" ]
- then
- fetch_file "${CDMNT}/packages/${CATEGORY}/${PACKAGE}" "${SAVEDIR}/" "0"
- fi
-};
-
fetch_package()
{
CATEGORY="${1}"
PACKAGE="${2}"
SAVEDIR="${3}"
+ # Fetch package, but skip if installing from local media
case "${INSTALLMEDIUM}" in
- usb|dvd) fetch_package_by_fs "${CATEGORY}" "${PACKAGE}" "${SAVEDIR}" ;;
+ usb|dvd|local) return ;;
ftp) fetch_package_by_ftp "${CATEGORY}" "${PACKAGE}" "${SAVEDIR}" ;;
sftp) ;;
esac
};
+
+bootstrap_pkgng()
+{
+ # Check if we need to boot-strap pkgng
+ if run_chroot_cmd "which pkg-static" >/dev/null 2>/dev/null
+ then
+ return
+ fi
+ local PKGPTH
+
+ # Ok, lets boot-strap this sucker
+ echo_log "Bootstraping pkgng.."
+ fetch_package "Latest" "pkg" "${PKGDLDIR}"
+
+ # Figure out real location of "pkg" package
+ case "${INSTALLMEDIUM}" in
+ usb|dvd|local) PKGPTH="${PKGTMPDIR}/Latest/pkg.${PKGEXT}" ;;
+ *) PKGPTH="${PKGTMPDIR}/pkg.${PKGEXT}" ;;
+ esac
+ rc_halt "pkg -c ${FSMNT} add ${PKGPTH}" ; run_chroot_cmd "pkg2ng"
+}
+
+get_package_location()
+{
+ case "${INSTALLMEDIUM}" in
+ usb|dvd) rc_halt "mount_nullfs ${CDMNT}/packages ${FSMNT}${PKGTMPDIR}"
+ PKGDLDIR="${FSMNT}${PKGTMPDIR}/All" ;;
+ local) rc_halt "mount_nullfs ${LOCALPATH}/packages ${FSMNT}${PKGTMPDIR}"
+ PKGDLDIR="${FSMNT}${PKGTMPDIR}/All" ;;
+ *) PKGDLDIR="${FSMNT}${PKGTMPDIR}" ;;
+ esac
+ export PKGDLDIR
+}
diff --git a/usr.sbin/pc-sysinstall/backend/functions-parse.sh b/usr.sbin/pc-sysinstall/backend/functions-parse.sh
index ed0a3e6..fb7cdd2 100755
--- a/usr.sbin/pc-sysinstall/backend/functions-parse.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions-parse.sh
@@ -45,7 +45,7 @@ get_value_from_cfg_with_spaces()
{
if [ -n "${1}" ]
then
- export VAL=`grep "^${1}=" ${CFGF} | head -n 1 | cut -d '=' -f 2-`
+ export VAL="`grep ^${1}= ${CFGF} | head -n 1 | cut -d '=' -f 2-`"
else
exit_err "Error: Did we forgot to supply a setting to grab?"
fi
diff --git a/usr.sbin/pc-sysinstall/backend/functions.sh b/usr.sbin/pc-sysinstall/backend/functions.sh
index 33d0005..a2d039b 100755
--- a/usr.sbin/pc-sysinstall/backend/functions.sh
+++ b/usr.sbin/pc-sysinstall/backend/functions.sh
@@ -277,7 +277,11 @@ get_zpool_name()
while :
do
NEWNAME="${BASENAME}${NUM}"
- zpool import | grep -qw "${NEWNAME}" || break
+ zpool list | grep -qw "${NEWNAME}"
+ local chk1=$?
+ zpool import | grep -qw "${NEWNAME}"
+ local chk2=$?
+ if [ $chk1 -eq 1 -a $chk2 -eq 1 ] ; then break ; fi
NUM=$((NUM+1))
done
diff --git a/usr.sbin/pc-sysinstall/backend/parseconfig.sh b/usr.sbin/pc-sysinstall/backend/parseconfig.sh
index c852cea..f3d89fc 100755
--- a/usr.sbin/pc-sysinstall/backend/parseconfig.sh
+++ b/usr.sbin/pc-sysinstall/backend/parseconfig.sh
@@ -69,7 +69,7 @@ file_sanity_check "installMode installType installMedium packageType"
check_value installMode "fresh upgrade extract"
check_value installType "PCBSD FreeBSD"
check_value installMedium "dvd usb ftp rsync image local"
-check_value packageType "uzip tar rsync split"
+check_value packageType "uzip tar rsync split dist"
if_check_value_exists mirrorbal "load prefer round-robin split"
# We passed all sanity checks! Yay, lets start the install
diff --git a/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf b/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf
index 5d682dc..9c01e31 100644
--- a/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf
+++ b/usr.sbin/pc-sysinstall/conf/pc-sysinstall.conf
@@ -5,11 +5,9 @@
TMPDIR="/tmp/.pc-sysinstall"
export TMPDIR
-if [ ! -d "${TMPDIR}" ]
-then
- mkdir -p ${TMPDIR}
- chmod 777 ${TMPDIR}
-fi
+# Create a fresh TMPDIR
+if [ -d "${TMPDIR}" -a "$TMPDIR" != '/' ]; then rm -rf ${TMPDIR}; fi
+mkdir -p ${TMPDIR}
# Set our temp directory for storing partition information
PARTDIR="${TMPDIR}/part-info"
diff --git a/usr.sbin/pc-sysinstall/examples/README b/usr.sbin/pc-sysinstall/examples/README
index cc269a2..1e8d32d 100644
--- a/usr.sbin/pc-sysinstall/examples/README
+++ b/usr.sbin/pc-sysinstall/examples/README
@@ -243,11 +243,16 @@ Set installMedium= to the source type we will be using for this install.
Available Types:
dvd - Search for and mount the DVD which contains the install archive
+local - Pull files directly from a local directory
usb - Search for and mount the USB drive which contains the install archive
ftp - The install archive will be fetched from a FTP / HTTP server before install
rsync - Pull the system data from a ssh + rsync server, specified with variables below
image - Install system from an image
+# localPath=/usr/freebsd-dist
+
+Location of the directory we will be pulling installation files from
+
# installType=(PCBSD, FreeBSD)
Set the type of system we are installing, PCBSD or FreeBSD
@@ -256,10 +261,14 @@ Set the type of system we are installing, PCBSD or FreeBSD
The installer archive, if not using the defaults specified in conf/pc-sysinstall.conf
-# packageType=(tar, uzip, split)
+# packageType=(tar, uzip, split, dist)
The archive type we are extracting from when using dvd, usb or ftp
+# distFiles=base src kernel
+
+List of dist files to install when packageType=dist
+
# ftpPath=ftp://ftp.pcbsd.org/pub/8.0/netinstall
Location of the installer archive when using a installMedium=ftp
diff --git a/usr.sbin/pciconf/pciconf.c b/usr.sbin/pciconf/pciconf.c
index 52ad09a..58ffddd 100644
--- a/usr.sbin/pciconf/pciconf.c
+++ b/usr.sbin/pciconf/pciconf.c
@@ -290,7 +290,7 @@ list_bars(int fd, struct pci_conf *p)
}
printf(" bar [%02x] = type %s, range %2d, base %#jx, ",
PCIR_BAR(i), type, range, (uintmax_t)base);
- printf("size %2d, %s\n", (int)bar.pbi_length,
+ printf("size %ju, %s\n", (uintmax_t)bar.pbi_length,
bar.pbi_enabled ? "enabled" : "disabled");
}
}
diff --git a/usr.sbin/pkg/Makefile b/usr.sbin/pkg/Makefile
index c2ca0a3..d244bd2 100644
--- a/usr.sbin/pkg/Makefile
+++ b/usr.sbin/pkg/Makefile
@@ -1,10 +1,10 @@
# $FreeBSD$
PROG= pkg
-SRCS= pkg.c dns_utils.c
+SRCS= pkg.c dns_utils.c config.c
NO_MAN= yes
-DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH}
-LDADD= -larchive -lelf -lfetch
+DPADD= ${LIBARCHIVE} ${LIBELF} ${LIBFETCH} ${LIBBSDYML} ${LIBSBUF}
+LDADD= -larchive -lelf -lfetch -lbsdyml -lsbuf
.include <bsd.prog.mk>
diff --git a/usr.sbin/pkg/config.c b/usr.sbin/pkg/config.c
new file mode 100644
index 0000000..5924d57
--- /dev/null
+++ b/usr.sbin/pkg/config.c
@@ -0,0 +1,428 @@
+/*-
+ * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sbuf.h>
+#include <sys/elf_common.h>
+#include <sys/endian.h>
+
+#include <bsdyml.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "elf_tables.h"
+#include "config.h"
+
+#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
+
+struct config_entry {
+ uint8_t type;
+ const char *key;
+ const char *val;
+ char *value;
+ bool envset;
+};
+
+static struct config_entry c[] = {
+ [PACKAGESITE] = {
+ PKG_CONFIG_STRING,
+ "PACKAGESITE",
+ "http://pkg.FreeBSD.org/${ABI}/latest",
+ NULL,
+ false,
+ },
+ [ABI] = {
+ PKG_CONFIG_STRING,
+ "ABI",
+ NULL,
+ NULL,
+ false,
+ },
+ [MIRROR_TYPE] = {
+ PKG_CONFIG_STRING,
+ "MIRROR_TYPE",
+ "SRV",
+ NULL,
+ false,
+ },
+ [ASSUME_ALWAYS_YES] = {
+ PKG_CONFIG_BOOL,
+ "ASSUME_ALWAYS_YES",
+ "NO",
+ NULL,
+ false,
+ }
+};
+
+static const char *
+elf_corres_to_string(struct _elf_corres *m, int e)
+{
+ int i;
+
+ for (i = 0; m[i].string != NULL; i++)
+ if (m[i].elf_nb == e)
+ return (m[i].string);
+
+ return ("unknown");
+}
+
+static int
+pkg_get_myabi(char *dest, size_t sz)
+{
+ Elf *elf;
+ Elf_Data *data;
+ Elf_Note note;
+ Elf_Scn *scn;
+ char *src, *osname;
+ const char *abi;
+ GElf_Ehdr elfhdr;
+ GElf_Shdr shdr;
+ int fd, i, ret;
+ uint32_t version;
+
+ version = 0;
+ ret = -1;
+ scn = NULL;
+ abi = NULL;
+
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ warnx("ELF library initialization failed: %s",
+ elf_errmsg(-1));
+ return (-1);
+ }
+
+ if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
+ warn("open()");
+ return (-1);
+ }
+
+ if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+ ret = -1;
+ warnx("elf_begin() failed: %s.", elf_errmsg(-1));
+ goto cleanup;
+ }
+
+ if (gelf_getehdr(elf, &elfhdr) == NULL) {
+ ret = -1;
+ warn("getehdr() failed: %s.", elf_errmsg(-1));
+ goto cleanup;
+ }
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) != &shdr) {
+ ret = -1;
+ warn("getshdr() failed: %s.", elf_errmsg(-1));
+ goto cleanup;
+ }
+
+ if (shdr.sh_type == SHT_NOTE)
+ break;
+ }
+
+ if (scn == NULL) {
+ ret = -1;
+ warn("failed to get the note section");
+ goto cleanup;
+ }
+
+ data = elf_getdata(scn, NULL);
+ src = data->d_buf;
+ for (;;) {
+ memcpy(&note, src, sizeof(Elf_Note));
+ src += sizeof(Elf_Note);
+ if (note.n_type == NT_VERSION)
+ break;
+ src += note.n_namesz + note.n_descsz;
+ }
+ osname = src;
+ src += roundup2(note.n_namesz, 4);
+ if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
+ version = be32dec(src);
+ else
+ version = le32dec(src);
+
+ for (i = 0; osname[i] != '\0'; i++)
+ osname[i] = (char)tolower(osname[i]);
+
+ snprintf(dest, sz, "%s:%d:%s:%s",
+ osname, version / 100000,
+ elf_corres_to_string(mach_corres, (int)elfhdr.e_machine),
+ elf_corres_to_string(wordsize_corres,
+ (int)elfhdr.e_ident[EI_CLASS]));
+
+ ret = 0;
+
+ switch (elfhdr.e_machine) {
+ case EM_ARM:
+ snprintf(dest + strlen(dest), sz - strlen(dest),
+ ":%s:%s:%s", elf_corres_to_string(endian_corres,
+ (int)elfhdr.e_ident[EI_DATA]),
+ (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ?
+ "eabi" : "oabi",
+ (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ?
+ "softfp" : "vfp");
+ break;
+ case EM_MIPS:
+ /*
+ * this is taken from binutils sources:
+ * include/elf/mips.h
+ * mapping is figured out from binutils:
+ * gas/config/tc-mips.c
+ */
+ switch (elfhdr.e_flags & EF_MIPS_ABI) {
+ case E_MIPS_ABI_O32:
+ abi = "o32";
+ break;
+ case E_MIPS_ABI_N32:
+ abi = "n32";
+ break;
+ default:
+ if (elfhdr.e_ident[EI_DATA] ==
+ ELFCLASS32)
+ abi = "o32";
+ else if (elfhdr.e_ident[EI_DATA] ==
+ ELFCLASS64)
+ abi = "n64";
+ break;
+ }
+ snprintf(dest + strlen(dest), sz - strlen(dest),
+ ":%s:%s", elf_corres_to_string(endian_corres,
+ (int)elfhdr.e_ident[EI_DATA]), abi);
+ break;
+ }
+
+cleanup:
+ if (elf != NULL)
+ elf_end(elf);
+
+ close(fd);
+ return (ret);
+}
+
+static void
+subst_packagesite(const char *abi)
+{
+ struct sbuf *newval;
+ const char *variable_string;
+ const char *oldval;
+
+ if (c[PACKAGESITE].value != NULL)
+ oldval = c[PACKAGESITE].value;
+ else
+ oldval = c[PACKAGESITE].val;
+
+ if ((variable_string = strstr(oldval, "${ABI}")) == NULL)
+ return;
+
+ newval = sbuf_new_auto();
+ sbuf_bcat(newval, oldval, variable_string - oldval);
+ sbuf_cat(newval, abi);
+ sbuf_cat(newval, variable_string + strlen("${ABI}"));
+ sbuf_finish(newval);
+
+ free(c[PACKAGESITE].value);
+ c[PACKAGESITE].value = strdup(sbuf_data(newval));
+}
+
+static void
+config_parse(yaml_document_t *doc, yaml_node_t *node)
+{
+ yaml_node_pair_t *pair;
+ yaml_node_t *key, *val;
+ struct sbuf *buf = sbuf_new_auto();
+ int i;
+ size_t j;
+
+ pair = node->data.mapping.pairs.start;
+
+ 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;
+ continue;
+ }
+
+ /*
+ * 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;
+ }
+
+ 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;
+ continue;
+ }
+
+ /* env has priority over config file */
+ if (c[i].envset) {
+ ++pair;
+ continue;
+ }
+
+ c[i].value = strdup(val->data.scalar.value);
+ ++pair;
+ }
+
+ sbuf_delete(buf);
+}
+
+int
+config_init(void)
+{
+ FILE *fp;
+ yaml_parser_t parser;
+ yaml_document_t doc;
+ yaml_node_t *node;
+ const char *val;
+ int i;
+ const char *localbase;
+ char confpath[MAXPATHLEN];
+ 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;
+ }
+ }
+
+ localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _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 */
+ 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");
+ }
+
+ yaml_document_delete(&doc);
+ yaml_parser_delete(&parser);
+
+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");
+ c[ABI].val = abi;
+ }
+
+ subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val);
+
+ return (0);
+}
+
+int
+config_string(pkg_config_key k, const char **val)
+{
+ if (c[k].type != PKG_CONFIG_STRING)
+ return (-1);
+
+ if (c[k].value != NULL)
+ *val = c[k].value;
+ else
+ *val = c[k].val;
+
+ return (0);
+}
+
+int
+config_bool(pkg_config_key k, bool *val)
+{
+ const char *value;
+
+ if (c[k].type != PKG_CONFIG_BOOL)
+ return (-1);
+
+ *val = false;
+
+ if (c[k].value != NULL)
+ value = c[k].value;
+ else
+ value = c[k].val;
+
+ if (strcasecmp(value, "true") == 0 ||
+ strcasecmp(value, "yes") == 0 ||
+ strcasecmp(value, "on") == 0 ||
+ *value == '1')
+ *val = true;
+
+ return (0);
+}
+
+void
+config_finish(void) {
+ int i;
+
+ for (i = 0; i < CONFIG_SIZE; i++)
+ free(c[i].value);
+}
diff --git a/usr.sbin/mount_portalfs/pathnames.h b/usr.sbin/pkg/config.h
index 9373c7d..e592f6d 100644
--- a/usr.sbin/mount_portalfs/pathnames.h
+++ b/usr.sbin/pkg/config.h
@@ -1,11 +1,7 @@
-/*
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
+/*-
+ * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org>
* All rights reserved.
*
- * This code is derived from software donated to Berkeley by
- * Jan-Simon Pendry.
- *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -14,14 +10,11 @@
* 2. Redistributions in binary form must 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
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS 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)
@@ -30,11 +23,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
- *
* $FreeBSD$
*/
-#include <paths.h>
+#ifndef _PKG_CONFIG_H
+#define _PKG_CONFIG_H
+
+#define _LOCALBASE "/usr/local"
+
+typedef enum {
+ PACKAGESITE = 0,
+ ABI,
+ MIRROR_TYPE,
+ ASSUME_ALWAYS_YES,
+ CONFIG_SIZE
+} pkg_config_key;
+
+typedef enum {
+ PKG_CONFIG_STRING=0,
+ PKG_CONFIG_BOOL,
+} pkg_config_t;
+
+int config_init(void);
+void config_finish(void);
+int config_string(pkg_config_key, const char **);
+int config_bool(pkg_config_key, bool *);
-#define _PATH_TMPPORTAL "/tmp/portalXXXXXXXXXX" /* Scratch socket name */
+#endif
diff --git a/usr.sbin/pkg/pkg.c b/usr.sbin/pkg/pkg.c
index 1b3146b..0aef3da 100644
--- a/usr.sbin/pkg/pkg.c
+++ b/usr.sbin/pkg/pkg.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
@@ -28,175 +28,23 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/elf_common.h>
-#include <sys/endian.h>
#include <sys/wait.h>
#include <archive.h>
#include <archive_entry.h>
-#include <ctype.h>
#include <err.h>
#include <errno.h>
-#include <fcntl.h>
#include <fetch.h>
-#include <gelf.h>
#include <paths.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
-#include "elf_tables.h"
#include "dns_utils.h"
-
-#define _LOCALBASE "/usr/local"
-#define _PKGS_URL "http://pkg.FreeBSD.org"
-
-static const char *
-elf_corres_to_string(struct _elf_corres *m, int e)
-{
- int i;
-
- for (i = 0; m[i].string != NULL; i++)
- if (m[i].elf_nb == e)
- return (m[i].string);
-
- return ("unknown");
-}
-
-static int
-pkg_get_myabi(char *dest, size_t sz)
-{
- Elf *elf;
- Elf_Data *data;
- Elf_Note note;
- Elf_Scn *scn;
- char *src, *osname;
- const char *abi;
- GElf_Ehdr elfhdr;
- GElf_Shdr shdr;
- int fd, i, ret;
- uint32_t version;
-
- version = 0;
- ret = -1;
- scn = NULL;
- abi = NULL;
-
- if (elf_version(EV_CURRENT) == EV_NONE) {
- warnx("ELF library initialization failed: %s",
- elf_errmsg(-1));
- return (-1);
- }
-
- if ((fd = open("/bin/sh", O_RDONLY)) < 0) {
- warn("open()");
- return (-1);
- }
-
- if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
- ret = -1;
- warnx("elf_begin() failed: %s.", elf_errmsg(-1));
- goto cleanup;
- }
-
- if (gelf_getehdr(elf, &elfhdr) == NULL) {
- ret = -1;
- warn("getehdr() failed: %s.", elf_errmsg(-1));
- goto cleanup;
- }
-
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- if (gelf_getshdr(scn, &shdr) != &shdr) {
- ret = -1;
- warn("getshdr() failed: %s.", elf_errmsg(-1));
- goto cleanup;
- }
-
- if (shdr.sh_type == SHT_NOTE)
- break;
- }
-
- if (scn == NULL) {
- ret = -1;
- warn("failed to get the note section");
- goto cleanup;
- }
-
- data = elf_getdata(scn, NULL);
- src = data->d_buf;
- for (;;) {
- memcpy(&note, src, sizeof(Elf_Note));
- src += sizeof(Elf_Note);
- if (note.n_type == NT_VERSION)
- break;
- src += note.n_namesz + note.n_descsz;
- }
- osname = src;
- src += note.n_namesz;
- if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
- version = be32dec(src);
- else
- version = le32dec(src);
-
- for (i = 0; osname[i] != '\0'; i++)
- osname[i] = (char)tolower(osname[i]);
-
- snprintf(dest, sz, "%s:%d:%s:%s",
- osname, version / 100000,
- elf_corres_to_string(mach_corres, (int)elfhdr.e_machine),
- elf_corres_to_string(wordsize_corres,
- (int)elfhdr.e_ident[EI_CLASS]));
-
- ret = 0;
-
- switch (elfhdr.e_machine) {
- case EM_ARM:
- snprintf(dest + strlen(dest), sz - strlen(dest),
- ":%s:%s:%s", elf_corres_to_string(endian_corres,
- (int)elfhdr.e_ident[EI_DATA]),
- (elfhdr.e_flags & EF_ARM_NEW_ABI) > 0 ?
- "eabi" : "oabi",
- (elfhdr.e_flags & EF_ARM_VFP_FLOAT) > 0 ?
- "softfp" : "vfp");
- break;
- case EM_MIPS:
- /*
- * this is taken from binutils sources:
- * include/elf/mips.h
- * mapping is figured out from binutils:
- * gas/config/tc-mips.c
- */
- switch (elfhdr.e_flags & EF_MIPS_ABI) {
- case E_MIPS_ABI_O32:
- abi = "o32";
- break;
- case E_MIPS_ABI_N32:
- abi = "n32";
- break;
- default:
- if (elfhdr.e_ident[EI_DATA] ==
- ELFCLASS32)
- abi = "o32";
- else if (elfhdr.e_ident[EI_DATA] ==
- ELFCLASS64)
- abi = "n64";
- break;
- }
- snprintf(dest + strlen(dest), sz - strlen(dest),
- ":%s:%s", elf_corres_to_string(endian_corres,
- (int)elfhdr.e_ident[EI_DATA]), abi);
- break;
- }
-
-cleanup:
- if (elf != NULL)
- elf_end(elf);
-
- close(fd);
- return (ret);
-}
+#include "config.h"
static int
extract_pkg_static(int fd, char *p, int sz)
@@ -212,7 +60,7 @@ extract_pkg_static(int fd, char *p, int sz)
warn("archive_read_new");
return (ret);
}
- archive_read_support_compression_all(a);
+ archive_read_support_filter_all(a);
archive_read_support_format_tar(a);
if (lseek(fd, 0, 0) == -1) {
@@ -247,7 +95,7 @@ extract_pkg_static(int fd, char *p, int sz)
warnx("fail to extract pkg-static");
cleanup:
- archive_read_finish(a);
+ archive_read_free(a);
return (ret);
}
@@ -291,8 +139,8 @@ bootstrap_pkg(void)
char zone[MAXHOSTNAMELEN + 13];
char url[MAXPATHLEN];
char conf[MAXPATHLEN];
- char abi[BUFSIZ];
char tmppkg[MAXPATHLEN];
+ const char *packagesite, *mirror_type;
char buf[10240];
char pkgstatic[MAXPATHLEN];
int fd, retry, ret, max_retry;
@@ -311,17 +159,15 @@ bootstrap_pkg(void)
printf("Bootstrapping pkg please wait\n");
- if (pkg_get_myabi(abi, MAXPATHLEN) != 0) {
- warnx("failed to determine the system ABI");
+ if (config_string(PACKAGESITE, &packagesite) != 0) {
+ warnx("No PACKAGESITE defined");
return (-1);
}
-
- if (getenv("PACKAGESITE") != NULL)
- snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", getenv("PACKAGESITE"));
- else
- snprintf(url, MAXPATHLEN, "%s/%s/latest/Latest/pkg.txz",
- getenv("PACKAGEROOT") ? getenv("PACKAGEROOT") : _PKGS_URL,
- getenv("ABI") ? getenv("ABI") : abi);
+ if (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);
@@ -336,10 +182,10 @@ bootstrap_pkg(void)
u = fetchParseURL(url);
while (remote == NULL) {
if (retry == max_retry) {
- if (strcmp(u->scheme, "file") != 0) {
+ if (strcmp(u->scheme, "file") != 0 &&
+ strcasecmp(mirror_type, "srv") == 0) {
snprintf(zone, sizeof(zone),
"_%s._tcp.%s", u->scheme, u->host);
- printf("%s\n", zone);
mirrors = dns_getsrvinfo(zone);
current = mirrors;
}
@@ -411,6 +257,8 @@ bootstrap_pkg(void)
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");
cleanup:
if (remote != NULL)
@@ -447,6 +295,7 @@ int
main(__unused int argc, char *argv[])
{
char pkgpath[MAXPATHLEN];
+ bool yes = false;
snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg",
getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE);
@@ -465,7 +314,9 @@ main(__unused int argc, char *argv[])
* not tty. Check the environment to see if user has answer
* tucked in there already.
*/
- if (getenv("ASSUME_ALWAYS_YES") == NULL) {
+ config_init();
+ config_bool(ASSUME_ALWAYS_YES, &yes);
+ if (!yes) {
printf("%s", confirmation_message);
if (!isatty(fileno(stdin)))
exit(EXIT_FAILURE);
@@ -475,6 +326,7 @@ main(__unused int argc, char *argv[])
}
if (bootstrap_pkg() != 0)
exit(EXIT_FAILURE);
+ config_finish();
}
execv(pkgpath, argv);
diff --git a/usr.sbin/pmcannotate/pmcannotate.8 b/usr.sbin/pmcannotate/pmcannotate.8
index 17c7c0e..8f791c1 100644
--- a/usr.sbin/pmcannotate/pmcannotate.8
+++ b/usr.sbin/pmcannotate/pmcannotate.8
@@ -45,7 +45,7 @@ The
.Nm
utility can produce both C sources or assembly sources of a program with
a line-by-line based profiling.
-The profiling informations are retrieved through a
+The profiling information is retrieved through a
.Xr pmcstat 8
raw output while the program operations are retrieved through the
.Xr objdump 1
@@ -71,9 +71,9 @@ The following options are available:
.Bl -tag -width indent
.It Fl a
Shows the program profiling inlined in the assembly code only.
-No C informations involving C sources are provided.
+No C information involving C sources is provided.
.It Fl h
-Prints out informations about the usage of the tool.
+Prints out information about the usage of the tool.
.It Fl l Ar level
Changes the lower bound (expressed in percentage) for traced functions
that will be printed out in the report.
diff --git a/usr.sbin/rarpd/rarpd.c b/usr.sbin/rarpd/rarpd.c
index 5386185..74f7940 100644
--- a/usr.sbin/rarpd/rarpd.c
+++ b/usr.sbin/rarpd/rarpd.c
@@ -90,13 +90,13 @@ struct if_info {
* The list of all interfaces that are being listened to. rarp_loop()
* "selects" on the descriptors in this list.
*/
-struct if_info *iflist;
+static struct if_info *iflist;
-int verbose; /* verbose messages */
-const char *tftp_dir = TFTP_DIR; /* tftp directory */
+static int verbose; /* verbose messages */
+static const char *tftp_dir = TFTP_DIR; /* tftp directory */
-int dflag; /* messages to stdout/stderr, not syslog(3) */
-int sflag; /* ignore /tftpboot */
+static int dflag; /* messages to stdout/stderr, not syslog(3) */
+static int sflag; /* ignore /tftpboot */
static u_char zero[6];
@@ -308,6 +308,7 @@ init_one(struct ifaddrs *ifa, char *target, int pass1)
break;
}
}
+
/*
* Initialize all "candidate" interfaces that are in the system
* configuration list. A "candidate" is up, not loopback and not
@@ -369,6 +370,7 @@ init(char *target)
static void
usage(void)
{
+
(void)fprintf(stderr, "%s\n%s\n",
"usage: rarpd -a [-dfsv] [-t directory] [-P pidfile]",
" rarpd [-dfsv] [-t directory] [-P pidfile] interface");
@@ -630,6 +632,7 @@ rarp_bootable_err:
static in_addr_t
choose_ipaddr(in_addr_t **alist, in_addr_t net, in_addr_t netmask)
{
+
for (; *alist; ++alist)
if ((**alist & netmask) == net)
return **alist;
@@ -692,16 +695,18 @@ rarp_process(struct if_info *ii, u_char *pkt, u_int len)
* host (i.e. the guy running rarpd), won't try to ARP for the hardware
* address of the guy being booted (he cannot answer the ARP).
*/
-struct sockaddr_in sin_inarp = {
+static struct sockaddr_in sin_inarp = {
sizeof(struct sockaddr_in), AF_INET, 0,
{0},
{0},
};
-struct sockaddr_dl sin_dl = {
+
+static struct sockaddr_dl sin_dl = {
sizeof(struct sockaddr_dl), AF_LINK, 0, IFT_ETHER, 0, 6,
0, ""
};
-struct {
+
+static struct {
struct rt_msghdr rthdr;
char rtspace[512];
} rtmsg;
@@ -883,6 +888,7 @@ rarp_reply(struct if_info *ii, struct ether_header *ep, in_addr_t ipaddr,
static in_addr_t
ipaddrtonetmask(in_addr_t addr)
{
+
addr = ntohl(addr);
if (IN_CLASSA(addr))
return htonl(IN_CLASSA_NET);
diff --git a/usr.sbin/rtadvd/rtadvd.8 b/usr.sbin/rtadvd/rtadvd.8
index ad39887..fcb46fe 100644
--- a/usr.sbin/rtadvd/rtadvd.8
+++ b/usr.sbin/rtadvd/rtadvd.8
@@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 14, 2011
+.Dd February 25, 2013
.Dt RTADVD 8
.Os
.Sh NAME
@@ -39,13 +39,19 @@
.Nm
.Op Fl dDfRs
.Op Fl c Ar configfile
+.Op Fl C Ar ctlsock
.Op Fl M Ar ifname
.Op Fl p Ar pidfile
-.Ar interface ...
+.Op Ar interface ...
.Sh DESCRIPTION
.Nm
sends router advertisement packets to the specified
.Ar interfaces .
+If no interfaces are specified,
+.Nm
+will still run, but will not advertise any routes until interfaces are
+added using
+.Xr rtadvctl 8 .
.Pp
The program will daemonize itself on invocation.
It will then send router advertisement packets periodically, as well
@@ -121,6 +127,11 @@ for the configuration file.
By default,
.Pa /etc/rtadvd.conf
is used.
+.It Fl C
+Specify an alternate location for the control socket used by
+.Xr rtadvctl 8 .
+The default is
+.Pa /var/run/rtadvd.sock .
.It Fl d
Print debugging information.
.It Fl D
@@ -185,6 +196,7 @@ The default process ID file.
.Ex -std
.Sh SEE ALSO
.Xr rtadvd.conf 5 ,
+.Xr rtadvctl 8 ,
.Xr rtsol 8
.Rs
.%A Thomas Narten
diff --git a/usr.sbin/rtadvd/rtadvd.c b/usr.sbin/rtadvd/rtadvd.c
index a5f306d..880b283 100644
--- a/usr.sbin/rtadvd/rtadvd.c
+++ b/usr.sbin/rtadvd/rtadvd.c
@@ -166,6 +166,15 @@ static void rtmsg_input(struct sockinfo *);
static void set_short_delay(struct ifinfo *);
static int check_accept_rtadv(int);
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: rtadvd [-dDfRs] "
+ "[-c configfile] [-C ctlsock] [-M ifname] [-p pidfile]\n");
+ exit(1);
+}
+
int
main(int argc, char *argv[])
{
@@ -177,7 +186,7 @@ main(int argc, char *argv[])
pid_t pid, otherpid;
/* get command line options and arguments */
- while ((ch = getopt(argc, argv, "c:C:dDfM:p:Rs")) != -1) {
+ while ((ch = getopt(argc, argv, "c:C:dDfhM:p:Rs")) != -1) {
switch (ch) {
case 'c':
conffile = optarg;
@@ -209,17 +218,12 @@ main(int argc, char *argv[])
case 'p':
pidfilename = optarg;
break;
+ default:
+ usage();
}
}
argc -= optind;
argv += optind;
- if (argc == 0) {
- fprintf(stderr,
- "usage: rtadvd [-dDfRs] [-c conffile] "
- "[-C ctrlsockname] [-M ifname] "
- "[-p pidfile] interfaces...\n");
- exit(1);
- }
logopt = LOG_NDELAY | LOG_PID;
if (fflag)
@@ -1004,6 +1008,8 @@ set_short_delay(struct ifinfo *ifi)
long delay; /* must not be greater than 1000000 */
struct timeval interval, now, min_delay, tm_tmp, *rest;
+ if (ifi->ifi_ra_timer == NULL)
+ return;
/*
* Compute a random delay. If the computed value
* corresponds to a time later than the time the next
diff --git a/usr.sbin/sendmail/Makefile b/usr.sbin/sendmail/Makefile
index b68ed0f..a9f7fbb 100644
--- a/usr.sbin/sendmail/Makefile
+++ b/usr.sbin/sendmail/Makefile
@@ -45,11 +45,6 @@ CFLAGS+= -DNETINET6
WARNS?= 1
-# Unfortunately, clang gives warnings about sendmail code that cannot
-# be turned off yet. Since this is contrib code, and we don't really
-# care about the warnings, just make them non-fatal for now.
-NO_WERROR.clang=
-
DPADD= ${LIBUTIL} ${LIBWRAP}
LDADD= -lutil -lwrap
diff --git a/usr.sbin/services_mkdb/services_mkdb.8 b/usr.sbin/services_mkdb/services_mkdb.8
index ff74261..834423a 100644
--- a/usr.sbin/services_mkdb/services_mkdb.8
+++ b/usr.sbin/services_mkdb/services_mkdb.8
@@ -64,7 +64,7 @@ The options are as follows:
.It Fl o Ar database
Put the output databases in the named file.
.It Fl q
-Don't warn about duplicate services.
+Do not warn about duplicate services.
.It Fl u
Print the services file to stdout, omitting duplicate entries and comments.
.El
diff --git a/usr.sbin/tzsetup/tzsetup.c b/usr.sbin/tzsetup/tzsetup.c
index 97daa0b..cea8533 100644
--- a/usr.sbin/tzsetup/tzsetup.c
+++ b/usr.sbin/tzsetup/tzsetup.c
@@ -703,8 +703,13 @@ install_zoneinfo_file(const char *zoneinfo_file)
return (DITEM_FAILURE | DITEM_RECREATE);
}
#ifdef VERBOSE
+ snprintf(title, sizeof(title), "Done");
snprintf(prompt, sizeof(prompt),
"Removed %s", path_localtime);
+ if (usedialog)
+ dialog_msgbox(title, prompt, 8, 72, 1);
+ else
+ fprintf(stderr, "%s\n", prompt);
#endif
return (DITEM_LEAVE_MENU);
}
diff --git a/usr.sbin/usbconfig/dump.c b/usr.sbin/usbconfig/dump.c
index 7ee89da..52dd132 100644
--- a/usr.sbin/usbconfig/dump.c
+++ b/usr.sbin/usbconfig/dump.c
@@ -225,13 +225,17 @@ dump_device_info(struct libusb20_device *pdev, uint8_t show_ifdrv)
{
char buf[128];
uint8_t n;
+ unsigned int usage;
- printf("%s, cfg=%u md=%s spd=%s pwr=%s\n",
+ usage = libusb20_dev_get_power_usage(pdev);
+
+ printf("%s, cfg=%u md=%s spd=%s pwr=%s (%umA)\n",
libusb20_dev_get_desc(pdev),
libusb20_dev_get_config_index(pdev),
dump_mode(libusb20_dev_get_mode(pdev)),
dump_speed(libusb20_dev_get_speed(pdev)),
- dump_power_mode(libusb20_dev_get_power_mode(pdev)));
+ dump_power_mode(libusb20_dev_get_power_mode(pdev)),
+ usage);
if (!show_ifdrv)
return;
diff --git a/usr.sbin/usbconfig/usbconfig.c b/usr.sbin/usbconfig/usbconfig.c
index a1fa694..c046003 100644
--- a/usr.sbin/usbconfig/usbconfig.c
+++ b/usr.sbin/usbconfig/usbconfig.c
@@ -33,6 +33,7 @@
#include <grp.h>
#include <errno.h>
#include <ctype.h>
+#include <sys/types.h>
#include <libusb20_desc.h>
#include <libusb20.h>
diff --git a/usr.sbin/watchdogd/watchdogd.8 b/usr.sbin/watchdogd/watchdogd.8
index b00fef1..b8a5505 100644
--- a/usr.sbin/watchdogd/watchdogd.8
+++ b/usr.sbin/watchdogd/watchdogd.8
@@ -1,3 +1,5 @@
+.\" Copyright (c) 2013 iXsystems.com,
+.\" author: Alfred Perlstein <alfred@freebsd.org>
.\" Copyright (c) 2004 Poul-Henning Kamp <phk@FreeBSD.org>
.\" Copyright (c) 2003 Sean M. Kelly <smkelly@FreeBSD.org>
.\" All rights reserved.
@@ -25,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 2, 2006
+.Dd March 5, 2013
.Dt WATCHDOGD 8
.Os
.Sh NAME
@@ -33,11 +35,17 @@
.Nd watchdog daemon
.Sh SYNOPSIS
.Nm
-.Op Fl d
+.Op Fl dnSw
+.Op Fl -debug
+.Op Fl -softtimeout
+.Op Fl -softtimeout-action Ar action
+.Op Fl -pretimeout Ar timeout
+.Op Fl -pretimeout-action Ar action
.Op Fl e Ar cmd
.Op Fl I Ar file
.Op Fl s Ar sleep
.Op Fl t Ar timeout
+.Op Fl T Ar script_timeout
.Sh DESCRIPTION
The
.Nm
@@ -62,6 +70,13 @@ is not specified, the daemon will perform a trivial file system
check instead.
.Pp
The
+.Fl n
+argument 'dry-run' will cause watchdog not to arm the system watchdog and
+instead only run the watchdog function and report on failures.
+This is useful for developing new watchdogd scripts as the system will not
+reboot if there are problems with the script.
+.Pp
+The
.Fl s Ar sleep
argument can be used to control the sleep period between each execution
of the check and defaults to one second.
@@ -78,6 +93,16 @@ If this occurs,
will no longer execute and thus the kernel's watchdog routines will take
action after a configurable timeout.
.Pp
+The
+.Fl T Ar script_timeout
+specifies the threshold (in seconds) at which the watchdogd will complain
+that its script has run for too long.
+If unset
+.Ar script_timeout
+defaults to the value specified by the
+.Fl s Ar sleep
+option.
+.Pp
Upon receiving the
.Dv SIGTERM
or
@@ -90,17 +115,95 @@ will terminate.
The
.Nm
utility recognizes the following runtime options:
-.Bl -tag -width ".Fl I Ar file"
+.Bl -tag -width ".Fl -softtimeout-action Ar action "
.It Fl I Ar file
Write the process ID of the
.Nm
utility in the specified file.
-.It Fl d
+.It Fl d Fl -debug
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
+.Fl -pretimeout-action
+and
+.Fl -softtimeout-action
+flags:
+.Bl -tag -width ".Ar printf "
+.It Ar panic
+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
+Actions can be combined in a comma separated list as so:
+.Ar log,printf
+which would both
+.Xr printf 9
+and
+.Xr log 9
+which will send messages both to
+.Xr dmesg 8
+and the kernel
+.Xr log 4
+device for
+.Xr syslog 8 .
.Sh FILES
.Bl -tag -width ".Pa /var/run/watchdogd.pid" -compact
.It Pa /var/run/watchdogd.pid
@@ -125,3 +228,6 @@ and
.Pp
Some contributions made by
.An Jeff Roberson Aq jeff@FreeBSD.org .
+.Pp
+The pretimeout and softtimeout action system was added by
+.An Alfred Perlstein Aq alfred@freebsd.org .
diff --git a/usr.sbin/watchdogd/watchdogd.c b/usr.sbin/watchdogd/watchdogd.c
index 50bdd91..5416751 100644
--- a/usr.sbin/watchdogd/watchdogd.c
+++ b/usr.sbin/watchdogd/watchdogd.c
@@ -1,5 +1,8 @@
/*-
* Copyright (c) 2003-2004 Sean M. Kelly <smkelly@FreeBSD.org>
+ * Copyright (c) 2013 iXsystems.com,
+ * author: Alfred Perlstein <alfred@freebsd.org>
+ *
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,8 +53,11 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <strings.h>
#include <sysexits.h>
+#include <syslog.h>
#include <unistd.h>
+#include <getopt.h>
+
static void parseargs(int, char *[]);
static void sighandler(int);
static void watchdog_loop(void);
@@ -63,13 +69,39 @@ static void usage(void);
static int debugging = 0;
static int end_program = 0;
static const char *pidfile = _PATH_VARRUN "watchdogd.pid";
-static u_int timeout = WD_TO_16SEC;
+static u_int timeout = WD_TO_128SEC;
+static u_int pretimeout = 0;
static u_int passive = 0;
static int is_daemon = 0;
+static int is_dry_run = 0; /* do not arm the watchdog, only
+ report on timing of the watch
+ program */
+static int do_timedog = 0;
+static int do_syslog = 1;
static int fd = -1;
static int nap = 1;
+static int carp_thresh_seconds = -1;
static char *test_cmd = NULL;
+static const char *getopt_shortopts;
+
+static int pretimeout_set;
+static int pretimeout_act;
+static int pretimeout_act_set;
+
+static int softtimeout_set;
+static int softtimeout_act;
+static int softtimeout_act_set;
+
+static struct option longopts[] = {
+ { "debug", no_argument, &debugging, 1 },
+ { "pretimeout", required_argument, &pretimeout_set, 1 },
+ { "pretimeout-action", required_argument, &pretimeout_act_set, 1 },
+ { "softtimeout", no_argument, &softtimeout_set, 1 },
+ { "softtimeout-action", required_argument, &softtimeout_act_set, 1 },
+ { NULL, 0, NULL, 0}
+};
+
/*
* Ask malloc() to map minimum-sized chunks of virtual address space at a time,
* so that mlockall() won't needlessly wire megabytes of unused memory into the
@@ -93,12 +125,16 @@ main(int argc, char *argv[])
parseargs(argc, argv);
+ if (do_syslog)
+ openlog("watchdogd", LOG_CONS|LOG_NDELAY|LOG_PERROR,
+ LOG_DAEMON);
+
rtp.type = RTP_PRIO_REALTIME;
rtp.prio = 0;
if (rtprio(RTP_SET, 0, &rtp) == -1)
err(EX_OSERR, "rtprio");
- if (watchdog_init() == -1)
+ if (!is_dry_run && watchdog_init() == -1)
errx(EX_SOFTWARE, "unable to initialize watchdog");
if (is_daemon) {
@@ -108,6 +144,7 @@ main(int argc, char *argv[])
pfh = pidfile_open(pidfile, 0600, &otherpid);
if (pfh == NULL) {
if (errno == EEXIST) {
+ watchdog_onoff(0);
errx(EX_SOFTWARE, "%s already running, pid: %d",
getprogname(), otherpid);
}
@@ -164,6 +201,9 @@ static int
watchdog_init(void)
{
+ if (is_dry_run)
+ return 0;
+
fd = open("/dev/" _PATH_WATCHDOG, O_RDWR);
if (fd >= 0)
return (0);
@@ -172,26 +212,111 @@ watchdog_init(void)
}
/*
+ * If we are doing timing, then get the time.
+ */
+static int
+watchdog_getuptime(struct timespec *tp)
+{
+ int error;
+
+ if (!do_timedog)
+ return 0;
+
+ error = clock_gettime(CLOCK_UPTIME_FAST, tp);
+ if (error)
+ warn("clock_gettime");
+ return (error);
+}
+
+static long
+watchdog_check_dogfunction_time(struct timespec *tp_start,
+ struct timespec *tp_end)
+{
+ struct timeval tv_start, tv_end, tv_now, tv;
+ const char *cmd_prefix, *cmd;
+ struct timespec tp_now;
+ int sec;
+
+ if (!do_timedog)
+ return (0);
+
+ TIMESPEC_TO_TIMEVAL(&tv_start, tp_start);
+ TIMESPEC_TO_TIMEVAL(&tv_end, tp_end);
+ timersub(&tv_end, &tv_start, &tv);
+ sec = tv.tv_sec;
+ if (sec < carp_thresh_seconds)
+ return (sec);
+
+ if (test_cmd) {
+ cmd_prefix = "Watchdog program";
+ cmd = test_cmd;
+ } else {
+ cmd_prefix = "Watchdog operation";
+ cmd = "stat(\"/etc\", &sb)";
+ }
+ if (do_syslog)
+ syslog(LOG_CRIT, "%s: '%s' took too long: "
+ "%d.%06ld seconds >= %d seconds threshold",
+ cmd_prefix, cmd, sec, (long)tv.tv_usec,
+ carp_thresh_seconds);
+ else
+ warnx("%s: '%s' took too long: "
+ "%d.%06ld seconds >= %d seconds threshold",
+ cmd_prefix, cmd, sec, (long)tv.tv_usec,
+ carp_thresh_seconds);
+
+ /*
+ * Adjust the sleep interval again in case syslog(3) took a non-trivial
+ * amount of time to run.
+ */
+ if (watchdog_getuptime(&tp_now))
+ return (sec);
+ TIMESPEC_TO_TIMEVAL(&tv_now, &tp_now);
+ timersub(&tv_now, &tv_start, &tv);
+ sec = tv.tv_sec;
+
+ return (sec);
+}
+
+/*
* Main program loop which is iterated every second.
*/
static void
watchdog_loop(void)
{
+ struct timespec ts_start, ts_end;
struct stat sb;
- int failed;
+ long waited;
+ int error, failed;
while (end_program != 2) {
failed = 0;
+ error = watchdog_getuptime(&ts_start);
+ if (error) {
+ end_program = 1;
+ goto try_end;
+ }
+
if (test_cmd != NULL)
failed = system(test_cmd);
else
failed = stat("/etc", &sb);
+ error = watchdog_getuptime(&ts_end);
+ if (error) {
+ end_program = 1;
+ goto try_end;
+ }
+
if (failed == 0)
watchdog_patpat(timeout|WD_ACTIVE);
- sleep(nap);
+ waited = watchdog_check_dogfunction_time(&ts_start, &ts_end);
+ if (nap - waited > 0)
+ sleep(nap - waited);
+
+try_end:
if (end_program != 0) {
if (watchdog_onoff(0) == 0) {
end_program = 2;
@@ -211,6 +336,9 @@ static int
watchdog_patpat(u_int t)
{
+ if (is_dry_run)
+ return 0;
+
return ioctl(fd, WDIOCPATPAT, &t);
}
@@ -221,11 +349,62 @@ watchdog_patpat(u_int t)
static int
watchdog_onoff(int onoff)
{
-
- if (onoff)
+ int error;
+
+ /* fake successful watchdog op if a dry run */
+ if (is_dry_run)
+ return 0;
+
+ if (onoff) {
+ /*
+ * Call the WDIOC_SETSOFT regardless of softtimeout_set
+ * because we'll need to turn it off if someone had turned
+ * it on.
+ */
+ error = ioctl(fd, WDIOC_SETSOFT, &softtimeout_set);
+ if (error) {
+ warn("setting WDIOC_SETSOFT %d", softtimeout_set);
+ return (error);
+ }
+ error = watchdog_patpat((timeout|WD_ACTIVE));
+ if (error) {
+ warn("watchdog_patpat failed");
+ goto failsafe;
+ }
+ if (softtimeout_act_set) {
+ error = ioctl(fd, WDIOC_SETSOFTTIMEOUTACT,
+ &softtimeout_act);
+ if (error) {
+ warn("setting WDIOC_SETSOFTTIMEOUTACT %d",
+ softtimeout_act);
+ goto failsafe;
+ }
+ }
+ if (pretimeout_set) {
+ error = ioctl(fd, WDIOC_SETPRETIMEOUT, &pretimeout);
+ if (error) {
+ warn("setting WDIOC_SETPRETIMEOUT %d",
+ pretimeout);
+ goto failsafe;
+ }
+ }
+ if (pretimeout_act_set) {
+ error = ioctl(fd, WDIOC_SETPRETIMEOUTACT,
+ &pretimeout_act);
+ if (error) {
+ warn("setting WDIOC_SETPRETIMEOUTACT %d",
+ pretimeout_act);
+ goto failsafe;
+ }
+ }
+ /* pat one more time for good measure */
return watchdog_patpat((timeout|WD_ACTIVE));
- else
+ } else {
return watchdog_patpat(0);
+ }
+failsafe:
+ watchdog_patpat(0);
+ return (error);
}
/*
@@ -235,27 +414,132 @@ static void
usage(void)
{
if (is_daemon)
- fprintf(stderr, "usage: watchdogd [-d] [-e cmd] [-I file] [-s sleep] [-t timeout]\n");
+ fprintf(stderr, "usage:\n"
+" watchdogd [-dnSw] [-e cmd] [-I file] [-s sleep] [-t timeout]\n"
+" [-T script_timeout]\n"
+" [--debug]\n"
+" [--pretimeout seconds] [-pretimeout-action action]\n"
+" [--softtimeout] [-softtimeout-action action]\n"
+);
else
fprintf(stderr, "usage: watchdog [-d] [-t timeout]\n");
exit(EX_USAGE);
}
+static long
+fetchtimeout(int opt, const char *longopt, const char *myoptarg)
+{
+ const char *errstr;
+ char *p;
+ long rv;
+
+ errstr = NULL;
+ p = NULL;
+ errno = 0;
+ rv = strtol(myoptarg, &p, 0);
+ if ((p != NULL && *p != '\0') || errno != 0)
+ errstr = "is not a number";
+ if (rv <= 0)
+ errstr = "must be greater than zero";
+ if (errstr) {
+ if (longopt)
+ errx(EX_USAGE, "--%s argument %s", longopt, errstr);
+ else
+ errx(EX_USAGE, "-%c argument %s", opt, errstr);
+ }
+ return (rv);
+}
+
+struct act_tbl {
+ const char *at_act;
+ int at_value;
+};
+
+static const struct act_tbl act_tbl[] = {
+ { "panic", WD_SOFT_PANIC },
+ { "ddb", WD_SOFT_DDB },
+ { "log", WD_SOFT_LOG },
+ { "printf", WD_SOFT_PRINTF },
+ { NULL, 0 }
+};
+
+static void
+timeout_act_error(const char *lopt, const char *badact)
+{
+ char *opts, *oldopts;
+ int i;
+
+ opts = NULL;
+ for (i = 0; act_tbl[i].at_act != NULL; i++) {
+ oldopts = opts;
+ if (asprintf(&opts, "%s%s%s",
+ oldopts == NULL ? "" : oldopts,
+ oldopts == NULL ? "" : ", ",
+ act_tbl[i].at_act) == -1)
+ err(EX_OSERR, "malloc");
+ free(oldopts);
+ }
+ warnx("bad --%s argument '%s' must be one of (%s).",
+ lopt, badact, opts);
+ usage();
+}
+
+/*
+ * Take a comma separated list of actions and or the flags
+ * together for the ioctl.
+ */
+static int
+timeout_act_str2int(const char *lopt, const char *acts)
+{
+ int i;
+ char *dupacts, *tofree;
+ char *o;
+ int rv = 0;
+
+ tofree = dupacts = strdup(acts);
+ if (!tofree)
+ err(EX_OSERR, "malloc");
+ while ((o = strsep(&dupacts, ",")) != NULL) {
+ for (i = 0; act_tbl[i].at_act != NULL; i++) {
+ if (!strcmp(o, act_tbl[i].at_act)) {
+ rv |= act_tbl[i].at_value;
+ break;
+ }
+ }
+ if (act_tbl[i].at_act == NULL)
+ timeout_act_error(lopt, o);
+ }
+ free(tofree);
+ return rv;
+}
+
/*
* Handle the few command line arguments supported.
*/
static void
parseargs(int argc, char *argv[])
{
+ int longindex;
int c;
char *p;
+ const char *lopt;
double a;
+ /*
+ * if we end with a 'd' aka 'watchdogd' then we are the daemon program,
+ * otherwise run as a command line utility.
+ */
c = strlen(argv[0]);
if (argv[0][c - 1] == 'd')
is_daemon = 1;
- while ((c = getopt(argc, argv,
- is_daemon ? "I:de:s:t:?" : "dt:?")) != -1) {
+
+ if (is_daemon)
+ getopt_shortopts = "I:de:ns:t:ST:w?";
+ else
+ getopt_shortopts = "dt:?";
+
+ while ((c = getopt_long(argc, argv, getopt_shortopts, longopts,
+ &longindex)) != -1) {
switch (c) {
case 'I':
pidfile = optarg;
@@ -266,17 +550,19 @@ parseargs(int argc, char *argv[])
case 'e':
test_cmd = strdup(optarg);
break;
+ case 'n':
+ is_dry_run = 1;
+ break;
#ifdef notyet
case 'p':
passive = 1;
break;
#endif
case 's':
- p = NULL;
- errno = 0;
- nap = strtol(optarg, &p, 0);
- if ((p != NULL && *p != '\0') || errno != 0)
- errx(EX_USAGE, "-s argument is not a number");
+ nap = fetchtimeout(c, NULL, optarg);
+ break;
+ case 'S':
+ do_syslog = 0;
break;
case 't':
p = NULL;
@@ -286,6 +572,7 @@ parseargs(int argc, char *argv[])
errx(EX_USAGE, "-t argument is not a number");
if (a < 0)
errx(EX_USAGE, "-t argument must be positive");
+
if (a == 0)
timeout = WD_TO_NEVER;
else
@@ -294,12 +581,39 @@ parseargs(int argc, char *argv[])
printf("Timeout is 2^%d nanoseconds\n",
timeout);
break;
+ case 'T':
+ carp_thresh_seconds = fetchtimeout(c, "NULL", optarg);
+ break;
+ case 'w':
+ do_timedog = 1;
+ break;
+ case 0:
+ lopt = longopts[longindex].name;
+ if (!strcmp(lopt, "pretimeout")) {
+ pretimeout = fetchtimeout(0, lopt, optarg);
+ } else if (!strcmp(lopt, "pretimeout-action")) {
+ pretimeout_act = timeout_act_str2int(lopt,
+ optarg);
+ } else if (!strcmp(lopt, "softtimeout-action")) {
+ softtimeout_act = timeout_act_str2int(lopt,
+ optarg);
+ } else {
+ /* warnx("bad option at index %d: %s", optind,
+ argv[optind]);
+ usage();
+ */
+ }
+ break;
case '?':
default:
usage();
/* NOTREACHED */
}
}
+
+ if (carp_thresh_seconds == -1)
+ carp_thresh_seconds = nap;
+
if (argc != optind)
errx(EX_USAGE, "extra arguments.");
if (is_daemon && timeout < WD_TO_1SEC)
OpenPOWER on IntegriCloud