]> git.saurik.com Git - apple/system_cmds.git/commitdiff
system_cmds-230.tar.gz mac-os-x-102 mac-os-x-1021 mac-os-x-1022 mac-os-x-1023 mac-os-x-1024 mac-os-x-1025 mac-os-x-1026 v230
authorApple <opensource@apple.com>
Thu, 4 Jul 2002 04:54:59 +0000 (04:54 +0000)
committerApple <opensource@apple.com>
Thu, 4 Jul 2002 04:54:59 +0000 (04:54 +0000)
164 files changed:
Makefile
PB.project
README.rtf
ac.tproj/Makefile.postamble
ac.tproj/Makefile.preamble
arch.tproj/Makefile
arch.tproj/Makefile.postamble
arch.tproj/arch.1 [new file with mode: 0644]
arch.tproj/machine.1 [new file with mode: 0644]
at.tproj/Makefile.postamble
fs_usage.tproj/Makefile
fs_usage.tproj/fs_usage.1
fs_usage.tproj/fs_usage.c
init.tproj/Makefile.postamble
init.tproj/Makefile.preamble
init.tproj/init.c
iostat.tproj/Makefile
iostat.tproj/Makefile.postamble
iostat.tproj/PB.project
iostat.tproj/iostat.8
iostat.tproj/iostat.c
iostat.tproj/names.c [deleted file]
kdump.tproj/Makefile [new file with mode: 0644]
kdump.tproj/Makefile.postamble [new file with mode: 0644]
kdump.tproj/Makefile.preamble [new file with mode: 0644]
kdump.tproj/PB.project [new file with mode: 0644]
kdump.tproj/kdump.1 [new file with mode: 0644]
kdump.tproj/kdump.c [new file with mode: 0644]
kdump.tproj/mkioctls [new file with mode: 0644]
kdump.tproj/syscalls.c [new file with mode: 0644]
kextd.tproj/GetSymbolFromPEF.h [deleted file]
kextd.tproj/KEXTD.c [deleted file]
kextd.tproj/KEXTD.h [deleted file]
kextd.tproj/KEXTD_main.c [deleted file]
kextd.tproj/Makefile [deleted file]
kextd.tproj/Makefile.preamble [deleted file]
kextd.tproj/PB.project [deleted file]
kextd.tproj/PEFSupport.c [deleted file]
kextd.tproj/PTLock.c [deleted file]
kextd.tproj/PTLock.h [deleted file]
kextload.tproj/Makefile [deleted file]
kextload.tproj/Makefile.postamble [deleted file]
kextload.tproj/Makefile.preamble [deleted file]
kextload.tproj/PB.project [deleted file]
kextload.tproj/kextload.8 [deleted file]
kextload.tproj/kextload_main.c [deleted file]
kextunload.tproj/Makefile [deleted file]
kextunload.tproj/Makefile.postamble [deleted file]
kextunload.tproj/Makefile.preamble [deleted file]
kextunload.tproj/PB.project [deleted file]
kextunload.tproj/kextunload.8 [deleted file]
kextunload.tproj/kextunload_main.c [deleted file]
kmodload.tproj/Makefile [deleted file]
kmodload.tproj/Makefile.postamble [deleted file]
kmodload.tproj/Makefile.preamble [deleted file]
kmodload.tproj/PB.project [deleted file]
kmodload.tproj/kld_patch.c [deleted file]
kmodload.tproj/kld_patch.h [deleted file]
kmodload.tproj/kmodload.8 [deleted file]
kmodload.tproj/kmodload.c [deleted file]
kmodload.tproj/kmodsyms.8 [deleted file]
kmodstat.tproj/Makefile [deleted file]
kmodstat.tproj/Makefile.postamble [deleted file]
kmodstat.tproj/Makefile.preamble [deleted file]
kmodstat.tproj/PB.project [deleted file]
kmodstat.tproj/kmodstat.8 [deleted file]
kmodstat.tproj/kmodstat.c [deleted file]
kmodunload.tproj/Makefile [deleted file]
kmodunload.tproj/Makefile.postamble [deleted file]
kmodunload.tproj/Makefile.preamble [deleted file]
kmodunload.tproj/PB.project [deleted file]
kmodunload.tproj/kmodunload.8 [deleted file]
kmodunload.tproj/kmodunload.c [deleted file]
ktrace.tproj/Makefile
ktrace.tproj/Makefile.postamble [new file with mode: 0644]
ktrace.tproj/Makefile.preamble
ktrace.tproj/PB.project
ktrace.tproj/ktrace.1
ktrace.tproj/ktrace.c
ktrace.tproj/ktrace.h
ktrace.tproj/subr.c
latency.tproj/Makefile
latency.tproj/latency.c
login.tproj/Makefile
login.tproj/Makefile.postamble
login.tproj/Makefile.preamble
login.tproj/login.c
mach_init.tproj/Makefile
mach_init.tproj/Makefile.postamble [new file with mode: 0644]
mach_init.tproj/Makefile.preamble
mach_init.tproj/Notes [deleted file]
mach_init.tproj/PB.project
mach_init.tproj/bootstrap.c
mach_init.tproj/bootstrap.defs
mach_init.tproj/bootstrap_internal.h
mach_init.tproj/error_log.c
mach_init.tproj/error_log.h
mach_init.tproj/initConf [deleted file]
mach_init.tproj/lists.c
mach_init.tproj/lists.h
mach_init.tproj/mach_init.8 [new file with mode: 0644]
mach_init.tproj/parser.c [deleted file]
mach_init.tproj/parser.h [deleted file]
mach_init.tproj/rpc_services.c
mach_init.tproj/testConfig [deleted file]
mach_init.tproj/testConfig2 [deleted file]
mach_init.tproj/testServer/Makefile [deleted file]
mach_init.tproj/testServer/boot_subset.c [deleted file]
mach_init.tproj/testServer/listServer.c [deleted file]
mach_init.tproj/testServer/testServer.c [deleted file]
mkfile.tproj/Makefile
mkfile.tproj/Makefile.postamble [new file with mode: 0644]
mkfile.tproj/mkfile.8 [new file with mode: 0644]
nologin.tproj/Makefile.postamble
nologin.tproj/nologin.8
nvram.tproj/nvram.8
nvram.tproj/nvram.c
sc_usage.tproj/Makefile
sc_usage.tproj/sc_usage.c
sc_usage.tproj/trace.codes
sysctl.tproj/Makefile.postamble
sysctl.tproj/Makefile.preamble
sysctl.tproj/sysctl.8
sysctl.tproj/sysctl.c
top.tproj/Makefile
top.tproj/top.c
update.tproj/Makefile.postamble
update.tproj/Makefile.preamble
vm_stat.tproj/Makefile
vm_stat.tproj/Makefile.postamble
vm_stat.tproj/vm_stat.1 [new file with mode: 0644]
zic.tproj/HACK/CST6CDT
zic.tproj/HACK/Cuba
zic.tproj/HACK/EST
zic.tproj/HACK/EST5EDT
zic.tproj/HACK/Egypt
zic.tproj/HACK/Eire
zic.tproj/HACK/Factory
zic.tproj/HACK/HST
zic.tproj/HACK/Hongkong
zic.tproj/HACK/Israel
zic.tproj/HACK/Jamaica
zic.tproj/HACK/Japan
zic.tproj/HACK/Libya
zic.tproj/HACK/MST
zic.tproj/HACK/MST7MDT
zic.tproj/HACK/Navajo
zic.tproj/HACK/PST8PDT
zic.tproj/HACK/Poland
zic.tproj/HACK/Portugal
zic.tproj/HACK/W-SU
zic.tproj/Makefile.postamble
zic.tproj/datfiles/africa
zic.tproj/datfiles/antarctica
zic.tproj/datfiles/asia
zic.tproj/datfiles/australasia
zic.tproj/datfiles/backward
zic.tproj/datfiles/etcetera
zic.tproj/datfiles/europe
zic.tproj/datfiles/factory
zic.tproj/datfiles/leapseconds
zic.tproj/datfiles/northamerica
zic.tproj/datfiles/southamerica
zic.tproj/datfiles/systemv

index 6a0101688e9b976a5009cb0978f2b2dfde7078b7..e567192e58cfb19b904b26c2d329c30cf8c05097 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -12,18 +12,15 @@ NAME = system_cmds
 PROJECTVERSION = 2.8
 PROJECT_TYPE = Aggregate
 
-SUBPROJECTS = 
-
 TOOLS = dynamic_pager.tproj ac.tproj accton.tproj arch.tproj at.tproj\
         atrun.tproj chkpasswd.tproj chpass.tproj dmesg.tproj\
         getty.tproj halt.tproj hostinfo.tproj init.tproj iostat.tproj\
-        kgmon.tproj kmodload.tproj kmodstat.tproj kmodunload.tproj\
-        ktrace.tproj login.tproj mach_init.tproj makekey.tproj\
-        mkfile.tproj nvram.tproj passwd.tproj pwd_mkdb.tproj\
-        reboot.tproj shutdown.tproj sync.tproj sysctl.tproj\
-        update.tproj vipw.tproj zic.tproj zdump.tproj vm_stat.tproj\
-        zprint.tproj top.tproj kextload.tproj kextunload.tproj kextd.tproj\
-        latency.tproj sc_usage.tproj fs_usage.tproj
+        kgmon.tproj ktrace.tproj login.tproj mach_init.tproj\
+        makekey.tproj mkfile.tproj nvram.tproj passwd.tproj\
+        pwd_mkdb.tproj reboot.tproj shutdown.tproj sync.tproj\
+        sysctl.tproj update.tproj vipw.tproj zic.tproj zdump.tproj\
+        vm_stat.tproj zprint.tproj top.tproj latency.tproj\
+        sc_usage.tproj fs_usage.tproj kdump.tproj
 
 LIBRARIES = dp_notify_lib
 
index 295cf6eeebc0f03d23fb485b9a06c1064f47541b..8f42f58f09644abd6fd772608e1a5c61b2c02625 100644 (file)
@@ -1,79 +1,74 @@
 {
-    English_RESOURCES = {}; 
+    "English_RESOURCES" = {}; 
     FILESTABLE = {
-        CLASSES = (zprint.c); 
-        C_FILES = (); 
+        CLASSES = ("zprint.c"); 
+        "C_FILES" = (); 
         FRAMEWORKS = (); 
         HEADERSEARCH = (); 
-        H_FILES = (); 
-        M_FILES = (); 
-        OTHER_LINKED = (); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, README.rtf, APPLE_LICENSE); 
-        PRECOMPILED_HEADERS = (); 
-        PROJECT_HEADERS = (); 
-        PUBLIC_HEADERS = (); 
+        "H_FILES" = (); 
+        "M_FILES" = (); 
+        "OTHER_LINKED" = (); 
+        "OTHER_SOURCES" = ("Makefile.preamble", Makefile, "README.rtf", "APPLE_LICENSE"); 
+        "PRECOMPILED_HEADERS" = (); 
+        "PROJECT_HEADERS" = (); 
+        "PUBLIC_HEADERS" = (); 
         SUBPROJECTS = (
-            dynamic_pager.tproj, 
-            dp_notify_lib, 
-            ac.tproj, 
-            accton.tproj, 
-            arch.tproj, 
-            at.tproj, 
-            atrun.tproj, 
-            chkpasswd.tproj, 
-            chpass.tproj, 
-            dmesg.tproj, 
-            fastboot.tproj, 
-            getty.tproj, 
-            halt.tproj, 
-            hostinfo.tproj, 
-            init.tproj, 
-            iostat.tproj, 
-            kgmon.tproj, 
-            kmodload.tproj, 
-            kmodstat.tproj, 
-            kmodunload.tproj, 
-            ktrace.tproj, 
-            login.tproj, 
-            mach_init.tproj, 
-            makekey.tproj, 
-            mkfile.tproj, 
-            nologin.tproj, 
-            nvram.tproj, 
-            pagesize.tproj, 
-            passwd.tproj, 
-            pwd_mkdb.tproj, 
-            reboot.tproj, 
-            shutdown.tproj, 
-            sync.tproj, 
-            sysctl.tproj, 
-            update.tproj, 
-            vipw.tproj, 
-            zic.tproj, 
-            zdump.tproj, 
-            vm_stat.tproj, 
-            zprint.tproj, 
-            top.tproj, 
-            kextload.tproj, 
-            kextunload.tproj, 
-            kextd.tproj, 
-            latency.tproj, 
-            sc_usage.tproj, 
-            fs_usage.tproj
+            "dynamic_pager.tproj", 
+            "dp_notify_lib", 
+            "ac.tproj", 
+            "accton.tproj", 
+            "arch.tproj", 
+            "at.tproj", 
+            "atrun.tproj", 
+            "chkpasswd.tproj", 
+            "chpass.tproj", 
+            "dmesg.tproj", 
+            "fastboot.tproj", 
+            "getty.tproj", 
+            "halt.tproj", 
+            "hostinfo.tproj", 
+            "init.tproj", 
+            "iostat.tproj", 
+            "kgmon.tproj", 
+            "ktrace.tproj", 
+            "login.tproj", 
+            "mach_init.tproj", 
+            "makekey.tproj", 
+            "mkfile.tproj", 
+            "nologin.tproj", 
+            "nvram.tproj", 
+            "pagesize.tproj", 
+            "passwd.tproj", 
+            "pwd_mkdb.tproj", 
+            "reboot.tproj", 
+            "shutdown.tproj", 
+            "sync.tproj", 
+            "sysctl.tproj", 
+            "update.tproj", 
+            "vipw.tproj", 
+            "zic.tproj", 
+            "zdump.tproj", 
+            "vm_stat.tproj", 
+            "zprint.tproj", 
+            "top.tproj", 
+            "latency.tproj", 
+            "sc_usage.tproj", 
+            "fs_usage.tproj", 
+            "kdump.tproj"
         ); 
     }; 
     LANGUAGE = English; 
-    LOCALIZABLE_FILES = {}; 
+    "LOCALIZABLE_FILES" = {}; 
     MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = system_cmds
+    "NEXTSTEP_BUILDTOOL" = "/bin/gnumake"
+    "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"
+    "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"
+    "PDO_UNIX_JAVA_COMPILER" = "$(NEXTDEV_BIN)/javac"; 
+    "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = "system_cmds"
     PROJECTTYPE = Aggregate; 
-    PROJECTVERSION = 2.8
+    PROJECTVERSION = "2.8"
     TARGETS = (); 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+    "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; 
+    "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; 
 }
index a8eb01437af864e29c77605143d1e2b0de8a72f4..9e6cc5bd38ef1138631d391ef4706efaabdb5bf2 100644 (file)
@@ -1,11 +1,13 @@
-{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
-\paperw4880
-\paperh7420
-\margl120
-\margr120
-\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b\i0\ulnone\fs24\fc0\cf0 system_cmds failures\
+{\rtf1\mac\ansicpg10000\cocoartf100
+{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;\f2\fswiss\fcharset77 Helvetica-Oblique;
+}
+{\colortbl;\red255\green255\blue255;}
+\margl120\margr120\vieww4640\viewh7420\viewkind0
+\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\ql\qnatural
+
+\f0\b\fs24 \cf0 system_cmds failures\
 
-\b0 \
+\f1\b0 \
 cgore\
        <a.out.h>\
 \
@@ -19,13 +21,12 @@ kvm_mkdb\
        KERNBASE undeclared\
 \
 mach_swapon\
-       <bsd/sys/table.h> not found\
+       <sys/table.h> not found\
        \
 savecore\
        KERNBASE undeclared\
 \
 vmstat\
 
-\i     <vm/vm.h> not found\
-
-}
+\f2\i  <vm/vm.h> not found\
+}
\ No newline at end of file
index 70b747fd5435a8d12cfd99aac7d73f59e40f0edb..a9b68c9f840dec4046d0c03cc10bde82307fe7b1 100644 (file)
 # Makefile API), which are rules that get invoked before and after the install 
 # target runs.  Such rules should be specified with the '::' syntax rather than 
 # a single colon.
+
+after_install:
+       mkdir -p "$(DSTROOT)/usr/share/man/man8"
+       install -c -m 644 ac.8 "$(DSTROOT)/usr/share/man/man8/ac.8"
index fc1c6499d5dd470ac19be539b10fa8fa8501d461..e5a7929dad5edefa2b4abe1f404ddec2e60183e2 100644 (file)
@@ -110,3 +110,4 @@ OTHER_HELP_DIRS =
 # $(NAME).%d[.%d][.%d] and the following line must be uncommented.
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
 
+AFTER_INSTALL = after_install
index 20bbb504a4370c2daf8a2040ab5b02c75d53dc4b..c490a16e887beb71b8378e41cc1dbaa7b93aa957 100644 (file)
@@ -14,7 +14,7 @@ PROJECT_TYPE = Tool
 
 CFILES = arch.c
 
-OTHERSRCS = Makefile PB.project Makefile.postamble
+OTHERSRCS = Makefile PB.project Makefile.postamble arch.1 machine.1
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
index eaf5363f71d463bc15c547e7d3b0db7d15e11f60..e031809b8ac108e10911634ff3683aa17bf543f7 100644 (file)
@@ -1,3 +1,6 @@
 after_install::
+       install -d $(DSTROOT)/usr/share/man/man1
+       install -c -m 444 arch.1 $(DSTROOT)/usr/share/man/man1
+       install -c -m 444 machine.1 $(DSTROOT)/usr/share/man/man1
        @-$(RM) -f $(DSTROOT)$(INSTALLDIR)/machine
-       ln $(DSTROOT)$(INSTALLDIR)/arch $(DSTROOT)$(INSTALLDIR)/machine
\ No newline at end of file
+       ln $(DSTROOT)$(INSTALLDIR)/arch $(DSTROOT)$(INSTALLDIR)/machine
diff --git a/arch.tproj/arch.1 b/arch.tproj/arch.1
new file mode 100644 (file)
index 0000000..71ce882
--- /dev/null
@@ -0,0 +1,46 @@
+.\" Copyright (c) 1994 SigmaSoft, Th. Lockert
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 SigmaSoft, Th. Lockert.
+.\" 4. 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.
+.\"
+.\"    $OpenBSD: arch.1,v 1.2 1996/06/29 20:29:34 tholo Exp $
+.\"
+.\" Modifications made 8/20/97 (c) Apple Computer, Inc.
+
+.Dd August 20, 1997
+.Dt ARCH 1
+.Os Mac OS X
+.Sh NAME
+.Nm arch
+.Nd print architecture type
+.Sh SYNOPSIS
+.Nm arch
+.Sh DESCRIPTION
+The
+.Nm arch
+command displays the machine's architecture type.
+.Sh SEE ALSO
+.Xr machine 1
diff --git a/arch.tproj/machine.1 b/arch.tproj/machine.1
new file mode 100644 (file)
index 0000000..5c130aa
--- /dev/null
@@ -0,0 +1,53 @@
+.\"    $OpenBSD: machine.1,v 1.2 1996/06/26 05:36:23 deraadt Exp $
+.\" Copyright (c) 1980, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    from: @(#)machine.1     5.5 (Berkeley) 7/26/91
+.\"
+.Dd July 26, 1991
+.Dt MACHINE 1
+.Os
+.Sh NAME
+.Nm machine
+.Nd print machine type
+.Sh SYNOPSIS
+.Nm machine
+.Sh DESCRIPTION
+The
+.Nm machine
+command displays the machine type.
+.Sh SEE ALSO
+.Xr make 1
+.Sh HISTORY
+The
+.Nm machine
+command is
+.Ud .
index 6f6d32be241f86b68d310e7a50a49f20b8e8ed38..266d5d63b8586bdc827491292d6237f974c80bd7 100644 (file)
@@ -4,3 +4,10 @@ after_install::
        $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/atq
        $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/atrm
        $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/batch
+       mkdir -p "$(DSTROOT)/private/var/at/spool"
+       touch "$(DSTROOT)/private/var/at/at.deny"
+       mkdir -p "$(DSTROOT)/usr/share/man/man1"
+       install -c -m 644 at.1 "$(DSTROOT)/usr/share/man/man1/at.1"
+       ln -f "$(DSTROOT)/usr/share/man/man1/at.1" "$(DSTROOT)/usr/share/man/man1/atrm.1"
+       ln -f "$(DSTROOT)/usr/share/man/man1/at.1" "$(DSTROOT)/usr/share/man/man1/atq.1"
+       ln -f "$(DSTROOT)/usr/share/man/man1/at.1" "$(DSTROOT)/usr/share/man/man1/batch.1"
index 958a48c7827d851a5c5e14b8bd5169812aaa2a07..705acceec81bbea75abe136f874231298a22bd34 100644 (file)
@@ -23,7 +23,7 @@ MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /usr/bin
 WINDOWS_INSTALLDIR = /Library/Executables
 PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
+LIBS = -lcurses
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
index 67a1fba90f9b4af40a8452bda8b6dcd9e43d51c7..dd06a8358e3b2e3f11f9cf0e06d0ffae73189a96 100644 (file)
@@ -1,7 +1,7 @@
 
 .\" Copyright (c) 2000, Apple Computer, Inc.  All rights reserved.
 .\"
-.Dd March 28, 2000
+.Dd November 26, 2001
 .Dt FS_USAGE 1
 .Os "Mac OS X"
 .Sh NAME
@@ -17,7 +17,7 @@ information pertaining to filesystem activity.  By default
 this includes all system processes except the running
 fs_usage process,
 Terminal, telnetd, sshd, rlogind, tcsh, csh and sh.
-These defaluts can be overridden such that output is limited to
+These defaults can be overridden such that output is limited to
 include or exclude a list of processes specified by the user.
 .Pp
 The output presented by
@@ -55,8 +55,12 @@ option has the opposite effect, excluding sampled data
 relating to the given list of process ids or commands.
 .El
 .Pp
-If "/tmp/FileTracing" is present when a Carbon Application
-is launched, then the high level Carbon FileManager
+If you set the DYLD_IMAGE_SUFFIX environment variable 
+to "_debug", then an application will use 
+the debug version of all libraries including the 
+Carbon FileManager.  See dyld(1).  When
+fs_usage is run against a Carbon Application launched
+in this environment, then the high level Carbon FileManager
 calls will be displayed bracketing the system calls that they
 are built on.
 .Pp
@@ -65,9 +69,9 @@ The data columns displayed are as follows:
 .Pp
 .It TIMESTAMP
 TOD when call occurred. Wide mode will
-have millesecond granularity.
+have millisecond granularity.
 .It CALL
-the name of the filesystem call or page-in.
+the name of the filesystem call, page-in, page-out or physical disk access.
 .It FILE DESCRIPTOR
 Of the form F=x, x is a file descriptor. Depending
 on the type of system call, this will be either
@@ -81,6 +85,9 @@ Pathname of the file accessed (up to the last 28 bytes).
 .It FAULT ADDRESS
 Of the form A=0xnnnnnnnn, where 0xnnnnnnnn is the
 address being faulted.
+.It DISK BLOCK NUMBER
+Of the form D=0xnnnnnnnn, where 0xnnnnnnnn is the block number
+of the physical disk block being read or written.
 .It TIME INTERVAL(W)
 The elapsed time spent in the system call.
 A 'W' after the elapsed time indicates
@@ -103,3 +110,4 @@ data output will be displayed in the window.
 .Xr top 1
 .Xr sc_usage 1
 .Xr latency 1
+.Xr dyld 1
index 465d0dcfc74c842eaa9b33d2330241d3aba96303..c41e3f0b859fc6df993a4d7303498160ec44622b 100644 (file)
@@ -35,6 +35,7 @@ cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
 #include <nlist.h>
 #include <fcntl.h>
 #include <string.h>
+#include <dirent.h>
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -42,7 +43,6 @@ cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
 #include <sys/ioctl.h>
 
 #ifndef KERNEL_PRIVATE
@@ -60,6 +60,23 @@ cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
 
 extern int errno;
 
+
+
+#define MAXINDEX 2048
+
+typedef struct LibraryInfo {
+     unsigned long address;
+     char     *name;
+} LibraryInfo;
+
+LibraryInfo frameworkInfo[MAXINDEX];
+int numFrameworks = 0;
+
+char seg_addr_table[256]="/AppleInternal/Developer/seg_addr_table";
+
+char *lookup_name();
+
+
 /* 
    MAXCOLS controls when extra data kicks in.
    MAX_WIDE_MODE_COLS controls -w mode to get even wider data in path.
@@ -94,12 +111,49 @@ int  cur_max = 0;
 int  need_new_map = 1;
 int  bias_secs;
 int  wideflag = 0;
+int  columns = 0;
 int  select_pid_mode = 0;  /* Flag set indicates that output is restricted
                              to selected pids or commands */
 
 int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 
 
+#define NFS_DEV -1
+
+struct diskrec {
+        struct diskrec *next;
+        char *diskname;
+        int   dev;
+};
+
+struct diskio {
+        struct diskio *next;
+        struct diskio *prev;
+        int  type;
+        int  bp;
+        int  dev;
+        int  blkno;
+        int  iosize;
+        int  io_errno;
+        int  issuing_thread;
+        int  completion_thread;
+        char issuing_command[MAXCOMLEN];
+        double issued_time;
+        double completed_time;
+};
+
+struct diskrec *disk_list = NULL;
+struct diskio *free_diskios = NULL;
+struct diskio *busy_diskios = NULL;
+
+struct diskio *insert_diskio();
+struct diskio *complete_diskio();
+void           free_diskio();
+void           print_diskio();
+void           format_print();
+char           *find_disk_name();
+
+
 #define DBG_ZERO_FILL_FAULT   1
 #define DBG_PAGEIN_FAULT      2
 #define DBG_COW_FAULT         3
@@ -110,11 +164,39 @@ int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 #define TRACE_STRING_EXEC      0x07010008
 
 #define MACH_vmfault    0x01300000
+#define MACH_pageout    0x01300004
 #define MACH_sched      0x01400000
 #define MACH_stkhandoff 0x01400008
 #define VFS_LOOKUP      0x03010090
 #define BSC_exit        0x040C0004
 
+#define P_WrData       0x03020000
+#define P_RdData       0x03020008
+#define P_WrMeta       0x03020020
+#define P_RdMeta       0x03020028
+#define P_PgOut                0x03020040
+#define P_PgIn         0x03020048
+#define P_WrDataAsync  0x03020010
+#define P_RdDataAsync  0x03020018
+#define P_WrMetaAsync  0x03020030
+#define P_RdMetaAsync  0x03020038
+#define P_PgOutAsync   0x03020050
+#define P_PgInAsync    0x03020058
+
+#define P_WrDataDone   0x03020004
+#define P_RdDataDone   0x0302000C
+#define P_WrMetaDone   0x03020024
+#define P_RdMetaDone   0x0302002C
+#define P_PgOutDone    0x03020044
+#define P_PgInDone     0x0302004C
+#define P_WrDataAsyncDone      0x03020014
+#define P_RdDataAsyncDone      0x0302001C
+#define P_WrMetaAsyncDone      0x03020034
+#define P_RdMetaAsyncDone      0x0302003C
+#define P_PgOutAsyncDone       0x03020054
+#define P_PgInAsyncDone                0x0302005C
+
+
 #define MSC_map_fd   0x010c00ac
 #define        BSC_recvmsg  0x040C006C
 #define        BSC_sendmsg  0x040C0070
@@ -127,23 +209,30 @@ int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 #define BSC_close    0x040C0018
 #define BSC_link     0x040C0024
 #define BSC_unlink   0x040C0028
+#define BSC_chdir    0x040c0030
+#define BSC_fchdir   0x040c0034
 #define BSC_mknod    0x040C0038        
 #define BSC_chmod    0x040C003C        
 #define BSC_chown    0x040C0040        
 #define BSC_access   0x040C0084        
 #define BSC_chflags  0x040C0088        
 #define BSC_fchflags 0x040C008C
-#define BSC_sync     0x040C0090        
+#define BSC_sync     0x040C0090
+#define BSC_revoke   0x040C00E0
 #define BSC_symlink  0x040C00E4        
-#define BSC_readlink 0x040C00E8        
+#define BSC_readlink 0x040C00E8
+#define BSC_chroot   0x040C00F4        
 #define BSC_fsync    0x040C017C        
 #define BSC_readv    0x040C01E0        
 #define BSC_writev   0x040C01E4        
 #define BSC_fchown   0x040C01EC        
 #define BSC_fchmod   0x040C01F0        
-#define BSC_rename   0x040C0200        
+#define BSC_rename   0x040C0200
+#define BSC_mkfifo   0x040c0210        
 #define BSC_mkdir    0x040C0220        
-#define BSC_rmdir    0x040C0224        
+#define BSC_rmdir    0x040C0224
+#define BSC_utimes   0x040C0228
+#define BSC_futimes  0x040C022C
 #define BSC_statfs   0x040C0274        
 #define BSC_fstatfs  0x040C0278        
 #define BSC_stat     0x040C02F0        
@@ -155,17 +244,22 @@ int  one_good_pid = 0;    /* Used to fail gracefully when bad pids given */
 #define BSC_mmap     0x040c0314
 #define BSC_lseek    0x040c031c
 #define BSC_truncate 0x040C0320
-#define BSC_ftruncate     0x040C0324   
+#define BSC_ftruncate     0x040C0324
+#define BSC_undelete 0x040C0334
 #define BSC_statv    0x040C0364        
 #define BSC_lstatv   0x040C0368        
 #define BSC_fstatv   0x040C036C        
-#define BSC_mkcomplex     0x040C0360   
+#define BSC_mkcomplex   0x040C0360     
 #define BSC_getattrlist 0x040C0370     
 #define BSC_setattrlist 0x040C0374     
 #define BSC_getdirentriesattr 0x040C0378       
 #define BSC_exchangedata  0x040C037C   
 #define BSC_checkuseraccess   0x040C0380       
-#define BSC_searchfs    0x040C0384     
+#define BSC_searchfs    0x040C0384
+#define BSC_delete      0x040C0388
+#define BSC_copyfile    0x040C038C
+#define BSC_fsctl       0x040C03C8
+#define BSC_load_shared_file  0x040C04A0
 
 // Carbon File Manager support
 #define FILEMGR_PBGETCATALOGINFO                0x1e000020
@@ -259,9 +353,7 @@ int kp_nentries = 0;
 #define DBG_FUNC_ALL   (DBG_FUNC_START | DBG_FUNC_END)
 #define DBG_FUNC_MASK  0xfffffffc
 
-/* Default divisor */
-#define DIVISOR 16.6666        /* Trace divisor converts to microseconds */
-double divisor = DIVISOR;
+double divisor = 0.0;       /* Trace divisor converts to microseconds */
 
 int mib[6];
 size_t needed;
@@ -308,10 +400,23 @@ void leave()                      /* exit under normal conditions -- INT handler */
 }
 
 
+void get_screenwidth()
+{
+        struct winsize size;
+
+       columns = MAXCOLS;
+
+       if (isatty(1)) {
+               if (ioctl(1, TIOCGWINSZ, &size) != -1)
+                       columns = size.ws_col;
+       }
+}
+
+
 void sigwinch()
 {
-  if (!wideflag)
-    initscr();
+        if (!wideflag)
+               get_screenwidth();
 }
 
 int
@@ -349,8 +454,7 @@ main(argc, argv)
             printf("'fs_usage' must be run as root...\n");
             exit(1);
         }
-
-       initscr();
+       get_screenwidth();
 
        /* get our name */
        if (argc > 0) {
@@ -370,8 +474,8 @@ main(argc, argv)
                    break;
                 case 'w':
                    wideflag = 1;
-                   if (COLS < MAX_WIDE_MODE_COLS)
-                     COLS = MAX_WIDE_MODE_COLS;
+                   if (columns < MAX_WIDE_MODE_COLS)
+                     columns = MAX_WIDE_MODE_COLS;
                    break;
               default:
                 exit_usage(myname);             
@@ -397,6 +501,7 @@ main(argc, argv)
          {
            argtopid("Terminal");
            argtopid("telnetd");
+           argtopid("telnet");
            argtopid("sshd");
            argtopid("rlogind");
            argtopid("tcsh");
@@ -426,12 +531,16 @@ main(argc, argv)
        /* set up signal handlers */
        signal(SIGINT, leave);
        signal(SIGQUIT, leave);
+       signal(SIGHUP, leave);
        signal(SIGTERM, leave);
        signal(SIGWINCH, sigwinch);
 
        if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
            quit("can't allocate memory for tracing info\n");
 
+       ReadSegAddrTable();
+        cache_disk_names();
+
        set_remove();
        set_numbufs(SAMPLE_SIZE);
        set_init();
@@ -461,7 +570,7 @@ main(argc, argv)
        /* main loop */
 
        while (1) {
-               usleep(1000 * 50);
+               usleep(1000 * 25);
 
                sample_sc();
        }
@@ -470,7 +579,7 @@ main(argc, argv)
 void
 find_proc_names()
 {
-       size_t                  bufSize = 0;
+        size_t                 bufSize = 0;
        struct kinfo_proc       *kp;
        int quit();
 
@@ -512,6 +621,18 @@ struct th_info *find_thread(int thread, int type) {
        return ((struct th_info *)0);
 }
 
+
+mark_thread_waited(int thread) {
+       struct th_info *ti;
+
+       for (ti = th_state; ti < &th_state[cur_max]; ti++) {
+              if (ti->thread == thread) {
+                    ti->waited = 1;
+              }
+       }
+}
+
+
 void
 set_enable(int val) 
 {
@@ -624,8 +745,6 @@ get_bufinfo(kbufinfo_t *val)
 void
 set_remove() 
 {
-        extern int errno;
-
         errno = 0;
 
        mib[0] = CTL_KERN;
@@ -726,6 +845,7 @@ sample_sc()
                long *sargptr;
                unsigned long long now;
                struct th_info *ti;
+                struct diskio  *dio;
                void enter_syscall();
                void exit_syscall();
                void kill_thread_map();
@@ -733,9 +853,47 @@ sample_sc()
                thread  = kd[i].arg5 & KDBG_THREAD_MASK;
                debugid = kd[i].debugid;
                type    = kd[i].debugid & DBG_FUNC_MASK;
+                
+                now = (((unsigned long long)kd[i].timestamp.tv_sec) << 32) |
+                        (unsigned long long)((unsigned int)(kd[i].timestamp.tv_nsec));
+
 
                switch (type) {
 
+                case P_RdMeta:
+                case P_WrMeta:
+                case P_RdData:
+                case P_WrData:
+                case P_PgIn:
+                case P_PgOut:
+                case P_RdMetaAsync:
+                case P_WrMetaAsync:
+                case P_RdDataAsync:
+                case P_WrDataAsync:
+                case P_PgInAsync:
+                case P_PgOutAsync:
+                    insert_diskio(type, kd[i].arg1, kd[i].arg2, kd[i].arg3, kd[i].arg4, thread, (double)now);
+                    continue;
+                
+                case P_RdMetaDone:
+                case P_WrMetaDone:
+                case P_RdDataDone:
+                case P_WrDataDone:
+                case P_PgInDone:
+                case P_PgOutDone:
+                case P_RdMetaAsyncDone:
+                case P_WrMetaAsyncDone:
+                case P_RdDataAsyncDone:
+                case P_WrDataAsyncDone:
+                case P_PgInAsyncDone:
+                case P_PgOutAsyncDone:
+                    if (dio = complete_diskio(kd[i].arg1, kd[i].arg4, kd[i].arg3, thread, (double)now)) {
+                        print_diskio(dio);
+                        free_diskio(dio);
+                    }
+                    continue;
+
+
                case TRACE_DATA_NEWTHREAD:
                   
                    for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
@@ -774,8 +932,7 @@ sample_sc()
 
                case MACH_sched:
                case MACH_stkhandoff:
-                   if (ti = find_thread(thread, 0))
-                           ti->waited = 1;
+                    mark_thread_waited(thread);
                    continue;
 
                case VFS_LOOKUP:
@@ -789,7 +946,6 @@ sample_sc()
                            *sargptr++ = kd[i].arg3;
                            *sargptr++ = kd[i].arg4;
                            ti->pathptr = sargptr;
-
                    } else {
                            sargptr = ti->pathptr;
 
@@ -802,6 +958,19 @@ sample_sc()
                            if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
                              continue;
 
+                            /*
+                             We need to detect consecutive vfslookup entries.
+                             So, if we get here and find a START entry,
+                             fake the pathptr so we can bypass all further
+                             vfslookup entries.
+                           */
+
+                           if (debugid & DBG_FUNC_START)
+                             {
+                               (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH];
+                               continue;
+                             }
+
                            *sargptr++ = kd[i].arg1;
                            *sargptr++ = kd[i].arg2;
                            *sargptr++ = kd[i].arg3;
@@ -810,8 +979,6 @@ sample_sc()
                    }
                    continue;
                }
-               now = (((unsigned long long)kd[i].timestamp.tv_sec) << 32) |
-                       (unsigned long long)((unsigned int)(kd[i].timestamp.tv_nsec));
 
                if (debugid & DBG_FUNC_START) {
                       char *p;
@@ -1025,9 +1192,18 @@ sample_sc()
                }
                switch (type) {
 
+               case MACH_pageout:
+                   if (kd[i].arg2) 
+                           exit_syscall("PAGE_OUT_D", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
+                   else
+                           exit_syscall("PAGE_OUT_V", thread, type, 0, kd[i].arg1, 0, 4, (double)now);
+                   break;
+
                case MACH_vmfault:
                    if (kd[i].arg2 == DBG_PAGEIN_FAULT)
-                           exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
+                           exit_syscall("PAGE_IN", thread, type, kd[i].arg4, kd[i].arg1, 0, 6, (double)now);
+                    else if (kd[i].arg2 == DBG_CACHE_HIT_FAULT)
+                           exit_syscall("CACHE_HIT", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
                    else {
                            if (ti = find_thread(thread, type)) {
                                    if (ti == &th_state[cur_max - 1])
@@ -1064,6 +1240,10 @@ sample_sc()
                case BSC_stat:
                    exit_syscall("stat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
+                    
+               case BSC_load_shared_file:
+                   exit_syscall("load_sf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
 
                case BSC_open:
                    exit_syscall("open", thread, type, kd[i].arg1, kd[i].arg2, 2, 0, (double)now);
@@ -1113,13 +1293,49 @@ sample_sc()
                    exit_syscall("access", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
 
+               case BSC_chdir:
+                   exit_syscall("chdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_chroot:
+                   exit_syscall("chroot", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_utimes:
+                   exit_syscall("utimes", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_delete:
+                   exit_syscall("delete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_undelete:
+                   exit_syscall("undelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_revoke:
+                   exit_syscall("revoke", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
+               case BSC_fsctl:
+                   exit_syscall("fsctl", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+                    
                case BSC_chflags:
                    exit_syscall("chflags", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
-
+                    
                case BSC_fchflags:
                    exit_syscall("fchflags", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
+                    
+               case BSC_fchdir:
+                   exit_syscall("fchdir", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+                    
+               case BSC_futimes:
+                   exit_syscall("futimes", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
 
                case BSC_sync:
                    exit_syscall("sync", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
@@ -1153,13 +1369,13 @@ sample_sc()
                    exit_syscall("fchmod", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
                    break;
 
-               case BSC_rename:
-                   exit_syscall("rename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
-                   break;
-
                case BSC_mkdir:
                    exit_syscall("mkdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
+                    
+               case BSC_mkfifo:
+                   exit_syscall("mkfifo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
 
                case BSC_rmdir:
                    exit_syscall("rmdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
@@ -1225,9 +1441,19 @@ sample_sc()
                    exit_syscall("getdirentriesattr", thread, type, kd[i].arg1, kd[i].arg2, 0, 1, (double)now);
                    break;
 
+
                case BSC_exchangedata:
                    exit_syscall("exchangedata", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
                    break;
+                    
+               case BSC_rename:
+                   exit_syscall("rename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_copyfile:
+                   exit_syscall("copyfile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
 
                case BSC_checkuseraccess:
                    exit_syscall("checkuseraccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
@@ -1461,6 +1687,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
 
        switch (type) {
 
+       case MACH_pageout:
        case MACH_vmfault:
        case MSC_map_fd:
        case BSC_mmap:
@@ -1469,6 +1696,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
        case BSC_recvfrom:
        case BSC_sendto:
        case BSC_stat:
+       case BSC_load_shared_file:
        case BSC_open:
        case BSC_close:
        case BSC_read:
@@ -1483,6 +1711,16 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
        case BSC_access:
        case BSC_chflags:
        case BSC_fchflags:
+       case BSC_fchdir:
+       case BSC_futimes:
+       case BSC_chdir:
+       case BSC_utimes:
+       case BSC_chroot:
+       case BSC_undelete:
+       case BSC_delete:
+       case BSC_revoke:
+       case BSC_fsctl:
+       case BSC_copyfile:
        case BSC_sync:
        case BSC_symlink:
        case BSC_readlink:
@@ -1493,6 +1731,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
        case BSC_fchmod:
        case BSC_rename:
        case BSC_mkdir:
+       case BSC_mkfifo:
        case BSC_rmdir:
        case BSC_statfs:
        case BSC_fstatfs:
@@ -1589,6 +1828,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
                   return;
           if (i >= cur_max)
                   cur_max = i + 1;
+                   
 
           if ((type >> 24) == FILEMGR_CLASS) {
                   ti->in_filemgr = 1;
@@ -1604,7 +1844,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
                   sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
                   tsclen = strlen(buf);
 
-                  if (COLS > MAXCOLS || wideflag) {
+                  if (columns > MAXCOLS || wideflag) {
                           usecs = l_usecs - (long long)((long long)secs * 1000000);
                           sprintf(&buf[tsclen], ".%03ld", (long)usecs / 1000);
                           tsclen = strlen(buf);
@@ -1625,12 +1865,12 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
                       /*
                         Calculate white space out to command
                       */
-                      if (COLS > MAXCOLS || wideflag)
+                      if (columns > MAXCOLS || wideflag)
                         {
-                          clen = COLS - (tsclen + nmclen + argsclen + 20);
+                          clen = columns - (tsclen + nmclen + argsclen + 20);
                         }
                       else
-                        clen = COLS - (tsclen + nmclen + argsclen + 12);
+                        clen = columns - (tsclen + nmclen + argsclen + 12);
 
                       if(clen > 0)
                         {
@@ -1647,7 +1887,7 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
                           printf(buf);
                         }
 
-                      if (COLS > MAXCOLS || wideflag)
+                      if (columns > MAXCOLS || wideflag)
                           printf("%-20.20s\n", map->command); 
                       else
                           printf("%-12.12s\n", map->command); 
@@ -1666,7 +1906,6 @@ enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
           ti->arg4   = kd->arg4;
           ti->pathptr = (long *)0;
           ti->pathname[0] = 0;
-
           break;
 
        default:
@@ -1680,21 +1919,45 @@ void
 exit_syscall(char *sc_name, int thread, int type, int error, int retval,
                            int has_fd, int has_ret, double now)
 {
-       struct th_info *ti;
+    struct th_info *ti;
+      
+    if ((ti = find_thread(thread, type)) == (struct th_info *)0)
+        return;
+               
+    format_print(ti, sc_name, thread, type, error, retval, has_fd, has_ret, now, ti->stime, ti->waited, ti->pathname, NULL);
+
+    if (ti == &th_state[cur_max - 1])
+        cur_max--;
+    ti->thread = 0;
+}
+
+
+
+void
+format_print(struct th_info *ti, char *sc_name, int thread, int type, int error, int retval,
+                           int has_fd, int has_ret, double now, double stime, int waited, char *pathname, struct diskio *dio)
+{
        int secs;
        int usecs;
        int nopadding;
        long long l_usecs;
        long curr_time;
+       char *command_name;
        kd_threadmap *map;
        kd_threadmap *find_thread_map();
        int len = 0;
        int clen = 0;
+       char *framework_name;
        char buf[MAXCOLS];
       
-       if ((ti = find_thread(thread, type)) == (struct th_info *)0)
-              return;
-       map = find_thread_map(thread);
+       command_name = "";
+       
+       if (dio)
+            command_name = dio->issuing_command;
+       else {
+            if (map = find_thread_map(thread))
+                command_name = map->command;
+       }
        l_usecs = (long long)(now / divisor);
        secs = l_usecs / 1000000;
 
@@ -1706,11 +1969,12 @@ exit_syscall(char *sc_name, int thread, int type, int error, int retval,
        sprintf(buf, "%-8.8s", &(ctime(&curr_time)[11]));
        clen = strlen(buf);
 
-       if (COLS > MAXCOLS || wideflag) {
+       if (columns > MAXCOLS || wideflag) {
               nopadding = 0;
               usecs = l_usecs - (long long)((long long)secs * 1000000);
               sprintf(&buf[clen], ".%03ld", (long)usecs / 1000);
               clen = strlen(buf);
+               
               if ((type >> 24) != FILEMGR_CLASS) {
                   if (find_thread(thread, -1)) {
                       sprintf(&buf[clen], "   ");
@@ -1721,53 +1985,75 @@ exit_syscall(char *sc_name, int thread, int type, int error, int retval,
        } else
               nopadding = 1;
 
-       if (((type >> 24) == FILEMGR_CLASS) && (COLS > MAXCOLS || wideflag))
+       if (((type >> 24) == FILEMGR_CLASS) && (columns > MAXCOLS || wideflag))
               sprintf(&buf[clen], "  %-18.18s", sc_name);
        else
               sprintf(&buf[clen], "  %-15.15s", sc_name);
 
        clen = strlen(buf);
-
-       if (COLS > MAXCOLS || wideflag) {
+       
+       framework_name = (char *)0;
+
+       if (columns > MAXCOLS || wideflag) {
+            if (has_ret == 7) {
+                sprintf(&buf[clen], " D=0x%8.8x", dio->blkno);
+                
+                clen = strlen(buf);
+                
+                if (dio->io_errno)
+                    sprintf(&buf[clen], "  [%3d]       ", dio->io_errno);
+                else
+                    sprintf(&buf[clen], "  B=0x%-6x   /dev/%s", dio->iosize, find_disk_name(dio->dev));
+            } else {
+              
               if (has_fd == 2 && error == 0)
                       sprintf(&buf[clen], " F=%-3d", retval);
               else if (has_fd == 1)
                       sprintf(&buf[clen], " F=%-3d", ti->arg1);
-              else if (has_ret != 2)
+              else if (has_ret != 2 && has_ret != 6)
                       sprintf(&buf[clen], "      ");
 
               clen = strlen(buf);
 
-              if (error)
+              if (has_ret == 2 || has_ret == 6)
+                      framework_name = lookup_name(retval);
+
+              if (error && has_ret != 6)
                       sprintf(&buf[clen], "[%3d]       ", error);
               else if (has_ret == 3)
                       sprintf(&buf[clen], "O=0x%8.8x", ti->arg3);
               else if (has_ret == 5)
                       sprintf(&buf[clen], "O=0x%8.8x", retval);
               else if (has_ret == 2) 
-                      sprintf(&buf[clen], " A=0x%8.8x     ", retval);
+                      sprintf(&buf[clen], " A=0x%8.8x              ", retval);
+              else if (has_ret == 6) 
+                      sprintf(&buf[clen], " A=0x%8.8x  B=0x%-8x", retval, error);
               else if (has_ret == 1)
                       sprintf(&buf[clen], "  B=0x%-6x", retval);
               else if (has_ret == 4)
-                      sprintf(&buf[clen], "R=0x%-8x", retval);
+                      sprintf(&buf[clen], "B=0x%-8x", retval);
               else
                       sprintf(&buf[clen], "            ");
-              clen = strlen(buf);
+            }
+            clen = strlen(buf);
        }
        printf(buf);
 
        /*
         Calculate space available to print pathname
        */
-       if (COLS > MAXCOLS || wideflag)
-        clen =  COLS - (clen + 13 + 20);
+       if (columns > MAXCOLS || wideflag)
+        clen =  columns - (clen + 13 + 20);
        else
-        clen =  COLS - (clen + 13 + 12);
+        clen =  columns - (clen + 13 + 12);
 
        if ((type >> 24) != FILEMGR_CLASS && !nopadding)
         clen -= 3;
 
-       sprintf(&buf[0], " %s ", ti->pathname);
+       if (framework_name)
+        sprintf(&buf[0], " %s ", framework_name);
+       else
+        sprintf(&buf[0], " %s ", pathname);
        len = strlen(buf);
        
        if (clen > len)
@@ -1791,30 +2077,26 @@ exit_syscall(char *sc_name, int thread, int type, int error, int retval,
           printf(&buf[len - clen]);
         }
 
-       usecs = (unsigned long)(((double)now - ti->stime) / divisor);
+       usecs = (unsigned long)((now - stime) / divisor);
        secs = usecs / 1000000;
        usecs -= secs * 1000000;
 
        if ((type >> 24) != FILEMGR_CLASS && !nopadding)
               printf("   ");
               
-       printf(" %2ld.%06ld", (long)secs, (long)usecs);
-       if (ti->waited)
+       printf(" %2ld.%06ld", (unsigned long)secs, (unsigned long)usecs);
+       
+       if (waited)
               printf(" W");
        else
               printf("  ");
 
-       if (map) {
-              if (COLS > MAXCOLS || wideflag)
-                      printf(" %-20.20s", map->command);
-              else
-                      printf(" %-12.12s", map->command);
-       }
-       printf("\n");
+       if (columns > MAXCOLS || wideflag)
+               printf(" %-20.20s", command_name);
+       else
+               printf(" %-12.12s", command_name);
 
-       if (ti == &th_state[cur_max - 1])
-                cur_max--;
-       ti->thread = 0;
+       printf("\n");
        fflush (0);
 }
 
@@ -1849,7 +2131,7 @@ void getdivisor()
     unsigned int proc_to_abs_num;
     unsigned int proc_to_abs_denom;
 
-       extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
+    extern void MKGetTimeBaseInfo(unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
 
     MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
                       &proc_to_abs_num,  &proc_to_abs_denom);
@@ -1875,10 +2157,7 @@ void read_command_map()
         if (mapptr = (kd_threadmap *) malloc(size))
             bzero (mapptr, size);
        else
-       {
-           printf("Thread map is not initialized -- this is not fatal\n");
            return;
-       }
     }
  
     /* Now read the threadmap */
@@ -1891,13 +2170,9 @@ void read_command_map()
     if (sysctl(mib, 3, mapptr, &size, NULL, 0) < 0)
     {
         /* This is not fatal -- just means I cant map command strings */
-
-        printf("Can't read the thread map -- this is not fatal\n");
        free(mapptr);
        mapptr = 0;
-       return;
     }
-    return;
 }
 
 
@@ -2012,3 +2287,376 @@ argtopid(str)
 }
 
 
+
+char *lookup_name(unsigned long addr) 
+{       
+        register int i;
+       register int start, last;
+
+
+       if (numFrameworks == 0 || addr < frameworkInfo[0].address || addr > frameworkInfo[numFrameworks].address)
+               return (0);
+
+       start = 0;
+       last  = numFrameworks;
+
+       for (i = numFrameworks / 2; i >= 0 && i < numFrameworks; ) {
+
+               if (addr >= frameworkInfo[i].address && addr < frameworkInfo[i+1].address)
+                       return(frameworkInfo[i].name);
+
+               if (addr >= frameworkInfo[i].address) {
+                       start = i;
+                       i = start + ((last - i) / 2);
+               } else {
+                       last = i;
+                       i = start + ((i - start) / 2);
+               }
+       }
+       return (0);
+}
+
+
+/*
+ * Comparison routines for sorting
+ */
+static int compareFrameworkAddress(const void  *aa, const void *bb)
+{
+    LibraryInfo *a = (LibraryInfo *)aa;
+    LibraryInfo *b = (LibraryInfo *)bb;
+
+    if (a->address < b->address) return -1;
+    if (a->address == b->address) return 0;
+    return 1;
+}
+
+
+int scanline(char *inputstring,char **argv)
+{
+     int n = 0;
+     char **ap = argv, *p, *val;  
+
+     for (p = inputstring; p != NULL; ) 
+     {
+        while ((val = strsep(&p, " \t")) != NULL && *val == '\0');
+        *ap++ = val;
+        n++; 
+     }
+     *ap = 0;
+     return n;
+}
+
+
+int ReadSegAddrTable()
+{
+    char buf[1024];
+
+    FILE *fd;
+    unsigned long frameworkAddress, frameworkDataAddress, previousFrameworkAddress;
+    char frameworkName[256];
+    char *tokens[64];
+    int  ntokens;
+    char *substring,*ptr;
+    int  founddylib = 0;
+    int  i;
+
+
+    bzero(buf, sizeof(buf));
+    bzero(tokens, sizeof(tokens));
+    
+    numFrameworks = 0;
+
+    if ((fd = fopen(seg_addr_table, "r")) == 0)
+    {
+        return 0;
+    }
+    fgets(buf, 1023, fd);
+
+    if (*buf == '#')
+    {
+        founddylib = 0;
+        frameworkName[0] = 0;
+        previousFrameworkAddress = 0;
+
+        while (fgets(buf, 1023, fd) && numFrameworks < (MAXINDEX - 2))
+        {
+           /*
+            * Get rid of EOL
+            */
+           buf[strlen(buf)-1] = 0;
+
+           if (strncmp(buf, "# dyld:", 7) == 0) {
+               /*
+                * the next line in the file will contain info about dyld
+                */
+               founddylib = 1;
+               continue;
+           }
+           /*
+            * This is a split library line: parse it into 3 tokens
+            */
+           ntokens = scanline(buf, tokens);
+
+           if (ntokens < 3)
+               continue;
+
+           frameworkAddress     = strtoul(tokens[0], 0, 16);
+           frameworkDataAddress = strtoul(tokens[1], 0, 16);
+
+           if (founddylib) {
+               /*
+                * dyld entry is of a different form from the std split library
+                * it consists of a base address and a size instead of a code
+                * and data base address
+                */
+               frameworkInfo[numFrameworks].address   = frameworkAddress;
+               frameworkInfo[numFrameworks+1].address = frameworkAddress + frameworkDataAddress;
+
+               frameworkInfo[numFrameworks].name   = (char *)"dylib";
+               frameworkInfo[numFrameworks+1].name = (char *)0;
+
+               numFrameworks += 2;
+               founddylib = 0;
+
+               continue;
+           }  
+
+           /*
+            * Make sure that we have 2 addresses and a path
+            */
+           if (!frameworkAddress)
+               continue;
+           if (!frameworkDataAddress)
+               continue;
+           if (*tokens[2] != '/')
+               continue;
+           if (frameworkAddress == previousFrameworkAddress) 
+               continue;
+           previousFrameworkAddress = frameworkAddress;
+
+            /*
+            * Extract lib name from path name
+            */
+           if (substring = strrchr(tokens[2], '.'))
+           {           
+               /*
+                * There is a ".": name is whatever is between the "/" around the "." 
+                */
+             while ( *substring != '/') {                  /* find "/" before "." */
+                   substring--;
+               }
+               substring++;
+               strcpy(frameworkName, substring);           /* copy path from "/" */
+               substring = frameworkName;
+
+               while ( *substring != '/' && *substring)    /* find "/" after "." and stop string there */
+                   substring++;
+               *substring = 0;
+           }
+           else 
+           {
+               /*
+                * No ".": take segment after last "/"
+                */
+               ptr = tokens[2];
+               substring = ptr;
+
+               while (*ptr) 
+               {
+                   if (*ptr == '/')
+                       substring = ptr + 1;
+                   ptr++;
+               }
+               strcpy(frameworkName, substring);
+           }
+           frameworkInfo[numFrameworks].address   = frameworkAddress;
+           frameworkInfo[numFrameworks+1].address = frameworkDataAddress;
+
+           frameworkInfo[numFrameworks].name = (char *)malloc(strlen(frameworkName) + 1);
+           strcpy(frameworkInfo[numFrameworks].name, frameworkName);
+           frameworkInfo[numFrameworks+1].name = frameworkInfo[numFrameworks].name;
+
+           numFrameworks += 2;
+        }
+    }
+    frameworkInfo[numFrameworks].address = frameworkInfo[numFrameworks - 1].address + 0x800000;
+    frameworkInfo[numFrameworks].name = (char *)0;
+
+    fclose(fd);
+
+    qsort(frameworkInfo, numFrameworks, sizeof(LibraryInfo), compareFrameworkAddress);
+
+    return 1;
+}
+
+
+struct diskio *insert_diskio(int type, int bp, int dev, int blkno, int io_size, int thread, double curtime)
+{
+    register struct diskio *dio;
+    register kd_threadmap  *map;
+    
+    if (dio = free_diskios)
+        free_diskios = dio->next;
+    else {
+        if ((dio = (struct diskio *)malloc(sizeof(struct diskio))) == NULL)
+            return (NULL);
+    }
+    dio->prev = NULL;
+    
+    dio->type = type;
+    dio->bp = bp;
+    dio->dev = dev;
+    dio->blkno = blkno;
+    dio->iosize = io_size;
+    dio->issued_time = curtime;
+    dio->issuing_thread = thread;
+    
+    if (map = find_thread_map(thread))
+        strcpy(dio->issuing_command, map->command);
+    else
+        strcpy(dio->issuing_command, "");
+    
+    dio->next = busy_diskios;
+    if (dio->next)
+        dio->next->prev = dio;
+    busy_diskios = dio;
+
+    return (dio);
+}
+
+
+struct diskio *complete_diskio(int bp, int io_errno, int resid, int thread, double curtime)
+{
+    register struct diskio *dio;
+    
+    for (dio = busy_diskios; dio; dio = dio->next) {
+        if (dio->bp == bp) {
+        
+            if (dio == busy_diskios) {
+                if (busy_diskios = dio->next)
+                    dio->next->prev = NULL;
+            } else {
+                if (dio->next)
+                    dio->next->prev = dio->prev;
+                dio->prev->next = dio->next;
+            }
+            dio->iosize -= resid;
+            dio->io_errno = io_errno;
+            dio->completed_time = curtime;
+            dio->completion_thread = thread;
+            
+           return (dio);
+        }    
+    }
+    return ((struct diskio *)0);
+}
+
+
+void free_diskio(struct diskio *dio)
+{
+    dio->next = free_diskios;
+    free_diskios = dio;
+}
+
+
+void print_diskio(struct diskio *dio)
+{
+    register char  *p;
+    struct th_info *ti;
+
+    switch (dio->type) {
+
+        case P_RdMeta:
+            p = "  RdMeta";
+            break;
+        case P_WrMeta:
+            p = "  WrMeta";
+            break;
+        case P_RdData:
+            p = "  RdData";
+            break;
+        case P_WrData:
+            p = "  WrData";
+            break;        
+        case P_PgIn:
+            p = "  PgIn";
+            break;
+        case P_PgOut:
+            p = "  PgOut";
+            break;
+        case P_RdMetaAsync:
+            p = "  RdMeta[async]";
+            break;
+        case P_WrMetaAsync:
+            p = "  WrMeta[async]";
+            break;
+        case P_RdDataAsync:
+            p = "  RdData[async]";
+            break;
+        case P_WrDataAsync:
+            p = "  WrData[async]";
+            break;        
+        case P_PgInAsync:
+            p = "  PgIn[async]";
+            break;
+        case P_PgOutAsync:
+            p = "  PgOut[async]";
+            break;
+
+    }
+    format_print(NULL, p, dio->issuing_thread, dio->type, 0, 0, 0, 7, dio->completed_time, dio->issued_time, 1, "", dio);
+}
+
+
+cache_disk_names()
+{
+    struct stat    st;
+    DIR            *dirp = NULL;
+    struct dirent  *dir;
+    struct diskrec *dnp;
+
+
+    if ((dirp = opendir("/dev")) == NULL)
+        return;
+        
+    while ((dir = readdir(dirp)) != NULL) {
+        char nbuf[MAXPATHLEN];
+        
+        if (dir->d_namlen < 5 || strncmp("disk", dir->d_name, 4))
+            continue;
+        sprintf(nbuf, "%s/%s", "/dev", dir->d_name);
+        
+       if (stat(nbuf, &st) < 0)
+            continue;
+
+        if ((dnp = (struct diskrec *)malloc(sizeof(struct diskrec))) == NULL)
+            continue;
+            
+        if ((dnp->diskname = (char *)malloc(dir->d_namlen + 1)) == NULL) {
+            free(dnp);
+            continue;
+        }
+        strncpy(dnp->diskname, dir->d_name, dir->d_namlen);
+        dnp->diskname[dir->d_namlen] = 0;
+        dnp->dev = st.st_rdev;
+        
+        dnp->next = disk_list;
+        disk_list = dnp;
+    }
+    (void) closedir(dirp);
+}
+
+
+char *find_disk_name(int dev)
+{
+    struct diskrec *dnp;
+    
+    if (dev == NFS_DEV)
+        return ("NFS");
+        
+    for (dnp = disk_list; dnp; dnp = dnp->next) {
+        if (dnp->dev == dev)
+            return (dnp->diskname);
+    }
+    return ("NOTFOUND");
+}
index 2929636a1f2adae105bfb500051015401284f428..f6545061f9e0a60d8452dcf217e2cc4b2dc3b3fd 100644 (file)
@@ -2,4 +2,7 @@ INSTALL_PERMISSIONS = 500  # If set, 'install' chmod's executable to this
 #CHFLAGS = /usr/bin/chflags
 #after_install::
 #      $(CHFLAGS) schg  $(DSTROOT)$(INSTALLDIR)/$(NAME)
-
+after_install:
+       mkdir -p "$(DSTROOT)/usr/share/man/man8"
+       install -c -m 644 init.8 "$(DSTROOT)/usr/share/man/man8/init.8"
+       ln -f "$(DSTROOT)/usr/share/man/man8/init.8" "$(DSTROOT)/usr/share/man/man8/securelevel.8"
index 3ab1a1d609d2572543a549fe8aaa521b9865aa97..04b6fe7bbb3d8dc19684022904915e17470685b2 100644 (file)
@@ -1,4 +1,4 @@
 # can be added to Compiler Flags to provide Secure login
 # -DSECURE  LIBS = -lutil   
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
+AFTER_INSTALL = after_install
index 1dd3015391e9ce17034c24f69399b7add334e258..b5b097973fce54fe09ae9edb1ae77130ec7c0d58 100644 (file)
@@ -884,7 +884,7 @@ runcom()
                {
                    argv[1] = _PATH_RUNCOM_BOOT;
                    argv[2] = requested_transition == single_user
-                           ? "singleuser" : 0;
+                           ? "singleuser" : "multiuser";
                }
                else /* runcom_mode != BOOT_SCRIPT */
                {
index c18265a57db77a1dccb4c96a6ec983016c3c61b1..e8456220322dffff540146764096090bbcb076ab 100644 (file)
@@ -14,8 +14,7 @@ PROJECT_TYPE = Tool
 
 CFILES = iostat.c
 
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble iostat.8\
-            names.c
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble iostat.8
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
@@ -29,6 +28,7 @@ DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
 
+FRAMEWORKS = -framework CoreFoundation -framework IOKit
 
 
 NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
index a3733f4e34e814ba379b3c256a04f86cd64e77cb..e2b071cffb0817f385156c2cf96bb781d0c1a6c2 100644 (file)
@@ -85,8 +85,8 @@
 
 # Ownership and permissions of files installed by 'install' target
 #INSTALL_AS_USER = root        # User to chown app to
-INSTALL_AS_GROUP = kmem      # Group to chgrp app to 
-INSTALL_PERMISSIONS = 2555        # If set, 'install' chmod's executable to this
+#INSTALL_AS_GROUP = kmem      # Group to chgrp app to 
+#INSTALL_PERMISSIONS = 2555        # If set, 'install' chmod's executable to this
 
 # Options to strip for bundles, apps with bundles, and apps without bundles, 
 # respectively.
index 9f8d67b49d82a925b3d6ced9dfdf8b6f36be5ae5..5cae2dce3f84f12f8389d34ae237adaa44976623 100644 (file)
@@ -1,11 +1,12 @@
 {
     DOCICONFILES = (); 
     FILESTABLE = {
+        FRAMEWORKS = (CoreFoundation.framework, IOKit.framework); 
         C_FILES = (); 
         H_FILES = (); 
         OTHER_LIBS = (); 
         OTHER_LINKED = (iostat.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, iostat.8, names.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, iostat.8); 
         PRECOMPILED_HEADERS = (); 
         PROJECT_HEADERS = (); 
         PUBLIC_HEADERS = (); 
index 48ef627b86aa6aff64d554525b3e63256dff23a3..129945eb00d0d0d2bfc5349301b3526845d077a7 100644 (file)
@@ -1,3 +1,32 @@
+.\"
+.\" Copyright (c) 1997 Kenneth D. Merry.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD: src/usr.sbin/iostat/iostat.8,v 1.20 2001/08/07 13:59:48 ru Exp $
+.\"
 .\" Copyright (c) 1985, 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
 .\"
 .\"    @(#)iostat.8    8.1 (Berkeley) 6/6/93
 .\"
-.Dd June 6, 1993
+.Dd September 27, 2001
 .Dt IOSTAT 8
-.Os BSD 4
+.Os
 .Sh NAME
 .Nm iostat
 .Nd report
 .Tn I/O
 statistics
 .Sh SYNOPSIS
-.Nm iostat
+.Nm
+.Op Fl CdKIoT?\&
 .Op Fl c Ar count
-.Op Fl M Ar core
-.Op Fl N Ar system
+.Op Fl n Ar devs
 .Op Fl w Ar wait
 .Op Ar drives
 .Sh DESCRIPTION
 .Nm Iostat
 displays kernel
 .Tn I/O
-statistics on terminal, disk and cpu
-operations.
+statistics on terminal, device and cpu operations.
+The first statistics that are printed are averaged over the system uptime.
+To get information about the current activity, a suitable wait time should
+be specified, so that the subsequent sets of printed statistics will be
+averaged over that time.
 .Pp
 The options are as follows:
 .Bl -tag -width flag
@@ -59,18 +91,50 @@ The options are as follows:
 Repeat the display
 .Ar count
 times.
-The first display is for the time since a reboot and each subsequent
-report is for the time period since the last display.
 If no
 .Ar wait
 interval is specified, the default is 1 second.
-.It Fl M
-Extract values associated with the name list from the specified core
-instead of the default
-.Dq Pa /dev/kmem .
-.It Fl N
-Extract the name list from the specified system instead of the default
-.Dq Pa /vmunix .
+.It Fl C
+Display CPU statistics.
+This is on by default, unless
+.Fl d
+is specified.
+.It Fl d
+Display only device statistics.
+If this flag is turned on, only device statistics will be displayed, unless
+.Fl C
+or
+.Fl T
+is also specfied to enable the display of CPU or TTY statistics.
+.It Fl I
+Display total statstics for a given time period, rather than average
+statistics for each second during that time period.
+.It Fl K
+In the blocks transfered display (-o), display block count in kilobytes rather
+then the device native block size.
+.It Fl n
+Display up to
+.Ar devs
+number of devices.
+.Nm
+will display fewer devices if there aren't
+.Ar devs
+devices present.
+.It Fl o
+Display old-style
+.Nm
+device statistics.
+Sectors per second, transfers per second, and miliseconds per seek are
+displayed.
+If
+.Fl I
+is specified, total blocks/sectors, total transfers, and
+miliseconds per seek are displayed.
+.It Fl T
+Display TTY statistics.
+This is on by default, unless
+.Fl d
+is specified.
 .It Fl w
 Pause
 .Ar wait
@@ -78,6 +142,8 @@ seconds between each display.
 If no repeat
 .Ar count
 is specified, the default is infinity.
+.It Fl ?\&
+Display a usage statement and exit.
 .El
 .Pp
 .Nm Iostat
@@ -90,16 +156,66 @@ characters read from terminals
 .It tout
 characters written to terminals
 .El
-.It disks
-Disk operations (this field is system dependent). 
-The header of the field is the disk name and unit number.
-If more than four disk drives are configured in the system,
-.Nm iostat
-displays only the first four drives.
+.It devices
+Device operations.
+The header of the field is the device name and unit number.
+.Nm
+will display as many devices as will fit in a standard 80 column screen, or
+the maximum number of devices in the system, whichever is smaller.
+If
+.Fl n
+is specified on the command line,
+.Nm
+will display the smaller of the
+requested number of devices, and the maximum number of devices in the system.
 To force
-.Nm iostat
+.Nm
 to display specific drives, their names may be supplied on the command
 line.
+.Nm
+will not display more devices than will fit in an 80 column screen, unless
+the
+.Fl n
+argument is given on the command line to specify a maximum number of
+devices to display, or the list of specified devices exceeds 80 columns.
+If fewer devices are specified on the command line than will fit in an 80
+column screen,
+.Nm
+will show only the specified devices.
+.Pp
+The standard
+.Nm
+device display shows the following statistics:
+.Pp
+.Bl -tag -width indent -compact
+.It KB/t
+kilobytes per transfer
+.It tps
+transfers per second
+.It MB/s
+megabytes per second
+.El
+.Pp
+The standard
+.Nm
+device display, with the
+.Fl I
+flag specified, shows the following statistics:
+.Pp
+.Bl -tag -width indent -compact
+.It KB/t
+kilobytes per transfer
+.It xfrs
+total number of transfers
+.It MB
+total number of megabytes transferred
+.El
+.Pp
+The old-style
+.Nm
+display (using
+.Fl o )
+shows the following statistics:
 .Pp
 .Bl -tag -width indent -compact
 .It sps
@@ -107,36 +223,70 @@ sectors transferred per second
 .It tps
 transfers per second
 .It msps
-milliseconds per average seek (including implied
-seeks and rotational latency)
+average milliseconds per transaction
+.El
+.Pp
+The old-style
+.Nm
+display, with the
+.Fl I
+flag specified, shows the following statistics:
+.Pp
+.Bl -tag -width indent -compact
+.It blk
+total blocks/sectors transferred
+.It xfr
+total transfers
+.It msps
+average milliseconds per transaction
 .El
 .It cpu
 .Bl -tag -width indent -compact
 .It \&us
 % of cpu time in user mode
-.It \&ni
-% of cpu time in user mode running niced processes
 .It \&sy
 % of cpu time in system mode
 .It \&id
 % of cpu time in idle mode
 .El
 .El
-.Sh FILES
-.Bl -tag -width /dev/kmem -compact
-.It Pa /vmunix
-Default kernel namelist.
-.It Pa /dev/kmem
-Default memory file.
-.El
+.Sh EXAMPLES
+.Dl iostat -w 1 disk0 disk2
+.Pp
+Display statistics for the first and third disk devices device every
+second ad infinitum.
+.Pp
+.Dl iostat -c 2
+.Pp
+Display the statistics for the first four devices in the system twice, with
+a one second display interval.
+.Pp
+.Dl iostat -Iw 3
+.Pp
+Display total statistics every three seconds ad infinitum.
+.Pp
+.Dl iostat -odICTw 2 -c 9
+.Pp
+Display total statistics using the old-style output format 9 times, with
+a two second interval between each measurement/display.
+The
+.Fl d
+flag generally disables the TTY and CPU displays, but since the
+.Fl T
+and
+.Fl C
+flags are given, the TTY and CPU displays will be displayed.
 .Sh SEE ALSO
 .Xr fstat 1 ,
 .Xr netstat 1 ,
 .Xr nfsstat 1 ,
-.Xr \&ps 1 ,
-.Xr systat 1 ,
-.Xr vmstat 1 ,
-.Xr pstat 8
+.Xr ps 1 ,
+.Xr pstat 8 ,
 .Pp
 The sections starting with ``Interpreting system activity'' in
 .%T "Installing and Operating 4.3BSD" .
+.Sh HISTORY
+This version of
+.Nm
+first appeared in
+.Nm FreeBSD 3.0 .
index 54cbf1c10ea0ac32a151b403d89be8d77fe03830..da5fe41014f589f330e8a525b29e8416c6c0d9aa 100644 (file)
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
+/*
+ * Copyright (c) 1997, 1998, 2000, 2001  Kenneth D. Merry
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.sbin/iostat/iostat.c,v 1.22 2001/09/01 07:40:19 kris Exp $
+ */
+/*
+ * Parts of this program are derived from the original FreeBSD iostat
+ * program:
+ */
 /*-
  * Copyright (c) 1986, 1991, 1993
  *     The Regents of the University of California.  All rights reserved.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+/*
+ * Ideas for the new iostat statistics output modes taken from the NetBSD
+ * version of iostat:
+ */
+/*
+ * Copyright (c) 1996 John M. Vinopal
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 for the NetBSD Project
+ *      by John M. Vinopal.
+ * 4. 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.
+ */
 
-#ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1986, 1991, 1993\n\
-       The Regents of the University of California.  All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)iostat.c   8.3 (Berkeley) 4/28/95";
-#endif /* not lint */
+#define IOKIT  1       /* to get io_name_t in device_types.h */
 
 #include <sys/param.h>
-#include <sys/buf.h>
-#include <sys/dkstat.h>
+#include <sys/sysctl.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOBlockStorageDriver.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/IOBSD.h>
 
 #include <err.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <kvm.h>
-#include <limits.h>
-#include <nlist.h>
-#include <paths.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-struct nlist namelist[] = {
-#define        X_DK_TIME       0
-       { "_dk_time" },
-#define        X_DK_XFER       1
-       { "_dk_xfer" },
-#define        X_DK_WDS        2
-       { "_dk_wds" },
-#define        X_TK_NIN        3
-       { "_tk_nin" },
-#define        X_TK_NOUT       4
-       { "_tk_nout" },
-#define        X_DK_SEEK       5
-       { "_dk_seek" },
-#define        X_CP_TIME       6
-       { "_cp_time" },
-#define        X_DK_WPMS       7
-       { "_dk_wpms" },
-#define        X_HZ            8
-       { "_hz" },
-#define        X_STATHZ        9
-       { "_stathz" },
-#define        X_DK_NDRIVE     10
-       { "_dk_ndrive" },
-#define        X_END           10
-#if defined(hp300) || defined(luna68k)
-#define        X_HPDINIT       (X_END+1)
-       { "_hp_dinit" },
-#endif
-#ifdef mips
-#define        X_SCSI_DINIT    (X_END+1)
-       { "_scsi_dinit" },
-#endif
-#ifdef tahoe
-#define        X_VBDINIT       (X_END+1)
-       { "_vbdinit" },
-#endif
-#ifdef vax
-       { "_mbdinit" },
-#define X_MBDINIT      (X_END+1)
-       { "_ubdinit" },
-#define X_UBDINIT      (X_END+2)
-#endif
-       { NULL },
+#define MAXDRIVES      16      /* most drives we will record */
+#define MAXDRIVENAME   31      /* largest drive name we allow */
+
+struct drivestats {
+       io_registry_entry_t     driver;
+       char                    name[MAXDRIVENAME + 1];
+       u_int64_t               blocksize;
+       u_int64_t               total_bytes;
+       u_int64_t               total_transfers;
+       u_int64_t               total_time;
 };
 
-struct _disk {
-       long    cp_time[CPUSTATES];
-       long    *dk_time;
-       long    *dk_wds;
-       long    *dk_seek;
-       long    *dk_xfer;
-       long    tk_nin;
-       long    tk_nout;
-} cur, last;
+static struct drivestats drivestat[MAXDRIVES];
+
+static struct timeval  cur_time, last_time;
+
+struct statinfo {
+       long            tk_nin;
+       long            tk_nout;
+       host_cpu_load_info_data_t load;
+};
+
+static struct statinfo cur, last;
+
+static mach_port_t host_priv_port;
+static mach_port_t masterPort;
+
+static int num_devices;
+static int maxshowdevs;
+static int dflag = 0, Iflag = 0, Cflag = 0, Tflag = 0, oflag = 0, Kflag = 0;
+static volatile sig_atomic_t phdr_flag = 0;
 
-kvm_t   *kd;
-double   etime;
-long    *dk_wpms;
-int      dk_ndrive, *dr_select, hz, kmemfd, ndrives;
-char   **dr_name;
+/* local function declarations */
+static void usage(void);
+static void phdr(int signo);
+static void do_phdr();
+static void devstats(int perf_select, long double etime, int havelast);
+static void cpustats(void);
+static int readvar(const char *name, void *ptr, size_t len);
 
-#define nlread(x, v) \
-       kvm_read(kd, namelist[x].n_value, &(v), sizeof(v))
+static int record_all_devices(void);
+static int record_one_device(char *name);
+static int record_device(io_registry_entry_t drive);
 
-#include "names.c"                             /* XXX */
+static long double compute_etime(struct timeval cur_time, 
+                                struct timeval prev_time);
 
-void cpustats __P((void));
-void dkstats __P((void));
-void phdr __P((int));
-void usage __P((void));
+static void
+usage(void)
+{
+       /*
+        * We also support the following 'traditional' syntax:
+        * iostat [drives] [wait [count]]
+        * This isn't mentioned in the man page, or the usage statement,
+        * but it is supported.
+        */
+       fprintf(stderr, "usage: iostat [-CdIKoT?] [-c count] [-n devs]\n"
+               "\t      [-w wait] [drives]\n");
+}
 
 int
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(int argc, char **argv)
 {
-       register int i;
-       long tmp;
-       int ch, hdrcnt, reps, interval, stathz, ndrives;
-       char **cp, *memf, *nlistf, buf[30];
-        char errbuf[_POSIX2_LINE_MAX];
-
-       interval = reps = 0;
-       nlistf = memf = NULL;
-       while ((ch = getopt(argc, argv, "c:M:N:w:")) != EOF)
-               switch(ch) {
-               case 'c':
-                       if ((reps = atoi(optarg)) <= 0)
-                               errx(1, "repetition count <= 0.");
-                       break;
-               case 'M':
-                       memf = optarg;
-                       break;
-               case 'N':
-                       nlistf = optarg;
-                       break;
-               case 'w':
-                       if ((interval = atoi(optarg)) <= 0)
-                               errx(1, "interval <= 0.");
-                       break;
-               case '?':
-               default:
-                       usage();
+       int c;
+       int hflag = 0, cflag = 0, wflag = 0, nflag = 0;
+       int count = 0, waittime = 0;
+       int headercount;
+       int num_devices_specified;
+       int havelast = 0;
+
+       maxshowdevs = 3;
+
+       while ((c = getopt(argc, argv, "c:CdIKM:n:oTw:?")) != -1) {
+               switch(c) {
+                       case 'c':
+                               cflag++;
+                               count = atoi(optarg);
+                               if (count < 1)
+                                       errx(1, "count %d is < 1", count);
+                               break;
+                       case 'C':
+                               Cflag++;
+                               break;
+                       case 'd':
+                               dflag++;
+                               break;
+                       case 'I':
+                               Iflag++;
+                               break;
+                       case 'K':
+                               Kflag++;
+                               break;
+                       case 'n':
+                               nflag++;
+                               maxshowdevs = atoi(optarg);
+                               if (maxshowdevs < 0)
+                                       errx(1, "number of devices %d is < 0",
+                                            maxshowdevs);
+                               break;
+                       case 'o':
+                               oflag++;
+                               break;
+                       case 'T':
+                               Tflag++;
+                               break;
+                       case 'w':
+                               wflag++;
+                               waittime = atoi(optarg);
+                               if (waittime < 1)
+                                       errx(1, "wait time is < 1");
+                               break;
+                       default:
+                               usage();
+                               exit(1);
+                               break;
                }
+       }
+
        argc -= optind;
        argv += optind;
 
        /*
-        * Discard setgid privileges if not the running kernel so that bad
-        * guys can't print interesting stuff from kernel memory.
+        * Get the Mach private port.
+        */
+       host_priv_port = mach_host_self();
+
+       /*
+        * Get the I/O Kit communication handle.
+        */
+       IOMasterPort(bootstrap_port, &masterPort);
+
+       /*
+        * Make sure Tflag and/or Cflag are set if dflag == 0.  If dflag is
+        * greater than 0, they may be 0 or non-zero.
         */
-       if (nlistf != NULL || memf != NULL)
-               setgid(getgid());
-
-        kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
-       if (kd == 0)
-               errx(1, "kvm_openfiles: %s", errbuf);
-       if (kvm_nlist(kd, namelist) == -1)
-               errx(1, "kvm_nlist: %s", kvm_geterr(kd));
-       if (namelist[X_DK_NDRIVE].n_type == 0)
-               errx(1, "dk_ndrive not found in namelist");
-       (void)nlread(X_DK_NDRIVE, dk_ndrive);
-       if (dk_ndrive <= 0)
-               errx(1, "invalid dk_ndrive %d\n", dk_ndrive);
-
-       cur.dk_time = calloc(dk_ndrive, sizeof(long));
-       cur.dk_wds = calloc(dk_ndrive, sizeof(long));
-       cur.dk_seek = calloc(dk_ndrive, sizeof(long));
-       cur.dk_xfer = calloc(dk_ndrive, sizeof(long));
-       last.dk_time = calloc(dk_ndrive, sizeof(long));
-       last.dk_wds = calloc(dk_ndrive, sizeof(long));
-       last.dk_seek = calloc(dk_ndrive, sizeof(long));
-       last.dk_xfer = calloc(dk_ndrive, sizeof(long));
-       dr_select = calloc(dk_ndrive, sizeof(int));
-       dr_name = calloc(dk_ndrive, sizeof(char *));
-       dk_wpms = calloc(dk_ndrive, sizeof(long));
-
-       for (i = 0; i < dk_ndrive; i++) {
-               (void)sprintf(buf, "dk%d", i);
-               dr_name[i] = strdup(buf);
+       if (dflag == 0) {
+               Cflag = 1;
+               Tflag = 1;
        }
-       if (!read_names())
-               exit(1);
-       (void)nlread(X_HZ, hz);
-       (void)nlread(X_STATHZ, stathz);
-       if (stathz)
-               hz = stathz;
-       (void)kvm_read(kd, namelist[X_DK_WPMS].n_value, dk_wpms,
-               dk_ndrive * sizeof(dk_wpms));
 
        /*
-        * Choose drives to be displayed.  Priority goes to (in order) drives
-        * supplied as arguments and default drives.  If everything isn't
-        * filled in and there are drives not taken care of, display the first
-        * few that fit.
-        *
-        * The backward compatibility #ifdefs permit the syntax:
-        *      iostat [ drives ] [ interval [ count ] ]
+        * Figure out how many devices we should display if not given
+        * an explicit value.
+        */
+       if (nflag == 0) {
+               if (oflag > 0) {
+                       if ((dflag > 0) && (Cflag == 0) && (Tflag == 0))
+                               maxshowdevs = 5;
+                       else if ((dflag > 0) && (Tflag > 0) && (Cflag == 0))
+                               maxshowdevs = 5;
+                       else
+                               maxshowdevs = 4;
+               } else {
+                       if ((dflag > 0) && (Cflag == 0))
+                               maxshowdevs = 4;                
+                       else
+                               maxshowdevs = 3;
+               }
+       }
+
+       /*
+        * If the user specified any devices on the command line, record
+        * them for monitoring.
         */
-#define        BACKWARD_COMPATIBILITY
-       for (ndrives = 0; *argv; ++argv) {
-#ifdef BACKWARD_COMPATIBILITY
+       for (num_devices_specified = 0; *argv; ++argv) {
                if (isdigit(**argv))
                        break;
-#endif
-               for (i = 0; i < dk_ndrive; i++) {
-                       if (strcmp(dr_name[i], *argv))
-                               continue;
-                       dr_select[i] = 1;
-                       ++ndrives;
-               }
+               if (record_one_device(*argv))
+                       errx(1, "can't record '%s' for monitoring");
+               num_devices_specified++;
        }
-#ifdef BACKWARD_COMPATIBILITY
+       if (nflag == 0 && maxshowdevs < num_devices_specified)
+               maxshowdevs = num_devices_specified;
+
+       /* if no devices were specified, pick them ourselves */
+       if ((num_devices_specified == 0) && record_all_devices())
+               err(1, "can't find any devices to display");
+
+       /*
+        * Look for the traditional wait time and count arguments.
+        */
        if (*argv) {
-               interval = atoi(*argv);
-               if (*++argv)
-                       reps = atoi(*argv);
-       }
-#endif
-
-       if (interval) {
-               if (!reps)
-                       reps = -1;
-       } else
-               if (reps)
-                       interval = 1;
-
-       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
-               if (dr_select[i] || dk_wpms[i] == 0)
-                       continue;
-               for (cp = defdrives; *cp; cp++)
-                       if (strcmp(dr_name[i], *cp) == 0) {
-                               dr_select[i] = 1;
-                               ++ndrives;
-                               break;
-                       }
-       }
-       for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
-               if (dr_select[i])
-                       continue;
-               dr_select[i] = 1;
-               ++ndrives;
+               waittime = atoi(*argv);
+
+               /* Let the user know he goofed, but keep going anyway */
+               if (wflag != 0) 
+                       warnx("discarding previous wait interval, using"
+                             " %d instead", waittime);
+               wflag++;
+
+               if (*++argv) {
+                       count = atoi(*argv);
+                       if (cflag != 0)
+                               warnx("discarding previous count, using %d"
+                                     " instead", count);
+                       cflag++;
+               } else
+                       count = -1;
        }
 
+       /*
+        * If the user specified a count, but not an interval, we default
+        * to an interval of 1 second.
+        */
+       if ((wflag == 0) && (cflag > 0))
+               waittime = 1;
+
+       /*
+        * If the user specified a wait time, but not a count, we want to
+        * go on ad infinitum.  This can be redundant if the user uses the
+        * traditional method of specifying the wait, since in that case we
+        * already set count = -1 above.  Oh well.
+        */
+       if ((wflag > 0) && (cflag == 0))
+               count = -1;
+
+       cur.tk_nout = 0;
+       cur.tk_nin = 0;
+
+       /*
+        * Set the busy time to the system boot time, so the stats are
+        * calculated since system boot.
+        */
+       if (readvar("kern.boottime", &cur_time, sizeof(cur_time)) != 0)
+               exit(1);
+
+       /*
+        * If the user stops the program (control-Z) and then resumes it,
+        * print out the header again.
+        */
        (void)signal(SIGCONT, phdr);
 
-       for (hdrcnt = 1;;) {
-               if (!--hdrcnt) {
-                       phdr(0);
-                       hdrcnt = 20;
+       for (headercount = 1;;) {
+               long tmp;
+               long double etime;
+
+               if (Tflag > 0) {
+                       if ((readvar("kern.tty_nin", &cur.tk_nin,
+                            sizeof(cur.tk_nin)) != 0)
+                        || (readvar("kern.tty_nout",
+                            &cur.tk_nout, sizeof(cur.tk_nout))!= 0)) {
+                               Tflag = 0;
+                               warnx("disabling TTY statistics");
+                       }
+                }
+
+               if (phdr_flag) {
+                       phdr_flag = 0;
+                       do_phdr();
                }
-               (void)kvm_read(kd, namelist[X_DK_TIME].n_value,
-                   cur.dk_time, dk_ndrive * sizeof(long));
-               (void)kvm_read(kd, namelist[X_DK_XFER].n_value,
-                   cur.dk_xfer, dk_ndrive * sizeof(long));
-               (void)kvm_read(kd, namelist[X_DK_WDS].n_value,
-                   cur.dk_wds, dk_ndrive * sizeof(long));
-               (void)kvm_read(kd, namelist[X_DK_SEEK].n_value,
-                   cur.dk_seek, dk_ndrive * sizeof(long));
-               (void)kvm_read(kd, namelist[X_TK_NIN].n_value,
-                   &cur.tk_nin, sizeof(cur.tk_nin));
-               (void)kvm_read(kd, namelist[X_TK_NOUT].n_value,
-                   &cur.tk_nout, sizeof(cur.tk_nout));
-               (void)kvm_read(kd, namelist[X_CP_TIME].n_value,
-                   cur.cp_time, sizeof(cur.cp_time));
-               for (i = 0; i < dk_ndrive; i++) {
-                       if (!dr_select[i])
-                               continue;
-#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp
-                       X(dk_xfer);
-                       X(dk_seek);
-                       X(dk_wds);
-                       X(dk_time);
+               
+               if (!--headercount) {
+                       do_phdr();
+                       headercount = 20;
                }
-               tmp = cur.tk_nin;
-               cur.tk_nin -= last.tk_nin;
-               last.tk_nin = tmp;
-               tmp = cur.tk_nout;
-               cur.tk_nout -= last.tk_nout;
-               last.tk_nout = tmp;
-               etime = 0;
-               for (i = 0; i < CPUSTATES; i++) {
-                       X(cp_time);
-                       etime += cur.cp_time[i];
+
+               last_time = cur_time;
+               gettimeofday(&cur_time, NULL);
+
+               if (Tflag > 0) {
+                       tmp = cur.tk_nin;
+                       cur.tk_nin -= last.tk_nin;
+                       last.tk_nin = tmp;
+                       tmp = cur.tk_nout;
+                       cur.tk_nout -= last.tk_nout;
+                       last.tk_nout = tmp;
                }
+
+               etime = compute_etime(cur_time, last_time);
+
                if (etime == 0.0)
                        etime = 1.0;
-               etime /= (float)hz;
-               (void)printf("%4.0f%5.0f",
-                   cur.tk_nin / etime, cur.tk_nout / etime);
-               dkstats();
-               cpustats();
-               (void)printf("\n");
-               (void)fflush(stdout);
 
-               if (reps >= 0 && --reps <= 0)
+               if (Tflag > 0)
+                       printf("%4.0Lf%5.0Lf", cur.tk_nin / etime, 
+                               cur.tk_nout / etime);
+
+               devstats(hflag, etime, havelast);
+
+               if (Cflag > 0)
+                       cpustats();
+
+               printf("\n");
+               fflush(stdout);
+
+               if (count >= 0 && --count <= 0)
                        break;
-               (void)sleep(interval);
+
+               sleep(waittime);
+               havelast = 1;
        }
+
        exit(0);
 }
 
-/* ARGUSED */
-void
-phdr(signo)
-       int signo;
+static void
+phdr(int signo)
+{
+
+       phdr_flag = 1;  
+}
+
+static void
+do_phdr() 
 {
        register int i;
 
-       (void)printf("      tty");
-       for (i = 0; i < dk_ndrive; i++)
-               if (dr_select[i])
-                       (void)printf("          %3.3s ", dr_name[i]);
-       (void)printf("         cpu\n tin tout");
-       for (i = 0; i < dk_ndrive; i++)
-               if (dr_select[i])
-                       (void)printf(" sps tps msps ");
-       (void)printf(" us ni sy in id\n");
+       if (Tflag > 0)
+               (void)printf("      tty");
+
+       for (i = 0; (i < num_devices); i++){
+               if (oflag > 0)
+                       (void)printf("%12.6s ", drivestat[i].name);
+               else
+                       printf("%15.6s ", drivestat[i].name);
+       }
+               
+       if (Cflag > 0)
+               (void)printf("      cpu\n");
+       else
+               (void)printf("\n");
+
+       if (Tflag > 0)
+               (void)printf(" tin tout");
+
+       for (i=0; i < num_devices; i++){
+               if (oflag > 0) {
+                       if (Iflag == 0)
+                               (void)printf(" sps tps msps ");
+                       else
+                               (void)printf(" blk xfr msps ");
+               } else {
+                       if (Iflag == 0)
+                               printf("  KB/t tps  MB/s ");
+                       else
+                               printf("  KB/t xfrs   MB ");
+               }
+       }
+
+       if (Cflag > 0)
+               (void)printf(" us sy id\n");
+       else
+               printf("\n");
 }
 
-void
-dkstats()
+static void
+devstats(int perf_select, long double etime, int havelast)
 {
-       register int dn;
-       double atime, itime, msps, words, xtime;
-
-       for (dn = 0; dn < dk_ndrive; ++dn) {
-               if (!dr_select[dn])
-                       continue;
-               words = cur.dk_wds[dn] * 32;            /* words xfer'd */
-               (void)printf("%4.0f",                   /* sectors */
-                   words / (DEV_BSIZE / 2) / etime);
-
-               (void)printf("%4.0f", cur.dk_xfer[dn] / etime);
-
-               if (dk_wpms[dn] && cur.dk_xfer[dn]) {
-                       atime = cur.dk_time[dn];        /* ticks disk busy */
-                       atime /= (float)hz;             /* ticks to seconds */
-                       xtime = words / dk_wpms[dn];    /* transfer time */
-                       itime = atime - xtime;          /* time not xfer'ing */
-                       if (itime < 0)
-                               msps = 0;
+       CFNumberRef number;
+       CFDictionaryRef properties;
+       CFDictionaryRef statistics;
+       long double transfers_per_second;
+       long double kb_per_transfer, mb_per_second;
+       u_int64_t value;
+       u_int64_t total_bytes, total_transfers, total_blocks, total_time;
+       u_int64_t interval_bytes, interval_transfers, interval_blocks;
+       u_int64_t interval_time;
+       long double interval_mb;
+       long double blocks_per_second, ms_per_transaction;
+       kern_return_t status;
+       int i;
+
+       for (i = 0; i < num_devices; i++) {
+
+               /*
+                * If the drive goes away, we may not get any properties
+                * for it.  So take some defaults.
+                */
+               total_bytes = 0;
+               total_transfers = 0;
+               total_time = 0;
+
+               /* get drive properties */
+               status = IORegistryEntryCreateCFProperties(drivestat[i].driver,
+                       (CFMutableDictionaryRef *)&properties,
+                       kCFAllocatorDefault,
+                       kNilOptions);
+               if (status != KERN_SUCCESS)
+                       err(1, "device has no properties");
+
+               /* get statistics from properties */
+               statistics = (CFDictionaryRef)CFDictionaryGetValue(properties,
+                       CFSTR(kIOBlockStorageDriverStatisticsKey));
+               if (statistics) {
+
+                       /*
+                        * Get I/O volume.
+                        */
+                       if ((number = (CFNumberRef)CFDictionaryGetValue(statistics,
+                               CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) {
+                               CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               total_bytes += value;
+                       }
+                       if ((number = (CFNumberRef)CFDictionaryGetValue(statistics,
+                               CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) {
+                               CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               total_bytes += value;
+                       }
+
+                       /*
+                        * Get I/O counts.
+                        */
+                       if ((number = (CFNumberRef)CFDictionaryGetValue(statistics,
+                               CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) {
+                               CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               total_transfers += value;
+                       }
+                       if ((number = (CFNumberRef)CFDictionaryGetValue(statistics,
+                               CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) {
+                               CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               total_transfers += value;
+                       }
+
+                       /*
+                        * Get I/O time.
+                        */
+                       if ((number = (CFNumberRef)CFDictionaryGetValue(statistics,
+                               CFSTR(kIOBlockStorageDriverStatisticsLatentReadTimeKey)))) {
+                               CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               total_time += value;
+                       }
+                       if ((number = (CFNumberRef)CFDictionaryGetValue(statistics,
+                               CFSTR(kIOBlockStorageDriverStatisticsLatentWriteTimeKey)))) {
+                               CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               total_time += value;
+                       }
+
+               }
+               CFRelease(properties);
+
+               /*
+                * Compute delta values and stats.
+                */
+               interval_bytes = total_bytes - drivestat[i].total_bytes;
+               interval_transfers = total_transfers 
+                       - drivestat[i].total_transfers;
+               interval_time = total_time - drivestat[i].total_time;
+
+               /* update running totals, only once for -I */
+               if ((Iflag == 0) || (drivestat[i].total_bytes == 0)) {
+                       drivestat[i].total_bytes = total_bytes;
+                       drivestat[i].total_transfers = total_transfers;
+                       drivestat[i].total_time = total_time;
+               }                               
+
+               interval_blocks = interval_bytes / drivestat[i].blocksize;
+               total_blocks = total_bytes / drivestat[i].blocksize;
+
+               blocks_per_second = interval_blocks / etime;
+               transfers_per_second = interval_transfers / etime;
+               mb_per_second = (interval_bytes / etime) / (1024 * 1024);
+
+               kb_per_transfer = (interval_transfers > 0) ?
+                       ((long double)interval_bytes / interval_transfers) 
+                       / 1024 : 0;
+
+               /* times are in nanoseconds, convert to milliseconds */
+               ms_per_transaction = (interval_transfers > 0) ?
+                       ((long double)interval_time / interval_transfers) 
+                       / 1000 : 0;
+
+               if (Kflag)
+                       total_blocks = total_blocks * drivestat[i].blocksize 
+                               / 1024;
+
+               if (oflag > 0) {
+                       int msdig = (ms_per_transaction < 100.0) ? 1 : 0;
+
+                       if (Iflag == 0)
+                               printf("%4.0Lf%4.0Lf%5.*Lf ",
+                                      blocks_per_second,
+                                      transfers_per_second,
+                                      msdig,
+                                      ms_per_transaction);
                        else 
-                               msps = itime * 1000 / cur.dk_xfer[dn];
-               } else
-                       msps = 0;
-               (void)printf("%5.1f ", msps);
+                               printf("%4.1qu%4.1qu%5.*Lf ",
+                                      interval_blocks,
+                                      interval_transfers,
+                                      msdig,
+                                      ms_per_transaction);
+               } else {
+                       if (Iflag == 0)
+                               printf(" %5.2Lf %3.0Lf %5.2Lf ", 
+                                      kb_per_transfer,
+                                      transfers_per_second,
+                                      mb_per_second);
+                       else {
+                               interval_mb = interval_bytes;
+                               interval_mb /= 1024 * 1024;
+
+                               printf(" %5.2Lf %3.1qu %5.2Lf ", 
+                                      kb_per_transfer,
+                                      interval_transfers,
+                                      interval_mb);
+                       }
+               }
        }
 }
 
-void
-cpustats()
+static void
+cpustats(void)
 {
-       register int state;
+       mach_msg_type_number_t count;
+       kern_return_t status;
        double time;
 
-       time = 0;
-       for (state = 0; state < CPUSTATES; ++state)
-               time += cur.cp_time[state];
-       for (state = 0; state < CPUSTATES; ++state)
-               (void)printf("%3.0f",
-                   100. * cur.cp_time[state] / (time ? time : 1));
+       /*
+        * Get CPU usage counters.
+        */
+       count = HOST_CPU_LOAD_INFO_COUNT;
+       status = host_statistics(host_priv_port, HOST_CPU_LOAD_INFO,
+               (host_info_t)&cur.load, &count);
+       if (status != KERN_SUCCESS)
+               errx(1, "couldn't fetch CPU stats");
+
+       /*
+        * Make 'cur' fields relative, update 'last' fields to current values,
+        * calculate total elapsed time.
+        */
+       time = 0.0;
+       cur.load.cpu_ticks[CPU_STATE_USER]
+               -= last.load.cpu_ticks[CPU_STATE_USER];
+       last.load.cpu_ticks[CPU_STATE_USER]
+               += cur.load.cpu_ticks[CPU_STATE_USER];
+       time += cur.load.cpu_ticks[CPU_STATE_USER];
+       cur.load.cpu_ticks[CPU_STATE_SYSTEM]
+               -= last.load.cpu_ticks[CPU_STATE_SYSTEM];
+       last.load.cpu_ticks[CPU_STATE_SYSTEM]
+               += cur.load.cpu_ticks[CPU_STATE_SYSTEM];
+       time += cur.load.cpu_ticks[CPU_STATE_SYSTEM];
+       cur.load.cpu_ticks[CPU_STATE_IDLE]
+               -= last.load.cpu_ticks[CPU_STATE_IDLE];
+       last.load.cpu_ticks[CPU_STATE_IDLE]
+               += cur.load.cpu_ticks[CPU_STATE_IDLE];
+       time += cur.load.cpu_ticks[CPU_STATE_IDLE];
+       
+       /*
+        * Print times.
+        */
+       printf("%3.0f",
+               rint(100. * cur.load.cpu_ticks[CPU_STATE_USER]
+                    / (time ? time : 1)));
+       printf("%3.0f",
+               rint(100. * cur.load.cpu_ticks[CPU_STATE_SYSTEM]
+                    / (time ? time : 1)));
+       printf("%3.0f",
+               rint(100. * cur.load.cpu_ticks[CPU_STATE_IDLE]
+                    / (time ? time : 1)));
+}
+
+static int
+readvar(const char *name, void *ptr, size_t len)
+{
+       int     oid[4];
+       int     oidlen;
+
+       size_t nlen = len;
+
+       if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
+               if (errno != ENOENT) {
+                       warn("sysctl(%s) failed", name);
+                       return (1);
+               }
+               /*
+                * XXX fallback code to deal with systems where
+                * sysctlbyname can't find "old" OIDs, should be removed.
+                */
+               if (!strcmp(name, "kern.boottime")) {
+                       oid[0] = CTL_KERN;
+                       oid[1] = KERN_BOOTTIME;
+                       oidlen = 2;
+               } else {
+                       warn("sysctl(%s) failed", name);
+                       return (1);
+               }
+
+               nlen = len;
+               if (sysctl(oid, oidlen, ptr, &nlen, NULL, 0) == -1) {
+                       warn("sysctl(%s) failed", name);
+                       return (1);
+               }
+       }
+       if (nlen != len) {
+               warnx("sysctl(%s): expected %lu, got %lu", name,
+                     (unsigned long)len, (unsigned long)nlen);
+               return (1);
+       }
+       return (0);
 }
 
-void
-usage()
+static long double
+compute_etime(struct timeval cur_time, struct timeval prev_time)
 {
-       (void)fprintf(stderr,
-"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n");
-       exit(1);
+       struct timeval busy_time;
+       u_int64_t busy_usec;
+       long double etime;
+
+       timersub(&cur_time, &prev_time, &busy_time);
+
+       busy_usec = busy_time.tv_sec;  
+       busy_usec *= 1000000;          
+       busy_usec += busy_time.tv_usec;
+       etime = busy_usec;
+       etime /= 1000000;
+
+       return(etime);
+}
+
+/*
+ * Record all "whole" IOMedia objects as being interesting.
+ */
+static int
+record_all_devices(void)
+{
+       io_iterator_t drivelist;
+       io_registry_entry_t drive;
+       CFMutableDictionaryRef match;
+       int error, ndrives;
+       kern_return_t status;
+
+       /*
+        * Get an iterator for IOMedia objects.
+        */
+       match = IOServiceMatching("IOMedia");
+       CFDictionaryAddValue(match, CFSTR(kIOMediaWholeKey), kCFBooleanTrue);
+       status = IOServiceGetMatchingServices(masterPort, match, &drivelist);
+       if (status != KERN_SUCCESS)
+               errx(1, "couldn't match whole IOMedia devices");
+
+       /*
+        * Scan all of the IOMedia objects, and for each
+        * object that has a parent IOBlockStorageDriver, save
+        * the object's name and the parent (from which we can
+        * fetch statistics).
+        *
+        * XXX What about RAID devices?
+        */
+       error = 1;
+       ndrives = 0;
+       while ((drive = IOIteratorNext(drivelist))
+               && (ndrives < maxshowdevs)) {
+               if (!record_device(drive)) {
+                       error = 0;
+                       ndrives++;
+               }
+               IOObjectRelease(drive);
+       }
+       IOObjectRelease(drivelist);
+
+       return(error);
+}
+
+/*
+ * Try to record the named device as interesting.  It
+ * must be an IOMedia device.
+ */
+static int
+record_one_device(char *name)
+{
+       io_iterator_t drivelist;
+       io_registry_entry_t drive;
+       kern_return_t status;
+
+       /*
+        * Find the device.
+        */
+       status = IOServiceGetMatchingServices(masterPort,
+               IOBSDNameMatching(masterPort, kNilOptions, name),
+               &drivelist);
+       if (status != KERN_SUCCESS)
+               errx(1, "couldn't match '%s'", name);
+
+       /*
+        * Get the first match (should only be one)
+        */
+       if ((drive = IOIteratorNext(drivelist)) == NULL)
+               errx(1, "'%s' not found", name);
+       if (!IOObjectConformsTo(drive, "IOMedia"))
+               errx(1, "'%s' is not a storage device", name);
+
+       /*
+        * Record the device.
+        */
+       if (record_device(drive))
+               errx(1, "could not record '%s' for monitoring", name);
+
+       IOObjectRelease(drive);
+       IOObjectRelease(drivelist);
+
+       return(0);
+}
+
+/*
+ * Determine whether an IORegistryEntry refers to a valid
+ * I/O device, and if so, record it.
+ */
+static int
+record_device(io_registry_entry_t drive)
+{
+       io_registry_entry_t parent;
+       CFDictionaryRef properties;
+       CFStringRef name;
+       CFNumberRef number;
+       kern_return_t status;
+       
+       /* get drive's parent */
+       status = IORegistryEntryGetParentEntry(drive,
+               kIOServicePlane, &parent);
+       if (status != KERN_SUCCESS)
+               errx(1, "device has no parent");
+       if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) {
+               drivestat[num_devices].driver = parent;
+
+               /* get drive properties */
+               status = IORegistryEntryCreateCFProperties(drive,
+                       (CFMutableDictionaryRef *)&properties,
+                       kCFAllocatorDefault,
+                       kNilOptions);
+               if (status != KERN_SUCCESS)
+                       errx(1, "device has no properties");
+
+               /* get name from properties */
+               name = (CFStringRef)CFDictionaryGetValue(properties,
+                       CFSTR(kIOBSDNameKey));
+               CFStringGetCString(name, drivestat[num_devices].name, 
+                       MAXDRIVENAME, CFStringGetSystemEncoding());
+
+               /* get blocksize from properties */
+               number = (CFNumberRef)CFDictionaryGetValue(properties,
+                       CFSTR(kIOMediaPreferredBlockSizeKey));
+               CFNumberGetValue(number, kCFNumberSInt64Type,
+                       &drivestat[num_devices].blocksize);
+
+               /* clean up, return success */
+               CFRelease(properties);
+               num_devices++;
+               return(0);
+       }
+
+       /* failed, don't keep parent */
+       IOObjectRelease(parent);
+       return(1);
 }
diff --git a/iostat.tproj/names.c b/iostat.tproj/names.c
deleted file mode 100644 (file)
index 099ea61..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*-
- * Copyright (c) 1986, 1991, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#if !defined(hp300) && !defined(tahoe) && !defined(vax) && \
-       !defined(luna68k) && !defined(mips)
-char *defdrives[] = { 0 };
-int
-read_names()
-{
-    return 0;
-}
-#endif
-
-#if defined(hp300) || defined(luna68k)
-#if defined(hp300)
-#include <hp/dev/device.h>
-#else
-#include <luna68k/dev/device.h>
-#endif
-
-char *defdrives[] = { "sd0", "sd1", "sd2", "rd0", "rd1", "rd2", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       register u_long hp;
-       static char buf[BUFSIZ];
-       struct hp_device hdev;
-       struct driver hdrv;
-       char name[10];
-
-       hp = namelist[X_HPDINIT].n_value;
-       if (hp == 0) {
-               (void)fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       for (;; hp += sizeof hdev) {
-               (void)kvm_read(kd, hp, &hdev, sizeof hdev);
-               if (hdev.hp_driver == 0)
-                       break;
-               if (hdev.hp_dk < 0 || hdev.hp_alive == 0 ||
-                   hdev.hp_cdriver == 0)
-                       continue;
-               (void)kvm_read(kd, (u_long)hdev.hp_driver, &hdrv, sizeof hdrv);
-               (void)kvm_read(kd, (u_long)hdrv.d_name, name, sizeof name);
-               dr_name[hdev.hp_dk] = p;
-               p += sprintf(p, "%s%d", name, hdev.hp_unit) + 1;
-       }
-       return (1);
-}
-#endif /* hp300 || luna68k */
-
-#ifdef tahoe
-#include <tahoe/vba/vbavar.h>
-
-char *defdrives[] = { "dk0", "dk1", "dk2", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       struct vba_device udev, *up;
-       struct vba_driver udrv;
-       char name[10];
-       static char buf[BUFSIZ];
-
-       up = (struct vba_device *)namelist[X_VBDINIT].n_value;
-       if (up == 0) {
-               (void) fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       for (;; up += sizeof udev) {
-               (void)kvm_read(kd, up, &udev, sizeof udev);
-               if (udev.ui_driver == 0)
-                       break;
-               if (udev.ui_dk < 0 || udev.ui_alive == 0)
-                       continue;
-               (void)kvm_read(kd, udev.ui_driver, &udrv, sizeof udrv);
-               (void)kvm_read(kd, udrv.ud_dname, name, sizeof name);
-               dr_name[udev.ui_dk] = p;
-               p += sprintf(p, "%s%d", name, udev.ui_unit);
-       }
-       return (1);
-}
-#endif /* tahoe */
-
-#ifdef vax
-#include <vax/uba/ubavar.h>
-#include <vax/mba/mbavar.h>
-
-char *defdrives[] = { "hp0", "hp1", "hp2", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       unsigned long mp, up;
-       struct mba_device mdev;
-       struct mba_driver mdrv;
-       struct uba_device udev;
-       struct uba_driver udrv;
-       char name[10];
-       static char buf[BUFSIZ];
-
-       mp = namelist[X_MBDINIT].n_value;
-       up = namelist[X_UBDINIT].n_value;
-       if (mp == 0 && up == 0) {
-               (void)fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       if (mp)
-               for (;; mp += sizeof mdev) {
-                       (void)kvm_read(kd, mp, &mdev, sizeof mdev);
-                       if (mdev.mi_driver == 0)
-                               break;
-                       if (mdev.mi_dk < 0 || mdev.mi_alive == 0)
-                               continue;
-                       (void)kvm_read(kd, mdev.mi_driver, &mdrv, sizeof mdrv);
-                       (void)kvm_rea(kd, mdrv.md_dname, name, sizeof name);
-                       dr_name[mdev.mi_dk] = p;
-                       p += sprintf(p, "%s%d", name, mdev.mi_unit);
-               }
-       if (up)
-               for (;; up += sizeof udev) {
-                       (void)kvm_read(kd, up, &udev, sizeof udev);
-                       if (udev.ui_driver == 0)
-                               break;
-                       if (udev.ui_dk < 0 || udev.ui_alive == 0)
-                               continue;
-                       (void)kvm_read(kd, udev.ui_driver, &udrv, sizeof udrv);
-                       (void)kvm_read(kd, udrv.ud_dname, name, sizeof name);
-                       dr_name[udev.ui_dk] = p;
-                       p += sprintf(p, "%s%d", name, udev.ui_unit);
-               }
-       return (1);
-}
-#endif /* vax */
-
-#ifdef sun
-#include <sundev/mbvar.h>
-
-int
-read_names()
-{
-       static int once = 0;
-       struct mb_device mdev;
-       struct mb_driver mdrv;
-       short two_char;
-       char *cp = (char *) &two_char;
-       register struct mb_device *mp;
-
-       mp = (struct mb_device *)namelist[X_MBDINIT].n_value;
-       if (mp == 0) {
-               (void)fprintf(stderr,
-                   "disk init info not in namelist\n");
-               return (0);
-       }
-       for (;; ++mp) {
-               (void)kvm_read(kd, mp++, &mdev, sizeof(mdev));
-               if (mdev.md_driver == 0)
-                       break;
-               if (mdev.md_dk < 0 || mdev.md_alive == 0)
-                       continue;
-               (void)kvm_read(kd, mdev.md_driver, &mdrv, sizeof(mdrv));
-               (void)kvm_read(kd, mdrv.mdr_dname, &two_char, sizeof(two_char));
-               (void)sprintf(dr_name[mdev.md_dk],
-                   "%c%c%d", cp[0], cp[1], mdev.md_unit);
-       }
-       return(1);
-}
-#endif /* sun */
-
-#if defined(mips)
-#include <pmax/dev/device.h>
-
-char *defdrives[] = { "rz0", "rz1", "rz2", "rz3", "rz4", "rz5", "rz6", 0 };
-
-int
-read_names()
-{
-       register char *p;
-       register u_long sp;
-       static char buf[BUFSIZ];
-       struct scsi_device sdev;
-       struct driver hdrv;
-       char name[10];
-
-       sp = namelist[X_SCSI_DINIT].n_value;
-       if (sp == 0) {
-               (void)fprintf(stderr, "disk init info not in namelist\n");
-               return (0);
-       }
-       p = buf;
-       for (;; sp += sizeof sdev) {
-               (void)kvm_read(kd, sp, &sdev, sizeof sdev);
-               if (sdev.sd_driver == 0)
-                       break;
-               if (sdev.sd_dk < 0 || sdev.sd_alive == 0 ||
-                   sdev.sd_cdriver == 0)
-                       continue;
-               (void)kvm_read(kd, (u_long)sdev.sd_driver, &hdrv, sizeof hdrv);
-               (void)kvm_read(kd, (u_long)hdrv.d_name, name, sizeof name);
-               dr_name[sdev.sd_dk] = p;
-               p += sprintf(p, "%s%d", name, sdev.sd_unit) + 1;
-       }
-       return (1);
-}
-#endif /* mips */
diff --git a/kdump.tproj/Makefile b/kdump.tproj/Makefile
new file mode 100644 (file)
index 0000000..f09af30
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# Generated by the Apple Project Builder.
+#
+# NOTE: Do NOT change this file -- Project Builder maintains it.
+#
+# Put all of your customizations in files called Makefile.preamble
+# and Makefile.postamble (both optional), and Makefile will include them.
+#
+
+NAME = kdump
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = kdump.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kdump.1\
+            mkioctls syscalls.c
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I../ktrace.tproj
+NEXTSTEP_PB_CFLAGS = -DMACH_USER_API
+WINDOWS_PB_CFLAGS = -DMACH_USER_API
+PDO_UNIX_PB_CFLAGS = -DMACH_USER_API
+
+
+NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
+WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
+PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
+NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
+WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
+PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/kdump.tproj/Makefile.postamble b/kdump.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..1e2ae06
--- /dev/null
@@ -0,0 +1,8 @@
+VPATH += :../ktrace.tproj
+
+ioctl.c: mkioctls
+       $(SHELL) mkioctls -s /usr/include > $(SFILE_DIR)/ioctl.c
+
+install-man-page:
+       install -d $(DSTROOT)/usr/share/man/man1
+       install -c -m 444 kdump.1 $(DSTROOT)/usr/share/man/man1/kdump.1
diff --git a/kdump.tproj/Makefile.preamble b/kdump.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..1bf99f7
--- /dev/null
@@ -0,0 +1,7 @@
+KTRACE_CFILES = subr.c
+GENERATED_CFILES = ioctl.c
+OTHER_INITIAL_DEPENDS = $(GENERATED_CFILES)
+OTHER_OFILES = $(GENERATED_CFILES:.c=.o) $(KTRACE_CFILES:.c=.o)
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+AFTER_INSTALL += install-man-page
+-include ../Makefile.include
diff --git a/kdump.tproj/PB.project b/kdump.tproj/PB.project
new file mode 100644 (file)
index 0000000..1fbdcd4
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        HEADERSEARCH = (../ktrace.tproj); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (kdump.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            kdump.1, 
+            mkioctls, 
+            syscalls.c
+        ); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDTOOL = make; 
+    NEXTSTEP_COMPILEROPTIONS = "-DMACH_USER_API"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = kdump; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DMACH_USER_API"; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_MAINNIB = kdump; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = kdump; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = make; 
+    WINDOWS_COMPILEROPTIONS = "-DMACH_USER_API"; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = kdump; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/kdump.tproj/kdump.1 b/kdump.tproj/kdump.1
new file mode 100644 (file)
index 0000000..ab9c37a
--- /dev/null
@@ -0,0 +1,102 @@
+.\" Copyright (c) 1990, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)kdump.1     8.1 (Berkeley) 6/6/93
+.\" $FreeBSD: src/usr.bin/kdump/kdump.1,v 1.5.2.2 2001/08/16 13:16:51 ru Exp $
+.\"
+.Dd June 6, 1993
+.Dt KDUMP 1
+.Os
+.Sh NAME
+.Nm kdump
+.Nd display kernel trace data
+.Sh SYNOPSIS
+.Nm
+.Op Fl dnlRT
+.Op Fl f Ar file
+.Op Fl m Ar maxdata
+.Op Fl t Op cnisuw
+.Sh DESCRIPTION
+The
+.Nm
+command displays the kernel trace files produced with
+.Xr ktrace 1
+in human readable format.
+By default, the file
+.Pa ktrace.out
+in the current directory is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width Fl
+.It Fl d
+Display all numbers in decimal.
+.It Fl f Ar file
+Display the specified file instead of
+.Pa ktrace.out .
+.It Fl l
+Loop reading the trace file, once the end-of-file is reached, waiting for
+more data.
+.It Fl m Ar maxdata
+Display at most
+.Ar maxdata
+bytes when decoding
+.Tn I/O .
+.It Fl n
+Suppress ad hoc translations.
+Normally
+.Nm
+tries to decode many system calls into a more human readable format.
+For example,
+.Xr ioctl 2
+values are replaced with the macro name and
+.Va errno
+values are replaced with the
+.Xr strerror 3
+string.
+Suppressing this feature yields a more consistent output format and is
+easily amenable to further processing.
+.It Fl R
+Display relative timestamps (time since previous entry).
+.It Fl T
+Display absolute timestamps for each entry (seconds since epoch).
+.It Fl t Ar cnisuw
+See the
+.Fl t
+option of
+.Xr ktrace 1 .
+.El
+.Sh SEE ALSO
+.Xr ktrace 1
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.4 .
diff --git a/kdump.tproj/kdump.c b/kdump.tproj/kdump.c
new file mode 100644 (file)
index 0000000..7f1238e
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Reserved.  This file contains Original Code and/or Modifications of
+ * Original Code as defined in and that are subject to the Apple Public
+ * Source License Version 1.0 (the 'License').  You may not use this file
+ * except in compliance with the License.  Please obtain a copy of the
+ * License at http://www.apple.com/publicsource and read it before using
+ * this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License."
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*-
+ * Copyright (c) 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)kdump.c    8.1 (Berkeley) 6/6/93";
+#endif
+static const char rcsid[] =
+  "$FreeBSD: src/usr.bin/kdump/kdump.c,v 1.17 1999/12/29 05:05:33 peter Exp $";
+#endif /* not lint */
+
+#define KERNEL
+extern int errno;
+#include <sys/errno.h>
+#undef KERNEL
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <err.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <vis.h>
+#include "ktrace.h"
+
+int timestamp, decimal, fancy = 1, tail, maxdata;
+char *tracefile = DEF_TRACEFILE;
+struct ktr_header ktr_header;
+
+#define eqs(s1, s2)    (strcmp((s1), (s2)) == 0)
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int ch, ktrlen, size;
+       register void *m;
+       int trpoints = ALL_POINTS;
+
+       (void) setlocale(LC_CTYPE, "");
+
+       while ((ch = getopt(argc,argv,"f:dlm:nRTt:")) != -1)
+               switch((char)ch) {
+               case 'f':
+                       tracefile = optarg;
+                       break;
+               case 'd':
+                       decimal = 1;
+                       break;
+               case 'l':
+                       tail = 1;
+                       break;
+               case 'm':
+                       maxdata = atoi(optarg);
+                       break;
+               case 'n':
+                       fancy = 0;
+                       break;
+               case 'R':
+                       timestamp = 2;  /* relative timestamp */
+                       break;
+               case 'T':
+                       timestamp = 1;
+                       break;
+               case 't':
+                       trpoints = getpoints(optarg);
+                       if (trpoints < 0)
+                               errx(1, "unknown trace point in %s", optarg);
+                       break;
+               default:
+                       usage();
+               }
+
+       if (argc > optind)
+               usage();
+
+       m = (void *)malloc(size = 1025);
+       if (m == NULL)
+               errx(1, "%s", strerror(ENOMEM));
+       if (!freopen(tracefile, "r", stdin))
+               err(1, "%s", tracefile);
+       while (fread_tail(&ktr_header, sizeof(struct ktr_header), 1)) {
+               if (trpoints & (1<<ktr_header.ktr_type))
+                       dumpheader(&ktr_header);
+               if ((ktrlen = ktr_header.ktr_len) < 0)
+                       errx(1, "bogus length 0x%x", ktrlen);
+               if (ktrlen > size) {
+                       m = (void *)realloc(m, ktrlen+1);
+                       if (m == NULL)
+                               errx(1, "%s", strerror(ENOMEM));
+                       size = ktrlen;
+               }
+               if (ktrlen && fread_tail(m, ktrlen, 1) == 0)
+                       errx(1, "data too short");
+               if ((trpoints & (1<<ktr_header.ktr_type)) == 0)
+                       continue;
+               switch (ktr_header.ktr_type) {
+               case KTR_SYSCALL:
+                       ktrsyscall((struct ktr_syscall *)m);
+                       break;
+               case KTR_SYSRET:
+                       ktrsysret((struct ktr_sysret *)m);
+                       break;
+               case KTR_NAMEI:
+                       ktrnamei(m, ktrlen);
+                       break;
+               case KTR_GENIO:
+                       ktrgenio((struct ktr_genio *)m, ktrlen);
+                       break;
+               case KTR_PSIG:
+                       ktrpsig((struct ktr_psig *)m);
+                       break;
+               case KTR_CSW:
+                       ktrcsw((struct ktr_csw *)m);
+                       break;
+               case KTR_USER:
+                       ktruser(ktrlen, m);
+                       break;
+               }
+               if (tail)
+                       (void)fflush(stdout);
+       }
+}
+
+fread_tail(buf, size, num)
+       char *buf;
+       int num, size;
+{
+       int i;
+
+       while ((i = fread(buf, size, num, stdin)) == 0 && tail) {
+               (void)sleep(1);
+               clearerr(stdin);
+       }
+       return (i);
+}
+
+dumpheader(kth)
+       struct ktr_header *kth;
+{
+       static char unknown[64];
+       static struct timeval prevtime, temp;
+       char *type;
+
+       switch (kth->ktr_type) {
+       case KTR_SYSCALL:
+               type = "CALL";
+               break;
+       case KTR_SYSRET:
+               type = "RET ";
+               break;
+       case KTR_NAMEI:
+               type = "NAMI";
+               break;
+       case KTR_GENIO:
+               type = "GIO ";
+               break;
+       case KTR_PSIG:
+               type = "PSIG";
+               break;
+       case KTR_CSW:
+               type = "CSW";
+               break;
+       case KTR_USER:
+               type = "USER";
+               break;
+       default:
+               (void)sprintf(unknown, "UNKNOWN(%d)", kth->ktr_type);
+               type = unknown;
+       }
+
+       (void)printf("%6d %-8.*s ", kth->ktr_pid, MAXCOMLEN, kth->ktr_comm);
+       if (timestamp) {
+               if (timestamp == 2) {
+                       temp = kth->ktr_time;
+                       timevalsub(&kth->ktr_time, &prevtime);
+                       prevtime = temp;
+               }
+               (void)printf("%ld.%06ld ",
+                   kth->ktr_time.tv_sec, kth->ktr_time.tv_usec);
+       }
+       (void)printf("%s  ", type);
+}
+
+#include <sys/syscall.h>
+#include "syscalls.c"
+int nsyscalls = sizeof (syscallnames) / sizeof (syscallnames[0]);
+
+static char *ptrace_ops[] = {
+       "PT_TRACE_ME",  "PT_READ_I",    "PT_READ_D",    "PT_READ_U",
+       "PT_WRITE_I",   "PT_WRITE_D",   "PT_WRITE_U",   "PT_CONTINUE",
+       "PT_KILL",      "PT_STEP",      "PT_ATTACH",    "PT_DETACH",
+};
+
+ktrsyscall(ktr)
+       register struct ktr_syscall *ktr;
+{
+       register narg = ktr->ktr_narg;
+       register register_t *ip;
+       char *ioctlname();
+
+       if (ktr->ktr_code >= nsyscalls || ktr->ktr_code < 0)
+               (void)printf("[%d]", ktr->ktr_code);
+       else
+               (void)printf("%s", syscallnames[ktr->ktr_code]);
+       ip = &ktr->ktr_args[0];
+       if (narg) {
+               char c = '(';
+               if (fancy) {
+                       if (ktr->ktr_code == SYS_ioctl) {
+                               char *cp;
+                               if (decimal)
+                                       (void)printf("(%ld", (long)*ip);
+                               else
+                                       (void)printf("(%#lx", (long)*ip);
+                               ip++;
+                               narg--;
+                               if ((cp = ioctlname(*ip)) != NULL)
+                                       (void)printf(",%s", cp);
+                               else {
+                                       if (decimal)
+                                               (void)printf(",%ld", (long)*ip);
+                                       else
+                                               (void)printf(",%#lx ", (long)*ip);
+                               }
+                               c = ',';
+                               ip++;
+                               narg--;
+                       } else if (ktr->ktr_code == SYS_ptrace) {
+                               if (*ip < sizeof(ptrace_ops) /
+                                   sizeof(ptrace_ops[0]) && *ip >= 0)
+                                       (void)printf("(%s", ptrace_ops[*ip]);
+#ifdef PT_GETREGS
+                               else if (*ip == PT_GETREGS)
+                                       (void)printf("(%s", "PT_GETREGS");
+#endif
+#ifdef PT_SETREGS
+                               else if (*ip == PT_SETREGS)
+                                       (void)printf("(%s", "PT_SETREGS");
+#endif
+#ifdef PT_GETFPREGS
+                               else if (*ip == PT_GETFPREGS)
+                                       (void)printf("(%s", "PT_GETFPREGS");
+#endif
+#ifdef PT_SETFPREGS
+                               else if (*ip == PT_SETFPREGS)
+                                       (void)printf("(%s", "PT_SETFPREGS");
+#endif
+#ifdef PT_GETDBREGS
+                               else if (*ip == PT_GETDBREGS)
+                                       (void)printf("(%s", "PT_GETDBREGS");
+#endif
+#ifdef PT_SETDBREGS
+                               else if (*ip == PT_SETDBREGS)
+                                       (void)printf("(%s", "PT_SETDBREGS");
+#endif
+                               else
+                                       (void)printf("(%ld", (long)*ip);
+                               c = ',';
+                               ip++;
+                               narg--;
+                       }
+               }
+               while (narg) {
+                       if (decimal)
+                               (void)printf("%c%ld", c, (long)*ip);
+                       else
+                               (void)printf("%c%#lx", c, (long)*ip);
+                       c = ',';
+                       ip++;
+                       narg--;
+               }
+               (void)putchar(')');
+       }
+       (void)putchar('\n');
+}
+
+ktrsysret(ktr)
+       struct ktr_sysret *ktr;
+{
+       register register_t ret = ktr->ktr_retval;
+       register int error = ktr->ktr_error;
+       register int code = ktr->ktr_code;
+
+       if (code >= nsyscalls || code < 0)
+               (void)printf("[%d] ", code);
+       else
+               (void)printf("%s ", syscallnames[code]);
+
+       if (error == 0) {
+               if (fancy) {
+                       (void)printf("%d", ret);
+                       if (ret < 0 || ret > 9)
+                               (void)printf("/%#lx", (long)ret);
+               } else {
+                       if (decimal)
+                               (void)printf("%ld", (long)ret);
+                       else
+                               (void)printf("%#lx", (long)ret);
+               }
+       } else if (error == ERESTART)
+               (void)printf("RESTART");
+       else if (error == EJUSTRETURN)
+               (void)printf("JUSTRETURN");
+       else {
+               (void)printf("-1 errno %d", ktr->ktr_error);
+               if (fancy)
+                       (void)printf(" %s", strerror(ktr->ktr_error));
+       }
+       (void)putchar('\n');
+}
+
+ktrnamei(cp, len)
+       char *cp;
+{
+       (void)printf("\"%.*s\"\n", len, cp);
+}
+
+ktrgenio(ktr, len)
+       struct ktr_genio *ktr;
+{
+       register int datalen = len - sizeof (struct ktr_genio);
+       register char *dp = (char *)ktr + sizeof (struct ktr_genio);
+       register char *cp;
+       register int col = 0;
+       register width;
+       char visbuf[5];
+       static screenwidth = 0;
+
+       if (screenwidth == 0) {
+               struct winsize ws;
+
+               if (fancy && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 &&
+                   ws.ws_col > 8)
+                       screenwidth = ws.ws_col;
+               else
+                       screenwidth = 80;
+       }
+       printf("fd %d %s %d byte%s\n", ktr->ktr_fd,
+               ktr->ktr_rw == UIO_READ ? "read" : "wrote", datalen,
+               datalen == 1 ? "" : "s");
+       if (maxdata && datalen > maxdata)
+               datalen = maxdata;
+       (void)printf("       \"");
+       col = 8;
+       for (;datalen > 0; datalen--, dp++) {
+               (void) vis(visbuf, *dp, VIS_CSTYLE, *(dp+1));
+               cp = visbuf;
+               /*
+                * Keep track of printables and
+                * space chars (like fold(1)).
+                */
+               if (col == 0) {
+                       (void)putchar('\t');
+                       col = 8;
+               }
+               switch(*cp) {
+               case '\n':
+                       col = 0;
+                       (void)putchar('\n');
+                       continue;
+               case '\t':
+                       width = 8 - (col&07);
+                       break;
+               default:
+                       width = strlen(cp);
+               }
+               if (col + width > (screenwidth-2)) {
+                       (void)printf("\\\n\t");
+                       col = 8;
+               }
+               col += width;
+               do {
+                       (void)putchar(*cp++);
+               } while (*cp);
+       }
+       if (col == 0)
+               (void)printf("       ");
+       (void)printf("\"\n");
+}
+
+char *signames[] = {
+       "NULL", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT",     /*  1 - 6  */
+       "EMT", "FPE", "KILL", "BUS", "SEGV", "SYS",             /*  7 - 12 */
+       "PIPE", "ALRM",  "TERM", "URG", "STOP", "TSTP",         /* 13 - 18 */
+       "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU",           /* 19 - 24 */
+       "XFSZ", "VTALRM", "PROF", "WINCH", "29", "USR1",        /* 25 - 30 */
+       "USR2", NULL,                                           /* 31 - 32 */
+};
+
+ktrpsig(psig)
+       struct ktr_psig *psig;
+{
+       (void)printf("SIG%s ", signames[psig->signo]);
+       if (psig->action == SIG_DFL)
+               (void)printf("SIG_DFL\n");
+       else
+               (void)printf("caught handler=0x%lx mask=0x%x code=0x%x\n",
+                   (u_long)psig->action, psig->mask, psig->code);
+}
+
+ktrcsw(cs)
+       struct ktr_csw *cs;
+{
+       (void)printf("%s %s\n", cs->out ? "stop" : "resume",
+               cs->user ? "user" : "kernel");
+}
+
+ktruser(len, p)
+       int len;
+       unsigned char *p;
+{
+       (void)printf("%d ", len);
+       while (len--)
+               (void)printf(" %02x", *p++);
+       (void)printf("\n");
+               
+}
+
+usage()
+{
+       (void)fprintf(stderr,
+           "usage: kdump [-dnlRT] [-f trfile] [-m maxdata] [-t [cnisuw]]\n");
+       exit(1);
+}
diff --git a/kdump.tproj/mkioctls b/kdump.tproj/mkioctls
new file mode 100644 (file)
index 0000000..53c8afd
--- /dev/null
@@ -0,0 +1,91 @@
+set -e
+
+# $FreeBSD: src/usr.bin/kdump/mkioctls,v 1.15.2.3 2001/04/07 11:09:28 ru Exp $
+
+if [ "x$1" = "x-s" ]; then
+       use_switch=1
+       shift
+else
+       use_switch=0
+fi
+
+if [ -z "$1" ]; then
+       echo "usage: sh $0 [-s] include-dir"
+       exit 1
+fi
+
+LC_ALL=C; export LC_ALL
+
+# Build a list of headers that have ioctls in them.
+# XXX should we use an ANSI cpp?
+# XXX netipx conflicts with netns (leave out netns).
+ioctl_includes=`
+       cd $1
+       find * -name '*.h' |
+               egrep -v '^(netns)/' |
+               egrep -v 'if_atm' |
+               egrep -v 'disklabel' |
+               egrep -v 'if_ppp' |
+               egrep -v 'bpf' |
+               egrep -v '^(netiso)/' |
+               egrep -v '^(netccitt)/' |
+               xargs egrep -l \
+'^#[   ]*define[       ]+[A-Za-z_][A-Za-z0-9_]*[       ]+_IO[^a-z0-9_]' |
+               sed -e 's/^/#include </' -e s'/$/>/' 
+`
+
+echo "/* XXX obnoxious prerequisites. */"
+echo "#define COMPAT_43 1"
+echo "#include <sys/param.h>"
+echo "#include <sys/socket.h>"
+echo "#include <sys/time.h>"
+echo "#include <sys/tty.h>"
+echo "#include <net/ethernet.h>"
+echo "#include <net/if.h>"
+echo "#include <net/if_var.h>"
+echo "#include <net/route.h>"
+echo "#include <netinet/in.h>"
+echo "#include <netinet/ip_compat.h>"
+echo "#include <netinet/ip_mroute.h>"
+echo "#include <netinet6/in6_var.h>"
+echo "#include <netinet6/nd6.h>"
+echo "#include <netinet6/ip6_mroute.h>"
+echo "#include <netat/appletalk.h>"
+echo "#include <stdio.h>"
+echo ""
+echo "$ioctl_includes"
+echo ""
+
+echo "$ioctl_includes" |
+       cc -no-cpp-precomp -E -I$1 -dM - |
+       awk -v use_switch="$use_switch" '
+BEGIN {
+       print "char *"
+       print "ioctlname(register_t val)"
+       print "{"
+       print ""
+       if (use_switch)
+               print "\tswitch(val) {"
+}
+
+/^#[   ]*define[       ]+[A-Za-z_][A-Za-z0-9_]*[       ]+_IO/ {
+       
+       # find where the name starts
+       for (i = 1; i <= NF; i++)
+               if ($i ~ /define/)
+                       break;
+       ++i;
+       # 
+       if (use_switch)
+               printf("\tcase %s:\n\t\treturn(\"%s\");\n", $i, $i);
+       else
+               printf("\tif (val ==  %s)\n\t\treturn(\"%s\");\n", $i, $i);
+
+}
+END {
+       if (use_switch)
+               print "\t}"
+       print "\n\treturn(NULL);"
+       print "}"
+}
+'
diff --git a/kdump.tproj/syscalls.c b/kdump.tproj/syscalls.c
new file mode 100644 (file)
index 0000000..71a9215
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* Copyright (c) 1992,1995-1999 Apple Computer, Inc.  All rights resereved. */
+
+char *syscallnames[] = {
+       "syscall",                      /* 0 = syscall */
+       "exit",                         /* 1 = exit */
+       "fork",                         /* 2 = fork */
+       "read",                         /* 3 = read */
+       "write",                        /* 4 = write */
+       "open",                         /* 5 = open */
+       "close",                        /* 6 = close */
+       "wait4",                        /* 7 = wait4 */
+       "obs_creat",            /* 8 = old creat */
+       "link",                         /* 9 = link */
+       "unlink",                       /* 10 = unlink */
+       "obs_execv",            /* 11 = obsolete execv */
+       "chdir",                        /* 12 = chdir */
+       "fchdir",                       /* 13 = fchdir */
+       "mknod",                        /* 14 = mknod */
+       "chmod",                        /* 15 = chmod */
+       "chown",                        /* 16 = chown */
+       "obs_break",            /* 17 = obsolete break */
+       "obs_getfsstat",        /* 18 = obsolete getfsstat */
+       "old_lseek",            /* 19 = old lseek */
+       "getpid",                       /* 20 = getpid */
+       "obs_mount",            /* 21 = obsolete mount */
+       "obs_unmount",          /* 22 = obsolete unmount */
+       "setuid",                       /* 23 = setuid */
+       "getuid",                       /* 24 = getuid */
+       "geteuid",                      /* 25 = geteuid */
+       "ptrace",                       /* 26 = ptrace */
+       "recvmsg",                      /* 27 = recvmsg */
+       "sendmsg",                      /* 28 = sendmsg */
+       "recvfrom",                     /* 29 = recvfrom */
+       "accept",                       /* 30 = accept */
+       "getpeername",          /* 31 = getpeername */
+       "getsockname",          /* 32 = getsockname */
+       "access",                       /* 33 = access */
+       "chflags",                      /* 34 = chflags */
+       "fchflags",                     /* 35 = fchflags */
+       "sync",                         /* 36 = sync */
+       "kill",                         /* 37 = kill */
+       "obs_stat",                     /* 38 = old stat */
+       "getppid",                      /* 39 = getppid */
+       "obs_lstat",            /* 40 = old lstat */
+       "dup",                          /* 41 = dup */
+       "pipe",                         /* 42 = pipe */
+       "getegid",                      /* 43 = getegid */
+       "profil",                       /* 44 = profil */
+       "ktrace",                       /* 45 = ktrace */
+       "sigaction",            /* 46 = sigaction */
+       "getgid",                       /* 47 = getgid */
+       "sigprocmask",          /* 48 = sigprocmask */
+       "getlogin",                     /* 49 = getlogin */
+       "setlogin",                     /* 50 = setlogin */
+       "acct",                         /* 51 = acct */
+       "sigpending",           /* 52 = sigpending */
+       "sigaltstack",          /* 53 = sigaltstack */
+       "ioctl",                        /* 54 = ioctl */
+       "reboot",                       /* 55 = reboot */
+       "revoke",                       /* 56 = revoke */
+       "symlink",                      /* 57 = symlink */
+       "readlink",                     /* 58 = readlink */
+       "execve",                       /* 59 = execve */
+       "umask",                        /* 60 = umask */
+       "chroot",                       /* 61 = chroot */
+       "obs_fstat",            /* 62 = old fstat */
+       "#63",                          /* 63 = reserved */
+       "obs_getpagesize",      /* 64 = old getpagesize */
+       "msync",                        /* 65 = msync */
+       "vfork",                        /* 66 = vfork */
+       "obs_vread",            /* 67 = obsolete vread */
+       "obs_vwrite",           /* 68 = obsolete vwrite */
+       "sbrk",                         /* 69 = sbrk */
+       "sstk",                         /* 70 = sstk */
+       "obs_mmap",                     /* 71 = old mmap */
+       "obs_vadvise",          /* 72 = obsolete vadvise */
+       "munmap",                       /* 73 = munmap */
+       "mprotect",                     /* 74 = mprotect */
+       "madvise",                      /* 75 = madvise */
+       "#76",                          /* 76 = obsolete vhangup */
+       "#77",                          /* 77 = obsolete vlimit */
+       "mincore",                      /* 78 = mincore */
+       "getgroups",            /* 79 = getgroups */
+       "setgroups",            /* 80 = setgroups */
+       "getpgrp",                      /* 81 = getpgrp */
+       "setpgid",                      /* 82 = setpgid */
+       "setitimer",            /* 83 = setitimer */
+       "old_wait",                     /* 84 = old wait */
+       "obs_swapon",           /* 85 = swapon */
+       "getitimer",            /* 86 = getitimer */
+       "obs_gethostname",      /* 87 = old gethostname */
+       "obs_sethostname",      /* 88 = old sethostname */
+       "getdtablesize",        /* 89 = getdtablesize */
+       "dup2",                         /* 90 = dup2 */
+       "#91",                          /* 91 = getdopt */
+       "fcntl",                        /* 92 = fcntl */
+       "select",                       /* 93 = select */
+       "#94",                          /* 94 = setdopt */
+       "fsync",                        /* 95 = fsync */
+       "setpriority",          /* 96 = setpriority */
+       "socket",                       /* 97 = socket */
+       "connect",                      /* 98 = connect */
+       "obs_accept",           /* 99 = old accept */
+       "getpriority",          /* 100 = getpriority */
+       "old_send",                     /* 101 = old send */
+       "old_recv",                     /* 102 = old recv */
+       "sigreturn",            /* 103 = sigreturn */
+       "bind",                         /* 104 = bind */
+       "setsockopt",           /* 105 = setsockopt */
+       "listen",                       /* 106 = listen */
+       "#107",                         /* 107 = obsolete vtimes */
+       "obs_sigvec",           /* 108 = old sigvec */
+       "obs_sigblock",         /* 109 = old sigblock */
+       "obs_sigsetmask",       /* 110 = old sigsetmask */
+       "sigsuspend",           /* 111 = sigsuspend */
+       "obs_sigstack",         /* 112 = old sigstack */
+       "obs_recvmsg",          /* 113 = old recvmsg */
+       "obs_sendmsg",          /* 114 = old sendmsg */
+       "#115",                         /* 115 = obsolete vtrace */
+       "gettimeofday",         /* 116 = gettimeofday */
+       "getrusage",            /* 117 = getrusage */
+       "getsockopt",           /* 118 = getsockopt */
+       "#119",                         /* 119 = nosys */
+       "readv",                        /* 120 = readv */
+       "writev",                       /* 121 = writev */
+       "settimeofday",         /* 122 = settimeofday */
+       "fchown",                       /* 123 = fchown */
+       "fchmod",                       /* 124 = fchmod */
+       "obs_recvfrom",         /* 125 = old recvfrom */
+       "obs_setreuid",         /* 126 = old setreuid */
+       "obs_setregid",         /* 127 = old setregid */
+       "rename",                       /* 128 = rename */
+       "obs_truncate",         /* 129 = old truncate */
+       "obs_ftruncate",        /* 130 = old ftruncate */
+       "flock",                        /* 131 = flock */
+       "mkfifo",                       /* 132 = mkfifo */
+       "sendto",                       /* 133 = sendto */
+       "shutdown",                     /* 134 = shutdown */
+       "socketpair",           /* 135 = socketpair */
+       "mkdir",                        /* 136 = mkdir */
+       "rmdir",                        /* 137 = rmdir */
+       "utimes",                       /* 138 = utimes */
+       "futimes",                      /* 139 = futimes */
+       "adjtime",                      /* 140 = adjtime */
+       "obs_getpeername",      /* 141 = old getpeername */
+       "obs_gethostid",        /* 142 = old gethostid */
+       "#143",                         /* 143 = old sethostid */
+       "obs_getrlimit",        /* 144 = old getrlimit */
+       "obs_setrlimit",        /* 145 = old setrlimit */
+       "obs_killpg",           /* 146 = old killpg */
+       "setsid",                       /* 147 = setsid */
+       "#148",                         /* 148 = obsolete setquota */
+       "#149",                         /* 149 = obsolete qquota */
+       "obs_getsockname",      /* 150 = old getsockname */
+       "#151",                         /* 151 = nosys */
+       "setprivexec",          /* 152 = setprivexec */
+       "pread",                        /* 153 = pread */
+       "pwrite",                       /* 154 = pwrite */
+       "nfssvc",                       /* 155 = nfssvc */
+       "getdirentries",        /* 156 =getdirentries */
+       "statfs",                       /* 157 = statfs */
+       "fstatfs",                      /* 158 = fstatfs */
+       "unmount",                      /* 159 = unmount */
+       "#160",                         /* 160 = obsolete async_daemon */
+       "getfh",                        /* 161 = getfh */
+       "obs_getdomainname",/* 162 = old getdomainname */
+       "obs_setdomainname",/* 163 = old setdomainname */
+       "#164",                         /* 164 */
+       "quotactl",                     /* 165 = quotactl */
+       "#166",                         /* 166 = obsolete exportfs */
+       "mount",                        /* 167 = mount */
+       "#168",                         /* 168 = obsolete ustat */
+       "#169",                         /* 169 = nosys */
+       "#170",                         /* 170 = obsolete table */
+       "obs_wait3",            /* 171 = old wait3 */
+       "#172",                         /* 172 = obsolete rpause */
+       "#173",                         /* 173 = nosys */
+       "#174",                         /* 174 = obsolete getdents */
+       "#175",                         /* 175 = nosys */
+       "add_profil",           /* 176 = add_profil */ /* NeXT */
+       "#177",                         /* 177 = nosys */
+       "#178",                         /* 178 = nosys */
+       "#179",                         /* 179 = nosys */
+       "kdebug_trace",         /* 180 = kdebug_trace */
+       "setgid",                       /* 181 = setgid */
+       "setegid",                      /* 182 = setegid */
+       "seteuid",                      /* 183 = seteuid */
+       "#184",                         /* 184 = nosys */
+       "#185",                         /* 185 = nosys */
+       "#186",                         /* 186 = nosys */
+       "#187",                         /* 187 = nosys */
+       "stat",                         /* 188 = stat */
+       "fstat",                        /* 189 = fstat */
+       "lstat",                        /* 190 = lstat */
+       "pathconf",                     /* 191 = pathconf */
+       "fpathconf",            /* 192 = fpathconf */
+       "obs_getfsstat",        /* 193 = old getfsstat */
+       "getrlimit",            /* 194 = getrlimit */
+       "setrlimit",            /* 195 = setrlimit */
+       "getdirentries",        /* 196 = getdirentries */
+       "mmap",                         /* 197 = mmap */
+       "#198",                         /* 198 = __syscall */
+       "lseek",                        /* 199 = lseek */
+       "truncate",                     /* 200 = truncate */
+       "ftruncate",            /* 201 = ftruncate */
+       "__sysctl",                     /* 202 = __sysctl */
+       "mlock",                        /* 203 = mlock */
+       "munlock",                      /* 204 = munlock */
+       "undelete",                     /* 205 = undelete */
+       "ATsocket",                     /* 206 = ATsocket */
+       "ATgetmsg",                     /* 207 = ATgetmsg */
+       "ATputmsg",                     /* 208 = ATputmsg */
+       "ATPsndreq",            /* 209 = ATPsndreq */
+       "ATPsndrsp",            /* 210 = ATPsndrsp */
+       "ATPgetreq",            /* 211 = ATPgetreq */
+       "ATPgetrsp",            /* 212 = ATPgetrsp */
+       "#213",                         /* 213 = Reserved for AppleTalk */
+       "#214",                         /* 214 = Reserved for AppleTalk */
+       "#215",                         /* 215 = Reserved for AppleTalk */
+       "#216",                         /* 216 = Reserved */
+       "#217",                         /* 217 = Reserved */
+       "#218",                         /* 218 = Reserved */
+       "#219",                         /* 219 = Reserved */
+       "getattrlist",          /* 220 = getattrlist */
+       "setattrlist",          /* 221 = setattrlist */
+       "getdirentriesattr",    /* 222 = getdirentriesattr */
+       "exchangedata",         /* 223 = exchangedata */
+       "checkuseraccess",      /* 224 - checkuseraccess */
+       "searchfs",                     /* 225 = searchfs */
+       "delete",                       /* 226 = private delete call */
+       "copyfile",                     /* 227 = copyfile  */
+       "#228",                         /* 228 = nosys */
+       "#229",                         /* 229 = nosys */
+       "#230",                         /* 230 = reserved for AFS */
+       "watchevent",           /* 231 = watchevent */
+       "waitevent",            /* 232 = waitevent */
+       "modwatch",                     /* 233 = modwatch */
+       "#234",                         /* 234 = nosys */
+       "#235",                         /* 235 = nosys */
+       "#236",                         /* 236 = nosys */
+       "#237",                         /* 237 = nosys */
+       "#238",                         /* 238 = nosys */
+       "#239",                         /* 239 = nosys */
+       "#240",                         /* 240 = nosys */
+       "#241",                         /* 241 = nosys */
+       "fsctl",                        /* 242 = fsctl */
+       "#243",                         /* 243 = nosys */
+       "#244",                         /* 244 = nosys */
+       "#245",                         /* 245 = nosys */
+       "#246",                         /* 246 = nosys */
+       "#247",                         /* 247 = nosys */
+       "#248",                         /* 248 = nosys */
+       "#249",                         /* 249 = nosys */
+       "minherit",                     /* 250 = minherit */
+       "semsys",                       /* 251 = semsys */
+       "msgsys",                       /* 252 = msgsys */
+       "shmsys",                       /* 253 = shmsys */
+       "semctl",                       /* 254 = semctl */
+       "semget",                       /* 255 = semget */
+       "semop",                        /* 256 = semop */
+       "semconfig",            /* 257 = semconfig */
+       "msgctl",                       /* 258 = msgctl */
+       "msgget",                       /* 259 = msgget */
+       "msgsnd",                       /* 260 = msgsnd */
+       "msgrcv",                       /* 261 = msgrcv */
+       "shmat",                        /* 262 = shmat */
+       "shmctl",                       /* 263 = shmctl */
+       "shmdt",                        /* 264 = shmdt */
+       "shmget",                       /* 265 = shmget */
+       "shm_open",                     /* 266 = shm_open */
+       "shm_unlink",           /* 267 = shm_unlink */
+       "sem_open",                     /* 268 = sem_open */
+       "sem_close",            /* 269 = sem_close */
+       "sem_unlink",           /* 270 = sem_unlink */
+       "sem_wait",                     /* 271 = sem_wait */
+       "sem_trywait",          /* 272 = sem_trywait */
+       "sem_post",                     /* 273 = sem_post */
+       "sem_getvalue",         /* 274 = sem_getvalue */
+       "sem_init",                     /* 275 = sem_init */
+       "sem_destroy",          /* 276 = sem_destroy */
+       "#277",                         /* 277 = nosys */
+       "#278",                         /* 278 = nosys */
+       "#279",                         /* 279 = nosys */
+       "#280",                         /* 280 = nosys */
+       "#281",                         /* 281 = nosys */
+       "#282",                         /* 282 = nosys */
+       "#283",                         /* 283 = nosys */
+       "#284",                         /* 284 = nosys */
+       "#285",                         /* 285 = nosys */
+       "#286",                         /* 286 = nosys */
+       "#287",                         /* 287 = nosys */
+       "#288",                         /* 288 = nosys */
+       "#289",                         /* 289 = nosys */
+       "#290",                         /* 290 = nosys */
+       "#291",                         /* 291 = nosys */
+       "#292",                         /* 292 = nosys */
+       "#293",                         /* 293 = nosys */
+       "#294",                         /* 294 = nosys */
+       "#295",                         /* 295 = nosys */
+       "load_shared_file",     /* 296 = load_shared_file */
+       "reset_shared_file",    /* 297 = reset_shared_file */
+       "new_system_shared_regions",    /* 298 = new_system_shared_regions */
+       "#299",                         /* 299 = nosys */
+       "#300",                         /* 300 = modnext */
+       "#301",                         /* 301 = modstat */
+       "#302",                         /* 302 = modfnext */
+       "#303",                         /* 303 = modfind */
+       "#304",                         /* 304 = kldload */
+       "#305",                         /* 305 = kldunload */
+       "#306",                         /* 306 = kldfind */
+       "#307",                         /* 307 = kldnext */
+       "#308",                         /* 308 = kldstat */
+       "#309",                         /* 309 = kldfirstmod */
+       "#310",                         /* 310 = getsid */
+       "#311",                         /* 311 = setresuid */
+       "#312",                         /* 312 = setresgid */
+       "#313",                         /* 313 = obsolete signanosleep */
+       "#314",                         /* 314 = aio_return */
+       "#315",                         /* 315 = aio_suspend */
+       "#316",                         /* 316 = aio_cancel */
+       "#317",                         /* 317 = aio_error */
+       "#318",                         /* 318 = aio_read */
+       "#319",                         /* 319 = aio_write */
+       "#320",                         /* 320 = lio_listio */
+       "#321",                         /* 321 = yield */
+       "#322",                         /* 322 = thr_sleep */
+       "#323",                         /* 323 = thr_wakeup */
+       "mlockall",                     /* 324 = mlockall */
+       "munlockall",           /* 325 = munlockall */
+       "#326",                         /* 326 */
+       "issetugid",            /* 327 = issetugid */
+       "__pthread_kill",       /* 328  = __pthread_kill */
+       "pthread_sigmask",      /* 329  = pthread_sigmask */
+       "sigwait",                      /* 330 = sigwait */
+       "#331",                         /* 331 */
+       "#332",                         /* 332 */
+       "#333",                         /* 333 */
+       "#334",                         /* 334 */
+       "utrace",                       /* 335 = utrace */
+       "#336",                         /* 336 */
+       "#337",                         /* 337 */
+       "#338",                         /* 338 */
+       "#339",                         /* 339 */
+       "#340",                         /* 340 */
+       "#341",                         /* 341 */
+       "#342",                         /* 342 */
+       "#343",                         /* 343 */
+       "#344",                         /* 344 */
+       "#345",                         /* 345 */
+       "#346",                         /* 346 */
+       "#347",                         /* 347 */
+       "#348",                         /* 348 */
+       "#349"                          /* 349 */
+};
diff --git a/kextd.tproj/GetSymbolFromPEF.h b/kextd.tproj/GetSymbolFromPEF.h
deleted file mode 100644 (file)
index 378eca6..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- * 
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
-       File:           GetSymbolFromPEF.h
-
-       Contains:       xxx put contents here xxx
-
-       Written by:     Jeffrey Robbin
-
-       Copyright:      Â© 1994 by Apple Computer, Inc., all rights reserved.
-
-       Change History (most recent first):
-
-                <2>     9/20/94        TS              Dump the globals!
-                <1>      9/6/94        TS              first checked in
-
-*/
-
-#ifndef __GETSYMBOLFROMPEF__
-#define __GETSYMBOLFROMPEF__
-
-//#include <Types.h>
-
-#pragma options align=mac68k
-
-#define NewPtrSys(a)   malloc(a)
-#define DisposePtr(a)  free(a)
-
-/*
-       Container information
-*/
-
-struct ContainerHeader {                                       /* File/container header layout:                                        */
-       unsigned long   magicCookie;                    /*              PEF container magic cookie                                      */
-       unsigned long   containerID;                    /*              'peff'                                                                          */
-       unsigned long   architectureID;                 /*              'pwpc' | 'm68k'                                                         */
-       unsigned long   versionNumber;                  /*              format version number                                           */
-       unsigned long   dateTimeStamp;                  /*              date/time stamp (Mac format)                            */
-       unsigned long   oldDefVersion;                  /*              old definition version number                           */
-       unsigned long   oldImpVersion;                  /*              old implementation version number                       */
-       unsigned long   currentVersion;                 /*              current version number                                          */
-       short                   nbrOfSections;                  /*              nbr of sections (rel. 1)                                        */
-       short                   loadableSections;               /*              nbr of loadable sectionsfor execution           */
-                                                       /*              (= nbr of 1st non-loadable section)                     */
-       LogicalAddress  memoryAddress;                  /*              location this container was last loaded         */
-};
-typedef struct ContainerHeader ContainerHeader, *ContainerHeaderPtr;
-
-#define        kMagic1         'joy!'
-#define        kMagic2         'peff'
-
-
-/*
-       Section information
-*/
-
-struct SectionHeader {                                         /* Section header layout:                                               */
-       long                    sectionName;                    /*              section name (str tbl container offset) */
-       unsigned long   sectionAddress;                 /*              preferred base address for the section  */
-       long                    execSize;                               /*              execution (byte) size including 0 init) */
-       long                    initSize;                               /*              init (byte) size before 0 init                  */
-       long                    rawSize;                                /*              raw data size (bytes)                                   */
-       long                    containerOffset;                /*              container offest to section's raw data  */
-       unsigned char   regionKind;                             /*              section/region classification                   */
-       unsigned char   shareKind;                              /*              sharing classification                                  */
-       unsigned char   alignment;                              /*              log 2 alignment                                                 */
-       unsigned char   reserved;                               /*              <reserved>                                                              */
-};
-typedef struct SectionHeader SectionHeader, *SectionHeaderPtr;
-
-                                                                                       /* regionKind section classification:                   */
-                                                                                       /*              loadable sections                                               */
-#define kCodeSection           0U                              /*                              code section                                    */
-#define kDataSection           1U                              /*                              data section                                    */
-#define kPIDataSection                 2U                              /*                              "pattern" initialized data              */
-#define kConstantSection       3U                              /*                              read-only data                                  */
-#define kExecDataSection       6U                              /*                              "self modifying" code (!?)              */
-                                                                                       /*              non-loadable sections                                   */
-#define kLoaderSection                 4U                              /*                              loader                                                  */
-#define kDebugSection          5U                              /*                              debugging info                                  */
-#define kExceptionSection      7U                              /*                              exception data                                  */
-#define kTracebackSection      8U                              /*                              traceback data                                  */
-
-
-/*
-       Loader Information
-*/
-
-struct LoaderHeader {                                          /* Loader raw data section header layout:               */
-       long entrySection;                                              /*              entry point section number                              */
-       long entryOffset;                                               /*              entry point descr. ldr section offset   */
-       long initSection;                                               /*              init routine section number                             */
-       long initOffset;                                                /*              init routine descr. ldr section offset  */
-       long termSection;                                               /*              term routine section number                             */
-       long termOffset;                                                /*              term routine descr. ldr section offset  */
-       long nbrImportIDs;                                              /*              nbr of import container id entries              */
-       long nbrImportSyms;                                             /*              nbr of import symbol table entries              */
-       long nbrRelocSects;                                             /*              nbr of relocation sections (headers)    */
-       long relocsOffset;                                              /*              reloc. instructions ldr section offset  */
-       long strTblOffset;                                              /*              string table ldr section offset                 */
-       long slotTblOffset;                                     /*              hash slot table ldr section offset              */
-       long hashSlotTblSz;                                     /*              log 2 of nbr of hash slot entries               */
-       long nbrExportSyms;                                             /*              nbr of export symbol table entries              */
-};
-typedef struct LoaderHeader LoaderHeader, *LoaderHeaderPtr;
-
-struct LoaderHashSlotEntry {                           /* Loader export hash slot table entry layout:  */
-       unsigned long slotEntry;                                /*              chain count (0:13), chain index (14:31) */
-};
-typedef struct LoaderHashSlotEntry LoaderHashSlotEntry, *LoaderHashSlotEntryPtr;
-
-struct LoaderExportChainEntry {                                /* Loader export hash chain tbl entry layout:   */
-       union {
-               unsigned long _hashWord;                        /*              name length and hash value                              */
-               struct {
-                       unsigned short _nameLength;             /*              name length is top half of hash word    */
-                       unsigned short doNotUseThis;    /*              this field should never be accessed!    */
-               } _h_h;
-       } _h;
-};
-typedef struct LoaderExportChainEntry LoaderExportChainEntry, *LoaderExportChainEntryPtr;
-
-struct ExportSymbolEntry {                                     /* Loader export symbol table entry layout:             */
-       unsigned long   class_and_name;                 /*              symClass (0:7), nameOffset (8:31)               */
-       long                    address;                                /*              ldr section offset to exported symbol   */
-       short                   sectionNumber;                  /*              section nbr that this export belongs to */
-};
-typedef struct ExportSymbolEntry ExportSymbolEntry, *ExportSymbolEntryPtr;
-
-
-
-/*
-       Unpacking Information
-*/
-
-                                                                                       /* "pattern" initialized data opcodes:                   */
-#define kZero                                  0U                      /*              zero (clear) bytes                                              */
-#define kBlock                                         1U                      /*              block transfer bytes                                    */
-#define kRepeat                                2U                      /*              repeat block xfer       bytes                           */
-#define kRepeatBlock                   3U                      /*              repeat block xfer with contant prefix   */
-#define kRepeatZero                    4U                      /*              repeat block xfer with contant prefix 0 */
-
-#define kOpcodeShift                   0x05U           /* shift to access opcode                                               */
-#define kFirstOperandMask              0x1FU           /* mask to access 1st operand (count)                   */
-
-#define PIOP(x)        (unsigned char)((x) >> kOpcodeShift)    /* extract opcode                               */
-#define PICNT(x) (long)((x) & kFirstOperandMask)                       /* extract 1st operand (count)  */
-
-/* The following macros are used for extracting count value operands from pidata...                    */
-
-#define kCountShift                            0x07UL          /* value shift to concat count bytes                    */
-#define kCountMask                             0x7FUL          /* mask to extract count bits from a byte               */
-
-#define IS_LAST_PICNT_BYTE(x) (((x) & 0x80U) == 0)                     /* true if last count byte              */
-
-#define CONCAT_PICNT(value, x) (((value)<<kCountShift) | ((x) & kCountMask))
-
-
-
-/*
-       Function Prototypes
-*/
-
-static OSStatus GetSymbolFromPEF (     StringPtr               theSymbolName,
-                                                       LogicalAddress  thePEFPtr,
-                                                       LogicalAddress  theSymbolPtr,
-                                                       ByteCount               theSymbolSize);
-
-static Boolean SymbolCompare ( StringPtr               theLookedForSymbol,
-                                               StringPtr               theExportSymbol,
-                                               unsigned long   theExportSymbolLength);
-                                               
-static OSErr UnpackPiData (LogicalAddress              thePEFPtr,
-                                       SectionHeaderPtr        sectionHeaderPtr,
-                                       LogicalAddress *        theData);
-
-static unsigned char PEFGetNextByte (unsigned char** rawBuffer, long* rawBufferRemaining);
-
-static unsigned long PEFGetCount(unsigned char** rawBuffer, long* rawBufferRemaining);
-
-
-#pragma options align=reset
-
-#endif
diff --git a/kextd.tproj/KEXTD.c b/kextd.tproj/KEXTD.c
deleted file mode 100644 (file)
index 2030b48..0000000
+++ /dev/null
@@ -1,1838 +0,0 @@
-#define CFRUNLOOP_NEW_API 1
-
-#include "KEXTD.h"
-#include "PTLock.h"
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOKitServer.h>
-#include <IOKit/IOCFSerialize.h>
-#include <IOKit/IOCFURLAccess.h>
-#include <pthread.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <mach/mach.h>
-#include <mach/mach_host.h>
-#include <mach/bootstrap.h>
-#include <mach/kmod.h>
-#include <syslog.h>
-
-#include <CoreFoundation/CFPriv.h>              // for _CFRunLoopSetCurrent();
-
-#define TIMER_PERIOD_S 10
-#define LOOKAPPLENDRV 1
-
-static Boolean gDebug;
-static void KEXTdaemonSignal(void);
-
-// from kernserv/queue.h   now kern/queue.h
-
-/*
- *     A generic doubly-linked list (queue).
- */
-
-struct queue_entry {
-        struct queue_entry     *next;          /* next element */
-        struct queue_entry     *prev;          /* previous element */
-};
-
-typedef struct queue_entry     *queue_t;
-typedef        struct queue_entry      queue_head_t;
-typedef        struct queue_entry      queue_chain_t;
-typedef        struct queue_entry      *queue_entry_t;
-
-/*
- *     Macro:          queue_init
- *     Function:
- *             Initialize the given queue.
- *     Header:
- *             void queue_init(q)
- *                     queue_t         q;      \* MODIFIED *\
- */
-#define        queue_init(q)   ((q)->next = (q)->prev = q)
-
-/*
- *     Macro:          queue_first
- *     Function:
- *             Returns the first entry in the queue,
- *     Header:
- *             queue_entry_t queue_first(q)
- *                     queue_t q;              \* IN *\
- */
-#define        queue_first(q)  ((q)->next)
-
-/*
- *     Macro:          queue_next
- *     Header:
- *             queue_entry_t queue_next(qc)
- *                     queue_t qc;
- */
-#define        queue_next(qc)  ((qc)->next)
-
-/*
- *     Macro:          queue_end
- *     Header:
- *             boolean_t queue_end(q, qe)
- *                     queue_t q;
- *                     queue_entry_t qe;
- */
-#define        queue_end(q, qe)        ((q) == (qe))
-
-#define        queue_empty(q)          queue_end((q), queue_first(q))
-
-/*
- *     Macro:          queue_enter
- *     Header:
- *             void queue_enter(q, elt, type, field)
- *                     queue_t q;
- *                     <type> elt;
- *                     <type> is what's in our queue
- *                     <field> is the chain field in (*<type>)
- */
-#define queue_enter(head, elt, type, field)                    \
-do {                                                   \
-        if (queue_empty((head))) {                             \
-                (head)->next = (queue_entry_t) elt;            \
-                (head)->prev = (queue_entry_t) elt;            \
-                (elt)->field.next = head;                      \
-                (elt)->field.prev = head;                      \
-        }                                                      \
-        else {                                                 \
-                register queue_entry_t prev;                   \
-                                                                \
-                prev = (head)->prev;                           \
-                (elt)->field.prev = prev;                      \
-                (elt)->field.next = head;                      \
-                (head)->prev = (queue_entry_t)(elt);           \
-                ((type)prev)->field.next = (queue_entry_t)(elt);\
-        }                                                      \
-} while(0)
-
-/*
- *     Macro:          queue_field [internal use only]
- *     Function:
- *             Find the queue_chain_t (or queue_t) for the
- *             given element (thing) in the given queue (head)
- */
-#define        queue_field(head, thing, type, field)                   \
-                (((head) == (thing)) ? (head) : &((type)(thing))->field)
-
-/*
- *     Macro:          queue_remove
- *     Header:
- *             void queue_remove(q, qe, type, field)
- *                     arguments as in queue_enter
- */
-#define        queue_remove(head, elt, type, field)                    \
-do {                                                   \
-        register queue_entry_t next, prev;                     \
-                                                                \
-        next = (elt)->field.next;                              \
-        prev = (elt)->field.prev;                              \
-                                                                \
-        queue_field((head), next, type, field)->prev = prev;   \
-        queue_field((head), prev, type, field)->next = next;   \
-} while(0)
-
-
-typedef struct _KEXTD {
-    CFIndex _refcount;
-    CFRunLoopRef _runloop;
-    CFRunLoopSourceRef _signalsource;
-    CFRunLoopSourceRef _kernelsource;
-    CFMutableArrayRef _scanPaths;
-    CFMutableArrayRef _unloaded;
-    CFMutableArrayRef _helpers;
-    queue_head_t _requestQ;
-    PTLockRef _runloop_lock;
-    PTLockRef _queue_lock;
-    KEXTManagerRef _manager;
-    mach_port_t _catPort;
-    Boolean _initializing;
-    Boolean _beVerbose;
-#if TIMERSOURCE
-    Boolean _pollFileSystem;
-    CFIndex _pollingPeriod;
-#endif
-} KEXTD;
-
-typedef struct _request {
-    unsigned int       type;
-    CFStringRef                kmodname;
-    CFStringRef                kmodvers;
-    queue_chain_t      link;
-} request_t;
-
-typedef struct _KEXTDHelper {
-    void * context;
-    KEXTDHelperCallbacks cbs;
-} KEXTDHelper;
-
-CFDictionaryRef   _KEXTPersonalityGetProperties(KEXTPersonalityRef personality);
-static void       _KEXTDRemovePersonalitiesFromUnloadedList(KEXTDRef kextd, CFStringRef parentKey);
-static void       _KEXTDAddPersonalitiesWithModuleToUnloadedList(KEXTDRef kextd, CFStringRef modName);
-const void *      _KEXTPersonalityRetainCB(CFAllocatorRef allocator, const void *ptr);
-void              _KEXTPersonalityReleaseCB(CFAllocatorRef allocator, const void *ptr);
-Boolean           _KEXTPersonalityEqualCB(const void *ptr1, const void *ptr2);
-mach_port_t       _KEXTManagerGetMachPort(KEXTManagerRef manager);
-
-extern kern_return_t
-kmod_control(host_t host,
-             kmod_t id,
-             kmod_control_flavor_t flavor,
-             kmod_args_t *data,
-             mach_msg_type_number_t *dataCount);
-
-extern KEXTReturn KERN2KEXTReturn(kern_return_t kr);
-
-static KEXTDRef _kextd = NULL;
-
-static void logErrorFunction(const char * string)
-{
-    syslog(LOG_ERR, string);
-    return;
-}
-
-static void logMessageFunction(const char * string)
-{
-    syslog(LOG_INFO, string);
-    return;
-}
-
-
-static void ArrayMergeFunc(const void * val, void * context)
-{
-    CFMutableArrayRef array;
-
-    array = context;
-
-    CFArrayAppendValue(array, val);
-}
-
-static void CFArrayMergeArray(CFMutableArrayRef array1, CFArrayRef array2)
-{
-    CFRange range;
-
-    if ( !array1 || !array2 ) {
-        return;
-    }
-
-    range = CFRangeMake(0, CFArrayGetCount(array2));
-    CFArrayApplyFunction(array2, range, ArrayMergeFunc, array1);
-}
-
-static void CallHelperEvent(void * val, void * context[])
-{
-    KEXTDRef kextd;
-    KEXTEvent event;
-    KEXTDHelper * helper;
-    CFTypeRef item;
-
-    helper = val;
-    kextd = context[0];
-    event = *(KEXTEvent *)context[1];
-    item = context[2];
-
-    if ( helper && context && helper->cbs.EventOccurred ) {
-        helper->cbs.EventOccurred(event, item, kextd);
-    }
-}
-
-static void ConfigsForBundles(const void * var, void * context[])
-{
-    KEXTManagerRef manager;
-    KEXTBundleRef bundle;
-    CFMutableArrayRef array;
-    CFArrayRef configs;
-
-    bundle = (KEXTBundleRef)var;
-
-    manager = context[0];
-    array = context[1];
-
-    configs = KEXTManagerCopyConfigsForBundle(manager, bundle);
-    if ( configs ) {
-        CFArrayMergeArray(array, configs);
-        CFRelease(configs);
-    }
-}
-
-
-static inline KEXTBootlevel _KEXTDGetBootlevel(KEXTPersonalityRef personality)
-{
-    KEXTBootlevel bootlevel;
-    CFStringRef priority;
-    CFStringRef category;
-
-    bootlevel = kKEXTBootlevelExempt;
-    priority = KEXTPersonalityGetProperty(personality, CFSTR("BootPriority"));
-    if ( !priority ) {
-        category = KEXTPersonalityGetProperty(personality, CFSTR("DeviceCategory"));
-        if ( !category ) {
-            return kKEXTBootlevelExempt;
-        }
-
-        if ( CFEqual(category, CFSTR("System Controller")) ) {
-             bootlevel = kKEXTBootlevelRequired;
-        }
-        else if ( CFEqual(category, CFSTR("Bus Controller")) ) {
-             bootlevel = kKEXTBootlevelFlexible;
-        }
-        else if ( CFEqual(category, CFSTR("Keyboard")) ) {
-             bootlevel = kKEXTBootlevelSingleUser;
-        }
-        else if ( CFEqual(category, CFSTR("Input Device")) ) {
-             bootlevel = kKEXTBootlevelExempt;
-        }
-        else if ( CFEqual(category, CFSTR("Pointing Device")) ) {
-             bootlevel = kKEXTBootlevelExempt;
-        }
-        else if ( CFEqual(category, CFSTR("Mouse")) ) {
-             bootlevel = kKEXTBootlevelRecovery;
-        }
-        else if ( CFEqual(category, CFSTR("Graphics Controller")) ) {
-             bootlevel = kKEXTBootlevelRecovery;
-        }
-        else if ( CFEqual(category, CFSTR("Graphics Accelerator")) ) {
-             bootlevel = kKEXTBootlevelExempt;
-        }
-        else if ( CFEqual(category, CFSTR("Video Device")) ) {
-             bootlevel = kKEXTBootlevelExempt;
-        }
-        else if ( CFEqual(category, CFSTR("Disk Controller")) ) {
-             bootlevel = kKEXTBootlevelFlexible;
-        }
-        else if ( CFEqual(category, CFSTR("Disk Media")) ) {
-             bootlevel = kKEXTBootlevelFlexible;
-        }
-        else if ( CFEqual(category, CFSTR("Audio Controller")) ) {
-             bootlevel = kKEXTBootlevelExempt;
-        }
-        else if ( CFEqual(category, CFSTR("Sound Device")) ) {
-             bootlevel = kKEXTBootlevelExempt;
-        }
-        else if ( CFEqual(category, CFSTR("Network Controller")) ) {
-             bootlevel = kKEXTBootlevelFlexible;
-        }
-
-        return bootlevel;
-    }
-
-    if ( CFEqual(priority, CFSTR("Exempt")) ) {
-        bootlevel = kKEXTBootlevelExempt;
-    }
-    else if ( CFEqual(priority, CFSTR("Recovery")) ) {
-        bootlevel = kKEXTBootlevelRecovery;
-    }
-    else if ( CFEqual(priority, CFSTR("Special")) ) {
-        bootlevel = kKEXTBootlevelSingleUser;
-    }
-    else if ( CFEqual(priority, CFSTR("Flexible")) ) {
-        bootlevel = kKEXTBootlevelFlexible;
-    }
-    else if ( CFEqual(priority, CFSTR("Required")) ) {
-        bootlevel = kKEXTBootlevelRequired;
-    }
-
-    return bootlevel;
-}
-
-static void ArrayAddToLoadList(void * val, void * context[])
-{
-    KEXTPersonalityRef person;
-    KEXTBootlevel bootlevel;
-    CFMutableArrayRef unloaded;
-    CFMutableArrayRef loadlist;
-    CFRange range;
-    Boolean doAdd;
-
-    if ( !val || !context ) {
-        return;
-    }
-
-    doAdd = true;
-    person = val;
-    unloaded = context[0];
-    loadlist = context[1];
-    bootlevel = *(KEXTBootlevel *)context[2];
-
-    if ( bootlevel != kKEXTBootlevelNormal ) {
-        doAdd  = _KEXTDGetBootlevel(person) & bootlevel;
-    }
-
-    if ( doAdd ) {
-        range = CFRangeMake(0, CFArrayGetCount(loadlist));
-        if ( !CFArrayContainsValue(loadlist, range, person) ) {
-            CFArrayAppendValue(loadlist, person);
-        }
-    }
-    else {
-        range = CFRangeMake(0, CFArrayGetCount(unloaded));
-        if ( !CFArrayContainsValue(unloaded, range, person) ) {
-            CFArrayAppendValue(unloaded, person);
-        }
-        CFArrayAppendValue(unloaded, person);
-    }
-}
-
-static void signalhandler(int signal)
-{
-    if ( _kextd && (signal == SIGHUP) ) {
-        KEXTDHangup(_kextd);
-    }
-}
-
-static KEXTReturn _KEXTDInitSyslog(KEXTD * k)
-{
-    openlog("kextd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
-
-    return kKEXTReturnSuccess;
-}
-
-// This is called when authenticating a new bundle.
-static KEXTReturn _KEXTDAuthenticateBundleCB(CFURLRef url, void * context)
-{
-    Boolean ret;
-
-    ret = KEXTManagerAuthenticateURL(url);
-    if ( !ret ) {
-        KEXTD * k = (KEXTD *)context;
-        KEXTEvent event;
-        CFStringRef urlString;
-        CFRange range;
-        char name[256];
-        void * context2[3];
-
-        urlString = CFURLGetString(url);
-        if ( CFStringGetCString(urlString, name, 256, kCFStringEncodingNonLossyASCII) )
-            syslog(LOG_ERR, "%s failed authentication.", name);
-
-        event = kKEXTEventBundleAuthenticationFailed;
-        context2[0] = k;
-        context2[1] = &event;
-        context2[2] = (void *)url;
-
-        range = CFRangeMake(0, CFArrayGetCount(k->_helpers));
-        CFArrayApplyFunction(k->_helpers, range, (CFArrayApplierFunction)CallHelperEvent, context2);
-    }
-
-    return ret;
-}
-
-// This is called when a new bundle has been found.
-static Boolean _KEXTDWillAddBundleCB(KEXTManagerRef manager, KEXTBundleRef bundle, void * context)
-{
-    KEXTD * k = (KEXTD *)context;
-    CFURLRef url;
-    CFIndex count;
-    CFIndex i;
-    Boolean ret;
-
-    ret = true;
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.BundleAdd ) {
-            ret = helper->cbs.BundleAdd(bundle, helper->context);
-            if ( !ret )
-                break;
-        }
-    }
-
-    url = KEXTBundleCopyURL(bundle);
-    if ( url ) {
-        if ( k->_beVerbose && ret ) {
-            CFStringRef cfstr;
-            char str[256];
-
-            cfstr = CFURLGetString(url);
-            if ( CFStringGetCString(cfstr, str, 256, kCFStringEncodingNonLossyASCII) ) {
-                syslog(LOG_INFO, "%s added.", str);
-            }
-        }
-
-        // Remove any unloaded personalities from look-aside queue
-        // which are in this bundle.
-        _KEXTDRemovePersonalitiesFromUnloadedList((KEXTDRef)k, KEXTBundleGetPrimaryKey(bundle));
-        CFRelease(url);
-    }
-
-    return ret;
-}
-
-// This is called after a bundle has been added to the KEXTManager database.
-static void _KEXTDWasAddedBundleCB(KEXTManagerRef manager, KEXTBundleRef bundle, void * context)
-{
-    KEXTD * k;
-    KEXTBootlevel bootlevel;
-    CFMutableArrayRef toload;
-    CFArrayRef persons;
-    CFArrayRef configs;
-    CFArrayRef unloaded;
-    CFRange range;
-    void * context2[3];
-
-    k = (KEXTD *)context;
-    if ( k->_initializing ) {
-        return;
-    }
-
-    bootlevel = kKEXTBootlevelNormal;
-
-    toload = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    if ( !toload ) {
-        return;
-    }
-
-    context2[0] = k->_unloaded;
-    context2[1] = toload;
-    context2[2] = &bootlevel;
-
-
-    // Create a list of all personalities and configurations
-    // and send it to the catalogue.  First, get the unloaded
-    // personalities.
-    unloaded = CFArrayCreateCopy(kCFAllocatorDefault, k->_unloaded);
-    CFArrayRemoveAllValues(k->_unloaded);
-    if ( unloaded ) {
-        range = CFRangeMake(0, CFArrayGetCount(unloaded));
-        CFArrayApplyFunction(unloaded, range, (CFArrayApplierFunction)ArrayAddToLoadList, context2);
-        CFRelease(unloaded);
-    }
-
-    persons = KEXTManagerCopyPersonalitiesForBundle(manager, bundle);
-    if ( persons ) {
-        range = CFRangeMake(0, CFArrayGetCount(persons));
-        CFArrayApplyFunction(persons, range, (CFArrayApplierFunction)ArrayAddToLoadList, context2);
-        CFRelease(persons);
-    }
-
-    configs = KEXTManagerCopyConfigsForBundle(manager, bundle);
-    if ( configs ) {
-        range = CFRangeMake(0, CFArrayGetCount(configs));
-        CFArrayApplyFunction(configs, range, (CFArrayApplierFunction)ArrayAddToLoadList, context2);
-        CFRelease(configs);
-        
-    }
-
-    // Send the list to IOCatalogue.
-    if ( CFArrayGetCount(toload) > 0 ) {
-        KEXTManagerLoadPersonalities(k->_manager, toload);
-    }
-    
-    CFRelease(toload);
-}
-
-static void _KEXTDConfigWasAdded(KEXTManagerRef manager, KEXTConfigRef config, void * context)
-{
-    KEXTD * kextd;
-
-    if ( !manager || !config || !context ) {
-        return;
-    }
-
-    kextd = context;
-
-    if ( !kextd->_initializing ) {
-        CFStringRef primaryKey;
-        CFArrayRef array;
-        void * vals[1];
-
-        primaryKey = CFDictionaryGetValue(config, CFSTR("ParentKey"));
-        if ( !primaryKey ) {
-            return;
-        }
-
-        if ( !KEXTManagerGetBundle(manager, primaryKey) ) {
-            return;
-        }
-        
-        vals[0] = config;
-        array = CFArrayCreate(kCFAllocatorDefault, vals, 1, &kCFTypeArrayCallBacks);
-        if ( array ) {
-            KEXTManagerLoadPersonalities(manager, array);
-            CFRelease(array);
-        }
-    }
-}
-
-static void _KEXTDConfigWasRemoved(KEXTManagerRef manager, KEXTConfigRef config, void * context)
-{
-    KEXTD * kextd;
-    
-    if ( !manager || !config || !context ) {
-        return;
-    }
-
-    kextd = context;
-    
-    if ( !kextd->_initializing ) {
-        KEXTManagerUnloadPersonality(manager, config);
-    }
-}
-
-static void ArrayUnloadPersonality(const void * val, void * context)
-{
-    KEXTManagerRef manager;
-    KEXTPersonalityRef person;
-
-    manager = context;
-    person = (KEXTPersonalityRef)val;
-    
-    KEXTManagerUnloadPersonality(manager, person);
-}
-
-// This is called when a bundle has been removed from the filesystem.
-static Boolean _KEXTDWillRemoveBundleCB(KEXTManagerRef manager, KEXTBundleRef bundle, void * context)
-{
-    KEXTD * k = (KEXTD *)context;
-    CFIndex count;
-    CFIndex i;
-    Boolean ret;
-
-    ret = true;
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.BundleRemove ) {
-            ret = helper->cbs.BundleRemove(bundle, helper->context);
-            if ( !ret )
-                break;
-        }
-    }
-    
-    if ( ret ) {
-        CFArrayRef personalities;
-        CFArrayRef configs;
-        CFURLRef url;
-        CFRange range;
-
-        // XXX -- svail: might want to unload bundle personalities
-        // from IOCatalogue and maybe unload the modules if possible.
-        // If a module is present with active personalities, don't remove
-        // bundle from database.
-        personalities = KEXTManagerCopyPersonalitiesForBundle(manager, bundle);
-        if ( personalities ) {
-            range = CFRangeMake(0, CFArrayGetCount(personalities));
-            CFArrayApplyFunction(personalities, range, ArrayUnloadPersonality, manager);
-            CFRelease(personalities);
-        }
-        
-        configs = KEXTManagerCopyConfigsForBundle(manager, bundle);
-        if ( configs ) {
-            range = CFRangeMake(0, CFArrayGetCount(configs));
-            CFArrayApplyFunction(configs, range, ArrayUnloadPersonality, manager);
-            CFRelease(configs);
-        }
-        
-        url = KEXTBundleCopyURL(bundle);
-        if ( url ) {
-            if ( k->_beVerbose && ret ) {
-                CFStringRef cfstr;
-                char str[256];
-
-                cfstr = CFURLGetString(url);
-                if ( CFStringGetCString(cfstr, str, 256, kCFStringEncodingNonLossyASCII) ) {
-                    syslog(LOG_INFO, "%s removed.", str);
-                }
-            }
-
-            // Remove any unloaded personalities from the unloaded
-            // list if they are associated with the bundle.
-
-            _KEXTDRemovePersonalitiesFromUnloadedList((KEXTDRef)k, KEXTBundleGetPrimaryKey(bundle));
-            CFRelease(url);
-        }
-    }
-    
-    return ret;
-}
-
-// This is called before KEXT loads a KMOD.
-static Boolean _KEXTDModuleWillLoadCB(KEXTManagerRef manager, KEXTModuleRef module, void * context)
-{
-    KEXTD * k;
-    CFIndex count;
-    CFIndex i;
-    Boolean ret;
-
-    k = (KEXTD *)context;
-
-    ret = true;
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.ModuleWillLoad ) {
-            if ( !helper->cbs.ModuleWillLoad(module, helper->context) ) {
-                ret = false;
-                break;
-            }
-        }
-    }
-
-    if ( ret ) {
-        CFStringRef moduleName;
-        char name[256];
-
-        moduleName = KEXTModuleGetProperty(module, CFSTR("CFBundleIdentifier"));
-        if ( !moduleName )
-            return false;
-
-        if ( !CFStringGetCString(moduleName, name, 256, kCFStringEncodingNonLossyASCII) )
-            return false;
-
-        syslog(LOG_INFO, "loading module: %s.\n", name);
-    }
-
-    return ret;
-}
-
-// This is called when a module has been successfully loaded.
-static void _KEXTDModuleWasLoadedCB(KEXTManagerRef manager, KEXTModuleRef module, void * context)
-{
-    KEXTD * k;
-    CFArrayRef array;
-    CFMutableArrayRef send;
-    CFIndex count;
-    CFIndex i;
-
-    k = (KEXTD *)context;
-
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.ModuleWasLoaded ) {
-            helper->cbs.ModuleWasLoaded(module, helper->context);
-        }
-    }
-
-    // Remove personalities from unloaded list if they
-    // are associated with the module and pass them to the
-    // kernel just in case they aren't there yet.
-
-    array = CFArrayCreateCopy(kCFAllocatorDefault, k->_unloaded);
-    send = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    count = CFArrayGetCount(array);
-    
-    CFArrayRemoveAllValues(k->_unloaded);
-
-    for ( i = 0; i < count; i++ ) {
-        KEXTPersonalityRef person;
-        CFStringRef moduleID;
-        CFStringRef personalityBundleID;
-
-        person = (KEXTPersonalityRef)CFArrayGetValueAtIndex(array, i);
-        if ( !person ) {
-            continue;
-        }
-        
-        moduleID = KEXTPersonalityGetProperty(person, CFSTR("CFBundleIdentifier"));
-        if ( !moduleID ) {
-            continue;
-        }
-
-        personalityBundleID = KEXTModuleGetProperty(module, CFSTR("CFBundleIdentifier"));
-        if ( !personalityBundleID ) {
-            continue;
-        }
-
-        if ( !CFEqual(moduleID, personalityBundleID) ) {
-            CFArrayAppendValue(k->_unloaded, person);
-        }
-        else {
-            CFArrayAppendValue(send, person);
-        }
-    }
-
-    if ( CFArrayGetCount(send) > 0 ) {
-        KEXTManagerLoadPersonalities(k->_manager, send);
-    }
-    
-    CFRelease(send);
-    CFRelease(array);
-    
-    if ( k->_beVerbose ) {
-        CFStringRef moduleName;
-        char name[256];
-
-        moduleName = KEXTModuleGetProperty(module, CFSTR("CFBundleIdentifier"));
-        if ( !moduleName )
-            return;
-
-        if ( !CFStringGetCString(moduleName, name, 256, kCFStringEncodingNonLossyASCII) )
-            return;
-        
-        syslog(LOG_INFO, "loaded module: %s\n", name);
-    }
-}
-
-static KEXTReturn _KEXTDModuleErrorCB(KEXTManagerRef manager, KEXTModuleRef module, KEXTReturn error, void * context)
-{
-    char name[256];
-    KEXTD * k;
-    KEXTReturn ret;
-    CFIndex i;
-    CFIndex count;
-    CFStringRef moduleName;
-
-    k = (KEXTD *)context;
-
-    moduleName = KEXTModuleGetProperty(module, CFSTR("CFBundleIdentifier"));
-    if ( !moduleName )
-        return kKEXTReturnPropertyNotFound;
-
-    if ( !CFStringGetCString(moduleName, name, 256, kCFStringEncodingNonLossyASCII) )
-        return kKEXTReturnNoMemory;
-
-    if ( error == kKEXTReturnModuleAlreadyLoaded ) {
-        if ( k->_beVerbose )
-            syslog(LOG_INFO, "module already loaded: %s.\n", name);
-
-        return error;
-    }
-
-    ret = error;
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.ModuleLoadError ) {
-            ret = helper->cbs.ModuleLoadError(module, error, helper->context);
-            if ( ret == kKEXTReturnSuccess ) {
-                break;
-            }
-        }
-    }
-    if ( ret == kKEXTReturnSuccess )
-        return kKEXTReturnSuccess;
-
-    syslog(LOG_ERR, "error (%d) loading module: %s.\n", ret, name);
-
-    return ret;
-}
-
-#if TIMERSOURCE
-static void _KEXTDTimerCallout(CFRunLoopTimerRef timer, void * info)
-{
-    KEXTDScanPaths((KEXTDRef)info, false);
-}
-#endif
-
-static void _KEXTDSIGHUPCallout(void * info)
-{
-    KEXTD * k;
-
-    k = (KEXTD *)info;
-    if ( k->_beVerbose ) {
-        syslog(LOG_INFO, "user requests directory re-scan.");
-    }
-
-    // Check for new or removed bundles and do the appropriate
-    // things.
-    KEXTDScanPaths((KEXTDRef)info, false);
-
-    // Make sure we try to load the unloaded personalities
-    // It's probably overkill to do this here.
-    if ( CFArrayGetCount(k->_unloaded) > 0 ) {
-        KEXTManagerLoadPersonalities(k->_manager, k->_unloaded);
-    }
-}
-
-// This function is called when IOCatalogue requests a driver module.
-static void _KEXTDPerform(void * info)
-{
-    KEXTD * k;
-    unsigned int type;
-
-    k = (KEXTD *)info;
-
-//    KEXTDScanPaths((KEXTDRef)k, false);
-
-    PTLockTakeLock(k->_queue_lock);
-    while ( !queue_empty(&k->_requestQ) ) {
-        request_t * reqstruct;
-        CFStringRef name;
-
-        // Dequeue the kernel request structure.
-        reqstruct = (request_t *)queue_first(&k->_requestQ);
-        queue_remove(&k->_requestQ, reqstruct, request_t *, link);
-        PTLockUnlock(k->_queue_lock);
-
-        type = reqstruct->type;
-        name = reqstruct->kmodname;
-        free(reqstruct);
-
-        if ( name ) {
-
-            if ( k->_beVerbose ) {
-                char modname[256];
-
-                if ( CFStringGetCString(name, modname, 256, kCFStringEncodingNonLossyASCII) ) {
-                    syslog(LOG_INFO, "kernel requests module: %s", modname);
-                }
-            }
-
-            KEXTDKernelRequest((KEXTDRef)k, name);
-            CFRelease(name);
-        }
-
-        PTLockTakeLock(k->_queue_lock);
-    }
-    PTLockUnlock(k->_queue_lock);
-}
-
-KEXTDRef KEXTDCreate(CFArrayRef scanPaths, KEXTReturn * error)
-{
-    KEXTD * kextd;
-
-    kextd = (KEXTD *)malloc(sizeof(KEXTD));
-    if ( !kextd ) {
-        *error = kKEXTReturnNoMemory;
-        return NULL;
-    }
-    memset(kextd, 0, sizeof(KEXTD));
-
-    kextd->_queue_lock = PTLockCreate();
-    kextd->_runloop_lock = PTLockCreate();
-
-    kextd->_helpers = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);
-    kextd->_unloaded = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    kextd->_scanPaths = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    if ( !kextd->_scanPaths || !kextd->_unloaded || !kextd->_helpers ) {
-        *error = kKEXTReturnNoMemory;
-        KEXTDFree((KEXTDRef)kextd);
-        return NULL;
-    }
-
-    kextd->_initializing = true;
-    kextd->_beVerbose = false;
-#if TIMERSOURCE
-    kextd->_pollFileSystem = false;
-    kextd->_pollingPeriod = TIMER_PERIOD_S;
-#endif
-
-    queue_init(&kextd->_requestQ);
-    
-    if ( scanPaths ) {
-        CFURLRef url;
-        CFIndex count;
-        CFIndex i;
-
-        count = CFArrayGetCount(scanPaths);
-        for ( i = 0; i < count; i++ ) {
-            url = (CFURLRef)CFArrayGetValueAtIndex(scanPaths, i);
-            KEXTDAddScanPath((KEXTDRef)kextd, url);
-        }
-    }
-
-    return (KEXTDRef)kextd;
-}
-
-static void _KEXTDFlushHelpers(KEXTDRef kextd)
-{
-    KEXTD * k;
-    CFIndex count;
-    CFIndex i;
-
-    k = (KEXTD *)kextd;
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.DaemonWillTerminate )
-            helper->cbs.DaemonWillTerminate(helper->context);
-        if ( helper->cbs.HelperFinalize )
-            helper->cbs.HelperFinalize(helper->context);
-
-        free(helper);
-    }
-}
-
-void KEXTDFree(KEXTDRef kextd)
-{
-    KEXTD * k;
-
-    k = (KEXTD *)kextd;
-
-    syslog(LOG_DEBUG, "terminating.");
-
-    if ( k->_helpers ) {
-        _KEXTDFlushHelpers(kextd);
-        CFRelease(k->_helpers);
-    }
-    if ( k->_kernelsource )
-        CFRelease(k->_kernelsource);
-    if ( k->_signalsource )
-        CFRelease(k->_signalsource);
-    if ( k->_runloop )  
-        CFRelease(k->_runloop);
-    if ( k->_scanPaths )
-        CFRelease(k->_scanPaths);
-    if ( k->_manager )
-        KEXTManagerRelease(k->_manager);
-    if ( k->_queue_lock )
-        PTLockFree(k->_queue_lock);
-    if ( k->_runloop_lock )
-        PTLockFree(k->_runloop_lock);
-    
-    closelog();
-
-    free(kextd);
-}
-
-void KEXTDReset(KEXTDRef kextd)
-{
-    KEXTD * k;
-    CFIndex count;
-    CFIndex i;
-
-    syslog(LOG_DEBUG, "resetting.");
-    
-    k = (KEXTD *)kextd;
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.EventOccurred )
-            helper->cbs.EventOccurred(kKEXTEventReset, NULL, helper->context);
-    }
-
-    if ( k->_manager )
-        KEXTManagerReset(k->_manager);
-    
-    KEXTDScanPaths(kextd, false);
-}
-
-static KEXTReturn _KEXTDSendDataToCatalog(KEXTDRef kextd, int flag, CFTypeRef obj)
-{
-    KEXTD * k;
-    KEXTReturn error;
-    CFDataRef data;
-    CFIndex len;
-    void * ptr;
-
-    k = (KEXTD *)kextd;
-    data = NULL;
-    error = kKEXTReturnSuccess;
-
-    data = IOCFSerialize(obj, 0);
-    if ( !data ) {
-        return kKEXTReturnSerializationError;
-    }
-
-    len = CFDataGetLength(data);
-    ptr = (void *)CFDataGetBytePtr(data);
-    error = KERN2KEXTReturn(IOCatalogueSendData(k->_catPort, flag, ptr, len));
-    CFRelease(data);
-
-    return error;
-}
-
-static KEXTReturn _KEXTDSendPersonalities(KEXTDRef kextd, KEXTBootlevel bootlevel)
-{
-    KEXTReturn error;
-    CFArrayRef persons;
-    CFArrayRef bundles;
-    CFMutableArrayRef configs;
-    CFMutableArrayRef toload;
-    CFRange range;
-    void * context[3];
-
-    error = kKEXTReturnSuccess;
-
-    toload = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    if ( !toload ) {
-        return kKEXTReturnNoMemory;
-    }
-
-    configs = NULL;
-    bundles = KEXTManagerCopyAllBundles(((KEXTD*)kextd)->_manager);
-    if ( bundles ) {
-        configs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-        if ( !configs ) {
-            CFRelease(bundles);
-            CFRelease(toload);
-            return kKEXTReturnNoMemory;
-        }
-
-        context[0] = ((KEXTD*)kextd)->_manager;
-        context[1] = configs;
-
-        range = CFRangeMake(0, CFArrayGetCount(bundles));
-        CFArrayApplyFunction(bundles, range, (CFArrayApplierFunction)ConfigsForBundles, context);
-        CFRelease(bundles);
-    }
-    
-    // Filter out any inappropriate personalities given the bootlevel of the 
-    // system. Store these personalities in the _unloaded list, they will be
-    // loaded when a SIGHUP is sent to the daemon.
-    context[0] = ((KEXTD *)kextd)->_unloaded;
-    context[1] = toload;
-    context[2] = &bootlevel;
-
-    persons = KEXTManagerCopyAllPersonalities(((KEXTD*)kextd)->_manager);
-    if ( persons ) {
-        range = CFRangeMake(0, CFArrayGetCount(persons));
-        CFArrayApplyFunction(persons, range, (CFArrayApplierFunction)ArrayAddToLoadList, context);
-        CFRelease(persons);
-    }
-
-    if ( configs ) {
-        range = CFRangeMake(0, CFArrayGetCount(configs));
-        CFArrayApplyFunction(configs, range, (CFArrayApplierFunction)ArrayAddToLoadList, context);
-        CFRelease(configs);
-    }
-
-    if ( CFArrayGetCount(toload) > 0 ) {
-        error = KEXTManagerLoadPersonalities(((KEXTD *)kextd)->_manager, toload);
-    }
-
-    KEXTdaemonSignal();
-
-    CFRelease(toload);
-
-    return error;
-
-}
-
-static inline Boolean _KEXTPersonalityNeedsModule(KEXTPersonalityRef person, CFStringRef modName)
-{
-    CFStringRef name;
-
-    name = KEXTPersonalityGetProperty(person, CFSTR("CFBundleIdentifier"));
-    if ( !name ) {
-        return false;
-    }
-
-    return CFEqual(name, modName);
-}
-
-// If a module fails to load for some reason, then put the
-// personalities associated with this module in a look-aside
-// buffer, we'll try loading them later, maybe when a broken
-// dependency is fixed.
-static void _KEXTDAddPersonalitiesWithModuleToUnloadedList(KEXTDRef kextd, CFStringRef modName)
-{
-    CFArrayRef array;
-    CFIndex i;
-    CFIndex count;
-    KEXTD * k;
-
-    if ( !modName )
-        return;
-
-    k = (KEXTD *)kextd;
-
-    array = KEXTManagerCopyAllEntities(k->_manager);
-    if ( !array )
-        return;
-    
-    // Find personalities which depend on this module.
-    count = CFArrayGetCount(array);
-    for ( i = 0; i < count; i++ ) {
-        CFStringRef type;
-        CFStringRef name;
-        CFRange range;
-        KEXTEntityRef entity;
-
-        entity = (KEXTEntityRef)CFArrayGetValueAtIndex(array, i);
-        if ( !entity )
-            continue;
-
-        type = KEXTManagerGetEntityType(entity);
-        if ( !type || !CFEqual(type, KEXTPersonalityGetEntityType()) ) {
-            continue;
-        }
-
-        name = KEXTPersonalityGetProperty(entity, CFSTR("CFBundleIdentifier"));
-        if ( !name || !CFEqual(modName, name) ) {
-            continue;
-        }
-
-        range = CFRangeMake(0, CFArrayGetCount(k->_unloaded));
-
-        if ( CFArrayContainsValue(k->_unloaded, range, entity) ) {
-            continue;
-        }
-
-        CFArrayAppendValue(k->_unloaded, entity);
-
-        if ( !k->_initializing ) {
-            KEXTManagerUnloadPersonality(k->_manager, entity);
-        }
-
-    }
-    CFRelease(array);
-}
-
-static void RemovePersonsWithParentFromUnloadedList(void * val, void * context[])
-{
-    KEXTPersonalityRef person;
-    CFMutableArrayRef unloaded;
-    CFStringRef parentKey;
-    CFStringRef key;
-
-    if ( !val || !context ) {
-        return;
-    }
-    
-    person = val;
-    unloaded = context[0];
-    parentKey = context[1];
-
-    key = CFDictionaryGetValue(person, CFSTR("ParentKey"));
-    if ( !parentKey || !key || CFEqual(parentKey, key) ) {
-        return;
-    }
-
-    CFArrayAppendValue(unloaded, person);
-}
-
-// Remove personalities from the unloaded list if their
-// associated bundle is removed.
-static void _KEXTDRemovePersonalitiesFromUnloadedList(KEXTDRef kextd, CFStringRef parentKey)
-{
-    CFMutableArrayRef unloaded;
-    CFArrayRef array;
-    CFRange range;
-    void * context[2];
-    
-    unloaded = ((KEXTD *)kextd)->_unloaded;
-    
-    array = CFArrayCreateCopy(kCFAllocatorDefault, unloaded);
-    CFArrayRemoveAllValues(unloaded);
-
-    context[0] = unloaded;
-    context[1] = (void *)parentKey;
-    
-    range = CFRangeMake(0, CFArrayGetCount(array));
-    CFArrayApplyFunction(
-                    array,
-                    range,
-                    (CFArrayApplierFunction)RemovePersonsWithParentFromUnloadedList,
-                    context);
-    
-    CFRelease(array);
-}
-
-static KEXTReturn _KEXTDProcessLoadCommand(KEXTDRef kextd, CFStringRef name)
-{
-    char cname[256];
-    KEXTReturn error;
-    KEXTD * k;
-
-    k = (KEXTD *)kextd;
-    if ( !CFStringGetCString(name, cname, 256, kCFStringEncodingNonLossyASCII) ) {
-        error = kKEXTReturnNoMemory;
-        return error;
-    }
-    
-    error = KEXTDLoadModule(kextd, name);
-    if ( error != kKEXTReturnSuccess &&
-         error != kKEXTReturnModuleAlreadyLoaded ) {
-        CFDictionaryRef matchingDict;
-        const void * keys[1];
-        const void * vals[1];
-
-        do {
-            keys[0] = CFSTR("CFBundleIdentifier");
-            vals[0] = name;
-
-            if ( !vals[0] ) {
-                error = kKEXTReturnPropertyNotFound;
-                break;
-            }
-
-            matchingDict = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-            if ( !matchingDict ) {
-                error = kKEXTReturnNoMemory;
-                break;
-            }
-
-            error = _KEXTDSendDataToCatalog(kextd, kIOCatalogRemoveDrivers, matchingDict);
-            CFRelease(matchingDict);
-            if ( error != kKEXTReturnSuccess ) {
-                syslog(LOG_DEBUG, "error ( %d) removing drivers.", error);
-                break;
-            }
-        } while ( false );
-
-        // Place personalities which failed to load this module onto
-        // a look-aside queue.  We'll try to load the module later
-        // when a broken dependency is fixed.
-        _KEXTDAddPersonalitiesWithModuleToUnloadedList(kextd, name);
-    }
-    else {
-
-        error = KERN2KEXTReturn(IOCatalogueModuleLoaded(k->_catPort, cname));
-        if ( error != kKEXTReturnSuccess ) {
-            syslog(LOG_DEBUG, "error (%d) signalling IOCatalogue.", error);
-        }
-    }
-    
-    return error;
-}
-
-void KEXTDHangup(KEXTDRef kextd)
-{
-    KEXTD * k;
-
-    k = (KEXTD *)kextd;
-    if ( k->_signalsource ) {
-        PTLockTakeLock(k->_runloop_lock);
-        CFRunLoopSourceSignal(k->_signalsource);
-        CFRunLoopWakeUp(k->_runloop);
-        PTLockUnlock(k->_runloop_lock);
-    }
-}
-
-KEXTReturn KEXTDKernelRequest(KEXTDRef kextd, CFStringRef name)
-{
-    KEXTD * k;
-    KEXTReturn ret;
-    
-    k = (KEXTD *)kextd;
-    ret = kKEXTReturnBadArgument;
-    if ( name ) {
-        KEXTEvent event;
-        CFRange range;
-        void * context[3];
-
-        event = kKEXTEventModuleRequest;
-
-        context[0] = kextd;
-        context[1] = &event;
-        context[2] = (void *)name;
-
-        range = CFRangeMake(0, CFArrayGetCount(k->_helpers));
-        CFArrayApplyFunction(k->_helpers, range, (CFArrayApplierFunction)CallHelperEvent, context);
-        ret = _KEXTDProcessLoadCommand((KEXTDRef)k, name);
-    }
-
-    return ret;
-}
-
-// The kernel blocks the thread which entered this
-// function until the kernel requests a driver to load.
-static void * _KEXTDKmodWait(void * info)
-{
-    mach_port_t kmodPort;
-    KEXTD * kextd;
-    KEXTReturn error;
-    request_t * reqstruct;
-    CFStringRef str;
-    unsigned int type;
-
-    if ( !info )
-        return (void *)kKEXTReturnBadArgument;
-
-    kmodPort = mach_host_self(); /* must be privileged to work */
-
-    kextd = (KEXTD *)info;
-    if ( !kextd->_kernelsource )
-        return (void *)kKEXTReturnBadArgument;
-
-    while ( 1 ) {
-        kmod_args_t data;
-        kmod_load_extension_cmd_t * cmd;
-        mach_msg_type_number_t dataCount;
-        kern_return_t kr;
-
-        data = 0;
-        dataCount = 0;
-        error = kKEXTReturnSuccess;
-
-        // Wait for kernel to unblock the thread.
-        kr = kmod_control(kmodPort, 0, KMOD_CNTL_GET_CMD, &data, &dataCount);
-        if ( kr != KERN_SUCCESS ) {
-            syslog(LOG_ERR, "error (%d): kmod_control.\n", kr);
-            continue;
-        }
-
-        cmd = (kmod_load_extension_cmd_t *)data;
-       type = cmd->type;
-       str = 0;
-
-        switch ( type ) {
-
-            case kIOCatalogMatchIdle: 
-               break;
-
-            case KMOD_LOAD_EXTENSION_PACKET: {
-                    
-                    str = CFStringCreateWithCString(NULL, cmd->name, kCFStringEncodingNonLossyASCII);
-                   if( str)
-                       break;
-                   // else fall thru
-                }
-            default:
-                error = kKEXTReturnError;
-                break;
-        }
-
-       if( error == kKEXTReturnSuccess) {
-
-            reqstruct = (request_t *)malloc(sizeof(request_t));
-            if( reqstruct) {
-                memset(reqstruct, 0, sizeof(request_t));
-                reqstruct->type = cmd->type;
-                reqstruct->kmodname = str;
-                // queue up a reqest.
-                PTLockTakeLock(kextd->_queue_lock);
-                queue_enter(&kextd->_requestQ, reqstruct, request_t *, link);
-                PTLockUnlock(kextd->_queue_lock);
-
-                // wake up the runloop.
-                PTLockTakeLock(kextd->_runloop_lock);
-                CFRunLoopSourceSignal(kextd->_kernelsource);
-                CFRunLoopWakeUp(kextd->_runloop);
-                PTLockUnlock(kextd->_runloop_lock);
-            }
-       }
-
-        // Deallocate kernel allocated memory.
-        vm_deallocate(mach_task_self(), (vm_address_t)data, dataCount);
-        if ( kr != KERN_SUCCESS ) {
-            syslog(LOG_DEBUG, "vm_deallocate failed. aborting.\n");
-            exit(1);
-        }
-    }
-    
-    return (void *)kKEXTReturnSuccess;
-}
-
-
-#include <fcntl.h>
-#include <paths.h>
-#include <unistd.h>
-#include <assert.h>
-#include <mach/semaphore.h>
-#include <mach/sync_policy.h>
-#include <mach/bootstrap.h>    /* bootstrap_ports */
-#undef _bootstrap_user_                /* XXX FIXME */
-#include <servers/bootstrap.h> /* bootstrap_look_up */
-#include <servers/bootstrap_defs.h>
-
-static void
-KEXTdaemonSignal(void)
-{
-    kern_return_t      kr;
-    mach_port_t                bs_port;
-    semaphore_t                sema;
-    static boolean_t   signalled = false;
-
-    if (signalled)
-       return;
-    signalled = TRUE;
-    if (gDebug) {
-        printf("kextd: signal\n");
-       return;
-    }
-
-    kr = task_get_bootstrap_port(mach_task_self(), &bs_port);
-    if( kr != KERN_SUCCESS )
-        syslog(LOG_ERR, "task_get_bootstrap_port (%lx)\n", kr);
-    kr = bootstrap_look_up(bs_port, "kextdsignal", &sema);
-    if( kr != BOOTSTRAP_SUCCESS )
-        syslog(LOG_ERR, "bootstrap_look_up(%lx)\n", kr);
-    kr = semaphore_signal_all( sema );
-    if( kr != KERN_SUCCESS )
-        syslog(LOG_ERR, "semaphore_signal_all(%lx)\n", kr);
-
-}
-
-static semaphore_t gDaemonSema;
-
-static void
-KEXTdaemonWait(void)
-{
-    kern_return_t      kr;
-    mach_port_t                masterPort;
-    mach_timespec_t    waitTime = { 40, 0 };
-
-    kr = semaphore_timedwait( gDaemonSema, waitTime );
-    if( kr != KERN_SUCCESS )
-        syslog(LOG_ERR, "semaphore_timedwait(%lx)\n", kr);
-
-    IOMasterPort( MACH_PORT_NULL, &masterPort );
-    IOKitWaitQuiet( masterPort, &waitTime );
-    if( kr != KERN_SUCCESS )
-        syslog(LOG_ERR, "IOKitWaitQuiet(%lx)\n", kr);
-}
-
-static int
-KEXTdaemon(nochdir, noclose)
-       int nochdir, noclose;
-{
-    kern_return_t      kr;
-    mach_port_t                bs_port;
-    int fd;
-
-    kr = semaphore_create( mach_task_self(), &gDaemonSema, SYNC_POLICY_FIFO, 0);
-    if( kr != KERN_SUCCESS )
-        syslog(LOG_ERR, "semaphore_create(%lx)\n", kr);
-    kr = task_get_bootstrap_port(mach_task_self(), &bs_port);
-    if( kr != KERN_SUCCESS )
-        syslog(LOG_ERR, "task_get_bootstrap_port(%lx)\n", kr);
-    kr = bootstrap_register(bs_port, "kextdsignal", gDaemonSema);
-    if( kr != BOOTSTRAP_SUCCESS )
-        syslog(LOG_ERR, "bootstrap_look_up(%lx)\n", kr);
-
-    switch (fork()) {
-    case -1:
-            return (-1);
-    case 0:
-           /*
-            * Under some circumstances a CFRunLoop could have been established
-            * in the parent process.  Since the mach ports associated with the
-            * run loop are not passed to the child process we need to start
-            * with a clean slate.
-            */
-            _CFRunLoopSetCurrent(NULL);
-
-            break;
-    default:
-            KEXTdaemonWait();
-            _exit(0);
-    }
-
-    if (setsid() == -1)
-            return (-1);
-
-    if (!nochdir)
-            (void)chdir("/");
-
-    if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
-            (void)dup2(fd, STDIN_FILENO);
-            (void)dup2(fd, STDOUT_FILENO);
-            (void)dup2(fd, STDERR_FILENO);
-            if (fd > 2)
-                    (void)close (fd);
-    }
-    return (0);
-}
-
-
-#if TIMERSOURCE
-KEXTReturn KEXTDStartMain(KEXTDRef kextd, Boolean beVerbose, Boolean safeBoot, Boolean debug, Boolean poll, CFIndex period, KEXTBootlevel bootlevel, Boolean cdMKextBoot)
-#else
-KEXTReturn KEXTDStartMain(KEXTDRef kextd, Boolean beVerbose, Boolean safeBoot, Boolean debug, KEXTBootlevel bootlevel, Boolean cdMKextBoot)
-#endif
-{
-    pthread_attr_t kmod_thread_attr;
-    pthread_t kmod_thread;
-    KEXTReturn error;
-    KEXTD * k;
-    CFIndex count;
-    CFIndex i;
-    CFRunLoopSourceContext sourceContext;
-    KEXTManagerBundleLoadingCallbacks bcb = {
-        0,
-        _KEXTDAuthenticateBundleCB,
-        _KEXTDWillAddBundleCB,
-        _KEXTDWasAddedBundleCB,
-        NULL,
-        _KEXTDWillRemoveBundleCB,
-        NULL,
-    };
-    KEXTManagerModuleLoadingCallbacks modcbs = {
-        0,
-        _KEXTDModuleWillLoadCB,
-        _KEXTDModuleWasLoadedCB,
-        _KEXTDModuleErrorCB,
-        NULL,
-        NULL,
-    };
-    KEXTManagerConfigsCallbacks cfgcbs = {
-        0,
-        NULL,
-        _KEXTDConfigWasAdded,
-        NULL,
-        _KEXTDConfigWasRemoved,
-    };
-
-    gDebug = debug;
-    if (!debug && !cdMKextBoot) {
-        errno = 0;
-        KEXTdaemon(0, 0);
-        if ( errno ) {
-            syslog(LOG_ERR, "failed to daemonize process. Aborting!\n");
-            return kKEXTReturnError;
-        }
-    }
-
-    k = (KEXTD *)kextd;
-    k->_manager = KEXTManagerCreate(&bcb, &modcbs, NULL, &cfgcbs, kextd,
-        &logErrorFunction, &logMessageFunction, safeBoot, &error);
-    if ( !k->_manager )
-        return error;
-
-    k->_initializing = true;
-    k->_catPort = _KEXTManagerGetMachPort(k->_manager);
-    k->_beVerbose = beVerbose;
-#if TIMERSOURCE
-    k->_pollFileSystem = poll;
-    k->_pollingPeriod = period;
-#endif
-    memset(&sourceContext, NULL, sizeof(CFRunLoopSourceContext));
-
-    error = _KEXTDInitSyslog(k);
-    if ( error != kKEXTReturnSuccess ) {
-        return error;
-    }
-
-    _kextd = kextd;
-
-    if( cdMKextBoot) {
-        KEXTDScanPaths(kextd, true);
-        return kKEXTReturnSuccess;
-    }
-
-    // FIXME: Need a way to make this synchronous!
-    error = KERN2KEXTReturn(IOCatalogueSendData(k->_catPort, kIOCatalogRemoveKernelLinker, 0, 0));
-    if (error != kKEXTReturnSuccess) {
-        syslog(LOG_ERR, "couldn't remove linker from kernel (may have been removed already).",
-            error);
-        // this is only serious the first time kextd launches....
-        // FIXME: how exactly should we handle this? Create a separate program
-        // to trigger KLD unload?
-    }
-    
-    signal(SIGHUP, signalhandler);
-
-    k->_runloop = CFRunLoopGetCurrent();
-    if ( !k->_runloop ) {
-        syslog(LOG_ERR, "error allocating runloop.\n");
-        return NULL;
-    }
-
-    sourceContext.version = 0;
-    sourceContext.info = k;
-    sourceContext.perform = _KEXTDSIGHUPCallout;
-    k->_signalsource = CFRunLoopSourceCreate(kCFAllocatorDefault, 1, &sourceContext);
-    if ( !k->_signalsource ) {
-        syslog(LOG_ERR, "error allocating signal runloop source.\n");
-        return NULL;
-    }
-    CFRunLoopAddSource(k->_runloop, k->_signalsource, kCFRunLoopDefaultMode);
-
-    sourceContext.perform = _KEXTDPerform;
-    k->_kernelsource = CFRunLoopSourceCreate(kCFAllocatorDefault, 2, &sourceContext);
-    if ( !k->_kernelsource ) {
-        syslog(LOG_ERR, "error allocating kernel runloop source.\n");
-        return NULL;
-    }
-    CFRunLoopAddSource(k->_runloop, k->_kernelsource, kCFRunLoopDefaultMode);
-
-    count = CFArrayGetCount(k->_helpers);
-    for ( i = 0; i < count; i++ ) {
-        KEXTDHelper * helper;
-
-        helper = (KEXTDHelper *)CFArrayGetValueAtIndex(k->_helpers, i);
-        if ( !helper )
-            continue;
-
-        if ( helper->cbs.DaemonDidFinishLaunching )
-            helper->cbs.DaemonDidFinishLaunching(helper->context);
-    }
-
-    // Fork off the kmod_control message thread.
-    pthread_attr_init(&kmod_thread_attr);
-    pthread_create(&kmod_thread, &kmod_thread_attr, _KEXTDKmodWait, kextd);
-    pthread_detach(kmod_thread);
-
-    syslog(LOG_INFO, "started.");
-
-    IOCatalogueReset(k->_catPort, kIOCatalogResetDefault);
-    KEXTDScanPaths(kextd, false);
-
-#if TIMERSOURCE
-    if ( poll ) {
-        CFRunLoopTimerRef timer;
-        CFRunLoopTimerContext timerContext = {
-            0, kextd, NULL, NULL, NULL,
-        };
-
-        timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), period, 0, 10, _KEXTDTimerCallout, &timerContext);
-        if ( !timer ) {
-            syslog(LOG_ERR, "error allocating kmod runloop timer.\n");
-            return kKEXTReturnError;
-        }
-
-        CFRunLoopAddTimer(k->_runloop, timer, kCFRunLoopDefaultMode);
-        CFRelease(timer);
-    }
-#endif
-
-    if ( (error = _KEXTDSendPersonalities(kextd, bootlevel)) != kKEXTReturnSuccess ) {
-        // KEXTError(error, CFSTR("Error sending personalities to IOCatalogue"));
-        syslog(LOG_ERR, "error (%d) sending personalities to IOCatalogue.", error);
-        return error;
-    }
-
-    k->_initializing = false;
-
-    CFRunLoopRun();
-    
-    return kKEXTReturnSuccess;
-}
-
-void KEXTDScanPaths(KEXTDRef kextd, Boolean cdMKextBoot)
-{
-    KEXTReturn error;
-    KEXTD * k;
-    CFIndex count;
-    CFIndex i;
-
-    k = (KEXTD *)kextd;
-    if ( !k->_manager )
-        return;
-    
-    count = CFArrayGetCount(k->_scanPaths);
-    for ( i = 0; i < count; i++ ) {
-        CFURLRef url;
-
-        url = (CFURLRef)CFArrayGetValueAtIndex(k->_scanPaths, i);
-
-        if ( url ) {
-            if ( k->_beVerbose ) {
-                CFStringRef cfstr;
-                char str[256];
-
-                cfstr = CFURLGetString(url);
-                if ( CFStringGetCString(cfstr, str, 256, kCFStringEncodingNonLossyASCII) ) {
-                    syslog(LOG_INFO, "scanning: %s.", str);
-                }
-            }
-            if( !cdMKextBoot) {
-                error = KEXTManagerScanPath(k->_manager, url);
-                if ( error != kKEXTReturnSuccess ) {
-                    syslog(LOG_ERR, "error (%d) scanning path.\n", error);
-                }
-            }
-#if LOOKAPPLENDRV
-           do {
-                CFURLRef       path;
-               CFArrayRef      array;
-               CFIndex         count, index;
-                SInt32         err;
-
-                path = CFURLCreateCopyAppendingPathComponent(
-                                    kCFAllocatorDefault,
-                                    url,
-                                    CFSTR("AppleNDRV"),
-                                    TRUE);
-                if ( !path )
-                   continue;
-                array = (CFArrayRef)IOURLCreatePropertyFromResource(
-                                            kCFAllocatorDefault, path,
-                                            kIOURLFileDirectoryContents,
-                                            &err);
-               CFRelease( path );
-                if ( !array )
-                   continue;
-
-                count = CFArrayGetCount(array);
-                for ( index = 0; index < count; index++ ) {
-                    CFURLRef file;
-                    file = (CFURLRef) CFArrayGetValueAtIndex(array, index);
-                    if ( !file )
-                        continue;
-                    PEFExamineFile( k->_catPort, file );
-               }
-               CFRelease(array);
-
-            } while( false );
-#endif /* LOOKAPPLENDRV */
-       }
-    }
-}
-
-void KEXTDAddScanPath(KEXTDRef kextd, CFURLRef path)
-{
-    if ( !kextd || !path )
-        return;
-
-    if ( CFURLGetTypeID() != CFGetTypeID(path) )
-        return;
-
-    CFArrayAppendValue(((KEXTD *)kextd)->_scanPaths, path);
-}
-
-void KEXTDRegisterHelperCallbacks(KEXTDRef kextd, KEXTDHelperCallbacks * callbacks)
-{
-    KEXTD * k;
-    KEXTDHelper * helper;
-
-    if ( !kextd || !callbacks )
-        return;
-    
-    k = (KEXTD *)kextd;
-    helper = (KEXTDHelper *)malloc(sizeof(KEXTDHelper));
-    if ( !helper )
-        return;
-
-    helper->cbs.HelperInitialize = callbacks->HelperInitialize;
-    helper->cbs.HelperFinalize = callbacks->HelperFinalize;
-    helper->cbs.DaemonDidFinishLaunching = callbacks->DaemonDidFinishLaunching;
-    helper->cbs.DaemonWillTerminate = callbacks->DaemonWillTerminate;
-    helper->cbs.BundleAdd = callbacks->BundleAdd;
-    helper->cbs.BundleRemove = callbacks->BundleRemove;
-    helper->cbs.EventOccurred = callbacks->EventOccurred;
-    helper->cbs.ModuleWillLoad = callbacks->ModuleWillLoad;
-    helper->cbs.ModuleWasLoaded = callbacks->ModuleWasLoaded;
-    helper->cbs.ModuleLoadError = callbacks->ModuleLoadError;
-
-    helper->context = helper->cbs.HelperInitialize(kextd);
-
-    CFArrayAppendValue(k->_helpers, helper);
-}
-
-KEXTReturn KEXTDLoadModule(KEXTDRef kextd, CFStringRef moduleName)
-{
-    KEXTD * k = (KEXTD *)kextd;
-    KEXTModuleRef module;
-
-    if ( !kextd || !moduleName )
-        return kKEXTReturnBadArgument;
-    
-    module = KEXTManagerGetModule(k->_manager, moduleName);
-    if ( !module )
-        return kKEXTReturnModuleNotFound;
-
-    return KEXTManagerLoadModule(k->_manager, module);
-}
-
-
diff --git a/kextd.tproj/KEXTD.h b/kextd.tproj/KEXTD.h
deleted file mode 100644 (file)
index 9cd5055..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-
-#ifndef __KEXTD_H_
-#define __KEXTD_H_
-
-#include <IOKit/kext/KEXTManager.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-typedef struct __KEXTD * KEXTDRef;
-
-typedef enum {
-    kKEXTBootlevelNormal     = 0x00,
-    kKEXTBootlevelExempt     = 0x01,
-    kKEXTBootlevelRecovery   = 0x02,
-    kKEXTBootlevelSingleUser = 0x04,
-    kKEXTBootlevelFlexible   = 0x08,
-    kKEXTBootlevelRequired   = 0x10,
-} KEXTBootlevel;
-
-typedef enum {
-    kKEXTEventReset,
-    kKEXTEventModuleRequest,
-    kKEXTEventPersonalityRequest,
-    kKEXTEventBundleAuthenticationFailed,
-} KEXTEvent;
-
-typedef struct {
-    CFIndex version;
-    void *     (*HelperInitialize)(KEXTDRef kextd);
-    void       (*HelperFinalize)(void * context);
-    void       (*DaemonDidFinishLaunching)(void * context);
-    void       (*DaemonWillTerminate)(void * context);
-    Boolean    (*BundleAdd)(KEXTBundleRef bundle, void * context);
-    Boolean    (*BundleRemove)(KEXTBundleRef bundle, void * context);
-    void       (*EventOccurred)(KEXTEvent event, CFTypeRef data, void * context);
-    Boolean    (*ModuleWillLoad)(KEXTModuleRef module, void * context);
-    void       (*ModuleWasLoaded)(KEXTModuleRef module, void * context);
-    KEXTReturn (*ModuleLoadError)(KEXTModuleRef module, KEXTReturn error, void * context);
-} KEXTDHelperCallbacks;
-
-
-KEXTDRef       KEXTDCreate(CFArrayRef scanPaths, KEXTReturn * error);
-void           KEXTDFree(KEXTDRef kextd);
-
-void            KEXTDHangup(KEXTDRef kextd);
-void           KEXTDReset(KEXTDRef kextd);
-#if TIMERSOURCE
-KEXTReturn     KEXTDStartMain(KEXTDRef kextd, Boolean beVerbose, Boolean safeBoot, Boolean debug, Boolean poll, CFIndex period, KEXTBootlevel bootlevel, Boolean cdMKextBoot);
-#else
-KEXTReturn     KEXTDStartMain(KEXTDRef kextd, Boolean beVerbose, Boolean safeBoot, Boolean debug, KEXTBootlevel bootlevel, Boolean cdMKextBoot);
-#endif
-void           KEXTDScanPaths(KEXTDRef kextd, Boolean cdMKextBoot);
-void           KEXTDAddScanPath(KEXTDRef kextd, CFURLRef path);
-void           KEXTDRegisterHelperCallbacks(KEXTDRef kextd, KEXTDHelperCallbacks * callbacks);
-KEXTReturn      KEXTDKernelRequest(KEXTDRef kextd, CFStringRef moduleName);
-KEXTReturn     KEXTDLoadModule(KEXTDRef kextd, CFStringRef moduleName);
-
-#if defined(__cplusplus)
-} /* "C" */
-#endif
-
-#endif __KEXTD_H_
-
diff --git a/kextd.tproj/KEXTD_main.c b/kextd.tproj/KEXTD_main.c
deleted file mode 100644 (file)
index 778b187..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-#include <unistd.h>
-#include <CoreFoundation/CoreFoundation.h>
-#include "KEXTD.h"
-
-#define TIMER_PERIOD_S         10
-#define DEFAULT_SEARCH_PATH    "/System/Library/Extensions/"
-
-static const char * arg0 = NULL;
-
-static void usage(void)
-{
-    printf("usage: %s [-v] [-d] [-x] [-j] [-b bootlevel] [-f dirpath]\n", arg0);
-    exit(1);
-}
-
-int main (int argc, const char *argv[])
-{
-    KEXTDRef kextd;
-    KEXTReturn error;
-    KEXTBootlevel bootlevel;
-    CFStringRef str;
-    CFURLRef url;
-    CFMutableArrayRef array;
-    CFIndex period;
-    Boolean safeBoot;
-    Boolean beVerbose;
-    Boolean enableTimer;
-    Boolean debug;
-    Boolean cdMKextBoot;
-    int c;
-
-    arg0 = argv[0];
-    period = TIMER_PERIOD_S;
-    debug = false;
-    safeBoot = false;
-    beVerbose = false;
-    enableTimer = false;
-    cdMKextBoot = false;
-    bootlevel = kKEXTBootlevelNormal;
-
-    url = CFURLCreateWithFileSystemPath(NULL, CFSTR(DEFAULT_SEARCH_PATH), kCFURLPOSIXPathStyle, true);
-    if ( !url ) {
-        printf("Error opening: %s.\n", DEFAULT_SEARCH_PATH);
-        exit(1);
-    }
-    array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    CFArrayAppendValue(array, url);
-    CFRelease(url);
-
-    while ( (c = getopt(argc, (char **)argv, "xvdjb:f:")) != -1 ) {
-        switch ( c ) {
-
-            case 'x':
-                safeBoot = true;
-                break;
-            case 'v':
-                beVerbose = true;
-                break;
-            case 'd':
-                debug = true;
-                break;
-#if TIMERSOURCE
-            case 'p':
-                if ( !optarg ) {
-                    usage();
-                }
-                else {
-                    period = strtoul(optarg, NULL, 0);
-                    if ( period > 0 )
-                        enableTimer = true;
-                }
-                break;
-#endif
-
-            case 'b':
-                if ( !optarg ) {
-                    usage();
-                }
-                bootlevel = strtoul(optarg, NULL, 0);
-                if ( bootlevel > 0x1f ) {
-                    usage();
-                }
-                break;
-
-            case 'j':
-                cdMKextBoot = true;
-                break;
-                
-            case 'f':
-                if ( !optarg ) {
-                    usage();
-                }
-                str = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingNonLossyASCII);
-                if ( str )
-                    url = CFURLCreateWithFileSystemPath(NULL, str, kCFURLPOSIXPathStyle, true);
-                else
-                    url = NULL;
-                if ( !url ) {
-                    printf("Error opening: %s.\n", optarg);
-                } else {
-                    CFArrayAppendValue(array, url);
-                    CFRelease(url);
-                }
-                break;
-
-            default:
-                usage();
-        }
-    }
-    argc -= optind;
-    argv += optind;
-
-    if (argc != 0) {
-        usage();
-    }
-
-    kextd = KEXTDCreate(array, &error);
-    CFRelease(array);
-    if ( !kextd ) {
-        KEXTError(error, CFSTR("Error creating kextd"));
-        exit(error);
-    }
-    
-    KEXTDRegisterHelperCallbacks(kextd, NULL);
-#if TIMERSOURCE
-    error = KEXTDStartMain(kextd, beVerbose, safeBoot, debug, enableTimer, period, bootlevel, cdMKextBoot);
-#else
-    error = KEXTDStartMain(kextd, beVerbose, safeBoot, debug, bootlevel, cdMKextBoot);
-#endif
-    if ( error != kKEXTReturnSuccess ) {
-        KEXTDFree(kextd);
-        KEXTError(error, CFSTR("Error starting kextd"));
-        exit(error);
-    }
-    KEXTDFree(kextd);
-    
-    return error;
-}
diff --git a/kextd.tproj/Makefile b/kextd.tproj/Makefile
deleted file mode 100644 (file)
index a43517e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# Generated by the Apple Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = kextd
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-HFILES = GetSymbolFromPEF.h KEXTD.h PTLock.h
-
-CFILES = KEXTD.c KEXTD_main.c PEFSupport.c PTLock.c
-
-OTHERSRCS = Makefile.preamble Makefile
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/libexec
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-NEXTSTEP_PB_CFLAGS = -fpascal-strings -Wno-four-char-constants
-
-FRAMEWORKS = -framework CoreFoundation -framework IOKit
-
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/kextd.tproj/Makefile.preamble b/kextd.tproj/Makefile.preamble
deleted file mode 100644 (file)
index c1624b4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-###############################################################################
-#  Makefile.preamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile for configuring the standard application makefiles 
-#  associated with ProjectBuilder. It is included before the main makefile.
-#  In Makefile.preamble you set attributes for a project, so they are available
-#  to the project's makefiles.  In contrast, you typically write additional rules or 
-#  override built-in behavior in the Makefile.postamble.
-#  
-#  Each directory in a project tree (main project plus subprojects) should 
-#  have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible.  To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
-#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
-#      flags in OTHER_MFLAGS, etc.
-#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
-#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
-#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
-#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
-#      precompiling header files
-#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
-#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
-#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
-#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
-#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every 
-# stage of the make:
-#
-#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
-#    AFTER_PREBUILD: targets to build after installing headers for a subproject
-#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
-#    BEFORE_BUILD: targets to make before a build, but after subprojects
-#    AFTER_BUILD: targets to make after a build
-#
-#    BEFORE_INSTALL: targets to build before installing the product
-#    AFTER_INSTALL: targets to build after installing the product
-#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
-#         subproject
-#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-#    BEFORE_DEPEND: targets to build before building dependencies for a
-#        subproject
-#    AFTER_DEPEND: targets to build after building dependencies for a
-#        subproject
-#
-#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-#        updated every time the project is built.  If NO, the dependency
-#        file is only built when the depend target is invoked.
-
-# Framework-related variables:
-#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the framework's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-#    PUBLIC_HEADER_DIR:  Determines where public exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.  For library projects you should
-#       set this to something like /Developer/Headers/$(NAME).  Do not set
-#       this variable for framework projects unless you do not want the
-#       header files included in the framework.
-#    PRIVATE_HEADER_DIR:  Determines where private exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.
-#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
-#      whether the libraries produced are statically linked when they
-#      are used or if they are dynamically loadable. This defaults to
-#       DYNAMIC.
-#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the library's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-#
-#    INSTALL_AS_USER: owner of the intalled products (default root)
-#    INSTALL_AS_GROUP: group of the installed products (default wheel)
-#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-#      passed on the command line to recursive invocations of make.  Note that
-#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
-#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
-#      OTHER_RECURSIVE_VARIABLES. 
-
-# Additional headers to export beyond those in the PB.project:
-#    OTHER_PUBLIC_HEADERS
-#    OTHER_PROJECT_HEADERS
-#    OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/kextd.tproj/PB.project b/kextd.tproj/PB.project
deleted file mode 100644 (file)
index dd503bf..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (CoreFoundation.framework, IOKit.framework); 
-        FRAMEWORKSEARCH = (); 
-        H_FILES = (GetSymbolFromPEF.h, KEXTD.h, PTLock.h); 
-        OTHER_LINKED = (KEXTD.c, KEXTD_main.c, PEFSupport.c, PTLock.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile); 
-        SUBPROJECTS = (); 
-    }; 
-    LANGUAGE = English; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
-    NEXTSTEP_COMPILEROPTIONS = "-fpascal-strings -Wno-four-char-constants"; 
-    NEXTSTEP_INSTALLDIR = /usr/libexec; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_INSTALLDIR = /bin; 
-    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = kextd; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_INSTALLDIR = /Library/Executables; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/kextd.tproj/PEFSupport.c b/kextd.tproj/PEFSupport.c
deleted file mode 100644 (file)
index 567f915..0000000
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
- * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
-    File:      UnpackPiData.c
-    Written by:        Jeffrey Robbin
-    Copyright: Â© 1994, 1996 by Apple Computer, Inc., all rights reserved.
-
-    File:      GetSymbolFromPEF.c
-    Written by:        Jeffrey Robbin
-    Copyright: Â© 1994, 1996 by Apple Computer, Inc., all rights reserved.
-*/
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/kext/KEXTManager.h>
-#include <stdlib.h>
-#include <err.h>
-#include <sys/file.h>
-#include <nlist.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-#include <paths.h>
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <mach/mach_host.h>
-
-#include "GetSymbolFromPEF.h"
-
-static unsigned char
-PEFGetNextByte (unsigned char** rawBuffer, long* rawBufferRemaining)
-{
-    *rawBufferRemaining = *rawBufferRemaining - 1;
-    return *(*rawBuffer)++;
-}
-
-
-static unsigned long
-PEFGetCount(unsigned char** rawBuffer, long* rawBufferRemaining)
-{
-    register unsigned char b;
-    register unsigned long value = 0UL;
-
-    /* Scan the count value.  All required bytes MUST be present...                                        */
-
-    b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
-    if (!IS_LAST_PICNT_BYTE(b)) {                            /* if 1st byte is not that last...            */
-        value = CONCAT_PICNT(value, b);                        /*   ...init value using 1st byte            */
-
-        b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
-        if (!IS_LAST_PICNT_BYTE(b)) {                        /*      if 2nd byte is not the last...            */
-            value = CONCAT_PICNT(value, b);                    /*     ...add in 2nd byte                        */
-
-            b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
-            if (!IS_LAST_PICNT_BYTE(b)) {                    /*        if 3rd byte is not the last...         */
-                value = CONCAT_PICNT(value, b);                /*       ...add in 3rd byte                    */
-
-                b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
-                if (!IS_LAST_PICNT_BYTE(b)) {                /*           if 4th byte is not the last...    */
-                    value = CONCAT_PICNT(value, b);            /*           ...add in 4th byte                */
-
-                    /*          5th byte is definitly last!        */
-                    b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
-                }
-            }
-        }
-    }
-
-value = CONCAT_PICNT(value, b);                            /* add in "last" byte (whichever one)        */
-
-return (value);
-}
-
-
-
-// UnpackPiData expands a compressed section into memory.
-
-static OSErr
-UnpackPiData (LogicalAddress        thePEFPtr,
-                    SectionHeaderPtr    sectionHeaderPtr,
-                    LogicalAddress*        theData)
-{
-    long              cntX, cnt, rpt, dcnt, delta;
-    unsigned char    op, b;
-    unsigned char*    unpackBuffer;
-    unsigned char*    originalUnpackBuffer;
-    unsigned char*    endUnpackBuffer;
-    unsigned char*    oldRawBuffer;
-    long            oldRawBufferRemaining;
-    unsigned char*    rawBuffer;
-    long            rawBufferRemaining;
-    
-    // Verify incoming section is packed.
-    if (sectionHeaderPtr->regionKind != kPIDataSection)
-        return (paramErr);
-
-    
-    // Allocate memory to unpack into
-    originalUnpackBuffer = (unsigned char*)NewPtrSys(sectionHeaderPtr->initSize);
-    if (originalUnpackBuffer == nil)
-        return memFullErr;
-
-    unpackBuffer        = originalUnpackBuffer;
-    endUnpackBuffer     = unpackBuffer + sectionHeaderPtr->initSize;
-    rawBuffer            = (unsigned char*)((unsigned long)thePEFPtr + sectionHeaderPtr->containerOffset);
-    rawBufferRemaining    = sectionHeaderPtr->rawSize;
-
-
-    /* Expand the pidata instructions.  EOF will terminate processing through the setjmp    */
-    /* on pidData_jmpbuf above...                                                            */
-
-    while (rawBufferRemaining > 0) {
-
-        /* The first byte of each instruction contains the opcode and a count. If the count    */
-        /* is 0, the count starts in the next byte...                                        */
-
-        /* Pick up the opcode and first count operand...                                    */
-
-        b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-
-        op  = PIOP(b);
-        cnt = PICNT(b);
-
-        if (cnt == 0)
-            cnt = PEFGetCount(&rawBuffer, &rawBufferRemaining);
-
-        /* Unpack the data as a function of the opcode... */
-
-        switch (op) {
-            case kZero:                                    /* zero out cnt bytes...*/
-                if (unpackBuffer + cnt > endUnpackBuffer)
-                    goto Error;
-                memset(unpackBuffer, 0, cnt);
-                unpackBuffer += cnt;
-                break;
-
-            case kBlock:                                  /* copy cnt bytes...*/
-                if (unpackBuffer + cnt > endUnpackBuffer)
-                    goto Error;
-                while (--cnt >= 0)
-                    *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-                    break;
-
-            case kRepeat:                               /* copy cnt bytes rpt times...*/
-                rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining) + 1;
-
-                if (cnt == 1)
-                {
-                    if (unpackBuffer + rpt > endUnpackBuffer)
-                        goto Error;
-                    b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-                    memset(unpackBuffer, b, rpt);
-                    unpackBuffer += rpt;
-                }
-                    else
-                    {
-                        oldRawBufferRemaining    = rawBufferRemaining;
-                        oldRawBuffer            = rawBuffer;
-                        while (--rpt >= 0) {
-                            if (unpackBuffer + cnt > endUnpackBuffer)
-                                goto Error;
-                            rawBufferRemaining    = oldRawBufferRemaining;
-                            rawBuffer            = oldRawBuffer;
-                            cntX = cnt;
-                            while (--cntX >= 0)
-                                *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-                        }
-                    }
-                    break;
-
-            case kRepeatZero:                                                        /* copy cnt 0's and dcnt bytes rpt times*/
-                dcnt              = PEFGetCount(&rawBuffer, &rawBufferRemaining);    /* ...then copy cnt more 0's            */
-                rpt               = PEFGetCount(&rawBuffer, &rawBufferRemaining);
-
-                goto rptPart1;                                        /* jump into loop to copy 0's first...    */
-
-                while (--rpt >= 0) {
-                    if (unpackBuffer + dcnt > endUnpackBuffer)
-                        goto Error;
-                    cntX = dcnt;                                    /* cnt repeating parts follow each other*/
-                    while (--cntX >= 0)
-                        *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-rptPart1:                                                            /* non-repeating part is always 0's...    */
-                        if (unpackBuffer + cnt > endUnpackBuffer)
-                            goto Error;
-                    memset(unpackBuffer, 0, cnt);
-                    unpackBuffer += cnt;
-                }
-
-                    break;
-
-            case kRepeatBlock:                                        /* copy cnt repeating bytes and dcnt         */
-                dcnt              = PEFGetCount(&rawBuffer, &rawBufferRemaining);                    /* non-repating bytes rcnt times...            */
-                rpt               = PEFGetCount(&rawBuffer, &rawBufferRemaining);                    /* ...then copy cnt repeating bytes            */
-
-                oldRawBufferRemaining    = rawBufferRemaining;
-                oldRawBuffer            = rawBuffer;
-                delta                    = 0;                        /*  the repeating part and each non-rep    */
-
-                goto rptPart2;                                        /* jump into loop to copy rptng part 1st*/
-
-                while (--rpt >= 0) {
-                    if (unpackBuffer + dcnt > endUnpackBuffer)
-                        goto Error;
-
-                    rawBuffer            = oldRawBuffer + cnt + delta;
-                    rawBufferRemaining    = oldRawBufferRemaining - (cnt + delta);
-                    cntX = dcnt;
-                    while (--cntX >= 0)
-                        *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-                    delta += dcnt;
-rptPart2:
-                        if (unpackBuffer + cnt > endUnpackBuffer)
-                            goto Error;
-                    rawBuffer            = oldRawBuffer;
-                    rawBufferRemaining    = oldRawBufferRemaining;
-                    cntX = cnt;
-                    while (--cntX >= 0)
-                        *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
-                }
-
-                    rawBuffer            = oldRawBuffer + cnt + delta;
-                rawBufferRemaining    = oldRawBufferRemaining - (cnt + delta);
-                break;
-
-            default:
-                goto Error;
-        } /* switch */
-    } /* for */
-    
-    *theData = originalUnpackBuffer;
-        
-    return noErr;
-
-Error:
-    if (unpackBuffer)
-        DisposePtr((Ptr)originalUnpackBuffer);
-    
-    *theData = nil;
-
-    return paramErr;
-}
-
-// GetSymbolFromPEF will extract from a PEF container the data associated
-// with a given symbol name.  It requires that the PEF file have been previously
-// loaded into memory.
-
-static OSStatus
-GetSymbolFromPEF( StringPtr      theSymbolName,
-                    const LogicalAddress thePEFPtr,
-                    LogicalAddress theSymbolPtr,
-                    ByteCount      theSymbolSize )
-{
-    ContainerHeaderPtr         containerHeaderPtr;    // Pointer to the Container Header
-    SectionHeaderPtr           loaderSectionPtr;    // Pointer to the Loader Section Header
-    SectionHeaderPtr           exportSectionPtr;    // Pointer to the Section Header with the symbol
-    short                      currentSection;
-    Boolean                    foundSection;
-    Boolean                    foundSymbol;
-    long                        numExportSymbols;
-    LoaderHeaderPtr            loaderHeaderPtr;
-    ExportSymbolEntryPtr        exportSymbolEntryPtr;
-    LoaderExportChainEntryPtr  exportChainEntryPtr;
-    StringPtr                  exportSymbolName;
-    LogicalAddress             expandedDataPtr;
-    unsigned char*             sourceDataPtr;
-    unsigned char*             destDataPtr;
-
-
-    containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr;
-    
-    // Does the magic cookie match?
-    if (containerHeaderPtr->magicCookie != 'Joy!')
-        return cfragFragmentFormatErr;
-    
-    // Is this a known PEF container format?
-    if (containerHeaderPtr->containerID != 'peff')
-        return cfragFragmentFormatErr;
-    
-    // Validate parameters
-    if (theSymbolPtr == nil)
-        return paramErr;
-
-    
-    // Find the loader section.
-    foundSection = false;
-    for (currentSection = 0; currentSection < containerHeaderPtr->nbrOfSections; currentSection++)
-    {
-        loaderSectionPtr = (SectionHeaderPtr)(    (unsigned long)containerHeaderPtr +
-                                               sizeof(ContainerHeader) +
-                                               (sizeof(SectionHeader) * currentSection));
-        if (loaderSectionPtr->regionKind == kLoaderSection)
-        {
-            foundSection = true;
-            break;
-        }
-    }
-
-    if (foundSection == false)
-        return cfragNoSectionErr;
-    
-    // Get the number of export symbols.
-    loaderHeaderPtr        = (LoaderHeaderPtr)((unsigned long)thePEFPtr + loaderSectionPtr->containerOffset);
-    numExportSymbols    = loaderHeaderPtr->nbrExportSyms;
-    
-    // Start at the first exported symbol.
-    exportSymbolEntryPtr = (ExportSymbolEntryPtr)(    (unsigned long)loaderHeaderPtr +
-                                                   loaderHeaderPtr->slotTblOffset +
-                                                   (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)) +
-                                                   (sizeof(LoaderExportChainEntry) * numExportSymbols));
-
-    exportChainEntryPtr = (LoaderExportChainEntryPtr)(    (unsigned long)loaderHeaderPtr +
-                                                       loaderHeaderPtr->slotTblOffset +
-                                                       (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)));
-
-    foundSymbol = false;
-    while (numExportSymbols-- > 0)
-    {
-        exportSymbolName = (StringPtr)(    (unsigned long)loaderHeaderPtr +
-                                        loaderHeaderPtr->strTblOffset +
-                                        (exportSymbolEntryPtr->class_and_name & 0x00FFFFFF));
-        if (SymbolCompare(theSymbolName, exportSymbolName, exportChainEntryPtr->_h._h_h._nameLength))
-        {
-            foundSymbol = true;
-            break;
-        }
-        exportSymbolEntryPtr = (ExportSymbolEntryPtr)(((int)exportSymbolEntryPtr) + 10);
-        exportChainEntryPtr++;
-    }
-
-    if (foundSymbol == false)
-        return cfragNoSymbolErr;
-
-    
-    // Found the symbol, so... let's go get the data!
-
-    exportSectionPtr = (SectionHeaderPtr)(    (unsigned long)containerHeaderPtr +
-                                           sizeof(ContainerHeader) +
-                                           (sizeof(SectionHeader) * exportSymbolEntryPtr->sectionNumber));
-
-    expandedDataPtr = nil;
-
-    switch (exportSectionPtr -> regionKind)
-    {
-        case kPIDataSection:
-            
-            // Expand the data!  (Not yet... :)
-
-            if (UnpackPiData (thePEFPtr, exportSectionPtr, &expandedDataPtr) != noErr)
-                return cfragFragmentCorruptErr;
-
-            sourceDataPtr = (unsigned char*)((unsigned long)expandedDataPtr +
-                                             exportSymbolEntryPtr->address);
-            break;
-
-        default:
-            sourceDataPtr = (unsigned char*)((unsigned long)thePEFPtr +
-                                             exportSectionPtr->containerOffset +
-                                             exportSymbolEntryPtr->address);
-            break;
-    }
-
-    
-    // Copy the data!
-
-    destDataPtr = (unsigned char*)theSymbolPtr;
-
-
-    while (theSymbolSize-- > 0)
-        *destDataPtr++ = *sourceDataPtr++;
-
-    
-    // Cleanup any expanded data
-
-    if (expandedDataPtr != nil)
-        DisposePtr((Ptr)expandedDataPtr);
-
-    return noErr;
-}
-
-
-static IOByteCount GetPEFLen ( LogicalAddress thePEFPtr)
-{
-    ContainerHeaderPtr         containerHeaderPtr;    // Pointer to the Container Header
-    SectionHeaderPtr           sections;
-    short                      currentSection;
-    long                       lastOffset = 0;
-    long                       len = 0;
-
-    containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr;
-    
-    // Does the magic cookie match?
-    if (containerHeaderPtr->magicCookie != 'Joy!')
-        return 0;
-    
-    // Is this a known PEF container format?
-    if (containerHeaderPtr->containerID != 'peff')
-        return 0;
-    
-    // Find the loader section.
-    sections = (SectionHeaderPtr) (containerHeaderPtr + 1);
-    for (currentSection = 0; currentSection < containerHeaderPtr->nbrOfSections; currentSection++)
-    {
-       if( sections[currentSection].containerOffset > lastOffset) {
-           lastOffset  = sections[currentSection].containerOffset;
-           len         = sections[currentSection].rawSize;
-       }
-    }
-
-    return( lastOffset + len );
-}
-
-//
-// SymbolCompare
-//
-// theExportSymbol is NOT null-terminated, so use theExportSymbolLength.
-//
-static Boolean SymbolCompare ( StringPtr       theLookedForSymbol,
-                                StringPtr      theExportSymbol,
-                                unsigned long  theExportSymbolLength)
-{
-    unsigned char*     p1 = (unsigned char*)theLookedForSymbol;
-    unsigned char*     p2 = (unsigned char*)theExportSymbol;
-    
-       // Same length?
-       // (skip over p string len byte)
-    if ( theExportSymbolLength != *p1++ )
-        return false;
-
-    while ( theExportSymbolLength-- != 0 )
-    {
-        if ( *p1++ != *p2++ )
-            return false;
-    }
-
-    return true;
-}
-
-static int
-readFile(char *path, char **objAddr, long *objSize)
-{
-    int fd;
-    int err;
-    struct stat stat_buf;
-
-    *objAddr = 0;
-    *objSize = 0;
-
-    if((fd = open(path, O_RDONLY)) == -1)
-       return errno;
-
-    do {
-       if(fstat(fd, &stat_buf) == -1) {
-           err = errno;
-           continue;
-       }
-       *objSize = stat_buf.st_size;
-
-       if( KERN_SUCCESS != map_fd(fd, 0, (vm_offset_t *) objAddr, TRUE, *objSize)) {
-            *objAddr = 0;
-            *objSize = 0;
-           err = errno;
-           continue;
-       }
-
-       err = 0;
-
-    } while( false );
-
-    close(fd);
-
-    return( err );
-}
-
-
-// The Driver Description
-enum {
-  kInitialDriverDescriptor     = 0,
-  kVersionOneDriverDescriptor  = 1,
-  kTheDescriptionSignature     = 'mtej',
-};
-
-struct DriverType {
-  unsigned char nameInfoStr[32]; // Driver Name/Info String
-  unsigned long        version;         // Driver Version Number - really NumVersion
-};
-typedef struct DriverType DriverType;
-
-struct DriverDescription {
-  unsigned long driverDescSignature; // Signature field of this structure
-  unsigned long driverDescVersion;   // Version of this data structure
-  DriverType    driverType;          // Type of Driver
-  char          otherStuff[512];
-};
-typedef struct DriverDescription DriverDescription;
-
-static void
-ExaminePEF( mach_port_t masterPort, char *pef, IOByteCount pefLen, CFArrayRef okList )
-{
-    char              descripName[] = "\pTheDriverDescription";
-    long              err;
-    DriverDescription descrip;
-    DriverDescription curDesc;
-    char              matchName[40];
-    char              okName[40];
-    unsigned long     newVersion;
-    unsigned long     curVersion;
-    IOReturn         kr;
-    io_iterator_t     iter;
-    io_service_t      service;
-    io_service_t      child;
-    io_string_t              path;
-    CFStringRef              ndrvPropName = CFSTR("driver,AAPL,MacOS,PowerPC");
-    CFDataRef        ndrv;
-    CFMutableDictionaryRef dict;
-    CFIndex          index;
-    CFStringRef              okStr;
-    Boolean          ok;
-
-    err = GetSymbolFromPEF(descripName, pef, &descrip, sizeof(descrip));
-    if(err != 0) {
-        printf("\nGetSymbolFromPEF returns %ld\n",err);
-        return;
-    }
-    if((descrip.driverDescSignature != kTheDescriptionSignature) ||
-        (descrip.driverDescVersion != kInitialDriverDescriptor))
-        return;
-
-    strncpy(matchName, descrip.driverType.nameInfoStr + 1,
-            descrip.driverType.nameInfoStr[0]);
-    matchName[ descrip.driverType.nameInfoStr[0] ] = 0;
-    
-    ok = (!okList);
-    for( index = 0; (!ok) && (index < CFArrayGetCount(okList)); index++) {
-        okStr = CFArrayGetValueAtIndex( okList, index);
-        if( CFStringGetTypeID() != CFGetTypeID(okStr))
-            continue;
-        ok = CFStringGetCString( okStr, okName, sizeof(okName),
-                                kCFStringEncodingMacRoman)
-            && (0 == strcmp( okName, matchName));
-    }
-
-    newVersion = descrip.driverType.version;
-    if((newVersion & 0xffff) == 0x8000)  // final stage, release rev
-        newVersion |= 0xff;
-
-    IOMasterPort(mach_task_self(), &masterPort);
-
-    kr = IOServiceGetMatchingServices(masterPort,
-                                       IOServiceNameMatching(matchName),
-                                       &iter);
-    if( kIOReturnSuccess != kr)
-       return;
-    
-    for(
-      ;
-      (service = IOIteratorNext(iter));
-      IOObjectRelease(service)) {
-
-       kr = IORegistryEntryGetPath( service, kIOServicePlane, path );
-        if( kIOReturnSuccess == kr)
-            printf("Name %s matches %s, ", matchName, path);
-        if( !ok) {
-            printf("(skipping)\n");
-            continue;
-        }
-
-       ndrv = (CFDataRef) IORegistryEntryCreateCFProperty( service, ndrvPropName,
-                                               kCFAllocatorDefault, kNilOptions );
-
-       if( ndrv) {
-            err = GetSymbolFromPEF( descripName, CFDataGetBytePtr(ndrv),
-                                   &curDesc, sizeof(curDesc));
-            if (err != noErr)
-                printf("GetSymbolFromPEF returns %ld\n",err);
-            else {
-                if((curDesc.driverDescSignature == kTheDescriptionSignature) &&
-                   (curDesc.driverDescVersion == kInitialDriverDescriptor)) {
-
-                    curVersion = curDesc.driverType.version;
-                    printf("new version %08lx, current version %08lx\n", newVersion, curVersion);
-                    if((curVersion & 0xffff) == 0x8000) // final stage, release rev
-                        curVersion |= 0xff;
-
-                    if( newVersion <= curVersion)
-                        pefLen = 0;
-                }
-           }
-           CFRelease(ndrv);
-        }
-
-        if( pefLen == 0)
-           continue;
-
-       ndrv = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
-                                          pef, pefLen, kCFAllocatorNull);
-        if( ndrv == 0)
-           continue;
-        printf("Installing ndrv (");
-        dict = CFDictionaryCreateMutable( kCFAllocatorDefault, 0,
-                    &kCFTypeDictionaryKeyCallBacks,
-                    &kCFTypeDictionaryValueCallBacks);
-
-       if( dict) {
-            CFDictionarySetValue(dict, ndrvPropName, ndrv);
-           kr = IORegistryEntryGetChildEntry( service, kIOServicePlane, &child );
-           if( kr == kIOReturnSuccess) {
-                kr = IORegistryEntrySetCFProperties( child, dict );
-               IOObjectRelease( child );
-           }
-            CFRelease( dict);
-       } else
-           kr = kIOReturnNoMemory;
-
-       CFRelease(ndrv);
-        printf("%08x)\n", kr);
-    }
-    IOObjectRelease( iter );
-
-    return;
-}
-
-int
-PEFExamineFile( mach_port_t masterPort, CFURLRef file )
-{
-    char *             pefBytes;
-    char *             plistBytes;
-    char *             pef;
-    long               pefFileLen, plistLen;
-    IOByteCount                pefLen, pos = 0;
-    int                        err;
-    CFDictionaryRef    props = 0;
-    CFDataRef          data = 0;
-    CFArrayRef         okList = 0;
-    enum               { kIOCFMaxPathSize = 1026 };
-    char               cFile[kIOCFMaxPathSize];
-
-    if (CFURLGetFileSystemRepresentation(file, TRUE, cFile, kIOCFMaxPathSize))
-        err = readFile(cFile, &pefBytes, &pefFileLen);
-    else
-        err = kIOReturnIOError;
-    if( err)
-       return( err);
-
-    do {
-        strcat( cFile, ".plist");
-        err = readFile(cFile, &plistBytes, &plistLen);
-        if( err)
-            continue;
-
-        data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault,
-                    plistBytes, plistLen, kCFAllocatorNull);
-        if( !data)
-            continue;
-        props = (CFDictionaryRef) CFPropertyListCreateFromXMLData(
-                            kCFAllocatorDefault, data, kCFPropertyListImmutable, 0 );
-        if( !props)
-            continue;
-        if( CFDictionaryGetTypeID() != CFGetTypeID(props))
-            continue;
-
-        okList = CFDictionaryGetValue( props, CFSTR("IONDRVList") );
-        if( CFArrayGetTypeID() != CFGetTypeID(okList))
-            okList = 0;
-
-    } while( false );
-
-    pef = pefBytes;
-    while( (pos < pefFileLen) && (pefLen = GetPEFLen( pef ))) {
-       ExaminePEF( masterPort, pef, pefLen, okList );
-       pefLen = (pefLen + 15) & ~15;
-       pef += pefLen;
-       pos += pefLen;
-    }
-
-    if( data)
-        CFRelease(data);
-    if( props)
-        CFRelease(props);
-
-    if( plistBytes)
-        vm_deallocate( mach_task_self(), (vm_address_t) plistBytes, plistLen );
-    if( pefBytes)
-        vm_deallocate( mach_task_self(), (vm_address_t) pefBytes, pefFileLen );
-
-    return( 0 );
-}
-
-
-
diff --git a/kextd.tproj/PTLock.c b/kextd.tproj/PTLock.c
deleted file mode 100644 (file)
index 92316a5..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-
-#include <PTLock.h>
-#include <stdlib.h>
-#include <mach/message.h>
-
-#define mutex_t                pthread_mutex_t
-#define condition_t            pthread_cond_t
-
-#define mutex_init(m)          pthread_mutex_init(m, NULL)
-#define mutex_free(m)          pthread_mutex_destroy(m)
-#define mutex_lock(m)          pthread_mutex_lock(m)
-#define mutex_unlock(m)        pthread_mutex_unlock(m)
-
-#define condition_init(c)      pthread_cond_init(c, NULL)
-#define condition_free(c)      pthread_cond_destroy(c)
-#define condition_wait(c, m)   pthread_cond_wait(c, m)
-#define condition_signal(c)    pthread_cond_signal(c)
-#define condition_broadcast(c) pthread_cond_broadcast(c)
-
-
-typedef struct _PTLock {
-    Boolean locked;
-    pthread_mutex_t m;
-    pthread_cond_t c;
-} PTLock;
-
-
-PTLockRef
-PTLockCreate(void)
-{
-    PTLock * l;
-
-    l = (PTLock *)malloc(sizeof(PTLock));
-    if ( !l )
-        return NULL;
-
-    l->locked = false;
-    mutex_init(&l->m);
-    condition_init(&l->c);
-
-    return (PTLockRef)l;
-}
-
-void
-PTLockFree(PTLockRef lock)
-{
-    PTLock * l = (PTLock *)lock;
-    
-    if ( !lock )
-        return;
-
-    mutex_free(&l->m);
-    condition_free(&l->c);
-    free(lock);
-}
-
-void
-PTLockTakeLock(PTLockRef lock)
-{
-    PTLock * l = (PTLock *)lock;
-
-    mutex_lock(&l->m);
-    while ( l->locked )
-        condition_wait(&l->c, &l->m);
-    l->locked = true;
-    mutex_unlock(&l->m);
-}
-
-void
-PTLockUnlock(PTLockRef lock)
-{
-    PTLock * l = (PTLock *)lock;
-
-    mutex_lock(&l->m);
-    l->locked = false;
-    condition_signal(&l->c);
-    mutex_unlock(&l->m);
-}
-
-Boolean
-PTLockTryLock(PTLockRef lock)
-{
-    PTLock * l = (PTLock *)lock;
-
-    Boolean ret;
-
-    mutex_lock(&l->m);
-    ret = !l->locked;
-    if ( ret )
-        l->locked = true;
-    mutex_unlock(&l->m);
-
-    return ret;
-}
-
diff --git a/kextd.tproj/PTLock.h b/kextd.tproj/PTLock.h
deleted file mode 100644 (file)
index 3f18ae5..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#ifndef _PTLOCK_H_
-#define _PTLOCK_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-    
-#include <CoreFoundation/CFBase.h>
-#include <pthread.h>
-
-typedef struct __PTLock * PTLockRef;
-
-PTLockRef      PTLockCreate(void);
-void           PTLockFree(PTLockRef lock);
-
-Boolean                PTLockTryLock(PTLockRef lock);
-void           PTLockTakeLock(PTLockRef lock);
-void           PTLockUnlock(PTLockRef lock);
-
-#ifdef __cplusplus
-}
-#endif
-#endif _PTLOCK_H_
-
diff --git a/kextload.tproj/Makefile b/kextload.tproj/Makefile
deleted file mode 100644 (file)
index d09afc4..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Generated by the Apple Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = kextload
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = kextload_main.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kextload.8
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-FRAMEWORKS = -framework CoreFoundation -framework IOKit
-
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/kextload.tproj/Makefile.postamble b/kextload.tproj/Makefile.postamble
deleted file mode 100644 (file)
index b3bd25c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-MAN_PAGE = kextload.8
-MAN_PATH = /usr/share/man/man8
-
-after_install::
-       -mkdir -p ${DSTROOT}$(MAN_PATH)
-       -rm -f ${DSTROOT}$(MAN_PATH)/$(MAN_PAGE)
-       cp $(MAN_PAGE) ${DSTROOT}$(MAN_PATH)/$(MAN_PAGE)
-       chmod og-w ${DSTROOT}$(MAN_PATH)/$(MAN_PAGE)
-
diff --git a/kextload.tproj/Makefile.preamble b/kextload.tproj/Makefile.preamble
deleted file mode 100644 (file)
index c1624b4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-###############################################################################
-#  Makefile.preamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile for configuring the standard application makefiles 
-#  associated with ProjectBuilder. It is included before the main makefile.
-#  In Makefile.preamble you set attributes for a project, so they are available
-#  to the project's makefiles.  In contrast, you typically write additional rules or 
-#  override built-in behavior in the Makefile.postamble.
-#  
-#  Each directory in a project tree (main project plus subprojects) should 
-#  have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible.  To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
-#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
-#      flags in OTHER_MFLAGS, etc.
-#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
-#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
-#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
-#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
-#      precompiling header files
-#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
-#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
-#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
-#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
-#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every 
-# stage of the make:
-#
-#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
-#    AFTER_PREBUILD: targets to build after installing headers for a subproject
-#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
-#    BEFORE_BUILD: targets to make before a build, but after subprojects
-#    AFTER_BUILD: targets to make after a build
-#
-#    BEFORE_INSTALL: targets to build before installing the product
-#    AFTER_INSTALL: targets to build after installing the product
-#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
-#         subproject
-#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-#    BEFORE_DEPEND: targets to build before building dependencies for a
-#        subproject
-#    AFTER_DEPEND: targets to build after building dependencies for a
-#        subproject
-#
-#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-#        updated every time the project is built.  If NO, the dependency
-#        file is only built when the depend target is invoked.
-
-# Framework-related variables:
-#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the framework's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-#    PUBLIC_HEADER_DIR:  Determines where public exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.  For library projects you should
-#       set this to something like /Developer/Headers/$(NAME).  Do not set
-#       this variable for framework projects unless you do not want the
-#       header files included in the framework.
-#    PRIVATE_HEADER_DIR:  Determines where private exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.
-#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
-#      whether the libraries produced are statically linked when they
-#      are used or if they are dynamically loadable. This defaults to
-#       DYNAMIC.
-#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the library's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-#
-#    INSTALL_AS_USER: owner of the intalled products (default root)
-#    INSTALL_AS_GROUP: group of the installed products (default wheel)
-#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-#      passed on the command line to recursive invocations of make.  Note that
-#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
-#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
-#      OTHER_RECURSIVE_VARIABLES. 
-
-# Additional headers to export beyond those in the PB.project:
-#    OTHER_PUBLIC_HEADERS
-#    OTHER_PROJECT_HEADERS
-#    OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/kextload.tproj/PB.project b/kextload.tproj/PB.project
deleted file mode 100644 (file)
index d23d6b3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (CoreFoundation.framework, IOKit.framework); 
-        OTHER_LINKED = (kextload_main.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kextload.8); 
-        SUBPROJECTS = (); 
-    }; 
-    LANGUAGE = English; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
-    NEXTSTEP_INSTALLDIR = /sbin; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_INSTALLDIR = /bin; 
-    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = kextload; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_INSTALLDIR = /Library/Executables; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/kextload.tproj/kextload.8 b/kextload.tproj/kextload.8
deleted file mode 100644 (file)
index e2d34c7..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-.\"
-.\" Copyright (c) 1997 Doug Rabson
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    $Id: kextload.8,v 1.5 2001/01/19 22:51:09 lindak Exp $
-.\"
-.Dd October 11, 1999
-.Dt kextload 8
-.Os FreeBSD
-.Sh NAME
-.Nm kextload
-.Nd loads and starts a kernel extension
-.Sh SYNOPSIS
-.Nm kextload
-.Op Fl i
-.Op Fl v
-.Op Fl h
-.Op Fl x
-.Ar kextbundle
-.Sh DESCRIPTION
-The
-.Nm
-utility loads the module files contained within 
-.Ar kextbundle
-into the kernel and starts their execution either by calling a predefined initialization routine or by passing a personality description to the kernel.  All module dependencies for 
-.Ar kextbundle 
-must reside in /System/Library/Extensions.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl v
-Be more verbose.
-.It Fl v
-Simulate safe boot (for testing).
-.It Fl i
-Set interactive mode.
-.It Fl h
-Provide quick help.
-.El
-.Sh FILES
-.Bl -tag -width /modules -compact
-.It Pa /TBD
-directory (bundle) containing loadable kernel modules.
-.Sh DIAGNOSTICS
-The
-.Nm
-utility exits with a status of 0 on success or with a nonzero status if an error occurs.
-.Sh SEE ALSO
-.Xr kmodload 8 ,
-.Xr kmodstat 8 ,
-.Xr kmodsyms 8 ,
-.Xr kmodunload 8
diff --git a/kextload.tproj/kextload_main.c b/kextload.tproj/kextload_main.c
deleted file mode 100644 (file)
index 6624995..0000000
+++ /dev/null
@@ -1,629 +0,0 @@
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sysexits.h>
-#include <sys/wait.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOKitServer.h>
-#include <IOKit/IOCFSerialize.h>
-#include <mach/mach_types.h>
-
-#include <IOKit/kext/KEXTManager.h>
-
-static Boolean sSafeBoot = false;
-static Boolean sVerbose = false;
-static Boolean sInteractive = false;
-static Boolean sAuthenticateAll = false;
-
-static KEXTManagerRef manager = NULL;
-static const char * sCmdName;
-
-#define kBundleIDKey        "CFBundleIdentifier"
-#define kPersonalityNameKey "IOPersonalityName"
-
-#if 0
-// no longer (or never was!) used
-#define kModuleKey         "Module"
-#define kModulesKey        "Modules"
-#define kModuleFileKey     "File"
-#define kPersonalityKey           "Personality"
-#define kPersonalitiesKey  "Personalities"
-#define kNameKey           "Name"
-#define kVendorKey         "Vendor"
-#define kVersionKey        "Version"
-#define kRequiresKey       "Requires"
-#define kModuleAliasesKey  "Aliases"
-#endif 0
-
-#define kDefaultSearchPath "/System/Library/Extensions"
-
-// these don't seem to be used
-#if 0
-#define kInfoMacOS         "Info-macos"
-#define kInfoMacOSType     "xml"
-#endif 0
-
-static void usage(Boolean help)
-{
-    fprintf(stderr, "Usage: %s [-eihvx] [[-L dir] ...] [-p personality] kextpath\n", sCmdName);
-    if ( help ) {
-        fprintf(stderr, "\t-e   Don't scan System extensions.\n");
-        fprintf(stderr, "\t-h   Help (this menu).\n");
-        fprintf(stderr, "\t-i   Interactive mode.\n");
-        fprintf(stderr, "\t-L   Search Library dir.\n");
-        fprintf(stderr, "\t-p   Personality to load.\n");
-        fprintf(stderr, "\t-v   Verbose mode.\n");
-        fprintf(stderr, "\t-x   Run in safe boot mode.\n");
-    }
-    exit(EX_USAGE);
-}
-
-static void printError(const char * string)
-{
-    fprintf(stderr, string);
-    return;
-}
-
-static void printMessage(const char * string)
-{
-    if (sVerbose) {
-        fprintf(stdout, string);
-    }
-    return;
-}
-
-static Boolean Prompt(CFStringRef message, Boolean defaultValue)
-{
-    Boolean ret;
-    CFIndex len;
-    char * buf;
-    char * dp;
-    char c;
-    char dv;
-
-    ret = false;
-    len = CFStringGetLength(message) + 1;
-    buf = (char *)malloc(sizeof(char) * len);
-    if ( !CFStringGetCString(message, buf, len, kCFStringEncodingASCII) ) {
-        free(buf);
-        return false;
-    }
-    
-    dv = defaultValue?'y':'n';
-    dp = defaultValue?" [Y/n]":" [y/N]";
-    
-    while ( 1 ) {
-        printf(buf);
-        printf(dp);
-        printf("? ");
-        fflush(stdout);
-        fscanf(stdin, "%c", &c);
-        if ( c != 10 ) while ( fgetc(stdin) != 10 );
-        if ( (c == 10) || (tolower(c) == dv) ) {
-            ret = defaultValue;
-            break;
-        }
-        else if ( tolower(c) == 'y' ) {
-            ret = true;
-            break;
-        }
-        else if ( tolower(c) == 'n' ) {
-            ret = false;
-            break;
-        }
-    }
-    free(buf);
-
-    return ret;
-}
-
-static CFURLRef
-URLCreateAbsoluteWithPath(CFStringRef path)
-{
-    CFURLRef url, base;
-
-    url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
-                                        path, kCFURLPOSIXPathStyle, true);
-    base = CFURLCopyAbsoluteURL(url); CFRelease(url);
-    path = CFURLGetString(base);
-    
-    url = CFURLCreateWithString(kCFAllocatorDefault, path, NULL);
-    CFRelease(base);
-
-    return url;
-}
-
-// Override the default authentication scheme so we can load
-// kext not owned by root into the kernel.
-static KEXTReturn authenticate(CFURLRef url, void * context)
-{
-    if ( !sAuthenticateAll ) {
-        KEXTReturn ret;
-        
-        ret = KEXTManagerAuthenticateURL(url);
-        if ( ret != kKEXTReturnSuccess ) {
-            if ( sVerbose ) {
-                CFURLRef absUrl;
-                CFStringRef message;
-                CFStringRef path;
-
-                absUrl = CFURLCopyAbsoluteURL(url);
-                path = CFURLGetString(absUrl);
-
-                message = CFStringCreateWithFormat(
-                                            kCFAllocatorDefault,
-                                            NULL,
-                                            CFSTR("Error (%d) Authentication failed: %@"),
-                                            ret,
-                                            path);
-
-                CFShow(message);
-                CFRelease(message);
-                CFRelease(absUrl);
-            }
-            return ret;
-        }
-    }
-
-    return kKEXTReturnSuccess;
-}
-
-// Print out a message when a module is about to load.
-static Boolean mWillLoad(KEXTManagerRef manager, KEXTModuleRef module, void * context)
-{
-    CFStringRef name;
-    CFStringRef message;
-
-    if ( !sVerbose ) {
-        return true;
-    }
-    
-    name = (CFStringRef)KEXTModuleGetProperty(module, CFSTR(kBundleIDKey));
-    message = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Loading module: %@."), name);
-    CFShow(message);
-    CFRelease(message);
-    
-    return true;
-}
-
-// Print out a message when the module was successfully loaded.
-static void mWasLoaded(KEXTManagerRef manager, KEXTModuleRef module, void * context)
-{
-    CFStringRef name;
-    CFStringRef message;
-
-    if ( !sVerbose ) {
-        return;
-    }
-
-    name = (CFStringRef)KEXTModuleGetProperty(module, CFSTR(kBundleIDKey));
-    message = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Loaded module: %@."), name);
-    CFShow(message);
-    CFRelease(message);
-}
-
-// Print an error message if there was an error loading the module.
-static KEXTReturn mLoadError(KEXTManagerRef manager, KEXTModuleRef module, KEXTReturn error, void * context)
-{
-    CFStringRef name;
-    CFStringRef message;
-
-    name = (CFStringRef)KEXTModuleGetProperty(module, CFSTR(kBundleIDKey));
-    switch ( error ) {
-        case kKEXTReturnModuleAlreadyLoaded:
-
-           /* If the module was already loaded, that isn't an error
-            * as far as kextload is concerned.
-            */
-            error = kKEXTReturnSuccess;
-
-            if ( sVerbose ) {
-                    message = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-                        CFSTR("Module '%@' is already loaded; continuing."), name);
-                    CFShow(message);
-                    CFRelease(message);
-            }
-            break;
-
-        default:
-            if ( sVerbose ) {
-                message = CFStringCreateWithFormat(kCFAllocatorDefault, NULL,
-                    CFSTR("Error loading module '%@'"), name);
-                KEXTError(error, message);
-                CFRelease(message);
-            }
-            break;
-    }
-
-    return error;
-}
-
-// Initialize the KEXTManager.
-static Boolean InitManager(CFArrayRef libList)
-{
-    CFStringRef scanpath;
-    int i, count;
-    CFURLRef url;
-    KEXTReturn error;
-    KEXTManagerBundleLoadingCallbacks bCallback = {
-        0, authenticate, NULL, NULL, NULL, NULL, NULL,
-    };
-    KEXTManagerModuleLoadingCallbacks mCallbacks = {
-        0, mWillLoad, mWasLoaded, mLoadError, NULL, NULL,
-    };
-
-    // Create the manager database.
-    manager = KEXTManagerCreate(&bCallback, &mCallbacks, NULL, NULL, NULL, &printError, &printMessage, sSafeBoot, &error);
-    if ( !manager ) {
-        fprintf(stderr, "Manager not created.\n");
-        return false;
-    }
-
-    for (i = 0, count = CFArrayGetCount(libList); i < count; i++) {
-        scanpath = CFArrayGetValueAtIndex(libList, i);
-        url = URLCreateAbsoluteWithPath(scanpath);
-        // Now scan in all the bundles in the extensions directory.
-        error = KEXTManagerScanPath(manager, url);
-        CFRelease(url);
-        if (error != kKEXTReturnSuccess) {
-            if (sVerbose) {
-                CFStringRef errMsg = CFStringCreateWithFormat(
-                                        kCFAllocatorDefault,
-                                        NULL,
-                                        CFSTR("Error scanning path - %@"),
-                                        scanpath);
-                KEXTError(error, errMsg);
-            }
-        };
-    }
-
-    return true;
-}
-
-static void PromptForLoading(void * val, void * context)
-{
-    KEXTPersonalityRef person;
-    CFMutableArrayRef toLoad;
-    Boolean boolval;
-
-    person = val;
-    toLoad = context;
-
-    boolval = true;
-    if ( sInteractive ) {
-        CFStringRef name;
-
-        name = KEXTPersonalityGetProperty(person, CFSTR(kBundleIDKey));
-        if ( name ) {
-            CFStringRef message;
-            
-            message = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Load personality '%@'"), name);
-            boolval = Prompt(message, true);
-            CFRelease(message);
-        }
-    }
-
-    if ( boolval ) {
-        CFArrayAppendValue(toLoad, person);
-    }
-}
-
-static void ArrayGetModuleList(void * val, void * context[])
-{
-    KEXTPersonalityRef person;
-    KEXTModuleRef module;
-    KEXTReturn error;
-    CFMutableArrayRef modules;
-    CFStringRef name;
-    CFStringRef modName;
-    CFStringRef message;
-
-    person = val;
-    modules = context[0];
-    error = *(KEXTReturn *)context[1];
-
-    if ( error != kKEXTReturnSuccess ) {
-        return;
-    }
-
-    // Once we have the personality entity, we can
-    // attempt to load it into the kernel...
-    modName = KEXTPersonalityGetProperty(person, CFSTR(kBundleIDKey));
-    if ( !modName ) {
-        name = KEXTPersonalityGetProperty(person, CFSTR(kBundleIDKey));
-        message = CFStringCreateWithFormat(kCFAllocatorDefault,
-                                            NULL,
-                                            CFSTR("Error: '%@' has no Module key."),
-                                            name);
-        CFShow(message);
-        CFRelease(message);
-
-        if ( sInteractive ) {
-            if ( !Prompt(CFSTR("Continue"), true) ) {
-                *(KEXTReturn *)(context[1]) = error;
-                return;
-            }
-        }
-        return;
-    }
-
-    module = KEXTManagerGetModule(manager, modName);
-    if ( module ) {
-        CFRange range;
-
-        range = CFRangeMake(0, CFArrayGetCount(modules));
-        if ( !CFArrayContainsValue(modules, range, module) ) {
-            CFArrayAppendValue(modules, module);
-        }
-    }
-}
-
-static void ArrayLoadMods(void * val, void * context)
-{
-    KEXTModuleRef mod;
-    KEXTReturn error;
-    Boolean boolval;
-
-    error = *(KEXTReturn *)context;
-    if ( error != kKEXTReturnSuccess ) {
-        return;
-    }
-
-    mod = val;
-    
-    boolval = true;
-    if ( sInteractive ) {
-        CFStringRef name;
-
-        name = KEXTModuleGetProperty(mod, CFSTR(kBundleIDKey));
-        if ( name ) {
-            CFStringRef message;
-
-            message = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("Load module '%@'"), name);
-            boolval = Prompt(message, true);
-            CFRelease(message);
-        }
-    }
-
-    if ( boolval ) {
-        error = KEXTManagerLoadModule(manager, mod);
-        if ( error != kKEXTReturnSuccess ) {
-            KEXTError(error, CFSTR("Error loading module"));
-            *(KEXTReturn *)context = error;
-        }
-    }
-}
-
-static KEXTReturn LoadAllModules(KEXTBundleRef bundle)
-{
-    CFArrayRef modules;
-    CFRange range;
-    KEXTReturn error;
-
-    if ( !bundle ) {
-        return kKEXTReturnBadArgument;
-    }
-    
-    modules = KEXTManagerCopyModulesForBundle(manager, bundle);
-    if ( !modules ) {
-        return kKEXTReturnModuleNotFound;
-    }
-
-    error = kKEXTReturnSuccess;
-    range = CFRangeMake(0, CFArrayGetCount(modules));
-    CFArrayApplyFunction(modules, range, (CFArrayApplierFunction)ArrayLoadMods, &error);
-
-    CFRelease(modules);
-
-    return error;
-}
-
-static KEXTReturn LoadAllPersonalities(KEXTBundleRef bundle)
-{
-    CFArrayRef array;
-    CFArrayRef configs;
-    CFMutableArrayRef toLoad;
-    CFMutableArrayRef modules;
-    CFRange range;
-    KEXTReturn error;
-    void * context[2];
-
-    error = kKEXTReturnSuccess;
-
-    // Get the configurations associated with this bundle.
-    configs = KEXTManagerCopyConfigsForBundle(manager, bundle);
-
-    // Get the personality entities associated with
-    // this particular bundle.  We use these keys to aquire\
-    // personality entities from the database.
-    array = KEXTManagerCopyPersonalitiesForBundle(manager, bundle);
-
-    if ( !array && !configs ) {
-        return kKEXTReturnPersonalityNotFound;
-    }
-
-    // This is the list of personalities and configurations to load.
-    toLoad = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    modules = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-
-    if ( configs ) {
-        range = CFRangeMake(0, CFArrayGetCount(configs));
-        CFArrayApplyFunction(configs, range, (CFArrayApplierFunction)PromptForLoading, toLoad);
-        CFRelease(configs);
-    }
-
-    if ( array ) {
-        range = CFRangeMake(0, CFArrayGetCount(array));
-        CFArrayApplyFunction(array, range, (CFArrayApplierFunction)PromptForLoading, toLoad);
-        CFRelease(array);
-    }
-
-    context[0] = modules;
-    context[1] = &error;
-
-    range = CFRangeMake(0, CFArrayGetCount(toLoad));
-    CFArrayApplyFunction(toLoad, range, (CFArrayApplierFunction)ArrayGetModuleList, context);
-
-    if ( error != kKEXTReturnSuccess ) {
-        CFRelease(toLoad);
-        CFRelease(modules);
-        return error;
-    }
-
-    // Load all the modules.
-    sInteractive = false;
-    range = CFRangeMake(0, CFArrayGetCount(modules));
-    CFArrayApplyFunction(modules, range, (CFArrayApplierFunction)ArrayLoadMods, &error);
-    sInteractive = true;
-
-    if ( error != kKEXTReturnSuccess ) {
-        CFRelease(toLoad);
-        CFRelease(modules);
-        return error;
-    }
-    
-    // We need to send all personalities together.
-    error = KEXTManagerLoadPersonalities(manager, toLoad);
-    CFRelease(toLoad);
-    CFRelease(modules);
-
-    return error;
-}
-
-int main (int argc, const char *argv[])
-{
-    int c;
-
-    CFMutableArrayRef libList;
-    CFURLRef abs;
-    CFStringRef defaultLibDir = NULL;
-    CFStringRef path;
-    CFStringRef name;
-    KEXTBundleRef bundle;
-    KEXTReturn error;
-
-    sCmdName = argv[0];
-
-    name  = NULL;
-    defaultLibDir = CFSTR(kDefaultSearchPath);
-    libList = CFArrayCreateMutable
-                (kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
-    if (!libList) {
-        fprintf(stderr, "%s: Not enough memory to run\n", sCmdName);
-        exit(EX_SOFTWARE);
-    }
-
-    while ( (c = getopt(argc, (char **)argv, "eihvxp:L:")) != -1 ) {
-        switch ( c ) {
-        case 'e':
-            defaultLibDir = NULL;
-            break;
-
-        case 'v':
-            sVerbose = true;
-            break;
-
-        case 'x':
-            sSafeBoot = true;
-            break;
-
-        case 'i':
-            sInteractive = true;
-            break;
-
-        case 'h':
-            usage(true);
-
-        case 'L':
-            if ( !optarg )
-                usage(false);
-            else if (strlen(optarg)) {
-                path = CFStringCreateWithCString
-                    (kCFAllocatorDefault, optarg, kCFStringEncodingASCII);
-                CFArrayAppendValue(libList, path);
-                CFRelease(path);
-            }
-
-        case 'p':
-            if ( !optarg )
-                usage(false);
-            else
-                name = CFStringCreateWithCString(kCFAllocatorDefault, optarg, kCFStringEncodingASCII);
-            break;
-
-        default:
-            usage(false);
-        }
-    }
-    argc -= optind;
-    argv += optind;
-
-    if (argc < 1)
-        usage(false);
-
-    if (defaultLibDir)
-        CFArrayInsertValueAtIndex(libList, 0, defaultLibDir);
-
-    path = CFStringCreateWithCString
-            (kCFAllocatorDefault, argv[argc - 1], kCFStringEncodingASCII);
-    abs = URLCreateAbsoluteWithPath(path);
-    CFRelease(path);
-
-    if ( !abs ) {
-        fprintf(stderr, "Invalid path: %s.\n", argv[argc - 1]);
-        CFRelease(abs);
-        exit(-1);
-    }
-
-    if ( sVerbose ) {
-        fprintf(stderr, "Examining: %s\n", argv[argc - 1]);
-    }
-
-    sAuthenticateAll = false;
-    if ( !InitManager(libList) ) {
-        fprintf(stderr, "Error initializing KEXT Manager.\n");
-        exit(-1);
-    }
-
-    // Don't authenticate the target bundle, this
-    // is just a convenience for developers.
-    sAuthenticateAll = true;
-    
-    // Add the bundle to the database.
-    error = KEXTManagerAddBundle(manager, abs);
-    if ( error != kKEXTReturnSuccess ) {
-        fprintf(stderr, "Error (%d) adding bundle to database.\n", error);
-        exit(1);
-    }
-    // Re-enable the authentication.
-    sAuthenticateAll = false;
-    // Now, get the bundle entity from the database,
-    // this is the handle we use for accessing bundle resources.
-    bundle = KEXTManagerGetBundleWithURL(manager, abs);
-    if ( !bundle ) {
-        fprintf(stderr, "Bundle not found in database.\n");
-        exit(EX_DATAERR);
-    }
-
-    // If no name was given, then assume all personalities should be loaded.
-    error = LoadAllPersonalities(bundle);
-    if ( error != kKEXTReturnSuccess ) {
-        // No personalities are found, then this is probably
-        // a kmod bundle.  Try loading just the modules.
-        if ( error == kKEXTReturnPersonalityNotFound ) {
-            // XXX -- Attempt to load modules.
-            LoadAllModules(bundle);
-        }
-    }
-
-    if ( manager ) {
-        KEXTManagerRelease(manager);
-    }
-
-    if ( sVerbose ) {
-        printf("Done.\n");
-    }
-
-    return 0;      // ...and make main fit the ANSI spec.
-}
diff --git a/kextunload.tproj/Makefile b/kextunload.tproj/Makefile
deleted file mode 100644 (file)
index 2df3398..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# Generated by the Apple Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = kextunload
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = kextunload_main.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kextunload.8
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-FRAMEWORKS = -framework CoreFoundation -framework IOKit
-
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/kextunload.tproj/Makefile.postamble b/kextunload.tproj/Makefile.postamble
deleted file mode 100644 (file)
index 15092aa..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-MAN_PAGE = kextunload.8
-MAN_PATH = /usr/share/man/man8
-
-after_install::
-       -mkdir -p ${DSTROOT}$(MAN_PATH)
-       -rm -f ${DSTROOT}$(MAN_PATH)/$(MAN_PAGE)
-       cp $(MAN_PAGE) ${DSTROOT}$(MAN_PATH)/$(MAN_PAGE)
-       chmod og-w ${DSTROOT}$(MAN_PATH)/$(MAN_PAGE)
-
diff --git a/kextunload.tproj/Makefile.preamble b/kextunload.tproj/Makefile.preamble
deleted file mode 100644 (file)
index c1624b4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-###############################################################################
-#  Makefile.preamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile for configuring the standard application makefiles 
-#  associated with ProjectBuilder. It is included before the main makefile.
-#  In Makefile.preamble you set attributes for a project, so they are available
-#  to the project's makefiles.  In contrast, you typically write additional rules or 
-#  override built-in behavior in the Makefile.postamble.
-#  
-#  Each directory in a project tree (main project plus subprojects) should 
-#  have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible.  To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
-#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
-#      flags in OTHER_MFLAGS, etc.
-#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
-#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
-#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
-#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
-#      precompiling header files
-#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
-#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
-#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
-#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
-#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every 
-# stage of the make:
-#
-#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
-#    AFTER_PREBUILD: targets to build after installing headers for a subproject
-#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
-#    BEFORE_BUILD: targets to make before a build, but after subprojects
-#    AFTER_BUILD: targets to make after a build
-#
-#    BEFORE_INSTALL: targets to build before installing the product
-#    AFTER_INSTALL: targets to build after installing the product
-#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
-#         subproject
-#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-#    BEFORE_DEPEND: targets to build before building dependencies for a
-#        subproject
-#    AFTER_DEPEND: targets to build after building dependencies for a
-#        subproject
-#
-#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-#        updated every time the project is built.  If NO, the dependency
-#        file is only built when the depend target is invoked.
-
-# Framework-related variables:
-#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the framework's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-#    PUBLIC_HEADER_DIR:  Determines where public exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.  For library projects you should
-#       set this to something like /Developer/Headers/$(NAME).  Do not set
-#       this variable for framework projects unless you do not want the
-#       header files included in the framework.
-#    PRIVATE_HEADER_DIR:  Determines where private exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.
-#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
-#      whether the libraries produced are statically linked when they
-#      are used or if they are dynamically loadable. This defaults to
-#       DYNAMIC.
-#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the library's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-#
-#    INSTALL_AS_USER: owner of the intalled products (default root)
-#    INSTALL_AS_GROUP: group of the installed products (default wheel)
-#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-#      passed on the command line to recursive invocations of make.  Note that
-#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
-#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
-#      OTHER_RECURSIVE_VARIABLES. 
-
-# Additional headers to export beyond those in the PB.project:
-#    OTHER_PUBLIC_HEADERS
-#    OTHER_PROJECT_HEADERS
-#    OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/kextunload.tproj/PB.project b/kextunload.tproj/PB.project
deleted file mode 100644 (file)
index 3b29511..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (CoreFoundation.framework, IOKit.framework); 
-        OTHER_LINKED = (kextunload_main.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kextunload.8); 
-    }; 
-    LANGUAGE = English; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
-    NEXTSTEP_INSTALLDIR = /sbin; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_INSTALLDIR = /bin; 
-    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = kextunload; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_INSTALLDIR = /Library/Executables; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/kextunload.tproj/kextunload.8 b/kextunload.tproj/kextunload.8
deleted file mode 100644 (file)
index f622928..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-.\"
-.\"
-.Dd July 5, 2000
-.Dt kextunload 8
-.Os Apple Computer, Inc.
-.Sh NAME
-.Nm kextunload
-.Nd terminates classes, unloads modules associated with a kernel extension
-.Sh SYNOPSIS
-.Nm kextunload
-.Op Fl c Ar classname
-.Op Fl m Ar modulename
-.Op Fl h
-.Op Ar kextbundle
-.Sh DESCRIPTION
-The
-.Nm
-utility terminates classes and unloads the module files contained within 
-.Ar kextbundle
-or with a given name. Modules and classes in the kernel must be written correctly to handle the termination and unload process for this to be successful.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl h
-Provide quick help.
-.It Fl m
-Terminate the classes found in the module name given, and unload the module.
-.It Fl c
-Terminate the classes in the kernel with the given name.
-.El
-.Sh FILES
-.Bl -tag -width /modules -compact
-.Ar kextbundle
-directory containing loadable kernel modules.
-.Sh DIAGNOSTICS
-The
-.Nm
-utility exits with a status of 0 on success or with a nonzero status if an error occurs.
-.Sh SEE ALSO
-.Xr kextload 8 ,
-.Xr kmodload 8 ,
-.Xr kmodstat 8 ,
-.Xr kmodunload 8
diff --git a/kextunload.tproj/kextunload_main.c b/kextunload.tproj/kextunload_main.c
deleted file mode 100644 (file)
index 852cd2c..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOKitServer.h>
-#include <IOKit/IOCFSerialize.h>
-#include <mach/mach_types.h>
-
-#include <IOKit/kext/KEXTManager.h>
-
-static Boolean sVerbose = false;
-static Boolean sAuthenticateAll = false;
-
-static KEXTManagerRef manager = NULL;
-static const char * sArgv0;
-static mach_port_t sMasterPort;
-
-#define kBundleIDKey       "CFBundleIdentifier"
-
-
-#if 0
-// never were used
-#define kModuleKey         "Module"
-#define kModulesKey        "Modules"
-#define kModuleFileKey     "File"
-#define kPersonalityKey           "Personality"
-#define kPersonalitiesKey  "Personalities"
-#define kNameKey           "Name"
-#define kVendorKey         "Vendor"
-#define kVersionKey        "Version"
-#define kRequiresKey       "Requires"
-#define kModuleAliasesKey  "Aliases"
-#endif 0
-
-
-#define kDefaultSearchPath "/System/Library/Extensions"
-
-// These don't seem to be used
-#if 0
-#define kInfoMacOS         "Info-macos"
-#define kInfoMacOSType     "xml"
-#endif 0
-
-#define defaultPath CFSTR(kDefaultSearchPath)
-
-
-static void usage(Boolean help)
-{
-    printf("Usage: %s [-h] [-m modulename] [-c classname] [kextpath]\n", sArgv0);
-    exit(-1);
-}
-
-
-// Override the default authentication scheme so we can load
-// kext not owned by root into the kernel.
-static KEXTReturn authenticate(CFURLRef url, void * context)
-{
-    if ( !sAuthenticateAll ) {
-        KEXTReturn ret;
-        
-        ret = KEXTManagerAuthenticateURL(url);
-        if ( ret != kKEXTReturnSuccess ) {
-            if ( sVerbose ) {
-                CFURLRef absUrl;
-                CFStringRef message;
-                CFStringRef path;
-
-                absUrl = CFURLCopyAbsoluteURL(url);
-                path = CFURLGetString(absUrl);
-
-                message = CFStringCreateWithFormat(
-                                            kCFAllocatorDefault,
-                                            NULL,
-                                            CFSTR("Error (%) Authentication failed: %@"),
-                                            ret,
-                                            path);
-
-                CFShow(message);
-                CFRelease(message);
-                CFRelease(absUrl);
-            }
-            return ret;
-        }
-    }
-
-    return kKEXTReturnSuccess;
-}
-
-// Initialize the KEXTManager.
-static Boolean InitManager(void)
-{
-    CFURLRef url;
-    KEXTReturn error;
-    KEXTManagerBundleLoadingCallbacks bCallback = {
-        0, authenticate, NULL, NULL, NULL, NULL, NULL,
-    };
-    KEXTManagerModuleLoadingCallbacks mCallbacks = {
-        0, NULL, NULL, NULL, NULL, NULL,
-    };
-
-    // Give the manager the default path to the Extensions folder.
-    // This is needed for dependency matching.
-    url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, defaultPath, kCFURLPOSIXPathStyle, true);
-
-    // Create the manager database.
-    manager = KEXTManagerCreate(&bCallback, &mCallbacks, NULL, NULL, NULL, NULL, NULL, false, &error);
-    if ( !manager ) {
-        printf("Manager not created.\n");
-        return false;
-    }
-
-    // Now scan in all the bundles in the extensions directory.
-    if ( (error = KEXTManagerScanPath(manager, url)) != kKEXTReturnSuccess ) {
-        if ( sVerbose ) {
-            KEXTError(error, CFSTR("Error scanning path"));
-        }
-        return false;
-    };
-
-    return true;
-}
-
-
-static KEXTReturn KEXTUnloadAllModules(KEXTBundleRef bundle)
-{
-    CFArrayRef modules;
-    kern_return_t kr;
-    KEXTModuleRef mod;
-    char buf[256];
-    unsigned int i;
-    CFIndex count;
-
-    if ( !bundle ) {
-        return kKEXTReturnBadArgument;
-    }
-    
-    modules = KEXTManagerCopyModulesForBundle(manager, bundle);
-    if ( !modules ) {
-        return kKEXTReturnModuleNotFound;
-    }
-    
-    for( i = 0, count = CFArrayGetCount(modules); i < count; i++) {
-        CFStringRef name;
-
-        mod = (KEXTModuleRef) CFArrayGetValueAtIndex( modules, i);
-        name = KEXTModuleGetProperty( mod, CFSTR(kBundleIDKey));
-
-        if( CFStringGetCString( name, buf, sizeof(buf), kCFStringEncodingMacRoman)) {
-   
-            kr = IOCatalogueTerminate( sMasterPort, kIOCatalogModuleUnload, buf );
-            printf("IOCatalogueTerminate(Module %s) [%x]\n", buf, kr);
-        }
-    }
-
-    CFRelease(modules);
-
-    return kKEXTReturnSuccess;
-}
-
-KEXTReturn KEXTUnload( const char * cPath )
-{
-    CFURLRef url;
-    CFURLRef abs;
-    CFStringRef path;
-    KEXTBundleRef bundle;
-    KEXTReturn error;
-
-    path = CFStringCreateWithCString(kCFAllocatorDefault, cPath, kCFStringEncodingASCII);
-    url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path, kCFURLPOSIXPathStyle, true);
-    CFRelease(path);
-    
-    abs = CFURLCopyAbsoluteURL(url);
-    CFRelease(url);
-
-    if ( !abs ) {
-        printf("Invalid path: %s.\n", cPath);
-        CFRelease(abs);
-        exit(-1);
-    }
-
-    sAuthenticateAll = false;
-    if ( !InitManager() ) {
-        printf("Error initializing KEXT Manager.\n");
-        exit(-1);
-    }
-
-    // Don't authenticate the target bundle, this
-    // is just a convenience for developers.
-    sAuthenticateAll = true;
-    
-    // Add the bundle to the database.
-    error = KEXTManagerAddBundle(manager, abs);
-    if ( error != kKEXTReturnSuccess ) {
-        printf("Error (%d) adding bundle to database.\n", error);
-        exit(1);
-    }
-    // Re-enable the authentication.
-    sAuthenticateAll = false;
-    // Now, get the bundle entity from the database,
-    // this is the handle we use for accessing bundle resources.
-    bundle = KEXTManagerGetBundleWithURL(manager, abs);
-    if ( !bundle ) {
-        printf("Bundle not found in database.\n");
-        exit(1);
-    }
-
-    error = KEXTUnloadAllModules(bundle);
-
-    if ( manager ) {
-        KEXTManagerRelease(manager);
-    }
-
-    return( error );
-}
-
-int main (int argc, const char *argv[])
-{
-    int c;
-    const char * name  = NULL;
-    int command = 0;
-    KEXTReturn error;
-    kern_return_t kr;
-
-    // Obtain the I/O Kit communication handle.
-    kr = IOMasterPort(bootstrap_port, &sMasterPort);
-    if( kr != KERN_SUCCESS)
-        exit(-1);
-
-    sArgv0 = argv[0];
-
-    if (argc < 2)
-        usage(false);
-
-    while ( (c = getopt(argc, (char **)argv, "hm:c:")) != -1 ) {
-        switch ( c ) {
-
-            case 'h':
-                usage(true);
-
-            case 'c':
-                command = kIOCatalogServiceTerminate;
-                if ( !optarg )
-                    usage(false);
-                else
-                    name = optarg;
-                break;
-
-            case 'm':
-                command = kIOCatalogModuleUnload;
-                if ( !optarg )
-                    usage(false);
-                else
-                    name = optarg;
-                break;
-
-            default:
-                usage(false);
-        }
-    }
-
-    argc -= optind;
-    argv += optind;
-    if (argc >= 1) {
-        name = argv[argc - 1];
-        error = KEXTUnload( name );
-    }
-
-    if( command >= kIOCatalogModuleUnload) {
-        kr = IOCatalogueTerminate( sMasterPort, command, (char *) name );
-        printf("IOCatalogueTerminate(%s %s) [%x]\n",
-            (command == kIOCatalogModuleUnload) ? "Module" : "Class",
-            name, kr);
-    }
-    printf("done.\n");
-
-    return 0;      // ...and make main fit the ANSI spec.
-}
diff --git a/kmodload.tproj/Makefile b/kmodload.tproj/Makefile
deleted file mode 100644 (file)
index 508f918..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# Generated by the Apple Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = kmodload
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-HFILES = kld_patch.h
-
-CFILES = kld_patch.c kmodload.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kmodload.8\
-            kmodsyms.8
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = -lkld
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/kmodload.tproj/Makefile.postamble b/kmodload.tproj/Makefile.postamble
deleted file mode 100644 (file)
index b5254fc..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-###############################################################################
-#  Makefile.postamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile, which is imported after all other makefiles, to
-#  override attributes for a project's Makefile environment. This allows you  
-#  to take advantage of the environment set up by the other Makefiles. 
-#  You can also define custom rules at the end of this file.
-#
-###############################################################################
-# 
-# These variables are exported by the standard makefiles and can be 
-# used in any customizations you make.  They are *outputs* of
-# the Makefiles and should be used, not set.
-# 
-#  PRODUCTS: products to install.  All of these products will be placed in
-#       the directory $(DSTROOT)$(INSTALLDIR)
-#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-#  OFILE_DIR: Directory into which .o object files are generated.
-#  DERIVED_SRC_DIR: Directory used for all other derived files
-#
-#  ALL_CFLAGS:  flags to pass when compiling .c files
-#  ALL_MFLAGS:  flags to pass when compiling .m files
-#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
-#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
-#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
-#  ALL_LDFLAGS:  flags to pass when linking object files
-#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
-#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
-#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
-#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
-#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
-#
-#  NAME: name of application, bundle, subproject, palette, etc.
-#  LANGUAGES: langages in which the project is written (default "English")
-#  English_RESOURCES: localized resources (e.g. nib's, images) of project
-#  GLOBAL_RESOURCES: non-localized resources of project
-#
-#  SRCROOT:  base directory in which to place the new source files
-#  SRCPATH:  relative path from SRCROOT to present subdirectory
-#
-#  INSTALLDIR: Directory the product will be installed into by 'install' target
-#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
-#        to prefix this with DSTROOT when you use it.
-#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
-#       to prefix this with DSTROOT when you use it.
-#
-#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
-#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
-#      to -g)
-#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
-#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
-#      to -O)
-#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
-#      to -pg -DPROFILE)
-#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
-#      the include path (defaults to -I.)
-#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-#      passed to ld/libtool (defaults to nothing)
-
-
-# Library and Framework projects only:
-#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
-#      against the framework will run against the correct version even if
-#      the current version of the framework changes.  You may override this
-#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-#      development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
-        # User/group ownership 
-#INSTALL_AS_GROUP = wheel
-        # (probably want to set both of these) 
-#INSTALL_PERMISSIONS =
-        # If set, 'install' chmod's executable to this
-
-
-# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here.  Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where 
-# derived files should go.
-#
-
-after_install::
-       -mkdir -p ${DSTROOT}/usr/share/man/man8
-       -rm -f ${DSTROOT}/usr/share/man/man8/kmodload.8
-       cp kmodload.8 ${DSTROOT}/usr/share/man/man8/kmodload.8
-       chmod og-w ${DSTROOT}/usr/share/man/man8/kmodload.8
-       -rm -f ${DSTROOT}/usr/share/man/man8/kmodsyms.8
-       cp kmodsyms.8 ${DSTROOT}/usr/share/man/man8/kmodsyms.8
-       chmod og-w ${DSTROOT}/usr/share/man/man8/kmodsyms.8
-       $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)/usr/sbin/kmodsyms
diff --git a/kmodload.tproj/Makefile.preamble b/kmodload.tproj/Makefile.preamble
deleted file mode 100644 (file)
index c1624b4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-###############################################################################
-#  Makefile.preamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile for configuring the standard application makefiles 
-#  associated with ProjectBuilder. It is included before the main makefile.
-#  In Makefile.preamble you set attributes for a project, so they are available
-#  to the project's makefiles.  In contrast, you typically write additional rules or 
-#  override built-in behavior in the Makefile.postamble.
-#  
-#  Each directory in a project tree (main project plus subprojects) should 
-#  have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible.  To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
-#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
-#      flags in OTHER_MFLAGS, etc.
-#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
-#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
-#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
-#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
-#      precompiling header files
-#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
-#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
-#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
-#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
-#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every 
-# stage of the make:
-#
-#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
-#    AFTER_PREBUILD: targets to build after installing headers for a subproject
-#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
-#    BEFORE_BUILD: targets to make before a build, but after subprojects
-#    AFTER_BUILD: targets to make after a build
-#
-#    BEFORE_INSTALL: targets to build before installing the product
-#    AFTER_INSTALL: targets to build after installing the product
-#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
-#         subproject
-#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-#    BEFORE_DEPEND: targets to build before building dependencies for a
-#        subproject
-#    AFTER_DEPEND: targets to build after building dependencies for a
-#        subproject
-#
-#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-#        updated every time the project is built.  If NO, the dependency
-#        file is only built when the depend target is invoked.
-
-# Framework-related variables:
-#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the framework's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-#    PUBLIC_HEADER_DIR:  Determines where public exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.  For library projects you should
-#       set this to something like /Developer/Headers/$(NAME).  Do not set
-#       this variable for framework projects unless you do not want the
-#       header files included in the framework.
-#    PRIVATE_HEADER_DIR:  Determines where private exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.
-#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
-#      whether the libraries produced are statically linked when they
-#      are used or if they are dynamically loadable. This defaults to
-#       DYNAMIC.
-#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the library's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-#
-#    INSTALL_AS_USER: owner of the intalled products (default root)
-#    INSTALL_AS_GROUP: group of the installed products (default wheel)
-#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-#      passed on the command line to recursive invocations of make.  Note that
-#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
-#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
-#      OTHER_RECURSIVE_VARIABLES. 
-
-# Additional headers to export beyond those in the PB.project:
-#    OTHER_PUBLIC_HEADERS
-#    OTHER_PROJECT_HEADERS
-#    OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/kmodload.tproj/PB.project b/kmodload.tproj/PB.project
deleted file mode 100644 (file)
index 474d5fe..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (); 
-        HEADERSEARCH = (); 
-        H_FILES = (kld_patch.h); 
-        OTHER_LIBS = (kld); 
-        OTHER_LINKED = (kld_patch.c, kmodload.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kmodload.8, kmodsyms.8); 
-    }; 
-    LANGUAGE = English; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; 
-    NEXTSTEP_INSTALLDIR = /sbin; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_INSTALLDIR = /bin; 
-    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = kmodload; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_INSTALLDIR = /Library/Executables; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/kmodload.tproj/kld_patch.c b/kmodload.tproj/kld_patch.c
deleted file mode 100644 (file)
index 646bf14..0000000
+++ /dev/null
@@ -1,2124 +0,0 @@
-/*
- * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * History:
- *  2001-05-30         gvdl    Initial implementation of the vtable patcher.
- */
-// 45678901234567890123456789012345678901234567890123456789012345678901234567890
-
-#include <mach-o/fat.h>
-#include <mach-o/loader.h>
-#include <mach-o/nlist.h>
-#include <mach-o/reloc.h>
-
-#if KERNEL
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <sys/systm.h>
-
-#include <libkern/OSTypes.h>
-
-#include <libsa/stdlib.h>
-#include <libsa/mach/mach.h>
-
-#include "mach_loader.h"
-
-#include <vm/vm_kern.h>
-
-enum { false = 0, true = 1 };
-
-#define vm_page_size page_size
-
-extern load_return_t fatfile_getarch(
-    void            * vp,       // normally a (struct vnode *)
-    vm_offset_t       data_ptr,
-    struct fat_arch * archret);
-
-#else /* !KERNEL */
-#include <unistd.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/errno.h> 
-#include <sys/fcntl.h>
-#include <sys/stat.h>   
-#include <sys/mman.h>   
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-
-#include <mach-o/arch.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#endif /* KERNEL */
-
-#include "kld_patch.h"
-
-#if 0
-static __inline__ void DIE(void) { IODelay(2000000000); }
-
-#define LOG_DELAY()    IODelay(200000)
-#define DEBUG_LOG(x)   do { IOLog x; LOG_DELAY(); } while(0)
-#else
-
-#define DIE()
-#define LOG_DELAY()
-#define DEBUG_LOG(x)
-
-#endif
-
-// OSObject symbol prefixes and suffixes
-#define kVTablePrefix          "___vt"
-#define kReservedPrefix                "__RESERVED"
-#define kSuperClassSuffix      ".superClass"
-#define kGMetaSuffix           ".gMetaClass"
-#define kLinkEditSegName       SEG_LINKEDIT
-
-// GCC 2.95 drops 2 leading constants in the vtable
-#define kVTablePreambleLen 2
-
-// Last address that I'm willing to try find vm in
-#define kTopAddr  ((unsigned char *) (1024 * 1024 * 1024))
-
-// Size in bytes that Data Ref object's get increased in size
-// Must be a power of 2
-#define kDataCapacityIncrement 128
-
-// My usual set of helper macros.  I personally find these macros
-// easier to read in the code rather than an explicit error condition
-// check.  If I don't make it easy then I may get lazy ond not check
-// everything.  I'm sorry if you find this code harder to read.
-
-// break_if will evaluate the expression and if it is true
-// then it will print the msg, which is enclosed in parens
-// and then break.  Usually used in loops are do { } while (0)
-#define break_if(expr, msg)                                    \
-    if (expr) {                                                        \
-       errprintf msg;                                          \
-        break;                                                 \
-    }
-
-// return_if will evaluate expr and if true it will log the
-// msg, which is enclosed in parens, and then it will return
-// with the return code of ret.
-#define return_if(expr, ret, msg) do {                         \
-    if (expr) {                                                        \
-       errprintf msg;                                          \
-        return ret;                                            \
-    }                                                          \
-} while (0)
-
-#ifndef MIN
-#define        MIN(a,b) (((a)<(b))?(a):(b))
-#endif /* MIN */
-#ifndef MAX
-#define        MAX(a,b) (((a)>(b))?(a):(b))
-#endif /* MAX */
-
-typedef struct Data {
-    unsigned long fLength, fCapacity;
-    unsigned char *fData;
-} Data, *DataRef;
-
-struct sectionRecord {
-    const struct section *fSection;
-    DataRef fRelocCache;
-};
-
-enum patchState {
-    kSymbolIdentical,
-    kSymbolLocal,
-    kSymbolPadUpdate,
-    kSymbolSuperUpdate,
-    kSymbolMismatch
-};
-
-struct patchRecord {
-    struct nlist *fSymbol;
-    enum patchState fType;
-};
-
-struct relocRecord {
-    void *fValue;
-    const struct nlist *fSymbol;
-    struct relocation_info *fRInfo;
-    void *reserved;
-};
-
-struct metaClassRecord {
-    char *fSuperName;
-    struct fileRecord *fFile;
-    const struct nlist *fVTableSym;
-    struct patchRecord *fPatchedVTable;
-    char fClassName[1];
-};
-
-struct fileRecord {
-    size_t fMapSize, fMachOSize;
-    const char *fPath;
-    unsigned char *fMap, *fMachO, *fPadEnd;
-    DataRef fClassList;
-    DataRef fSectData;
-    DataRef fNewSymbols, fNewStrings;
-    struct symtab_command *fSymtab;
-    struct sectionRecord *fSections;
-    char *fStringBase;
-    struct nlist *fSymbolBase;
-    const struct nlist *fLocalSyms;
-    unsigned int fNSects;
-    int fNLocal;
-    int fNewStringsLen;
-    Boolean fIsKernel, fNoKernelExecutable, fIsKmem;
-    Boolean fImageDirty, fSymbolsDirty;
-};
-
-static DataRef sFilesTable;
-static struct fileRecord *sKernelFile;
-
-static DataRef sMergedFiles;
-static DataRef sMergeMetaClasses;
-static Boolean sMergedKernel;
-
-static void errprintf(const char *fmt, ...)
-{
-    extern void kld_error_vprintf(const char *format, va_list ap);
-
-    va_list ap;
-
-    va_start(ap, fmt);
-    kld_error_vprintf(fmt, ap);
-    va_end(ap);
-
-DIE();
-}
-
-static __inline__ unsigned long DataGetLength(DataRef data)
-{
-    return data->fLength;
-}
-
-static __inline__ unsigned char *DataGetPtr(DataRef data)
-{
-    return data->fData;
-}
-
-
-static __inline__ Boolean DataContainsAddr(DataRef data, void *vAddr)
-{
-    unsigned char *addr = vAddr;
-
-    return (data->fData <= addr) && (addr < data->fData + data->fLength);
-}
-
-static __inline__ Boolean DataAddLength(DataRef data, unsigned long length)
-{
-    static Boolean DataSetLength(DataRef data, unsigned long length);
-    return DataSetLength(data, data->fLength + length);
-}
-
-static __inline__ Boolean
-DataAppendBytes(DataRef data, const void *addr, unsigned int len)
-{
-    unsigned long size = DataGetLength(data);
-
-    if (!DataAddLength(data, len))
-       return false;
-
-    bcopy(addr, DataGetPtr(data) + size, len);
-    return true;
-}
-
-static __inline__ Boolean DataAppendData(DataRef dst, DataRef src)
-{
-    return DataAppendBytes(dst, DataGetPtr(src), DataGetLength(src));
-}
-
-static Boolean DataSetLength(DataRef data, unsigned long length)
-{
-    // Don't bother to ever shrink a data object.
-    if (length > data->fCapacity) {
-       unsigned char *newData;
-       unsigned long newCapacity;
-
-       newCapacity  = length + kDataCapacityIncrement - 1;
-       newCapacity &= ~(kDataCapacityIncrement - 1);
-       newData = (unsigned char *) realloc(data->fData, newCapacity);
-       if (!newData)
-           return false;
-
-       bzero(newData + data->fCapacity, newCapacity - data->fCapacity);
-       data->fData = newData;
-       data->fCapacity = newCapacity;
-    }
-
-    data->fLength = length;
-    return true;
-}
-
-static DataRef DataCreate(unsigned long length)
-{
-    DataRef data = (DataRef) malloc(sizeof(Data));
-
-    if (data) {
-       if (!length)
-           data->fCapacity = kDataCapacityIncrement;
-       else {
-           data->fCapacity  = length + kDataCapacityIncrement - 1;
-           data->fCapacity &= ~(kDataCapacityIncrement - 1);
-       }
-
-       data->fData = (unsigned char *) malloc(data->fCapacity);
-       if (!data->fData) {
-           free(data);
-           return NULL;
-       }
-
-       bzero(data->fData, data->fCapacity);
-       data->fLength = length;
-    }
-    return data;
-}
-
-static void DataRelease(DataRef data)
-{
-    if (data) {
-       if (data->fData)
-           free(data->fData);
-       data->fData = 0;
-       free(data);
-    }
-}
-
-static const char *
-symbolname(const struct fileRecord *file, const struct nlist *sym)
-{
-    unsigned long strsize;
-    long strx = sym->n_un.n_strx;
-
-    if (strx >= 0)
-       return file->fStringBase + strx;
-
-    strsize = file->fSymtab->strsize;
-    strx = -strx;
-    if (strx < strsize)
-       return file->fStringBase + strx;
-
-    strx -= strsize;
-    return (char *) DataGetPtr(file->fNewStrings) + strx;
-}
-
-static struct fileRecord *getFile(const char *path)
-{
-    if (sFilesTable) {
-       int i, nfiles;
-       struct fileRecord **files;
-
-        // Check to see if we have already merged this file
-       nfiles = DataGetLength(sFilesTable) / sizeof(struct fileRecord *);
-       files = (struct fileRecord **) DataGetPtr(sFilesTable);
-       for (i = 0; i < nfiles; i++) {
-           if (!strcmp(path, files[i]->fPath))
-               return files[i];
-       }
-    }
-
-    return NULL;
-}
-
-static struct fileRecord * addFile(struct fileRecord *file)
-{
-    struct fileRecord *newFile;
-
-    if (!sFilesTable) {
-       sFilesTable = DataCreate(0);
-       if (!sFilesTable)
-           return NULL;
-    }
-
-    newFile = (struct fileRecord *) malloc(sizeof(struct fileRecord));
-    if (!newFile)
-       return NULL;
-
-    if (!DataAppendBytes(sFilesTable, &newFile, sizeof(newFile))) {
-       free(newFile);
-       return NULL;
-    }
-
-    bcopy(file, newFile, sizeof(struct fileRecord));
-    return newFile;
-}
-
-// @@@ gvdl: need to clean up the sMergeMetaClasses
-// @@@ gvdl: I had better fix the object file up again
-static void removeFile(struct fileRecord *file)
-{
-    if (file->fClassList) {
-       DataRelease(file->fClassList);
-       file->fClassList = 0;
-    }
-
-    if (file->fSectData) {
-       struct sectionRecord *section;
-       unsigned int i, nsect;
-
-       nsect = file->fNSects;
-       section = file->fSections;
-       for (i = 0; i < nsect; i++, section++) {
-           if (section->fRelocCache) {
-               DataRelease(section->fRelocCache);
-               section->fRelocCache = 0;
-           }
-       }
-
-       DataRelease(file->fSectData);
-       file->fSectData = 0;
-       file->fSections = 0;
-       file->fNSects = 0;
-    }
-
-    if (file->fMap) {
-#if KERNEL
-       if (file->fIsKmem)
-           kmem_free(kernel_map, (vm_address_t) file->fMap, file->fMapSize);
-#else /* !KERNEL */
-       if (file->fPadEnd) {
-           vm_address_t padVM;
-           vm_size_t padSize;
-
-           padVM = round_page((vm_address_t) file->fMap + file->fMapSize);
-           padSize  = (vm_size_t) ((vm_address_t) file->fPadEnd - padVM);
-           (void) vm_deallocate(mach_task_self(), padVM, padSize);
-           file->fPadEnd = 0;
-       }
-
-       (void) munmap((caddr_t) file->fMap, file->fMapSize);
-#endif /* !KERNEL */
-       file->fMap = 0;
-    }
-
-    file->fPath = 0;
-}
-
-#if !KERNEL
-static Boolean
-mapObjectFile(struct fileRecord *file)
-{
-    Boolean result = false;
-    static unsigned char *sFileMapBaseAddr;
-
-    int fd = 0;
-
-    if (!sFileMapBaseAddr) {
-        kern_return_t ret;
-       vm_address_t probeAddr;
-
-       // If we don't already have a base addr find any random chunk
-       // of 32 meg of VM and to use the 16 meg boundrary as a base.
-        ret = vm_allocate(mach_task_self(), &probeAddr,
-                           32 * 1024 * 1024, VM_FLAGS_ANYWHERE);
-       return_if(KERN_SUCCESS != ret, false,
-           ("Unable to allocate base memory %s\n", mach_error_string(ret)));
-        (void) vm_deallocate(mach_task_self(), probeAddr, 32 * 1024 * 1024);
-
-       // Now round to the next 16 Meg boundrary
-       probeAddr = (probeAddr +  (16 * 1024 * 1024 - 1))
-                              & ~(16 * 1024 * 1024 - 1);
-       sFileMapBaseAddr = (unsigned char *) probeAddr;
-    }
-
-    fd = open(file->fPath, O_RDONLY, 0);
-    return_if(fd == -1, false, ("Can't open %s for reading - %s\n",
-       file->fPath, strerror(errno)));
-
-    do {
-       kern_return_t ret;
-       struct stat sb;
-       int retaddr = -1;
-
-       break_if(fstat(fd, &sb) == -1,
-           ("Can't stat %s - %s\n", file->fPath, strerror(errno)));
-
-       file->fMapSize = sb.st_size;
-       file->fMap = sFileMapBaseAddr;
-       ret = KERN_SUCCESS;
-       while (file->fMap < kTopAddr) {
-           vm_address_t padVM;
-           vm_address_t padVMEnd;
-           vm_size_t padSize;
-
-           padVM = round_page((vm_address_t) file->fMap + file->fMapSize);
-           retaddr = (int) mmap(file->fMap, file->fMapSize,
-                                PROT_READ|PROT_WRITE, 
-                                MAP_FIXED|MAP_FILE|MAP_PRIVATE,
-                                fd, 0);
-           if (-1 == retaddr) {
-               break_if(ENOMEM != errno,
-                   ("mmap failed %d - %s\n", errno, strerror(errno)));
-
-               file->fMap = (unsigned char *) padVM;
-               continue;
-           }
-
-
-           // Round up padVM to the next page after the file and assign at
-           // least another fMapSize more room rounded up to the next page
-           // boundary.
-           padVMEnd = round_page(padVM + file->fMapSize);
-           padSize  = padVMEnd - padVM;
-           ret = vm_allocate(
-               mach_task_self(), &padVM, padSize, VM_FLAGS_FIXED);
-           if (KERN_SUCCESS == ret) {
-               file->fPadEnd = (unsigned char *) padVMEnd;
-               break;
-           }
-           else {
-               munmap(file->fMap, file->fMapSize);
-               break_if(KERN_INVALID_ADDRESS != ret,
-                   ("Unable to allocate pad vm for %s - %s\n",
-                       file->fPath, mach_error_string(ret)));
-
-               file->fMap = (unsigned char *) padVMEnd;
-               continue; // try again wherever the vm system wants
-           }
-       }
-
-       if (-1 == retaddr || KERN_SUCCESS != ret)
-           break;
-
-       break_if(file->fMap >= kTopAddr,
-           ("Unable to map memory %s\n", file->fPath));
-
-       sFileMapBaseAddr = file->fPadEnd;
-       result = true;
-    } while(0);
-
-    close(fd);
-    return result;
-}
-#endif /* !KERNEL */
-
-static Boolean findBestArch(struct fileRecord *file)
-{
-    unsigned long magic;
-    struct fat_header *fat;
-
-
-    file->fMachOSize = file->fMapSize;
-    file->fMachO = file->fMap;
-    magic = ((const struct mach_header *) file->fMachO)->magic;
-    fat = (struct fat_header *) file->fMachO;
-
-    // Try to figure out what type of file this is
-    return_if(file->fMapSize < sizeof(unsigned long), false,
-       ("%s isn't a valid object file - no magic\n", file->fPath));
-
-#if KERNEL
-
-    // CIGAM is byte-swapped MAGIC
-    if (magic == FAT_MAGIC || magic == FAT_CIGAM) {
-
-        load_return_t load_return;
-        struct fat_arch fatinfo;
-
-        load_return = fatfile_getarch(NULL, (vm_address_t) fat, &fatinfo);
-       return_if(load_return != LOAD_SUCCESS, false,
-           ("Extension \"%s\": has no code for this computer\n", file->fPath));
-
-       file->fMachO = file->fMap + fatinfo.offset;
-       file->fMachOSize = fatinfo.size;
-       magic = ((const struct mach_header *) file->fMachO)->magic;
-    }
-
-#else /* !KERNEL */
-
-    // Do we need to in-place swap the endianness of the fat header?
-    if (magic == FAT_CIGAM) {
-       unsigned long i;
-       struct fat_arch *arch;
-
-       fat->nfat_arch = NXSwapBigLongToHost(fat->nfat_arch);
-       return_if(file->fMapSize < sizeof(struct fat_header)
-                                   + fat->nfat_arch * sizeof(struct fat_arch),
-           false, ("%s is too fat\n", file->fPath));
-
-       arch = (struct fat_arch *) &fat[1];
-       for (i = 0; i < fat->nfat_arch; i++) {
-           arch[i].cputype    = NXSwapBigLongToHost(arch[i].cputype);
-           arch[i].cpusubtype = NXSwapBigLongToHost(arch[i].cpusubtype);
-           arch[i].offset     = NXSwapBigLongToHost(arch[i].offset);
-           arch[i].size       = NXSwapBigLongToHost(arch[i].size);
-           arch[i].align      = NXSwapBigLongToHost(arch[i].align);
-       }
-
-       magic = NXSwapBigLongToHost(fat->magic);
-    }
-
-    // Now see if we can find any valid architectures
-    if (magic == FAT_MAGIC) {
-       const NXArchInfo *myArch;
-       unsigned long fatsize;
-       struct fat_arch *arch;
-
-       fatsize = sizeof(struct fat_header)
-           + fat->nfat_arch * sizeof(struct fat_arch);
-       return_if(file->fMapSize < fatsize,
-           false, ("%s isn't a valid fat file\n", file->fPath));
-
-       myArch = NXGetLocalArchInfo();
-       arch = NXFindBestFatArch(myArch->cputype, myArch->cpusubtype,
-               (struct fat_arch *) &fat[1], fat->nfat_arch);
-       return_if(!arch,
-           false, ("%s hasn't got arch for %s\n", file->fPath, myArch->name));
-       return_if(arch->offset + arch->size > file->fMapSize,
-           false, ("%s's %s arch is incomplete\n", file->fPath, myArch->name));
-       file->fMachO = file->fMap + arch->offset;
-       file->fMachOSize = arch->size;
-       magic = ((const struct mach_header *) file->fMachO)->magic;
-    }
-
-#endif /* KERNEL */
-
-    return_if(magic != MH_MAGIC,
-       false, ("%s isn't a valid mach-o\n", file->fPath));
-
-    return true;
-}
-
-static Boolean
-parseSegments(struct fileRecord *file, struct segment_command *seg)
-{
-    struct sectionRecord *sections;
-    int i, nsects = seg->nsects;
-    const struct segmentMap {
-       struct segment_command seg;
-       const struct section sect[1];
-    } *segMap;
-
-    if (!nsects) {
-#if KERNEL
-       // We don't need to look for the LinkEdit segment unless
-       // we are running in the kernel environment.
-       if (!strcmp(kLinkEditSegName, seg->segname)) {
-           // Grab symbol table from linkedit we will need this later
-           file->fSymbolBase = (void *) seg;
-       }
-#endif
-
-       return true;    // Nothing more to do, so that was easy.
-    }
-
-    if (!file->fSectData) {
-       file->fSectData = DataCreate(0);
-       if (!file->fSectData)
-           return false;
-    }
-
-    // Increase length of section DataRef and cache data pointer
-    if (!DataAddLength(file->fSectData, nsects * sizeof(struct sectionRecord)))
-       return false;
-    file->fSections = (struct sectionRecord *) DataGetPtr(file->fSectData);
-
-    // Initialise the new sections
-    sections = &file->fSections[file->fNSects];
-    file->fNSects += nsects;
-    for (i = 0, segMap = (struct segmentMap *) seg; i < nsects; i++)
-       sections[i].fSection = &segMap->sect[i];
-
-    return true;
-}
-
-// @@@ gvdl:  These functions need to be hashed they are
-// going to be way too slow for production code.
-static const struct nlist *
-findSymbolByAddress(const struct fileRecord *file, void *entry)
-{
-    // not quite so dumb linear search of all symbols
-    const struct nlist *sym;
-    int i, nsyms;
-
-    // First try to find the symbol in the most likely place which is the
-    // extern symbols
-    sym = file->fLocalSyms;
-    for (i = 0, nsyms = file->fNLocal; i < nsyms; i++, sym++) {
-       if (sym->n_value == (unsigned long) entry && !(sym->n_type & N_STAB) )
-           return sym;
-    }
-
-    // Didn't find it in the external symbols so try to local symbols before
-    // giving up.
-    sym = file->fSymbolBase;
-    for (i = 0, nsyms = file->fSymtab->nsyms; i < nsyms; i++, sym++) {
-       if ( (sym->n_type & N_EXT) )
-           return NULL;
-       if ( sym->n_value == (unsigned long) entry && !(sym->n_type & N_STAB) )
-           return sym;
-    }
-
-    return NULL;
-}
-
-struct searchContext {
-    const char *fSymname;
-    const char *fStrbase;
-};
-
-static int symbolSearch(const void *vKey, const void *vSym)
-{
-    const struct searchContext *key = (const struct searchContext *) vKey;
-    const struct nlist *sym = (const struct nlist *) vSym;
-
-    return strcmp(key->fSymname, key->fStrbase + sym->n_un.n_strx);
-}
-
-static const struct nlist *
-findSymbolByName(struct fileRecord *file, const char *symname)
-{
-    struct searchContext context;
-
-    context.fSymname = symname;
-    context.fStrbase = file->fStringBase;
-    return (struct nlist *)
-       bsearch(&context,
-               file->fLocalSyms, file->fNLocal, sizeof(struct nlist),
-               symbolSearch);
-}
-
-static Boolean
-relocateSection(const struct fileRecord *file, struct sectionRecord *sectionRec)
-{
-    const struct nlist *symbol;
-    const struct section *section;
-    struct relocRecord *rec;
-    struct relocation_info *rinfo;
-    unsigned long i;
-    unsigned long r_address, r_symbolnum, r_length;
-    enum reloc_type_generic r_type;
-    UInt8 *sectionBase;
-    void **entry;
-
-    sectionRec->fRelocCache = DataCreate(
-       sectionRec->fSection->nreloc * sizeof(struct relocRecord));
-    if (!sectionRec->fRelocCache)
-       return false;
-
-    section = sectionRec->fSection;
-    sectionBase = file->fMachO + section->offset;
-
-    rec = (struct relocRecord *) DataGetPtr(sectionRec->fRelocCache);
-    rinfo = (struct relocation_info *) (file->fMachO + section->reloff);
-    for (i = 0; i < section->nreloc; i++, rec++, rinfo++) {
-
-       // Totally uninterested in scattered relocation entries
-       if ( (rinfo->r_address & R_SCATTERED) )
-           continue;
-
-       r_address = rinfo->r_address;
-       entry = (void **) (sectionBase + r_address);
-
-       /*
-        * The r_address field is really an offset into the contents of the
-        * section and must reference something inside the section (Note
-        * that this is not the case for PPC_RELOC_PAIR entries but this
-        * can't be one with the above checks).
-        */
-       return_if(r_address >= section->size, false,
-           ("Invalid relocation entry in %s - not in section\n", file->fPath));
-
-       // If we don't have a VANILLA entry or the Vanilla entry isn't
-       // a 'long' then ignore the entry and try the next.
-       r_type = (enum reloc_type_generic) rinfo->r_type;
-       r_length = rinfo->r_length;
-       if (r_type != GENERIC_RELOC_VANILLA || r_length != 2)
-           continue;
-
-       r_symbolnum = rinfo->r_symbolnum;
-
-       /*
-        * If rinfo->r_extern is set this relocation entry is an external entry
-        * else it is a local entry.
-        */
-       if (rinfo->r_extern) {
-           /*
-            * This is an external relocation entry.
-            * r_symbolnum is an index into the input file's symbol table
-            * of the symbol being refered to.  The symbol must be
-            * undefined to be used in an external relocation entry.
-            */
-           return_if(r_symbolnum >= file->fSymtab->nsyms, false, 
-               ("Invalid relocation entry in %s - no symbol\n", file->fPath));
-
-           /*
-            * If this is an indirect symbol resolve indirection (all chains
-            * of indirect symbols have been resolved so that they point at
-            * a symbol that is not an indirect symbol).
-            */
-           symbol = file->fSymbolBase;
-           if ((symbol[r_symbolnum].n_type & N_TYPE) == N_INDR)
-               r_symbolnum = symbol[r_symbolnum].n_value;
-           symbol = &symbol[r_symbolnum];
-
-           return_if(symbol->n_type != (N_EXT | N_UNDF), false, 
-               ("Invalid relocation entry in %s - extern\n", file->fPath));
-       }
-       else {
-           /*
-            * If the symbol is not in any section then it can't be a
-            * pointer to a local segment and I don't care about it.
-            */
-           if (r_symbolnum == R_ABS)
-               continue;
-
-           // Note segment references are offset by 1 from 0.
-           return_if(r_symbolnum > file->fNSects, false,
-               ("Invalid relocation entry in %s - local\n", file->fPath));
-
-           // Find the symbol, if any, that backs this entry 
-           symbol = findSymbolByAddress(file, *entry);
-       }
-
-       rec->fValue  = *entry;          // Save the previous value
-       rec->fRInfo  =  rinfo;          // Save a pointer to the reloc
-       rec->fSymbol =  symbol;         // Record the current symbol
-
-       *entry = (void *) rec;  // Save pointer to record in object image
-    }
-
-    ((struct fileRecord *) file)->fImageDirty = true;
-
-    return true;
-}
-
-static const struct nlist *
-findSymbolRefAtLocation(const struct fileRecord *file,
-                       struct sectionRecord *sctn, void **loc)
-{
-    if (file->fIsKernel) {
-       if (*loc)
-           return findSymbolByAddress(file, *loc);
-    }
-    else if (sctn->fRelocCache || relocateSection(file, sctn)) {
-       struct relocRecord *reloc = (struct relocRecord *) *loc;
-
-       if (DataContainsAddr(sctn->fRelocCache, reloc))
-           return reloc->fSymbol;
-    }
-
-    return NULL;
-}
-
-static Boolean
-addClass(struct fileRecord *file,
-        struct metaClassRecord *inClass,
-        const char *cname)
-{
-    struct metaClassRecord *newClass = NULL;
-    struct metaClassRecord **fileClasses = NULL;
-    int len;
-
-if (!file->fIsKernel) {        // @@@ gvdl:
-    DEBUG_LOG(("Adding Class %s\n", cname));
-}
-
-    if (!file->fClassList) {
-       file->fClassList = DataCreate(0);
-       if (!file->fClassList)
-           return false;
-    }
-
-    do {
-       // Attempt to allocate all necessary resource first
-       len = strlen(cname) + 1
-           + (int) (&((struct metaClassRecord *) 0)->fClassName);
-       newClass = (struct metaClassRecord *) malloc(len);
-       if (!newClass)
-           break;
-
-       if (!DataAddLength(file->fClassList, sizeof(struct metaClassRecord *)))
-           break;
-       fileClasses = (struct metaClassRecord **)
-           (DataGetPtr(file->fClassList) + DataGetLength(file->fClassList));
-
-       // Copy the meta Class structure and string name into newClass
-       // and insert object at end of the file->fClassList and sMergeMetaClasses 
-       *newClass = *inClass;
-       strcpy(newClass->fClassName, cname);
-       fileClasses[-1]   = newClass;
-
-       return true;
-    } while (0);
-
-    if (fileClasses)
-       DataAddLength(file->fClassList, -sizeof(struct metaClassRecord *));
-
-    if (newClass)
-       free(newClass);
-
-    return false;
-}
-
-static struct metaClassRecord *getClass(DataRef classList, const char *cname)
-{
-    if (classList) {
-       int i, nclass;
-       struct metaClassRecord **classes, *thisClass;
-    
-       nclass = DataGetLength(classList) / sizeof(struct metaClassRecord *);
-       classes = (struct metaClassRecord **) DataGetPtr(classList);
-       for (i = 0; i < nclass; i++) {
-           thisClass = classes[i];
-           if (!strcmp(thisClass->fClassName, cname))
-               return thisClass;
-       }
-    }
-
-    return NULL;
-}
-
-// Add the class 'cname' to the list of known OSObject based classes
-// Note 'sym' is the <cname>.superClass symbol. 
-static Boolean
-recordClass(struct fileRecord *file, const char *cname, const struct nlist *sym)
-{
-    char *supername = NULL;
-    const char *classname = NULL;
-    struct metaClassRecord newClass;
-    char strbuffer[1024];
-
-    // Only do the work actual work to find the super class if we are
-    // not currently working on  the kernel.  The kernel is the end
-    // of all superclass chains as by definition the kernel is binary
-    // compatible with itself.
-    if (!file->fIsKernel) {
-       const char *dot;
-       const struct nlist *supersym;
-       const struct section *section;
-       struct sectionRecord *sectionRec;
-       unsigned char sectind = sym->n_sect;
-       const char *superstr;
-       void **location;
-
-       // We can't resolve anything that isn't in a real section
-       // Note that the sectind is starts at one to make room for the
-       // NO_SECT flag but the fNSects field isn't offset so we have a
-       // '>' test.  Which means this isn't an OSObject based class
-       if (sectind == NO_SECT || sectind > file->fNSects)
-           return true;
-    
-       sectionRec = file->fSections + sectind - 1;
-       section = sectionRec->fSection;
-       location = (void **) ( file->fMachO + section->offset
-                           + sym->n_value - section->addr );
-    
-       supersym = findSymbolRefAtLocation(file, sectionRec, location);
-       if (!supersym)
-           return true;        // No superclass symbol then it isn't an OSObject.
-
-       // Find string in file and skip leading '_' and find last '.'
-       superstr = symbolname(file, supersym) + 1;
-       dot = strrchr(superstr, '.');
-       if (!dot || strcmp(dot, kGMetaSuffix))
-           return true;        // Not an OSObject superclass so ignore it.
-
-       supername = (char *) malloc(dot - superstr + 1);
-       strncpy(supername, superstr, dot - superstr);
-       supername[dot - superstr] = '\0';
-    }
-
-    do {
-       break_if(getClass(file->fClassList, cname),
-           ("Duplicate class %s in %s\n", cname, file->fPath));
-    
-       snprintf(strbuffer, sizeof(strbuffer), "%s%s", kVTablePrefix, cname);
-       newClass.fVTableSym = findSymbolByName(file, strbuffer);
-       break_if(!newClass.fVTableSym,
-           ("Can't find vtable %s in %s\n", cname, file->fPath));
-
-       newClass.fFile = file;
-       newClass.fSuperName = supername;
-       newClass.fPatchedVTable = NULL;
-    
-       // Can't use cname as it may be a stack variable
-       // However the vtable's string has the class name as a suffix
-       // so why don't we use that rather than mallocing a string.
-       classname = symbolname(file, newClass.fVTableSym)
-               + sizeof(kVTablePrefix) - 1;
-       break_if(!addClass(file, &newClass, classname), 
-                   ("recordClass - no memory?\n"));
-
-       return true;
-    } while (0);
-    
-    if (supername)
-       free(supername);
-
-    return false;
-}
-
-static Boolean getMetaClassGraph(struct fileRecord *file)
-{
-    const struct nlist *sym;
-    const char *strbase;
-    int i, nsyms;
-
-    // Search the symbol table for the local symbols that are generated
-    // by the metaclass system.  There are three metaclass variables
-    // that are relevant.
-    //
-    //   <ClassName>.metaClass A pointer to the meta class structure.
-    //  <ClassName>.superClass A pointer to the super class's meta class.
-    //  <ClassName>.gMetaClass The meta class structure itself.
-    //  ___vt<ClassName>       The VTable for the class <ClassName>.
-    //
-    // In this code I'm going to search for any symbols that
-    // ends in kSuperClassSuffix as this indicates this class is a conforming
-    // OSObject subclass and will need to be patched, and it also
-    // contains a pointer to the super class's meta class structure.
-    strbase = file->fStringBase;
-    sym = file->fLocalSyms;
-    for (i = 0, nsyms = file->fNLocal; i < nsyms; i++, sym++) {
-       const char *symname;
-       const char *dot;
-       char classname[1024];
-       unsigned char n_type = sym->n_type & (N_TYPE | N_EXT);
-
-       // Check that the symbols is a global and that it has a name.
-       if (((N_SECT | N_EXT) != n_type && (N_ABS | N_EXT) != n_type)
-       ||  !sym->n_un.n_strx)
-           continue;
-
-       // Only search from the last '.' in the symbol.
-       // but skip the leading '_' in all symbols first.
-       symname = strbase + sym->n_un.n_strx + 1;
-       dot = strrchr(symname, '.');
-       if (!dot || strcmp(dot, kSuperClassSuffix))
-           continue;
-
-       // Got a candidate so hand it over for class processing.
-       return_if(dot - symname >= (int) sizeof(classname),
-           false, ("Symbol %s is too long\n", symname));
-
-       bcopy(symname, classname, dot - symname);
-       classname[dot - symname] = '\0';
-       if (!recordClass(file, classname, sym))
-           return false;
-    }
-
-    return_if(!file->fClassList, false, ("Internal error, "
-             "getMetaClassGraph(%s) found no classes", file->fPath)); 
-
-    DEBUG_LOG(("Found %d classes in %x for %s\n",
-       DataGetLength(file->fClassList)/sizeof(void*),
-       file->fClassList, file->fPath));
-
-    return true;
-}
-
-static Boolean mergeOSObjectsForFile(const struct fileRecord *file)
-{
-    int i, nmerged;
-    Boolean foundDuplicates = false;
-
-DEBUG_LOG(("Merging file %s\n", file->fPath)); // @@@ gvdl:
-
-    if (!file->fClassList)
-       return true;
-
-    if (!sMergedFiles) {
-       sMergedFiles = DataCreate(0);
-       return_if(!sMergedFiles, false,
-           ("Unable to allocate memory metaclass list\n", file->fPath));
-    }
-
-    // Check to see if we have already merged this file
-    nmerged = DataGetLength(sMergedFiles) / sizeof(struct fileRecord *);
-    for (i = 0; i < nmerged; i++) {
-       if (file == ((void **) DataGetPtr(sMergedFiles))[i])
-           return true;
-    }
-
-    if (!sMergeMetaClasses) {
-       sMergeMetaClasses = DataCreate(0);
-       return_if(!sMergeMetaClasses, false,
-           ("Unable to allocate memory metaclass list\n", file->fPath));
-    }
-    else {     /* perform a duplicate check */
-       int i, j, cnt1, cnt2;
-       struct metaClassRecord **list1, **list2;
-
-       list1 = (struct metaClassRecord **) DataGetPtr(file->fClassList);
-       cnt1  = DataGetLength(file->fClassList)  / sizeof(*list1);
-       list2 = (struct metaClassRecord **) DataGetPtr(sMergeMetaClasses);
-       cnt2  = DataGetLength(sMergeMetaClasses) / sizeof(*list2);
-
-       for (i = 0; i < cnt1; i++) {
-           for (j = 0; j < cnt2; j++) {
-               if (!strcmp(list1[i]->fClassName, list2[j]->fClassName)) {
-                   errprintf("duplicate class %s in %s & %s\n",
-                             list1[i]->fClassName,
-                             file->fPath, list2[j]->fFile->fPath);
-               }
-           }
-       }
-    }
-    if (foundDuplicates)
-       return false;
-
-    return_if(!DataAppendBytes(sMergedFiles, &file, sizeof(file)), false,
-       ("Unable to allocate memory to merge %s\n", file->fPath));
-
-    return_if(!DataAppendData(sMergeMetaClasses, file->fClassList), false,
-       ("Unable to allocate memory to merge %s\n", file->fPath));
-
-    if (file == sKernelFile)
-       sMergedKernel = true;
-
-    return true;
-}
-
-// Returns a pointer to the base of the section offset by the sections
-// base address.  The offset is so that we can add nlist::n_values directly
-// to this address and get a valid pointer in our memory.
-static unsigned char *
-getSectionForSymbol(const struct fileRecord *file, const struct nlist *symb,
-                   void ***endP)
-{
-    const struct section *section;
-    unsigned char sectind;
-    unsigned char *base;
-
-    sectind = symb->n_sect;    // Default to symbols section
-    if ((symb->n_type & N_TYPE) == N_ABS && file->fIsKernel) {
-       // Absolute symbol so we have to iterate over our sections
-       for (sectind = 1; sectind <= file->fNSects; sectind++) {
-           unsigned long start, end;
-
-           section = file->fSections[sectind - 1].fSection;
-           start = section->addr;
-           end   = start + section->size;
-           if (start <= symb->n_value && symb->n_value < end) {
-               // Found the relevant section
-               break;
-           }
-       }
-    }
-
-    // Is the vtable in a valid section?
-    return_if(sectind == NO_SECT || sectind > file->fNSects,
-       (unsigned char *) -1,
-       ("%s isn't a valid kext, bad section reference\n", file->fPath));
-
-    section = file->fSections[sectind - 1].fSection;
-
-    // for when we start walking the vtable so compute offset's now.
-    base = file->fMachO + section->offset;
-    *endP = (void **) (base + section->size);
-
-    return base - section->addr;       // return with addr offset
-}
-
-static Boolean resolveKernelVTable(struct metaClassRecord *metaClass)
-{
-    const struct fileRecord *file;
-    struct patchRecord *patchedVTable;
-    void **curEntry, **vtableEntries, **endSection;
-    unsigned char *sectionBase;
-    struct patchRecord *curPatch;
-    int classSize;
-
-    // Should never occur but it doesn't cost us anything to check.
-    if (metaClass->fPatchedVTable)
-       return true;
-
-DEBUG_LOG(("Kernel vtable %s\n", metaClass->fClassName));      // @@@ gvdl:
-
-    // Do we have a valid vtable to patch?
-    return_if(!metaClass->fVTableSym,
-       false, ("Internal error - no class vtable symbol?\n"));
-
-    file = metaClass->fFile;
-
-    // If the metaClass we are being to ask is in the kernel then we
-    // need to do a quick scan to grab the fPatchList in a reliable format
-    // however we don't need to check the superclass in the kernel
-    // as the kernel vtables are always correct wrt themselves.
-    // Note this ends the superclass chain recursion.
-    return_if(!file->fIsKernel,
-       false, ("Internal error - resolveKernelVTable not kernel\n"));
-
-    if (file->fNoKernelExecutable) {
-       // Oh dear attempt to map the kernel's VM into my memory space
-       return_if(file->fNoKernelExecutable, false,
-           ("Internal error - fNoKernelExecutable not implemented yet\n"));
-    }
-
-    // We are going to need the base and the end
-    sectionBase = getSectionForSymbol(file, metaClass->fVTableSym, &endSection);
-    if (-1 == (long) sectionBase)
-       return false;
-
-    vtableEntries  = (void **) (sectionBase + metaClass->fVTableSym->n_value);
-    curEntry = vtableEntries + kVTablePreambleLen;
-    for (classSize = 0; curEntry < endSection && *curEntry; classSize++)
-       curEntry++;
-
-    return_if(*curEntry, false, ("Bad kernel image, short section\n"));
-
-    patchedVTable = (struct patchRecord *)
-       malloc((classSize + 1) * sizeof(struct patchRecord));
-    return_if(!patchedVTable, false, ("resolveKernelVTable - no memory\n"));
-
-    // Copy the vtable of this class into the patch table
-    curPatch = patchedVTable;
-    curEntry = vtableEntries + kVTablePreambleLen;
-    for (; *curEntry; curEntry++, curPatch++) {
-       curPatch->fSymbol = (struct nlist *) 
-           findSymbolByAddress(file, *curEntry);
-       curPatch->fType = kSymbolLocal;
-    }
-
-    // Tag the end of the patch vtable
-    curPatch->fSymbol = NULL;
-    metaClass->fPatchedVTable = patchedVTable;
-
-    return true;
-}
-
-// reloc->fPatch must contain a valid pointer on entry
-static struct nlist *
-getNewSymbol(struct fileRecord *file,
-            const struct relocRecord *reloc, const char *supername)
-{
-    unsigned int size, i, namelen;
-    struct nlist **sym;
-    struct nlist *msym;
-    const char *strbase;
-    struct relocation_info *rinfo;
-    long strx;
-
-    if (!file->fNewSymbols) {
-       file->fNewSymbols = DataCreate(0);
-       return_if(!file->fNewSymbols, NULL,
-           ("Unable to allocate new symbol table for %s\n", file->fPath));
-    }
-
-    // Make sure we have a string table as well for the new symbol
-    if (!file->fNewStrings) {
-       file->fNewStrings = DataCreate(0);
-       return_if(!file->fNewStrings, NULL,
-           ("Unable to allocate string table for %s\n", file->fPath));
-    }
-
-    rinfo = (struct relocation_info *) reloc->fRInfo;
-    size = DataGetLength(file->fNewSymbols) / sizeof(struct nlist *);
-    sym = (const struct nlist **) DataGetPtr(file->fNewSymbols);
-    // remember that the n_strx for new symbols names is negated
-    strbase = (const char *)
-               DataGetPtr(file->fNewStrings) - file->fSymtab->strsize;
-    for (i = 0; i < size; i++, sym++) {
-        const char *symname = strbase - (*sym)->n_un.n_strx;
-
-       if (!strcmp(symname, supername)) {
-           rinfo->r_symbolnum = i + file->fSymtab->nsyms;
-           file->fSymbolsDirty = true; 
-           return *sym;
-       }
-    }
-
-    // Assert that this is a vaild symbol.  I need this condition to be true
-    // for the later code to make non-zero.  So the first time through I'd 
-    // better make sure that it is 0.
-    return_if(reloc->fSymbol->n_sect, NULL,
-       ("Undefined symbol entry with non-zero section %s:%s\n",
-       file->fPath, symbolname(file, reloc->fSymbol)));
-
-    msym = (struct nlist *) malloc(sizeof(struct nlist));
-    return_if(!msym,
-       NULL, ("Unable to create symbol table entry for %s\n", file->fPath));
-
-    // If we are here we didn't find the symbol so create a new one now
-    if (!DataAppendBytes(file->fNewSymbols, &msym, sizeof(msym))) {
-       free(msym);
-       return_if(true,
-           NULL, ("Unable to grow symbol table for %s\n", file->fPath));
-    }
-
-    namelen = strlen(supername) + 1;
-    strx = DataGetLength(file->fNewStrings);
-    if (!DataAppendBytes(file->fNewStrings, supername, namelen)) {
-       free(msym);
-       DataAddLength(file->fNewSymbols, -sizeof(struct nlist)); // Undo harm
-       return_if(true, NULL,
-                ("Unable to grow string table for %s\n", file->fPath));
-    }
-
-    // Offset the string index by the original string table size
-    // and negate the address to indicate that this is a 'new' symbol
-    msym->n_un.n_strx = -(strx + file->fSymtab->strsize);
-    msym->n_type = (N_EXT | N_UNDF);
-    msym->n_sect = NO_SECT;
-    msym->n_desc = 0;
-    msym->n_value = 0;
-
-    // Mark the old symbol as being potentially deletable I can use the
-    // n_sect field as the input symbol must be of type N_UNDF which means
-    // that the n_sect field must be set to NO_SECT otherwise it is an
-    // in valid input file.
-    ((struct nlist *) reloc->fSymbol)->n_un.n_strx
-       = -reloc->fSymbol->n_un.n_strx;    
-    ((struct nlist *) reloc->fSymbol)->n_sect = (unsigned char) -1;
-
-    rinfo->r_symbolnum = i + file->fSymtab->nsyms;
-    file->fSymbolsDirty = true; 
-    return msym;
-}
-
-static struct nlist *
-fixOldSymbol(struct fileRecord *file,
-            const struct relocRecord *reloc, const char *supername)
-{
-    unsigned int namelen;
-    struct nlist *sym = (struct nlist *) reloc->fSymbol;
-    const char *oldname = symbolname(file, sym);
-
-    // assert(sym->n_un.n_strx >= 0);
-
-    namelen = strlen(supername);
-    if (namelen < strlen(oldname)) {
-       // Overwrite old string in string table
-       strcpy((char *) oldname, supername);
-    }
-    else {
-       long strx;
-
-       // Make sure we have a string table as well for this symbol
-       if (!file->fNewStrings) {
-           file->fNewStrings = DataCreate(0);
-           return_if(!file->fNewStrings, NULL,
-               ("Unable to allocate string table for %s\n", file->fPath));
-       }
-
-       // Find the end of the fNewStrings data structure;
-       strx = DataGetLength(file->fNewStrings);
-       return_if(!DataAppendBytes(file->fNewStrings, supername, namelen + 1),
-           NULL, ("Unable to grow string table for %s\n", file->fPath));
-
-       // now add the current table size to the offset
-       sym->n_un.n_strx = strx + file->fSymtab->strsize;
-    }
-
-    // Mark the symbol as having been processed by negating it.
-    // Also note that we have dirtied the file and need to repair the
-    // symbol table.
-    sym->n_un.n_strx = -sym->n_un.n_strx;
-    file->fSymbolsDirty = true; 
-    return sym;
-}
-
-static enum patchState
-symbolCompare(const struct fileRecord *file,
-             const struct nlist *classsym,
-             const char *supername)
-{
-    const char *classname;
-    
-
-    // Check to see if the target function is locally defined
-    // if it is then we can assume this is a local vtable override
-    if ((classsym->n_type & N_TYPE) != N_UNDF)
-       return kSymbolLocal;
-
-    // Check to see if both symbols point to the same symbol name
-    // if so then we are still identical.
-    classname = symbolname(file, classsym);
-    if (!strcmp(classname, supername))
-       return kSymbolIdentical;
-
-    // Right now we know that the target's vtable entry is different from the
-    // superclass' vtable entry.  This means that we will have to apply a
-    // patch to the current entry, however before returning lets check to
-    // see if we have a _RESERVEDnnn field 'cause we can use this as a
-    // registration point that must align between vtables.
-    if (!strncmp(supername, kReservedPrefix, sizeof(kReservedPrefix) - 1))
-       return kSymbolMismatch;
-
-    // OK, we have a superclass difference where the superclass doesn't
-    // reference a pad function so assume that the superclass is correct.
-    if (!strncmp(classname, kReservedPrefix, sizeof(kReservedPrefix) - 1))
-       return kSymbolPadUpdate; 
-    else
-       return kSymbolSuperUpdate;
-}
-
-static Boolean patchVTable(struct metaClassRecord *metaClass)
-{
-    struct metaClassRecord *super = NULL;
-    struct fileRecord *file;
-    struct patchRecord *patchedVTable;
-    struct relocRecord **curReloc, **vtableRelocs, **endSection;
-    unsigned char *sectionBase;
-    int classSize;
-
-    // Should never occur but it doesn't cost us anything to check.
-    if (metaClass->fPatchedVTable)
-       return true;
-
-    // Do we have a valid vtable to patch?
-    return_if(!metaClass->fVTableSym,
-       false, ("Internal error - no class vtable symbol?\n"));
-
-    file = metaClass->fFile;
-
-    // If the metaClass we are being to ask is in the kernel then we
-    // need to do a quick scan to grab the fPatchList in a reliable format
-    // however we don't need to check the superclass in the kernel
-    // as the kernel vtables are always correct wrt themselves.
-    // Note this ends the superclass chain recursion.
-    return_if(file->fIsKernel,
-       false, ("Internal error - patchVTable shouldn't used for kernel\n"));
-
-    if (!metaClass->fSuperName)
-       return false;
-
-    // The class isn't in the kernel so make sure that the super class 
-    // is patched before patching ouselves.
-    super = getClass(sMergeMetaClasses, metaClass->fSuperName);
-    return_if(!super, false, ("Can't find superclass for %s : %s \n",
-       metaClass->fClassName, metaClass->fSuperName));
-
-    // Superclass recursion if necessary
-    if (!super->fPatchedVTable) {
-       Boolean res;
-
-       if (super->fFile->fIsKernel)
-           res = resolveKernelVTable(super);
-       else
-           res = patchVTable(super);
-       if (!res)
-           return false;
-    }
-
-DEBUG_LOG(("Patching %s\n", metaClass->fClassName));   // @@@ gvdl:
-
-    // We are going to need the base and the end
-
-    sectionBase = getSectionForSymbol(file,
-       metaClass->fVTableSym, (void ***) &endSection);
-    if (-1 == (long) sectionBase)
-       return false;
-
-    vtableRelocs  = (struct relocRecord **)
-                       (sectionBase + metaClass->fVTableSym->n_value);
-    curReloc = vtableRelocs + kVTablePreambleLen;
-    for (classSize = 0; curReloc < endSection && *curReloc; classSize++)
-       curReloc++;
-
-    return_if(*curReloc, false,
-       ("%s isn't a valid kext, short section\n", file->fPath));
-
-    patchedVTable = (struct patchRecord *)
-       malloc((classSize + 1) * sizeof(struct patchRecord));
-    return_if(!patchedVTable, false, ("patchedVTable - no memory\n"));
-
-    do {
-       struct patchRecord *curPatch;
-       struct nlist *symbol;
-
-       curPatch = patchedVTable;
-       curReloc = vtableRelocs + kVTablePreambleLen;
-
-       // Grab the super table patches if necessary
-       // Can't be patching a kernel table as we don't walk super
-       // class chains in the kernel symbol space.
-       if (super && super->fPatchedVTable) {
-           const struct patchRecord *spp;
-
-           spp = super->fPatchedVTable;
-
-           for ( ; spp->fSymbol; curReloc++, spp++, curPatch++) {
-               const char *supername =
-                   symbolname(super->fFile, spp->fSymbol);
-
-                symbol = (struct nlist *) (*curReloc)->fSymbol;
-
-               curPatch->fType = symbolCompare(file, symbol, supername);
-               switch (curPatch->fType) {
-               case kSymbolIdentical:
-               case kSymbolLocal:
-                   break;
-    
-               case kSymbolSuperUpdate:
-                   symbol = getNewSymbol(file, (*curReloc), supername);
-                   break;
-
-               case kSymbolPadUpdate:
-                   symbol = fixOldSymbol(file, (*curReloc), supername);
-                   break;
-
-               case kSymbolMismatch:
-                   errprintf("%s is not compatible with its %s superclass, "
-                             "broken superclass?\n",
-                             metaClass->fClassName, super->fClassName);
-                   goto abortPatch;
-
-               default:
-                   errprintf("Internal error - unknown patch type\n");
-                   goto abortPatch;
-               }
-               if (symbol) {
-                   curPatch->fSymbol = symbol;
-                   (*curReloc)->fSymbol = symbol;
-               }
-               else
-                   goto abortPatch;
-           }
-       }
-
-       // Copy the remainder of this class' vtable into the patch table
-       for (; *curReloc; curReloc++, curPatch++) {
-           // Local reloc symbols
-           curPatch->fType = kSymbolLocal;
-           curPatch->fSymbol = (struct nlist *) (*curReloc)->fSymbol;
-       }
-
-       // Tag the end of the patch vtable
-       curPatch->fSymbol = NULL;
-
-       metaClass->fPatchedVTable = patchedVTable;
-       return true;
-    } while(0);
-
-abortPatch:
-    if (patchedVTable)
-       free(patchedVTable);
-
-    return false;
-}
-
-static Boolean growImage(struct fileRecord *file, vm_size_t delta)
-{
-#if !KERNEL
-    file->fMachOSize += delta;
-    return (file->fMachO + file->fMachOSize <= file->fPadEnd);
-#else /* KERNEL */
-    vm_address_t startMachO, endMachO, endMap;
-    vm_offset_t newMachO;
-    vm_size_t newsize;
-    unsigned long i, nsect, nclass = 0;
-    struct metaClassRecord **classes = NULL;
-    struct sectionRecord *section;
-    kern_return_t ret;
-
-    startMachO = (vm_address_t) file->fMachO;
-    endMachO = startMachO + file->fMachOSize + delta;
-    endMap   = (vm_address_t) file->fMap + file->fMapSize;
-
-    // Do we have room in the current mapped image
-    if (endMachO < round_page(endMap)) {
-       file->fMachOSize += delta;
-       return true;
-    }
-
-    newsize = endMachO - startMachO;
-    if (newsize < round_page(file->fMapSize)) {
-       // We have room in the map if we shift the macho image within the
-       // current map.  We will have to patch up pointers into the object.
-       newMachO = (vm_offset_t) file->fMap;
-       bcopy((char *) startMachO, (char *) newMachO, file->fMachOSize);
-    }
-    else if (file->fIsKmem) {
-       // kmem_alloced mapping so we can try a kmem_realloc
-       ret = kmem_realloc(kernel_map,
-                         (vm_address_t) file->fMap,
-                         (vm_size_t) file->fMapSize,
-                         &newMachO,
-                         newsize);
-       if (KERN_SUCCESS != ret)
-           return false;
-
-       // If the mapping didn't move then just return
-       if ((vm_address_t) file->fMap == newMachO) {
-           file->fMachOSize = file->fMapSize = newsize;
-           return true;
-       }
-
-       // We have relocated the kmem image so we are going to have to
-       // move all of the pointers into the image around.
-    }
-    else {
-       // The image doesn't have room for us and I can't kmem_realloc
-       // then I just have to bite the bullet and copy the object code
-       // into a bigger memory segment
-       ret = kmem_alloc(kernel_map, &newMachO, newsize);
-       
-       if (KERN_SUCCESS != ret)
-           return false;
-       bcopy((char *) startMachO, (void *) newMachO, file->fMachOSize);
-       file->fIsKmem = true;
-    }
-
-
-    file->fMap = file->fMachO = (unsigned char *) newMachO;
-    file->fMapSize = newsize;
-    file->fMachOSize += delta; // Increment the image size
-
-    // If we are here then we have shifted the object image in memory
-    // I really should change all of my pointers into the image to machO offsets
-    // but I have run out of time.  So I'm going to very quickly go over the
-    // cached data structures and add adjustments to the addresses that are
-    // affected.  I wonder how long it will take me to get them all.
-    //
-    // For every pointer into the MachO I need to add an adjustment satisfying
-    // the following simultanous equations
-    // addr_old = macho_old + fixed_offset
-    // addr_new = macho_new + fixed_offset     therefore:
-    // addr_new = addr_old + (macho_new - macho_old)
-#define REBASE(addr, delta)    ( ((vm_address_t) (addr)) += (delta) )
-    delta = newMachO - startMachO;
-
-    // Rebase the cached in object 'struct symtab_command' pointer
-    REBASE(file->fSymtab, delta);
-
-    // Rebase the cached in object 'struct nlist' pointer for all symbols
-    REBASE(file->fSymbolBase, delta);
-
-    // Rebase the cached in object 'struct nlist' pointer for local symbols
-    REBASE(file->fLocalSyms, delta);
-
-    // Rebase the cached in object 'char' pointer for the string table
-    REBASE(file->fStringBase, delta);
-
-    // Ok now we have to go over all of the relocs one last time
-    // to clean up the pad updates which had their string index negated
-    // to indicate that we have finished with them.
-    section = file->fSections;
-    for (i = 0, nsect = file->fNSects; i < nsect; i++, section++)
-       REBASE(section->fSection, delta);
-
-    // We only ever grow images that contain class lists so dont bother
-    // the check if file->fClassList is non-zero 'cause it can't be
-    // assert(file->fClassList);
-    nclass = DataGetLength(file->fClassList)
-          / sizeof(struct metaClassRecord *);
-    classes = (struct metaClassRecord **) DataGetPtr(file->fClassList);
-    for (i = 0; i < nclass; i++) {
-       struct patchRecord *patch;
-
-       for (patch = classes[i]->fPatchedVTable; patch->fSymbol; patch++) {
-           vm_address_t symAddr = (vm_address_t) patch->fSymbol;
-           if (symAddr >= startMachO && symAddr < endMachO)
-               REBASE(patch->fSymbol, delta);
-       }
-    }
-
-
-#undef REBASE
-
-    return true;
-
-#endif /* KERNEL */
-}
-
-static Boolean
-prepareFileForLink(struct fileRecord *file)
-{
-    unsigned long i, last, numnewsyms, newsymsize, newstrsize;
-    struct sectionRecord *section;
-    struct nlist **symp, *sym;
-
-    // If we didn't even do a pseudo 'relocate' and dirty the image
-    // then we can just return now.
-    if (!file->fImageDirty)
-       return true;
-
-DEBUG_LOG(("Linking 2 %s\n", file->fPath));    // @@@ gvdl:
-
-    // We have to go over all of the relocs to repair the damage
-    // that we have done to the image when we did our 'relocation'
-    section = file->fSections;
-    for (i = 0, last = file->fNSects; i < last; i++, section++) {
-       unsigned char *sectionBase;
-       struct relocRecord *rec;
-       unsigned long j, nreloc;
-
-       if (section->fRelocCache) {
-           sectionBase = file->fMachO + section->fSection->offset;
-           nreloc = section->fSection->nreloc;
-           rec = (struct relocRecord *) DataGetPtr(section->fRelocCache);
-    
-           // We will need to repair the reloc list 
-           for (j = 0; j < nreloc; j++, rec++) {
-               void **entry;
-               struct nlist *sym;
-    
-               // Repair Damage to object image
-               entry = (void **) (sectionBase + rec->fRInfo->r_address);
-               *entry = rec->fValue;
-
-               // Check if the symbol that this relocation entry points
-               // to is marked as erasable 
-               sym = (struct nlist *) rec->fSymbol;
-               if (sym && sym->n_type == (N_EXT | N_UNDF)
-               &&  sym->n_sect == (unsigned char) -1) {
-                   // clear mark now
-                   sym->n_un.n_strx = -sym->n_un.n_strx;
-                   sym->n_sect = NO_SECT;
-               }
-           }
-
-           // Clean up the fRelocCache we don't need it any more.
-           DataRelease(section->fRelocCache);
-           section->fRelocCache = 0;
-       }
-    }
-    file->fImageDirty = false; // Image is clean
-
-    // If we didn't dirty the symbol table then just return
-    if (!file->fSymbolsDirty)
-       return true;
-
-    // calculate total file size increase and check against padding
-    numnewsyms  = (file->fNewSymbols)? DataGetLength(file->fNewSymbols) : 0;
-    numnewsyms /= sizeof(struct nlist *);
-    newsymsize  = numnewsyms * sizeof(struct nlist);
-    newstrsize  = (file->fNewStrings)? DataGetLength(file->fNewStrings) : 0;
-    newstrsize  = (newstrsize + 3) & ~3;       // Round to nearest word
-    
-    return_if(!growImage(file, newsymsize + newstrsize),
-       false, ("Unable to patch the extension, no memory\n", file->fPath));
-
-    // Push out the new symbol table if necessary
-    if (numnewsyms) {
-       caddr_t base;
-
-       // Move the string table out of the way of the grown symbol table
-       // Don't forget the '\0' from end of string table.
-       base = (caddr_t) file->fStringBase;
-       bcopy(base, base + newsymsize, file->fSymtab->strsize);
-       file->fStringBase     += newsymsize;
-       file->fSymtab->stroff += newsymsize;
-
-       // Now append the new symbols to the symbol table.
-       base = (caddr_t) file->fSymbolBase
-            + file->fSymtab->nsyms * sizeof(struct nlist);
-       symp = (struct nlist **) DataGetPtr(file->fNewSymbols);
-       for (i = 0; i < numnewsyms; i++, base += sizeof(struct nlist), symp++)
-           bcopy(*symp, base, sizeof(struct nlist));
-       file->fSymtab->nsyms  += numnewsyms;
-
-       DataRelease(file->fNewSymbols);
-       file->fNewSymbols = 0;
-    }
-
-    // Push out the new string table if necessary
-    if (newstrsize) {
-       caddr_t base = (caddr_t) file->fStringBase + file->fSymtab->strsize;
-       unsigned long actuallen = DataGetLength(file->fNewStrings);
-
-       // Set the last word in string table to zero before copying data
-       *((unsigned long *) ((char *) base + newstrsize - 4)) = 0;
-
-       // Now append the new strings to the end of the file
-       bcopy((caddr_t) DataGetPtr(file->fNewStrings), base, actuallen);
-
-       file->fSymtab->strsize += newstrsize;
-
-       DataRelease(file->fNewStrings);
-       file->fNewStrings = 0;
-    }
-
-    // Repair the symbol table string index values
-    // I used negative strx's to indicate symbol has been processed
-    sym = file->fSymbolBase;
-    for (i = 0, last = file->fSymtab->nsyms; i < last; i++, sym++) {
-       if (sym->n_un.n_strx < 0) {
-           if ( sym->n_type != (N_EXT | N_UNDF)
-           || (unsigned char) -1 != sym->n_sect)
-               sym->n_un.n_strx = -sym->n_un.n_strx;
-           else {
-               // This symbol isn't being used by any vtable's reloc so
-               // convert it into an N_ABS style of symbol, remove the
-               // external bit and null out the symbol name.
-               bzero(sym, sizeof(*sym));
-               sym->n_type = N_ABS;    /* type flag, see below */
-           }
-       }
-    }
-    file->fSymbolsDirty = false;
-
-    return true;
-}
-
-Boolean
-#if KERNEL
-kld_file_map(const char *pathName,
-            unsigned char *map,
-            size_t mapSize,
-            Boolean isKmem)
-#else
-kld_file_map(const char *pathName)
-#endif /* KERNEL */
-{
-    struct fileRecord file, *fp = 0;
-
-    // Already done no need to repeat
-    fp = getFile(pathName);
-    if (fp)
-       return true;
-
-    bzero(&file, sizeof(file));
-    file.fPath = pathName;
-
-#if KERNEL
-    file.fMap = map;
-    file.fMapSize = mapSize;
-    file.fIsKmem = isKmem;
-#else
-    if (!mapObjectFile(&file))
-       return false;
-#endif /* KERNEL */
-
-    do {
-       const struct machOMapping {
-           struct mach_header h;
-           struct load_command c[1];
-       } *machO;
-       const struct load_command *cmd;
-       const struct nlist *sym;
-       unsigned int i, firstlocal, nsyms;
-       unsigned long strsize;
-       const char *strbase;
-       Boolean foundOSObject;
-
-       if (!findBestArch(&file))
-           break;
-    
-       machO = (const struct machOMapping *) file.fMachO;
-       if (file.fMachOSize < machO->h.sizeofcmds)
-           break;
-
-       // If the file type is MH_EXECUTE then this must be a kernel
-       // as all Kernel extensions must be of type MH_OBJECT
-       for (i = 0, cmd = &machO->c[0]; i < machO->h.ncmds; i++) {
-           if (cmd->cmd == LC_SEGMENT) {
-               return_if(!parseSegments(&file, (struct segment_command *) cmd),
-                   false, ("%s isn't a valid mach-o, bad segment\n",
-                           file.fPath));
-           }
-           else if (cmd->cmd == LC_SYMTAB)
-               file.fSymtab = (struct symtab_command *) cmd;
-    
-           cmd = (struct load_command *) ((UInt8 *) cmd + cmd->cmdsize);
-       }
-       break_if(!file.fSymtab,
-           ("%s isn't a valid mach-o, no symbols\n", file.fPath));
-
-       // we found a link edit segment so recompute the bases
-       if (file.fSymbolBase) {
-           struct segment_command *link =
-               (struct segment_command *) file.fSymbolBase;
-
-           file.fSymbolBase = (struct nlist *)
-               (link->vmaddr + (file.fSymtab->symoff - link->fileoff));
-           file.fStringBase = (char *)
-               (link->vmaddr + (file.fSymtab->stroff - link->fileoff));
-           break_if( ( (caddr_t) file.fStringBase + file.fSymtab->strsize
-                     > (caddr_t) link->vmaddr + link->vmsize ),
-               ("%s isn't a valid mach-o le, bad symbols\n", file.fPath));
-       }
-       else {
-           file.fSymbolBase = (struct nlist *)
-               (file.fMachO + file.fSymtab->symoff); 
-           file.fStringBase = (char *)
-               (file.fMachO + file.fSymtab->stroff); 
-           break_if( ( file.fSymtab->stroff + file.fSymtab->strsize
-                     > file.fMachOSize ),
-               ("%s isn't a valid mach-o, bad symbols\n", file.fPath));
-       }
-
-       // If this file the kernel and do we have an executable image
-       file.fIsKernel = (MH_EXECUTE == machO->h.filetype);
-       file.fNoKernelExecutable = (vm_page_size == file.fSymtab->symoff)
-                               && (file.fSections[0].fSection->size == 0);
-
-       // Search for the first non-stab symbol in table
-       strsize = file.fSymtab->strsize;
-       strbase = file.fStringBase;
-       sym = file.fSymbolBase;
-       firstlocal = 0;
-       foundOSObject = false;
-       for (i = 0, nsyms = file.fSymtab->nsyms; i < nsyms; i++, sym++) {
-           if ((unsigned long) sym->n_un.n_strx > strsize)
-               break;
-
-           // Find the first exported symbol
-           if ( !file.fLocalSyms && (sym->n_type & N_EXT) ) {
-               file.fLocalSyms = sym;
-               firstlocal = i;
-           }
-
-           // Find the a OSObject based subclass by searching for symbols
-           // that have a suffix of '.superClass'
-           if (!foundOSObject
-           && ((sym->n_type & (N_TYPE | N_EXT)) == (N_SECT | N_EXT)
-            || (sym->n_type & (N_TYPE | N_EXT)) == (N_ABS | N_EXT))
-           &&  sym->n_un.n_strx) {
-               const char *dot;
-
-               // Only search from the last '.' in the symbol.
-               // but skip the leading '_' in all symbols first.
-               dot = strrchr(strbase + sym->n_un.n_strx + 1, '.');
-               if (dot && !strcmp(dot, kSuperClassSuffix))
-                   foundOSObject = true;
-           }
-
-           // Find the last local symbol
-           if ( !file.fNLocal && sym->n_type == (N_EXT | N_UNDF) )
-               file.fNLocal = i - firstlocal;
-
-       }
-       break_if(i < nsyms,
-           ("%s isn't a valid mach-o, bad symbol strings\n", file.fPath));
-
-       break_if(!file.fLocalSyms, ("%s has no symbols?\n", file.fPath));
-
-       // If we don't have any undefined symbols then all symbols
-       // must be local so just compute it now if necessary.
-       if ( !file.fNLocal )
-           file.fNLocal = i - firstlocal;
-
-       fp = addFile(&file);
-       if (!fp)
-           break;
-
-       if (foundOSObject && !getMetaClassGraph(fp))
-           break;
-
-       if (file.fIsKernel)
-           sKernelFile = fp;
-#if KERNEL
-       if (!sKernelFile) {
-           extern struct mach_header _mh_execute_header;
-           extern struct segment_command *getsegbyname(char *seg_name);
-    
-           struct segment_command *sg;
-           size_t kernelSize;
-           Boolean ret;
-
-           sg = (struct segment_command *) getsegbyname(kLinkEditSegName); 
-           break_if(!sg, ("Can't find kernel link edit segment\n"));
-    
-           kernelSize = sg->vmaddr + sg->vmsize - (size_t) &_mh_execute_header;
-           ret = kld_file_map(kld_basefile_name,
-               (unsigned char *) &_mh_execute_header, kernelSize,
-               /* isKmem */ false);
-           break_if(!ret, ("kld can't map kernel file"));
-       }
-#endif /* KERNEL */
-
-       return true;
-    } while(0);
-
-    removeFile(&file);
-
-    return false;
-}
-
-void *kld_file_getaddr(const char *pathName, long *size)
-{
-    struct fileRecord *file = getFile(pathName);
-
-    if (!file)
-       return 0;
-
-    if (size)
-       *size = file->fMachOSize;
-
-    return file->fMachO;
-}
-
-void *kld_file_lookupsymbol(const char *pathName, const char *symname)
-{
-    struct fileRecord *file = getFile(pathName);
-    const struct nlist *sym;
-    const struct section *section;
-    unsigned char *sectionBase;
-    unsigned char sectind;
-
-    return_if(!file,
-       NULL, ("Unknown file %s\n", pathName));
-
-    sym = findSymbolByName(file, symname);
-
-    // May be a non-extern symbol so look for it there
-    if (!sym) {
-       const char *strbase;
-       unsigned int i, nsyms;
-
-       sym = file->fSymbolBase;
-       strbase = file->fStringBase;
-       for (i = 0, nsyms = file->fSymtab->nsyms; i < nsyms; i++, sym++) {
-           if ( (sym->n_type & N_EXT) ) {
-               sym = 0;
-               break;  // Terminate search when we hit an extern
-           }
-           if ( (sym->n_type & N_STAB) )
-               continue;
-           if ( !strcmp(symname, strbase + sym->n_un.n_strx) )
-               break;
-       }
-    }
-
-    return_if(!sym,
-       NULL, ("Unknown symbol %s in %s\n", symname, pathName));
-
-    // Is the vtable in a valid section?
-    sectind = sym->n_sect;
-    return_if(sectind == NO_SECT || sectind > file->fNSects, NULL,
-       ("Malformed object file, invalid section reference for %s in %s\n",
-           symname, pathName));
-
-    section = file->fSections[sectind - 1].fSection;
-    sectionBase = file->fMachO + section->offset - section->addr;
-
-    return (void *) (sectionBase + sym->n_value);
-}
-
-Boolean kld_file_merge_OSObjects(const char *pathName)
-{
-    struct fileRecord *file = getFile(pathName);
-
-    return_if(!file,
-       false, ("Internal error - unable to find file %s\n", pathName));
-
-    return mergeOSObjectsForFile(file);
-}
-
-Boolean kld_file_patch_OSObjects(const char *pathName)
-{
-    struct fileRecord *file = getFile(pathName);
-    struct metaClassRecord **classes;
-    unsigned long i, last;
-
-    return_if(!file,
-       false, ("Internal error - unable to find file %s\n", pathName));
-
-DEBUG_LOG(("Patch file %s\n", pathName));      // @@@ gvdl:
-
-    // If we don't have any classes we can return now.
-    if (!file->fClassList)
-       return true;
-
-    // If we haven't alread merged the kernel then do it now
-    if (!sMergedKernel && sKernelFile)
-       mergeOSObjectsForFile(sKernelFile);
-    return_if(!sMergedKernel, false, ("Internal error no kernel?\n"));
-
-    if (!mergeOSObjectsForFile(file))
-       return false;
-
-    // Patch all of the classes in this executable
-    last = DataGetLength(file->fClassList) / sizeof(void *);
-    classes = (struct metaClassRecord **) DataGetPtr(file->fClassList);
-    for (i = 0; i < last; i++) {
-       if (!patchVTable(classes[i]))
-           return false;
-    }
-
-    return true;
-}
-
-Boolean kld_file_prepare_for_link()
-{
-    if (sMergedFiles) {
-       unsigned long i, nmerged = 0;
-       struct fileRecord **files;
-    
-       // Check to see if we have already merged this file
-       nmerged = DataGetLength(sMergedFiles) / sizeof(struct fileRecord *);
-       files = (struct fileRecord **) DataGetPtr(sMergedFiles);
-       for (i = 0; i < nmerged; i++) {
-           if (!prepareFileForLink(files[i]))
-               return false;
-       }
-    }
-
-    // Clear down the meta class table and merged file lists
-    DataRelease(sMergeMetaClasses);
-    DataRelease(sMergedFiles);
-    sMergedFiles = sMergeMetaClasses = NULL;
-    sMergedKernel = false;
-
-    return true;
-}
-
-void kld_file_cleanup_all_resources()
-{
-    unsigned long i, nfiles;
-
-#if KERNEL     // @@@ gvdl:
-    // Debugger("kld_file_cleanup_all_resources");
-#endif
-
-    if (!sFilesTable || !(nfiles = DataGetLength(sFilesTable)))
-       return; // Nothing to do just return now
-
-    nfiles /= sizeof(struct fileRecord *);
-    for (i = 0; i < nfiles; i++)
-       removeFile(((void **) DataGetPtr(sFilesTable))[i]);
-
-    // Don't really have to clean up anything more as the whole
-    // malloc engine is going to be released and I couldn't be bothered.
-}
-
-#if !KERNEL
-Boolean kld_file_debug_dump(const char *pathName, const char *outName)
-{
-    const struct fileRecord *file = getFile(pathName);
-    int fd;
-    Boolean ret = false;
-
-    return_if(!file, false, ("Unknown file %s for dumping\n", pathName));
-
-    fd = open(outName, O_WRONLY|O_CREAT|O_TRUNC, 0666);
-    return_if(-1 == fd, false, ("Can't create output file %s - %s(%d)\n",
-       outName, strerror(errno), errno));
-
-    do {
-       break_if(-1 == write(fd, file->fMachO, file->fMachOSize),
-           ("Can't dump output file %s - %s(%d)\n", 
-               outName, strerror(errno), errno));
-       ret = true;
-    } while(0);
-
-    close(fd);
-
-    return ret;
-}
-#endif /* !KERNEL */
-
diff --git a/kmodload.tproj/kld_patch.h b/kmodload.tproj/kld_patch.h
deleted file mode 100644 (file)
index b0e6058..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2001 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * History:
- *  2001-05-30         gvdl    Initial implementation of the vtable patcher.
- */
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-#if KERNEL
-extern Boolean kld_file_map(const char *pathName,
-                           unsigned char *map, size_t mapSize,
-                           Boolean isKmem);
-#else
-extern Boolean kld_file_map(const char *pathName);
-
-extern void *
-    kld_file_lookupsymbol(const char *pathName, const char *symbolname);
-
-Boolean kld_file_debug_dump(const char *pathName, const char *outName);
-#endif /* KERNEL */
-
-extern void *kld_file_getaddr(const char *pathName, long *size);
-
-extern Boolean kld_file_merge_OSObjects(const char *pathName);
-
-extern Boolean kld_file_patch_OSObjects(const char *pathName);
-
-extern Boolean kld_file_prepare_for_link();
-
-extern void kld_file_cleanup_all_resources();
-
-__END_DECLS
diff --git a/kmodload.tproj/kmodload.8 b/kmodload.tproj/kmodload.8
deleted file mode 100644 (file)
index a5e6914..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-.\"
-.\" Copyright (c) 1997 Doug Rabson
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    $Id: kmodload.8,v 1.3 2000/12/15 05:33:01 lindak Exp $
-.\"
-.Dd April 8, 1999
-.Dt KMODLOAD 8
-.Os FreeBSD
-.Sh NAME
-.Nm kmodload
-.Nd loads and starts a kernel module
-.Sh SYNOPSIS
-.Nm kmodload
-.Op Fl v
-.Op Fl k Ar kernelfile
-.Op Fl d Ar dependencyfile
-.Op Fl o Ar symbolfile
-.Ar modulefile
-.Sh DESCRIPTION
-The
-.Nm
-loads the file 
-.Ar modulefile
-into the kernel and starts its execution.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl v
-Be more verbose.
-.It Fl k Ar kernelfile
-Use alternate file
-.Ar kernelfile
-instead of default file /mach for linking
-.Ar modulefile .
-.It Fl d Ar dependencyfile
-Add symbols from
-.Ar dependencyfile
-to kernel symbols prior to linking of
-.Ar modulefile .
-The file 
-.Ar dependencyfile
-must already be loaded.
-.It Fl o Ar symbolfile
-Creates file named
-.Ar symbolfile
-that contains statically linked output suitable to use with
-.Xr gdb 1 
-for remote debugging.
-.El
-.Sh FILES
-.Bl -tag -width /modules -compact
-.It Pa /System/Library/Extensions
-directory containing loadable kernel modules.
-.Sh DIAGNOSTICS
-The
-.Nm
-utility exits with a status of 0 on success.
-A status of 1 indicates a usage error.
-A status of 2 indicates a indicates a permissions error.
-A status of 3 indicates a problem with linking the module.
-A status of 4 indicates a internal or system error.
-A status of 5 indicates the module has already been loaded. 
-.Sh SEE ALSO
-.Xr kmodstat 8 ,
-.Xr kmodsyms 8 ,
-.Xr kmodunload 8
-.Sh HISTORY
-The
-.Nm
-command is based on the command kldload written by
-.An Doug Rabson Aq dfr@FreeBSD.org
diff --git a/kmodload.tproj/kmodload.c b/kmodload.tproj/kmodload.c
deleted file mode 100644 (file)
index 4108282..0000000
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*-
- * Copyright (c) 1997 Doug Rabson
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original code from:
- *     "kldload.c,v 1.5 1998/07/06 06:58:32 charnier Exp"
- */
-#ifndef lint
-static const char rcsid[] =
-       "$Id: kmodload.c,v 1.10 2001/08/02 20:57:01 lindak Exp $";
-#endif /* not lint */
-
-#include <stdlib.h>
-#include <err.h>
-#include <sys/file.h>
-#include <nlist.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/mman.h>
-
-#include <paths.h>
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <mach/mach_host.h>
-#include <mach-o/kld.h>
-#include <mach-o/fat.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-
-#include "kld_patch.h"
-
-#define KMOD_ERROR_USAGE       1
-#define KMOD_ERROR_PERMS       2
-#define KMOD_ERROR_LOADING     3               
-#define KMOD_ERROR_INTERNAL    4
-#define KMOD_ERROR_ALREADY     5
-
-#define kKMOD_INFO_SYMBOLNAME "_kmod_info"
-#define kKmodsymsName "kmodsyms"
-
-static mach_port_t kernel_port;
-static mach_port_t kernel_priv_port;
-
-static kmod_info_t *module_dependencies = 0;
-static vm_address_t kernel_alloc_address = 0;
-static unsigned long kernel_alloc_size = 0;
-static vm_address_t kernel_load_address = 0;
-static unsigned long kernel_load_size = 0;
-static unsigned long kernel_hdr_size = 0;
-static unsigned long kernel_hdr_pad = 0;
-static unsigned long faked_kernel_load_address = 0;
-
-static kmod_info_t *loaded_modules = 0;
-static int loaded_count = 0;
-
-static char *progname = "program name?";
-static int kmodsyms = 0;
-static int link_addrs_set = 0;
-static int verbose = 0;
-
-static char *debugdumpfile = NULL;
-
-// must not be static; kld library calls
-extern void                    kld_error_vprintf(const char *format, va_list ap);
-static void                    e_printf(const char *fmt, ...);
-static void                    v_printf(const char *fmt, ...);
-
-static void                    machwarn(int error, const char *message);
-static void                    macherr(int error, const char *message);
-
-static unsigned long   linkedit_address(unsigned long size,
-                                                unsigned long headers_size);
-static void                    abort_load(int exitcode, const char *fmt, ...);
-static void                    map_and_patch(const char *base,
-                                                                 const char **library_paths,
-                                                                 const char *module);
-static void                    link_base(const char *base,
-                                         const char **dependency_paths,
-                                         const vm_address_t *dependency_addrs);
-static void                    clear_globals(void);
-static kmod_info_t *map_module(const char *filename);
-static struct mach_header *link_module(const char *filename, 
-                                            const char *output);
-static vm_address_t            update_kmod_info(struct mach_header *mach_header);
-static kmod_t                  load_module(struct mach_header *mach_header,
-                                           vm_address_t info);
-static void                    set_module_dependencies(kmod_t id);
-static void                    start_module(kmod_t id);
-
-static void
-usage(void)
-{
-       if (kmodsyms) {
-               fprintf(stderr, "usage: %s [-v] [-k kernelfile] [-d dependencyfile] -o symbolfile modulefile\n", progname);
-               fprintf(stderr, "       %s [-v]  -k kernelfile  [-d dependencyfile@address] -o symbolfile modulefile@address\n",
-                       progname);
-       } else {
-               fprintf(stderr, "usage: %s [-v] [-k kernelfile] [-d dependencyfile] [-o symbolfile] modulefile\n", progname);
-       }
-       fflush(stderr);
-       exit(KMOD_ERROR_USAGE);
-}
-
-int
-main(int argc, char** argv)
-{
-       int c, r, i;
-       char * kernel = _PATH_UNIX;
-       int kernel_set = 0;
-       char * gdbfile = 0;
-#define MAX_DEPENDANCIES       128
-       char * dependencies[MAX_DEPENDANCIES];
-       vm_address_t loaded_addresses[MAX_DEPENDANCIES];
-       int dependency_count = 0;
-       struct mach_header *rld_header;
-
-       char * module_path = "";
-       vm_address_t module_info = 0;
-       vm_address_t module_faked_address = 0;
-       kmod_t module_id = 0;
-       kmod_info_t *file_kinfo;
-
-       if ((progname = strrchr(argv[0], '/')) == NULL)
-               progname = argv[0];
-       else
-               ++progname;
-
-       kmodsyms = !strcmp(progname, kKmodsymsName);
-
-       // XXX things to add:
-       //  -p data string to send as outofband data on start
-       //  -P data file to send as outofband data on start
-
-       while ((c = getopt(argc, argv, "D:d:o:k:v")) != -1)
-               switch (c) {
-               case 'd':
-                       dependencies[dependency_count] = optarg;
-                       if (kmodsyms) {
-                               char *address;
-                               if ((address = strrchr(optarg, '@'))) {
-                                       *address++ = 0;
-                                       loaded_addresses[dependency_count] = strtoul(address, NULL, 0);
-                                       link_addrs_set++;
-                               } else {
-                                       loaded_addresses[dependency_count] = 0;
-                               }
-                       }
-                       if (++dependency_count == MAX_DEPENDANCIES) {
-                               abort_load(KMOD_ERROR_INTERNAL, 
-                                       "internal error, dependency count overflow."); 
-                       }
-                       break;
-               case 'o':
-                       gdbfile = optarg;
-                       break;
-               case 'k':
-                       kernel_set++;
-                       kernel = optarg;
-                       break;
-               case 'v':
-                       verbose = 1;
-                       break;
-               case 'D':
-                       debugdumpfile = optarg;
-                       break;
-               default:
-                       usage();
-               }
-       argc -= optind;
-       argv += optind;
-
-       dependencies[dependency_count] = 0;
-       loaded_addresses[dependency_count] = 0;
-
-       if (argc != 1) usage();
-
-       module_path = argv[0];
-
-       if (kmodsyms) {
-               char *address;
-
-               if (!gdbfile) usage();
-
-               // check for @address
-               if ((address = strrchr(module_path, '@'))) {
-                       *address++ = 0;
-                       module_faked_address = strtoul(address, NULL, 0);
-                       link_addrs_set++;
-               } else {
-                       module_faked_address = 0;
-               }
-
-               // if any arg uses @address then they all must be and the kernel must be set
-               if (link_addrs_set) {
-                       if (!kernel_set) usage();
-                       if (!module_faked_address) usage();
-                       for (i=0; i < dependency_count; i++) {
-                               if (!loaded_addresses[i]) usage();
-                       }
-               }
-       }
-
-       // map the module if possible, map_module will fail if there is a problem
-       file_kinfo = map_module(module_path);
-
-       if (!link_addrs_set) {
-               kmod_info_t *k;
-
-               // we only need the kernel port if we need to lookup loaded kmods
-               r = task_for_pid(mach_task_self(), 0, &kernel_port);
-               machwarn(r, "unable to get kernel task port");
-               if (KERN_SUCCESS != r) {
-                       abort_load(KMOD_ERROR_PERMS,
-                               "You must be running as root to load modules in the kernel.");
-               }
-
-               //get loaded modules
-               r = kmod_get_info(kernel_port, (void *)&loaded_modules, &loaded_count);  // never freed
-               macherr(r, "kmod_get_info() failed");
-
-               // check to see if the module has been loaded
-               k = loaded_modules;
-               while (k) {
-                       if (!strcmp(k->name, file_kinfo->name)) {
-                               if (!kmodsyms) {
-                                       abort_load(KMOD_ERROR_ALREADY,
-                                               "the module named '%s' is already loaded.", k->name); 
-                               } else {
-                                       module_faked_address = k->address;
-                               }
-                               break;
-                       }
-                       k = (k->next) ? (k + 1) : 0;
-               }
-
-               if (kmodsyms && !module_faked_address) {
-                       abort_load(KMOD_ERROR_USAGE,
-                               "the module named '%s' has not been loaded.", file_kinfo->name);
-               }
-               
-               //XXX it would be nice to be able to verify this is the correct kernel
-               //XXX by comparing the kernel version strings (once we have them)
-       }
-
-       map_and_patch(kernel, dependencies, module_path);
-       if (debugdumpfile) kld_file_debug_dump(module_path, debugdumpfile);
-
-       // Tell the kld linker where to get its load address from
-       kld_address_func(linkedit_address);
-
-       // link the kernel along with any dependencies
-       link_base(kernel, dependencies, loaded_addresses);
-
-       if (kmodsyms) {
-           faked_kernel_load_address = module_faked_address;
-
-           if (!faked_kernel_load_address) {
-                       abort_load(KMOD_ERROR_INTERNAL,
-                         "internal error, fell thru without setting module load address.");
-           }
-       }
-
-       rld_header = link_module(module_path, gdbfile);
-       module_info = update_kmod_info(rld_header);
-
-       if (kmodsyms) return 0;
-
-       // we need the priv port to load modules into the kernel
-       kernel_priv_port = mach_host_self();  /* if we are privileged */
-
-       module_id = load_module(rld_header, module_info);
-       set_module_dependencies(module_id);
-       start_module(module_id);
-
-       return 0;
-}
-
-static void
-machwarn(int error, const char *message)
-{
-       if (KERN_SUCCESS != error)
-               e_printf("%s: %s", message, mach_error_string(error));
-}
-
-static void
-macherr(int error, const char *message)
-{
-       if (KERN_SUCCESS != error)
-               abort_load(KMOD_ERROR_INTERNAL,
-                       "%s: %s", message, mach_error_string(error));
-}
-
-static kmod_info_t *map_module(const char *filename)
-{
-       kmod_info_t *file_kinfo;
-
-       if (!kld_file_map(filename))
-               exit(KMOD_ERROR_LOADING);
-
-       file_kinfo = kld_file_lookupsymbol(filename, kKMOD_INFO_SYMBOLNAME);
-       if (!file_kinfo) {
-               abort_load(KMOD_ERROR_USAGE,
-                       "%s is not a valid kernel module.", filename);
-       }
-       
-       return file_kinfo;
-}
-
-static void
-map_and_patch(const char *base, const char **library_paths, const char *module)
-{
-       if (!kld_file_map(base))
-               exit(KMOD_ERROR_INTERNAL);
-       if (!kld_file_merge_OSObjects(base))
-               abort_load(KMOD_ERROR_LOADING, NULL);
-
-       if (*library_paths) {
-               char **library;
-               for (library = library_paths; *library; library++) {
-                       map_module(*library);
-                       if (!kld_file_patch_OSObjects(*library))
-                               abort_load(KMOD_ERROR_LOADING, NULL);
-               }
-       }
-
-       // Patch the vtables of the object module we are about to load
-       // The module has already been mapped in the main() routine as part
-       // of validation
-       if (!kld_file_patch_OSObjects(module))
-               abort_load(KMOD_ERROR_LOADING, NULL);
-
-       // During the patch up process the mapped images were modified
-       // to avoid having to allocate more data than necessary.
-       // Now we have to give the patcher a chance to clean up after itself.
-       if (!kld_file_prepare_for_link())
-               abort_load(KMOD_ERROR_LOADING, NULL);
-}
-
-static void
-link_base(const char *base,
-         const char **dependency_paths,
-         const vm_address_t *dependency_addrs)
-{
-       struct mach_header *rld_header;
-       char *base_addr;
-       long base_size;
-       int ok;
-
-       // Get the address and size of the base, usually the kernel
-       base_addr = kld_file_getaddr(base, &base_size);
-       if (!base_addr)
-               exit(KMOD_ERROR_INTERNAL);      // Error reported by kld library.
-
-       ok = kld_load_basefile_from_memory(base, base_addr, base_size);
-       fflush(stdout);
-       if (!ok)
-               abort_load(KMOD_ERROR_LOADING, "kld_load_basefile(%s) failed.", base); 
-
-       if (*dependency_paths) {
-               char **dependency = dependency_paths;
-               const vm_address_t *load_addr = dependency_addrs;
-
-               while (*dependency) {
-                       kmod_info_t *file_kinfo;
-
-                       // Find the kmod_info structure in the image.
-                       file_kinfo =
-                               kld_file_lookupsymbol(*dependency, kKMOD_INFO_SYMBOLNAME);
-                       if (!file_kinfo) {
-                               abort_load(KMOD_ERROR_USAGE, 
-                                       "%s is not a valid kernel module.", *dependency);
-                       }
-
-                       // find the address that this dependency is loaded at
-                       if (kmodsyms && *load_addr) {
-                               faked_kernel_load_address = *load_addr;
-                       } else {
-                               kmod_info_t *k;
-                               kmod_info_t *tmp;
-                               int found_it = 0;
-
-                               // match up file version of kmod_info with kernel version
-                               k = loaded_modules;
-                               while (k) {
-                                       if (!strcmp(k->name, file_kinfo->name)) {
-                                               if (strcmp(k->version, file_kinfo->version)) {
-                                                       e_printf("loaded kernel module '%s' version differs.", *dependency);
-                                                       abort_load(KMOD_ERROR_LOADING, 
-                                                               "loaded version '%s', file version '%s'.",
-                                                               k->version, file_kinfo->version);
-                                               }
-                                               found_it++;
-                                               break;
-                                       }
-                                       k = (k->next) ? (k + 1) : 0;
-                               }
-                               if (!found_it) {
-                                       abort_load(KMOD_ERROR_USAGE, 
-                                               "kernel module '%s' is not loaded.", *dependency);
-                               }       
-                       
-                               tmp = malloc(sizeof(kmod_info_t));
-                               if (!tmp)
-                                       abort_load(KMOD_ERROR_LOADING, "no memory.");
-
-                               *tmp = *k;
-                               tmp->next = module_dependencies;
-                               module_dependencies = tmp;
-
-                               faked_kernel_load_address = k->address;
-                       }
-
-                       rld_header = link_module(*dependency, 0);
-
-                       (void) update_kmod_info(rld_header);
-
-                       dependency++; load_addr++;
-               }
-               /* make sure we clear these so clean up does the right thing. */
-               clear_globals();
-       }
-}
-
-#if !defined(page_round)
-#define page_trunc(p) ((int)(p)&~(vm_page_size-1))
-#define page_round(p) page_trunc((int)(p)+vm_page_size-1)
-#endif
-
-static unsigned long
-linkedit_address(unsigned long size, unsigned long headers_size)
-{
-    int r;
-    unsigned long round_segments_size;
-    unsigned long round_headers_size;
-    unsigned long round_size;
-
-    kernel_load_size = size;  // The actual size allocated by kld_load...
-
-    round_headers_size = page_round(headers_size);
-    round_segments_size = page_round(size - headers_size);
-    round_size =  round_headers_size + round_segments_size;
-
-    kernel_alloc_size = round_size;
-    kernel_hdr_size = headers_size;  // will need to be rounded to page *after* link.
-    kernel_hdr_pad = round_headers_size - headers_size;
-
-    if (faked_kernel_load_address) {
-        kernel_load_address = faked_kernel_load_address + kernel_hdr_pad;
-        v_printf("Returning fake load address of 0x%8x", kernel_load_address);
-        return kernel_load_address;
-    }
-    if (kmodsyms) {
-               abort_load(KMOD_ERROR_INTERNAL, 
-                       "internal error, almost tried to alloc kernel memory."); 
-    }
-
-    r = vm_allocate(kernel_port, &kernel_alloc_address, 
-        kernel_alloc_size, TRUE);
-    macherr(r, "unable to allocate kernel memory");
-
-    v_printf("allocated %ld bytes in kernel space at 0x%8x",
-        kernel_alloc_size, kernel_alloc_address);
-
-    kernel_load_address = kernel_alloc_address + kernel_hdr_pad;
-
-    v_printf("Returning load address of 0x%x", kernel_load_address);
-
-    return kernel_load_address;
-}
-
-static void
-clear_globals(void)
-{
-    faked_kernel_load_address = 0;
-    kernel_alloc_address = 0;
-    kernel_alloc_size = 0;
-    kernel_load_address = 0;
-    kernel_load_size = 0;
-    kernel_hdr_size = 0;
-    kernel_hdr_pad = 0;
-    return;
-}
-
-static struct mach_header *
-link_module(const char *filename, const char *output)
-{
-       struct mach_header *rld_header;
-       char *object_addr;
-       long object_size;
-       int ok;
-
-       // Get the address of the thined MachO image.
-       object_addr = kld_file_getaddr(filename, &object_size);
-       if (!object_addr)
-               abort_load(KMOD_ERROR_LOADING, NULL);
-
-       ok = kld_load_from_memory(&rld_header, filename,
-                                                               object_addr, object_size, output);
-       fflush(stdout);
-       if (!ok)
-               abort_load(KMOD_ERROR_LOADING, "kld_load() failed.");
-
-       return rld_header;
-}
-
-// Update the kmod_info_t structure in the image to be laoded
-// Side effect of removing the kKMOD_INFO_SYMBOLNAME from the 
-// loaded symbol name space, otherwise we would have a duplicate
-// defined symbol failure
-vm_address_t
-update_kmod_info(struct mach_header *mach_header)
-{
-       char * symbol = kKMOD_INFO_SYMBOLNAME;
-       kmod_info_t *info;
-       unsigned long value;
-       int ok;
-
-       ok = kld_lookup(symbol, &value); fflush(stdout);
-       if (!ok)
-               abort_load(KMOD_ERROR_LOADING, "kld_lookup(%s) failed.", symbol);
-
-       ok = kld_forget_symbol(symbol); fflush(stdout);
-       if (!ok)
-               abort_load(KMOD_ERROR_LOADING, "kld_forget_symbol(%s) failed.", symbol);
-
-       /* Get the kmod info by translating from the kernel address at value.
-        */
-       info = (kmod_info_t *)(value - (unsigned long)kernel_load_address + (unsigned long)mach_header);
-       v_printf("kmod name: %s", info->name);
-       v_printf("kmod start @ 0x%x", (vm_address_t)info->start);
-       v_printf("kmod stop  @ 0x%x", (vm_address_t)info->stop);
-
-       /* Record link info in kmod info struct, rounding the hdr_size to fit
-        * the adjustment that was made.
-        */
-       info->address = kernel_alloc_address;
-       info->size = kernel_alloc_size;
-       info->hdr_size = page_round(kernel_hdr_size);
-
-       if (!info->start)
-               abort_load(KMOD_ERROR_LOADING, "invalid start address?");
-       else if (!info->stop)
-               abort_load(KMOD_ERROR_LOADING, "invalid stop address?");
-
-       return (vm_address_t)value;
-}
-
-static kmod_t 
-load_module(struct mach_header *mach_header, vm_address_t info)
-{
-    int r;
-    kmod_t id;
-    vm_address_t vm_buffer = 0;
-
-    r = vm_allocate(mach_task_self(), &vm_buffer,
-        kernel_alloc_size, TRUE);
-    macherr(r, "unable to vm_allocate() copy buffer");
-
-   /* Copy the linked segment data into the page-aligned buffer.
-    * Do not round the header size here.
-    */
-    bzero((void *)vm_buffer, kernel_alloc_size);
-    memcpy((void *)vm_buffer, mach_header, kernel_hdr_size);
-    memcpy((void *)vm_buffer + page_round(kernel_hdr_size),
-        (void *)((unsigned long)mach_header + kernel_hdr_size),
-        kernel_load_size - kernel_hdr_size);
-
-    // copy linked header into kernel address space
-    r = vm_write(kernel_port, kernel_alloc_address,
-        vm_buffer, kernel_alloc_size);
-    macherr(r, "unable to write module into kernel memory");
-
-    // let the kernel know about it
-    r = kmod_create(kernel_priv_port, info, &id);
-    macherr(r, "unable to register module with kernel");
-
-    v_printf("kmod id %d successfully created at 0x%x size %ld.\n", 
-        id, kernel_alloc_address, kernel_alloc_size);
-
-    // FIXME: make sure this happens even on failure
-
-    vm_deallocate(mach_task_self(), vm_buffer, kernel_alloc_size);
-    return id;
-}
-
-static void
-set_module_dependencies(kmod_t id)
-{
-       int r;
-       void * args = 0;
-       int argsCount= 0;
-       kmod_info_t *module = module_dependencies;
-
-       while (module) {
-
-               r = kmod_control(kernel_priv_port, KMOD_PACK_IDS(id, module->id), KMOD_CNTL_RETAIN, &args, &argsCount);
-               machwarn(r, "kmod_control(retain) failed");
-               if (r) {
-                       clear_globals();
-                       r = kmod_destroy(kernel_priv_port, id);
-                       macherr(r, "kmod_destroy failed");
-               }
-
-               v_printf("kmod id %d reference count was sucessfully incremented.", module->id);
-
-               module = module->next;
-       }
-}
-
-static void
-start_module(kmod_t id)
-{
-       int r;
-       void * args = 0;
-       int argsCount= 0;
-
-       r = kmod_control(kernel_priv_port, id, KMOD_CNTL_START, &args, &argsCount);
-       machwarn(r, "kmod_control(start) failed");
-       if (r) {
-               clear_globals();
-               kmod_destroy(kernel_priv_port, id);
-               macherr(r, "kmod_destroy failed");
-       }
-
-       v_printf("kmod id %d successfully started.", id);
-}
-
-static void e_printf(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       kld_error_vprintf(fmt, ap);
-       va_end(ap);
-}
-
-static void v_printf(const char *fmt, ...)
-{
-       va_list ap;
-       char msg[1024];
-
-       if (!verbose) return;
-
-       va_start(ap, fmt);
-       vsnprintf(msg, sizeof(msg), fmt, ap);
-       va_end(ap);
-
-       printf("%s: %s\n", progname, msg);
-}
-
-static void abort_load(int exitcode, const char *fmt, ...)
-{
-       if (fmt) {
-               va_list ap;
-       
-               va_start(ap, fmt);
-               kld_error_vprintf(fmt, ap);
-               va_end(ap);
-       }
-
-       if (!faked_kernel_load_address
-       && (kernel_alloc_address || kernel_alloc_size)) {       
-               int r;
-
-               v_printf("freeing %ld bytes in kernel space at 0x%x",
-                                       kernel_alloc_size, kernel_alloc_address);
-               r = vm_deallocate(kernel_port, kernel_alloc_address, kernel_alloc_size);
-               machwarn(r, "unable to cleanup kernel memory");
-       }
-
-       exit(exitcode);
-}
-
-__private_extern__ void
-kld_error_vprintf(const char *fmt, va_list ap)
-{
-    char msg[1024];
-
-    vsnprintf(msg, sizeof(msg), fmt, ap);
-    fprintf(stderr, "%s: %s", progname, msg);
-
-    fflush(stderr);
-}
diff --git a/kmodload.tproj/kmodsyms.8 b/kmodload.tproj/kmodsyms.8
deleted file mode 100644 (file)
index f3f18cf..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-.\"
-.\" Copyright (c) 1997 Doug Rabson
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    $Id: kmodsyms.8,v 1.2 2000/02/24 22:31:35 lindak Exp $
-.\"
-.Dd April 8, 1999
-.Dt KMODSYMS 8
-.Os FreeBSD
-.Sh NAME
-.Nm kmodsyms
-.Nd creates a statically linked symbol file for remote debugging
-.Sh SYNOPSIS
-.Nm kmodsyms
-.Op Fl v
-.Op Fl k Ar kernelfile
-.Op Fl d Ar dependencyfile
-.Fl o Ar symbolfile
-.Ar modulefile
-.Nm kmodsyms
-.Op Fl v
-.Fl k Ar kernelfile
-.Op Fl d Ar dependencyfile@address
-.Fl o Ar symbolfile
-.Ar modulefile@address
-.Sh DESCRIPTION
-The
-.Nm
-creates a statically linked symbol file for remote debugging using
-.Ar modulefile[@address] .
-If an address is specified for either the
-.Ar modulefile
-or
-.Ar dependacyfile
-they both must have the address tag. If addresses are specified it assumed that the command is being run on a different machine with a potentially different kernel, thus the
-.Ar kernelfile
-argument is also required.
-If addresses are not specified they taken from the currently running host machine.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl v
-Be more verbose.
-.It Fl k Ar kernelfile
-Use alternate file
-.Ar kernelfile
-instead of default file /mach for linking
-.Ar modulefile .
-.It Fl d Ar dependacyfile[@address]
-Add symbols from
-.Ar dependacyfile
-to kernel symbols prior to linking of
-.Ar modulefile .
-The file 
-.Ar dependacyfile
-must already be loaded.
-.It Fl o Ar symbolfile
-Creates file named
-.Ar symbolfile
-that contains statically linked output suitable to use with
-.Xr gdb 1 
-for remote debugging.
-.El
-.Sh FILES
-.Bl -tag -width /modules -compact
-.It Pa /System/Library/Extensions
-directory containing loadable kernel modules.
-.Sh DIAGNOSTICS
-The
-.Nm
-utility exits with a status of 0 on success. 
-A status of 1 indicates a usage error.
-A status of 2 indicates a indicates a permissions error.
-A status of 3 indicates a problem with linking the module.
-A status of 4 indicates a internal or system error.
-.Sh SEE ALSO
-.Xr kmodload 8 ,
-.Xr kmodstat 8 ,
-.Xr kmodunload 8
-.Sh HISTORY
-The
-.Nm
-command is based on the command kldload written by
-.An Doug Rabson Aq dfr@FreeBSD.org
diff --git a/kmodstat.tproj/Makefile b/kmodstat.tproj/Makefile
deleted file mode 100644 (file)
index 2c9f9ed..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Generated by the NeXT Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = kmodstat
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = kmodstat.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kmodstat.8
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /usr/sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/kmodstat.tproj/Makefile.postamble b/kmodstat.tproj/Makefile.postamble
deleted file mode 100644 (file)
index 5d1130d..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-###############################################################################
-#  Makefile.postamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile, which is imported after all other makefiles, to
-#  override attributes for a project's Makefile environment. This allows you  
-#  to take advantage of the environment set up by the other Makefiles. 
-#  You can also define custom rules at the end of this file.
-#
-###############################################################################
-# 
-# These variables are exported by the standard makefiles and can be 
-# used in any customizations you make.  They are *outputs* of
-# the Makefiles and should be used, not set.
-# 
-#  PRODUCTS: products to install.  All of these products will be placed in
-#       the directory $(DSTROOT)$(INSTALLDIR)
-#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-#  OFILE_DIR: Directory into which .o object files are generated.
-#  DERIVED_SRC_DIR: Directory used for all other derived files
-#
-#  ALL_CFLAGS:  flags to pass when compiling .c files
-#  ALL_MFLAGS:  flags to pass when compiling .m files
-#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
-#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
-#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
-#  ALL_LDFLAGS:  flags to pass when linking object files
-#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
-#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
-#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
-#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
-#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
-#
-#  NAME: name of application, bundle, subproject, palette, etc.
-#  LANGUAGES: langages in which the project is written (default "English")
-#  English_RESOURCES: localized resources (e.g. nib's, images) of project
-#  GLOBAL_RESOURCES: non-localized resources of project
-#
-#  SRCROOT:  base directory in which to place the new source files
-#  SRCPATH:  relative path from SRCROOT to present subdirectory
-#
-#  INSTALLDIR: Directory the product will be installed into by 'install' target
-#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
-#        to prefix this with DSTROOT when you use it.
-#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
-#       to prefix this with DSTROOT when you use it.
-#
-#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
-#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
-#      to -g)
-#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
-#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
-#      to -O)
-#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
-#      to -pg -DPROFILE)
-#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
-#      the include path (defaults to -I.)
-#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-#      passed to ld/libtool (defaults to nothing)
-
-
-# Library and Framework projects only:
-#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
-#      against the framework will run against the correct version even if
-#      the current version of the framework changes.  You may override this
-#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-#      development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
-        # User/group ownership 
-#INSTALL_AS_GROUP = wheel
-        # (probably want to set both of these) 
-#INSTALL_PERMISSIONS =
-        # If set, 'install' chmod's executable to this
-
-
-# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here.  Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where 
-# derived files should go.
-#
-
-after_install::
-       -mkdir -p ${DSTROOT}/usr/share/man/man8
-       -rm -f ${DSTROOT}/usr/share/man/man8/kmodstat.8
-       cp kmodstat.8 ${DSTROOT}/usr/share/man/man8/kmodstat.8
-       chmod og-w ${DSTROOT}/usr/share/man/man8/kmodstat.8
diff --git a/kmodstat.tproj/Makefile.preamble b/kmodstat.tproj/Makefile.preamble
deleted file mode 100644 (file)
index c1624b4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-###############################################################################
-#  Makefile.preamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile for configuring the standard application makefiles 
-#  associated with ProjectBuilder. It is included before the main makefile.
-#  In Makefile.preamble you set attributes for a project, so they are available
-#  to the project's makefiles.  In contrast, you typically write additional rules or 
-#  override built-in behavior in the Makefile.postamble.
-#  
-#  Each directory in a project tree (main project plus subprojects) should 
-#  have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible.  To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
-#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
-#      flags in OTHER_MFLAGS, etc.
-#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
-#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
-#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
-#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
-#      precompiling header files
-#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
-#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
-#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
-#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
-#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every 
-# stage of the make:
-#
-#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
-#    AFTER_PREBUILD: targets to build after installing headers for a subproject
-#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
-#    BEFORE_BUILD: targets to make before a build, but after subprojects
-#    AFTER_BUILD: targets to make after a build
-#
-#    BEFORE_INSTALL: targets to build before installing the product
-#    AFTER_INSTALL: targets to build after installing the product
-#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
-#         subproject
-#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-#    BEFORE_DEPEND: targets to build before building dependencies for a
-#        subproject
-#    AFTER_DEPEND: targets to build after building dependencies for a
-#        subproject
-#
-#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-#        updated every time the project is built.  If NO, the dependency
-#        file is only built when the depend target is invoked.
-
-# Framework-related variables:
-#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the framework's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-#    PUBLIC_HEADER_DIR:  Determines where public exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.  For library projects you should
-#       set this to something like /Developer/Headers/$(NAME).  Do not set
-#       this variable for framework projects unless you do not want the
-#       header files included in the framework.
-#    PRIVATE_HEADER_DIR:  Determines where private exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.
-#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
-#      whether the libraries produced are statically linked when they
-#      are used or if they are dynamically loadable. This defaults to
-#       DYNAMIC.
-#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the library's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-#
-#    INSTALL_AS_USER: owner of the intalled products (default root)
-#    INSTALL_AS_GROUP: group of the installed products (default wheel)
-#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-#      passed on the command line to recursive invocations of make.  Note that
-#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
-#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
-#      OTHER_RECURSIVE_VARIABLES. 
-
-# Additional headers to export beyond those in the PB.project:
-#    OTHER_PUBLIC_HEADERS
-#    OTHER_PROJECT_HEADERS
-#    OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/kmodstat.tproj/PB.project b/kmodstat.tproj/PB.project
deleted file mode 100644 (file)
index 8e9b705..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (); 
-        OTHER_LINKED = (kmodstat.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kmodstat.8); 
-    }; 
-    LANGUAGE = English; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
-    NEXTSTEP_INSTALLDIR = /usr/sbin; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_INSTALLDIR = /bin; 
-    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = kmodstat; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_INSTALLDIR = /Library/Executables; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/kmodstat.tproj/kmodstat.8 b/kmodstat.tproj/kmodstat.8
deleted file mode 100644 (file)
index 2353406..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-.\"
-.\" Copyright (c) 1997 Doug Rabson
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    $Id: kmodstat.8,v 1.1.1.1 2000/01/11 02:10:18 wsanchez Exp $
-.\"
-.Dd April 8, 1999
-.Dt KMODSTAT 8
-.Os FreeBSD
-.Sh NAME
-.Nm kmodstat
-.Nd display status of dynamically loaded kernel modules
-.Sh SYNOPSIS
-.Nm kmodstat
-.Op Fl i Ar id
-.Op Fl n Ar name
-.Sh DESCRIPTION
-The
-.Nm
-utility displays the status of any kernel modules dynamically
-linked into the kernel.
-.Pp
-The following options are available:
-.Bl -tag -width indentXX
-.It Fl i Ar id
-Display the status of only the kernel module with this ID.
-.It Fl n Ar name
-Display the status of only the kernel module with this name.
-.El
-.Sh DIAGNOSTICS
-The
-.Nm
-utility exits with a status of 0 on success
-and with a nonzero status if an error occurs.
-.Sh SEE ALSO
-.Xr kmodload 8 ,
-.Xr kmodsyms 8 ,
-.Xr kmodunload 8
-.Sh HISTORY
-The
-.Nm
-command is based on the command kldstat written by
-.An Doug Rabson Aq dfr@FreeBSD.org
diff --git a/kmodstat.tproj/kmodstat.c b/kmodstat.tproj/kmodstat.c
deleted file mode 100644 (file)
index 2f39c73..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*-
- * Copyright (c) 1997 Doug Rabson
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original code from:
- *     "kldstat.c,v 1.5 1998/11/07 00:29:09 des Exp";
- */
-
-#ifndef lint
-static const char rcsid[] =
-       "$Id: kmodstat.c,v 1.3 2000/04/26 21:27:57 lindak Exp $";
-#endif /* not lint */
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/param.h>
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <mach/mach_host.h>
-
-static void
-machwarn(int error, const char *message)
-{
-       if (error == KERN_SUCCESS) return;
-       fprintf(stderr, "kmodstat: %s: %s\n", message, mach_error_string(error));
-}
-
-static void
-macherr(int error, const char *message)
-{
-       if (error == KERN_SUCCESS) return;
-       fprintf(stderr, "kmodstat: %s: %s\n", message, mach_error_string(error));
-       exit(1);
-}
-
-static int
-kmod_compare(const void *a, const void *b)
-{
-       return (((kmod_info_t *)a)->id - ((kmod_info_t *)b)->id);
-}
-
-static void
-usage(void)
-{
-       fprintf(stderr, "usage: kmodstat [-i id] [-n name]\n");
-       exit(1);
-}
-
-int
-main(int argc, char** argv)
-{
-       int c, idset = 0, id = 0;
-       char* name = 0;
-       kmod_info_t *info, *k;
-       kmod_reference_t *r;
-       int i, j, rc, foundit, count, rcount;
-       mach_port_t kernel_port;
-
-       while ((c = getopt(argc, argv, "i:n:")) != -1)
-               switch (c) {
-               case 'i':
-                       idset++;
-                       id = atoi(optarg);
-                       break;
-               case 'n':
-                       name = optarg;
-                       break;
-               default:
-                       usage();
-               }
-       argc -= optind;
-       argv += optind;
-
-       if (!idset && !name && (argc == 1)) {
-               name = *argv;
-               argc--;
-       }
-    
-       if (argc != 0) usage();
-
-       rc = task_for_pid(mach_task_self(), 0, &kernel_port);
-       machwarn(rc, "unable to get kernel task port");
-       if (rc) {
-               fprintf(stderr, "kmodstat: Are you running as root?\n");
-               exit(1);
-       }
-
-       rc= kmod_get_info(kernel_port, (void *)&info, &count);
-       macherr(rc, "kmod_get_info() failed");
-
-       k = info; count = 0;
-       while (k) {
-               count++;
-               k  = (k->next) ? (k + 1) : 0;
-       }
-
-       k = info; r = (kmod_reference_t *)(info + count);
-       while (k) {
-               if ((rcount = (int)k->reference_list)) {
-                       k->reference_list = r;
-                       for (i=0; i < rcount; i++) {
-                               foundit = 0;
-                               for (j=0; j < count; j++) {
-                                       if (r->info == info[j].next) {
-                                               r->info = (kmod_info_t *)info[j].id;
-                                               foundit++;
-                                               break;
-                                       }
-                               }
-                               // force the id in here, the sorting below messes up the pointers
-                               if (!foundit) r->info = (kmod_info_t *)info[count - 1].id;
-                               r->next = r + 1;
-                               r++;
-                       }
-                       k->reference_list[rcount - 1].next = 0;
-               }
-               k  = (k->next) ? (k + 1) : 0;
-       }
-
-       printf("Id Refs Address    Size       Wired      Name (Version) <Linked Against>\n");
-
-       if (!count) return 0;
-
-       qsort(info, count, sizeof(kmod_info_t), kmod_compare);
-
-       if (idset || name) {
-               kmod_info_t *k = info;
-               int match_count = 0;
-               for (i=0; i < count; i++, k++) {
-                       if ((idset && id == k->id) || (name && !strcmp(k->name, name))) {
-                               info[match_count++] = *k;
-                       }
-               }
-               count = match_count;
-       } 
-       for (i=0; i < count; i++, info++) {
-               printf("%2d %4d %-10p %-10p %-10p %s (%s)",
-                      info->id, info->reference_count, (void *)info->address, 
-                      (void *)info->size, (void *)(info->size - info->hdr_size),
-                      info->name, info->version);
-
-               if ((r = info->reference_list)) {
-                       printf(" <%d", (int)r->info);
-                       r = r->next;
-                       while (r) {
-                               printf(" %d", (int)r->info);
-                               r = r->next;
-                       }
-                       printf(">");
-               }
-               printf("\n");
-       }
-
-       return 0;
-}
diff --git a/kmodunload.tproj/Makefile b/kmodunload.tproj/Makefile
deleted file mode 100644 (file)
index 1700393..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Generated by the NeXT Project Builder.
-#
-# NOTE: Do NOT change this file -- Project Builder maintains it.
-#
-# Put all of your customizations in files called Makefile.preamble
-# and Makefile.postamble (both optional), and Makefile will include them.
-#
-
-NAME = kmodunload
-
-PROJECTVERSION = 2.8
-PROJECT_TYPE = Tool
-
-CFILES = kmodunload.c
-
-OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kmodunload.8
-
-
-MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
-CODE_GEN_STYLE = DYNAMIC
-MAKEFILE = tool.make
-NEXTSTEP_INSTALLDIR = /sbin
-WINDOWS_INSTALLDIR = /Library/Executables
-PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
-DEBUG_LIBS = $(LIBS)
-PROF_LIBS = $(LIBS)
-
-
-
-
-NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc
-PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc
-NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe
-PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac
-
-include $(MAKEFILEDIR)/platform.make
-
--include Makefile.preamble
-
-include $(MAKEFILEDIR)/$(MAKEFILE)
-
--include Makefile.postamble
-
--include Makefile.dependencies
diff --git a/kmodunload.tproj/Makefile.postamble b/kmodunload.tproj/Makefile.postamble
deleted file mode 100644 (file)
index c2d62c5..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-###############################################################################
-#  Makefile.postamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile, which is imported after all other makefiles, to
-#  override attributes for a project's Makefile environment. This allows you  
-#  to take advantage of the environment set up by the other Makefiles. 
-#  You can also define custom rules at the end of this file.
-#
-###############################################################################
-# 
-# These variables are exported by the standard makefiles and can be 
-# used in any customizations you make.  They are *outputs* of
-# the Makefiles and should be used, not set.
-# 
-#  PRODUCTS: products to install.  All of these products will be placed in
-#       the directory $(DSTROOT)$(INSTALLDIR)
-#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
-#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
-#  OFILE_DIR: Directory into which .o object files are generated.
-#  DERIVED_SRC_DIR: Directory used for all other derived files
-#
-#  ALL_CFLAGS:  flags to pass when compiling .c files
-#  ALL_MFLAGS:  flags to pass when compiling .m files
-#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
-#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
-#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
-#  ALL_LDFLAGS:  flags to pass when linking object files
-#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
-#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
-#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
-#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
-#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
-#
-#  NAME: name of application, bundle, subproject, palette, etc.
-#  LANGUAGES: langages in which the project is written (default "English")
-#  English_RESOURCES: localized resources (e.g. nib's, images) of project
-#  GLOBAL_RESOURCES: non-localized resources of project
-#
-#  SRCROOT:  base directory in which to place the new source files
-#  SRCPATH:  relative path from SRCROOT to present subdirectory
-#
-#  INSTALLDIR: Directory the product will be installed into by 'install' target
-#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
-#        to prefix this with DSTROOT when you use it.
-#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
-#       to prefix this with DSTROOT when you use it.
-#
-#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
-#
-###############################################################################
-
-# Some compiler flags can be overridden here for certain build situations.
-#
-#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
-#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
-#      to -g)
-#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
-#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
-#      to -O)
-#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
-#      to -pg -DPROFILE)
-#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
-#      the include path (defaults to -I.)
-#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
-#      passed to ld/libtool (defaults to nothing)
-
-
-# Library and Framework projects only:
-#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
-#      against the framework will run against the correct version even if
-#      the current version of the framework changes.  You may override this
-#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
-#      development cycle, but be sure to restore it before installing.
-
-
-# Ownership and permissions of files installed by 'install' target
-
-#INSTALL_AS_USER = root
-        # User/group ownership 
-#INSTALL_AS_GROUP = wheel
-        # (probably want to set both of these) 
-#INSTALL_PERMISSIONS =
-        # If set, 'install' chmod's executable to this
-
-
-# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
-# down further with -x or, if they load no bundles, with no options at all).
-
-#STRIPFLAGS = -S
-
-
-#########################################################################
-# Put rules to extend the behavior of the standard Makefiles here.  Include them in
-# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
-#
-# You should avoid redefining things like "install" or "app", as they are
-# owned by the top-level Makefile API and no context has been set up for where 
-# derived files should go.
-#
-
-after_install::
-       -mkdir -p ${DSTROOT}/usr/share/man/man8
-       -rm -f ${DSTROOT}/usr/share/man/man8/kmodunload.8
-       cp kmodunload.8 ${DSTROOT}/usr/share/man/man8/kmodunload.8
-       chmod og-w ${DSTROOT}/usr/share/man/man8/kmodunload.8
diff --git a/kmodunload.tproj/Makefile.preamble b/kmodunload.tproj/Makefile.preamble
deleted file mode 100644 (file)
index c1624b4..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-###############################################################################
-#  Makefile.preamble
-#  Copyright 1997, Apple Computer, Inc.
-#
-#  Use this makefile for configuring the standard application makefiles 
-#  associated with ProjectBuilder. It is included before the main makefile.
-#  In Makefile.preamble you set attributes for a project, so they are available
-#  to the project's makefiles.  In contrast, you typically write additional rules or 
-#  override built-in behavior in the Makefile.postamble.
-#  
-#  Each directory in a project tree (main project plus subprojects) should 
-#  have its own Makefile.preamble and Makefile.postamble.
-###############################################################################
-#
-# Before the main makefile is included for this project, you may set:
-#
-#    MAKEFILEDIR: Directory in which to find $(MAKEFILE)
-#    MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make)
-
-# Compiler/linker flags added to the defaults:  The OTHER_* variables will be 
-# inherited by all nested sub-projects, but the LOCAL_ versions of the same
-# variables will not.  Put your -I, -D, -U, and -L flags in ProjectBuilder's
-# Build Attributes inspector if at all possible.  To override the default flags
-# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble.  The
-# variables below are *inputs* to the build process and distinct from the override
-# settings done (less often) in the Makefile.postamble.
-#
-#    OTHER_CFLAGS, LOCAL_CFLAGS:  additional flags to pass to the compiler
-#      Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m,
-#      .cc, .cxx, .C, and .M files.  There is no need to respecify the
-#      flags in OTHER_MFLAGS, etc.
-#    OTHER_MFLAGS, LOCAL_MFLAGS:  additional flags for .m files
-#    OTHER_CCFLAGS, LOCAL_CCFLAGS:  additional flags for .cc, .cxx, and ...C files
-#    OTHER_MMFLAGS, LOCAL_MMFLAGS:  additional flags for .mm and .M files
-#    OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS:  additional flags used when
-#      precompiling header files
-#    OTHER_LDFLAGS, LOCAL_LDFLAGS:  additional flags passed to ld and libtool
-#    OTHER_PSWFLAGS, LOCAL_PSWFLAGS:  additional flags passed to pswrap
-#    OTHER_RPCFLAGS, LOCAL_RPCFLAGS:  additional flags passed to rpcgen
-#    OTHER_YFLAGS, LOCAL_YFLAGS:  additional flags passed to yacc
-#    OTHER_LFLAGS, LOCAL_LFLAGS:  additional flags passed to lex
-
-# These variables provide hooks enabling you to add behavior at almost every 
-# stage of the make:
-#
-#    BEFORE_PREBUILD: targets to build before installing headers for a subproject
-#    AFTER_PREBUILD: targets to build after installing headers for a subproject
-#    BEFORE_BUILD_RECURSION: targets to make before building subprojects
-#    BEFORE_BUILD: targets to make before a build, but after subprojects
-#    AFTER_BUILD: targets to make after a build
-#
-#    BEFORE_INSTALL: targets to build before installing the product
-#    AFTER_INSTALL: targets to build after installing the product
-#    BEFORE_POSTINSTALL: targets to build before postinstalling every subproject
-#    AFTER_POSTINSTALL: targts to build after postinstalling every subproject
-#
-#    BEFORE_INSTALLHDRS: targets to build before installing headers for a 
-#         subproject
-#    AFTER_INSTALLHDRS: targets to build after installing headers for a subproject
-#    BEFORE_INSTALLSRC: targets to build before installing source for a subproject
-#    AFTER_INSTALLSRC: targets to build after installing source for a subproject
-#
-#    BEFORE_DEPEND: targets to build before building dependencies for a
-#        subproject
-#    AFTER_DEPEND: targets to build after building dependencies for a
-#        subproject
-#
-#    AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is
-#        updated every time the project is built.  If NO, the dependency
-#        file is only built when the depend target is invoked.
-
-# Framework-related variables:
-#    FRAMEWORK_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the framework's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-
-# Library-related variables:
-#    PUBLIC_HEADER_DIR:  Determines where public exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.  For library projects you should
-#       set this to something like /Developer/Headers/$(NAME).  Do not set
-#       this variable for framework projects unless you do not want the
-#       header files included in the framework.
-#    PRIVATE_HEADER_DIR:  Determines where private exported header files
-#      should be installed.  Do not include $(DSTROOT) in this value --
-#      it is prefixed automatically.
-#    LIBRARY_STYLE:  This may be either STATIC or DYNAMIC, and determines
-#      whether the libraries produced are statically linked when they
-#      are used or if they are dynamically loadable. This defaults to
-#       DYNAMIC.
-#    LIBRARY_DLL_INSTALLDIR:  On Windows platforms, this variable indicates
-#      where to put the library's DLL.  This variable defaults to 
-#      $(INSTALLDIR)/../Executables
-#
-#    INSTALL_AS_USER: owner of the intalled products (default root)
-#    INSTALL_AS_GROUP: group of the installed products (default wheel)
-#    INSTALL_PERMISSIONS: permissions of the installed product (default o+rX)
-#
-#    OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be
-#      passed on the command line to recursive invocations of make.  Note that
-#      the values in OTHER_*FLAGS are inherited by subprojects automatically --
-#      you do not have to (and shouldn't) add OTHER_*FLAGS to 
-#      OTHER_RECURSIVE_VARIABLES. 
-
-# Additional headers to export beyond those in the PB.project:
-#    OTHER_PUBLIC_HEADERS
-#    OTHER_PROJECT_HEADERS
-#    OTHER_PRIVATE_HEADERS
-
-# Additional files for the project's product: <<path relative to proj?>>
-#    OTHER_RESOURCES: (non-localized) resources for this project
-#    OTHER_OFILES: relocatables to be linked into this project
-#    OTHER_LIBS: more libraries to link against
-#    OTHER_PRODUCT_DEPENDS: other dependencies of this project
-#    OTHER_SOURCEFILES: other source files maintained by .pre/postamble
-#    OTHER_GARBAGE: additional files to be removed by `make clean'
-
-# Set this to YES if you don't want a final libtool call for a library/framework.
-#    BUILD_OFILES_LIST_ONLY
-
-# To include a version string, project source must exist in a directory named 
-# $(NAME).%d[.%d][.%d] and the following line must be uncommented.
-# OTHER_GENERATED_OFILES = $(VERS_OFILE)
-
-# This definition will suppress stripping of debug symbols when an executable
-# is installed.  By default it is YES.
-# STRIP_ON_INSTALL = NO
-
-# Uncomment to suppress generation of a KeyValueCoding index when installing 
-# frameworks (This index is used by WOB and IB to determine keys available
-# for an object).  Set to YES by default.
-# PREINDEX_FRAMEWORK = NO
-
-# Change this definition to install projects somewhere other than the
-# standard locations.  NEXT_ROOT defaults to "C:/Apple" on Windows systems
-# and "" on other systems.
-DSTROOT = $(HOME)
diff --git a/kmodunload.tproj/PB.project b/kmodunload.tproj/PB.project
deleted file mode 100644 (file)
index 7d909c1..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    DYNAMIC_CODE_GEN = YES; 
-    FILESTABLE = {
-        FRAMEWORKS = (); 
-        OTHER_LINKED = (kmodunload.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kmodunload.8); 
-    }; 
-    LANGUAGE = English; 
-    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
-    NEXTSTEP_INSTALLDIR = /sbin; 
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
-    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
-    PDO_UNIX_INSTALLDIR = /bin; 
-    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = kmodunload; 
-    PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8; 
-    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
-    WINDOWS_INSTALLDIR = /Library/Executables; 
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
-}
diff --git a/kmodunload.tproj/kmodunload.8 b/kmodunload.tproj/kmodunload.8
deleted file mode 100644 (file)
index 358030c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-.\"
-.\" Copyright (c) 1997 Doug Rabson
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    $Id: kmodunload.8,v 1.1.1.1 2000/01/11 02:10:18 wsanchez Exp $
-.\"
-.Dd April 8, 1999
-.Dt KMODUNLOAD 8
-.Os FreeBSD
-.Sh NAME
-.Nm kmodunload
-.Nd stops and unloads a kernel module
-.Sh SYNOPSIS
-.Nm kmodunload
-.Op Fl v
-.Fl i Ar id
-.Nm kmodunload
-.Op Fl v
-.Fl n Ar name
-.Sh DESCRIPTION
-The
-.Nm
-utility stops and unloads a kernel module which was previously loaded with
-.Xr kmodload 8 .
-.Pp
-The following options are available:
-.Bl -tag -width indentXX
-.It Fl v
-Be more verbose.
-.It Fl i Ar id
-Unload the kernel module with this ID.
-.It Fl n Ar name
-Unload the kernel module with this name.
-.El
-.Sh DIAGNOSTICS
-The
-.Nm
-utility exits with a status of 0 on success
-and with a nonzero status if an error occurs.
-.Sh SEE ALSO
-.Xr kmodload 8 ,
-.Xr kmodstat 8 ,
-.Xr kmodsyms 8
-.Sh HISTORY
-The
-.Nm
-command is based on the command kldunload written by
-.An Doug Rabson Aq dfr@FreeBSD.org
diff --git a/kmodunload.tproj/kmodunload.c b/kmodunload.tproj/kmodunload.c
deleted file mode 100644 (file)
index 4fb96b0..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*-
- * Copyright (c) 1997 Doug Rabson
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Original code from:
- *     "kldunload.c,v 1.7 1998/11/07 00:42:52 des Exp"
- */
-
-#ifndef lint
-static const char rcsid[] =
-       "$Id: kmodunload.c,v 1.3 2001/02/05 19:53:16 lindak Exp $";
-#endif /* not lint */
-
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <mach/mach.h>
-#include <mach/mach_error.h>
-#include <mach/mach_host.h>
-
-static int verbose = 0;
-#define v_printf       if (verbose) printf
-
-static void
-machwarn(int error, const char *message)
-{
-       if (error == KERN_SUCCESS) return;
-       fprintf(stderr, "kmodunload: %s: %s\n", message, mach_error_string(error));
-}
-
-static void
-macherr(int error, const char *message)
-{
-       if (error == KERN_SUCCESS) return;
-       fprintf(stderr, "kmodunload: %s: %s\n", message, mach_error_string(error));
-       exit(1);
-}
-
-static mach_port_t kernel_priv_port;
-
-static void
-stop_module(kmod_t id)
-{
-       int r;
-       void * args = 0;
-       int argsCount= 0;
-
-       r = kmod_control(kernel_priv_port, id, KMOD_CNTL_STOP, &args, &argsCount);
-       macherr(r, "kmod_control(stop) failed");
-
-       v_printf("kmodunload: kmod id %d successfully stopped.\n", id);
-}
-
-static void
-unload_module(kmod_t id)
-{
-       int r;
-
-       r = kmod_destroy(kernel_priv_port, id);
-       macherr(r, "kmod_destroy() failed");
-
-       v_printf("kmodunload: kmod id %d successfully unloaded.\n", id);
-}
-
-static void
-usage(void)
-{
-       fprintf(stderr, "usage: kmodunload [-v] -i id\n");
-       fprintf(stderr, "       kmodunload [-v] -n name\n");
-       exit(1);
-}
-
-int
-main(int argc, char** argv)
-{
-       int c;
-       int id = 0;
-       char* name = 0;
-       kmod_info_t *info;
-       int r;
-       int count;
-       mach_port_t kernel_port;
-
-       while ((c = getopt(argc, argv, "i:n:v")) != -1)
-               switch (c) {
-               case 'i':
-                       id = atoi(optarg);
-                       break;
-               case 'n':
-                       name = optarg;
-                       break;
-               case 'v':
-                       verbose = 1;
-                       break;
-               default:
-                       usage();
-               }
-       argc -= optind;
-       argv += optind;
-
-       if (!id && !name && (argc == 1)) {
-               name = *argv;
-               argc--;
-       }
-    
-       if ((argc != 0) || (id && name))
-               usage();
-
-       if ((id == 0) && (name == 0))
-               usage();
-
-       r = task_for_pid(mach_task_self(), 0, &kernel_port);
-       machwarn(r, "unable to get kernel task port");
-       if (r) {
-               fprintf(stderr, "kmodunload: Are you running as root?\n");
-               exit(1);
-       }
-
-       r = kmod_get_info(kernel_port, (void *)&info, &count);
-       macherr(r, "kmod_get_info() failed");
-
-       if (count < 1) {
-               fprintf(stderr, "kmodunload: there is nothing to unload?\n");
-               exit(1);
-       }
-
-       if (name) {
-               kmod_info_t *k = info;
-               while (k) {
-                       if (!strcmp(k->name, name)) {
-                               id = k->id;
-                               break;
-                       }
-                       k = (k->next) ? (k + 1) : 0;
-               }
-               if (!k) {
-                       fprintf(stderr, "kmodunload: can't kmod named: %s.\n", name);
-                       exit(1);
-               }
-       } else {
-               kmod_info_t *k = info;
-               while (k) {
-                       if (id == k->id) {
-                               name = k->name;
-                               break;
-                       }
-                       k = (k->next) ? (k + 1) : 0;
-               }
-               if (!name) {
-                       fprintf(stderr, "kmodunload: can't find kmod id %d.\n", id);
-                       exit(1);
-               }
-       }
-       
-       v_printf("kmodunload: found kmod %s, id %d.\n", name, id);
-       kernel_priv_port = mach_host_self(); /* if we are privileged */
-
-       stop_module(id);
-       unload_module(id);
-
-       return 0;
-}
-
index 6369360f20843859a63e64820b49342c555568d6..254b43ae5b9ccb53ffc2f1ac2cda360257b138da 100644 (file)
@@ -16,7 +16,7 @@ HFILES = ktrace.h
 
 CFILES = ktrace.c subr.c
 
-OTHERSRCS = Makefile.preamble Makefile ktrace.1
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ktrace.1
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
diff --git a/ktrace.tproj/Makefile.postamble b/ktrace.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..f7143e4
--- /dev/null
@@ -0,0 +1,4 @@
+install-man-page:
+       install -d $(DSTROOT)/usr/share/man/man1
+       install -c -m 444 ktrace.1 $(DSTROOT)/usr/share/man/man1/ktrace.1
+
index d5059b1a9606b91618e13146f4f3c48551b75880..de796cee60718f87b21fc8e36de887ac3142b9b5 100644 (file)
@@ -1,2 +1,3 @@
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
+AFTER_INSTALL += install-man-page
 
index c0b395a42e7882a4277fc739f91320e33fe993d9..1a3d2e9c50131ccc0e5bb61433cf11ec56794f80 100644 (file)
@@ -8,7 +8,7 @@
         M_FILES = (); 
         OTHER_LIBS = (); 
         OTHER_LINKED = (ktrace.c, subr.c); 
-        OTHER_SOURCES = (Makefile.preamble, Makefile, ktrace.1); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ktrace.1); 
         SUBPROJECTS = (); 
     }; 
     LANGUAGE = English; 
index d080b4e2b8b31afe877d09e41effb5d4646063e7..082e34b6925c776d6d54c47404088cb3b1f01384 100644 (file)
 .\" SUCH DAMAGE.
 .\"
 .\"    @(#)ktrace.1    8.1 (Berkeley) 6/6/93
+.\" $FreeBSD: src/usr.bin/ktrace/ktrace.1,v 1.8.2.5 2001/08/16 13:16:53 ru Exp $
 .\"
 .Dd June 6, 1993
 .Dt KTRACE 1
-.Os BSD 4.4
+.Os
 .Sh NAME
 .Nm ktrace
 .Nd enable kernel process tracing
 .Sh SYNOPSIS
-.Nm ktrace
+.Nm
 .Op Fl aCcdi
 .Op Fl f Ar trfile
-.Op Fl g Ar pgrp
-.Op Fl p Ar pid
+.Op Fl g Ar pgrp | Fl p Ar pid
 .Op Fl t Ar trstr
-.Nm ktrace
+.Nm
 .Op Fl adi
 .Op Fl f Ar trfile
 .Op Fl t Ar trstr
-command
+.Ar command
 .Sh DESCRIPTION
-.Nm Ktrace
-enables kernel trace logging for the specified processes.
+The
+.Nm
+command enables kernel trace logging for the specified processes.
 Kernel trace data is logged to the file
 .Pa ktrace.out .
 The kernel operations that are traced include system calls, namei
@@ -66,7 +67,7 @@ attempting to trace a process.
 The following command is sufficient to disable tracing on all user owned
 processes, and, if executed by root, all processes:
 .Pp
-.Dl \&$ trace -C
+.Dl \&$ ktrace -C
 .Pp
 The trace file is not human readable; use
 .Xr kdump 1
@@ -75,7 +76,7 @@ to decode it.
 The options are as follows:
 .Bl -tag -width indent
 .It Fl a
-Append to the trace file instead of truncating it.
+Append to the trace file instead of recreating it.
 .It Fl C
 Disable tracing on all user owned processes, and, if executed by root, all
 processes in the system.
@@ -84,23 +85,23 @@ Clear the trace points associated with the specified file or processes.
 .It Fl d
 Descendants; perform the operation for all current children of the
 designated processes.
-.It Fl f Ar file 
+.It Fl f Ar file
 Log trace records to
 .Ar file
 instead of
 .Pa ktrace.out .
-.It Fl g Ar pgid 
+.It Fl g Ar pgid
 Enable (disable) tracing on all processes in the process group (only one
 .Fl g
 flag is permitted).
 .It Fl i
 Inherit; pass the trace flags to all future children of the designated
 processes.
-.It Fl p Ar pid 
+.It Fl p Ar pid
 Enable (disable) tracing on the indicated process id (only one
 .Fl p
 flag is permitted).
-.It Fl t Ar trstr 
+.It Fl t Ar trstr
 The string argument represents the kernel trace points, one per letter.
 The following table equates the letters with the tracepoints:
 .Pp
@@ -114,6 +115,10 @@ trace
 .Tn I/O
 .It Cm s
 trace signal processing
+.It Cm u
+userland traces
+.It Cm w
+context switches
 .El
 .It Ar command
 Execute
@@ -156,8 +161,12 @@ on process 67
 .Dl $ ktrace -C
 .Sh SEE ALSO
 .Xr kdump 1
+.Sh BUGS
+Only works if
+.Ar file
+is a regular file.
 .Sh HISTORY
 The
-.Nm ktrace
-command appears in
+.Nm
+command appeared in
 .Bx 4.4 .
index 188e9baa31273f747c4bcfe6a4f764b98b76652f..dc096491391ac41a1c03ee145758c3b73683d5ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -23,7 +23,7 @@
  */
 /*-
  * Copyright (c) 1988, 1993
- *      The Regents of the University of California.  All rights reserved.
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,8 +35,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  */
 
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ktrace.c   8.1 (Berkeley) 6/6/93";
+#endif
+static const char rcsid[] =
+  "$FreeBSD: src/usr.bin/ktrace/ktrace.c,v 1.12.2.3 2001/07/11 00:29:27 mikeh Exp $";
+#endif /* not lint */
+
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/file.h>
@@ -64,7 +78,6 @@
 
 #include <err.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <unistd.h>
 
 #include "ktrace.h"
@@ -79,12 +92,14 @@ main(argc, argv)
        enum { NOTSET, CLEAR, CLEARALL } clear;
        int append, ch, fd, inherit, ops, pid, pidset, trpoints;
        char *tracefile;
+       mode_t omask;
+       struct stat sb;
 
        clear = NOTSET;
        append = ops = pidset = inherit = 0;
        trpoints = DEF_POINTS;
        tracefile = DEF_TRACEFILE;
-       while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != EOF)
+       while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != -1)
                switch((char)ch) {
                case 'a':
                        append = 1;
@@ -139,26 +154,38 @@ main(argc, argv)
                        trpoints = ALL_POINTS;
                        pid = 1;
                } else
-                       ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE;
+                       ops |= pidset ? KTROP_CLEAR : KTROP_CLEARFILE;
 
                if (ktrace(tracefile, ops, trpoints, pid) < 0)
-                       err(1, tracefile);
+                       err(1, "%s", tracefile);
                exit(0);
        }
 
-       if ((fd = open(tracefile, O_CREAT | O_WRONLY | (append ? 0 : O_TRUNC),
-           DEFFILEMODE)) < 0)
-               err(1, tracefile);
+       omask = umask(S_IRWXG|S_IRWXO);
+       if (append) {
+               if ((fd = open(tracefile, O_CREAT | O_WRONLY, DEFFILEMODE)) < 0)
+                       err(1, "%s", tracefile);
+               if (fstat(fd, &sb) != 0 || sb.st_uid != getuid())
+                       errx(1, "Refuse to append to %s not owned by you.",
+                           tracefile);
+       } else {
+               if (unlink(tracefile) == -1 && errno != ENOENT)
+                       err(1, "unlink %s", tracefile);
+               if ((fd = open(tracefile, O_CREAT | O_EXCL | O_WRONLY,
+                   DEFFILEMODE)) < 0)
+                       err(1, "%s", tracefile);
+       }
+       (void)umask(omask);
        (void)close(fd);
 
        if (*argv) { 
                if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
-                       err(1, tracefile);
+                       err(1, "%s", tracefile);
                execvp(argv[0], &argv[0]);
                err(1, "exec of '%s' failed", argv[0]);
        }
        else if (ktrace(tracefile, ops, trpoints, pid) < 0)
-               err(1, tracefile);
+               err(1, "%s", tracefile);
        exit(0);
 }
 
@@ -181,8 +208,9 @@ rpid(p)
 void
 usage()
 {
-       (void)fprintf(stderr,
-"usage:\tktrace [-aCcid] [-f trfile] [-g pgid] [-p pid] [-t [acgn]\n\tktrace [-aCcid] [-f trfile] [-t [acgn] command\n");
+       (void)fprintf(stderr, "%s\n%s\n",
+"usage: ktrace [-aCcdi] [-f trfile] [-g pgrp | -p pid] [-t cnisuw]",
+"       ktrace [-adi] [-f trfile] [-t cnisuw] command");
        exit(1);
 }
 
index 75c4eabc05ee8b52893d6ed1568b0e6f02940e9a..9f6431acc201c3ee274a0b7742b63e5b1d8605f3 100644 (file)
@@ -1,26 +1,3 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
 /*-
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -57,7 +34,7 @@
  */
 
 #define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
-                 KTRFAC_GENIO | KTRFAC_PSIG)
+                 KTRFAC_GENIO | KTRFAC_PSIG | KTRFAC_USER)
 
 #define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
 
index 08be41529b8f9a382225ffc0d4d71f8383d82902..90144d341ae424ccb030e5ef09c997a335083845 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999, 2000-2001 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -23,7 +23,7 @@
  */
 /*-
  * Copyright (c) 1988, 1993
- *      The Regents of the University of California.  All rights reserved.
+ *     The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,8 +35,8 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *      This product includes software developed by the University of
- *      California, Berkeley and its contributors.
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
  * 4. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  * SUCH DAMAGE.
  */
 
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)subr.c     8.1 (Berkeley) 6/6/93";
+#endif
+static const char rcsid[] =
+  "$FreeBSD: src/usr.bin/ktrace/subr.c,v 1.6 1999/08/28 01:02:34 peter Exp $";
+#endif /* not lint */
+
 #include <sys/param.h>
 #include <sys/file.h>
 #include <sys/user.h>
@@ -84,6 +92,9 @@ getpoints(s)
                case 's':
                        facs |= KTRFAC_PSIG;
                        break;
+               case 'u':
+                       facs |= KTRFAC_USER;
+                       break;
                case 'w':
                        facs |= KTRFAC_CSW;
                        break;
index b647e65b8ba1d78925605f528bc895dcd5d02500..9ff5ba4e589339124c26429ae162ef02d91d2d29 100644 (file)
@@ -23,7 +23,7 @@ MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /usr/bin
 WINDOWS_INSTALLDIR = /Library/Executables
 PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
+LIBS = -lcurses
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
index fc2cf35c93cde70583d297b1ea7c63776b6c844a..f9bb800af1213050585c3f75c46d7c13650c6c76 100644 (file)
@@ -24,7 +24,7 @@
 
 
 /* 
-   cc -I. -DKERNEL_PRIVATE -O -o latency latency.c
+   cc -I. -DKERNEL_PRIVATE -O -o latency latency.c -lncurses
 */
 
 #include <mach/mach.h>
@@ -42,7 +42,7 @@
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
+#include <curses.h>
 #include <sys/ioctl.h>
 
 #ifndef KERNEL_PRIVATE
@@ -124,6 +124,8 @@ char       pcstring[128];
 double   divisor;
 int      gotSIGWINCH = 0;
 int      trace_enabled = 0;
+struct host_basic_info  hi;
+
 
 #define SAMPLE_SIZE 300000
 
@@ -205,6 +207,9 @@ static kern_return_t        set_standard_policy(void);
 int decrementer_val = 0;     /* Value used to reset decrementer */
 int set_remove_flag = 1;     /* By default, remove trace buffer */
 
+kd_buf **last_decrementer_kd;   /* last DECR_TRAP per cpu */
+#define MAX_LOG_COUNT  30       /* limits the number of entries dumped in log_decrementer */
+
 int
 quit(s)
 char *s;
@@ -434,7 +439,7 @@ void sigintr()
         exit(1);
 }
 
-void sigquit()
+void leave()    /* exit under normal conditions -- signal handler */
 {
         set_enable(0);
        set_pidexclude(getpid(), 0);
@@ -444,17 +449,6 @@ void sigquit()
         exit(1);
 }
 
-void sigterm()
-{
-        set_enable(0);
-       set_pidexclude(getpid(), 0);
-       set_rtcdec(0);
-       set_remove();
-       
-        exit(1);
-}
-
-
 void
 screen_update(FILE *fp)
 {
@@ -695,6 +689,10 @@ char *argv[];
        double   nanosecs_to_sleep;
        int      loop_cnt, sample_sc_now;
        int      decrementer_usec = 0;
+        kern_return_t           ret;
+        int                     size;
+        int                     i, count;
+        host_name_port_t        host;
        void     getdivisor();
        void     sample_sc();
        void     init_code_file();
@@ -792,6 +790,18 @@ char *argv[];
        getdivisor();
        decrementer_val = decrementer_usec * divisor;
 
+       /* get the cpu count for the DECR_TRAP array */
+        host = mach_host_self();
+       size = sizeof(hi)/sizeof(int);
+        ret = host_info(host, HOST_BASIC_INFO, (host_info_t)&hi, &size);
+        if (ret != KERN_SUCCESS) {
+            mach_error(argv[0], ret);
+            exit(EXIT_FAILURE);
+       }
+
+       if ((last_decrementer_kd = (kd_buf **)malloc(hi.avail_cpus * sizeof(kd_buf *))) == (kd_buf **)0)
+               quit("can't allocate memory for decrementer tracing info\n");
+
        nanosecs_to_sleep = (double)(num_of_usecs_to_sleep * 1000);
        fdelay = nanosecs_to_sleep * (divisor /1000);
        adelay = (uint64_t)fdelay;
@@ -805,13 +815,19 @@ char *argv[];
        */
        set_rtcdec(decrementer_val);
 
-       initscr();
+       if (initscr() == (WINDOW *) 0)
+         {
+           printf("Unrecognized TERM type, try vt100\n");
+           exit(1);
+         }
+
        clear();
        refresh();
        signal(SIGWINCH, sigwinch);
        signal(SIGINT, sigintr);
-       signal(SIGQUIT, sigquit);
-       signal(SIGTERM, sigterm);
+       signal(SIGQUIT, leave);
+       signal(SIGTERM, leave);
+       signal(SIGHUP, leave);
 
 
        if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
@@ -904,7 +920,11 @@ char *argv[];
                        }
                }
                if (gotSIGWINCH) {
-                       initscr();
+                       /*
+                         No need to check for initscr error return.
+                         We won't get here if it fails on the first call.
+                       */
+                       endwin();
                        clear();
                        refresh();
 
@@ -1135,9 +1155,9 @@ char *find_code(type)
 
 void sample_sc(uint64_t start, uint64_t stop)
 {
-       kd_buf   *kd, *last_mach_sched, *last_decrementer_kd, *start_kd, *end_of_sample;
+       kd_buf   *kd, *last_mach_sched, *start_kd, *end_of_sample;
        uint64_t now;
-       int count;
+       int count, i;
        int first_entry = 1;
        char   command[32];
        double timestamp, last_timestamp, delta, start_bias;
@@ -1171,8 +1191,6 @@ void sample_sc(uint64_t start, uint64_t stop)
        count = needed;
 
        if (bufinfo.flags & KDBG_WRAPPED) {
-               int i;
-
                for (i = 0; i < cur_max; i++) {
                        th_state[i].thread = 0;
                        th_state[i].type = -1;
@@ -1196,7 +1214,11 @@ void sample_sc(uint64_t start, uint64_t stop)
                }
        }
        end_of_sample = &((kd_buf *)my_buffer)[count];
-       last_decrementer_kd = (kd_buf *)my_buffer;
+
+       /* Always reinitialize the DECR_TRAP array */
+       for (i=0; i < hi.avail_cpus; i++)
+             last_decrementer_kd[i] = (kd_buf *)my_buffer;
+
        last_mach_sched = (kd_buf *)0;
 
        for (kd = (kd_buf *)my_buffer; kd < end_of_sample; kd++) {
@@ -1205,6 +1227,7 @@ void sample_sc(uint64_t start, uint64_t stop)
                int len;
                char *p;
                long *sargptr;
+               kd_buf *cur_kd;
                double i_latency;
                struct th_info *ti;
                char   command1[32];
@@ -1240,21 +1263,27 @@ void sample_sc(uint64_t start, uint64_t stop)
                        else if (debugid & DBG_FUNC_END)
                                exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 0);
                        else if (type == DECR_TRAP) {
+                               cur_kd = kd;
                                if (log_fp && i_thresh_hold && (int)i_latency > i_thresh_hold) {
-                                       start_kd = last_decrementer_kd;
+                                       start_kd = last_decrementer_kd[cpunum];
                                        kd = log_decrementer(start_kd, kd, end_of_sample, i_latency);
-
                                        if (kd >= end_of_sample)
                                                break;
                                }
-                               last_decrementer_kd = kd;
+                               if ((kd->debugid & DBG_FUNC_MASK) == DECR_TRAP)
+                                 {
+                                   cpunum =  (kd->arg5 & KDBG_CPU_MASK) ? 1: 0;
+                                   last_decrementer_kd[cpunum] = kd;
+                                 }
+                               else
+                                 last_decrementer_kd[cpunum] = cur_kd;
                        }
                        continue;
                }
                if (first_entry) {
                        double latency;
-                       char buf1[128];
-                       char buf2[128];
+                       char buf1[132];
+                       char buf2[132];
 
                        latency = (double)(stop - start) / divisor;
                        latency -= (double)num_of_usecs_to_sleep;
@@ -1323,7 +1352,7 @@ void sample_sc(uint64_t start, uint64_t stop)
                    break;
 
                case DECR_TRAP:
-                   last_decrementer_kd = kd;
+                   last_decrementer_kd[cpunum] = kd;
 
                    if (i_thresh_hold && (int)i_latency > i_thresh_hold)
                            p = "*";
@@ -1401,7 +1430,9 @@ void sample_sc(uint64_t start, uint64_t stop)
                            ti->pathptr = (long *)0;
                            ti->child_thread = 0;
                    }
-                   if (!ti->pathptr) {
+                   while ( (kd < end_of_sample) && ((kd->debugid & DBG_FUNC_MASK) == VFS_LOOKUP))
+                     {
+                       if (!ti->pathptr) {
                            ti->arg1 = kd->arg1;
                            memset(&ti->pathname[0], 0, (PATHLENGTH + 1));
                            sargptr = (long *)&ti->pathname[0];
@@ -1411,7 +1442,7 @@ void sample_sc(uint64_t start, uint64_t stop)
                            *sargptr++ = kd->arg4;
                            ti->pathptr = sargptr;
 
-                   } else {
+                       } else {
                            sargptr = ti->pathptr;
 
                            /*
@@ -1420,28 +1451,50 @@ void sample_sc(uint64_t start, uint64_t stop)
                                handle.
                            */
 
-                            if ((long *)sargptr < (long *)&ti->pathname[PATHLENGTH])
+                            if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
+                             {
+                               kd++;
+                               continue;
+                             }
+
+                            /*
+                              We need to detect consecutive vfslookup entries.
+                              So, if we get here and find a START entry,
+                              fake the pathptr so we can bypass all further
+                              vfslookup entries.
+                           */
+
+                            if (kd->debugid & DBG_FUNC_START)
+                              {
+                                (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH];
+                              }
+                           else
                              {
                                *sargptr++ = kd->arg1;
                                *sargptr++ = kd->arg2;
                                *sargptr++ = kd->arg3;
                                *sargptr++ = kd->arg4;
                                ti->pathptr = sargptr;
+                             }
+                       }
+                       kd++;
+                   }
+
+                   kd--;
 
                                /* print the tail end of the pathname */
-                               len = strlen(ti->pathname);
-                               if (len > 28)
-                                 len -= 28;
-                               else
-                                 len = 0;
+                   len = strlen(ti->pathname);
+                   if (len > 42)
+                     len -= 42;
+                   else
+                     len = 0;
                            
-                               if (log_fp) {
-                                 fprintf(log_fp, "%9.1f %8.1f\t\t%-28.28s %-28s    %-8x   %-8x  %d  %s\n",
-                                         timestamp - start_bias, delta, "VFS_LOOKUP", 
-                                         &ti->pathname[len], ti->arg1, thread, cpunum, command);
-                               }
-                           }
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-42s    %-8x   %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, "VFS_LOOKUP", 
+                             &ti->pathname[len], ti->arg1, thread, cpunum, command);
                    }
+
                    last_timestamp = timestamp;
                    break;
 
@@ -1664,6 +1717,7 @@ check_for_thread_update(int thread, int type, kd_buf *kd)
 kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, double i_latency)
 {
         kd_buf *kd, *kd_start, *kd_stop;
+       int kd_count;     /* Limit the boundary of kd_start */
        double timestamp, last_timestamp, delta, start_bias;
        int thread, cpunum;
        int debugid, type, clen;
@@ -1690,18 +1744,39 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d
        fprintf(log_fp, "RelTime(Us)  Delta              debugid                      arg1       arg2       arg3      arg4       thread   cpu   command\n\n");
 
        thread = kd_beg->arg5 & KDBG_THREAD_MASK;
+       cpunum =  (kd_end->arg5 & KDBG_CPU_MASK) ? 1: 0;
 
-       for (kd_start = kd_beg - 1; (kd_start >= (kd_buf *)my_buffer) && (kd_start->arg5 & KDBG_THREAD_MASK) == thread; kd_start--) {
-               if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP)
+       for (kd_count = 0, kd_start = kd_beg - 1; (kd_start >= (kd_buf *)my_buffer); kd_start--, kd_count++) {
+               if (kd_count == MAX_LOG_COUNT)
+                       break;
+
+               if((kd_start->arg5 & KDBG_CPU_MASK) != cpunum)
+                       continue;
+                                                                                    
+               if ((kd_start->debugid & DBG_FUNC_MASK) == DECR_TRAP)
+                       break;
+
+               if((kd_start->arg5 & KDBG_THREAD_MASK) != thread)
                        break;
        }
+
        if (kd_start < (kd_buf *)my_buffer)
                kd_start = (kd_buf *)my_buffer;
 
-       for (kd_stop = kd_end + 1; kd_stop < end_of_sample && (kd_start->arg5 & KDBG_THREAD_MASK) == thread; kd_stop++) {
-               if ((kd_stop->debugid & DBG_FUNC_MASK) == DECR_TRAP)
+       thread = kd_end->arg5 & KDBG_THREAD_MASK;
+
+       for (kd_stop = kd_end + 1; kd_stop < end_of_sample; kd_stop++) {
+                                                                                    
+               if ((kd_stop->debugid & DBG_FUNC_MASK) == DECR_TRAP)
+                       break;
+
+               if((kd_stop->arg5 & KDBG_CPU_MASK) != cpunum)
+                       continue;
+
+               if((kd_stop->arg5 & KDBG_THREAD_MASK) != thread)
                        break;
        }
+
        if (kd_stop >= end_of_sample)
                kd_stop = end_of_sample - 1;
 
@@ -1825,7 +1900,10 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d
                            ti->pathptr = (long *)0;
                            ti->child_thread = 0;
                    }
-                   if (!ti->pathptr) {
+
+                   while ( (kd <= kd_stop) && (kd->debugid & DBG_FUNC_MASK) == VFS_LOOKUP)
+                     {
+                       if (!ti->pathptr) {
                            ti->arg1 = kd->arg1;
                            memset(&ti->pathname[0], 0, (PATHLENGTH + 1));
                            sargptr = (long *)&ti->pathname[0];
@@ -1835,7 +1913,7 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d
                            *sargptr++ = kd->arg4;
                            ti->pathptr = sargptr;
 
-                   } else {
+                       } else {
                            sargptr = ti->pathptr;
 
                            /*
@@ -1844,25 +1922,47 @@ kd_buf *log_decrementer(kd_buf *kd_beg, kd_buf *kd_end, kd_buf *end_of_sample, d
                                handle.
                            */
 
-                            if ((long *)sargptr < (long *)&ti->pathname[PATHLENGTH])
+                            if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
+                             {
+                               kd++;
+                               continue;
+                             }
+
+                            /*
+                              We need to detect consecutive vfslookup entries.
+                              So, if we get here and find a START entry,
+                              fake the pathptr so we can bypass all further
+                              vfslookup entries.
+                           */
+
+                            if (kd->debugid & DBG_FUNC_START)
+                              {
+                                (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH];
+                              }
+                           else
                              {
                                *sargptr++ = kd->arg1;
                                *sargptr++ = kd->arg2;
                                *sargptr++ = kd->arg3;
                                *sargptr++ = kd->arg4;
-
-                               /* print the tail end of the pathname */
-                               len = strlen(ti->pathname);
-                               if (len > 28)
-                                 len -= 28;
-                               else
-                                 len = 0;
-                           
-                               fprintf(log_fp, "%9.1f %8.1f\t\t%-28.28s %-28s    %-8x   %-8x  %d  %s\n",
-                                       timestamp - start_bias, delta, "VFS_LOOKUP", 
-                                       &ti->pathname[len], ti->arg1, thread, cpunum, command);
+                               ti->pathptr = sargptr;
                              }
+                       }
+                       kd++;
                    }
+
+                   kd--;
+                   /* print the tail end of the pathname */
+                   len = strlen(ti->pathname);
+                   if (len > 42)
+                     len -= 42;
+                   else
+                     len = 0;
+                   
+                   fprintf(log_fp, "%9.1f %8.1f\t\t%-14.14s %-42s    %-8x   %-8x  %d  %s\n",
+                           timestamp - start_bias, delta, "VFS_LOOKUP", 
+                           &ti->pathname[len], ti->arg1, thread, cpunum, command);
+
                    last_timestamp = timestamp;
                    break;
 
index a148d4bed149a03803748c8e4fc9fd41df6222b2..66d930a81b91a4e18648c7e1b73d45490eefa530 100644 (file)
@@ -25,7 +25,7 @@ MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /usr/bin
 WINDOWS_INSTALLDIR = /usr/bin
 PDO_UNIX_INSTALLDIR = /usr/bin
-LIBS = 
+LIBS = -lpam -lpam_misc
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
index ec7f60d899936396874c5f83b9f5b08a449631cd..039c5edbf0c917d5a88baba40cd3244793cf0039 100644 (file)
@@ -1,6 +1,6 @@
 INSTALL_AS_USER =      root
 INSTALL_PERMISSIONS = 4555
-#CHFLAGS = /usr/bin/chflags
 
-#after_install::
-#      $(CHFLAGS) schg  $(DSTROOT)$(INSTALLDIR)/$(NAME)
+after_install:
+       mkdir -p "$(DSTROOT)/usr/share/man/man1"
+       install -c -m 644 login.1 "$(DSTROOT)/usr/share/man/man1/login.1"
index b7b38d0c5d6ad291a29b1e7e85ec6c41275156e8..802d9eb043da9f9f6c6a3becc081b51fa04bb78b 100644 (file)
@@ -1,3 +1,5 @@
 CLEAN_ALL_SUBPROJECTS = YES
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
+OTHER_CFLAGS = -DUSE_PAM -no-cpp-precomp
 
+AFTER_INSTALL = after_install
index cbfd71987f5afac2b8fa17eeb9f124b7bd3587a8..8b260841e4cb327347396272b66b352e23e8c018 100644 (file)
@@ -70,6 +70,7 @@ static char copyright[] =
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/file.h>
+#include <sys/wait.h>
 
 #include <err.h>
 #include <errno.h>
@@ -86,6 +87,11 @@ static char copyright[] =
 #include <unistd.h>
 #include <utmp.h>
 
+#ifdef USE_PAM
+#include <pam/pam_appl.h>
+#include <pam/pam_misc.h>
+#endif
+
 #include "pathnames.h"
 
 void    badlogin __P((char *));
@@ -121,7 +127,7 @@ int authok;
 
 struct passwd *pwd;
 int    failures;
-char   term[64], *envinit[1], *hostname, *username, *tty;
+char   term[64], *hostname, *username = NULL, *tty;
 
 int
 main(argc, argv)
@@ -133,11 +139,19 @@ main(argc, argv)
        struct stat st;
        struct timeval tp;
        struct utmp utmp;
-       int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
+       int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin = 0, rval;
        uid_t uid;
+       uid_t euid;
+       gid_t egid;
        char *domain, *p, *salt, *ttyn;
        char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
        char localhost[MAXHOSTNAMELEN];
+#ifdef USE_PAM
+       pam_handle_t *pamh = NULL;
+       struct pam_conv conv = { misc_conv, NULL };
+       char **pmenv;
+       pid_t pid;
+#endif
 
        (void)signal(SIGALRM, timedout);
        (void)alarm(timeout);
@@ -158,6 +172,9 @@ main(argc, argv)
                syslog(LOG_ERR, "couldn't get local hostname: %m");
        else
                domain = strchr(localhost, '.');
+       
+       euid = geteuid();
+       egid = getegid();
 
        fflag = hflag = pflag = 0;
        uid = getuid();
@@ -208,6 +225,91 @@ main(argc, argv)
        else
                tty = ttyn;
 
+#ifdef USE_PAM
+       rval = pam_start("login", username, &conv, &pamh);
+       if( rval != PAM_SUCCESS ) {
+               fprintf(stderr, "login: PAM Error:  %s\n", pam_strerror(pamh, rval));
+               exit(1);
+       }
+       rval = pam_set_item(pamh, PAM_TTY, tty);
+       if( rval != PAM_SUCCESS ) {
+               fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval));
+               exit(1);
+       }
+
+       rval = pam_set_item(pamh, PAM_RHOST, hostname);
+       if( rval != PAM_SUCCESS ) {
+               fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval));
+               exit(1);
+       }
+
+       rval = pam_set_item(pamh, PAM_USER_PROMPT, "login: ");
+       if( rval != PAM_SUCCESS ) {
+               fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval));
+               exit(1);
+       }
+
+       if( !username )
+               getloginname();
+       pam_set_item(pamh, PAM_USER, username);
+       pwd = getpwnam(username);
+       if( (pwd != NULL) && (pwd->pw_uid == 0) )
+               rootlogin = 1;
+
+       if( (pwd != NULL) && fflag && ((uid == 0) || (uid == pwd->pw_uid)) ){
+               rval = 0;
+       } else {
+
+               rval = pam_authenticate(pamh, 0);
+               while( (cnt++ < 10) && ((rval == PAM_AUTH_ERR) ||
+                               (rval == PAM_USER_UNKNOWN) ||
+                               (rval == PAM_CRED_INSUFFICIENT) ||
+                               (rval == PAM_AUTHINFO_UNAVAIL))) {
+                       badlogin(username);
+                       printf("Login incorrect\n");
+                       rootlogin = 0;
+                       getloginname();
+                       pwd = getpwnam(username);
+                       if( (pwd != NULL) && (pwd->pw_uid == 0) )
+                               rootlogin = 1;
+                       pam_set_item(pamh, PAM_USER, username);
+                       rval = pam_authenticate(pamh, 0);
+               }
+
+               if( rval != PAM_SUCCESS ) {
+                       pam_get_item(pamh, PAM_USER, (void *)&username);
+                       badlogin(username);
+                       printf("Login incorrect\n");
+                       exit(1);
+               }
+
+               rval = pam_acct_mgmt(pamh, 0);
+               if( rval == PAM_NEW_AUTHTOK_REQD ) {
+                       rval = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+               }
+               if( rval != PAM_SUCCESS ) {
+                       fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval));
+                       exit(1);
+               }
+       }
+
+       rval = pam_get_item(pamh, PAM_USER, (void *)&username);
+       if( (rval == PAM_SUCCESS) && username && *username) 
+               pwd = getpwnam(username);
+
+       rval = pam_open_session(pamh, 0);
+       if( rval != PAM_SUCCESS ) {
+               fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval));
+               exit(1);
+       }
+
+       rval = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+       if( rval != PAM_SUCCESS ) {
+               fprintf(stderr, "login: PAM Error: %s\n", pam_strerror(pamh, rval));
+               exit(1);
+       }
+
+#else /* USE_PAM */
        for (cnt = 0;; ask = 1) {
                if (ask) {
                        fflag = 0;
@@ -312,6 +414,7 @@ main(argc, argv)
                        sleep((u_int)((cnt - 3) * 5));
                }
        }
+#endif
 
        /* committed to login -- turn off timeout */
        (void)alarm((u_int)0);
@@ -322,6 +425,12 @@ main(argc, argv)
        if (!rootlogin)
                checknologin();
 
+       setegid(pwd->pw_gid);
+       seteuid(rootlogin ? 0 : pwd->pw_uid);
+
+       /* First do a stat in case the homedir is automounted */
+\r              stat(pwd->pw_dir,&st);
+
        if (chdir(pwd->pw_dir) < 0) {
                (void)printf("No home directory %s!\n", pwd->pw_dir);
                if (chdir("/"))
@@ -329,28 +438,11 @@ main(argc, argv)
                pwd->pw_dir = "/";
                (void)printf("Logging in with home = \"/\".\n");
        }
+       seteuid(euid);
+       setegid(egid);
 
        quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0;
 
-       if (pwd->pw_change || pwd->pw_expire)
-               (void)gettimeofday(&tp, (struct timezone *)NULL);
-       if (pwd->pw_change)
-               if (tp.tv_sec >= pwd->pw_change) {
-                       (void)printf("Sorry -- your password has expired.\n");
-                       sleepexit(1);
-               } else if (pwd->pw_change - tp.tv_sec <
-                   2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
-                       (void)printf("Warning: your password expires on %s",
-                           ctime(&pwd->pw_change));
-       if (pwd->pw_expire)
-               if (tp.tv_sec >= pwd->pw_expire) {
-                       (void)printf("Sorry -- your account has expired.\n");
-                       sleepexit(1);
-               } else if (pwd->pw_expire - tp.tv_sec <
-                   2 * DAYSPERWEEK * SECSPERDAY && !quietlog)
-                       (void)printf("Warning: your account expires on %s",
-                           ctime(&pwd->pw_expire));
-
        /* Nothing else left to fail -- really log in. */
        memset((void *)&utmp, 0, sizeof(utmp));
        (void)time(&utmp.ut_time);
@@ -373,8 +465,10 @@ main(argc, argv)
                pwd->pw_shell = _PATH_BSHELL;
 
        /* Destroy environment unless user has requested its preservation. */
-       if (!pflag)
-               environ = envinit;
+       if (!pflag) {
+               environ = malloc(sizeof(char *));
+               *environ = NULL;
+       }
        (void)setenv("HOME", pwd->pw_dir, 1);
        (void)setenv("SHELL", pwd->pw_shell, 1);
        if (term[0] == '\0')
@@ -388,6 +482,24 @@ main(argc, argv)
                (void)setenv("KRBTKFILE", krbtkfile_env, 1);
 #endif
 
+#ifdef USE_PAM
+       pmenv = pam_getenvlist(pamh);
+       for( cnt = 0; pmenv && pmenv[cnt]; cnt++ ) 
+               putenv(pmenv[cnt]);
+
+       pid = fork();
+       if ( pid < 0 ) {
+               err(1, "fork");
+       } else if( pid != 0 ) {
+               waitpid(pid, NULL, 0);
+               pam_setcred(pamh, PAM_DELETE_CRED);
+               rval = pam_close_session(pamh, 0);
+               pam_end(pamh,rval);
+               exit(0);
+       }
+
+#endif
+
        if (tty[sizeof("tty")-1] == 'd')
                syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
 
@@ -436,9 +548,9 @@ main(argc, argv)
 }
 
 #ifdef KERBEROS
-#define        NBUFSIZ         (UT_NAMESIZE + 1 + 5)   /* .root suffix */
+#define        NBUFSIZ         (MAXLOGNAME + 1 + 5)    /* .root suffix */
 #else
-#define        NBUFSIZ         (UT_NAMESIZE + 1)
+#define        NBUFSIZ         (MAXLOGNAME + 1)
 #endif
 
 void
@@ -458,7 +570,7 @@ getloginname()
                        if (p < nbuf + (NBUFSIZ - 1))
                                *p++ = ch;
                }
-               if (p > nbuf)
+               if (p > nbuf) {
                        if (nbuf[0] == '-')
                                (void)fprintf(stderr,
                                    "login names may not start with '-'.\n");
@@ -467,6 +579,7 @@ getloginname()
                                username = nbuf;
                                break;
                        }
+               }
        }
 }
 
index 706d04cf408ab3e8606773a6e7957d75d88fa352..57431ebc3ee901c81f7ce5c4de09c5898ff3318f 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Generated by the NeXT Project Builder.
+# Generated by the Apple Project Builder.
 #
 # NOTE: Do NOT change this file -- Project Builder maintains it.
 #
@@ -12,12 +12,12 @@ NAME = mach_init
 PROJECTVERSION = 2.8
 PROJECT_TYPE = Tool
 
-HFILES = bootstrap_internal.h error_log.h lists.h parser.h
+HFILES = bootstrap_internal.h error_log.h lists.h
 
-CFILES = bootstrap.c error_log.c lists.c parser.c rpc_services.c
+CFILES = bootstrap.c error_log.c lists.c rpc_services.c
 
-OTHERSRCS = Makefile.preamble Makefile initConf Notes testConfig\
-            testConfig2 bootstrap.defs testServer
+OTHERSRCS = Makefile.preamble Makefile bootstrap.defs mach_init.8\
+            Makefile.postamble
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
diff --git a/mach_init.tproj/Makefile.postamble b/mach_init.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..9bd8df1
--- /dev/null
@@ -0,0 +1,104 @@
+###############################################################################
+#  Makefile.postamble
+#  Copyright 1997, Apple Computer, Inc.
+#
+#  Use this makefile, which is imported after all other makefiles, to
+#  override attributes for a project's Makefile environment. This allows you  
+#  to take advantage of the environment set up by the other Makefiles. 
+#  You can also define custom rules at the end of this file.
+#
+###############################################################################
+# 
+# These variables are exported by the standard makefiles and can be 
+# used in any customizations you make.  They are *outputs* of
+# the Makefiles and should be used, not set.
+# 
+#  PRODUCTS: products to install.  All of these products will be placed in
+#       the directory $(DSTROOT)$(INSTALLDIR)
+#  GLOBAL_RESOURCE_DIR: The directory to which resources are copied.
+#  LOCAL_RESOURCE_DIR: The directory to which localized resources are copied.
+#  OFILE_DIR: Directory into which .o object files are generated.
+#  DERIVED_SRC_DIR: Directory used for all other derived files
+#
+#  ALL_CFLAGS:  flags to pass when compiling .c files
+#  ALL_MFLAGS:  flags to pass when compiling .m files
+#  ALL_CCFLAGS:  flags to pass when compiling .cc, .cxx, and .C files
+#  ALL_MMFLAGS:  flags to pass when compiling .mm, .mxx, and .M files
+#  ALL_PRECOMPFLAGS:  flags to pass when precompiling .h files
+#  ALL_LDFLAGS:  flags to pass when linking object files
+#  ALL_LIBTOOL_FLAGS:  flags to pass when libtooling object files
+#  ALL_PSWFLAGS:  flags to pass when processing .psw and .pswm (pswrap) files
+#  ALL_RPCFLAGS:  flags to pass when processing .rpc (rpcgen) files
+#  ALL_YFLAGS:  flags to pass when processing .y (yacc) files
+#  ALL_LFLAGS:  flags to pass when processing .l (lex) files
+#
+#  NAME: name of application, bundle, subproject, palette, etc.
+#  LANGUAGES: langages in which the project is written (default "English")
+#  English_RESOURCES: localized resources (e.g. nib's, images) of project
+#  GLOBAL_RESOURCES: non-localized resources of project
+#
+#  SRCROOT:  base directory in which to place the new source files
+#  SRCPATH:  relative path from SRCROOT to present subdirectory
+#
+#  INSTALLDIR: Directory the product will be installed into by 'install' target
+#  PUBLIC_HDR_INSTALLDIR: where to install public headers.  Don't forget
+#        to prefix this with DSTROOT when you use it.
+#  PRIVATE_HDR_INSTALLDIR: where to install private headers.  Don't forget
+#       to prefix this with DSTROOT when you use it.
+#
+#  EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows)
+#
+###############################################################################
+
+# Some compiler flags can be overridden here for certain build situations.
+#
+#    WARNING_CFLAGS:  flag used to set warning level (defaults to -Wmost)
+#    DEBUG_SYMBOLS_CFLAGS:  debug-symbol flag passed to all builds (defaults
+#      to -g)
+#    DEBUG_BUILD_CFLAGS:  flags passed during debug builds (defaults to -DDEBUG)
+#    OPTIMIZE_BUILD_CFLAGS:  flags passed during optimized builds (defaults
+#      to -O)
+#    PROFILE_BUILD_CFLAGS:  flags passed during profile builds (defaults
+#      to -pg -DPROFILE)
+#    LOCAL_DIR_INCLUDE_DIRECTIVE:  flag used to add current directory to
+#      the include path (defaults to -I.)
+#    DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags
+#      passed to ld/libtool (defaults to nothing)
+
+
+# Library and Framework projects only:
+#    INSTALL_NAME_DIRECTIVE:  This directive ensures that executables linked
+#      against the framework will run against the correct version even if
+#      the current version of the framework changes.  You may override this
+#      to "" as an alternative to using the DYLD_LIBRARY_PATH during your
+#      development cycle, but be sure to restore it before installing.
+
+
+# Ownership and permissions of files installed by 'install' target
+
+#INSTALL_AS_USER = root
+        # User/group ownership 
+#INSTALL_AS_GROUP = wheel
+        # (probably want to set both of these) 
+#INSTALL_PERMISSIONS = 4555
+        # If set, 'install' chmod's executable to this
+
+
+# Options to strip.  Note: -S strips debugging symbols (executables can be stripped
+# down further with -x or, if they load no bundles, with no options at all).
+
+#STRIPFLAGS = -S
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Include them in
+# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble.
+#
+# You should avoid redefining things like "install" or "app", as they are
+# owned by the top-level Makefile API and no context has been set up for where 
+# derived files should go.
+#
+
+install-man-page:
+       install -d $(DSTROOT)/usr/share/man/man8
+       install -c -m 444 mach_init.8 $(DSTROOT)/usr/share/man/man8/mach_init.8
index ef0b259ae1037752016e001ec20d6c99f1b4f127..02b60f4893ed4a4ff4dc65faae10ca97660692a8 100644 (file)
@@ -1,4 +1,4 @@
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
 BEFORE_BUILD += bootstrap.h
 OTHER_OFILES = bootstrapServer.o
-
+AFTER_INSTALL += install-man-page
diff --git a/mach_init.tproj/Notes b/mach_init.tproj/Notes
deleted file mode 100644 (file)
index 4c09847..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-# gvdl@next 3 Aug 1995
-# Need to get the bootstrap .defs stuff working properly
-
-Format of /etc/bootstrap.conf
-
-[[restartable] (server|init) "SERVER_PATH ARGS"] [services { SERVICE_NAME
- [, SERVICE_NAME]* }]
-
-struct service {
-       struct service *next;
-       struct service *prev;
-       char *name;
-       port_t port;
-       struct server *server;
-       struct service *server_link;
-};
-
-struct server {
-       struct server *next;
-       struct server *prev;
-       boolean_t restartable;
-       boolean_t isEtcInit;
-       char **argv;
-       struct service *services;
-};
-
-Service entries create service-port pairs.  Lookup rpc's return send rights.  Checkin rpc's return all rights.  Checkin's can only be done from "privileged" bootstrap ports (see server, below).  Bootstrap is the default backup for service ports, if bootstrap receives the port back, it holds onto all rights (to give out on a later checkin), and marks the service inactive.  Lookup's on inactive services continue to return the service port.  Lookup's on unregistered services return PORT_NULL.
-
-Server entries initiate server tasks.  Server tasks receive a privileged bootstrap port that allows the server task to register new service-port pairs and perform checkin's.  Servers can obtain an unprivileged lookup/status-only port with an rpc; that port should be passed to untrusted progeny.  Servers are initiated in the order that they appear in bootstrap.conf.  Restartable servers are re-initiated if port destroyed or port deleted notification is received for all of the service ports declared by that server in bootstrap.conf.  On restart, a server may reobtain receive rights for service ports that were returned to bootstrap via the port backup mechanism.  New ports for are created for declared service ports without back-up when bootstrap receives a port deleted notification.  If bootstrap receives a port deleted notification for a registered, but undeclared service port, further lookups on that name return PORT_NULL.  Runtime registered ports are not associated with a server and are not involved in restart determination.  Rights for registered ports that specify bootstrap as backup will be held and may later be transfered to a new server instantiation via the checkin.  Should a new server instantiation re-register the service, the port and associated receive rights will be deallocated.
-
-There may only be a single init entry; it is a special server entry and provides a (hack) mechanism to allow /etc/init to be exec'ed as pid 1.  In the longer run, bootstrap should take over system shutdown/reconfig responsibilities and this won't be necessary.
-
-As a compatability hack, the initial version of bootstrap will initialize the ports inherited on task_create() via mach_ports_register().  Existing services utilizing service_checkin() will have to be modified to use bootstrap_checkin().
-
-Bootstrap rpc's:
-
-bootstrap_checkin(port_t priv_bootstrap_port, char *service_name,
-       port *service_port);
-       
-       Returns receive rights in service_port for service named by service_name.
-       FIXME: Success/Failure indication???
-       
-bootstrap_register(port_t priv_bootstrap_port, char *service_name,
-       port service_port);
-       
-       Registers service_name -- service_port pair.
-       FIXME: Success/Failure indication???
-       
-bootstrap_checkout(port_t priv_bootstrap_port, char *service_name);
-
-       Removes registration for service named by service_name.
-       Fails is service is currently active.
-       FIXME: Success/Failure indication???
-       
-bootstrap_lookup(port_t bootstrap_port, char *service_name, port_t service_port);
-
-       Returns service port for service named by service_name.
-       
-bootstrap_lookup_array(port_t bootstrap_port, name_array_t service_names, port_array_t service_ports, int service_count);
-
-       Returns service ports for all services named in service_names array.
-
-boostrap_status(port_t bootstrap_port, name_array_t service_names,
-       bool_array_t service_actives, int *service_count);
-       
-       Returns names and active status for all known services.
-       
-bootstrap_get_unpriv_port(port_t bootstrap_port, port_t *unpriv_bootstrap_port);
-
-       Returns the unprivileged bootstrap service port.
-
index d937124b0d46a54d32efac39a374ad4c6df64780..c09942842326c4590e7429f8e0efd8750249fb9d 100644 (file)
@@ -3,47 +3,44 @@
     FILESTABLE = {
         BUNDLES = (); 
         CLASSES = (); 
-        C_FILES = (); 
+        "C_FILES" = (); 
         FRAMEWORKS = (); 
         FRAMEWORKSEARCH = (); 
         HEADERSEARCH = (); 
-        H_FILES = (bootstrap_internal.h, error_log.h, lists.h, parser.h); 
-        M_FILES = (); 
-        OTHER_LIBS = (); 
-        OTHER_LINKED = (bootstrap.c, error_log.c, lists.c, parser.c, rpc_services.c); 
-        OTHER_SOURCES = (
-            Makefile.preamble
+        "H_FILES" = ("bootstrap_internal.h", "error_log.h", "lists.h"); 
+        "M_FILES" = (); 
+        "OTHER_LIBS" = (); 
+        "OTHER_LINKED" = ("bootstrap.c", "error_log.c", "lists.c", "rpc_services.c"); 
+        "OTHER_SOURCES" = (
+            "Makefile.preamble"
             Makefile, 
-            initConf, 
-            Notes, 
-            testConfig, 
-            testConfig2, 
-            bootstrap.defs, 
-            testServer
+            "bootstrap.defs", 
+            "mach_init.8", 
+            "Makefile.postamble"
         ); 
         SUBPROJECTS = (); 
         TOOLS = (); 
     }; 
     LANGUAGE = English; 
-    LOCALIZABLE_FILES = {}; 
-    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
-    NEXTSTEP_BUILDTOOL = /bin/gnumake
-    NEXTSTEP_COMPILEROPTIONS = "-DMACH_USER_API"; 
-    NEXTSTEP_INSTALLDIR = /sbin
-    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac
-    NEXTSTEP_MAINNIB = mach_init
-    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc
-    PDO_UNIX_COMPILEROPTIONS = "-DMACH_USER_API"; 
-    PDO_UNIX_INSTALLDIR = /sbin
-    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
-    PDO_UNIX_MAINNIB = mach_init
-    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
-    PROJECTNAME = mach_init
+    "LOCALIZABLE_FILES" = {}; 
+    "NEXTSTEP_BUILDDIR" = "/tmp/$(USER)/BUILD"; 
+    "NEXTSTEP_BUILDTOOL" = "/bin/gnumake"
+    "NEXTSTEP_COMPILEROPTIONS" = "-DMACH_USER_API"; 
+    "NEXTSTEP_INSTALLDIR" = "/sbin"
+    "NEXTSTEP_JAVA_COMPILER" = "/usr/bin/javac"
+    "NEXTSTEP_MAINNIB" = "mach_init"
+    "NEXTSTEP_OBJCPLUS_COMPILER" = "/usr/bin/cc"
+    "PDO_UNIX_COMPILEROPTIONS" = "-DMACH_USER_API"; 
+    "PDO_UNIX_INSTALLDIR" = "/sbin"
+    "PDO_UNIX_JAVA_COMPILER" = "$(NEXTDEV_BIN)/javac"; 
+    "PDO_UNIX_MAINNIB" = "mach_init"
+    "PDO_UNIX_OBJCPLUS_COMPILER" = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = "mach_init"
     PROJECTTYPE = Tool; 
-    PROJECTVERSION = 2.8
-    WINDOWS_COMPILEROPTIONS = "-DMACH_USER_API"; 
-    WINDOWS_INSTALLDIR = /sbin
-    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
-    WINDOWS_MAINNIB = mach_init
-    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+    PROJECTVERSION = "2.8"
+    "WINDOWS_COMPILEROPTIONS" = "-DMACH_USER_API"; 
+    "WINDOWS_INSTALLDIR" = "/sbin"
+    "WINDOWS_JAVA_COMPILER" = "$(JDKBINDIR)/javac.exe"; 
+    "WINDOWS_MAINNIB" = "mach_init"
+    "WINDOWS_OBJCPLUS_COMPILER" = "$(DEVDIR)/gcc"; 
 }
index f55d1918d932fbbc3fe9ef04d443c141a73fff16..03c394df1060c73fd3a8d87ff2c9b06c96eba973 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <mach/exception.h>
 
 #import <sys/ioctl.h>
+#import <sys/types.h>
+#import <sys/wait.h>
+#import <pthread.h>
 #import        <string.h>
 #import        <ctype.h>
 #import        <stdio.h>
 #import <libc.h>
 
-#include "bootstrap.h"
+#import "bootstrap.h"
 
 #import "bootstrap_internal.h"
 #import "lists.h"
 #import "error_log.h"
-#import "parser.h"
 
 /* Mig should produce a declaration for this,  but doesn't */
 extern boolean_t bootstrap_server(mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP);
@@ -65,41 +67,19 @@ extern boolean_t bootstrap_server(mach_msg_header_t *InHeadP, mach_msg_header_t
  */
 const char *program_name;      /* our name for error messages */
 
-#ifndef CONF_FILE
-#define        CONF_FILE       "/etc/bootstrap.conf"   /* default config file */
-#endif CONF_FILE
-
-const char *conf_file = CONF_FILE;
-
-const unsigned BOOTSTRAP_REPLY_TIMEOUT = 10 * 1000; // 10 sec reply timeout
-#ifdef notyet
-port_all_t backup_port;
-#endif /* notyet */
-/*
- * Last resort configuration
- *
- * If we can't find a /etc/bootstrap.conf, we use this configuration.
- * The services defined here are compatable with the old mach port stuff,
- * and of course, the names for these services should not be modified without
- * modifying mach_init in libc.
- */
-const char *default_conf =
-       "init \"/sbin/init\";"
-       "services NetMessage;";
+#ifndef INIT_PATH
+#define INIT_PATH      "/sbin/init"                    /* default init path */
+#endif  INIT_PATH
        
+uid_t inherited_uid;
 mach_port_t inherited_bootstrap_port = MACH_PORT_NULL;
 boolean_t forward_ok = FALSE;
+boolean_t shutdown_in_progress = FALSE;
 boolean_t debugging = FALSE;
 boolean_t register_self = FALSE;
-int init_priority = BASEPRI_USER;
-char *register_name = NULL;
-mach_port_t    bootstrap_master_device_port;   /* local name */
-mach_port_t    bootstrap_master_host_port;     /* local name */
-mach_port_t    bootstrap_notification_port;    /* local name */
-mach_port_t    security_port;
-mach_port_t    root_ledger_wired;
-mach_port_t    root_ledger_paged;
-task_port_t    bootstrap_self;
+boolean_t force_fork = FALSE;
+const char *register_name;
+task_t bootstrap_self;
 
 #ifndef ASSERT
 #define ASSERT(p)
@@ -115,15 +95,20 @@ task_port_t        bootstrap_self;
 /*
  * Private declarations
  */    
-static void add_init_arg(const char *arg);
 static void wait_for_go(mach_port_t init_notify_port);
 static void init_ports(void);
 static void start_server(server_t *serverp);
-static void unblock_init(task_port_t task, mach_port_t newBootstrap);
+static void unblock_init(mach_port_t init_notify_port, mach_port_t newBootstrap);
 static void exec_server(server_t *serverp);
 static char **argvize(const char *string);
+static void *demand_loop(void *arg);
 static void server_loop(void);
-static void msg_destroy(mach_msg_header_t *m);
+extern kern_return_t bootstrap_register
+(
+       mach_port_t bootstrap_port,
+       name_t service_name,
+       mach_port_t service_port
+);
 
 /*
  * Private ports we hold receive rights for.  We also hold receive rights
@@ -131,35 +116,134 @@ static void msg_destroy(mach_msg_header_t *m);
  * structs.
  */
 mach_port_t bootstrap_port_set;
+mach_port_t demand_port_set;
+pthread_t      demand_thread;
+
 mach_port_t notify_port;
+mach_port_t backup_port;
 
-static int init_pid;
-static int running_servers;
-static char init_args[BOOTSTRAP_MAX_CMD_LEN];
+static void
+notify_server_loop(mach_port_name_t about)
+{
+       mach_port_destroyed_notification_t not;
+       mach_msg_return_t nresult;
+
+       not.not_header.msgh_id = DEMAND_REQUEST;
+       not.not_header.msgh_remote_port = backup_port;
+       not.not_header.msgh_local_port = MACH_PORT_NULL;
+       not.not_header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
+       not.not_header.msgh_size = sizeof(not) - sizeof(not.trailer);
+       not.not_body.msgh_descriptor_count = 1;
+       not.not_port.type = MACH_MSG_PORT_DESCRIPTOR;
+       not.not_port.disposition = MACH_MSG_TYPE_PORT_NAME;
+       not.not_port.name = about;
+       nresult = mach_msg_send(&not.not_header);
+       if (nresult != MACH_MSG_SUCCESS) {
+               kern_error(nresult, "notify_server: mach_msg_send()");
+       }
+}
 
 void _myExit(int arg)
 {
     exit(arg);
 }
 
-/* It was a bozo who made main return a value!  Civil disobedience, here. */
-void
-main(int argc, const char * const argv[])
+void toggle_debug(int signal)
+{
+       debugging = (debugging) ? FALSE : TRUE;
+}
+
+void start_shutdown(int signal)
+{
+       debug("received SIGTERM");
+       shutdown_in_progress = TRUE;
+       notify_server_loop(MACH_PORT_DEAD);
+}
+
+int
+main(int argc, char * argv[])
 {
        const char *argp;
        char c;
-       server_t *init_serverp;
        server_t *serverp;
-       mach_port_t init_notify_port;
        kern_return_t result;
+       mach_port_t init_notify_port;
+       pthread_attr_t  attr;
+       sigset_t mask;
        int pid;
-       int force_fork = FALSE;
-       mach_port_t prev_port;
-#if defined(__APPLE__)
-        extern void exit(int);
-       
-       /* signal (SIGUSR2, _myExit); */
-#endif
+
+       /*
+        * If we are pid one, we have to exec init.  Before doing so, we'll
+        * fork a child, and that will become the true mach_init.  But we have
+        * to be very careful about ports.  They aren't inherited across fork,
+        * so we have to avoid storing port names in memory before the fork that
+        * might not be valid after.
+        */
+       pid = getpid();
+       if (pid == 1)
+       {
+               close(0);
+               freopen("/dev/console", "r", stdin);
+               setbuf(stdin, NULL);
+               close(1);
+               freopen("/dev/console", "w", stdout);
+               setbuf(stdout, NULL);
+               close(2);
+               freopen("/dev/console", "w", stderr);
+               setbuf(stderr, NULL);
+
+               result = mach_port_allocate(
+                                               mach_task_self(),
+                                               MACH_PORT_RIGHT_RECEIVE,
+                                               &init_notify_port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_allocate");
+
+               result = mach_port_insert_right(
+                                               mach_task_self(),
+                                               init_notify_port,
+                                               init_notify_port,
+                                               MACH_MSG_TYPE_MAKE_SEND);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_insert_right");
+
+               result = task_set_bootstrap_port(
+                                               mach_task_self(),
+                                               init_notify_port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "task_set_bootstrap_port");
+
+               pid = fork();
+
+               if (pid < 0)
+                       unix_fatal("fork");
+
+               else if (pid != 0) {  /* PARENT - will become init when ready */
+                       int fd;
+
+                       /*
+                        * Wait for mach_init ot give us a real bootstrap port
+                        */
+                       wait_for_go(init_notify_port);
+                       info("Execing init");
+
+                       close(0);
+                       close(1);
+                       close(2);
+                       fd = open("/dev/tty", O_RDONLY);
+                       if (fd >= 0) {
+                               ioctl(fd, TIOCNOTTY, 0);
+                               close(fd);
+                       }
+                       
+                       /* pass our arguments on to init */
+                       argv[0] = INIT_PATH;
+                       execv(argv[0], argv);
+                       exit(1);  /* will likely trigger a panic */
+
+               }
+       } else
+               init_notify_port = MACH_PORT_NULL;
 
        /* Initialize error handling */
        program_name = rindex(*argv, '/');
@@ -169,35 +253,8 @@ main(int argc, const char * const argv[])
                program_name = *argv;
        argv++; argc--;
 
-       init_pid = getpid();
-       init_errlog(init_pid == 1);
-
-       /*
-        * Get master host and device ports
-        */
-#if 0
-       result = bootstrap_ports(bootstrap_port,
-                            &bootstrap_master_host_port,
-                            &bootstrap_master_device_port,
-                            &root_ledger_wired,
-                            &root_ledger_paged,
-                            &security_port);
-       if (result != KERN_SUCCESS) {
-       printf("bootstrap_ports failed \n");
-               kern_error(result, "bootstrap_ports");
-       }
-#endif /* 0 */
-       /*
-        *      This task will become the bootstrap task.
-        */
-       bootstrap_self = mach_task_self();
-
-       /* Initialize globals */
-       init_lists();
-
        /* Parse command line args */
        while (argc > 0 && **argv == '-') {
-               boolean_t init_arg = FALSE;
                argp = *argv++ + 1; argc--;
                while (*argp) {
                        switch (c = *argp++) {
@@ -210,15 +267,6 @@ main(int argc, const char * const argv[])
                        case 'F':
                                force_fork = TRUE;
                                break;
-                       case 'f':
-                               if (argc > 0) {
-                                       conf_file = *argv++; argc--;
-                               } else
-                                       fatal("-f requires config file name");
-                               break;
-                       case '-':
-                               init_arg = TRUE;
-                               break;
                        case 'r':
                                register_self = forward_ok = TRUE;
                                if (argc > 0) {
@@ -226,232 +274,265 @@ main(int argc, const char * const argv[])
                                } else
                                        fatal("-r requires name");
                                break;
+                       case '-':
                        default:
-                               init_arg = TRUE;
                                break;
                        }
                }
-               if (init_arg) {
-                       add_init_arg(argv[-1]);
-                       goto copyargs;
-               }
-       }
-    copyargs:
-       while (argc != 0) {
-               argc--;
-               add_init_arg(*argv++);
        }
 
-       log("Started");
-
-       /* Parse the config file */
-       init_config();
-
-       /* set_default_policy(bootstrap_master_host_port); */
-
        /*
-        * If we have to run init as pid 1, use notify port to
-        * synchronize init and bootstrap
+        * If we must fork, do it now before we get Mach ports in use
         */
-       if ((init_serverp = find_init_server()) != NULL) {
-               if (init_pid != 1 && ! debugging)
-                       fatal("Can't start init server if not pid 1");
-            result = mach_port_allocate(bootstrap_self, MACH_PORT_RIGHT_RECEIVE,
-                                    &init_notify_port);
-            if (result != KERN_SUCCESS)
-                    kern_fatal(result, "mach_port_allocate");
-            result = mach_port_insert_right(mach_task_self(), init_notify_port, init_notify_port, MACH_MSG_TYPE_MAKE_SEND);
-            if (result != KERN_SUCCESS)
-                kern_fatal(result, "mach_port_insert_right");
-            task_set_bootstrap_port(bootstrap_self, init_notify_port);
-            if (result != KERN_SUCCESS)
-                kern_fatal(result, "task_set_bootstrap_port");
-           /*
-            *  XXX restart the service if it dies?
-            */
-                result = mach_port_request_notification(mach_task_self(),
-                                               mach_task_self(),
-                                               MACH_NOTIFY_DEAD_NAME,
-                                               0,
-                                               init_notify_port,
-                                               MACH_MSG_TYPE_MAKE_SEND_ONCE,
-                                               &prev_port);
-           if (result != KERN_SUCCESS)
-                       kern_fatal(result, "mach_port_request_notification");
-               debug("Set port %d for parent proc notify port",
-                     init_notify_port);
-                } else if (init_args[0] != '\0')
-               fatal("Extraneous command line arguments");
-       
-       /* Fork if either not debugging or running /etc/init */
-       if (force_fork || !debugging || init_serverp != NULL) {
+       if (force_fork) {
                pid = fork();
                if (pid < 0)
                        unix_fatal("fork");
-       } else
-               pid = 0;
+               else if (pid != 0) /* PARENT: just exit */
+                       exit(0);
+       }
+
+       /* block all but SIGHUP and SIGTERM and mark us as an init process */
+       setsid();
+       sigfillset(&mask);
+       sigdelset(&mask, SIGHUP);
+       signal(SIGHUP, toggle_debug);
+       sigdelset(&mask, SIGTERM);
+       signal(SIGTERM, start_shutdown);
+       (void) sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
+
+       init_errlog(pid == 0); /* are we a daemon? */
+       init_lists();
+
+       /*
+        *      This task will become the bootstrap task, so go ahead and
+        *      initialize the ports now.
+        */
+       bootstrap_self = mach_task_self();
+       inherited_uid = getuid();
+       init_ports();
        
-       /* Bootstrap service runs in child (if there is one) */
-       if (pid == 0) { /* CHILD */
-               /*
-                * If we're initiated by pid 1, we shouldn't get ever get 
-                * killed; designate ourselves as an "init process".
-                *
-                * This should go away with new signal stuff!
-                */
-            if (init_pid == 1)
-                       init_process();
+       log("Started with uid=%d%s%s%s",
+               inherited_uid,
+               (register_self) ? " registered-as=" : "",
+               (register_self) ? register_name : "",
+               (debugging) ? " in debug-mode" : "");
 
-            /* Create declared service ports, our service port, etc */ 
-               init_ports();
 
-               /* Kick off all server processes */
-               for (  serverp = FIRST(servers)
-                    ; !IS_END(serverp, servers)
-                    ; serverp = NEXT(serverp))
-                       start_server(serverp);
-               
-               /*
-                * If our priority's to be changed, set it up here.
-                */
-#ifdef notyet
-               if (init_priority >= 0) {
-                       result = task_priority(mach_task_self(), init_priority,
-                               TRUE);
+       /*
+        * If we are supposed to coordinate with init, we have to
+        * get that port again, because we only have a (probably wrong)
+        * name in memory, not a proper right.
+        */
+       if (init_notify_port != MACH_PORT_NULL) {
+               result = task_get_bootstrap_port(
+                                                       bootstrap_self,
+                                                       &init_notify_port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "task_get_bootstrap_port");
+
+               unblock_init(init_notify_port, bootstraps.bootstrap_port);
+
+               result = task_set_bootstrap_port(
+                                                       bootstrap_self,
+                                                       MACH_PORT_NULL);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "task_set_bootstrap_port");
+
+               result = mach_port_deallocate(
+                                                       bootstrap_self,
+                                                       init_notify_port);  
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_deallocate");
+
+               forward_ok = FALSE;
+               inherited_bootstrap_port = MACH_PORT_NULL;
+
+       } else {
+
+               /* get inherited bootstrap port */
+               result = task_get_bootstrap_port(
+                                                       bootstrap_self,
+                                                       &inherited_bootstrap_port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "task_get_bootstrap_port");
+
+               /* We set this explicitly as we start each child */
+               task_set_bootstrap_port(bootstrap_self, MACH_PORT_NULL);
+               if (inherited_bootstrap_port == MACH_PORT_NULL)
+                       forward_ok = FALSE;
+
+               /* register "self" port with anscestor */               
+               if (register_self && forward_ok) {
+                       result = bootstrap_register(
+                                                       inherited_bootstrap_port,
+                                                       (char *)register_name,
+                                                       bootstraps.bootstrap_port);
                        if (result != KERN_SUCCESS)
-                               kern_error(result, "task_priority %d",
-                                       init_priority);
+                               kern_fatal(result, "register self");
                }
-#endif /* notyet */
-               /* Process bootstrap service requests */
-               server_loop();  /* Should never return */
-                exit(1);
        }
-       
-       /* PARENT */
-       if (init_serverp != NULL) {
-               int i;
 
-               strncat(init_serverp->cmd,
-                       init_args,
-                       sizeof(init_serverp->cmd));
-               /*
-                * Wait, then either exec /etc/init or exit
-                * (which panics the system)
-                */
-               for (i = 3; i; i--)
-                       close(i);
-               wait_for_go(init_notify_port);
-                exec_server(init_serverp);
+
+       /* Kick off all continuously running server processes */
+       for (  serverp = FIRST(servers)
+               ; !IS_END(serverp, servers)
+               ; serverp = NEXT(serverp))
+               if (serverp->servertype != DEMAND)
+                       start_server(serverp);
+
+       pthread_attr_init (&attr);
+       pthread_attr_setdetachstate ( &attr, PTHREAD_CREATE_DETACHED );
+       result = pthread_create(
+                                               &demand_thread,
+                                               &attr,
+                                               demand_loop,
+                                               NULL);
+       if (result) {
+               unix_error("pthread_create()");
                exit(1);
        }
-       exit(0);
-}
 
-static void
-add_init_arg(const char *arg)
-{
-       strncat(init_args, " ", sizeof(init_args));
-       strncat(init_args, arg, sizeof(init_args));
+       /* Process bootstrap service requests */
+       server_loop();  /* Should never return */
+       exit(1);
 }
 
 static void
 wait_for_go(mach_port_t init_notify_port)
 {
-        struct {
+       struct {
             mach_msg_header_t hdr;
             mach_msg_trailer_t trailer;
-        } init_go_msg;
+       } init_go_msg;
        kern_return_t result;
 
-        /*
+       /*
         * For now, we just blindly wait until we receive a message or
         * timeout.  We don't expect any notifications, and if we get one,
         * it probably means something dire has happened; so we might as
         * well give a shot at letting init run.
         */     
-        result = mach_msg(&init_go_msg.hdr, MACH_RCV_MSG, 0, sizeof(init_go_msg), init_notify_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-        if (result != KERN_SUCCESS) {
-            kern_error(result, "mach_msg(receive) failed in wait_for_go");
-        }
-        result = task_set_bootstrap_port(mach_task_self(), init_go_msg.hdr.msgh_remote_port);
-        if (result != KERN_SUCCESS) {
-            kern_error(result, "task_get_bootstrap_port()");
-        }
+       result = mach_msg(
+                                               &init_go_msg.hdr, MACH_RCV_MSG,
+                                               0, sizeof(init_go_msg), init_notify_port,
+                                               MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+       if (result != KERN_SUCCESS) {
+               kern_error(result, "mach_msg(receive) failed in wait_for_go");
+       }
+       result = task_set_bootstrap_port(
+                                               mach_task_self(),
+                                               init_go_msg.hdr.msgh_remote_port);
+       if (result != KERN_SUCCESS) {
+               kern_error(result, "task_get_bootstrap_port()");
+       }
 }
 
+
+static void
+unblock_init(mach_port_t init_notify_port, 
+                        mach_port_t newBootstrap)
+{
+       mach_msg_header_t init_go_msg;
+       kern_return_t result;
+
+       /*
+        * Proc 1 is blocked in a msg_receive on its notify port, this lets
+        * it continue, and we hand off its new bootstrap port
+        */
+       init_go_msg.msgh_remote_port = init_notify_port;
+       init_go_msg.msgh_local_port = newBootstrap;
+        init_go_msg.msgh_bits = MACH_MSGH_BITS(
+                                                               MACH_MSG_TYPE_COPY_SEND,
+                                                               MACH_MSG_TYPE_MAKE_SEND);
+       init_go_msg.msgh_size = sizeof(init_go_msg);
+        result = mach_msg_send(&init_go_msg);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "unblock_init mach_msg_send() failed");
+       debug("sent go message");
+}
+
+
 static void
 init_ports(void)
 {
        kern_return_t result;
        service_t *servicep;
-       mach_port_name_t previous;
-       mach_port_t pport;
 
        /*
         *      This task will become the bootstrap task.
         */
-       bootstrap_self = mach_task_self();
-
-       /* get inherited bootstrap port */
-       result = task_get_bootstrap_port(bootstrap_self,
-                                        &inherited_bootstrap_port);
+       /* Create port set that server loop listens to */
+       result = mach_port_allocate(
+                                               bootstrap_self,
+                                               MACH_PORT_RIGHT_PORT_SET,
+                                               &bootstrap_port_set);
        if (result != KERN_SUCCESS)
-               kern_fatal(result, "task_get_bootstrap_port");
+               kern_fatal(result, "port_set_allocate");
 
-       /* We set this explicitly as we start each child */
-       task_set_bootstrap_port(bootstrap_self, MACH_PORT_NULL);
-       if (inherited_bootstrap_port == MACH_PORT_NULL)
-               forward_ok = FALSE;
-       
-       /* Create port set that server loop listens to */
-       result = mach_port_allocate(bootstrap_self, MACH_PORT_RIGHT_PORT_SET,
-                               &bootstrap_port_set);
+       /* Create demand port set that second thread listens to */
+       result = mach_port_allocate(
+                                               bootstrap_self,
+                                               MACH_PORT_RIGHT_PORT_SET,
+                                               &demand_port_set);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "port_set_allocate");
+
        /* Create notify port and add to server port set */
-       result = mach_port_allocate(bootstrap_self, MACH_PORT_RIGHT_RECEIVE,
-                               &notify_port);
+       result = mach_port_allocate(
+                                               bootstrap_self,
+                                               MACH_PORT_RIGHT_RECEIVE,
+                                               &notify_port);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "mach_port_allocate");
 
-       result = mach_port_request_notification(bootstrap_self,
+       result = mach_port_move_member(
                                                bootstrap_self,
-                                               MACH_NOTIFY_DEAD_NAME,
-                                               0,
                                                notify_port,
-                                               MACH_MSG_TYPE_MAKE_SEND_ONCE,
-                                               &pport);
+                                               bootstrap_port_set);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "mach_port_move_member");
+       
+       /* Create backup port and add to server port set */
+       result = mach_port_allocate(
+                                               bootstrap_self,
+                                               MACH_PORT_RIGHT_RECEIVE,
+                                               &backup_port);
        if (result != KERN_SUCCESS)
-               kern_fatal(result, "task_set_notify_port");
+               kern_fatal(result, "mach_port_allocate");
 
-       result = mach_port_move_member(bootstrap_self,
-                                  notify_port,
-                                  bootstrap_port_set);
+       result = mach_port_move_member(
+                                               bootstrap_self,
+                                               backup_port,
+                                               bootstrap_port_set);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "mach_port_move_member");
        
        /* Create "self" port and add to server port set */
-       result = mach_port_allocate(bootstrap_self, MACH_PORT_RIGHT_RECEIVE,
-                               &bootstraps.bootstrap_port);
+       result = mach_port_allocate(
+                                               bootstrap_self,
+                                               MACH_PORT_RIGHT_RECEIVE,
+                                               &bootstraps.bootstrap_port);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "mach_port_allocate");
-        result = mach_port_insert_right(mach_task_self(), bootstraps.bootstrap_port, bootstraps.bootstrap_port, MACH_MSG_TYPE_MAKE_SEND);
-        if (result != KERN_SUCCESS)
-            kern_fatal(result, "mach_port_insert_right");
-       result = mach_port_move_member(bootstrap_self,
-                                  bootstraps.bootstrap_port,
-                                  bootstrap_port_set);
+       result = mach_port_insert_right(
+                                               bootstrap_self,
+                                               bootstraps.bootstrap_port,
+                                               bootstraps.bootstrap_port,
+                                               MACH_MSG_TYPE_MAKE_SEND);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "mach_port_insert_right");
+
+       /* keep the root bootstrap port "active" */
+       bootstraps.requestor_port = bootstraps.bootstrap_port;
+
+       result = mach_port_move_member(
+                                               bootstrap_self,
+                                               bootstraps.bootstrap_port,
+                                               bootstrap_port_set);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "mach_port_move_member");
-#ifdef notyet 
-       /* register "self" port with anscestor */               
-       if (register_self && forward_ok) {
-               result = bootstrap_register(inherited_bootstrap_port, register_name, bootstraps.bootstrap_port);
-               if (result != KERN_SUCCESS)
-                       kern_fatal(result, "register self");
-       }
-#endif /* notyet*/
+
        /*
         * Allocate service ports for declared services.
         */
@@ -461,32 +542,45 @@ init_ports(void)
        {
                switch (servicep->servicetype) {
                case DECLARED:
-                       result = mach_port_allocate(bootstrap_self, MACH_PORT_RIGHT_RECEIVE,
-                               &(servicep->port));
+                       result = mach_port_allocate(
+                                                       bootstrap_self,
+                                                       MACH_PORT_RIGHT_RECEIVE,
+                                                       &(servicep->port));
                        if (result != KERN_SUCCESS)
                                kern_fatal(result, "mach_port_allocate");
-                       result = mach_port_insert_right(bootstrap_self, servicep->port, servicep->port, MACH_MSG_TYPE_MAKE_SEND);
+
+                       result = mach_port_insert_right(
+                                                       bootstrap_self,
+                                                       servicep->port,
+                                                       servicep->port,
+                                                       MACH_MSG_TYPE_MAKE_SEND);
                        if (result != KERN_SUCCESS)
                                kern_fatal(result, "mach_port_insert_right");
-                       debug("Declared port %d for service %s",
+                       info("Declared port %x for service %s",
                              servicep->port,
                              servicep->name);
-#ifdef notyet
-                       result = port_set_backup(task_self(),
-                                                servicep->port,
-                                                backup_port,
-                                                &previous);
-                       if (result != KERN_SUCCESS)
-                               kern_fatal(result, "port_set_backup");
-#endif /* notyet */
+
+                       if (servicep->server != NULL_SERVER &&
+                               servicep->server->servertype == DEMAND) {
+                               result = mach_port_move_member(
+                                                               bootstrap_self,
+                                                               servicep->port,
+                                                               demand_port_set);
+                               if (result != KERN_SUCCESS)
+                                       kern_fatal(result, "mach_port_move_member");
+                       }
                        break;
+
                case SELF:
                        servicep->port = bootstraps.bootstrap_port;
-                       servicep->server = new_server(MACHINIT,
-                               program_name, init_priority);
-                       info("Set port %d for self port",
+                       servicep->server = new_server(&bootstraps,
+                                                       program_name,
+                                                       inherited_uid,
+                                                       MACHINIT);
+                       info("Set port %x for self port",
                              bootstraps.bootstrap_port);
                        break;
+
                case REGISTERED:
                        fatal("Can't allocate REGISTERED port!?!");
                        break;
@@ -494,152 +588,278 @@ init_ports(void)
        }
 }
 
+boolean_t
+active_bootstrap(bootstrap_info_t *bootstrap)
+{
+       return (bootstrap->requestor_port != MACH_PORT_NULL);
+}
+
+boolean_t
+useless_server(server_t *serverp)
+{
+       return (        !active_bootstrap(serverp->bootstrap) || 
+                               !lookup_service_by_server(serverp) ||
+                               !serverp->activity);
+}
+
+boolean_t
+active_server(server_t *serverp)
+{
+       return (
+#ifdef DELAYED_BOOTSTRAP_DESTROY
+                       serverp->port ||
+#else
+                       (serverp->port && serverp->pid == NO_PID) ||
+#endif
+                       serverp->task_port || serverp->active_services);
+}
+
 static void
-start_server(server_t *serverp)
+reap_server(server_t *serverp)
+{
+       kern_return_t result;
+       pid_t   presult;
+       int             wstatus;
+
+       /*
+        * Reap our children.
+        */
+       presult = waitpid(serverp->pid, &wstatus, WNOHANG);
+       if (presult != serverp->pid) {
+               unix_error("waitpid: cmd = %s", serverp->cmd);
+       } else if (wstatus) {
+               log("Server %x in bootstrap %x uid %d: \"%s\": %s %d [pid %d]",
+                       serverp->port, serverp->bootstrap->bootstrap_port,
+                       serverp->uid, serverp->cmd, 
+                       ((WIFEXITED(wstatus)) ? 
+                        "exited with non-zero status" :
+                        "exited as a result of signal"),
+                       ((WIFEXITED(wstatus)) ? WEXITSTATUS(wstatus) : WTERMSIG(wstatus)),
+                       serverp->pid);
+       }
+       serverp->pid = 0;
+
+       /*
+        * Release the server task port reference, if we ever
+        * got it in the first place.
+        */
+       if (serverp->task_port != MACH_PORT_NULL) {
+               result = mach_port_deallocate(
+                                       mach_task_self(),
+                                       serverp->task_port);
+               if (result != KERN_SUCCESS)
+                       kern_error(result, "mach_port_deallocate");
+               serverp->task_port = MACH_PORT_NULL;
+       }
+}
+
+static void
+demand_server(server_t *serverp)
+{
+       service_t *servicep;
+       kern_return_t result;
+
+       /*
+        * For on-demand servers, make sure that the service ports are
+        * back in on-demand portset.  Active service ports should come
+        * back through a PORT_DESTROYED notification.  We only have to
+        * worry about the inactive ports that may have been previously
+        * pulled from the set but never checked-in by the server.
+        */
+
+       for (  servicep = FIRST(services)
+                          ; !IS_END(servicep, services)
+                          ; servicep = NEXT(servicep))
+       {
+               if (serverp == servicep->server && !servicep->isActive) {
+                       result = mach_port_move_member(
+                                                       mach_task_self(),
+                                                       servicep->port,
+                                                       demand_port_set);
+                       if (result != KERN_SUCCESS)
+                               kern_fatal(result, "mach_port_move_member");
+               }
+       }
+}
+
+static
+void dispatch_server(server_t *serverp)
+{
+       if (!active_server(serverp)) {
+               if (useless_server(serverp))
+                       delete_server(serverp);
+               else if (serverp->servertype == RESTARTABLE)
+                       start_server(serverp);
+               else if (serverp->servertype == DEMAND)
+                       demand_server(serverp);
+       }
+}
+
+void
+setup_server(server_t *serverp)
 {
        kern_return_t result;
        mach_port_t old_port;
-       task_port_t init_task;
-       int pid;
        
-       /* get rid of any old server port (this might be a restart) */
-       old_port = serverp->port;
-       serverp->port = MACH_PORT_NULL;
-        if (old_port != MACH_PORT_NULL) {
-            msg_destroy_port(old_port);
-        }
        /* Allocate privileged port for requests from service */
-       result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE ,&serverp->port);
-       info("Allocating port %d for server %s", serverp->port, serverp->cmd);
+       result = mach_port_allocate(mach_task_self(),
+                                               MACH_PORT_RIGHT_RECEIVE ,
+                                               &serverp->port);
+       info("Allocating port %x for server %s", serverp->port, serverp->cmd);
        if (result != KERN_SUCCESS)     
                kern_fatal(result, "port_allocate");
 
-        result = mach_port_insert_right(mach_task_self(), serverp->port, serverp->port, MACH_MSG_TYPE_MAKE_SEND);
-        if (result != KERN_SUCCESS)
-            kern_fatal(result, "mach_port_insert_right");
+       /* Request no-senders notification so we can tell when server dies */
+       result = mach_port_request_notification(mach_task_self(),
+                                               serverp->port,
+                                               MACH_NOTIFY_NO_SENDERS,
+                                               1,
+                                               serverp->port,
+                                               MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                               &old_port);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "mach_port_request_notification");
+
        /* Add privileged server port to bootstrap port set */
        result = mach_port_move_member(mach_task_self(),
-                                  serverp->port,
-                                  bootstrap_port_set);
+                                               serverp->port,
+                                               bootstrap_port_set);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "mach_port_move_member");
+}
+
+static void
+start_server(server_t *serverp)
+{
+       kern_return_t result;
+       mach_port_t old_port;
+       int pid;
 
        /*
         * Do what's appropriate to get bootstrap port setup in server task
         */
        switch (serverp->servertype) {
-       case ETCINIT:
-               /*
-                * This is pid 1 init program -- need to punch stuff
-                * back into pid 1 task rather than create a new task
-                */
-               result = task_for_pid(mach_task_self(), init_pid, &init_task);
-                if (result != KERN_SUCCESS)
-                    kern_fatal(result, "task_for_pid");
-               serverp->task_port = init_task;
-                unblock_init(init_task, serverp->port);
-               break;
 
        case MACHINIT:
                break;
 
        case SERVER:
+       case DEMAND:
        case RESTARTABLE:
+#ifdef DELAYED_BOOTSTRAP_DESTROY
+         if (!serverp->port)
+#endif
+             setup_server(serverp);
+
+         serverp->activity = 0;
+
+         /* Insert a send right */
+         result = mach_port_insert_right(mach_task_self(),
+                                               serverp->port,
+                                               serverp->port,
+                                               MACH_MSG_TYPE_MAKE_SEND);
+         if (result != KERN_SUCCESS)
+               kern_fatal(result, "mach_port_insert_right");
+
                /* Give trusted service a unique bootstrap port */
-               result = task_set_bootstrap_port(mach_task_self(), serverp->port);
+               result = task_set_bootstrap_port(mach_task_self(),
+                                                serverp->port);
                if (result != KERN_SUCCESS)
                        kern_fatal(result, "task_set_bootstrap_port");
 
+               result = mach_port_deallocate(mach_task_self(),
+                                             serverp->port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_deallocate");
+
                pid = fork();
-               if (pid < 0)
+               if (pid < 0) {
                        unix_error("fork");
-               else if (pid == 0) {    /* CHILD */
+               } else if (pid == 0) {  /* CHILD */
                        exec_server(serverp);
                        exit(1);
                } else {                /* PARENT */
-                       result = task_set_bootstrap_port(mach_task_self(),
-                                                        MACH_PORT_NULL);
+
+                       result = task_set_bootstrap_port(
+                                                       mach_task_self(),
+                                                       MACH_PORT_NULL);
                        if (result != KERN_SUCCESS)
                                kern_fatal(result, "task_set_bootstrap_port");
 
-                       result = task_for_pid(mach_task_self(),
-                                                 pid,
-                                                 &serverp->task_port);
-                       if (result != KERN_SUCCESS)
-                               kern_fatal(result, "getting server task port");
-                       running_servers += 1;
+                       info("Launched server %x in bootstrap %x uid %d: \"%s\": [pid %d]",
+                            serverp->port, serverp->bootstrap->bootstrap_port,
+                                serverp->uid, serverp->cmd, pid);
+                       serverp->pid = pid;
+                       result = task_for_pid(
+                                                       mach_task_self(),
+                                                       pid,
+                                                       &serverp->task_port);
+                       if (result != KERN_SUCCESS) {
+                               kern_error(result, "getting server task port");
+                               reap_server(serverp);
+                               dispatch_server(serverp);
+                               break;
+                       }
+                               
+                       /* Request dead name notification to tell when task dies */
+                       result = mach_port_request_notification(
+                                                       mach_task_self(),
+                                                       serverp->task_port,
+                                                       MACH_NOTIFY_DEAD_NAME,
+                                                       0,
+                                                       notify_port,
+                                                       MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                                       &old_port);
+                       if (result != KERN_SUCCESS) {
+                               kern_error(result, "mach_port_request_notification");
+                               reap_server(serverp);
+                               dispatch_server(serverp);
+                       }
                }
                break;
        }
 }
 
-static void
-unblock_init(task_port_t task, mach_port_t newBootstrap)
-{
-       mach_msg_header_t init_go_msg;
-       kern_return_t result;
-
-       /*
-        * Proc 1 is blocked in a msg_receive on its notify port, this lets
-        * it continue, and we hand off its new bootstrap port
-        */
-       init_go_msg.msgh_remote_port = inherited_bootstrap_port;
-       init_go_msg.msgh_local_port = newBootstrap;
-        init_go_msg.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND);
-        result = mach_msg(&init_go_msg, MACH_SEND_MSG, sizeof(init_go_msg), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-       if (result != KERN_SUCCESS)
-               kern_fatal(result, "unblock_init mach_msg(send) failed");
-       debug("sent go message");
-}
-
 static void
 exec_server(server_t *serverp)
 {
-       int nfds, fd;
-        char **argv;
-       
+       char **argv;
+       sigset_t mask;
+
        /*
         * Setup environment for server, someday this should be Mach stuff
         * rather than Unix crud
         */
-       log("Initiating server %s [pid %d]", serverp->cmd, getpid());
        argv = argvize(serverp->cmd);
-       nfds = getdtablesize();
-
-#ifdef notyet 
-       /*
-        * If our priority's to be changed, set it up here.
-        */
-       if (serverp->priority >= 0) {
-               kern_return_t result;
-               result = task_priority(mach_task_self(), serverp->priority,
-                                        TRUE);
-               if (result != KERN_SUCCESS)
-                       kern_error(result, "task_priority %d",
-                               serverp->priority);
-       }
-#endif /* notyet */
        close_errlog();
 
-       /*
-        * Mark this process as an "init process" so that it won't be
-        * blown away by init when it starts up (or changes states).
-        */
-       if (init_pid == 1) {
-               debug("marking process %s as init_process\n", argv[0]);
-               init_process();
+       if (serverp->uid != inherited_uid)
+               if (setuid(serverp->uid) < 0)
+                       unix_fatal("Disabled server %x bootstrap %x: \"%s\": setuid(%d)",
+                                        serverp->port, serverp->bootstrap->bootstrap_port,
+                                          serverp->cmd, serverp->uid);
+
+       if (setsid() < 0) {
+               /*
+                * We can't keep this from happening, but we shouldn't start
+                * the server not as a process group leader.  So, just fake like
+                * there was real activity, and exit the child.  If needed,
+                * we'll re-launch it under another pid.
+                */
+               serverp->activity = 1;
+               unix_fatal("Temporary failure server %x bootstrap %x: \"%s\": setsid()",
+                          serverp->port, serverp->bootstrap->bootstrap_port,
+                          serverp->cmd);
        }
 
-        for (fd =  debugging ? 3 : 0; fd < nfds; fd++)
-               close(fd);
-       fd = open("/dev/tty", O_RDONLY);
-       if (fd >= 0) {
-               ioctl(fd, TIOCNOTTY, 0);
-               close(fd);
-       }
+       sigemptyset(&mask);
+       (void) sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);
 
-        execv(argv[0], argv);
-       unix_error("Can't exec %s", argv[0]);
+       execv(argv[0], argv);
+       unix_fatal("Disabled server %x bootstrap %x: \"%s\": exec()",
+                          serverp->port,
+                          serverp->bootstrap->bootstrap_port,
+                          serverp->cmd);
 }      
 
 static char **
@@ -676,284 +896,326 @@ argvize(const char *string)
        return argv;
 }
 
+static void *
+demand_loop(void *arg)
+{
+       mach_msg_empty_rcv_t dummy;
+       kern_return_t dresult;
+
+
+       for(;;) {
+               mach_port_name_array_t members;
+               mach_msg_type_number_t membersCnt;
+               mach_port_status_t status;
+               mach_msg_type_number_t statusCnt;
+               int i;
+
+               /*
+                * Receive indication of message on demand service
+                * ports without actually receiving the message (we'll
+                * let the actual server do that.
+                */
+               dresult = mach_msg(
+                                                       &dummy.header,
+                                                       MACH_RCV_MSG|MACH_RCV_LARGE,
+                                                       0,
+                                                       0,
+                                                       demand_port_set,
+                                                       0,
+                                                       MACH_PORT_NULL);
+               if (dresult != MACH_RCV_TOO_LARGE) {
+                       kern_error(dresult, "demand_loop: mach_msg()");
+                       continue;
+               }
+
+               /*
+                * If we are shutting down, there is no use processing
+                * any more of these messages.
+                */
+               if (shutdown_in_progress == TRUE)
+                       return arg;     
+
+               /*
+                * Some port(s) now have messages on them, find out
+                * which ones (there is no indication of which port
+                * triggered in the MACH_RCV_TOO_LARGE indication).
+                */
+               dresult = mach_port_get_set_status(
+                                                       mach_task_self(),
+                                                       demand_port_set,
+                                                       &members,
+                                                       &membersCnt);
+               if (dresult != KERN_SUCCESS) {
+                       kern_error(dresult, "demand_loop: mach_port_get_set_status()");
+                       continue;
+               }
+
+               for (i = 0; i < membersCnt; i++) {
+                       statusCnt = MACH_PORT_RECEIVE_STATUS_COUNT;
+                       dresult = mach_port_get_attributes(
+                                                               mach_task_self(),
+                                                               members[i],
+                                                               MACH_PORT_RECEIVE_STATUS,
+                                                               (mach_port_info_t)&status,
+                                                               &statusCnt);
+                       if (dresult != KERN_SUCCESS) {
+                               kern_error(dresult, "demand_loop: mach_port_get_attributes()");
+                               continue;
+                       }
+
+                       /*
+                        * For each port with messages, take it out of the
+                        * demand service portset, and inform the main thread
+                        * that it might have to start the server responsible
+                        * for it.
+                        */
+                       if (status.mps_msgcount) {
+                               dresult = mach_port_move_member(
+                                                               mach_task_self(),
+                                                               members[i],
+                                                               MACH_PORT_NULL);
+                               if (dresult != KERN_SUCCESS) {
+                                       kern_error(dresult, "demand_loop: mach_port_move_member()");
+                                       continue;
+                               }
+                               notify_server_loop(members[i]);
+                       }
+               }
+
+               dresult = vm_deallocate(
+                                               mach_task_self(),
+                                               (vm_address_t) members,
+                                               (vm_size_t) membersCnt * sizeof(mach_port_name_t));
+               if (dresult != KERN_SUCCESS) {
+                       kern_error(dresult, "demand_loop: vm_deallocate()");
+                       continue;
+               }
+       }
+       return NULL;
+}
+                                                               
 /*
- * server_loop -- pick requests off our service port and process them
+ * server_demux -- processes requests off our service port
  * Also handles notifications
  */
-#define        bootstrapMaxRequestSize 1024
-#define        bootstrapMaxReplySize   1024
 
-static void
-server_loop(void)
+static boolean_t
+server_demux(
+       mach_msg_header_t *Request,
+       mach_msg_header_t *Reply)
 {
     bootstrap_info_t *bootstrap;
     service_t *servicep;
     server_t *serverp;
     kern_return_t result;
-    mach_port_name_t previous;
-    mach_port_array_t array;
-    mach_msg_type_number_t count;
-    int i;
+       mig_reply_error_t *reply;
         
-    union {
-       mach_msg_header_t hdr;
-       char body[bootstrapMaxRequestSize];
-    } msg;
-    union {
-       mach_msg_header_t hdr;
-#ifdef notyet
-       death_pill_t death;
-#endif /* notyet */
-       char body[bootstrapMaxReplySize];
-    } reply;
-           
-    for (;;) {
-       memset(&msg, 0, sizeof(msg));
-        result = mach_msg_overwrite_trap(&msg.hdr, MACH_RCV_MSG|MACH_RCV_INTERRUPT|MACH_RCV_TIMEOUT, 0, sizeof(msg), bootstrap_port_set, 500, MACH_PORT_NULL, MACH_MSG_NULL, 0);
-       if (result != KERN_SUCCESS) {
-            if (result != MACH_RCV_TIMED_OUT) {
-                kern_error(result, "server_loop: msg_receive()");
-            }
-           continue;
-       }
+       debug("received message on port %x\n", Request->msgh_local_port);
 
-#if    DEBUG
-       debug("received message on port %d\n", msg.hdr.msgh_local_port);
-#endif DEBUG
+       /*
+        * Do minimal cleanup and then exit.
+        */
+       if (shutdown_in_progress == TRUE) {
+               log("Shutting down. Deactivating root bootstrap (%x) ...",
+                       bootstraps.bootstrap_port);
+               deactivate_bootstrap(&bootstraps);
+               log("Done.");
+               exit(0);
+       }
+                                       
+       reply = (mig_reply_error_t *)Reply;
 
        /*
         * Pick off notification messages
         */
-       if (msg.hdr.msgh_local_port == notify_port) {
-           mach_port_name_t np;
-
-            switch (msg.hdr.msgh_id) {
-           case MACH_NOTIFY_DEAD_NAME:
-                np = ((mach_dead_name_notification_t *)&msg)->not_port;
-#if    DEBUG
-               info("Notified dead name %d", np);
-#endif DEBUG
-               if (np == inherited_bootstrap_port)
-               {
-                   inherited_bootstrap_port = MACH_PORT_NULL;
-                   forward_ok = FALSE;
-                   break;
-               }
+       if (Request->msgh_local_port == notify_port) {
+               mach_port_name_t np;
+
+               memset(reply, 0, sizeof(*reply));
+               switch (Request->msgh_id) {
+               case MACH_NOTIFY_DEAD_NAME:
+                       np = ((mach_dead_name_notification_t *)Request)->not_port;
+                       debug("Notified dead name %x", np);
+
+                       if (np == inherited_bootstrap_port) {
+                               inherited_bootstrap_port = MACH_PORT_NULL;
+                               forward_ok = FALSE;
+                       }
                
-               /*
-                * This may be notification that the task_port associated
-                * with a task we've launched has been deleted.  This
-                * happens only when the server dies.
-                */
-               serverp = lookup_server_by_task_port(np);
-               if (serverp != NULL) {
-                   info("Notified that server %s died\n", serverp->cmd);
-                   if (running_servers <= 0) {
-                           /* This "can't" happen */
-                           running_servers = 0;
-                           error("task count error");
-                   } else {
-                           running_servers -= 1;
-                           log("server %s died",
-                               serverp != NULL ? serverp->cmd : "Unknown");
-                           if (serverp != NULL) {
-                                   /*
-                                    * FIXME: need to control execs
-                                    * when server fails immediately
-                                    */
-                                   if (   serverp->servertype == RESTARTABLE
-                                       /*
-                                       && haven't started this recently */)
-                                           start_server(serverp);
-                           }
-                   }
-                   break;
-               }
+                       /*
+                        * Check to see if a subset requestor port was deleted.
+                        */
+                       while (bootstrap = lookup_bootstrap_by_req_port(np)) {
+                               debug("Received dead name notification for bootstrap subset %x requestor port %x",
+                                        bootstrap->bootstrap_port, bootstrap->requestor_port);
+                               mach_port_deallocate(
+                                                                        mach_task_self(),
+                                                                        bootstrap->requestor_port);
+                               bootstrap->requestor_port = MACH_PORT_NULL;
+                               deactivate_bootstrap(bootstrap);
+                       }
 
-               /*
-                * Check to see if a subset requestor port was deleted.
-                */
-               while (bootstrap = lookup_bootstrap_req_by_port(np)) {
-                       info("notified that requestor of subset %d died",
-                               bootstrap->bootstrap_port);
-                       delete_bootstrap(bootstrap);
-               }
+                       /*
+                        * Check to see if a defined service has gone
+                        * away.
+                        */
+                       while (servicep = lookup_service_by_port(np)) {
+                               /*
+                                * Port gone, registered service died.
+                                */
+                               debug("Received dead name notification for service %s "
+                                         "on bootstrap port %x\n",
+                                         servicep->name, servicep->bootstrap);
+                               debug("Service %s failed - deallocate", servicep->name);
+                               delete_service(servicep);
+                       }
 
-               /*
-                * Check to see if a defined service has gone
-                * away.
-                */
-               while (servicep = lookup_service_by_port(np)) {
-                   /*
-                    * Port gone, server died.
-                    */
-                   debug("Received destroyed notification for service %s "
-                         "on bootstrap port %d\n",
-                         servicep->name, servicep->bootstrap);
-                   if (servicep->servicetype == REGISTERED) {
-                       debug("Service %s failed - deallocate", servicep->name);
-                       mach_port_deallocate(mach_task_self(),np);
-                       mach_port_deallocate(mach_task_self(),servicep->port);
-                       delete_service(servicep);
-                   } else {
                        /*
-                        * Allocate a new, backed-up port for this service.
+                        * Check to see if a launched server task has gone
+                        * away.
                         */
-                       log("Service %s failed - re-initialize",
-                           servicep->name);
-                       msg_destroy_port(servicep->port);
-                       result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &servicep->port);
-                       if (result != KERN_SUCCESS)
-                               kern_fatal(result, "port_allocate");
-                        result = mach_port_insert_right(bootstrap_self, servicep->port, servicep->port, MACH_MSG_TYPE_MAKE_SEND);
-                        if (result != KERN_SUCCESS)
-                                kern_fatal(result, "mach_port_insert_right");
-#if 0
-                        result = port_set_backup(mach_task_self(),
-                                                   servicep->port,
-                                                   backup_port,
-                                                   &previous);
-                       if (result != KERN_SUCCESS)
-                               kern_fatal(result, "port_set_backup");
-#endif
-                        servicep->isActive = FALSE;
-                   }
+                       if (serverp = lookup_server_by_task_port(np)) {
+                               /*
+                                * Port gone, server died.
+                                */
+                               debug("Received task death notification for server %s ",
+                                         serverp->cmd);
+                               reap_server(serverp);
+                               dispatch_server(serverp);
+                       }
+
+                       mach_port_deallocate(mach_task_self(), np);
+                       reply->RetCode = KERN_SUCCESS;
+                       break;
+
+               case MACH_NOTIFY_PORT_DELETED:
+                       np = ((mach_port_deleted_notification_t *)Request)->not_port;
+                       debug("port deleted notification on 0x%x\n", np);
+                       reply->RetCode = KERN_SUCCESS;
+                       break;
+
+               case MACH_NOTIFY_SEND_ONCE:
+                       debug("notification send-once right went unused\n");
+                       reply->RetCode = KERN_SUCCESS;
+                       break;
+
+               default:
+                       error("Unexpected notification: %d", Request->msgh_id);
+                       reply->RetCode = KERN_FAILURE;
+                       break;
                }
-               break;
-           default:
-               error("Unexpected notification: %d", msg.hdr.msgh_id);
-               break;
-           }
-       }
-#if 0
-        else if (msg.hdr.msg_local_port == backup_port) {
-           notification_t *not = (notification_t *) &msg.hdr;
-           mach_port_name_t np = not->notify_port;
-
-           /*
-            * Port sent back to us, server died.
-            */
-           info("port %d returned via backup", np);
-           servicep = lookup_service_by_port(np);
-           if (servicep != NULL) {
-               debug("Received %s notification for service %s",
-                     not->notify_header.msg_id
-                     == NOTIFY_PORT_DESTROYED
-                     ? "destroyed" : "receive rights",
-                     servicep->name);
-               log("Service %s failed - port backed-up", servicep->name);
-               ASSERT(canReceive(servicep->port));
-               servicep->isActive = FALSE;
-               result = port_set_backup(mach_task_self(),
-                                        servicep->port,
-                                        backup_port,
-                                        &previous);
-               if (result != KERN_SUCCESS)
-                       kern_fatal(result, "port_set_backup");
-           } else
-               msg_destroy_port(np);
        }
-#endif
-        else
-            {  /* must be a service request */
-            bootstrap_server(&msg.hdr, &reply.hdr);
-#ifdef DEBUG
-           debug("Handled request.");
-#endif DEBUG
-               reply.hdr.msgh_local_port = MACH_PORT_NULL;
-                result = mach_msg(&reply.hdr, MACH_SEND_MSG|MACH_SEND_TIMEOUT, reply.hdr.msgh_size, 0, MACH_PORT_NULL,
-                                 BOOTSTRAP_REPLY_TIMEOUT, MACH_PORT_NULL);
-#ifdef DEBUG
-               debug("Reply sent.");
-#endif DEBUG
-                if (result != MACH_MSG_SUCCESS) {
-                   kern_error(result, "msg_send");
-                }
-            }
-       /* deallocate uninteresting ports received in message */
-       msg_destroy(&msg.hdr);
-    }
-}
 
-/*
- * msg_destroy -- walk through a received message and deallocate any
- * useless ports or out-of-line memory
- */
-static void
-msg_destroy(mach_msg_header_t *m)
-{
-#ifdef notyet /* [ */
-       msg_type_t *mtp;
-       msg_type_long_t *mtlp;
-       void *dp;
-       unsigned type, size, num;
-       boolean_t inlne;
-       mach_port_t *pp;
-       kern_return_t result;
+       else if (Request->msgh_local_port == backup_port) {
+               mach_port_name_t np;
+
+               memset(reply, 0, sizeof(*reply));
+
+               np = ((mach_port_destroyed_notification_t *)Request)->not_port.name; 
+               servicep = lookup_service_by_port(np);
+               if (servicep != NULL) {
+                       server_t *serverp = servicep->server;
+
+                       switch (Request->msgh_id) {
+
+                       case MACH_NOTIFY_PORT_DESTROYED:
+                               /*
+                                * Port sent back to us, server died.
+                                */
+                               debug("Received destroyed notification for service %s",
+                                         servicep->name);
+                               debug("Service %x bootstrap %x backed up: %s",
+                                    servicep->port, servicep->bootstrap->bootstrap_port,
+                                        servicep->name);
+                               ASSERT(canReceive(servicep->port));
+                               servicep->isActive = FALSE;
+                               serverp->active_services--;
+                               dispatch_server(serverp);
+                               reply->RetCode = KERN_SUCCESS;
+                               break;
 
-       msg_destroy_port(m->msg_remote_port);
-       for (  mtp = (msg_type_t *)(m + 1)
-            ; (unsigned)mtp - (unsigned)m < m->msg_size
-            ;)
-       {
-               inlne = mtp->msg_type_inline;
-               if (mtp->msg_type_longform) {
-                       mtlp = (msg_type_long_t *)mtp;
-                       type = mtlp->msg_type_long_name;
-                       size = mtlp->msg_type_long_size;
-                       num = mtlp->msg_type_long_number;
-                       dp = (void *)(mtlp + 1);
+                       case DEMAND_REQUEST:
+                               /* message reflected over from demand start thread */
+                               if (!active_server(serverp))
+                                       start_server(serverp);
+                               reply->RetCode = KERN_SUCCESS;
+                               break;
+
+                       default:
+                               debug("Mysterious backup_port notification %d", Request->msgh_id);
+                               reply->RetCode = KERN_FAILURE;
+                               break;
+                       }
                } else {
-                       type = mtp->msg_type_name;
-                       size = mtp->msg_type_size;
-                       num = mtp->msg_type_number;
-                       dp = (void *)(mtp + 1);
+                       debug("Backup_port notification - previously deleted service");
+                       reply->RetCode = KERN_FAILURE;
                }
-               if (inlne)
-                       mtp = (msg_type_t *)(dp + num * (size/BITS_PER_BYTE));
-               else {
-                       mtp = (msg_type_t *)(dp + sizeof(void *));
-                       dp = *(char **)dp;
-               }
-               if (MSG_TYPE_PORT_ANY(type)) {
-                       for (pp = (mach_port_t *)dp; num-- > 0; pp++)
-                               msg_destroy_port(*pp);
-               }
-               if ( ! inlne ) {
-                       result = vm_deallocate(mach_task_self(), (vm_address_t)dp,
-                        num * (size/BITS_PER_BYTE));
-                       if (result != KERN_SUCCESS)
-                               kern_error(result,
-                                          "vm_deallocate: msg_destroy");
+       }
+
+       else if (Request->msgh_id == MACH_NOTIFY_NO_SENDERS) {
+               mach_port_t ns = Request->msgh_local_port;
+
+               if ((serverp = lookup_server_by_port(ns)) != NULL_SERVER) {
+                       /*
+                        * A server we launched has released his bootstrap
+                        * port send right.  We won't re-launch him unless
+                        * his services came back to roost.  But we need to
+                        * destroy the bootstrap port for fear of leaking.
+                        */
+                       debug("server %s dropped server port", serverp->cmd);
+                       serverp->port = MACH_PORT_NULL;
+                       dispatch_server(serverp);
+               } else if (bootstrap = lookup_bootstrap_by_port(ns)) {
+                       /*
+                        * The last direct user of a deactivated bootstrap went away.
+                        * We can finally free it.
+                        */
+                       debug("Deallocating bootstrap %x: no more clients", ns);
+                       bootstrap->bootstrap_port = MACH_PORT_NULL;
+                       deallocate_bootstrap(bootstrap);
                }
+               
+               result = mach_port_mod_refs(
+                                               mach_task_self(),
+                                               ns,
+                                               MACH_PORT_RIGHT_RECEIVE,
+                                               -1);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_mod_refs");
+
+               memset(reply, 0, sizeof(*reply));
+               reply->RetCode = KERN_SUCCESS;
+       }
+     
+       else {  /* must be a service request */
+               debug("Handled request.");
+               return bootstrap_server(Request, Reply);
        }
-#endif /* notyet ] */
+       return TRUE;
 }
 
 /*
- * msg_destroy_port -- deallocate port if it's not important to bootstrap
- * Bad name, this is used for things other than msg_destroy.
+ * server_loop -- pick requests off our service port and process them
+ * Also handles notifications
  */
-void
-msg_destroy_port(mach_port_t p)
+#define        bootstrapMaxRequestSize 1024
+#define        bootstrapMaxReplySize   1024
+
+static void
+server_loop(void)
 {
-       if (   p == MACH_PORT_NULL
-           || p == mach_task_self()
-           || p == mig_get_reply_port()
-           || p == bootstrap_port_set
-           || p == inherited_bootstrap_port
-           || lookup_service_by_port(p)
-           || lookup_server_by_port(p)
-           || lookup_bootstrap_by_port(p) != &bootstraps
-           || lookup_bootstrap_req_by_port(p) != &bootstraps
-           || p == bootstraps.bootstrap_port
-           || p == bootstraps.requestor_port)
-               return;
-
-#if    DEBUG
-       debug("Deallocating port %d", p);
-#endif DEBUG
-       (void) mach_port_deallocate(mach_task_self(), p);
+       mach_msg_return_t mresult;
+
+       for (;;) {
+               mresult = mach_msg_server(
+                                               server_demux,
+                                               bootstrapMaxRequestSize,
+                                               bootstrap_port_set,
+                        MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_SENDER)|
+                        MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
+               if (mresult != MACH_MSG_SUCCESS)
+                               kern_error(mresult, "mach_msg_server");
+       }
 }
 
 boolean_t
@@ -984,44 +1246,3 @@ canSend(mach_port_t port)
        }
        return ((p_type & MACH_PORT_TYPE_PORT_RIGHTS) != 0);
 }
-void
-set_default_policy(
-       mach_port_t master_host_port)
-{
-#if 0
-    host_priority_info_data_t  host_pri_info;
-       mach_port_t             default_processor_set_name;
-       mach_port_t             default_processor_set;
-       policy_rr_base_data_t   rr_base;
-       policy_rr_limit_data_t  rr_limit;
-       kern_return_t           result;
-       mach_msg_type_number_t  count;
-       static char here[] = "default_pager_set_policy";
-
-       count = HOST_PRIORITY_INFO_COUNT;
-       result = host_info(mach_host_self(),
-                     HOST_PRIORITY_INFO,
-                     (host_info_t) &host_pri_info,
-                     &count);
-       if (result != KERN_SUCCESS)
-               kern_fatal(result, "Could not get host priority info");
-
-       rr_base.quantum = 0;
-       rr_base.base_priority = host_pri_info.system_priority;
-       rr_limit.max_priority = host_pri_info.system_priority;
-
-       (void)processor_set_default(mach_host_self(),
-                                   &default_processor_set_name);
-       (void)host_processor_set_priv(master_host_port,
-                                     default_processor_set_name,
-                                     &default_processor_set);
-
-       result = task_set_policy(mach_host_self(), default_processor_set,
-                           POLICY_RR,
-                           (policy_base_t) & rr_base, POLICY_RR_BASE_COUNT,
-                           (policy_limit_t) & rr_limit, POLICY_RR_LIMIT_COUNT,
-                           TRUE);
-       if (result != KERN_SUCCESS)
-               kern_fatal(result, "Could not set task policy ");
-#endif
-}
index 99af0ccbcd1e082b26d384fc989e653e21fc3e3b..43a0b601e86258a5ed6f556077e7365f7f8b099e 100644 (file)
@@ -37,19 +37,15 @@ subsystem bootstrap 400;
  *  The bootstrap server is the first user-mode task initiated by the Mach
  *  kernel at system boot time.  The bootstrap server provides two services,
  *  it initiates other system tasks, and manages a table of name-port bindings
- *  for fundamental system services  (e.g. the NetMsgServer, and the Unix
- *  emulation service).
- *
- *  The file /etc/bootstrap.conf is read by bootstrap to determine other system
- *  services to initiate at system boot time.  The format of this file is
- *  described later.
+ *  for fundamental system services  (e.g. lookupd, Window Manager, etc...).
  *
  *  Name-port bindings can be established with the bootstrap server by either 
  *  of two mechanisms:
  *
- *  1.  The binding can be indicated in the file /etc/bootstrap.conf.  In this
- *  case, bootstrap will immediately create a port and bind the indicated name
- *  with that port.  At a later time, a service may "checkin" for the name-port
+ *  1.  The binding can be indicated, in advance of the service that backs it
+ *  being available, via a "service create" request.  In this case, bootstrap
+ *  will immediately create a port and bind the indicated name with that port.
+ *  At a later time, a service may "checkin" for the name-port
  *  binding and will be returned receive rights for the bound port.  Lookup's
  *  on bindings created by this mechanism will return send rights to the port,
  *  even if no service has "checked-in".  In this case, requests sent to the
@@ -73,98 +69,112 @@ subsystem bootstrap 400;
  *  it is marked available for check-out again.  This allows crashed servers to 
  *  resume service to previous clients.  Lookup's on this named port will 
  *  continue to be serviced by bootstrap while holding receive rights for the 
- *  bound port.  A client may detect that the service is inactive via the.
- *  bootstrap status request.  If the service re-registers rather than
- *  "checking-in" the original bound port is destroyed.
+ *  bound port.  A client may detect that the service is inactive via the
+ *  bootstrap status request.  If an inactive service re-registers rather
+ *  than "checking-in" the original bound port is destroyed.
  *
  *  The status of a named service may be obtained via the "status" request.
  *  A service is "active" if a name-port binding exists and receive rights
  *  to the bound port are held by a task other than bootstrap.
  *
- *  Bootstrap initiates server tasks and creates initial name-port bindings as
- *  directed by the configuration file /etc/bootstrap.conf.  This file has
- *  entries with the following formats:
- *
- *     services [ SERVICE_NAME ]+ ;
- *
- *             E.g:
- *             services OldService=1 SomeService;
- *
- *             Creates a port and binds the name "OldService" to it.
- *             For compatability, assigns the port via mach_ports_register to
- *             slot 1.  Also creates a port and binds the name "SomeService".
- *
- *     self [ SERVICE_NAME ]+ ;
- *
- *             E.g:
- *             self BootStrapService;
- *
- *             Provides a binding to bootstrap's own service port named
- *             "BootStrapService".
- *
- *     [restartable] server SERVER_FILE_AND_ARGS [ services ... ] ;
- *
- *             E.g:
- *             server "/usr/etc/sigserver -i" services UnixSignalService;
- *
- *             Initiates the server task "/usr/etc/sigserver" with
- *             command-line argument "-i", and also creates a name-port
- *             binding for the name UnixSignalService.  Checkin requests for
- *             UnixSignalService are only accepted via the bootstrap service
- *             port passed to/usr/etc/sigserver.  If the "restartable" option
- *             had been specified, bootstrap will reinitiate the server task
- *             if it receives notification that all of the server's service
- *             ports have been destroyed or deallocated.  The server command
- *             may be specified without surrounding quotes if it does not
- *             include blanks.
- *
- *     init SERVER_FILE_AND_ARGS [ services ... ] ;
- *
- *             E.g:
- *             init /etc/init services NetMsgService=0 PSWindowService=4;
- *
- *             Functions like "server" request above, except process is
- *             started as pid 1.  Illegal if bootstrap itself was not
- *             initiated as pid 1.
- *
- *     forward;
- *
- *             If present, bootstrap will forward unknown lookup requests to
- *             its bootstrap service port (if not PORT_NULL), and forward any
- *             reply to the original requester.
- *
- *     # Comment string up to end of line.
- *
- *             A line terminated comment starts with a sharp sign (#).
- *
- *  Lexical notes:  Strings are either enclosed in double quotes ("), or must
- *  start with a letter or underscore (_) and followed by a string of
- *  alphanumerics and underscores; backslash (\) escapes the following
- *  character.  Strings are limited to a (large) length.  Numbers must be
- *  decimal.  Blanks and newlines may be freely used outside of strings.
+ *  The bootstrap server may also (re)start server processes associated with
+ *  with a set of services. The definition of the server process is done
+ *  through the "create server" request.  The server will be launched in the
+ *  same bootstrap context in which it was registered.
  */
 
 #include <mach/std_types.defs>
+#include <mach/mach_types.defs>
 import <servers/bootstrap_defs.h>;
 
-type name_t            = c_string[128];
-type name_array_t      = ^array [] of name_t;
-type bool_array_t      = ^array [] of boolean_t;
+type cmd_t                     = c_string[512];
+type name_t                    = c_string[128];
+type cmd_array_t               = ^array [] of cmd_t;
+type name_array_t              = ^array [] of name_t;
+type bootstrap_status_t                = integer_t;
+type bootstrap_status_array_t  = ^array [] of bootstrap_status_t;
 
 serverprefix x_;
 
-/*  old service_checkin */
-skip;
-/*  old service_status */
-skip;
+/*
+ * kern_return_t
+ * bootstrap_create_server(mach_port_t bootstrap_port,
+ *                     cmd_t server_command,
+ *                     integer_t server_uid,
+ *                     boolean_t on_demand,
+ *                     mach_port_t *server_port)
+ *
+ * Declares a server that mach_init will re-spawn within the specified
+ * bootstrap context.  The server is considered already "active"
+ * (i.e. will not be re-spawned) until the returned server_port is
+ * deallocated.
+ *
+ * In the meantime, services can be declared against the server,
+ * by using the server_port as the privileged bootstrap target of
+ * subsequent bootstrap_create_service() calls.
+ *
+ * When mach_init re-spawns the server, its task bootstrap port
+ * is set to the privileged sever_port.  Through this special
+ * bootstrap port, it can access all of parent bootstrap's context
+ * (and all services are created in the parent's namespace). But
+ * all additional service declarations (and declaration removals)
+ * will be associated with this particular server.
+ *
+ * Only a holder of the server_port privilege bootstrap port can
+ * check in or register over those services.  
+ *
+ * When all services associated with a server are deleted, and the server
+ * exits, it will automatically be deleted itself.
+ *
+ * If the server is declared "on_demand," then a non-running server
+ * will be re-launched on first use of one of the service ports
+ * registered against it.  Otherwise, it will be re-launched
+ * immediately upon exiting (whether any client is actively using
+ * any of the service ports or not).
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NOT_PRIVILEGED, bootstrap or uid invalid.
+ */
+routine bootstrap_create_server(
+               bootstrap_port  : mach_port_t;
+               server_cmd      : cmd_t;
+               server_uid      : integer_t;
+               on_demand       : boolean_t;
+ ServerSecToken        token           : security_token_t;
+       out     server_port     : mach_port_make_send_t);
+
+/*
+ * kern_return_t
+ * bootstrap_unprivileged(mach_port_t bootstrap_port,
+ *                       mach_port_t *unpriv_port)
+ *
+ * Given a bootstrap port, return its unprivileged equivalent.  If
+ * the port is already unprivileged, another reference to the same
+ * port is returned.
+ *
+ * This is most often used by servers, which are launched with their
+ * bootstrap port set to the privileged port for the server, to get
+ * an unprivileged version of the same port for use by its unprivileged
+ * children (or any offspring that it does not want to count as part
+ * of the "server" for mach_init registration and re-launch purposes).
+ */
+routine bootstrap_unprivileged(
+               bootstrap_port  : mach_port_t;
+       out     unpriv_port     : mach_port_t);
 
 /*
  * kern_return_t
  * bootstrap_check_in(mach_port_t bootstrap_port,
  *                  name_t service_name,
- *                  port_all_t *service_port)
+ *                  mach_port_t *service_port)
  *
- * Returns all rights to service_port of service named by service_name.
+ * Returns the receive right for the service named by service_name. The
+ * service must have previously been declared in this bootstrap context via
+ * a call to bootstrap_create_service().  Attempts to check_in a service
+ * which is already active are not allowed.
+ *
+ * If the service was declared as being associated with a server, the
+ * check_in must come from the server's privileged port (server_port).
  *
  * Errors:     Returns appropriate kernel errors on rpc failure.
  *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
@@ -184,14 +194,15 @@ routine bootstrap_check_in(
  *                   name_t service_name,
  *                   mach_port_t service_port)
  *
- * Registers send rights for the port service_port for the service named by
- * service_name.  Attempts to registering a service where an active binding
- * already exists are rejected.  On the otherhand, registering a service where
- * and inactive binding exists (i.e. bootstrap currently holds receive rights
- * for the service port) is allowed; in this case the previous service port
- * will be deallocated.  Restarting services wishing to resume service for
- * previous clients must first attempt to checkin to the service in order to
- * recover the previous service port.
+ * Registers a send right for service_port with the service identified by
+ * service_name.  Attempts to register a service where an active binding
+ * already exists are rejected.
+ *
+ * If the service was previously declared with bootstrap_create_service(),
+ * but is not currently active, this call can be used to undeclare the
+ * service. The bootstrap port used must have sufficient privilege to
+ * do so.  (Registering MACH_PORT_NULL is especially useful for shutting
+ * down declared services).
  *
  * Errors:     Returns appropriate kernel errors on rpc failure.
  *             Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
@@ -210,8 +221,9 @@ routine bootstrap_register(
  *                 name_t service_name,
  *                 mach_port_t *service_port)
  *
- * Returns send rights for the service port of the service named by
- * service_name in service_port.  Service is not guaranteed to be active.
+ * Returns a send right for the service port declared/registered under the
+ * name service_name. The service is not guaranteed to be active.  Use the
+ * bootstrap_status call to determine the status of the service.
  *
  * Errors:     Returns appropriate kernel errors on rpc failure.
  *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
@@ -249,16 +261,33 @@ routine bootstrap_look_up_array(
        out     service_ports   : mach_port_array_t;
        out     all_services_known: boolean_t);
 
-/*  old bootstrap_get_unpriv_port */
-skip;
+/*
+ * kern_return_t
+ * bootstrap_parent(mach_port_t bootstrap_port,
+ *                 mach_port_t *parent_port);
+ *
+ * Given a bootstrap subset port, return the parent bootstrap port.
+ * If the specified bootstrap port is already the root subset,
+ * MACH_PORT_NULL will be returned.
+ *
+ * Errors:
+ *     Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running
+ *     with an effective user id of root (as determined by the security
+ *     token in the message trailer).
+ */
+routine bootstrap_parent(
+               bootstrap_port  : mach_port_t;
+ ServerSecToken        token           : security_token_t;
+       out     parent_port     : mach_port_t);
 
 /*
  * kern_return_t
  * bootstrap_status(mach_port_t bootstrap_port,
  *                 name_t service_name,
- *                 boolean_t *service_active);
+ *                 bootstrap_status_t *service_active);
  *
- * Returns: service_active is true if service is available.
+ * Returns: service_active indicates if service is active, inactive, or
+ *         associated with a launch-on-demand server.
  *                     
  * Errors:     Returns appropriate kernel errors on rpc failure.
  *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
@@ -266,7 +295,7 @@ skip;
 routine bootstrap_status(
                bootstrap_port  :       mach_port_t;
                service_name    :       name_t;
-       out     service_active  :       boolean_t);
+       out     service_active  :       bootstrap_status_t);
 
 /*
  * kern_return_t
@@ -284,7 +313,7 @@ routine bootstrap_info(
                bootstrap_port  : mach_port_t;
        out     service_names   : name_array_t, dealloc;
        out server_names        : name_array_t, dealloc;
-       out service_active      : bool_array_t, dealloc);
+       out service_active      : bootstrap_status_array_t, dealloc);
 
 /*
  * kern_return_t
@@ -301,7 +330,7 @@ routine bootstrap_info(
  * registered with an ancestor port may be registered with the subset port
  * are allowed.  Services already advertised may then be effectively removed
  * by registering PORT_NULL for the service.
- * When it is detected that the requestor_port is destroied the subset
+ * When it is detected that the requestor_port is destroyed the subset
  * port and all services advertized by it are destroied as well.
  *
  * Errors:     Returns appropriate kernel errors on rpc failure.
@@ -328,3 +357,4 @@ routine bootstrap_create_service(
                bootstrap_port  : mach_port_t;
                service_name    : name_t;
        out     service_port    : mach_port_t);
+
index b494e93ab7ce94995fb9e4bd46675a9b53d06f2a..bf8192506fda7cedb1e8f08b3321a8e635b47601 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2002-1999 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 
 #import <mach/mach.h>
 #import <mach/boolean.h>
+#import <mach/notify.h>
 
-#define BASEPRI_USER   10      /* AOF Thu Feb 16 14:42:57 PST 1995 */
+#define BASEPRI_USER   31      /* AOF 20/02/2002 */
 
 #define        BITS_PER_BYTE   8       /* this SHOULD be a well defined constant */
 #define        ANYWHERE        TRUE    /* For use with vm_allocate() */
 
+#define DEMAND_REQUEST MACH_NOTIFY_LAST        /* demand service messaged */
+
+#define DELAYED_BOOTSTRAP_DESTROY TRUE         /* destroyed on last reference */
+
 extern const char *program_name;
-extern const char *conf_file;
-extern const char *default_conf;
 extern mach_port_t lookup_only_port;
 extern mach_port_t inherited_bootstrap_port;
 extern mach_port_t self_port;          /* Compatability hack */
 extern boolean_t forward_ok;
 extern boolean_t debugging;
 extern mach_port_t bootstrap_port_set;
-extern int init_priority;
+extern mach_port_t demand_port_set;
+extern mach_port_t notify_port;
+extern mach_port_t backup_port;
 extern boolean_t canReceive(mach_port_t port);
 extern boolean_t canSend(mach_port_t port);
-
-extern void msg_destroy_port(mach_port_t p);
index 599e4d975d73b85a98ab3648a20369dc376035b4..183abfcab42caeefc149819a6528f1c150e10f57 100644 (file)
 #import "error_log.h"
 
 static pthread_mutex_t errlog_lock = PTHREAD_MUTEX_INITIALIZER;
+static boolean_t stderr_open = FALSE;
+static boolean_t log_stopped = FALSE;
 
 void
-init_errlog(boolean_t is_init)
+init_errlog(boolean_t daemon)
 {
        int nfds, fd;
 
-       if (is_init) {
-               close(0);
-               freopen("/dev/console", "r", stdin);
-               setbuf(stdin, NULL);
-               close(1);
-               freopen("/dev/console", "w", stdout);
-               setbuf(stdout, NULL);
-               close(2);
-               freopen("/dev/console", "w", stderr);
-               setbuf(stderr, NULL);
+       if (!daemon) {
+               stderr_open = TRUE; 
+               nfds = getdtablesize();
+               for (fd = 3; fd < nfds; fd++)
+                       close(fd);
+       } else {
+               openlog((char *)program_name, LOG_PID|LOG_CONS, LOG_DAEMON);
+               setlogmask(LOG_UPTO(LOG_DEBUG)); /* we'll do our own filtering */
        }
+}
 
-       nfds = getdtablesize();
-       for (fd = 3; fd < nfds; fd++)
-               close(fd);
-       openlog((char *)program_name, LOG_PID, LOG_DAEMON);
-       setlogmask(LOG_UPTO(LOG_INFO));
+void
+stop_errlog(void)
+{
+       log_stopped = TRUE;
 }
 
 void
 close_errlog(void)
 {
+       stop_errlog();
        closelog();
 }
 
 static void do_log(const int level, const char *format, va_list ap)
 {
-       pthread_mutex_lock(&errlog_lock);
-       if (debugging) {
-               fprintf(stderr, "%s[%d]%s: ",
-                       level == LOG_ALERT ? " FATAL" : "",
-                       getpid(), program_name);
-               vfprintf(stderr, format, ap);
-               fprintf(stderr, "\n");
-       } else {
-               vsyslog(level, format, ap);
+       if (!log_stopped && (debugging || level <= LOG_NOTICE)) {
+               pthread_mutex_lock(&errlog_lock);
+               if (stderr_open) {
+                       fprintf(stderr, "%s[%d]%s: ",
+                               level == LOG_ALERT ? " FATAL" : "",
+                               getpid(), program_name);
+                       vfprintf(stderr, format, ap);
+                       fprintf(stderr, "\n");
+               } else {
+                       vsyslog(level, format, ap);
+               }
+               pthread_mutex_unlock(&errlog_lock);
        }
-       pthread_mutex_unlock(&errlog_lock);
 }
 
 void debug(const char *format, ...)
index 027ab75354a04730987d3c6099897f702f5c8bc3..f6dc4df11066959539c03f8da28b19d473b23cf5 100644 (file)
@@ -31,7 +31,9 @@
 
 #import <mach/mach.h>
 
-extern void init_errlog(boolean_t is_init);
+extern void init_errlog(boolean_t);
+extern void stop_errlog(void);
+extern void close_errlog(void);
 extern void debug(const char *format, ...);
 extern void info(const char *format, ...);
 extern void log(const char *format, ...);
@@ -42,5 +44,4 @@ extern void unix_error(const char *msg, ...);
 extern void fatal(const char *msg, ...);
 extern void kern_fatal(kern_return_t result, const char *msg, ...);
 extern void unix_fatal(const char *msg, ...);
-extern void close_errlog(void);
 
diff --git a/mach_init.tproj/initConf b/mach_init.tproj/initConf
deleted file mode 100644 (file)
index b52c7e9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-services FreeService1 FreeService2 EnvironService=1;
-init testServer services Service=2 TerminalService;
-# server "/NextApps/Terminal -Lines 24 -Columns 60" services TerminalService;
-server "/NextApps/Shell" services ShellService;
-machports 0=NetMsgService=0 3=WindowService=3;
-
-
index 9f371a1ed9e1a3cf8f67b6fd7875c5a72417537c..ee1a008b298a7b0315a950d632a87f6eb41262fd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -62,6 +62,7 @@ unsigned nservices;           /* number of services in list */
 void
 init_lists(void)
 {
+       bootstraps.ref_count = 2; /* make sure we never deallocate this one */
        bootstraps.next = bootstraps.prev = &bootstraps;
        servers.next = servers.prev = &servers;
        services.next = services.prev = &services;
@@ -70,13 +71,14 @@ init_lists(void)
 
 server_t *
 new_server(
-       servertype_t    servertype,
-       const char      *cmd,
-       int             priority)
+       bootstrap_info_t        *bootstrap,
+       const char              *cmd,
+       int                     uid,
+       servertype_t            servertype)
 {
        server_t *serverp;
 
-       debug("adding new server \"%s\" with priority %d\n", cmd, priority);    
+       debug("adding new server \"%s\" with uid %d\n", cmd, uid);      
        serverp = NEW(server_t, 1);
        if (serverp != NULL) {
                /* Doubly linked list */
@@ -85,15 +87,23 @@ new_server(
                serverp->next = &servers;
                servers.prev = serverp;
 
+               bootstrap->ref_count++;
+               serverp->bootstrap = bootstrap;
+
+               serverp->pid = NO_PID;
+               serverp->task_port = MACH_PORT_NULL;
+               serverp->uid = uid;
+
                serverp->port = MACH_PORT_NULL;
                serverp->servertype = servertype;
-               serverp->priority = priority;
+               serverp->activity = 0;
+               serverp->active_services = 0;
                strncpy(serverp->cmd, cmd, sizeof serverp->cmd);
                LAST_ELEMENT(serverp->cmd) = '\0';
        }
        return serverp;
 }
-                       
+       
 service_t *
 new_service(
        bootstrap_info_t        *bootstrap,
@@ -103,10 +113,7 @@ new_service(
        servicetype_t   servicetype,
        server_t        *serverp)
 {
-       extern mach_port_t notify_port;
         service_t *servicep;
-       mach_port_t pport;
-        kern_return_t result;
         
        servicep = NEW(service_t, 1);
        if (servicep != NULL) {
@@ -120,23 +127,11 @@ new_service(
                
                strncpy(servicep->name, name, sizeof servicep->name);
                LAST_ELEMENT(servicep->name) = '\0';
+               servicep->servicetype = servicetype;
                servicep->bootstrap = bootstrap;
-               servicep->server = serverp;
                servicep->port = service_port;
-                result = mach_port_request_notification(mach_task_self(),
-                                                        service_port,
-                                                        MACH_NOTIFY_DEAD_NAME,
-                                                        0,
-                                                        notify_port,
-                                                        MACH_MSG_TYPE_MAKE_SEND_ONCE,
-                                                        &pport);
-                if (result == KERN_SUCCESS) {
-                    debug("added notification for %s\n", servicep->name);
-                } else {
-                    error("couldn't add notification for %s: %s\n", servicep->name, mach_error_string(result));
-                }
-                servicep->isActive = isActive;
-               servicep->servicetype = servicetype;
+               servicep->server = serverp;
+               servicep->isActive = isActive;
        }
        return servicep;
 }
@@ -147,10 +142,7 @@ new_bootstrap(
        mach_port_t     bootstrap_port,
        mach_port_t     requestor_port)
 {
-       extern mach_port_t notify_port;
        bootstrap_info_t *bootstrap;
-       mach_port_t pport;
-       kern_return_t result;
 
        bootstrap = NEW(bootstrap_info_t, 1);
        if (bootstrap != NULL) {
@@ -162,19 +154,10 @@ new_bootstrap(
                
                bootstrap->bootstrap_port = bootstrap_port;
                bootstrap->requestor_port = requestor_port;
-               bootstrap->parent = parent;
-                result = mach_port_request_notification(mach_task_self(),
-                                                        requestor_port,
-                                                        MACH_NOTIFY_DEAD_NAME,
-                                                        0,
-                                                        notify_port,
-                                                        MACH_MSG_TYPE_MAKE_SEND_ONCE, &pport); 
-                if (result == KERN_SUCCESS) {
-                    info("added notification for sub-bootstrap");
-                } else {
-                    error("couldn't add notification for sub-bootstrap: %s\n", mach_error_string(result));
-                }
 
+               bootstrap->ref_count = 1;
+               bootstrap->parent = parent;
+               parent->ref_count++;
        }
        return bootstrap;
 }
@@ -183,20 +166,28 @@ bootstrap_info_t *
 lookup_bootstrap_by_port(mach_port_t port)
 {
        bootstrap_info_t *bootstrap;
+       bootstrap_info_t *first;
+       server_t *serverp;
 
-       for (  bootstrap = FIRST(bootstraps)
-            ; !IS_END(bootstrap, bootstraps)
-            ; bootstrap = NEXT(bootstrap))
-       {
+       bootstrap = first = FIRST(bootstraps);
+       do {  
                if (bootstrap->bootstrap_port == port)
                        return bootstrap;
+               bootstrap = NEXT(bootstrap);
+       } while (bootstrap != first);
+       
+       for (  serverp = FIRST(servers)
+            ; !IS_END(serverp, servers)
+            ; serverp = NEXT(serverp))
+       {
+               if (port == serverp->port)
+                       return serverp->bootstrap;
        }
-
-       return &bootstraps;
+       return NULL;
 }
 
 bootstrap_info_t *
-lookup_bootstrap_req_by_port(mach_port_t port)
+lookup_bootstrap_by_req_port(mach_port_t port)
 {
        bootstrap_info_t *bootstrap;
 
@@ -247,13 +238,32 @@ void
 delete_service(service_t *servicep)
 {
        unlink_service(servicep);
+       switch (servicep->servicetype) {
+       case REGISTERED:
+               info("Registered service %s deleted", servicep->name);
+               mach_port_deallocate(mach_task_self(), servicep->port);
+               break;
+       case DECLARED:
+               info("Declared service %s now unavailable", servicep->name);
+               mach_port_deallocate(mach_task_self(), servicep->port);
+               mach_port_mod_refs(mach_task_self(), servicep->port,
+                                  MACH_PORT_RIGHT_RECEIVE, -1);
+               break;
+       case SELF:
+               error("Self service %s now unavailable", servicep->name);
+               break;
+       default:
+               error("unknown service type %d\n", servicep->servicetype);
+               break;
+       }
        free(servicep);
        nservices -= 1;
 }
 
 void
-destroy_services(bootstrap_info_t *bootstrap)
+delete_bootstrap_services(bootstrap_info_t *bootstrap)
 {
+       server_t  *serverp;
        service_t *servicep;
        service_t *next;
        
@@ -264,24 +274,17 @@ destroy_services(bootstrap_info_t *bootstrap)
                next = NEXT(servicep);
                if (bootstrap != servicep->bootstrap)
                        continue;
-               unlink_service(servicep);
-               switch (servicep->servicetype) {
-               case REGISTERED:
-                       log("Service %s deleted - bootstrap deleted", servicep->name);
-                       msg_destroy_port(servicep->port);
-                       delete_service(servicep);
-                       break;
-               case DECLARED:  // don't alter status of (now unavailable) server
-                       error("Declared service %s now unavailable", servicep->name);
+
+               if (!servicep->isActive || !servicep->server) {
                        delete_service(servicep);
-                       break;
-               case SELF:
-                       error("Self service %s now unavailable", servicep->name);
-                       break;
-               default:
-                       error("unknown service type %d\n", servicep->servicetype);
-                       break;
+                       continue;
                }
+
+               serverp = servicep->server;
+               delete_service(servicep);
+               serverp->active_services--;
+               if (!active_server(serverp))
+                       delete_server(serverp);
        }
 }
 
@@ -300,6 +303,21 @@ lookup_service_by_port(mach_port_t port)
         return NULL;
 }
 
+service_t *
+lookup_service_by_server(server_t *serverp)
+{
+       service_t *servicep;
+       
+        for (  servicep = FIRST(services)
+            ; !IS_END(servicep, services)
+            ; servicep = NEXT(servicep))
+       {
+               if (serverp == servicep->server)
+                       return servicep;
+       }
+        return NULL;
+}
+
 server_t *
 lookup_server_by_task_port(mach_port_t port)
 {
@@ -315,33 +333,6 @@ lookup_server_by_task_port(mach_port_t port)
        return NULL;
 }
 
-void
-delete_bootstrap(bootstrap_info_t *bootstrap)
-{
-       bootstrap_info_t *child_bootstrap;
-
-       ASSERT(bootstrap->prev->next == bootstrap);
-       ASSERT(bootstrap->next->prev == bootstrap);
-
-       destroy_services(bootstrap);
-       for (  child_bootstrap = FIRST(bootstraps)
-            ; !IS_END(child_bootstrap, bootstraps)
-            ; child_bootstrap = NEXT(child_bootstrap))
-       {
-               if (child_bootstrap->parent == bootstrap)
-                       delete_bootstrap(child_bootstrap);
-       }
-
-       debug("deleting bootstrap %d, requestor %d",
-               bootstrap->bootstrap_port,
-               bootstrap->requestor_port);
-       bootstrap->prev->next = bootstrap->next;
-       bootstrap->next->prev = bootstrap->prev;
-       mach_port_destroy(mach_task_self(), bootstrap->bootstrap_port);
-       mach_port_deallocate(mach_task_self(), bootstrap->requestor_port);
-       free(bootstrap);
-}
-
 server_t *
 lookup_server_by_port(mach_port_t port)
 {
@@ -357,19 +348,135 @@ lookup_server_by_port(mach_port_t port)
        return NULL;
 }
 
-server_t *
-find_init_server(void)
+void
+delete_server(server_t *serverp)
 {
-       server_t *serverp;
-       
-       for (  serverp = FIRST(servers)
-            ; !IS_END(serverp, servers)
-            ; serverp = NEXT(serverp))
+       service_t *servicep;
+       service_t *next;
+
+       info("Deleting server %s", serverp->cmd);
+       ASSERT(serverp->prev->next == serverp);
+       ASSERT(serverp->next->prev == serverp);
+       serverp->prev->next = serverp->next;
+       serverp->next->prev = serverp->prev;
+
+       for (  servicep = FIRST(services)
+            ; !IS_END(servicep, services)
+            ; servicep = next)
        {
-               if (serverp->servertype == ETCINIT)
-                       return serverp;
+               next = NEXT(servicep);
+               if (serverp == servicep->server)
+                       delete_service(servicep);
        }
-       return NULL;
+
+       deallocate_bootstrap(serverp->bootstrap);
+
+#ifndef DELAYED_BOOTSTRAP_DESTROY
+       if (serverp->port)
+               mach_port_mod_refs(mach_task_self(), serverp->port,
+                                  MACH_PORT_RIGHT_RECEIVE, -1);
+#endif 
+
+       free(serverp);
+}      
+
+void
+deactivate_bootstrap(bootstrap_info_t *bootstrap)
+{
+       bootstrap_info_t *deactivating_bootstraps;
+       bootstrap_info_t *query_bootstrap;
+       bootstrap_info_t *next_limit;
+       bootstrap_info_t *limit;
+
+       /*
+        * we need to recursively deactivate the whole subset tree below
+        * this point.  But we don't want to do real recursion because
+        * we don't have a limit on the depth.  So, build up a chain of
+        * active bootstraps anywhere underneath this one.
+        */
+       deactivating_bootstraps = bootstrap;
+       bootstrap->deactivate = NULL;
+       for (next_limit = deactivating_bootstraps, limit = NULL
+                        ; deactivating_bootstraps != limit
+                        ; limit = next_limit, next_limit = deactivating_bootstraps)
+       {
+               for (bootstrap = deactivating_bootstraps
+                                ; bootstrap != limit
+                                ; bootstrap = bootstrap->deactivate)
+               {
+                       for (  query_bootstrap = FIRST(bootstraps)
+                                  ; !IS_END(query_bootstrap, bootstraps)
+                                  ; query_bootstrap = NEXT(query_bootstrap))
+                       {
+                               if (query_bootstrap->parent == bootstrap &&
+                                       query_bootstrap->requestor_port != MACH_PORT_NULL) {
+                                       mach_port_deallocate(
+                                                                                mach_task_self(),
+                                                                                query_bootstrap->requestor_port);
+                                       query_bootstrap->requestor_port = MACH_PORT_NULL;
+                                       query_bootstrap->deactivate = deactivating_bootstraps;
+                                       deactivating_bootstraps = query_bootstrap;
+                               }
+                       }
+               }
+       }
+
+       /*
+        * The list is ordered with the furthest away progeny being
+        * at the front, and concluding with the one we started with.
+        * This allows us to safely deactivate and remove the reference
+        * each holds on their parent without fear of the chain getting
+        * corrupted (because each active parent holds a reference on
+        * itself and that doesn't get removed until we reach its spot
+        * in the list).
+        */
+       do {
+               bootstrap = deactivating_bootstraps;
+               deactivating_bootstraps = bootstrap->deactivate;
+
+               info("deactivating bootstrap %x", bootstrap->bootstrap_port);
+
+               delete_bootstrap_services(bootstrap);
+               
+               mach_port_deallocate(mach_task_self(), bootstrap->bootstrap_port);
+
+#ifdef DELAYED_BOOTSTRAP_DESTROY
+               {
+                       mach_port_t previous;
+                       mach_port_request_notification(
+                                       mach_task_self(),
+                                       bootstrap->bootstrap_port,
+                                       MACH_NOTIFY_NO_SENDERS,
+                                       1,
+                                       bootstrap->bootstrap_port,
+                                       MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                       &previous);
+               }
+#else
+               mach_port_mod_refs(
+                                       mach_task_self(),
+                                       bootstrap->bootstrap_port,
+                                       MACH_PORT_RIGHT_RECEIVE,
+                                       -1);
+               bootstrap->bootstrap_port = MACH_PORT_NULL;
+               deallocate_bootstrap(bootstrap);
+#endif
+
+       } while (deactivating_bootstraps != NULL);
+}
+
+void
+deallocate_bootstrap(bootstrap_info_t *bootstrap)
+{
+       ASSERT(bootstrap->prev->next == bootstrap);
+       ASSERT(bootstrap->next->prev == bootstrap);
+       if (--bootstrap->ref_count > 0)
+               return;
+
+       bootstrap->prev->next = bootstrap->next;
+       bootstrap->next->prev = bootstrap->prev;
+       deallocate_bootstrap(bootstrap->parent);
+       free(bootstrap);
 }
 
 void *
index 99e5478981d4e934d5e9e4b94cfa1b6086049010..4ad1515350dd219c035663b0fe73a0bd1627c361 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
@@ -29,6 +29,7 @@
  * lists.h -- interface to list routines
  */
 
+#import <sys/types.h>
 #import <mach/mach.h>
 #import <mach/boolean.h>
 #import <servers/bootstrap_defs.h>
@@ -46,8 +47,10 @@ struct bootstrap {
        bootstrap_info_t                *next;          /* list of all bootstraps */
        bootstrap_info_t                *prev;
        bootstrap_info_t                *parent;
+       bootstrap_info_t                *deactivate;    /* list being deactivated */
        mach_port_name_t                bootstrap_port;
        mach_port_name_t                requestor_port;
+       unsigned int                    ref_count;
 };
 
 /* Service types */
@@ -74,8 +77,8 @@ struct service {
 typedef enum {
        SERVER,         /* Launchable server */
        RESTARTABLE,    /* Restartable server */
-       ETCINIT,        /* Special processing for /etc/init */
-       MACHINIT        /* mach_init doesn't get launched. */
+       DEMAND,         /* Restartable server - on demand */
+       MACHINIT,       /* mach_init doesn't get launched. */
 } servertype_t;
 
 #define        NULL_SERVER     NULL
@@ -86,25 +89,33 @@ struct server {
        server_t        *prev;
        servertype_t    servertype;
        cmd_t           cmd;            /* server command to exec */
-       int             priority;       /* priority to give server */
+       int                     uid;            /* uid to exec server with */
        mach_port_t     port;           /* server's priv bootstrap port */
-       mach_port_name_t        task_port;      /* server's task port */
+       mach_port_t     task_port;      /* server's task port */
+       pid_t           pid;            /* server's pid */
+       int             activity;               /* count of checkins/registers this instance */
+       int             active_services;/* count of active services */
+       bootstrap_info_t *bootstrap; /* bootstrap context */
 };
 
 #define        NO_PID  (-1)
 
 extern void init_lists(void);
+
 extern server_t *new_server(
-       servertype_t    servertype,
-       const char      *cmd,
-       int             priority);
-extern service_t *new_service(
+       bootstrap_info_t        *bootstrap,
+       const char                      *cmd,
+       int                                     uid,
+       servertype_t            servertype);
+
+extern service_t               *new_service(
        bootstrap_info_t        *bootstrap,
-       const char      *name,
-       mach_port_t             service_port,
-       boolean_t       isActive,
-       servicetype_t   servicetype,
-       server_t        *serverp);
+       const char                      *name,
+       mach_port_t                     service_port,
+       boolean_t                       isActive,
+       servicetype_t           servicetype,
+       server_t                        *serverp);
+
 extern bootstrap_info_t *new_bootstrap(
        bootstrap_info_t        *parent,
        mach_port_name_t        bootstrap_port,
@@ -112,13 +123,22 @@ extern bootstrap_info_t *new_bootstrap(
 
 extern server_t *lookup_server_by_port(mach_port_t port);
 extern server_t *lookup_server_by_task_port(mach_port_t port);
-extern bootstrap_info_t *lookup_bootstrap_by_port(mach_port_t port);
-extern bootstrap_info_t *lookup_bootstrap_req_by_port(mach_port_t port);
+extern void setup_server(server_t *serverp);
+extern void delete_server(server_t *serverp);
+extern boolean_t active_server(server_t *serverp);
+extern boolean_t useless_server(server_t *serverp);
+
+extern void delete_service(service_t *servicep);
 extern service_t *lookup_service_by_name(bootstrap_info_t *bootstrap, name_t name);
 extern service_t *lookup_service_by_port(mach_port_t port);
-extern server_t *find_init_server(void);
-extern void delete_service(service_t *servicep);
-extern void delete_bootstrap(bootstrap_info_t *bootstrap);
+extern service_t *lookup_service_by_server(server_t *serverp);
+
+extern bootstrap_info_t *lookup_bootstrap_by_port(mach_port_t port);
+extern bootstrap_info_t *lookup_bootstrap_by_req_port(mach_port_t port);
+extern void deactivate_bootstrap(bootstrap_info_t *bootstrap);
+extern void deallocate_bootstrap(bootstrap_info_t *bootstrap);
+extern boolean_t active_bootstrap(bootstrap_info_t *bootstrap);
+
 extern void *ckmalloc(unsigned nbytes);
 
 extern bootstrap_info_t bootstraps;            /* head of list of bootstrap ports */
diff --git a/mach_init.tproj/mach_init.8 b/mach_init.tproj/mach_init.8
new file mode 100644 (file)
index 0000000..84694cd
--- /dev/null
@@ -0,0 +1,100 @@
+.\" Copyright (c) 2002, Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd March 20, 2002
+.Dt MACH_INIT 8
+.Os "Mac OS X"
+.Sh NAME
+.Nm mach_init
+.Nd Mach service naming (bootstrap) daemon
+.Sh SYNOPSIS
+.Nm mach_init
+.Op Fl D
+.Op Fl d
+.Op Fl F
+.Op Fl r Ar name-in-existing-server
+.Sh DESCRIPTION
+.Nm mach_init
+is a daemon that maintains various mappings between service names and
+the Mach ports that provide access to those services.  Clients of mach_init
+can register and lookup services, create new mapping subsets, and
+associate services with declared servers.  The mach_init daemon will
+also be responsible for launching (and/or re-launching) those service
+providing servers when attempts to use one or more of the associated services
+is detected.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl D
+When the
+.Fl D
+option is specified,
+.Nm mach_init
+starts in normal (non-debug) mode.  This is the default.
+.It Fl d
+When the
+.Fl d
+option is specified,
+.Nm mach_init
+starts in debug mode.
+.It Fl F
+When the
+.Fl F
+option is specified,
+.Nm mach_init
+forks during initialization so that it doesn't have to be put in
+the background manually by the caller.
+.It Fl r
+Using the
+.Fl r
+option tells
+.Nm mach_init
+to register itself in a previously running copy of
+.Nm mach_init
+under the service name
+.Ar name-in-existing-server.
+This is most useful when debugging new instances of
+.Nm mach_init
+itself, but can also be used for robustness or to allow the subsequent
+.Nm mach_init
+processes to run as a non-root user.  As mach_init is often used to
+launch servers, this could be more secure.  However, 
+.Nm mach_init
+will not allow a server declaration to specify a user id different
+than that of the requesting client (unless the client is running as root).
+So it shouldn't be required for a secure configuration.
+.El
+.Pp
+Access to
+.Nm mach_init 
+is provided through the bootstrap series of RPC APIs
+over service ports published by mach_init itself. Each Mach task has
+an assigned bootstrap port retrieved via task_get_bootstrap_port().
+These bootstrap port registrations are inherited across fork().
+.Pp
+The service registrations are grouped into subsets, providing a level
+of security. Only processes with access to the subset's bootstrap port
+will be able to register/lookup Mach ports within that subset.  Lookups
+from within a subset will search the subset first, then move on to its
+parent, and then its grand-parent, etc... until a string name match is
+found or the top of the bootstrap tree is reached.  Subsets are sometimes
+associated with login sessions to protect session-specific ports from being
+exposed outside the session.
+.Pp
+The first instance of
+.Nm mach_init
+is responsible for launching the traditional BSD process control initialization
+daemon (/sbin/init).
+.Sh SAMPLE USAGE
+.Pp
+mach_init -d -r com.company.bootstrap
+.Pp
+.Nm mach_init
+will start in debug mode, and register itself in an already running
+instance of
+.Nm mach_init
+under the service name com.company.bootstrap.
+.Sh NOTE
+.Pp
+Sending a SIGHUP to a running mach_init will toggle debug mode.
+.Sh SEE ALSO
+.Xr init 8
diff --git a/mach_init.tproj/parser.c b/mach_init.tproj/parser.c
deleted file mode 100644 (file)
index e20f194..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * bootstrap -- fundamental service initiator and port server
- * Mike DeMoney, NeXT, Inc.
- * Copyright, 1990.  All rights reserved.
- *
- * parser.c -- configuration file parser
- */
-#import        <mach/boolean.h>
-#import <mach/port.h>
-
-#import        <string.h>
-#import <libc.h>
-#import        <ctype.h>
-#import <stdio.h>
-
-#import "lists.h"
-#import "bootstrap_internal.h"
-#import "error_log.h"
-#import "parser.h"
-
-
-#ifndef ASSERT
-#define ASSERT(p)
-#endif
-
-#define        MAX_TOKEN_LEN   128
-
-#define        NELEM(x)                        (sizeof(x)/sizeof((x)[0]))
-#define        LAST_ELEMENT(x)         ((x)[NELEM(x)-1])
-#define        STREQ(a, b)                     (strcmp(a, b) == 0)
-#define        NEW(type, num)          ((type *)ckmalloc(sizeof(type) * (num)))
-
-typedef enum {
-       ASSIGN_TKN, EOF_TKN, FORWARD_TKN, INIT_TKN, NUM_TKN,
-       RESTARTABLE_TKN, SELF_TKN, SEMICOLON_TKN, SERVER_TKN, SERVICES_TKN,
-       STRING_TKN, ERROR_TKN, PRI_TKN
-} token_t;
-
-typedef struct {
-       char *string;
-       token_t token;
-} keyword_t;
-
-static keyword_t keywords[] = {
-       { "forward",                    FORWARD_TKN },
-       { "init",                       INIT_TKN },
-       { "priority",                   PRI_TKN },
-       { "restartable",                RESTARTABLE_TKN },
-       { "self",                       SELF_TKN },
-       { "server",                     SERVER_TKN },
-       { "services",                   SERVICES_TKN },
-       { NULL,                         ERROR_TKN }
-};
-
-static FILE *conf;
-static int (*charget)(void);
-static const char *default_conf_ptr;
-
-static char token_string[MAX_TOKEN_LEN];
-static token_t current_token;
-static int token_num;
-static int token_priority;
-static int peekc;
-
-static int get_from_conf(void);
-static int get_from_default(void);
-static boolean_t parse_conf_file(void);
-static boolean_t parse_self(void);
-static boolean_t parse_server(void);
-static boolean_t parse_service(server_t *serverp);
-static boolean_t parse_pri(void);
-static void advance_token(void);
-static token_t keyword_lookup(void);
-
-/*
- * init_config -- read configuration file and build-up initial server and
- * service lists
- *
- * If can't find a suitable bootstrap.conf, use configuration given in
- * bootstrap.c to get system booted so someone can correct bootstrap.conf
- */
-void
-init_config(void)
-{
-       boolean_t parse_ok;
-
-       conf = fopen(conf_file, "r");
-       if (conf != NULL)
-               charget = get_from_conf;
-       else {
-               error("Can't open %s -- using default configuration", conf_file);
-               charget = get_from_default;
-       }
-       
-       parse_ok = parse_conf_file();
-       if ( ! parse_ok && charget == get_from_conf) {
-               error("Can't parse %s -- using default configuration", conf_file);
-               charget = get_from_default;
-               init_lists();
-               peekc = 0;
-               parse_ok = parse_conf_file();
-       }
-       if ( ! parse_ok )
-               fatal("Can't parse default configuration file");
-}
-
-/*
- * Function pointer "charget" points at get_from_conf or get_from_default
- */
-static int
-get_from_conf(void)
-{
-       return getc(conf);
-}
-
-static int
-get_from_default(void)
-{
-       int c;
-       
-       if (default_conf_ptr == NULL)
-               default_conf_ptr = default_conf;
-               
-       if (c = *default_conf_ptr)
-               default_conf_ptr++;
-       if (c == '\0')
-               c = EOF;
-       return c;
-}
-
-/*
- * What follows is a simple recursive descent parser
- * ("we don't need no stinkin' yacc")
- */
-static boolean_t
-parse_conf_file(void)
-{
-       boolean_t parse_ok, good_parse;
-       
-       /*
-        * Configuration file syntax (and parsing routines).
-        *
-        * (parse_conf_file)
-        * CONF_FILE := STMT [ ; STMT ]* [ ; ]
-        * STMT := SERVER | SERVICE | SELF | forward | initpri
-        *
-        * (parse_server)
-        * SERVER := [ restartable ]  ( server | init ) SERVER_PATH_ARGS [ SERVICE ]
-        *
-        * (parse_service)
-        * SERVICE := services [ SERVICE_DECL ]+
-        * SERVICE_DECL := SERVICE_NAME
-        *
-        * (parse_self)
-        * SELF := self [ priority = NUM ] SERVICE_DECL
-        *
-        * Or more simply, just a list of:
-        *
-        * [[restartable] (server|init) SERVER_PATH_ARGS] [ priority = NUM ]
-        *   [services SERVICE_NAME [ SERVICE_NAME [ = NUM ]]*] ;
-        *
-        * self [ SERVICE_NAME ]+
-        *
-        * [ forward ]
-        *
-        */
-       advance_token();
-       if (current_token == EOF_TKN) {
-               error("Empty configuration file: %s", conf_file);
-               return FALSE;
-       }
-       
-       good_parse = TRUE;
-       while (current_token != EOF_TKN) {
-               parse_ok = TRUE;
-               switch (current_token) {
-               case RESTARTABLE_TKN:
-               case SERVER_TKN:
-               case INIT_TKN:
-                       parse_ok = parse_server();
-                       break;
-               case SERVICES_TKN:
-                       parse_ok = parse_service(NULL);
-                       break;
-               case SELF_TKN:
-                       parse_ok = parse_self();
-                       break;
-               case FORWARD_TKN:
-                       forward_ok = TRUE;
-                       advance_token();
-                       break;
-               case SEMICOLON_TKN:
-                       advance_token();
-                       break;
-               case EOF_TKN:
-                       break;
-               default:
-                       parse_error(token_string, "start of new declaration");
-                       parse_ok = FALSE;
-                       break;
-               }
-               switch (current_token) {
-               case SEMICOLON_TKN:
-                       advance_token();
-                       break;
-               case EOF_TKN:
-                       break;
-               default:
-                       if (parse_ok)
-                               parse_error(token_string, "expected ';'");
-                       /* Try to re-sync with input */
-                       while (current_token != SEMICOLON_TKN && current_token != EOF_TKN)
-                               advance_token();
-                       parse_ok = FALSE;
-                       break;
-               }
-               if (! parse_ok)
-                       good_parse = FALSE;
-       }
-       return good_parse;
-}
-
-static boolean_t
-parse_self(void)
-{
-       name_t name;
-       
-       ASSERT(current_token == SELF_TKN);
-       advance_token();                /* Skip SELF_TKN */
-       if (current_token == PRI_TKN) {
-               boolean_t ok;
-               ok = parse_pri();
-               if (!ok)
-                       return FALSE;
-               init_priority = token_priority;
-       }
-       while (current_token == STRING_TKN) {
-               if (strlen(token_string) >= sizeof(name_t)) {
-                       parse_error(token_string, "Service name too long");
-                       return FALSE;
-               }
-               if (lookup_service_by_name(&bootstraps, token_string) != NULL)
-               {
-                       parse_error(token_string, "Service name previously declared");
-                       return FALSE;
-               }
-               strcpy(name, token_string);
-               advance_token();
-               (void) new_service(&bootstraps, name, MACH_PORT_NULL, ACTIVE, SELF,
-                                  NULL_SERVER);
-       }
-       return TRUE;
-}
-
-static boolean_t
-parse_server(void)
-{
-       server_t *serverp;
-       servertype_t servertype = SERVER;
-       
-       if (current_token == RESTARTABLE_TKN) {
-               advance_token();
-               servertype = RESTARTABLE;
-       }
-       switch (current_token) {
-       case SERVER_TKN:
-               advance_token();
-               break;
-       case INIT_TKN:
-               if (find_init_server() != NULL) {
-                       parse_error(token_string,
-                               "Can't specify multiple init servers");
-                       return FALSE;
-               }
-               if (servertype == RESTARTABLE) {
-                       parse_error(token_string,
-                               "Init server can not be restartable");
-                       return FALSE;
-               }
-               servertype = ETCINIT;
-               advance_token();
-               break;
-       default:
-               parse_error(token_string, "expected \"server\" or \"init\"");
-               return FALSE;
-       }
-       if (current_token == PRI_TKN) {
-               boolean_t ok;
-               ok = parse_pri();
-               if (!ok)
-                       return FALSE;
-       } else
-               token_priority = BASEPRI_USER;
-       if (current_token != STRING_TKN) {
-               parse_error(token_string,
-                           "expected string giving server to exec");
-               return FALSE;
-       }
-       serverp = new_server(servertype, token_string, token_priority);
-       advance_token();
-       if (current_token == SERVICES_TKN)
-               return parse_service(serverp);
-       return TRUE;
-}
-
-static boolean_t
-parse_service(server_t *serverp)
-{
-       name_t name;
-       
-       ASSERT(current_token == SERVICES_TKN);
-       advance_token();                /* Skip SERVICES_TKN */
-       while (current_token == STRING_TKN) {
-               if (strlen(token_string) >= sizeof(name_t)) {
-                       parse_error(token_string, "Service name too long");
-                       return FALSE;
-               }
-               if (lookup_service_by_name(&bootstraps, token_string) != NULL)
-               {
-                       parse_error(token_string, "Service name previously declared");
-                       return FALSE;
-               }
-               strcpy(name, token_string);
-               advance_token();
-               (void) new_service(&bootstraps, name, MACH_PORT_NULL, !ACTIVE,
-                                  DECLARED, serverp);
-       }
-       return TRUE;
-}
-
-/*
- * Parse priority=NUM
- */
-static boolean_t
-parse_pri(void)
-{
-       ASSERT(current_token == PRI_TKN);
-       advance_token();                /* Skip PRI_TKN */
-       if (current_token != ASSIGN_TKN) {
-               parse_error(token_string, "expected '='");
-               return FALSE;
-       }
-       advance_token();                /* Skip = */
-       if (current_token != NUM_TKN) {
-               parse_error(token_string, "expected NUM");
-               return FALSE;
-       }
-       advance_token();                /* Skip NUM */
-       token_priority = token_num;
-       return TRUE;
-}
-/*
- * advance_token -- advances input to next token
- *     Anything from a '#' on is comment and ignored
- *     
- * On return:
- *             current_token contains token_t of next token
- *             token_string contains string value of next token
- *             if token was number, token_num contains numeric value of token
- */
-static void
-advance_token(void)
-{
-       char *cp;
-
-again: 
-       while (peekc == '\0' || isspace(peekc))
-               peekc = (*charget)();
-       
-       /* Skip comments */
-       if (peekc == '#') {
-               while (peekc != EOF && peekc != '\n')
-                       peekc = (*charget)();
-               goto again;
-       }
-       
-       cp = token_string;
-       *cp = '\0';
-       
-       if (peekc == EOF) {
-               current_token = EOF_TKN;
-               return;
-       }
-
-       if (isalpha(peekc) || peekc == '\\') {
-               /*
-                * this only allows names to be alphanumerics, '_', and
-                * backslash escaped characters.
-                * If you want something fancier, use "..."
-                */
-               current_token = STRING_TKN;     /* guarantee it's not ERROR_TKN */
-               for (; isalnum(peekc) || peekc == '_' || peekc == '\\';
-                peekc = (*charget)()) {
-                       if (cp >= &LAST_ELEMENT(token_string)) {
-                               cp = token_string;
-                               parse_error(token_string, "token too long");
-                               current_token = ERROR_TKN;
-                       }
-                       if (peekc == '\\')
-                               peekc = (*charget)();
-                       *cp++ = peekc;
-               }
-               *cp = '\0';
-               if (current_token != ERROR_TKN)
-                       current_token = keyword_lookup();
-               return;
-       }
-       
-       /* Handle "-quoted strings */
-       if (peekc == '"') {
-               peekc = (*charget)();
-               for (; peekc != EOF && peekc != '"'; peekc = (*charget)()) {
-                       if (cp >= &LAST_ELEMENT(token_string)) {
-                               cp = token_string;
-                               parse_error(token_string, "token too long");
-                               current_token = ERROR_TKN;
-                       }
-                       if (peekc == '\\')
-                               peekc = (*charget)();
-                       if (peekc == '\n') {
-                               cp = token_string;
-                               parse_error(token_string, "Missing \"");
-                               current_token = ERROR_TKN;
-                       }
-                       *cp++ = peekc;
-               }
-               if (peekc == EOF) {
-                       cp = token_string;
-                       parse_error(token_string, "Missing \"");
-                       current_token = ERROR_TKN;
-               } else
-                       peekc = (*charget)();   /* skip closing " */
-               *cp = '\0';
-               if (current_token != ERROR_TKN)
-                       current_token = STRING_TKN;
-               return;
-       }
-
-       if (isdigit(peekc)) {
-               for (token_num = 0; isdigit(peekc); peekc = (*charget)())
-                       token_num = token_num * 10 + peekc - '0';
-               current_token = NUM_TKN;
-               return;
-       }
-       
-       if (peekc == ';') {
-               peekc = (*charget)();
-               current_token = SEMICOLON_TKN;
-               return;
-       }
-       
-       if (peekc == '=') {
-               peekc = (*charget)();
-               current_token = ASSIGN_TKN;
-               return;
-       }
-       
-       current_token = ERROR_TKN;
-       return;
-}      
-
-static token_t
-keyword_lookup(void)
-{
-       keyword_t *kwp;
-       
-       for (kwp = keywords; kwp->string; kwp++)
-               if (STREQ(kwp->string, token_string))
-                       return kwp->token;
-       return STRING_TKN;
-}
-
diff --git a/mach_init.tproj/parser.h b/mach_init.tproj/parser.h
deleted file mode 100644 (file)
index 079ec7b..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * bootstrap -- fundamental service initiator and port server
- * Mike DeMoney, NeXT, Inc.
- * Copyright, 1990.  All rights reserved.
- *
- * parser.h -- interface to configuration file parser
- */
-#import "lists.h"
-
-extern void init_config(void);
-
-
index 6c08bbea95f9edebe3de1f320c9e8a3dad6afe9f..193e18027dc225dd94579162f1ff92e0367cd256 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #define        NULL    ((void *)0)
 #endif NULL
  
+#define bsstatus(servicep) \
+       (((servicep)->isActive) ? BOOTSTRAP_STATUS_ACTIVE : \
+        (((servicep)->server && (servicep)->server->servertype == DEMAND) ? \
+               BOOTSTRAP_STATUS_ON_DEMAND : BOOTSTRAP_STATUS_INACTIVE))
+
 /* extern port_all_t backup_port; */
 
+/*
+ * kern_return_t
+ * bootstrap_create_server(mach_port_t bootstrap_port,
+ *      cmd_t server_cmd,
+ *      integer_t server_uid,
+ *      boolean_t on_demand,
+ *      mach_port_t *server_portp)
+ *
+ * Returns send rights to server_port of service.  At this point, the
+ * server appears active, so nothing will try to launch it.  The server_port
+ * can be used to delare services associated with this server by calling
+ * bootstrap_create_service() and passing server_port as the bootstrap port.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NOT_PRIVILEGED, if bootstrap port invalid.
+ */
+kern_return_t
+x_bootstrap_create_server(
+       mach_port_t bootstrap_port,
+       cmd_t server_cmd,
+       int server_uid,
+       boolean_t on_demand,
+       security_token_t sectoken,
+       mach_port_t *server_portp)
+{
+       server_t *serverp;
+       bootstrap_info_t *bootstrap;
+
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       debug("Server create attempt: \"%s\" bootstrap %x",
+             server_cmd, bootstrap_port);
+
+       /* No forwarding allowed for this call - security risk (we run as root) */
+       if (!bootstrap || !active_bootstrap(bootstrap)) {
+               debug("Server create: \"%s\": invalid bootstrap %x",
+                       server_cmd, bootstrap_port);
+               return BOOTSTRAP_NOT_PRIVILEGED;
+       }
+
+       /* only same uid (or root client) */
+       if (sectoken.val[0] && sectoken.val[0] != server_uid) {
+               log("Server create: \"%s\": invalid security token (%d != %d)",
+                       server_cmd, sectoken.val[0], server_uid);
+               return BOOTSTRAP_NOT_PRIVILEGED;
+       }
+       serverp = new_server(
+                                       bootstrap,
+                                       server_cmd,
+                                       server_uid,
+                                       (on_demand) ? DEMAND : RESTARTABLE);
+       setup_server(serverp);
+
+       info("New server %x in bootstrap %x: \"%s\"",
+                                       serverp->port, bootstrap_port, server_cmd);
+       *server_portp = serverp->port;
+       return BOOTSTRAP_SUCCESS;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_unprivileged(mach_port_t bootstrap_port,
+ *                       mach_port_t *unpriv_port)
+ *
+ * Given a bootstrap port, return its unprivileged equivalent.  If
+ * the port is already unprivileged, another reference to the same
+ * port is returned.
+ *
+ * This is most often used by servers, which are launched with their
+ * bootstrap port set to the privileged port for the server, to get
+ * an unprivileged version of the same port for use by its unprivileged
+ * children (or any offspring that it does not want to count as part
+ * of the "server" for mach_init registration and re-launch purposes).
+ */
+kern_return_t
+x_bootstrap_unprivileged(
+       mach_port_t bootstrap_port,
+       mach_port_t *unpriv_portp)
+{
+       bootstrap_info_t *bootstrap;
+
+       debug("Get unprivileged attempt for bootstrap %x", bootstrap_port);
+
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       if (!bootstrap || !active_bootstrap(bootstrap)) {
+               debug("Get unprivileged: invalid bootstrap %x", bootstrap_port);
+               return BOOTSTRAP_NOT_PRIVILEGED;
+       }
+
+       *unpriv_portp = bootstrap->bootstrap_port;
+
+       debug ("Get unpriv bootstrap %x returned for bootstrap %x",
+              bootstrap->bootstrap_port, bootstrap_port);
+       return BOOTSTRAP_SUCCESS;
+}
+
+  
 /*
  * kern_return_t
  * bootstrap_check_in(mach_port_t bootstrap_port,
@@ -69,23 +170,26 @@ x_bootstrap_check_in(
        mach_port_t     *service_portp)
 {
        kern_return_t result;
+       mach_port_t previous;
        service_t *servicep;
        server_t *serverp;
        bootstrap_info_t *bootstrap;
 
-       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
        serverp = lookup_server_by_port(bootstrap_port);
-       if (serverp == NULL) {
-               debug("bootstrap_check_in service %s has no server",
-                       service_name);
-               return BOOTSTRAP_NOT_PRIVILEGED;
-       }
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       debug("Service checkin attempt for service %s bootstrap %x",
+             service_name, bootstrap_port);
+
        servicep = lookup_service_by_name(bootstrap, service_name);
        if (servicep == NULL || servicep->port == MACH_PORT_NULL) {
                debug("bootstrap_check_in service %s unknown%s", service_name,
                        forward_ok ? " forwarding" : "");
-               result = BOOTSTRAP_UNKNOWN_SERVICE;
-               goto forward;
+               return  forward_ok ?
+                       bootstrap_check_in(
+                                       inherited_bootstrap_port,
+                                       service_name,
+                                       service_portp) :
+                       BOOTSTRAP_UNKNOWN_SERVICE;
        }
        if (servicep->server != NULL && servicep->server != serverp) {
                debug("bootstrap_check_in service %s not privileged",
@@ -98,19 +202,54 @@ x_bootstrap_check_in(
                        service_name);
                return BOOTSTRAP_SERVICE_ACTIVE;
        }
-       log("Checkin service %s", service_name);
+       debug("Checkin service %s for bootstrap %x", service_name,
+             bootstrap->bootstrap_port);
        ASSERT(servicep->isActive == FALSE);
        servicep->isActive = TRUE;
+
+       if (servicep->server != NULL_SERVER) {
+               /* registered server - service needs backup */
+               serverp->activity++;
+               serverp->active_services++;
+               result = mach_port_request_notification(
+                                       mach_task_self(),
+                                       servicep->port,
+                                       MACH_NOTIFY_PORT_DESTROYED,
+                                       0,
+                                       backup_port,
+                                       MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                       &previous);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_request_notification");
+       } else {
+               /* one time use/created service */
+               servicep->servicetype = REGISTERED;
+               result = mach_port_request_notification(
+                                       mach_task_self(),
+                                       servicep->port,
+                                       MACH_NOTIFY_DEAD_NAME,
+                                       0,
+                                       notify_port,
+                                       MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                       &previous);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_request_notification");
+               else if (previous != MACH_PORT_NULL) {
+                       debug("deallocating old notification port (%x) for checked in service %x",
+                               previous, servicep->port);
+                       result = mach_port_deallocate(
+                                               mach_task_self(),
+                                               previous);
+                       if (result != KERN_SUCCESS)
+                               kern_fatal(result, "mach_port_deallocate");
+               }
+       }
+
+       info("Check-in service %x in bootstrap %x: %s",
+             servicep->port, servicep->bootstrap->bootstrap_port, servicep->name);
+
        *service_portp = servicep->port;
-       info("Check-in port %d for service %s\n",
-             servicep->port, servicep->name);
        return BOOTSTRAP_SUCCESS;
-    forward:
-       return forward_ok
-        ? bootstrap_check_in(inherited_bootstrap_port,
-                            service_name,
-                            service_portp)
-        : result;
 }
 
 /*
@@ -139,16 +278,22 @@ x_bootstrap_register(
        name_t  service_name,
        mach_port_t     service_port)
 {
+       kern_return_t result;
        service_t *servicep;
        server_t *serverp;
        bootstrap_info_t *bootstrap;
        mach_port_t old_port;
 
-       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
-       ASSERT(canSend(service_port));
-       debug("Register attempt for service %s port %d",
+       debug("Register attempt for service %s port %x",
              service_name, service_port);
 
+       /*
+        * Validate the bootstrap.
+        */
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       if (!bootstrap || !active_bootstrap(bootstrap))
+               return BOOTSTRAP_NOT_PRIVILEGED;
+         
        /*
         * If this bootstrap port is for a server, or it's an unprivileged
         * bootstrap can't register the port.
@@ -158,11 +303,6 @@ x_bootstrap_register(
        if (servicep && servicep->server && servicep->server != serverp)
                return BOOTSTRAP_NOT_PRIVILEGED;
 
-       if (serverp)
-               bootstrap_port = bootstrap->bootstrap_port;
-       else if (bootstrap_port != bootstrap->bootstrap_port)
-               return BOOTSTRAP_NOT_PRIVILEGED;
-
        if (servicep == NULL || servicep->bootstrap != bootstrap) {
                servicep = new_service(bootstrap,
                                       service_name,
@@ -172,21 +312,68 @@ x_bootstrap_register(
                                       NULL_SERVER);
                debug("Registered new service %s", service_name);
        } else {
-            if (servicep->isActive) {
-                       debug("Register: service %s already active, port %d",
+               if (servicep->isActive) {
+                       debug("Register: service %s already active, port %x",
                              servicep->name, servicep->port);
                        ASSERT(!canReceive(servicep->port));
                        return BOOTSTRAP_SERVICE_ACTIVE;
                }
-            old_port = servicep->port;
+               old_port = servicep->port;
+               if (servicep->servicetype == DECLARED) {
+                       servicep->servicetype = REGISTERED;
+
+                       if (servicep->server) {
+                               ASSERT(servicep->server == serverp);
+                               ASSERT(active_server(serverp));
+                               servicep->server = NULL_SERVER;
+                               serverp->activity++;
+                       }
+
+                       result = mach_port_mod_refs(
+                                       mach_task_self(),
+                                       old_port,
+                                       MACH_PORT_RIGHT_RECEIVE, 
+                                       -1);
+                       if (result != KERN_SUCCESS)
+                               kern_fatal(result, "mach_port_mod_refs");
+               }
+               result = mach_port_deallocate(
+                               mach_task_self(),
+                               old_port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_mod_refs");
+               
                servicep->port = service_port;
-               msg_destroy_port(old_port);
                servicep->isActive = TRUE;
-               log("Re-registered inactive service %s", service_name);
+               debug("Re-registered inactive service %x bootstrap %x: %s",
+                       servicep->port, servicep->bootstrap->bootstrap_port, service_name);
        }
-       debug("Registering port %d for service %s\n",
-             servicep->port,
-             servicep->name);
+
+       /* detect the new service port going dead */
+       result = mach_port_request_notification(
+                       mach_task_self(),
+                       service_port,
+                       MACH_NOTIFY_DEAD_NAME,
+                       0,
+                       notify_port,
+                       MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                       &old_port);
+       if (result != KERN_SUCCESS) {
+               debug("Can't request notification on service %x bootstrap %x: %s",
+                      service_port, servicep->bootstrap->bootstrap_port, "must be dead");
+               delete_service(servicep);
+               return BOOTSTRAP_SUCCESS;
+       } else if (old_port != MACH_PORT_NULL) {
+               debug("deallocating old notification port (%x) for service %x",
+                     old_port, service_port);
+               result = mach_port_deallocate(
+                               mach_task_self(),
+                               old_port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_deallocate");
+       }
+       info("Registered service %x bootstrap %x: %s",
+            servicep->port, servicep->bootstrap->bootstrap_port, servicep->name);
        return BOOTSTRAP_SUCCESS;
 }
 
@@ -215,35 +402,21 @@ x_bootstrap_look_up(
        servicep = lookup_service_by_name(bootstrap, service_name);
        if (servicep == NULL || servicep->port == MACH_PORT_NULL) {
                if (forward_ok) {
-#if    DEBUG
                        debug("bootstrap_look_up service %s forwarding",
                                service_name);
-#endif DEBUG
                        return bootstrap_look_up(inherited_bootstrap_port,
                                                service_name,
                                                service_portp);
                } else {
-#if    DEBUG
                        debug("bootstrap_look_up service %s unknown",
                                service_name);
-#endif DEBUG
                        return BOOTSTRAP_UNKNOWN_SERVICE;
                }
        }
-       if (!canSend(servicep->port)) {
-               error("Mysterious loss of send rights on port %d, "
-                     "deleting service %s",
-                     servicep->port,
-                     servicep->name);
-               delete_service(servicep);
-               return BOOTSTRAP_UNKNOWN_SERVICE;
-       }
        *service_portp = servicep->port;
-#if    DEBUG
-       debug("Lookup returns port %d for service %s\n",
+       debug("Lookup returns port %x for service %s",
              servicep->port,
              servicep->name);
-#endif DEBUG
        return BOOTSTRAP_SUCCESS;
 }
 
@@ -296,29 +469,74 @@ x_bootstrap_look_up_array(
                        service_ports[i] = MACH_PORT_NULL;
                }
        }
-#if    DEBUG
        debug("bootstrap_look_up_array returns %d ports", service_names_cnt);
-#endif DEBUG
        *service_portsp = service_ports;
        return BOOTSTRAP_SUCCESS;
 }
 
+/*
+ * kern_return_t
+ * bootstrap_parent(mach_port_t bootstrap_port,
+ *                 mach_port_t *parent_port);
+ *
+ * Given a bootstrap subset port, return the parent bootstrap port.
+ * If the specified bootstrap port is already the root subset,
+ * MACH_PORT_NULL will be returned.
+ *
+ * Errors:
+ *     Returns BOOTSTRAP_NOT_PRIVILEGED if the caller is not running
+ *     with an effective user id of root (as determined by the security
+ *     token in the message trailer).
+ */
+kern_return_t
+x_bootstrap_parent(
+       mach_port_t bootstrap_port,
+       security_token_t sectoken,
+       mach_port_t *parent_port)
+{
+#if 0
+       bootstrap_info_t *bootstrap;
+
+       debug("Parent attempt for bootstrap %x", bootstrap_port);
+
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       if (!bootstrap || !active_bootstrap(bootstrap)) { 
+               debug("Parent attempt for bootstrap %x: invalid bootstrap",
+                     bootstrap_port);
+               return BOOTSTRAP_NOT_PRIVILEGED;
+       }
+       if (sectoken.val[0]) {
+               log("Bootstrap parent for bootstrap %x: invalid security token (%d)",
+                   bootstrap_port, sectoken.val[0]);
+               return BOOTSTRAP_NOT_PRIVILEGED;
+       }
+       debug("Returning bootstrap parent %x for bootstrap %x",
+             bootstrap->parent->bootstrap_port, bootstrap_port);
+       *parent_port = bootstrap->parent->bootstrap_port;
+       return BOOTSTRAP_SUCCESS;
+#else
+       debug("bootstrap parent for bootstrap %x: not implemented", 
+             bootstrap_port);
+       return BOOTSTRAP_NOT_PRIVILEGED;
+#endif
+}
+
 /*
  * kern_return_t
  * bootstrap_status(mach_port_t bootstrap_port,
  *     name_t service_name,
- *     boolean_t *service_active);
+ *     bootstrap_status_t *service_active);
  *
- * Returns: service_active is true if service is available.
+ * Returns: service_active indicates if service is available.
  *                     
  * Errors:     Returns appropriate kernel errors on rpc failure.
  *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
  */
 kern_return_t
 x_bootstrap_status(
-       mach_port_t     bootstrap_port,
-       name_t          service_name,
-       boolean_t       *service_active)
+       mach_port_t             bootstrap_port,
+       name_t                  service_name,
+       bootstrap_status_t      *service_active)
 {
        service_t *servicep;
        bootstrap_info_t *bootstrap;
@@ -333,18 +551,15 @@ x_bootstrap_status(
                                                service_name,
                                                service_active);
                } else {
-#if    DEBUG
                        debug("bootstrap_status service %s unknown",
                                service_name);
-#endif DEBUG
                        return BOOTSTRAP_UNKNOWN_SERVICE;
                }
        }
-       *service_active = servicep->isActive;
-#if    DEBUG
+       *service_active = bsstatus(servicep);
+
        debug("bootstrap_status server %s %sactive", service_name,
                servicep->isActive ? "" : "in");
-#endif DEBUG
        return BOOTSTRAP_SUCCESS;
 }
 
@@ -355,7 +570,7 @@ x_bootstrap_status(
  *     int *service_names_cnt,
  *     name_array_t *server_names,
  *     int *server_names_cnt,
- *     bool_array_t *service_actives,
+ *     bootstrap_status_array_t *service_actives,
  *     int *service_active_cnt);
  *
  * Returns bootstrap status for all known services.
@@ -364,13 +579,13 @@ x_bootstrap_status(
  */
 kern_return_t
 x_bootstrap_info(
-       mach_port_t     bootstrap_port,
-       name_array_t    *service_namesp,
-       unsigned int    *service_names_cnt,
-       name_array_t    *server_namesp,
-       unsigned int    *server_names_cnt,
-       bool_array_t    *service_activesp,
-       unsigned int    *service_actives_cnt)
+       mach_port_t                     bootstrap_port,
+       name_array_t                    *service_namesp,
+       unsigned int                    *service_names_cnt,
+       name_array_t                    *server_namesp,
+       unsigned int                    *server_names_cnt,
+       bootstrap_status_array_t        *service_activesp,
+       unsigned int                    *service_actives_cnt)
 {
        kern_return_t result;
        unsigned int i, cnt;
@@ -379,7 +594,7 @@ x_bootstrap_info(
        bootstrap_info_t *bootstrap;
        name_array_t service_names;
        name_array_t server_names;
-       bool_array_t service_actives;
+       bootstrap_status_array_t service_actives;
 
        bootstrap = lookup_bootstrap_by_port(bootstrap_port);
 
@@ -424,7 +639,7 @@ x_bootstrap_info(
        }
 
        for (  i = 0, servicep = services.next
-            ; i < nservices
+            ; i < cnt
             ; servicep = servicep->next)
        {
            if (   lookup_service_by_name(bootstrap, servicep->name)
@@ -448,7 +663,7 @@ x_bootstrap_info(
                    debug("bootstrap info service %s %sactive",
                        servicep->name, servicep->isActive ? "" : "in"); 
            }
-           service_actives[i] = servicep->isActive;
+           service_actives[i] = bsstatus(servicep);
            i++;
        }
        *service_namesp = service_names;
@@ -490,23 +705,65 @@ x_bootstrap_subset(
        bootstrap_info_t *bootstrap;
        bootstrap_info_t *subset;
        mach_port_t new_bootstrap_port;
+       mach_port_t previous;
+
+       debug("Subset create attempt: bootstrap %x, requestor: %x",
+             bootstrap_port, requestor_port);
 
        bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       if (!bootstrap || !active_bootstrap(bootstrap))
+               return BOOTSTRAP_NOT_PRIVILEGED;
 
-       result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &new_bootstrap_port);
+       result = mach_port_allocate(
+                               mach_task_self(), 
+                               MACH_PORT_RIGHT_RECEIVE,
+                               &new_bootstrap_port);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "mach_port_allocate");
-       result = mach_port_insert_right(mach_task_self(),  new_bootstrap_port, new_bootstrap_port, MACH_MSG_TYPE_MAKE_SEND);
+
+       result = mach_port_insert_right(
+                               mach_task_self(),
+                               new_bootstrap_port,
+                               new_bootstrap_port,
+                               MACH_MSG_TYPE_MAKE_SEND);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "failed to insert send right");
 
-       result = mach_port_move_member(mach_task_self(), new_bootstrap_port, bootstrap_port_set);
+       result = mach_port_insert_member(
+                               mach_task_self(),
+                               new_bootstrap_port,
+                               bootstrap_port_set);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "port_set_add");
 
        subset = new_bootstrap(bootstrap, new_bootstrap_port, requestor_port);
+
+       result = mach_port_request_notification(
+                               mach_task_self(),
+                               requestor_port,
+                               MACH_NOTIFY_DEAD_NAME,
+                               0,
+                               notify_port,
+                               MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                               &previous); 
+       if (result != KERN_SUCCESS) {
+               kern_error(result, "mach_port_request_notification");
+               mach_port_deallocate(mach_task_self(), requestor_port);
+               subset->requestor_port = MACH_PORT_NULL;
+               deactivate_bootstrap(subset);
+       } else if (previous != MACH_PORT_NULL) {
+               debug("deallocating old notification port (%x) for requestor %x",
+                         previous, requestor_port);
+               result = mach_port_deallocate(
+                               mach_task_self(),
+                               previous);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "mach_port_deallocate");
+       }
+
+       info("Created bootstrap subset %x parent %x requestor %x", 
+               new_bootstrap_port, bootstrap_port, requestor_port);
        *subset_port = new_bootstrap_port;
-       debug("bootstrap_subset new bootstrap %d", new_bootstrap_port);
        return BOOTSTRAP_SUCCESS;
 }
 
@@ -529,14 +786,17 @@ x_bootstrap_create_service(
        name_t  service_name,
        mach_port_t *service_port)
 {
+       server_t *serverp;
        service_t *servicep;
        bootstrap_info_t *bootstrap;
        kern_return_t result;
-       mach_port_t previous;
 
        bootstrap = lookup_bootstrap_by_port(bootstrap_port);
-       ASSERT(bootstrap);
-       debug("Service creation attempt for service %s", service_name);
+       if (!bootstrap || !active_bootstrap(bootstrap))
+               return BOOTSTRAP_NOT_PRIVILEGED;
+
+       debug("Service creation attempt for service %s bootstrap %x",
+             service_name, bootstrap_port);
 
        servicep = lookup_service_by_name(bootstrap, service_name);
        if (servicep) {
@@ -545,29 +805,27 @@ x_bootstrap_create_service(
                return BOOTSTRAP_NAME_IN_USE;
        }
 
+       serverp = lookup_server_by_port(bootstrap_port);
+
        result = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE,  service_port);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "port_allocate");
        result = mach_port_insert_right(mach_task_self(), *service_port, *service_port, MACH_MSG_TYPE_MAKE_SEND);
        if (result != KERN_SUCCESS)
                kern_fatal(result, "failed to insert send right");
-#if notyet
-       result = port_set_backup(mach_task_self(), *service_port, backup_port,
-                                &previous);
-       if (result != KERN_SUCCESS)
-               kern_fatal(result, "port_set_backup");
-       info("Declared port %d for service %s", *service_port,
-               service_name);
-#endif /*notyet */
+
+       if (serverp)
+               serverp->activity++;
 
        servicep = new_service(bootstrap,
                                service_name,
                                *service_port,
                                !ACTIVE,
                                DECLARED,
-                               NULL_SERVER);
+                               serverp);
 
-       log("Created new service %s", service_name);
+       info("Created new service %x in bootstrap %x: %s", 
+           servicep->port, bootstrap->bootstrap_port, service_name);
 
        return BOOTSTRAP_SUCCESS;
 }
diff --git a/mach_init.tproj/testConfig b/mach_init.tproj/testConfig
deleted file mode 100644 (file)
index 893009e..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-services FreeService1 FreeService2;
-# server testServer services BndService3 BndMachService2=2;
-restartable server priority=16 "/NextApps/Terminal" services TerminalService;
-server "/usr/bin/sleep 10" services SleepService;
-self priority=15 Service=2;
-services NetMsgService=0 EnvironService=1 WindowService=3;
-forward;
diff --git a/mach_init.tproj/testConfig2 b/mach_init.tproj/testConfig2
deleted file mode 100644 (file)
index fbb72de..0000000
+++ /dev/null
@@ -1 +0,0 @@
-services foobar;
diff --git a/mach_init.tproj/testServer/Makefile b/mach_init.tproj/testServer/Makefile
deleted file mode 100644 (file)
index 25019ea..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-CFLAGS = -g -I..
-
-all: boot_subset testServer listServer
-
-boot_subset: boot_subset.o
-       cc -o boot_subset boot_subset.o
-
-testServer: testServer.o bootstrapUser.o
-       cc -o testServer testServer.o bootstrapUser.o
-
-listServer: listServer.o bootstrapUser.o
-       cc -o listServer listServer.o bootstrapUser.o
-
-
-bootstrapUser.o: ../bootstrapUser.c
-       cc -c -g ../bootstrapUser.c
-
-clean:
-       rm -f *.o testServer listServer
diff --git a/mach_init.tproj/testServer/boot_subset.c b/mach_init.tproj/testServer/boot_subset.c
deleted file mode 100644 (file)
index 75c67a7..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*
- * Bootstrap subset exercise.
- *
- *     do {
- *             create a subset port with requestor = req_port;
- *             register "foo" on subset_port;
- *             deallocate req_port; 
- *     } until error;
- */
-#import <sys/types.h>
-#import <mach.h>
-#import <servers/bootstrap.h>
-#import <libc.h>
-#import <mach_error.h>
-
-void log_boot_servers(port_t boot_port);
-
-int main(int argc, char **argv)
-{
-       kern_return_t krtn;
-       port_t subset_port;
-       port_t requestor_port;
-       port_t foo_port;
-       int loop = 0;
-       int deallocate_subset = 0;
-       
-       if (argc >= 2 && argv[1][0] == '-' && argv[1][1] == 'r') {
-               port_t  newboot;
-
-               krtn = bootstrap_look_up(bootstrap_port, &argv[1][2], &newboot);
-               if (krtn) {
-                       mach_error("bootstrap lookup", krtn);
-                       exit(1);
-               }
-               bootstrap_port = newboot;
-               --argc; ++argv;
-       }
-       if(argc >= 2) {
-               if(argv[1][0] == '-' && argv[1][0] == 'd')
-                       deallocate_subset = 1;
-       }
-       
-       /*
-        * Allocate some resources.
-        */
-       krtn = port_allocate(task_self(), &foo_port);
-       if(krtn) {
-               mach_error("port_allocate", krtn);
-               exit(1);
-       }
-       
-       do {
-               krtn = port_allocate(task_self(), &requestor_port);
-               if(krtn) {
-                       mach_error("port_allocate", krtn);
-                       exit(1);
-               }
-               krtn = bootstrap_subset(bootstrap_port,
-                       requestor_port,                 /* requestor */
-                       &subset_port);
-               if(krtn) {
-                       mach_error("bootstrap_subset", krtn);
-                       break;
-               }
-               printf("Loop %d, prior to bootstrap_register:\n", loop);
-               log_boot_servers(subset_port);  
-               
-               krtn = bootstrap_register(subset_port,
-                       "foo",
-                       foo_port);
-               if(krtn) {
-                       mach_error("bootstrap_register (subset)", krtn);
-                       exit(1);
-               }
-               printf("Loop %d, after bootstrap_register:\n", loop);
-               log_boot_servers(subset_port);  
-               
-               /*
-                * Delete requestor_port, subset should go away.
-                */
-               krtn = port_deallocate(task_self(), requestor_port);
-               if(krtn) {
-                       mach_error("port_deallocate", krtn);
-                       exit(1);
-               }
-               
-               if(deallocate_subset) {
-                       krtn = port_deallocate(task_self(), subset_port);
-                       if(krtn) {
-                               mach_error("port_deallocate(subset)", krtn);
-                               exit(1);
-                       }
-               }
-               loop++;
-       } while(krtn == KERN_SUCCESS);
-
-       printf("...done\n");
-       exit(0);
-}
-
-void log_boot_servers(port_t boot_port)
-{
-       int i;
-       name_array_t service_names;
-       unsigned int service_cnt;
-       name_array_t server_names;
-       unsigned int server_cnt;
-       bool_array_t service_active;
-       unsigned int service_active_cnt;
-       kern_return_t krtn;
-       
-       krtn = bootstrap_info(boot_port, 
-               &service_names, 
-               &service_cnt,
-               &server_names, 
-               &server_cnt, 
-               &service_active, 
-               &service_active_cnt);
-       if (krtn != BOOTSTRAP_SUCCESS)
-               printf("ERROR:  info failed: %d", krtn);
-       else {
-               printf("log_boot_server: service_cnt = %d\n", service_cnt);
-               for (i = 0; i < service_cnt; i++)
-                       printf("Name: %-15s   Server: %-15s    "
-                           "Active: %-4s",
-                       service_names[i],
-                       server_names[i][0] == '\0' ? 
-                           "Unknown" : server_names[i],
-                       service_active[i] ? "Yes\n" : "No\n");
-       }
-}
-
-   
\ No newline at end of file
diff --git a/mach_init.tproj/testServer/listServer.c b/mach_init.tproj/testServer/listServer.c
deleted file mode 100644 (file)
index cc2073d..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-#import "bootstrap.h"
-
-#import <mach.h>
-#import <stdarg.h>
-#import <stdio.h>
-#import <sys/boolean.h>
-
-#define        NELEM(x)        (sizeof(x)/sizeof(x[0]))
-#define        LAST_ELEMENT(x) ((x)[NELEM(x)-1])
-
-print(const char *format, ...)
-{
-       va_list ap;
-       
-       va_start(ap, format);
-       vfprintf(stderr, format, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-}
-
-error(const char *format, ...)
-{
-       va_list ap;
-       
-       va_start(ap, format);
-       fprintf(stderr, "ERROR: ");
-       vfprintf(stderr, format, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-}
-
-
-main()
-{
-       kern_return_t result;
-       port_t bootstrap_port;
-       name_array_t service_names;
-       unsigned service_cnt, server_cnt, service_active_cnt;
-       name_array_t server_names;
-       boolean_t *service_actives;
-       int i;
-       
-       result = task_get_bootstrap_port(task_self(), &bootstrap_port);
-       if (result != KERN_SUCCESS) {
-               error("Couldn't get bootstrap port: %d", result);
-               exit(1);
-       }
-       if (bootstrap_port == PORT_NULL) {
-               error("Invalid bootstrap port");
-               exit(1);
-       }
-
-       result = bootstrap_info(bootstrap_port, &service_names, &service_cnt,
-         &server_names, &server_cnt, &service_actives, &service_active_cnt);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("info failed: %d", result);
-       else {
-               for (i = 0; i < service_cnt; i++)
-                       print("Name: %-15s   Server: %-15s    Active: %-4s",
-                        service_names[i],
-                        server_names[i][0] == '\0' ? "Unknown" : server_names[i],
-                        service_actives[i] ? "Yes" : "No");
-       }
-               
-       exit(0);
-}
-       
-       
-
-
diff --git a/mach_init.tproj/testServer/testServer.c b/mach_init.tproj/testServer/testServer.c
deleted file mode 100644 (file)
index 8fc640a..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
- * Reserved.  This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.0 (the 'License').  You may not use this file
- * except in compliance with the License.  Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License."
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-#import "bootstrap.h"
-
-#import <mach.h>
-#import <stdarg.h>
-#import <stdio.h>
-#import <sys/boolean.h>
-
-#define        NELEM(x)        (sizeof(x)/sizeof(x[0]))
-#define        LAST_ELEMENT(x) ((x)[NELEM(x)-1])
-
-print(const char *format, ...)
-{
-       va_list ap;
-       
-       va_start(ap, format);
-       vfprintf(stderr, format, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-}
-
-error(const char *format, ...)
-{
-       va_list ap;
-       
-       va_start(ap, format);
-       fprintf(stderr, "ERROR: ");
-       vfprintf(stderr, format, ap);
-       fprintf(stderr, "\n");
-       va_end(ap);
-}
-
-
-main()
-{
-       kern_return_t result;
-       port_t bootstrap_port, port, myport;
-       port_type_t ptype;
-       port_t *mach_ports;
-       port_t *ports;
-       unsigned port_cnt;
-       unsigned mach_ports_cnt;
-       name_t name_array[4];
-       boolean_t all_known;
-       port_t unpriv_port;
-       port_t subset_port;
-       port_t sub_reg_port;
-       boolean_t active;
-       name_array_t service_names;
-       unsigned service_cnt, server_cnt, service_active_cnt;
-       name_array_t server_names;
-       boolean_t *service_actives;
-       int i;
-       
-       print("test server running");
-       result = task_get_bootstrap_port(task_self(), &bootstrap_port);
-       if (result != KERN_SUCCESS) {
-               error("Couldn't get bootstrap port: %d", result);
-               exit(1);
-       } else
-               print("Bootstrap port is %d", bootstrap_port);
-       if (bootstrap_port == PORT_NULL) {
-               error("Invalid bootstrap port");
-               exit(1);
-       }
-       
-       /*
-        * Try a checkin
-        */
-       print("Checkin test 1");
-       result = bootstrap_check_in(bootstrap_port, "FreeService1", &port);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("Checkin failed: %d", result);
-       else {
-               result = port_type(task_self(), port, &ptype);
-               if (result != KERN_SUCCESS)
-                       error("port type failed: %d", result);
-               else
-                       print("Checkin returned port type 0x%x", ptype);
-               /*
-                * Try a status request
-                */
-               result = bootstrap_status(bootstrap_port, "FreeService1", &active);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Status failed: %d", result);
-               else if (active != TRUE)
-                       error("Service shown inactive");
-       }
-       
-       /*
-        * Try a lookup
-        */
-       print("lookup test");
-       result = bootstrap_look_up(bootstrap_port, "FreeService2", &port);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("lookup failed: %d", result);
-       else {
-               result = port_type(task_self(), port, &ptype);
-               if (result != KERN_SUCCESS)
-                       error("port type failed: %d", result);
-               else
-                       print("Lookup returned port type 0x%x", ptype);
-               /*
-                * Try a status request
-                */
-               result = bootstrap_status(bootstrap_port, "FreeService2", &active);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Status failed: %d", result);
-               else if (active != FALSE)
-                       error("Service shown active");
-       }
-       
-       /*
-        * Test that mach ports are initialized
-        */
-       print("mach ports test");
-       result = mach_ports_lookup(task_self(), &mach_ports, &mach_ports_cnt);
-       if (result != KERN_SUCCESS)
-               error("mach_ports_lookup failed: %d", result);
-       else {
-               result = bootstrap_look_up(bootstrap_port, "NetMsgService", &port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Lookup of NetMsgService failed: %d", result);
-               else if (port != mach_ports[0])
-                       error("mach ports not setup correctly for NetMsgService");
-               
-               result = bootstrap_look_up(bootstrap_port, "EnvironService", &port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Lookup of EnvironService failed: %d", result);
-               else if (port != mach_ports[1])
-                       error("mach ports not setup correctly for EnvironService");
-
-               result = bootstrap_look_up(bootstrap_port, "Service", &port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Lookup of Service failed: %d", result);
-               else if (port != mach_ports[2])
-                       error("mach ports not setup correctly for Service");
-                       
-               result = bootstrap_look_up(bootstrap_port, "WindowService", &port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Lookup of WindowService failed: %d", result);
-               else if (port != mach_ports[3])
-                       error("mach ports not setup correctly for WindowService");
-       }
-       
-       /*
-        * Try doing a checkin with the old service interface
-        */
-       result = service_checkin(mach_ports[2], mach_ports[1], &myport);
-       if (result != KERN_SUCCESS)
-               error("service checkin failed: %d", result);
-       else {
-               result = port_type(task_self(), myport, &ptype);
-               if (result != KERN_SUCCESS)
-                       error("port type failed: %d", result);
-               else
-                       print("Checkin returned port type 0x%x", ptype);
-       }
-       
-       /*
-        * Try a register
-        */
-       print("register test");
-       print("...Dynamic creation");
-       result = port_allocate(task_self(), &myport);
-       if (result != KERN_SUCCESS)
-               error("couldn't allocate port: %d", result);
-       else {
-               result = bootstrap_register(bootstrap_port, "NewService", myport);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Couldn't register port: %d", result);
-               else {
-       
-                       /*
-                        * Try a lookup on just registered port
-                        */
-                       result = bootstrap_look_up(bootstrap_port, "NewService", &port);
-                       if (result != BOOTSTRAP_SUCCESS)
-                               error("lookup failed: %d", result);
-                       else {
-                               result = port_type(task_self(), port, &ptype);
-                               if (result != KERN_SUCCESS)
-                                       error("port type failed: %d", result);
-                               else {
-                                       print("Lookup returned port type 0x%x", ptype);
-                                       if (port != myport)
-                                               error("lookup didn't match register");
-                               }
-                       }
-                       
-                       /*
-                        * Try re-registering service name
-                        */
-                       result = bootstrap_register(bootstrap_port, "NewService", myport);
-                       if (result != BOOTSTRAP_SERVICE_ACTIVE)
-                               error("Unexpected register response: %d", result);
-
-                       /*
-                        * Delete the port.  This should cause the service to go away
-                        * in the server.
-                        */
-                       port_deallocate(task_self(), myport);
-                       
-                       result = bootstrap_look_up(bootstrap_port, "NewService", &port);
-                       if (result != BOOTSTRAP_UNKNOWN_SERVICE)
-                               error("service active after port deleted");
-               }
-       }
-
-       print("...Declared service");
-       result = port_allocate(task_self(), &myport);
-       if (result != KERN_SUCCESS)
-               error("couldn't allocate port: %d", result);
-       else {
-               result = bootstrap_register(bootstrap_port, "FreeService2", myport);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Couldn't register port: %d", result);
-               else {
-       
-                       /*
-                        * Try a lookup on just registered port
-                        */
-                       result = bootstrap_look_up(bootstrap_port, "FreeService2", &port);
-                       if (result != BOOTSTRAP_SUCCESS)
-                               error("lookup failed: %d", result);
-                       else {
-                               result = port_type(task_self(), port, &ptype);
-                               if (result != KERN_SUCCESS)
-                                       error("port type failed: %d", result);
-                               else {
-                                       print("Lookup returned port type 0x%x", ptype);
-                                       if (port != myport)
-                                               error("lookup didn't match register");
-                               }
-                       }
-                       
-                       /*
-                        * Delete the port.  This should cause service to revert.
-                        */
-                       port_deallocate(task_self(), myport);
-                       
-                       result = bootstrap_status(bootstrap_port, "FreeService2", &active);
-                       if (result != BOOTSTRAP_SUCCESS)
-                               error("Status failed: %d", result);
-                       else if (active != FALSE)
-                               error("Service shown active");
-               }
-       }
-
-       /*
-        * Try a checkin on a port bound to Terminal server
-        */
-       print("Bound checkin test -- Terminal");
-       result = bootstrap_check_in(bootstrap_port, "TerminalService", &port);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("Checkin of TerminalService failed: %d", result);
-       else {
-               result = port_type(task_self(), port, &ptype);
-               if (result != KERN_SUCCESS)
-                       error("port type failed: %d", result);
-               print("Checkin returned port type 0x%x", ptype);
-       }
-
-       /*
-        * Try a checkin on a port bound to Sleep server
-        */
-       print("Bound checkin test -- Sleep");
-       result = bootstrap_check_in(bootstrap_port, "SleepService", &port);
-       if (result != BOOTSTRAP_SUCCESS)
-               print("Checkin of SleepService failed (as expected): %d",
-                       result);
-       else {
-               result = port_type(task_self(), port, &ptype);
-               if (result != KERN_SUCCESS)
-                       error("port type failed: %d", result);
-               error("Checkin returned port type 0x%x(didn't fail!)", ptype);
-       }
-
-       /*
-        * Try a lookup_array
-        */
-       print("Lookup array test");
-       
-       strncpy(&name_array[0], "NetMsgService", sizeof(name_array[0]));
-       LAST_ELEMENT(name_array[0]) = '\0';
-       strncpy(&name_array[1], "EnvironService", sizeof(name_array[1]));
-       LAST_ELEMENT(name_array[1]) = '\0';
-       strncpy(&name_array[2], "Service", sizeof(name_array[2]));
-       LAST_ELEMENT(name_array[2]) = '\0';
-       strncpy(&name_array[3], "WindowService", sizeof(name_array[3]));
-       LAST_ELEMENT(name_array[3]) = '\0';
-       
-       result = bootstrap_look_up_array(bootstrap_port, name_array, 4, &ports,
-        &port_cnt, &all_known);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("Lookup array failed: %d", result);
-       else {
-               print("Port count = %d, all known = %d", port_cnt, all_known);
-               for (i = 0; i < 4; i++)
-                       if (ports[i] != mach_ports[i])
-                               error("port mismatch on port %d", i);
-       }
-       
-       /*
-        * Get an unprivileged port
-        */
-       print("Unprivileged port test");
-       result = port_allocate(task_self(), &myport);
-       result = bootstrap_get_unpriv_port(bootstrap_port, &unpriv_port);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("Couldn't get unpriv port: %d", result);
-       else {
-               /*
-                * Try doing an unpriv operation
-                */
-               result = bootstrap_look_up(unpriv_port, "FreeService2", &port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("lookup failed: %d", result);
-               /*
-                * Try doing a privileged operation
-                */
-               result = bootstrap_register(unpriv_port, "ANewService", myport);
-               if (result != BOOTSTRAP_NOT_PRIVILEGED)
-                       error("Unexpected register port response: %d", result);
-
-               /*
-                * Try creating a subset port.
-                */
-               result = bootstrap_subset(unpriv_port, task_self(),
-                       &subset_port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("Couldn't get subset port from unpriv %d",
-                               result);
-       }
-
-       /*
-        * Get a subset port.
-        */
-       print("Subset port test");
-       result = bootstrap_subset(bootstrap_port, task_self(), &subset_port);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("Couldn't get subset port: %d", result);
-       else {
-
-               /*
-                * Register a port.
-                */
-               result = port_allocate(task_self(), &sub_reg_port);
-               if (result != KERN_SUCCESS)
-                       error("port_allocate of sub_reg_port failed %d",
-                               result);
-               result = bootstrap_register(subset_port, "SubsetReg",
-                                           sub_reg_port);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("register of SubsetReg failed on subset port %d",
-                               result);
-               /*
-                * Check that port registered only in subset.
-                */
-               result = bootstrap_status(bootstrap_port, "SubsetReg",
-                                       &active);
-               if (result != BOOTSTRAP_UNKNOWN_SERVICE)
-                       error("status of SubsetReg  ok on bootstrap! %d",
-                               result);
-               result = bootstrap_status(subset_port, "SubsetReg",
-                                       &active);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("status of SubsetReg failed on subset port %d",
-                               result);
-               if (!active)
-                       error("SubsetReg isn't active");
-
-
-               /*
-                * Try an info request.
-                */
-               print("Subset info request");
-               result = bootstrap_info(subset_port, &service_names,
-                       &service_cnt,
-                       &server_names, &server_cnt, &service_actives,
-                       &service_active_cnt);
-               if (result != BOOTSTRAP_SUCCESS)
-                       error("info failed: %d", result);
-               else {
-                       for (i = 0; i < service_cnt; i++)
-                               print("Name: %s Server: %s      Active: %s",
-                                   service_names[i],
-                                   server_names[i][0] == '\0'
-                                    ? "Unknown"
-                                    : server_names[i],
-                                   service_actives[i] ? "Yes" : "No");
-               }
-       }
-
-       /*
-        * Try an info request
-        */
-       print("Info test");
-       result = bootstrap_info(bootstrap_port, &service_names, &service_cnt,
-         &server_names, &server_cnt, &service_actives, &service_active_cnt);
-       if (result != BOOTSTRAP_SUCCESS)
-               error("info failed: %d", result);
-       else {
-               for (i = 0; i < service_cnt; i++)
-                       print("Name: %s Server: %s      Active: %s", service_names[i],
-                        server_names[i][0] == '\0' ? "Unknown" : server_names[i],
-                        service_actives[i] ? "Yes" : "No");
-       }
-               
-       exit(0);
-}
-
-
-
index 9a46e786902a529d32e94a0371fbd635ad5ee8e4..998b2d25bafb36f68df7a3f47c3c8c8c069f3bd2 100644 (file)
@@ -14,7 +14,7 @@ PROJECT_TYPE = Tool
 
 CFILES = mkfile.c
 
-OTHERSRCS = Makefile.preamble
+OTHERSRCS = Makefile.preamble Makefile.postamble mkfile.8
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
diff --git a/mkfile.tproj/Makefile.postamble b/mkfile.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..01925dd
--- /dev/null
@@ -0,0 +1,3 @@
+after_install:
+       install -d $(DSTROOT)/usr/share/man/man8
+       install -c -m 444 mkfile.8 $(DSTROOT)/usr/share/man/man8
diff --git a/mkfile.tproj/mkfile.8 b/mkfile.tproj/mkfile.8
new file mode 100644 (file)
index 0000000..beed0c1
--- /dev/null
@@ -0,0 +1,47 @@
+.\" (c) 1997 Apple Computer, Inc.
+.TH MKFILE 8 "1 September 1997"
+.SH NAME
+mkfile \- create a file
+.SH SYNOPSIS
+.B mkfile
+.RB [ " -nv " ]
+.I size\c
+[\c
+.BR b | k | m | g\c
+]
+.IR filename " .\|.\|."
+.SH DESCRIPTION
+.B mkfile
+creates one or more files that are suitable for use as
+.SM NFS-\s0mounted
+swap areas.  The sticky bit is set, and
+the file is padded with zeroes by default.
+Non-root users must set the sticky bit using
+chmod(1).
+The default size unit is bytes, but the following suffixes
+may be used to multiply by the given factor:
+.B b
+(512),
+.B k
+(1024),
+.B m
+(1048576), and
+.B g
+(1073741824).
+.SH OPTIONS
+.TP
+.B \-n
+Create an empty
+.IR filename .
+The size is noted, but disk blocks aren't allocated until data is
+written to them.
+.TP
+.B \-v
+Verbose.  Report the names and sizes of created files.
+.SH WARNING
+If a client's swap file is removed and recreated, it must be
+re-exported before the client will be able to access it.
+This action may only be done when the client is not running.
+.SH "SEE ALSO"
+.TP
+chmod(2), stat(2), exportfs(8), sticky(8)
index 6979d8726211fa34d751a7ad21519442f4735254..2cd9b355557ed7c58edcf8ed7d1f099c5480306b 100644 (file)
 # Note: on MS Windows, executables, have an extension, so rules and dependencies
 #       for generated tools should use $(EXECUTABLE_EXT) on the end.
 
+SHAREDIR = /usr/share
+MANDIR   = $(SHAREDIR)/man/man8
+MANPAGE  = nologin.8
+
 nologin: nologin.sh
        $(CP) nologin.sh ${SYM_DIR}/nologin
 
 after_install::
        $(CP) -p ${SYM_DIR}/nologin $(DSTROOT)$(INSTALLDIR)/nologin
        $(CHMOD) 555 $(DSTROOT)$(INSTALLDIR)/nologin
+       $(MKDIRS) $(DSTROOT)$(MANDIR)
+       $(CP) -f $(MANPAGE) $(DSTROOT)$(MANDIR)/$(MANPAGE)
+       $(CHMOD) og-w $(DSTROOT)$(MANDIR)/$(MANPAGE)
index 32a7e73070b840b6e206f92891ad5da4f7f0cef0..07ddc980a36ccf6d333e68064b2aae5266cffed4 100644 (file)
@@ -1,3 +1,6 @@
+.\"    $OpenBSD: nologin.8,v 1.3 1997/02/16 04:15:32 downsj Exp $
+.\"    $NetBSD: nologin.8,v 1.3 1995/03/18 14:59:09 cgd Exp $
+.\"
 .\" Copyright (c) 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,9 +34,9 @@
 .\"
 .\"     @(#)nologin.8  8.1 (Berkeley) 6/19/93
 .\"
-.Dd June 19, 1993
+.Dd February 15, 1997
 .Dt NOLOGIN 8
-.Os BSD 4.4
+.Os
 .Sh NAME
 .Nm nologin
 .Nd politely refuse a login 
@@ -45,6 +48,12 @@ displays a message that an account is not available and
 exits non-zero.
 It is intended as a replacement shell field for accounts that
 have been disabled.
+.Pp
+If the file
+.Pa /etc/nologin.txt
+exists,
+.Nm nologin
+displays its contents to the user instead of the default message.
 .Sh SEE ALSO
 .Xr login 1
 .Sh HISTORY
index 7392f2e032907fbd748bf2c5ad9e3fac7c1c474d..57d22d5ee7b95fadf5b5b1e93ac586a23acc2792 100644 (file)
@@ -27,8 +27,8 @@ In principle,
 .IR name
 can be any string.  In practice, not all strings will be accepted.
 Old world machines have a fixed set of Open Firmware variables.
-New World machines can create new varibles as desired.  Some variables
-require adminstrator privilege to get or set.
+New World machines can create new variables as desired.  Some variables
+require administrator privilege to get or set.
 .LP
 The given
 .IR value
@@ -72,14 +72,14 @@ list name=value statements.  If the last character of a line is
 example% nvram boot-args="-s rd=*hd:10"
 .RE
 .LP
-Set the boot-args variable to "-s rd=*hd:10".  This would specifiy
+Set the boot-args variable to "-s rd=*hd:10".  This would specify
 single user mode with the root device in hard drive partition 10.
 .LP
 .RS
 example% nvram my-variable="String One%00String Two%00%00"
 .RE
 .LP
-Create a new variable, my-variable, containging a list of two
+Create a new variable, my-variable, containing a list of two
 C-strings that is terminated by a NUL.
 .SH FILES
 .PD 0
index d23b79c210df447db42f421d8052ea9960298853..c450f3257205c8fee0933f1995f744b465f4b61e 100644 (file)
@@ -409,10 +409,11 @@ static void PrintOFVariable(const void *key, const void *value, void *context)
   long          cnt, cnt2;
   const char    *nameString;
   char          numberBuffer[10];
-  char          *dataPtr, dataChar;
+  const uint8_t *dataPtr;
+  uint8_t       dataChar;
   char          *dataBuffer = 0;
-  char          *valueString = 0;
-  unsigned long number, length;
+  const char    *valueString = 0;
+  uint32_t      number, length;
   CFTypeID      typeID;
   
   // Get the OF variable's name.
index 6f5764661323ba2db432a1c7544ba129952888de..f50e9a52179c6fd99dc23c6110910775d7097385 100644 (file)
@@ -24,7 +24,7 @@ MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /usr/bin
 WINDOWS_INSTALLDIR = /Library/Executables
 PDO_UNIX_INSTALLDIR = /bin
-LIBS = 
+LIBS = -lcurses
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
index 5198d9aeadbba17d4bda465472d4a51f951a5070..965d369ed17dac7bfee2e6f56ff90541e0205aca 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 /*
-cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
+cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c -lncurses
 */
 
 #define        Default_DELAY   1       /* default delay interval */
@@ -42,7 +42,7 @@ cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
+#include <curses.h>
 
 #include <sys/ioctl.h>
 
@@ -192,7 +192,6 @@ int    scalls;
 #define DIVISOR 16.6666        /* Trace divisor converts to microseconds */
 double divisor = DIVISOR;
 
-struct termios tmode, omode;
 
 int mib[6];
 size_t needed;
@@ -226,8 +225,6 @@ void leave()                        /* exit under normal conditions -- INT handler */
                move(LINES - 1, 0);
                refresh();
                endwin();
-
-               tcsetattr(0, TCSANOW, &omode);
        }
        set_enable(0);
        set_pidcheck(pid, 0);
@@ -243,8 +240,6 @@ char *s;
                move(LINES - 1, 0);
                refresh();
                endwin();
-
-               tcsetattr(0, TCSANOW, &omode);
        }
 
         printf("sc_usage: ");
@@ -423,22 +418,17 @@ main(argc, argv)
 
 
        if (no_screen_refresh == 0) {
-               if (tcgetattr(0, &tmode) < 0) {
-                       printf("can't get terminal attributes\n");
-                       exit(1);
-               }
-               omode = tmode;
-       
-               tmode.c_lflag &= ~ICANON;
-               tmode.c_cc[VMIN] = 0;
-               tmode.c_cc[VTIME] = 1;
 
-               if (tcsetattr(0, TCSANOW, &tmode) < 0) {
-                       printf("can't set terminal attributes\n");
-                       exit(1);
-               }
                /* initializes curses and screen (last) */
-               initscr();
+               if (initscr() == (WINDOW *) 0)
+                 {
+                   printf("Unrecognized TERM type, try vt100\n");
+                   exit(1);
+                 }
+               cbreak();
+               timeout(100);
+               noecho();
+
                clear();
                refresh();
        }
@@ -447,6 +437,8 @@ main(argc, argv)
        /* set up signal handlers */
        signal(SIGINT, leave);
        signal(SIGQUIT, leave);
+        signal(SIGHUP, leave);
+        signal(SIGTERM, leave);
        signal(SIGWINCH, sigwinch);
 
         if (no_screen_refresh == 0)
@@ -480,21 +472,16 @@ main(argc, argv)
        while (1) {
                int     i;
                int     cnt;
-               char    ibuf[128];
+               char    c;
                void    sample_sc();
                
                for (i = 0; i < (10 * delay) && newLINES == 0; i++) {
 
                        if (no_screen_refresh == 0) {
-                               if ((cnt = read(0, &ibuf, 128)) > 0) {
-                                       int   n;
-
-                                       for (n = 0; n < cnt; n++)
-                                               if (ibuf[n] == 'q')
-                                                       leave();
-                                       reset_counters();
-                                       break;
-                               }
+                               if ((c = getch()) != ERR && (char)c == 'q') 
+                                       leave();
+                               if (c != ERR)
+                                       reset_counters();
                        } else
                                usleep(100000);
                        sample_sc();
@@ -502,7 +489,11 @@ main(argc, argv)
                (void)sort_scalls();
 
                if (newLINES) {
-                       initscr();
+                       /*
+                         No need to check for initscr error return.
+                         We won't get here if it fails on the first call.
+                       */
+                       endwin();
                        clear();
                        refresh();
 
@@ -1425,11 +1416,12 @@ sample_sc()
                        (uint64_t)((unsigned int)(kd[i].timestamp.tv_nsec));
                baseid = debugid & 0xffff0000;
 
-               if (debugid == vfs_lookup) {
+               if (type == vfs_lookup) {
                        long *sargptr;
 
                        if ((ti = find_thread(thread)) == (struct th_info *)0)
                                continue;
+
                        if (ti->vfslookup == 1) {
                                ti->vfslookup++;
                                memset(&ti->pathname[0], 0, (PATHLENGTH + 1));
@@ -1451,7 +1443,21 @@ sample_sc()
                                */
 
                                if ((long *)sargptr >= (long *)&ti->pathname[PATHLENGTH])
-                                 continue;
+                                       continue;
+
+                               /*
+                                 We need to detect consecutive vfslookup entries.
+                                 So, if we get here and find a START entry,
+                                 fake the pathptr so we can bypass all further
+                                 vfslookup entries.
+                               */
+
+                               if (debugid & DBG_FUNC_START)
+                                 {
+                                   (long *)ti->pathptr = (long *)&ti->pathname[PATHLENGTH];
+                                   continue;
+                                 }
+
                                *sargptr++ = kd[i].arg1;
                                *sargptr++ = kd[i].arg2;
                                *sargptr++ = kd[i].arg3;
index 25331b5b309af2e3c9f796ca84e87bd4022b7af9..a2caffd81b6f579bb9dee7867f69f3e31e04cd28 100644 (file)
@@ -1,4 +1,65 @@
-773
+892
+0x1f000000     DYLD_initialize
+0x1f010000     DYLD_CALL_image_init_routine
+0x1f010004     DYLD_CALL_dependent_init_routine
+0x1f010008     DYLD_CALL_lazy_init_routine
+0x1f01000c     DYLD_CALL_module_init_for_library
+0x1f010010     DYLD_CALL_module_init_for_object
+0x1f010014     DYLD_CALL_module_terminator_for_object
+0x1f010018     DYLD_CALL_module_init_for_dylib
+0x1f01001c     DYLD_CALL_mod_term_func
+0x1f010020     DYLD_CALL_object_func
+0x1f010024     DYLD_CALL_library_func
+0x1f010028     DYLD_CALL_add_image_func
+0x1f01002c     DYLD_CALL_remove_image_func
+0x1f010030     DYLD_CALL_link_object_module_func
+0x1f010034     DYLD_CALL_link_library_module_func
+0x1f010038     DYLD_CALL_link_module_func
+0x1f020000     DYLD_lookup_and_bind_with_hint
+0x1f020004     DYLD_lookup_and_bind_fully
+0x1f020008     DYLD_link_module
+0x1f02000c     DYLD_ulink_module
+0x1f020010     DYLD_bind_objc_module
+0x1f020014     DYLD_bind_fully_image_containing_address
+0x1f020018     DYLD_make_delayed_module_initializer_calls
+0x1f02001c     DYLD_NSNameOfSymbol
+0x1f020020     DYLD_NSAddressOfSymbol
+0x1f020024     DYLD_NSModuleForSymbol
+0x1f020028     DYLD_NSLookupAndBindSymbolWithHint
+0x1f02002c     DYLD_NSLookupSymbolInModule
+0x1f020030     DYLD_NSLookupSymbolInImage
+0x1f020034     DYLD_NSIsSymbolNameDefined
+0x1f020038     DYLD_NSIsSymbolNameDefinedWithHint
+0x1f02003c     DYLD_NSIsSymbolNameDefinedInImage
+0x1f020040     DYLD_NSNameOfModule
+0x1f020044     DYLD_NSLibraryNameForModule
+0x1f020048     DYLD_NSAddLibrary
+0x1f02004c     DYLD_NSAddLibraryWithSearching
+0x1f020050     DYLD_NSAddImage
+0x1f030000     DYLD_lookup_symbol
+0x1f030004     DYLD_bind_lazy_symbol_reference
+0x1f030008     DYLD_bind_symbol_by_name
+0x1f03000c     DYLD_link_in_need_modules
+0x1f040000     DYLD_map_image
+0x1f040004     DYLD_load_executable_image
+0x1f040008     DYLD_load_library_image
+0x1f04000c     DYLD_map_library_image
+0x1f040010     DYLD_map_bundle_image
+0x1f040014     DYLD_load_dependent_libraries
+0x1f040018     DYLD_notify_prebinding_agent
+0x1fff0000     LAUNCH_START_FINDER
+0x1fff0100     LAUNCH_START_DOCK
+0x1fff0200     LAUNCH_LSOpen
+0x1fff0204     LAUNCH_LSRegisterItem
+0x1fff0208     LAUNCH_LSGetApplicationAndFlagsForInfo
+0x1fff0300     LAUNCH_CPSLaunch
+0x1fff0304     LAUNCH_CPSRegisterwithServer
+0x1fff0308     LAUNCH_CGSCheckInNewProcess
+0x1fff030c      LAUNCH_CPSExecProcess
+0x1fff0310     LAUNCH_APP_EnterEventLoop
+0x1fff0314     LAUNCH_APP_WillOpenUntitled
+0x1fff031c     LAUNCH_APP_DidOpenUntitled
+0x1fffffff     LAUNCH_END
 0xff000104     MSG_mach_notify_port_deleted
 0xff000114     MSG_mach_notify_port_destroyed
 0xff000118     MSG_mach_notify_no_senders
@@ -30,7 +91,7 @@
 0xff000658     MSG_vm_allocate_cpm
 0xff00065c     MSG_host_processors
 0xff000660     MSG_host_get_clock_control
-0xff000664     MSG_kmod_create
+0xff000664     MSG_kmod_creat
 0xff000668     MSG_kmod_destroy
 0xff00066c     MSG_kmod_control
 0xff000670     MSG_host_get_special_port
 0xff002584     MSG_exception_raise
 0xff002588     MSG_exception_raise_state
 0xff00258c     MSG_exception_raise_state_identity
+0xff002648     MSG_samples
+0xff00264c     MSG_notices
 0xff002bc0     MSG_io_object_get_class
 0xff002bc4     MSG_io_object_conforms_to
 0xff002bc8     MSG_io_iterator_next
 0xff003218     MSG_mach_port_deallocate
 0xff00321c     MSG_mach_port_get_refs
 0xff003220     MSG_mach_port_mod_refs
-0xff003224     MSG_mach_port_allocate_subsystem
 0xff003228     MSG_mach_port_set_mscount
 0xff00322c     MSG_mach_port_get_set_status
 0xff003230     MSG_mach_port_move_member
 0xff003598     MSG_task_assign_default
 0xff00359c     MSG_task_get_assignment
 0xff0035a0     MSG_task_set_policy
-0xff0035a4     MSG_mach_subsystem_create
 0xff003840     MSG_thread_terminate
 0xff003844     MSG_act_get_state
 0xff003848     MSG_act_set_state
 0xff25a8ac     MSG_lock_make_stable
 0xff25a8b0     MSG_lock_handoff
 0xff25a8b4     MSG_lock_handoff_accept
+0xff25abc0     MSG_semaphore_signal
+0xff25abc4     MSG_semaphore_signal_all
+0xff25abc8     MSG_semaphore_wait
+0xff25abcc     MSG_semaphore_signal_thread
+0xff25abd0     MSG_semaphore_timedwait
+0xff25abd4     MSG_semaphore_wait_signal
+0xff25abd8     MSG_semaphore_timedwait_signal
 0xff3d0904     MSG_bootstrap_ports
 0xff3d0908     MSG_bootstrap_arguments
 0xff3d090c     MSG_bootstrap_environment
 0xff3d0910     MSG_bootstrap_completed
+0xffbebdcc     MSG_clock_alarm_reply
 0x1300000      MACH_vmfault
+0x1300004      MACH_Pageout
 0x1400000      MACH_SCHED
 0x1400008      MACH_STKHANDOFF
 0x1400018      MACH_MKRUNNABLE
 0x10c0070      MSC_task_self_trap
 0x10c0074      MSC_host_self_trap
 0x10c0078      MSC_kern_invalid_#30
-0x10c007c      MSC_kern_invalid_#31
+0x10c007c      MSC_mach_msg_trap
 0x10c0080      MSC_mach_msg_overwrite_trap
 0x10c0084      MSC_semaphore_signal_trap
 0x10c0088      MSC_semaphore_signal_all_trap
 0x10c01fc      MSC_kern_invalid_#127
 0x1050000      INTERRUPT
 0x3010090      VFS_LOOKUP
+0x3020000       P_WrData
+0x3020008       P_RdData
+0x3020020       P_WrMeta
+0x3020028       P_RdMeta
+0x3020040       P_PgOut
+0x3020048       P_PgIn
+0x3020010       P_WrDataAsync
+0x3020018       P_RdDataAsync
+0x3020030       P_WrMetaAsync
+0x3020038       P_RdMetaAsync
+0x3020050       P_PgOutAsync
+0x3020058       P_PgInAsync
+0x3020004       P_WrDataDone
+0x302000C       P_RdDataDone
+0x3020024       P_WrMetaDone
+0x302002C       P_RdMetaDone
+0x3020044       P_PgOutDone
+0x302004C       P_PgInDone
+0x3020014       P_WrDataAsyncDone
+0x302001C       P_RdDataAsyncDone
+0x3020034       P_WrMetaAsyncDone
+0x302003C       P_RdMetaAsyncDone
+0x3020054       P_PgOutAsyncDone
+0x302005C       P_PgInAsyncDone
 0x40c0000      BSC_SysCall
 0x40c0004      BSC_exit
 0x40c0008      BSC_fork
 0x40c0014      BSC_open
 0x40c0018      BSC_close
 0x40c001c      BSC_wait4
-0x40c0020      BSC_old_creat
+0x40c0020      BSC_obs_creat
 0x40c0024      BSC_link
 0x40c0028      BSC_unlink
 0x40c002c      BSC_obs_execv
 0x40c0038      BSC_mknod
 0x40c003c      BSC_chmod
 0x40c0040      BSC_chown
-0x40c0044      BSC_sbreak
-0x40c0048      BSC_getfsstat
+0x40c0044      BSC_obs_break
+0x40c0048      BSC_obs_getfsstat
 0x40c004c      BSC_old_lseek
 0x40c0050      BSC_getpid
 0x40c0054      BSC_obs_mount
 0x40c008c      BSC_fchflags
 0x40c0090      BSC_sync
 0x40c0094      BSC_kill
-0x40c0098      BSC_old_stat
+0x40c0098      BSC_obs_stat
 0x40c009c      BSC_getppid
-0x40c00a0      BSC_old_lstat
+0x40c00a0      BSC_obs_lstat
 0x40c00a4      BSC_dup
 0x40c00a8      BSC_pipe
 0x40c00ac      BSC_getegid
 0x40c00ec      BSC_execve
 0x40c00f0      BSC_umask
 0x40c00f4      BSC_chroot
-0x40c00f8      BSC_old_fstat
-0x40c00fc      BSC_old_getkerninfo
-0x40c0100      BSC_old_getpagesize
+0x40c00f8      BSC_obs_fstat
+0x40c00fc      BSC_#63
+0x40c0100      BSC_obs_getpagesize
 0x40c0104      BSC_msync
 0x40c0108      BSC_vfork
 0x40c010c      BSC_obs_vread
 0x40c0110      BSC_obs_vwrite
 0x40c0114      BSC_sbrk
 0x40c0118      BSC_sstk
-0x40c011c      BSC_old_mmap
+0x40c011c      BSC_obs_mmap
 0x40c0120      BSC_obs_vadvise
 0x40c0124      BSC_munmap
 0x40c0128      BSC_mprotect
 0x40c012c      BSC_madvise
-0x40c0130      BSC_obs_vhangup
-0x40c0134      BSC_obs_vlimit
+0x40c0130      BSC_#76
+0x40c0134      BSC_#77
 0x40c0138      BSC_mincore
 0x40c013c      BSC_getgroups
 0x40c0140      BSC_setgroups
 0x40c0148      BSC_setpgid
 0x40c014c      BSC_setitimer
 0x40c0150      BSC_old_wait
-0x40c0154      BSC_swapon
+0x40c0154      BSC_obs_swapon
 0x40c0158      BSC_getitimer
-0x40c015c      BSC_old_gethostname
-0x40c0160      BSC_old_sethostname
+0x40c015c      BSC_obs_gethostname
+0x40c0160      BSC_obs_sethostname
 0x40c0164      BSC_getdtablesize
 0x40c0168      BSC_dup2
 0x40c016c      BSC_#91
 0x40c0180      BSC_setpriority
 0x40c0184      BSC_socket
 0x40c0188      BSC_connect
-0x40c018c      BSC_old_accept
+0x40c018c      BSC_obs_accept
 0x40c0190      BSC_getpriority
 0x40c0194      BSC_old_send
 0x40c0198      BSC_old_recv
 0x40c01a0      BSC_bind
 0x40c01a4      BSC_setsockopt
 0x40c01a8      BSC_listen
-0x40c01ac      BSC_obs_vtimes
-0x40c01b0      BSC_old_sigvec
-0x40c01b4      BSC_old_sigblock
-0x40c01b8      BSC_old_sigsetmask
+0x40c01ac      BSC_#107
+0x40c01b0      BSC_obs_sigvec
+0x40c01b4      BSC_obs_sigblock
+0x40c01b8      BSC_obs_sigsetmask
 0x40c01bc      BSC_sigsuspend
-0x40c01c0      BSC_old_sigstack
-0x40c01c4      BSC_old_recvmsg
-0x40c01c8      BSC_old_sendmsg
-0x40c01cc      BSC_obs_vtrace
+0x40c01c0      BSC_obs_sigstack
+0x40c01c4      BSC_obs_recvmsg
+0x40c01c8      BSC_obs_sendmsg
+0x40c01cc      BSC_#115
 0x40c01d0      BSC_gettimeofday
 0x40c01d4      BSC_getrusage
 0x40c01d8      BSC_getsockopt
 0x40c01e8      BSC_settimeofday
 0x40c01ec      BSC_fchown
 0x40c01f0      BSC_fchmod
-0x40c01f4      BSC_old_recvfrom
-0x40c01f8      BSC_old_setreuid
-0x40c01fc      BSC_old_setregid
+0x40c01f4      BSC_obs_recvfrom
+0x40c01f8      BSC_obs_setreuid
+0x40c01fc      BSC_obs_setregid
 0x40c0200      BSC_rename
-0x40c0204      BSC_old_truncate
-0x40c0208      BSC_old_ftruncate
+0x40c0204      BSC_obs_truncate
+0x40c0208      BSC_obs_ftruncate
 0x40c020c      BSC_flock
 0x40c0210      BSC_mkfifo
 0x40c0214      BSC_sendto
 0x40c0220      BSC_mkdir
 0x40c0224      BSC_rmdir
 0x40c0228      BSC_utimes
-0x40c022c      BSC_#139
+0x40c022c      BSC_futimes
 0x40c0230      BSC_adjtime
-0x40c0234      BSC_old_getpeername
-0x40c0238      BSC_old_gethostid
-0x40c023c      BSC_old_sethostid
-0x40c0240      BSC_old_getrlimit
-0x40c0244      BSC_old_setrlimit
-0x40c0248      BSC_old_killpg
+0x40c0234      BSC_obs_getpeername
+0x40c0238      BSC_obs_gethostid
+0x40c023c      BSC_#143
+0x40c0240      BSC_obs_getrlimit
+0x40c0244      BSC_obs_setrlimit
+0x40c0248      BSC_obs_killpg
 0x40c024c      BSC_setsid
-0x40c0250      BSC_obs_setquota
-0x40c0254      BSC_obs_quota
-0x40c0258      BSC_old_getsockname
-0x40c025c      BSC_#151
+0x40c0250      BSC_#148
+0x40c0254      BSC_#149
+0x40c0258      BSC_obs_getsockname
+0x40c025c      BSC_getpgid
 0x40c0260      BSC_setprivexec
-0x40c0264      BSC_#153
-0x40c0268      BSC_#154
+0x40c0264      BSC_pread
+0x40c0268      BSC_pwrite
 0x40c026c      BSC_nfssvc
 0x40c0270      BSC_getdirentries
 0x40c0274      BSC_statfs
 0x40c0278      BSC_fstatfs
 0x40c027c      BSC_unmount
-0x40c0280      BSC_obs_async_daemon
+0x40c0280      BSC_#160
 0x40c0284      BSC_getfh
-0x40c0288      BSC_old_getdomainname
-0x40c028c      BSC_old_setdomainname
-0x40c0290      BSC_obs_pcfs_mount
+0x40c0288      BSC_obs_getdomainname
+0x40c028c      BSC_obs_setdomainname
+0x40c0290      BSC_#164
 0x40c0294      BSC_quotactl
-0x40c0298      BSC_obs_exportfs
+0x40c0298      BSC_#166
 0x40c029c      BSC_mount
-0x40c02a0      BSC_obs_ustat
+0x40c02a0      BSC_#168
 0x40c02a4      BSC_#169
-0x40c02a8      BSC_obs_table
-0x40c02ac      BSC_old_wait_3
-0x40c02b0      BSC_obs_rpause
+0x40c02a8      BSC_#170
+0x40c02ac      BSC_obs_wait3
+0x40c02b0      BSC_#172
 0x40c02b4      BSC_#173
-0x40c02b8      BSC_obs_getdents
+0x40c02b8      BSC_#174
 0x40c02bc      BSC_#175
 0x40c02c0      BSC_add_profil
 0x40c02c4      BSC_#177
 0x40c02c8      BSC_#178
 0x40c02cc      BSC_#179
-0x40c02d0      BSC_kdebug
+0x40c02d0      BSC_kdebug_trace
 0x40c02d4      BSC_setgid
 0x40c02d8      BSC_setegid
 0x40c02dc      BSC_seteuid
-0x40c02e0      BSC_lfs_bmapv
-0x40c02e4      BSC_lfs_markv
-0x40c02e8      BSC_lfs_segclean
-0x40c02ec      BSC_lfs_segwait
+0x40c02e0      BSC_#184
+0x40c02e4      BSC_#185
+0x40c02e8      BSC_#186
+0x40c02ec      BSC_#187
 0x40c02f0      BSC_stat
 0x40c02f4      BSC_fstat
 0x40c02f8      BSC_lstat
 0x40c02fc      BSC_pathconf
 0x40c0300      BSC_fpathconf
-0x40c0304      BSC_getfsstat
+0x40c0304      BSC_obs_getfsstat
 0x40c0308      BSC_getrlimit
 0x40c030c      BSC_setrlimit
 0x40c0310      BSC_getdirentries
 0x40c0314      BSC_mmap
-0x40c0318      BSC___syscall
+0x40c0318      BSC_#198
 0x40c031c      BSC_lseek
 0x40c0320      BSC_truncate
 0x40c0324      BSC_ftruncate
 0x40c0354      BSC_#213
 0x40c0358      BSC_#214
 0x40c035c      BSC_#215
-0x40c0360      BSC_mkcomplex
-0x40c0364      BSC_statv
-0x40c0368      BSC_lstatv
-0x40c036c      BSC_fstatv
+0x40c0360      BSC_#216
+0x40c0364      BSC_#217
+0x40c0368      BSC_#218
+0x40c036c      BSC_#219
 0x40c0370      BSC_getattrlist
 0x40c0374      BSC_setattrlist
 0x40c0378      BSC_getdirentriesattr
 0x40c037c      BSC_exchangedata
 0x40c0380      BSC_checkuseraccess
 0x40c0384      BSC_searchfs
-0x40c0388      BSC_#226
-0x40c038c      BSC_#227
+0x40c0388      BSC_delete
+0x40c038c      BSC_copyfile
 0x40c0390      BSC_#228
 0x40c0394      BSC_#229
 0x40c0398      BSC_#230
 0x40c03bc      BSC_#239
 0x40c03c0      BSC_#240
 0x40c03c4      BSC_#241
-0x40c03c8      BSC_#242
+0x40c03c8      BSC_fsctl
 0x40c03cc      BSC_#243
 0x40c03d0      BSC_#244
 0x40c03d4      BSC_#245
 0x40c049c      BSC_#295
 0x40c04a0      BSC_load_shared_file
 0x40c04a4      BSC_reset_shared_file
-0x40c04a8      BSC_#298
+0x40c04a8      BSC_new_system_shared_regions
 0x40c04ac      BSC_#299
 0x40c04b0      BSC_#300
 0x40c04b4      BSC_#301
 0x40c04cc      BSC_#307
 0x40c04d0      BSC_#308
 0x40c04d4      BSC_#309
-0x40c04d8      BSC_#310
+0x40c04d8      BSC_getsid
 0x40c04dc      BSC_#311
 0x40c04e0      BSC_#312
 0x40c04e4      BSC_#313
 0x40c050c      BSC_#323
 0x40c0510      BSC_mlockall
 0x40c0514      BSC_munlockall
+0x40c0518      BSC_#326
+0x40c051c      BSC_issetugid
+0x40c0520      BSC_pthread_kill
+0x40c0524      BSC_pthread_sigmask
+0x40c0528      BSC_sigwait
+0x40c052c      BSC_#331
+0x40c0530      BSC_#332
+0x40c0534      BSC_#333
+0x40c0538      BSC_#334
+0x40c053c      BSC_utrace
+0x40c0540      BSC_#336
+0x40c0544      BSC_#337
+0x40c0548      BSC_#338
+0x40c054c      BSC_#339
+0x40c0550      BSC_#340
+0x40c0554      BSC_#341
+0x40c0558      BSC_#342
+0x40c055c      BSC_#343
+0x40c0560      BSC_#344
+0x40c0564      BSC_#345
+0x40c0568      BSC_#346
+0x40c056c      BSC_#347
+0x40c0570      BSC_#348
+0x40c0574      BSC_#349
 0x50b0018      IES_action
 0x50b001c      IES_filter
 0x50c0010      TES_action
index 70b747fd5435a8d12cfd99aac7d73f59e40f0edb..f5f7c67e2f307cb273fbef35990904aee6e49b9d 100644 (file)
 # Makefile API), which are rules that get invoked before and after the install 
 # target runs.  Such rules should be specified with the '::' syntax rather than 
 # a single colon.
+
+after_install:
+       mkdir -p "$(DSTROOT)/usr/share/man/man8"
+       install -c -m 644 sysctl.8 "$(DSTROOT)/usr/share/man/man8/sysctl.8"
index e371f9d2d21d092e96afbfdc108e52ceff94a880..3a44cfd39a0ec8771a7f1e8e0c00fd054cff50de 100644 (file)
@@ -111,3 +111,4 @@ OTHER_HELP_DIRS =
 # $(NAME).%d[.%d][.%d] and the following line must be uncommented.
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
 
+AFTER_INSTALL = after_install
index bc348a9d905176f8504ce8c2944a215c6727d73d..b5151c1c906e890c70d91783d958196208e63240 100644 (file)
@@ -93,7 +93,7 @@ purpose programs such as
 .Nm systat ,
 and
 .Nm netstat .
-The string and integer information is summaried below.
+The string and integer information is summarized below.
 For a detailed description of these variable see
 .Xr sysctl 3 .
 The changeable column indicates whether a process with appropriate
index fb0dbb4be12e198cf2c98aed22a2b9de30ca5f38..b1b8e7523758f0fc44207a85261f1bd1b2ae21f5 100644 (file)
@@ -346,6 +346,7 @@ old_parse(string, flags)
                break;
 
        case CTL_HW:
+               useUnsignedInt = 1;
                break;
 
        case CTL_VM:
@@ -887,10 +888,11 @@ oidfmt(int *oid, int len, char *fmt, u_int *kind)
 static int
 show_var(int *oid, int nlen)
 {
-       u_char buf[BUFSIZ], *val, *p;
+       u_char buf[BUFSIZ], *val, *mval, *p;
        char name[BUFSIZ], /* descr[BUFSIZ], */ *fmt;
        int qoid[CTL_MAXNAME+2];
        int i;
+       int retval;
        size_t j, len;
        u_int kind;
        int (*func)(int, void *) = 0;
@@ -909,15 +911,18 @@ show_var(int *oid, int nlen)
        i = sysctl(oid, nlen, 0, &j, 0, 0);
        j += j; /* we want to be sure :-) */
 
-       val = alloca(j);
+       val = mval = malloc(j);
        len = j;
        i = sysctl(oid, nlen, val, &len, 0, 0);
-       if (i || !len)
-               return (1);
+       if (i || !len) {
+               retval = 1;
+               goto RETURN;
+       }
 
        if (bflag) {
                fwrite(val, 1, len, stdout);
-               return (0);
+               retval = 0;
+               goto RETURN;
        }
 
        qoid[1] = 4;
@@ -936,7 +941,8 @@ show_var(int *oid, int nlen)
                if (!nflag)
                        printf("%s: ", name);
                printf("%s", p);
-               return (0);
+               retval = 0;
+               goto RETURN;
                
        case 'I':
                if (!nflag)
@@ -952,7 +958,8 @@ show_var(int *oid, int nlen)
                        len -= sizeof (int);
                        p += sizeof (int);
                }
-               return (0);
+               retval = 0;
+               goto RETURN;
 
        case 'L':
                if (!nflag)
@@ -968,13 +975,15 @@ show_var(int *oid, int nlen)
                        len -= sizeof (long);
                        p += sizeof (long);
                }
-               return (0);
+               retval = 0;
+               goto RETURN;
 
        case 'P':
                if (!nflag)
                        printf("%s: ", name);
                printf("%p", *(void **)p);
-               return (0);
+               retval = 0;
+               goto RETURN;
 
        case 'T':
        case 'S':
@@ -986,12 +995,15 @@ show_var(int *oid, int nlen)
                if (func) {
                        if (!nflag)
                                printf("%s: ", name);
-                       return ((*func)(len, p));
+                       retval = (*func)(len, p);
+                       goto RETURN;
                }
                /* FALL THROUGH */
        default:
-               if (!Aflag)
-                       return (1);
+               if (!Aflag) {
+                       retval = 1;
+                       goto RETURN;
+               }
                if (!nflag)
                        printf("%s: ", name);
                printf("Format:%s Length:%ld Dump:0x", fmt, len);
@@ -1002,9 +1014,14 @@ show_var(int *oid, int nlen)
                        printf("...");
                        break;
                }
-               return (0);
+               retval = 0;
+               goto RETURN;
        }
-       return (1);
+
+       retval = 1;
+       RETURN:
+       free(mval);
+       return (retval);
 }
 
 static int
index aa6611699bd5a40527f7a794ef9d686ac7b28241..b9c6003addb41f38872e6070206b53337bc4ff20 100644 (file)
@@ -23,7 +23,7 @@ MAKEFILE = tool.make
 NEXTSTEP_INSTALLDIR = /usr/bin
 WINDOWS_INSTALLDIR = /Library/Executables
 PDO_UNIX_INSTALLDIR = /usr/bin
-LIBS = 
+LIBS = -lcurses
 DEBUG_LIBS = $(LIBS)
 PROF_LIBS = $(LIBS)
 
index d4dd62809d7082eeb4eee1abf2c8a55117908fb5..f1755f123669726f02a5e48b85218c8e9d5a2ee4 100644 (file)
@@ -69,6 +69,7 @@
 #include <mach/vm_map.h>
 #include <mach/vm_types.h>
 #include <mach/vm_prot.h>
+#include <mach/shared_memory_server.h>
 
 #include <device/device_types.h>
 #include <CoreFoundation/CoreFoundation.h>
@@ -82,7 +83,8 @@
 
 #include <libc.h>
 #include <termios.h>
-#include <bsd/curses.h>
+#include <curses.h>
+#include <sys/ioctl.h>
 
 /* Number of lines of header information on the standard screen */
 #define        HEADER_LINES    8
@@ -120,7 +122,6 @@ int werase(WINDOW *win);
 int total_threads;
 unsigned long long total_fw_private;
 
-struct termios tmode, omode;
 char   bytesread[128];
 
 host_cpu_load_info_data_t lastcounters, curcounters, startcounters;
@@ -228,10 +229,6 @@ struct object_info      *shared_hash_table[OBJECT_TABLE_SIZE];
 
 struct object_info *of_free_list = 0;
 
-#define FW_CODE_BEG_ADDR  0x70000000
-#define FW_DATA_BEG_ADDR  0x80000000
-#define FW_DATA_END_ADDR  0x90000000
-
 /*
  *     Translate thread state to a number in an ordered scale.
  *     When collapsing all the threads' states to one for the
@@ -451,7 +448,7 @@ pmem_doit(task_port_t task, int pid, int *shared, int *private, int *aliased, in
                                    &count, &object_name))
                        break;
 
-               if (address >= FW_CODE_BEG_ADDR && address < FW_DATA_END_ADDR) {
+               if (address >= GLOBAL_SHARED_TEXT_SEGMENT && address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
 
                        *fw_private += info.private_pages_resident * vm_page_size;
 
@@ -529,13 +526,13 @@ pmem_doit(task_port_t task, int pid, int *shared, int *private, int *aliased, in
                }
        }
        if (split)
-               *vsize -= (FW_DATA_END_ADDR - FW_CODE_BEG_ADDR);
+               *vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
 }
 
 
 void
 pmem_fw_resident(unsigned int *num_fw, unsigned long long *vsize, unsigned int *code_size, unsigned int *data_size, unsigned int *linkedit_size)
-{       vm_address_t   address = FW_CODE_BEG_ADDR;
+{       vm_address_t   address = GLOBAL_SHARED_TEXT_SEGMENT;
        kern_return_t   err = 0;
        int             state = 0;
 
@@ -545,7 +542,7 @@ pmem_fw_resident(unsigned int *num_fw, unsigned long long *vsize, unsigned int *
         *data_size = 0;
         *linkedit_size = 0;
 
-       while (address < FW_DATA_END_ADDR) {
+       while (address < (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE)) {
                vm_region_submap_info_data_64_t   s_info;
                mach_msg_type_number_t         count;
                vm_size_t       size;
@@ -557,9 +554,9 @@ pmem_fw_resident(unsigned int *num_fw, unsigned long long *vsize, unsigned int *
                if (err = vm_region_recurse_64(mach_task_self(), &address, &size, &nesting_depth, (vm_region_info_t)&s_info, &count))
                        break;
 
-               if (address >= FW_DATA_END_ADDR)
+               if (address >= (GLOBAL_SHARED_DATA_SEGMENT + SHARED_DATA_REGION_SIZE))
                        break;
-               if (address < FW_DATA_BEG_ADDR) {
+               if (address < GLOBAL_SHARED_DATA_SEGMENT) {
 
                        if (s_info.share_mode == SM_SHARED || s_info.share_mode == SM_COW) {
                                if (s_info.max_protection & VM_PROT_EXECUTE) {
@@ -884,8 +881,6 @@ void leave()                        /* exit under normal conditions -- INT handler */
                move(LINES - 1, 0);
                refresh();
                endwin();
-
-               tcsetattr(0, TCSANOW, &omode);
        }
        exit(0);
 }
@@ -893,10 +888,8 @@ void leave()                       /* exit under normal conditions -- INT handler */
 void quit(status)              /* exit under duress */
        int status;
 {
-        if (!oneshot) {
+        if (!oneshot)
                endwin();
-               tcsetattr(0, TCSANOW, &omode);
-       }
        exit(status);
 }
 
@@ -1313,22 +1306,10 @@ main(argc, argv)
        /* initializes curses and screen (last) */
 
        if (!oneshot) {
-               if (tcgetattr(0, &tmode) < 0) {
-                       printf("can't get terminal attributes\n");
-                       exit(1);
-               }
-               omode = tmode;
-       
-               tmode.c_lflag &= ~ICANON;
-               tmode.c_cc[VMIN] = 0;
-               tmode.c_cc[VTIME] = (delay * 10);
-
-               if (tcsetattr(0, TCSANOW, &tmode) < 0) {
-                       printf("can't set terminal attributes\n");
-                       exit(1);
-               }
                initscr();
-               refresh();
+               cbreak();
+               timeout(delay * 1000);
+               noecho();
                erase();
                clear();
                refresh();
@@ -1387,12 +1368,16 @@ main(argc, argv)
                int   n;
 
                if (newLINES) {
+                       newLINES = 0;
 
                        if (!oneshot) {
-                               initscr();
-                               erase();
-                               clear();
-                               refresh();
+                               struct winsize size;
+
+                               if (ioctl(1, TIOCGWINSZ, &size) != -1) {
+                                       resizeterm(size.ws_row, size.ws_col);
+                                       erase();
+                                       clear();
+                               }
                        }
                        n = LINES - Header_lines;
 
@@ -1408,19 +1393,14 @@ main(argc, argv)
                                                topn = n;
                                }
                        }
-                       newLINES = 0;
                }
                (void)screen_update();
 
                if (!oneshot) {
+                       int     c;
 
-                       if ((n = read(0, &bytesread, 128)) > 0) {
-                               int   i;
-
-                               for (i = 0; i < n; i++)
-                                       if (bytesread[i] == 'q')
-                                               leave();
-                       }
+                       if ((c = getch()) != ERR && (char)c == 'q') 
+                               leave();
                } else
                        sleep(delay);
        }
@@ -2241,11 +2221,12 @@ getDISKcounters()
                                                             (CFMutableDictionaryRef *) &properties,
                                                            kCFAllocatorDefault,
                                                            kNilOptions);
+                if (properties) {
 
-               /* Obtain the statistics from the drive properties */
-               statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
+                    /* Obtain the statistics from the drive properties */
+                    statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
 
-               if (statistics) {
+                    if (statistics) {
                        /* Obtain the number of bytes read from the drive statistics */
                        number = (CFNumberRef) CFDictionaryGetValue (statistics,
                                                                     CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
@@ -2275,10 +2256,11 @@ getDISKcounters()
                                status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
                                totalWriteBytes += value;
                        }
-               }
-               /* Release resources */
+                    }
+                    /* Release resources */
 
-               CFRelease(properties); properties = 0;
+                    CFRelease(properties); properties = 0;
+                }
                IOObjectRelease(drive); drive = 0;
        }
        IOIteratorReset(drivelist);
index 70b747fd5435a8d12cfd99aac7d73f59e40f0edb..0e581847df0289b3bdcb99a4b812999ee2eee121 100644 (file)
 # Makefile API), which are rules that get invoked before and after the install 
 # target runs.  Such rules should be specified with the '::' syntax rather than 
 # a single colon.
+
+after_install:
+       mkdir -p "$(DSTROOT)/usr/share/man/man8"
+       install -c -m 644 update.8 "$(DSTROOT)/usr/share/man/man8/update.8"
index e371f9d2d21d092e96afbfdc108e52ceff94a880..3a44cfd39a0ec8771a7f1e8e0c00fd054cff50de 100644 (file)
@@ -111,3 +111,4 @@ OTHER_HELP_DIRS =
 # $(NAME).%d[.%d][.%d] and the following line must be uncommented.
 OTHER_GENERATED_OFILES = $(VERS_OFILE)
 
+AFTER_INSTALL = after_install
index 4b21a74f193dffe837cd9cfb87a58ef5c5b40525..943af742339d43d366ab6727638d3f4aa82ccc5f 100644 (file)
@@ -15,7 +15,7 @@ PROJECT_TYPE = Tool
 CFILES = vm_stat.c
 
 OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
-            h.template
+            h.template vm_stat.1
 
 
 MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
index 411cde671ba3609c8e79214db2e6e92b9dffb667..ee7c567726ee79981c68e75ca9f565e62737be55 100644 (file)
@@ -98,3 +98,6 @@
 # owned by the top-level Makefile API and no context has been set up for where 
 # derived files should go.
 #
+after_install:
+       install -d $(DSTROOT)/usr/share/man/man1
+       install -c -m 444 vm_stat.1 $(DSTROOT)/usr/share/man/man1
diff --git a/vm_stat.tproj/vm_stat.1 b/vm_stat.tproj/vm_stat.1
new file mode 100644 (file)
index 0000000..4ce6212
--- /dev/null
@@ -0,0 +1,60 @@
+.\" Copyright (c) 1997, Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd August 13, 1997
+.Dt VM_STAT 1
+.Os Mac OS X
+.Sh NAME
+.Nm vm_stat
+.Nd show Mach virtual memory statistics
+.Sh SYNOPSIS
+.Nm vm_stat
+.Op Ar interval
+.Sh DESCRIPTION
+.Nm vm_stat 
+displays Mach virtual memory statistics.  If the optional 
+.Ar interval 
+is specified, then 
+.Nm vm_stat 
+will display the statistics every 
+.Ar interval 
+seconds.  In this case, each line of output displays the change in
+each statistic (an
+.Ar interval 
+count of 1 displays the values per second).  However, the first line
+of output following each banner displays the system-wide totals for
+each statistic.  The following values are displayed:
+.Bl -tag -width indent -compact
+.It Pages free
+the total number of free pages in the system.
+.It Pages active
+the total number of pages currently in use and pageable.
+.It Pages inactive
+the total number of pages on the inactive list.
+.It Pages wired down
+the total number of pages wired down.  That is, pages that cannot be
+paged out.
+.It Translation faults
+the number of times the "vm_fault" routine has been called.
+.It Pages copy-on-write
+the number of faults that caused a page to be
+copied (generally caused by copy-on-write faults).
+.It Pages zero filled
+the total number of pages that have been zero-filled on demand.
+.It Pages reactivated
+the total number of pages that have been moved from the inactive list
+to the active list (reactivated).
+.It Pageins
+the number of requests for pages from a pager (such as the inode pager).
+.It Pageouts
+the number of pages that have been paged out.
+.Pp
+If 
+.Ar interval 
+is not specified, then 
+.Nm vm_stat 
+displays all accumulated statistics along with the page size and the
+object cache performance.
+
+
+.Sh SEE ALSO
+.Xr vm_statistics 2
index 7ffb1d8e28afd09b3260c5f56595d5dd9ebd376e..1edb43c253f31b4bb24274c013bda6e9b39f8536 100644 (file)
Binary files a/zic.tproj/HACK/CST6CDT and b/zic.tproj/HACK/CST6CDT differ
index 50fd5db0cc033c5d2c0037a9bae450e6d70c2cb3..d3350e326520a1e23b4f55a1341a0602ea973e13 100644 (file)
Binary files a/zic.tproj/HACK/Cuba and b/zic.tproj/HACK/Cuba differ
index 3961e6565c64ad60c80755558524f8e3d97afdf9..2d5f332abb11a2e8ec1a44e68184c80a5884f451 100644 (file)
Binary files a/zic.tproj/HACK/EST and b/zic.tproj/HACK/EST differ
index 2ddcd429597596a11eec0ed36090b472b3171347..46d19f7304b485b2d4a970bec68c93ffe0ffc958 100644 (file)
Binary files a/zic.tproj/HACK/EST5EDT and b/zic.tproj/HACK/EST5EDT differ
index a084b0ab5346086537b634042275545401bc7ecf..6e3d7bf229b54dcbdc7f030ea5e941225020c879 100644 (file)
Binary files a/zic.tproj/HACK/Egypt and b/zic.tproj/HACK/Egypt differ
index fab6a199383b6d18fd92633f7831c835c51dd4ea..6b51dd87c6f9705d6b43491406c025d623fea543 100644 (file)
Binary files a/zic.tproj/HACK/Eire and b/zic.tproj/HACK/Eire differ
index bc3e2e4d514869e0321729592888d1f8d0be92da..1be7c8e9a543c9953d51f194cbc9570d7e2344cb 100644 (file)
Binary files a/zic.tproj/HACK/Factory and b/zic.tproj/HACK/Factory differ
index 47e56ddbe7b81d8353d090d1d0b58f4a7cf753ea..3e79673e1959836862d20e508a9068bbac207866 100644 (file)
Binary files a/zic.tproj/HACK/HST and b/zic.tproj/HACK/HST differ
index ad523a5a9577ae685702558312a5606670ab55b9..5f788c84f7671c72d4a69fd1267a1266dc88a6eb 100644 (file)
Binary files a/zic.tproj/HACK/Hongkong and b/zic.tproj/HACK/Hongkong differ
index b604803358821b60e26c76234abb3cc1e8c786e6..08c0c58a98c20fbb29a604b89121cb6a8672b6f4 100644 (file)
Binary files a/zic.tproj/HACK/Israel and b/zic.tproj/HACK/Israel differ
index a77982e0a8c1993d144c1d8b1bdd8ea0fa8f094d..64be57cf3e652d96aeea5caee79fe1a2ad47b96d 100644 (file)
Binary files a/zic.tproj/HACK/Jamaica and b/zic.tproj/HACK/Jamaica differ
index 5494fd200649d381afc02b94a00f3222878a38bf..6d77fe83a016fd07bcf04ff27156342ad9eceb64 100644 (file)
Binary files a/zic.tproj/HACK/Japan and b/zic.tproj/HACK/Japan differ
index 4ca7448f9478c520b13b7556687cec0c36427559..865e083e61b0b24d17abf938c9b7682b765a7aa3 100644 (file)
Binary files a/zic.tproj/HACK/Libya and b/zic.tproj/HACK/Libya differ
index d684fb39956e69e6b7c1d5eb98391c0d965328e4..7dc48caa5cc055ddbdaa4f8ce6254fa25581d991 100644 (file)
Binary files a/zic.tproj/HACK/MST and b/zic.tproj/HACK/MST differ
index fc45907a08f34a2225e5557f3083d2dad235602d..889d6f05389dbc179b745aed8c6a4d438ba5553d 100644 (file)
Binary files a/zic.tproj/HACK/MST7MDT and b/zic.tproj/HACK/MST7MDT differ
index fc45907a08f34a2225e5557f3083d2dad235602d..889d6f05389dbc179b745aed8c6a4d438ba5553d 100644 (file)
Binary files a/zic.tproj/HACK/Navajo and b/zic.tproj/HACK/Navajo differ
index 458d9b7a0d7e026019bd911d8f536545252f29e2..c9ccbc1714b240e525e2e7ddbe8ae785e7831487 100644 (file)
Binary files a/zic.tproj/HACK/PST8PDT and b/zic.tproj/HACK/PST8PDT differ
index c6ea4cd6bc64dc8586337531473337704f00fcc3..7fda6e6be233bb32ae3e8526f3f503f934e478c2 100644 (file)
Binary files a/zic.tproj/HACK/Poland and b/zic.tproj/HACK/Poland differ
index 84933f9aa3779995ac86991c089221bbbd0d9665..340fc401f7b1d391bcd9b343a25d556fec0fefa7 100644 (file)
Binary files a/zic.tproj/HACK/Portugal and b/zic.tproj/HACK/Portugal differ
index af292f7decb8dad7e80cef99fd42cebee0dbac28..38651468ac9724fa40287d4492995762de4313ae 100644 (file)
Binary files a/zic.tproj/HACK/W-SU and b/zic.tproj/HACK/W-SU differ
index 4db6c70ec50240f3ff9dd119330179e7bdc0a198..ead4ca77adf921bbd66d3bf9e0f53e64ea2007c3 100644 (file)
@@ -191,10 +191,16 @@ right_posix: right_only other_two
 #      ln -s ${TZDIR}/${LOCALTIME} ${DSTROOT}/etc/localtime
 
 #since we are not doing native builds ... hack hack hack
+
+ZONE_FILES = africa antarctica asia australasia europe northamerica southamerica pacificnew etcetera factory backward systemv solar87 solar88 solar89
+
 after_install::
        -mkdir -p ${DSTROOT}/usr/share
        -rm -rf ${DSTROOT}/usr/share/zoneinfo
-       cp -r HACK ${DSTROOT}/usr/share/zoneinfo
+       mkdir -p ${DSTROOT}/usr/share/zoneinfo
+       for tz in $(ZONE_FILES); do \
+               zic -L /dev/null -d ${DSTROOT}/usr/share/zoneinfo -y datfiles/yearistype.sh datfiles/$${tz}; \
+       done
        chmod -R og-w ${DSTROOT}/usr/share/zoneinfo
        -mkdir -p ${DSTROOT}/private/etc
        -rm -f ${DSTROOT}/private/etc/localtime
index 1a601c9ce929fee3dcb687b3689668730955f486..6ce6106d85e867fb102fcfd094fad66596233613 100644 (file)
@@ -1,17 +1,18 @@
-#      $OpenBSD: africa,v 1.4 1997/01/14 04:36:47 millert Exp $
-# @(#)africa   7.16
+# @(#)africa   7.34
+
+# $FreeBSD: src/share/zoneinfo/africa,v 1.12 2000/10/25 19:36:48 wollman Exp $
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
 # tz@elsie.nci.nih.gov for general use in the future).
 
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# From Paul Eggert <eggert@twinsun.com> (1999-03-22):
 #
 # A good source for time zone historical data outside the U.S. is
-# Thomas G. Shanks, The International Atlas (3rd edition),
-# San Diego: ACS Publications, Inc. (1991).
+# Thomas G. Shanks, The International Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1999).
 #
-# Gwillim Law <LAW@encmail.encompass.com> writes that a good source
+# Gwillim Law <Gwil_Law@bridge-point.com> writes that a good source
 # for recent time zone data is the International Air Transport
 # Association's Standard Schedules Information Manual (IATA SSIM),
 # published semiannually.  Law sent in several helpful summaries
 # I found in the UCLA library.
 #
 # A reliable and entertaining source about time zones is
-# Derek Howse, Greenwich time and the discovery of the longitude,
-# Oxford University Press (1980).
-#
-# I added so many Zone names that the old, mostly flat name space was unwieldy.
-# So I renamed the Zones to have the form AREA/LOCATION, where
-# AREA is the name of a continent or ocean, and
-# LOCATION is the name of a specific location within that region.
-# For example, the old zone name `Egypt' is now `Africa/Cairo'.
-#
-# Here are the general rules I used for choosing location names,
-# in decreasing order of importance:
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-#      Use only valid Posix file names.  Use only Ascii letters, digits, `.',
-#              `-' and `_'.  Do not exceed 14 characters or start with `-'.
-#              E.g. prefer `Brunei' to `Bandar_Seri_Begawan'.
-#      Include at least one location per time zone rule set per country.
-#              One such location is enough.
-#      If all the clocks in a country's region have agreed since 1970,
-#              don't bother to include more than one location
-#              even if subregions' clocks disagreed before 1970.
-#              Otherwise these tables would become annoyingly large.
-#      If a name is ambiguous, use a less ambiguous alternative;
-#              e.g. many cities are named San Jose and Georgetown, so
-#              prefer `Costa_Rica' to `San_Jose' and `Guyana' to `Georgetown'.
-#      Keep locations compact.  Use cities or small islands, not countries
-#              or regions, so that any future time zone changes do not split
-#              locations into different time zones.  E.g. prefer `Paris'
-#              to `France', since France has had multiple time zones.
-#      Use traditional English spelling, e.g. prefer `Rome' to `Roma', and
-#              prefer `Athens' to the true name (which uses Greek letters).
-#              The Posix file name restrictions encourage this rule.
-#      Use the most populous among locations in a country's time zone,
-#              e.g. prefer `Shanghai' to `Beijing'.  Among locations with
-#              similar populations, pick the best-known location,
-#              e.g. prefer `Rome' to `Milan'.
-#      Use the singular form, e.g. prefer `Canary' to `Canaries'.
-#      Omit common suffixes like `_Islands' and `_City', unless that
-#              would lead to ambiguity.  E.g. prefer `Cayman' to
-#              `Cayman_Islands' and `Guatemala' to `Guatemala_City',
-#              but prefer `Mexico_City' to `Mexico' because the country
-#              of Mexico has several time zones.
-#      Use `_' to represent a space.
-#      Omit `.' from abbreviations in names, e.g. prefer `St_Helena'
-#              to `St._Helena'.
+# Previous editions of this database used WAT, CAT, SAT, and EAT
+# for +0:00 through +3:00, respectively,
+# but Mark R V Murray <markm@grondar.za> reports that
+# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
+# `CAT' is commonly used for +2:00 in countries north of South Africa, and
+# `WAT' is probably the best name for +1:00, as the common phrase for
+# the area that includes Nigeria is ``West Africa''.
+# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
 #
-# For time zone abbreviations like `EST' I used the following rules,
-# in decreasing order of importance:
+# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
+# I'd guess that this was because people needed _some_ name for -1:00,
+# and at the time, far west Africa was the only major land area in -1:00.
+# This usage is now obsolete, as the last use of -1:00 on the African
+# mainland seems to have been 1976 in Western Sahara.
 #
-#      Use abbreviations that consist of 3 or more upper-case Ascii letters,
-#              except use "___" for locations while uninhabited.
-#              Posix.1 requires at least 3 characters, and the restriction to
-#              upper-case Ascii letters follows most traditions.
-#              Previous editions of this database also used characters like
-#              ' ' and '?', but these characters have a special meaning to
-#              the shell and cause commands like
-#                      set `date`
-#              to have unexpected effects.  In theory, the character set could
-#              be !%./@A-Z^_a-z{}, but these tables use only upper-case
-#              Ascii letters (and "___").
-#      Use abbreviations that are in common use among English-speakers,
-#              e.g. `EST' for Eastern Standard Time in North America.
-#              We assume that applications translate them to other languages
-#              as part of the normal localization process; for example,
-#              a French application might translate `EST' to `HNE'.
-#      For zones whose times are taken from a city's longitude, use the
-#              traditional xMT notation, e.g. `PMT' for Paris Mean Time.
-#              The only name like this in current use is `GMT'.
-#      If there is no common English abbreviation, abbreviate the English
-#              translation of the usual phrase used by native speakers.
-#              If this is not available or is a phrase mentioning the country
-#              (e.g. ``Cape Verde Time''), then:
+# To summarize, the following abbreviations seem to have some currency:
+#      -1:00   WAT     West Africa Time (no longer used)
+#       0:00   GMT     Greenwich Mean Time
+#       2:00   CAT     Central Africa Time
+#       2:00   SAST    South Africa Standard Time
+# and Murray suggests the following abbreviation:
+#       1:00   WAT     West Africa Time
+# I realize that this leads to `WAT' being used for both -1:00 and 1:00
+# for times before 1976, but this is the best I can think of
+# until we get more information.
 #
-#              When a country has a single or principal time zone region,
-#                      append `T' to the country's ISO code, e.g. `CVT' for
-#                      Cape Verde Time.  For summer time append `ST';
-#                      for double summer time append `DST'; etc.
-#              When a country has multiple time zones, take the first three
-#                      letters of an English place name identifying each zone
-#                      and then append `T', `ST', etc. as before;
-#                      e.g. `MOSST' for MOScow Summer Time.
-#
-#
-# For Africa I invented the following time zone abbreviations.
-#              LMT     Local Mean Time
-#      -1:00   AAT     Atlantic Africa Time (no longer used)
-#       0:00   WAT     West Africa Time
-#       1:00   CAT     Central Africa Time
-#       2:00   SAT     South Africa Time
+# I invented the following abbreviations; corrections are welcome!
+#       2:00   WAST    West Africa Summer Time
+#       2:30   BEAT    British East Africa Time (no longer used)
+#       2:45   BEAUT   British East Africa Unified Time (no longer used)
+#       3:00   CAST    Central Africa Summer Time (no longer used)
+#       3:00   SAST    South Africa Summer Time (no longer used)
 #       3:00   EAT     East Africa Time
-# The final `T' is replaced by `ST' for summer time, e.g. `SAST'.
-# BEAT is British East Africa Time, which was 2:30 before 1948 and 2:45 after.
-
+#       4:00   EAST    East Africa Summer Time (no longer used)
 
 # Algeria
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -159,40 +104,37 @@ Zone      Africa/Algiers  0:12:12 -       LMT     1891 Mar 15 0:01
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Luanda   0:52:56 -       LMT     1892
                        0:52:04 -       LMT     1911 May 26 # Luanda Mean Time?
-                       1:00    -       CAT
-
-# Bassas da India
-# uninhabited
+                       1:00    -       WAT
 
 # Benin
 # Whitman says they switched to 1:00 in 1946, not 1934; go with Shanks.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Porto-Novo 0:10:28 -       LMT     1912
-                       0:00    -       WAT     1934 Feb 26
-                       1:00    -       CAT
+                       0:00    -       GMT     1934 Feb 26
+                       1:00    -       WAT
 
 # Botswana
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Gaborone 1:43:40 -       LMT     1885
-                       2:00    -       SAT     1943 Sep 19 2:00
-                       2:00    1:00    SAST    1944 Mar 19 2:00
-                       2:00    -       SAT
+                       2:00    -       CAT     1943 Sep 19 2:00
+                       2:00    1:00    CAST    1944 Mar 19 2:00
+                       2:00    -       CAT
 
 # Burkina Faso
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Ouagadougou        -0:06:04 -      LMT     1912
-                        0:00   -       WAT
+                        0:00   -       GMT
 
 # Burundi
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Bujumbura  1:57:28 -       LMT     1890
-                       2:00    -       SAT
+                       2:00    -       CAT
 
 # Cameroon
 # Whitman says they switched to 1:00 in 1920; go with Shanks.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Douala   0:38:48 -       LMT     1912
-                       1:00    -       CAT
+                       1:00    -       WAT
 
 # Cape Verde
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -205,29 +147,36 @@ Zone Atlantic/Cape_Verde -1:34:04 -       LMT     1907                    # Praia
 # Central African Republic
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Bangui   1:14:20 -       LMT     1912
-                       1:00    -       CAT
+                       1:00    -       WAT
 
 # Chad
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Ndjamena 1:00:12 -       LMT     1912
-                       1:00    -       CAT     1979 Oct 14
-                       1:00    1:00    CAST    1980 Mar  8
-                       1:00    -       CAT
+                       1:00    -       WAT     1979 Oct 14
+                       1:00    1:00    WAST    1980 Mar  8
+                       1:00    -       WAT
 
 # Comoros
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Indian/Comoro   2:53:04 -       LMT     1911 Jul   # Moroni, Gran Comoro
                        3:00    -       EAT
 
-# Congo
+# Democratic Republic of Congo
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Kinshasa   1:01:12 -       LMT     1897 Nov 9
+                       1:00    -       WAT
+Zone Africa/Lubumbashi 1:49:52 -       LMT     1897 Nov 9
+                       2:00    -       CAT
+
+# Republic of the Congo
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Brazzaville        1:01:08 -       LMT     1912
-                       1:00    -       CAT
+                       1:00    -       WAT
 
 # Cote D'Ivoire
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Abidjan  -0:16:08 -      LMT     1912
-                        0:00   -       WAT
+                        0:00   -       GMT
 
 # Djibouti
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -238,18 +187,6 @@ Zone       Africa/Djibouti 2:52:36 -       LMT     1911 Jul
 
 # Egypt
 
-# From Bob Devine (1988-01-28):
-# Egypt: DST from first day of May to first of October (ending may
-# also be on Sept 30th not 31st -- you might want to ask one of the
-# soc.* groups, you might hit someone who could ask an embassy).
-# DST since 1960 except for 1981-82.
-
-# From U. S. Naval Observatory (1989-01-19):
-# EGYPT               2 H  AHEAD OF UTC
-# EGYPT               3 H  AHEAD OF UTC  MAY 17 - SEP 30 (AFTER
-# EGYPT                                  RAMADAN)
-
-# From Shanks (1991):
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Egypt   1940    only    -       Jul     15      0:00    1:00    S
 Rule   Egypt   1940    only    -       Oct      1      0:00    0       -
@@ -264,16 +201,16 @@ Rule      Egypt   1957    1958    -       Oct      1      0:00    0       -
 Rule   Egypt   1958    only    -       May      1      0:00    1:00    S
 Rule   Egypt   1959    1981    -       May      1      1:00    1:00    S
 Rule   Egypt   1959    1965    -       Sep     30      3:00    0       -
-Rule   Egypt   1966    1990    -       Oct      1      3:00    0       -
+Rule   Egypt   1966    1994    -       Oct      1      3:00    0       -
 Rule   Egypt   1982    only    -       Jul     25      1:00    1:00    S
 Rule   Egypt   1983    only    -       Jul     12      1:00    1:00    S
 Rule   Egypt   1984    1988    -       May      1      1:00    1:00    S
 Rule   Egypt   1989    only    -       May      6      1:00    1:00    S
-Rule   Egypt   1990    only    -       May      1      1:00    1:00    S
-Rule   Egypt   1991    1994    -       May      1      0:00    1:00    S
-Rule   Egypt   1991    1994    -       Oct      1      0:00    0       -
-Rule   Egypt   1995    max     -       Apr     lastFri 0:00    1:00    S
-Rule   Egypt   1995    max     -       Sep     lastFri 0:00    0       -
+Rule   Egypt   1990    1994    -       May      1      1:00    1:00    S
+# IATA (after 1990) says transitions are at 0:00.
+# Go with IATA starting in 1995, except correct 1995 entry from 09-30 to 09-29.
+Rule   Egypt   1995    max     -       Apr     lastFri  0:00s  1:00    S
+Rule   Egypt   1995    max     -       Sep     lastThu 23:00s  0       -
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Cairo    2:05:00 -       LMT     1900 Oct
@@ -282,113 +219,93 @@ Zone     Africa/Cairo    2:05:00 -       LMT     1900 Oct
 # Equatorial Guinea
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Malabo   0:35:08 -       LMT     1912
-                       0:00    -       WAT     1963 Dec 15
-                       1:00    -       CAT
+                       0:00    -       GMT     1963 Dec 15
+                       1:00    -       WAT
 
 # Eritrea
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Asmera   2:35:32 -       LMT     1870
                        2:35:32 -       AMT     1890          # Asmera Mean Time
-                       2:35:20 -       AAMT    1936 May 5    # Addis Ababa MT?
+                       2:35:20 -       ADMT    1936 May 5    # Adis Dera MT
                        3:00    -       EAT
 
 # Ethiopia
+# From Paul Eggert (1997-10-05):
+# Shanks writes that Ethiopia had six narrowly-spaced time zones between
+# 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
+# We'll guess that 38E50 is for Adis Dera.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Addis_Ababa        2:34:48 -       LMT     1870
-                       2:35:20 -       AAMT    1936 May 5    # Addis Ababa MT?
+                       2:35:20 -       ADMT    1936 May 5    # Adis Dera MT
                        3:00    -       EAT
 
-# Europa Island
-# uninhabited
-
 # Gabon
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Libreville 0:37:48 -       LMT     1912
-                       1:00    -       CAT
+                       1:00    -       WAT
 
 # Gambia
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Banjul   -1:06:36 -      LMT     1912
                        -1:06:36 -      BMT     1935    # Banjul Mean Time
-                       -1:00   -       AAT     1964
-                        0:00   -       WAT
+                       -1:00   -       WAT     1964
+                        0:00   -       GMT
 
 # Ghana
-# From Paul Eggert <eggert@twinsun.com> (1996-09-03):
-# WATST is my invention for ``West Africa one-Third Summer Time''.
-# From Shanks (1991):
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 # Whitman says DST was observed from 1931 to ``the present''; go with Shanks.
-Rule   Ghana   1936    1942    -       Sep      1      0:00    0:20    WATST
-Rule   Ghana   1936    1942    -       Dec     31      0:00    0       WAT
+Rule   Ghana   1936    1942    -       Sep      1      0:00    0:20    GHST
+Rule   Ghana   1936    1942    -       Dec     31      0:00    0       GMT
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Accra    -0:00:52 -      LMT     1918
                         0:00   Ghana   %s
 
-# Glorioso Is
-# uninhabited
-
 # Guinea
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Conakry  -0:54:52 -      LMT     1912
-                        0:00   -       WAT     1934 Feb 26
-                        1:00   -       CAT     1960
-                        0:00   -       WAT
+                        0:00   -       GMT     1934 Feb 26
+                       -1:00   -       WAT     1960
+                        0:00   -       GMT
 
 # Guinea-Bissau
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Bissau   -1:02:20 -      LMT     1911 May 26
-                        1:00   -       CAT     1975
-                        0:00   -       WAT
-
-# Juan de Nova
-# uninhabited
+                       -1:00   -       WAT     1975
+                        0:00   -       GMT
 
 # Kenya
-# From Paul Eggert <eggert@twinsun.com> (1993-11-18):
-# Shanks says the transition to 2:45 was in 1940, but it must have been 1948.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Nairobi  2:27:16 -       LMT     1928 Jul
                        3:00    -       EAT     1930
-                       2:30    -       BEAT    1948
-                       2:45    -       BEA   1960
+                       2:30    -       BEAT    1940
+                       2:45    -       BEAUT   1960
                        3:00    -       EAT
 
 # Lesotho
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Maseru   1:50:00 -       LMT     1903 Mar
-                       2:00    -       SA    1943 Sep 19 2:00
+                       2:00    -       SAST    1943 Sep 19 2:00
                        2:00    1:00    SAST    1944 Mar 19 2:00
-                       2:00    -       SAT
+                       2:00    -       SAST
 
 # Liberia
 # From Paul Eggert <eggert@twinsun.com> (1993-11-18):
 # In 1972 Liberia was the last country to switch
-# from a GMT offset that was not a multiple of 15 minutes.
+# from a UTC offset that was not a multiple of 15 minutes.
 # Howse reports that it was in honor of their president's birthday.
 # Shanks reports the date as May 1, whereas Howse reports Jan; go with Shanks.
 # For Liberia before 1972, Shanks reports -0:44, whereas Howse and Whitman
 # each report -0:44:30; go with the more precise figure.
-#
-# From Shanks (1991), as corrected by Whitman:
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Monrovia -0:43:08 -      LMT     1882
                        -0:43:08 -      MMT     1919 Mar # Monrovia Mean Time
                        -0:44:30 -      LRT     1972 May # Liberia Time
-                        0:00   -       WAT
+                        0:00   -       GMT
 
 ###############################################################################
 
 # Libya
 
-# From Bob Devine (January 28 1988):
-# Libya: Since 1982 April 1st to September 30th (?)
-
-# From U. S. Naval Observatory (1989-01-19):
-# LIBYAN ARAB         1 H  AHEAD OF UTC  JAMAHIRIYA/LIBYA
-# LIBYAN ARAB         2 H  AHEAD OF UTC  APR 1 - SEP 30 JAMAHIRIYA/LIBYA
-
-# From Shanks (1991):
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Libya   1951    only    -       Oct     14      2:00    1:00    S
 Rule   Libya   1952    only    -       Jan      1      0:00    0       -
@@ -403,16 +320,17 @@ Rule      Libya   1986    only    -       Apr      4      0:00    1:00    S
 Rule   Libya   1986    only    -       Oct      3      0:00    0       -
 Rule   Libya   1987    1989    -       Apr      1      0:00    1:00    S
 Rule   Libya   1987    1990    -       Oct      1      0:00    0       -
-Rule   Libya   1990    only    -       May      4      0:00    1:00    S
-Rule   Libya   1996    max     -       Mar     30      2:00s   1:00    S
-Rule   Libya   1996    max     -       Sep     30      2:00s   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Tripoli  0:52:44 -       LMT     1920
                        1:00    Libya   CE%sT   1959
                        2:00    -       EET     1982
-                       1:00    Libya   CE%sT   1991
-                       2:00    -       EET     1996 Mar 30 3:00
-                       1:00    Libya   CE%sT
+                       1:00    Libya   CE%sT   1990 May  4
+# The following entries are all from Shanks;
+# the IATA SSIM data contain some obvious errors.
+                       2:00    -       EET     1996 Sep 30
+                       1:00    -       CET     1997 Apr  4
+                       1:00    1:00    CEST    1997 Oct  4
+                       2:00    -       EET
 
 # Madagascar
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -424,24 +342,24 @@ Zone Indian/Antananarivo 3:10:04 -        LMT     1911 Jul
 # Malawi
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Blantyre 2:20:00 -       LMT     1903 Mar
-                       2:00    -       SAT
+                       2:00    -       CAT
 
 # Mali
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Bamako   -0:32:00 -      LMT     1912
-                        0:00   -       WAT     1934 Feb 26
-                       -1:00   -       AAT     1960 Jun 20
-                        0:00   -       WAT
+                        0:00   -       GMT     1934 Feb 26
+                       -1:00   -       WAT     1960 Jun 20
+                        0:00   -       GMT
 # no longer different from Bamako, but too famous to omit
 Zone   Africa/Timbuktu -0:12:04 -      LMT     1912
-                        0:00   -       WAT
+                        0:00   -       GMT
 
 # Mauritania
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Nouakchott -1:03:48 -      LMT     1912
-                        0:00   -       WAT     1934 Feb 26
-                       -1:00   -       AAT     1960 Jun 20
-                        0:00   -       WAT
+                        0:00   -       GMT     1934 Feb 26
+                       -1:00   -       WAT     1960 Nov 28
+                        0:00   -       GMT
 
 # Mauritius
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -456,6 +374,7 @@ Zone        Indian/Mayotte  3:00:56 -       LMT     1911 Jul        # Mamoutzou
                        3:00    -       EAT
 
 # Morocco
+# See the `europe' file for Spanish Morocco (Africa/Ceuta).
 # RULE NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Morocco 1939    only    -       Sep     12       0:00   1:00    S
 Rule   Morocco 1939    only    -       Nov     19       0:00   0       -
@@ -479,68 +398,86 @@ Zone Africa/Casablanca    -0:30:20 -      LMT     1913 Oct 26
                         0:00   -       WET
 # Western Sahara
 Zone Africa/El_Aaiun   -0:52:48 -      LMT     1934 Jan
-                       -1:00   -       AAT     1976 Apr 14
+                       -1:00   -       WAT     1976 Apr 14
                         0:00   -       WET
 
 # Mozambique
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Maputo   2:10:20 -       LMT     1903 Mar
-                       2:00    -       SAT
+                       2:00    -       CAT
 
 # Namibia
+# The 1994-04-03 transition is from Shanks.
+# Shanks reports no DST after 1998-04; go with IATA.
 # RULE NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Namibia 1994    max     -       Sep     Sun>=1  2:00    1:00    S
 Rule   Namibia 1995    max     -       Apr     Sun>=1  2:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Windhoek 1:08:24 -       LMT     1892 Feb 8
                        1:30    -       SWAT    1903 Mar        # SW Africa Time
-                       2:00    -       SA    1942 Sep 20 2:00
+                       2:00    -       SAST    1942 Sep 20 2:00
                        2:00    1:00    SAST    1943 Mar 21 2:00
-                       2:00    Namibia SA%sT
+                       2:00    -       SAST    1990 Mar 21 # independence
+                       2:00    -       CAT     1994 Apr  3
+                       1:00    Namibia WA%sT
 
 # Niger
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Africa/Niamey   0:08:28 -       LMT     1912
-                       1:00    -       CAT     1934 Feb 26
-                       0:00    -       WAT     1960
-                       1:00    -       CAT
+Zone   Africa/Niamey    0:08:28 -      LMT     1912
+                       -1:00   -       WAT     1934 Feb 26
+                        0:00   -       GMT     1960
+                        1:00   -       WAT
 
 # Nigeria
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Lagos    0:13:36 -       LMT     1919 Sep
-                       1:00    -       CAT
+                       1:00    -       WAT
 
 # Reunion
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Indian/Reunion  3:41:52 -       LMT     1911 Jun        # Saint-Denis
                        4:00    -       RET     # Reunion Time
+#
+# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
+# The following information about them is taken from
+# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
+# no longer available as of 1999-08-17).
+# We have no info about their time zone histories.
+#
+# Bassas da India - uninhabited
+# Europa Island - inhabited from 1905 to 1910 by two families
+# Glorioso Is - inhabited until at least 1958
+# Juan de Nova - uninhabited
+# Tromelin - inhabited until at least 1958
 
 # Rwanda
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Kigali   2:00:16 -       LMT     1935 Jun
-                       2:00    -       SAT
+                       2:00    -       CAT
 
 # St Helena
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Atlantic/St_Helena        -0:22:48 -      LMT     1890            # Jamestown
-                       -0:06   -       SHT     1951    # St Helena Time (?)
+                       -0:22:48 -      JMT     1951    # Jamestown Mean Time
                         0:00   -       GMT
 # The other parts of the St Helena territory are similar:
-#      Tristan da Cunha: on GMT, says Whitman
-#      Ascension: on GMT, says usno1995
-#      Gough, Inaccessible, Nightingale: no information, but probably GMT
+#      Tristan da Cunha: on GMT, say Whitman and the CIA
+#      Ascension: on GMT, says usno1995 and the CIA
+#      Gough (scientific station since 1955; sealers wintered previously):
+#              on GMT, says the CIA
+#      Inaccessible, Nightingale: no information, but probably GMT
 
 # Sao Tome and Principe
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Sao_Tome  0:26:56 -      LMT     1884
                        -0:36:32 -      LMT     1912    # Lisbon Mean Time
-                        0:00   -       WAT
+                        0:00   -       GMT
 
 # Senegal
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Dakar    -1:09:44 -      LMT     1912
-                       -1:00   -       AAT     1941 Jun
-                        0:00   -       WAT
+                       -1:00   -       WAT     1941 Jun
+                        0:00   -       GMT
 
 # Seychelles
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -550,42 +487,44 @@ Zone      Indian/Mahe     3:41:48 -       LMT     1906 Jun        # Victoria
 # Sierra Leone
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 # Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks.
-Rule   SL      1935    1942    -       Jun      1      0:00    1:00    S
-Rule   SL      1935    1942    -       Oct      1      0:00    0       -
-Rule   SL      1957    1962    -       Jun      1      0:00    1:00    S
-Rule   SL      1957    1962    -       Sep      1      0:00    0       -
+Rule   SL      1935    1942    -       Jun      1      0:00    0:40    SLST
+Rule   SL      1935    1942    -       Oct      1      0:00    0       WAT
+Rule   SL      1957    1962    -       Jun      1      0:00    1:00    SLST
+Rule   SL      1957    1962    -       Sep      1      0:00    0       GMT
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Freetown -0:53:00 -      LMT     1882
                        -0:53:00 -      FMT     1913 Jun # Freetown Mean Time
-                       -1:00   SL      AA%sT   1957
-                        0:00   SL      WA%sT
+                       -1:00   SL      %s      1957
+                        0:00   SL      %s
 
 # Somalia
-# From Paul Eggert <eggert@twinsun.com> (1993-11-18):
-# Shanks omits the 1948 transition to 2:45; this is probably a typo.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Mogadishu  3:01:28 -       LMT     1893 Nov
                        3:00    -       EAT     1931
-                       2:30    -       BEAT    1948
-                       2:45    -       BEAT    1957    # not in Shanks
+                       2:30    -       BEAT    1957
                        3:00    -       EAT
 
 # South Africa
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   SA      1942    1943    -       Sep     Sun>=15 2:00    1:00    S
+Rule   SA      1942    1943    -       Sep     Sun>=15 2:00    1:00    -
 Rule   SA      1943    1944    -       Mar     Sun>=15 2:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Johannesburg 1:52:00 -     LMT     1892 Feb 8
-                       1:30    -       SAT     1903 Mar
-                       2:00    SA      SA%sT
-# Prince Edward Is
+                       1:30    -       SAST    1903 Mar
+                       2:00    SA      SAST
+# Marion and Prince Edward Is
+# scientific station since 1947
 # no information
 
 # Sudan
-# From Michael Ross <mross@antigone.com> (1995-11-15):
-# Sudan no longer observes any form of daylight time change.
-# I verified this today by telephone with the Sudan Mission to the
-# United Nations: 212-573-6033
+#
+# From <a href="http://www.sunanews.net/sn13jane.html">
+# Sudan News Agency (2000-01-13)
+# </a>, also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
+# Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
+# Saturday....  This was announced Thursday by Caretaker State Minister for
+# Manpower Abdul-Rahman Nur-Eddin.
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Sudan   1970    only    -       May      1      0:00    1:00    S
 Rule   Sudan   1970    1985    -       Oct     15      0:00    0       -
@@ -593,27 +532,25 @@ Rule      Sudan   1971    only    -       Apr     30      0:00    1:00    S
 Rule   Sudan   1972    1985    -       Apr     lastSun 0:00    1:00    S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Khartoum 2:10:08 -       LMT     1931
-                       2:00    Sudan   EE%sT
+                       2:00    Sudan   CA%sT   2000 Jan 15 12:00
+                       3:00    -       EAT
 
 # Swaziland
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Mbabane  2:04:24 -       LMT     1903 Mar
-                       2:00    -       SAT
+                       2:00    -       SAST
 
 # Tanzania
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Africa/Dar_es_Salaam 2:37:08 -    LMT     1931
                        3:00    -       EAT     1948
-                       2:45    -       BEA   1961
+                       2:45    -       BEAUT   1961
                        3:00    -       EAT
 
 # Togo
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Lome     0:04:52 -       LMT     1893
-                       0:00    -       WAT
-
-# Tromelin
-# uninhabited
+                       0:00    -       GMT
 
 # Tunisia
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -650,22 +587,15 @@ Zone      Africa/Tunis    0:40:44 -       LMT     1881 May 12
 Zone   Africa/Kampala  2:09:40 -       LMT     1928 Jul
                        3:00    -       EAT     1930
                        2:30    -       BEAT    1948
-                       2:45    -       BEA   1957
+                       2:45    -       BEAUT   1957
                        3:00    -       EAT
 
-# Zaire
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Africa/Kinshasa   1:01:12 -       LMT     1897 Nov 9
-                       1:00    -       CAT
-Zone Africa/Lubumbashi 1:49:52 -       LMT     1897 Nov 9
-                       2:00    -       SAT
-
 # Zambia
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Lusaka   1:53:08 -       LMT     1903 Mar
-                       2:00    -       SAT
+                       2:00    -       CAT
 
 # Zimbabwe
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Africa/Harare   2:04:12 -       LMT     1903 Mar
-                       2:00    -       SAT
+                       2:00    -       CAT
index 01262d72b8b5f14743ff5ee51a2684f33d7c6f54..c98e528c1e4b769780dfa4dfba1d3f92cc701aa8 100644 (file)
@@ -1,13 +1,32 @@
-#      $OpenBSD: antarctica,v 1.3 1997/01/14 04:36:48 millert Exp $
-# @(#)antarctica       7.5
+# @(#)antarctica       7.21
 
-# From Paul Eggert (1996-09-03):
-# To keep things manageable, we list only locations occupied year-round;
-# see <URL:http://earth.agu.org/amen/nations.html> (1996-05-24).
+# From Paul Eggert (1999-11-15):
+# To keep things manageable, we list only locations occupied year-round; see
+# <a href="http://www.comnap.aq/comnap/comnap.nsf/P/Stations/">
+# COMNAP - Stations and Bases
+# </a>
+# and
+# <a href="http://www.spri.cam.ac.uk/bob/periant.htm">
+# Summary of the Peri-Antarctic Islands (1998-07-23)
+# </a>
+# for information.
 # Unless otherwise specified, we have no time zone information.
 #
+# Except for the French entries,
 # I made up all time zone abbreviations mentioned here; corrections welcome!
-# FORMAT is `___' and GMTOFF is 0 for locations while uninhabited.
+# FORMAT is `zzz' and GMTOFF is 0 for locations while uninhabited.
+
+# These rules are stolen from the `europe' file.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   RussAQ  1981    1984    -       Apr      1       0:00   1:00    S
+Rule   RussAQ  1981    1983    -       Oct      1       0:00   0       -
+Rule   RussAQ  1984    1991    -       Sep     lastSun  2:00s  0       -
+Rule   RussAQ  1985    1991    -       Mar     lastSun  2:00s  1:00    S
+Rule   RussAQ  1992    only    -       Mar     lastSat  23:00  1:00    S
+Rule   RussAQ  1992    only    -       Sep     lastSat  23:00  0       -
+Rule   RussAQ  1993    max     -       Mar     lastSun  2:00s  1:00    S
+Rule   RussAQ  1993    1995    -       Sep     lastSun  2:00s  0       -
+Rule   RussAQ  1996    max     -       Oct     lastSun  2:00s  0       -
 
 # These rules are stolen from the `southamerica' file.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -20,53 +39,108 @@ Rule       ArgAQ   1974    only    -       Jan     23      0:00    1:00    S
 Rule   ArgAQ   1974    only    -       May      1      0:00    0       -
 Rule   ArgAQ   1974    1976    -       Oct     Sun<=7  0:00    1:00    S
 Rule   ArgAQ   1975    1977    -       Apr     Sun<=7  0:00    0       -
-Rule   ChileAQ 1969    max     -       Oct     Sun>=9  0:00    1:00    S
-Rule   ChileAQ 1970    max     -       Mar     Sun>=9  0:00    0       -
+Rule   ChileAQ 1969    1997    -       Oct     Sun>=9  0:00    1:00    S
+Rule   ChileAQ 1970    1998    -       Mar     Sun>=9  0:00    0       -
+Rule   ChileAQ 1998    only    -       Sep     27      0:00    1:00    S
+Rule   ChileAQ 1999    only    -       Apr      4      0:00    0       -
+Rule   ChileAQ 1999    max     -       Oct     Sun>=9  0:00    1:00    S
+Rule   ChileAQ 2000    max     -       Mar     Sun>=9  0:00    0       -
 
 
-# Argentina - 6 year-round bases
-# General Belgrano II
-# 5 others
+# Argentina - year-round bases
+# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
+# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
+# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
+# Marambio, Seymour I, -6414-05637, since 1969-10-29
+# Orcadas, Laurie I, -6016-04444, since 1904-02-22
+# San Martin, Debenham I, -6807-06708, since 1951-03-21
+#      (except 1960-03 / 1976-03-21)
 
 # Australia - territories
-# Heard Island, McDonald Islands
+# Heard Island, McDonald Islands (uninhabited)
+#      previously sealers and scientific personnel wintered
+#      <a href="http://www.dstc.qut.edu.au/DST/marg/daylight.html">
+#      Margaret Turner reports
+#      </a> (1999-09-30) that they're UTC+5, with no DST;
+#      presumably this is when they have visitors.
 #
 # year-round bases
-# Casey, Bailey Peninsula, since 1969
-# Davis, Vestfold Hills, since 1957-01-13 (except 1965-01 -  1969-02)
-# Mawson, Holme Bay, since 1954-02-13
+# Casey, Bailey Peninsula, -6617+11032, since 1969
+# Davis, Vestfold Hills, -6835+07759, since 1957-01-13
+#      (except 1964-11 - 1969-02)
+# Mawson, Holme Bay, -6736+06253, since 1954-02-13
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Antarctica/Casey  0       -       ___     1969
+Zone Antarctica/Casey  0       -       zzz     1969
                        8:00    -       WST     # Western (Aus) Standard Time
-#Zone Antartica/Davis  unknown
-Zone Antarctica/Mawson 0       -       ___     1954 Feb 13
+Zone Antarctica/Davis  0       -       zzz     1957 Jan 13
+                       7:00    -       DAVT    1964 Nov # Davis Time
+                       0       -       zzz     1969 Feb
+                       7:00    -       DAVT
+Zone Antarctica/Mawson 0       -       zzz     1954 Feb 13
                        6:00    -       MAWT    # Mawson Time
 # References:
-# <URL:http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html> (1996-07-15)
-# <URL:http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html> (1996-04-19)
+# <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html">
+# Casey Weather (1998-02-26)
+# </a>
+# <a href="http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html">
+# Davis Station, Antarctica (1998-02-26)
+# </a>
+# <a href="http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html">
+# Mawson Station, Antarctica (1998-02-25)
+# </a>
 
 # Brazil - year-round base
 # Ferraz, King George Island, since 1983/4
 
-# Chile - 4 year-round bases
+# Chile - year-round bases
+# Escudero, South Shetland Is, -621157-0585735, since 1994
+# Frei, King George Is, -6214-05848, since 1969
+# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
+# Prat, -6230-05941
 
 # China - year-round bases
 # Great Wall, King George Island, since 1985-02-20
 # Zhongshan, Larsemann Hills, Prydz Bay, since 1989-02-26
 
-# Finland - year-round base
-# Aboa, Queen Maud Land, since 1988
-
-# France
+# France - year-round bases
+#
+# From Antoine Leca <Antoine.Leca@Renault.FR> (1997-01-20):
+# Time data are from Nicole Pailleau at the IFRTP
+# (French Institute for Polar Research and Technology).
+# She confirms that French Southern Territories and Terre Adelie bases
+# don't observe daylight saving time, even if Terre Adelie supplies came
+# from Tasmania.
 #
 # French Southern Territories with year-round inhabitants
-# Amsterdam Island
-# Crozet Islands
-# Kerguelen Islands
-# St Paul Island
 #
-# year-round base
-# Dumont d'Urville, Adelie Land, since IGY
+# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
+# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
+# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
+#      whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
+#
+# St Paul Island - near Amsterdam, uninhabited
+#      fishing stations operated variously 1819/1931
+#
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Indian/Kerguelen  0       -       zzz     1950    # Port-aux-Francais
+                       5:00    -       TFT     # ISO code TF Time
+#
+# year-round base in the main continent
+# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
+#
+# Another base at Port-Martin, 50km east, began operation in 1947.
+# It was destroyed by fire on 1952-01-14.
+#
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Antarctica/DumontDUrville 0 -     zzz     1947
+                       10:00   -       PMT     1952 Jan 14 # Port-Martin Time
+                       0       -       zzz     1956 Nov
+                       10:00   -       DDUT    # Dumont-d'Urville Time
+# Reference:
+# <a href="http://www.icair.iac.org.nz/science/reports/fr/IFRTP.html">
+# Support and Development of Polar Research and Technology (1997-02-03)
+# </a>
+
 
 # Germany - year-round base
 # Georg von Neumayer
@@ -77,13 +151,29 @@ Zone Antarctica/Mawson     0       -       ___     1954 Feb 13
 # Japan - year-round bases
 # Dome Fuji
 # Syowa
+#
+# From Hideyuki Suzuki (1999-02-06):
+# In all Japanese stations, +0300 is used as the standard time.  [See]
+# <a href="http://www.crl.go.jp/uk/uk201/basyo.htm">[reference in Japanese]</a>
+# and information from KAMO Hiroyasu <wd@ics.nara-wu.ac.jp>.
+#
+# Syowa station, which is the first antarctic station of Japan,
+# was established on 1957-01-29.  Since Syowa station is still the main
+# station of Japan, it's appropriate for the principal location.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Antarctica/Syowa  0       -       zzz     1957 Jan 29
+                       3:00    -       SYOT    # Syowa Time
+# See:
+# <a href="http://www.nipr.ac.jp/english/ara01.html">
+# NIPR Antarctic Research Activities (1999-08-17)
+# </a>
 
 # S Korea - year-round base
 # King Sejong, King George Island, since 1988
 
 # New Zealand - claims
-# Balleny Islands
-# Scott Island
+# Balleny Islands (never inhabited)
+# Scott Island (never inhabited)
 #
 # year-round base
 # Scott, Ross Island, since 1957-01, is like Antarctica/McMurdo.
@@ -99,20 +189,38 @@ Rule       NZAQ    1976    1989    -       Mar     Sun>=1  2:00s   0       S
 Rule   NZAQ    1990    max     -       Mar     Sun>=15 2:00s   0       S
 
 # Norway - territories
-# Bouvet (uninhabited)
+# Bouvet (never inhabited)
 #
 # claims
-# Peter I Island (uninhabited)
+# Peter I Island (never inhabited)
 
 # Poland - year-round base
-# Arctowski, King George Island, since 1977
+# Arctowski, King George Island, -620945-0582745, since 1977
 
 # Russia - year-round bases
-# Bellingshausen, King George Island
-# Mirny
-# Molodezhnaya
-# Novolazarevskaya
-# Vostok
+# Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
+# Mirny, Davis coast, -6633+09301, since 1956-02
+# Molodezhnaya, Alasheyev Bay, year-round from 1962-02 to 1999-07-01
+# Novolazarevskaya, Queen Maud Land, -7046+01150,
+#      year-round from 1960/61 to 1992
+
+# Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
+# <a href="http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP">
+# From Craig Mundell (1994-12-15)</a>:
+# Vostok, which is one of the Russian stations, is set on the same
+# time as Moscow, Russia.
+#
+# From Lee Hotz (2001-03-08):
+# I queried the folks at Columbia who spent the summer at Vostok and this is
+# what they had to say about time there:
+# ``in the US Camp (East Camp) we have been on New Zealand (McMurdo)
+# time, which is 12 hours ahead of GMT. The Russian Station Vostok was
+# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead
+# of GMT). This is a time zone I think two hours east of Moscow. The
+# natural time zone is in between the two: 8 hours ahead of GMT.''
+#
+Zone Antarctica/Vostok 0       -       zzz     1957 Dec 16
+                       6:00    -       VOST    # Vostok time
 
 # S Africa - year-round bases
 # Marion Island
@@ -122,14 +230,23 @@ Rule      NZAQ    1990    max     -       Mar     Sun>=15 2:00s   0       S
 #
 # British Antarctic Territories (BAT) claims
 # South Orkney Islands
+#      scientific station from 1903
+#      whaling station at Signy I 1920/1926
 # South Shetland Islands
 #
 # year-round bases
-# Halley, Coates Land, -7535-2619, since 1956-01-06
+# Bird Island, South Georgia, -5400-03803, since 1983
+# Deception Island, -6259-06034, whaling station 1912/1931,
+#      scientific station 1943/1967,
+#      previously sealers and a scientific expedition wintered by accident,
+#      and a garrison was deployed briefly
+# Halley, Coates Land, -7535-02604, since 1956-01-06
+#      Halley is on a moving ice shelf and is periodically relocated
+#      so that it is never more than 10km from its nominal location.
 # Rothera, Adelaide Island, -6734-6808, since 1976-12-01
 
 # Uruguay - year round base
-# Artigas, King George Island
+# Artigas, King George Island, -621104-0585107
 
 # USA - year-round bases
 #
@@ -143,18 +260,19 @@ Rule      NZAQ    1990    max     -       Mar     Sun>=15 2:00s   0       S
 # Palmer used to be supplied from Argentina.
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Antarctica/Palmer 0       -       ___     1965
+Zone Antarctica/Palmer 0       -       zzz     1965
                        -4:00   ArgAQ   AR%sT   1969 Oct 5
                        -3:00   ArgAQ   AR%sT   1982 May
                        -4:00   ChileAQ CL%sT
 #
 #
-# McMurdo, Ross Island, since 1956
+# McMurdo, Ross Island, since 1955-12
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Antarctica/McMurdo        0       -       ___     1956
+Zone Antarctica/McMurdo        0       -       zzz     1956
                        12:00   NZAQ    NZ%sT
 #
-# Amundsen-Scott, South Pole, since 1957-01-23
+# Amundsen-Scott, South Pole, continuously occupied since 1956-11-20
+#
 # From Paul Eggert (1996-09-03):
 # Normally it wouldn't have a separate entry, since it's like the
 # larger Antarctica/McMurdo since 1970, but it's too famous to omit.
@@ -167,8 +285,10 @@ Zone Antarctica/McMurdo    0       -       ___     1956
 # which was on GMT+12 because New Zealand was on GMT+12 all year
 # at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
 #
-# From Susan Smith <URL:http://www.cybertours.com/whs/pole10.html>
-# (1995-11-13 16:24:56 +1300): We use the same time as McMurdo does.
+# From Susan Smith
+# http://www.cybertours.com/whs/pole10.html
+# (1995-11-13 16:24:56 +1300, no longer available):
+# We use the same time as McMurdo does.
 # And they use the same time as Christchurch, NZ does....
 # One last quirk about South Pole time.
 # All the electric clocks are usually wrong.
index f921fb0111ea73432eb2cca2e6970a427ab5c848..cfefc19ccfb531f5691f287555967eaaf4d5622a 100644 (file)
@@ -1,18 +1,18 @@
-#      $OpenBSD: asia,v 1.5 1997/01/14 04:36:48 millert Exp $
-# @(#)asia     7.27
+# @(#)asia     7.63
+
+# $FreeBSD: src/share/zoneinfo/asia,v 1.18 2001/04/06 16:46:52 wollman Exp $
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
 # tz@elsie.nci.nih.gov for general use in the future).
 
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# From Paul Eggert <eggert@twinsun.com> (1999-03-22):
 #
 # A good source for time zone historical data outside the U.S. is
-# Thomas G. Shanks, The International Atlas (3rd edition),
-# San Diego: ACS Publications, Inc. (1991).
-# Except where otherwise noted, it is the source for the data below.
+# Thomas G. Shanks, The International Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1999).
 #
-# Gwillim Law <LAW@encmail.encompass.com> writes that a good source
+# Gwillim Law <Gwil_Law@bridge-point.com> writes that a good source
 # for recent time zone data is the International Air Transport
 # Association's Standard Schedules Information Manual (IATA SSIM),
 # published semiannually.  Law sent in several helpful summaries
@@ -26,8 +26,7 @@
 # I found in the UCLA library.
 #
 # A reliable and entertaining source about time zones is
-# Derek Howse, Greenwich time and the discovery of the longitude,
-# Oxford University Press (1980).
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
 # I invented the abbreviations marked `*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 #      5:30    IST     India
 #      7:00    ICT     Indochina*
 #      8:00    CST     China
+#      9:00    CJT     Central Japanese Time (1896/1937)*
 #      9:00    JST     Japan
 #      9:00    KST     Korea
 #      9:30    CST     (Australian) Central Standard Time
 #
 # See the `europe' file for Russia and Turkey in Asia.
-#
-# See the `africa' file for time zone naming and abbreviation conventions.
 
 # From Guy Harris:
 # Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
@@ -81,24 +79,27 @@ Zone        Asia/Kabul      4:36:48 -       LMT     1890
                        4:30    -       AFT
 
 # Armenia
-# From Paul Eggert (1996-05-04):
+# From Paul Eggert (1999-10-29):
 # Shanks has Yerevan switching to 3:00 (with Russian DST) in spring 1991,
-# but usno1995 has Armenia at 4:00 (with DST), and Edgar Der-Danieliantz
-# <edd@AIC.NET> reported today that Yerevan probably won't use DST this year,
-# though it did use DST in 1995.  We guess Yerevan stayed in sync with Moscow
-# between 1990 and 1995, but stopped using DST in 1996.
-# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Armenia 1991    1995    -       Mar     lastSun 2:00s   1:00    S
-Rule   Armenia 1991    1995    -       Sep     lastSun 2:00s   0       -
+# then to 4:00 with no DST in fall 1995, then readopting Russian DST in 1997.
+# Go with Shanks, even when he disagrees with others.  Edgar Der-Danieliantz
+# <edd@AIC.NET> reported (1996-05-04) that Yerevan probably wouldn't use DST
+# in 1996, though it did use DST in 1995.  IATA SSIM (1991/1998) reports that
+# Armenia switched from 3:00 to 4:00 in 1998 and observed DST after 1991,
+# but started switching at 3:00s in 1998.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Yerevan    2:58:00 -       LMT     1924 May  2
                        3:00    -       YERT    1957 Mar    # Yerevan Time
                        4:00 RussiaAsia YER%sT  1991 Mar 31 2:00s
                        3:00    1:00    YERST   1991 Sep 23 # independence
-                       3:00    Armenia AM%sT   1992 Jan 19 2:00s # Armenia Time
-                       4:00    Armenia AM%sT
+                       3:00 RussiaAsia AM%sT   1995 Sep 24 2:00s
+                       4:00    -       AMT     1997
+                       4:00 RussiaAsia AM%sT
 
 # Azerbaijan
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Azer    1997    max     -       Mar     lastSun  1:00   1:00    S
+Rule   Azer    1997    max     -       Oct     lastSun  1:00   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Baku       3:19:24 -       LMT     1924 May  2
                        3:00    -       BAKT    1957 Mar    # Baku Time
@@ -106,17 +107,18 @@ Zone      Asia/Baku       3:19:24 -       LMT     1924 May  2
                        3:00    1:00    BAKST   1991 Aug 30 # independence
                        3:00 RussiaAsia AZ%sT   1992 Sep lastSun 2:00s
                        4:00    -       AZT     1996 # Azerbaijan time
-                       4:00    EUAsia  AZ%sT
+                       4:00    EUAsia  AZ%sT   1997
+                       4:00    Azer    AZ%sT
 
 # Bahrain
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Bahrain    3:22:20 -       LMT     1920            # Al-Manamah
+Zone   Asia/Bahrain    3:22:20 -       LMT     1920            # Al Manamah
                        4:00    -       GST     1972 Jun
                        3:00    -       AST
 
 # Bangladesh
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Dacca      6:01:40 -       LMT     1890
+Zone   Asia/Dhaka      6:01:40 -       LMT     1890
                        5:53:20 -       HMT     1941 Oct    # Howrah Mean Time?
                        6:30    -       BURT    1942 May 15 # Burma Time
                        5:30    -       IST     1942 Sep
@@ -126,7 +128,7 @@ Zone        Asia/Dacca      6:01:40 -       LMT     1890
 
 # Bhutan
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Thimbu     5:58:36 -       LMT     1947 Aug 15
+Zone   Asia/Thimphu    5:58:36 -       LMT     1947 Aug 15 # or Thimbu
                        5:30    -       IST     1987 Oct
                        6:00    -       BTT     # Bhutan Time
 
@@ -157,7 +159,7 @@ Zone        Asia/Phnom_Penh 6:59:40 -       LMT     1906 Jun  9
                        8:00    -       ICT     1931 May
                        7:00    -       ICT
 
-# People's Republic of China
+# China
 
 # From Guy Harris:
 # People's Republic of China.  Yes, they really have only one time zone.
@@ -186,7 +188,7 @@ Zone        Asia/Phnom_Penh 6:59:40 -       LMT     1906 Jun  9
 # note about Time magazine, though apparently _something_ happened in 1986.
 # Go with Shanks for now.  I made up names for the other pre-1980 time zones.
 
-# From Shanks (1991):
+# From Shanks:
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Shang   1940    only    -       Jun      3      0:00    1:00    D
 Rule   Shang   1940    1941    -       Oct      1      0:00    0       S
@@ -196,7 +198,7 @@ Rule        PRC     1986    only    -       May      4      0:00    1:00    D
 Rule   PRC     1986    1991    -       Sep     Sun>=11 0:00    0       S
 Rule   PRC     1987    1991    -       Apr     Sun>=10 0:00    1:00    D
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Harbin     8:26:44 -       LMT     1928
+Zone   Asia/Harbin     8:26:44 -       LMT     1928 # or Haerbin
                        8:30    -       HART    1932 Mar # Harbin Time
                        8:00    -       CST     1940
                        9:00    -       HART    1966 May
@@ -205,20 +207,45 @@ Zone      Asia/Harbin     8:26:44 -       LMT     1928
 Zone   Asia/Shanghai   8:05:52 -       LMT     1928
                        8:00    Shang   C%sT    1949
                        8:00    PRC     C%sT
-Zone   Asia/Chungking  7:06:20 -       LMT     1928
+Zone   Asia/Chungking  7:06:20 -       LMT     1928 # or Chongqing
                        7:00    -       CHUT    1980 May # Chungking Time
                        8:00    PRC     C%sT
-Zone   Asia/Urumqi     5:50:20 -       LMT     1928
+Zone   Asia/Urumqi     5:50:20 -       LMT     1928 # or Urumchi
                        6:00    -       URUT    1980 May # Urumqi Time
                        8:00    PRC     C%sT
-Zone   Asia/Kashgar    5:03:56 -       LMT     1928
+Zone   Asia/Kashgar    5:03:56 -       LMT     1928 # or Kashi or Kaxgar
                        5:30    -       KAST    1940     # Kashgar Time
                        5:00    -       KAST    1980 May
                        8:00    PRC     C%sT
+# Hong Kong (Xianggang)
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   HK      1946    only    -       Apr     20      3:30    1:00    S
+Rule   HK      1946    only    -       Dec     1       3:30    0       -
+Rule   HK      1947    only    -       Apr     13      3:30    1:00    S
+Rule   HK      1947    only    -       Dec     30      3:30    0       -
+Rule   HK      1948    only    -       May     2       3:30    1:00    S
+Rule   HK      1948    1952    -       Oct     lastSun 3:30    0       -
+Rule   HK      1949    1953    -       Apr     Sun>=1  3:30    1:00    S
+Rule   HK      1953    only    -       Nov     1       3:30    0       -
+Rule   HK      1954    1964    -       Mar     Sun>=18 3:30    1:00    S
+Rule   HK      1954    only    -       Oct     31      3:30    0       -
+Rule   HK      1955    1964    -       Nov     Sun>=1  3:30    0       -
+Rule   HK      1965    1977    -       Apr     Sun>=16 3:30    1:00    S
+Rule   HK      1965    1977    -       Oct     Sun>=16 3:30    0       -
+Rule   HK      1979    1980    -       May     Sun>=8  3:30    1:00    S
+Rule   HK      1979    1980    -       Oct     Sun>=16 3:30    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Hong_Kong  7:36:36 -       LMT     1904 Oct 30
+                       8:00    HK      HK%sT
+
 
 ###############################################################################
 
-# Republic of China
+# Taiwan
+
+# Shanks writes that Taiwan observed DST during 1945, when it
+# was still controlled by Japan.  This is hard to believe, but we don't
+# have any other information.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Taiwan  1945    1951    -       May     1       0:00    1:00    D
@@ -236,30 +263,7 @@ Rule       Taiwan  1980    only    -       Sep     30      0:00    0       S
 Zone   Asia/Taipei     8:06:00 -       LMT     1896
                        8:00    Taiwan  C%sT
 
-###############################################################################
-# Hong Kong
-# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   HK      1946    only    -       Apr     20      3:30    1:00    S
-Rule   HK      1946    only    -       Dec     1       3:30    0       -
-Rule   HK      1947    only    -       Apr     13      3:30    1:00    S
-Rule   HK      1947    only    -       Dec     30      3:30    0       -
-Rule   HK      1948    only    -       May     2       3:30    1:00    S
-Rule   HK      1948    1952    -       Oct     lastSun 3:30    0       -
-Rule   HK      1949    1953    -       Apr     Sun>=1  3:30    1:00    S
-Rule   HK      1953    only    -       Nov     1       3:30    0       -
-Rule   HK      1954    1964    -       Mar     Sun>=18 3:30    1:00    S
-Rule   HK      1954    only    -       Oct     31      3:30    0       -
-Rule   HK      1955    1964    -       Nov     Sun>=1  3:30    0       -
-Rule   HK      1965    1977    -       Apr     Sun>=16 3:30    1:00    S
-Rule   HK      1965    1977    -       Oct     Sun>=16 3:30    0       -
-Rule   HK      1979    1980    -       May     Sun>=8  3:30    1:00    S
-Rule   HK      1979    1980    -       Oct     Sun>=16 3:30    0       -
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Hong_Kong  7:36:36 -       LMT     1904 Oct 30
-                       8:00    HK      HK%sT   1997 Jul  1 # return to China
-                       8:00    PRC     C%sT
-
-# Macao
+# Macao (Macau, Aomen)
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Macao   1961    1962    -       Mar     Sun>=16 3:30    1:00    S
 Rule   Macao   1961    1964    -       Nov     Sun>=1  3:30    0       -
@@ -292,11 +296,17 @@ Rule      Cyprus  1976    only    -       Oct     11      0:00    0       -
 Rule   Cyprus  1977    1980    -       Apr     Sun>=1  0:00    1:00    S
 Rule   Cyprus  1977    only    -       Sep     25      0:00    0       -
 Rule   Cyprus  1978    only    -       Oct     2       0:00    0       -
-Rule   Cyprus  1979    max     -       Sep     lastSun 0:00    0       -
-Rule   Cyprus  1981    max     -       Mar     lastSun 0:00    1:00    S
+Rule   Cyprus  1979    1997    -       Sep     lastSun 0:00    0       -
+Rule   Cyprus  1981    1998    -       Mar     lastSun 0:00    1:00    S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Nicosia    2:13:28 -       LMT     1921 Nov 14
-                       2:00    Cyprus  EE%sT
+                       2:00    Cyprus  EE%sT   1998 Sep
+                       2:00    EUAsia  EE%sT
+# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+
+# Classically, Cyprus belongs to Asia; e.g. see Herodotus, Histories, I.72.
+# However, for various reasons many users expect to find it under Europe.
+Link   Asia/Nicosia    Europe/Nicosia
 
 # Georgia
 # From Paul Eggert <eggert@twinsun.com> (1994-11-19):
@@ -318,7 +328,39 @@ Zone       Asia/Tbilisi    2:59:16 -       LMT     1880
                        3:00 RussiaAsia GE%sT   1992 # Georgia Time
                        3:00 E-EurAsia  GE%sT   1994 Sep lastSun
                        4:00 E-EurAsia  GE%sT   1996 Oct lastSun
-                       5:00    -       GET
+                       4:00    1:00    GEST    1997 Mar lastSun
+                       4:00 E-EurAsia  GE%sT
+
+# East Timor
+
+# From Joao Carrascalao, brother of the former governor of East Timor, in
+# <a href="http://etan.org/et99c/december/26-31/30ETMAY.htm">
+# East Timor may be late for its millennium
+# </a> (1999-12-26/31):
+# Portugal tried to change the time forward in 1974 because the sun
+# rises too early but the suggestion raised a lot of problems with the
+# Timorese and I still don't think it would work today because it
+# conflicts with their way of life.
+
+# From Paul Eggert (2000-12-04):
+# We don't have any record of the above attempt.
+# Most likely our records are incomplete, but we have no better data.
+
+# <a href="http://www.hri.org/news/world/undh/last/00-08-16.undh.html">
+# From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
+# (2000-08-16)</a>:
+# The Cabinet of the East Timor Transition Administration decided
+# today to advance East Timor's time by one hour.  The time change,
+# which will be permanent, with no seasonal adjustment, will happen at
+# midnight on Saturday, September 16.
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Dili       8:22:20 -       LMT     1912
+                       8:00    -       TPT     1942 Feb 21 23:00 # E Timor Time
+                       9:00    -       JST     1945 Aug
+                       9:00    -       TPT     1976 May  3
+                       8:00    -       TPT     2000 Sep 17 00:00
+                       9:00    -       TPT
 
 # India
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -336,7 +378,9 @@ Zone        Asia/Calcutta   5:53:28 -       LMT     1880
 # Indonesia
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Asia/Jakarta      7:07:12 -       LMT     1867 Aug 10
-                       7:07:12 -       JMT     1924 Jan  1 0:13 # Jakarta MT
+# Shanks says the next transition was at 1924 Jan 1 0:13,
+# but this must be a typo.
+                       7:07:12 -       JMT     1923 Dec 31 23:47:12 # Jakarta
                        7:20    -       JAVT    1932 Nov         # Java Time
                        7:30    -       JAVT    1942 Mar 23
                        9:00    -       JST     1945 Aug
@@ -355,9 +399,12 @@ Zone Asia/Jayapura 9:22:48 -       LMT     1932 Nov
                        9:00    -       JAYT
 
 # Iran
-# From Paul Eggert (1996-12-17), following up a suggestion by Rich Wales:
-# Ahmad Alavi <URL:http://tehran.stanford.edu/Iran_Lib/Calendar/taghveem.txt>
-# (1993-08-04) writes ``Daylight saving time in Iran starts from the first day
+# From Paul Eggert (2000-06-12), following up a suggestion by Rich Wales:
+# Ahmea Alavi in
+# <a href="http://www.persia.org/Iran_Lib/Calendar/taghveem.txt">
+# TAGHVEEM (1993-07-12)
+# </a>
+# writes ``Daylight saving time in Iran starts from the first day
 # of Farvardin and ends the first day of Mehr.''  This disagrees with the SSIM:
 #
 #                 DST start       DST end
@@ -367,8 +414,13 @@ Zone Asia/Jayapura 9:22:48 -       LMT     1932 Nov
 #      1993    03-21   03-21   09-23   09-23
 #      1994    03-21   03-21   09-22!= 09-23
 #      1995    03-21   03-21   09-22!= 09-23
-#      1996    03-21!= 03-20   09-21!= 09-22
-#      1997    03-21   03-21   09-21!= 09-23
+#      1996    03-21!= 03-20   09-22   09-22
+#      1997    03-22!= 03-21   09-22!= 09-23
+#      1998    03-21   03-21   09-21!= 09-23
+#      1999    03-22!= 03-21   09-22!= 09-23
+#      2000    03-21!= 03-20   09-21!= 09-22
+#      2001    03-19!= 03-21   09-19!= 09-23
+#      2002    03-18!= 03-21   09-18!= 09-23
 #
 # Go with Alavi starting with 1992.
 # I used Ed Reingold's cal-persia in GNU Emacs 19.34 to compute Persian dates.
@@ -433,7 +485,23 @@ Zone       Asia/Tehran     3:25:44 -       LMT     1916
                        4:00    Iran    IR%sT   1979
                        3:30    Iran    IR%sT
 
+
 # Iraq
+#
+# From Jonathan Lennox <lennox@cs.columbia.edu> (2000-06-12):
+# An article in this week's Economist ("Inside the Saddam-free zone", p. 50 in
+# the U.S. edition) on the Iraqi Kurds contains a paragraph:
+# "The three northern provinces ... switched their clocks this spring and
+# are an hour ahead of Baghdad."
+#
+# But Rives McDow (2000-06-18) quotes a contact in Iraqi-Kurdistan as follows:
+# In the past, some Kurdish nationalists, as a protest to the Iraqi
+# Government, did not adhere to daylight saving time.  They referred
+# to daylight saving as Saddam time.  But, as of today, the time zone
+# in Iraqi-Kurdistan is on standard time with Baghdad, Iraq.
+#
+# So we'll ignore the Economist's claim.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Iraq    1982    only    -       May     1       0:00    1:00    D
 Rule   Iraq    1982    1984    -       Oct     1       0:00    0       S
@@ -442,8 +510,9 @@ Rule        Iraq    1984    1985    -       Apr     1       0:00    1:00    D
 Rule   Iraq    1985    1990    -       Sep     lastSun 1:00s   0       S
 Rule   Iraq    1986    1990    -       Mar     lastSun 1:00s   1:00    D
 # IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
+# Shanks says Iraq did not observe DST 1992/1997 or 1999 on; ignore this.
 Rule   Iraq    1991    max     -       Apr      1      3:00s   1:00    D
-Rule   Iraq    1991    max     -       Oct      1      3:00s   0       D
+Rule   Iraq    1991    max     -       Oct      1      3:00s   0       S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Baghdad    2:57:40 -       LMT     1890
                        2:57:36 -       BMT     1918        # Baghdad Mean Time?
@@ -455,16 +524,27 @@ Zone      Asia/Baghdad    2:57:40 -       LMT     1890
 
 # Israel
 
-# From U. S. Naval Observatory (1989-01-19):
-# ISRAEL              2 H  AHEAD OF UTC
-# ISRAEL              3 H  AHEAD OF UTC  APR 10 - SEP 3
-
-# From Paul Eggert <eggert@twinsun.com> (1993-11-18):
+# From Ephraim Silverberg (2001-01-11):
+#
+# I coined "IST/IDT" circa 1988.  Until then there were three
+# different abbreviations in use:
+#
+# JST  Jerusalem Standard Time [Danny Braniss, Hebrew University]
+# IZT  Israel Zonal (sic) Time [Prof. Haim Papo, Technion]
+# EEST Eastern Europe Standard Time [used by almost everyone else]
+#
+# Since timezones should be called by country and not capital cities,
+# I ruled out JST.  As Israel is in Asia Minor and not Eastern Europe,
+# EEST was equally unacceptable.  Since "zonal" was not compatible with
+# any other timezone abbreviation, I felt that 'IST' was the way to go
+# and, indeed, it has received almost universal acceptance in timezone
+# settings in Israeli computers.
 #
-# Shanks gives the following rules for Jerusalem from 1918 through 1991.
-# After 1989 Shanks often disagrees with Silverberg; we go with Silverberg.
+# In any case, I am happy to share timezone abbreviations with India,
+# high on my favorite-country list (and not only because my wife's
+# family is from India).
 
-# From Shanks (1991):
+# From Shanks:
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Zion    1940    only    -       Jun      1      0:00    1:00    D
 Rule   Zion    1942    1944    -       Nov      1      0:00    0       S
@@ -507,22 +587,31 @@ Rule      Zion    1987    only    -       Sep     13      0:00    0       S
 Rule   Zion    1988    only    -       Apr      9      0:00    1:00    D
 Rule   Zion    1988    only    -       Sep      3      0:00    0       S
 
-# From Ephraim Silverberg (1996-01-02):
-#
+# From Ephraim Silverberg <ephraim@cs.huji.ac.il>
+# (1997-03-04, 1998-03-16, 1998-12-28, 2000-01-17 and 2000-07-25):
+
 # According to the Office of the Secretary General of the Ministry of
 # Interior, there is NO set rule for Daylight-Savings/Standard time changes.
-# Each year they decide anew what havoc to wreak on the country.  However,
-# there is a "supposed" set of rules which is subject to change depending
-# on the party the Minister of Interior, the size of the coalition
-# government, the phase of the moon and the direction of the wind.  Hence,
-# changes may need to be made on a semi-annual basis.  One thing is entrenched
-# in law, however: that there must be at least 150 days of daylight savings
-# time annually.  Ever since 1993, the change to daylight savings time has
-# been from midnight Thursday night to 1 a.m. Friday morning and the change
-# back to standard time on Saturday night from midnight daylight savings time
-# to 11 p.m. standard time.  1996 is an exception to this rule where the
-# change back to standard time takes place on Sunday night instead of Saturday
-# night to avoid conflicts with the Jewish New Year.
+# One thing is entrenched in law, however: that there must be at least 150
+# days of daylight savings time annually.  From 1993-1998, the change to
+# daylight savings time was on a Friday morning from midnight IST to
+# 1 a.m IDT; up until 1998, the change back to standard time was on a
+# Saturday night from midnight daylight savings time to 11 p.m. standard
+# time.  1996 is an exception to this rule where the change back to standard
+# time took place on Sunday night instead of Saturday night to avoid
+# conflicts with the Jewish New Year.  In 1999, the change to
+# daylight savings time was still on a Friday morning but from
+# 2 a.m. IST to 3 a.m. IDT; furthermore, the change back to standard time
+# was also on a Friday morning from 2 a.m. IDT to 1 a.m. IST for
+# 1999 only.  In the year 2000, the change to daylight savings time was
+# similar to 1999, but although the change back will be on a Friday, it
+# will take place from 1 a.m. IDT to midnight IST.  Starting in 2001, all
+# changes to/from will take place at 1 a.m. old time, but now there is no
+# rule as to what day of the week it will take place in as the start date
+# (except in 2003) is the night after the Passover Seder (i.e. the eve
+# of the 16th of Nisan in the lunar Hebrew calendar) and the end date
+# (except in 2002) is three nights before Yom Kippur [Day of Atonement]
+# (the eve of the 7th of Tishrei in the lunar Hebrew calendar).
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Zion    1989    only    -       Apr     30      0:00    1:00    D
@@ -538,34 +627,69 @@ Rule      Zion    1993    only    -       Sep      5      0:00    0       S
 
 # The dates for 1994-1995 were obtained from Office of the Spokeswoman for the
 # Ministry of Interior, Jerusalem, Israel.  The spokeswoman can be reached by
-# calling the switchboard at 972-2-701411 and asking for the spokeswoman.
+# calling the office directly at 972-2-6701447 or 972-2-6701448.
 
-# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Zion    1994    only    -       Apr      1      0:00    1:00    D
 Rule   Zion    1994    only    -       Aug     28      0:00    0       S
 Rule   Zion    1995    only    -       Mar     31      0:00    1:00    D
 Rule   Zion    1995    only    -       Sep      3      0:00    0       S
 
-# The dates for 1996-1998 were also obtained from Office of the Spokeswoman
-# for the Ministry of Interior, Jerusalem, Israel.  The official announcement
-# can be viewed (in Hebrew) at the following URL:
+# The dates for 1996 were determined by the Minister of Interior of the
+# time, Haim Ramon.  The official announcement regarding 1996-1998
+# (with the dates for 1997-1998 no longer being relevant) can be viewed at:
+#
+#   ftp://ftp.huji.ac.il/pub/tz/announcements/1996-1998.ramon.ps.gz
+#
+# The dates for 1997-1998 were altered by his successor, Rabbi Eli Suissa.
+#
+# The official announcements for the years 1997-1999 can be viewed at:
 #
-#   ftp://ftp.huji.ac.il/pub/misc/timezones/announcements/1996-1998.ps.gz
+#   ftp://ftp.huji.ac.il/pub/tz/announcements/YYYY.ps.gz
 #
-# Caveat emptor: The dates for the years 1996-1998 were originally announced
-# on 1995-08-31, by the previous Minister of Interior.  The new Minister
-# of Interior changed the dates on 1996-01-01, to take into account the
-# desires of certain portions of Israeli society (the next election is in the
-# Fall of 1996).  After this (1996) year's Daylight Savings Time is over, the
-# new minister has announced that a study will be conducted as to the wishes of
-# the populace regarding the length of Daylight Savings Time and the Interior
-# Committee will meet to review the results of the study and make any necessary
-# changes to the 1997-1998 dates.  Never a dull moment in the State of Israel.
+#       where YYYY is the relevant year.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Zion    1996    1998    -       Mar     Fri>=14 0:00    1:00    D
+Rule   Zion    1996    only    -       Mar     15      0:00    1:00    D
 Rule   Zion    1996    only    -       Sep     16      0:00    0       S
-Rule   Zion    1997    1998    -       Oct     Sun>=14 0:00    0       S
+Rule   Zion    1997    only    -       Mar     21      0:00    1:00    D
+Rule   Zion    1997    only    -       Sep     14      0:00    0       S
+Rule   Zion    1998    only    -       Mar     20      0:00    1:00    D
+Rule   Zion    1998    only    -       Sep      6      0:00    0       S
+Rule   Zion    1999    only    -       Apr      2      2:00    1:00    D
+Rule   Zion    1999    only    -       Sep      3      2:00    0       S
+
+# The Knesset Interior Committee has changed the dates for 2000 for
+# the third time in just over a year and have set new dates for the
+# years 2001-2004 as well.
+#
+# The official announcement for the start date of 2000 can be viewed at:
+#
+#      ftp://ftp.huji.ac.il/pub/tz/announcements/2000-start.ps.gz
+#
+# The official announcement for the end date of 2000 and the dates
+# for the years 2001-2004 can be viewed at:
+#
+#      ftp://ftp.huji.ac.il/pub/tz/announcements/2000-2004.ps.gz
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Zion    2000    only    -       Apr     14      2:00    1:00    D
+Rule   Zion    2000    only    -       Oct      6      1:00    0       S
+Rule   Zion    2001    only    -       Apr      9      1:00    1:00    D
+Rule   Zion    2001    only    -       Sep     24      1:00    0       S
+Rule   Zion    2002    only    -       Mar     29      1:00    1:00    D
+Rule   Zion    2002    only    -       Oct      7      1:00    0       S
+Rule   Zion    2003    only    -       Mar     28      1:00    1:00    D
+Rule   Zion    2003    only    -       Oct      3      1:00    0       S
+Rule   Zion    2004    only    -       Apr      7      1:00    1:00    D
+Rule   Zion    2004    only    -       Sep     22      1:00    0       S
+
+# From Paul Eggert (2000-07-25):
+# Here are guesses for rules after 2004.
+# They are probably wrong, but they are more likely than no DST at all.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Zion    2005    max     -       Apr      1      1:00    1:00    D
+Rule   Zion    2005    max     -       Oct      1      1:00    0       S
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Jerusalem  2:20:56 -       LMT     1880
@@ -592,36 +716,76 @@ Zone      Asia/Jerusalem  2:20:56 -       LMT     1880
 # but the only locations using it were US military bases.
 # We go with Shanks and omit daylight saving in those years for Asia/Tokyo.
 
+# From Hideyuki Suzuki (1998-11-09):
+# 'Tokyo' usually stands for the former location of Tokyo Astronomical
+# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
+# This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
+# edited by National Astronomical Observatory of Japan....
+# JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
+# The law is enacted on 1886-07-07.
+
+# From Hideyuki Suzuki (1998-11-16):
+# The ordinance No. 51 (1886) established "standard time" in Japan,
+# which stands for the time on E 135 degree.
+# In the ordinance No. 167 (1895), "standard time" was renamed to "central
+# standard time".  And the same ordinance also established "western standard
+# time", which stands for the time on E 120 degree....  But "western standard
+# time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
+# 167, there is no mention regarding for what place western standard time is
+# standard....
+#
+# I wrote "ordinance" above, but I don't know how to translate.
+# In Japanese it's "chokurei", which means ordinance from emperor.
+
+# Shanks claims JST in use since 1896, and that a few places (e.g. Ishigaki)
+# use +0800; go with Suzuki.  Guess that all ordinances took effect on Jan 1.
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Tokyo      9:19:04 -       LMT     1896
+Zone   Asia/Tokyo      9:18:59 -       LMT     1887 Dec 31 15:00u
+                       9:00    -       JST     1896
+                       9:00    -       CJT     1938
                        9:00    -       JST
-Zone   Asia/Ishigaki   8:16:36 -       LMT     1896
-                       8:00    -       CST
-# There is no information for Marcus.
-# Other Japanese possessions are probably like Asia/Tokyo.
+# Since 1938, all Japanese possessions have been like Asia/Tokyo.
 
 # Jordan
+#
+# From <a href="http://star.arabia.com/990701/JO9.html">
+# Jordan Week (1999-07-01) </a> via Steffen Thorsen (1999-09-09):
+# Clocks in Jordan were forwarded one hour on Wednesday at midnight,
+# in accordance with the government's decision to implement summer time
+# all year round.
+#
+# From <a href="http://star.arabia.com/990930/JO9.html">
+# Jordan Week (1999-09-30) </a> via Steffen Thorsen (1999-11-09):
+# Winter time starts today Thursday, 30 September. Clocks will be turned back
+# by one hour.  This is the latest government decision and it's final!
+# The decision was taken because of the increase in working hours in
+# government's departments from six to seven hours.
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule    Jordan 1973    only    -       Jun     6       0:00    1:00    S
-Rule    Jordan 1973    1975    -       Oct     1       0:00    0       -
-Rule    Jordan 1974    1977    -       May     1       0:00    1:00    S
-Rule    Jordan 1976    only    -       Nov     1       0:00    0       -
-Rule    Jordan 1977    only    -       Oct     1       0:00    0       -
-Rule    Jordan 1978    only    -       Apr     30      0:00    1:00    S
-Rule    Jordan 1978    only    -       Sep     30      0:00    0       -
-Rule    Jordan 1985    only    -       Apr     1       0:00    1:00    S
-Rule    Jordan 1985    only    -       Oct     1       0:00    0       -
-Rule    Jordan 1986    1988    -       Apr     Fri>=1  0:00    1:00    S
-Rule    Jordan 1986    1990    -       Oct     Fri>=1  0:00    0       -
-Rule    Jordan 1989    only    -       May     8       0:00    1:00    S
-Rule    Jordan 1990    only    -       Apr     27      0:00    1:00    S
-Rule    Jordan 1991    only    -       Apr     17      0:00    1:00    S
-Rule    Jordan 1991    only    -       Sep     27      0:00    0       -
-Rule    Jordan 1992    only    -       Apr     10      0:00    1:00    S
-Rule    Jordan 1992    1993    -       Oct     Fri>=1  0:00    0       -
-Rule    Jordan 1993    max     -       Apr     Fri>=1  0:00    1:00    S
-Rule    Jordan 1994    only    -       Sep     Fri>=15 0:00    0       -
-Rule    Jordan 1995    max     -       Sep     Fri>=15 0:00s   0       -
+Rule   Jordan  1973    only    -       Jun     6       0:00    1:00    S
+Rule   Jordan  1973    1975    -       Oct     1       0:00    0       -
+Rule   Jordan  1974    1977    -       May     1       0:00    1:00    S
+Rule   Jordan  1976    only    -       Nov     1       0:00    0       -
+Rule   Jordan  1977    only    -       Oct     1       0:00    0       -
+Rule   Jordan  1978    only    -       Apr     30      0:00    1:00    S
+Rule   Jordan  1978    only    -       Sep     30      0:00    0       -
+Rule   Jordan  1985    only    -       Apr     1       0:00    1:00    S
+Rule   Jordan  1985    only    -       Oct     1       0:00    0       -
+Rule   Jordan  1986    1988    -       Apr     Fri>=1  0:00    1:00    S
+Rule   Jordan  1986    1990    -       Oct     Fri>=1  0:00    0       -
+Rule   Jordan  1989    only    -       May     8       0:00    1:00    S
+Rule   Jordan  1990    only    -       Apr     27      0:00    1:00    S
+Rule   Jordan  1991    only    -       Apr     17      0:00    1:00    S
+Rule   Jordan  1991    only    -       Sep     27      0:00    0       -
+Rule   Jordan  1992    only    -       Apr     10      0:00    1:00    S
+Rule   Jordan  1992    1993    -       Oct     Fri>=1  0:00    0       -
+Rule   Jordan  1993    1998    -       Apr     Fri>=1  0:00    1:00    S
+Rule   Jordan  1994    only    -       Sep     Fri>=15 0:00    0       -
+Rule   Jordan  1995    1998    -       Sep     Fri>=15 0:00s   0       -
+Rule   Jordan  1999    only    -       Jul      1      0:00s   1:00    S
+Rule   Jordan  1999    max     -       Sep     lastThu 0:00s   0       -
+Rule   Jordan  2000    max     -       Mar     lastThu 0:00s   1:00    S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Amman      2:23:44 -       LMT     1931
                        2:00    Jordan  EE%sT
@@ -635,7 +799,7 @@ Zone        Asia/Amman      2:23:44 -       LMT     1931
 # IATA SSIM mentions a third time zone in Kazakhstan.
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Alma-Ata   5:07:48 -       LMT     1924 May  2 # or Almaty
+Zone   Asia/Almaty     5:07:48 -       LMT     1924 May  2 # or Alma-Ata
                        5:00    -       ALMT    1957 Mar # Alma-Ata Time
                        6:00 RussiaAsia ALM%sT  1991 Mar 31 2:00s
                        5:00    1:00    ALMST   1991 Sep 29 2:00s
@@ -655,27 +819,30 @@ Zone      Asia/Aqtau      3:21:04 -       LMT     1924 May  2 # or Aktau
                        5:00 E-EurAsia  AQT%sT  1995 Sep lastSun
                        4:00 E-EurAsia  AQT%sT
 
-# Kirgizstan
+# Kyrgyzstan (Kirgizstan)
+# Transitions through 1991 are from Shanks.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Kirgiz  1992    max     -       Apr     Sun>=7  0:00    1:00    S
-Rule   Kirgiz  1991    max     -       Sep     lastSun 0:00    0       -
+Rule   Kirgiz  1992    1996    -       Apr     Sun>=7  0:00    1:00    S
+Rule   Kirgiz  1992    1996    -       Sep     lastSun 0:00    0       -
+Rule   Kirgiz  1997    max     -       Mar     lastSun 2:30    1:00    S
+Rule   Kirgiz  1997    max     -       Oct     lastSun 2:30    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Bishkek    4:58:24 -       LMT     1924 May  2
-                       5:00    -       FRUT    1957 Mar    # Frunze Time
+                       5:00    -       FRUT    1930 Jun 21 # Frunze Time
                        6:00 RussiaAsia FRU%sT  1991 Mar 31 2:00s
-                       5:00    1:00    FRUST   1991 Aug 31 # independence
+                       5:00    1:00    FRUST   1991 Aug 31 2:00 # independence
                        5:00    Kirgiz  KG%sT               # Kirgizstan Time
 
 ###############################################################################
 
-# Korea
+# Korea (North and South)
 
 # From Guy Harris:
 # According to someone at the Korean Times in San Francisco,
 # Daylight Savings Time was not observed until 1987.  He did not know
 # at what time of day DST starts or ends.
 
-# From Shanks (1991):
+# From Shanks:
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   ROK     1960    only    -       May     15      0:00    1:00    D
 Rule   ROK     1960    only    -       Sep     13      0:00    0       S
@@ -708,7 +875,7 @@ Zone        Asia/Kuwait     3:11:56 -       LMT     1950
 
 # Laos
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Vientiane  6:50:24 -       LMT     1906 Jun  9
+Zone   Asia/Vientiane  6:50:24 -       LMT     1906 Jun  9 # or Viangchan
                        7:06:20 -       SMT     1911 Mar 11 0:01 # Saigon MT?
                        7:00    -       ICT     1912 May
                        8:00    -       ICT     1931 May
@@ -738,7 +905,8 @@ Rule        Lebanon 1989    only    -       May     10      0:00    1:00    S
 Rule   Lebanon 1990    1992    -       May     1       0:00    1:00    S
 Rule   Lebanon 1992    only    -       Oct     4       0:00    0       -
 Rule   Lebanon 1993    max     -       Mar     lastSun 0:00    1:00    S
-Rule   Lebanon 1993    max     -       Sep     lastSun 0:00    0       -
+Rule   Lebanon 1993    1998    -       Sep     lastSun 0:00    0       -
+Rule   Lebanon 1999    max     -       Oct     lastSun 0:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Beirut     2:22:00 -       LMT     1880
                        2:00    Lebanon EE%sT
@@ -770,29 +938,62 @@ Zone      Indian/Maldives 4:54:00 -       LMT     1880    # Male
                        5:00    -       MVT             # Maldives Time
 
 # Mongolia
-# Shanks says that Mongolia has three time zones, but usno1995 and
-# <URL:http://www.odci.gov/cia/publications/95fact/802389h.gif> (1995)
+
+# Shanks says that Mongolia has three time zones, but usno1995 and the CIA map
+# Standard Time Zones of the World (1997-01)
 # both say that it has just one.
-# Let's comment out the western and eastern Mongolian time zones
-# till we know what their principal towns are.
+
+# From Oscar van Vlijmen (1999-12-11):
+# <a href="http://www.mongoliatourism.gov.mn/general.htm">
+# General Information Mongolia
+# </a> (1999-09)
+# "Time: Mongolia has two time zones. Three westernmost provinces of
+# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
+# the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
+# eight hours."
+
+# From Rives McDow (1999-12-13):
+# Mongolia discontinued the use of daylight savings time in 1999; 1998
+# being the last year it was implemented.  The dates of implementation I am
+# unsure of, but most probably it was similar to Russia, except for the time
+# of implementation may have been different....
+# Some maps in the past have indicated that there was an additional time
+# zone in the eastern part of Mongolia, including the provinces of Dornod,
+# Suhbaatar, and possibly Khentij.
+
+# From Paul Eggert (1999-12-15):
+# For now, we'll comment out the east zone (Choybalsan)
+# and use Shanks's and the IATA's data for the daylight-saving rules.
+# Naming and spelling is tricky in Mongolia.
+# We'll use Hovd (also spelled Chovd and Khovd) to represent the west zone;
+# the capital of the Hovd province is sometimes called Hovd, sometimes Dund-Us,
+# and sometimes Jirgalanta (with variant spellings), but the name Hovd
+# is good enough for our purposes.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Mongol  1981    1984    -       Apr     1       0:00    1:00    S
 Rule   Mongol  1981    1984    -       Oct     1       0:00    0       -
 Rule   Mongol  1985    1990    -       Mar     lastSun 2:00    1:00    S
 Rule   Mongol  1985    1990    -       Sep     lastSun 3:00    0       -
-Rule   Mongol  1991    max     -       Mar     lastSun 0:00    1:00    S
+Rule   Mongol  1991    1998    -       Mar     lastSun 0:00    1:00    S
 Rule   Mongol  1991    1995    -       Sep     lastSun 0:00    0       -
-Rule   Mongol  1996    max     -       Oct     Fri>=22 0:00    0       -
+# IATA SSIM (1996-09) says 1996-10-25; go with Shanks.
+Rule   Mongol  1996    only    -       Oct     lastSun 0:00    0       -
+Rule   Mongol  1997    1998    -       Sep     lastSun 0:00    0       -
+# IATA SSIM (1999-09) says Mongolia no longer observes DST.
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-#Zone  Asia/Dariv      6:14:32 -       LMT     1905 Aug
-#                      6:00    -       DART    1978    # Dariv Time
-#                      7:00    Mongol  DAR%sT
-Zone   Asia/Ulan_Bator 7:07:32 -       LMT     1905 Aug
-                       7:00    -       ULAT    1978    # Ulan Bator Time
+Zone   Asia/Hovd       6:06:36 -       LMT     1905 Aug
+                       6:00    -       HOVT    1978    # Hovd Time
+                       7:00    Mongol  HOV%sT
+Zone   Asia/Ulaanbaatar 7:07:32 -      LMT     1905 Aug
+                       7:00    -       ULAT    1978    # Ulaanbaatar Time
                        8:00    Mongol  ULA%sT
-#Zone Asia/Baruun-Urt  7:33:00 -       LMT     1905 Aug
-#                      8:00    -       BART    1978    # Baruun-Urt Time
-#                      9:00    Mongol  BAR%sT
+# We're not sure about this entry yet, so we'll omit it for now.
+#Zone Asia/Choybalsan  7:38:00 -       LMT     1905 Aug
+#                      8:00    -       CHOT    1978    # Choybalsan Time
+#                      9:00    Mongol  CHO%sT  19??
+#                      8:00    Mongol  ULA%sT
 
 # Nepal
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -815,7 +1016,80 @@ Zone      Asia/Karachi    4:28:12 -       LMT     1907
                        5:00    -       PKT     # Pakistan Time
 
 # Palestine
-# These rules for Egypt are stolen from the `africa' file.
+
+# From Amos Shapir <amos@nsof.co.il> (1998-02-15):
+#
+# From 1917 until 1948-05-15, all of Palestine, including the parts now
+# known as the Gaza Strip and the West Bank, was under British rule.
+# Therefore the rules given for Israel for that period, apply there too...
+#
+# The Gaza Strip was under Egyptian rule between 1948-05-15 until 1967-06-05
+# (except a short occupation by Israel from 1956-11 till 1957-03, but no
+# time zone was affected then).  It was never formally annexed to Egypt,
+# though.
+#
+# The rest of Palestine was under Jordanian rule at that time, formally
+# annexed in 1950 as the West Bank (and the word "Trans" was dropped from
+# the country's previous name of "the Hashemite Kingdom of the
+# Trans-Jordan").  So the rules for Jordan for that time apply.  Major
+# towns in that area are Nablus (Shchem), El-Halil (Hebron), Ramallah, and
+# East Jerusalem.
+#
+# Both areas were occupied by Israel in June 1967, but not annexed (except
+# for East Jerusalem).  They were on Israel time since then; there might
+# have been a Military Governor's order about time zones, but I'm not aware
+# of any (such orders may have been issued semi-annually whenever summer
+# time was in effect, but maybe the legal aspect of time was just neglected).
+#
+# The Palestinian Authority was established in 1993, and got hold of most
+# towns in the West Bank and Gaza by 1995.  I know that in order to
+# demonstrate...independence, they have been switching to
+# summer time and back on a different schedule than Israel's, but I don't
+# know when this was started, or what algorithm is used (most likely the
+# Jordanian one).
+#
+# To summarize, the table should probably look something like that:
+#
+# Area \ when | 1918-1947 | 1948-1967 | 1967-1995 | 1996-
+# ------------+-----------+-----------+-----------+-----------
+# Israel      | Zion      | Zion      | Zion      | Zion
+# West bank   | Zion      | Jordan    | Zion      | Jordan
+# Gaza        | Zion      | Egypt     | Zion      | Jordan
+#
+# I guess more info may be available from the PA's web page (if/when they
+# have one).
+
+# From Paul Eggert (1998-02-25):
+# Shanks writes that Gaza did not observe DST until 1957, but we'll go
+# with Shapir and assume that it observed DST from 1940 through 1947,
+# and that it used Jordanian rules starting in 1996.
+# We don't yet need a separate entry for the West Bank, since
+# the only differences between it and Gaza that we know about
+# occurred before our cutoff date of 1970.
+# However, as we get more information, we may need to add entries
+# for parts of the West Bank as they transitioned from Israel's rules
+# to Palestine's rules.  If you have more info about this, please
+# send it to tz@elsie.nci.nih.gov for incorporation into future editions.
+
+# From IINS News Service - Israel - 1998-03-23 10:38:07 Israel time,
+# forwarded by Ephraim Silverberg:
+#
+# Despite the fact that Israel changed over to daylight savings time
+# last week, the PLO Authority (PA) has decided not to turn its clocks
+# one-hour forward at this time.  As a sign of independence from Israeli rule,
+# the PA has decided to implement DST in April.
+
+# From Paul Eggert (1999-09-20):
+# Daoud Kuttab writes in
+# <a href="http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html">
+# Holiday havoc
+# </a> (Jerusalem Post, 1999-04-22) that
+# the Palestinian National Authority changed to DST on 1999-04-15.
+# I vaguely recall that they switch back in October (sorry, forgot the source).
+# For now, let's assume that the spring switch was at 24:00,
+# and that they switch at 0:00 on the 3rd Fridays of April and October.
+
+# The rules for Egypt are stolen from the `africa' file.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule EgyptAsia 1957    only    -       May     10      0:00    1:00    S
 Rule EgyptAsia 1957    1958    -       Oct      1      0:00    0       -
@@ -823,17 +1097,26 @@ Rule EgyptAsia   1958    only    -       May      1      0:00    1:00    S
 Rule EgyptAsia 1959    1967    -       May      1      1:00    1:00    S
 Rule EgyptAsia 1959    1965    -       Sep     30      3:00    0       -
 Rule EgyptAsia 1966    only    -       Oct      1      3:00    0       -
+
+Rule Palestine 1999    max     -       Apr     Fri>=15 0:00    1:00    S
+Rule Palestine 1999    max     -       Oct     Fri>=15 0:00    0       -
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Gaza       2:17:52 -       LMT     1900 Oct
-                       2:00    -       EET     1957 May 10
-                       2:00 EgyptAsia  EE%sT   1967 Jun 30
-                       2:00    Zion    I%sT
+                       2:00    Zion    EET     1948 May 15
+                       2:00 EgyptAsia  EE%sT   1967 Jun  5
+                       2:00    Zion    I%sT    1996
+                       2:00    Jordan  EE%sT   1999
+                       2:00 Palestine  EE%sT
 
 # Paracel Is
 # no information
 
 # Philippines
-# Howse writes (p 162) that until 1844 the Philippines kept American date.
+# On 1844-08-16, Narciso Claveria, governor-general of the
+# Philippines, issued a proclamation announcing that 1844-12-30 was to
+# be immediately followed by 1845-01-01.  Robert H. van Gent has a
+# transcript of the decree in <http://www.phys.uu.nl/~vgent/idl/idl.htm>.
 # The rest of this data is from Shanks.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Phil    1936    only    -       Nov     1       0:00    1:00    S
@@ -843,7 +1126,7 @@ Rule       Phil    1954    only    -       Jul     1       0:00    0       -
 Rule   Phil    1978    only    -       Mar     22      0:00    1:00    S
 Rule   Phil    1978    only    -       Sep     21      0:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Manila     -15:56:00 -     LMT     1844
+Zone   Asia/Manila     -15:56:00 -     LMT     1844 Dec 31
                        8:04:00 -       LMT     1899 May 11
                        8:00    Phil    PH%sT   1942 May
                        9:00    -       JST     1944 Nov
@@ -851,7 +1134,7 @@ Zone       Asia/Manila     -15:56:00 -     LMT     1844
 
 # Qatar
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Qatar      3:26:08 -       LMT     1920            # Al Dawhah
+Zone   Asia/Qatar      3:26:08 -       LMT     1920    # Al Dawhah / Doha
                        4:00    -       GST     1972 Jun
                        3:00    -       AST
 
@@ -877,19 +1160,29 @@ Zone     Asia/Singapore  6:55:24 -       LMT     1880
 
 # Sri Lanka
 # From Paul Eggert (1996-09-03):
-# <URL:http://www.virtual-pc.com/lankaweb/news/items/240596-2.html> (1996-05-24)
+# "Sri Lanka advances clock by an hour to avoid blackout"
+# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
+# no longer available as of 1999-08-17)
 # reported ``the country's standard time will be put forward by one hour at
 # midnight Friday (1830 GMT) `in the light of the present power crisis'.''
-# Transitions before 1996 are from Shanks (1991).
+#
+# From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
+# by Shamindra in
+# <a href="news:54rka5$m5h@mtinsc01-mgt.ops.worldnet.att.net">
+# Daily News - Hot News Section (1996-10-26)
+# </a>:
+# With effect from 12.30 a.m. on 26th October 1996
+# Sri Lanka will be six (06) hours ahead of GMT.
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Colombo    5:19:24 -       LMT     1880
-                       5:20    -       CEYT    1906    # Ceylon Time
+                       5:19:32 -       MMT     1906    # Moratuwa Mean Time
                        5:30    -       IST     1942 Jan  5
                        5:30    0:30    IHST    1942 Sep
                        5:30    1:00    IST     1945 Oct 16 2:00
                        5:30    -       IST     1996 May 25 0:00
-                       6:30    -       LKT     # Sri Lanka Time
+                       6:30    -       LKT     1996 Oct 26 0:30
+                       6:00    -       LKT
 
 # Syria
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -921,20 +1214,25 @@ Rule     Syria   1991    1992    -       Oct      1      0:00    0       -
 Rule   Syria   1992    only    -       Apr      8      0:00    1:00    S
 Rule   Syria   1993    only    -       Mar     26      0:00    1:00    S
 Rule   Syria   1993    only    -       Sep     25      0:00    0       -
-# IATA SSIM (1996-09) says 1997-03-31; assume that it should be 1997-04-01.
-Rule   Syria   1994    max     -       Apr      1      0:00    1:00    S
+# IATA SSIM (1998-02) says 1998-04-02;
+# (1998-09) says 1999-03-29 and 1999-09-29; (1999-02) says 1999-04-02,
+# 2000-04-02, and 2001-04-02; (1999-09) says 2000-03-31 and 2001-03-31;
+# ignore all these claims and go with Shanks.
+Rule   Syria   1994    1996    -       Apr      1      0:00    1:00    S
 Rule   Syria   1994    max     -       Oct      1      0:00    0       -
+Rule   Syria   1997    1998    -       Mar     lastMon 0:00    1:00    S
+Rule   Syria   1999    max     -       Apr      1      0:00    1:00    S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Damascus   2:25:12 -       LMT     1920
+Zone   Asia/Damascus   2:25:12 -       LMT     1920    # Dimashq
                        2:00    Syria   EE%sT
 
 # Tajikistan
+# From Shanks.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Dushanbe   4:35:12 -       LMT     1924 May  2
-                       5:00    -       DUST    1957 Mar    # Dushanbe Time
+                       5:00    -       DUST    1930 Jun 21 # Dushanbe Time
                        6:00 RussiaAsia DUS%sT  1991 Mar 31 2:00s
-                       5:00    1:00    DUSST   1991 Sep  9 # independence
-                       5:00 RussiaAsia TJ%sT   1992
+                       5:00    1:00    DUSST   1991 Sep  9 2:00s
                        5:00    -       TJT                 # Tajikistan Time
 
 # Thailand
@@ -944,14 +1242,14 @@ Zone     Asia/Bangkok    6:42:04 -       LMT     1880
                        7:00    -       ICT
 
 # Turkmenistan
+# From Shanks.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Ashkhabad  3:53:32 -       LMT     1924 May  2 # or Ashgabat
-                       4:00    -       ASHT    1957 Mar    # Ashkhabad Time
-                       5:00 RussiaAsia ASH%sT  1991 Mar 31 2:00s
-                       4:00    1:00    ASHST   1991 Sep 29 2:00s
-                       4:00    -       ASHT    1991 Oct 27 # independence
-                       4:00    -       TMT     1992 Jan 19 2:00s
-                       5:00    -       TMT     # Turkmenistan Time
+Zone   Asia/Ashgabat   3:53:32 -       LMT     1924 May  2 # or Ashkhabad
+                       4:00    -       ASHT    1930 Jun 21 # Ashkhabad Time
+                       5:00 RussiaAsia ASH%sT  1991 Mar 31 2:00
+                       4:00 RussiaAsia ASH%sT  1991 Oct 27 # independence
+                       4:00 RussiaAsia TM%sT   1992 Jan 19 2:00
+                       5:00    -       TMT
 
 # United Arab Emirates
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -960,23 +1258,28 @@ Zone     Asia/Dubai      3:41:12 -       LMT     1920
 
 # Uzbekistan
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Samarkand  4:27:12 -       LMT     1924 May  2
+                       4:00    -       SAMT    1930 Jun 21 # Samarkand Time
+                       5:00    -       SAMT    1981 Apr  1
+                       5:00    1:00    SAMST   1981 Oct  1
+                       6:00 RussiaAsia TAS%sT  1991 Mar 31 2:00 # Tashkent Time
+                       5:00 RussiaAsia TAS%sT  1991 Sep  1 # independence
+                       5:00 RussiaAsia UZ%sT   1992
+                       5:00 RussiaAsia UZ%sT   1993
+                       5:00    -       UZT
 Zone   Asia/Tashkent   4:37:12 -       LMT     1924 May  2
-                       5:00    -       TAST    1957 Mar    # Tashkent Time
+                       5:00    -       TAST    1930 Jun 21 # Tashkent Time
                        6:00 RussiaAsia TAS%sT  1991 Mar 31 2:00s
-                       5:00    1:00    TASST   1991 Sep 29 2:00s
-                       5:00    -       UZT                 # Uzbekistan Time
-# Shanks has Tashkent using DST after 1991, but usno1995 says they don't.
-# Guess no DST after 1991.
-# <URL:http://www.odci.gov/cia/publications/95fact/802389h.gif> (1995)
-# says that Uzbekistan has two time zones, but a cable
-# <URL:http://www.itaiep.doc.gov/bisnis/cables/960510uz.html> (1996-05-10)
-# from the American Embassy in Tashkent implies that they have just one.
+                       5:00 RussiaAsia TAS%sT  1991 Sep  1 # independence
+                       5:00 RussiaAsia UZ%sT   1992
+                       5:00 RussiaAsia UZ%sT   1993
+                       5:00    -       UZT
 
 # Vietnam
 # From Paul Eggert <eggert@twinsun.com> (1993-11-18):
 # Saigon's official name is Thanh-Pho Ho Chi Minh, but it's too long.
 # We'll stick with the traditional name for now.
-# From Shanks (1991):
+# From Shanks:
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Saigon     7:06:40 -       LMT     1906 Jun  9
                        7:06:20 -       SMT     1911 Mar 11 0:01 # Saigon MT?
index e1e567a5bae4165f7920625f2c3cdd9661f42122..f0db6a9e1684b2024e92b443e3f6d1c0e1492c5f 100644 (file)
@@ -1,7 +1,6 @@
-#      $OpenBSD: australasia,v 1.5 1997/01/14 04:36:50 millert Exp $
-# @(#)australasia      7.31
+# @(#)australasia      7.64
 # This file also includes Pacific islands.
-
+# $FreeBSD: src/share/zoneinfo/australasia,v 1.19 2001/05/01 14:10:12 schweikh Exp $
 # Notes are at the end of this file
 
 ###############################################################################
@@ -9,26 +8,26 @@
 # Australia
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-# Shanks gives 1917 Jan 1 0:01; go with Whitman (and guess 2:00).
-Rule   Aus     1916    only    -       Oct      1      2:00    1:00    -
+Rule   Aus     1917    only    -       Jan      1      0:01    1:00    -
 Rule   Aus     1917    only    -       Mar     25      2:00    0       -
 Rule   Aus     1942    only    -       Jan      1      2:00    1:00    -
 Rule   Aus     1942    only    -       Mar     29      2:00    0       -
 Rule   Aus     1942    only    -       Sep     27      2:00    1:00    -
 Rule   Aus     1943    1944    -       Mar     lastSun 2:00    0       -
 Rule   Aus     1943    only    -       Oct      3      2:00    1:00    -
-# Whitman says W Australia didn't use DST in 1943/1944, and that
-# 1944/1945 was just like 1943/1944; go with Shanks.
+# Go with Whitman and the Australian National Standards Commission, which
+# says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
+# 1944/1945 was just like 1943/1944.
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 # Northern Territory
 Zone Australia/Darwin   8:43:20 -      LMT     1895 Feb
-                        9:30   -       CST     1917 Jan 1 0:01
+                        9:00   -       CST     1899 May
                         9:30   Aus     CST
 # Western Australia
 Zone Australia/Perth    7:43:24 -      LMT     1895 Dec
-                        8:00   -       WST     1917 Jan 1 0:01
-                        8:00   Aus     WST     1974 Oct lastSun 2:00s
+                        8:00   Aus     WST     1943 Jul
+                        8:00   -       WST     1974 Oct lastSun 2:00s
                         8:00   1:00    WST     1975 Mar Sun>=1 2:00s
                         8:00   -       WST     1983 Oct lastSun 2:00s
                         8:00   1:00    WST     1984 Mar Sun>=1 2:00s
@@ -49,19 +48,18 @@ Zone Australia/Perth         7:43:24 -      LMT     1895 Dec
 # so use Lindeman.
 #
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   AQ      1971    only    -       Oct     lastSun 2:00s   1:00    -
+Rule   AQ      1972    only    -       Feb     lastSun 2:00s   0       -
 Rule   AQ      1989    1991    -       Oct     lastSun 2:00s   1:00    -
 Rule   AQ      1990    1992    -       Mar     Sun>=1  2:00s   0       -
-Rule   Holiday 1989    1993    -       Oct     lastSun 2:00s   1:00    -
-Rule   Holiday 1990    1994    -       Mar     Sun>=1  2:00s   0       -
+Rule   Holiday 1992    1993    -       Oct     lastSun 2:00s   1:00    -
+Rule   Holiday 1993    1994    -       Mar     Sun>=1  2:00s   0       -
 Zone Australia/Brisbane        10:12:08 -      LMT     1895
-                       10:00   -       EST     1917 Jan 1 0:01
-                       10:00   Aus     EST     1971 Oct lastSun 2:00s
-                       10:00   1:00    EST     1972 Feb lastSun 2:00s
+                       10:00   Aus     EST     1971
                        10:00   AQ      EST
 Zone Australia/Lindeman  9:55:56 -     LMT     1895
-                       10:00   -       EST     1917 Jan 1 0:01
-                       10:00   Aus     EST     1971 Oct lastSun 2:00s
-                       10:00   1:00    EST     1972 Feb lastSun 2:00s
+                       10:00   Aus     EST     1971
+                       10:00   AQ      EST     1992 Jul
                        10:00   Holiday EST
 
 # South Australia
@@ -72,51 +70,58 @@ Rule        AS      1987    max     -       Oct     lastSun 2:00s   1:00    -
 Rule   AS      1972    only    -       Feb     27      2:00s   0       -
 Rule   AS      1973    1985    -       Mar     Sun>=1  2:00s   0       -
 Rule   AS      1986    1989    -       Mar     Sun>=15 2:00s   0       -
-Rule   AS      1990    1994    even    Mar     Sun>=18 2:00s   0       -
-Rule   AS      1990    1994    odd     Mar     Sun>=1  2:00s   0       -
+Rule   AS      1990    only    -       Mar     Sun>=18 2:00s   0       -
+Rule   AS      1991    only    -       Mar     Sun>=1  2:00s   0       -
+Rule   AS      1992    only    -       Mar     Sun>=18 2:00s   0       -
+Rule   AS      1993    only    -       Mar     Sun>=1  2:00s   0       -
+Rule   AS      1994    only    -       Mar     Sun>=18 2:00s   0       -
 Rule   AS      1995    max     -       Mar     lastSun 2:00s   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Australia/Adelaide        9:14:20 -       LMT     1895 Feb
                        9:00    -       CST     1899 May
-                       9:30    -       CST     1917 Jan 1 0:01
-                       9:30    Aus     CST     1971 Oct lastSun 2:00s
+                       9:30    Aus     CST     1971
                        9:30    AS      CST
 
 # Tasmania
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   AT      1967    only    -       Oct     1       2:00s   1:00    -
-Rule   AT      1968    only    -       Mar     31      2:00s   0       -
+Rule   AT      1967    only    -       Oct     Sun>=1  2:00s   1:00    -
+Rule   AT      1968    only    -       Mar     lastSun 2:00s   0       -
 Rule   AT      1968    1985    -       Oct     lastSun 2:00s   1:00    -
 Rule   AT      1969    1971    -       Mar     Sun>=8  2:00s   0       -
-Rule   AT      1972    only    -       Feb     27      2:00s   0       -
+Rule   AT      1972    only    -       Feb     lastSun 2:00s   0       -
 Rule   AT      1973    1981    -       Mar     Sun>=1  2:00s   0       -
 Rule   AT      1982    1983    -       Mar     lastSun 2:00s   0       -
 Rule   AT      1984    1986    -       Mar     Sun>=1  2:00s   0       -
-Rule   AT      1986    only    -       Oct     19      2:00s   1:00    -
+Rule   AT      1986    only    -       Oct     Sun>=15 2:00s   1:00    -
 Rule   AT      1987    1990    -       Mar     Sun>=15 2:00s   0       -
-Rule   AT      1987    1990    -       Oct     lastSun 2:00s   1:00    -
-Rule   AT      1991    max     -       Oct     Sun>=1  2:00s   1:00    -
+Rule   AT      1987    only    -       Oct     Sun>=22 2:00s   1:00    -
+Rule   AT      1988    1990    -       Oct     lastSun 2:00s   1:00    -
+Rule   AT      1991    1999    -       Oct     Sun>=1  2:00s   1:00    -
 Rule   AT      1991    max     -       Mar     lastSun 2:00s   0       -
+Rule   AT      2000    only    -       Aug     lastSun 2:00s   1:00    -
+Rule   AT      2001    max     -       Oct     Sun>=1  2:00s   1:00    -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Australia/Hobart  9:49:16 -       LMT     1895 Sep
-                       10:00   -       EST     1917 Jan 1 0:01
-                       10:00   Aus     EST     1967 Oct 1 2:00s
+                       10:00   -       EST     1916 Oct 1 2:00
+                       10:00   1:00    EST     1917 Feb
+                       10:00   Aus     EST     1967
                        10:00   AT      EST
 
 # Victoria
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   AV      1971    1985    -       Oct     lastSun 2:00s   1:00    -
-Rule   AV      1972    only    -       Feb     27      2:00s   0       -
+Rule   AV      1972    only    -       Feb     lastSun 2:00s   0       -
 Rule   AV      1973    1985    -       Mar     Sun>=1  2:00s   0       -
 Rule   AV      1986    1990    -       Mar     Sun>=15 2:00s   0       -
-Rule   AV      1986    only    -       Oct     19      2:00s   1:00    -
-Rule   AV      1987    max     -       Oct     lastSun 2:00s   1:00    -
+Rule   AV      1986    1987    -       Oct     Sun>=15 2:00s   1:00    -
+Rule   AV      1988    1999    -       Oct     lastSun 2:00s   1:00    -
 Rule   AV      1991    1994    -       Mar     Sun>=1  2:00s   0       -
 Rule   AV      1995    max     -       Mar     lastSun 2:00s   0       -
+Rule   AV      2000    only    -       Aug     lastSun 2:00s   1:00    -
+Rule   AV      2001    max     -       Oct     lastSun 2:00s   1:00    -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Australia/Melbourne 9:39:52 -     LMT     1895 Feb
-                       10:00   -       EST     1917 Jan 1 0:01
-                       10:00   Aus     EST     1971 Oct 31 2:00s
+                       10:00   Aus     EST     1971
                        10:00   AV      EST
 
 # New South Wales
@@ -128,57 +133,64 @@ Rule      AN      1982    only    -       Apr     Sun>=1  2:00s   0       -
 Rule   AN      1983    1985    -       Mar     Sun>=1  2:00s   0       -
 Rule   AN      1986    1989    -       Mar     Sun>=15 2:00s   0       -
 Rule   AN      1986    only    -       Oct     19      2:00s   1:00    -
-Rule   AN      1987    max     -       Oct     lastSun 2:00s   1:00    -
+Rule   AN      1987    1999    -       Oct     lastSun 2:00s   1:00    -
 Rule   AN      1990    1995    -       Mar     Sun>=1  2:00s   0       -
 Rule   AN      1996    max     -       Mar     lastSun 2:00s   0       -
+Rule   AN      2000    only    -       Aug     lastSun 2:00s   1:00    -
+Rule   AN      2001    max     -       Oct     lastSun 2:00s   1:00    -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Australia/Sydney  10:04:52 -      LMT     1895 Feb
-                       10:00   -       EST     1917 Jan 1 0:01
-                       10:00   Aus     EST     1971 Oct 31 2:00s
+                       10:00   Aus     EST     1971
                        10:00   AN      EST
 Zone Australia/Broken_Hill 9:25:48 -   LMT     1895 Feb
                        10:00   -       EST     1896 Aug 23
                        9:00    -       CST     1899 May
-                       9:30    -       CST     1917 Jan 1 0:01
-                       9:30    Aus     CST     1971 Oct 31 2:00s
-                       9:30    AN      CST
+                       9:30    Aus     CST     1971
+                       9:30    AN      CST     2000
+                       9:30    AS      CST
 
 # Lord Howe Island
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   LH      1981    1984    -       Oct     lastSun 2:00s   1:00    -
-Rule   LH      1982    1985    -       Mar     Sun>=1  2:00s   0       -
-Rule   LH      1985    only    -       Oct     lastSun 2:00s   0:30    -
-Rule   LH      1986    1989    -       Mar     Sun>=15 2:00s   0       -
-Rule   LH      1986    only    -       Oct     19      2:00s   0:30    -
-Rule   LH      1987    max     -       Oct     lastSun 2:00s   0:30    -
-Rule   LH      1990    1995    -       Mar     Sun>=1  2:00s   0       -
-Rule   LH      1996    max     -       Mar     lastSun 2:00s   0       -
+Rule   LH      1981    1984    -       Oct     lastSun 2:00    1:00    -
+Rule   LH      1982    1985    -       Mar     Sun>=1  2:00    0       -
+Rule   LH      1985    only    -       Oct     lastSun 2:00    0:30    -
+Rule   LH      1986    1989    -       Mar     Sun>=15 2:00    0       -
+Rule   LH      1986    only    -       Oct     19      2:00    0:30    -
+Rule   LH      1987    1999    -       Oct     lastSun 2:00    0:30    -
+Rule   LH      1990    1995    -       Mar     Sun>=1  2:00    0       -
+Rule   LH      1996    max     -       Mar     lastSun 2:00    0       -
+Rule   LH      2000    only    -       Aug     lastSun 2:00    0:30    -
+Rule   LH      2001    max     -       Oct     lastSun 2:00    0:30    -
 Zone Australia/Lord_Howe 10:36:20 -    LMT     1895 Feb
                        10:00   -       EST     1981 Mar
                        10:30   LH      LHST
 
 # Australian miscellany
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Indian/Christmas  7:02:52 -       LMT     1895 Feb
-                       7:00    -       CXT     # Christmas Island Time
 #
 # Ashmore Is, Cartier
 # no indigenous inhabitants; only seasonal caretakers
-# no information; probably like Australia/Perth
+# like Australia/Perth, says Turner
 #
 # Coral Sea Is
 # no indigenous inhabitants; only meteorologists
 # no information
 #
-# Macquarie, Manihiki, Penrhyn, Rakehanga
-# no information
+# Macquarie
+# permanent occupation (scientific station) since 1948;
+# sealing and penguin oil station operated 1888/1917
+# like Australia/Hobart, says Turner
 
+# Christmas
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Indian/Christmas  7:02:52 -       LMT     1895 Feb
+                       7:00    -       CXT     # Christmas Island Time
 
 # Cook Is
+# From Shanks:
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Cook    1978    only    -       Nov     12      0:00    0:30    HS
-Rule   Cook    1979    max     -       Mar     Sun>=1  0:00    0       -
-Rule   Cook    1979    max     -       Oct     lastSun 0:00    0:30    HS
+Rule   Cook    1979    1991    -       Mar     Sun>=1  0:00    0       -
+Rule   Cook    1979    1990    -       Oct     lastSun 0:00    0:30    HS
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Pacific/Rarotonga -10:39:04 -     LMT     1901            # Avarua
                        -10:30  -       CKT     1978 Nov 12     # Cook Is Time
@@ -190,9 +202,12 @@ Zone Pacific/Rarotonga     -10:39:04 -     LMT     1901            # Avarua
 Zone   Indian/Cocos    6:30    -       CCT     # Cocos Islands Time
 
 # Fiji
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Fiji    1998    1999    -       Nov     Sun>=1  2:00    1:00    S
+Rule   Fiji    1999    2000    -       Feb     lastSun 3:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Pacific/Fiji    11:53:40 -      LMT     1915 Oct 26     # Suva
-                       12:00   -       FJT     # Fiji Time
+                       12:00   Fiji    FJ%sT   # Fiji Time
 
 # French Polynesia
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -202,26 +217,15 @@ Zone      Pacific/Marquesas -9:18:00 -    LMT     1912 Oct
                         -9:30  -       MART    # Marquesas Time
 Zone   Pacific/Tahiti   -9:58:16 -     LMT     1912 Oct        # Papeete
                        -10:00  -       TAHT    # Tahiti Time
+# Clipperton (near North America) is administered from French Polynesia;
+# it is uninhabited.
 
 # Guam
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Pacific/Guam     9:39:00 -      LMT     1901            # Agana
-                       10:00   -       GST
-
-# Howland, Baker
-# uninhabited since World War II
-# no information; was probably like Pacific/Pago_Pago
-
-# Jarvis
-# uninhabited since 1958
-# no information; was probably like Pacific/Kiritimati
-
-# Johnston
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Pacific/Johnston  -10:00  -       HST
-
-# Kingman
-# uninhabited
+Zone   Pacific/Guam    -14:21:00 -     LMT     1844 Dec 31
+                        9:39:00 -      LMT     1901            # Agana
+                       10:00   -       GST     2000 Dec 23     # Guam
+                       10:00   -       ChST    # Chamorro Standard Time
 
 # Kiribati
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -238,9 +242,11 @@ Zone Pacific/Kiritimati    -10:29:20 -     LMT     1901
 
 # N Mariana Is
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Pacific/Saipan     9:43:00 -      LMT     1901
+Zone Pacific/Saipan    -14:17:00 -     LMT     1844 Dec 31
+                        9:43:00 -      LMT     1901
                         9:00   -       MPT     1969 Oct # N Mariana Is Time
-                       10:00   -       MPT
+                       10:00   -       MPT     2000 Dec 23
+                       10:00   -       ChST    # Chamorro Standard Time
 
 # Marshall Is
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -262,8 +268,9 @@ Zone Pacific/Truk   10:07:08 -      LMT     1901
 Zone Pacific/Ponape    10:32:52 -      LMT     1901            # Kolonia
                        11:00   -       PONT                    # Ponape Time
 Zone Pacific/Kosrae    10:51:56 -      LMT     1901
-                       11:00   -       PONT    1969 Oct
-                       12:00   -       KOST                    # Kosrae Time
+                       11:00   -       KOST    1969 Oct        # Kosrae Time
+                       12:00   -       KOST    1999
+                       11:00   -       KOST
 
 # Nauru
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -277,6 +284,9 @@ Zone        Pacific/Nauru   11:07:40 -      LMT     1921 Jan 15     # Uaobe
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   NC      1977    1978    -       Dec     Sun>=1  0:00    1:00    S
 Rule   NC      1978    1979    -       Feb     27      0:00    0       -
+Rule   NC      1996    only    -       Dec      1      2:00s   1:00    S
+# Shanks says the following was at 2:00; go with IATA.
+Rule   NC      1997    only    -       Mar      2      2:00s   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Pacific/Noumea  11:05:48 -      LMT     1912 Jan 13
                        11:00   NC      NC%sT
@@ -295,7 +305,7 @@ Rule        NZ      1928    only    -       Nov      4      2:00    0:30    HD
 Rule   NZ      1929    only    -       Oct     30      2:00    0:30    HD
 Rule   NZ      1930    1933    -       Mar     Sun>=15 2:00    0       S
 Rule   NZ      1930    1933    -       Oct     Sun>=8  2:00    0:30    HD
-# Whitman says DST went on and off during war years, and the base GMT offset
+# Whitman says DST went on and off during war years, and the base UT offset
 # didn't change until 1945 Apr 30; go with Shanks.
 Rule   NZ      1934    1940    -       Apr     lastSun 2:00    0       S
 Rule   NZ      1934    1939    -       Sep     lastSun 2:00    0:30    HD
@@ -315,8 +325,15 @@ Zone Pacific/Auckland      11:39:04 -      LMT     1868
 Zone Pacific/Chatham   12:45   Chatham CHA%sT
 
 
-# Antipodes Is, Kermadec Is
-# uninhabited except by research personnel; probably like Pacific/Auckland
+# Auckland Is
+# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
+# and scientific personnel have wintered
+
+# Campbell I
+# minor whaling stations operated 1909/1914
+# scientific station operated 1941/1995;
+# previously whalers, sealers, pastoralists, and scientific personnel wintered
+# was probably like Pacific/Auckland
 
 ###############################################################################
 
@@ -334,14 +351,11 @@ Zone      Pacific/Norfolk 11:11:52 -      LMT     1901            # Kingston
                        11:12   -       NMT     1951    # Norfolk Mean Time
                        11:30   -       NFT             # Norfolk Time
 
-# Palau
+# Palau (Belau)
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Pacific/Palau     8:57:56 -       LMT     1901            # Koror
                        9:00    -       PWT     # Palau Time
 
-# Palmyra
-# uninhabited since World War II; was probably like Pacific/Kiritimati
-
 # Papua New Guinea
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Pacific/Port_Moresby 9:48:40 -    LMT     1880
@@ -351,7 +365,8 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT     1880
 # Pitcairn
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Pacific/Pitcairn  -8:40:20 -      LMT     1901            # Adamstown
-                       -8:30   -       PNT     # Pitcairn Time
+                       -8:30   -       PNT     1998 Apr 27 00:00
+                       -8:00   -       PST     # Pitcairn Standard Time
 
 # American Samoa
 Zone Pacific/Pago_Pago  12:37:12 -     LMT     1879 Jul  5
@@ -379,16 +394,55 @@ Zone      Pacific/Fakaofo -11:24:56 -     LMT     1901
                        -10:00  -       TKT     # Tokelau Time
 
 # Tonga
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Tonga   1999    only    -       Oct      7      2:00s   1:00    S
+Rule   Tonga   2000    only    -       Mar     19      2:00s   0       -
+Rule   Tonga   2000    only    -       Nov      4      2:00s   1:00    S
+Rule   Tonga   2001    only    -       Jan     27      2:00s   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Pacific/Tongatapu 12:19:20 -      LMT     1901
-                       12:20   -       TOT     1968 Oct # Tonga Time
-                       13:00   -       TOT
+                       12:20   -       TOT     1941 # Tonga Time
+                       13:00   -       TOT     1999
+                       13:00   Tonga   TO%sT
 
 # Tuvalu
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Pacific/Funafuti  11:56:52 -      LMT     1901
                        12:00   -       TVT     # Tuvalu Time
 
+
+# US minor outlying islands
+
+# Howland, Baker
+# uninhabited since World War II
+# no information; was probably like Pacific/Pago_Pago
+
+# Jarvis
+# uninhabited since 1958
+# no information; was probably like Pacific/Kiritimati
+
+# Johnston
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Johnston  -10:00  -       HST
+
+# Kingman
+# uninhabited
+
+# Midway
+Zone Pacific/Midway    -11:49:28 -     LMT     1901
+                       -11:00  -       NST     1967 Apr        # N=Nome
+                       -11:00  -       BST     1983 Nov 30     # B=Bering
+                       -11:00  -       SST                     # S=Samoa
+
+# Palmyra
+# uninhabited since World War II; was probably like Pacific/Kiritimati
+
+# Wake
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Wake    11:06:28 -      LMT     1901
+                       12:00   -       WAKT    # Wake Time
+
+
 # Vanuatu
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Vanuatu 1983    only    -       Sep     25      0:00    1:00    S
@@ -401,11 +455,6 @@ Rule       Vanuatu 1992    only    -       Oct     Sun>=23 0:00    1:00    S
 Zone   Pacific/Efate   11:13:16 -      LMT     1912 Jan 13             # Vila
                        11:00   Vanuatu VU%sT   # Vanuatu Time
 
-# Wake
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Pacific/Wake    11:06:28 -      LMT     1901
-                       12:00   -       WAKT    # Wake Time
-
 # Wallis and Futuna
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Pacific/Wallis  12:15:20 -      LMT     1901
@@ -419,12 +468,12 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 # go ahead and edit the file (and please send any changes to
 # tz@elsie.nci.nih.gov for general use in the future).
 
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# From Paul Eggert <eggert@twinsun.com> (1999-10-29):
 # A good source for time zone historical data outside the U.S. is
-# Thomas G. Shanks, The International Atlas (3rd edition),
-# San Diego: ACS Publications, Inc. (1991).
+# Thomas G. Shanks, The International Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1999).
 #
-# Gwillim Law <LAW@encmail.encompass.com> writes that a good source
+# Gwillim Law <Gwil_Law@bridge-point.com> writes that a good source
 # for recent time zone data is the International Air Transport
 # Association's Standard Schedules Information Manual (IATA SSIM),
 # published semiannually.  Law sent in several helpful summaries
@@ -438,8 +487,7 @@ Zone        Pacific/Wallis  12:15:20 -      LMT     1901
 # I found in the UCLA library.
 #
 # A reliable and entertaining source about time zones is
-# Derek Howse, Greenwich time and the discovery of the longitude,
-# Oxford University Press (1980).
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
 # I invented the abbreviations marked `*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
@@ -450,22 +498,25 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 #        9:00  JST     Japan
 #        9:30  CST CST Central Australia
 #       10:00  EST EST Eastern Australia
-#       10:00  GST     Guam
+#       10:00  ChST    Chamorro
 #       10:30  LHST LHST Lord Howe*
 #       12:00  NZST NZDT New Zealand
 #       12:45  CHAST CHADT Chatham*
 #      -11:00  SST     Samoa
 #      -10:00  HST     Hawaii
+#      - 8:00  PST     Pitcairn*
 #
 # See the `northamerica' file for Hawaii.
 # See the `southamerica' file for Easter I and the Galapagos Is.
-#
-# See the `africa' file for time zone naming and abbreviation conventions.
 
 ###############################################################################
 
 # Australia
 
+# <a href="http://www.dstc.qut.edu.au/DST/marg/daylight.html">
+# Australia's Daylight Saving Times
+# </a>, by Margaret Turner, summarizes daylight saving issues in Australia.
+
 # From John Mackin (1991-03-06):
 # We in Australia have _never_ referred to DST as `daylight' time.
 # It is called `summer' time.  Now by a happy coincidence, `summer'
@@ -498,6 +549,25 @@ Zone       Pacific/Wallis  12:15:20 -      LMT     1901
 # and perhaps the newspaper's `2:00' is referring to standard time.
 # For now we'll continue to assume 2:00s for changes since 1960.
 
+# From Eric Ulevik <eau@zip.com.au> (1998-01-05):
+#
+# Here are some URLs to Australian time legislation. These URLs are stable,
+# and should probably be included in the data file. There are probably more
+# relevant entries in this database.
+#
+# NSW (including LHI and Broken Hill):
+# <a href="http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html">
+# Standard Time Act 1987 (updated 1995-04-04)
+# </a>
+# ACT
+# <a href="http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html">
+# Standard Time and Summer Time Act 1972
+# </a>
+# SA
+# <a href="http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html">
+# Standard Time Act, 1898
+# </a>
+
 # Northern Territory
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
@@ -543,6 +613,11 @@ Zone       Pacific/Wallis  12:15:20 -      LMT     1901
 # The 1992 ending date used in the rules is a best guess;
 # it matches what was used in the past.
 
+# <a href="http://www.bom.gov.au/faq/faqgen.htm">
+# The Australian Bureau of Meteorology FAQ
+# </a> (1999-09-27) writes that Giles Meteorological Station uses
+# South Australian time even though it's located in Western Australia.
+
 # Queensland
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # #   The state of QUEENSLAND.. [ Courtesy Qld. Dept Premier Econ&Trade Devel ]
@@ -654,66 +729,32 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 
 # Tasmania
 
-# From Bradley White (1991-03-04):
-# A recent excerpt from an Australian newspaper...
-# ...Tasmania will revert to Australian Eastern Standard Time on March 31...
-
-# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# The rules for 1967 through 1991 were reported by George Shepherd
+# via Simon Woodhead via Robert Elz (1991-03-06):
 # #  The state of TASMANIA.. [Courtesy Tasmanian Dept of Premier + Cabinet ]
 # #                                    [ Nov 1990 ]
-# ...
-# Zone Australia/Tasmania      10:00   AT      %sST
-# ...
-# Rule AT      1967    only    -       Oct     Sun>=1  2:00    1:00    D
-# Rule AT      1968    only    -       Mar     lastSun 3:00    0       E
-# Rule AT      1968    1985    -       Oct     lastSun 2:00    1:00    D
-# Rule AT      1969    1971    -       Mar     Sun>=8  3:00    0       E
-# Rule AT      1972    only    -       Feb     lastSun 3:00    0       E
-# Rule AT      1973    1981    -       Mar     Sun>=1  3:00    0       E
-# Rule AT      1982    1983    -       Mar     lastSun 3:00    0       E
-# Rule AT      1984    1986    -       Mar     Sun>=1  3:00    0       E
-# Rule AT      1986    only    -       Oct     Sun>=15 2:00    1:00    D
-# Rule AT      1987    1990    -       Mar     Sun>=15 3:00    0       E
-# Rule AT      1987    only    -       Oct     Sun>=22 2:00    1:00    D
-# Rule AT      1988    1990    -       Oct     lastSun 2:00    1:00    D
-# Rule AT      1991    max     -       Oct     Sun>=1  2:00    1:00    D
-# Rule AT      1991    max     -       Mar     lastSun 3:00    0       E
-
-# From Bill Hart via Alexander Dupuy and Guy Harris (1991-10-10):
-# My state Government in there eagerness to get a few more bucks for the
-# tourist industry industry decided to change the daylight savings times
-# yet again (we now have almost 6 months per year)...
-# ...
-# Rule  Oz      1986    1990    -       Oct     Sun<=24 2:00    1:00    -
-# Rule  Oz      1991    max     -       Oct     Sun>=1  2:00    1:00    -
-# ...
-# Rule  Oz      1987    1990    -       Mar     Sun<=21 3:00    0       -
-# Rule  Oz      1991    max     -       Mar     Sun<=31 3:00    0       -
 
 # From Bill Hart via Guy Harris (1991-10-10):
 # Oh yes, the new daylight savings rules are uniquely tasmanian, we have
 # 6 weeks a year now when we are out of sync with the rest of Australia
 # (but nothing new about that).
 
-# Victoria
+# From Alex Livingston (1999-10-04):
+# I heard on the ABC (Australian Broadcasting Corporation) radio news on the
+# (long) weekend that Tasmania, which usually goes its own way in this regard,
+# has decided to join with most of NSW, the ACT, and most of Victoria
+# (Australia) and start daylight saving on the last Sunday in August in 2000
+# instead of the first Sunday in October.
 
-# From Bradley White (1991-03-04):
-# A recent excerpt from an Australian newspaper...
-# ...Victoria...[has] agreed to end daylight saving at 3am tomorrow (March 3)...
+# Sim Alam (2000-07-03) reported a legal citation for the 2000/2001 rules:
+# http://www.thelaw.tas.gov.au/fragview/42++1968+GS3A@EN+2000070300
 
-# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# Victoria
+
+# The rules for 1971 through 1991 were reported by George Shepherd
+# via Simon Woodhead via Robert Elz (1991-03-06):
 # #   The state of VICTORIA.. [ Courtesy of Vic. Dept of Premier + Cabinet ]
 # #                                            [ Nov 1990 ]
-# ...
-# Zone Australia/Victoria      10:00   AV      %sST
-# ...
-# Rule AV      1971    1985    -       Oct     lastSun 2:00    1:00    D
-# Rule AV      1972    only    -       Feb     lastSun 3:00    0       E
-# Rule AV      1973    1985    -       Mar     Sun>=1  3:00    0       E
-# Rule AV      1986    1990    -       Mar     Sun>=15 3:00    0       E
-# Rule AV      1986    1987    -       Oct     Sun>=15 2:00    1:00    D
-# Rule AV      1988    max     -       Oct     lastSun 2:00    1:00    D
-# Rule AV      1991    max     -       Mar     Sun>=1  3:00    0       E
 
 # New South Wales
 
@@ -728,43 +769,80 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 #      legislation.  This is very important to understand.
 #      I have researched New South Wales time only...
 
-# From Dave Davey (1990-03-03):
-# Rule NSW     1988    only    -       Mar     Sun>=1  3:00    0       -
-# Rule NSW     1989    only    -       Mar     Sun<=21 3:00    0       -
-
-# From Bradley White (1991-03-04):
-# A recent excerpt from an Australian newspaper...
-# NSW...[has] agreed to end daylight saving at 3am tomorrow (March 3)...
-
-# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
-# # The state of NEW SOUTH WALES.. [confirmed by Attorney General's Dept N.S.W]
-# #                                    [ Dec 1990 ]
-# ...
-# Rule  AN     1988    1989    -       Mar     Sun<=21 3:00    0       E
-# ...
-
-# From John Mackin (1991-03-09)
-# I have confirmed the accuracy of the historical data for NSW in the
-# file Robert forwarded
+# From Paul Eggert (1999-09-27):
+# The Information Service of the Australian National Standards Commission
+# <a href="http://www.nsc.gov.au/InfoServ/Ileaflet/il27.htm">
+# Daylight Saving
+# </a> page (1995-04) has an excellent overall history of Australian DST.
+# The Community Relations Division of the NSW Attorney General's Department
+# publishes a history of daylight saving in NSW.  See:
+# <a href="http://www.lawlink.nsw.gov.au/crd.nsf/pages/time2">
+# Lawlink NSW: Daylight Saving in New South Wales
+# </a>
+
+# From Eric Ulevik <eau@ozemail.com.au> (1999-05-26):
+# DST will start in NSW on the last Sunday of August, rather than the usual
+# October in 2000.  [See: Matthew Moore,
+# <a href="http://www.smh.com.au/news/9905/26/pageone/pageone4.html">
+# Two months more daylight saving
+# </a>
+# Sydney Morning Herald (1999-05-26).]
+
+# From Paul Eggert (1999-09-27):
+# See the following official NSW source:
+# <a href="http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ">
+# Daylight Saving in New South Wales.
+# </a>
+#
+# Narrabri Shire (NSW) council has announced it will ignore the extension of
+# daylight saving next year.  See:
+# <a href="http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm">
+# Narrabri Council to ignore daylight saving
+# </a> (1999-07-22).  For now, we'll wait to see if this really happens.
+#
+# Victoria will following NSW.  See:
+# <a href="http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm">
+# Vic to extend daylight saving
+# </a> (1999-07-28).
+#
+# However, South Australia rejected the DST request.  See:
+# <a href="http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm">
+# South Australia rejects Olympics daylight savings request
+# </a> (1999-07-19).
+#
+# Queensland also will not observe DST for the Olympics.  See:
+# <a href="http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm">
+# Qld says no to daylight savings for Olympics
+# </a> (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
+# ``Look you've got to remember in my family when this came up last time
+# I voted for it, my wife voted against it and she said to me it's all very
+# well for you, you don't have to worry about getting the children out of
+# bed, getting them to school, getting them to sleep at night.
+# I've been through all this argument domestically...my wife rules.''
+#
+# Broken Hill will stick with South Australian time in 2000.  See:
+# <a href="http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm">
+# Broken Hill to be behind the times
+# </a> (1999-07-21).
 
-# From Arthur David Olson (1992-03-08):
-# Sources differ on whether DST ended March 6 or March 20 in 1988;
-# March 20 (the "confirmed" date) is in the chosen rules.
+# IATA SSIM (1998-09) says that the spring 2000 change for Australian
+# Capital Territory, New South Wales except Lord Howe Island and Broken
+# Hill, and Victoria will be August 27, presumably due to the Sydney Olympics.
 
-# From Bradley White (1995-05-20):
-# Prem Bob Carr announced NSW will fall into line with other E states
-# and SA and continue daylight savings to the last Sun in Mar.
+# From Eric Ulevik, referring to Sydney's Sun Herald (2000-08-13), page 29:
+# The Queensland Premier Peter Beattie is encouraging northern NSW
+# towns to use Queensland time.
 
 # Yancowinna
 
-# From John Basser (1989-01-04):
+# From John Mackin (1989-01-04):
 # `Broken Hill' means the County of Yancowinna.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
 # #                                    [ Dec 1990 ]
 # ...
-# # Yancowinna uses Central Standard Time, despite it's location on the
+# # Yancowinna uses Central Standard Time, despite [its] location on the
 # # New South Wales side of the S.A. border. Most business and social dealings
 # # are with CST zones, therefore CST is legislated by local government
 # # although the switch to Summer Time occurs in line with N.S.W. There have
@@ -784,16 +862,31 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 # Lord Howe Island is located off the New South Wales coast, and is half an
 # hour ahead of NSW time.
 
-# From Paul Eggert (1995-12-19):
-# For Lord Howe we use Shanks through its time of publication (1991).
-# Lord Howe is part of NSW, so we'll guess it has used the same transition
-# times as NSW since 1991, even though Shanks writes that Lord Howe went
-# with Victoria when NSW and Victoria disagreed in 1982.
+# From James Lonergan, Secretary, Lord Howe Island Board (2000-01-27):
+# Lord Howe Island summer time in 2000/2001 will commence on the same
+# date as the rest of NSW (i.e. 2000-08-27).  For your information the
+# Lord Howe Island Board (controlling authority for the Island) is
+# seeking the community's views on various options for summer time
+# arrangements on the Island, e.g. advance clocks by 1 full hour
+# instead of only 30 minutes.  Dependent on the wishes of residents
+# the Board may approach the NSW government to change the existing
+# arrangements.  The starting date for summer time on the Island will
+# however always coincide with the rest of NSW.
+
+# From James Lonergan, Secretary, Lord Howe Island Board (2000-10-25):
+# Lord Howe Island advances clocks by 30 minutes during DST in NSW and retards
+# clocks by 30 minutes when DST finishes. Since DST was most recently
+# introduced in NSW, the "changeover" time on the Island has been 02:00 as
+# shown on clocks on LHI. I guess this means that for 30 minutes at the start
+# of DST, LHI is actually 1 hour ahead of the rest of NSW.
+
+# From Paul Eggert (2001-02-09):
+# For Lord Howe dates we use Shanks through 1989, and Lonergan thereafter.
+# For times we use Lonergan.
 
 ###############################################################################
 
-# New Zealand, from Elz' asia 1.1
-# Elz says "no guarantees"
+# New Zealand
 
 # From Mark Davies (1990-10-03):
 # the 1989/90 year was a trial of an extended "daylight saving" period.
@@ -826,24 +919,44 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 # time on both the first Sunday in October and the third Sunday in March.
 # As with Australia, we'll assume the tradition is 2:00s, not 2:00.
 #
-# From Paul Eggert (1996-11-22):
-# Shanks gives no data for Chatham; usno1989 says it's +12:45,
-# usno1995 says it's +12:45/+13:45, and IATA SSIM (1991/1996)
+# From Paul Eggert (1999-10-29):
+# Shanks gives no time data for Chatham; usno1989 says it's +12:45,
+# usno1995 says it's +12:45/+13:45, and IATA SSIM (1991/1999)
 # gives the NZ rules but with transitions at 2:45 local standard time.
-# Guess that they adopted DST in 1990.
+# Guess that they have been in lock-step with NZ since 1990.
 
 ###############################################################################
 
+
 # Fiji
 
-# Howse writes (p 162) that in 1879 the British governor of Fiji
-# enacted an ordinance standardizing the islands on +12:00.
-# Perhaps it didn't take.  We go with Shanks's more precise date in 1915.
+# Howse writes (p 153) that in 1879 the British governor of Fiji
+# enacted an ordinance standardizing the islands on Antipodean Time
+# instead of the American system (which was one day behind).
+
+# From Rives McDow (1998-10-08):
+# Fiji will introduce DST effective 0200 local time, 1998-11-01
+# until 0300 local time 1999-02-28.  Each year the DST period will
+# be from the first Sunday in November until the last Sunday in February.
+
+# From Paul Eggert (2000-01-08):
+# IATA SSIM (1999-09) says DST ends 0100 local time.  Go with McDow.
+
+# From the BBC World Service (1998-10-31 11:32 UTC):
+# The Fijiian government says the main reasons for the time change is to
+# improve productivity and reduce road accidents.  But correspondents say it
+# also hopes the move will boost Fiji's ability to compete with other pacific
+# islands in the effort to attract tourists to witness the dawning of the new
+# millenium.
+
+# http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
+# reports that Fiji has discontinued DST.
 
 # Johnston
 
 # Johnston data is from usno1995.
 
+
 # Kiribati
 
 # From Paul Eggert (1996-01-22):
@@ -851,6 +964,7 @@ Zone        Pacific/Wallis  12:15:20 -      LMT     1901
 # ``declared it the same day throught the country as of Jan. 1, 1995''
 # as part of the competition to be first into the 21st century.
 
+
 # Kwajalein
 
 # In comp.risks 14.87 (26 August 1993), Peter Neumann writes:
@@ -859,12 +973,20 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 # respect to the International Date Line, to rejoin its fellow islands,
 # going from 11:59 p.m. Thursday to 12:00 m. Saturday in a blink.
 
+
 # N Mariana Is, Guam
 
-# Howse writes (p 162) ``The Spaniards, on the other hand, reached the
+# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
 # Philippines and the Ladrones from America,'' and implies that the Ladrones
 # (now called the Marianas) kept American date for quite some time.
-# Ignore this for now, as we have no hard data.  See also Asia/Manila.
+# For now, we assume the Ladrones switched at the same time as the Philippines;
+# see Asia/Manila.
+
+# US Public Law 106-564 (2000-12-23) made UTC+10 the official standard time,
+# under the name "Chamorro Standard Time".  There is no official abbreviation,
+# but Congressman Robert A. Underwood, author of the bill that became law,
+# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
+
 
 # Micronesia
 
@@ -872,19 +994,155 @@ Zone     Pacific/Wallis  12:15:20 -      LMT     1901
 # ``I am certain, having lived there for the past decade, that "Truk"
 # (now properly known as Chuuk) ... is in the time zone GMT+10.''
 #
-# Shanks writes that Truk switched from GMT+10 to GMT+11 on 1978-10-01;
+# Shanks writes that Truk switched from UTC+10 to UTC+11 on 1978-10-01;
 # ignore this for now.
 
+# From Paul Eggert (1999-10-29):
+# The Federated States of Micronesia Visitors Board writes in
+# <a href="http://www.fsmgov.org/info/clocks.html">
+# The Federated States of Micronesia - Visitor Information
+# </a> (1999-01-26)
+# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
+# We don't know when Kosrae switched from UTC+12; assume January 1 for now.
+
+
+# Pitcairn
+
+# From Rives McDow (1999-11-08):
+# A Proclamation was signed by the Governor of Pitcairn on the 27th March 1998
+# with regard to Pitcairn Standard Time.  The Proclamation is as follows.
+#
+#      The local time for general purposes in the Islands shall be
+#      Co-ordinated Universal time minus 8 hours and shall be known
+#      as Pitcairn Standard Time.
+#
+# ... I have also seen Pitcairn listed as UTC minus 9 hours in several
+# references, and can only assume that this was an error in interpretation
+# somehow in light of this proclamation.
+
+# From Rives McDow (1999-11-09):
+# The Proclamation regarding Pitcairn time came into effect on 27 April 1998
+# ... at midnight.
+
+# From Howie Phelps (1999-11-10), who talked to a Pitcairner via shortwave:
+# Betty Christian told me yesterday that their local time is the same as
+# Pacific Standard Time. They used to be 1/2 hour different from us here in
+# Sacramento but it was changed a couple of years ago.
+
+
 # Samoa
 
-# Howse writes that in 1879 the King of Samoa decided to change
+# Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
+# that in 1879 the King of Samoa decided to change
 # ``the date in his kingdom from the Antipodean to the American system,
 # ordaining -- by a masterpiece of diplomatic flattery -- that
 # the Fourth of July should be celebrated twice in that year.''
 
+
 # Tonga
 
 # From Paul Eggert (1996-01-22):
 # Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
 # to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
 # Since Kiribati has moved the Date Line it's not clear what Tonga will do.
+
+# Don Mundell writes in the 1997-02-20 Tonga Chronicle
+# <a href="http://www.tongatapu.net.to/tonga/homeland/timebegins.htm">
+# How Tonga became `The Land where Time Begins'
+# </a>:
+
+# Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
+# 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
+# standard time in 1940s, Tonga had the choice of subtracting from its
+# local time to come on the same standard time as New Zealand or of
+# advancing its time to maintain the differential of 13 degrees
+# (approximately 50 minutes ahead of New Zealand time).
+#
+# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
+# Tungi, preferred to ensure Tonga's title as the land where time
+# begins, the Legislative Assembly approved the latter change.
+#
+# But some of the older, more conservative members from the outer
+# islands objected. "If at midnight on Dec. 31, we move ahead 40
+# minutes, as your Royal Highness wishes, what becomes of the 40
+# minutes we have lost?"
+#
+# The Crown Prince, presented an unanswerable argument: "Remember that
+# on the World Day of Prayer, you would be the first people on Earth
+# to say your prayers in the morning."
+
+# From Paul Eggert (1999-08-12):
+# Shanks says the transition was on 1968-10-01; go with Mundell.
+
+# From Eric Ulevik (1999-05-03):
+# Tonga's director of tourism, who is also secretary of the National Millenium
+# Committee, has a plan to get Tonga back in front.
+# He has proposed a one-off move to tropical daylight saving for Tonga from
+# October to March, which has won approval in principle from the Tongan
+# Government.
+
+# From Steffen Thorsen [straen@thorsen.priv.no] (1999-09-09):
+# * Tonga will introduce DST in November
+#
+# I was given this link by John Letts <johnletts@earthlink.net>:
+# <a hef="http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm">
+# http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
+# </a>
+#
+# I have not been able to find exact dates for the transition in November
+# yet. By reading this article it seems like Fiji will be 14 hours ahead
+# of UTC as well, but as far as I know Fiji will only be 13 hours ahead
+# (12 + 1 hour DST).
+
+# From Arthur David Olson [arthur_david_olson@nih.gov] (1999-09-20):
+# According to <a href="http://www.tongaonline.com/news/sept1799.html>
+# http://www.tongaonline.com/news/sept1799.html
+# </a>:
+# "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
+# and annually thereafter from the first Saturday in October through the
+# third Saturday of April.  Under the system approved by Privy Council on
+# Sept. 10, clocks must be turned ahead one hour on the opening day and
+# set back an hour on the closing date."
+# Alas, no indication of the time of day.
+
+# From Rives McDow (1999-10-06):
+# Tonga started its Daylight Saving on Saturday morning October 2nd at 0200am.
+# Daylight Saving ends on April 16 at 0300am which is Sunday morning.
+
+# From Steffen Thorsen (2000-10-31):
+# Back in March I found a notice on the website http://www.tongaonline.com
+# that Tonga changed back to standard time one month early, on March 19
+# instead of the original reported date April 16. Unfortunately, the article
+# is no longer available on the site, and I did not make a copy of the
+# text, and I have forgotten to report it here.
+# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
+
+# From Rives McDow (2000-12-01):
+# Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
+
+###############################################################################
+
+# The International Date Line
+
+# From Gwillim Law (2000-01-03):
+#
+# The International Date Line is not defined by any international standard,
+# convention, or treaty.  Mapmakers are free to draw it as they please.
+# Reputable mapmakers will simply ensure that every point of land appears on
+# the correct side of the IDL, according to the date legally observed there.
+#
+# When Kiribati adopted a uniform date in 1995, thereby moving the Phoenix and
+# Line Islands to the west side of the IDL (or, if you prefer, moving the IDL
+# to the east side of the Phoenix and Line Islands), I suppose that most
+# mapmakers redrew the IDL following the boundary of Kiribati.  Even that line
+# has a rather arbitrary nature.  The straight-line boundaries between Pacific
+# island nations that are shown on many maps are based on an international
+# convention, but are not legally binding national borders.
+#
+# An Anglo-French Conference on Time-Keeping at Sea (June, 1917) agreed that
+# legal time on the high seas would be zone time, i.e., the standard time at
+# the nearest meridian that is a multiple of fifteen degrees.  The date is
+# governed by the IDL; therefore, even on the high seas, there may be some
+# places as late as fourteen hours later than UTC.  And, since the IDL is not
+# an international standard, there are some places on the high seas where the
+# correct date is ambiguous.
index 793d37b34533812ff66e2cc690b40997e4934bd8..0bfa8724f4b9e2e6ab7451103769cf365713cd7e 100644 (file)
@@ -1,14 +1,19 @@
-#      $OpenBSD: backward,v 1.4 1997/01/14 04:36:50 millert Exp $
-# @(#)backward 7.13
+# @(#)backward 7.20
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
 
 Link   America/Adak            America/Atka
+Link   America/Tijuana         America/Ensenada
 Link   America/Indianapolis    America/Fort_Wayne
 Link   America/Indiana/Knox    America/Knox_IN
+Link   America/Rio_Branco      America/Porto_Acre
 Link   America/St_Thomas       America/Virgin
+Link   Asia/Dhaka              Asia/Dacca
+Link   Asia/Ashgabat           Asia/Ashkhabad
 Link   Asia/Jerusalem          Asia/Tel_Aviv
+Link   Asia/Thimphu            Asia/Thimbu
+Link   Asia/Ulaanbaatar        Asia/Ulan_Bator
 Link   Australia/Sydney        Australia/ACT
 Link   Australia/Sydney        Australia/Canberra
 Link   Australia/Lord_Howe     Australia/LHI
@@ -39,7 +44,8 @@ Link  America/Havana          Cuba
 Link   Africa/Cairo            Egypt
 Link   Europe/Dublin           Eire
 Link   Europe/London           GB
-Link   Etc/GMT                 GMT
+Link   Europe/London           GB-Eire
+Link   Europe/Chisinau         Europe/Tiraspol
 Link   Etc/GMT+0               GMT+0
 Link   Etc/GMT-0               GMT-0
 Link   Etc/GMT0                GMT0
index 8786abed63e8d3189258f00a9059fd999c3b37c6..f87a76ea48a7000b533ea80c27fd45e8c533094c 100644 (file)
@@ -1,5 +1,4 @@
-#      $OpenBSD: etcetera,v 1.3 1997/01/14 04:36:51 millert Exp $
-# @(#)etcetera 7.6
+# @(#)etcetera 7.11
 
 # These entries are mostly present for historical reasons, so that
 # people in areas not otherwise covered by the tz files could "zic -l"
@@ -11,6 +10,12 @@ Zone Etc/GMT         0       -       GMT
 Zone   Etc/UTC         0       -       UTC
 Zone   Etc/UCT         0       -       UCT
 
+# The following link uses older naming conventions,
+# but it belongs here, not in the file `backward',
+# as functions like gmtime load the "GMT" file to handle leap seconds properly.
+# We want this to work even on installations that omit the other older names.
+Link   Etc/GMT                         GMT
+
 Link   Etc/UTC                         Etc/Universal
 Link   Etc/UTC                         Etc/Zulu
 
@@ -19,10 +24,24 @@ Link        Etc/GMT                         Etc/GMT-0
 Link   Etc/GMT                         Etc/GMT+0
 Link   Etc/GMT                         Etc/GMT0
 
-# We use POSIX-style signedness in the names and output,
-# internal-style signedness in the specifications.
-# For example, TZ=Etc/GMT+4 corresponds to 4 hours _behind_ GMT;
-# it is equivalent to TZ=GMT+4, which is implemented directly as per POSIX.
+# We use POSIX-style signs in the Zone names and the output abbreviations,
+# even though this is the opposite of what many people expect.
+# POSIX has positive signs west of Greenwich, but many people expect
+# positive signs east of Greenwich.  For example, TZ='Etc/GMT+4' uses
+# the abbreviation "GMT+4" and corresponds to 4 hours behind UTC
+# (i.e. west of Greenwich) even though many people would expect it to
+# mean 4 hours ahead of UTC (i.e. east of Greenwich).
+#
+# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation
+# (which is not yet supported by the tz code) allows for
+# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to
+# ISO 8601 you can use TZ='<-0400>+4'.  Thus the commonly-expected
+# offset is kept within the angle bracket (and is used for display)
+# while the POSIX sign is kept outside the angle bracket (and is used
+# for calculation).
+#
+# Do not use a TZ setting like TZ='GMT+4', which is four hours behind
+# GMT but uses the completely misleading abbreviation "GMT".
 
 # Earlier incarnations of this package were not POSIX-compliant,
 # and had lines such as
index ac1aec13beac6951286e555f73c74b07ea62c258..04a8f8433dc2c80ef8548e7d97a669e17d4cd2ed 100644 (file)
@@ -1,27 +1,36 @@
-#      $OpenBSD: europe,v 1.5 1997/01/14 04:36:52 millert Exp $
-# @(#)europe   7.42
+# @(#)europe   7.78
+
+# $FreeBSD: src/share/zoneinfo/europe,v 1.22 2001/04/06 16:46:52 wollman Exp $
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
 # tz@elsie.nci.nih.gov for general use in the future).
 
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# From Paul Eggert <eggert@twinsun.com> (1999-10-29):
 # A good source for time zone historical data outside the U.S. is
-# Thomas G. Shanks, The International Atlas (3rd edition),
-# San Diego: ACS Publications, Inc. (1991).
+# Thomas G. Shanks, The International Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1999).
 #
-# Gwillim Law <LAW@encmail.encompass.com> writes that a good source
+# Gwillim Law <Gwil_Law@bridge-point.com> writes that a good source
 # for recent time zone data is the International Air Transport
 # Association's Standard Schedules Information Manual (IATA SSIM),
 # published semiannually.  Law sent in several helpful summaries
 # of the IATA's data after 1990.
 #
-# Except where otherwise noted, Shanks is the source for entries through 1990,
-# and IATA SSIM is the source for entries after 1990.
+# Except where otherwise noted, Shanks is the source for entries through 1991,
+# and IATA SSIM is the source for entries afterwards.
+#
+# Other sources occasionally used include:
 #
-# Another source occasionally used is Edward W. Whitman, World Time Differences,
-# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated), which
-# I found in the UCLA library.
+#      Edward W. Whitman, World Time Differences,
+#      Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
+#      which I found in the UCLA library.
+#
+#      Brazil's Departamento Servico da Hora (DSH),
+#      <a href="http://pcdsh01.on.br/HISTHV.htm">
+#      History of Summer Time
+#      </a> (1998-09-21, in Portuguese)
+
 #
 # I invented the abbreviations marked `*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 #       2:00   EET EEST Eastern Europe
 #       3:00   MSK MSD Moscow
 #
-# See the `africa' file for time zone naming and abbreviation conventions.
-#
 # A reliable and entertaining source about time zones, especially in Britain,
-# is Derek Howse, Greenwich time and the discovery of the longitude,
-# Oxford University Press (1980).
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 
 # From Peter Ilieve <peter@memex.co.uk> (1994-12-04),
 # The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -68,8 +74,7 @@
 
 ###############################################################################
 
-# United Kingdom
-# The UK and its colonies adopted the Gregorian calendar on 1752-09-14.
+# Britain (United Kingdom) and Ireland (Eire)
 
 # From Peter Ilieve <peter@memex.co.uk> (1994-07-06):
 #
 # Howse writes that Britain was the first country to use standard time.
 # The railways cared most about the inconsistencies of local mean time,
 # and it was they who forced a uniform time on the country.
-# The original idea was credited to Dr. William Hyde Wollaston (1766-1828);
-# it was popularized in 1840 by Capt. Basil Hall, RN (1788-1844),
-# famed explorer and former Commissioner for Longitude.
+# The original idea was credited to Dr. William Hyde Wollaston (1766-1828)
+# and was popularized by Abraham Follett Osler (1808-1903).
 # The first railway to adopt London time was the Great Western Railway
 # in November 1840; other railways followed suit, and by 1847 most
-# (though not all) railways used London time.  On 1847 Sep 22 the
+# (though not all) railways used London time.  On 1847-09-22 the
 # Railway Clearing House, an industry standards body, recommended that GMT be
-# adopted at all stations; the January 1848 Bradshaw's lists most major
+# adopted at all stations as soon as the General Post Office permitted it.
+# The transition occurred on 12-01 for the L&NW, the Caledonian,
+# and presumably other railways; the January 1848 Bradshaw's lists many
 # railways as using GMT.  By 1855 the vast majority of public
-# clocks in Britain were set to GMT (though some, like the Great Clock
-# in Tom Tower at Christ Church, Oxford, were fitted with two minute hands,
+# clocks in Britain were set to GMT (though some, like the great clock
+# on Tom Tower at Christ Church, Oxford, were fitted with two minute hands,
 # one for local time and one for GMT).  The last major holdout was the legal
 # system, which stubbornly stuck to local time for many years, leading
 # to oddities like polls opening at 08:13 and closing at 16:13.
 # The legal system finally switched to GMT when the Statutes (Definition
-# of Time) Act took effect; it received the Royal Assent on 1880 Aug 2.
+# of Time) Act took effect; it received the Royal Assent on 1880-08-02.
 #
 # In the tables below, we condense this complicated story into a single
-# transition date for London, namely 1847 Sep 22.  We don't know as much
-# about Dublin, so we use 1880 Aug 2, the legal transition time.
+# transition date for London, namely 1847-12-01.  We don't know as much
+# about Dublin, so we use 1880-08-02, the legal transition time.
 
-# From Paul Eggert (1996-06-12):
+# From Paul Eggert (1999-01-30):
 # Summer Time was first seriously proposed by William Willett (1857-1915),
-# a London builder who circulated a pamphlet ``Waste of Daylight'' (1907)
+# a London builder and member of the Royal Astronomical Society
+# who circulated a pamphlet ``The Waste of Daylight'' (1907)
 # that proposed advancing clocks 20 minutes on each of four Sundays in April,
 # and retarding them by the same amount on four Sundays in September.
 # A bill was drafted in 1909 and introduced in Parliament several times,
 # but it met with ridicule and opposition, especially from farming interests.
 # One-hour Summer Time was eventually adopted as a wartime measure in 1916.
+# See:
+# <a href="http://www.the-times.co.uk/news/pages/tim/2000/05/18/x-timcrtcrt01011.html">
+# Summer Time Arrives Early, The Times (2000-05-18)
+# </a>
+# A monument was erected in 1927 to Willett, in an open space in a 45-acre wood
+# near Chiselhurst, Kent that was purchased by popular subscription and open
+# to the public.
 
 # From Paul Eggert (1996-09-03):
 # The OED Supplement says that the English originally said ``Daylight Saving''
 # If you can predict what Parliament will do, you should be in
 # politics making a fortune, not computing.
 
-# From Peter Ilieve <peter@memex.co.uk> (1993-09-03):
-#
-# Our Government...couldn't...make a decision after the 1989 consultation
-# exercise about the UK changing its timezone so it just let things drift
-# (different from deciding to keep the status quo).  According to the
-# Summer Time Order 1992 (SI 1992/1729) the dates of Summer Time for 1993
-# and 1994 are:
-#      Start           End
-# 1993 28 March        24 October
-# 1994 27 March        23 October
-# All start and end times are at 01:00 GMT.
-#
-# There [was] an error in your tables for the start and end times prior to 1981.
-# The UK always used to change at 02:00 GMT. In 1981 it changed to 01:00 GMT
-# as a part of EC harmonisation and has remained at that time since.
-#
-# I have found the default algorithm for UK Summer Time, it is in the
-# Summer Time Act 1972. Section 1 states that in the absence of an Order
-# in Council Summer Time starts at 02:00 GMT on the morning of the day
-# after the third Saturday in March, unless that day is Easter Day, in
-# which case it is the morning of the day after the second Saturday.
-# It ends at 02:00 GMT on the morning of the day after the fourth Saturday
-# in October. (All the redundant `morning of the day ...' is in the Act.)
-# This is only of passing interest now as it will always be overridden by
-# an Order in Council (a Statutory Instrument, the SI thing mentioned above)
-# to specify the EC specified dates.
-
-# From Peter Ilieve <peter@memex.co.uk> (1993-10-18):
-#
-# My contact in the Ministry of Defence Public Relations department
-# accepted the challenge of looking into this and produced the following,
-# from Hansard (the official record of the UK Parliament), Oral Answers,
-# 1 March 1945, cols 1559--60:
-#
-# `58. Major Sir Goronwy Owen asked the Secretary of State for the Home
-# Department if he is now able to state the Government's proposals
-# regarding double summer time.
-#
-# [two other similar questions omitted]
-#
-# Mr. H. Morrison: The Government, in reviewing the matter, have
-# considered, [...] the conclusion has been reached that the adoption of
-# double summer time from the beginning of April is essential to the
-# maintenance of the war effort. [...] As 1st April is Easter Sunday,
-# when very early services are held in many churches, it is proposed that
-# double summer time shall start not in the night preceding Easter
-# Sunday, but in the night of Sunday- Monday so that it will operate from
-# Monday, 2nd April.'
-
 # From Chris Carrier <72157.3334@CompuServe.COM> (1996-06-14):
 # I remember reading in various wartime issues of the London Times the
 # acronym BDST for British Double Summer Time.  Look for the published
 # time of sunrise and sunset in The Times, when BDST was in effect, and
 # if you find a zone reference it will say, "All times B.D.S.T."
 
-# From Peter Ilieve <peter@memex.co.uk> (1993-09-03):
-#
-# > # Current rules
-# > Rule GB-Eire 1981  max     -       Mar     lastSun 1:00s   1:00    BST
-# > Rule GB-Eire 1981  max     -       Oct     Sun>=23 1:00s   0       GMT
-#
-# The ending rule here doesn't match the EC rules, which specify the fourth
-# Sunday in October for the UK and Eire. The `fourth Sunday' rule wasn't
-# followed in 1989, but then the sixth EC directive wasn't in force then
-# and I don't know what previous ones said. 1995 is the next year with
-# the 4th Sun on 22 Oct, but that year isn't covered by the UK Summer Time
-# Order or the sixth EC directive. Your Oct Sun>=23 rule matches history
-# and with things only announced for 2 years or so in advance who knows
-# what will happen.
-#
-# There are renewed rumours that the Government here will make another
-# attempt at resolving this issue, which is what prompted me to start
-# asking the Home Office and the EC about it again. The EC categorically
-# state they are not asking anybody to change timezone, they only want
-# common start/end dates. The UK Govt. seem to want to change our zone
-# and blame the resulting fuss on the EC. Me, I think we should scrap
-# summer time completely, noon is when the Sun is overhead, and that should
-# be the end of it.
-
-# From Peter Ilieve <peter@memex.co.uk> (1993-10-22):
-#
-# I now have the text of the Summer Time Act 1916, the granddaddy of them all.
-# It is headed: `An Act to provide for the Time in Great Britain and Ireland
-# being in advance of Greenwich and Dublin mean time respectively in the
-# summer months'.
-#
-# It specifies 21 May and 1 October for 1916 (both at 02:00 GMT) and whatever
-# dates an Order in Council may specify for subsequent years.
-#
-# Section 4 states: `This act shall apply to Ireland in like manner as it
-# applies to Great Britain, with the substitution however of references
-# to Dublin mean time for references to Greenwich mean time.'
-#
-# Lorna, my learned legal friend who supplied it, also offers this quote
-# from Halsbury's Statutes on the extent of Acts:
-#
-# `An Act of the United Kingdom Parliament is to be construed prima facie
-# to apply to the whole of the United Kingdom and not to any place outside.
-# [...] The expression "United Kingdom" for this purpose includes (since
-# 1922) Great Britain (ie. England, Wales and Scotland) and Northern Ireland,
-# but it does not include the Channel Islands or the Isle of Man.'
-#
-# She goes on to say the seminal event of 1922 was the establishment of
-# the Irish Free State, now called Eire.
-#
-# The Act doesn't say anything about Wales (or Scotland) so I would assert
-# that Shanks is wrong here. I would like to know why he thinks Wales
-# was different.
-#
-# It also confirms the fact that Ireland followed Dublin time back then,
-# and 25 minutes behind Greenwich, as Shanks has it, would be correct.
-
-# From Peter Ilieve <peter@memex.co.uk> (1993-10-28):
-#
-# I now have before me, thanks to my learned legal friend Lorna, the text of
-# the Time (Ireland) Act 1916.
-#
-# It says that as from 2 AM Dublin Mean Time on 1 October 1916 the time
-# for general purposes in Ireland shall be the same as the rest of Great
-# Britain (ie. GMT with the Summer Time periods specified by the Summer Time
-# Act 1916)....  As Ireland was behind GMT/BST at 02:00 DMT on 1 Oct GB would
-# have already put the clocks back. Using DST as Dublin Summer Time the
-# sequence would have been:
-# Dublin               London
-# 02:34 DST    02:59 BST
-# 02:35 DST    02:00 GMT
-# 02:59 DST    02:24 GMT
-# 02:25 GMT    02:25 GMT
-# with the transition 03:00 DST -> 02:00 DMT -> 02:25 GMT all at once.
-#
-# In a table of repeals in the Schedule to the Act it mentions the
-# Statutes (Definition of Time) Act 1880. This is presumably the source
-# of the 1880 date in Shanks.  The little bit of it that is repealed
-# also refers solely to Ireland and Dublin Mean Time.
-
-# From Peter Ilieve <peter@memex.co.uk> (1993-10-29):
-#
-# My case is that, with the sole exception of Ireland in 1916 using Dublin
-# Mean Time, Summer Time has been uniform throughout the United Kingdom
-# ever since it first started in 1916.
-#
-# The United Kingdom is England, Wales and Scotland plus all of Ireland from
-# 1916 up to and including 1921, or plus Northern Ireland from 1922 to date.
-#
-# The dates used are those specified in the table in Summer Time: A Consultation
-# Document (Cm 722, 1989) that are now included in the europe file, with a
-# change to a single date, the start in 1924. I made a typo in my 1989 mail
-# and the table itself is also wrong.  The correct date is 13 April.
-# The times were 02:00 GMT up to and including 1980, 01:00 GMT from 1981 on,
-# except for wartime double summer time.
-#
-# As evidence I would cite:
-#
-# - The Summer Time Act, 1916.
-#
-# This specifically states that it applies to Ireland, specifies dates of
-# 21 May and 1 October and times of 02:00, and says that in Ireland the
-# times relate to Dublin mean time. It specifies an offset of 1 hour.
-#
-# - The Time (Ireland) Act, 1916
-#
-# This abolishes Dublin mean time on 02:00 DMT 1 October 1916.
-# It repeals that section of the Statutes (Definition of Time) Act, 1880
-# that specifies DMT. It is therefore a safe bet that DMT existed at least
-# from 1880 and was the only alternative standard time in the UK.
-#
-# - The Summer Time Act, 1922
-#
-# This specifies an offset of 1 hour and dates of the day after the third
-# Saturday in April, unless that be Easter, in which case it is the day after
-# the second Saturday, and the day after the third Saturday in September.
-# The time is 02:00 GMT. It applied in 1922 and 1923, and longer if Parliament
-# so approved.
-#
-# It specifically states that it applies to Northern Ireland, the Channel
-# Islands, and the Isle of Man.
-#
-# - The Summer Time Act, 1925
-#
-# This makes the 1922 Act permanent, with a change to the end date to the
-# day after the first Saturday in October. It says nothing about extent,
-# so that part of the 1922 Act will still apply.
-#
-# - The Defence (Summer Time) Regulations, 1939, SR&O 1939 No. 1379
-#   [SR&O == Statutory Regulation and Order]
-#
-# These were made under the Emergency Powers (Defence) Act, 1939.
-# It changes the end date to be the day after the third Saturday in November.
-# It makes consequential changes to some vehicle lighting legislation,
-# which includes the Motor Vehicles and Road Traffic (Northern Ireland) Act,
-# 1934, so it seems clear it applies in Northern Ireland.
-#
-# - An Order in Council amending the The Defence (Summer Time) Regulations,
-#   1939, SR&O 1940 No. 1883
-#
-# This continues summer time throughout the year after it starts in 1940.
-# It says nothing about extent and has no consequential changes.
-#
-# - An Order in Council amending the The Defence (Summer Time) Regulations,
-#   1939, SR&O 1941 No. 476
-#
-# This introduces double summer time, starting at 01:00 GMT on the day after
-# the first Saturday in May and ending at 01:00 GMT on the day after the
-# second Saturday in August, offset another hour from normal summer time,
-# which continues throughout the rest of the year. It goes on a lot about
-# consequential changes to agricultural wages legislation, and says in part
-# `... and in its application to Northern Ireland have effect as
-# if for the references to the Agricultural Wages (Regulation) Acts, 1924 and
-# 1940, there were substituted references to the Agricultural Wages (Regulation)
-# Acts (Northern Ireland), 1939 and 1940, ...'. It also has a similar section
-# for Scotland. Both sections substitute the local Agricultural Wages Board
-# for the Agricultural Wages Board for England and Wales, showing that
-# England and Wales were indivisible.
-#
-# - An Order in Council amending the The Defence (Summer Time) Regulations,
-#   1939, SR&O 1942 No. 506
-#
-# This changes the start date of double summer time to the day after the first
-# Saturday in April. It says nothing about extent.
-#
-# - An Order in Council amending the The Defence (Summer Time) Regulations,
-#   1939, SR&O 1944 No. 932
-#
-# This changed the end date of double summer time to 17 September 1944.
-# (I don't have the text of this, just a note of what it did, the text almost
-# certainly had the `day after the nth Saturday' form.)
-#
-# (I am missing whatever regulations there were to change things in 1945
-# and the Summer Time Act, 1947.)
-#
-# - The British Standard Time Act, 1968
-#
-# This came into force on 27 October 1968 and continued summer time throughout
-# the year as an experiment until it expired on 31 October 1971.
-# There was no double summer time so we didn't have to change the clocks at all.
-# It specifically said it applied to Northern Ireland. It also said it
-# applied to Jersey, Guernsey and the Isle of Man unless they passed
-# measures saying it didn't.
-#
-# - The Manx Time Act, 1968
-#
-# This is an Act of Tynwald (the Isle of Man Parliament) that said that
-# henceforth Manx time would be the same as the time in Great Britain.
-#
-# - The Summer Time Act, 1972
-#
-# This specified a reversion to normal summer time behaviour with a start
-# date of the day after the third Saturday in March, unless that is Easter,
-# when it is the day after the second Saturday, and an end date of the day
-# after the fourth Saturday in October. Times are at 02:00 GMT, offset is
-# 1 hour.
-#
-# It has the same wording about extent as the British Standard Time Act, 1968,
-# applying to Northern Ireland unconditionally and to Jersey, Guernsey and the
-# Isle of Man if they don't do something about it.
-#
-# (I am missing various Summer Time Orders that modified the 1972 Act to
-# harmonise with the EC since 1981. The major change is that the time changes
-# to 01:00 GMT.)
-#
-# - The Summer Time Order, 1992, SI 1992/1729 [SI == Statutory Instrument]
-#
-# This specifies dates of:
-#       Start       End
-# 1993  28 March    24 October
-# 1994  27 March    23 October
-# All start and end times are at 01:00 GMT....
-#
-# - Some text on the extent of Acts, from Halsbury's Statutes
-#
-# `An Act of the United Kingdom Parliament is to be construed prima facie
-# to apply to the whole of the United Kingdom and not to any place outside.
-# [...] The expression "United Kingdom" for this purpose includes (since
-# 1922) Great Britain (ie. England, Wales and Scotland) and Northern Ireland,
-# but it does not include the Channel Islands or the Isle of Man.'
-#
-# So, many of these measures specifically include Northern Ireland,
-# the Channel Islands and the Isle of Man. None of them exclude any
-# part of the UK. The default interpretation of Acts is that they apply
-# throughout the UK.
-#
-# With that, I rest my case Milud :-)
-#
-# Thanks are due to my learned legal friend Lorna Montgomerie, who dug out
-# the dusty old statutes, and to Melanie Allison of the Ministry of Defence,
-# who provided the wartime regulations and a snippet of Hansard explaining
-# why double summer time started on a Monday in 1945 (it was Easter).
-
-# From Peter Ilieve <peter@aldie.co.uk> (1996-05-29):
-# I have now got a copy of the British Standard Time Act 1968.
-# It says (S4(2)) that it expires at 02:00 GMT on 31 October 1971 unless
-# an Order in Council was passed in Parliament to make the Act permanent.
-# No Order was passed, so 02:00 1971-10-31 it is...
-#
-# Interestingly, it says baldly `This Act shall come into force on
-# 27 October 1968', without giving a time. As S1 of the Act merely
-# stated that `The time for general purposes in the United Kingdom
-# (to be known as British standard time) shall be one hour in
-# advance of Greenwich mean time throughout the year; ...' you could
-# possibly argue that the start time of BStandardT was 00:00 1968-10-27,
-# especially as the Act repealed the Summer Time Acts 1916--1947 in toto,
-# thereby destroying the authority of the Summer Time Order specifying
-# summer time in 1968....
-
-# From Peter Ilieve <peter@memex.co.uk> (1993-11-18)
-#
-# Here is a revised version of my tabrules file for the perl script I sent
-# before. I have personally verified the various Orders back to 1953 and
-# all the Acts.
-#
-# There are no changes to the dates we already have.
-#
-# My doubt about an early start in 1967 on 18 Feb was misplaced, the Order
-# does say 18 Feb. This is an interesting case as the first Order gave a
-# different date of 7 April 1967 for the Isle of Man but this was changed
-# before it came into effect by another Order for the Isle of Man alone.
-#
-# I don't think I will be able to find any more of the earlier Orders.
-# The annual volumes for 1949--52 do not contain the various Summer Time
-# Orders. They therefore don't appear in the index. They rate a mention in
-# italics in the numerical list at the start but that is all.
-# I think what happens is that the annual volume is produced well after the
-# end of the year in question, by which time the Summer Time Order is spent.
-# They assume that nobody would ever be stupid enough to want to see it
-# again so they leave it out.
-#
-# It might be a good idea to put this table, or the output of tabscript
-# showing all the moves because of Easter, in the europe file comments in
-# place of my old transcription of the Green Paper table [the UK Government
-# paper "Summer Time: A Consultation Document" (HMSO Cm722 June 1989)].
-#
-#              Peter Ilieve            peter@memex.co.uk
-#
-#
-# ## control file for tabscript, a program to generate UK summer time dates
-# ## matching the table in Cm 722, the 1989 Green Paper.
-# ## Lines like this are comments.
-# ## Lines with a single # at the start are copied into the output
-# ## Control lines are of the form
-# ## <years> <start date> <end date> <flags> <double start> <double end>
-# ## <years> is either a single year or a hyphen separated range, with --
-# ## also accepted as I use this in TeX a lot.
-# ## <start date> and <end date> are a digit followed bu a month name.
-# ## It is either an nth Saturday or an explicit date, depending on <flags>.
-# ## 0 and/or none are used when there is no date, as during 1968--71.
-# ## <flags> can contain `fixed' to indicate explicit dates and `double'
-# ## to indicate double summer time dates are present.
-# ## At present double requires fixed as well.
-# ## <double start> and <double end> are like the start and end dates, with
-# ## the exception of the 0 and/or none feature.
-#
-# ## Blank lines are also ignored.
-#
-# ## Places where I am uncertain, not having personally verified the dates
-# ## against the Act or Order, are marked ???
-# ## These dates are taken from the Cm 722 table.
-#
-# # Summer Time Act, 1916
-# 1916 21 May 1 October fixed
-#
-# ## I haven't yet looked for Orders for 1916--22 and I doubt I will find them.
-# # unknown Order or Orders ???
-# 1917 8 apr 17 sep fixed
-# 1918 24 mar 30 sep fixed
-# 1919 30 mar 29 sep fixed
-# # end date extended in 1920 from 27 Sep because of coal strike (from Cm 722)
-# 1920 28 mar 25 oct fixed
-# 1921 3 apr 3 oct fixed
-#
-# # Summer Time Act, 1922
-# # came into force 22 July 1922, too late for 1922, so missing Order ???
-# 1922 26 mar 8 oct fixed
-# 1923-1924 3 April 3 September
-#
-# # Summer Time Act, 1925
-# 1925--1938 3 April 1 October
-#
-# # Defence (Summer Time) Regulations, 1939
-# 1939 3 April 3 November
-# # 1940 amendment (SR&O 1940 Nos. 172 & 1883)
-# 1940 4 feb 0 none
-# # 1941 amendment (SR&O 1941 No. 476)
-# 1941 0 none 0 none fixed,double 4 may 10 aug
-# # 1942 amendment (SR&O 1942 No. 506)
-# 1942 0 none 0 none fixed,double 5 apr 9 aug
-# 1943 0 none 0 none fixed,double 4 apr 15 aug
-# # 1944 amendment (SR&O 1944 No. 932)
-# 1944 0 none 0 none fixed,double 2 apr 17 sep
-# # 1945 dates from Hansard, Oral Answers, 1 March 1945
-# 1945 0 none 7 oct fixed,double 2 apr 15 jul
-#
-# # reversion to Summer Time Act, 1925
-# 1946 3 April 1 October
-#
-# # Summer Time Act, 1947
-# # Fixed dates for 1947 only, gives power to have double summer time
-# 1947 16 mar 2 nov fixed,double 13 apr 10 aug
-# ## I can't find any trace of the Order for 1948.
-# # Unknown Order ???
-# 1948 14 mar 31 oct fixed
-# ## I know the numbers for the 1949--52 ones but the text is missing from the
-# ## annual volumes. I also don't know if the 49 Order was for 49 or 50, etc.
-# # Summer Time Order, 1949 (SI1949/373) ???
-# 1949 3 apr 30 oct fixed
-# # Summer Time Order, 1950 (SI1950/518) ???
-# 1950 16 apr 22 oct fixed
-# # Summer Time Order, 1951 (SI1951/430) ???
-# 1951 15 apr 21 oct fixed
-# # Summer Time Order, 1952 (SI1952/451) ???
-# 1952 20 apr 26 oct fixed
-#
-# # reversion to Summer Time Act, 1925
-# 1953--1960 3 April 1 October
-#
-# ## All Orders from here on specify fixed dates, not day after nth Sunday
-# ## Start pattern looks like Mar lastSun up to 1963, Mar Sun>=19 up to 1967.
-# ## End pattern looks like Oct Sun>=23 up to 1967.
-# # Summer Time Order, 1961 (SI1961/71)
-# 1961 26 March 29 October fixed
-# # Summer Time (1962) Order, 1961 (SI1961/2465)
-# 1962 25 Mar 28 Oct fixed
-# # Summer Time Order, 1963 (SI1963/81)
-# 1963 31 March 27 October fixed
-# # Summer Time (1964) Order, 1963 (SI1963/2101)
-# 1964 22 March 25 October fixed
-# # Summer Time Order, 1964 (SI1964/1201)
-# 1965 21 Mar 24 Oct fixed
-# 1966 20 Mar 23 Oct fixed
-# 1967 19 Mar 29 Oct fixed
-# # Summer Time Order, 1967 (SI1967/1148)
-# # Specifies different start date of 7 April for Isle of Man
-# # Summer Time Order, 1968 (SI1968/117)
-# # Changes Isle of Man start date to 18 Feb to match rest of UK
-# # British Standard Time Act, 1968
-# 1968 18 feb 0 none fixed
-# 1969--1970 0 none 0 none
-# 1971 0 none 31 oct fixed
-#
-# # Summer Time Act, 1972
-# 1972-1980 3 March 4 October
-#
-# # The pattern here looks like Last Sun in Mar, day after 4th Sat in Oct
-# # First EC Directive ???
-# # Summer Time Order, 1980 (SI1980/1089)
-# 1981    29 Mar  25 Oct fixed
-# 1982    28 Mar  24 Oct fixed
-# # Second EC Directive ???
-# # Summer Time Order, 1982 (SI1982/1673)
-# 1983    27 Mar  23 Oct fixed
-# 1984    25 Mar  28 Oct fixed
-# 1985    31 Mar  27 Oct fixed
-# # Third EC Directive ???
-# # Summer Time Order, 1986 (SI1986/223)
-# 1986    30 Mar  26 Oct fixed
-# 1987    29 Mar  25 Oct fixed
-# 1988    27 Mar  23 Oct fixed
-# # Fourth EC Directive ???
-# # Summer Time Order, 1988 (SI1988/931)
-# 1989    26 Mar  29 Oct fixed
-# # Fifth EC Directive ???
-# # Summer Time Order, 1989 (SI1989/985)
-# 1990    25 Mar  28 Oct fixed
-# 1991    31 Mar  27 Oct fixed
-# 1992    29 Mar  25 Oct fixed
-# # Sixth EC Directive
-# # Summer Time Order, 1992 (SI1992/1729)
-# 1993    28 Mar  24 Oct fixed
-# 1994    27 Mar  23 Oct fixed
-
-# From Peter Ilieve <peter@memex.co.uk> (1994-08-18):
-# I now have the text of the 7th EC directive on summer time arrangements
-# (94/21/EC), which was approved on 30 May....
-# The major changes from existing practice are that 1995 will be the last year
-# that the UK and Eire finish on a different date from everyone else,
-# and the common end date from 1996 onwards will be the last Sunday in October.
-# Year  Start          End             End (UK & Eire, 1995 only)
-# (rule) (last Sun)    (last Sun)      (4th Sun)
-# 1995 26 March        24 September    22 October
-# 1996 31 March        27 October
-# 1997 30 March        26 October
-#
-# From Peter Ilieve <peter@memex.co.uk> (1994-12-01):
-# The final piece of the legislative jigsaw for summer time in the UK for
-# 1995-97 is now in place.  The Summer Time Order 1994 (SI 1994/2798)
-# came into force on 16 November.  It restates the dates from the EC
-# seventh Summer Time Directive....
-#
-# From Peter Ilieve <peter@aldie.co.uk> (1996-04-20):
-# Proposals for the eighth directive were supposed to have been produced
-# by the Commission by 1 Jan 96. They have not yet appeared (I asked just
-# before Easter).
-
-# From Peter Ilieve <peter@memex.co.uk> (1994-03-28):
-# The [GB-Eire] end date of 22 October [1995] conflicts with your current rule
-# of Oct Sun>=23, and the historical UK formula of Sun after 4th Sat.
-# The last time 4th Sun and Sun after 4th Sat differed was in 1989,
-# when 29 October was used.  That year was covered by a UK Summer Time Order
-# for only a single year and it looks as though there was a matching 4th EC
-# directive for just this year.  I don't have the text of the 5th EC
-# directive (for 1990--92) but my guess would be it said 4th Sun.
-# To maintain strict historical accuracy you could start a new UK ending rule
-# of Oct Sun>=22 in 1990.
-
-# From Paul Eggert <eggert@twinsun.com> (1996-06-12):
-#
-# As Ilieve remarks, the date `20 April 1924' in the table of ``Summer Time: A
-# Consultation Document'' (Cm 722, 1989) table is a transcription error;
-# 20 April was an Easter Sunday.  Shanks has 13 April, the correct date.
-# Also, the table is not quite right for 1925 through 1938; the correct rules
-# (which Shanks uses) are given in the Summer Time Acts of 1922 and 1925.
-# Shanks and the UK Government paper disagree about the Apr 1956 transition;
-# since we have no other data, and since Shanks was correct in the other
-# points of disagreement about London, we'll believe Shanks for now.
-# Also, for lack of other data, we'll follow Shanks for Eire in 1940-1948.
-#
-# Given Peter Ilieve's comments, the following claims by Shanks are incorrect:
-#     * Wales did not switch from GMT to daylight savings time until
+# From Joseph S. Myers (1999-09-02):
+# ... some military cables (WO 219/4100 - this is a copy from the
+# main SHAEF archives held in the US National Archives, SHAEF/5252/8/516)
+# agree that the usage is BDST (this appears in a message dated 17 Feb 1945).
+
+# From Joseph S. Myers (2000-10-03):
+# On 18th April 1941, Sir Stephen Tallents of the BBC wrote to Sir
+# Alexander Maxwell of the Home Office asking whether there was any
+# official designation; the reply of the 21st was that there wasn't
+# but he couldn't think of anything better than the "Double British
+# Summer Time" that the BBC had been using informally.
+# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
+# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
+
+# From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
+# [N]o official designation has as far as I know been adopted for the time
+# which is to be introduced in May....
+# I cannot think of anything better than "Double British Summer Time"
+# which could not be said to run counter to any official description.
+
+# From Paul Eggert (2000-10-02):
+# Howse writes (p 157) `DBST' too, but `BDST' seems to have been common
+# and follows the more usual convention of putting the location name first,
+# so we use `BDST'.
+
+# Peter Ilieve <peter@aldie.co.uk> (1998-04-19) described at length
+# the history of summer time legislation in the United Kingdom.
+# Since 1998 Joseph S. Myers <jsm28@cam.ac.uk> has been updating
+# and extending this list, which can be found in
+# <a href="http://student.cusu.cam.ac.uk/~jsm28/british-time/">
+# History of legal time in Britain
+# </a> (2000-02-12).
+
+# From Joseph S. Myers <jsm28@cam.ac.uk> (1998-01-06):
+#
+# The legal time in the UK outside of summer time is definitely GMT, not UTC;
+# see Lord Tanlaw's speech
+# <a href="http://www.parliament.the-stationery-office.co.uk/pa/ld199697/ldhansrd/pdvn/lds97/text/70611-20.htm#70611-20_head0">
+# (Lords Hansard 11 June 1997 columns 964 to 976)
+# </a>.
+
+# From Paul Eggert (2000-02-17):
+#
+# For lack of other data, we'll follow Shanks for Eire in 1940-1948.
+#
+# Given Ilieve and Myers's data, the following claims by Shanks are incorrect:
+#     * Wales did not switch from GMT to daylight saving time until
 #      1921 Apr 3, when they began to conform with the rest of Great Britain.
 # Actually, Wales was identical after 1880.
 #     * Eire had two transitions on 1916 Oct 1.
 # It actually just had one transition.
-#     * Northern Ireland used single daylight savings time throughout WW II.
+#     * Northern Ireland used single daylight saving time throughout WW II.
 # Actually, it conformed to Britain.
 #     * GB-Eire changed standard time to 1 hour ahead of GMT on 1968-02-18.
 # Actually, that date saw the usual switch to summer time.
 # Standard time was not changed until 1968-10-27 (the clocks didn't change).
 #
-# The following claims by Shanks are possible though doubtful;
-# we'll ignore them for now.
+# Here is another incorrect claim by Shanks:
 #     * Jersey, Guernsey, and the Isle of Man did not switch from GMT
-#      to daylight savings time until 1921 Apr 3, when they began to
+#      to daylight saving time until 1921 Apr 3, when they began to
 #      conform with Great Britain.
+# S.R.&O. 1916, No. 382 and HO 45/10811/312364 (quoted above) say otherwise.
+#
+# The following claim by Shanks is possible though doubtful;
+# we'll ignore it for now.
 #     * Dublin's 1971-10-31 switch was at 02:00, even though London's was 03:00.
 #
 #
 # Whitman says Dublin Mean Time was -0:25:21, which is more precise than Shanks.
 
+# From Paul Eggert (1999-03-28):
+# Clive Feather (<news:859845706.26043.0@office.demon.net>, 1997-03-31)
+# reports that Folkestone (Cheriton) Shuttle Terminal uses Concession Time
+# (CT), equivalent to French civil time.
+# Julian Hill (<news:36118128.5A14@virgin.net>, 1998-09-30) reports that
+# trains between Dollands Moor (the freight facility next door)
+# and Frethun run in CT.
+# My admittedly uninformed guess is that the terminal has two authorities,
+# the French concession operators and the British civil authorities,
+# and that the time depends on who you're talking to.
+# If, say, the British police were called to the station for some reason,
+# I would expect the official police report to use GMT/BST and not CET/CEST.
+# This is a borderline case, but for now let's stick to GMT/BST.
+
 # From an anonymous contributor (1996-06-02):
 # The law governing time in Ireland is under Statutory Instrument SI 395/94,
 # which gives force to European Union 7th Council Directive # 94/21/EC.
 # "Irish Summer Time", abbreviated to "IST".
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-# 1916 to 1925--irregular
+# Summer Time Act, 1916
 Rule   GB-Eire 1916    only    -       May     21      2:00s   1:00    BST
 Rule   GB-Eire 1916    only    -       Oct      1      2:00s   0       GMT
+# S.R.&O. 1917, No. 358
 Rule   GB-Eire 1917    only    -       Apr      8      2:00s   1:00    BST
 Rule   GB-Eire 1917    only    -       Sep     17      2:00s   0       GMT
+# S.R.&O. 1918, No. 274
 Rule   GB-Eire 1918    only    -       Mar     24      2:00s   1:00    BST
 Rule   GB-Eire 1918    only    -       Sep     30      2:00s   0       GMT
+# S.R.&O. 1919, No. 297
 Rule   GB-Eire 1919    only    -       Mar     30      2:00s   1:00    BST
 Rule   GB-Eire 1919    only    -       Sep     29      2:00s   0       GMT
+# S.R.&O. 1920, No. 458
 Rule   GB-Eire 1920    only    -       Mar     28      2:00s   1:00    BST
+# S.R.&O. 1920, No. 1844
 Rule   GB-Eire 1920    only    -       Oct     25      2:00s   0       GMT
+# S.R.&O. 1921, No. 363
 Rule   GB-Eire 1921    only    -       Apr      3      2:00s   1:00    BST
 Rule   GB-Eire 1921    only    -       Oct      3      2:00s   0       GMT
+# S.R.&O. 1922, No. 264
 Rule   GB-Eire 1922    only    -       Mar     26      2:00s   1:00    BST
 Rule   GB-Eire 1922    only    -       Oct      8      2:00s   0       GMT
+# The Summer Time Act, 1922
 Rule   GB-Eire 1923    only    -       Apr     Sun>=16 2:00s   1:00    BST
 Rule   GB-Eire 1923    1924    -       Sep     Sun>=16 2:00s   0       GMT
-Rule   GB-Eire 1924    only    -       Apr     13      2:00s   1:00    BST
-# 1925 to 1939 start--regular, except for avoiding Easter
+Rule   GB-Eire 1924    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1925    1926    -       Apr     Sun>=16 2:00s   1:00    BST
+# The Summer Time Act, 1925
 Rule   GB-Eire 1925    1938    -       Oct     Sun>=2  2:00s   0       GMT
-Rule   GB-Eire 1927    only    -       Apr     10      2:00s   1:00    BST
+Rule   GB-Eire 1927    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1928    1929    -       Apr     Sun>=16 2:00s   1:00    BST
-Rule   GB-Eire 1930    only    -       Apr     13      2:00s   1:00    BST
+Rule   GB-Eire 1930    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1931    1932    -       Apr     Sun>=16 2:00s   1:00    BST
-Rule   GB-Eire 1933    only    -       Apr      9      2:00s   1:00    BST
+Rule   GB-Eire 1933    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1934    only    -       Apr     Sun>=16 2:00s   1:00    BST
-Rule   GB-Eire 1935    only    -       Apr     14      2:00s   1:00    BST
+Rule   GB-Eire 1935    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1936    1937    -       Apr     Sun>=16 2:00s   1:00    BST
-Rule   GB-Eire 1938    only    -       Apr     10      2:00s   1:00    BST
+Rule   GB-Eire 1938    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1939    only    -       Apr     Sun>=16 2:00s   1:00    BST
-# 1939 end to 1947--irregular, and with double summer time
-Rule   GB-Eire 1939    only    -       Nov     19      2:00s   0       GMT
-Rule   GB-Eire 1940    only    -       Feb     25      2:00s   1:00    BST
+# S.R.&O. 1939, No. 1379
+Rule   GB-Eire 1939    only    -       Nov     Sun>=16 2:00s   0       GMT
+# S.R.&O. 1940, No. 172 and No. 1883
+Rule   GB-Eire 1940    only    -       Feb     Sun>=23 2:00s   1:00    BST
+# S.R.&O. 1941, No. 476
 Rule   GB-Eire 1941    only    -       May     Sun>=2  1:00s   2:00    BDST
 Rule   GB-Eire 1941    1943    -       Aug     Sun>=9  1:00s   1:00    BST
+# S.R.&O. 1942, No. 506
 Rule   GB-Eire 1942    1944    -       Apr     Sun>=2  1:00s   2:00    BDST
+# S.R.&O. 1944, No. 932
 Rule   GB-Eire 1944    only    -       Sep     Sun>=16 1:00s   1:00    BST
-# Double daylight starts on a Monday in 1945--see above.
-Rule   GB-Eire 1945    only    -       Apr      2      1:00s   2:00    BDST
-Rule   GB-Eire 1945    only    -       Jul     15      1:00s   1:00    BST
-Rule   GB-Eire 1945    only    -       Oct      7      2:00s   0       GMT
-Rule   GB-Eire 1946    only    -       Apr     14      2:00s   1:00    BST
-Rule   GB-Eire 1946    only    -       Oct      6      2:00s   0       GMT
+# S.R.&O. 1945, No. 312
+Rule   GB-Eire 1945    only    -       Apr     Mon>=2  1:00s   2:00    BDST
+Rule   GB-Eire 1945    only    -       Jul     Sun>=9  1:00s   1:00    BST
+# S.R.&O. 1945, No. 1208
+Rule   GB-Eire 1945    1946    -       Oct     Sun>=2  2:00s   0       GMT
+Rule   GB-Eire 1946    only    -       Apr     Sun>=9  2:00s   1:00    BST
+# The Summer Time Act, 1947
 Rule   GB-Eire 1947    only    -       Mar     16      2:00s   1:00    BST
 Rule   GB-Eire 1947    only    -       Apr     13      1:00s   2:00    BDST
 Rule   GB-Eire 1947    only    -       Aug     10      1:00s   1:00    BST
 Rule   GB-Eire 1947    only    -       Nov      2      2:00s   0       GMT
-# So much for double saving time.  1948 and 1949, irregular.
+# Summer Time Order, 1948 (S.I. 1948/495)
 Rule   GB-Eire 1948    only    -       Mar     14      2:00s   1:00    BST
-Rule   GB-Eire 1948    1949    -       Oct     lastSun 2:00s   0       GMT
+Rule   GB-Eire 1948    only    -       Oct     31      2:00s   0       GMT
+# Summer Time Order, 1949 (S.I. 1949/373)
 Rule   GB-Eire 1949    only    -       Apr      3      2:00s   1:00    BST
-# 1950 through start of 1953, regular.
-Rule   GB-Eire 1950    1953    -       Apr     Sun>=14 2:00s   1:00    BST
+Rule   GB-Eire 1949    only    -       Oct     30      2:00s   0       GMT
+# Summer Time Order, 1950 (S.I. 1950/518)
+# Summer Time Order, 1951 (S.I. 1951/430)
+# Summer Time Order, 1952 (S.I. 1952/451)
+Rule   GB-Eire 1950    1952    -       Apr     Sun>=14 2:00s   1:00    BST
 Rule   GB-Eire 1950    1952    -       Oct     Sun>=21 2:00s   0       GMT
-# 1954 to 1980, starting rules
-Rule   GB-Eire 1954    only    -       Apr     11      2:00s   1:00    BST
+# revert to the rules of the Summer Time Act, 1925
+Rule   GB-Eire 1953    only    -       Apr     Sun>=16 2:00s   1:00    BST
+Rule   GB-Eire 1953    1960    -       Oct     Sun>=2  2:00s   0       GMT
+Rule   GB-Eire 1954    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1955    1956    -       Apr     Sun>=16 2:00s   1:00    BST
-Rule   GB-Eire 1957    only    -       Apr     14      2:00s   1:00    BST
+Rule   GB-Eire 1957    only    -       Apr     Sun>=9  2:00s   1:00    BST
 Rule   GB-Eire 1958    1959    -       Apr     Sun>=16 2:00s   1:00    BST
-Rule   GB-Eire 1960    only    -       Apr     10      2:00s   1:00    BST
+Rule   GB-Eire 1960    only    -       Apr     Sun>=9  2:00s   1:00    BST
+# Summer Time Order, 1961 (S.I. 1961/71)
+# Summer Time (1962) Order, 1961 (S.I. 1961/2465)
+# Summer Time Order, 1963 (S.I. 1963/81)
 Rule   GB-Eire 1961    1963    -       Mar     lastSun 2:00s   1:00    BST
+Rule   GB-Eire 1961    1968    -       Oct     Sun>=23 2:00s   0       GMT
+# Summer Time (1964) Order, 1963 (S.I. 1963/2101)
+# Summer Time Order, 1964 (S.I. 1964/1201)
+# Summer Time Order, 1967 (S.I. 1967/1148)
 Rule   GB-Eire 1964    1967    -       Mar     Sun>=19 2:00s   1:00    BST
+# Summer Time Order, 1968 (S.I. 1968/117)
 Rule   GB-Eire 1968    only    -       Feb     18      2:00s   1:00    BST
+# The British Standard Time Act, 1968
+#      (no summer time)
+# The Summer Time Act, 1972
 Rule   GB-Eire 1972    1980    -       Mar     Sun>=16 2:00s   1:00    BST
-# 1953 to 1980, ending rules
-Rule   GB-Eire 1953    1960    -       Oct     Sun>=1  2:00s   0       GMT
-Rule   GB-Eire 1961    1968    -       Oct     Sun>=23 2:00s   0       GMT
 Rule   GB-Eire 1972    1980    -       Oct     Sun>=23 2:00s   0       GMT
-# 1981 on
+# Summer Time Order, 1980 (S.I. 1980/1089)
+# Summer Time Order, 1982 (S.I. 1982/1673)
+# Summer Time Order, 1986 (S.I. 1986/223)
+# Summer Time Order, 1988 (S.I. 1988/931)
 Rule   GB-Eire 1981    1995    -       Mar     lastSun 1:00u   1:00    BST
 Rule   GB-Eire 1981    1989    -       Oct     Sun>=23 1:00u   0       GMT
+# Summer Time Order, 1989 (S.I. 1989/985)
+# Summer Time Order, 1992 (S.I. 1992/1729)
+# Summer Time Order 1994 (S.I. 1994/2798)
 Rule   GB-Eire 1990    1995    -       Oct     Sun>=22 1:00u   0       GMT
+# Summer Time Order 1997 (S.I. 1997/2982)
 # See EU for rules starting in 1996.
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/London   -0:01:15 -      LMT     1847 Sep 22
+Zone   Europe/London   -0:01:15 -      LMT     1847 Dec  1
                         0:00   GB-Eire %s      1968 Oct 27
                         1:00   -       BST     1971 Oct 31 2:00u
                         0:00   GB-Eire %s      1996
                         0:00   EU      GMT/BST
 Zone   Europe/Belfast  -0:23:40 -      LMT     1880 Aug  2
                        -0:25:21 -      DMT     1916 May 21 2:00    # Dublin MT
-                       -0:25:21 1:00   IST     1916 Oct  1 3:00    # Irish Summer Time
+                       -0:25:21 1:00   IST     1916 Oct  1 2:00s   # Irish Summer Time
                         0:00   GB-Eire %s      1968 Oct 27
                         1:00   -       BST     1971 Oct 31 2:00u
                         0:00   GB-Eire %s      1996
                         0:00   EU      GMT/BST
 Zone   Europe/Dublin   -0:25:21 -      LMT     1880 Aug  2
                        -0:25:21 -      DMT     1916 May 21 2:00    # Dublin MT
-                       -0:25:21 1:00   IST     1916 Oct  1 3:00
+                       -0:25:21 1:00   IST     1916 Oct  1 2:00s
                         0:00   GB-Eire %s      1921 Dec  6 # independence
                         0:00   GB-Eire GMT/IST 1940 Feb 25 2:00
                         0:00   1:00    IST     1946 Oct  6 2:00
@@ -806,6 +407,11 @@ Rule       EU      1978    only    -       Oct      1       1:00u  0       -
 Rule   EU      1979    1995    -       Sep     lastSun  1:00u  0       -
 Rule   EU      1981    max     -       Mar     lastSun  1:00u  1:00    S
 Rule   EU      1996    max     -       Oct     lastSun  1:00u  0       -
+# The most recent directive covers the years starting in 2002.  See:
+# <a href="http://europa.eu.int/eur-lex/en/lif/dat/2000/en_300L0084.html"
+# Directive 2000/84/EC of the European Parliament and of the Council
+# of 19 January 2001 on summer-time arrangements.
+# </a>
 
 # W-Eur differs from EU only in that W-Eur uses standard time.
 Rule   W-Eur   1977    1980    -       Apr     Sun>=1   1:00s  1:00    S
@@ -822,7 +428,6 @@ Rule        C-Eur   1916    only    -       Oct      1       1:00   0       -
 Rule   C-Eur   1917    1918    -       Apr     Mon>=15  2:00s  1:00    S
 Rule   C-Eur   1917    1918    -       Sep     Mon>=15  2:00s  0       -
 Rule   C-Eur   1940    only    -       Apr      1       2:00s  1:00    S
-# Whitman says 1941 DST was only from Feb 25 to Oct 5; go with Shanks.
 Rule   C-Eur   1942    only    -       Nov      2       2:00s  0       -
 Rule   C-Eur   1943    only    -       Mar     29       2:00s  1:00    S
 Rule   C-Eur   1943    only    -       Oct      4       2:00s  0       -
@@ -848,21 +453,22 @@ Rule      E-Eur   1996    max     -       Oct     lastSun  0:00   0       -
 Rule   Russia  1917    only    -       Jul      1      23:00   1:00    MST     # Moscow Summer Time
 Rule   Russia  1917    only    -       Dec     28       0:00   0       MMT     # Moscow Mean Time
 Rule   Russia  1918    only    -       May     31      22:00   2:00    MDST    # Moscow Double Summer Time
-Rule   Russia  1918    only    -       Sep     17       0:00   1:00    MST
+Rule   Russia  1918    only    -       Sep     16       1:00   1:00    MST
 Rule   Russia  1919    only    -       May     31      23:00   2:00    MDST
 Rule   Russia  1919    only    -       Jul      1       2:00   1:00    S
 Rule   Russia  1919    only    -       Aug     16       0:00   0       -
 Rule   Russia  1921    only    -       Feb     14      23:00   1:00    S
-# Shanks gives 1921 Mar 21 for the following transition.
-# From Andrey A. Chernov <ache@astral.msk.su> (1993-11-12):
-# My sources says, that it is Mar 20, not 21.
-Rule   Russia  1921    only    -       Mar     20      23:00   2:00    DS
+Rule   Russia  1921    only    -       Mar     20      23:00   2:00    M # Midsummer
 Rule   Russia  1921    only    -       Sep      1       0:00   1:00    S
 Rule   Russia  1921    only    -       Oct      1       0:00   0       -
+# Act No.925 of the Council of Ministers of the USSR (1980-10-24):
 Rule   Russia  1981    1984    -       Apr      1       0:00   1:00    S
 Rule   Russia  1981    1983    -       Oct      1       0:00   0       -
+# Act No.967 of the Council of Ministers of the USSR (1984-09-13), repeated in
+# Act No.227 of the Council of Ministers of the USSR (1989-03-14):
 Rule   Russia  1984    1991    -       Sep     lastSun  2:00s  0       -
 Rule   Russia  1985    1991    -       Mar     lastSun  2:00s  1:00    S
+#
 Rule   Russia  1992    only    -       Mar     lastSat  23:00  1:00    S
 Rule   Russia  1992    only    -       Sep     lastSat  23:00  0       -
 Rule   Russia  1993    max     -       Mar     lastSun  2:00s  1:00    S
@@ -931,12 +537,10 @@ Rule      Albania 1982    only    -       Oct      3      0:00    0       -
 Rule   Albania 1983    only    -       Apr     18      0:00    1:00    S
 Rule   Albania 1983    only    -       Oct      1      0:00    0       -
 Rule   Albania 1984    only    -       Apr      1      0:00    1:00    S
-Rule   Albania 1984    only    -       Oct      1      0:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Tirane   1:19:20 -       LMT     1914
                        1:00    -       CET     1940 Jun 16
-                       1:00    Albania CE%sT   1985 Mar 31 1:00
-                       1:00    W-Eur   CE%sT   1991
+                       1:00    Albania CE%sT   1984 Jul
                        1:00    EU      CE%sT
 
 # Andorra
@@ -967,73 +571,91 @@ Zone      Europe/Vienna   1:05:20 -       LMT     1893 Apr
 # Belarus
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Minsk    1:50:16 -       LMT     1880
-                       2:30:20 Russia  %s      1919 Jul 1 2:00
-                       3:00    Russia  MSK/MSD 1922 Oct
+                       1:50    -       MMT     1924 May 2 # Minsk Mean Time
                        2:00    -       EET     1930 Jun 21
-                       3:00    Russia  MSK/MSD 1991 Mar 31 2:00s
+                       3:00    -       MSK     1941 Jun 28
+                       1:00    C-Eur   CE%sT   1944 Jul  3
+                       3:00    Russia  MSK/MSD 1990
+                       3:00    -       MSK     1991 Mar 31 2:00s
                        2:00    1:00    EEST    1991 Sep 29 2:00s
-                       2:00    -       EET     1992 Mar 29 0:00
-                       2:00    1:00    EEST    1992 Sep 27 0:00
+                       2:00    -       EET     1992 Mar 29 0:00s
+                       2:00    1:00    EEST    1992 Sep 27 0:00s
                        2:00    Russia  EE%sT
 
 # Belgium
-# Whitman and Shanks disagree; go with Shanks, usually.
+#
+# From Paul Eggert (1997-07-02):
+# Entries from 1918 through 1991 are taken from:
+#      Annuaire de L'Observatoire Royal de Belgique,
+#      Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
+#      (Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
+#      pp 8-9.
+# LMT before 1892 was 0:17:30, according to the official journal of Belgium:
+#      Moniteur Belge, Samedi 30 Avril 1892, N.121.
+# Thanks to Pascal Delmoitie <pascal@belnet.be> for these references.
+# The 1918 rules are listed for completeness; they apply to unoccupied Belgium.
+# Assume Brussels switched to WET in 1918 when the armistice took effect.
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-# From Whitman:
+Rule   Belgium 1918    only    -       Mar      9       0:00s  1:00    S
+Rule   Belgium 1918    1919    -       Oct     Sat>=1  23:00s  0       -
 Rule   Belgium 1919    only    -       Mar      1      23:00s  1:00    S
-Rule   Belgium 1919    only    -       Oct      4      23:00s  0       -
-# Shanks gives 1920 Feb 14 23:00s; go with Whitman.
-Rule   Belgium 1920    1921    -       Mar     14      23:00s  1:00    S
+Rule   Belgium 1920    only    -       Feb     14      23:00s  1:00    S
 Rule   Belgium 1920    only    -       Oct     23      23:00s  0       -
+Rule   Belgium 1921    only    -       Mar     14      23:00s  1:00    S
 Rule   Belgium 1921    only    -       Oct     25      23:00s  0       -
 Rule   Belgium 1922    only    -       Mar     25      23:00s  1:00    S
-# Whitman gives 1927 Oct 1 2:00s and 1928 Oct 7 2:00s; go with Shanks.
-Rule   Belgium 1922    1928    -       Oct     Sat>=1  23:00s  0       -
+Rule   Belgium 1922    1927    -       Oct     Sat>=1  23:00s  0       -
 Rule   Belgium 1923    only    -       Apr     21      23:00s  1:00    S
 Rule   Belgium 1924    only    -       Mar     29      23:00s  1:00    S
 Rule   Belgium 1925    only    -       Apr      4      23:00s  1:00    S
+# DSH writes that a royal decree of 1926-02-22 specified the Sun following 3rd
+# Sat in Apr (except if it's Easter, in which case it's one Sunday earlier),
+# to Sun following 1st Sat in Oct, and that a royal decree of 1928-09-15
+# changed the transition times to 02:00 GMT.
 Rule   Belgium 1926    only    -       Apr     17      23:00s  1:00    S
 Rule   Belgium 1927    only    -       Apr      9      23:00s  1:00    S
 Rule   Belgium 1928    only    -       Apr     14      23:00s  1:00    S
+Rule   Belgium 1928    1938    -       Oct     Sun>=2   2:00s  0       -
 Rule   Belgium 1929    only    -       Apr     21       2:00s  1:00    S
-Rule   Belgium 1929    1938    -       Oct     Sun>=2   2:00s  0       -
 Rule   Belgium 1930    only    -       Apr     13       2:00s  1:00    S
 Rule   Belgium 1931    only    -       Apr     19       2:00s  1:00    S
-Rule   Belgium 1932    only    -       Apr     17       2:00s  1:00    S
+Rule   Belgium 1932    only    -       Apr      3       2:00s  1:00    S
 Rule   Belgium 1933    only    -       Mar     26       2:00s  1:00    S
 Rule   Belgium 1934    only    -       Apr      8       2:00s  1:00    S
 Rule   Belgium 1935    only    -       Mar     31       2:00s  1:00    S
 Rule   Belgium 1936    only    -       Apr     19       2:00s  1:00    S
-# Whitman says 1937 Apr 18 2:00s; go with Shanks.
 Rule   Belgium 1937    only    -       Apr      4       2:00s  1:00    S
-# Whitman says 1938 Apr 10 2:00s; go with Shanks.
 Rule   Belgium 1938    only    -       Mar     27       2:00s  1:00    S
 Rule   Belgium 1939    only    -       Apr     16       2:00s  1:00    S
 Rule   Belgium 1939    only    -       Nov     19       2:00s  0       -
+Rule   Belgium 1940    only    -       Feb     25       2:00s  1:00    S
+Rule   Belgium 1944    only    -       Sep     17       2:00s  0       -
 Rule   Belgium 1945    only    -       Apr      2       2:00s  1:00    S
 Rule   Belgium 1945    only    -       Sep     16       2:00s  0       -
 Rule   Belgium 1946    only    -       May     19       2:00s  1:00    S
 Rule   Belgium 1946    only    -       Oct      7       2:00s  0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/Brussels 0:17:20 -       LMT     1880
-                       0:17:20 -       BMT     1892 May  1 12:00 # Brussels MT
-                       0:00    -       WET     1914 Aug  4
-                       1:00    C-Eur   CE%sT   1919 Mar  1 23:00
-                       0:00    Belgium WE%sT   1940 Feb 24 23:00
-                       1:00    C-Eur   CE%sT   1945 Apr  2  2:00
+Zone   Europe/Brussels 0:17:30 -       LMT     1880
+                       0:17:30 -       BMT     1892 May  1 12:00 # Brussels MT
+                       0:00    -       WET     1914 Nov  8
+                       1:00    -       CET     1916 May  1  0:00
+                       1:00    C-Eur   CE%sT   1918 Nov 11 11:00u
+                       0:00    Belgium WE%sT   1940 May 20  2:00s
+                       1:00    C-Eur   CE%sT   1944 Sep  3
                        1:00    Belgium CE%sT   1977
                        1:00    EU      CE%sT
 
 # Bosnia and Herzegovina
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/Sarajevo 1:13:40 -       LMT     1884
-                       1:00    -       CET     1941 Apr 18 23:00
-                       1:00    C-Eur   CE%sT   1945 May  8  2:00s
-                       1:00    1:00    CEST    1945 Sep 16  2:00s
-                       1:00    -       CET     1983
-                       1:00    EU      CE%sT
+# see Yugoslavia
 
 # Bulgaria
+#
+# From Plamen Simenov <P.Simeonov@cnsys.bg> via Steffen Thorsen (1999-09-09):
+# A document of Government of Bulgaria (No.94/1997) says:
+# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
+# EETDST --> EET is in 04:00 Local time in last Sunday of October
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Bulg    1979    only    -       Mar     31      23:00   1:00    S
 Rule   Bulg    1979    only    -       Oct      1       1:00   0       -
@@ -1048,19 +670,13 @@ Zone     Europe/Sofia    1:33:16 -       LMT     1880
                        2:00    -       EET     1979 Mar 31 23:00
                        2:00    Bulg    EE%sT   1982 Sep 26  2:00
                        2:00    C-Eur   EE%sT   1991
-                       2:00    E-Eur   EE%sT
+                       2:00    E-Eur   EE%sT   1997
+                       2:00    EU      EE%sT
 
 # Croatia
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/Zagreb   1:03:52 -       LMT     1884
-                       1:00    -       CET     1941 Apr 18 23:00
-                       1:00    C-Eur   CE%sT   1945 May  8  2:00s
-                       1:00    1:00    CEST    1945 Sep 16  2:00s
-                       1:00    -       CET     1983
-                       1:00    EU      CE%sT
+# see Yugosloavia
 
 # Czech Republic
-# Gregorian calendar adopted 1584-01-17.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Czech   1945    only    -       Apr      8      2:00s   1:00    S
 Rule   Czech   1945    only    -       Nov     18      2:00s   0       -
@@ -1076,8 +692,7 @@ Zone       Europe/Prague   0:57:44 -       LMT     1850
                        1:00    Czech   CE%sT   1979
                        1:00    EU      CE%sT
 
-# Denmark
-# Gregorian calendar adopted 1700-03-01.
+# Denmark, Faeroe Islands, and Greenland
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Denmark 1916    only    -       May     14      23:00   1:00    S
 Rule   Denmark 1916    only    -       Sep     30      23:00   0       -
@@ -1118,14 +733,14 @@ Rule     Thule   1993    max     -       Apr     Sun>=1  2:00    1:00    D
 Rule   Thule   1993    max     -       Oct     lastSun 2:00    0       S
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone America/Scoresbysund -1:29:00 -   LMT     1916 Jul 28 # Ittoqqortoormit
+Zone America/Scoresbysund -1:29:00 -   LMT     1916 Jul 28 # Ittoqqortoormiit
                        -2:00   -       CGT     1980 Apr  6 2:00
                        -2:00   C-Eur   CG%sT   1981 Mar 29
                        -1:00   EU      EG%sT
 Zone America/Godthab   -3:26:56 -      LMT     1916 Jul 28 # Nuuk
                        -3:00   -       WGT     1980 Apr  6 2:00
                        -3:00   EU      WG%sT
-Zone America/Thule     -4:35:08 -      LMT     1916 Jul 28 # Pituffik
+Zone America/Thule     -4:35:08 -      LMT     1916 Jul 28 # Pituffik air base
                        -4:00   Thule   A%sT
 
 # Estonia
@@ -1143,6 +758,32 @@ Zone America/Thule        -4:35:08 -      LMT     1916 Jul 28 # Pituffik
 # A discussion is running about the summer time efficiency and effect on
 # human physiology.  It seems that Estonia maybe will not change to
 # summer time next spring.''
+
+# From Peter Ilieve <peter@aldie.co.uk> (1998-11-04), heavily edited:
+# <a href="http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390">
+# The 1998-09-22 Estonian time law
+# </a>
+# refers to the Eighth Directive and cites the association agreement between
+# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
+#
+# I also asked [my relative] whether they use any standard abbreviation
+# for their standard and summer times. He says no, they use "suveaeg"
+# (summer time) and "talveaeg" (winter time).
+
+# From <a href="http://www.baltictimes.com/">The Baltic Times</a> (1999-09-09)
+# via Steffen Thorsen:
+# This year will mark the last time Estonia shifts to summer time,
+# a council of the ruling coalition announced Sept. 6....
+# But what this could mean for Estonia's chances of joining the European
+# Union are still unclear.  In 1994, the EU declared summer time compulsory
+# for all member states until 2001.  Brussels has yet to decide what to do
+# after that.
+
+# From Mart Oruaas (2000-01-29):
+# Regulation no. 301 (1999-10-12) obsoletes previous regulation
+# no. 206 (1998-09-22) and thus sticks Estonia to +02:00 GMT for all
+# the year round.  The regulation is effective 1999-11-01.
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Tallinn  1:39:00 -       LMT     1880
                        1:39:00 -       TMT     1918 Feb # Tallinn Mean Time
@@ -1153,10 +794,11 @@ Zone     Europe/Tallinn  1:39:00 -       LMT     1880
                        1:00    C-Eur   CE%sT   1944 Sep 22
                        3:00    Russia  MSK/MSD 1989 Mar 26 2:00s
                        2:00    1:00    EEST    1989 Sep 24 2:00s
-                       2:00    C-Eur   EE%sT
+                       2:00    C-Eur   EE%sT   1998 Sep 22
+                       2:00    EU      EE%sT   1999 Nov  1
+                       2:00    -       EET
 
 # Finland
-# See Sweden for when the Gregorian calendar was adopted.
 #
 # From Hannu Strang <chs@apu.fi> (25 Sep 1994 06:03:37 UTC):
 # Well, here in Helsinki we're just changing from summer time to regular one,
@@ -1176,14 +818,24 @@ Zone     Europe/Helsinki 1:39:52 -       LMT     1878 May 31
                        2:00    EU      EE%sT
 
 # France
-# Gregorian calendar adopted 1582-12-20.
-# French Revolutionary calendar used 1792-09-22 - 1805-12-31.
+
+# From Ciro Discepolo (2000-12-20):
+#
+# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
+# Traditionnelles - Paris 2 books, 1993
+#
+# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
+# Paris, 1991
+#
+# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
+# Guy tredaniel, Paris 1987
+
+
 #
 # Shanks seems to use `24:00' ambiguously; we resolve it with Whitman.
-# From Shanks (1991):
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   France  1916    only    -       Jun     14      23:00s  1:00    S
-Rule   France  1916    1919    -       Oct     Sun>=1   0:00   0       -
+Rule   France  1916    1919    -       Oct     Sun>=1  23:00s  0       -
 Rule   France  1917    only    -       Mar     24      23:00s  1:00    S
 Rule   France  1918    only    -       Mar      9      23:00s  1:00    S
 Rule   France  1919    only    -       Mar      1      23:00s  1:00    S
@@ -1192,6 +844,9 @@ Rule       France  1920    only    -       Oct     23      23:00s  0       -
 Rule   France  1921    only    -       Mar     14      23:00s  1:00    S
 Rule   France  1921    only    -       Oct     25      23:00s  0       -
 Rule   France  1922    only    -       Mar     25      23:00s  1:00    S
+# DSH writes that a law of 1923-05-24 specified 3rd Sat in Apr at 23:00 to 1st
+# Sat in Oct at 24:00; and that in 1930, because of Easter, the transitions
+# were Apr 12 and Oct 5.  Go with Shanks.
 Rule   France  1922    1938    -       Oct     Sat>=1  23:00s  0       -
 Rule   France  1923    only    -       May     26      23:00s  1:00    S
 Rule   France  1924    only    -       Mar     29      23:00s  1:00    S
@@ -1212,45 +867,73 @@ Rule     France  1938    only    -       Mar     26      23:00s  1:00    S
 Rule   France  1939    only    -       Apr     15      23:00s  1:00    S
 Rule   France  1939    only    -       Nov     18      23:00s  0       -
 Rule   France  1940    only    -       Feb     25       2:00   1:00    S
-# The French rules for 1941-1944 were not used in Paris,
-# but were used in other places (e.g. Monaco).
-Rule   France  1941    only    -       May      5       0:00   2:00    DS
-Rule   France  1941    only    -       Oct      6       1:00   1:00    S
-Rule   France  1942    only    -       Mar      8       0:00   2:00    DS
+# The French rules for 1941-1944 were not used in Paris, but Shanks writes
+# that they were used in Monaco and in many French locations.
+# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
+# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
+# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Decartes,
+# Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
+# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
+# Dole, Morez, St-Claude, and Collognes (Haute-Savioe).
+Rule   France  1941    only    -       May      5       0:00   2:00    M # Midsummer
+# Shanks says this transition occurred at Oct 6 1:00,
+# but go with Denis.Excoffier@ens.fr (1997-12-12),
+# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
+# as saying 5/10/41 22hUT.
+Rule   France  1941    only    -       Oct      6       0:00   1:00    S
+Rule   France  1942    only    -       Mar      9       0:00   2:00    M
 Rule   France  1942    only    -       Nov      2       3:00   1:00    S
-Rule   France  1943    only    -       Mar     29       2:00   2:00    DS
-Rule   France  1943    only    -       Nov      4       3:00   1:00    S
-Rule   France  1944    only    -       Apr      3       2:00   2:00    DS
+Rule   France  1943    only    -       Mar     29       2:00   2:00    M
+Rule   France  1943    only    -       Oct      4       3:00   1:00    S
+Rule   France  1944    only    -       Apr      3       2:00   2:00    M
 Rule   France  1944    only    -       Oct      8       1:00   1:00    S
-Rule   France  1945    only    -       Apr      2       2:00   2:00    DS
+Rule   France  1945    only    -       Apr      2       2:00   2:00    M
 Rule   France  1945    only    -       Sep     16       3:00   0       -
-Rule   France  1976    only    -       Mar     28       2:00s  1:00    S
-Rule   France  1976    only    -       Sep     lastSun  2:00s  0       -
+# Shanks gives Mar 28 2:00 and Sep 26 3:00;
+# go with Excoffier's 28/3/76 0hUT and 25/9/76 23hUT.
+Rule   France  1976    only    -       Mar     28       1:00   1:00    S
+Rule   France  1976    only    -       Sep     26       1:00   0       -
 # Shanks gives 0:09 for Paris Mean Time, and Whitman gives 0:09:05,
 # but Howse quotes the actual French legislation as saying 0:09:21.
 # Go with Howse.  Howse writes that the time in France was officially based
 # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/Paris    0:09:21 -       LMT     1891 Mar 15 0:01
-                       0:09:21 -       PMT     1911 Mar 11    # Paris Mean Time
-                       0:00    France  WE%sT   1940 Jun 14
+Zone   Europe/Paris    0:09:21 -       LMT     1891 Mar 15  0:01
+                       0:09:21 -       PMT     1911 Mar 11  0:01  # Paris MT
+# Shanks gives 1940 Jun 14 0:00; go with Excoffier and Le Corre.
+                       0:00    France  WE%sT   1940 Jun 14 23:00
+# Le Corre says Paris stuck with occupied-France time after the liberation;
+# go with Shanks.
                        1:00    C-Eur   CE%sT   1944 Aug 25
-                       0:00    France  WE%sT   1945 Sep 16 3:00
+                       0:00    France  WE%sT   1945 Sep 16  3:00
                        1:00    France  CE%sT   1977
                        1:00    EU      CE%sT
 
 # Germany
 
+# From Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> (1998-09-29):
+# The German time zone web site by the Physikalisch-Technische
+# Bundesanstalt contains DST information back to 1916.
+#
+#      <a href="http://www.ptb.de/english/org/4/43/432/lega.htm">
+#      Realisation of Legal Time in Germany
+#      </a>
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Germany 1945    only    -       Apr      2      2:00s   1:00    S
-Rule   Germany 1945    only    -       May     24      2:00    2:00    DS
-Rule   Germany 1945    only    -       Sep     24      3:00    1:00    S
+# Shanks says 05-24 2:00 to 09-24 3:00 for DDST; go with the PTB, who quotes
+# the Archiv fuer publizist. Arbeit (Munzinger-Archiv) 652 (Zeitsystem)
+# (1961-11-25), which gives dates only.  Guess 3:00 transition times.
+Rule   Germany 1945    only    -       May     31      3:00    2:00    M # Midsummer
+Rule   Germany 1945    only    -       Sep     23      3:00    1:00    S
 Rule   Germany 1945    only    -       Nov     18      2:00s   0       -
 Rule   Germany 1946    only    -       Apr     14      2:00s   1:00    S
-# Whitman gives 1948 Oct 31; go with Shanks.
-Rule   Germany 1946    1949    -       Oct     Sun>=1  2:00s   0       -
+Rule   Germany 1946    only    -       Oct      7      2:00s   0       -
+Rule   Germany 1947    1949    -       Oct     Sun>=1  2:00s   0       -
 Rule   Germany 1947    only    -       Apr      6      2:00s   1:00    S
-Rule   Germany 1947    only    -       May     11      2:00s   2:00    DS
+# The PTB gives 3:00 CET and 3:00 CEST for the midsummer transition times;
+# go with Shanks.
+Rule   Germany 1947    only    -       May     11      2:00s   2:00    M
 Rule   Germany 1947    only    -       Jun     29      3:00    1:00    S
 Rule   Germany 1948    only    -       Apr     18      2:00s   1:00    S
 Rule   Germany 1949    only    -       Apr     10      2:00s   1:00    S
@@ -1303,7 +986,6 @@ Zone       Europe/Athens   1:34:52 -       LMT     1895 Sep 14
                        2:00    EU      EE%sT
 
 # Hungary
-# Gregorian calendar adopted 1587-11-01.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Hungary 1918    only    -       Apr      1       3:00   1:00    S
 Rule   Hungary 1918    only    -       Sep     29       3:00   0       -
@@ -1362,10 +1044,10 @@ Zone    Europe/Budapest 1:16:20 -       LMT     1890 Oct
 # might be a reference to the Julian calendar as opposed to Gregorian, or it
 # might mean something else (???).
 #
-# From Paul Eggert <eggert@twinsun.com> (1993-12-09):
+# From Paul Eggert <eggert@twinsun.com> (1999-10-29):
 # The Iceland Almanak, Shanks and Whitman disagree on many points.
 # We go with the Almanak, except for one claim from Shanks, namely that
-# Reykavik was -1:28 from 1837 to 1908, local mean time before that.
+# Reykavik was 21W57 from 1837 to 1908, local mean time before that.
 #
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Iceland 1917    1918    -       Feb     19      23:00   1:00    S
@@ -1395,13 +1077,21 @@ Zone Atlantic/Reykjavik -1:27:24 -      LMT     1837
                         0:00   -       GMT
 
 # Italy
-# Gregorian calendar adopted 1582-10-15.
+#
+# From Paul Eggert (2001-03-06):
+# Sicily and Sardinia each had their own time zones from 1866 to 1893,
+# called ``Palermo Time'' (+0053) and ``Cagliari Time'' (+0038).
+# During World War II, German-controlled Italy used German time.
+# But these events all occurred before the 1970 cutoff,
+# so record only the time in Rome.
 #
 # From Paul Eggert (1996-05-06):
 # For Italian DST we have three sources: Shanks, Whitman, and F. Pollastri
-# <URL:http://pisolo.cstv.to.cnr.it/toi/uk/ienitlt.html> (1996-03-14) (`FP'
-# below), taken from an Italian National Electrotechnical Institute publication.
-# When the three sources disagree, guess who's right, as follows:
+# <a href="http://toi.iriti.cnr.it/uk/ienitlt.html">
+# Day-light Saving Time in Italy (1996-03-14)
+# </a>
+# (`FP' below), taken from an Italian National Electrotechnical Institute
+# publication. When the three sources disagree, guess who's right, as follows:
 #
 # year FP      Shanks (S)      Whitman (W)     Go with:
 # 1916 06-03   06-03 24:00     06-03 00:00     FP & W
@@ -1469,14 +1159,65 @@ Link    Europe/Rome     Europe/Vatican
 Link   Europe/Rome     Europe/San_Marino
 
 # Latvia
-# From Paul Eggert (1996-11-22):
-# Rules after 1991 are by extension from Shanks.  They contradict
-# IATA SSIM (1992/1996), which claims Latvia uses W-Eur rules, but
-# Peter Ilieve's relative writes that Latvia switched in September this year,
-# so we'll assume that the old C-Eur-style rules still apply.
+
+# From Liene Kanepe <Liene_Kanepe@lm.gov.lv> (1998-09-17):
+
+# I asked about this matter Scientific Secretary of the Institute of Astronomy
+# of The University of Latvia Dr. paed Mr. Ilgonis Vilks. I also searched the
+# correct data in juridical acts and I found some juridical documents about
+# changes in the counting of time in Latvia from 1981....
+#
+# Act No.35 of the Council of Ministers of Latvian SSR of 1981-01-22 ...
+# according to the Act No.925 of the Council of Ministers of USSR of 1980-10-24
+# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
+# the hands of the clock 1 hour forward on 1 April at 00:00 (GMT 31 March 21:00)
+# and 1 hour backward on the 1 October at 00:00 (GMT 30 September 20:00).
+#
+# Act No.592 of the Council of Ministers of Latvian SSR of 1984-09-24 ...
+# according to the Act No.967 of the Council of Ministers of USSR of 1984-09-13
+# ...: all year round the time of 2nd time zone + 1 hour, in addition turning
+# the hands of the clock 1 hour forward on the last Sunday of March at 02:00
+# (GMT 23:00 on the previous day) and 1 hour backward on the last Sunday of
+# September at 03:00 (GMT 23:00 on the previous day).
+#
+# Act No.81 of the Council of Ministers of Latvian SSR of 1989-03-22 ...
+# according to the Act No.227 of the Council of Ministers of USSR of 1989-03-14
+# ...: since the last Sunday of March 1989 in Lithuanian SSR, Latvian SSR,
+# Estonian SSR and Kaliningrad region of Russian Federation all year round the
+# time of 2nd time zone (Moscow time minus one hour). On the territory of Latvia
+# transition to summer time is performed on the last Sunday of March at 02:00
+# (GMT 00:00), turning the hands of the clock 1 hour forward.  The end of
+# daylight saving time is performed on the last Sunday of September at 03:00
+# (GMT 00:00), turning the hands of the clock 1 hour backward. Exception is
+# 1989-03-26, when we must not turn the hands of the clock....
+#
+# The Regulations of the Cabinet of Ministers of the Republic of Latvia of
+# 1997-01-21 on transition to Summer time ... established the same order of
+# daylight savings time settings as in the States of the European Union.
+
+# From Andrei Ivanov (2000-03-06):
+# This year Latvia will not switch to Daylight Savings Time (as specified in
+# <a href="http://www.lv-laiks.lv/wwwraksti/2000/071072/vd4.htm">
+# The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
+# 29-Feb-2000 (#79)</a>, in Latvian for subscribers only).
+
+# <a href="http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html">
+# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
+# </a>
+# The Latvian government on 2 January decided that the country will
+# institute daylight-saving time this spring, LETA reported.
+# Last February the three Baltic states decided not to turn back their
+# clocks one hour in the spring....
+# Minister of Economy Aigars Kalvitis noted that Latvia had too few
+# daylight hours and thus decided to comply with a draft European
+# Commission directive that provides for instituting daylight-saving
+# time in EU countries between 2002 and 2006. The Latvian government
+# urged Lithuania and Estonia to adopt a similar time policy, but it
+# appears that they will not do so....
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Latvia  1992    max     -       Mar     lastSun  2:00s  1:00    S
-Rule   Latvia  1992    max     -       Sep     lastSun  2:00s  0       -
+Rule   Latvia  1989    1996    -       Mar     lastSun  2:00s  1:00    S
+Rule   Latvia  1989    1996    -       Sep     lastSun  2:00s  0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Riga     1:36:24 -       LMT     1880
                        1:36:24 -       RMT     1918 Apr 15 2:00 #Riga Mean Time
@@ -1486,10 +1227,13 @@ Zone    Europe/Riga     1:36:24 -       LMT     1880
                        1:36:24 -       RMT     1926 May 11
                        2:00    -       EET     1940 Aug  5
                        3:00    -       MSK     1941 Jul
-                       1:00    C-Eur   CE%sT   1944 Aug  8
-                       3:00    Russia  MSK/MSD 1991 Mar 31 2:00s
-                       2:00    1:00    EEST    1991 Sep 29 2:00s
-                       2:00    Latvia  EE%sT
+                       1:00    C-Eur   CE%sT   1944 Oct 13
+                       3:00    Russia  MSK/MSD 1989 Mar lastSun 2:00s
+                       2:00    1:00    EEST    1989 Sep lastSun 2:00s
+                       2:00    Latvia  EE%sT   1997 Jan 21
+                       2:00    EU      EE%sT   2000 Feb 29
+                       2:00    -       EET     2001
+                       2:00    EU      EE%sT
 
 # Liechtenstein
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -1498,6 +1242,28 @@ Zone     Europe/Vaduz    0:38:04 -       LMT     1894 Jun
                        1:00    EU      CE%sT
 
 # Lithuania
+
+# From Paul Eggert (1996-11-22):
+# IATA SSIM (1992/1996) says Lithuania uses W-Eur rules, but since it is
+# known to be wrong about Estonia and Latvia, assume it's wrong here too.
+
+# From Marius Gedminas <mgedmin@pub.osf.lt> (1998-08-07):
+# I would like to inform that in this year Lithuanian time zone
+# (Europe/Vilnius) was changed.
+
+# From <a href="http://www.elta.lt/">ELTA</a> No. 972 (2582) (1999-09-29),
+# via Steffen Thorsen:
+# Lithuania has shifted back to the second time zone (GMT plus two hours)
+# to be valid here starting from October 31,
+# as decided by the national government on Wednesday....
+# The Lithuanian government also announced plans to consider a
+# motion to give up shifting to summer time in spring, as it was
+# already done by Estonia.
+
+# From the <a href="http://www.tourism.lt/informa/ff.htm">
+# Fact File, Lithuanian State Department of Tourism
+# </a> (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Vilnius  1:41:16 -       LMT     1880
                        1:24:00 -       WMT     1917        # Warsaw Mean Time
@@ -1509,10 +1275,10 @@ Zone    Europe/Vilnius  1:41:16 -       LMT     1880
                        1:00    C-Eur   CE%sT   1944 Aug
                        3:00    Russia  MSK/MSD 1991 Mar 31 2:00s
                        2:00    1:00    EEST    1991 Sep 29 2:00s
-                       2:00    C-Eur   EE%sT
-# From Paul Eggert (1996-11-22):
-# IATA SSIM (1992/1996) says Lithuania uses W-Eur rules, but since it is
-# known to be wrong about Estonia and Latvia, assume it's wrong here too.
+                       2:00    C-Eur   EE%sT   1998
+                       2:00    -       EET     1998 Mar 29 1:00u
+                       1:00    EU      CE%sT   1999 Oct 31 1:00u
+                       2:00    -       EET
 
 # Luxembourg
 # Whitman disagrees with most of these dates in minor ways; go with Shanks.
@@ -1550,13 +1316,7 @@ Zone Europe/Luxembourg   0:24:36 -       LMT     1904 Jun
                        1:00    EU      CE%sT
 
 # Macedonia
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/Skopje   1:25:44 -       LMT     1884
-                       1:00    -       CET     1941 Apr 18 23:00
-                       1:00    C-Eur   CE%sT   1945 May  8  2:00s
-                       1:00    1:00    CEST    1945 Sep 16  2:00s
-                       1:00    -       CET     1983
-                       1:00    EU      CE%sT
+# see Yugoslavia
 
 # Malta
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -1576,12 +1336,32 @@ Zone    Europe/Malta    0:58:04 -       LMT     1893 Nov  2     # Valletta
                        1:00    EU      CE%sT
 
 # Moldova
+
+# From Paul Eggert (2001-02-11):
+# A previous version of this database followed Shanks, who writes that
+# Tiraspol switched to Moscow time on 1992-01-19 at 02:00.
+# However, this is most likely an error, as Moldova declared independence
+# on 1991-08-27 (the 1992-01-19 date is that of a Russian decree).
+# In early 1992 there was large-scale interethnic violence in the area
+# and it's possible that some Russophones continued to observe Moscow time.
+# But moldavizolit@tirastel.md and mk@tirastel.md separately reported via
+# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
+# The Tiraspol entry has therefore been removed for now.
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Europe/Chisinau 1:55:20 -       LMT     1924 May  2
-                       2:00    -       EET     1930 Jun 21
-                       3:00    Russia  MSK/MSD 1991 Mar 31 2:00s
-                       2:00    1:00    EEST    1991 Sep 29 2:00s
-                       2:00    E-Eur   EE%sT
+Zone   Europe/Chisinau 1:55:20 -       LMT     1880
+                       1:55    -       CMT     1918 Feb 15 # Chisinau MT
+                       1:44:24 -       BMT     1931 Jul 24 # Bucharest MT
+                       2:00    Romania EE%sT   1940 Aug 15
+                       2:00    1:00    EEST    1941 Jul 17
+                       1:00    C-Eur   CE%sT   1944 Aug 24
+                       3:00    Russia  MSK/MSD 1990
+                       3:00    -       MSK     1990 May 6
+                       2:00    -       EET     1991
+                       2:00    Russia  EE%sT   1992
+                       2:00    E-Eur   EE%sT   1997
+# See Romania commentary for the guessed 1997 transition to EU rules.
+                       2:00    EU      EE%sT
 
 # Monaco
 # Shanks gives 0:09 for Paris Mean Time; go with Howse's more precise 0:09:21.
@@ -1595,52 +1375,44 @@ Zone    Europe/Monaco   0:29:32 -       LMT     1891 Mar 15
 # Netherlands
 # Howse writes that the Netherlands' railways used GMT between 1892 and 1940,
 # but for other purposes the Netherlands used Amsterdam mean time.
+# The data before 1945 is taken from
+# <http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm>.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-# Shanks gives 1916 May 1 0:00 and 1916 Oct 1 0:00; go with Whitman.
-Rule   Neth    1916    only    -       May      1      2:00s   1:00    NST     # Netherlands Summer Time
-Rule   Neth    1916    only    -       Oct      2      2:00s   0       AMT     # Amsterdam Mean Time
+Rule   Neth    1916    only    -       May      1      0:00    1:00    NST     # Netherlands Summer Time
+Rule   Neth    1916    only    -       Oct      1      0:00    0       AMT     # Amsterdam Mean Time
 Rule   Neth    1917    only    -       Apr     16      2:00s   1:00    NST
 Rule   Neth    1917    only    -       Sep     17      2:00s   0       AMT
-# Whitman gives 1918 Apr 14, 1918 Oct 31, and 1921 Sep 28; go with Shanks.
 Rule   Neth    1918    1921    -       Apr     Mon>=1  2:00s   1:00    NST
-Rule   Neth    1918    1921    -       Sep     Mon>=24 2:00s   0       AMT
-Rule   Neth    1922    only    -       Mar     26      2:00s   1:00    NST
-# Whitman gives 1939 Oct 1; go with Shanks.
+Rule   Neth    1918    1921    -       Sep     lastSun 2:00s   0       AMT
+Rule   Neth    1922    only    -       Mar     lastSun 2:00s   1:00    NST
 Rule   Neth    1922    1936    -       Oct     Sun>=2  2:00s   0       AMT
-Rule   Neth    1923    only    -       Jun      1      2:00s   1:00    NST
-Rule   Neth    1924    only    -       Mar     30      2:00s   1:00    NST
-# Whitman gives 1925 Apr 5; go with Shanks.
-Rule   Neth    1925    only    -       Jun      5      2:00s   1:00    NST
-# For 1926 through 1930 Whitman gives Apr 15; go with Shanks.
+Rule   Neth    1923    only    -       Jun     Fri>=1  2:00s   1:00    NST
+Rule   Neth    1924    only    -       Mar     lastSun 2:00s   1:00    NST
+Rule   Neth    1925    only    -       Jun     Fri>=1  2:00s   1:00    NST
 Rule   Neth    1926    1931    -       May     15      2:00s   1:00    NST
 Rule   Neth    1932    only    -       May     22      2:00s   1:00    NST
 Rule   Neth    1933    1936    -       May     15      2:00s   1:00    NST
 Rule   Neth    1937    only    -       May     22      2:00s   1:00    NST
 Rule   Neth    1937    only    -       Jul      1      0:00    1:00    S
 Rule   Neth    1937    1939    -       Oct     Sun>=2  2:00s   0       -
-# Whitman gives 1939 Apr 15 and 1940 Apr 19; go with Shanks.
 Rule   Neth    1938    1939    -       May     15      2:00s   1:00    S
 Rule   Neth    1945    only    -       Apr      2      2:00s   1:00    S
-Rule   Neth    1945    only    -       May     20      2:00s   0       -
-# Before 1937, Shanks says just `0:20'; we use Whitman's more precise figure.
+Rule   Neth    1945    only    -       Sep     16      2:00s   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Europe/Amsterdam  0:19:28 -       LMT     1892 May
                        0:19:28 Neth    %s      1937 Jul
-                       0:20    Neth    NE%sT   1940 May 16 0:40
+                       0:20    Neth    NE%sT   1940 May 17 0:00
                        1:00    C-Eur   CE%sT   1945 Apr  2 2:00
                        1:00    Neth    CE%sT   1977
                        1:00    EU      CE%sT
 
 # Norway
-# Gregorian calendar adopted 1700-03-01.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 # Whitman gives 1916 May 21 - 1916 Oct 21; go with Shanks.
 Rule   Norway  1916    only    -       May     22      1:00    1:00    S
 Rule   Norway  1916    only    -       Sep     30      0:00    0       -
-# Shanks omits the following transition; go with Whitman.
-Rule   Norway  1935    only    -       Aug     11      0:00    1:00    S
-# Whitman says DST observed until 1942 Nov 1, then 1943 Mar 29 - Oct 4,
-# 1944 Apr 3 - Oct 2, and 1945 Apr 1 - Oct 1; go with Shanks after 1940.
+# Whitman says DST observed 1935-08-11/1942-11-01, then 1943-03-29/10-04,
+# 1944-04-03/10-02, and 1945-04-01/10-01; go with Shanks.
 Rule   Norway  1945    only    -       Apr      2      2:00s   1:00    S
 Rule   Norway  1945    only    -       Oct      1      2:00s   0       -
 Rule   Norway  1959    1964    -       Mar     Sun>=15 2:00s   1:00    S
@@ -1652,11 +1424,9 @@ Zone     Europe/Oslo     0:43:00 -       LMT     1895
                        1:00    C-Eur   CE%sT   1945 Apr  2  2:00
                        1:00    Norway  CE%sT   1980
                        1:00    EU      CE%sT
-#
-# Svalbard
+
+# Svalbard & Jan Mayen
 Link   Europe/Oslo     Arctic/Longyearbyen
-#
-# Jan Mayen
 # From Whitman:
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Atlantic/Jan_Mayen        -1:00   -       EGT
@@ -1692,14 +1462,26 @@ Zone    Europe/Warsaw   1:24:00 -       LMT     1880
                        1:00    Poland  CE%sT   1940 Jun 23 2:00
                        1:00    C-Eur   CE%sT   1944 Oct
                        1:00    Poland  CE%sT   1977 Apr  3 1:00
-                       1:00    W-Eur   CE%sT
+                       1:00    W-Eur   CE%sT   1999
 # IATA SSIM (1991/1996) gives EU rules, but the _The Warsaw Voice_
-# <URL:http://www.contact.waw.pl/voice/v361/NewsInBrief.shtml>
-# (1995-09-24) says the autumn 1995 switch was at 02:00.
+# <a href="http://www.warsawvoice.com.pl/v361/NewsInBrief.shtml">
+# http://www.warsawvoice.com/pl/v361/NewsInBrief.shtml (1995-09-24)
+# </a>
+# says the autumn 1995 switch was at 02:00.
 # Stick with W-Eur for now.
+#
+# From Marcin.Kasperski@softax.com.pl (1999-06-10):
+# According to my colleagues someone recently decided, that Poland would
+# follow European Union regulations, so - I think - the matter is not
+# worth further discussion.
+#
+# From Paul Eggert (1999-06-10):
+# Kasperski also writes that the government futzed with the rules in 1997
+# or 1998 but he doesn't remember the details.  Assume they switched to
+# EU rules in 1999.
+                       1:00    EU      CE%sT
 
 # Portugal
-# Gregorian calendar adopted 1582-10-15.
 #
 # From Rui Pedro Salgueiro <rps@inescca.inescc.pt> (1992-11-12):
 # Portugal has recently (September, 27) changed timezone
@@ -1718,6 +1500,9 @@ Zone      Europe/Warsaw   1:24:00 -       LMT     1880
 # harmonized with the EU), and that they stayed +0:00 that winter.
 #
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# DSH writes that despite Decree 1,469 (1915), the change to the clocks was not
+# done every year, depending on what Spain did, because of railroad schedules.
+# Go with Shanks.
 Rule   Port    1916    only    -       Jun     17      23:00   1:00    S
 # Whitman gives 1916 Oct 31; go with Shanks.
 Rule   Port    1916    only    -       Nov      1       1:00   0       -
@@ -1756,12 +1541,12 @@ Rule    Port    1940    only    -       Feb     24      23:00s  1:00    S
 Rule   Port    1940    1941    -       Oct      5      23:00s  0       -
 Rule   Port    1941    only    -       Apr      5      23:00s  1:00    S
 Rule   Port    1942    1945    -       Mar     Sat>=8  23:00s  1:00    S
-Rule   Port    1942    only    -       Apr     25      22:00s  2:00    DS
+Rule   Port    1942    only    -       Apr     25      22:00s  2:00    M # Midsummer
 Rule   Port    1942    only    -       Aug     15      22:00s  1:00    S
 Rule   Port    1942    1945    -       Oct     Sat>=24 23:00s  0       -
-Rule   Port    1943    only    -       Apr     17      22:00s  2:00    DS
+Rule   Port    1943    only    -       Apr     17      22:00s  2:00    M
 Rule   Port    1943    1945    -       Aug     Sat>=25 22:00s  1:00    S
-Rule   Port    1944    1945    -       Apr     Sat>=21 22:00s  2:00    DS
+Rule   Port    1944    1945    -       Apr     Sat>=21 22:00s  2:00    M
 Rule   Port    1946    only    -       Apr     Sat>=1  23:00s  1:00    S
 Rule   Port    1946    only    -       Oct     Sat>=1  23:00s  0       -
 Rule   Port    1947    1949    -       Apr     Sun>=1   2:00s  1:00    S
@@ -1801,6 +1586,14 @@ Zone Atlantic/Madeira    -1:07:36 -      LMT     1884            # Funchal
                         0:00   EU      WE%sT
 
 # Romania
+#
+# From Paul Eggert (1999-10-07):
+# <a href="http://www.nineoclock.ro/POL/1778pol.html">
+# Nine O'clock</a> (1998-10-23) reports that the switch occurred at
+# 04:00 local time in fall 1998.  For lack of better info,
+# assume that Romania and Moldova switched to EU rules in 1997,
+# the same year as Bulgaria.
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Romania 1932    only    -       May     21       0:00s  1:00    S
 Rule   Romania 1932    1939    -       Oct     Sun>=1   0:00s  0       -
@@ -1817,24 +1610,16 @@ Zone Europe/Bucharest   1:44:24 -       LMT     1891 Oct
                        2:00    Romania EE%sT   1981 Mar 29 2:00s
                        2:00    C-Eur   EE%sT   1991
                        2:00    Romania EE%sT   1994
-                       2:00    E-Eur   EE%sT
+                       2:00    E-Eur   EE%sT   1997
+                       2:00    EU      EE%sT
 
 # Russia
 
-# From Chris Carrier <72157.3334@CompuServe.COM> (1996-12-02):
-# On 1929-10-01 the Soviet Union instituted an ``Eternal Calendar''
-# with 30-day months plus 5 holidays, with a 5-day week.
-# On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
-# Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
-# reverted to the 7-day week.  With the 6-day week the usual days
-# off were the 6th, 12th, 18th, 24th and 30th of the month.
-# (Source: Evitiar Zerubavel, _The Seven Day Circle_)
-#
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
-# Except for Moscow after 1919-07-01, I invented the time zone abbreviations,
-# and (unless otherwise specified) guessed what happened after 1991.
+# From Paul Eggert <eggert@twinsun.com> (1999-11-12):
+# Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
 # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
-# are from Andrey A. Chernov.  The rest is from Shanks and the IATA.
+# are from Andrey A. Chernov.  The rest is from Shanks, except we follow
+# Chernov's report that 1992 DST transitions were Sat 23:00, not Sun 02:00s.
 #
 # From Andrey A. Chernov <ache@nagual.ru> (1996-10-04):
 # `MSK' and `MSD' were born and used initially on Moscow computers with
@@ -1847,115 +1632,101 @@ Zone Europe/Bucharest 1:44:24 -       LMT     1891 Oct
 # Moscow to Irkutsk in 1995, public air and rail transport in Russia ...
 # still follows Moscow time, no matter where in Russia it is located.
 #
+# For Grozny, Chechnya, we have the following story from
+# John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
+# News--often false--is spread by word of mouth.  A rumor that it was
+# time to move the clocks back put this whole city out of sync with
+# the rest of Russia for two weeks--even soldiers stationed here began
+# enforcing curfew at the wrong time.
+#
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Europe/Kaliningrad         1:22:00 -      LMT     1893 Apr
                         1:00   C-Eur   CE%sT   1945
-                        2:00   Poland  CET     1946
+                        2:00   Poland  CE%sT   1946
                         3:00   Russia  MSK/MSD 1991 Mar 31 2:00s
-                        2:00   1:00    EEST    1991 Sep 29 2:00s
-                        2:00   -       EET     1992 Jan 19 2:00s
-                        3:00   Russia  MSK/MSD 1994
-# IATA SSIM (1994-02) says Kaliningrad is at UTC+2; guess 1994 change.
                         2:00   Russia  EE%sT
 Zone Europe/Moscow      2:30:20 -      LMT     1880
-                        2:30:20 Russia %s      1919 Jul  1 2:00
+                        2:30   -       MMT     1916 Jul  3 # Moscow Mean Time
+                        2:30:48 Russia %s      1919 Jul  1 2:00
                         3:00   Russia  MSK/MSD 1922 Oct
                         2:00   -       EET     1930 Jun 21
                         3:00   Russia  MSK/MSD 1991 Mar 31 2:00s
-                        2:00   1:00    EEST    1991 Sep 29 2:00s
-                        2:00   -       EET     1992 Jan 19 2:00s
+                        2:00   Russia  EE%sT   1992 Jan 19 2:00s
                         3:00   Russia  MSK/MSD
-Zone Europe/Samara      3:20:36 -      LMT     1924 May  2
-                        3:00   -       KUYT    1957 Mar # Kuybyshev Time
-                        4:00   Russia  KUY%sT  1991 Mar 31 2:00s
-                        3:00   1:00    KUYST   1991 Sep 29 2:00s
-                        3:00   -       SAMT    1992 Jan 19 2:00s # Samara Time
-                        4:00   Russia  SAM%sT
-Zone Asia/Yekaterinburg         4:02:34 -      LMT     1924 May  2
-                        4:00   -       SVET    1957 Mar # Sverdlovsk Time
+Zone Europe/Samara      3:20:36 -      LMT     1919 Jul  1 2:00
+                        3:00   -       KUYT    1930 Jun 21 # Kuybyshev
+                        4:00   Russia  KUY%sT  1989 Mar 26 2:00s
+                        3:00   Russia  KUY%sT  1991 Mar 31 2:00s
+                        2:00   Russia  KUY%sT  1991 Sep 29 2:00s
+                        3:00   -       KUYT    1991 Oct 20 3:00
+                        4:00   Russia  SAM%sT  # Samara Time
+Zone Asia/Yekaterinburg         4:02:24 -      LMT     1919 Jul 15 4:00
+                        4:00   -       SVET    1930 Jun 21 # Sverdlovsk Time
                         5:00   Russia  SVE%sT  1991 Mar 31 2:00s
-                        4:00   1:00    SVEST   1991 Sep 29 2:00s
-                        4:00   -       SVET    1992 Jan 19 2:00s
+                        4:00   Russia  SVE%sT  1992 Jan 19 2:00s
                         5:00   Russia  YEK%sT  # Yekaterinburg Time
-Zone Asia/Omsk          4:53:36 -      LMT     1924 May  2
-                        5:00   -       OMST    1957 Mar # Omsk Time
+Zone Asia/Omsk          4:53:36 -      LMT     1919 Nov 14
+                        5:00   -       OMST    1930 Jun 21 # Omsk TIme
                         6:00   Russia  OMS%sT  1991 Mar 31 2:00s
-                        5:00   1:00    OMSST   1991 Sep 29 2:00s
-                        5:00   -       OMST    1992 Jan 19 2:00s
+                        5:00   Russia  OMS%sT  1992 Jan 19 2:00s
                         6:00   Russia  OMS%sT
 # From Stanislaw A. Kuzikowski <S.A.Kuz@iae.nsk.su> (1994-06-29):
 # But now it is some months since Novosibirsk is 3 hours ahead of Moscow!
 # I do not know why they have decided to make this change;
 # as far as I remember it was done exactly during winter->summer switching
 # so we (Novosibirsk) simply did not switch.
-Zone Asia/Novosibirsk   5:31:40 -      LMT     1924 May  2
-                        6:00   -       NOVT    1957 Mar # Novosibirsk Time
+Zone Asia/Novosibirsk   5:31:40 -      LMT     1919 Dec 14 6:00
+                        6:00   -       NOVT    1930 Jun 21 # Novosibirsk Time
                         7:00   Russia  NOV%sT  1991 Mar 31 2:00s
-                        6:00   1:00    NOVST   1991 Sep 29 2:00s
-                        6:00   -       NOVT    1992 Jan 19 2:00s
-                        7:00   Russia  NOV%sT  1994 Mar 27 2:00s
-                        6:00   1:00    NOVST   1994 Sep 25 2:00s
+                        6:00   Russia  NOV%sT  1992 Jan 19 2:00s
+                        7:00   Russia  NOV%sT  1993 May 23 # says Shanks
                         6:00   Russia  NOV%sT
-Zone Asia/Krasnoyarsk   6:11:20 -      LMT     1924 May  2
-                        6:00   -       KRAT    1957 Mar # Krasnoyarsk Time
+Zone Asia/Krasnoyarsk   6:11:20 -      LMT     1920 Jan  6
+                        6:00   -       KRAT    1930 Jun 21 # Krasnoyarsk Time
                         7:00   Russia  KRA%sT  1991 Mar 31 2:00s
-                        6:00   1:00    KRAST   1991 Sep 29 2:00s
-                        6:00   -       KRAT    1992 Jan 19 2:00s
+                        6:00   Russia  KRA%sT  1992 Jan 19 2:00s
                         7:00   Russia  KRA%sT
 Zone Asia/Irkutsk       6:57:20 -      LMT     1880
-                        6:57:20 -      IMT     1924 May  2 # Irkutsk Mean Time
-                        7:00   -       IRKT    1957 Mar # Irkutsk Time
+                        6:57:20 -      IMT     1920 Jan 25 # Irkutsk Mean Time
+                        7:00   -       IRKT    1930 Jun 21 # Irkutsk Time
                         8:00   Russia  IRK%sT  1991 Mar 31 2:00s
-                        7:00   1:00    IRKST   1991 Sep 29 2:00s
-                        7:00   -       IRKT    1992 Jan 19 2:00s
+                        7:00   Russia  IRK%sT  1992 Jan 19 2:00s
                         8:00   Russia  IRK%sT
-Zone Asia/Yakutsk       8:38:40 -      LMT     1924 May  2
-                        8:00   -       YAKT    1957 Mar # Yakutsk Time
+Zone Asia/Yakutsk       8:38:40 -      LMT     1919 Dec 15
+                        8:00   -       YAKT    1930 Jun 21 # Yakutsk Time
                         9:00   Russia  YAK%sT  1991 Mar 31 2:00s
-                        8:00   1:00    YAKST   1991 Sep 29 2:00s
-                        8:00   -       YAKT    1992 Jan 19 2:00s
+                        8:00   Russia  YAK%sT  1992 Jan 19 2:00s
                         9:00   Russia  YAK%sT
-Zone Asia/Vladivostok   8:47:44 -      LMT     1880
-                        8:47:44 -      VMT     1924 May  2 # Vladivostok MT
-                        9:00   -       VLAT    1957 Mar # Vladivostok Time
+Zone Asia/Vladivostok   8:47:44 -      LMT     1922 Nov 15
+                        9:00   -       VLAT    1930 Jun 21 # Vladivostok Time
                        10:00   Russia  VLA%sT  1991 Mar 31 2:00s
-                        9:00   1:00    VLAST   1991 Sep 29 2:00s
-                        9:00   -       VLAT    1992 Jan 19 2:00s
+                        9:00   Russia  VLA%sST 1992 Jan 19 2:00s
                        10:00   Russia  VLA%sT
 Zone Asia/Magadan      10:03:12 -      LMT     1924 May  2
-                       10:00   -       MAGT    1957 Mar # Magadan Time
+                       10:00   -       MAGT    1930 Jun 21 # Magadan Time
                        11:00   Russia  MAG%sT  1991 Mar 31 2:00s
-                       10:00   1:00    MAGST   1991 Sep 29 2:00s
-                       10:00   -       MAGT    1992 Jan 19 2:00s
+                       10:00   Russia  MAG%sT  1992 Jan 19 2:00s
                        11:00   Russia  MAG%sT
 # This name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
-Zone Asia/Kamchatka    10:34:36 -      LMT     1924 May  2
-                       11:00   -       PETT    1957 Mar # P-K Time
+Zone Asia/Kamchatka    10:34:36 -      LMT     1922 Nov 10
+                       11:00   -       PETT    1930 Jun 21 # P-K Time
                        12:00   Russia  PET%sT  1991 Mar 31 2:00s
-                       11:00   1:00    PETST   1991 Sep 29 2:00s
-                       11:00   -       PETT    1992 Jan 19 2:00s
+                       11:00   Russia  PET%sT  1992 Jan 19 2:00s
                        12:00   Russia  PET%sT
 Zone Asia/Anadyr       11:49:56 -      LMT     1924 May  2
-                       12:00   -       ANAT    1957 Mar # Anadyr Time
-                       13:00   Russia  ANA%sT  1991 Mar 31 2:00s
-                       12:00   1:00    ANAST   1991 Sep 29 2:00s
-                       12:00   -       ANAT    1992 Jan 19 2:00s
-                       13:00   Russia  ANA%sT
+                       12:00   -       ANAT    1930 Jun 21 # Anadyr Time
+                       13:00   Russia  ANA%sT  1982 Apr  1 0:00s
+                       12:00   Russia  ANA%sT  1991 Mar 31 2:00s
+                       11:00   Russia  ANA%sT  1992 Jan 19 2:00s
+                       12:00   Russia  ANA%sT
 
 # Slovakia
 Link Europe/Prague Europe/Bratislava
 
 # Slovenia
-# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Europe/Ljubljana  0:58:04 -       LMT     1884
-                       1:00    -       CET     1941 Apr 18 23:00
-                       1:00    C-Eur   CE%sT   1945 May  8  2:00s
-                       1:00    1:00    CEST    1945 Sep 16  2:00s
-                       1:00    -       CET     1983
-                       1:00    EU      CE%sT
+# see Yugoslavia
 
 # Spain
-# Gregorian calendar adopted 1582-10-15.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 # For 1917-1919 Whitman gives Apr Sat>=1 - Oct Sat>=1; go with Shanks.
 Rule   Spain   1917    only    -       May      5      23:00s  1:00    S
@@ -1979,9 +1750,9 @@ Rule      Spain   1938    only    -       Mar     22      23:00s  1:00    S
 Rule   Spain   1939    only    -       Apr     15      23:00s  1:00    S
 Rule   Spain   1940    only    -       Mar     16      23:00s  1:00    S
 # Whitman says no DST 1942-1945; go with Shanks.
-Rule   Spain   1942    only    -       May      2      22:00s  2:00    DS
+Rule   Spain   1942    only    -       May      2      22:00s  2:00    M # Midsummer
 Rule   Spain   1942    only    -       Sep      1      22:00s  1:00    S
-Rule   Spain   1943    1946    -       Apr     Sat>=13 22:00s  2:00    DS
+Rule   Spain   1943    1946    -       Apr     Sat>=13 22:00s  2:00    M
 Rule   Spain   1943    only    -       Oct      3      22:00s  1:00    S
 Rule   Spain   1944    only    -       Oct     10      22:00s  1:00    S
 Rule   Spain   1945    only    -       Sep     30       1:00   1:00    S
@@ -2026,28 +1797,6 @@ Zone     Atlantic/Canary -1:01:36 -      LMT     1922 Mar # Las Palmas de Gran C.
 # Ignore this for now, as the Canaries are part of the EU.
 
 # Sweden
-
-# From: msb@sq.com (Mark Brader) <URL:news:1996Jul6.012937.29190@sq.com>:
-#
-# In 1700, Denmark made the transition from Julian to Gregorian.  Sweden
-# decided to *start* a transition in 1700 as well, but rather than have one of
-# those unsightly calendar gaps :-), they simply decreed that the next leap
-# year after 1696 would be in 1744 -- putting the whole country on a calendar
-# different from both Julian and Gregorian for a period of 40 years.
-#
-# However, in 1704 something went wrong and the plan was not carried through;
-# they did, after all, have a leap year that year.  And one in 1708.  In 1712
-# they gave it up and went back to Julian, putting 30 days in February that
-# year!...
-#
-# Then in 1753, Sweden made the transition to Gregorian in the usual manner,
-# getting there only 13 years behind the original schedule.
-#
-# (A previous posting of this story was challenged, and Swedish readers
-# produced the following references to support it: "Tiderakning och historia"
-# by Natanael Beckman (1924) and "Tid, en bok om tiderakning och
-# kalendervasen" by Lars-Olof Lode'n (no date was given).)
-
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Europe/Stockholm  1:12:12 -       LMT     1878 May 31
                        1:12:12 -       SMT     1900 Jan  1  1:00 # Stockholm MT
@@ -2057,7 +1806,7 @@ Zone Europe/Stockholm     1:12:12 -       LMT     1878 May 31
                        1:00    EU      CE%sT
 
 # Switzerland
-# From Howse (1988), p 82:
+# From Howse:
 # By the end of the 18th century clocks and watches became commonplace
 # and their performance improved enormously.  Communities began to keep
 # mean time in preference to apparent time -- Geneva from 1780 ....
@@ -2065,7 +1814,7 @@ Zone Europe/Stockholm     1:12:12 -       LMT     1878 May 31
 # From Whitman (who writes ``Midnight?''):
 Rule   Swiss   1940    only    -       Nov      2      0:00    1:00    S
 Rule   Swiss   1940    only    -       Dec     31      0:00    0       -
-# From Shanks (1991):
+# From Shanks:
 Rule   Swiss   1941    1942    -       May     Sun>=1  2:00    1:00    S
 Rule   Swiss   1941    1942    -       Oct     Sun>=1  0:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -2088,7 +1837,6 @@ Rule      Turkey  1922    only    -       Oct      8      0:00    0       -
 Rule   Turkey  1924    only    -       May     13      0:00    1:00    S
 Rule   Turkey  1924    1925    -       Oct      1      0:00    0       -
 Rule   Turkey  1925    only    -       May      1      0:00    1:00    S
-# Shanks omits the first two transitions in 1940; go with Whitman.
 Rule   Turkey  1940    only    -       Jun     30      0:00    1:00    S
 Rule   Turkey  1940    only    -       Oct      5      0:00    0       -
 Rule   Turkey  1940    only    -       Dec      1      0:00    1:00    S
@@ -2139,51 +1887,63 @@ Zone    Europe/Istanbul 1:55:52 -       LMT     1880
 Link   Europe/Istanbul Asia/Istanbul   # Istanbul is in both continents.
 
 # Ukraine
-# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Ukraine 1917    only    -       Jul      1      23:00   1:00    UST     # Ukrainian Summer Time
-Rule   Ukraine 1917    only    -       Dec     28       0:00   0       KMT     # Kiev Mean Time
-Rule   Ukraine 1918    only    -       May     31      22:00   2:00    UDST    # Ukrainian Double Summer Time
-Rule   Ukraine 1918    only    -       Sep     17       0:00   1:00    UST
-Rule   Ukraine 1919    only    -       May     31      23:00   2:00    UDST
-Rule   Ukraine 1919    only    -       Jul      1       2:00   1:00    UST
-Rule   Ukraine 1919    only    -       Aug     16       0:00   0       KMT
-Rule   Ukraine 1921    only    -       Feb     14      23:00   1:00    UST
-Rule   Ukraine 1921    only    -       Mar     21      23:00   2:00    UDST
-Rule   Ukraine 1921    only    -       Sep      1       0:00   1:00    UST
-Rule   Ukraine 1921    only    -       Oct      1       0:00   0       KMT
-Rule   Crimea  1917    only    -       Jul      1      23:00   1:00    CST     # Crimean Summer Time
-Rule   Crimea  1917    only    -       Dec     28       0:00   0       NMT     # Nikolayev Mean Time
-Rule   Crimea  1918    only    -       May     31      22:00   2:00    CDST    # Crimean Double Summer Time
-Rule   Crimea  1918    only    -       Sep     17       0:00   1:00    CST
-Rule   Crimea  1919    only    -       May     31      23:00   2:00    CDST
-Rule   Crimea  1919    only    -       Jul      1       2:00   1:00    CST
-Rule   Crimea  1919    only    -       Aug     16       0:00   0       NMT
-Rule   Crimea  1921    only    -       Feb     14      23:00   1:00    CST
-Rule   Crimea  1921    only    -       Mar     21      23:00   2:00    CDST
-Rule   Crimea  1921    only    -       Sep      1       0:00   1:00    CST
-Rule   Crimea  1921    only    -       Oct      1       0:00   0       NMT
-Rule   Crimea  1996    max     -       Mar     lastSun  0:00u  1:00    -
-Rule   Crimea  1996    max     -       Oct     lastSun  0:00u  0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+# Most of Ukraine since 1970 has been like Kiev.
 Zone Europe/Kiev       2:02:04 -       LMT     1880
-                       2:02:04 Ukraine %s      1924 May  2
+                       2:02:04 -       KMT     1924 May  2 # Kiev Mean Time
                        2:00    -       EET     1930 Jun 21
-                       3:00    Russia  MSK/MSD 1990 Jul 17
-                       2:00    E-Eur   EE%sT   1996
+                       3:00    -       MSK     1941 Sep 20
+                       1:00    C-Eur   CE%sT   1943 Nov  6
+                       3:00    Russia  MSK/MSD 1990
+                       3:00    -       MSK     1990 Jul  1 2:00
+                       2:00    -       EET     1992
+                       2:00    E-Eur   EE%sT   1995
+                       2:00    EU      EE%sT
+# Ruthenia used CET 1990/1991.
+Zone Europe/Uzhgorod   1:29:12 -       LMT     1890 Oct
+                       1:00    -       CET     1940
+                       1:00    C-Eur   CE%sT   1944 Oct
+                       1:00    1:00    CEST    1944 Oct 26
+                       1:00    -       CET     1945 Jun 29
+                       3:00    Russia  MSK/MSD 1990
+                       3:00    -       MSK     1990 Jul  1 2:00
+                       1:00    -       CET     1991 Mar 31 3:00
+                       2:00    -       EET     1992
+                       2:00    E-Eur   EE%sT   1995
                        2:00    EU      EE%sT
+# Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991.
+# Zaporozh'ye has an apostrophe, but Posix file names can't have apostrophes.
+Zone Europe/Zaporozhye 2:20:40 -       LMT     1880
+                       2:20    -       CUT     1924 May  2 # Central Ukraine T
+                       2:00    -       EET     1930 Jun 21
+                       3:00    -       MSK     1941 Aug 25
+                       1:00    C-Eur   CE%sT   1943 Oct 25
+                       3:00    Russia  MSK/MSD 1991 Mar 31 2:00
+                       2:00    E-Eur   EE%sT   1995
+                       2:00    EU      EE%sT
+# Central Crimea used Moscow time 1994/1997.
 Zone Europe/Simferopol 2:16:24 -       LMT     1880
-                       2:08:00 Crimea  %s      1924 May  2
+                       2:16    -       SMT     1924 May  2 # Simferopol Mean T
                        2:00    -       EET     1930 Jun 21
-                       3:00    Russia  MSK/MSD 1991 Mar 31 2:00s
-                       2:00    1:00    EEST    1991 Sep 29 2:00s
-# From Paul Eggert <eggert@twinsun.com> (1996-10-21):
-# The _Economist_ (1994-05-28, p 45) reports that most of Crimea switched
+                       3:00    -       MSK     1941 Nov
+                       1:00    C-Eur   CE%sT   1944 Apr 13
+                       3:00    Russia  MSK/MSD 1990
+                       3:00    -       MSK     1990 Jul  1 2:00
+                       2:00    -       EET     1992
+# From Paul Eggert <eggert@twinsun.com> (1999-11-12):
+# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
 # from Kiev to Moscow time sometime after the January 1994 elections.
-# For now, guess it changed Feb 1.
-                       2:00    C-Eur   EE%sT   1994 Feb
-# From IATA SSIM (1994/1996), which also says that Kerch is still like Kiev.
-                       3:00    E-Eur   MSK/MSD 1996
-                       3:00    Crimea  MSK/MSD
+# Shanks says ``date of change uncertain'', but implies that it happened
+# sometime between the 1994 DST switches.  For now, guess it changed in May.
+                       2:00    E-Eur   EE%sT   1994 May
+# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
+                       3:00    E-Eur   MSK/MSD 1996 Mar 31 3:00s
+                       3:00    1:00    MSD     1996 Oct 27 3:00s
+# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
+# Assume it happened in March by not changing the clocks.
+                       3:00    Russia  MSK/MSD 1997
+                       3:00    -       MSK     1997 Mar lastSun 1:00u
+                       2:00    EU      EE%sT
 
 # Yugoslavia
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -2191,8 +1951,15 @@ Zone     Europe/Belgrade 1:22:00 -       LMT     1884
                        1:00    -       CET     1941 Apr 18 23:00
                        1:00    C-Eur   CE%sT   1945 May  8  2:00s
                        1:00    1:00    CEST    1945 Sep 16  2:00s
-                       1:00    -       CET     1983
+# Metod Kozelj <metod.kozelj@rzs-hm.si> reports that the legal date of
+# transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
+# Shanks doesn't give as much detail, so go with Kozelj.
+                       1:00    -       CET     1982 Nov 27
                        1:00    EU      CE%sT
+Link Europe/Belgrade Europe/Ljubljana  # Slovenia
+Link Europe/Belgrade Europe/Sarajevo   # Bosnia and Herzegovina
+Link Europe/Belgrade Europe/Skopje     # Macedonia
+Link Europe/Belgrade Europe/Zagreb     # Croatia
 
 ###############################################################################
 
@@ -2269,21 +2036,3 @@ Zone     Europe/Belgrade 1:22:00 -       LMT     1884
 # ...
 # Monaco: has same DST as France.
 # ...
-
-# ...
-# Date: Fri, 3 Sep 93 13:43:41 BST
-# From: Peter Ilieve <peter@memex.co.uk>
-# ...
-# Turning to Europe, I now have a copy of the `Sixth Council Directive 92/20/EEC
-# of 26 March 1992 on summertime arrangements'. This only covers 1993 and
-# 1994, a seventh one is in the works but I doubt that the algorithm will
-# change. This says summertime starts at 01:00 GMT on the last Sunday in March
-# and ends at 01:00 GMT on the last Sunday in September, except for the UK
-# and Eire where it ends at 01:00 GMT on the fourth Sunday in October.
-# It says the arrangements for 1995 onwards will be decided by 1 January 1994,
-# but as the sixth directive was supposed to appear by 1 Jan 92 and didn't
-# arrive til March I wouldn't hold your breath.
-#
-# The first summertime directive was adopted in 1980, although the UK didn't
-# seem to use it until 1981. I suspect it would be safe to move your start
-# dates for the -Eur rules back to 1981.
index 9d24283563d36cf8d528f62ac474a52e7ef69bbf..ebcc92b3967f86f8b192a22b1b91e721ac3a6dd5 100644 (file)
@@ -1,9 +1,8 @@
-#      $OpenBSD: factory,v 1.2 1997/01/14 04:36:53 millert Exp $
-# @(#)factory  7.1
+# @(#)factory  7.3
 
 # For companies who don't want to put time zone specification in
 # their installation procedures.  When users run date, they'll get the message.
 # Also useful for the "comp.sources" version.
 
 # Zone NAME    GMTOFF  RULES   FORMAT
-Zone   Factory 0       - "Local time zone must be set--see zic manual page"
+Zone   Factory 0       - "Local time zone must be set--use tzsetup"
index 279d6bb81a0bd41c08f4d500141739cc59ad6759..390f9cb8c5f2c07a35531e476b0fb484d8d3a14a 100644 (file)
@@ -1,10 +1,12 @@
-#      $OpenBSD: leapseconds,v 1.2 1997/01/14 04:36:54 millert Exp $
-# @(#)leapseconds      7.8
+# @(#)leapseconds      7.13
+
+# $FreeBSD: src/share/zoneinfo/leapseconds,v 1.6 2001/04/06 16:46:52 wollman Exp $
 
 # Allowance for leapseconds added to each timezone file.
 
 # The International Earth Rotation Service periodically uses leap seconds
-# to keep UTC to within 0.9 s of TAI (atomic time); see
+# to keep UTC to within 0.9 s of UT1
+# (which measures the true angular orientation of the earth in space); see
 # Terry J Quinn, The BIPM and the accurate measure of time,
 # Proc IEEE 79, 7 (July 1991), 894-905.
 # There were no leap seconds before 1972, because the official mechanism
@@ -18,7 +20,7 @@
 #      Leap    YEAR    MON     DAY     23:59:59        -       R/S
 
 # If the leapsecond is Rolling (R) the given time is local time
-# If the leapsecond is Stationary (S) the given time is GMT
+# If the leapsecond is Stationary (S) the given time is UTC
 
 # Leap YEAR    MONTH   DAY     HH:MM:SS        CORR    R/S
 Leap   1972    Jun     30      23:59:60        +       S
@@ -41,3 +43,24 @@ Leap 1992    Jun     30      23:59:60        +       S
 Leap   1993    Jun     30      23:59:60        +       S
 Leap   1994    Jun     30      23:59:60        +       S
 Leap   1995    Dec     31      23:59:60        +       S
+Leap   1997    Jun     30      23:59:60        +       S
+Leap   1998    Dec     31      23:59:60        +       S
+# INTERNATIONAL EARTH ROTATION SERVICE (IERS)
+# SERVICE INTERNATIONAL DE LA ROTATION TERRESTRE
+# 
+# SERVICE DE LA ROTATION TERRESTRE
+# OBSERVATOIRE DE PARIS
+# 61, Av. de l'Observatoire 75014 PARIS (France)
+# Tel.      : 33 (0) 1 40 51 22 26
+# FAX       : 33 (0) 1 40 51 22 91
+# Internet  : iers@obspm.fr
+# 
+# Paris, 11 January 2001
+# 
+# Bulletin C 21
+# 
+# To authorities responsible for the measurement and distribution of time
+# 
+# INFORMATION ON UTC - TAI
+# 
+# NO positive leap second will be introduced at the end of June 2001.
index ee484cbe51d50cb7878b9f8383361c7abff9d831..8630edb862ea0f9664844ba6b5828ac263ce438a 100644 (file)
@@ -1,20 +1,31 @@
-#      $OpenBSD: northamerica,v 1.5 1997/01/14 04:36:54 millert Exp $
-# @(#)northamerica     7.30
+# @(#)northamerica     7.58
 # also includes Central America and the Caribbean
 
+# $FreeBSD: src/share/zoneinfo/northamerica,v 1.18 2001/04/06 16:46:52 wollman Exp $
+
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
 # tz@elsie.nci.nih.gov for general use in the future).
 
-# From Paul Eggert <eggert@twinsun.com> (1994-08-17):
+# From Paul Eggert <eggert@twinsun.com> (1999-03-22):
 # A reliable and entertaining source about time zones is
-# Derek Howse, Greenwich time and the discovery of the longitude,
-# Oxford University Press (1980).
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 
 ###############################################################################
 
 # United States
 
+# From Paul Eggert (1999-03-31):
+# Howse writes (pp 121-125) that time zones were invented by
+# Professor Charles Ferdinand Dowd (1825-1904),
+# Principal of Temple Grove Ladies' Seminary (Saratoga Springs, NY).
+# His pamphlet ``A System of National Time for Railroads'' (1870)
+# was the result of his proposals at the Convention of Railroad Trunk Lines
+# in New York City (1869-10).  His 1870 proposal was based on Washington, DC,
+# but in 1872-05 he moved the proposed origin to Greenwich.
+# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
+# and the most of the country soon followed suit.
+
 # From Paul Eggert <eggert@twinsun.com> (1995-12-19):
 # A good source for time zone historical data in the US is
 # Thomas G. Shanks, The American Atlas (5th edition),
 # Make sure you have the errata sheet; the book is somewhat useless without it.
 # It is the source for the US and Puerto Rico entries below.
 
-# From Paul Eggert (1996-06-12):
+# From Paul Eggert (2001-03-06):
 # Daylight Saving Time was first suggested as a joke by Benjamin Franklin
-# in his whimsical essay ``Turkey vs Eagle, McCauley is my Beagle'' (1784).
+# in his whimsical essay ``An Economical Project for Diminishing the Cost
+# of Light'' published in the Journal de Paris (1784-04-26).
 # Not everyone is happy with the results:
 #
 #      I don't really care how time is reckoned so long as there is some
 #      them healthy, wealthy and wise in spite of themselves.
 #
 #      -- Robertson Davies, The Diary of Samuel Marchbanks (1947), XIX, Sunday
+#
+# For more about the first ten years of DST in the United States, see
+# Robert Garland's <a href="http://www.clpgh.org/exhibit/dst.html">
+# Ten years of daylight saving from the Pittsburgh standpoint
+# (Carnegie Library of Pittsburgh, 1927)</a>.
+#
+# Shanks says that DST was called "War Time" in the US in 1918 and 1919.
+# However, DST was imposed by the Standard Time Act of 1918, which
+# was the first nationwide legal time standard, and apparently
+# time was just called "Standard Time" or "Daylight Saving Time".
 
 # From Arthur David Olson:
 # US Daylight Saving Time ended on the last Sunday of *October* in 1974.
 # Before the Uniform Time Act of 1966 took effect in 1967, observance of
 # Daylight Saving Time in the US was by local option, except during wartime.
 
+# From Arthur David Olson (2000-09-25):
+# Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
+# In the introduction, Oboler spoke of "Eastern Peace Time."
+# An AltaVista search turned up
+# <a href="http://rowayton.org/rhs/hstaug45.html">:
+# "When the time is announced over the radio now, it is 'Eastern Peace
+# Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
+# </a> (August 1945) by way of confirmation.
+
+# From Joseph Gallant <notquite@hotmail.com>, citing
+# George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
+# At 7 P.M. (Eastern War Time) [on 1945-08-14], the networks were set
+# to switch to London for Atlee's address, but the American people
+# never got to hear his speech live. According to one press account,
+# CBS' Bob Trout was first to announce the word of Japan's surrender,
+# but a few seconds later, NBC, ABC and Mutual also flashed the word
+# of surrender, all of whom interrupting the bells of Big Ben in
+# London which were to precede Mr. Atlee's speech.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   US      1918    1919    -       Mar     lastSun 2:00    1:00    W # War
+Rule   US      1918    1919    -       Mar     lastSun 2:00    1:00    D
 Rule   US      1918    1919    -       Oct     lastSun 2:00    0       S
 Rule   US      1942    only    -       Feb     9       2:00    1:00    W # War
+Rule   US      1945    only    -       Aug     14      23:00u  1:00    P # Peace
 Rule   US      1945    only    -       Sep     30      2:00    0       S
 Rule   US      1967    max     -       Oct     lastSun 2:00    0       S
 Rule   US      1967    1973    -       Apr     lastSun 2:00    1:00    D
@@ -60,6 +102,9 @@ Rule US      1974    only    -       Jan     6       2:00    1:00    D
 Rule   US      1975    only    -       Feb     23      2:00    1:00    D
 Rule   US      1976    1986    -       Apr     lastSun 2:00    1:00    D
 Rule   US      1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# <a href="http://thomas.loc.gov/cgi-bin/bdquery/z?d106:h.r.00177:">
+# H.R.177
+# </a> (introduced 1999-01-06) would change April to March in the above rule.
 
 # From Bob Devine (1988-01-28):
 # ...Alaska (and Hawaii) had the timezone names changed in 1967.
@@ -136,8 +181,28 @@ Rule       US      1987    max     -       Apr     Sun>=1  2:00    1:00    D
 # From Paul Eggert (1995-12-19):
 # Shanks uses 1983-10-30, not 1983-11-30, for the 1983 transitions.
 # Go with Shanks.
+#
+# From Paul Eggert (2000-01-08), following a heads-up from Rives McDow:
+# Public law 106-564 (2000-12-23) introduced the abbreviation
+# "Chamorro Standard Time" for time in Guam and the Northern Marianas.
+# See the file "australasia".
+
+# From Ryan Alessi of the Thousand Oaks Star (2001-02-15) via Rives McDow:
+# Brad Sherman, D-Sherman Oaks, introduced a bill in Congress on
+# Wednesday that could have California operating on Denver time as
+# early as this summer....  The options include keeping
+# daylight-saving time all year long, or setting clocks back two hours
+# -- instead of just one -- during the existing daylight-saving time.
+
 
 # US Eastern time, represented by New York
+
+# Connecticut, Delaware, District of Columbia, most of Florida,
+# Georgia, far southeastern Indiana, eastern Kentucky, Maine,
+# Maryland, Massachusetts, New Hampshire, New Jersey, New York, North
+# Carolina, Ohio, Pennsylvania, Rhode Island, South Carolina, eastern
+# Tennessee, Vermont, Virginia, West Virginia
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   NYC     1920    only    -       Mar     lastSun 2:00    1:00    D
 Rule   NYC     1920    only    -       Oct     lastSun 2:00    0       S
@@ -153,6 +218,13 @@ Zone America/New_York      -4:56:02 -      LMT     1883 Nov 18 12:00
                        -5:00   US      E%sT
 
 # US Central time, represented by Chicago
+
+# Alabama, Arkansas, Florida panhandle, Illinois, western Indiana
+# corners, Iowa, most of Kansas, western Kentucky, Louisiana,
+# Minnesota, Mississippi, Missouri, eastern Nebraska, eastern North
+# Dakota, Oklahoma, eastern South Dakota, western Tennessee, most of
+# Texas, Wisconsin
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   Chicago 1920    only    -       Jun     13      2:00    1:00    D
 Rule   Chicago 1920    1921    -       Oct     lastSun 2:00    0       S
@@ -171,6 +243,12 @@ Zone America/Chicago       -5:50:36 -      LMT     1883 Nov 18 12:00
                        -6:00   US      C%sT
 
 # US Mountain time, represented by Denver
+#
+# Colorado, southern Idaho, far western Kansas, Montana, western
+# Nebraska, New Mexico, southwestern North Dakota, far eastern Oregon,
+# western South Dakota, far western Texas (El Paso County, Hudspeth County,
+# and Pine Springs and Nickel Creek in Culberson County), Utah, Wyoming
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   Denver  1920    1921    -       Mar     lastSun 2:00    1:00    D
 Rule   Denver  1920    only    -       Oct     lastSun 2:00    0       S
@@ -186,6 +264,9 @@ Zone America/Denver -6:59:56 -      LMT     1883 Nov 18 12:00
                        -7:00   US      M%sT
 
 # US Pacific time, represented by Los Angeles
+#
+# California, northern Idaho, Nevada, most of Oregon, and Washington
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   CA      1948    only    -       Mar     14      2:00    1:00    D
 Rule   CA      1949    only    -       Jan      1      2:00    0       S
@@ -201,40 +282,47 @@ Zone America/Los_Angeles -7:52:58 -       LMT     1883 Nov 18 12:00
 # Alaska
 # AK%sT is the modern abbreviation for -9:00 per USNO.
 #
-# From Paul Eggert (1995-12-19):
+# From Paul Eggert (2001-04-01):
 # Howse writes that Alaska switched from the Julian to the Gregorian calendar,
 # and from east-of-GMT to west-of-GMT days, when the US bought it from Russia.
-# This was on 1867-10-18.  We omit this transition, since we can't represent
-# changes from Julian to Gregorian.
+# This was on 1867-10-18, a Friday; the previous day was 1867-10-06 Julian,
+# also a Friday.  Include only the time zone part of this transition,
+# ignoring the switch from Julian to Gregorian, since we can't represent
+# the Julian calendar.
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone America/Juneau     -8:57:41 -     LMT     1900 Aug 20 12:00
+Zone America/Juneau     15:02:19 -     LMT     1867 Oct 18
+                        -8:57:41 -     LMT     1900 Aug 20 12:00
                         -8:00  -       PST     1942
                         -8:00  US      P%sT    1946
                         -8:00  -       PST     1969
                         -8:00  US      P%sT    1983 Oct 30 2:00
                         -9:00  US      AK%sT
-Zone America/Yakutat    -9:18:55 -     LMT     1900 Aug 20 12:00
+Zone America/Yakutat    14:41:05 -     LMT     1867 Oct 18
+                        -9:18:55 -     LMT     1900 Aug 20 12:00
                         -9:00  -       YST     1942
                         -9:00  US      Y%sT    1946
                         -9:00  -       YST     1969
                         -9:00  US      Y%sT    1983 Oct 30 2:00
                         -9:00  US      AK%sT
-Zone America/Anchorage  -9:59:36 -     LMT     1900 Aug 20 12:00
+Zone America/Anchorage  14:00:24 -     LMT     1867 Oct 18
+                        -9:59:36 -     LMT     1900 Aug 20 12:00
                        -10:00  -       CAT     1942
                        -10:00  US      CAT/CAWT 1946
                        -10:00  -       CAT     1967 Apr
                        -10:00  -       AHST    1969
                        -10:00  US      AH%sT   1983 Oct 30 2:00
                         -9:00  US      AK%sT
-Zone America/Nome      -11:01:38 -     LMT     1900 Aug 20 12:00
+Zone America/Nome       12:58:21 -     LMT     1867 Oct 18
+                       -11:01:38 -     LMT     1900 Aug 20 12:00
                        -11:00  -       NST     1942
                        -11:00  US      N%sT    1946
                        -11:00  -       NST     1967 Apr
                        -11:00  -       BST     1969
                        -11:00  US      B%sT    1983 Oct 30 2:00
                         -9:00  US      AK%sT
-Zone America/Adak      -11:46:38 -     LMT     1900 Aug 20 12:00
+Zone America/Adak       12:13:21 -     LMT     1867 Oct 18
+                       -11:46:38 -     LMT     1900 Aug 20 12:00
                        -11:00  -       NST     1942
                        -11:00  US      N%sT    1946
                        -11:00  -       NST     1967 Apr
@@ -263,11 +351,6 @@ Zone Pacific/Honolulu      -10:31:26 -     LMT     1900 Jan  1 12:00
                        -10:30  US      H%sT    1947 Jun  8 2:00
                        -10:00  -       HST
 
-Zone Pacific/Midway    -11:49:28 -     LMT     1901
-                       -11:00  -       NST     1967 Apr        # N=Nome
-                       -11:00  -       BST     1983 Nov 30     # B=Bering
-                       -11:00  -       SST                     # S=Samoa
-
 # Now we turn to US areas that have diverged from the consensus since 1970.
 
 # Arizona mostly uses MST.
@@ -297,6 +380,11 @@ Zone America/Boise -7:44:49 -      LMT     1883 Nov 18 12:00
 
 # Indiana
 #
+# For a map of Indiana's time zone regions, see:
+# <a href="http://www.mccsc.edu/time.html">
+# What time is it in Indiana?
+# </a> (1999-04-06)
+#
 # From Paul Eggert (1995-12-19):
 # Indiana generally observes either EST all year, or CST/CDT,
 # but areas near Cincinnati and Louisville use those cities' timekeeping
@@ -316,6 +404,13 @@ Zone America/Boise -7:44:49 -      LMT     1883 Nov 18 12:00
 # So we reluctantly put them all in a subdirectory `America/Indiana'.
 #
 # Most of EST-only Indiana last observed DST in 1970.
+
+# From Paul Eggert (2001-03-06), following a tip by Markus Kuhn:
+# Pam Belluck reported in the New York Times (2001-01-31) that the
+# Indiana Legislature is considering a bill to adopt DST statewide.
+# Her article mentioned Vevay, whose post office observes a different
+# time zone than Danner's Hardware across the street.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule Indianapolis 1941 only    -       Jun     22      2:00    1:00    D
 Rule Indianapolis 1941 1954    -       Sep     lastSun 2:00    0       S
@@ -378,6 +473,7 @@ Zone America/Indiana/Vevay -5:40:16 -       LMT     1883 Nov 18 12:00
                        -5:00   -       EST
 
 # Part of Kentucky left its clocks alone in 1974.
+# This also includes a part of Indiana immediately adjacent to Louisville.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule Louisville        1921    only    -       May     1       2:00    1:00    D
 Rule Louisville        1921    only    -       Sep     1       2:00    0       S
@@ -396,15 +492,59 @@ Zone America/Louisville   -5:43:02 -      LMT     1883 Nov 18 12:00
                        -5:00   US      E%sT    1974 Jan  6 2:00
                        -6:00   1:00    CDT     1974 Oct 27 2:00
                        -5:00   US      E%sT
+Link America/Louisville America/Kentucky/Louisville
+#
+# Wayne, Clinton, and Russell Counties, Kentucky
+#
+# From
+# <a href="http://www.lake-cumberland.com/life/archive/news990129time.shtml">
+# Lake Cumberland LIFE
+# </a> (1999-01-29) via WKYM-101.7:
+# Clinton County has joined Wayne County in asking the DoT to change from
+# the Central to the Eastern time zone....  The Wayne County government made
+# the same request in December.  And while Russell County officials have not
+# taken action, the majority of respondents to a poll conducted there in
+# August indicated they would like to change to "fast time" also.
+# The three Lake Cumberland counties are the farthest east of any U.S.
+# location in the Central time zone.
+#
+# From Rich Wales (2000-08-29):
+# After prolonged debate, and despite continuing deep differences of opinion,
+# Wayne County (central Kentucky) is switching from Central (-0600) to Eastern
+# (-0500) time.  They won't "fall back" this year.  See Sara Shipley,
+# The difference an hour makes, Nando Times (2000-08-29 15:33 -0400).
+Zone America/Kentucky/Monticello -5:39:24 - LMT        1883 Nov 18 12:00
+                       -6:00   US      C%sT    1946
+                       -6:00   -       CST     1968
+                       -6:00   US      C%sT    2000 Oct 29  2:00
+                       -5:00   US      E%sT
+
+
+# From Rives McDow (2000-08-30):
+# Here ... are all the changes in the US since 1985.
+# Kearny County, KS (put all of county on central;
+#      previously split between MST and CST) ... 1990-10
+# Starke County, IN (from CST to EST) ... 1991-10
+# Oliver County, ND (from MST to CST) ... 1992-10
+# West Wendover, NV (from PST TO MST) ... 1999-10
+# Wayne County, KY (from CST to EST) ... 2000-10
+# There is another change in the offing; Mercer County, ND is looking
+# to change from MT to CT. It is possible that two other ND counties
+# (Sioux and Morton) will look to change also.  If made, the earliest
+# a change would be effective is October 2001.
+#
+# From Paul Eggert (2000-10-02):
+# FIXME: I haven't yet had time to incorporate all the above changes.
 
 # Michigan
 #
 # From Bob Devine (1988-01-28):
 # Michigan didn't observe DST from 1968 to 1973.
 #
-# From Paul Eggert (1995-12-19):
-# Shanks writes that Michigan started using standard time on 1885 Sep 18,
-# but Howse (p 126) writes that Detroit kept
+# From Paul Eggert (1999-03-31):
+# Shanks writes that Michigan started using standard time on 1885-09-18,
+# but Howse writes (pp 124-125, referring to Popular Astronomy, 1901-01)
+# that Detroit kept
 #
 #      local time until 1900 when the City Council decreed that clocks should
 #      be put back twenty-eight minutes to Central Standard Time.  Half the
@@ -416,6 +556,11 @@ Zone America/Louisville    -5:43:02 -      LMT     1883 Nov 18 12:00
 #
 # This story is too entertaining to be false, so go with Howse over Shanks.
 #
+# From Paul Eggert (2001-03-06):
+# Garland (1927) writes ``Cleveland and Detroit advanced their clocks
+# one hour in 1914.''  This change is not in Shanks.  We have no more
+# info, so omit this for now.
+#
 # Most of Michigan observed DST from 1973 on, but was a bit late in 1975.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   Detroit 1948    only    -       Apr     lastSun 2:00    1:00    D
@@ -446,8 +591,14 @@ Zone America/Menominee     -5:50:27 -      LMT     1885 Sep 18 12:00
                        -6:00   US      C%sT
 
 # Navassa
-# uninhabited
-
+# claimed by US under the provisions of the 1856 Guano Islands Act
+# also claimed by Haiti
+# occupied 1857/1900 by the Navassa Phosphate Co
+# US lighthouse 1917/1997-01
+# currently uninhabited
+# see Mark Fineman, ``An Isle Rich in Guano and Discord'',
+# _Los Angeles Times_ (1998-11-10), A1, A10; it cites
+# Jimmy Skaggs, _The Great Guano Rush_ (1994).
 
 # Old names, for S5 users
 
@@ -463,12 +614,12 @@ Link      Pacific/Honolulu        HST
 ################################################################################
 
 
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# From Paul Eggert <eggert@twinsun.com> (1999-10-29):
 # A good source for time zone historical data outside the US is
-# Thomas G. Shanks, The International Atlas (3rd edition),
-# San Diego: ACS Publications, Inc. (1991).
+# Thomas G. Shanks, The International Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1999).
 #
-# Gwillim Law <LAW@encmail.encompass.com> writes that a good source
+# Gwillim Law <Gwil_Law@bridge-point.com> writes that a good source
 # for recent time zone data is the International Air Transport
 # Association's Standard Schedules Information Manual (IATA SSIM),
 # published semiannually.  Law sent in several helpful summaries
@@ -482,8 +633,6 @@ Link        Pacific/Honolulu        HST
 # I found in the UCLA library.
 #
 # See the `europe' file for Greenland.
-#
-# See the `africa' file for time zone naming and abbreviation conventions.
 
 # Canada
 
@@ -519,20 +668,38 @@ Link      Pacific/Honolulu        HST
 # From Paul Eggert <eggert@twinsun.com> (1994-11-22):
 # Alas, this sort of thing must be handled by localization software.
 
-# The data for Canada are all from Shanks (1991).
+# Unless otherwise specified, the data for Canada are all from Shanks.
 
+# From Paul Eggert (2000-10-02):
+# H. David Matthews and Mary Vincent's map
+# <a href="http://www.canadiangeographic.ca/SO98/geomap.htm">
+# "It's about TIME", _Canadian Geographic_ (September-October 1998)
+# </a> contains detailed boundaries for regions observing nonstandard
+# time and daylight saving time arrangements in Canada circa 1998.
+#
+# INMS, the Institute for National Measurement Standards in Ottawa, has
+# <a href="http://www.nrc.ca/inms/time/tze.html">
+# information about standard and daylight saving time zones in Canada.
+# </a> (updated periodically).
+# Its unofficial information is often taken from Matthews and Vincent.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Canada  1918    only    -       Apr     14      2:00    1:00    D
 Rule   Canada  1918    only    -       Oct     31      2:00    0       S
-Rule   Canada  1942    only    -       Feb      9      2:00    1:00    D
+Rule   Canada  1942    only    -       Feb      9      2:00    1:00    W
 Rule   Canada  1945    only    -       Sep     30      2:00    0       S
 Rule   Canada  1974    1986    -       Apr     lastSun 2:00    1:00    D
 Rule   Canada  1974    max     -       Oct     lastSun 2:00    0       S
 Rule   Canada  1987    max     -       Apr     Sun>=1  2:00    1:00    D
 
 
-# Newfoundland (except Labrador)
+# Newfoundland (and far southeast Labrador)
+
+# From Paul Eggert (2000-10-02):
+# Matthews and Vincent (1998) write that Labrador should use NST/NDT,
+# but the only part of Labrador that follows the rules is the
+# southeast corner, including Port Hope Simpson and Mary's Harbour,
+# but excluding, say, Black Tickle.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   StJohns 1917    1918    -       Apr     Sun>=8  2:00    1:00    D
@@ -548,13 +715,13 @@ Rule      StJohns 1920    1935    -       Oct     lastSun 23:00   0       S
 Rule   StJohns 1936    1941    -       May     Sun>=8  0:00    1:00    D
 Rule   StJohns 1936    1941    -       Oct     Sun>=1  0:00    0       S
 # Shanks gives 1942 May 11 - 1945 Sep 30; go with Whitman.
-Rule   StJohns 1942    only    -       Mar      1      0:00    1:00    D
+Rule   StJohns 1942    only    -       Mar      1      0:00    1:00    W
 Rule   StJohns 1942    only    -       Dec     31      0:00    0       S
-Rule   StJohns 1943    only    -       May     30      0:00    1:00    D
+Rule   StJohns 1943    only    -       May     30      0:00    1:00    W
 Rule   StJohns 1943    only    -       Sep      5      0:00    0       S
-Rule   StJohns 1944    only    -       Jul     10      0:00    1:00    D
+Rule   StJohns 1944    only    -       Jul     10      0:00    1:00    W
 Rule   StJohns 1944    only    -       Sep      2      0:00    0       S
-Rule   StJohns 1945    only    -       Jan      1      0:00    1:00    D
+Rule   StJohns 1945    only    -       Jan      1      0:00    1:00    W
 Rule   StJohns 1945    only    -       Oct      7      2:00    0       S
 # For 1946-9 Whitman gives May 5,4,9,1 - Oct 1,5,3,2, and for 1950 he gives
 # Apr 30 - Sep 24; go with Shanks.
@@ -562,10 +729,14 @@ Rule      StJohns 1946    1950    -       May     Sun>=8  2:00    1:00    D
 Rule   StJohns 1946    1950    -       Oct     Sun>=2  2:00    0       S
 Rule   StJohns 1951    1986    -       Apr     lastSun 2:00    1:00    D
 Rule   StJohns 1951    1959    -       Sep     lastSun 2:00    0       S
-Rule   StJohns 1960    max     -       Oct     lastSun 2:00    0       S
-Rule   StJohns 1987    only    -       Apr     Sun>=1  2:00    1:00    D
-Rule   StJohns 1988    only    -       Apr     Sun>=1  2:00    2:00    DD
-Rule   StJohns 1989    max     -       Apr     Sun>=1  2:00    1:00    D
+Rule   StJohns 1960    1986    -       Oct     lastSun 2:00    0       S
+# From Paul Eggert (2000-10-02):
+# INMS (2000-09-12) says that, since 1988 at least, Newfoundland switches
+# at 00:01 local time.  For now, assume it started in 1987.
+Rule   StJohns 1987    only    -       Apr     Sun>=1  0:01    1:00    D
+Rule   StJohns 1987    max     -       Oct     lastSun 0:01    0       S
+Rule   StJohns 1988    only    -       Apr     Sun>=1  0:01    2:00    DD
+Rule   StJohns 1989    max     -       Apr     Sun>=1  0:01    1:00    D
 # St John's has an apostrophe, but Posix file names can't have apostrophes.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/St_Johns  -3:30:52 -      LMT     1884
@@ -573,7 +744,7 @@ Zone America/St_Johns       -3:30:52 -      LMT     1884
                        -3:30   StJohns N%sT
 
 
-# east Labrador
+# most of east Labrador
 
 # The name `Happy Valley-Goose Bay' is too long; use `Goose Bay'.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -594,6 +765,11 @@ Zone America/Goose_Bay     -4:01:40 -      LMT     1884 # Happy Valley-Goose Bay
 # Shanks also writes that Liverpool, NS was the only town in Canada to observe
 # DST in 1971 but not 1970; for now we'll assume this is a typo.
 
+# From Paul Eggert (2000-10-02):
+# INMS (2000-09-12) says that, since 1988 at least, New Brunswick switches
+# at 00:01 local time.  FIXME: verify and create a new Zone for this.
+
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule Halifax   1916    only    -       Apr      1      0:00    1:00    D
 Rule Halifax   1916    only    -       Oct      1      0:00    0       S
@@ -629,7 +805,7 @@ Rule Halifax        1937    1938    -       May     Sun>=1  0:00    1:00    D
 Rule Halifax   1937    1941    -       Sep     Mon>=24 0:00    0       S
 Rule Halifax   1939    only    -       May     28      0:00    1:00    D
 Rule Halifax   1940    1941    -       May     Sun>=1  0:00    1:00    D
-Rule Halifax   1942    only    -       Feb     9       2:00    1:00    D
+Rule Halifax   1942    only    -       Feb     9       2:00    1:00    W
 Rule Halifax   1945    1959    -       Sep     lastSun 2:00    0       S
 Rule Halifax   1946    1959    -       Apr     lastSun 2:00    1:00    D
 Rule Halifax   1962    1986    -       Apr     lastSun 2:00    1:00    D
@@ -654,6 +830,31 @@ Zone America/Glace_Bay     -3:59:48 -      LMT     1902 Jun 15
 # Nipigon (EST) and Rainy River (CST) are the largest that we know of.
 # Far west Ontario is like Winnipeg; far east Quebec is like Halifax.
 
+# From Paul Eggert (1997-10-17):
+# msb@sq.com writes that an article in the 1997-10-14 Toronto Star
+# says that Atikokan, Ontario currently does not observe DST,
+# but will vote on 11-10 whether to use EST/EDT.
+# He also writes that the
+# <a href="http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html">
+# Ontario Time Act (1990, Chapter T.9)
+# </a>
+# says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
+# Officially Atikokan is therefore on CST/CDT, and most likely this report
+# concerns a non-official time observed as a matter of local practice.
+# For what it's worth, Shanks says that Atikokan has agreed with
+# Rainy River ever since standard time was introduced.
+
+# From Paul Eggert (2000-10-02):
+# Matthews and Vincent (1998) write that Atikokan, Pickle Lake, and
+# New Osnaburgh observe CST all year, that Big Trout Lake observes
+# CST/CDT, and that Upsala and Shebandowan observe EST/EDT, all in
+# violation of the official Ontario rules.
+# They also write that Quebec east of the -63 meridian is supposed to
+# observe AST, but residents as far east as Natashquan use EST/EDT,
+# and residents east of Natashquan use AST.
+# We probably need Zones for far east Quebec and for Atikokan,
+# but we don't know when their practices started.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Mont    1917    only    -       Mar     25      2:00    1:00    D
 Rule   Mont    1917    only    -       Apr     24      0:00    0       S
@@ -706,7 +907,7 @@ Rule        Winn    1918    only    -       Apr     14      2:00    1:00    D
 Rule   Winn    1918    only    -       Oct     31      2:00    0       S
 Rule   Winn    1937    only    -       May     16      2:00    1:00    D
 Rule   Winn    1937    only    -       Sep     26      2:00    0       S
-Rule   Winn    1942    only    -       Feb      9      2:00    1:00    D
+Rule   Winn    1942    only    -       Feb      9      2:00    1:00    W
 Rule   Winn    1945    only    -       Sep     lastSun 2:00    0       S
 Rule   Winn    1946    only    -       May     12      2:00    1:00    D
 Rule   Winn    1946    only    -       Oct     13      2:00    0       S
@@ -721,8 +922,12 @@ Rule       Winn    1960    only    -       Sep     lastSun 2:00    0       S
 Rule   Winn    1963    only    -       Apr     lastSun 2:00    1:00    D
 Rule   Winn    1963    only    -       Sep     22      2:00    0       S
 Rule   Winn    1966    1986    -       Apr     lastSun 2:00    1:00    D
-Rule   Winn    1966    max     -       Oct     lastSun 2:00    0       S
+Rule   Winn    1966    1986    -       Oct     lastSun 2:00    0       S
 Rule   Winn    1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# From Paul Eggert (2000-10-02):
+# INMS (2000-09-12) says that, since 1988 at least, Manitoba switches from
+# DST at 03:00 local time.  For now, assume it started in 1987.
+Rule   Winn    1987    max     -       Oct     lastSun 2:00s   0       S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Winnipeg  -6:28:36 -      LMT     1887 Jul 16
                        -6:00   Winn    C%sT
@@ -730,10 +935,12 @@ Zone America/Winnipeg     -6:28:36 -      LMT     1887 Jul 16
 
 # Saskatchewan
 
-# From Paul Eggert (1996-06-12):
+# From Paul Eggert (2000-10-02):
 # Shanks writes that since 1970 most of this region has been like Regina.
 # Some western towns (e.g. Swift Current) switched from MST/MDT to CST in 1972.
 # Other western towns (e.g. Lloydminster) are like Edmonton.
+# Matthews and Vincent (1998) write that Denare Beach and Creighton
+# are like Winnipeg, in violation of Saskatchewan law.
 
 # From W. Jones <jones@skdad.usask.ca> (1992-11-06):
 # The. . .below is based on information I got from our law library, the
@@ -770,7 +977,7 @@ Rule        Regina  1937    1941    -       Apr     Sun>=8  0:00    1:00    D
 Rule   Regina  1937    only    -       Oct     Sun>=8  0:00    0       S
 Rule   Regina  1938    only    -       Oct     Sun>=1  0:00    0       S
 Rule   Regina  1939    1941    -       Oct     Sun>=8  0:00    0       S
-Rule   Regina  1942    only    -       Feb      9      2:00    1:00    D
+Rule   Regina  1942    only    -       Feb      9      2:00    1:00    W
 Rule   Regina  1945    only    -       Sep     lastSun 2:00    0       S
 Rule   Regina  1946    only    -       Apr     Sun>=8  2:00    1:00    D
 Rule   Regina  1946    only    -       Oct     Sun>=8  2:00    0       S
@@ -803,7 +1010,7 @@ Rule       Edm     1919    only    -       May     27      2:00    0       S
 Rule   Edm     1920    1923    -       Apr     lastSun 2:00    1:00    D
 Rule   Edm     1920    only    -       Oct     lastSun 2:00    0       S
 Rule   Edm     1921    1923    -       Sep     lastSun 2:00    0       S
-Rule   Edm     1942    only    -       Feb      9      2:00    1:00    D
+Rule   Edm     1942    only    -       Feb      9      2:00    1:00    W
 Rule   Edm     1945    only    -       Sep     lastSun 2:00    0       S
 Rule   Edm     1947    only    -       Apr     lastSun 2:00    1:00    D
 Rule   Edm     1947    only    -       Sep     lastSun 2:00    0       S
@@ -821,14 +1028,15 @@ Zone America/Edmonton    -7:33:52 -      LMT     1906 Sep
 
 # British Columbia
 
-# From Paul Eggert (1996-06-12):
+# From Paul Eggert (2000-10-02):
 # Shanks writes that since 1970 most of this region has been like Vancouver.
-# Dawswon Creek uses MST.  Much of east BC is like Edmonton.
+# Dawson Creek uses MST.  Much of east BC is like Edmonton.
+# Matthews and Vincent (1998) write that Creston is like Dawson Creek.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Vanc    1918    only    -       Apr     14      2:00    1:00    D
 Rule   Vanc    1918    only    -       Oct     31      2:00    0       S
-Rule   Vanc    1942    only    -       Feb      9      2:00    1:00    D
+Rule   Vanc    1942    only    -       Feb      9      2:00    1:00    W
 Rule   Vanc    1945    only    -       Sep     30      2:00    0       S
 Rule   Vanc    1946    1986    -       Apr     lastSun 2:00    1:00    D
 Rule   Vanc    1946    only    -       Oct     13      2:00    0       S
@@ -844,11 +1052,10 @@ Zone America/Dawson_Creek -8:00:56 -     LMT     1884
                        -7:00   -       MST
 
 
-# Northwest Territories, Yukon
+# Northwest Territories, Nunavut, Yukon
 
-# From Paul Eggert (1996-10-07):
+# From Paul Eggert (1999-10-29):
 # Dawson switched to PST in 1973.  Inuvik switched to MST in 1979.
-# Shanks's table for Watson Lake is corrupted, so we have no data there.
 # Mathew Englander <mathew@io.org> (1996-10-07) gives the following refs:
 #      * 1967. Paragraph 28(34)(g) of the Interpretation Act, S.C. 1967-68,
 #      c. 7 defines Yukon standard time as UTC-9.  This is still valid;
@@ -858,12 +1065,104 @@ Zone America/Dawson_Creek -8:00:56 -    LMT     1884
 #      * O.I.C. 1987/056 changed DST to Apr firstSun 2:00 to Oct lastSun 2:00.
 # Shanks says Yukon's 1973-10-28 switch was at 2:00; go with Englander.
 
+# From Rives McDow (1999-09-04):
+# Nunavut ... moved ... to incorporate the whole territory into one time zone.
+# <a href="http://www.nunatsiaq.com/nunavut/nvt90903_13.html">
+# Nunavut moves to single time zone Oct. 31
+# </a>
+#
+# From Antoine Leca (1999-09-06):
+# We then need to create a new timezone for the Kitikmeot region of Nunavut
+# to differentiate it from the Yellowknife region.
+
+# From Paul Eggert (1999-09-20):
+# <a href="http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html">
+# Basic Facts: The New Territory
+# </a> (1999) reports that Pangnirtung operates on Eastern time,
+# and that Coral Harbour does not observe DST.  We don't know when
+# Pangnirtung switched to Eastern time; we'll guess 1995.
+# We'll ignore the claim about Coral Harbour for now,
+# since we have no further info.
+
+# From Rives McDow (1999-11-08):
+# On October 31, when the rest of Nunavut went to Central time,
+# Pangnirtung wobbled.  Here is the result of their wobble:
+#
+# The following businesses and organizations in Pangnirtung use Central Time:
+#
+#      First Air, Power Corp, Nunavut Construction, Health Center, RCMP,
+#      Eastern Arctic National Parks, A & D Specialist
+#
+# The following businesses and organizations in Pangnirtung use Eastern Time:
+#
+#      Hamlet office, All other businesses, Both schools, Airport operator
+#
+# This has made for an interesting situation there, which warranted the news.
+# No one there that I spoke with seems concerned, or has plans to
+# change the local methods of keeping time, as it evidently does not
+# really interfere with any activities or make things difficult locally.
+# They plan to celebrate New Year's turn-over twice, one hour apart,
+# so it appears that the situation will last at least that long.
+# The Nunavut Intergovernmental Affairs hopes that they will "come to
+# their senses", but the locals evidently don't see any problem with
+# the current state of affairs.
+
+# From Michaela Rodrigue, writing in the
+# <a href="http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html">
+# Nunatsiaq News (1999-11-19)</a>:
+# Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
+# central - or Nunavut time - for government offices, and eastern time
+# for municipal offices and schools....  Igloolik [was similar but then]
+# made the switch to central time on Saturday, Nov. 6.
+
+# From Paul Eggert (2000-10-02):
+# Matthews and Vincent (1998) say the following, but we lack histories
+# for these potential new Zones.
+#
+# The Canadian Forces station at Alert uses Eastern Time while the
+# handful of residents at the Eureka weather station [in the Central
+# zone] skip daylight savings.  Baffin Island, which is crossed by the
+# Central, Eastern and Atlantic Time zones only uses Eastern Time.
+# Gjoa Haven, Taloyoak and Pelly Bay all use Mountain instead of
+# Central Time and Southampton Island [in the Central zone] is not
+# required to use daylight savings.
+
+# From
+# <a href="http://www.nunatsiaq.com/archives/nunavut001130/nvt21110_02.html">
+# Nunavut now has two time zones
+# </a> (2000-11-10):
+# The Nunavut government would allow its employees in Kugluktuk and
+# Cambridge Bay to operate on central time year-round, putting them
+# one hour behind the rest of Nunavut for six months during the winter.
+# At the end of October the two communities had rebelled against
+# Nunavut's unified time zone, refusing to shift to eastern time with
+# the rest of the territory for the winter.  Cambridge Bay remained on
+# central time, while Kugluktuk, even farther west, reverted to
+# mountain time, which they had used before the advent of Nunavut's
+# unified time zone in 1999.
+#
+# From Rives McDow (2001-01-20), quoting the Nunavut government:
+# The preceding decision came into effect at midnight, Saturday Nov 4, 2000.
+
+# From Paul Eggert (2000-12-04):
+# Let's just keep track of the official times for now.
+
+# From Rives McDow (2001-03-07):
+# The premier of Nunavut has issued a ministerial statement advising
+# that effective 2001-04-01, the territory of Nunavut will revert
+# back to three time zones (mountain, central, and eastern).  Of the
+# cities in Nunavut, Coral Harbor is the only one that I know of that
+# has said it will not observe dst, staying on EST year round.  I'm
+# checking for more info, and will get back to you if I come up with
+# more.
+# [Also see <http://www.nunatsiaq.com/nunavut/nvt10309_06.html> (2001-03-09).]
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   NT_YK   1918    only    -       Apr     14      2:00    1:00    D
 Rule   NT_YK   1918    only    -       Oct     27      2:00    0       S
 Rule   NT_YK   1919    only    -       May     25      2:00    1:00    D
 Rule   NT_YK   1919    only    -       Nov      1      0:00    0       S
-Rule   NT_YK   1942    only    -       Feb      9      2:00    1:00    D
+Rule   NT_YK   1942    only    -       Feb      9      2:00    1:00    W
 Rule   NT_YK   1945    only    -       Sep     30      2:00    0       S
 Rule   NT_YK   1965    only    -       Apr     lastSun 0:00    2:00    DD
 Rule   NT_YK   1965    only    -       Oct     lastSun 2:00    0       S
@@ -872,11 +1171,24 @@ Rule     NT_YK   1980    max     -       Oct     lastSun 2:00    0       S
 Rule   NT_YK   1987    max     -       Apr     Sun>=1  2:00    1:00    D
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Pangnirtung -4:22:56 -    LMT     1884
-                       -4:00   NT_YK   A%sT
-Zone America/Iqaluit   -4:33:52 -      LMT     1884    # Frobisher Bay
-                       -5:00   NT_YK   E%sT
+                       -4:00   NT_YK   A%sT    1995 Apr Sun>=1 2:00
+                       -5:00   Canada  E%sT    1999 Oct 31 2:00
+                       -6:00   Canada  C%sT    2000 Oct 29 2:00
+                       -5:00   Canada  E%sT
+Zone America/Iqaluit   -4:33:52 -      LMT     1884 # Frobisher Bay before 1987
+                       -5:00   NT_YK   E%sT    1999 Oct 31 2:00
+                       -6:00   Canada  C%sT    2000 Oct 29 2:00
+                       -5:00   Canada  E%sT
 Zone America/Rankin_Inlet -6:08:40 -   LMT     1884
-                       -6:00   NT_YK   C%sT
+                       -6:00   NT_YK   C%sT    2000 Oct 29 2:00
+                       -5:00   -       EST     2001 Apr  1 3:00
+                       -6:00   Canada  C%sT
+Zone America/Cambridge_Bay -7:00:20 -  LMT     1884
+                       -7:00   NT_YK   M%sT    1999 Oct 31 2:00
+                       -6:00   Canada  C%sT    2000 Oct 29 2:00
+                       -5:00   -       EST     2000 Nov  5 0:00
+                       -6:00   -       CST     2001 Apr  1 3:00
+                       -7:00   Canada  M%sT
 Zone America/Yellowknife -7:37:24 -    LMT     1884
                        -7:00   NT_YK   M%sT
 Zone America/Inuvik    -8:54:00 -      LMT     1884
@@ -894,139 +1206,233 @@ Zone America/Dawson    -9:17:40 -      LMT     1900 Aug 20
 
 # Mexico
 
-# From Guy Harris:
-# Rules are from the Official Airline Guide, Worldwide Edition, for 1987.
-# Rules prior to 1987 are unknown.
-# The comments in the OAG say "Only Ensenada, Mexicale, San Felipe and Tijuana
-# observe DST."  This is presumably Baja California Norte, above 28th parallel,
-# as listed there; [there is also] "Baja California Sur and N. Pacific
-# Coast (States of Sinaloa and Sonora)."
-
-# From Bob Devine (1988-01-28):
-# The Federal District (where Mexico City is) has observed [DST] several
-# times but not recently.
-#
-# I don't where to drawn the line in the North Baja area.  28th latitude
-# sounds good -- but it may be higher (how far [d]o radio stations from
-# San Diego affect culture?).
+# From Paul Eggert (2001-03-05):
+# The Investigation and Analysis Service of the
+# Mexican Library of Congress (MLoC) has published a
+# <a href="http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/">
+# history of Mexican local time (in Spanish)
+# </a>.
 #
-# The dates of DST probably go back to 1981.  The rules are the same as
-# US's.  This is going to be a headache for US presidential electi[o]n years!
-
-# From Arthur David Olson (1988-02-13)
-# Since the 1981 starting date is only "probable," we'll keep the 1987
-# starting date below.
-
-# From U. S. Naval Observatory (1989-01-19):
-# MEXICO BAJA CAL N   7 H  BEHIND UTC    BAJA CALIFORNIA SUR AND
-# MEXICO BAJA CAL N                      N. PACIFIC COAST (STATES
-# MEXICO BAJA CAL N                      OF SINALOA AND SONORA)
-# MEXICO BAJA CAL N   8 H  BEHIND UTC    ABOVE 28TH PARALLEL APR 3
-# MEXICO BAJA CAL N                      - OCT 29
-# MEXICO BAJA CAL N   7 H  BEHIND UTC    ABOVE 28TH PARALLEL APR 3
-# MEXICO BAJA CAL N                      - 0CT 29
-# MEXICO              6 H  BEHIND UTC    STATES OF DURANGO,
-# MEXICO                                 COAHUILA, NUEVO LEON,
-# MEXICO                                 TAMAULIPAS
-# MEXICO              5 H  BEHIND UTC    STATES OF DURANGO,
-# MEXICO                                 COAHUILA, NUEVO LEON,
-# MEXICO                                 TAMAULIPAS  APR 3 - OCT 29
-# MEXICO              6 H  BEHIND UTC    GENERAL MEXICO, STATES OF
-# MEXICO                                 CAMPECHE, QUINTANA ROO AND
-# MEXICO                                 YUCATAN
-
-# From Arthur David Olson (1989-01-21):
-# April 3 fell on a Sunday in 1988; October 29 fell on a Sunday in 1989.  Ahem.
-# USNO claims there should be four Mexican zones rather than three:
-# a zone that's GMT-8 with DST; a zone that's always GMT-7;
-# a zone that's GMT-6 with DST; and a zone that's always GMT-6.
-
-# From Paul Eggert <eggert@twinsun.com> (1993-11-18):
-# Shanks also says there are four zones, but disagrees about the fourth.
-# Instead of GMT-6 with DST, he says there's GMT-8 without DST.
+# Here are the discrepancies between Shanks and the MLoC.
+# (In all cases we go with the MLoC.)
+# Shanks reports that Baja was at -8:00 in 1922/1923.
+# Shanks says the 1930 transition in Baja was 1930-11-16.
+# Shanks reports no DST during summer 1931.
+# Shanks reports a transition at 1032-03-30 23:00, not 1932-04-01.
+# Shanks does not report transitions for Baja in 1945 or 1948.
+# Shanks reports southern Mexico transitions on 1981-12-01, not 12-23.
+# Shanks says Quintana Roo switched to -6:00 on 1982-12-02, and to -5:00
+# on 1997-10-26 at 02:00.
+
+# From Gwillim Law (2001-02-20):
+# There are some other discrepancies between the Decrees page and the
+# tz database.  I think they can best be explained by supposing that
+# the researchers who prepared the Decrees page failed to find some of
+# the relevant documents.
+
+# From Paul Eggert (2000-07-26):
+# Shanks gives 1942-04-01 instead of 1942-04-24, and omits the 1981
+# and 1988 DST experiments.  Go with spin.com.mx.
 
 # From Alan Perry <alan.perry@eng.sun.com> (1996-02-15):
 # A guy from our Mexico subsidiary finally found the Presidential Decree
 # outlining the timezone changes in Mexico.
-# 
+#
 # ------------- Begin Forwarded Message -------------
-# 
+#
 # I finally got my hands on the Official Presidential Decree that sets up the
 # rules for the DST changes. The rules are:
-# 
+#
 # 1. The country is divided in 3 timezones:
 #    - Baja California Norte (the Mexico/BajaNorte TZ)
 #    - Baja California Sur, Nayarit, Sinaloa and Sonora (the Mexico/BajaSur TZ)
 #    - The rest of the country (the Mexico/General TZ)
-#    
+#
 # 2. From the first Sunday in April at 2:00 AM to the last Sunday in October
 #    at 2:00 AM, the times in each zone are as follows:
 #    BajaNorte: GMT+7
 #    BajaSur:   GMT+6
 #    General:   GMT+5
-#    
+#
 # 3. The rest of the year, the times are as follows:
 #    BajaNorte: GMT+8
 #    BajaSur:   GMT+7
 #    General:   GMT+6
-#    
+#
 # The Decree was published in Mexico's Official Newspaper on January 4th.
-# 
+#
 # -------------- End Forwarded Message --------------
 # From Paul Eggert (1996-06-12):
-# For an English translation of the decree,
-# see ``Diario Oficial: Time Zone Changeover'',
-# <URL:http://mexico-travel.com/extra/timezone_eng.html> (1996-01-04).
+# For an English translation of the decree, see
+# <a href="http://mexico-travel.com/extra/timezone_eng.html">
+# ``Diario Oficial: Time Zone Changeover'' (1996-01-04).
+# </a>
+
+# From Rives McDow (1998-10-08):
+# The State of Quintana Roo has reverted back to central STD and DST times
+# (i.e. UTC -0600 and -0500 as of 1998-08-02).
+
+# From Rives McDow (2000-01-10):
+# Effective April 4, 1999 at 2:00 AM local time, Sonora changed to the time
+# zone 5 hours from the International Date Line, and will not observe daylight
+# savings time so as to stay on the same time zone as the southern part of
+# Arizona year round.
+
+# From Jesper Norgaard, translating
+# <http://www.reforma.com/nacional/articulo/064327/> (2001-01-17):
+# In Oaxaca, the 55.000 teachers from the Section 22 of the National
+# Syndicate of Education Workers, refuse to apply daylight saving each
+# year, so that the more than 10,000 schools work at normal hour the
+# whole year.
+
+# From Gwillim Law (2001-01-19):
+# <http://www.reforma.com/negocios_y_dinero/articulo/064481/> ... says
+# (translated):...
+# January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
+# that Summer Time will be reduced from seven to five months, starting
+# this year....
+# <http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001>
+# [translated], says "summer time will ... take effect on the first Sunday
+# in May, and end on the last Sunday of September.
+
+# From Arthur David Olson (2001-01-25):
+# The 2001-01-24 traditional Washington Post contained the page one
+# story "Timely Issue Divides Mexicans."...
+# http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
+# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
+# Mexico City and its 20 million residents on a different time than
+# the rest of the country..." In particular, Lopez Obrador would abolish
+# observation of Daylight Saving Time.
+
+# <a href="http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre">
+# Official statute published by the Energy Department
+# </a> (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
+# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
+
+# From Paul Eggert (2001-03-03):
+#
+# <a href="http://www.latimes.com/news/nation/20010303/t000018766.html">
+# James F. Smith writes in today's LA Times
+# </a>
+# * Sonora will continue to observe standard time.
+# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
+#   the Federal District will not adopt DST.
+# * 4 of 16 district leaders announced they'll ignore the decree.
+# * The decree does not affect federal-controlled facilities including
+#   the airport, banks, hospitals, and schools.
+#
+# For now we'll assume that the Federal District will bow to federal rules.
+
+# From Jesper Norgaard (2001-04-01):
+# I found some references to the Mexican application of daylight
+# saving, which modifies what I had already sent you, stating earlier
+# that a number of northern Mexican states would go on daylight
+# saving. The modification reverts this to only cover Baja California
+# (Norte), while all other states (except Sonora, who has no daylight
+# saving all year) will follow the original decree of president
+# Vicente Fox, starting daylight saving May 6, 2001 and ending
+# September 30, 2001.
+# References: "Diario de Monterrey" <www.diariodemonterrey.com/index.asp>
+# Palabra <http://palabra.infosel.com/010331/primera/ppri3101.pdf> (2001-03-31)
 
-# From Shanks (1991):
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Mexico  1939    only    -       Feb     5       0:00    1:00    D
 Rule   Mexico  1939    only    -       Jun     25      0:00    0       S
 Rule   Mexico  1940    only    -       Dec     9       0:00    1:00    D
 Rule   Mexico  1941    only    -       Apr     1       0:00    0       S
-Rule   Mexico  1943    only    -       Dec     16      0:00    1:00    D
+Rule   Mexico  1943    only    -       Dec     16      0:00    1:00    W
 Rule   Mexico  1944    only    -       May     1       0:00    0       S
 Rule   Mexico  1950    only    -       Feb     12      0:00    1:00    D
 Rule   Mexico  1950    only    -       Jul     30      0:00    0       S
-Rule   Mexico  1996    max     -       Apr     Sun>=1  2:00    1:00    D
-Rule   Mexico  1996    max     -       Oct     lastSun 2:00    0       S
-#
-Rule   BajaN   1950    1966    -       Apr     lastSun 2:00    1:00    D
-Rule   BajaN   1950    1961    -       Sep     lastSun 2:00    0       S
-Rule   BajaN   1961    1966    -       Oct     lastSun 2:00    0       S
+Rule   Mexico  1996    2000    -       Apr     Sun>=1  2:00    1:00    D
+Rule   Mexico  1996    2000    -       Oct     lastSun 2:00    0       S
+Rule   Mexico  2001    max     -       May     Sun>=1  2:00    1:00    D
+Rule   Mexico  2001    max     -       Sep     lastSun 2:00    0       S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+# Quintana Roo
+Zone America/Cancun    -5:47:04 -      LMT     1922 Jan  1  0:12:56
+                       -6:00   -       CST     1981 Dec 23
+                       -5:00   Mexico  E%sT    1998 Aug  2  2:00
+                       -6:00   Mexico  C%sT
+# Campeche, Yucatan
+Zone America/Merida    -5:58:28 -      LMT     1922 Jan  1  0:01:32
+                       -6:00   -       CST     1981 Dec 23
+                       -5:00   -       EST     1982 Dec  2
+                       -6:00   Mexico  C%sT
+# Coahuila, Durango, Nuevo Leon, Tamaulipas
+Zone America/Monterrey -6:41:16 -      LMT     1921 Dec 31 23:18:44
+                       -6:00   -       CST     1988
+                       -6:00   US      C%sT    1989
+                       -6:00   Mexico  C%sT
+# Central Mexico
 Zone America/Mexico_City -6:36:36 -    LMT     1922 Jan  1  0:23:24
                        -7:00   -       MST     1927 Jun 10 23:00
                        -6:00   -       CST     1930 Nov 15
                        -7:00   -       MST     1931 May  1 23:00
                        -6:00   -       CST     1931 Oct
-                       -7:00   -       MST     1932 Mar 30 23:00
+                       -7:00   -       MST     1932 Apr  1
                        -6:00   Mexico  C%sT
+# Chihuahua
+Zone America/Chihuahua -7:04:20 -      LMT     1921 Dec 31 23:55:40
+                       -7:00   -       MST     1927 Jun 10 23:00
+                       -6:00   -       CST     1930 Nov 15
+                       -7:00   -       MST     1931 May  1 23:00
+                       -6:00   -       CST     1931 Oct
+                       -7:00   -       MST     1932 Apr  1
+                       -6:00   -       CST     1996
+                       -6:00   Mexico  C%sT    1998
+                       -6:00   -       CST     1998 Apr Sun>=1 3:00
+                       -7:00   Mexico  M%sT
+# Sonora
+Zone America/Hermosillo        -7:23:52 -      LMT     1921 Dec 31 23:36:08
+                       -7:00   -       MST     1927 Jun 10 23:00
+                       -6:00   -       CST     1930 Nov 15
+                       -7:00   -       MST     1931 May  1 23:00
+                       -6:00   -       CST     1931 Oct
+                       -7:00   -       MST     1932 Apr  1
+                       -6:00   -       CST     1942 Apr 24
+                       -7:00   -       MST     1949 Jan 14
+                       -8:00   -       PST     1970
+                       -7:00   Mexico  M%sT    1999
+                       -7:00   -       MST
+# Baja California Sur, Nayarit, Sinaloa
 Zone America/Mazatlan  -7:05:40 -      LMT     1921 Dec 31 23:54:20
                        -7:00   -       MST     1927 Jun 10 23:00
                        -6:00   -       CST     1930 Nov 15
                        -7:00   -       MST     1931 May  1 23:00
                        -6:00   -       CST     1931 Oct
-                       -7:00   -       MST     1932 Mar 30 23:00
-                       -6:00   -       CST     1942 Apr
+                       -7:00   -       MST     1932 Apr  1
+                       -6:00   -       CST     1942 Apr 24
                        -7:00   -       MST     1949 Jan 14
                        -8:00   -       PST     1970
                        -7:00   Mexico  M%sT
+# Baja California
 Zone America/Tijuana   -7:48:04 -      LMT     1922 Jan  1  0:11:56
+                       -7:00   -       MST     1924
                        -8:00   -       PST     1927 Jun 10 23:00
-                       -7:00   -       MST     1930 Nov 16
-                       -8:00   -       PST     1942 Apr
-                       -7:00   -       MST     1949 Jan 14
-                       -8:00   BajaN   P%sT    1967 Apr lastSun 2:00
+                       -7:00   -       MST     1930 Nov 15
+                       -8:00   -       PST     1931 Apr  1
+                       -8:00   1:00    PDT     1931 Sep 30
+                       -8:00   -       PST     1942 Apr 24
+                       -8:00   1:00    PWT     1945 Nov 12
+                       -8:00   -       PST     1948 Apr  5
+                       -8:00   1:00    PDT     1949 Jan 14
+                       -8:00   -       PST     1954
+                       -8:00   CA      P%sT    1961
+                       -8:00   -       PST     1976
                        -8:00   US      P%sT    1996
-                       -8:00   Mexico  P%sT
-Zone America/Ensenada  -7:46:28 -      LMT     1922 Jan  1  0:13:32
-                       -8:00   -       PST     1927 Jun 10 23:00
-                       -7:00   -       MST     1930 Nov 16
-                       -8:00   -       PST     1942 Apr
-                       -7:00   -       MST     1949 Jan 14
-                       -8:00   -       PST     1996
-                       -8:00   Mexico  P%sT
+                       -8:00   Mexico  P%sT    2001
+                       -8:00   US      P%sT
+# From Paul Eggert (2001-03-05):
+# Formerly there was an America/Ensenada zone, which differed from
+# America/Tijuana only in that it did not observe DST from 1976
+# through 1995.  This was as per Shanks.  However, Guy Harris reports
+# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
+# Tijuana observe DST," which contradicts Shanks but does imply that
+# DST-observance was a town-by-town matter back then.  This concerns
+# data after 1970 so most likely there should be at least one Zone
+# other than America/Tijuana for Baja, but it's not clear yet what its
+# name or contents should be.
 #
 # Revillagigedo Is
 # no information
@@ -1062,7 +1468,7 @@ Rule      Barb    1979    only    -       Sep     30      2:00    0       S
 Rule   Barb    1980    only    -       Sep     25      2:00    0       S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Barbados  -3:58:28 -      LMT     1924            # Bridgetown
-                       -3:58   -       BMT     1932      # Bridgetown Mean Time
+                       -3:58:28 -      BMT     1932      # Bridgetown Mean Time
                        -4:00   Barb    A%sT
 
 # Belize
@@ -1087,15 +1493,10 @@ Zone Atlantic/Bermuda   -4:19:04 -      LMT     1930 Jan  1 2:00    # Hamilton
 # Cayman Is
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   America/Cayman  -5:25:32 -      LMT     1890            # Georgetown
-                       -5:07   -       KMT     1912 Feb    # Kingston Mean Time
+                       -5:07:12 -      KMT     1912 Feb    # Kingston Mean Time
                        -5:00   -       EST
 
-# Clipperton
-# uninhabited
-
 # Costa Rica
-# Shanks gives some very odd dates for 1991, and stops there.
-# For now, we won't guess further.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   CR      1979    1980    -       Feb     lastSun 0:00    1:00    D
 Rule   CR      1979    1980    -       Jun     Sun>=1  0:00    0       S
@@ -1106,23 +1507,24 @@ Rule    CR      1992    only    -       Mar     15      0:00    0       S
 # There are too many San Joses elsewhere, so we'll use `Costa Rica'.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Costa_Rica        -5:36:20 -      LMT     1890            # San Jose
-                       -5:36   -       SJMT    1921 Jan 15 # San Jose Mean Time
+                       -5:36:20 -      SJMT    1921 Jan 15 # San Jose Mean Time
                        -6:00   CR      C%sT
 # Coco
 # no information; probably like America/Costa_Rica
 
 # Cuba
 
-# From Bob Devine (1988-01-28):
-# . . .DST is from 2nd Sunday in May to 2nd Sunday in October since 1981.
-# Change at midnight.  In 1979 & 1980, started at 3rd Sunday in March
-# (I think).
-
-# From U. S. Naval Observatory (1989-01-19):
-# CUBA                5 H  BEHIND UTC
-# CUBA                4 H  BEHIND UTC    MAR 20 - OCT 8
+# From Arthur David Olson (1999-03-29):
+# The 1999-03-28 exhibition baseball game held in Havana, Cuba, between
+# the Cuban National Team and the Baltimore Orioles was carried live on
+# the Orioles Radio Network, including affiliate WTOP in Washington, DC.
+# During the game, play-by-play announcer Jim Hunter noted that
+# "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
+# Time today."  (The "two hour" remark referred to losing one hour of
+# sleep on 1999-03-28--when the announcers were in Cuba as it switched
+# to DST--and one more hour on 1999-04-04--when the announcers will have
+# returned to Baltimore, which switches on that date.)
 
-# From Shanks (1991):
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Cuba    1928    only    -       Jun     10      0:00    1:00    D
 Rule   Cuba    1928    only    -       Oct     10      0:00    0       S
@@ -1142,18 +1544,21 @@ Rule    Cuba    1969    1971    -       Oct     lastSun 0:00    0       S
 Rule   Cuba    1972    1974    -       Oct     8       0:00    0       S
 Rule   Cuba    1975    1977    -       Oct     lastSun 0:00    0       S
 Rule   Cuba    1978    only    -       May     7       0:00    1:00    D
-Rule   Cuba    1978    1980    -       Oct     Sun>=8  0:00    0       S
+Rule   Cuba    1978    1990    -       Oct     Sun>=8  0:00    0       S
 Rule   Cuba    1979    1980    -       Mar     Sun>=15 0:00    1:00    D
 Rule   Cuba    1981    1985    -       May     Sun>=5  0:00    1:00    D
-Rule   Cuba    1981    1990    -       Oct     Sun>=8  0:00    0       S
 Rule   Cuba    1986    1989    -       Mar     Sun>=14 0:00    1:00    D
-Rule   Cuba    1990    max     -       Apr     Sun>=1  0:00    1:00    D
+Rule   Cuba    1990    1997    -       Apr     Sun>=1  0:00    1:00    D
 Rule   Cuba    1991    1995    -       Oct     Sun>=8  0:00s   0       S
-Rule   Cuba    1996    max     -       Oct     Sun>=1  0:00s   0       S
+Rule   Cuba    1996    only    -       Oct      6      0:00s   0       S
+Rule   Cuba    1997    only    -       Oct     12      0:00s   0       S
+Rule   Cuba    1998    1999    -       Mar     lastSun 0:00s   1:00    D
+Rule   Cuba    1998    max     -       Oct     lastSun 0:00s   0       S
+Rule   Cuba    2000    max     -       Apr     Sun>=1  0:00s   1:00    D
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   America/Havana  -5:29:28 -      LMT     1890
-                       -5:30   -       HMT     1925 Jul 19 12:00 # Havana MT
+                       -5:29:36 -      HMT     1925 Jul 19 12:00 # Havana MT
                        -5:00   Cuba    C%sT
 
 # Dominica
@@ -1162,6 +1567,25 @@ Zone America/Dominica    -4:05:36 -      LMT     1911 Jul 1 0:01         # Roseau
                        -4:00   -       AST
 
 # Dominican Republic
+
+# From Steffen Thorsen (2000-10-30):
+# Enrique Morales reported to me that the Dominican Republic has changed the
+# time zone to Eastern Standard Time as of Sunday 29 at 2 am....
+# http://www.listin.com.do/antes/261000/republica/princi.html
+
+# From Paul Eggert (2000-12-04):
+# That URL (2000-10-26, in Spanish) says they planned to use US-style DST.
+
+# From Rives McDow (2000-12-01):
+# Dominican Republic changed its mind and presidential decree on Tuesday,
+# November 28, 2000, with a new decree.  On Sunday, December 3 at 1:00 AM the
+# Dominican Republic will be reverting to 8 hours from the International Date
+# Line, and will not be using DST in the foreseeable future.  The reason they
+# decided to use DST was to be in synch with Puerto Rico, who was also going
+# to implement DST.  When Puerto Rico didn't implement DST, the president
+# decided to revert.
+
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   DR      1966    only    -       Oct     30      0:00    1:00    D
 Rule   DR      1967    only    -       Feb     28      0:00    0       S
@@ -1173,6 +1597,8 @@ Rule      DR      1972    1974    -       Jan     21      0:00    0       S
 Zone America/Santo_Domingo -4:39:36 -  LMT     1890
                        -4:40   -       SDMT    1933 Apr  1 12:00 # S. Dom. MT
                        -5:00   DR      E%sT    1974 Oct 27
+                       -4:00   -       AST     2000 Oct 29 02:00
+                       -5:00   US      E%sT    2000 Dec  3 01:00
                        -4:00   -       AST
 
 # El Salvador
@@ -1211,9 +1637,9 @@ Zone America/Guatemala    -6:02:04 -      LMT     1918 Oct 5
 Rule   Haiti   1983    only    -       May     8       0:00    1:00    D
 Rule   Haiti   1984    1987    -       Apr     lastSun 0:00    1:00    D
 Rule   Haiti   1983    1987    -       Oct     lastSun 0:00    0       S
-# Shanks says AT is 2:00, but IATA SSIM (1991/1996) says 1:00s.  Go with IATA.
-Rule   Haiti   1988    max     -       Apr     Sun>=1  1:00s   1:00    D
-Rule   Haiti   1988    max     -       Oct     lastSun 1:00s   0       S
+# Shanks says AT is 2:00, but IATA SSIM (1991/1997) says 1:00s.  Go with IATA.
+Rule   Haiti   1988    1997    -       Apr     Sun>=1  1:00s   1:00    D
+Rule   Haiti   1988    1997    -       Oct     lastSun 1:00s   0       S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Port-au-Prince -4:49:20 - LMT     1890
                        -4:49   -       PPMT    1917 Jan 24 12:00 # P-a-P MT
@@ -1224,6 +1650,8 @@ Zone America/Port-au-Prince -4:49:20 -    LMT     1890
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Tegucigalpa -5:48:52 -    LMT     1921 Apr
                        -6:00   Salv    C%sT
+#
+# Great Swan I ceded by US to Honduras in 1972
 
 # Jamaica
 
@@ -1233,11 +1661,11 @@ Zone America/Tegucigalpa -5:48:52 -     LMT     1921 Apr
 # From U. S. Naval Observatory (1989-01-19):
 # JAMAICA             5 H  BEHIND UTC
 
-# From Shanks (1991):
+# From Shanks:
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   America/Jamaica -5:07:12 -      LMT     1890            # Kingston
-                       -5:07   -       KMT     1912 Feb    # Kingston Mean Time
-                       -5:00   -       EST     1974 Jan 6 2:00
+                       -5:07:12 -      KMT     1912 Feb    # Kingston Mean Time
+                       -5:00   -       EST     1974 Apr 28 2:00
                        -5:00   US      E%sT    1984
                        -5:00   -       EST
 
@@ -1250,11 +1678,19 @@ Zone America/Martinique -4:04:20 -      LMT     1890            # Fort-de-France
                        -4:00   -       AST
 
 # Montserrat
+# From Paul Eggert (1997-08-31):
+# Recent volcanic eruptions have forced evacuation of Plymouth, the capital.
+# Luckily, Olveston, the current de facto capital, has the same longitude.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone America/Montserrat        -4:08:52 -      LMT     1911 Jul 1 0:01   # Plymouth
+Zone America/Montserrat        -4:08:52 -      LMT     1911 Jul 1 0:01   # Olveston
                        -4:00   -       AST
 
 # Nicaragua
+#
+# From Steffen Thorsen (1998-12-29):
+# Nicaragua seems to be back at -6:00 but I have not been able to find when
+# they changed from -5:00.
+#
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Nic     1979    1980    -       Mar     Sun>=16 0:00    1:00    D
 Rule   Nic     1979    1980    -       Jun     Mon>=23 0:00    0       S
@@ -1266,7 +1702,8 @@ Zone      America/Managua -5:45:08 -      LMT     1890
                        -6:00   -       CST     1973 May
                        -5:00   -       EST     1975 Feb 16
                        -6:00   Nic     C%sT    1993 Jan 1 4:00
-                       -5:00   -       EST
+                       -5:00   -       EST     1998 Dec
+                       -6:00   -       CST
 
 # Panama
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -1303,12 +1740,12 @@ Zone America/Miquelon   -3:44:40 -      LMT     1911 May 15     # St Pierre
 # St Vincent and the Grenadines
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/St_Vincent        -4:04:56 -      LMT     1890            # Kingstown
-                       -4:05   -       KMT     1912       # Kingstown Mean Time
+                       -4:04:56 -      KMT     1912       # Kingstown Mean Time
                        -4:00   -       AST
 
 # Turks and Caicos
-# From Paul Eggert (1996-11-22):
-# Shanks says they use US DST rules, but IATA SSIM (1991/1996)
+# From Paul Eggert (1998-08-06):
+# Shanks says they use US DST rules, but IATA SSIM (1991/1998)
 # says they switch at midnight.  Go with IATA SSIM.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   TC      1979    1986    -       Apr     lastSun 0:00    1:00    D
@@ -1316,7 +1753,7 @@ Rule      TC      1979    max     -       Oct     lastSun 0:00    0       S
 Rule   TC      1987    max     -       Apr     Sun>=1  0:00    1:00    D
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Grand_Turk        -4:44:32 -      LMT     1890
-                       -5:07   -       KMT     1912 Feb    # Kingston Mean Time
+                       -5:07:12 -      KMT     1912 Feb    # Kingston Mean Time
                        -5:00   TC      E%sT
 
 # British Virgin Is
index 2e27ed0d0b0bff24641640e186ab0578372b8e55..96e371d0ba06ae9ddbde5e517c2af4d3d92e0433 100644 (file)
@@ -1,16 +1,17 @@
-#      $OpenBSD: southamerica,v 1.4 1997/01/14 04:36:57 millert Exp $
-# @(#)southamerica     7.16
+# @(#)southamerica     7.40
+
+# $FreeBSD: src/share/zoneinfo/southamerica,v 1.16 2001/04/06 16:46:52 wollman Exp $
 
 # This data is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
 # tz@elsie.nci.nih.gov for general use in the future).
 
-# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# From Paul Eggert <eggert@twinsun.com> (1999-07-07):
 # A good source for time zone historical data outside the U.S. is
-# Thomas G. Shanks, The International Atlas (3rd edition),
-# San Diego: ACS Publications, Inc. (1991).
+# Thomas G. Shanks, The International Atlas (5th edition),
+# San Diego: ACS Publications, Inc. (1999).
 #
-# Gwillim Law <LAW@encmail.encompass.com> writes that a good source
+# Gwillim Law <Gwil_Law@bridge-point.com> writes that a good source
 # for recent time zone data is the International Air Transport
 # Association's Standard Schedules Information Manual (IATA SSIM),
 # published semiannually.  Law sent in several helpful summaries
 # Except where otherwise noted, Shanks is the source for entries through 1990,
 # and IATA SSIM is the source for entries after 1990.
 #
-# The following abbreviations are used in this file.
-# Corrections are welcome!
-#              std     dst
-#              LMT             Local Mean Time
-#      -2:00   FST     FDT     Fernando de Noronha
-#      -3:00   EST     EDT     Eastern Brazil
-#      -4:00   WST     WDT     Western Brazil
-#      -4:00   AST     ADT     Atlantic
-#      -5:00   AST     ADT     Acre
-#
-# See the `africa' file for time zone naming and abbreviation conventions.
 # Earlier editions of these tables used the North American style (e.g. ARST and
 # ARDT for Argentine Standard and Daylight Time), but the following quote
 # suggests that it's better to use European style (e.g. ART and ARST).
 #      in Europe and South America.
 #      -- E O Cutler, _New York Times_ (1937-02-14), quoted in
 #      H L Mencken, _The American Language: Supplement I_ (1960), p 466
-
-
-# From Guy Harris:
-# From Official Airline Guide - Worldwide Edition (1987).  Countries not
-# listed here do not observe DST, according to the OAG.  Time zone names
-# are pure inventions, and none are supplied for countries not observing
-# DST; updates from natives would be appreciated.  The times that DST
-# starts and ends are based on the assumption that they switch a 2AM just
-# as everybody else does.
+#
+# Earlier editions of these tables also used the North American style
+# for time zones in Brazil, but this was incorrect, as Brazilians say
+# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
+# the railroad sector, writes (1999-07-06):
+#      The subject of time zones is currently a matter of discussion/debate in
+#      Brazil.  Let's say that "the Brasilia time" is considered the
+#      "official time" because Brasilia is the capital city.
+#      The other three time zones are called "Brasilia time "minus one" or
+#      "plus one" or "plus two".  As far as I know there is no such
+#      name/designation as "Eastern Time" or "Central Time".
+# So I invented the following (English-language) abbreviations for now.
+# Corrections are welcome!
+#              std     dst
+#      -2:00   FNT     FNST    Fernando de Noronha
+#      -3:00   BRT     BRST    Brasilia
+#      -4:00   AMT     AMST    Amazon
+#      -5:00   ACT     ACST    Acre
 
 ###############################################################################
 
@@ -83,12 +82,12 @@ Rule        Arg     1963    only    -       Dec     15      0:00    1:00    S
 Rule   Arg     1964    1966    -       Mar      1      0:00    0       -
 Rule   Arg     1964    1966    -       Oct     15      0:00    1:00    S
 Rule   Arg     1967    only    -       Apr      1      0:00    0       -
-Rule   Arg     1967    1968    -       Oct     Sun<=7  0:00    1:00    S
-Rule   Arg     1968    1969    -       Apr     Sun<=7  0:00    0       -
+Rule   Arg     1967    1968    -       Oct     Sun>=1  0:00    1:00    S
+Rule   Arg     1968    1969    -       Apr     Sun>=1  0:00    0       -
 Rule   Arg     1974    only    -       Jan     23      0:00    1:00    S
 Rule   Arg     1974    only    -       May      1      0:00    0       -
-Rule   Arg     1974    1976    -       Oct     Sun<=7  0:00    1:00    S
-Rule   Arg     1975    1977    -       Apr     Sun<=7  0:00    0       -
+Rule   Arg     1974    1976    -       Oct     Sun>=1  0:00    1:00    S
+Rule   Arg     1975    1977    -       Apr     Sun>=1  0:00    0       -
 Rule   Arg     1985    only    -       Nov      2      0:00    1:00    S
 Rule   Arg     1986    only    -       Mar     14      0:00    0       -
 Rule   Arg     1986    1987    -       Oct     25      0:00    1:00    S
@@ -102,7 +101,7 @@ Rule        Arg     1988    only    -       Dec      1      0:00    1:00    S
 # Talleres de Hidrografia Naval Argentina
 # (Argentine Naval Hydrography Institute)
 #
-# Shanks gives 1989 Mar 16 and stops after 1990 Mar 4; go with Otero.
+# Shanks stops after 1992-03-01; go with Otero.
 Rule   Arg     1989    1993    -       Mar     Sun>=1  0:00    0       -
 Rule   Arg     1989    1992    -       Oct     Sun>=15 0:00    1:00    S
 #
@@ -111,23 +110,44 @@ Rule      Arg     1989    1992    -       Oct     Sun>=15 0:00    1:00    S
 # time corrections was derogated and no more modifications
 # to the time zones (for daylight saving) are now made.
 #
+# From Rives McDow (2000-01-10):
+# On October 3, 1999, 0:00 local, Argentina implemented daylight savings time,
+# which did not result in the switch of a time zone, as they stayed 9 hours
+# from the International Date Line.
+Rule   Arg     1999    only    -       Oct     Sun>=1  0:00    1:00    S
+Rule   Arg     2000    only    -       Mar     Sun>=1  0:00    0       -
+#
+# From Peter Gradelski via Steffen Thorsen (2000-03-01):
+# We just checked with our Sao Paulo office and they say the government of
+# Argentina decided not to become one of the countries that go on or off DST.
+# So Buenos Aires should be -3 hours from GMT at all times.
+#
+# From Fabian L. Arce Jofre <farcejofre@bigfoot.com> (2000-04-04):
+# The law that claimed DST for Argentina was derogated by President Fernando
+# de la Rua on March 2, 2000, because it would make people spend more energy
+# in the winter time, rather than less.  The change took effect on March 3.
+#
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 #
-# Buenos Aires (BA), Distrito Federal (DF), Santa Cruz (SC),
-# Tierra del Fuego (TF) & Antartida e Islas
+# Buenos Aires (BA), Capital Federal (CF), Santa Cruz (SC),
+# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
 Zone America/Buenos_Aires -3:53:48 -   LMT     1894 Nov
                        -4:16:44 -      CMT     1920 May    # Cordoba Mean Time
                        -4:00   -       ART     1930 Dec
-                       -4:00   Arg     AR%sT   1969 Oct 5
-                       -3:00   Arg     AR%sT
+                       -4:00   Arg     AR%sT   1969 Oct  5
+                       -3:00   Arg     AR%sT   1999 Oct  3 0:00
+                       -4:00   Arg     AR%sT   2000 Mar  3 0:00
+                       -3:00   -       ART
 #
 # Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN), Chaco (CC),
 # Formosa (FM), La Pampa (LP), Chubut (CH)
 Zone America/Rosario   -4:02:40 -      LMT     1894 Nov
                        -4:16:44 -      CMT     1920 May
                        -4:00   -       ART     1930 Dec
-                       -4:00   Arg     AR%sT   1969 Oct 5
+                       -4:00   Arg     AR%sT   1969 Oct  5
                        -3:00   Arg     AR%sT   1991 Jul
+                       -3:00   -       ART     1999 Oct  3 0:00
+                       -4:00   Arg     AR%sT   2000 Mar  3 0:00
                        -3:00   -       ART
 #
 # Cordoba (CB), Santiago del Estero (SE), Salta (SA), Tucuman (TM), La Rioja (LR), San Juan (SJ), San Luis (SL),
@@ -135,8 +155,10 @@ Zone America/Rosario       -4:02:40 -      LMT     1894 Nov
 Zone America/Cordoba   -4:16:44 -      LMT     1894 Nov
                        -4:16:44 -      CMT     1920 May
                        -4:00   -       ART     1930 Dec
-                       -4:00   Arg     AR%sT   1969 Oct 5
+                       -4:00   Arg     AR%sT   1969 Oct  5
                        -3:00   Arg     AR%sT   1990 Jul
+                       -3:00   -       ART     1999 Oct  3 0:00
+                       -4:00   Arg     AR%sT   2000 Mar  3 0:00
                        -3:00   -       ART
 #
 # Jujuy (JY)
@@ -148,16 +170,20 @@ Zone America/Jujuy        -4:21:12 -      LMT     1894 Nov
                        -4:00   -       WART    1991 Oct  6
                        -4:00   1:00    WARST   1992 Mar 15
                        -4:00   -       WART    1992 Oct 18
+                       -3:00   -       ART     1999 Oct  3 0:00
+                       -4:00   Arg     AR%sT   2000 Mar  3 0:00
                        -3:00   -       ART
 #
 # Catamarca (CT)
 Zone America/Catamarca -4:23:08 -      LMT     1894 Nov
                        -4:16:44 -      CMT     1920 May
                        -4:00   -       ART     1930 Dec
-                       -4:00   Arg     AR%sT   1969 Oct 5
+                       -4:00   Arg     AR%sT   1969 Oct  5
                        -3:00   Arg     AR%sT   1990 Jul
                        -3:00   -       ART     1991 Jul
                        -3:00   Arg     AR%sT   1992 Jul
+                       -3:00   -       ART     1999 Oct  3 0:00
+                       -4:00   Arg     AR%sT   2000 Mar  3 0:00
                        -3:00   -       ART
 #
 # Mendoza (MZ)
@@ -169,6 +195,8 @@ Zone America/Mendoza        -4:35:16 -      LMT     1894 Nov
                        -4:00   -       WART    1991 Oct 15
                        -4:00   1:00    WARST   1992 Mar  1
                        -4:00   -       WART    1992 Oct 18
+                       -3:00   -       ART     1999 Oct  3 0:00
+                       -4:00   Arg     AR%sT   2000 Mar  3 0:00
                        -3:00   -       ART
 
 # Aruba
@@ -186,14 +214,6 @@ Zone       America/La_Paz  -4:32:36 -      LMT     1890
 
 # Brazil
 
-# From Guy Harris:
-# The OAG lists 1987-10-25 and 1988-02-12 as the starting and
-# ending dates, giving them as "estimated date(s) based on previous year".  We
-# infer a rule here from one example, always a dangerous practice....  Yes,
-# they really do switch on Saturday, according to the OAG.
-# "[America/Porto_Acre]" is for the Territory of Acre;
-# "[America/Noronha]" is for Fernando De Noronha.
-
 # From Paul Eggert <eggert@twinsun.com> (1993-11-18):
 # The mayor of Rio recently attempted to change the time zone rules
 # just in his city, in order to leave more summer time for the tourist trade.
@@ -227,98 +247,238 @@ Zone     America/La_Paz  -4:32:36 -      LMT     1890
 # Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
 # Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
 
-# From Paul Eggert (1996-11-22):
-# Let's make the following assumptions:
+# From Marcos Tadeu (1998-09-27):
+# <a href="http://pcdsh01.on.br/verao1.html">
+# Brazilian official page
+# </a>
+
+# From Jesper Norgaard (2000-11-03):
+# [For an official list of which regions in Brazil use which time zones, see:]
+# http://pcdsh01.on.br/Fusbr.htm
+# http://pcdsh01.on.br/Fusbrhv.htm
+
+# From Paul Eggert (2000-10-02):
+# The official decrees referenced below are taken from
+# <a href="http://pcdsh01.on.br/DecHV.html">
+# Decretos sobre o Horario de Verao no Brasil
+# </a> (1999-10-04, in Portuguese).
+# The official site for all decrees, including those not related to time, is
+# <a href="http://www.presidencia.gov.br/CCIVIL/decreto/principal_ano.htm">
+# Presidencia da Republica, Subchefia para Assuntos Juridicos, Decretos
+# </a> (in Portuguese).
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# Decree <a href="http://pcdsh01.on.br/HV20466.htm">20,466</a> (1931-10-01)
+# Decree <a href="http://pcdsh01.on.br/HV21896.htm">21,896</a> (1932-01-10)
+Rule   Brazil  1931    only    -       Oct      3      11:00   1:00    S
+Rule   Brazil  1932    1933    -       Apr      1       0:00   0       -
+Rule   Brazil  1932    only    -       Oct      3       0:00   1:00    S
+# Decree <a href="http://pcdsh01.on.br/HV23195.htm">23,195</a> (1933-10-10)
+# revoked DST.
+# Decree <a href="http://pcdsh01.on.br/HV27496.htm">27,496</a> (1949-11-24)
+# Decree <a href="http://pcdsh01.on.br/HV27998.htm">27,998</a> (1950-04-13)
+Rule   Brazil  1949    1952    -       Dec      1       0:00   1:00    S
+Rule   Brazil  1950    only    -       Apr     16       1:00   0       -
+Rule   Brazil  1951    1952    -       Apr      1       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV32308.htm">32,308</a> (1953-02-24)
+Rule   Brazil  1953    only    -       Mar      1       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV34724.htm">34,724</a> (1953-11-30)
+# revoked DST.
+# Decree <a href="http://pcdsh01.on.br/HV52700.htm">52,700</a> (1963-10-18)
+# established DST from 1963-10-23 00:00 to 1964-02-29 00:00
+# in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
+# Decree <a href="http://pcdsh01.on.br/HV53071.htm">53,071</a> (1963-12-03)
+# extended the above decree to all of the national territory on 12-09.
+Rule   Brazil  1963    only    -       Dec      9       0:00   1:00    S
+# Decree <a href="http://pcdsh01.on.br/HV53604.htm">53,604</a> (1964-02-25)
+# extended summer time by one day to 1964-03-01 00:00 (start of school).
+Rule   Brazil  1964    only    -       Mar      1       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV55639.htm">55,639</a> (1965-01-27)
+Rule   Brazil  1965    only    -       Jan     31       0:00   1:00    S
+Rule   Brazil  1965    only    -       Mar     31       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV57303.htm">57,303</a> (1965-11-22)
+Rule   Brazil  1965    only    -       Dec      1       0:00   1:00    S
+# Decree <a href="http://pcdsh01.on.br/HV57843.htm">57,843</a> (1966-02-18)
+Rule   Brazil  1966    1968    -       Mar      1       0:00   0       -
+Rule   Brazil  1966    1967    -       Nov      1       0:00   1:00    S
+# Decree <a href="http://pcdsh01.on.br/HV63429.htm">63,429</a> (1968-10-15)
+# revoked DST.
+# Decree <a href="http://pcdsh01.on.br/HV91698.htm">91,698</a> (1985-09-27)
+Rule   Brazil  1985    only    -       Nov      2       0:00   1:00    S
+# Decree 92,310 (1986-01-21)
+# Decree 92,463 (1986-03-13)
+Rule   Brazil  1986    only    -       Mar     15       0:00   0       -
+# Decree 93,316 (1986-10-01)
+Rule   Brazil  1986    only    -       Oct     25       0:00   1:00    S
+Rule   Brazil  1987    only    -       Feb     14       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV94922.htm">94,922</a> (1987-09-22)
+Rule   Brazil  1987    only    -       Oct     25       0:00   1:00    S
+Rule   Brazil  1988    only    -       Feb      7       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV96676.htm">96,676</a> (1988-09-12)
+# except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
+Rule   Brazil  1988    only    -       Oct     16       0:00   1:00    S
+Rule   Brazil  1989    only    -       Jan     29       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV98077.htm">98,077</a> (1989-08-21)
+# with the same exceptions
+Rule   Brazil  1989    only    -       Oct     15       0:00   1:00    S
+Rule   Brazil  1990    only    -       Feb     11       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV99530.htm">99,530</a> (1990-09-17)
+# adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
+# Decree 99,629 (1990-10-19) adds BA, MT.
+Rule   Brazil  1990    only    -       Oct     21       0:00   1:00    S
+Rule   Brazil  1991    only    -       Feb     17       0:00   0       -
+# <a href="http://pcdsh01.on.br/HV1991.htm">Unnumbered decree</a> (1991-09-25)
+# adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
+Rule   Brazil  1991    only    -       Oct     20       0:00   1:00    S
+Rule   Brazil  1992    only    -       Feb      9       0:00   0       -
+# <a href="http://pcdsh01.on.br/HV1992.htm">Unnumbered decree</a> (1992-10-16)
+# adopted by same states.
+Rule   Brazil  1992    only    -       Oct     25       0:00   1:00    S
+Rule   Brazil  1993    only    -       Jan     31       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV942.htm">942</a> (1993-09-28)
+# adopted by same states, plus AM.
+# Decree <a href="http://pcdsh01.on.br/HV1252.htm">1,252</a> (1994-09-22)
+# adopted by same states, minus AM.
+# Decree <a href="http://pcdsh01.on.br/HV1636.htm">1,636</a> (1995-09-14)
+# adopted by same states, plus TO.
+# Decree <a href="http://pcdsh01.on.br/HV1674.htm">1,674</a> (1995-10-13)
+# adds AL, SE.
+Rule   Brazil  1993    1995    -       Oct     Sun>=11  0:00   1:00    S
+Rule   Brazil  1994    1995    -       Feb     Sun>=15  0:00   0       -
+Rule   Brazil  1996    only    -       Feb     11       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/HV2000.htm">2,000</a> (1996-09-04)
+# adopted by same states, minus AL, SE.
+Rule   Brazil  1996    only    -       Oct      6       0:00   1:00    S
+Rule   Brazil  1997    only    -       Feb     16       0:00   0       -
+# From Daniel C. Sobral <dcs@gns.com.br> (1998-02-12):
+# In 1997, the DS began on October 6. The stated reason was that
+# because international television networks ignored Brazil's policy on DS,
+# they bought the wrong times on satellite for coverage of Pope's visit.
+# This year, the ending date of DS was postponed to March 1
+# to help dealing with the shortages of electric power.
 #
-# * All data in Shanks are correct through 1990.  In particular,
-#   Shanks was right when he said Acre stopped observing DST in mid-1988.
-# * Areas where Shanks reports DST up to 1990, but the IATA reports no DST
-#   in 1995, stopped observing DST in mid-1990.
+# From Paul Eggert (1998-02-25):
+# <a href="http://churchnet.ucsm.ac.uk/news/files2/news165.htm">
+# Brazil Prepares for Papal Visit
+# </a>,
+# Church Net UK (1997-10-02).
 #
-# Under these assumptions Brazil needs 7 entries to cover all the distinct
-# time zone histories since 1970:
+# Decree 2,317 (1997-09-04), adopted by same states.
+Rule   Brazil  1997    only    -       Oct      6       0:00   1:00    S
+# Decree <a href="http://pcdsh01.on.br/figuras/HV2495.JPG">2,495</a>
+# (1998-02-10)
+Rule   Brazil  1998    only    -       Mar      1       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/figuras/Hv98.jpg">2,780</a> (1998-09-11)
+# adopted by the same states as before.
+Rule   Brazil  1998    only    -       Oct     11       0:00   1:00    S
+Rule   Brazil  1999    only    -       Feb     21       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/figuras/HV3150.gif">3,150</a>
+# (1999-08-23) adopted by same states.
+# Decree <a href="http://pcdsh01.on.br/DecHV99.gif">3,188</a> (1999-09-30)
+# adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
+Rule   Brazil  1999    only    -       Oct      3       0:00   1:00    S
+Rule   Brazil  2000    only    -       Feb     27       0:00   0       -
+# Decree <a href="http://pcdsh01.on.br/DEC3592.htm">3,592</a> (2000-09-06)
+# adopted by the same states as before.
+# Decree <a href="http://pcdsh01.on.br/Dec3630.jpg">3,630</a> (2000-10-13)
+# repeals DST in PE and RR, effective 2000-10-15 00:00.
+# Decree <a href="http://pcdsh01.on.br/Dec3632.jpg">3,632</a> (2000-10-17)
+# repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
 #
-# Noronha (UTC-2), Fortaleza (UTC-3), and Manaus (UTC-4) stopped observing DST
-#      in mid-1990.
-# Maceio (UTC-3) stopped observing DST in mid-1990, but started again mid-1995.
-# Sao Paulo (UTC-3) and Cuiaba (UTC-4) always observed DST.
-# Porto Acre (UTC-5) stopped observing DST in mid-1988.
+# These give only one year's rules.  After that, the rules are guesses
+# and are quite possibly wrong, but are more likely than no DST at all.
+Rule   Brazil  2000    max     -       Oct     Sun>=8   0:00   1:00    S
+Rule   Brazil  2001    max     -       Feb     Sun>=15  0:00   0       -
 
-# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Brazil  1931    only    -       Oct      3      11:00   1:00    D
-Rule   Brazil  1932    1933    -       Apr      1       0:00   0       S
-Rule   Brazil  1932    only    -       Oct      3       0:00   1:00    D
-Rule   Brazil  1949    1952    -       Dec      1       0:00   1:00    D
-Rule   Brazil  1950    only    -       Apr     16       0:00   0       S
-Rule   Brazil  1951    1953    -       Apr      1       0:00   0       S
-Rule   Brazil  1963    only    -       Dec      9       0:00   1:00    D
-Rule   Brazil  1964    only    -       Mar      1       0:00   0       S
-Rule   Brazil  1965    only    -       Jan     31       0:00   1:00    D
-Rule   Brazil  1965    only    -       Apr      1       0:00   0       S
-Rule   Brazil  1965    only    -       Dec      1       0:00   1:00    D
-Rule   Brazil  1966    1968    -       Mar      1       0:00   0       S
-Rule   Brazil  1966    1967    -       Nov      1       0:00   1:00    D
-Rule   Brazil  1985    only    -       Nov      2       0:00   1:00    D
-Rule   Brazil  1986    only    -       Mar     15       0:00   0       S
-Rule   Brazil  1986    1987    -       Oct     Sat<=28  0:00   1:00    D
-Rule   Brazil  1987    only    -       Feb     14       0:00   0       S
-Rule   Brazil  1988    only    -       Feb      7       0:00   0       S
-Rule   Brazil  1989    only    -       Jan     22       0:00   0       S
-Rule   Brazil  1988    1989    -       Oct     Sun>=10  0:00   1:00    D
-Rule   Brazil  1990    1991    -       Feb     Sun>=11  0:00   0       S
-Rule   Brazil  1990    1992    -       Oct     Sun>=20  0:00   1:00    D
-Rule   Brazil  1992    only    -       Feb      9       0:00   0       S
-Rule   Brazil  1993    max     -       Oct     Sun>=11  0:00   1:00    D
-Rule   Brazil  1993    only    -       Jan     31       0:00   0       S
-Rule   Brazil  1994    1995    -       Feb     Sun>=15  0:00   0       S
-Rule   Brazil  1996    max     -       Feb     Sun>=11  0:00   0       S
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 #
-# Fernando de Noronha
+# Atlantic islands: Fernando de Noronha, Trindade, Martin Vaz,
+# Atol das Rocas, and Penedos de Sao Pedro e Sao Paulo
 Zone America/Noronha   -2:09:40 -      LMT     1914
-                       -2:00   -       FST     1963 Dec 9
-                       -2:00   Brazil  F%sT    1990 Jul
-                       -2:00   -       FST
+                       -2:00   Brazil  FN%sT   1990 Sep 17
+                       -2:00   -       FNT
 #
-# Amapa, east Para, Maranhao, Piaui, Ceara, Rio Grande do Norte, Paraiba,
-# Pernambuco (except Fernando de Noronha)
+# Amapa (AP), east Para (PA)
+# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
+Zone America/Belem     -3:13:56 -      LMT     1914
+                       -3:00   Brazil  BR%sT   1988 Sep 12
+                       -3:00   -       BRT
+#
+# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
+# Paraiba (PB)
 Zone America/Fortaleza -2:34:00 -      LMT     1914
-                       -3:00   -       EST     1963 Dec 9
-                       -3:00   Brazil  E%sT    1990 Jul
-                       -3:00   -       EST
+                       -3:00   Brazil  BR%sT   1990 Sep 17
+                       -3:00   -       BRT     1999 Sep 30
+                       -3:00   Brazil  BR%sT   2000 Oct 22
+                       -3:00   -       BRT
+#
+# Pernambuco (PE) (except Atlantic islands)
+Zone America/Recife    -2:19:36 -      LMT     1914
+                       -3:00   Brazil  BR%sT   1990 Sep 17
+                       -3:00   -       BRT     1999 Sep 30
+                       -3:00   Brazil  BR%sT   2000 Oct 15
+                       -3:00   -       BRT
 #
-# Alagoas, Sergipe, Tocantins
+# Tocantins (TO)
+Zone America/Araguaina -3:12:48 -      LMT     1914
+                       -3:00   Brazil  BR%sT   1990 Sep 17
+                       -3:00   -       BRT     1995 Sep 14
+                       -3:00   Brazil  BR%sT
+#
+# Alagoas (AL), Sergipe (SE)
 Zone America/Maceio    -2:22:52 -      LMT     1914
-                       -3:00   -       EST     1963 Dec 9
-                       -3:00   Brazil  E%sT    1990 Jul
-                       -3:00   -       EST     1995 Jul
-                       -3:00   Brazil  E%sT
+                       -3:00   Brazil  BR%sT   1990 Sep 17
+                       -3:00   -       BRT     1995 Oct 13
+                       -3:00   Brazil  BR%sT   1996 Sep  4
+                       -3:00   -       BRT     1999 Sep 30
+                       -3:00   Brazil  BR%sT   2000 Oct 22
+                       -3:00   -       BRT
 #
-# Bahia, Goias, Distrito Federal, Minas Gerais, Espirito Santo, Rio de Janeiro,
-# Sao Paulo, Parana, Santa Catarina, Rio Grande do Sul
+# Bahia (BA), Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
+# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
+# Santa Catarina (SC), Rio Grande do Sul (RS)
 Zone America/Sao_Paulo -3:06:28 -      LMT     1914
-                       -3:00   Brazil  E%sT
+                       -3:00   Brazil  BR%sT   1963 Oct 23 00:00
+                       -3:00   1:00    BRST    1964
+                       -3:00   Brazil  BR%sT
 #
 # Mato Grosso, Mato Grosso do Sul
 Zone America/Cuiaba    -3:44:20 -      LMT     1914
-                       -4:00   -       WST     1963 Dec 9
-                       -4:00   Brazil  W%sT
+                       -4:00   Brazil  AM%sT
+#
+# west Para (PA), Rondonia (RO)
+# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
+Zone America/Porto_Velho -4:15:36 -    LMT     1914
+                       -4:00   Brazil  AM%sT   1988 Sep 12
+                       -4:00   -       AMT
+#
+# Roraima (RR)
+Zone America/Boa_Vista -4:02:40 -      LMT     1914
+                       -4:00   Brazil  AM%sT   1988 Sep 12
+                       -4:00   -       AMT     1999 Sep 30
+                       -4:00   Brazil  AM%sT   2000 Oct 15
+                       -4:00   -       AMT
 #
-# Roraima, west Para, Amazonas, Rondonia
+# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
 Zone America/Manaus    -4:00:04 -      LMT     1914
-                       -4:00   -       WST     1963 Dec 9
-                       -4:00   Brazil  W%sT    1990 Jul
-                       -4:00   -       WST
+                       -4:00   Brazil  AM%sT   1988 Sep 12
+                       -4:00   -       AMT     1993 Sep 28
+                       -4:00   Brazil  AM%sT   1994 Sep 22
+                       -4:00   -       AMT
 #
-# Acre
-# Rio_Branco is too ambiguous, since there's a Rio Branco in Uruguay too.
-Zone America/Porto_Acre        -4:31:12 -      LMT     1914
-                       -5:00   -       AST     1963 Dec 9
-                       -5:00   Brazil  A%sT    1988 Jul
-                       -5:00   -       AST
+# west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
+#      Eirunepe, Envira, Ipixuna
+Zone America/Eirunepe  -4:39:28 -      LMT     1914
+                       -5:00   Brazil  AC%sT   1988 Sep 12
+                       -5:00   -       ACT     1993 Sep 28
+                       -5:00   Brazil  AC%sT   1994 Sep 22
+                       -5:00   -       ACT
 #
-# Martin Vaz and Trinidade are like America/Noronha.
+# Acre (AC)
+Zone America/Rio_Branco        -4:31:12 -      LMT     1914
+                       -5:00   Brazil  AC%sT   1988 Sep 12
+                       -5:00   -       ACT
 
 
 # Chile
@@ -326,16 +486,40 @@ Zone America/Porto_Acre   -4:31:12 -      LMT     1914
 # From Eduardo Krell (1995-10-19):
 # The law says to switch to DST at midnight [24:00] on the second SATURDAY
 # of October....  The law is the same for March and October.
+# (1998-09-29):
+# Because of the drought this year, the government decided to go into
+# DST earlier (saturday 9/26 at 24:00). This is a one-time change only ...
+# (unless there's another dry season next year, I guess).
+
+# From Julio I. Pacheco Troncoso (1999-03-18):
+# Because of the same drought, the government decided to end DST later,
+# on April 3, (one-time change).
+
+# From Gwillim Law (2001-02-20):
+# I came across a Chilean on-line newspaper, La Tercera.  Its
+# <a href="http://www.tercera.cl/diario/1998/03/13/extras.html">
+# 1998-03-13 issue
+# </a>, says (my translation):
+# "At 24:00 (midnight) tomorrow (Saturday) - 22:00 in the insular
+# territory [Easter Island, Juan Fernandez, etc.] - winter time will
+# begin in the entire country."
+
+# From Paul Eggert (2001-02-21):
+# Assume this rule has been used since DST was introduced in the islands.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Chile   1918    only    -       Sep     1       0:00    1:00    S
-Rule   Chile   1919    only    -       Jul     2       0:00    0       -
-Rule   Chile   1927    1931    -       Sep     1       0:00    1:00    S
-Rule   Chile   1928    1932    -       Apr     1       0:00    0       -
-Rule   Chile   1969    max     -       Oct     Sun>=9  0:00    1:00    S
-Rule   Chile   1970    max     -       Mar     Sun>=9  0:00    0       -
+Rule   Chile   1918    only    -       Sep      1      0:00    1:00    S
+Rule   Chile   1919    only    -       Jul      2      0:00    0       -
+Rule   Chile   1927    1931    -       Sep      1      0:00    1:00    S
+Rule   Chile   1928    1932    -       Apr      1      0:00    0       -
+Rule   Chile   1969    1997    -       Oct     Sun>=9  4:00u   1:00    S
+Rule   Chile   1970    1998    -       Mar     Sun>=9  3:00u   0       -
+Rule   Chile   1998    only    -       Sep     27      4:00u   1:00    S
+Rule   Chile   1999    only    -       Apr      4      3:00u   0       -
+Rule   Chile   1999    max     -       Oct     Sun>=9  4:00u   1:00    S
+Rule   Chile   2000    max     -       Mar     Sun>=9  3:00u   0       -
 # IATA SSIM anomalies: (1990-09) says 1990-09-16; (1992-02) says 1992-03-14;
-# (1996-09) says 1998-03-08.  Ignore these for now.
+# (1996-09) says 1998-03-08.  Ignore these.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Santiago  -4:42:40 -      LMT     1890
                        -4:42:40 -      SMT     1910        # Santiago Mean Time
@@ -352,6 +536,8 @@ Zone Pacific/Easter -7:17:28 -      LMT     1890        # Mataveri
 
 
 # Colombia
+# Shanks specifies 24:00 for 1992 transition times; go with IATA,
+# as it seems implausible to change clocks at midnight New Year's Eve.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   CO      1992    only    -       May      2      0:00    1:00    S
 Rule   CO      1992    only    -       Dec     31      0:00    0       -
@@ -363,6 +549,10 @@ Zone       America/Bogota  -4:56:20 -      LMT     1884 Mar 13
 # no information; probably like America/Bogota
 
 # Curacao
+# Shanks says that Bottom and Oranjestad have been at -4:00 since
+# standard time was introduced on 1912-03-02; and that Kralendijk and Rincon
+# used Kralendijk Mean Time (-4:33:08) from 1912-02-02 to 1965-01-01.
+# This all predates our 1970 cutoff, though.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   America/Curacao -4:35:44 -      LMT     1912 Feb 12     # Willemstad
                        -4:30   -       ANT     1965 # Netherlands Antilles Time
@@ -378,6 +568,56 @@ Zone Pacific/Galapagos     -5:58:24 -      LMT     1931 # Puerto Baquerizo Moreno
                        -6:00   -       GALT         # Galapagos Time
 
 # Falklands
+
+# From Paul Eggert (2001-03-05):
+# Between 1990 and 2000 inclusive, Shanks and the IATA agree except
+# the IATA gives 1996-09-08.  Go with Shanks.
+
+# From Falkland Islands Government Office, London (2001-01-22)
+# via Jesper Norgaard:
+# ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
+# April 2001 and advance one hour to summer time at 2 am on Sunday 2
+# September.  It is anticipated that the clocks will revert back at 2
+# am on Sunday 21 April 2002 and advance to summer time at 2 am on
+# Sunday 1 September.
+
+# From Rives McDow (2001-02-13):
+#
+# I have communicated several times with people there, and the last
+# time I had communications that was helpful was in 1998.  Here is
+# what was said then:
+#
+# "The general rule was that Stanley used daylight saving and the Camp
+# did not. However for various reasons many people in the Camp have
+# started to use daylight saving (known locally as 'Stanley Time')
+# There is no rule as to who uses daylight saving - it is a matter of
+# personal choice and so it is impossible to draw a map showing who
+# uses it and who does not. Any list would be out of date as soon as
+# it was produced. This year daylight saving ended on April 18/19th
+# and started again on September 12/13th.  I do not know what the rule
+# is, but can find out if you like.  We do not change at the same time
+# as UK or Chile."
+#
+# I did have in my notes that the rule was "Second Saturday in Sep at
+# 0:00 until third Saturday in Apr at 0:00".  I think that this does
+# not agree in some cases with Shanks; is this true?
+#
+# Also, there is no mention in the list that some areas in the
+# Falklands do not use DST.  I have found in my communications there
+# that these areas are on the western half of East Falkland and all of
+# West Falkland.  Stanley is the only place that consistently observes
+# DST.  Again, as in other places in the world, the farmers don't like
+# it.  West Falkland is almost entirely sheep farmers.
+#
+# I know one lady there that keeps a list of which farm keeps DST and
+# which doesn't each year.  She runs a shop in Stanley, and says that
+# the list changes each year.  She uses it to communicate to her
+# customers, catching them when they are home for lunch or dinner.
+
+# From Paul Eggert (2001-03-05):
+# For now, we'll just record the time in Stanley, since we have no
+# better info.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Falk    1937    1938    -       Sep     lastSun 0:00    1:00    S
 Rule   Falk    1938    1942    -       Mar     Sun>=19 0:00    0       -
@@ -387,9 +627,10 @@ Rule       Falk    1943    only    -       Jan     1       0:00    0       -
 Rule   Falk    1983    only    -       Sep     lastSun 0:00    1:00    S
 Rule   Falk    1984    1985    -       Apr     lastSun 0:00    0       -
 Rule   Falk    1984    only    -       Sep     16      0:00    1:00    S
-Rule   Falk    1985    1995    -       Sep     Sun>=9  0:00    1:00    S
-Rule   Falk    1986    max     -       Apr     Sun>=16 0:00    0       -
-Rule   Falk    1996    max     -       Sep     Sun>=8  0:00    1:00    S
+Rule   Falk    1985    2000    -       Sep     Sun>=9  0:00    1:00    S
+Rule   Falk    1986    2000    -       Apr     Sun>=16 0:00    0       -
+Rule   Falk    2001    max     -       Apr     Sun>=15 2:00    0       -
+Rule   Falk    2001    max     -       Sep     Sun>=1  2:00    1:00    S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Atlantic/Stanley  -3:51:24 -      LMT     1890
                        -3:51:24 -      SMT     1912 Mar 12  # Stanley Mean Time
@@ -413,31 +654,49 @@ Zone      America/Guyana  -3:52:40 -      LMT     1915 Mar        # Georgetown
                        -4:00   -       GYT
 
 # Paraguay
-
-# From Bob Devine (1988-01-28):
-# Paraguay: First day in October to last in March.  Midnight switch??
-# Since 1980.
-
-# From U. S. Naval Observatory (1989-01-19):
-# PARAGUAY            4 H  BEHIND UTC
-# PARAGUAY            3 H  BEHIND UTC    OCT 1, '88-MAR 31, '89
-
-# From Shanks (1991):
+# From Paul Eggert (1999-10-29):
+# Shanks (1999) says that spring transitions are from 01:00 -> 02:00,
+# and autumn transitions are from 00:00 -> 23:00.  Go with earlier
+# editions of Shanks, and with the IATA, who say transitions occur at 00:00.
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   Para    1975    1978    -       Oct      1      0:00    1:00    S
+Rule   Para    1975    1988    -       Oct      1      0:00    1:00    S
 Rule   Para    1975    1978    -       Mar      1      0:00    0       -
-# Shanks says 1979 was all DST.
-Rule   Para    1980    1991    -       Apr      1      0:00    0       -
-Rule   Para    1980    1988    -       Oct      1      0:00    1:00    S
+Rule   Para    1979    1991    -       Apr      1      0:00    0       -
 Rule   Para    1989    only    -       Oct     22      0:00    1:00    S
 Rule   Para    1990    only    -       Oct      1      0:00    1:00    S
 Rule   Para    1991    only    -       Oct      6      0:00    1:00    S
 Rule   Para    1992    only    -       Mar      1      0:00    0       -
 Rule   Para    1992    only    -       Oct      5      0:00    1:00    S
 Rule   Para    1993    only    -       Mar     31      0:00    0       -
-Rule   Para    1993    max     -       Oct      1      0:00    1:00    S
+Rule   Para    1993    1995    -       Oct      1      0:00    1:00    S
 Rule   Para    1994    1995    -       Feb     lastSun 0:00    0       -
-Rule   Para    1996    max     -       Mar      1      0:00    0       -
+Rule   Para    1996    only    -       Mar      1      0:00    0       -
+# IATA SSIM (2000-02) says 1999-10-10; ignore this for now.
+# From Steffen Thorsen (2000-10-02):
+# I have three independent reports that Paraguay changed to DST this Sunday
+# (10-01).
+#
+# Translated by Gwillim Law (2001-02-27) from
+# <a href="http://www.diarionoticias.com.py/011000/nacional/naciona1.htm">
+# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
+# </a>:
+# Starting at 0:00 today, the clock will be set forward 60 minutes, in
+# fulfillment of Decree No. 7,273 of the Executive Power....  The time change
+# system has been operating for several years.  Formerly there was a separate
+# decree each year; the new law has the same effect, but permanently.  Every
+# year, the time will change on the first Sunday of October; likewise, the
+# clock will be set back on the first Sunday of March.
+#
+# From Jesper Norgaard (2001-03-06) [an official URL saying similar things]:
+# http://gateway.abc.com.py:8000/pub/pag04.mbr/artic?FHA=2001-03-03-02.24.52.900592
+#
+Rule   Para    1996    max     -       Oct     Sun>=1  0:00    1:00    S
+# IATA SSIM (1997-09) says Mar 1; go with Shanks.
+Rule   Para    1997    only    -       Feb     lastSun 0:00    0       -
+# Shanks says 1999-02-28; IATA SSIM (1999-02) says 1999-02-27, but
+# (1999-09) reports no date; go with above sources and Gerd Knops (2001-02-27).
+Rule   Para    1998    max     -       Mar     Sun>=1  0:00    0       -
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Asuncion  -3:50:40 -      LMT     1890
                        -3:50:40 -      AMT     1931 Oct 10 # Asuncion Mean Time
@@ -455,8 +714,9 @@ Rule        Peru    1987    only    -       Jan      1      0:00    1:00    S
 Rule   Peru    1987    only    -       Apr      1      0:00    0       -
 Rule   Peru    1990    only    -       Jan      1      0:00    1:00    S
 Rule   Peru    1990    only    -       Apr      1      0:00    0       -
-Rule   Peru    1993    only    -       Jan      1      0:00    1:00    S
-Rule   Peru    1993    only    -       Apr      1      0:00    0       -
+# IATA is ambiguous for 1993/1995; go with Shanks.
+Rule   Peru    1994    only    -       Jan      1      0:00    1:00    S
+Rule   Peru    1994    only    -       Apr      1      0:00    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   America/Lima    -5:08:12 -      LMT     1890
                        -5:09   -       LMT     1908 Jul 28 # Lima Mean Time
@@ -468,7 +728,7 @@ Zone Atlantic/South_Georgia -2:26:08 -      LMT     1890            # Grytviken
                        -2:00   -       GST     # South Georgia Time
 
 # South Sandwich Is
-# uninhabited
+# uninhabited; scientific personnel have wintered
 
 # Suriname
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -487,7 +747,7 @@ Zone America/Port_of_Spain -4:06:04 -       LMT     1912 Mar 2
 # Uruguay
 # From Paul Eggert <eggert@twinsun.com> (1993-11-18):
 # Uruguay wins the prize for the strangest peacetime manipulation of the rules.
-# From Shanks (1991):
+# From Shanks:
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 # Whitman gives 1923 Oct 1; go with Shanks.
 Rule   Uruguay 1923    only    -       Oct      2       0:00   0:30    HS
@@ -529,9 +789,11 @@ Rule       Uruguay 1988    only    -       Mar     14       0:00   0       -
 Rule   Uruguay 1988    only    -       Dec     11       0:00   1:00    S
 Rule   Uruguay 1989    only    -       Mar     12       0:00   0       -
 Rule   Uruguay 1989    only    -       Oct     29       0:00   1:00    S
+# Shanks says no DST was observed in 1990/1 and 1991/2,
+# and that 1992/3's DST was from 10-25 to 03-01.  Go with IATA.
 Rule   Uruguay 1990    1992    -       Mar     Sun>=1   0:00   0       -
 Rule   Uruguay 1990    1991    -       Oct     Sun>=21  0:00   1:00    S
-Rule   Uruguay 1992    1993    -       Oct     Sun>=15  0:00   1:00    S
+Rule   Uruguay 1992    only    -       Oct     18       0:00   1:00    S
 Rule   Uruguay 1993    only    -       Feb     28       0:00   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone America/Montevideo        -3:44:44 -      LMT     1898 Jun 28
index 05a939d2fcd97d2c30976a979ea22fc9614451fd..c6a6b6404bdaee7a7cece449ad29a268460d9bec 100644 (file)
@@ -1,36 +1,50 @@
-#      $OpenBSD: systemv,v 1.2 1997/01/14 04:36:58 millert Exp $
-# @(#)systemv  7.2
+# @(#)systemv  7.3
 
 # Old rules, should the need arise.
 # No attempt is made to handle Newfoundland, since it cannot be expressed
 # using the System V "TZ" scheme (half-hour offset), or anything outside
 # North America (no support for non-standard DST start/end dates), nor
-# the change in the DST rules in the US in 1987 (can't split between
-# Canada, with no changes, and the US)
+# the change in the DST rules in the US in 1987 (which occurred before
+# the old rules were written).
 #
-# Be sure to compile this *without* leap second correction for true conformance.
+# If you need the old rules, uncomment ## lines and comment-out Link lines.
+# Compile this *without* leap second correction for true conformance.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-Rule   SystemV min     1973    -       Apr     lastSun 2:00    1:00    D
-Rule   SystemV min     1973    -       Oct     lastSun 2:00    0       S
-Rule   SystemV 1974    only    -       Jan     6       2:00    1:00    D
-Rule   SystemV 1974    only    -       Nov     lastSun 2:00    0       S
-Rule   SystemV 1975    only    -       Feb     23      2:00    1:00    D
-Rule   SystemV 1975    only    -       Oct     lastSun 2:00    0       S
-Rule   SystemV 1976    max     -       Apr     lastSun 2:00    1:00    D
-Rule   SystemV 1976    max     -       Oct     lastSun 2:00    0       S
+## Rule        SystemV min     1973    -       Apr     lastSun 2:00    1:00    D
+## Rule        SystemV min     1973    -       Oct     lastSun 2:00    0       S
+## Rule        SystemV 1974    only    -       Jan     6       2:00    1:00    D
+## Rule        SystemV 1974    only    -       Nov     lastSun 2:00    0       S
+## Rule        SystemV 1975    only    -       Feb     23      2:00    1:00    D
+## Rule        SystemV 1975    only    -       Oct     lastSun 2:00    0       S
+## Rule        SystemV 1976    max     -       Apr     lastSun 2:00    1:00    D
+## Rule        SystemV 1976    max     -       Oct     lastSun 2:00    0       S
 
 # Zone NAME            GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
-Zone   SystemV/AST4ADT -4:00   SystemV         A%sT
-Zone   SystemV/EST5EDT -5:00   SystemV         E%sT
-Zone   SystemV/CST6CDT -6:00   SystemV         C%sT
-Zone   SystemV/MST7MDT -7:00   SystemV         M%sT
-Zone   SystemV/PST8PDT -8:00   SystemV         P%sT
-Zone   SystemV/YST9YDT -9:00   SystemV         Y%sT
-Zone   SystemV/AST4    -4:00   -               AST
-Zone   SystemV/EST5    -5:00   -               EST
-Zone   SystemV/CST6    -6:00   -               CST
-Zone   SystemV/MST7    -7:00   -               MST
-Zone   SystemV/PST8    -8:00   -               PST
-Zone   SystemV/YST9    -9:00   -               YST
-Zone   SystemV/HST10   -10:00  -               HST
+## Zone        SystemV/AST4ADT -4:00   SystemV         A%sT
+## Zone        SystemV/EST5EDT -5:00   SystemV         E%sT
+## Zone        SystemV/CST6CDT -6:00   SystemV         C%sT
+## Zone        SystemV/MST7MDT -7:00   SystemV         M%sT
+## Zone        SystemV/PST8PDT -8:00   SystemV         P%sT
+## Zone        SystemV/YST9YDT -9:00   SystemV         Y%sT
+## Zone        SystemV/AST4    -4:00   -               AST
+## Zone        SystemV/EST5    -5:00   -               EST
+## Zone        SystemV/CST6    -6:00   -               CST
+## Zone        SystemV/MST7    -7:00   -               MST
+## Zone        SystemV/PST8    -8:00   -               PST
+## Zone        SystemV/YST9    -9:00   -               YST
+## Zone        SystemV/HST10   -10:00  -               HST
+# For now...
+Link   America/Halifax         SystemV/AST4ADT
+Link   America/New_York        SystemV/EST5EDT
+Link   America/Chicago         SystemV/CST6CDT
+Link   America/Denver          SystemV/MST7MDT
+Link   America/Los_Angeles     SystemV/PST8PDT
+Link   America/Anchorage       SystemV/YST9YDT
+Link   America/Puerto_Rico     SystemV/AST4
+Link   America/Indianapolis    SystemV/EST5
+Link   America/Regina          SystemV/CST6
+Link   America/Phoenix         SystemV/MST7
+Link   Pacific/Pitcairn        SystemV/PST8
+Link   Pacific/Gambier         SystemV/YST9
+Link   Pacific/Honolulu        SystemV/HST10