]> git.saurik.com Git - apple/system_cmds.git/commitdiff
system_cmds-175.tar.gz mac-os-x-100 v175
authorApple <opensource@apple.com>
Tue, 10 Apr 2001 12:54:17 +0000 (12:54 +0000)
committerApple <opensource@apple.com>
Tue, 10 Apr 2001 12:54:17 +0000 (12:54 +0000)
891 files changed:
APPLE_LICENSE [new file with mode: 0644]
Makefile [new file with mode: 0644]
Makefile.preamble [new file with mode: 0644]
PB.project [new file with mode: 0644]
README.rtf [new file with mode: 0644]
ac.tproj/Makefile [new file with mode: 0644]
ac.tproj/Makefile.postamble [new file with mode: 0644]
ac.tproj/Makefile.preamble [new file with mode: 0644]
ac.tproj/PB.project [new file with mode: 0644]
ac.tproj/ac.8 [new file with mode: 0644]
ac.tproj/ac.c [new file with mode: 0644]
accton.tproj/Makefile [new file with mode: 0644]
accton.tproj/Makefile.postamble [new file with mode: 0644]
accton.tproj/Makefile.preamble [new file with mode: 0644]
accton.tproj/PB.project [new file with mode: 0644]
accton.tproj/accton.c [new file with mode: 0644]
arch.tproj/Makefile [new file with mode: 0644]
arch.tproj/Makefile.postamble [new file with mode: 0644]
arch.tproj/PB.project [new file with mode: 0644]
arch.tproj/arch.c [new file with mode: 0644]
at.tproj/Makefile [new file with mode: 0644]
at.tproj/Makefile.dist [new file with mode: 0644]
at.tproj/Makefile.postamble [new file with mode: 0644]
at.tproj/Makefile.preamble [new file with mode: 0644]
at.tproj/PB.project [new file with mode: 0644]
at.tproj/at.1 [new file with mode: 0644]
at.tproj/at.c [new file with mode: 0644]
at.tproj/at.h [new file with mode: 0644]
at.tproj/panic.c [new file with mode: 0644]
at.tproj/panic.h [new file with mode: 0644]
at.tproj/parsetime.c [new file with mode: 0644]
at.tproj/parsetime.h [new file with mode: 0644]
at.tproj/pathnames.h [new file with mode: 0644]
at.tproj/perm.c [new file with mode: 0644]
at.tproj/perm.h [new file with mode: 0644]
at.tproj/privs.h [new file with mode: 0644]
atrun.tproj/Makefile [new file with mode: 0644]
atrun.tproj/Makefile.dist [new file with mode: 0644]
atrun.tproj/Makefile.preamble [new file with mode: 0644]
atrun.tproj/PB.project [new file with mode: 0644]
atrun.tproj/atrun.8 [new file with mode: 0644]
atrun.tproj/atrun.c [new file with mode: 0644]
atrun.tproj/atrun.h [new file with mode: 0644]
chkpasswd.tproj/Makefile [new file with mode: 0644]
chkpasswd.tproj/Makefile.postamble [new file with mode: 0644]
chkpasswd.tproj/Makefile.preamble [new file with mode: 0644]
chkpasswd.tproj/PB.project [new file with mode: 0644]
chkpasswd.tproj/file_passwd.c [new file with mode: 0644]
chkpasswd.tproj/netinfo_passwd.c [new file with mode: 0644]
chkpasswd.tproj/nis_passwd.c [new file with mode: 0644]
chkpasswd.tproj/passwd.c [new file with mode: 0644]
chkpasswd.tproj/stringops.c [new file with mode: 0644]
chkpasswd.tproj/stringops.h [new file with mode: 0644]
chpass.tproj/Makefile [new file with mode: 0644]
chpass.tproj/Makefile.dist [new file with mode: 0644]
chpass.tproj/Makefile.postamble [new file with mode: 0644]
chpass.tproj/Makefile.preamble [new file with mode: 0644]
chpass.tproj/PB.project [new file with mode: 0644]
chpass.tproj/chpass.1 [new file with mode: 0644]
chpass.tproj/chpass.c [new file with mode: 0644]
chpass.tproj/chpass.h [new file with mode: 0644]
chpass.tproj/edit.c [new file with mode: 0644]
chpass.tproj/field.c [new file with mode: 0644]
chpass.tproj/pathnames.h [new file with mode: 0644]
chpass.tproj/pw_copy.c [new file with mode: 0644]
chpass.tproj/pw_copy.h [new file with mode: 0644]
chpass.tproj/table.c [new file with mode: 0644]
chpass.tproj/util.c [new file with mode: 0644]
dmesg.tproj/Makefile [new file with mode: 0644]
dmesg.tproj/Makefile.dist [new file with mode: 0644]
dmesg.tproj/Makefile.postamble [new file with mode: 0644]
dmesg.tproj/Makefile.preamble [new file with mode: 0644]
dmesg.tproj/PB.project [new file with mode: 0644]
dmesg.tproj/dmesg.8 [new file with mode: 0644]
dmesg.tproj/dmesg.c [new file with mode: 0644]
dp_notify_lib/Makefile [new file with mode: 0644]
dp_notify_lib/Makefile.postamble [new file with mode: 0644]
dp_notify_lib/Makefile.preamble [new file with mode: 0644]
dp_notify_lib/PB.project [new file with mode: 0644]
dp_notify_lib/backing_store_alerts.defs [new file with mode: 0644]
dp_notify_lib/backing_store_triggers.defs [new file with mode: 0644]
dp_notify_lib/h.template [new file with mode: 0644]
dp_notify_lib/m.template [new file with mode: 0644]
dynamic_pager.tproj/Makefile [new file with mode: 0644]
dynamic_pager.tproj/Makefile.postamble [new file with mode: 0644]
dynamic_pager.tproj/Makefile.preamble [new file with mode: 0644]
dynamic_pager.tproj/PB.project [new file with mode: 0644]
dynamic_pager.tproj/backing_store_alerts.defs [new file with mode: 0644]
dynamic_pager.tproj/backing_store_triggers.defs [new file with mode: 0644]
dynamic_pager.tproj/default_pager_alerts.defs [new file with mode: 0644]
dynamic_pager.tproj/dynamic_pager.c [new file with mode: 0644]
fastboot.tproj/Makefile [new file with mode: 0644]
fastboot.tproj/Makefile.dist [new file with mode: 0644]
fastboot.tproj/Makefile.postamble [new file with mode: 0644]
fastboot.tproj/Makefile.preamble [new file with mode: 0644]
fastboot.tproj/PB.project [new file with mode: 0644]
fastboot.tproj/fastboot.8 [new file with mode: 0644]
fastboot.tproj/fastboot.sh [new file with mode: 0644]
fastboot.tproj/fasthalt.sh [new file with mode: 0644]
fs_usage.tproj/Makefile [new file with mode: 0644]
fs_usage.tproj/Makefile.postamble [new file with mode: 0644]
fs_usage.tproj/Makefile.preamble [new file with mode: 0644]
fs_usage.tproj/PB.project [new file with mode: 0644]
fs_usage.tproj/fs_usage.1 [new file with mode: 0644]
fs_usage.tproj/fs_usage.c [new file with mode: 0644]
getty.tproj/Makefile [new file with mode: 0644]
getty.tproj/Makefile.postamble [new file with mode: 0644]
getty.tproj/Makefile.preamble [new file with mode: 0644]
getty.tproj/PB.project [new file with mode: 0644]
getty.tproj/extern.h [new file with mode: 0644]
getty.tproj/getty.8 [new file with mode: 0644]
getty.tproj/gettytab.5 [new file with mode: 0644]
getty.tproj/gettytab.h [new file with mode: 0644]
getty.tproj/init.c [new file with mode: 0644]
getty.tproj/main.c [new file with mode: 0644]
getty.tproj/pathnames.h [new file with mode: 0644]
getty.tproj/subr.c [new file with mode: 0644]
getty.tproj/ttys.5 [new file with mode: 0644]
halt.tproj/Makefile [new file with mode: 0644]
halt.tproj/Makefile.dist [new file with mode: 0644]
halt.tproj/Makefile.preamble [new file with mode: 0644]
halt.tproj/PB.project [new file with mode: 0644]
halt.tproj/halt.8 [new file with mode: 0644]
halt.tproj/halt.c [new file with mode: 0644]
hostinfo.tproj/Makefile [new file with mode: 0644]
hostinfo.tproj/Makefile.postamble [new file with mode: 0644]
hostinfo.tproj/Makefile.preamble [new file with mode: 0644]
hostinfo.tproj/PB.project [new file with mode: 0644]
hostinfo.tproj/hostinfo.c [new file with mode: 0644]
init.tproj/Makefile [new file with mode: 0644]
init.tproj/Makefile.dist [new file with mode: 0644]
init.tproj/Makefile.postamble [new file with mode: 0644]
init.tproj/Makefile.preamble [new file with mode: 0644]
init.tproj/NOTES [new file with mode: 0644]
init.tproj/PB.project [new file with mode: 0644]
init.tproj/init.8 [new file with mode: 0644]
init.tproj/init.c [new file with mode: 0644]
init.tproj/pathnames.h [new file with mode: 0644]
iostat.tproj/Makefile [new file with mode: 0644]
iostat.tproj/Makefile.postamble [new file with mode: 0644]
iostat.tproj/Makefile.preamble [new file with mode: 0644]
iostat.tproj/PB.project [new file with mode: 0644]
iostat.tproj/iostat.8 [new file with mode: 0644]
iostat.tproj/iostat.c [new file with mode: 0644]
iostat.tproj/names.c [new file with mode: 0644]
kextd.tproj/GetSymbolFromPEF.h [new file with mode: 0644]
kextd.tproj/KEXTD.c [new file with mode: 0644]
kextd.tproj/KEXTD.h [new file with mode: 0644]
kextd.tproj/KEXTD_main.c [new file with mode: 0644]
kextd.tproj/Makefile [new file with mode: 0644]
kextd.tproj/Makefile.preamble [new file with mode: 0644]
kextd.tproj/PB.project [new file with mode: 0644]
kextd.tproj/PEFSupport.c [new file with mode: 0644]
kextd.tproj/PTLock.c [new file with mode: 0644]
kextd.tproj/PTLock.h [new file with mode: 0644]
kextload.tproj/Makefile [new file with mode: 0644]
kextload.tproj/Makefile.postamble [new file with mode: 0644]
kextload.tproj/Makefile.preamble [new file with mode: 0644]
kextload.tproj/PB.project [new file with mode: 0644]
kextload.tproj/kextload.8 [new file with mode: 0644]
kextload.tproj/kextload_main.c [new file with mode: 0644]
kextunload.tproj/Makefile [new file with mode: 0644]
kextunload.tproj/Makefile.postamble [new file with mode: 0644]
kextunload.tproj/Makefile.preamble [new file with mode: 0644]
kextunload.tproj/PB.project [new file with mode: 0644]
kextunload.tproj/kextunload.8 [new file with mode: 0644]
kextunload.tproj/kextunload_main.c [new file with mode: 0644]
kgmon.tproj/Makefile [new file with mode: 0644]
kgmon.tproj/Makefile.postamble [new file with mode: 0644]
kgmon.tproj/Makefile.preamble [new file with mode: 0644]
kgmon.tproj/PB.project [new file with mode: 0644]
kgmon.tproj/kgmon.8 [new file with mode: 0644]
kgmon.tproj/kgmon.c [new file with mode: 0644]
kmodload.tproj/Makefile [new file with mode: 0644]
kmodload.tproj/Makefile.postamble [new file with mode: 0644]
kmodload.tproj/Makefile.preamble [new file with mode: 0644]
kmodload.tproj/PB.project [new file with mode: 0644]
kmodload.tproj/kmodload.8 [new file with mode: 0644]
kmodload.tproj/kmodload.c [new file with mode: 0644]
kmodload.tproj/kmodsyms.8 [new file with mode: 0644]
kmodstat.tproj/Makefile [new file with mode: 0644]
kmodstat.tproj/Makefile.postamble [new file with mode: 0644]
kmodstat.tproj/Makefile.preamble [new file with mode: 0644]
kmodstat.tproj/PB.project [new file with mode: 0644]
kmodstat.tproj/kmodstat.8 [new file with mode: 0644]
kmodstat.tproj/kmodstat.c [new file with mode: 0644]
kmodunload.tproj/Makefile [new file with mode: 0644]
kmodunload.tproj/Makefile.postamble [new file with mode: 0644]
kmodunload.tproj/Makefile.preamble [new file with mode: 0644]
kmodunload.tproj/PB.project [new file with mode: 0644]
kmodunload.tproj/kmodunload.8 [new file with mode: 0644]
kmodunload.tproj/kmodunload.c [new file with mode: 0644]
ktrace.tproj/Makefile [new file with mode: 0644]
ktrace.tproj/Makefile.preamble [new file with mode: 0644]
ktrace.tproj/PB.project [new file with mode: 0644]
ktrace.tproj/ktrace.1 [new file with mode: 0644]
ktrace.tproj/ktrace.c [new file with mode: 0644]
ktrace.tproj/ktrace.h [new file with mode: 0644]
ktrace.tproj/subr.c [new file with mode: 0644]
latency.tproj/Makefile [new file with mode: 0644]
latency.tproj/Makefile.postamble [new file with mode: 0644]
latency.tproj/Makefile.preamble [new file with mode: 0644]
latency.tproj/PB.project [new file with mode: 0644]
latency.tproj/latency.1 [new file with mode: 0644]
latency.tproj/latency.c [new file with mode: 0644]
login.tproj/Makefile [new file with mode: 0644]
login.tproj/Makefile.postamble [new file with mode: 0644]
login.tproj/Makefile.preamble [new file with mode: 0644]
login.tproj/PB.project [new file with mode: 0644]
login.tproj/klogin.c [new file with mode: 0644]
login.tproj/login.1 [new file with mode: 0644]
login.tproj/login.c [new file with mode: 0644]
login.tproj/pathnames.h [new file with mode: 0644]
mach_init.tproj/Makefile [new file with mode: 0644]
mach_init.tproj/Makefile.preamble [new file with mode: 0644]
mach_init.tproj/Notes [new file with mode: 0644]
mach_init.tproj/PB.project [new file with mode: 0644]
mach_init.tproj/bootstrap.c [new file with mode: 0644]
mach_init.tproj/bootstrap.defs [new file with mode: 0644]
mach_init.tproj/bootstrap_internal.h [new file with mode: 0644]
mach_init.tproj/error_log.c [new file with mode: 0644]
mach_init.tproj/error_log.h [new file with mode: 0644]
mach_init.tproj/initConf [new file with mode: 0644]
mach_init.tproj/lists.c [new file with mode: 0644]
mach_init.tproj/lists.h [new file with mode: 0644]
mach_init.tproj/parser.c [new file with mode: 0644]
mach_init.tproj/parser.h [new file with mode: 0644]
mach_init.tproj/rpc_services.c [new file with mode: 0644]
mach_init.tproj/testConfig [new file with mode: 0644]
mach_init.tproj/testConfig2 [new file with mode: 0644]
mach_init.tproj/testServer/Makefile [new file with mode: 0644]
mach_init.tproj/testServer/boot_subset.c [new file with mode: 0644]
mach_init.tproj/testServer/listServer.c [new file with mode: 0644]
mach_init.tproj/testServer/testServer.c [new file with mode: 0644]
makekey.tproj/Makefile [new file with mode: 0644]
makekey.tproj/Makefile.postamble [new file with mode: 0644]
makekey.tproj/Makefile.preamble [new file with mode: 0644]
makekey.tproj/PB.project [new file with mode: 0644]
makekey.tproj/makekey.8 [new file with mode: 0644]
makekey.tproj/makekey.c [new file with mode: 0644]
mkfile.tproj/Makefile [new file with mode: 0644]
mkfile.tproj/Makefile.preamble [new file with mode: 0644]
mkfile.tproj/PB.project [new file with mode: 0644]
mkfile.tproj/mkfile.c [new file with mode: 0644]
nologin.tproj/Makefile [new file with mode: 0644]
nologin.tproj/Makefile.dist [new file with mode: 0644]
nologin.tproj/Makefile.postamble [new file with mode: 0644]
nologin.tproj/Makefile.preamble [new file with mode: 0644]
nologin.tproj/PB.project [new file with mode: 0644]
nologin.tproj/nologin.8 [new file with mode: 0644]
nologin.tproj/nologin.sh [new file with mode: 0644]
nvram.tproj/Makefile [new file with mode: 0644]
nvram.tproj/Makefile.postamble [new file with mode: 0644]
nvram.tproj/Makefile.preamble [new file with mode: 0644]
nvram.tproj/PB.project [new file with mode: 0644]
nvram.tproj/nvram.8 [new file with mode: 0644]
nvram.tproj/nvram.c [new file with mode: 0644]
nvram.tproj/nvram/Alchemy [new file with mode: 0644]
nvram.tproj/nvram/Gossamer [new file with mode: 0644]
nvram.tproj/nvram/Hooper [new file with mode: 0644]
nvram.tproj/nvram/Kanga [new file with mode: 0644]
nvram.tproj/nvram/Mainstreet [new file with mode: 0644]
nvram.tproj/nvram/PowerExpress [new file with mode: 0644]
nvram.tproj/nvram/PowerSurge [new file with mode: 0644]
nvram.tproj/nvram/Silk [new file with mode: 0644]
nvram.tproj/nvram/Wallstreet [new file with mode: 0644]
pagesize.tproj/Makefile [new file with mode: 0644]
pagesize.tproj/Makefile.dist [new file with mode: 0644]
pagesize.tproj/Makefile.postamble [new file with mode: 0644]
pagesize.tproj/Makefile.preamble [new file with mode: 0644]
pagesize.tproj/PB.project [new file with mode: 0644]
pagesize.tproj/pagesize.1 [new file with mode: 0644]
pagesize.tproj/pagesize.sh [new file with mode: 0644]
passwd.tproj/Makefile [new file with mode: 0644]
passwd.tproj/Makefile.postamble [new file with mode: 0644]
passwd.tproj/Makefile.preamble [new file with mode: 0644]
passwd.tproj/PB.project [new file with mode: 0644]
passwd.tproj/file_passwd.c [new file with mode: 0644]
passwd.tproj/netinfo_passwd.c [new file with mode: 0644]
passwd.tproj/nis_passwd.c [new file with mode: 0644]
passwd.tproj/passwd.1 [new file with mode: 0644]
passwd.tproj/passwd.c [new file with mode: 0644]
passwd.tproj/stringops.c [new file with mode: 0644]
passwd.tproj/stringops.h [new file with mode: 0644]
pwd_mkdb.tproj/Makefile [new file with mode: 0644]
pwd_mkdb.tproj/Makefile.postamble [new file with mode: 0644]
pwd_mkdb.tproj/Makefile.preamble [new file with mode: 0644]
pwd_mkdb.tproj/PB.project [new file with mode: 0644]
pwd_mkdb.tproj/pw_scan.c [new file with mode: 0644]
pwd_mkdb.tproj/pw_scan.h [new file with mode: 0644]
pwd_mkdb.tproj/pwd_mkdb.8 [new file with mode: 0644]
pwd_mkdb.tproj/pwd_mkdb.c [new file with mode: 0644]
reboot.tproj/Makefile [new file with mode: 0644]
reboot.tproj/Makefile.dist [new file with mode: 0644]
reboot.tproj/Makefile.postamble [new file with mode: 0644]
reboot.tproj/Makefile.preamble [new file with mode: 0644]
reboot.tproj/PB.project [new file with mode: 0644]
reboot.tproj/boot_hp300.8 [new file with mode: 0644]
reboot.tproj/boot_i386.8 [new file with mode: 0644]
reboot.tproj/boot_sparc.8 [new file with mode: 0644]
reboot.tproj/boot_tahoe.8 [new file with mode: 0644]
reboot.tproj/boot_vax.8 [new file with mode: 0644]
reboot.tproj/reboot.8 [new file with mode: 0644]
reboot.tproj/reboot.c [new file with mode: 0644]
sc_usage.tproj/Makefile [new file with mode: 0644]
sc_usage.tproj/Makefile.postamble [new file with mode: 0644]
sc_usage.tproj/Makefile.preamble [new file with mode: 0644]
sc_usage.tproj/PB.project [new file with mode: 0644]
sc_usage.tproj/sc_usage.1 [new file with mode: 0644]
sc_usage.tproj/sc_usage.c [new file with mode: 0644]
sc_usage.tproj/trace.codes [new file with mode: 0644]
shutdown.tproj/Makefile [new file with mode: 0644]
shutdown.tproj/Makefile.dist [new file with mode: 0644]
shutdown.tproj/Makefile.postamble [new file with mode: 0644]
shutdown.tproj/Makefile.preamble [new file with mode: 0644]
shutdown.tproj/PB.project [new file with mode: 0644]
shutdown.tproj/pathnames.h [new file with mode: 0644]
shutdown.tproj/shutdown.8 [new file with mode: 0644]
shutdown.tproj/shutdown.c [new file with mode: 0644]
sync.tproj/Makefile [new file with mode: 0644]
sync.tproj/Makefile.dist [new file with mode: 0644]
sync.tproj/Makefile.preamble [new file with mode: 0644]
sync.tproj/PB.project [new file with mode: 0644]
sync.tproj/sync.8 [new file with mode: 0644]
sync.tproj/sync.c [new file with mode: 0644]
sysctl.tproj/Makefile [new file with mode: 0644]
sysctl.tproj/Makefile.postamble [new file with mode: 0644]
sysctl.tproj/Makefile.preamble [new file with mode: 0644]
sysctl.tproj/PB.project [new file with mode: 0644]
sysctl.tproj/sysctl.8 [new file with mode: 0644]
sysctl.tproj/sysctl.c [new file with mode: 0644]
top.tproj/Makefile [new file with mode: 0644]
top.tproj/Makefile.postamble [new file with mode: 0644]
top.tproj/Makefile.preamble [new file with mode: 0644]
top.tproj/PB.project [new file with mode: 0644]
top.tproj/top.1 [new file with mode: 0644]
top.tproj/top.c [new file with mode: 0644]
update.tproj/Makefile [new file with mode: 0644]
update.tproj/Makefile.postamble [new file with mode: 0644]
update.tproj/Makefile.preamble [new file with mode: 0644]
update.tproj/PB.project [new file with mode: 0644]
update.tproj/update.8 [new file with mode: 0644]
update.tproj/update.c [new file with mode: 0644]
vipw.tproj/Makefile [new file with mode: 0644]
vipw.tproj/Makefile.postamble [new file with mode: 0644]
vipw.tproj/Makefile.preamble [new file with mode: 0644]
vipw.tproj/PB.project [new file with mode: 0644]
vipw.tproj/pw_util.c [new file with mode: 0644]
vipw.tproj/pw_util.h [new file with mode: 0644]
vipw.tproj/vipw.8 [new file with mode: 0644]
vipw.tproj/vipw.c [new file with mode: 0644]
vm_stat.tproj/Makefile [new file with mode: 0644]
vm_stat.tproj/Makefile.postamble [new file with mode: 0644]
vm_stat.tproj/Makefile.preamble [new file with mode: 0644]
vm_stat.tproj/PB.project [new file with mode: 0644]
vm_stat.tproj/h.template [new file with mode: 0644]
vm_stat.tproj/m.template [new file with mode: 0644]
vm_stat.tproj/vm_stat.c [new file with mode: 0644]
zdump.tproj/Makefile [new file with mode: 0644]
zdump.tproj/Makefile.postamble [new file with mode: 0644]
zdump.tproj/Makefile.preamble [new file with mode: 0644]
zdump.tproj/PB.project [new file with mode: 0644]
zdump.tproj/zdump.8 [new file with mode: 0644]
zdump.tproj/zdump.c [new file with mode: 0644]
zic.tproj/HACK/Africa/Abidjan [new file with mode: 0644]
zic.tproj/HACK/Africa/Accra [new file with mode: 0644]
zic.tproj/HACK/Africa/Addis_Ababa [new file with mode: 0644]
zic.tproj/HACK/Africa/Algiers [new file with mode: 0644]
zic.tproj/HACK/Africa/Asmera [new file with mode: 0644]
zic.tproj/HACK/Africa/Bamako [new file with mode: 0644]
zic.tproj/HACK/Africa/Bangui [new file with mode: 0644]
zic.tproj/HACK/Africa/Banjul [new file with mode: 0644]
zic.tproj/HACK/Africa/Bissau [new file with mode: 0644]
zic.tproj/HACK/Africa/Blantyre [new file with mode: 0644]
zic.tproj/HACK/Africa/Brazzaville [new file with mode: 0644]
zic.tproj/HACK/Africa/Bujumbura [new file with mode: 0644]
zic.tproj/HACK/Africa/Cairo [new file with mode: 0644]
zic.tproj/HACK/Africa/Casablanca [new file with mode: 0644]
zic.tproj/HACK/Africa/Ceuta [new file with mode: 0644]
zic.tproj/HACK/Africa/Conakry [new file with mode: 0644]
zic.tproj/HACK/Africa/Dakar [new file with mode: 0644]
zic.tproj/HACK/Africa/Dar_es_Salaam [new file with mode: 0644]
zic.tproj/HACK/Africa/Djibouti [new file with mode: 0644]
zic.tproj/HACK/Africa/Douala [new file with mode: 0644]
zic.tproj/HACK/Africa/El_Aaiun [new file with mode: 0644]
zic.tproj/HACK/Africa/Freetown [new file with mode: 0644]
zic.tproj/HACK/Africa/Gaborone [new file with mode: 0644]
zic.tproj/HACK/Africa/Harare [new file with mode: 0644]
zic.tproj/HACK/Africa/Johannesburg [new file with mode: 0644]
zic.tproj/HACK/Africa/Kampala [new file with mode: 0644]
zic.tproj/HACK/Africa/Khartoum [new file with mode: 0644]
zic.tproj/HACK/Africa/Kigali [new file with mode: 0644]
zic.tproj/HACK/Africa/Kinshasa [new file with mode: 0644]
zic.tproj/HACK/Africa/Lagos [new file with mode: 0644]
zic.tproj/HACK/Africa/Libreville [new file with mode: 0644]
zic.tproj/HACK/Africa/Lome [new file with mode: 0644]
zic.tproj/HACK/Africa/Luanda [new file with mode: 0644]
zic.tproj/HACK/Africa/Lubumbashi [new file with mode: 0644]
zic.tproj/HACK/Africa/Lusaka [new file with mode: 0644]
zic.tproj/HACK/Africa/Malabo [new file with mode: 0644]
zic.tproj/HACK/Africa/Maputo [new file with mode: 0644]
zic.tproj/HACK/Africa/Maseru [new file with mode: 0644]
zic.tproj/HACK/Africa/Mbabane [new file with mode: 0644]
zic.tproj/HACK/Africa/Mogadishu [new file with mode: 0644]
zic.tproj/HACK/Africa/Monrovia [new file with mode: 0644]
zic.tproj/HACK/Africa/Nairobi [new file with mode: 0644]
zic.tproj/HACK/Africa/Ndjamena [new file with mode: 0644]
zic.tproj/HACK/Africa/Niamey [new file with mode: 0644]
zic.tproj/HACK/Africa/Nouakchott [new file with mode: 0644]
zic.tproj/HACK/Africa/Ouagadougou [new file with mode: 0644]
zic.tproj/HACK/Africa/Porto-Novo [new file with mode: 0644]
zic.tproj/HACK/Africa/Sao_Tome [new file with mode: 0644]
zic.tproj/HACK/Africa/Timbuktu [new file with mode: 0644]
zic.tproj/HACK/Africa/Tripoli [new file with mode: 0644]
zic.tproj/HACK/Africa/Tunis [new file with mode: 0644]
zic.tproj/HACK/Africa/Windhoek [new file with mode: 0644]
zic.tproj/HACK/America/Adak [new file with mode: 0644]
zic.tproj/HACK/America/Anchorage [new file with mode: 0644]
zic.tproj/HACK/America/Anguilla [new file with mode: 0644]
zic.tproj/HACK/America/Antigua [new file with mode: 0644]
zic.tproj/HACK/America/Aruba [new file with mode: 0644]
zic.tproj/HACK/America/Asuncion [new file with mode: 0644]
zic.tproj/HACK/America/Atka [new file with mode: 0644]
zic.tproj/HACK/America/Barbados [new file with mode: 0644]
zic.tproj/HACK/America/Belize [new file with mode: 0644]
zic.tproj/HACK/America/Bogota [new file with mode: 0644]
zic.tproj/HACK/America/Boise [new file with mode: 0644]
zic.tproj/HACK/America/Buenos_Aires [new file with mode: 0644]
zic.tproj/HACK/America/Caracas [new file with mode: 0644]
zic.tproj/HACK/America/Catamarca [new file with mode: 0644]
zic.tproj/HACK/America/Cayenne [new file with mode: 0644]
zic.tproj/HACK/America/Cayman [new file with mode: 0644]
zic.tproj/HACK/America/Chicago [new file with mode: 0644]
zic.tproj/HACK/America/Cordoba [new file with mode: 0644]
zic.tproj/HACK/America/Costa_Rica [new file with mode: 0644]
zic.tproj/HACK/America/Cuiaba [new file with mode: 0644]
zic.tproj/HACK/America/Curacao [new file with mode: 0644]
zic.tproj/HACK/America/Dawson [new file with mode: 0644]
zic.tproj/HACK/America/Dawson_Creek [new file with mode: 0644]
zic.tproj/HACK/America/Denver [new file with mode: 0644]
zic.tproj/HACK/America/Detroit [new file with mode: 0644]
zic.tproj/HACK/America/Dominica [new file with mode: 0644]
zic.tproj/HACK/America/Edmonton [new file with mode: 0644]
zic.tproj/HACK/America/El_Salvador [new file with mode: 0644]
zic.tproj/HACK/America/Ensenada [new file with mode: 0644]
zic.tproj/HACK/America/Fort_Wayne [new file with mode: 0644]
zic.tproj/HACK/America/Fortaleza [new file with mode: 0644]
zic.tproj/HACK/America/Glace_Bay [new file with mode: 0644]
zic.tproj/HACK/America/Godthab [new file with mode: 0644]
zic.tproj/HACK/America/Goose_Bay [new file with mode: 0644]
zic.tproj/HACK/America/Grand_Turk [new file with mode: 0644]
zic.tproj/HACK/America/Grenada [new file with mode: 0644]
zic.tproj/HACK/America/Guadeloupe [new file with mode: 0644]
zic.tproj/HACK/America/Guatemala [new file with mode: 0644]
zic.tproj/HACK/America/Guayaquil [new file with mode: 0644]
zic.tproj/HACK/America/Guyana [new file with mode: 0644]
zic.tproj/HACK/America/Halifax [new file with mode: 0644]
zic.tproj/HACK/America/Havana [new file with mode: 0644]
zic.tproj/HACK/America/Indiana/Indianapolis [new file with mode: 0644]
zic.tproj/HACK/America/Indiana/Knox [new file with mode: 0644]
zic.tproj/HACK/America/Indiana/Marengo [new file with mode: 0644]
zic.tproj/HACK/America/Indiana/Vevay [new file with mode: 0644]
zic.tproj/HACK/America/Indianapolis [new file with mode: 0644]
zic.tproj/HACK/America/Inuvik [new file with mode: 0644]
zic.tproj/HACK/America/Iqaluit [new file with mode: 0644]
zic.tproj/HACK/America/Jamaica [new file with mode: 0644]
zic.tproj/HACK/America/Jujuy [new file with mode: 0644]
zic.tproj/HACK/America/Juneau [new file with mode: 0644]
zic.tproj/HACK/America/Knox_IN [new file with mode: 0644]
zic.tproj/HACK/America/La_Paz [new file with mode: 0644]
zic.tproj/HACK/America/Lima [new file with mode: 0644]
zic.tproj/HACK/America/Los_Angeles [new file with mode: 0644]
zic.tproj/HACK/America/Louisville [new file with mode: 0644]
zic.tproj/HACK/America/Maceio [new file with mode: 0644]
zic.tproj/HACK/America/Managua [new file with mode: 0644]
zic.tproj/HACK/America/Manaus [new file with mode: 0644]
zic.tproj/HACK/America/Martinique [new file with mode: 0644]
zic.tproj/HACK/America/Mazatlan [new file with mode: 0644]
zic.tproj/HACK/America/Mendoza [new file with mode: 0644]
zic.tproj/HACK/America/Menominee [new file with mode: 0644]
zic.tproj/HACK/America/Mexico_City [new file with mode: 0644]
zic.tproj/HACK/America/Miquelon [new file with mode: 0644]
zic.tproj/HACK/America/Montevideo [new file with mode: 0644]
zic.tproj/HACK/America/Montreal [new file with mode: 0644]
zic.tproj/HACK/America/Montserrat [new file with mode: 0644]
zic.tproj/HACK/America/Nassau [new file with mode: 0644]
zic.tproj/HACK/America/New_York [new file with mode: 0644]
zic.tproj/HACK/America/Nipigon [new file with mode: 0644]
zic.tproj/HACK/America/Nome [new file with mode: 0644]
zic.tproj/HACK/America/Noronha [new file with mode: 0644]
zic.tproj/HACK/America/Panama [new file with mode: 0644]
zic.tproj/HACK/America/Pangnirtung [new file with mode: 0644]
zic.tproj/HACK/America/Paramaribo [new file with mode: 0644]
zic.tproj/HACK/America/Phoenix [new file with mode: 0644]
zic.tproj/HACK/America/Port-au-Prince [new file with mode: 0644]
zic.tproj/HACK/America/Port_of_Spain [new file with mode: 0644]
zic.tproj/HACK/America/Porto_Acre [new file with mode: 0644]
zic.tproj/HACK/America/Puerto_Rico [new file with mode: 0644]
zic.tproj/HACK/America/Rainy_River [new file with mode: 0644]
zic.tproj/HACK/America/Rankin_Inlet [new file with mode: 0644]
zic.tproj/HACK/America/Regina [new file with mode: 0644]
zic.tproj/HACK/America/Rosario [new file with mode: 0644]
zic.tproj/HACK/America/Santiago [new file with mode: 0644]
zic.tproj/HACK/America/Santo_Domingo [new file with mode: 0644]
zic.tproj/HACK/America/Sao_Paulo [new file with mode: 0644]
zic.tproj/HACK/America/Scoresbysund [new file with mode: 0644]
zic.tproj/HACK/America/Shiprock [new file with mode: 0644]
zic.tproj/HACK/America/St_Johns [new file with mode: 0644]
zic.tproj/HACK/America/St_Kitts [new file with mode: 0644]
zic.tproj/HACK/America/St_Lucia [new file with mode: 0644]
zic.tproj/HACK/America/St_Thomas [new file with mode: 0644]
zic.tproj/HACK/America/St_Vincent [new file with mode: 0644]
zic.tproj/HACK/America/Swift_Current [new file with mode: 0644]
zic.tproj/HACK/America/Tegucigalpa [new file with mode: 0644]
zic.tproj/HACK/America/Thule [new file with mode: 0644]
zic.tproj/HACK/America/Thunder_Bay [new file with mode: 0644]
zic.tproj/HACK/America/Tijuana [new file with mode: 0644]
zic.tproj/HACK/America/Tortola [new file with mode: 0644]
zic.tproj/HACK/America/Vancouver [new file with mode: 0644]
zic.tproj/HACK/America/Virgin [new file with mode: 0644]
zic.tproj/HACK/America/Whitehorse [new file with mode: 0644]
zic.tproj/HACK/America/Winnipeg [new file with mode: 0644]
zic.tproj/HACK/America/Yakutat [new file with mode: 0644]
zic.tproj/HACK/America/Yellowknife [new file with mode: 0644]
zic.tproj/HACK/Antarctica/Casey [new file with mode: 0644]
zic.tproj/HACK/Antarctica/Mawson [new file with mode: 0644]
zic.tproj/HACK/Antarctica/McMurdo [new file with mode: 0644]
zic.tproj/HACK/Antarctica/Palmer [new file with mode: 0644]
zic.tproj/HACK/Antarctica/South_Pole [new file with mode: 0644]
zic.tproj/HACK/Arctic/Longyearbyen [new file with mode: 0644]
zic.tproj/HACK/Asia/Aden [new file with mode: 0644]
zic.tproj/HACK/Asia/Alma-Ata [new file with mode: 0644]
zic.tproj/HACK/Asia/Amman [new file with mode: 0644]
zic.tproj/HACK/Asia/Anadyr [new file with mode: 0644]
zic.tproj/HACK/Asia/Aqtau [new file with mode: 0644]
zic.tproj/HACK/Asia/Aqtobe [new file with mode: 0644]
zic.tproj/HACK/Asia/Ashkhabad [new file with mode: 0644]
zic.tproj/HACK/Asia/Baghdad [new file with mode: 0644]
zic.tproj/HACK/Asia/Bahrain [new file with mode: 0644]
zic.tproj/HACK/Asia/Baku [new file with mode: 0644]
zic.tproj/HACK/Asia/Bangkok [new file with mode: 0644]
zic.tproj/HACK/Asia/Beirut [new file with mode: 0644]
zic.tproj/HACK/Asia/Bishkek [new file with mode: 0644]
zic.tproj/HACK/Asia/Brunei [new file with mode: 0644]
zic.tproj/HACK/Asia/Calcutta [new file with mode: 0644]
zic.tproj/HACK/Asia/Chungking [new file with mode: 0644]
zic.tproj/HACK/Asia/Colombo [new file with mode: 0644]
zic.tproj/HACK/Asia/Dacca [new file with mode: 0644]
zic.tproj/HACK/Asia/Damascus [new file with mode: 0644]
zic.tproj/HACK/Asia/Dubai [new file with mode: 0644]
zic.tproj/HACK/Asia/Dushanbe [new file with mode: 0644]
zic.tproj/HACK/Asia/Gaza [new file with mode: 0644]
zic.tproj/HACK/Asia/Harbin [new file with mode: 0644]
zic.tproj/HACK/Asia/Hong_Kong [new file with mode: 0644]
zic.tproj/HACK/Asia/Irkutsk [new file with mode: 0644]
zic.tproj/HACK/Asia/Ishigaki [new file with mode: 0644]
zic.tproj/HACK/Asia/Istanbul [new file with mode: 0644]
zic.tproj/HACK/Asia/Jakarta [new file with mode: 0644]
zic.tproj/HACK/Asia/Jayapura [new file with mode: 0644]
zic.tproj/HACK/Asia/Jerusalem [new file with mode: 0644]
zic.tproj/HACK/Asia/Kabul [new file with mode: 0644]
zic.tproj/HACK/Asia/Kamchatka [new file with mode: 0644]
zic.tproj/HACK/Asia/Karachi [new file with mode: 0644]
zic.tproj/HACK/Asia/Kashgar [new file with mode: 0644]
zic.tproj/HACK/Asia/Katmandu [new file with mode: 0644]
zic.tproj/HACK/Asia/Krasnoyarsk [new file with mode: 0644]
zic.tproj/HACK/Asia/Kuala_Lumpur [new file with mode: 0644]
zic.tproj/HACK/Asia/Kuching [new file with mode: 0644]
zic.tproj/HACK/Asia/Kuwait [new file with mode: 0644]
zic.tproj/HACK/Asia/Macao [new file with mode: 0644]
zic.tproj/HACK/Asia/Magadan [new file with mode: 0644]
zic.tproj/HACK/Asia/Manila [new file with mode: 0644]
zic.tproj/HACK/Asia/Muscat [new file with mode: 0644]
zic.tproj/HACK/Asia/Nicosia [new file with mode: 0644]
zic.tproj/HACK/Asia/Novosibirsk [new file with mode: 0644]
zic.tproj/HACK/Asia/Omsk [new file with mode: 0644]
zic.tproj/HACK/Asia/Phnom_Penh [new file with mode: 0644]
zic.tproj/HACK/Asia/Pyongyang [new file with mode: 0644]
zic.tproj/HACK/Asia/Qatar [new file with mode: 0644]
zic.tproj/HACK/Asia/Rangoon [new file with mode: 0644]
zic.tproj/HACK/Asia/Riyadh [new file with mode: 0644]
zic.tproj/HACK/Asia/Riyadh87 [new file with mode: 0644]
zic.tproj/HACK/Asia/Riyadh88 [new file with mode: 0644]
zic.tproj/HACK/Asia/Riyadh89 [new file with mode: 0644]
zic.tproj/HACK/Asia/Saigon [new file with mode: 0644]
zic.tproj/HACK/Asia/Seoul [new file with mode: 0644]
zic.tproj/HACK/Asia/Shanghai [new file with mode: 0644]
zic.tproj/HACK/Asia/Singapore [new file with mode: 0644]
zic.tproj/HACK/Asia/Taipei [new file with mode: 0644]
zic.tproj/HACK/Asia/Tashkent [new file with mode: 0644]
zic.tproj/HACK/Asia/Tbilisi [new file with mode: 0644]
zic.tproj/HACK/Asia/Tehran [new file with mode: 0644]
zic.tproj/HACK/Asia/Tel_Aviv [new file with mode: 0644]
zic.tproj/HACK/Asia/Thimbu [new file with mode: 0644]
zic.tproj/HACK/Asia/Tokyo [new file with mode: 0644]
zic.tproj/HACK/Asia/Ujung_Pandang [new file with mode: 0644]
zic.tproj/HACK/Asia/Ulan_Bator [new file with mode: 0644]
zic.tproj/HACK/Asia/Urumqi [new file with mode: 0644]
zic.tproj/HACK/Asia/Vientiane [new file with mode: 0644]
zic.tproj/HACK/Asia/Vladivostok [new file with mode: 0644]
zic.tproj/HACK/Asia/Yakutsk [new file with mode: 0644]
zic.tproj/HACK/Asia/Yekaterinburg [new file with mode: 0644]
zic.tproj/HACK/Asia/Yerevan [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Azores [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Bermuda [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Canary [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Cape_Verde [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Faeroe [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Jan_Mayen [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Madeira [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Reykjavik [new file with mode: 0644]
zic.tproj/HACK/Atlantic/South_Georgia [new file with mode: 0644]
zic.tproj/HACK/Atlantic/St_Helena [new file with mode: 0644]
zic.tproj/HACK/Atlantic/Stanley [new file with mode: 0644]
zic.tproj/HACK/Australia/ACT [new file with mode: 0644]
zic.tproj/HACK/Australia/Adelaide [new file with mode: 0644]
zic.tproj/HACK/Australia/Brisbane [new file with mode: 0644]
zic.tproj/HACK/Australia/Broken_Hill [new file with mode: 0644]
zic.tproj/HACK/Australia/Canberra [new file with mode: 0644]
zic.tproj/HACK/Australia/Darwin [new file with mode: 0644]
zic.tproj/HACK/Australia/Hobart [new file with mode: 0644]
zic.tproj/HACK/Australia/LHI [new file with mode: 0644]
zic.tproj/HACK/Australia/Lindeman [new file with mode: 0644]
zic.tproj/HACK/Australia/Lord_Howe [new file with mode: 0644]
zic.tproj/HACK/Australia/Melbourne [new file with mode: 0644]
zic.tproj/HACK/Australia/NSW [new file with mode: 0644]
zic.tproj/HACK/Australia/North [new file with mode: 0644]
zic.tproj/HACK/Australia/Perth [new file with mode: 0644]
zic.tproj/HACK/Australia/Queensland [new file with mode: 0644]
zic.tproj/HACK/Australia/South [new file with mode: 0644]
zic.tproj/HACK/Australia/Sydney [new file with mode: 0644]
zic.tproj/HACK/Australia/Tasmania [new file with mode: 0644]
zic.tproj/HACK/Australia/Victoria [new file with mode: 0644]
zic.tproj/HACK/Australia/West [new file with mode: 0644]
zic.tproj/HACK/Australia/Yancowinna [new file with mode: 0644]
zic.tproj/HACK/Brazil/Acre [new file with mode: 0644]
zic.tproj/HACK/Brazil/DeNoronha [new file with mode: 0644]
zic.tproj/HACK/Brazil/East [new file with mode: 0644]
zic.tproj/HACK/Brazil/West [new file with mode: 0644]
zic.tproj/HACK/CET [new file with mode: 0644]
zic.tproj/HACK/CST6CDT [new file with mode: 0644]
zic.tproj/HACK/Canada/Atlantic [new file with mode: 0644]
zic.tproj/HACK/Canada/Central [new file with mode: 0644]
zic.tproj/HACK/Canada/East-Saskatchewan [new file with mode: 0644]
zic.tproj/HACK/Canada/Eastern [new file with mode: 0644]
zic.tproj/HACK/Canada/Mountain [new file with mode: 0644]
zic.tproj/HACK/Canada/Newfoundland [new file with mode: 0644]
zic.tproj/HACK/Canada/Pacific [new file with mode: 0644]
zic.tproj/HACK/Canada/Saskatchewan [new file with mode: 0644]
zic.tproj/HACK/Canada/Yukon [new file with mode: 0644]
zic.tproj/HACK/Chile/Continental [new file with mode: 0644]
zic.tproj/HACK/Chile/EasterIsland [new file with mode: 0644]
zic.tproj/HACK/Cuba [new file with mode: 0644]
zic.tproj/HACK/EET [new file with mode: 0644]
zic.tproj/HACK/EST [new file with mode: 0644]
zic.tproj/HACK/EST5EDT [new file with mode: 0644]
zic.tproj/HACK/Egypt [new file with mode: 0644]
zic.tproj/HACK/Eire [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+0 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+1 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+10 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+11 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+12 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+2 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+3 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+4 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+5 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+6 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+7 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+8 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT+9 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-0 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-1 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-10 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-11 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-12 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-13 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-14 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-2 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-3 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-4 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-5 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-6 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-7 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-8 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT-9 [new file with mode: 0644]
zic.tproj/HACK/Etc/GMT0 [new file with mode: 0644]
zic.tproj/HACK/Etc/Greenwich [new file with mode: 0644]
zic.tproj/HACK/Etc/UCT [new file with mode: 0644]
zic.tproj/HACK/Etc/UTC [new file with mode: 0644]
zic.tproj/HACK/Etc/Universal [new file with mode: 0644]
zic.tproj/HACK/Etc/Zulu [new file with mode: 0644]
zic.tproj/HACK/Europe/Amsterdam [new file with mode: 0644]
zic.tproj/HACK/Europe/Andorra [new file with mode: 0644]
zic.tproj/HACK/Europe/Athens [new file with mode: 0644]
zic.tproj/HACK/Europe/Belfast [new file with mode: 0644]
zic.tproj/HACK/Europe/Belgrade [new file with mode: 0644]
zic.tproj/HACK/Europe/Berlin [new file with mode: 0644]
zic.tproj/HACK/Europe/Bratislava [new file with mode: 0644]
zic.tproj/HACK/Europe/Brussels [new file with mode: 0644]
zic.tproj/HACK/Europe/Bucharest [new file with mode: 0644]
zic.tproj/HACK/Europe/Budapest [new file with mode: 0644]
zic.tproj/HACK/Europe/Chisinau [new file with mode: 0644]
zic.tproj/HACK/Europe/Copenhagen [new file with mode: 0644]
zic.tproj/HACK/Europe/Dublin [new file with mode: 0644]
zic.tproj/HACK/Europe/Gibraltar [new file with mode: 0644]
zic.tproj/HACK/Europe/Helsinki [new file with mode: 0644]
zic.tproj/HACK/Europe/Istanbul [new file with mode: 0644]
zic.tproj/HACK/Europe/Kaliningrad [new file with mode: 0644]
zic.tproj/HACK/Europe/Kiev [new file with mode: 0644]
zic.tproj/HACK/Europe/Lisbon [new file with mode: 0644]
zic.tproj/HACK/Europe/Ljubljana [new file with mode: 0644]
zic.tproj/HACK/Europe/London [new file with mode: 0644]
zic.tproj/HACK/Europe/Luxembourg [new file with mode: 0644]
zic.tproj/HACK/Europe/Madrid [new file with mode: 0644]
zic.tproj/HACK/Europe/Malta [new file with mode: 0644]
zic.tproj/HACK/Europe/Minsk [new file with mode: 0644]
zic.tproj/HACK/Europe/Monaco [new file with mode: 0644]
zic.tproj/HACK/Europe/Moscow [new file with mode: 0644]
zic.tproj/HACK/Europe/Oslo [new file with mode: 0644]
zic.tproj/HACK/Europe/Paris [new file with mode: 0644]
zic.tproj/HACK/Europe/Prague [new file with mode: 0644]
zic.tproj/HACK/Europe/Riga [new file with mode: 0644]
zic.tproj/HACK/Europe/Rome [new file with mode: 0644]
zic.tproj/HACK/Europe/Samara [new file with mode: 0644]
zic.tproj/HACK/Europe/San_Marino [new file with mode: 0644]
zic.tproj/HACK/Europe/Sarajevo [new file with mode: 0644]
zic.tproj/HACK/Europe/Simferopol [new file with mode: 0644]
zic.tproj/HACK/Europe/Skopje [new file with mode: 0644]
zic.tproj/HACK/Europe/Sofia [new file with mode: 0644]
zic.tproj/HACK/Europe/Stockholm [new file with mode: 0644]
zic.tproj/HACK/Europe/Tallinn [new file with mode: 0644]
zic.tproj/HACK/Europe/Tirane [new file with mode: 0644]
zic.tproj/HACK/Europe/Vaduz [new file with mode: 0644]
zic.tproj/HACK/Europe/Vatican [new file with mode: 0644]
zic.tproj/HACK/Europe/Vienna [new file with mode: 0644]
zic.tproj/HACK/Europe/Vilnius [new file with mode: 0644]
zic.tproj/HACK/Europe/Warsaw [new file with mode: 0644]
zic.tproj/HACK/Europe/Zagreb [new file with mode: 0644]
zic.tproj/HACK/Europe/Zurich [new file with mode: 0644]
zic.tproj/HACK/Factory [new file with mode: 0644]
zic.tproj/HACK/GB [new file with mode: 0644]
zic.tproj/HACK/GMT [new file with mode: 0644]
zic.tproj/HACK/GMT+0 [new file with mode: 0644]
zic.tproj/HACK/GMT-0 [new file with mode: 0644]
zic.tproj/HACK/GMT0 [new file with mode: 0644]
zic.tproj/HACK/Greenwich [new file with mode: 0644]
zic.tproj/HACK/HST [new file with mode: 0644]
zic.tproj/HACK/Hongkong [new file with mode: 0644]
zic.tproj/HACK/Iceland [new file with mode: 0644]
zic.tproj/HACK/Indian/Antananarivo [new file with mode: 0644]
zic.tproj/HACK/Indian/Chagos [new file with mode: 0644]
zic.tproj/HACK/Indian/Christmas [new file with mode: 0644]
zic.tproj/HACK/Indian/Cocos [new file with mode: 0644]
zic.tproj/HACK/Indian/Comoro [new file with mode: 0644]
zic.tproj/HACK/Indian/Mahe [new file with mode: 0644]
zic.tproj/HACK/Indian/Maldives [new file with mode: 0644]
zic.tproj/HACK/Indian/Mauritius [new file with mode: 0644]
zic.tproj/HACK/Indian/Mayotte [new file with mode: 0644]
zic.tproj/HACK/Indian/Reunion [new file with mode: 0644]
zic.tproj/HACK/Iran [new file with mode: 0644]
zic.tproj/HACK/Israel [new file with mode: 0644]
zic.tproj/HACK/Jamaica [new file with mode: 0644]
zic.tproj/HACK/Japan [new file with mode: 0644]
zic.tproj/HACK/Kwajalein [new file with mode: 0644]
zic.tproj/HACK/Libya [new file with mode: 0644]
zic.tproj/HACK/MET [new file with mode: 0644]
zic.tproj/HACK/MST [new file with mode: 0644]
zic.tproj/HACK/MST7MDT [new file with mode: 0644]
zic.tproj/HACK/Mexico/BajaNorte [new file with mode: 0644]
zic.tproj/HACK/Mexico/BajaSur [new file with mode: 0644]
zic.tproj/HACK/Mexico/General [new file with mode: 0644]
zic.tproj/HACK/Mideast/Riyadh87 [new file with mode: 0644]
zic.tproj/HACK/Mideast/Riyadh88 [new file with mode: 0644]
zic.tproj/HACK/Mideast/Riyadh89 [new file with mode: 0644]
zic.tproj/HACK/NZ [new file with mode: 0644]
zic.tproj/HACK/NZ-CHAT [new file with mode: 0644]
zic.tproj/HACK/Navajo [new file with mode: 0644]
zic.tproj/HACK/PRC [new file with mode: 0644]
zic.tproj/HACK/PST8PDT [new file with mode: 0644]
zic.tproj/HACK/Pacific/Apia [new file with mode: 0644]
zic.tproj/HACK/Pacific/Auckland [new file with mode: 0644]
zic.tproj/HACK/Pacific/Chatham [new file with mode: 0644]
zic.tproj/HACK/Pacific/Easter [new file with mode: 0644]
zic.tproj/HACK/Pacific/Efate [new file with mode: 0644]
zic.tproj/HACK/Pacific/Enderbury [new file with mode: 0644]
zic.tproj/HACK/Pacific/Fakaofo [new file with mode: 0644]
zic.tproj/HACK/Pacific/Fiji [new file with mode: 0644]
zic.tproj/HACK/Pacific/Funafuti [new file with mode: 0644]
zic.tproj/HACK/Pacific/Galapagos [new file with mode: 0644]
zic.tproj/HACK/Pacific/Gambier [new file with mode: 0644]
zic.tproj/HACK/Pacific/Guadalcanal [new file with mode: 0644]
zic.tproj/HACK/Pacific/Guam [new file with mode: 0644]
zic.tproj/HACK/Pacific/Honolulu [new file with mode: 0644]
zic.tproj/HACK/Pacific/Johnston [new file with mode: 0644]
zic.tproj/HACK/Pacific/Kiritimati [new file with mode: 0644]
zic.tproj/HACK/Pacific/Kosrae [new file with mode: 0644]
zic.tproj/HACK/Pacific/Kwajalein [new file with mode: 0644]
zic.tproj/HACK/Pacific/Majuro [new file with mode: 0644]
zic.tproj/HACK/Pacific/Marquesas [new file with mode: 0644]
zic.tproj/HACK/Pacific/Midway [new file with mode: 0644]
zic.tproj/HACK/Pacific/Nauru [new file with mode: 0644]
zic.tproj/HACK/Pacific/Niue [new file with mode: 0644]
zic.tproj/HACK/Pacific/Norfolk [new file with mode: 0644]
zic.tproj/HACK/Pacific/Noumea [new file with mode: 0644]
zic.tproj/HACK/Pacific/Pago_Pago [new file with mode: 0644]
zic.tproj/HACK/Pacific/Palau [new file with mode: 0644]
zic.tproj/HACK/Pacific/Pitcairn [new file with mode: 0644]
zic.tproj/HACK/Pacific/Ponape [new file with mode: 0644]
zic.tproj/HACK/Pacific/Port_Moresby [new file with mode: 0644]
zic.tproj/HACK/Pacific/Rarotonga [new file with mode: 0644]
zic.tproj/HACK/Pacific/Saipan [new file with mode: 0644]
zic.tproj/HACK/Pacific/Samoa [new file with mode: 0644]
zic.tproj/HACK/Pacific/Tahiti [new file with mode: 0644]
zic.tproj/HACK/Pacific/Tarawa [new file with mode: 0644]
zic.tproj/HACK/Pacific/Tongatapu [new file with mode: 0644]
zic.tproj/HACK/Pacific/Truk [new file with mode: 0644]
zic.tproj/HACK/Pacific/Wake [new file with mode: 0644]
zic.tproj/HACK/Pacific/Wallis [new file with mode: 0644]
zic.tproj/HACK/Pacific/Yap [new file with mode: 0644]
zic.tproj/HACK/Poland [new file with mode: 0644]
zic.tproj/HACK/Portugal [new file with mode: 0644]
zic.tproj/HACK/ROC [new file with mode: 0644]
zic.tproj/HACK/ROK [new file with mode: 0644]
zic.tproj/HACK/Singapore [new file with mode: 0644]
zic.tproj/HACK/SystemV/AST4 [new file with mode: 0644]
zic.tproj/HACK/SystemV/AST4ADT [new file with mode: 0644]
zic.tproj/HACK/SystemV/CST6 [new file with mode: 0644]
zic.tproj/HACK/SystemV/CST6CDT [new file with mode: 0644]
zic.tproj/HACK/SystemV/EST5 [new file with mode: 0644]
zic.tproj/HACK/SystemV/EST5EDT [new file with mode: 0644]
zic.tproj/HACK/SystemV/HST10 [new file with mode: 0644]
zic.tproj/HACK/SystemV/MST7 [new file with mode: 0644]
zic.tproj/HACK/SystemV/MST7MDT [new file with mode: 0644]
zic.tproj/HACK/SystemV/PST8 [new file with mode: 0644]
zic.tproj/HACK/SystemV/PST8PDT [new file with mode: 0644]
zic.tproj/HACK/SystemV/YST9 [new file with mode: 0644]
zic.tproj/HACK/SystemV/YST9YDT [new file with mode: 0644]
zic.tproj/HACK/Turkey [new file with mode: 0644]
zic.tproj/HACK/UCT [new file with mode: 0644]
zic.tproj/HACK/US/Alaska [new file with mode: 0644]
zic.tproj/HACK/US/Aleutian [new file with mode: 0644]
zic.tproj/HACK/US/Arizona [new file with mode: 0644]
zic.tproj/HACK/US/Central [new file with mode: 0644]
zic.tproj/HACK/US/East-Indiana [new file with mode: 0644]
zic.tproj/HACK/US/Eastern [new file with mode: 0644]
zic.tproj/HACK/US/Hawaii [new file with mode: 0644]
zic.tproj/HACK/US/Indiana-Starke [new file with mode: 0644]
zic.tproj/HACK/US/Michigan [new file with mode: 0644]
zic.tproj/HACK/US/Mountain [new file with mode: 0644]
zic.tproj/HACK/US/Pacific [new file with mode: 0644]
zic.tproj/HACK/US/Pacific-New [new file with mode: 0644]
zic.tproj/HACK/US/Samoa [new file with mode: 0644]
zic.tproj/HACK/UTC [new file with mode: 0644]
zic.tproj/HACK/Universal [new file with mode: 0644]
zic.tproj/HACK/W-SU [new file with mode: 0644]
zic.tproj/HACK/WET [new file with mode: 0644]
zic.tproj/HACK/Zulu [new file with mode: 0644]
zic.tproj/Makefile [new file with mode: 0644]
zic.tproj/Makefile.postamble [new file with mode: 0644]
zic.tproj/Makefile.preamble [new file with mode: 0644]
zic.tproj/PB.project [new file with mode: 0644]
zic.tproj/datfiles/africa [new file with mode: 0644]
zic.tproj/datfiles/antarctica [new file with mode: 0644]
zic.tproj/datfiles/asia [new file with mode: 0644]
zic.tproj/datfiles/australasia [new file with mode: 0644]
zic.tproj/datfiles/backward [new file with mode: 0644]
zic.tproj/datfiles/etcetera [new file with mode: 0644]
zic.tproj/datfiles/europe [new file with mode: 0644]
zic.tproj/datfiles/factory [new file with mode: 0644]
zic.tproj/datfiles/leapseconds [new file with mode: 0644]
zic.tproj/datfiles/northamerica [new file with mode: 0644]
zic.tproj/datfiles/pacificnew [new file with mode: 0644]
zic.tproj/datfiles/solar87 [new file with mode: 0644]
zic.tproj/datfiles/solar88 [new file with mode: 0644]
zic.tproj/datfiles/solar89 [new file with mode: 0644]
zic.tproj/datfiles/southamerica [new file with mode: 0644]
zic.tproj/datfiles/systemv [new file with mode: 0644]
zic.tproj/datfiles/yearistype.sh [new file with mode: 0755]
zic.tproj/ialloc.c [new file with mode: 0644]
zic.tproj/private.h [new file with mode: 0644]
zic.tproj/scheck.c [new file with mode: 0644]
zic.tproj/tzfile.h [new file with mode: 0644]
zic.tproj/zic.8 [new file with mode: 0644]
zic.tproj/zic.c [new file with mode: 0644]
zprint.tproj/Makefile [new file with mode: 0644]
zprint.tproj/Makefile.postamble [new file with mode: 0644]
zprint.tproj/Makefile.preamble [new file with mode: 0644]
zprint.tproj/PB.project [new file with mode: 0644]
zprint.tproj/zprint.c [new file with mode: 0644]

diff --git a/APPLE_LICENSE b/APPLE_LICENSE
new file mode 100644 (file)
index 0000000..e7aa7d0
--- /dev/null
@@ -0,0 +1,370 @@
+                    APPLE PUBLIC SOURCE LICENSE
+                    Version 1.0 - March 16, 1999
+
+Please read this License carefully before downloading this software.
+By downloading and using this software, you are agreeing to be bound
+by the terms of this License.  If you do not or cannot agree to the
+terms of this License, please do not download or use the software.
+
+1. General; Definitions.  This License applies to any program or other
+  work which Apple Computer, Inc. ("Apple") publicly announces as
+  subject to this Apple Public Source License and which contains a
+  notice placed by Apple identifying such program or work as "Original
+  Code" and stating that it is subject to the terms of this Apple
+  Public Source License version 1.0 (or subsequent version thereof),
+  as it may be revised from time to time by Apple ("License").  As
+  used in this License:
+
+1.1 "Applicable Patents" mean: (a) in the case where Apple is the
+  grantor of rights, (i) patents or patent applications that are now
+  or hereafter acquired, owned by or assigned to Apple and (ii) whose
+  claims cover subject matter contained in the Original Code, but only
+  to the extent necessary to use, reproduce and/or distribute the
+  Original Code without infringement; and (b) in the case where You
+  are the grantor of rights, (i) patents and patent applications that
+  are now or hereafter acquired, owned by or assigned to You and (ii)
+  whose claims cover subject matter in Your Modifications, taken alone
+  or in combination with Original Code.
+
+1.2 "Covered Code" means the Original Code, Modifications, the
+  combination of Original Code and any Modifications, and/or any
+  respective portions thereof.
+
+1.3 "Deploy" means to use, sublicense or distribute Covered Code other
+  than for Your internal research and development (R&D), and includes
+  without limitation, any and all internal use or distribution of
+  Covered Code within Your business or organization except for R&D
+  use, as well as direct or indirect sublicensing or distribution of
+  Covered Code by You to any third party in any form or manner.
+
+1.4 "Larger Work" means a work which combines Covered Code or portions
+  thereof with code not governed by the terms of this License.
+
+1.5 "Modifications" mean any addition to, deletion from, and/or change
+  to, the substance and/or structure of Covered Code.  When code is
+  released as a series of files, a Modification is: (a) any addition
+  to or deletion from the contents of a file containing Covered Code;
+  and/or (b) any new file or other representation of computer program
+  statements that contains any part of Covered Code.
+
+1.6 "Original Code" means the Source Code of a program or other work
+  as originally made available by Apple under this License, including
+  the Source Code of any updates or upgrades to such programs or works
+  made available by Apple under this License, and that has been
+  expressly identified by Apple as such in the header file(s) of such
+  work.
+
+1.7 "Source Code" means the human readable form of a program or other
+  work that is suitable for making modifications to it, including all
+  modules it contains, plus any associated interface definition files,
+  scripts used to control compilation and installation of an
+  executable (object code).
+
+1.8 "You" or "Your" means an individual or a legal entity exercising
+  rights under this License.  For legal entities, "You" or "Your"
+  includes any entity which controls, is controlled by, or is under
+  common control with, You, where "control" means (a) the power,
+  direct or indirect, to cause the direction or management of such
+  entity, whether by contract or otherwise, or (b) ownership of fifty
+  percent (50%) or more of the outstanding shares or beneficial
+  ownership of such entity.
+
+2. Permitted Uses; Conditions & Restrictions.  Subject to the terms
+  and conditions of this License, Apple hereby grants You, effective
+  on the date You accept this License and download the Original Code,
+  a world-wide, royalty-free, non-exclusive license, to the extent of
+  Apple's Applicable Patents and copyrights covering the Original
+  Code, to do the following:
+
+2.1 You may use, copy, modify and distribute Original Code, with or
+  without Modifications, solely for Your internal research and
+  development, provided that You must in each instance:
+
+(a) retain and reproduce in all copies of Original Code the copyright
+and other proprietary notices and disclaimers of Apple as they appear
+in the Original Code, and keep intact all notices in the Original Code
+that refer to this License;
+
+(b) include a copy of this License with every copy of Source Code of
+Covered Code and documentation You distribute, and You may not offer
+or impose any terms on such Source Code that alter or restrict this
+License or the recipients' rights hereunder, except as permitted under
+Section 6; and
+
+(c) completely and accurately document all Modifications that you have
+made and the date of each such Modification, designate the version of
+the Original Code you used, prominently include a file carrying such
+information with the Modifications, and duplicate the notice in
+Exhibit A in each file of the Source Code of all such Modifications.
+
+2.2 You may Deploy Covered Code, provided that You must in each
+  instance:
+
+(a) satisfy all the conditions of Section 2.1 with respect to the
+Source Code of the Covered Code;
+
+(b) make all Your Deployed Modifications publicly available in Source
+Code form via electronic distribution (e.g. download from a web site)
+under the terms of this License and subject to the license grants set
+forth in Section 3 below, and any additional terms You may choose to
+offer under Section 6.  You must continue to make the Source Code of
+Your Deployed Modifications available for as long as you Deploy the
+Covered Code or twelve (12) months from the date of initial
+Deployment, whichever is longer;
+
+(c) must notify Apple and other third parties of how to obtain Your
+Deployed Modifications by filling out and submitting the required
+information found at
+http://www.apple.com/publicsource/modifications.html; and
+
+(d) if you Deploy Covered Code in object code, executable form only,
+include a prominent notice, in the code itself as well as in related
+documentation, stating that Source Code of the Covered Code is
+available under the terms of this License with information on how and
+where to obtain such Source Code.
+
+3. Your Grants.  In consideration of, and as a condition to, the
+  licenses granted to You under this License:
+
+(a) You hereby grant to Apple and all third parties a non-exclusive,
+royalty-free license, under Your Applicable Patents and other
+intellectual property rights owned or controlled by You, to use,
+reproduce, modify, distribute and Deploy Your Modifications of the
+same scope and extent as Apple's licenses under Sections 2.1 and 2.2;
+and
+
+(b) You hereby grant to Apple and its subsidiaries a non-exclusive,
+worldwide, royalty-free, perpetual and irrevocable license, under Your
+Applicable Patents and other intellectual property rights owned or
+controlled by You, to use, reproduce, execute, compile, display,
+perform, modify or have modified (for Apple and/or its subsidiaries),
+sublicense and distribute Your Modifications, in any form, through
+multiple tiers of distribution.
+
+4. Larger Works.  You may create a Larger Work by combining Covered
+  Code with other code not governed by the terms of this License and
+  distribute the Larger Work as a single product.  In each such
+  instance, You must make sure the requirements of this License are
+  fulfilled for the Covered Code or any portion thereof.
+
+5. Limitations on Patent License.  Except as expressly stated in
+  Section 2, no other patent rights, express or implied, are granted
+  by Apple herein.  Modifications and/or Larger Works may require
+  additional patent licenses from Apple which Apple may grant in its
+  sole discretion.
+
+6. Additional Terms.  You may choose to offer, and to charge a fee
+  for, warranty, support, indemnity or liability obligations and/or
+  other rights consistent with the scope of the license granted herein
+  ("Additional Terms") to one or more recipients of Covered
+  Code. However, You may do so only on Your own behalf and as Your
+  sole responsibility, and not on behalf of Apple. You must obtain the
+  recipient's agreement that any such Additional Terms are offered by
+  You alone, and You hereby agree to indemnify, defend and hold Apple
+  harmless for any liability incurred by or claims asserted against
+  Apple by reason of any such Additional Terms.
+
+7. Versions of the License.  Apple may publish revised and/or new
+  versions of this License from time to time.  Each version will be
+  given a distinguishing version number.  Once Original Code has been
+  published under a particular version of this License, You may
+  continue to use it under the terms of that version. You may also
+  choose to use such Original Code under the terms of any subsequent
+  version of this License published by Apple.  No one other than Apple
+  has the right to modify the terms applicable to Covered Code created
+  under this License.
+
+8. NO WARRANTY OR SUPPORT.  The Original Code may contain in whole or
+  in part pre-release, untested, or not fully tested works.  The
+  Original Code may contain errors that could cause failures or loss
+  of data, and may be incomplete or contain inaccuracies.  You
+  expressly acknowledge and agree that use of the Original Code, or
+  any portion thereof, is at Your sole and entire risk.  THE ORIGINAL
+  CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT
+  OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (FOR THE PURPOSES OF
+  SECTIONS 8 AND 9, APPLE AND APPLE'S LICENSOR(S) ARE COLLECTIVELY
+  REFERRED TO AS "APPLE") EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR
+  CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY OR
+  SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT OF THIRD PARTY RIGHTS.  APPLE DOES NOT WARRANT THAT
+  THE FUNCTIONS CONTAINED IN THE ORIGINAL CODE WILL MEET YOUR
+  REQUIREMENTS, OR THAT THE OPERATION OF THE ORIGINAL CODE WILL BE
+  UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE ORIGINAL CODE
+  WILL BE CORRECTED.  NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN
+  BY APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE SHALL CREATE A
+  WARRANTY OR IN ANY WAY INCREASE THE SCOPE OF THIS WARRANTY.  You
+  acknowledge that the Original Code is not intended for use in the
+  operation of nuclear facilities, aircraft navigation, communication
+  systems, or air traffic control machines in which case the failure
+  of the Original Code could lead to death, personal injury, or severe
+  physical or environmental damage.
+
+9. Liability.
+
+9.1 Infringement.  If any of the Original Code becomes the subject of
+  a claim of infringement ("Affected Original Code"), Apple may, at
+  its sole discretion and option: (a) attempt to procure the rights
+  necessary for You to continue using the Affected Original Code; (b)
+  modify the Affected Original Code so that it is no longer
+  infringing; or (c) terminate Your rights to use the Affected
+  Original Code, effective immediately upon Apple's posting of a
+  notice to such effect on the Apple web site that is used for
+  implementation of this License.
+
+9.2 LIMITATION OF LIABILITY.  UNDER NO CIRCUMSTANCES SHALL APPLE BE
+  LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
+  DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR
+  INABILITY TO USE THE ORIGINAL CODE, OR ANY PORTION THEREOF, WHETHER
+  UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE),
+  PRODUCTS LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF
+  THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF
+  ESSENTIAL PURPOSE OF ANY REMEDY.  In no event shall Apple's total
+  liability to You for all damages under this License exceed the
+  amount of fifty dollars ($50.00).
+
+10. Trademarks.  This License does not grant any rights to use the
+   trademarks or trade names "Apple", "Apple Computer", "Mac OS X",
+   "Mac OS X Server" or any other trademarks or trade names belonging
+   to Apple (collectively "Apple Marks") and no Apple Marks may be
+   used to endorse or promote products derived from the Original Code
+   other than as permitted by and in strict compliance at all times
+   with Apple's third party trademark usage guidelines which are
+   posted at http://www.apple.com/legal/guidelinesfor3rdparties.html.
+
+11. Ownership.  Apple retains all rights, title and interest in and to
+   the Original Code and any Modifications made by or on behalf of
+   Apple ("Apple Modifications"), and such Apple Modifications will
+   not be automatically subject to this License.  Apple may, at its
+   sole discretion, choose to license such Apple Modifications under
+   this License, or on different terms from those contained in this
+   License or may choose not to license them at all.  Apple's
+   development, use, reproduction, modification, sublicensing and
+   distribution of Covered Code will not be subject to this License.
+
+12. Termination.
+
+12.1 Termination.  This License and the rights granted hereunder will
+   terminate:
+
+(a) automatically without notice from Apple if You fail to comply with
+any term(s) of this License and fail to cure such breach within 30
+days of becoming aware of such breach; (b) immediately in the event of
+the circumstances described in Sections 9.1 and/or 13.6(b); or (c)
+automatically without notice from Apple if You, at any time during the
+term of this License, commence an action for patent infringement
+against Apple.
+
+12.2 Effect of Termination.  Upon termination, You agree to
+   immediately stop any further use, reproduction, modification and
+   distribution of the Covered Code, or Affected Original Code in the
+   case of termination under Section 9.1, and to destroy all copies of
+   the Covered Code or Affected Original Code (in the case of
+   termination under Section 9.1) that are in your possession or
+   control.  All sublicenses to the Covered Code which have been
+   properly granted prior to termination shall survive any termination
+   of this License.  Provisions which, by their nature, should remain
+   in effect beyond the termination of this License shall survive,
+   including but not limited to Sections 3, 5, 8, 9, 10, 11, 12.2 and
+   13.  Neither party will be liable to the other for compensation,
+   indemnity or damages of any sort solely as a result of terminating
+   this License in accordance with its terms, and termination of this
+   License will be without prejudice to any other right or remedy of
+   either party.
+
+13.  Miscellaneous.
+
+13.1 Export Law Assurances.  You may not use or otherwise export or
+   re-export the Original Code except as authorized by United States
+   law and the laws of the jurisdiction in which the Original Code was
+   obtained.  In particular, but without limitation, the Original Code
+   may not be exported or re-exported (a) into (or to a national or
+   resident of) any U.S. embargoed country or (b) to anyone on the
+   U.S. Treasury Department's list of Specially Designated Nationals
+   or the U.S. Department of Commerce's Table of Denial Orders.  By
+   using the Original Code, You represent and warrant that You are not
+   located in, under control of, or a national or resident of any such
+   country or on any such list.
+
+13.2 Government End Users.  The Covered Code is a "commercial item" as
+   defined in FAR 2.101.  Government software and technical data
+   rights in the Covered Code include only those rights customarily
+   provided to the public as defined in this License. This customary
+   commercial license in technical data and software is provided in
+   accordance with FAR 12.211 (Technical Data) and 12.212 (Computer
+   Software) and, for Department of Defense purchases, DFAR
+   252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3
+   (Rights in Commercial Computer Software or Computer Software
+   Documentation).  Accordingly, all U.S. Government End Users acquire
+   Covered Code with only those rights set forth herein.
+
+13.3 Relationship of Parties.  This License will not be construed as
+   creating an agency, partnership, joint venture or any other form of
+   legal association between You and Apple, and You will not represent
+   to the contrary, whether expressly, by implication, appearance or
+   otherwise.
+
+13.4 Independent Development.  Nothing in this License will impair
+   Apple's right to acquire, license, develop, have others develop for
+   it, market and/or distribute technology or products that perform
+   the same or similar functions as, or otherwise compete with,
+   Modifications, Larger Works, technology or products that You may
+   develop, produce, market or distribute.
+
+13.5 Waiver; Construction.  Failure by Apple to enforce any provision
+   of this License will not be deemed a waiver of future enforcement
+   of that or any other provision.  Any law or regulation which
+   provides that the language of a contract shall be construed against
+   the drafter will not apply to this License.
+
+13.6 Severability.  (a) If for any reason a court of competent
+   jurisdiction finds any provision of this License, or portion
+   thereof, to be unenforceable, that provision of the License will be
+   enforced to the maximum extent permissible so as to effect the
+   economic benefits and intent of the parties, and the remainder of
+   this License will continue in full force and effect.  (b)
+   Notwithstanding the foregoing, if applicable law prohibits or
+   restricts You from fully and/or specifically complying with
+   Sections 2 and/or 3 or prevents the enforceability of either of
+   those Sections, this License will immediately terminate and You
+   must immediately discontinue any use of the Covered Code and
+   destroy all copies of it that are in your possession or control.
+
+13.7 Dispute Resolution.  Any litigation or other dispute resolution
+   between You and Apple relating to this License shall take place in
+   the Northern District of California, and You and Apple hereby
+   consent to the personal jurisdiction of, and venue in, the state
+   and federal courts within that District with respect to this
+   License. The application of the United Nations Convention on
+   Contracts for the International Sale of Goods is expressly
+   excluded.
+
+13.8 Entire Agreement; Governing Law.  This License constitutes the
+   entire agreement between the parties with respect to the subject
+   matter hereof.  This License shall be governed by the laws of the
+   United States and the State of California, except that body of
+   California law concerning conflicts of law.
+
+Where You are located in the province of Quebec, Canada, the following
+clause applies: The parties hereby confirm that they have requested
+that this License and all related documents be drafted in English. Les
+parties ont exige que le present contrat et tous les documents
+connexes soient rediges en anglais.
+
+EXHIBIT A. 
+
+"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."
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6a01016
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,60 @@
+#
+# 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 = 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
+
+LIBRARIES = dp_notify_lib
+
+LEGACIES = fastboot.tproj nologin.tproj pagesize.tproj
+
+OTHERSRCS = Makefile.preamble Makefile README.rtf APPLE_LICENSE
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = aggregate.make
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/Makefile.preamble b/Makefile.preamble
new file mode 100644 (file)
index 0000000..b15052f
--- /dev/null
@@ -0,0 +1,2 @@
+CLEAN_ALL_SUBPROJECTS = YES
+SUBPROJECTS = 
diff --git a/PB.project b/PB.project
new file mode 100644 (file)
index 0000000..295cf6e
--- /dev/null
@@ -0,0 +1,79 @@
+{
+    English_RESOURCES = {}; 
+    FILESTABLE = {
+        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 = (); 
+        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
+        ); 
+    }; 
+    LANGUAGE = English; 
+    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; 
+    PROJECTTYPE = Aggregate; 
+    PROJECTVERSION = 2.8; 
+    TARGETS = (); 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/README.rtf b/README.rtf
new file mode 100644 (file)
index 0000000..a8eb014
--- /dev/null
@@ -0,0 +1,31 @@
+{\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\
+
+\b0 \
+cgore\
+       <a.out.h>\
+\
+iostat\
+       names.c missing\
+       \
+kdump\
+       /sys/kern/syscalls.c missing\
+\
+kvm_mkdb\
+       KERNBASE undeclared\
+\
+mach_swapon\
+       <bsd/sys/table.h> not found\
+       \
+savecore\
+       KERNBASE undeclared\
+\
+vmstat\
+
+\i     <vm/vm.h> not found\
+
+}
diff --git a/ac.tproj/Makefile b/ac.tproj/Makefile
new file mode 100644 (file)
index 0000000..31dfe34
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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 = ac
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = ac.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ac.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ac.tproj/Makefile.postamble b/ac.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..70b747f
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/ac.tproj/Makefile.preamble b/ac.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..fc1c649
--- /dev/null
@@ -0,0 +1,112 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+#OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/ac.tproj/PB.project b/ac.tproj/PB.project
new file mode 100644 (file)
index 0000000..7e31b83
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ac.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ac.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ac; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ac.tproj/ac.8 b/ac.tproj/ac.8
new file mode 100644 (file)
index 0000000..0c834a7
--- /dev/null
@@ -0,0 +1,107 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"     @(#)ac.8       8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt AC 8
+.Os BSD 4
+.Sh NAME
+.Nm ac
+.Nd display connect time accounting
+.Sh SYNOPSIS
+.Nm ac
+.Op Fl d
+.Op Fl p
+.Op Fl w Ar file
+.Op Ar users ...
+.Sh DESCRIPTION
+If the file
+.Pa /var/log/wtmp
+exists,
+a record of individual
+login and logout times are written to it by
+.Xr init 8
+and
+.Xr login 8
+respectively.
+The program
+.Nm ac
+examines these
+records and writes the accumulated connect time for all logins to the
+standard output.
+.Pp
+Options available:
+.Bl -tag -width people
+.It Fl d
+Display the connect times in 24 hour chunks.
+.It Fl p
+Display individual user totals.
+.It Fl w Ar file
+Read raw connect time data from
+.Ar file
+instead of the default file
+.Pa /var/log/wtmp .
+.It Ar users ...
+Display totals for the given individuals
+only.
+.El
+.Pp
+If no arguments are given,
+.Nm
+displays the total amount of login time for all active accounts on the
+system.
+.Pp
+The default
+.Pa wtmp
+file is an infinitely increasing file
+unless frequently truncated.  This is normally
+done by the daily daemon scripts scheduled by
+.Xr cron 8
+which rename and rotate the
+.Pa wtmp
+files before truncating them (and keeping about a weeks worth on hand).
+No login times are collected however, if the file does not exist.
+.Sh FILES
+.Bl -tag -width /var/log/wtmp.[0-7] -compact
+.It Pa /var/log/wtmp
+.It Pa /var/log/wtmp.[0-7]
+rotated files
+.El
+.Sh SEE ALSO
+.Xr init 8 ,
+.Xr sa 8 ,
+.Xr login 1 ,
+.Xr utmp 5 .
+.Sh HISTORY
+A
+.Nm
+command appeared in Version 6 AT&T UNIX.
diff --git a/ac.tproj/ac.c b/ac.tproj/ac.c
new file mode 100644 (file)
index 0000000..f23915c
--- /dev/null
@@ -0,0 +1,580 @@
+/*
+ * 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) 1994 Christopher G. Demetriou.
+ *      @(#)Copyright (c) 1994, Simon J. Gerraty.
+ *      
+ *      This is free software.  It comes with NO WARRANTY.
+ *      Permission to use, modify and distribute this source code 
+ *      is granted subject to the following conditions.
+ *      1/ that the above copyright notice and this notice 
+ *      are preserved in all copies and that due credit be given 
+ *      to the author.  
+ *      2/ that any changes to this code are clearly commented 
+ *      as such so that the author does not get blamed for bugs 
+ *      other than his own.
+ */
+
+#ifndef lint
+static char rcsid[] = "$Id: ac.c,v 1.1.1.2 2000/01/11 02:09:57 wsanchez Exp $";
+#endif
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <err.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utmp.h>
+#include <unistd.h>
+
+/*
+ * this is for our list of currently logged in sessions
+ */
+struct utmp_list {
+       struct utmp_list *next;
+       struct utmp usr;
+};
+
+/*
+ * this is for our list of users that are accumulating time.
+ */
+struct user_list {
+       struct user_list *next;
+       char    name[UT_NAMESIZE+1];
+       time_t  secs;
+};
+
+/*
+ * this is for chosing whether to ignore a login
+ */
+struct tty_list {
+       struct tty_list *next;
+       char    name[UT_LINESIZE+3];
+       int     len;
+       int     ret;
+};
+
+/*
+ * globals - yes yuk
+ */
+#ifdef CONSOLE_TTY
+static char    *Console = CONSOLE_TTY;
+#endif
+static time_t  Total = 0;
+static time_t  FirstTime = 0;
+static int     Flags = 0;
+static struct user_list *Users = NULL;
+static struct tty_list *Ttys = NULL;
+
+#define NEW(type) (type *)malloc(sizeof (type))
+
+#define        AC_W    1                               /* not _PATH_WTMP */
+#define        AC_D    2                               /* daily totals (ignore -p) */
+#define        AC_P    4                               /* per-user totals */
+#define        AC_U    8                               /* specified users only */
+#define        AC_T    16                              /* specified ttys only */
+
+#ifdef DEBUG
+static int Debug = 0;
+#endif
+
+int                    main __P((int, char **));
+int                    ac __P((FILE *));
+struct tty_list                *add_tty __P((char *));
+int                    do_tty __P((char *));
+FILE                   *file __P((char *));
+struct utmp_list       *log_in __P((struct utmp_list *, struct utmp *));
+struct utmp_list       *log_out __P((struct utmp_list *, struct utmp *));
+int                    on_console __P((struct utmp_list *));
+void                   show __P((char *, time_t));
+void                   show_today __P((struct user_list *, struct utmp_list *,
+                           time_t));
+void                   show_users __P((struct user_list *));
+struct user_list       *update_user __P((struct user_list *, char *, time_t));
+void                   usage __P((void));
+
+/*
+ * open wtmp or die
+ */
+FILE *
+file(name)
+       char *name;
+{
+       FILE *fp;
+
+       if ((fp = fopen(name, "r")) == NULL)
+               err(1, "%s", name);
+       /* in case we want to discriminate */
+       if (strcmp(_PATH_WTMP, name))
+               Flags |= AC_W;
+       return fp;
+}
+
+struct tty_list *
+add_tty(name)
+       char *name;
+{
+       struct tty_list *tp;
+       register char *rcp;
+
+       Flags |= AC_T;
+       
+       if ((tp = NEW(struct tty_list)) == NULL)
+               err(1, "malloc");
+       tp->len = 0;                            /* full match */
+       tp->ret = 1;                            /* do if match */
+       if (*name == '!') {                     /* don't do if match */
+               tp->ret = 0;
+               name++;
+       }
+       (void)strncpy(tp->name, name, sizeof (tp->name) - 1);
+       tp->name[sizeof (tp->name) - 1] = '\0';
+       if ((rcp = strchr(tp->name, '*')) != NULL) {    /* wild card */
+               *rcp = '\0';
+               tp->len = strlen(tp->name);     /* match len bytes only */
+       }
+       tp->next = Ttys;
+       Ttys = tp;
+       return Ttys;
+}
+
+/*
+ * should we process the named tty?
+ */
+int
+do_tty(name)
+       char *name;
+{
+       struct tty_list *tp;
+       int def_ret = 0;
+       
+       for (tp = Ttys; tp != NULL; tp = tp->next) {
+               if (tp->ret == 0)               /* specific don't */
+                       def_ret = 1;            /* default do */
+               if (tp->len != 0) {
+                       if (strncmp(name, tp->name, tp->len) == 0)
+                               return tp->ret;
+               } else {
+                       if (strncmp(name, tp->name, sizeof (tp->name)) == 0)
+                               return tp->ret;
+               }
+       }
+       return def_ret;
+}
+
+#ifdef CONSOLE_TTY
+/*
+ * is someone logged in on Console?
+ */
+int
+on_console(head)
+       struct utmp_list *head;
+{
+       struct utmp_list *up;
+
+       for (up = head; up; up = up->next) {
+               if (strncmp(up->usr.ut_line, Console,
+                   sizeof (up->usr.ut_line)) == 0)
+                       return 1;
+       }
+       return 0;
+}
+#endif
+
+/*
+ * update user's login time
+ */
+struct user_list *
+update_user(head, name, secs)
+       struct user_list *head;
+       char    *name;
+       time_t  secs;
+{
+       struct user_list *up;
+
+       for (up = head; up != NULL; up = up->next) {
+               if (strncmp(up->name, name, sizeof (up->name)) == 0) {
+                       up->secs += secs;
+                       Total += secs;
+                       return head;
+               }
+       }
+       /*
+        * not found so add new user unless specified users only
+        */
+       if (Flags & AC_U)
+               return head;
+       
+       if ((up = NEW(struct user_list)) == NULL)
+               err(1, "malloc");
+       up->next = head;
+       (void)strncpy(up->name, name, sizeof (up->name) - 1);
+       up->name[sizeof (up->name) - 1] = '\0'; /* paranoid! */
+       up->secs = secs;
+       Total += secs;
+       return up;
+}
+
+int
+main(argc, argv)
+       int     argc;
+       char    **argv;
+{
+       FILE *fp;
+       int c;
+
+       fp = NULL;
+       while ((c = getopt(argc, argv, "Dc:dpt:w:")) != EOF) {
+               switch (c) {
+#ifdef DEBUG
+               case 'D':
+                       Debug++;
+                       break;
+#endif
+               case 'c':
+#ifdef CONSOLE_TTY
+                       Console = optarg;
+#else
+                       usage();                /* XXX */
+#endif
+                       break;
+               case 'd':
+                       Flags |= AC_D;
+                       break;
+               case 'p':
+                       Flags |= AC_P;
+                       break;
+               case 't':                       /* only do specified ttys */
+                       add_tty(optarg);
+                       break;
+               case 'w':
+                       fp = file(optarg);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       break;
+               }
+       }
+       if (optind < argc) {
+               /*
+                * initialize user list
+                */
+               for (; optind < argc; optind++) {
+                       Users = update_user(Users, argv[optind], 0L);
+               }
+               Flags |= AC_U;                  /* freeze user list */
+       }
+       if (Flags & AC_D)
+               Flags &= ~AC_P;
+       if (fp == NULL) {
+               /*
+                * if _PATH_WTMP does not exist, exit quietly
+                */
+               if (access(_PATH_WTMP, 0) != 0 && errno == ENOENT)
+                       return 0;
+               
+               fp = file(_PATH_WTMP);
+       }
+       ac(fp);
+       
+       return 0;
+}
+
+/*
+ * print login time in decimal hours
+ */
+void
+show(name, secs)
+       char *name;
+       time_t secs;
+{
+       (void)printf("\t%-*s %8.2f\n", UT_NAMESIZE, name,
+           ((double)secs / 3600));
+}
+
+void
+show_users(list)
+       struct user_list *list;
+{
+       struct user_list *lp;
+
+       for (lp = list; lp; lp = lp->next)
+               show(lp->name, lp->secs);
+}
+
+/*
+ * print total login time for 24hr period in decimal hours
+ */
+void
+show_today(users, logins, secs)
+       struct user_list *users;
+       struct utmp_list *logins;
+       time_t secs;
+{
+       struct user_list *up;
+       struct utmp_list *lp;
+       char date[64];
+       time_t yesterday = secs - 1;
+
+       (void)strftime(date, sizeof (date), "%b %e  total",
+           localtime(&yesterday));
+
+       /* restore the missing second */
+       yesterday++;
+       
+       for (lp = logins; lp != NULL; lp = lp->next) {
+               secs = yesterday - lp->usr.ut_time;
+               Users = update_user(Users, lp->usr.ut_name, secs);
+               lp->usr.ut_time = yesterday;    /* as if they just logged in */
+       }
+       secs = 0;
+       for (up = users; up != NULL; up = up->next) {
+               secs += up->secs;
+               up->secs = 0;                   /* for next day */
+       }
+       if (secs)
+               (void)printf("%s %11.2f\n", date, ((double)secs / 3600));
+}
+
+/*
+ * log a user out and update their times.
+ * if ut_line is "~", we log all users out as the system has
+ * been shut down.
+ */
+struct utmp_list *
+log_out(head, up)
+       struct utmp_list *head;
+       struct utmp *up;
+{
+       struct utmp_list *lp, *lp2, *tlp;
+       time_t secs;
+       
+       for (lp = head, lp2 = NULL; lp != NULL; )
+               if (*up->ut_line == '~' || strncmp(lp->usr.ut_line, up->ut_line,
+                   sizeof (up->ut_line)) == 0) {
+                       secs = up->ut_time - lp->usr.ut_time;
+                       Users = update_user(Users, lp->usr.ut_name, secs);
+#ifdef DEBUG
+                       if (Debug)
+                               printf("%-.*s %-.*s: %-.*s logged out (%2d:%02d:%02d)\n",
+                                   19, ctime(&up->ut_time),
+                                   sizeof (lp->usr.ut_line), lp->usr.ut_line,
+                                   sizeof (lp->usr.ut_name), lp->usr.ut_name,
+                                   secs / 3600, (secs % 3600) / 60, secs % 60);
+#endif
+                       /*
+                        * now lose it
+                        */
+                       tlp = lp;
+                       lp = lp->next;
+                       if (tlp == head)
+                               head = lp;
+                       else if (lp2 != NULL)
+                               lp2->next = lp;
+                       free(tlp);
+               } else {
+                       lp2 = lp;
+                       lp = lp->next;
+               }
+       return head;
+}
+
+
+/*
+ * if do_tty says ok, login a user
+ */
+struct utmp_list *
+log_in(head, up)
+       struct utmp_list *head;
+       struct utmp *up;
+{
+       struct utmp_list *lp;
+
+       /*
+        * this could be a login. if we're not dealing with
+        * the console name, say it is.
+        *
+        * If we are, and if ut_host==":0.0" we know that it
+        * isn't a real login. _But_ if we have not yet recorded
+        * someone being logged in on Console - due to the wtmp
+        * file starting after they logged in, we'll pretend they
+        * logged in, at the start of the wtmp file.
+        */
+
+#ifdef CONSOLE_TTY
+       if (up->ut_host[0] == ':') {
+               /*
+                * SunOS 4.0.2 does not treat ":0.0" as special but we
+                * do. 
+                */
+               if (on_console(head))
+                       return head;
+               /*
+                * ok, no recorded login, so they were here when wtmp
+                * started!  Adjust ut_time! 
+                */
+               up->ut_time = FirstTime;
+               /*
+                * this allows us to pick the right logout
+                */
+               (void)strncpy(up->ut_line, Console, sizeof (up->ut_line) - 1);
+               up->ut_line[sizeof (up->ut_line) - 1] = '\0'; /* paranoid! */
+       }
+#endif
+       /*
+        * If we are doing specified ttys only, we ignore
+        * anything else.
+        */
+       if (Flags & AC_T)
+               if (!do_tty(up->ut_line))
+                       return head;
+
+       /*
+        * go ahead and log them in
+        */
+       if ((lp = NEW(struct utmp_list)) == NULL)
+               err(1, "malloc");
+       lp->next = head;
+       head = lp;
+       memmove((char *)&lp->usr, (char *)up, sizeof (struct utmp));
+#ifdef DEBUG
+       if (Debug) {
+               printf("%-.*s %-.*s: %-.*s logged in", 19,
+                   ctime(&lp->usr.ut_time), sizeof (up->ut_line),
+                      up->ut_line, sizeof (up->ut_name), up->ut_name);
+               if (*up->ut_host)
+                       printf(" (%-.*s)", sizeof (up->ut_host), up->ut_host);
+               putchar('\n');
+       }
+#endif
+       return head;
+}
+
+int
+ac(fp)
+       FILE    *fp;
+{
+       struct utmp_list *lp, *head = NULL;
+       struct utmp usr;
+       struct tm *ltm;
+       time_t secs = 0;
+       int day = -1;
+       
+       while (fread((char *)&usr, sizeof(usr), 1, fp) == 1) {
+               if (!FirstTime)
+                       FirstTime = usr.ut_time;
+               if (Flags & AC_D) {
+                       ltm = localtime(&usr.ut_time);
+                       if (day >= 0 && day != ltm->tm_yday) {
+                               day = ltm->tm_yday;
+                               /*
+                                * print yesterday's total
+                                */
+                               secs = usr.ut_time;
+                               secs -= ltm->tm_sec;
+                               secs -= 60 * ltm->tm_min;
+                               secs -= 3600 * ltm->tm_hour;
+                               show_today(Users, head, secs);
+                       } else
+                               day = ltm->tm_yday;
+               }
+               switch(*usr.ut_line) {
+               case '|':
+                       secs = usr.ut_time;
+                       break;
+               case '{':
+                       secs -= usr.ut_time;
+                       /*
+                        * adjust time for those logged in
+                        */
+                       for (lp = head; lp != NULL; lp = lp->next)
+                               lp->usr.ut_time -= secs;
+                       break;
+               case '~':                       /* reboot or shutdown */
+                       head = log_out(head, &usr);
+                       FirstTime = usr.ut_time; /* shouldn't be needed */
+                       break;
+               default:
+                       /*
+                        * if they came in on tty[p-y]*, then it is only
+                        * a login session if the ut_host field is non-empty
+                        */
+                       if (*usr.ut_name) {
+                               if (strncmp(usr.ut_line, "tty", 3) != 0 ||
+                                   strchr("pqrstuvwxy", usr.ut_line[3]) == 0 ||
+                                   *usr.ut_host != '\0')
+                                       head = log_in(head, &usr);
+                       } else
+                               head = log_out(head, &usr);
+                       break;
+               }
+       }
+       (void)fclose(fp);
+       usr.ut_time = time((time_t *)0);
+       (void)strcpy(usr.ut_line, "~");
+       
+       if (Flags & AC_D) {
+               ltm = localtime(&usr.ut_time);
+               if (day >= 0 && day != ltm->tm_yday) {
+                       /*
+                        * print yesterday's total
+                        */
+                       secs = usr.ut_time;
+                       secs -= ltm->tm_sec;
+                       secs -= 60 * ltm->tm_min;
+                       secs -= 3600 * ltm->tm_hour;
+                       show_today(Users, head, secs);
+               }
+       }
+       /*
+        * anyone still logged in gets time up to now
+        */
+       head = log_out(head, &usr);
+
+       if (Flags & AC_D)
+               show_today(Users, head, time((time_t *)0));
+       else {
+               if (Flags & AC_P)
+                       show_users(Users);
+               show("total", Total);
+       }
+       return 0;
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr,
+#ifdef CONSOLE_TTY
+           "ac [-dp] [-c console] [-t tty] [-w wtmp] [users ...]\n");
+#else
+           "ac [-dp] [-t tty] [-w wtmp] [users ...]\n");
+#endif
+       exit(1);
+}
diff --git a/accton.tproj/Makefile b/accton.tproj/Makefile
new file mode 100644 (file)
index 0000000..1f7fe19
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = accton
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = accton.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/accton.tproj/Makefile.postamble b/accton.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..70b747f
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/accton.tproj/Makefile.preamble b/accton.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..1409816
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+#OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/accton.tproj/PB.project b/accton.tproj/PB.project
new file mode 100644 (file)
index 0000000..162e4d1
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (accton.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = accton; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/accton.tproj/accton.c b/accton.tproj/accton.c
new file mode 100644 (file)
index 0000000..723c336
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 char copyright[] =
+"@(#) Copyright (c) 1988, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)accton.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+void usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int ch;
+
+       while ((ch = getopt(argc, argv, "")) != EOF)
+               switch(ch) {
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       switch(argc) {
+       case 0: 
+               if (acct(NULL)) {
+                       (void)fprintf(stderr,
+                           "accton: %s\n", strerror(errno));
+                       exit(1);
+               }
+               break;
+       case 1:
+               if (acct(*argv)) {
+                       (void)fprintf(stderr,
+                           "accton: %s: %s\n", *argv, strerror(errno));
+                       exit(1);
+               }
+               break;
+       default:
+               usage();
+       }
+       exit(0);
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: accton [file]\n");
+       exit(1);
+}
diff --git a/arch.tproj/Makefile b/arch.tproj/Makefile
new file mode 100644 (file)
index 0000000..20bbb50
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# 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 = arch
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = arch.c
+
+OTHERSRCS = Makefile PB.project Makefile.postamble
+
+
+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)
+
+
+NEXTSTEP_PB_CFLAGS = -DARCH_PROG=\"arch\" -DMACHINE_PROG=\"machine\"
+WINDOWS_PB_CFLAGS = -DARCH_PROG=\"arch\" -DMACHINE_PROG=\"machine\"
+PDO_UNIX_PB_CFLAGS = -DARCH_PROG=\"arch\" -DMACHINE_PROG=\"machine\"
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/arch.tproj/Makefile.postamble b/arch.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..eaf5363
--- /dev/null
@@ -0,0 +1,3 @@
+after_install::
+       @-$(RM) -f $(DSTROOT)$(INSTALLDIR)/machine
+       ln $(DSTROOT)$(INSTALLDIR)/arch $(DSTROOT)$(INSTALLDIR)/machine
\ No newline at end of file
diff --git a/arch.tproj/PB.project b/arch.tproj/PB.project
new file mode 100644 (file)
index 0000000..86754f4
--- /dev/null
@@ -0,0 +1,35 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (arch.c); 
+        OTHER_SOURCES = (Makefile, PB.project, Makefile.postamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DARCH_PROG=\\\"arch\\\" -DMACHINE_PROG=\\\"machine\\\""; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = "-DARCH_PROG=\\\"arch\\\" -DMACHINE_PROG=\\\"machine\\\""; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = arch; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = "-DARCH_PROG=\\\"arch\\\" -DMACHINE_PROG=\\\"machine\\\""; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/arch.tproj/arch.c b/arch.tproj/arch.c
new file mode 100644 (file)
index 0000000..0e140fe
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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@
+ */
+/*
+ * arch.c - determine the architecture of the machine ran on
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <mach/mach.h>
+#include <mach-o/arch.h>
+
+char *
+  get_progname (char *name)
+{
+  char *tmp;
+  if (tmp = strrchr(name,'/'))
+    return tmp+1;
+  else return name;
+}
+
+int 
+  main (int argc, char **argv)
+{
+  char *progname;
+  const NXArchInfo *arch;
+
+  if (argc > 1)
+    {
+      fprintf (stderr,"*error: %s takes no arguments\n",argv[0]);
+      exit (-1);
+    }
+  arch = NXGetLocalArchInfo();
+  if (arch == NULL)
+    {
+      fprintf (stderr,"Unknown architecture.\n");
+      exit(-1);
+    }
+  progname = get_progname(argv[0]);
+  if (strcmp (progname,ARCH_PROG) == 0) {
+    arch = NXGetArchInfoFromCpuType(arch->cputype, CPU_SUBTYPE_MULTIPLE);
+    if (arch == NULL)
+    {
+       fprintf (stderr,"Unknown architecture.\n");
+       exit(-1);
+    }
+  }
+  else if (strcmp (progname,MACHINE_PROG) == 0)
+    ;
+  else
+    {
+      fprintf 
+       (stderr,"*error: This program must be named either %s or %s\n",ARCH_PROG,MACHINE_PROG);
+      exit (-1);
+    }
+  if (!isatty(fileno(stdin)))
+    printf("%s", arch->name);
+  else
+    printf ("%s\n", arch->name);
+    return 0;
+}
diff --git a/at.tproj/Makefile b/at.tproj/Makefile
new file mode 100644 (file)
index 0000000..c2335bf
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# 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 = at
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = at.h panic.h parsetime.h pathnames.h privs.h perm.h
+
+CFILES = at.c panic.c parsetime.c perm.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            at.1
+
+
+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)
+
+
+PROJECT_HEADERS = privs.h pathnames.h
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/at.tproj/Makefile.dist b/at.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..bdfa515
--- /dev/null
@@ -0,0 +1,15 @@
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 04:21:18 wsanchez Exp $
+
+PROG=  at
+SRCS=  at.c panic.c parsetime.c
+LINKS= ${BINDIR}/at ${BINDIR}/atq \
+       ${BINDIR}/at ${BINDIR}/atrm \
+       ${BINDIR}/at ${BINDIR}/batch
+MLINKS=        at.1 batch.1 \
+       at.1 atq.1 \
+       at.1 atrm.1
+
+BINOWN=        root
+BINMODE= 4555
+
+.include <bsd.prog.mk>
diff --git a/at.tproj/Makefile.postamble b/at.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..6f6d32b
--- /dev/null
@@ -0,0 +1,6 @@
+INSTALL_PERMISSIONS = 4555
+
+after_install::
+       $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/atq
+       $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/atrm
+       $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/batch
diff --git a/at.tproj/Makefile.preamble b/at.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/at.tproj/PB.project b/at.tproj/PB.project
new file mode 100644 (file)
index 0000000..d880b55
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (at.h, panic.h, parsetime.h, pathnames.h, privs.h, perm.h); 
+        OTHER_LINKED = (at.c, panic.c, parsetime.c, perm.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, at.1); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (privs.h, pathnames.h); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = at; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/at.tproj/at.1 b/at.tproj/at.1
new file mode 100644 (file)
index 0000000..f8869ca
--- /dev/null
@@ -0,0 +1,216 @@
+.\"
+.\" Copyright (c) 1993 Christopher G. Demetriou
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Christopher G. Demetriou.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\"    $Id: at.1,v 1.1.1.1 1999/05/02 04:21:18 wsanchez Exp $
+.\"
+.Dd December 5, 1993
+.Dt "AT" 1
+.Os NetBSD 0.9a
+.Sh NAME
+.Nm at, batch, atq, atrm
+.Nd queue, examine, or delete jobs for later execution
+.\"
+.Sh SYOPSIS
+.Nm at
+.Op Fl q Ar queue
+.Op Fl f Ar file
+.Op Fl m
+.Ar time
+.Pp
+.Nm atq
+.Op Fl q Ar queue
+.Op Fl v
+.Pp
+.Nm atrm
+.Ar job
+.Op Ar job ...
+.Pp
+.Nm batch
+.Op Fl f Ar file
+.Op Fl m
+.Ar time
+.Sh DESCRIPTION
+The
+.Nm at
+and
+.Nm batch
+utilities read commands from the standard input or a specified file
+which are to be executed at a later time, using
+.Xr sh 1 .
+.Pp
+The functions of the commands are as follows:
+.Bl -tag -width indent
+.It Nm at
+Executes commands at a specified time.
+.It Nm atq
+Lists the user's pending jobs, unless the user is
+the superuser.  In that case, everybody's jobs are
+listed.
+.It Nm atrm
+Deletes jobs.
+.It Nm batch
+executes commands when system load levels  permit.
+In other words, it executes the commands when the load
+average drops below a specified level.
+.El
+.Pp
+For both
+.Nm at
+and
+.Nm batch ,
+the working directory, environment (except for the variables
+.Nm TERM ,
+.Nm TERMCAP ,
+.Nm DISPLAY ,
+and
+.Nm _ )
+and the umask are retained from the time of invocation.  The user
+will be mailed the standard output and standard error from
+his commands if any output is generated.  If
+.Nm at
+is executed from a
+.Xr su 1
+shell, the owner of the login shell will receive the mail.
+.Sh OPTIONS
+.Bl -tag -width indent
+The available options are as follows:
+.It Fl q Ar queue
+Use the specified queue.  A queue designation consists
+of a single letter; valid queue designation range from
+.Ar a
+to
+.Ar l .
+The
+.Ar a
+queue is the default, and
+.Ar b
+is the batch queue.  Queues with higher letters run with
+increased niceness.  If
+.Nm atq
+is given a specific queue, it will only show jobs pending
+in that queue.
+.It Fl m
+Send mail to the user when the job has completed, even if
+there was no output.
+.It Fl f Ar file
+Reads the job from
+.Ar file
+rather than the standard input.
+.It Fl v
+Shows completed but not yet deleted jobs in the queue.
+.Sh TIME SPECIFICATION
+.Nm At
+allows some moderately complex time specifications.
+It accepts times of the form
+.Ar HHMM
+or
+.Ar HH:MM
+to run a job at a specific time of day.  If
+that time is already passed, the next day is assumed.
+You may also specify
+.Nm midnight ,
+.Nm noon ,
+or
+.Nm teatime
+(4PM) and you can give a time of day suffixed with
+.Nm AM
+or
+.Nm PM
+for running in the morning or the evening.  You can
+also specify the date on which the job will be run
+by giving a date in the form
+.Ar month-name day
+with an optional
+.Ar year ,
+or giving a date of the form
+.Ar MMDDYY ,
+.Ar MM/DD/YY
+or
+.Ar DD.MM.YY .
+You can also give times like
+.Nm now +
+.Ar count time-units ,
+where the time units can be
+.Nm minutes, hours, days,
+or
+.Nm weeks
+You can suffix the time with
+.Nm today
+to run the job today, or
+.Nm tomorrow
+to run the job tomorrow.
+.Pp
+For example, to run a job at 4PM three days from now, you
+would specify a time of
+.Nm 4PM + 3 days .
+To run a job at 10:00AM on on July 31, you would specify
+a time of
+.Nm 10AM Jul 31 .
+Finally, to run a job at 1AM tomorrow, you would specify
+a time of
+.Nm 1AM tomorrow .
+.Sh FILES
+.Bl -tag -width /var/at/lockfile -compact
+.It Pa /var/at/jobs
+Directory containing job files
+.It Pa /var/at/spool
+Directory containing output spool files
+.It Pa /var/at/lockfile
+Job-creation lock file.
+.It Pa /var/run/utmp
+.El
+.Sh SEE ALSO
+.Xr crond 8 ,
+.Xr nice 1 ,
+.Xr sh 1 ,
+.Xr atrun 8
+.Sh AUTHOR
+.Bl -tag
+Thomas Koenig, ig25@rz.uni-karlsruhe.de
+.El
+.Sh BUGS
+Traditional access control to
+.Nm at
+and
+.Nm batch
+via the files
+.Pa /var/at/at.allow
+and
+.Pa /var/at/at.deny
+is not implemented.
+.Pp
+If the file
+.Pa /var/run/utmp
+is not available or corrupted, or if the user is not
+logged in at the time
+.Nm at
+is invoked, the mail is sent to the userid found in the
+environment variable
+.Nm LOGNAME .
+If that is undefined or empty, the current userid is assumed.
diff --git a/at.tproj/at.c b/at.tproj/at.c
new file mode 100644 (file)
index 0000000..0caf2d1
--- /dev/null
@@ -0,0 +1,591 @@
+/*
+ * 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@
+ */
+/*
+ * at.c : Put file into atrun queue
+ * Copyright (C) 1993  Thomas Koenig
+ *
+ * Atrun & Atq modifications
+ * Copyright (C) 1993  David Parsons
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define _USE_BSD 1
+
+/* System Headers */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+/* Local headers */
+#include "at.h"
+#include "panic.h"
+#include "parsetime.h"
+#include "pathnames.h"
+#define MAIN
+#include "privs.h"
+#include "perm.h"
+
+/* Macros */
+#define ALARMC 10              /* Number of seconds to wait for timeout */
+
+#define SIZE 255
+#define TIMESIZE 50
+
+/* File scope variables */
+static char rcsid[] = "$Id: at.c,v 1.1.1.2 2000/01/11 02:10:04 wsanchez Exp $";
+char *no_export[] =
+{
+       "TERM", "TERMCAP", "DISPLAY", "_"
+};
+static send_mail = 0;
+
+/* External variables */
+extern char **environ;
+int fcreated;
+char *namep;
+char atfile[FILENAME_MAX];
+
+char *atinput = (char *) 0;    /* where to get input from */
+char atqueue = 0;              /* which queue to examine for jobs (atq) */
+char atverify = 0;             /* verify time instead of queuing job */
+
+/* Function declarations */
+static void sigc       __P((int signo));
+static void alarmc     __P((int signo));
+static char *cwdname   __P((void));
+static void writefile  __P((time_t runtimer, char queue));
+static void list_jobs  __P((void));
+
+/* Signal catching functions */
+
+static void 
+sigc(signo)
+       int signo;
+{
+/* If the user presses ^C, remove the spool file and exit
+ */
+       if (fcreated) {
+               PRIV_START
+               unlink(atfile);
+               PRIV_END
+       }
+
+       exit(EXIT_FAILURE);
+}
+
+static void 
+alarmc(signo)
+       int signo;
+{
+/* Time out after some seconds
+ */
+       panic("File locking timed out");
+}
+
+/* Local functions */
+
+static char *
+cwdname()
+{
+/* Read in the current directory; the name will be overwritten on
+ * subsequent calls.
+ */
+       static char *ptr = NULL;
+       static size_t size = SIZE;
+
+       if (ptr == NULL)
+               ptr = (char *) malloc(size);
+
+       while (1) {
+               if (ptr == NULL)
+                       panic("Out of memory");
+
+               if (getcwd(ptr, size - 1) != NULL)
+                       return ptr;
+
+               if (errno != ERANGE)
+                       perr("Cannot get directory");
+
+               free(ptr);
+               size += SIZE;
+               ptr = (char *) malloc(size);
+       }
+}
+
+static void
+writefile(runtimer, queue)
+       time_t runtimer;
+       char queue;
+{
+       /*
+        * This does most of the work if at or batch are invoked for
+        * writing a job.
+        */
+       int i;
+       char *ap, *ppos, *mailname;
+       struct passwd *pass_entry;
+       struct stat statbuf;
+       int fdes, lockdes, fd2;
+       FILE *fp, *fpin;
+       struct sigaction act;
+       char **atenv;
+       int ch;
+       mode_t cmask;
+       struct flock lock;
+
+       /*
+        * Install the signal handler for SIGINT; terminate after removing the
+        * spool file if necessary
+        */
+       act.sa_handler = sigc;
+       sigemptyset(&(act.sa_mask));
+       act.sa_flags = 0;
+
+       sigaction(SIGINT, &act, NULL);
+
+       strcpy(atfile, _PATH_ATJOBS);
+       ppos = atfile + strlen(_PATH_ATJOBS);
+
+       /*
+        * Loop over all possible file names for running something at this
+        *  particular time, see if a file is there; the first empty slot at
+        *  any particular time is used.  Lock the file _PATH_LOCKFILE first
+        *  to make sure we're alone when doing this.
+        */
+
+       PRIV_START
+
+       if ((lockdes = open(_PATH_LOCKFILE, O_WRONLY | O_CREAT, 0600)) < 0)
+               perr2("Cannot open lockfile ", _PATH_LOCKFILE);
+
+       lock.l_type = F_WRLCK;
+       lock.l_whence = SEEK_SET;
+       lock.l_start = 0;
+       lock.l_len = 0;
+
+       act.sa_handler = alarmc;
+       sigemptyset(&(act.sa_mask));
+       act.sa_flags = 0;
+
+       /*
+        * Set an alarm so a timeout occurs after ALARMC seconds, in case
+        * something is seriously broken.
+        */
+       sigaction(SIGALRM, &act, NULL);
+       alarm(ALARMC);
+       fcntl(lockdes, F_SETLKW, &lock);
+       alarm(0);
+
+       for (i = 0; i < AT_MAXJOBS; i++) {
+               sprintf(ppos, "%c%8lx.%3x", queue,
+                   (unsigned long) (runtimer / 60), i);
+               for (ap = ppos; *ap != '\0'; ap++)
+                       if (*ap == ' ')
+                               *ap = '0';
+
+               if (stat(atfile, &statbuf) != 0) {
+                       if (errno == ENOENT)
+                               break;
+                       else
+                               perr2("Cannot access ", _PATH_ATJOBS);
+               }
+       }                       /* for */
+
+       if (i >= AT_MAXJOBS)
+               panic("Too many jobs already");
+
+       /*
+        * Create the file. The x bit is only going to be set after it has
+        * been completely written out, to make sure it is not executed in
+        * the meantime.  To make sure they do not get deleted, turn off
+        * their r bit.  Yes, this is a kluge.
+        */
+       cmask = umask(S_IRUSR | S_IWUSR | S_IXUSR);
+       if ((fdes = creat(atfile, O_WRONLY)) == -1)
+               perr("Cannot create atjob file");
+
+       if ((fd2 = dup(fdes)) < 0)
+               perr("Error in dup() of job file");
+
+       if (fchown(fd2, real_uid, -1) != 0)
+               perr("Cannot give away file");
+
+       PRIV_END
+
+       /*
+        * We no longer need suid root; now we just need to be able to
+        * write to the directory, if necessary.
+        */
+
+           REDUCE_PRIV(0);
+
+       /*
+        * We've successfully created the file; let's set the flag so it
+        * gets removed in case of an interrupt or error.
+        */
+       fcreated = 1;
+
+       /* Now we can release the lock, so other people can access it */
+       lock.l_type = F_UNLCK;
+       lock.l_whence = SEEK_SET;
+       lock.l_start = 0;
+       lock.l_len = 0;
+       fcntl(lockdes, F_SETLKW, &lock);
+       close(lockdes);
+
+       if ((fp = fdopen(fdes, "w")) == NULL)
+               panic("Cannot reopen atjob file");
+
+       /*
+        * Get the userid to mail to, first by trying getlogin(), which
+        * reads /etc/utmp, then from LOGNAME, finally from getpwuid().
+        */
+       mailname = getlogin();
+       if (mailname == NULL)
+               mailname = getenv("LOGNAME");
+
+       if ((mailname == NULL) || (mailname[0] == '\0')
+           || (strlen(mailname) > 8)) {
+               pass_entry = getpwuid(getuid());
+               if (pass_entry != NULL)
+                       mailname = pass_entry->pw_name;
+       }
+
+       if (atinput != (char *) NULL) {
+               fpin = freopen(atinput, "r", stdin);
+               if (fpin == NULL)
+                       perr("Cannot open input file");
+       }
+       fprintf(fp, "#! /bin/sh\n# mail %8s %d\n", mailname, send_mail);
+
+       /* Write out the umask at the time of invocation */
+       fprintf(fp, "umask %lo\n", (unsigned long) cmask);
+
+       /*
+        * Write out the environment. Anything that may look like a special
+        * character to the shell is quoted, except for \n, which is done
+        * with a pair of "'s.  Dont't export the no_export list (such as
+        * TERM or DISPLAY) because we don't want these.
+        */
+       for (atenv = environ; *atenv != NULL; atenv++) {
+               int export = 1;
+               char *eqp;
+
+               eqp = strchr(*atenv, '=');
+               if (ap == NULL)
+                       eqp = *atenv;
+               else {
+                       int i;
+
+                       for (i = 0;i < sizeof(no_export) /
+                           sizeof(no_export[0]); i++) {
+                               export = export
+                                   && (strncmp(*atenv, no_export[i],
+                                       (size_t) (eqp - *atenv)) != 0);
+                       }
+                       eqp++;
+               }
+
+               if (export) {
+                       fwrite(*atenv, sizeof(char), eqp - *atenv, fp);
+                       for (ap = eqp; *ap != '\0'; ap++) {
+                               if (*ap == '\n')
+                                       fprintf(fp, "\"\n\"");
+                               else {
+                                       if (!isalnum(*ap))
+                                               fputc('\\', fp);
+
+                                       fputc(*ap, fp);
+                               }
+                       }
+                       fputs("; export ", fp);
+                       fwrite(*atenv, sizeof(char), eqp - *atenv - 1, fp);
+                       fputc('\n', fp);
+
+               }
+       }
+       /*
+        * Cd to the directory at the time and write out all the commands
+        * the user supplies from stdin.
+        */
+       fprintf(fp, "cd %s\n", cwdname());
+
+       while ((ch = getchar()) != EOF)
+               fputc(ch, fp);
+
+       fprintf(fp, "\n");
+       if (ferror(fp))
+               panic("Output error");
+
+       if (ferror(stdin))
+               panic("Input error");
+
+       fclose(fp);
+
+       /*
+        * Set the x bit so that we're ready to start executing
+        */
+       if (fchmod(fd2, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
+               perr("Cannot give away file");
+
+       close(fd2);
+       fprintf(stderr, "Job %s will be executed using /bin/sh\n", ppos);
+}
+
+static void
+list_jobs()
+{
+       /*
+        * List all a user's jobs in the queue, by looping through
+        * _PATH_ATJOBS, or everybody's if we are root
+        */
+       struct passwd *pw;
+       DIR *spool;
+       struct dirent *dirent;
+       struct stat buf;
+       struct tm runtime;
+       unsigned long ctm;
+       char queue;
+       time_t runtimer;
+       char timestr[TIMESIZE];
+       int first = 1;
+
+       PRIV_START
+
+           if (chdir(_PATH_ATJOBS) != 0)
+               perr2("Cannot change to ", _PATH_ATJOBS);
+
+       if ((spool = opendir(".")) == NULL)
+               perr2("Cannot open ", _PATH_ATJOBS);
+
+       /* Loop over every file in the directory */
+       while ((dirent = readdir(spool)) != NULL) {
+               if (stat(dirent->d_name, &buf) != 0)
+                       perr2("Cannot stat in ", _PATH_ATJOBS);
+
+               /*
+                * See it's a regular file and has its x bit turned on and
+                * is the user's
+                */
+               if (!S_ISREG(buf.st_mode)
+                   || ((buf.st_uid != real_uid) && !(real_uid == 0))
+                   || !(S_IXUSR & buf.st_mode || atverify))
+                       continue;
+
+               if (sscanf(dirent->d_name, "%c%8lx", &queue, &ctm) != 2)
+                       continue;
+
+               if (atqueue && (queue != atqueue))
+                       continue;
+
+               runtimer = 60 * (time_t) ctm;
+               runtime = *localtime(&runtimer);
+               strftime(timestr, TIMESIZE, "%X %x", &runtime);
+               if (first) {
+                       printf("Date\t\t\tOwner\tQueue\tJob#\n");
+                       first = 0;
+               }
+               pw = getpwuid(buf.st_uid);
+
+               printf("%s\t%s\t%c%s\t%s\n",
+                   timestr,
+                   pw ? pw->pw_name : "???",
+                   queue,
+                   (S_IXUSR & buf.st_mode) ? "" : "(done)",
+                   dirent->d_name);
+       }
+       PRIV_END
+}
+
+static void
+delete_jobs(argc, argv)
+       int argc;
+       char **argv;
+{
+       /* Delete every argument (job - ID) given */
+       int i;
+       struct stat buf;
+
+       PRIV_START
+
+           if (chdir(_PATH_ATJOBS) != 0)
+               perr2("Cannot change to ", _PATH_ATJOBS);
+
+       for (i = optind; i < argc; i++) {
+               if (stat(argv[i], &buf) != 0)
+                       perr(argv[i]);
+               if ((buf.st_uid != real_uid) && !(real_uid == 0)) {
+                       fprintf(stderr, "%s: Not owner\n", argv[i]);
+                       exit(EXIT_FAILURE);
+               }
+               if (unlink(argv[i]) != 0)
+                       perr(argv[i]);
+       }
+       PRIV_END
+}                              /* delete_jobs */
+
+/* Global functions */
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       int c;
+       char queue = 'a';
+       char *pgm;
+
+       enum {
+               ATQ, ATRM, AT, BATCH
+       };                      /* what program we want to run */
+       int program = AT;       /* our default program */
+       char *options = "q:f:mv";       /* default options for at */
+       time_t timer;
+
+       RELINQUISH_PRIVS
+
+       /* Eat any leading paths */
+       if ((pgm = strrchr(argv[0], '/')) == NULL)
+               pgm = argv[0];
+       else
+               pgm++;
+
+       namep = pgm;
+
+       /* find out what this program is supposed to do */
+       if (strcmp(pgm, "atq") == 0) {
+               program = ATQ;
+               options = "q:v";
+       } else if (strcmp(pgm, "atrm") == 0) {
+               program = ATRM;
+               options = "";
+       } else if (strcmp(pgm, "batch") == 0) {
+               program = BATCH;
+               options = "f:mv";
+       }
+
+       /* process whatever options we can process */
+       opterr = 1;
+       while ((c = getopt(argc, argv, options)) != EOF)
+               switch (c) {
+               case 'v':       /* verify time settings */
+                       atverify = 1;
+                       break;
+
+               case 'm':       /* send mail when job is complete */
+                       send_mail = 1;
+                       break;
+
+               case 'f':
+                       atinput = optarg;
+                       break;
+
+               case 'q':       /* specify queue */
+                       if (strlen(optarg) > 1)
+                               usage();
+
+                       atqueue = queue = *optarg;
+                       if ((!islower(queue)) || (queue > 'l'))
+                               usage();
+                       break;
+
+               default:
+                       usage();
+                       break;
+               }
+       /* end of options eating */
+
+       /* select our program */
+       if (!check_permission())
+       {
+               fprintf(stderr, "You do not have permission to use %s.\n",namep);
+               exit(EXIT_FAILURE);
+       }  
+       switch (program) {
+       case ATQ:
+
+               REDUCE_PRIV(0);
+
+               list_jobs();
+               break;
+
+       case ATRM:
+
+               REDUCE_PRIV(0);
+
+               delete_jobs(argc, argv);
+               break;
+
+       case AT:
+               timer = parsetime(argc, argv);
+               if (atverify) {
+                       struct tm *tm = localtime(&timer);
+
+                       fprintf(stderr, "%s\n", asctime(tm));
+               }
+               writefile(timer, queue);
+               break;
+
+       case BATCH:
+               writefile(time(NULL), 'b');
+               break;
+
+       default:
+               panic("Internal error");
+               break;
+       }
+       exit(EXIT_SUCCESS);
+}
diff --git a/at.tproj/at.h b/at.tproj/at.h
new file mode 100644 (file)
index 0000000..117a547
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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@
+ */
+/*
+ * at.h -  header for at(1)
+ * Copyright (c) 1993 by Thomas Koenig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: at.h,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $
+ */
+
+extern int fcreated;
+extern char *namep;
+extern char atfile[];
+extern char atverify;
+
+#define AT_MAXJOBS     255     /* max jobs outstanding per user */
diff --git a/at.tproj/panic.c b/at.tproj/panic.c
new file mode 100644 (file)
index 0000000..839a54c
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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@
+ */
+/*
+ * panic.c - terminate fast in case of error
+ * Copyright (c) 1993 by Thomas Koenig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* System Headers */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Local headers */
+
+#include "panic.h"
+#include "at.h"
+
+/* File scope variables */
+
+static char rcsid[] = "$Id: panic.c,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $";
+
+/* External variables */
+
+/* Global functions */
+
+#ifdef __APPLE__
+__private_extern__
+#endif
+void
+panic(a)
+       char *a;
+{
+/* Something fatal has happened, print error message and exit.
+ */
+       fprintf(stderr, "%s: %s\n", namep, a);
+       if (fcreated)
+               unlink(atfile);
+
+       exit(EXIT_FAILURE);
+}
+
+void
+perr(a)
+       char *a;
+{
+/* Some operating system error; print error message and exit.
+ */
+       perror(a);
+       if (fcreated)
+               unlink(atfile);
+
+       exit(EXIT_FAILURE);
+}
+
+void 
+perr2(a, b)
+       char *a, *b;
+{
+       fprintf(stderr, "%s", a);
+       perr(b);
+}
+
+void
+usage(void)
+{
+/* Print usage and exit.
+*/
+       fprintf(stderr, "Usage: at [-q x] [-f file] [-m] time\n"
+           "       atq [-q x] [-v]\n"
+           "       atrm [-q x] job ...\n"
+           "       batch [-f file] [-m]\n");
+       exit(EXIT_FAILURE);
+}
diff --git a/at.tproj/panic.h b/at.tproj/panic.h
new file mode 100644 (file)
index 0000000..dda9212
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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@
+ */
+/*
+ * panic.h -  header for at(1)
+ * Copyright (c) 1993 Thomas Koenig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: panic.h,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $
+ */
+
+void panic     __P((char *a));
+void perr      __P((char *a));
+void perr2     __P((char *a, char *b));
+void usage     __P((void));
diff --git a/at.tproj/parsetime.c b/at.tproj/parsetime.c
new file mode 100644 (file)
index 0000000..46811fa
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * 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@
+ */
+/* 
+ * parsetime.c - parse time for at(1)
+ * Copyright (C) 1993  Thomas Koenig
+ *
+ * modifications for english-language times
+ * Copyright (C) 1993  David Parsons
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  at [NOW] PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS
+ *     /NUMBER [DOT NUMBER] [AM|PM]\ /[MONTH NUMBER [NUMBER]]             \
+ *     |NOON                       | |[TOMORROW]                          |
+ *     |MIDNIGHT                   | |NUMBER [SLASH NUMBER [SLASH NUMBER]]|
+ *     \TEATIME                    / \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/
+ */
+
+/* System Headers */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+
+/* Local headers */
+
+#include "at.h"
+#include "panic.h"
+
+
+/* Structures and unions */
+
+enum { /* symbols */
+    MIDNIGHT, NOON, TEATIME,
+    PM, AM, TOMORROW, TODAY, NOW,
+    MINUTES, HOURS, DAYS, WEEKS,
+    NUMBER, PLUS, DOT, SLASH, ID, JUNK,
+    JAN, FEB, MAR, APR, MAY, JUN,
+    JUL, AUG, SEP, OCT, NOV, DEC
+};
+
+/*
+ * parse translation table - table driven parsers can be your FRIEND!
+ */
+struct {
+    char *name;        /* token name */
+    int value; /* token id */
+} Specials[] = {
+    { "midnight", MIDNIGHT },  /* 00:00:00 of today or tomorrow */
+    { "noon", NOON },          /* 12:00:00 of today or tomorrow */
+    { "teatime", TEATIME },    /* 16:00:00 of today or tomorrow */
+    { "am", AM },              /* morning times for 0-12 clock */
+    { "pm", PM },              /* evening times for 0-12 clock */
+    { "tomorrow", TOMORROW },  /* execute 24 hours from time */
+    { "today", TODAY },                /* execute today - don't advance time */
+    { "now", NOW },            /* opt prefix for PLUS */
+
+    { "minute", MINUTES },     /* minutes multiplier */
+    { "min", MINUTES },
+    { "m", MINUTES },
+    { "minutes", MINUTES },    /* (pluralized) */
+    { "hour", HOURS },         /* hours ... */
+    { "hr", HOURS },           /* abbreviated */
+    { "h", HOURS },
+    { "hours", HOURS },                /* (pluralized) */
+    { "day", DAYS },           /* days ... */
+    { "d", DAYS },
+    { "days", DAYS },          /* (pluralized) */
+    { "week", WEEKS },         /* week ... */
+    { "w", WEEKS },
+    { "weeks", WEEKS },                /* (pluralized) */
+    { "jan", JAN },
+    { "feb", FEB },
+    { "mar", MAR },
+    { "apr", APR },
+    { "may", MAY },
+    { "jun", JUN },
+    { "jul", JUL },
+    { "aug", AUG },
+    { "sep", SEP },
+    { "oct", OCT },
+    { "nov", NOV },
+    { "dec", DEC }
+} ;
+
+/* File scope variables */
+
+static char **scp;     /* scanner - pointer at arglist */
+static char scc;       /* scanner - count of remaining arguments */
+static char *sct;      /* scanner - next char pointer in current argument */
+static int need;       /* scanner - need to advance to next argument */
+
+static char *sc_token; /* scanner - token buffer */
+static size_t sc_len;   /* scanner - lenght of token buffer */
+static int sc_tokid;   /* scanner - token id */
+
+static char rcsid[] = "$Id: parsetime.c,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $";
+
+/* Local functions */
+
+/*
+ * parse a token, checking if it's something special to us
+ */
+static int
+parse_token(arg)
+       char *arg;
+{
+    int i;
+
+    for (i=0; i<(sizeof Specials/sizeof Specials[0]); i++)
+       if (strcasecmp(Specials[i].name, arg) == 0) {
+           return sc_tokid = Specials[i].value;
+       }
+
+    /* not special - must be some random id */
+    return ID;
+} /* parse_token */
+
+
+/*
+ * init_scanner() sets up the scanner to eat arguments
+ */
+static void
+init_scanner(argc, argv)
+       int argc;
+       char **argv;
+{
+    scp = argv;
+    scc = argc;
+    need = 1;
+    sc_len = 1;
+    while (--argc > 0)
+       sc_len += strlen(*++argv);
+
+    sc_token = (char *) malloc(sc_len);
+    if (sc_token == NULL)
+       panic("Insufficient virtual memory");
+} /* init_scanner */
+
+/*
+ * token() fetches a token from the input stream
+ */
+static int
+token()
+{
+    int idx;
+
+    while (1) {
+       memset(sc_token, 0, sc_len);
+       sc_tokid = EOF;
+       idx = 0;
+
+       /*
+        * if we need to read another argument, walk along the argument list;
+        * when we fall off the arglist, we'll just return EOF forever
+        */
+       if (need) {
+           if (scc < 1)
+               return sc_tokid;
+           sct = *scp;
+           scp++;
+           scc--;
+           need = 0;
+       }
+       /*
+        * eat whitespace now - if we walk off the end of the argument,
+        * we'll continue, which puts us up at the top of the while loop
+        * to fetch the next argument in
+        */
+       while (isspace(*sct))
+           ++sct;
+       if (!*sct) {
+           need = 1;
+           continue;
+       }
+
+       /*
+        * preserve the first character of the new token
+        */
+       sc_token[0] = *sct++;
+
+       /*
+        * then see what it is
+        */
+       if (isdigit(sc_token[0])) {
+           while (isdigit(*sct))
+               sc_token[++idx] = *sct++;
+           sc_token[++idx] = 0;
+           return sc_tokid = NUMBER;
+       } else if (isalpha(sc_token[0])) {
+           while (isalpha(*sct))
+               sc_token[++idx] = *sct++;
+           sc_token[++idx] = 0;
+           return parse_token(sc_token);
+       }
+       else if (sc_token[0] == ':' || sc_token[0] == '.')
+           return sc_tokid = DOT;
+       else if (sc_token[0] == '+')
+           return sc_tokid = PLUS;
+       else if (sc_token[0] == '/')
+           return sc_tokid = SLASH;
+       else
+           return sc_tokid = JUNK;
+    } /* while (1) */
+} /* token */
+
+
+/*
+ * plonk() gives an appropriate error message if a token is incorrect
+ */
+static void
+plonk(tok)
+       int tok;
+{
+    panic((tok == EOF) ? "incomplete time"
+                      : "garbled time");
+} /* plonk */
+
+
+/* 
+ * expect() gets a token and dies most horribly if it's not the token we want
+ */
+static void
+expect(desired)
+       int desired;
+{
+    if (token() != desired)
+       plonk(sc_tokid);        /* and we die here... */
+} /* expect */
+
+
+/*
+ * dateadd() adds a number of minutes to a date.  It is extraordinarily
+ * stupid regarding day-of-month overflow, and will most likely not
+ * work properly
+ */
+static void
+dateadd(minutes, tm)
+       int minutes;
+       struct tm *tm;
+{
+    /* increment days */
+
+    while (minutes > 24*60) {
+       minutes -= 24*60;
+       tm->tm_mday++;
+    }
+
+    /* increment hours */
+    while (minutes > 60) {
+       minutes -= 60;
+       tm->tm_hour++;
+       if (tm->tm_hour > 23) {
+           tm->tm_mday++;
+           tm->tm_hour = 0;
+       }
+    }
+
+    /* increment minutes */
+    tm->tm_min += minutes;
+
+    if (tm->tm_min > 59) {
+       tm->tm_hour++;
+       tm->tm_min -= 60;
+
+       if (tm->tm_hour > 23) {
+           tm->tm_mday++;
+           tm->tm_hour = 0;
+       }
+    }
+} /* dateadd */
+
+
+/*
+ * plus() parses a now + time
+ *
+ *  at [NOW] PLUS NUMBER [MINUTES|HOURS|DAYS|WEEKS]
+ *
+ */
+static void
+plus(tm)
+       struct tm *tm;
+{
+    int delay;
+
+    expect(NUMBER);
+
+    delay = atoi(sc_token);
+
+    switch (token()) {
+    case WEEKS:
+           delay *= 7;
+    case DAYS:
+           delay *= 24;
+    case HOURS:
+           delay *= 60;
+    case MINUTES:
+           dateadd(delay, tm);
+           return;
+    }
+    plonk(sc_tokid);
+} /* plus */
+
+
+/*
+ * tod() computes the time of day
+ *     [NUMBER [DOT NUMBER] [AM|PM]]
+ */
+static void
+tod(tm)
+       struct tm *tm;
+{
+    int hour, minute = 0;
+    int tlen;
+
+    hour = atoi(sc_token);
+    tlen = strlen(sc_token);
+
+    /*
+     * first pick out the time of day - if it's 4 digits, we assume
+     * a HHMM time, otherwise it's HH DOT MM time
+     */
+    if (token() == DOT) {
+       expect(NUMBER);
+       minute = atoi(sc_token);
+       if (minute > 59)
+           panic("garbled time");
+       token();
+    } else if (tlen == 4) {
+       minute = hour%100;
+       if (minute > 59)
+           panic("garbeld time");
+       hour = hour/100;
+    }
+
+    /*
+     * check if an AM or PM specifier was given
+     */
+    if (sc_tokid == AM || sc_tokid == PM) {
+       if (hour > 12)
+           panic("garbled time");
+
+       if (sc_tokid == PM)
+           hour += 12;
+       token();
+    } else if (hour > 23)
+       panic("garbled time");
+
+    /*
+     * if we specify an absolute time, we don't want to bump the day even
+     * if we've gone past that time - but if we're specifying a time plus
+     * a relative offset, it's okay to bump things
+     */
+    if ((sc_tokid == EOF || sc_tokid == PLUS) && tm->tm_hour > hour)
+       tm->tm_mday++;
+
+    tm->tm_hour = hour;
+    tm->tm_min = minute;
+    if (tm->tm_hour == 24) {
+       tm->tm_hour = 0;
+       tm->tm_mday++;
+    }
+} /* tod */
+
+
+/*
+ * assign_date() assigns a date, wrapping to next year if needed
+ */
+static void
+assign_date(tm, mday, mon, year)
+       struct tm *tm;
+       long mday, mon, year;
+{
+    if (year > 99) {
+       if (year > 1899)
+           year -= 1900;
+       else
+           panic("garbled time");
+    }
+
+    if (year < 0 &&
+       (tm->tm_mon > mon ||(tm->tm_mon == mon && tm->tm_mday > mday)))
+       year = tm->tm_year + 1;
+
+    tm->tm_mday = mday;
+    tm->tm_mon = mon;
+
+    if (year >= 0)
+       tm->tm_year = year;
+} /* assign_date */
+
+
+/* 
+ * month() picks apart a month specification
+ *
+ *  /[<month> NUMBER [NUMBER]]           \
+ *  |[TOMORROW]                          |
+ *  |NUMBER [SLASH NUMBER [SLASH NUMBER]]|
+ *  \PLUS NUMBER MINUTES|HOURS|DAYS|WEEKS/
+ */
+static void
+month(tm)
+       struct tm *tm;
+{
+    long year= (-1);
+    long mday, mon;
+    int tlen;
+
+    switch (sc_tokid) {
+    case PLUS:
+           plus(tm);
+           break;
+
+    case TOMORROW:
+           /* do something tomorrow */
+           tm->tm_mday ++;
+    case TODAY:        /* force ourselves to stay in today - no further processing */
+           token();
+           break;
+
+    case JAN: case FEB: case MAR: case APR: case MAY: case JUN:
+    case JUL: case AUG: case SEP: case OCT: case NOV: case DEC:
+           /*
+            * do month mday [year]
+            */
+           mon = (sc_tokid-JAN);
+           expect(NUMBER);
+           mday = atol(sc_token);
+           if (token() == NUMBER) {
+               year = atol(sc_token);
+               token();
+           }
+           assign_date(tm, mday, mon, year);
+           break;
+
+    case NUMBER:
+           /*
+            * get numeric MMDDYY, mm/dd/yy, or dd.mm.yy
+            */
+           tlen = strlen(sc_token);
+           mon = atol(sc_token);
+           token();
+
+           if (sc_tokid == SLASH || sc_tokid == DOT) {
+               int sep;
+
+               sep = sc_tokid;
+               expect(NUMBER);
+               mday = atol(sc_token);
+               if (token() == sep) {
+                   expect(NUMBER);
+                   year = atol(sc_token);
+                   token();
+               }
+
+               /*
+                * flip months and days for european timing
+                */
+               if (sep == DOT) {
+                   int x = mday;
+                   mday = mon;
+                   mon = x;
+               }
+           } else if (tlen == 6 || tlen == 8) {
+               if (tlen == 8) {
+                   year = (mon % 10000) - 1900;
+                   mon /= 10000;
+               } else {
+                   year = mon % 100;
+                   mon /= 100;
+               }
+               mday = mon % 100;
+               mon /= 100;
+           } else
+               panic("garbled time");
+
+           mon--;
+           if (mon < 0 || mon > 11 || mday < 1 || mday > 31)
+               panic("garbled time");
+
+           assign_date(tm, mday, mon, year);
+           break;
+    } /* case */
+} /* month */
+
+
+/* Global functions */
+
+time_t
+parsetime(argc, argv)
+       int argc;
+       char **argv;
+{
+/*
+ * Do the argument parsing, die if necessary, and return the time the job
+ * should be run.
+ */
+    time_t nowtimer, runtimer;
+    struct tm nowtime, runtime;
+    int hr = 0;
+    /* this MUST be initialized to zero for midnight/noon/teatime */
+
+    nowtimer = time(NULL);
+    nowtime = *localtime(&nowtimer);
+
+    runtime = nowtime;
+    runtime.tm_sec = 0;
+    runtime.tm_isdst = 0;
+
+    if (argc <= optind)
+       usage();
+
+    init_scanner(argc-optind, argv+optind);
+
+    switch (token()) {
+    case NOW:  /* now is optional prefix for PLUS tree */
+           expect(PLUS);
+    case PLUS:
+           plus(&runtime);
+           break;
+
+    case NUMBER:
+           tod(&runtime);
+           month(&runtime);
+           break;
+
+           /*
+            * evil coding for TEATIME|NOON|MIDNIGHT - we've initialised
+            * hr to zero up above, then fall into this case in such a
+            * way so we add +12 +4 hours to it for teatime, +12 hours
+            * to it for noon, and nothing at all for midnight, then
+            * set our runtime to that hour before leaping into the
+            * month scanner
+            */
+    case TEATIME:
+           hr += 4;
+    case NOON:
+           hr += 12;
+    case MIDNIGHT:
+           if (runtime.tm_hour >= hr)
+               runtime.tm_mday++;
+           runtime.tm_hour = hr;
+           runtime.tm_min = 0;
+           token();
+           /* fall through to month setting */
+    default:
+           month(&runtime);
+           break;
+    } /* ugly case statement */
+    expect(EOF);
+
+    /*
+     * adjust for daylight savings time
+     */
+    runtime.tm_isdst = -1;
+    runtimer = mktime(&runtime);
+    if (runtime.tm_isdst > 0) {
+       runtimer -= 3600;
+       runtimer = mktime(&runtime);
+    }
+
+    if (runtimer < 0)
+       panic("garbled time");
+
+    if (nowtimer > runtimer)
+       panic("Trying to travel back in time");
+
+    return runtimer;
+} /* parsetime */
diff --git a/at.tproj/parsetime.h b/at.tproj/parsetime.h
new file mode 100644 (file)
index 0000000..c2e792b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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@
+ */
+/*
+ * at.h -  header for at(1)
+ * Copyright (c) 1993 by Thomas Koenig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: parsetime.h,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $
+ */
+
+time_t parsetime       __P((int argc, char **argv));
diff --git a/at.tproj/pathnames.h b/at.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..daf1edc
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Christopher G. Demetriou.
+ * 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.
+ *
+ *     $Id: pathnames.h,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $
+ */
+
+#ifndef _PATHNAMES_H_
+#define        _PATHNAMES_H_
+
+#include <paths.h>
+
+#define _PATH_ATJOBS   "/var/at/jobs/"
+#define _PATH_ATSPOOL  "/var/at/spool/"
+#define _PATH_LOCKFILE "/var/at/.lockfile"
+#define _PATH_AT       "/var/at/"
+
+#endif                         /* !_PATHNAMES_H_ */
diff --git a/at.tproj/perm.c b/at.tproj/perm.c
new file mode 100644 (file)
index 0000000..0a5ba30
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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@
+ */
+/* 
+ *  perm.c - check user permission for at(1)
+ *  Copyright (C) 1994  Thomas Koenig
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* System Headers */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Local headers */
+
+#include "privs.h"
+#include "at.h"
+#include "pathnames.h"
+
+/* Macros */
+
+#define MAXUSERID 10
+
+/* Structures and unions */
+
+/* File scope variables */
+
+static char rcsid[] = "$Id: perm.c,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $";
+
+/* Function declarations */
+
+static int check_for_user(FILE *fp,const char *name);
+
+/* Local functions */
+
+static int check_for_user(FILE *fp,const char *name)
+{
+    char *buffer;
+    size_t len;
+    int found = 0;
+
+    len = strlen(name);
+    if ((buffer = malloc(sizeof (char) * (len+2))) == NULL) {
+       fprintf(stderr, "malloc error!");
+       exit(EXIT_FAILURE);
+    }
+
+    while(fgets(buffer, len+2, fp) != NULL)
+    {
+       if ((strncmp(name, buffer, len) == 0) &&
+           (buffer[len] == '\n'))
+       {
+           found = 1;
+           break;
+       }
+    }
+    fclose(fp);
+    free(buffer);
+    return found;
+}
+/* Global functions */
+int check_permission()
+{
+    FILE *fp;
+    uid_t uid = geteuid();
+    struct passwd *pentry;
+
+    if (uid==0)
+       return 1;
+
+    if ((pentry = getpwuid(uid)) == NULL)
+    {
+       perror("Cannot access user database");
+       exit(EXIT_FAILURE);
+    }
+
+    PRIV_START
+
+    fp=fopen(_PATH_AT "at.allow","r");
+
+    PRIV_END
+
+    if (fp != NULL)
+    {
+       return check_for_user(fp, pentry->pw_name);
+    }
+    else
+    {
+
+       PRIV_START
+
+       fp=fopen(_PATH_AT "at.deny", "r");
+
+       PRIV_END
+
+       if (fp != NULL)
+       {
+           return !check_for_user(fp, pentry->pw_name);
+       }
+       perror("at.deny");
+    }
+    return 0;
+}
diff --git a/at.tproj/perm.h b/at.tproj/perm.h
new file mode 100644 (file)
index 0000000..8d14b37
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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@
+ */
+/* 
+ *  perm.h -  header for at(1)
+ *  Copyright (C) 1994  Thomas Koenig
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+int check_permission();
diff --git a/at.tproj/privs.h b/at.tproj/privs.h
new file mode 100644 (file)
index 0000000..ae37877
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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@
+ */
+/*
+ * privs.h - header for privileged operations
+ * Copyright (c) 1993 by Thomas Koenig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (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: privs.h,v 1.1.1.2 2000/01/11 02:10:05 wsanchez Exp $
+ */
+
+#ifndef _PRIVS_H
+#define _PRIVS_H
+
+#include <unistd.h>
+
+/* Relinquish privileges temporarily for a setuid program
+ * with the option of getting them back later.  This is done by swapping
+ * the real and effective userid BSD style.  Call RELINQUISH_PRIVS once
+ * at the beginning of the main program.  This will cause all operatons
+ * to be executed with the real userid.  When you need the privileges
+ * of the setuid invocation, call PRIV_START; when you no longer
+ * need it, call PRIV_END.  Note that it is an error to call PRIV_START
+ * and not PRIV_END within the same function.
+ *
+ * Use RELINQUISH_PRIVS_ROOT(a) if your program started out running
+ * as root, and you want to drop back the effective userid to a
+ * and the effective group id to b, with the option to get them back
+ * later.
+ *
+ * If you no longer need root privileges, but those of some other
+ * userid, you can call REDUCE_PRIV(a) when your effective
+ * is the user's.
+ *
+ * Problems: Do not use return between PRIV_START and PRIV_END; this
+ * will cause the program to continue running in an unprivileged
+ * state.
+ *
+ * It is NOT safe to call exec(), system() or popen() with a user-
+ * supplied program (i.e. without carefully checking PATH and any
+ * library load paths) with relinquished privileges; the called program
+ * can aquire them just as easily.  Set both effective and real userid
+ * to the real userid before calling any of them.
+ */
+
+#ifndef MAIN
+extern
+#endif
+uid_t real_uid, effective_uid;
+
+#define RELINQUISH_PRIVS { \
+       real_uid = getuid(); \
+       effective_uid = geteuid(); \
+       seteuid(real_uid); \
+}
+
+#define RELINQUISH_PRIVS_ROOT(a) { \
+       real_uid = (a); \
+       effective_uid = geteuid(); \
+       seteuid(real_uid); \
+}
+
+#define PRIV_START { \
+       seteuid(effective_uid);
+
+#define PRIV_END \
+       seteuid(real_uid); \
+}
+
+#define REDUCE_PRIV(a) { \
+       seteuid(effective_uid); \
+       real_uid = effective_uid = (a); \
+       setuid(real_uid); \
+}
+#endif
diff --git a/atrun.tproj/Makefile b/atrun.tproj/Makefile
new file mode 100644 (file)
index 0000000..8150fd1
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = atrun
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = atrun.h
+
+CFILES = atrun.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist atrun.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I../at
+
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/atrun.tproj/Makefile.dist b/atrun.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..726a2e7
--- /dev/null
@@ -0,0 +1,11 @@
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 04:21:19 wsanchez Exp $
+
+PROG=  atrun
+BINDIR=        /usr/libexec
+MAN8=  atrun.0
+
+BINOWN=        root
+
+CFLAGS+= -I${.CURDIR}/../../usr.bin/at
+
+.include <bsd.prog.mk>
diff --git a/atrun.tproj/Makefile.preamble b/atrun.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/atrun.tproj/PB.project b/atrun.tproj/PB.project
new file mode 100644 (file)
index 0000000..e69c398
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        HEADERSEARCH = (../at); 
+        H_FILES = (atrun.h); 
+        OTHER_LINKED = (atrun.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, atrun.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = atrun; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/atrun.tproj/atrun.8 b/atrun.tproj/atrun.8
new file mode 100644 (file)
index 0000000..7ebc04e
--- /dev/null
@@ -0,0 +1,77 @@
+.\"
+.\" Copyright (c) 1993 Christopher G. Demetriou
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Christopher G. Demetriou.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\"    derived from this software without specific prior written permission
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\"    $Id: atrun.8,v 1.1.1.1 1999/05/02 04:21:19 wsanchez Exp $
+.\"
+.Dd December 5, 1993
+.Dt ATRUN 8
+.Os NetBSD 0.9a
+.Sh NAME
+.Nm atrun
+.Nd run jobs queued for later execution
+.\"
+.Sh SYOPSIS
+.Nm atrun
+.Sh DESCRIPTION
+The
+.Nm atrun
+utility runs commands queued by
+.Xr at 1 .
+It is usually invoked by
+.Xr crond 8
+every ten minutes.
+.Sh FILES
+.Bl -tag -width /var/at/lockfile -compact
+.It Pa /var/at/jobs
+Directory containing job files
+.It Pa /var/at/spool
+Directory containing output spool files
+.It Pa /var/at/lockfile
+Job-creation lock file.
+.El
+.Sh SEE ALSO
+.Xr crond 8 ,
+.Xr at 1
+.Sh AUTHOR
+.Bl -tag
+Thomas Koenig, ig25@rz.uni-karlsruhe.de
+.El
+.Sh BUGS
+The functionality of
+.Nm atrun
+should arguaby be merged into
+.Xr crond 8 .
+.Sh CAVEATS
+Since the default configuration causes
+.Nm atrun
+to be invoked every ten minutes,
+commands queued by
+.Xr at 1
+may end up being executed up to nine minutes
+later than would be otherwise expected.
diff --git a/atrun.tproj/atrun.c b/atrun.tproj/atrun.c
new file mode 100644 (file)
index 0000000..f9e31bd
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * 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@
+ */
+/*
+ * atrun.c - run jobs queued by at; run with root privileges.
+ * Copyright (c) 1993 by Thomas Koenig
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author(s) 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(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, 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, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* System Headers */
+
+#include <sys/fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <syslog.h>
+
+#include <paths.h>
+
+/* Local headers */
+
+#define MAIN
+#include "privs.h"
+#include "pathnames.h"
+#include "atrun.h"
+
+/* File scope variables */
+
+static char *namep;
+static char rcsid[] = "$Id: atrun.c,v 1.1.1.2 2000/01/11 02:10:06 wsanchez Exp $";
+
+/* Local functions */
+static void
+perr(a)
+       const char *a;
+{
+       syslog(LOG_ERR, "%s: %m", a);
+       exit(EXIT_FAILURE);
+}
+
+static int
+write_string(fd, a)
+       int fd;
+       const char *a;
+{
+       return write(fd, a, strlen(a));
+}
+
+static void
+run_file(filename, uid, gid)
+       const char *filename;
+       uid_t uid;
+       gid_t gid;
+{
+       /*
+        * Run a file by by spawning off a process which redirects I/O,
+        * spawns a subshell, then waits for it to complete and spawns another
+        * process to send mail to the user.
+        */
+       pid_t pid;
+       int fd_out, fd_in;
+       int queue;
+       char mailbuf[9];
+       char *mailname = NULL;
+       FILE *stream;
+       int send_mail = 0;
+       struct stat buf;
+       off_t size;
+       struct passwd *pentry;
+       int fflags;
+
+       pid = fork();
+       if (pid == -1)
+               perr("Cannot fork");
+       else if (pid > 0)
+               return;
+
+       /*
+        * Let's see who we mail to.  Hopefully, we can read it from the
+        * command file; if not, send it to the owner, or, failing that, to
+        * root.
+        */
+
+       PRIV_START
+
+           stream = fopen(filename, "r");
+
+       PRIV_END
+
+       if (stream == NULL)
+               perr("Cannot open input file");
+
+       if ((fd_in = dup(fileno(stream))) < 0)
+               perr("Error duplicating input file descriptor");
+
+       if ((fflags = fcntl(fd_in, F_GETFD)) < 0)
+               perr("Error in fcntl");
+
+       fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC);
+
+       if (fscanf(stream, "#! /bin/sh\n# mail %8s %d", mailbuf, &send_mail) == 2) {
+               mailname = mailbuf;
+       } else {
+               pentry = getpwuid(uid);
+               if (pentry == NULL)
+                       mailname = "root";
+               else
+                       mailname = pentry->pw_name;
+       }
+       fclose(stream);
+       if (chdir(_PATH_ATSPOOL) < 0)
+               perr("Cannot chdir to " _PATH_ATSPOOL);
+
+       /*
+        * Create a file to hold the output of the job we are  about to
+        * run. Write the mail header.
+        */
+       if ((fd_out = open(filename,
+                   O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0)
+               perr("Cannot create output file");
+
+       write_string(fd_out, "Subject: Output from your job ");
+       write_string(fd_out, filename);
+       write_string(fd_out, "\n\n");
+       fstat(fd_out, &buf);
+       size = buf.st_size;
+
+       close(STDIN_FILENO);
+       close(STDOUT_FILENO);
+       close(STDERR_FILENO);
+
+       pid = fork();
+       if (pid < 0)
+               perr("Error in fork");
+       else if (pid == 0) {
+               char *nul = NULL;
+               char **nenvp = &nul;
+
+               /*
+                * Set up things for the child; we want standard input from
+                * the input file, and standard output and error sent to
+                * our output file.
+                */
+
+               if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0)
+                       perr("Error in lseek");
+
+               if (dup(fd_in) != STDIN_FILENO)
+                       perr("Error in I/O redirection");
+
+               if (dup(fd_out) != STDOUT_FILENO)
+                       perr("Error in I/O redirection");
+
+               if (dup(fd_out) != STDERR_FILENO)
+                       perr("Error in I/O redirection");
+
+               close(fd_in);
+               close(fd_out);
+               if (chdir(_PATH_ATJOBS) < 0)
+                       perr("Cannot chdir to " _PATH_ATJOBS);
+
+               queue = *filename;
+
+               PRIV_START
+
+                   if (queue > 'b')
+                       nice(queue - 'b');
+
+               if (setgid(gid) < 0)
+                       perr("Cannot change group");
+
+               if (setuid(uid) < 0)
+                       perr("Cannot set user id");
+
+               chdir("/");
+
+               if (execle("/bin/sh", "sh", (char *) NULL, nenvp) != 0)
+                       perr("Exec failed");
+
+               PRIV_END
+       }
+       /* We're the parent.  Let's wait. */
+       close(fd_in);
+       close(fd_out);
+       waitpid(pid, (int *) NULL, 0);
+
+       stat(filename, &buf);
+       if ((buf.st_size != size) || send_mail) {
+               /* Fork off a child for sending mail */
+               pid = fork();
+               if (pid < 0)
+                       perr("Fork failed");
+               else if (pid == 0) {
+                       if (open(filename, O_RDONLY) != STDIN_FILENO)
+                               perr("Cannot reopen output file");
+
+                       execl(_PATH_SENDMAIL, _PATH_SENDMAIL, mailname,
+                           (char *) NULL);
+                       perr("Exec failed");
+               }
+               waitpid(pid, (int *) NULL, 0);
+       }
+       unlink(filename);
+       exit(EXIT_SUCCESS);
+}
+
+/* Global functions */
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       /*
+        * Browse through  _PATH_ATJOBS, checking all the jobfiles wether
+        * they should be executed and or deleted. The queue is coded into
+        * the first byte of the job filename, the date (in minutes since
+        * Eon) as a hex number in the following eight bytes, followed by
+        * a dot and a serial number.  A file which has not been executed
+        * yet is denoted by its execute - bit set.  For those files which
+        * are to be executed, run_file() is called, which forks off a
+        * child which takes care of I/O redirection, forks off another
+        * child for execution and yet another one, optionally, for sending
+        * mail.  Files which already have run are removed during the
+        * next invocation.
+        */
+       DIR *spool;
+       struct dirent *dirent;
+       struct stat buf;
+       int older;
+       unsigned long ctm;
+       char queue;
+
+       /*
+        * We don't need root privileges all the time; running under uid
+        * and gid daemon is fine.
+        */
+
+       RELINQUISH_PRIVS_ROOT(0) /* it's setuid root */
+       openlog("atrun", LOG_PID, LOG_CRON);
+
+       namep = argv[0];
+       if (chdir(_PATH_ATJOBS) != 0)
+               perr("Cannot change to " _PATH_ATJOBS);
+
+       /*
+        * Main loop. Open spool directory for reading and look over all
+        * the files in there. If the filename indicates that the job
+        * should be run and the x bit is set, fork off a child which sets
+        * its user and group id to that of the files and exec a /bin/sh
+        * which executes the shell script. Unlink older files if they
+        * should no longer be run.  For deletion, their r bit has to be
+        * turned on.
+        */
+       if ((spool = opendir(".")) == NULL)
+               perr("Cannot read " _PATH_ATJOBS);
+
+       while ((dirent = readdir(spool)) != NULL) {
+               double la;
+
+               if (stat(dirent->d_name, &buf) != 0)
+                       perr("Cannot stat in " _PATH_ATJOBS);
+
+               /* We don't want directories */
+               if (!S_ISREG(buf.st_mode))
+                       continue;
+
+               if (sscanf(dirent->d_name, "%c%8lx", &queue, &ctm) != 2)
+                       continue;
+
+               if ((queue == 'b') && ((getloadavg(&la, 1) != 1) ||
+                   (la > ATRUN_MAXLOAD)))
+                       continue;
+
+               older = (time_t) ctm *60 <= time(NULL);
+
+               /* The file is executable and old enough */
+               if (older && (S_IXUSR & buf.st_mode)) {
+                       /*
+                        * Now we know we want to run the file, we can turn
+                        * off the execute bit
+                        */
+
+                       PRIV_START
+
+                           if (chmod(dirent->d_name, S_IRUSR) != 0)
+                               perr("Cannot change file permissions");
+
+                       PRIV_END
+
+                       run_file(dirent->d_name, buf.st_uid, buf.st_gid);
+               }
+               /* Delete older files */
+               if (older && !(S_IXUSR & buf.st_mode) &&
+                   (S_IRUSR & buf.st_mode))
+                       unlink(dirent->d_name);
+       }
+       closelog();
+       exit(EXIT_SUCCESS);
+}
diff --git a/atrun.tproj/atrun.h b/atrun.tproj/atrun.h
new file mode 100644 (file)
index 0000000..af24723
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Christopher G. Demetriou.
+ * 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.
+ *
+ *     $Id: atrun.h,v 1.1.1.2 2000/01/11 02:10:06 wsanchez Exp $
+ */
+
+#define ATRUN_MAXLOAD  1.5
diff --git a/chkpasswd.tproj/Makefile b/chkpasswd.tproj/Makefile
new file mode 100644 (file)
index 0000000..1c335d1
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# 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 = chkpasswd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = stringops.h
+
+CFILES = nis_passwd.c file_passwd.c netinfo_passwd.c passwd.c\
+         stringops.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = /System/Developer/Makefiles/project
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/bin
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/chkpasswd.tproj/Makefile.postamble b/chkpasswd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..1518c3b
--- /dev/null
@@ -0,0 +1,6 @@
+
+INSTALL_AS_USER =      root
+INSTALL_PERMISSIONS =  4555
+#CHFLAGS = /usr/bin/chflags
+#after_install::
+#      $(CHFLAGS) schg  $(DSTROOT)$(INSTALLDIR)/$(NAME)
diff --git a/chkpasswd.tproj/Makefile.preamble b/chkpasswd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..efe44b4
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+CLEAN_ALL_SUBPROJECTS = YES
diff --git a/chkpasswd.tproj/PB.project b/chkpasswd.tproj/PB.project
new file mode 100644 (file)
index 0000000..600cfef
--- /dev/null
@@ -0,0 +1,29 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        CLASSES = (); 
+        C_FILES = (); 
+        H_FILES = (stringops.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (nis_passwd.c, file_passwd.c, netinfo_passwd.c, passwd.c, stringops.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = /System/Developer/Makefiles/project; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = chkpasswd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/chkpasswd.tproj/file_passwd.c b/chkpasswd.tproj/file_passwd.c
new file mode 100644 (file)
index 0000000..51fc8c1
--- /dev/null
@@ -0,0 +1,276 @@
+/*
+ * 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include "stringops.h"
+
+#define TEMP_FILE "/tmp/.pwtmp"
+
+#define _PASSWD_FILE "/etc/master.passwd"
+#define _COMPAT_FILE "/etc/passwd"
+#define _PASSWD_FIELDS 10
+#define BUFSIZE 8192
+
+extern void checkpasswd(char *, char *);
+
+static int do_compat = 1;
+
+char *
+getline(FILE *fp)
+{
+       static char s[BUFSIZE];
+       int len;
+
+    s[0] = '\0';
+
+    fgets(s, BUFSIZE, fp);
+    if (s == NULL || s[0] == '\0') return NULL;
+
+       if (s[0] == '#') return s;
+
+       len = strlen(s) - 1;
+       s[len] = '\0';
+
+       return s;
+}
+
+struct passwd *
+parse_user(char *line)
+{
+       static struct passwd pw = {0};
+       char **tokens;
+       int i, len;
+
+       if (pw.pw_name != NULL) free(pw.pw_name);
+       pw.pw_name = NULL;
+       if (pw.pw_passwd != NULL) free(pw.pw_passwd);
+       pw.pw_passwd = NULL;
+       if (pw.pw_gecos != NULL) free(pw.pw_gecos);
+       pw.pw_gecos = NULL;
+       if (pw.pw_dir != NULL) free(pw.pw_dir);
+       pw.pw_dir = NULL;
+       if (pw.pw_shell != NULL) free(pw.pw_shell);
+       pw.pw_shell = NULL;
+
+       if (pw.pw_class != NULL) free(pw.pw_class);
+       pw.pw_class = NULL;
+
+       if (line == NULL) return (struct passwd *)NULL;
+       tokens = explode(line, ':');
+       len = listLength(tokens);
+
+       if (len != _PASSWD_FIELDS)
+       {
+               freeList(tokens);
+               return (struct passwd *)NULL;
+       }
+
+       i = 0;
+       pw.pw_name = tokens[i++];
+       pw.pw_passwd = tokens[i++];
+       pw.pw_uid = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_gid = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_class = tokens[i++];
+       pw.pw_change = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_expire = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_gecos = tokens[i++];
+       pw.pw_dir = tokens[i++];
+       pw.pw_shell = tokens[i++];
+
+       return &pw;
+}
+
+struct passwd *
+find_user(char *uname, FILE *fp)
+{
+       char *line;
+       struct passwd *pw;
+
+       rewind(fp);
+
+       while (NULL != (line = getline(fp)))
+       {
+               if (line[0] == '#') continue;
+               pw = parse_user(line);
+               if (pw == (struct passwd *)NULL) continue;
+               if (!strcmp(uname, pw->pw_name)) return pw;
+       }
+
+       pw = parse_user(NULL);
+       return (struct passwd *)NULL;
+}
+
+void
+rewrite_file(char *pwname, FILE *fp, struct passwd *newpw)
+{
+       char *line;
+       struct passwd *pw;
+       FILE *tfp, *cfp;
+       char fname[256];
+       
+       sprintf(fname, "%s.%d", TEMP_FILE, getpid());
+
+       tfp = fopen(fname, "w+");
+       if (tfp == NULL)
+       {
+               fprintf(stderr, "can't write temporary file \"%s\": ", fname);
+               perror("");
+               exit(1);
+       }
+
+       cfp = NULL;
+       if (!strcmp(pwname, _PASSWD_FILE))
+       {
+               cfp = fopen(_COMPAT_FILE, "w");
+               if (cfp == NULL)
+               {
+                       fprintf(stderr, "warning: can't write compatability file \"%s\": ",
+                               _COMPAT_FILE);
+                       perror("");
+               }
+       }
+
+       if (cfp != NULL)
+       {
+               fprintf(cfp, "#\n");
+               fprintf(cfp, "# 4.3BSD-compatable User Database\n");
+               fprintf(cfp, "#\n");
+               fprintf(cfp, "# Note that this file is not consulted for login.\n");
+               fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n");
+               fprintf(cfp, "#\n");
+               fprintf(cfp, "# This file is automatically re-written by various system utilities.\n");
+               fprintf(cfp, "# Do not edit this file.  Changes will be lost.\n");
+               fprintf(cfp, "#\n");
+       }
+
+       rewind(fp);
+
+       while (NULL != (line = getline(fp)))
+       {
+               if (line[0] == '#')
+               {
+                       fprintf(tfp, "%s", line);
+                       continue;
+               }
+
+               pw = parse_user(line);
+               if (pw == (struct passwd *)NULL)
+               {
+                       fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line);
+                       fprintf(tfp, "%s\n", line);
+                       if (cfp != NULL) fprintf(cfp, "%s\n", line);
+                       continue;
+               }
+
+               if (strcmp(newpw->pw_name, pw->pw_name))
+               {
+                       fprintf(tfp, "%s\n", line);
+                       if (cfp != NULL) fprintf(cfp, "%s\n", line);
+                       continue;
+               }
+
+               fprintf(tfp, "%s:%s:%d:%d:%s:%d:%d:%s:%s:%s\n",
+                       newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid,
+                       newpw->pw_class, newpw->pw_change, newpw->pw_expire,
+                       newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell);
+               if (cfp != NULL)
+               {
+                       fprintf(cfp, "%s:",newpw->pw_name);
+                       if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0'))
+                               fprintf(cfp, ":");
+                       else
+                               fprintf(cfp, "*:");
+                       fprintf(cfp, "%d:%d:%s:%s:%s\n",
+                               newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos,
+                               newpw->pw_dir, newpw->pw_shell);
+               }
+       }
+
+       if (cfp != NULL) fclose(cfp);
+       fclose(fp);
+       if (unlink(pwname)  < 0)
+       {
+               fprintf(stderr, "can't update \"%s\": ", pwname);
+               perror("");
+       }
+
+       rewind(tfp);
+
+       fp = fopen(pwname, "w");
+       if (fp == NULL)
+       {
+               fprintf(stderr, "ERROR: lost file \"%s\"\n", pwname);
+               fprintf(stderr, "new passwd file is \"%s\"\n", fname);
+               perror("open");
+               exit(1);
+       }
+
+       while (NULL != (line = getline(tfp)))
+       {
+               fprintf(fp, "%s", line);
+               if (line[0] != '#') fprintf(fp, "\n");
+       }
+       fclose(fp);
+       fclose(tfp);
+       unlink(fname);
+}
+
+int
+file_check_passwd(char *uname, char *locn)
+{
+       FILE *fp;
+       char *fname;
+       struct passwd *pw;
+
+       fname = _PASSWD_FILE;
+       if (locn != NULL) fname = locn;
+
+       fp = fopen(fname, "r");
+       if (fp == NULL)
+       {
+               fprintf(stderr, "can't read file \"%s\": ", fname);
+               perror("");
+               exit(1);
+       }
+
+
+       pw = find_user(uname, fp);
+       if (pw == (struct passwd *)NULL)
+       {
+               fprintf(stderr, "user %s not found in file %s\n", uname, fname);
+               exit(1);
+       }
+
+       checkpasswd(uname, pw->pw_passwd);
+       fclose(fp);
+
+       return 0;
+}
diff --git a/chkpasswd.tproj/netinfo_passwd.c b/chkpasswd.tproj/netinfo_passwd.c
new file mode 100644 (file)
index 0000000..762f00d
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * 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@
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pwd.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <string.h>
+#include <netinfo/ni.h>
+
+extern void checkpasswd(char *, char *);
+
+static int
+sys_ismyaddress(unsigned long addr)
+{
+       struct ifconf ifc;
+       struct ifreq *ifr;
+       char buf[1024]; /* XXX */
+       int offset;
+       int sock;
+       struct sockaddr_in *sin;
+       int i, len;
+
+       if (addr == htonl(INADDR_LOOPBACK)) return 1;
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+       if (sock < 0) return 0;
+
+       ifc.ifc_len = sizeof(buf);
+       ifc.ifc_buf = buf;
+
+       if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0)
+       {
+               close(sock);
+               return 0;
+       }
+
+       offset = 0;
+
+       while (offset <= ifc.ifc_len)
+       {
+               ifr = (struct ifreq *)(ifc.ifc_buf + offset);
+               offset += IFNAMSIZ + ifr->ifr_addr.sa_len;
+
+               if (ifr->ifr_addr.sa_family != AF_INET) continue;
+               if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue;
+
+               sin = (struct sockaddr_in *)&ifr->ifr_addr;
+               if ((ifr->ifr_flags & IFF_UP) &&
+                       (!(ifr->ifr_flags & IFF_LOOPBACK)) &&
+                       (sin->sin_addr.s_addr == addr))
+               {
+                       close(sock);
+                       return 1;
+               }
+       }
+
+       close(sock);
+       return 0;
+}
+
+static int
+is_root_on_master(void *d)
+{
+       int uid;
+       char myhostname[MAXHOSTNAMELEN + 1];
+       char *p;
+       ni_index where;
+       ni_proplist     pl;
+       int status;
+       ni_id dir;
+       struct sockaddr_in addr;
+       char *tag;
+
+       uid = getuid();
+       if (uid != 0) return 0;
+
+       gethostname(myhostname, MAXHOSTNAMELEN);
+       p = strchr(myhostname, '.');
+       if (p != NULL) *p = '\0';
+
+       status = ni_root(d, &dir);
+       if (status != NI_OK) return 0;
+
+       status = ni_read(d, &dir, &pl);
+       if (status != NI_OK) return 0;
+
+       where = ni_proplist_match(pl, "master", NULL);
+       if (where == NI_INDEX_NULL)
+       {
+               ni_proplist_free(&pl);
+               return 0;
+       }
+
+       if (pl.ni_proplist_val[where].nip_val.ni_namelist_len == 0)
+       {
+               ni_proplist_free(&pl);
+               fprintf(stderr, "No value for NetInfo master property\n");
+               return 0;
+       }
+
+       p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '/');
+       if (p != NULL) *p = '\0';
+       
+       p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '.');
+       if (p != NULL) *p = '\0';
+       
+       if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], myhostname))
+       {
+               ni_proplist_free(&pl);
+               return 1;
+       }
+
+       if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], "localhost"))
+       {
+               ni_proplist_free(&pl);
+               ni_addrtag(d, &addr, &tag);
+               if (sys_ismyaddress(addr.sin_addr.s_addr)) return 1;
+       }
+
+       ni_proplist_free(&pl);
+       return 0;
+}
+
+static int
+secure_passwords()
+{
+       void *d, *d1;
+       int status;
+       ni_index where;
+       ni_id dir;
+       ni_namelist nl;
+
+       status = ni_open(NULL, ".", &d);
+       while (status == NI_OK)
+       {
+               dir.nii_object = 0;
+               status = ni_lookupprop(d, &dir, "security_options", &nl);
+               if (status == NI_OK) 
+               {
+                       where = ni_namelist_match(nl, "secure_passwords");
+                       if (where != NI_INDEX_NULL)
+                       {
+                               ni_free(d);
+                               return 1;
+                       }
+               }
+
+               d1 = d;
+               status = ni_open(d1, "..", &d);
+               ni_free(d1);
+       }
+
+       return 0;
+}
+
+static void
+parse_server_tag(char *str, struct sockaddr_in *server, char **t)
+{
+       /* utility to parse a server/tag string */
+
+       int len, i;
+       char *host, *tag, *slash;
+       struct hostent *hent;
+
+       len = strlen(str);
+
+       /* find the "/" character */
+       slash = index(str, '/');
+
+       /* check to see if the "/" is missing */
+       if (slash == NULL)
+       {
+               fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
+               exit(1);
+       }               
+
+       /* find the location of the '/' */
+       i = slash - str;
+
+       /* check if host string is empty */
+       if (i == 0)
+       {
+               fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
+               fprintf(stderr, "no server name specified\n");
+               exit(1);
+       }
+
+       /* check if tag string is empty */
+       if (i == (len - 1)) 
+       {
+               fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
+               fprintf(stderr, "no tag specified\n");
+               exit(1);
+       }
+
+       /* allocate some space for the host and tag */
+       host = (char *)malloc(i + 1);
+       *t = (char *)malloc(len - i);
+       tag = *t;
+
+       /* copy out the host */
+       strncpy(host, str, i);
+       host[i] = '\0';
+
+       /* copy out the tag */
+       strcpy(tag, slash + 1);
+
+       /* try interpreting the host portion as an address */
+       server->sin_addr.s_addr = inet_addr(host);
+
+       if (server->sin_addr.s_addr == -1)
+       {
+               /* This isn't a valid address.  Is it a known hostname? */
+               hent = gethostbyname(host);
+               if (hent != NULL)
+               {
+                       /* found a host with that name */
+                       bcopy(hent->h_addr, &server->sin_addr, hent->h_length);
+               }
+               else
+               {
+                       fprintf(stderr, "Can't find address for %s\n", host);
+                       free(host);
+                       free(tag);
+                       exit(1);
+               }
+   }
+
+       free(host);
+}
+
+static void *
+domain_for_user(char *uname, char *locn, ni_id *dir)
+{
+       char *upath;
+       int status;
+       void *d, *d1;
+       struct sockaddr_in server;
+       char *tag;
+       int bytag;
+
+       /*
+        * Find the user in NetInfo.
+        */
+       upath = malloc(8 + strlen(uname));
+       sprintf(upath, "/users/%s", uname);
+
+       if (locn != NULL)
+       {
+               bytag = 1;
+
+               if (locn[0] == '/') bytag = 0;
+               else if (!strncmp(locn, "./", 2)) bytag = 0;
+               else if (!strncmp(locn, "../", 3)) bytag = 0;
+
+               if (bytag == 1)
+               {
+                       parse_server_tag(locn, &server, &tag);
+                       d = ni_connect(&server, tag);
+                       if (d == (void *)NULL) return (void *)NULL;
+               }
+               else status = ni_open(NULL, locn, &d);
+               status = ni_pathsearch(d, dir, upath);
+               free(upath);
+
+               if (status == NI_OK) return d;
+
+               ni_free(d);
+               return (void *)NULL;
+       }
+
+       status = ni_open(NULL, ".", &d);
+       while (status == NI_OK)
+       {
+               status = ni_pathsearch(d, dir, upath);
+               if (status == NI_OK) break;
+               d1 = d;
+               status = ni_open(d1, "..", &d);
+               ni_free(d1);
+       }
+
+       free(upath);
+
+       if (status == NI_OK) return d;
+       return (void *)NULL;
+}
+
+int
+netinfo_check_passwd(char *uname, char *locn)
+{
+       char *oldpw;
+       void *d;
+       int status;
+       ni_id dir;
+       ni_namelist     nl;
+
+       d = domain_for_user(uname, locn, &dir);
+       if (d == (void *)NULL)
+       {
+               fprintf(stderr, "user %s not found in NetInfo\n", uname);
+               exit(1);
+       }
+
+       /*
+        * Read the passwd and uid from NetInfo.
+        */
+       status = ni_lookupprop(d, &dir, "passwd", &nl);
+       if (status == NI_NOPROP) nl.ni_namelist_len = 0;
+       else if (status != NI_OK)
+       {
+               ni_free(d);
+               fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
+               exit(1);
+       }
+
+       oldpw = NULL;
+       if (nl.ni_namelist_len > 0) oldpw = nl.ni_namelist_val[0];
+
+       checkpasswd(uname, oldpw);
+       ni_free(d);
+       return (0);
+}
diff --git a/chkpasswd.tproj/nis_passwd.c b/chkpasswd.tproj/nis_passwd.c
new file mode 100644 (file)
index 0000000..89b0411
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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) 1998 by Apple Computer, Inc.
+ * Portions Copyright (c) 1988 by Sun Microsystems, Inc.
+ * Portions Copyright (c) 1988 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.
+ */
+
+
+/* update a user's password in NIS. This was based on the Sun implementation
+ * we used in NEXTSTEP, although I've added some stuff from OpenBSD. And
+ * it uses the API to support Rhapsody's proprietry infosystem switch.
+ * lukeh
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <errno.h>
+
+extern int getrpcport(char *, int, int, int);
+extern void checkpasswd(char *, char *);
+
+static struct passwd *ypgetpwnam(char *name, char *domain);
+
+int nis_check_passwd(char *uname, char *domain)
+{      
+       int port;
+       char *master;
+       struct passwd *pwd;
+
+       if (domain == NULL)
+       {
+               if (yp_get_default_domain(&domain) != 0)
+               {
+                       (void)fprintf(stderr, "can't get domain\n");
+                       exit(1);
+               }
+       }
+       
+       if (yp_master(domain, "passwd.byname", &master) != 0)
+       {
+               (void)fprintf(stderr, "can't get master for passwd file\n");
+               exit(1);
+       }
+       
+       port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
+               IPPROTO_UDP);
+       if (port == 0)
+       {
+               (void)fprintf(stderr, "%s is not running yppasswd daemon\n",
+                             master);
+               exit(1);
+       }
+       if (port >= IPPORT_RESERVED)
+       {
+               (void)fprintf(stderr,
+                   "yppasswd daemon is not running on privileged port\n");
+               exit(1);
+       }
+
+       pwd = ypgetpwnam(uname, domain);
+       if (pwd == NULL)
+       {
+               (void)fprintf(stderr, "user %s not found\n", uname);
+               exit(1);
+       }
+       
+       checkpasswd(uname, pwd->pw_passwd);
+       return(0);
+}
+               
+static char *
+pwskip(register char *p)
+{
+       while (*p && *p != ':' && *p != '\n')
+               ++p;
+       if (*p)
+               *p++ = 0;
+       return (p);
+}
+
+struct passwd *
+interpret(struct passwd *pwent, char *line)
+{
+       register char   *p = line;
+
+       pwent->pw_passwd = "*";
+       pwent->pw_uid = 0;
+       pwent->pw_gid = 0;
+       pwent->pw_gecos = "";
+       pwent->pw_dir = "";
+       pwent->pw_shell = "";
+#ifndef __SLICK__
+       pwent->pw_change = 0;
+       pwent->pw_expire = 0;
+       pwent->pw_class = "";
+#endif
+
+       /* line without colon separators is no good, so ignore it */
+       if(!strchr(p, ':'))
+               return(NULL);
+
+       pwent->pw_name = p;
+       p = pwskip(p);
+       pwent->pw_passwd = p;
+       p = pwskip(p);
+       pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
+       p = pwskip(p);
+       pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
+       p = pwskip(p);
+       pwent->pw_gecos = p;
+       p = pwskip(p);
+       pwent->pw_dir = p;
+       p = pwskip(p);
+       pwent->pw_shell = p;
+       while (*p && *p != '\n')
+               p++;
+       *p = '\0';
+       return (pwent);
+}
+
+
+static struct passwd *
+ypgetpwnam(char *nam, char *domain)
+{
+       static struct passwd pwent;
+       char *val;
+       int reason, vallen;
+       static char *__yplin = NULL;
+
+       reason = yp_match(domain, "passwd.byname", nam, strlen(nam),
+           &val, &vallen);
+       switch(reason) {
+       case 0:
+               break;
+       default:
+               return (NULL);
+               break;
+       }
+       val[vallen] = '\0';
+       if (__yplin)
+               free(__yplin);
+       __yplin = (char *)malloc(vallen + 1);
+       strcpy(__yplin, val);
+       free(val);
+
+       return(interpret(&pwent, __yplin));
+}
diff --git a/chkpasswd.tproj/passwd.c b/chkpasswd.tproj/passwd.c
new file mode 100644 (file)
index 0000000..ae9c0d9
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * 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@
+ */
+#define INFO_NETINFO 0
+#define INFO_FILE 1
+#define INFO_NIS 2
+
+#ifndef __SLICK__
+#define _PASSWD_FILE "/etc/master.passwd"
+#else
+#define _PASSWD_FILE "/etc/passwd"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <pwd.h>
+#include <libc.h>
+#include <ctype.h>
+#include <string.h>
+#include <pwd.h>
+#include <netinfo/ni.h>
+#include "stringops.h"
+
+#ifdef __SLICK__
+#define _PASSWORD_LEN 8
+#endif
+
+static int literal = 0;
+
+extern int file_check_passwd(char *, char *);
+extern int netinfo_check_passwd(char *, char *);
+extern int nis_check_passwd(char *, char *);
+
+void
+checkpasswd(char *name, char *old_pw)
+{
+       int isNull;
+       char *p;
+
+       printf("Checking password for %s.\n", name);
+
+       p = "";
+       isNull = 0;
+       if (old_pw == NULL) isNull = 1;
+       if ((isNull == 0) && (old_pw[0] == '\0')) isNull = 1;
+       if (isNull == 0)
+       {
+               p = getpass("Password:");
+               sleep(1); // make sure this doesn't go too quickly
+               if (strcmp(literal ? p : crypt(p, old_pw), old_pw))
+               {
+                       errno = EACCES;
+                       fprintf(stderr, "Sorry\n");
+                       exit(1);
+               }
+       }
+       return;
+}
+
+void
+usage()
+{
+       fprintf(stderr, "usage: chkpasswd [-i infosystem] [-l location] [-c] [name]\n");
+       fprintf(stderr, "supported infosystems are:\n");
+       fprintf(stderr, "    netinfo\n");
+       fprintf(stderr, "    file\n");
+       fprintf(stderr, "    nis\n");
+       fprintf(stderr, "for netinfo, location may be a domain name or server/tag\n");
+       fprintf(stderr, "for file, location may be a file name (%s is the default)\n",
+               _PASSWD_FILE);
+       fprintf(stderr, "for nis, location may be a NIS domainname\n");
+       fprintf(stderr, "if -c is specified, the password you supply is compared\n");
+       fprintf(stderr, "verbatim without first being crypted\n");
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       char *user, *locn;
+       int i, infosystem;
+       struct passwd *pw;
+
+       infosystem = INFO_NETINFO;
+       user = NULL;
+       locn = NULL;
+
+       for (i = 1; i < argc; i++)
+       {
+               if (!strcmp(argv[i], "-i"))
+               {
+                       if (++i >= argc)
+                       {
+                               fprintf(stderr, "no argument for -i option\n");
+                               usage();
+                       }
+
+                       if (!strcmp(argv[i], "NetInfo")) infosystem = INFO_NETINFO;
+                       else if (!strcmp(argv[i], "netinfo")) infosystem = INFO_NETINFO;
+                       else if (!strcmp(argv[i], "File")) infosystem = INFO_FILE;
+                       else if (!strcmp(argv[i], "file")) infosystem = INFO_FILE;
+                       else if (!strcmp(argv[i], "NIS")) infosystem = INFO_NIS;
+                       else if (!strcmp(argv[i], "nis")) infosystem = INFO_NIS;
+                       else if (!strcmp(argv[i], "YP")) infosystem = INFO_NIS;
+                       else if (!strcmp(argv[i], "yp")) infosystem = INFO_NIS;
+                       else
+                       {
+                               fprintf(stderr, "unknown info system \"%s\"\n", argv[i]);
+                               usage();
+                       }
+               }
+
+               else if (!strcmp(argv[i], "-l"))
+               {
+                       if (++i >= argc)
+                       {
+                               fprintf(stderr, "no argument for -l option\n");
+                               usage();
+                       }
+                       locn = argv[i];
+               }
+
+               else if (!strcmp(argv[i], "-c")) literal++;
+               else if (user == NULL) user = argv[i];
+               else usage();
+       }
+
+       if (user == NULL)
+       {
+               if ((pw = getpwuid(getuid())) == NULL || (user = pw->pw_name) == NULL)
+               {
+                       fprintf(stderr, "you don't have a login name\n");
+                       exit(1);
+               }
+       }
+       
+       switch (infosystem)
+       {
+               case INFO_NETINFO:
+                       netinfo_check_passwd(user, locn);
+                       break;
+               case INFO_FILE:
+                       file_check_passwd(user, locn);
+                       break;
+               case INFO_NIS:
+                       nis_check_passwd(user, locn);
+                       break;
+       }
+
+       exit(0);
+}
+
diff --git a/chkpasswd.tproj/stringops.c b/chkpasswd.tproj/stringops.c
new file mode 100644 (file)
index 0000000..568a025
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * 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 <string.h>
+#import <stdlib.h>
+#import <stdio.h>
+#import <varargs.h>
+#import "stringops.h"
+
+char *copyString(char *s)
+{
+       int len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       len = strlen(s) + 1;
+       t = malloc(len);
+       bcopy(s, t, len);
+       return t;
+}
+
+char *concatString(char *s, char *t)
+{
+       int len;
+
+       if (t == NULL) return s;
+
+       len = strlen(s) + strlen(t) + 1;
+       s = realloc(s, len);
+       strcat(s, t);
+       return s;
+}
+
+char **insertString(char *s, char **l, unsigned int x)
+{
+       int i, len;
+
+       if (s == NULL) return l;
+       if (l == NULL) 
+       {
+               l = (char **)malloc(2 * sizeof(char *));
+               l[0] = copyString(s);
+               l[1] = NULL;
+               return l;
+       }
+
+       for (i = 0; l[i] != NULL; i++);
+       len = i + 1; /* count the NULL on the end of the list too! */
+
+       l = (char **)realloc(l, (len + 1) * sizeof(char *));
+
+       if ((x >= (len - 1)) || (x == IndexNull))
+       {
+               l[len - 1] = copyString(s);
+               l[len] = NULL;
+               return l;
+       }
+
+       for (i = len; i > x; i--) l[i] = l[i - 1];
+       l[x] = copyString(s);
+       return l;
+}
+
+char **appendString(char *s, char **l)
+{
+       return insertString(s, l, IndexNull);
+}
+
+void freeList(char **l)
+{
+       int i;
+
+       if (l == NULL) return;
+       for (i = 0; l[i] != NULL; i++)
+       {
+               if (l[i] != NULL) free(l[i]);
+               l[i] = NULL;
+       }
+       if (l != NULL) free(l);
+}
+
+void freeString(char *s)
+{
+       if (s == NULL) return;
+       free(s);
+}
+
+unsigned int listLength(char **l)
+{
+       int i;
+
+       if (l == NULL) return 0;
+       for (i = 0; l[i] != NULL; i++);
+       return i;
+}
+
+unsigned int listIndex(char *s,char **l)
+{
+       int i;
+
+       if (l == NULL) return IndexNull;
+       for (i = 0; l[i] != NULL; i++)
+       {
+               if (strcmp(s, l[i]) == 0) return i;
+       }
+       return IndexNull;
+}
+
+char *prefix(char *s, char c)
+{
+       int i;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++);
+       if (i == 0) return NULL;
+       if (s[i] == '\0') return copyString(s);
+
+       t = malloc(i + 1);
+       bcopy(s, t, i);
+       t[i] = '\0';
+       return t;
+}
+
+char *postfix(char *s, char c)
+{
+       int i, len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++);
+       if (s[i] == '\0') return NULL;
+       len = strlen(s) - i;
+       if (len == 1) return NULL;
+
+       t = malloc(len);
+       len--;
+       bcopy((s + i + 1), t, len);
+       t[len] = '\0';
+       return t;
+}
+       
+char *presuffix(char *s, char c)
+{
+       int i, len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       len = strlen(s);
+       for (i = len - 1; ((i >= 0) && (s[i] != c)); i--);
+       if (i == 0) return NULL;
+       if (s[0] == '\0') return NULL;
+
+       t = malloc(i + 1);
+       bcopy(s, t, i);
+       t[i] = '\0';
+       return t;
+}
+
+char *suffix(char *s, char c)
+{
+       int i, len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       len = strlen(s);
+       for (i = len - 1; ((i >= 0) && (s[i] != c)); i--);
+       if (i == 0) return NULL;
+       len -= i;
+       if (len == 1) return NULL;
+       t = malloc(len);
+       len--;
+       bcopy((s + i + 1), t, len);
+       t[len] = '\0';
+       return t;
+}
+
+char *lowerCase(char *s)
+{
+       int i;
+       char *t;
+
+       if (s == NULL) return NULL;
+       t = malloc(strlen(s) + 1);
+
+       for (i = 0; s[i] != '\0'; i++) 
+       {
+               if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32;
+               else t[i] = s[i];
+       }
+       t[i] = '\0';
+       return t;
+}
+
+char **explode(char *s, char c)
+{
+       char **l = NULL;
+       char *p, *t;
+       int i, n;
+
+       if (s == NULL) return NULL;
+
+       p = s;
+       while (p[0] != '\0')
+       {
+               for (i = 0; ((p[i] != '\0') && p[i] != c); i++);
+               n = i;
+               t = malloc(n + 1);
+               for (i = 0; i < n; i++) t[i] = p[i];
+               t[n] = '\0';
+               l = appendString(t, l);
+               free(t);
+               t = NULL;
+               if (p[i] == '\0') return l;
+               if (p[i + 1] == '\0') l = appendString("", l);
+               p = p + i + 1;
+       }
+       return l;
+}
+
+char *itoa(int n)
+{
+       char s[32];
+
+       sprintf(s, "%d", n);
+       return copyString(s);
+}
diff --git a/chkpasswd.tproj/stringops.h b/chkpasswd.tproj/stringops.h
new file mode 100644 (file)
index 0000000..417a167
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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@
+ */
+#define streq(A, B) (strcmp(A, B) == 0)
+#define IndexNull (unsigned int)-1
+char *copyString(char *);
+char *concatString(char *, char *);
+char **insertString(char *, char **, unsigned int);
+char **appendString(char *, char **);
+void freeList(char **);
+void freeString(char *);
+unsigned int listLength(char **);
+unsigned int listIndex(char *,char **);
+char *prefix(char *, char);
+char *postfix(char *, char);
+char *presuffix(char *, char);
+char *suffix(char *, char);
+char *lowerCase(char *);
+char **explode(char *, char);
+char *itoa(int);
diff --git a/chpass.tproj/Makefile b/chpass.tproj/Makefile
new file mode 100644 (file)
index 0000000..b0d8d24
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# 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 = chpass
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = chpass.h pathnames.h pw_copy.h
+
+CFILES = chpass.c edit.c field.c pw_copy.c table.c util.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble chpass.1\
+            Makefile.dist
+
+
+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../pwd_mkdb.tproj -I../vipw.tproj
+PROJECT_HEADERS = pw_copy.h
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/chpass.tproj/Makefile.dist b/chpass.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..b68ad10
--- /dev/null
@@ -0,0 +1,15 @@
+#      @(#)Makefile    8.2 (Berkeley) 4/2/94
+
+PROG=  chpass
+SRCS=  chpass.c edit.c field.c pw_copy.c pw_scan.c pw_util.c table.c util.c
+BINOWN=        root
+BINMODE=4555
+.PATH: ${.CURDIR}/../../usr.sbin/pwd_mkdb ${.CURDIR}/../../usr.sbin/vipw
+CFLAGS+=-I${.CURDIR}/../../usr.sbin/pwd_mkdb -I${.CURDIR}/../../usr.sbin/vipw
+LINKS= ${BINDIR}/chpass ${BINDIR}/chfn ${BINDIR}/chpass ${BINDIR}/chsh
+MLINKS=        chpass.1 chfn.1 chpass.1 chsh.1
+
+afterinstall:
+       chflags schg /usr/bin/chpass
+
+.include <bsd.prog.mk>
diff --git a/chpass.tproj/Makefile.postamble b/chpass.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..7b6db99
--- /dev/null
@@ -0,0 +1,10 @@
+VPATH += :../pwd_mkdb.tproj:../vipw.tproj
+
+INSTALL_AS_USER =      root
+INSTALL_PERMISSIONS =4555
+#CHFLAGS = /usr/bin/chflags
+after_install::
+       $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/chfn
+       $(LN) -f $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/chsh
+#      $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
+
diff --git a/chpass.tproj/Makefile.preamble b/chpass.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..cb6b681
--- /dev/null
@@ -0,0 +1,4 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_OFILES = pw_scan.o pw_util.o
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/chpass.tproj/PB.project b/chpass.tproj/PB.project
new file mode 100644 (file)
index 0000000..849c116
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        CLASSES = (); 
+        C_FILES = (); 
+        HEADERSEARCH = (../pwd_mkdb.tproj, ../vipw.tproj); 
+        H_FILES = (chpass.h, pathnames.h, pw_copy.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (chpass.c, edit.c, field.c, pw_copy.c, table.c, util.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, chpass.1, Makefile.dist); 
+        PROJECT_HEADERS = (pw_copy.h); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = chpass; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/chpass.tproj/chpass.1 b/chpass.tproj/chpass.1
new file mode 100644 (file)
index 0000000..1a40905
--- /dev/null
@@ -0,0 +1,231 @@
+.\" Copyright (c) 1988, 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.
+.\"
+.\"     @(#)chpass.1   8.2 (Berkeley) 12/30/93
+.\"
+.Dd December 30, 1993
+.Dt CHPASS 1
+.Os
+.Sh NAME
+.Nm chpass
+.Nd add or change user database information
+.Sh SYNOPSIS
+chpass
+.Op Fl a Ar list
+.Op Fl s Ar newshell
+.Op user
+.Sh DESCRIPTION
+.Nm Chpass
+allows editing of the user database information associated
+with
+.Ar user
+or, by default, the current user.
+The information is formatted and supplied to an editor for changes.
+.Pp
+Only the information that the user is allowed to change is displayed.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl a
+The super-user is allowed to directly supply a user database
+entry, in the format specified by
+.Xr passwd 5 ,
+as an argument.
+This argument must be a colon (``:'') separated list of all the
+user database fields, although they may be empty.
+.It Fl s
+The
+.Fl s
+option attempts to change the user's shell to
+.Ar newshell .
+.El
+.Pp
+Possible display items are as follows:
+.Pp
+.Bl -tag -width "Home Directory:" -compact -offset indent
+.It Login:
+user's login name
+.It Password:
+user's encrypted password
+.It Uid:
+user's login
+.It Gid:
+user's login group
+.It Change:
+password change time
+.It Expire:
+account expiration time
+.It Class:
+user's general classification
+.It Home Directory:
+user's home directory
+.It Shell:
+user's login shell
+.It Full Name:
+user's real name
+.It Location:
+user's normal location
+.It Home Phone:
+user's home phone
+.It Office Phone:
+user's office phone
+.El
+.Pp
+The
+.Ar login
+field is the user name used to access the computer account.
+.Pp
+The
+.Ar password
+field contains the encrypted form of the user's password.
+.Pp
+The
+.Ar uid
+field is the number associated with the
+.Ar login
+field.
+Both of these fields should be unique across the system (and often
+across a group of systems) as they control file access.
+.Pp
+While it is possible to have multiple entries with identical login names
+and/or identical user id's, it is usually a mistake to do so.  Routines
+that manipulate these files will often return only one of the multiple
+entries, and that one by random selection.
+.Pp
+The
+.Ar group
+field is the group that the user will be placed in at login.
+Since BSD supports multiple groups (see
+.Xr groups 1 )
+this field currently has little special meaning.
+This field may be filled in with either a number or a group name (see
+.Xr group 5 ) .
+.Pp
+The
+.Ar change
+field is the date by which the password must be changed.
+.Pp
+The
+.Ar expire
+field is the date on which the account expires.
+.Pp
+Both the
+.Ar change
+and
+.Ar expire
+fields should be entered in the form ``month day year'' where
+.Ar month
+is the month name (the first three characters are sufficient),
+.Ar day
+is the day of the month, and
+.Ar year
+is the year.
+.Pp
+The
+.Ar class
+field is currently unused.  In the near future it will be a key to
+a
+.Xr termcap 5
+style database of user attributes.
+.Pp
+The user's
+.Ar home directory
+is the full UNIX path name where the user
+will be placed at login.
+.Pp
+The
+.Ar shell
+field is the command interpreter the user prefers.
+If the
+.Ar shell
+field is empty, the Bourne shell,
+.Pa /bin/sh ,
+is assumed.
+When altering a login shell, and not the super-user, the user
+may not change from a non-standard shell or to a non-standard
+shell.
+Non-standard is defined as a shell not found in
+.Pa /etc/shells .
+.Pp
+The last four fields are for storing the user's
+.Ar full name , office location ,
+and
+.Ar home
+and
+.Ar work telephone
+numbers.
+.Pp
+Once the information has been verified,
+.Nm chpass
+uses
+.Xr pwd_mkdb 8
+to update the user database.
+.Sh ENVIRONMENT
+The
+.Xr vi 1
+editor will be used unless the environment variable EDITOR is set to
+an alternate editor.
+When the editor terminates, the information is re-read and used to
+update the user database itself.
+Only the user, or the super-user, may edit the information associated
+with the user.
+.Sh FILES
+.Bl -tag -width /etc/master.passwd -compact
+.It Pa /etc/master.passwd
+The user database
+.It Pa /etc/passwd
+A Version 7 format password file
+.It Pa /etc/chpass.XXXXXX
+Temporary copy of the password file
+.It Pa /etc/shells
+The list of approved shells
+.El
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr finger 1 ,
+.Xr passwd 1 ,
+.Xr getusershell 3 ,
+.Xr passwd 5 ,
+.Xr pwd_mkdb 8 ,
+.Xr vipw 8
+.Rs
+.%A Robert Morris
+and
+.%A Ken Thompson
+.%T "UNIX Password security"
+.Re
+.Sh BUGS
+User information should (and eventually will) be stored elsewhere.
+.Sh HISTORY
+The
+.Nm
+command appeared in 
+.Bx 4.3 Reno .
diff --git a/chpass.tproj/chpass.c b/chpass.tproj/chpass.c
new file mode 100644 (file)
index 0000000..8068511
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * 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) 1990, 1993, 1994
+ *      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 char copyright[] =
+"@(#) Copyright (c) 1988, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <pw_scan.h>
+#include <pw_util.h>
+#include "pw_copy.h"
+
+#include "chpass.h"
+#include "pathnames.h"
+
+char *progname = "chpass";
+char *tempname;
+uid_t uid;
+
+void   baduser __P((void));
+void   usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       enum { NEWSH, LOADENTRY, EDITENTRY } op;
+       struct passwd *pw, lpw;
+       int ch, pfd, tfd;
+       char *arg;
+
+       op = EDITENTRY;
+       while ((ch = getopt(argc, argv, "a:s:")) != EOF)
+               switch(ch) {
+               case 'a':
+                       op = LOADENTRY;
+                       arg = optarg;
+                       break;
+               case 's':
+                       op = NEWSH;
+                       arg = optarg;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       uid = getuid();
+
+       if (op == EDITENTRY || op == NEWSH)
+               switch(argc) {
+               case 0:
+                       if (!(pw = getpwuid(uid)))
+                               errx(1, "unknown user: uid %u", uid);
+                       break;
+               case 1:
+                       if (!(pw = getpwnam(*argv)))
+                               errx(1, "unknown user: %s", *argv);
+                       if (uid && uid != pw->pw_uid)
+                               baduser();
+                       break;
+               default:
+                       usage();
+               }
+
+       if (op == NEWSH) {
+               /* protect p_shell -- it thinks NULL is /bin/sh */
+               if (!arg[0])
+                       usage();
+               if (p_shell(arg, pw, (ENTRY *)NULL))
+                       pw_error((char *)NULL, 0, 1);
+       }
+
+       if (op == LOADENTRY) {
+               if (uid)
+                       baduser();
+               pw = &lpw;
+               if (!pw_scan(arg, pw))
+                       exit(1);
+       }
+
+       /*
+        * The temporary file/file descriptor usage is a little tricky here.
+        * 1:   We start off with two fd's, one for the master password
+        *      file (used to lock everything), and one for a temporary file.
+        * 2:   Display() gets an fp for the temporary file, and copies the
+        *      user's information into it.  It then gives the temporary file
+        *      to the user and closes the fp, closing the underlying fd.
+        * 3:   The user edits the temporary file some number of times.
+        * 4:   Verify() gets an fp for the temporary file, and verifies the
+        *      contents.  It can't use an fp derived from the step #2 fd,
+        *      because the user's editor may have created a new instance of
+        *      the file.  Once the file is verified, its contents are stored
+        *      in a password structure.  The verify routine closes the fp,
+        *      closing the underlying fd.
+        * 5:   Delete the temporary file.
+        * 6:   Get a new temporary file/fd.  Pw_copy() gets an fp for it
+        *      file and copies the master password file into it, replacing
+        *      the user record with a new one.  We can't use the first
+        *      temporary file for this because it was owned by the user.
+        *      Pw_copy() closes its fp, flushing the data and closing the
+        *      underlying file descriptor.  We can't close the master
+        *      password fp, or we'd lose the lock.
+        * 7:   Call pw_mkdb() (which renames the temporary file) and exit.
+        *      The exit closes the master passwd fp/fd.
+        */
+       pw_init();
+       pfd = pw_lock();
+       tfd = pw_tmp();
+
+       if (op == EDITENTRY) {
+               display(tfd, pw);
+               edit(pw);
+               (void)unlink(tempname);
+               tfd = pw_tmp();
+       }
+               
+       pw_copy(pfd, tfd, pw);
+
+       if (!pw_mkdb())
+               pw_error((char *)NULL, 0, 1);
+       exit(0);
+}
+
+void
+baduser()
+{
+
+       errx(1, "%s", strerror(EACCES));
+}
+
+void
+usage()
+{
+
+       (void)fprintf(stderr, "usage: chpass [-a list] [-s shell] [user]\n");
+       exit(1);
+}
diff --git a/chpass.tproj/chpass.h b/chpass.tproj/chpass.h
new file mode 100644 (file)
index 0000000..99209d2
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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, 1994
+ *      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.
+ *
+ *      @(#)chpass.h    8.4 (Berkeley) 4/2/94
+ */
+
+struct passwd;
+
+typedef struct _entry {
+       char *prompt;
+       int (*func)(), restricted, len;
+       char *except, *save;
+} ENTRY;
+
+/* Field numbers. */
+#define        E_BPHONE        8
+#define        E_HPHONE        9
+#define        E_LOCATE        10
+#define        E_NAME          7
+#define        E_SHELL         12
+
+extern ENTRY list[];
+extern uid_t uid;
+
+int     atot __P((char *, time_t *));
+void    display __P((int, struct passwd *));
+void    edit __P((struct passwd *));
+char    *ok_shell __P((char *));
+int     p_change __P((char *, struct passwd *, ENTRY *));
+int     p_class __P((char *, struct passwd *, ENTRY *));
+int     p_expire __P((char *, struct passwd *, ENTRY *));
+int     p_gecos __P((char *, struct passwd *, ENTRY *));
+int     p_gid __P((char *, struct passwd *, ENTRY *));
+int     p_hdir __P((char *, struct passwd *, ENTRY *));
+int     p_login __P((char *, struct passwd *, ENTRY *));
+int     p_login __P((char *, struct passwd *, ENTRY *));
+int     p_passwd __P((char *, struct passwd *, ENTRY *));
+int     p_shell __P((char *, struct passwd *, ENTRY *));
+int     p_uid __P((char *, struct passwd *, ENTRY *));
+char    *ttoa __P((time_t));
+int     verify __P((struct passwd *));
diff --git a/chpass.tproj/edit.c b/chpass.tproj/edit.c
new file mode 100644 (file)
index 0000000..0b9e3d2
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * 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) 1990, 1993, 1994
+ *      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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <pw_scan.h>
+#include <pw_util.h>
+
+#include "chpass.h"
+
+extern char *tempname;
+
+void
+edit(pw)
+       struct passwd *pw;
+{
+       struct stat begin, end;
+
+       for (;;) {
+               if (stat(tempname, &begin))
+                       pw_error(tempname, 1, 1);
+               pw_edit(1);
+               if (stat(tempname, &end))
+                       pw_error(tempname, 1, 1);
+               if (begin.st_mtime == end.st_mtime) {
+                       warnx("no changes made");
+                       pw_error(NULL, 0, 0);
+               }
+               if (verify(pw))
+                       break;
+               pw_prompt();
+       }
+}
+
+/*
+ * display --
+ *     print out the file for the user to edit; strange side-effect:
+ *     set conditional flag if the user gets to edit the shell.
+ */
+void
+display(fd, pw)
+       int fd;
+       struct passwd *pw;
+{
+       FILE *fp;
+       char *bp, *p, *ttoa();
+
+       if (!(fp = fdopen(fd, "w")))
+               pw_error(tempname, 1, 1);
+
+       (void)fprintf(fp,
+           "#Changing user database information for %s.\n", pw->pw_name);
+       if (!uid) {
+               (void)fprintf(fp, "Login: %s\n", pw->pw_name);
+               (void)fprintf(fp, "Password: %s\n", pw->pw_passwd);
+               (void)fprintf(fp, "Uid [#]: %d\n", pw->pw_uid);
+               (void)fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid);
+               (void)fprintf(fp, "Change [month day year]: %s\n",
+                   ttoa(pw->pw_change));
+               (void)fprintf(fp, "Expire [month day year]: %s\n",
+                   ttoa(pw->pw_expire));
+               (void)fprintf(fp, "Class: %s\n", pw->pw_class);
+               (void)fprintf(fp, "Home directory: %s\n", pw->pw_dir);
+               (void)fprintf(fp, "Shell: %s\n",
+                   *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
+       }
+       /* Only admin can change "restricted" shells. */
+       else if (ok_shell(pw->pw_shell))
+               /*
+                * Make shell a restricted field.  Ugly with a
+                * necklace, but there's not much else to do.
+                */
+               (void)fprintf(fp, "Shell: %s\n",
+                   *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL);
+       else
+               list[E_SHELL].restricted = 1;
+       bp = pw->pw_gecos;
+       p = strsep(&bp, ",");
+       (void)fprintf(fp, "Full Name: %s\n", p ? p : "");
+       p = strsep(&bp, ",");
+       (void)fprintf(fp, "Location: %s\n", p ? p : "");
+       p = strsep(&bp, ",");
+       (void)fprintf(fp, "Office Phone: %s\n", p ? p : "");
+       p = strsep(&bp, ",");
+       (void)fprintf(fp, "Home Phone: %s\n", p ? p : "");
+
+       (void)fchown(fd, getuid(), getgid());
+       (void)fclose(fp);
+}
+
+int
+verify(pw)
+       struct passwd *pw;
+{
+       ENTRY *ep;
+       char *p;
+       struct stat sb;
+       FILE *fp;
+       int len;
+       char buf[LINE_MAX];
+
+       if (!(fp = fopen(tempname, "r")))
+               pw_error(tempname, 1, 1);
+       if (fstat(fileno(fp), &sb))
+               pw_error(tempname, 1, 1);
+       if (sb.st_size == 0) {
+               warnx("corrupted temporary file");
+               goto bad;
+       }
+       while (fgets(buf, sizeof(buf), fp)) {
+               if (!buf[0] || buf[0] == '#')
+                       continue;
+               if (!(p = strchr(buf, '\n'))) {
+                       warnx("line too long");
+                       goto bad;
+               }
+               *p = '\0';
+               for (ep = list;; ++ep) {
+                       if (!ep->prompt) {
+                               warnx("unrecognized field");
+                               goto bad;
+                       }
+                       if (!strncasecmp(buf, ep->prompt, ep->len)) {
+                               if (ep->restricted && uid) {
+                                       warnx(
+                                           "you may not change the %s field",
+                                               ep->prompt);
+                                       goto bad;
+                               }
+                               if (!(p = strchr(buf, ':'))) {
+                                       warnx("line corrupted");
+                                       goto bad;
+                               }
+                               while (isspace(*++p));
+                               if (ep->except && strpbrk(p, ep->except)) {
+                                       warnx(
+                                  "illegal character in the \"%s\" field",
+                                           ep->prompt);
+                                       goto bad;
+                               }
+                               if ((ep->func)(p, pw, ep)) {
+bad:                                   (void)fclose(fp);
+                                       return (0);
+                               }
+                               break;
+                       }
+               }
+       }
+       (void)fclose(fp);
+
+       /* Build the gecos field. */
+       len = strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) +
+           strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) + 4;
+       if (!(p = malloc(len)))
+               err(1, NULL);
+       (void)sprintf(pw->pw_gecos = p, "%s,%s,%s,%s", list[E_NAME].save,
+           list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save);
+
+       if (snprintf(buf, sizeof(buf),
+           "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s",
+           pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class,
+           pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir,
+           pw->pw_shell) >= sizeof(buf)) {
+               warnx("entries too long");
+               return (0);
+       }
+       return (pw_scan(buf, pw));
+}
diff --git a/chpass.tproj/field.c b/chpass.tproj/field.c
new file mode 100644 (file)
index 0000000..2fc07ba
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * 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, 1994
+ *      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.
+ */
+
+#include <sys/param.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "chpass.h"
+#include "pathnames.h"
+
+/* ARGSUSED */
+int
+p_login(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!*p) {
+               warnx("empty login field");
+               return (1);
+       }
+       if (*p == '-') {
+               warnx("login names may not begin with a hyphen");
+               return (1);
+       }
+       if (!(pw->pw_name = strdup(p))) {
+               warnx("can't save entry");
+               return (1);
+       }
+       if (strchr(p, '.'))
+               warnx("\'.\' is dangerous in a login name");
+       for (; *p; ++p)
+               if (isupper(*p)) {
+                       warnx("upper-case letters are dangerous in a login name");
+                       break;
+               }
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_passwd(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!*p)
+               pw->pw_passwd = "";     /* "NOLOGIN"; */
+       else if (!(pw->pw_passwd = strdup(p))) {
+               warnx("can't save password entry");
+               return (1);
+       }
+       
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_uid(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       uid_t id;
+       char *np;
+
+       if (!*p) {
+               warnx("empty uid field");
+               return (1);
+       }
+       if (!isdigit(*p)) {
+               warnx("illegal uid");
+               return (1);
+       }
+       errno = 0;
+       id = strtoul(p, &np, 10);
+       if (*np || (id == ULONG_MAX && errno == ERANGE)) {
+               warnx("illegal uid");
+               return (1);
+       }
+       pw->pw_uid = id;
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_gid(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       struct group *gr;
+       gid_t id;
+       char *np;
+
+       if (!*p) {
+               warnx("empty gid field");
+               return (1);
+       }
+       if (!isdigit(*p)) {
+               if (!(gr = getgrnam(p))) {
+                       warnx("unknown group %s", p);
+                       return (1);
+               }
+               pw->pw_gid = gr->gr_gid;
+               return (0);
+       }
+       errno = 0;
+       id = strtoul(p, &np, 10);
+       if (*np || (id == ULONG_MAX && errno == ERANGE)) {
+               warnx("illegal gid");
+               return (1);
+       }
+       pw->pw_gid = id;
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_class(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!*p)
+               pw->pw_class = "";
+       else if (!(pw->pw_class = strdup(p))) {
+               warnx("can't save entry");
+               return (1);
+       }
+       
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_change(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!atot(p, &pw->pw_change))
+               return (0);
+       warnx("illegal date for change field");
+       return (1);
+}
+
+/* ARGSUSED */
+int
+p_expire(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!atot(p, &pw->pw_expire))
+               return (0);
+       warnx("illegal date for expire field");
+       return (1);
+}
+
+/* ARGSUSED */
+int
+p_gecos(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!*p)
+               ep->save = "";
+       else if (!(ep->save = strdup(p))) {
+               warnx("can't save entry");
+               return (1);
+       }
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_hdir(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       if (!*p) {
+               warnx("empty home directory field");
+               return (1);
+       }
+       if (!(pw->pw_dir = strdup(p))) {
+               warnx("can't save entry");
+               return (1);
+       }
+       return (0);
+}
+
+/* ARGSUSED */
+int
+p_shell(p, pw, ep)
+       char *p;
+       struct passwd *pw;
+       ENTRY *ep;
+{
+       char *t, *ok_shell();
+
+       if (!*p) {
+               pw->pw_shell = _PATH_BSHELL;
+               return (0);
+       }
+       /* only admin can change from or to "restricted" shells */
+       if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) {
+               warnx("%s: current shell non-standard", pw->pw_shell);
+               return (1);
+       }
+       if (!(t = ok_shell(p))) {
+               if (uid) {
+                       warnx("%s: non-standard shell", p);
+                       return (1);
+               }
+       }
+       else
+               p = t;
+       if (!(pw->pw_shell = strdup(p))) {
+               warnx("can't save entry");
+               return (1);
+       }
+       return (0);
+}
diff --git a/chpass.tproj/pathnames.h b/chpass.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..03c43a3
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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) 1989, 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.
+ *
+ *      @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <paths.h>
+
+#undef _PATH_TMP
+#define        _PATH_TMP       "/tmp/chpass.XXXXXX"
diff --git a/chpass.tproj/pw_copy.c b/chpass.tproj/pw_copy.c
new file mode 100644 (file)
index 0000000..64ddc9f
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * 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) 1990, 1993, 1994
+ *      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.
+ */
+
+/*
+ * This module is used to copy the master password file, replacing a single
+ * record, by chpass(1) and passwd(1).
+ */
+
+#include <err.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <pw_util.h>
+#include "pw_copy.h"
+
+extern char *tempname;
+
+void
+pw_copy(ffd, tfd, pw)
+       int ffd, tfd;
+       struct passwd *pw;
+{
+       FILE *from, *to;
+       int done;
+       char *p, buf[8192];
+
+       if (!(from = fdopen(ffd, "r")))
+               pw_error(_PATH_MASTERPASSWD, 1, 1);
+       if (!(to = fdopen(tfd, "w")))
+               pw_error(tempname, 1, 1);
+
+       for (done = 0; fgets(buf, sizeof(buf), from);) {
+               if (!strchr(buf, '\n')) {
+                       warnx("%s: line too long", _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+#if defined(__APPLE__)
+               if (done || (buf[0] == '#')) {
+#else
+               if (done) {
+#endif
+                       (void)fprintf(to, "%s", buf);
+                       if (ferror(to))
+                               goto err;
+                       continue;
+               }
+               if (!(p = strchr(buf, ':'))) {
+                       warnx("%s: corrupted entry", _PATH_MASTERPASSWD);
+                       pw_error(NULL, 0, 1);
+               }
+               *p = '\0';
+               if (strcmp(buf, pw->pw_name)) {
+                       *p = ':';
+                       (void)fprintf(to, "%s", buf);
+                       if (ferror(to))
+                               goto err;
+                       continue;
+               }
+               (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+                   pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
+                   pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos,
+                   pw->pw_dir, pw->pw_shell);
+               done = 1;
+               if (ferror(to))
+                       goto err;
+       }
+       if (!done)
+               (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n",
+                   pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid,
+                   pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos,
+                   pw->pw_dir, pw->pw_shell);
+
+       if (ferror(to))
+err:           pw_error(NULL, 1, 1);
+       (void)fclose(to);
+}
diff --git a/chpass.tproj/pw_copy.h b/chpass.tproj/pw_copy.h
new file mode 100644 (file)
index 0000000..4a742ac
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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) 1990, 1993, 1994
+ *      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.
+ */
+
+void    pw_copy __P((int, int, struct passwd *));
diff --git a/chpass.tproj/table.c b/chpass.tproj/table.c
new file mode 100644 (file)
index 0000000..dbae702
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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) 1990, 1993, 1994
+ *      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.
+ */
+
+#include <sys/types.h>
+#include <stddef.h>
+#include "chpass.h"
+
+char e1[] = ": ";
+char e2[] = ":,";
+
+ENTRY list[] = {
+       { "login",              p_login,  1,   5, e1,   },
+       { "password",           p_passwd, 1,   8, e1,   },
+       { "uid",                p_uid,    1,   3, e1,   },
+       { "gid",                p_gid,    1,   3, e1,   },
+       { "class",              p_class,  1,   5, e1,   },
+       { "change",             p_change, 1,   6, NULL, },
+       { "expire",             p_expire, 1,   6, NULL, },
+       { "full name",          p_gecos,  0,   9, e2,   },
+       { "office phone",       p_gecos,  0,  12, e2,   },
+       { "home phone",         p_gecos,  0,  10, e2,   },
+       { "location",           p_gecos,  0,   8, e2,   },
+       { "home directory",     p_hdir,   1,  14, e1,   },
+       { "shell",              p_shell,  0,   5, e1,   },
+       { NULL, 0, },
+};
diff --git a/chpass.tproj/util.c b/chpass.tproj/util.c
new file mode 100644 (file)
index 0000000..c4dd4d3
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * 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, 1994
+ *      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.
+ */
+
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <tzfile.h>
+#include <unistd.h>
+
+#include "chpass.h"
+#include "pathnames.h"
+
+static int dmsize[] =
+       { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static char *months[] =
+       { "January", "February", "March", "April", "May", "June",
+         "July", "August", "September", "October", "November",
+         "December", NULL };
+
+char *
+ttoa(tval)
+       time_t tval;
+{
+       struct tm *tp;
+       static char tbuf[50];
+
+       if (tval) {
+               tp = localtime(&tval);
+               (void)sprintf(tbuf, "%s %d, %d", months[tp->tm_mon],
+                   tp->tm_mday, tp->tm_year + TM_YEAR_BASE);
+       }
+       else
+               *tbuf = '\0';
+       return (tbuf);
+} 
+
+int
+atot(p, store)
+       char *p;
+       time_t *store;
+{
+       static struct tm *lt;
+       char *t, **mp;
+       time_t tval;
+       int day, month, year;
+
+       if (!*p) {
+               *store = 0;
+               return (0);
+       }
+       if (!lt) {
+               unsetenv("TZ");
+               (void)time(&tval);
+               lt = localtime(&tval);
+       }
+       if (!(t = strtok(p, " \t")))
+               goto bad;
+       for (mp = months;; ++mp) {
+               if (!*mp)
+                       goto bad;
+               if (!strncasecmp(*mp, t, 3)) {
+                       month = mp - months + 1;
+                       break;
+               }
+       }
+       if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t))
+               goto bad;
+       day = atoi(t);
+       if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t))
+               goto bad;
+       year = atoi(t);
+       if (day < 1 || day > 31 || month < 1 || month > 12 || !year)
+               goto bad;
+       if (year < 100)
+               year += TM_YEAR_BASE;
+       if (year <= EPOCH_YEAR)
+bad:           return (1);
+       tval = isleap(year) && month > 2;
+       for (--year; year >= EPOCH_YEAR; --year)
+               tval += isleap(year) ?
+                   DAYSPERLYEAR : DAYSPERNYEAR;
+       while (--month)
+               tval += dmsize[month];
+       tval += day;
+       tval = tval * HOURSPERDAY * MINSPERHOUR * SECSPERMIN;
+       tval -= lt->tm_gmtoff;
+       *store = tval;
+       return (0);
+}
+
+char *
+ok_shell(name)
+       char *name;
+{
+       char *p, *sh;
+
+       setusershell();
+       while (sh = getusershell()) {
+               if (!strcmp(name, sh))
+                       return (name);
+               /* allow just shell name, but use "real" path */
+               if ((p = strrchr(sh, '/')) && strcmp(name, p + 1) == 0)
+                       return (sh);
+       }
+       return (NULL);
+}
diff --git a/dmesg.tproj/Makefile b/dmesg.tproj/Makefile
new file mode 100644 (file)
index 0000000..878e0a7
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = dmesg
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = dmesg.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            dmesg.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/dmesg.tproj/Makefile.dist b/dmesg.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..fc5edce
--- /dev/null
@@ -0,0 +1,10 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  dmesg
+MAN8=  dmesg.0
+BINGRP=        kmem
+BINMODE=2555
+LDADD= -lkvm
+DPADD= ${LIBKVM}
+
+.include <bsd.prog.mk>
diff --git a/dmesg.tproj/Makefile.postamble b/dmesg.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..2e4a713
--- /dev/null
@@ -0,0 +1,2 @@
+INSTALL_AS_GROUP = kmem     # (probably want to set both of these) 
+INSTALL_PERMISSIONS = 2555  # If set, 'install' chmod's executable to this
diff --git a/dmesg.tproj/Makefile.preamble b/dmesg.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/dmesg.tproj/PB.project b/dmesg.tproj/PB.project
new file mode 100644 (file)
index 0000000..22572b4
--- /dev/null
@@ -0,0 +1,31 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (dmesg.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, dmesg.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = dmesg; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = dmesg; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = dmesg; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = dmesg; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/dmesg.tproj/dmesg.8 b/dmesg.tproj/dmesg.8
new file mode 100644 (file)
index 0000000..7dd0acf
--- /dev/null
@@ -0,0 +1,63 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"     @(#)dmesg.8    8.1 (Berkeley) 6/5/93
+.\"
+.Dd June 5, 1993
+.Dt DMESG 8
+.Os BSD 4
+.Sh NAME
+.Nm dmesg
+.Nd "display the system message buffer"
+.Sh SYNOPSIS
+.Nm dmesg
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Sh DESCRIPTION
+.Nm Dmesg
+displays the contents of the system message buffer.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default ``/dev/kmem''.
+.It Fl N
+Extract the name list from the specified system instead of the default
+``/vmunix''.
+.El
+.Sh SEE ALSO
+.Xr syslogd 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/dmesg.tproj/dmesg.c b/dmesg.tproj/dmesg.c
new file mode 100644 (file)
index 0000000..10d5cae
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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) 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.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/msgbuf.h>
+
+#include <fcntl.h>
+#include <kvm.h>
+#include <limits.h>
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <vis.h>
+
+struct nlist nl[] = {
+#define        X_MSGBUF        0
+       { "_msgbufp" },
+       { NULL },
+};
+
+void usage __P((void));
+
+#define        KREAD(addr, var) \
+       kvm_read(kd, addr, &var, sizeof(var)) != sizeof(var)
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register int ch, newl, skip;
+       register char *p, *ep;
+       struct msgbuf *bufp, cur;
+       char *memf, *nlistf;
+       kvm_t *kd;
+       char buf[5];
+
+       memf = nlistf = NULL;
+       while ((ch = getopt(argc, argv, "M:N:")) != EOF)
+               switch(ch) {
+               case 'M':
+                       memf = optarg;
+                       break;
+               case 'N':
+                       nlistf = optarg;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       /*
+        * Discard setgid privileges if not the running kernel so that bad
+        * guys can't print interesting stuff from kernel memory.
+        */
+       if (memf != NULL || nlistf != NULL)
+               setgid(getgid());
+
+       /* Read in kernel message buffer, do sanity checks. */
+       if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg")) == NULL)
+               exit (1);
+       if (kvm_nlist(kd, nl) == -1)
+               errx(1, "kvm_nlist: %s", kvm_geterr(kd));
+       if (nl[X_MSGBUF].n_type == 0)
+               errx(1, "%s: msgbufp not found", nlistf ? nlistf : "namelist");
+       if (KREAD(nl[X_MSGBUF].n_value, bufp) || KREAD((long)bufp, cur))
+               errx(1, "kvm_read: %s", kvm_geterr(kd));
+       kvm_close(kd);
+       if (cur.msg_magic != MSG_MAGIC)
+               errx(1, "magic number incorrect");
+       if (cur.msg_bufx >= MSG_BSIZE)
+               cur.msg_bufx = 0;
+
+       /*
+        * The message buffer is circular; start at the read pointer, and
+        * go to the write pointer - 1.
+        */
+       p = cur.msg_bufc + cur.msg_bufx;
+       ep = cur.msg_bufc + cur.msg_bufx - 1;
+       for (newl = skip = 0; p != ep; ++p) {
+               if (p == cur.msg_bufc + MSG_BSIZE)
+                       p = cur.msg_bufc;
+               ch = *p;
+               /* Skip "\n<.*>" syslog sequences. */
+               if (skip) {
+                       if (ch == '>')
+                               newl = skip = 0;
+                       continue;
+               }
+               if (newl && ch == '<') {
+                       skip = 1;
+                       continue;
+               }
+               if (ch == '\0')
+                       continue;
+               newl = ch == '\n';
+               (void)vis(buf, ch, 0, 0);
+               if (buf[1] == 0)
+                       (void)putchar(buf[0]);
+               else
+                       (void)printf("%s", buf);
+       }
+       if (!newl)
+               (void)putchar('\n');
+       exit(0);
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: dmesg [-M core] [-N system]\n");
+       exit(1);
+}
diff --git a/dp_notify_lib/Makefile b/dp_notify_lib/Makefile
new file mode 100644 (file)
index 0000000..725d4b4
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# 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 = dp_notify_lib
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Library
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template backing_store_alerts.defs\
+            backing_store_triggers.defs
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CURRENTLY_ACTIVE_VERSION = YES
+DEPLOY_WITH_VERSION_NAME = A
+CODE_GEN_STYLE = STATIC
+MAKEFILE = library.make
+NEXTSTEP_INSTALLDIR = /usr/local/lib
+WINDOWS_INSTALLDIR = /Developer/Libraries
+PDO_UNIX_INSTALLDIR = /lib
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+FRAMEWORK_PATHS =
+NEXTSTEP_PB_LDFLAGS = -static
+FRAMEWORKS = 
+
+
+WINDOWS_PUBLIC_HEADERS_DIR = $(HOMEDRIVE)$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)
+
+PDO_UNIX_PUBLIC_HEADERS_DIR = $(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)
+
+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/dp_notify_lib/Makefile.postamble b/dp_notify_lib/Makefile.postamble
new file mode 100644 (file)
index 0000000..0e1fe3c
--- /dev/null
@@ -0,0 +1,133 @@
+###############################################################################
+#  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
+
+INSTALLDIR = /usr/local/lib
+
+#########################################################################
+# 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.
+#
+MIGFLAGS = -traditional-cpp -R -untyped -DNO_DIRECT_RPC -I$(SRCROOT)
+MIG = $(NEXT_ROOT)/usr/bin/mig
+
+backing_store_alerts_server.c: \
+       backing_store_alerts.defs
+       ${MKDIRS}  \
+       ${DSTROOT}${PUBLIC_HDR_INSTALLDIR}${PUBLIC_HEADER_DIR_SUFFIX};
+       cp backing_store_alerts.defs $(SYM_DIR);
+       cd $(SYM_DIR) && \
+       $(MIG) $(MIGFLAGS) -user /dev/null -server \
+       backing_store_alerts_server.c -sheader backing_store_alerts_server.h \
+       backing_store_alerts.defs
+
+backing_store_triggers.c: \
+       backing_store_triggers.defs
+       cp backing_store_triggers.defs $(SYM_DIR);
+       cd $(SYM_DIR) && \
+       $(MIG) $(MIGFLAGS) -user backing_store_triggers.c -server /dev/null -header backing_store_triggers.h backing_store_triggers.defs
+
+backing_store_alerts_server.h: backing_store_alerts_server.c 
+
+backing_store_triggers.h: backing_store_triggers.c 
+
+static:
+       $(SILENT) unset $(CUMULATIVE_VARIABLES) ||: ; \
+       $(MAKE) BUILD_TYPE=$@ BUILD_TYPE_SUFFIX=$(STATIC_SUFFIX)
+
+copy_dstroot: 
+       ${CP}  $(SYM_DIR)/backing_store_triggers.h $(DSTROOT)${PUBLIC_HDR_INSTALLDIR}${PUBLIC_HEADER_DIR_SUFFIX}
+       ${CP}  $(SYM_DIR)/backing_store_alerts_server.h $(DSTROOT)${PUBLIC_HDR_INSTALLDIR}${PUBLIC_HEADER_DIR_SUFFIX}
+       ${CHMOD} 444 $(DSTROOT)${PUBLIC_HDR_INSTALLDIR}${PUBLIC_HEADER_DIR_SUFFIX}/backing_store_triggers.h
+       ${CHMOD} 444 $(DSTROOT)${PUBLIC_HDR_INSTALLDIR}${PUBLIC_HEADER_DIR_SUFFIX}/backing_store_alerts_server.h
diff --git a/dp_notify_lib/Makefile.preamble b/dp_notify_lib/Makefile.preamble
new file mode 100644 (file)
index 0000000..31a37e3
--- /dev/null
@@ -0,0 +1,145 @@
+###############################################################################
+#  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.
+VPATH_PREAMBLE = ../dynamic_pager.tproj:
+#DSTROOT = $(HOME)
+LIBRARY_STYLE = STATIC
+OTHER_OFILES = backing_store_alerts_server.o backing_store_triggers.o
+BEFORE_BUILD = backing_store_alerts_server.o backing_store_triggers.o
+PUBLIC_HDR_INSTALLDIR = /usr/local/include
+PUBLIC_HEADER_DIR_SUFFIX = /mach
+LIBRARY_STYLE = STATIC
+AFTER_INSTALL += copy_dstroot
diff --git a/dp_notify_lib/PB.project b/dp_notify_lib/PB.project
new file mode 100644 (file)
index 0000000..f749d81
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    CURRENTLY_ACTIVE_VERSION = YES; 
+    DEPLOY_WITH_VERSION_NAME = A; 
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            m.template, 
+            h.template, 
+            backing_store_alerts.defs, 
+            backing_store_triggers.defs
+        ); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/local/lib; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = "-static"; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_INSTALLDIR = /lib; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PDO_UNIX_PUBLICHEADERSDIR = "$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)"; 
+    PROJECTNAME = dp_notify_lib; 
+    PROJECTTYPE = Library; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_INSTALLDIR = /Developer/Libraries; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+    WINDOWS_PUBLICHEADERSDIR = "$(HOMEDRIVE)$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)"; 
+}
diff --git a/dp_notify_lib/backing_store_alerts.defs b/dp_notify_lib/backing_store_alerts.defs
new file mode 100644 (file)
index 0000000..661af83
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * File:       dynamic_pager.tproj/backing_store_alerts.defs
+ * Author:     Chris Youngworth
+ * Date:       Oct, 1999
+ *
+ *     Exported alerts from the dynamic_pager facility.
+ */
+
+subsystem
+
+       backing_store_alerts 1000;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+
+simpleroutine  backing_store_alert(
+               alert_port              : mach_port_t;
+       in      flags                   : int);
diff --git a/dp_notify_lib/backing_store_triggers.defs b/dp_notify_lib/backing_store_triggers.defs
new file mode 100644 (file)
index 0000000..a279266
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * File:       dynamic_pager.tproj/backing_store_triggers.defs
+ * Author:     Chris Youngworth
+ * Date:       Oct, 1999
+ *
+ *     Exported client calls to the dynamic_pager facility.
+ */
+subsystem
+
+       backing_store_triggers 1200;
+
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+
+simpleroutine  backing_store_triggers(
+               dynamic_pager           : mach_port_t;
+       in      hi_wat                  : int;
+       in      flags                   : int;
+       in      trigger_port            : mach_port_t);
diff --git a/dp_notify_lib/h.template b/dp_notify_lib/h.template
new file mode 100644 (file)
index 0000000..f3c1b04
--- /dev/null
@@ -0,0 +1,11 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
diff --git a/dp_notify_lib/m.template b/dp_notify_lib/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/dynamic_pager.tproj/Makefile b/dynamic_pager.tproj/Makefile
new file mode 100644 (file)
index 0000000..b406af1
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = dynamic_pager
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = dynamic_pager.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\
+            default_pager_alerts.defs backing_store_alerts.defs\
+            backing_store_triggers.defs
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -traditional-cpp -DNO_DIRECT_RPC
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/dynamic_pager.tproj/Makefile.postamble b/dynamic_pager.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..18e890b
--- /dev/null
@@ -0,0 +1,126 @@
+#PRECOMP_CFLAGS =
+#NONRECURSIVE_PRECOMPFLAGS =
+#OPTIMIZE_BUILD_CFLAGS =
+SRC_ROOT = $(SRCROOT)
+
+###############################################################################
+#  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.
+#  LANGUAGE: langage in which the project is written (default "English")
+#  LOCAL_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.
+#
+MIGFLAGS = -traditional-cpp -R  -untyped -DNO_DIRECT_RPC
+MIG = $(NEXT_ROOT)/usr/bin/mig 
+        
+default_pager_alerts_server.c : backing_store_alerts.c \
+       backing_store_triggers_server.c \
+       default_pager_alerts.defs
+       cp $(SRCROOT)/dynamic_pager.tproj/default_pager_alerts.defs $(SYM_DIR);
+       cd $(SYM_DIR) && \
+       $(MIG) $(MIGFLAGS) -user /dev/null -server default_pager_alerts_server.c -sheader default_pager_alerts_server.h default_pager_alerts.defs
+
+backing_store_alerts.c: \
+       backing_store_alerts.defs
+       cp $(SRCROOT)/dynamic_pager.tproj/backing_store_alerts.defs $(SYM_DIR);
+       cd $(SYM_DIR) && \
+       $(MIG) $(MIGFLAGS) -server /dev/null -user backing_store_alerts.c -header backing_store_alerts.h backing_store_alerts.defs
+
+backing_store_triggers_server.c: \
+       backing_store_triggers.defs
+       cp $(SRCROOT)/dynamic_pager.tproj/backing_store_triggers.defs $(SYM_DIR);
+       cd $(SYM_DIR) && \
+       $(MIG) $(MIGFLAGS) -user /dev/null -server backing_store_triggers_server.c -sheader backing_store_triggers_server.h backing_store_triggers.defs
diff --git a/dynamic_pager.tproj/Makefile.preamble b/dynamic_pager.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..088fb3c
--- /dev/null
@@ -0,0 +1,129 @@
+###############################################################################
+#  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.
+#    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. <<default?>>
+#    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
+OTHER_OFILES = default_pager_alerts_server.o backing_store_alerts.o backing_store_triggers_server.o
+#OTHER_PUBLIC_HEADERS = default_pager_alerts_server.h
+#OTHER_GENERATED_OFILES = $(VERS_OFILE)
+-include ../Makefile.include
+OTHER_CFLAGS =
+BEFORE_BUILD = default_pager_alerts_server.o 
diff --git a/dynamic_pager.tproj/PB.project b/dynamic_pager.tproj/PB.project
new file mode 100644 (file)
index 0000000..74203e7
--- /dev/null
@@ -0,0 +1,33 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        OTHER_LINKED = (dynamic_pager.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            default_pager_alerts.defs, 
+            backing_store_alerts.defs, 
+            backing_store_triggers.defs
+        ); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-traditional-cpp -DNO_DIRECT_RPC"; 
+    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_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = dynamic_pager; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/dynamic_pager.tproj/backing_store_alerts.defs b/dynamic_pager.tproj/backing_store_alerts.defs
new file mode 100644 (file)
index 0000000..661af83
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * File:       dynamic_pager.tproj/backing_store_alerts.defs
+ * Author:     Chris Youngworth
+ * Date:       Oct, 1999
+ *
+ *     Exported alerts from the dynamic_pager facility.
+ */
+
+subsystem
+
+       backing_store_alerts 1000;
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+
+simpleroutine  backing_store_alert(
+               alert_port              : mach_port_t;
+       in      flags                   : int);
diff --git a/dynamic_pager.tproj/backing_store_triggers.defs b/dynamic_pager.tproj/backing_store_triggers.defs
new file mode 100644 (file)
index 0000000..a279266
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * File:       dynamic_pager.tproj/backing_store_triggers.defs
+ * Author:     Chris Youngworth
+ * Date:       Oct, 1999
+ *
+ *     Exported client calls to the dynamic_pager facility.
+ */
+subsystem
+
+       backing_store_triggers 1200;
+
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+
+simpleroutine  backing_store_triggers(
+               dynamic_pager           : mach_port_t;
+       in      hi_wat                  : int;
+       in      flags                   : int;
+       in      trigger_port            : mach_port_t);
diff --git a/dynamic_pager.tproj/default_pager_alerts.defs b/dynamic_pager.tproj/default_pager_alerts.defs
new file mode 100644 (file)
index 0000000..4d8fe61
--- /dev/null
@@ -0,0 +1 @@
+#include <default_pager/default_pager_alerts.defs>
diff --git a/dynamic_pager.tproj/dynamic_pager.c b/dynamic_pager.tproj/dynamic_pager.c
new file mode 100644 (file)
index 0000000..51ce54c
--- /dev/null
@@ -0,0 +1,355 @@
+/* File created by Chris Youngworth, Apple Computer 2/11/99 */
+
+
+#define mig_external
+
+#include <mach/port.h>
+#include <mach/mach_error.h>
+#include <mach/mach_traps.h>
+#include <mach/mach.h>
+#ifndef MACH_BSD
+#define MACH_BSD
+#endif
+#include <mach/bootstrap.h>
+#include <mach/mach_syscalls.h>
+#include <mach/mig_errors.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/gmon.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <nlist.h>
+#include <ctype.h>
+#include <unistd.h> 
+#include <paths.h>
+
+#include <default_pager/default_pager_types.h>
+#include <default_pager_alerts_server.h>
+#include <backing_store_alerts.h>
+#include <backing_store_triggers_server.h>
+
+int    debug = 0;
+int    file_count = 0;
+int    low_water = 0;
+int    hi_water = 0;
+int    local_hi_water = 0;
+int    size  = 20000000;
+int    priority = 0;
+int    options = 0;
+char   fileroot[512];
+
+
+/* global parameters for application notification option */
+mach_port_t    trigger_port = NULL;
+mach_port_t    notify_port = NULL;
+int            notify_high = 0;
+int            bs_recovery;
+
+/*
+void   setprof __P((struct kvmvars *kvp, int state));
+void   dumpstate __P((struct kvmvars *kvp));
+void   reset __P((struct kvmvars *kvp));
+*/
+
+
+
+mach_msg_return_t
+server_alert_loop(
+    mach_msg_size_t max_size,
+    mach_port_t rcv_name,
+    mach_msg_options_t options)
+{
+    mig_reply_error_t *bufRequest = 0, *bufReply = 0;
+    register mach_msg_return_t mr;
+    register kern_return_t kr;
+
+    if ((kr = vm_allocate(mach_task_self(),
+                     (vm_address_t *)&bufRequest,
+                     max_size + MAX_TRAILER_SIZE,
+                     TRUE)) != KERN_SUCCESS)
+      return kr;
+    mlock(bufRequest, max_size + MAX_TRAILER_SIZE);
+    if ((kr = vm_allocate(mach_task_self(),
+                     (vm_address_t *)&bufReply,
+                     max_size + MAX_TRAILER_SIZE,
+                     TRUE)) != KERN_SUCCESS)
+      return kr;
+    mlock(bufReply, max_size + MAX_TRAILER_SIZE);
+    while(TRUE) {
+       mr = mach_msg_overwrite_trap(&bufRequest->Head, MACH_RCV_MSG|options,
+                                 0, max_size, rcv_name,
+                                 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL,
+                                 (mach_msg_header_t *) 0, 0);
+        if (mr == MACH_MSG_SUCCESS) {
+           /* we have a request message */
+
+           if(!(default_pager_alerts_server(
+                               &bufRequest->Head, &bufReply->Head)))
+               backing_store_triggers_server(
+                               &bufRequest->Head, &bufReply->Head);
+
+           if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
+               bufReply->RetCode != KERN_SUCCESS) {
+               if (bufReply->RetCode == MIG_NO_REPLY)
+                /*
+                 * This return code is a little tricky--
+                 * it appears that the demux routine found an
+                 * error of some sort, but since that error
+                 * would not normally get returned either to
+                 * the local user or the remote one, we pretend it's
+                 * ok.
+                 */
+
+               bufRequest->Head.msgh_remote_port = MACH_PORT_NULL;
+               mach_msg_destroy(&bufRequest->Head);
+              continue;
+           }
+
+           if (bufReply->Head.msgh_remote_port == MACH_PORT_NULL) {
+              /* no reply port, so destroy the reply */
+              if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)
+                  mach_msg_destroy(&bufReply->Head);
+          } else {
+               break;
+          }
+       } else {
+          break;
+       }   
+    } 
+
+    (void)vm_deallocate(mach_task_self(),
+                    (vm_address_t) bufRequest,
+                    max_size + MAX_TRAILER_SIZE);
+    (void)vm_deallocate(mach_task_self(),
+                    (vm_address_t) bufReply,
+                    max_size + MAX_TRAILER_SIZE);
+    return KERN_FAILURE;
+
+}       
+
+
+kern_return_t
+backing_store_triggers(dynamic_pager, hi_wat, flags, port)
+               mach_port_t     dynamic_pager;
+               int             hi_wat;
+               int             flags;
+               mach_port_t     port;
+{
+       if((hi_wat + size) > low_water) 
+               return KERN_FAILURE; /* let ipc system clean up port */
+       notify_port = port;
+       notify_high = hi_wat;
+       if(hi_water < notify_high) {
+               local_hi_water = notify_high;
+       } else {
+               local_hi_water = hi_water;
+       }
+       if(notify_high > hi_water) {
+               default_pager_space_alert(trigger_port, HI_WAT_ALERT);
+       }
+       return KERN_SUCCESS;
+}
+
+
+kern_return_t
+default_pager_space_alert(alert_port, flags)
+       mach_port_t     alert_port;
+       int     flags;
+{
+       char subfile[512];
+       FILE *file_ptr;
+       off_t   filesize = size;
+       int     error;
+
+       if(flags & HI_WAT_ALERT) {
+/* printf("HI WAT ALERT!!\n"); */
+               file_count++;
+               sprintf(subfile, "%s%d", fileroot, file_count);
+               file_ptr = fopen(subfile, "w+");
+               fchmod(fileno(file_ptr), (mode_t)01600);
+               error = fcntl(fileno(file_ptr), F_SETSIZE, &filesize);
+               fclose(file_ptr);
+               if(error == -1) {
+                       unlink(subfile);
+                       file_count--;
+                       local_hi_water = local_hi_water>>2;
+                       if(notify_high >= (local_hi_water)) {
+                               if(notify_port) {
+                                       /* notify monitoring app of */
+                                       /* backing store shortage  */
+                                       backing_store_alert(notify_port,
+                                                               HI_WAT_ALERT);
+                                       mach_port_deallocate(mach_task_self(), 
+                                                               notify_port);
+                                       notify_high = 0;
+                                       notify_port = 0;
+                               }
+                       }
+                       macx_triggers(local_hi_water, 
+                               low_water, HI_WAT_ALERT, alert_port);
+               } else {
+                       if(hi_water < notify_high) {
+                               if(local_hi_water < notify_high) {
+                                  bs_recovery = notify_high - local_hi_water;
+                               }
+                               local_hi_water = notify_high;
+                       } else {
+                               if(local_hi_water < hi_water) {
+                                  bs_recovery = hi_water - local_hi_water;
+                               }
+                               local_hi_water = hi_water;
+                       }
+                       macx_swapon(subfile, flags, size, priority);
+                       if(bs_recovery <= size) {
+                               if((bs_recovery != 0) && (notify_port)) {
+                                       backing_store_alert(notify_port,
+                                                               LO_WAT_ALERT);
+                                       mach_port_deallocate(mach_task_self(), 
+                                                               notify_port);
+                                       notify_high = 0;
+                                       notify_port = NULL;
+                                       
+                                       bs_recovery = 0;
+                               }
+                       } else 
+                               bs_recovery = bs_recovery-size;
+               }
+       
+               macx_triggers(local_hi_water, 
+                       low_water, HI_WAT_ALERT, alert_port);
+       }
+       if(flags & LO_WAT_ALERT) {
+/* Turn into a logged message printf("LO WAT ALERT!!\n"); */
+               sprintf(subfile, "%s%d", fileroot, file_count);
+               if(hi_water < notify_high) {
+                       local_hi_water = notify_high;
+               } else {
+                       local_hi_water = hi_water;
+               }
+               if((bs_recovery != 0) && (notify_port)) {
+                       backing_store_alert(notify_port, LO_WAT_ALERT);
+                       mach_port_deallocate(mach_task_self(), notify_port);
+                       notify_high = 0;
+                       notify_port = NULL;
+                                       
+                       bs_recovery = 0;
+               }
+               if(macx_swapoff(subfile, flags) == 0) {
+                       unlink(subfile);
+                       file_count--;
+               }
+               macx_triggers(local_hi_water, low_water, LO_WAT_ALERT, alert_port);
+       }
+       return KERN_SUCCESS;
+}
+
+void
+wait_on_paging_trigger(trigger_port)
+       mach_port_t     trigger_port;
+{
+       kern_return_t   result;
+       result = server_alert_loop(4096, trigger_port, MACH_MSG_OPTION_NONE);
+       if (result != KERN_SUCCESS) {
+            fprintf(stderr, "dynamic_pager: default pager alert failed\n");
+            exit(1);
+       }
+       exit(0);
+}
+
+void
+paging_setup(flags, size, priority, low, high)
+       int     flags;
+       int     size;
+       int     priority;
+       int     low;
+       int     high;
+{
+       off_t           filesize = size;
+       char            subfile[512];
+       FILE            *file_ptr;
+        kern_return_t   error;
+
+       file_count = 0;
+       sprintf(subfile, "%s%d", fileroot, file_count);
+       file_ptr = fopen(subfile, "w+");
+       fchmod(fileno(file_ptr), (mode_t)01600);
+       fcntl(fileno(file_ptr), F_SETSIZE, &filesize);
+       fclose(file_ptr);
+        
+       macx_swapon(subfile, flags, size, priority);
+       if(hi_water) {
+               daemon(0,0);
+
+               if (mach_port_allocate(mach_task_self(), 
+                               MACH_PORT_RIGHT_RECEIVE, 
+                               &trigger_port) != KERN_SUCCESS)  {
+                       fprintf(stderr,"allocation of trigger port failed\n");
+                       exit(1);
+               }
+               macx_triggers(high, low, HI_WAT_ALERT, trigger_port);
+               if(low) {
+                       macx_triggers(high, 
+                               low, LO_WAT_ALERT, trigger_port);
+               }
+               /* register control port for applications wishing to */
+               /* get backing store notifications or change dynamic */
+               /* pager settings. */
+               set_dp_control_port(mach_host_self(), trigger_port);
+               wait_on_paging_trigger(trigger_port); 
+       }
+        exit(0);
+}
+int
+main(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind;
+       char default_filename[] = "/private/var/vm/swapfile";
+       int ch;
+
+       seteuid(getuid());
+       strcpy(fileroot, default_filename);
+
+       while ((ch = getopt(argc, argv, "F:L:H:S:P:O:")) != EOF) {
+               switch((char)ch) {
+
+               case 'F':
+                       strncpy(fileroot, optarg, 500);
+                       break;
+
+               case 'L':
+                       low_water = atoi(optarg);
+                       break;
+               case 'H':
+                       hi_water = atoi(optarg);
+                       break;
+               case 'S':
+                       size = atoi(optarg);
+                       break;
+               case 'P':
+                       priority = atoi(optarg);
+                       break;
+
+               default:
+                       (void)fprintf(stderr,
+                           "usage: dynamic_pager [-F filename] [-L low water alert trigger] [-H high water alert trigger] [-S file size] [-P priority]\n");
+                       exit(1);
+               }
+       }
+       local_hi_water = hi_water;
+       if((low_water != 0) && (low_water <= (size + hi_water))) {
+               (void)fprintf(stderr,  "usage: low water trigger must be larger than size + hi_water\n"); 
+               exit(1);
+       }
+       argc -= optind;
+       argv += optind;
+       paging_setup(0, size, priority, low_water, hi_water);
+       return (0);
+}
diff --git a/fastboot.tproj/Makefile b/fastboot.tproj/Makefile
new file mode 100644 (file)
index 0000000..d38af02
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# 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 = fastboot
+
+PROJECTVERSION = 2.6
+PROJECT_TYPE = Legacy
+LANGUAGE = English
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            fastboot.8 fastboot.sh fasthalt.sh
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = common.make
+NEXTSTEP_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/fastboot.tproj/Makefile.dist b/fastboot.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..9504f79
--- /dev/null
@@ -0,0 +1,12 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+MAN8=  fastboot.0
+MLINKS=        fastboot.8 fasthalt.8
+
+beforeinstall:
+       install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+           ${.CURDIR}/fastboot.sh ${DESTDIR}${BINDIR}/fastboot
+       install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+           ${.CURDIR}/fasthalt.sh ${DESTDIR}${BINDIR}/fasthalt
+
+.include <bsd.prog.mk>
diff --git a/fastboot.tproj/Makefile.postamble b/fastboot.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..a98f3d1
--- /dev/null
@@ -0,0 +1,134 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+fastboot: fastboot.sh
+       $(CP) fastboot.sh ${SYM_DIR}/fastboot
+
+fasthalt: fasthalt.sh
+       $(CP) fasthalt.sh ${SYM_DIR}/fasthalt
+
+after_install::
+       $(CP) -p ${SYM_DIR}/fastboot $(DSTROOT)$(INSTALLDIR)/fastboot
+       $(CHMOD) 555 $(DSTROOT)$(INSTALLDIR)/fastboot
+       $(CP) -p ${SYM_DIR}/fasthalt $(DSTROOT)$(INSTALLDIR)/fasthalt
+       $(CHMOD) 555 $(DSTROOT)$(INSTALLDIR)/fasthalt
diff --git a/fastboot.tproj/Makefile.preamble b/fastboot.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..4ad2338
--- /dev/null
@@ -0,0 +1,132 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
+OTHER_INITIAL_TARGETS = fastboot fasthalt
diff --git a/fastboot.tproj/PB.project b/fastboot.tproj/PB.project
new file mode 100644 (file)
index 0000000..fd4d82c
--- /dev/null
@@ -0,0 +1,44 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        H_FILES = (); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            Makefile.dist, 
+            fastboot.8, 
+            fastboot.sh, 
+            fasthalt.sh
+        ); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = "# Set in Makefile"; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_MAINNIB = fastboot; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = "# Set in Makefile"; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = fastboot; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = fastboot; 
+    PROJECTTYPE = Legacy; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = "# Set in Makefile"; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = fastboot; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/fastboot.tproj/fastboot.8 b/fastboot.tproj/fastboot.8
new file mode 100644 (file)
index 0000000..2f6ac82
--- /dev/null
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1983, 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.
+.\"
+.\"     @(#)fastboot.8 8.1 (Berkeley) 6/5/93
+.\"
+.Dd June 5, 1993
+.Dt FASTBOOT 8
+.Os BSD 4.2
+.Sh NAME
+.Nm fastboot ,
+.Nm fasthalt
+.Nd "reboot/halt the system without checking the disks"
+.Sh SYNOPSIS
+.Nm fastboot
+.Op Ar boot-options
+.Nm fasthalt
+.Op Ar halt-options
+.Sh DESCRIPTION
+.Nm Fastboot
+and
+.Nm fasthalt
+are shell scripts which reboot and halt the system without
+checking the file systems.  This is done by creating a
+file 
+.Pa /fastboot ,
+then invoking the 
+.Xr reboot
+program.  The system startup script,
+.Pa /etc/rc ,
+looks for this file and, if present, skips the normal
+invocation of
+.Xr fsck 8 .
+.Sh SEE ALSO
+.Xr halt 8 ,
+.Xr reboot 8 ,
+.Xr rc 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/fastboot.tproj/fastboot.sh b/fastboot.tproj/fastboot.sh
new file mode 100644 (file)
index 0000000..852ec4a
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh -
+#
+# Copyright (c) 1985, 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.
+#
+#      @(#)fastboot.sh 8.1 (Berkeley) 6/5/93
+#
+
+cp /dev/null /fastboot
+/sbin/reboot $*
diff --git a/fastboot.tproj/fasthalt.sh b/fastboot.tproj/fasthalt.sh
new file mode 100644 (file)
index 0000000..c8e381f
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh -
+#
+# 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.
+#
+#      @(#)fasthalt.sh 8.1 (Berkeley) 6/5/93
+#
+
+cp /dev/null /fastboot
+/sbin/halt $*
diff --git a/fs_usage.tproj/Makefile b/fs_usage.tproj/Makefile
new file mode 100644 (file)
index 0000000..958a48c
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = fs_usage
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = fs_usage.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble fs_usage.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I$(NEXT_ROOT)/System/Library/System.framework/\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd\
+               -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd
+
+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/fs_usage.tproj/Makefile.postamble b/fs_usage.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..c7388e8
--- /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/man1
+       install -c -m 444 fs_usage.1 $(DSTROOT)/usr/share/man/man1/fs_usage.1
diff --git a/fs_usage.tproj/Makefile.preamble b/fs_usage.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..a4606c6
--- /dev/null
@@ -0,0 +1,140 @@
+###############################################################################
+#  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)
+
+AFTER_INSTALL += install-man-page
+
diff --git a/fs_usage.tproj/PB.project b/fs_usage.tproj/PB.project
new file mode 100644 (file)
index 0000000..cfa38d3
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        HEADERSEARCH = ("$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd"); 
+        OTHER_LINKED = (fs_usage.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, fs_usage.1); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DKERNEL_PRIVATE"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    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 = fs_usage; 
+    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/fs_usage.tproj/fs_usage.1 b/fs_usage.tproj/fs_usage.1
new file mode 100644 (file)
index 0000000..2d3af74
--- /dev/null
@@ -0,0 +1,103 @@
+
+.\" Copyright (c) 2000, Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd March 28, 2000
+.Dt FS_USAGE 1
+.Os "Mac OS X"
+.Sh NAME
+.Nm fs_usage
+.Nd reports system calls and page faults related to filesystem activity
+in real-time.
+.Sh SYNOPSIS
+.Nm fs_usage [-e] [-w] [ pid|cmd [pid|cmd] ...]
+.Sh DESCRIPTION
+.Nm fs_usage
+presents an ongoing display of system call usage
+information pertaining to filesystem activity.  By default
+this includes all system processes.  The information, however,
+may  be limited to include or exclude a specified list 
+of processes.
+.Pp
+The output presented by
+.Nm fs_usage
+is formatted according to the size of your window.
+A narrow window will display fewer columns of data.
+Use a wide window for maximum data display.  You may
+override the window formatting restrictions by
+forcing a wide display with the
+.Fl w
+option.  In this case, the data displayed will wrap
+when the window is not wide enough.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl e
+Specifying the
+.Fl e
+option generates output that excludes sampling
+of the running fs_usage tool. If a list of
+process ids or commands is also given, then
+those processes are also excluded from the sampled
+output.
+.It Fl w
+Specifying the
+.Fl w
+option forces a wider, more detailed output,
+regardless of the window size.
+.It  pid | cmd
+The sampled data can be limited to a list of process
+ids or commands.  When a command name is given, all
+processes with that name will be sampled.  Using the
+.Fl e
+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
+calls will be displayed bracketing the system calls that they
+are built on.
+.Pp
+The data columns displayed are as follows:
+.Bl -tag -width TIME_INTERVALWWWW -compact
+.Pp
+.It TIMESTAMP
+TOD when call occurred. Wide mode will
+have millesecond granularity.
+.It CALL
+the name of the filesystem call or page-in.
+.It FILE DESCRIPTOR
+Of the form F=x, x is a file descriptor. Depending
+on the type of system call, this will be either
+an input value or a return value.
+.It BYTE COUNT
+Of the form B=x, x is the number of bytes requested by the call.
+.It [ERRNO]
+On error, the errno is displayed in brackets.
+.It PATHNAME
+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 TIME INTERVAL(W)
+The elapsed time spent in the system call.
+A 'W' after the elapsed time indicates
+the process was scheduled out during 
+this file activity.  In this case, the elapsed
+time includes the wait time.
+.It PROCESS NAME
+The process that made the system call.
+.El
+.Pp
+.Sh SAMPLE USAGE
+.Pp
+fs_usage -w telnetd
+.Pp
+.Nm fs_usage
+will report file system usage data for all
+instances of processes named telnetd.  Maximum
+data output will be displayed in the window.
+.Sh SEE ALSO
+.Xr top 1
+.Xr sc_usage 1
+.Xr latency 1
diff --git a/fs_usage.tproj/fs_usage.c b/fs_usage.tproj/fs_usage.c
new file mode 100644 (file)
index 0000000..1027e59
--- /dev/null
@@ -0,0 +1,1888 @@
+/*
+ * 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@
+ */
+
+/*
+cc -I. -DKERNEL_PRIVATE -O -o fs_usage fs_usage.c
+*/
+
+#define        Default_DELAY   1       /* default delay interval */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <nlist.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <libc.h>
+#include <termios.h>
+#include <bsd/curses.h>
+#include <sys/ioctl.h>
+
+#ifndef KERNEL_PRIVATE
+#define KERNEL_PRIVATE
+#include <sys/kdebug.h>
+#undef KERNEL_PRIVATE
+#else
+#include <sys/kdebug.h>
+#endif /*KERNEL_PRIVATE*/
+
+#include <sys/sysctl.h>
+#include <errno.h>
+#import <mach/clock_types.h>
+#include <err.h>
+
+extern int errno;
+
+
+struct th_info {
+        int  in_filemgr;
+        int  thread;
+        int  type;
+        int  arg1;
+        int  arg2;
+        int  arg3;
+        int  arg4;
+        int  vfslookup;
+        int  child_thread;
+        int  waited;
+        double stime;
+        char pathname[32];
+};
+
+#define MAX_THREADS 512
+struct th_info th_state[MAX_THREADS];
+
+
+int  cur_max = 0;
+int  need_new_map = 1;
+int  bias_secs;
+int  wideflag = 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 DBG_ZERO_FILL_FAULT   1
+#define DBG_PAGEIN_FAULT      2
+#define DBG_COW_FAULT         3
+#define DBG_CACHE_HIT_FAULT   4
+
+#define TRACE_DATA_NEWTHREAD   0x07000004
+#define TRACE_STRING_NEWTHREAD 0x07010004
+#define TRACE_STRING_EXEC      0x07010008
+
+#define MACH_vmfault    0x01300000
+#define MACH_sched      0x01400000
+#define MACH_stkhandoff 0x01400008
+#define VFS_LOOKUP      0x03010090
+#define BSC_exit        0x040C0004
+
+#define MSC_map_fd   0x010c00ac
+#define        BSC_recvmsg  0x040C006C
+#define        BSC_sendmsg  0x040C0070
+#define        BSC_recvfrom 0x040C0074
+#define        BSC_sendto   0x040C0214
+
+#define BSC_read     0x040C000C
+#define BSC_write    0x040C0010
+#define BSC_open     0x040C0014
+#define BSC_close    0x040C0018
+#define BSC_link     0x040C0024
+#define BSC_unlink   0x040C0028
+#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_symlink  0x040C00E4        
+#define BSC_readlink 0x040C00E8        
+#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_mkdir    0x040C0220        
+#define BSC_rmdir    0x040C0224        
+#define BSC_statfs   0x040C0274        
+#define BSC_fstatfs  0x040C0278        
+#define BSC_stat     0x040C02F0        
+#define BSC_fstat    0x040C02F4        
+#define BSC_lstat    0x040C02F8        
+#define BSC_pathconf 0x040C02FC        
+#define BSC_fpathconf     0x040C0300
+#define BSC_getdirentries 0x040C0310
+#define BSC_mmap     0x040c0314
+#define BSC_lseek    0x040c031c
+#define BSC_truncate 0x040C0320
+#define BSC_ftruncate     0x040C0324   
+#define BSC_statv    0x040C0364        
+#define BSC_lstatv   0x040C0368        
+#define BSC_fstatv   0x040C036C        
+#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     
+
+// Carbon File Manager support
+#define FILEMGR_PBGETCATALOGINFO                0x1e000020
+#define FILEMGR_PBGETCATALOGINFOBULK    0x1e000024
+#define FILEMGR_PBCREATEFILEUNICODE             0x1e000028
+#define FILEMGR_PBCREATEDIRECTORYUNICODE 0x1e00002c
+#define FILEMGR_PBCREATEFORK                    0x1e000030
+#define FILEMGR_PBDELETEFORK                    0x1e000034
+#define FILEMGR_PBITERATEFORK                   0x1e000038
+#define FILEMGR_PBOPENFORK                              0x1e00003c
+#define FILEMGR_PBREADFORK                              0x1e000040
+#define FILEMGR_PBWRITEFORK                             0x1e000044
+#define FILEMGR_PBALLOCATEFORK                  0x1e000048
+#define FILEMGR_PBDELETEOBJECT                  0x1e00004c
+#define FILEMGR_PBEXCHANGEOBJECT                0x1e000050
+#define FILEMGR_PBGETFORKCBINFO                         0x1e000054
+#define FILEMGR_PBGETVOLUMEINFO                         0x1e000058
+#define FILEMGR_PBMAKEFSREF                             0x1e00005c
+#define FILEMGR_PBMAKEFSREFUNICODE              0x1e000060
+#define FILEMGR_PBMOVEOBJECT                    0x1e000064
+#define FILEMGR_PBOPENITERATOR                  0x1e000068
+#define FILEMGR_PBRENAMEUNICODE                         0x1e00006c
+#define FILEMGR_PBSETCATALOGINFO                0x1e000070
+#define FILEMGR_PBSETVOLUMEINFO                         0x1e000074
+#define FILEMGR_FSREFMAKEPATH                   0x1e000078
+#define FILEMGR_FSPATHMAKEREF                   0x1e00007c
+
+#define FILEMGR_PBGETCATINFO                    0x1e010000
+#define FILEMGR_PBGETCATINFOLITE                0x1e010004
+#define FILEMGR_PBHGETFINFO                             0x1e010008
+#define FILEMGR_PBXGETVOLINFO                   0x1e01000c
+#define FILEMGR_PBHCREATE                               0x1e010010
+#define FILEMGR_PBHOPENDF                               0x1e010014
+#define FILEMGR_PBHOPENRF                               0x1e010018
+#define FILEMGR_PBHGETDIRACCESS                         0x1e01001c
+#define FILEMGR_PBHSETDIRACCESS                         0x1e010020
+#define FILEMGR_PBHMAPID                                0x1e010024
+#define FILEMGR_PBHMAPNAME                              0x1e010028
+#define FILEMGR_PBCLOSE                                         0x1e01002c
+#define FILEMGR_PBFLUSHFILE                             0x1e010030
+#define FILEMGR_PBGETEOF                                0x1e010034
+#define FILEMGR_PBSETEOF                                0x1e010038
+#define FILEMGR_PBGETFPOS                               0x1e01003c
+#define FILEMGR_PBREAD                                  0x1e010040
+#define FILEMGR_PBWRITE                                         0x1e010044
+#define FILEMGR_PBGETFCBINFO                    0x1e010048
+#define FILEMGR_PBSETFINFO                              0x1e01004c
+#define FILEMGR_PBALLOCATE                              0x1e010050
+#define FILEMGR_PBALLOCCONTIG                   0x1e010054
+#define FILEMGR_PBSETFPOS                               0x1e010058
+#define FILEMGR_PBSETCATINFO                    0x1e01005c
+#define FILEMGR_PBGETVOLPARMS                   0x1e010060
+#define FILEMGR_PBSETVINFO                              0x1e010064
+#define FILEMGR_PBMAKEFSSPEC                    0x1e010068
+#define FILEMGR_PBHGETVINFO                             0x1e01006c
+#define FILEMGR_PBCREATEFILEIDREF               0x1e010070
+#define FILEMGR_PBDELETEFILEIDREF               0x1e010074
+#define FILEMGR_PBRESOLVEFILEIDREF              0x1e010078
+#define FILEMGR_PBFLUSHVOL                              0x1e01007c
+#define FILEMGR_PBHRENAME                               0x1e010080
+#define FILEMGR_PBCATMOVE                               0x1e010084
+#define FILEMGR_PBEXCHANGEFILES                         0x1e010088
+#define FILEMGR_PBHDELETE                               0x1e01008c
+#define FILEMGR_PBDIRCREATE                             0x1e010090
+#define FILEMGR_PBCATSEARCH                             0x1e010094
+#define FILEMGR_PBHSETFLOCK                             0x1e010098
+#define FILEMGR_PBHRSTFLOCK                             0x1e01009c
+#define FILEMGR_PBLOCKRANGE                             0x1e0100a0
+#define FILEMGR_PBUNLOCKRANGE                   0x1e0100a4
+
+
+#define FILEMGR_CLASS   0x1e
+
+#define MAX_PIDS 32
+int    pids[MAX_PIDS];
+
+int    num_of_pids = 0;
+int    exclude_pids = 0;
+
+struct kinfo_proc *kp_buffer = 0;
+int kp_nentries = 0;
+
+#define SAMPLE_SIZE 60000
+
+#define DBG_ZERO_FILL_FAULT   1
+#define DBG_PAGEIN_FAULT      2
+#define DBG_COW_FAULT         3
+#define DBG_CACHE_HIT_FAULT   4
+
+#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;
+
+int mib[6];
+size_t needed;
+char  *my_buffer;
+
+kbufinfo_t bufinfo = {0, 0, 0, 0};
+
+int total_threads = 0;
+kd_threadmap *mapptr = 0;
+
+int trace_enabled = 0;
+int set_remove_flag = 1;
+
+void set_numbufs();
+void set_init();
+void set_enable();
+void sample_sc();
+int quit();
+
+/*
+ *  signal handlers
+ */
+
+void leave()                   /* exit under normal conditions -- INT handler */
+{
+        int i;
+       void set_enable();
+       void set_pidcheck();
+       void set_pidexclude();
+       void set_remove();
+
+       set_enable(0);
+
+       if (exclude_pids == 0) {
+               for (i = 0; i < num_of_pids; i++)
+                       set_pidcheck(pids[i], 0);
+       }
+       else {
+               for (i = 0; i < num_of_pids; i++)
+                       set_pidexclude(pids[i], 0);
+       }
+       set_remove();
+       exit(0);
+}
+
+
+void sigwinch()
+{
+       initscr();
+}
+
+int
+exit_usage(myname) {
+
+        fprintf(stderr, "Usage: %s [-e] [-w] [pid | cmd [pid | cmd]....]\n", myname);
+       fprintf(stderr, "  -e    exclude the pids specified from the sample\n");
+       fprintf(stderr, "  -w    force wider, detailed, output\n");
+       fprintf(stderr, "  pid   selects process(s) to sample\n");
+       fprintf(stderr, "  cmd   selects process(s) matching command string to sample\n");
+
+       exit(1);
+}
+
+
+main(argc, argv)
+       int     argc;
+       char    *argv[];
+{
+       char    *myname = "fs_usage";
+       int     i;
+       char    ch;
+       void getdivisor();
+       void argtopid();
+       void set_remove();
+       void set_pidcheck();
+       void set_pidexclude();
+       int quit();
+
+        if ( geteuid() != 0 ) {
+            printf("'fs_usage' must be run as root...\n");
+            exit(1);
+        }
+
+       initscr();
+
+       /* get our name */
+       if (argc > 0) {
+               if ((myname = rindex(argv[0], '/')) == 0) {
+                       myname = argv[0];
+               }
+               else {
+                       myname++;
+               }
+       }
+       
+       while ((ch = getopt(argc, argv, "ew")) != EOF) {
+               switch(ch) {
+                case 'e':
+                   exclude_pids = 1;
+                   break;
+                case 'w':
+                   wideflag = 1;
+                   break;
+              default:
+                exit_usage(myname);             
+              }
+       }
+
+        argc -= optind;
+        argv += optind;
+
+       while (argc > 0 && num_of_pids < (MAX_PIDS - 1)) {
+         select_pid_mode++;
+         argtopid(argv[0]);
+         argc--;
+         argv++;
+       }
+
+       if (exclude_pids)
+               pids[num_of_pids++] = getpid();
+
+#if 0
+       for (i = 0; i < num_of_pids; i++)
+         {
+           if (exclude_pids)
+             printf("exclude pid %d\n", pids[i]);
+           else
+             printf("pid %d\n", pids[i]);
+         }
+#endif
+
+       /* set up signal handlers */
+       signal(SIGINT, leave);
+       signal(SIGQUIT, 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");
+
+       set_remove();
+       set_numbufs(SAMPLE_SIZE);
+       set_init();
+
+       if (exclude_pids == 0) {
+               for (i = 0; i < num_of_pids; i++)
+                       set_pidcheck(pids[i], 1);
+       } else {
+               for (i = 0; i < num_of_pids; i++)
+                       set_pidexclude(pids[i], 1);
+       }
+
+       if (select_pid_mode && !one_good_pid)
+         {
+           /* 
+              An attempt to restrict output to a given
+              pid or command has failed. Exit gracefully
+           */
+           set_remove();
+           exit_usage(myname);
+         }
+
+       set_enable(1);
+       getdivisor();
+
+
+       /* main loop */
+
+       while (1) {
+               usleep(1000 * 50);
+
+               sample_sc();
+       }
+}
+
+void
+find_proc_names()
+{
+       size_t                  bufSize = 0;
+       struct kinfo_proc       *kp;
+       int quit();
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROC;
+       mib[2] = KERN_PROC_ALL;
+       mib[3] = 0;
+
+       if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
+               quit("trace facility failure, KERN_PROC_ALL\n");
+
+       if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
+           quit("can't allocate memory for proc buffer\n");
+       
+       if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
+               quit("trace facility failure, KERN_PROC_ALL\n");
+
+        kp_nentries = bufSize/ sizeof(struct kinfo_proc);
+       kp_buffer = kp;
+}
+
+
+struct th_info *find_thread(int thread, int type) {
+       struct th_info *ti;
+
+       for (ti = th_state; ti < &th_state[cur_max]; ti++) {
+              if (ti->thread == thread) {
+                      if (type == ti->type)
+                              return(ti);
+                      if (ti->in_filemgr) {
+                              if (type == -1)
+                                      return(ti);
+                              continue;
+                      }
+                      if (type == 0)
+                              return(ti);
+              }
+       }
+       return ((struct th_info *)0);
+}
+
+void
+set_enable(int val) 
+{
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDENABLE;         /* protocol */
+       mib[3] = val;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDENABLE\n");
+
+       if (val)
+         trace_enabled = 1;
+       else
+         trace_enabled = 0;
+}
+
+void
+set_numbufs(int nbufs) 
+{
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETBUF;
+       mib[3] = nbufs;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETBUF\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+}
+
+void
+set_pidcheck(int pid, int on_off) 
+{
+        kd_regtype kr;
+
+       kr.type = KDBG_TYPENONE;
+       kr.value1 = pid;
+       kr.value2 = on_off;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDPIDTR;
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;
+
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
+               if (on_off == 1)
+                       printf("pid %d does not exist\n", pid);
+       }
+       else {
+         one_good_pid++;
+       }
+}
+
+/* 
+   on_off == 0 turns off pid exclusion
+   on_off == 1 turns on pid exclusion
+*/
+void
+set_pidexclude(int pid, int on_off) 
+{
+        kd_regtype kr;
+
+       one_good_pid++;
+
+       kr.type = KDBG_TYPENONE;
+       kr.value1 = pid;
+       kr.value2 = on_off;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDPIDEX;
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;
+
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
+               if (on_off == 1)
+                         printf("pid %d does not exist\n", pid);
+       }
+}
+
+void
+get_bufinfo(kbufinfo_t *val)
+{
+        needed = sizeof (*val);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDGETBUF;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
+               quit("trace facility failure, KERN_KDGETBUF\n");  
+
+}
+
+void
+set_remove() 
+{
+        extern int errno;
+
+        errno = 0;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDREMOVE;         /* protocol */
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+         {
+           set_remove_flag = 0;
+
+           if (errno == EBUSY)
+               quit("the trace facility is currently in use...\n          fs_usage, sc_usage, and latency use this feature.\n\n");
+           else
+               quit("trace facility failure, KERN_KDREMOVE\n");
+         }
+}
+
+void
+set_init() 
+{       kd_regtype kr;
+
+       kr.type = KDBG_RANGETYPE;
+       kr.value1 = 0;
+       kr.value2 = -1;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETREG;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETREG\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+}
+
+void
+sample_sc()
+{
+       kd_buf *kd;
+       int i, count;
+       void read_command_map();
+       void create_map_entry();
+
+        /* Get kernel buffer information */
+       get_bufinfo(&bufinfo);
+
+       if (need_new_map) {
+               read_command_map();
+               need_new_map = 0;
+       }
+       needed = bufinfo.nkdbufs * sizeof(kd_buf);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDREADTR;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
+                quit("trace facility failure, KERN_KDREADTR\n");
+       count = needed;
+
+       if (bufinfo.flags & KDBG_WRAPPED) {
+               printf("buffer wrapped  count = %d\n", count);
+
+               for (i = 0; i < cur_max; i++) {
+                       th_state[i].thread = 0;
+                       th_state[i].vfslookup = 0;
+                       th_state[i].pathname[0] = 0;
+               }
+               cur_max = 0;
+               need_new_map = 1;
+               
+               set_enable(0);
+               set_enable(1);
+       }
+       kd = (kd_buf *)my_buffer;
+#if 0
+       printf("READTR returned %d items\n", count);
+#endif
+       for (i = 0; i < count; i++) {
+               int debugid, thread;
+               int type, n;
+               long *sargptr;
+               unsigned long long now;
+               struct th_info *ti;
+               void enter_syscall();
+               void exit_syscall();
+               void kill_thread_map();
+
+               thread  = kd[i].arg5 & KDBG_THREAD_MASK;
+               debugid = kd[i].debugid;
+               type    = kd[i].debugid & DBG_FUNC_MASK;
+
+               switch (type) {
+
+               case TRACE_DATA_NEWTHREAD:
+                  
+                   for (n = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, n++) {
+                       if (ti->thread == 0)
+                          break;
+                   }
+                   if (ti == &th_state[MAX_THREADS])
+                       continue;
+                   if (n >= cur_max)
+                       cur_max = n + 1;
+
+                   ti->thread = thread;
+                   ti->child_thread = kd[i].arg1;
+                   continue;
+
+               case TRACE_STRING_NEWTHREAD:
+                   if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
+                           continue;
+                   if (ti->child_thread == 0)
+                           continue;
+                   create_map_entry(ti->child_thread, (char *)&kd[i].arg1);
+
+                   if (ti == &th_state[cur_max - 1])
+                       cur_max--;
+                   ti->child_thread = 0;
+                   ti->thread = 0;
+                   continue;
+
+               case TRACE_STRING_EXEC:
+                   create_map_entry(thread, (char *)&kd[i].arg1);
+                   continue;
+
+               case BSC_exit:
+                   kill_thread_map(thread);
+                   continue;
+
+               case MACH_sched:
+               case MACH_stkhandoff:
+                   if (ti = find_thread(thread, 0))
+                           ti->waited = 1;
+                   continue;
+
+               case VFS_LOOKUP:
+                   if ((ti = find_thread(thread, 0)) == (struct th_info *)0)
+                           continue;
+
+                   if (ti->vfslookup == 0) {
+                           ti->vfslookup = 1;
+                           memset(&ti->pathname[0], 0, 32);
+                           sargptr = (long *)&ti->pathname[0];
+                               
+                           *sargptr++ = kd[i].arg2;
+                           *sargptr++ = kd[i].arg3;
+                           *sargptr++ = kd[i].arg4;
+
+                   } else if (ti->vfslookup == 1) {
+                           ti->vfslookup = 2;
+         
+                           sargptr = (long *)&ti->pathname[12];
+                           *sargptr++ = kd[i].arg1;
+                           *sargptr++ = kd[i].arg2;
+                           *sargptr++ = kd[i].arg3;
+                           *sargptr++ = kd[i].arg4;
+                   }
+                   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;
+
+                      switch (type) {
+                          case FILEMGR_PBGETCATALOGINFO:
+                                       p = "GetCatalogInfo";
+                                       break;
+                          case FILEMGR_PBGETCATALOGINFOBULK:
+                                       p = "GetCatalogInfoBulk";
+                                       break;
+                          case FILEMGR_PBCREATEFILEUNICODE:
+                                       p = "CreateFileUnicode";
+                                       break;
+                          case FILEMGR_PBCREATEDIRECTORYUNICODE:
+                                       p = "CreateDirectoryUnicode";
+                                       break;
+                          case FILEMGR_PBCREATEFORK:
+                                       p = "PBCreateFork";
+                                       break;
+                          case FILEMGR_PBDELETEFORK:
+                                       p = "PBDeleteFork";
+                                       break;
+                          case FILEMGR_PBITERATEFORK:
+                                       p = "PBIterateFork";
+                                       break;
+                          case FILEMGR_PBOPENFORK:
+                                       p = "PBOpenFork";
+                                       break;
+                          case FILEMGR_PBREADFORK:
+                                       p = "PBReadFork";
+                                       break;
+                          case FILEMGR_PBWRITEFORK:
+                                       p = "PBWriteFork";
+                                       break;
+                          case FILEMGR_PBALLOCATEFORK:
+                                       p = "PBAllocateFork";
+                                       break;
+                          case FILEMGR_PBDELETEOBJECT:
+                                       p = "PBDeleteObject";
+                                       break;
+                          case FILEMGR_PBEXCHANGEOBJECT:
+                                       p = "PBExchangeObject";
+                                       break;
+                          case FILEMGR_PBGETFORKCBINFO:
+                                       p = "PBGetForkCBInfo";
+                                       break;
+                          case FILEMGR_PBGETVOLUMEINFO:
+                                       p = "PBGetVolumeInfo";
+                                       break;
+                          case FILEMGR_PBMAKEFSREF:
+                                       p = "PBMakeFSRef";
+                                       break;
+                          case FILEMGR_PBMAKEFSREFUNICODE:
+                                       p = "PBMakeFSRefUnicode";
+                                       break;
+                          case FILEMGR_PBMOVEOBJECT:
+                                       p = "PBMoveObject";
+                                       break;
+                          case FILEMGR_PBOPENITERATOR:
+                                       p = "PBOpenIterator";
+                                       break;
+                          case FILEMGR_PBRENAMEUNICODE:
+                                       p = "PBRenameUnicode";
+                                       break;
+                          case FILEMGR_PBSETCATALOGINFO:
+                                       p = "SetCatalogInfo";
+                                       break;
+                          case FILEMGR_PBSETVOLUMEINFO:
+                                       p = "SetVolumeInfo";
+                                       break;
+                          case FILEMGR_FSREFMAKEPATH:
+                                       p = "FSRefMakePath";
+                                       break;
+                          case FILEMGR_FSPATHMAKEREF:
+                                       p = "FSPathMakeRef";
+                                       break;
+                          // SPEC based calls
+                          case FILEMGR_PBGETCATINFO:
+                                       p = "GetCatInfo";
+                                       break;
+                          case FILEMGR_PBGETCATINFOLITE:
+                                       p = "GetCatInfoLite";
+                                       break;
+                          case FILEMGR_PBHGETFINFO:
+                                       p = "PBHGetFInfo";
+                                       break;
+                          case FILEMGR_PBXGETVOLINFO:
+                                       p = "PBXGetVolInfo";
+                                       break;
+                          case FILEMGR_PBHCREATE:
+                                       p = "PBHCreate";
+                                       break;
+                          case FILEMGR_PBHOPENDF:
+                                       p = "PBHOpenDF";
+                                       break;
+                          case FILEMGR_PBHOPENRF:
+                                       p = "PBHOpenRF";
+                                       break;
+                          case FILEMGR_PBHGETDIRACCESS:
+                                       p = "PBHGetDirAccess";
+                                       break;
+                          case FILEMGR_PBHSETDIRACCESS:
+                                       p = "PBHSetDirAccess";
+                                       break;
+                          case FILEMGR_PBHMAPID:
+                                       p = "PBHMapID";
+                                       break;
+                          case FILEMGR_PBHMAPNAME:
+                                       p = "PBHMapName";
+                                       break;
+                          case FILEMGR_PBCLOSE:
+                                       p = "PBClose";
+                                       break;
+                          case FILEMGR_PBFLUSHFILE:
+                                       p = "PBFlushFile";
+                                       break;
+                          case FILEMGR_PBGETEOF:
+                                       p = "PBGetEOF";
+                                       break;
+                          case FILEMGR_PBSETEOF:
+                                       p = "PBSetEOF";
+                                       break;
+                          case FILEMGR_PBGETFPOS:
+                                       p = "PBGetFPos";
+                                       break;
+                          case FILEMGR_PBREAD:
+                                       p = "PBRead";
+                                       break;
+                          case FILEMGR_PBWRITE:
+                                       p = "PBWrite";
+                                       break;
+                          case FILEMGR_PBGETFCBINFO:
+                                       p = "PBGetFCBInfo";
+                                       break;
+                          case FILEMGR_PBSETFINFO:
+                                       p = "PBSetFInfo";
+                                       break;
+                          case FILEMGR_PBALLOCATE:
+                                       p = "PBAllocate";
+                                       break;
+                          case FILEMGR_PBALLOCCONTIG:
+                                       p = "PBAllocContig";
+                                       break;
+                          case FILEMGR_PBSETFPOS:
+                                       p = "PBSetFPos";
+                                       break;
+                          case FILEMGR_PBSETCATINFO:
+                                       p = "PBSetCatInfo";
+                                       break;
+                          case FILEMGR_PBGETVOLPARMS:
+                                       p = "PBGetVolParms";
+                                       break;
+                          case FILEMGR_PBSETVINFO:
+                                       p = "PBSetVInfo";
+                                       break;
+                          case FILEMGR_PBMAKEFSSPEC:
+                                       p = "PBMakeFSSpec";
+                                       break;
+                          case FILEMGR_PBHGETVINFO:
+                                       p = "PBHGetVInfo";
+                                       break;
+                          case FILEMGR_PBCREATEFILEIDREF:
+                                       p = "PBCreateFileIDRef";
+                                       break;
+                          case FILEMGR_PBDELETEFILEIDREF:
+                                       p = "PBDeleteFileIDRef";
+                                       break;
+                          case FILEMGR_PBRESOLVEFILEIDREF:
+                                       p = "PBResolveFileIDRef";
+                                       break;
+                          case FILEMGR_PBFLUSHVOL:
+                                       p = "PBFlushVol";
+                                       break;
+                          case FILEMGR_PBHRENAME:
+                                       p = "PBHRename";
+                                       break;
+                          case FILEMGR_PBCATMOVE:
+                                       p = "PBCatMove";
+                                       break;
+                          case FILEMGR_PBEXCHANGEFILES:
+                                       p = "PBExchangeFiles";
+                                       break;
+                          case FILEMGR_PBHDELETE:
+                                       p = "PBHDelete";
+                                       break;
+                          case FILEMGR_PBDIRCREATE:
+                                       p = "PBDirCreate";
+                                       break;
+                          case FILEMGR_PBCATSEARCH:
+                                       p = "PBCatSearch";
+                                       break;
+                          case FILEMGR_PBHSETFLOCK:
+                                       p = "PBHSetFlock";
+                                       break;
+                          case FILEMGR_PBHRSTFLOCK:
+                                       p = "PBHRstFLock";
+                                       break;
+                          case FILEMGR_PBLOCKRANGE:
+                                       p = "PBLockRange";
+                                       break;
+                          case FILEMGR_PBUNLOCKRANGE:
+                                       p = "PBUnlockRange";
+                                       break;
+                          default:
+                                       p = (char *)0;
+                                       break;
+                       }
+                       enter_syscall(thread, type, &kd[i], p, (double)now);
+                       continue;
+               }
+               switch (type) {
+
+               case MACH_vmfault:
+                   if (kd[i].arg2 == DBG_PAGEIN_FAULT)
+                           exit_syscall("PAGE_IN", thread, type, 0, kd[i].arg1, 0, 2, (double)now);
+                   else {
+                           if (ti = find_thread(thread, type)) {
+                                   if (ti == &th_state[cur_max - 1])
+                                           cur_max--;
+                                   ti->thread = 0;
+                           }
+                   }
+                   break;
+
+               case MSC_map_fd:
+                   exit_syscall("map_fd", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_mmap:
+                   exit_syscall("mmap", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_recvmsg:
+                   exit_syscall("recvmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_sendmsg:
+                   exit_syscall("sendmsg", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_recvfrom:
+                   exit_syscall("recvfrom", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_sendto:
+                   exit_syscall("sendto", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_stat:
+                   exit_syscall("stat", 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);
+                   break;
+
+               case BSC_close:
+                   exit_syscall("close", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_read:
+                   exit_syscall("read", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_write:
+                   exit_syscall("write", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_fstat:
+                   exit_syscall("fstat", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_lstat:
+                   exit_syscall("lstat", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_link:
+                   exit_syscall("link", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_unlink:
+                   exit_syscall("unlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_mknod:
+                   exit_syscall("mknod", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_chmod:
+                   exit_syscall("chmod", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_chown:
+                   exit_syscall("chown", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_access:
+                   exit_syscall("access", 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_sync:
+                   exit_syscall("sync", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_symlink:
+                   exit_syscall("symlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_readlink:
+                   exit_syscall("readlink", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_fsync:
+                   exit_syscall("fsync", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_readv:
+                   exit_syscall("readv", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_writev:
+                   exit_syscall("writev", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_fchown:
+                   exit_syscall("fchown", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_fchmod:
+                   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_rmdir:
+                   exit_syscall("rmdir", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_statfs:
+                   exit_syscall("statfs", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_fstatfs:
+                   exit_syscall("fstatfs", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_pathconf:
+                   exit_syscall("pathconf", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_fpathconf:
+                   exit_syscall("fpathconf", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_getdirentries:
+                   exit_syscall("getdirentries", thread, type, kd[i].arg1, kd[i].arg2, 1, 1, (double)now);
+                   break;
+
+               case BSC_lseek:
+                   exit_syscall("lseek", thread, type, kd[i].arg1, kd[i].arg3, 1, 5, (double)now);
+                   break;
+
+               case BSC_truncate:
+                   exit_syscall("truncate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_ftruncate:
+                   exit_syscall("ftruncate", thread, type, kd[i].arg1, kd[i].arg2, 1, 3, (double)now);
+                   break;
+
+               case BSC_statv:
+                   exit_syscall("statv", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_lstatv:
+                   exit_syscall("lstatv", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_fstatv:
+                   exit_syscall("fstatv", thread, type, kd[i].arg1, kd[i].arg2, 1, 0, (double)now);
+                   break;
+
+               case BSC_mkcomplex:
+                   exit_syscall("mkcomplex", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_getattrlist:
+                   exit_syscall("getattrlist", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_setattrlist:
+                   exit_syscall("setattrlist", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_getdirentriesattr:
+                   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_checkuseraccess:
+                   exit_syscall("checkuseraccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+               case BSC_searchfs:
+                   exit_syscall("searchfs", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+
+          case FILEMGR_PBGETCATALOGINFO:
+                   exit_syscall("GetCatalogInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETCATALOGINFOBULK:
+                   exit_syscall("GetCatalogInfoBulk", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCREATEFILEUNICODE:
+                   exit_syscall("CreateFileUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCREATEDIRECTORYUNICODE:
+                   exit_syscall("CreateDirectoryUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCREATEFORK:
+                   exit_syscall("PBCreateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBDELETEFORK:
+                   exit_syscall("PBDeleteFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBITERATEFORK:
+                   exit_syscall("PBIterateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBOPENFORK:
+                   exit_syscall("PBOpenFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBREADFORK:
+                   exit_syscall("PBReadFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBWRITEFORK:
+                   exit_syscall("PBWriteFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBALLOCATEFORK:
+                   exit_syscall("PBAllocateFork", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBDELETEOBJECT:
+                   exit_syscall("PBDeleteObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBEXCHANGEOBJECT:
+                   exit_syscall("PBExchangeObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETFORKCBINFO:
+                   exit_syscall("PBGetForkCBInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETVOLUMEINFO:
+                   exit_syscall("PBGetVolumeInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBMAKEFSREF:
+                   exit_syscall("PBMakeFSRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBMAKEFSREFUNICODE:
+                   exit_syscall("PBMakeFSRefUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBMOVEOBJECT:
+                   exit_syscall("PBMoveObject", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBOPENITERATOR:
+                   exit_syscall("PBOpenIterator", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBRENAMEUNICODE:
+                   exit_syscall("PBRenameUnicode", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETCATALOGINFO:
+                   exit_syscall("PBSetCatalogInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETVOLUMEINFO:
+                   exit_syscall("PBSetVolumeInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_FSREFMAKEPATH:
+                   exit_syscall("FSRefMakePath", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_FSPATHMAKEREF:
+                   exit_syscall("FSPathMakeRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETCATINFO:
+                   exit_syscall("GetCatInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETCATINFOLITE:
+                   exit_syscall("GetCatInfoLite", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHGETFINFO:
+                   exit_syscall("PBHGetFInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBXGETVOLINFO:
+                   exit_syscall("PBXGetVolInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHCREATE:
+                   exit_syscall("PBHCreate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHOPENDF:
+                   exit_syscall("PBHOpenDF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHOPENRF:
+                   exit_syscall("PBHOpenRF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHGETDIRACCESS:
+                   exit_syscall("PBHGetDirAccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHSETDIRACCESS:
+                   exit_syscall("PBHSetDirAccess", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHMAPID:
+                   exit_syscall("PBHMapID", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHMAPNAME:
+                   exit_syscall("PBHMapName", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCLOSE:
+                   exit_syscall("PBClose", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBFLUSHFILE:
+                   exit_syscall("PBFlushFile", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETEOF:
+                   exit_syscall("PBGetEOF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETEOF:
+                   exit_syscall("PBSetEOF", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETFPOS:
+                   exit_syscall("PBGetFPos", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBREAD:
+                   exit_syscall("PBRead", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBWRITE:
+                   exit_syscall("PBWrite", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETFCBINFO:
+                   exit_syscall("PBGetFCBInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETFINFO:
+                   exit_syscall("PBSetFInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBALLOCATE:
+                   exit_syscall("PBAllocate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBALLOCCONTIG:
+                   exit_syscall("PBAllocContig", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETFPOS:
+                   exit_syscall("PBSetFPos", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETCATINFO:
+                   exit_syscall("PBSetCatInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBGETVOLPARMS:
+                   exit_syscall("PBGetVolParms", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBSETVINFO:
+                   exit_syscall("PBSetVInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBMAKEFSSPEC:
+                   exit_syscall("PBMakeFSSpec", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHGETVINFO:
+                   exit_syscall("PBHGetVInfo", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCREATEFILEIDREF:
+                   exit_syscall("PBCreateFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBDELETEFILEIDREF:
+                   exit_syscall("PBDeleteFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBRESOLVEFILEIDREF:
+                   exit_syscall("PBResolveFileIDRef", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBFLUSHVOL:
+                   exit_syscall("PBFlushVol", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHRENAME:
+                   exit_syscall("PBHRename", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCATMOVE:
+                   exit_syscall("PBCatMove", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBEXCHANGEFILES:
+                   exit_syscall("PBExchangeFiles", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHDELETE:
+                   exit_syscall("PBHDelete", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBDIRCREATE:
+                   exit_syscall("PBDirCreate", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBCATSEARCH:
+                   exit_syscall("PBCatSearch", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHSETFLOCK:
+                   exit_syscall("PBHSetFLock", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBHRSTFLOCK:
+                   exit_syscall("PBHRstFLock", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBLOCKRANGE:
+                   exit_syscall("PBLockRange", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+          case FILEMGR_PBUNLOCKRANGE:
+                   exit_syscall("PBUnlockRange", thread, type, kd[i].arg1, kd[i].arg2, 0, 0, (double)now);
+                   break;
+               default:
+                   break;
+               }
+       }
+       fflush(0);
+}
+
+void
+enter_syscall(int thread, int type, kd_buf *kd, char *name, double now)
+{
+       struct th_info *ti;
+       int    i;
+       int    secs;
+       int    usecs;
+       long long l_usecs;
+       long curr_time;
+          kd_threadmap *map;
+          kd_threadmap *find_thread_map();
+
+       switch (type) {
+
+       case MACH_vmfault:
+       case MSC_map_fd:
+       case BSC_mmap:
+       case BSC_recvmsg:
+       case BSC_sendmsg:
+       case BSC_recvfrom:
+       case BSC_sendto:
+       case BSC_stat:
+       case BSC_open:
+       case BSC_close:
+       case BSC_read:
+       case BSC_write:
+       case BSC_fstat:
+       case BSC_lstat:
+       case BSC_link:
+       case BSC_unlink:
+       case BSC_mknod:
+       case BSC_chmod:
+       case BSC_chown:
+       case BSC_access:
+       case BSC_chflags:
+       case BSC_fchflags:
+       case BSC_sync:
+       case BSC_symlink:
+       case BSC_readlink:
+       case BSC_fsync:
+       case BSC_readv:
+       case BSC_writev:
+       case BSC_fchown:
+       case BSC_fchmod:
+       case BSC_rename:
+       case BSC_mkdir:
+       case BSC_rmdir:
+       case BSC_statfs:
+       case BSC_fstatfs:
+       case BSC_pathconf:
+       case BSC_fpathconf:
+       case BSC_getdirentries:
+       case BSC_lseek:
+       case BSC_truncate:
+       case BSC_ftruncate:
+       case BSC_statv:
+       case BSC_lstatv:
+       case BSC_fstatv:
+       case BSC_mkcomplex:
+       case BSC_getattrlist:
+       case BSC_setattrlist:
+       case BSC_getdirentriesattr:
+       case BSC_exchangedata:
+       case BSC_checkuseraccess:
+       case BSC_searchfs:
+          case FILEMGR_PBGETCATALOGINFO:
+          case FILEMGR_PBGETCATALOGINFOBULK:
+          case FILEMGR_PBCREATEFILEUNICODE:
+          case FILEMGR_PBCREATEDIRECTORYUNICODE:
+          case FILEMGR_PBCREATEFORK:
+          case FILEMGR_PBDELETEFORK:
+          case FILEMGR_PBITERATEFORK:
+          case FILEMGR_PBOPENFORK:
+          case FILEMGR_PBREADFORK:
+          case FILEMGR_PBWRITEFORK:
+          case FILEMGR_PBALLOCATEFORK:
+          case FILEMGR_PBDELETEOBJECT:
+          case FILEMGR_PBEXCHANGEOBJECT:
+          case FILEMGR_PBGETFORKCBINFO:
+          case FILEMGR_PBGETVOLUMEINFO:
+          case FILEMGR_PBMAKEFSREF:
+          case FILEMGR_PBMAKEFSREFUNICODE:
+          case FILEMGR_PBMOVEOBJECT:
+          case FILEMGR_PBOPENITERATOR:
+          case FILEMGR_PBRENAMEUNICODE:
+          case FILEMGR_PBSETCATALOGINFO:
+          case FILEMGR_PBSETVOLUMEINFO:
+          case FILEMGR_FSREFMAKEPATH:
+          case FILEMGR_FSPATHMAKEREF:
+
+          case FILEMGR_PBGETCATINFO:
+          case FILEMGR_PBGETCATINFOLITE:
+          case FILEMGR_PBHGETFINFO:
+          case FILEMGR_PBXGETVOLINFO:
+          case FILEMGR_PBHCREATE:
+          case FILEMGR_PBHOPENDF:
+          case FILEMGR_PBHOPENRF:
+          case FILEMGR_PBHGETDIRACCESS:
+          case FILEMGR_PBHSETDIRACCESS:
+          case FILEMGR_PBHMAPID:
+          case FILEMGR_PBHMAPNAME:
+          case FILEMGR_PBCLOSE:
+          case FILEMGR_PBFLUSHFILE:
+          case FILEMGR_PBGETEOF:
+          case FILEMGR_PBSETEOF:
+          case FILEMGR_PBGETFPOS:
+          case FILEMGR_PBREAD:
+          case FILEMGR_PBWRITE:
+          case FILEMGR_PBGETFCBINFO:
+          case FILEMGR_PBSETFINFO:
+          case FILEMGR_PBALLOCATE:
+          case FILEMGR_PBALLOCCONTIG:
+          case FILEMGR_PBSETFPOS:
+          case FILEMGR_PBSETCATINFO:
+          case FILEMGR_PBGETVOLPARMS:
+          case FILEMGR_PBSETVINFO:
+          case FILEMGR_PBMAKEFSSPEC:
+          case FILEMGR_PBHGETVINFO:
+          case FILEMGR_PBCREATEFILEIDREF:
+          case FILEMGR_PBDELETEFILEIDREF:
+          case FILEMGR_PBRESOLVEFILEIDREF:
+          case FILEMGR_PBFLUSHVOL:
+          case FILEMGR_PBHRENAME:
+          case FILEMGR_PBCATMOVE:
+          case FILEMGR_PBEXCHANGEFILES:
+          case FILEMGR_PBHDELETE:
+          case FILEMGR_PBDIRCREATE:
+          case FILEMGR_PBCATSEARCH:
+          case FILEMGR_PBHSETFLOCK:
+          case FILEMGR_PBHRSTFLOCK:
+          case FILEMGR_PBLOCKRANGE:
+          case FILEMGR_PBUNLOCKRANGE:
+
+
+          for (i = 0, ti = th_state; ti < &th_state[MAX_THREADS]; ti++, i++) {
+                  if (ti->thread == 0)
+                          break;
+          }
+          if (ti == &th_state[MAX_THREADS])
+                  return;
+          if (i >= cur_max)
+                  cur_max = i + 1;
+
+          if ((type >> 24) == FILEMGR_CLASS) {
+                  ti->in_filemgr = 1;
+
+                  l_usecs = (long long)(now / divisor);
+                  secs = l_usecs / 1000000;
+
+                  if (bias_secs == 0) {
+                          curr_time = time((long *)0);
+                          bias_secs = curr_time - secs;
+                  }
+                  curr_time = bias_secs + secs;
+                  printf("%-8.8s", &(ctime(&curr_time)[11]));
+
+                  if (COLS > 110 || wideflag) {
+                          usecs = l_usecs - (long long)((long long)secs * 1000000);
+                          printf(".%03ld", (long)usecs / 1000);
+                  }
+                  map = find_thread_map(thread);
+                  if (map) {
+                      char buf[128];
+                      int  clen;
+
+                      sprintf(buf, "  %s", name);
+                      clen = strlen(buf);
+
+                      if (clen > 25)
+                          clen = 25;
+                      memset(&buf[clen], ' ', 26 - clen);
+
+                      sprintf(&buf[25], "(%d, 0x%x, 0x%x, 0x%x)", (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
+                      clen = strlen(&buf[25]) + 25;
+                      memset(&buf[clen], ' ', 128 - clen);
+
+                      if (COLS > 110 || wideflag)
+                          sprintf(&buf[81], "%s\n", map->command); 
+                      else
+                          sprintf(&buf[60], "%.12s\n", map->command); 
+
+                      printf(buf);
+
+                  } else
+                          printf("  %-24.24s (%5d, %#x, 0x%x, 0x%x)\n",         name, (short)kd->arg1, kd->arg2, kd->arg3, kd->arg4);
+      
+          } else {
+                          ti->in_filemgr = 0;
+          }
+          ti->thread = thread;
+          ti->vfslookup = 0;
+          ti->waited = 0;
+          ti->type   = type;
+          ti->stime  = now;
+          ti->arg1   = kd->arg1;
+          ti->arg2   = kd->arg2;
+          ti->arg3   = kd->arg3;
+          ti->arg4   = kd->arg4;
+          ti->pathname[0] = 0;
+
+          break;
+
+       default:
+          break;
+       }
+}
+
+
+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;
+       int secs;
+       int usecs;
+       int nopadding;
+       long long l_usecs;
+       long curr_time;
+       kd_threadmap *map;
+       kd_threadmap *find_thread_map();
+      
+       if ((ti = find_thread(thread, type)) == (struct th_info *)0)
+              return;
+       map = find_thread_map(thread);
+       l_usecs = (long long)(now / divisor);
+       secs = l_usecs / 1000000;
+
+       if (bias_secs == 0) {
+              curr_time = time((long *)0);
+              bias_secs = curr_time - secs;
+       }
+       curr_time = bias_secs + secs;
+       printf("%-8.8s", &(ctime(&curr_time)[11]));
+
+
+       if (COLS > 110 || wideflag) {
+              nopadding = 0;
+              usecs = l_usecs - (long long)((long long)secs * 1000000);
+              printf(".%03ld", (long)usecs / 1000);
+
+              if ((type >> 24) != FILEMGR_CLASS) {
+                  if (find_thread(thread, -1)) {
+                      printf("   ");
+                      nopadding = 1;
+                  }
+              }
+       } else
+              nopadding = 1;
+
+       if (((type >> 24) == FILEMGR_CLASS) && (COLS > 110 || wideflag)) 
+              printf("  %-18.18s", sc_name);
+       else
+              printf("  %-15.15s", sc_name);
+
+       if (COLS > 110 || wideflag) {
+              if (has_fd == 2 && error == 0)
+                      printf(" F=%-3d", retval);
+              else if (has_fd == 1)
+                      printf(" F=%-3d", ti->arg1);
+              else if (has_ret != 2)
+                      printf("      ");
+
+              if (error)
+                      printf("[%3d]       ", error);
+              else if (has_ret == 3)
+                      printf("O=0x%8.8x", ti->arg3);
+              else if (has_ret == 5)
+                      printf("O=0x%8.8x", retval);
+              else if (has_ret == 2) 
+                      printf(" A=0x%8.8x     ", retval);
+              else if (has_ret == 1)
+                      printf("  B=0x%-6x", retval);
+              else if (has_ret == 4)
+                      printf("R=0x%-8x", retval);
+              else
+                      printf("            ");
+       }
+       printf(" %-28.28s ",  ti->pathname);
+
+       usecs = (unsigned long)(((double)now - ti->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(" W");
+       else
+              printf("  ");
+
+       if (map) {
+              if (COLS > 110 || wideflag)
+                      printf(" %s", map->command);
+              else
+                      printf(" %.12s", map->command);
+       }
+       printf("\n");
+
+       if (ti == &th_state[cur_max - 1])
+                cur_max--;
+       ti->thread = 0;
+}
+
+int
+quit(s)
+char *s;
+{
+        if (trace_enabled)
+              set_enable(0);
+
+       /* 
+          This flag is turned off when calling
+          quit() due to a set_remove() failure.
+       */
+       if (set_remove_flag)
+               set_remove();
+
+        printf("fs_usage: ");
+       if (s)
+               printf("%s", s);
+
+       exit(1);
+}
+
+
+void getdivisor()
+{
+
+    unsigned int delta;
+    unsigned int abs_to_ns_num;
+    unsigned int abs_to_ns_denom;
+    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 *);
+
+    MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
+                      &proc_to_abs_num,  &proc_to_abs_denom);
+
+    divisor = ((double)abs_to_ns_denom / (double)abs_to_ns_num) * 1000;
+}
+
+
+void read_command_map()
+{
+    size_t size;
+    int mib[6];
+  
+    if (mapptr) {
+       free(mapptr);
+       mapptr = 0;
+    }
+    total_threads = bufinfo.nkdthreads;
+    size = bufinfo.nkdthreads * sizeof(kd_threadmap);
+
+    if (size)
+    {
+        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 */
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_KDEBUG;
+    mib[2] = KERN_KDTHRMAP;
+    mib[3] = 0;
+    mib[4] = 0;
+    mib[5] = 0;                /* no flags */
+    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;
+}
+
+
+void create_map_entry(int thread, char *command)
+{
+    int i, n;
+    kd_threadmap *map;
+
+    if (!mapptr)
+        return;
+
+    for (i = 0, map = 0; !map && i < total_threads; i++)
+    {
+        if (mapptr[i].thread == thread )       
+           map = &mapptr[i];   /* Reuse this entry, the thread has been reassigned */
+    }
+
+    if (!map)   /* look for invalid entries that I can reuse*/
+    {
+        for (i = 0, map = 0; !map && i < total_threads; i++)
+       {
+           if (mapptr[i].valid == 0 )  
+               map = &mapptr[i];   /* Reuse this invalid entry */
+       }
+    }
+  
+    if (!map)
+    {
+        /* If reach here, then this is a new thread and 
+        * there are no invalid entries to reuse
+        * Double the size of the thread map table.
+        */
+
+        n = total_threads * 2;
+       mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
+       bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
+       map = &mapptr[total_threads];
+       total_threads = n;
+    }
+
+    map->valid = 1;
+    map->thread = thread;
+    (void)strncpy (map->command, command, sizeof(map->command));
+    map->command[sizeof(map->command)-1] = '\0';
+}
+
+
+kd_threadmap *find_thread_map(int thread)
+{
+    int i;
+    kd_threadmap *map;
+
+    if (!mapptr)
+        return((kd_threadmap *)0);
+
+    for (i = 0; i < total_threads; i++)
+    {
+        map = &mapptr[i];
+       if (map->valid && (map->thread == thread))
+       {
+           return(map);
+       }
+    }
+    return ((kd_threadmap *)0);
+}
+
+
+void
+kill_thread_map(int thread)
+{
+    kd_threadmap *map;
+
+    if (map = find_thread_map(thread)) {
+        map->valid = 0;
+       map->thread = 0;
+       map->command[0] = '\0';
+    }
+}
+
+void
+argtopid(str)
+        char *str;
+{
+        char *cp;
+        int ret;
+       int i;
+
+        ret = (int)strtol(str, &cp, 10);
+        if (cp == str || *cp) {
+         /* Assume this is a command string and find matching pids */
+               if (!kp_buffer)
+                       find_proc_names();
+
+               for (i=0; i < kp_nentries && num_of_pids < (MAX_PIDS - 1); i++) {
+                     if(kp_buffer[i].kp_proc.p_stat == 0)
+                         continue;
+                     else {
+                         if(!strcmp(str, kp_buffer[i].kp_proc.p_comm))
+                           pids[num_of_pids++] = kp_buffer[i].kp_proc.p_pid;
+                     }
+               }
+       }
+       else if (num_of_pids < (MAX_PIDS - 1))
+               pids[num_of_pids++] = ret;
+
+        return;
+}
+
+
diff --git a/getty.tproj/Makefile b/getty.tproj/Makefile
new file mode 100644 (file)
index 0000000..f7c2acc
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = getty
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = extern.h gettytab.h pathnames.h
+
+CFILES = init.c main.c subr.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble getty.8\
+            gettytab.5 ttys.5
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/getty.tproj/Makefile.postamble b/getty.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..cb09ed6
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+
diff --git a/getty.tproj/Makefile.preamble b/getty.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..5741d84
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+
diff --git a/getty.tproj/PB.project b/getty.tproj/PB.project
new file mode 100644 (file)
index 0000000..f4b1c8b
--- /dev/null
@@ -0,0 +1,40 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (extern.h, gettytab.h, pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (init.c, main.c, subr.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, getty.8, gettytab.5, ttys.5); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = getty; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/getty.tproj/extern.h b/getty.tproj/extern.h
new file mode 100644 (file)
index 0000000..f8e759a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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) 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.
+ *
+ *     from: @(#)extern.h      8.1 (Berkeley) 6/4/93
+ *     $Id: extern.h,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $
+ */
+
+struct delayval;
+
+int     adelay __P((int, struct delayval *));
+char   *autobaud __P((void));
+int     delaybits __P((void));
+void    edithost __P((char *));
+void    gendefaults __P((void));
+int     getent __P((char *, char *));
+int     getflag __P((char *));
+long    getnum __P((char *));
+char   *getstr __P((char *, char **));
+void    gettable __P((char *, char *));
+void    makeenv __P((char *[]));
+char   *portselector __P((void));
+void    set_ttydefaults __P((int));
+void    setchars __P((void));
+void    setdefaults __P((void));
+void    setflags __P((int));
+int     speed __P((int));
+
+int     login_tty __P((int));                  /* From libutil. */
diff --git a/getty.tproj/getty.8 b/getty.tproj/getty.8
new file mode 100644 (file)
index 0000000..cc6612f
--- /dev/null
@@ -0,0 +1,128 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"     from: @(#)getty.8      8.1 (Berkeley) 6/4/93
+.\"    $Id: getty.8,v 1.1.1.1 1999/05/02 04:21:29 wsanchez Exp $
+.\"
+.Dd June 4, 1993
+.Dt GETTY 8
+.Os BSD 4
+.Sh NAME
+.Nm getty
+.Nd set terminal mode
+.Sh SYNOPSIS
+.Nm getty
+.Oo 
+.Ar type
+.Op Ar tty
+.Oc
+.Sh DESCRIPTION
+The
+.Nm getty
+program
+is called by
+.Xr init 8
+to open and initialize the tty line, read a login name, and invoke
+.Xr login 1 .
+.Pp
+The argument
+.Ar tty
+is the special device file in
+.Pa /dev
+to open for the terminal (for example, ``ttyh0'').
+If there is no argument or the argument is
+.Ql Fl ,
+the tty line is assumed to be open as file descriptor 0.
+.Pp
+The
+.Ar type
+argument can be used to make
+.Nm getty
+treat the terminal line specially.
+This argument is used as an index into the
+.Nm gettytab 5
+database, to determine the characteristics of the line.
+If there is no argument, or there is no such table, the
+.Em default
+table is used.
+If there is no
+.Pa /etc/gettytab
+a set of system defaults is used.
+If indicated by the table located,
+.Nm getty
+will clear the terminal screen,
+print a banner heading,
+and prompt for a login name.
+Usually either the banner or the login prompt will include
+the system hostname.
+.Pp
+Most of the default actions of
+.Nm getty
+can be circumvented, or modified, by a suitable
+.Nm gettytab
+table.
+.Pp
+The
+.Nm getty
+program
+can be set to timeout after some interval,
+which will cause dial up lines to hang up
+if the login name is not entered reasonably quickly.
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "ttyxx: No such device or address."
+.It "ttyxx: No such file or address."
+A terminal which is turned
+on in the
+.Xr ttys
+file cannot be opened, likely because the requisite
+lines are either not configured into the system, the associated device
+was not attached during boot-time system configuration,
+or the special file in
+.Pa /dev
+does not exist.
+.El
+.Sh FILES
+.Bl -tag -width /etc/gettytab -compact
+.It Pa /etc/gettytab
+.El
+.Sh SEE ALSO
+.Xr gettytab 5 ,
+.Xr init 8 ,
+.Xr login 1 ,
+.Xr ioctl 2 ,
+.Xr tty 4 ,
+.Xr ttys 5
+.Sh HISTORY
+A
+.Nm getty
+program appeared in
+.At v6 .
diff --git a/getty.tproj/gettytab.5 b/getty.tproj/gettytab.5
new file mode 100644 (file)
index 0000000..51d4cfe
--- /dev/null
@@ -0,0 +1,372 @@
+.\" Copyright (c) 1983, 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.
+.\"
+.\"     from: @(#)gettytab.5   8.4 (Berkeley) 4/19/94
+.\"    $Id: gettytab.5,v 1.1.1.1 1999/05/02 04:21:29 wsanchez Exp $
+.\"
+.Dd April 19, 1994
+.Dt GETTYTAB 5
+.Os BSD 4.2
+.Sh NAME
+.Nm gettytab
+.Nd terminal configuration data base
+.Sh SYNOPSIS
+.Nm gettytab
+.Sh DESCRIPTION
+The
+.Nm gettytab
+file
+is a simplified version of the
+.Xr termcap 5
+data base
+used to describe terminal lines.
+The initial terminal login process
+.Xr getty 8
+accesses the
+.Nm gettytab
+file each time it starts, allowing simpler
+reconfiguration of terminal characteristics.
+Each entry in the data base
+is used to describe one class of terminals.
+.Pp
+There is a default terminal class,
+.Em default ,
+that is used to set global defaults for all other classes.
+(That is, the
+.Em default
+entry is read, then the entry for the class required
+is used to override particular settings.)
+.Sh CAPABILITIES
+Refer to
+.Xr termcap 5
+for a description of the file layout.
+The
+.Em default
+column below lists defaults obtained if there is
+no entry in the table obtained, nor one in the special
+.Em default
+table.
+.Bl -column Namexx /usr/bin/login Default
+.It Sy Name    Type    Default Description
+.It "ap        bool    false   terminal uses any parity"
+.It "bk        str     0377    alternate end of line character (input break)"
+.It "c0        num     unused  tty control flags to write messages"
+.It "c1        num     unused  tty control flags to read login name"
+.It "c2        num     unused  tty control flags to leave terminal as"
+.It "ce        bool    false   use crt erase algorithm"
+.It "ck        bool    false   use crt kill algorithm"
+.It "cl        str" Ta Dv NULL Ta
+.No "screen clear sequence"
+.It "co        bool    false   console - add"
+.Ql \en
+after login prompt
+.It "ds        str" Ta So Li ^Y Sc Ta
+.No "delayed suspend character"
+.It "dx        bool    false   set"
+.Dv DECCTLQ
+.It "ec        bool    false   leave echo"
+.Tn OFF
+.It "ep        bool    false   terminal uses even parity"
+.It "er        str" Ta So Li ^? Sc Ta
+.No "erase character"
+.It "et        str" Ta So Li ^D Sc Ta
+.No "end of text"
+.Pq Dv EOF
+character
+.It "ev        str" Ta Dv NULL Ta
+.No "initial environment"
+.It "f0        num     unused  tty mode flags to write messages"
+.It "f1        num     unused  tty mode flags to read login name"
+.It "f2        num     unused  tty mode flags to leave terminal as"
+.It "fl        str" Ta So Li ^O Sc Ta
+.No "output flush character"
+.It "hc        bool    false   do"
+.Tn NOT
+hangup line on last close
+.It "he        str" Ta Dv NULL Ta
+.No "hostname editing string"
+.It "hn        str     hostname        hostname"
+.It "ht        bool    false   terminal has real tabs"
+.It "i0        num     unused  tty input flags to write messages"
+.It "i1        num     unused  tty input flags to read login name"
+.It "i2        num     unused  tty input flags to leave terminal as"
+.It "ig        bool    false   ignore garbage characters in login name"
+.It "im        str" Ta Dv NULL Ta
+.No "initial (banner) message"
+.It "in        str" Ta So Li ^C Sc Ta
+.No "interrupt character"
+.It "is        num     unused  input speed"
+.It "kl        str" Ta So Li ^U Sc Ta
+.No "kill character"
+.It "l0        num     unused  tty local flags to write messages"
+.It "l1        num     unused  tty local flags to read login name"
+.It "l2        num     unused  tty local flags to leave terminal as"
+.It "lc        bool    false   terminal has lower case"
+.It "lm        str     login:  login prompt"
+.It "ln        str" Ta So Li ^V Sc Ta
+.No "``literal next'' character"
+.It "lo        str" Ta Pa /usr/bin/login Ta
+.No "program to exec when name obtained"
+.It "mb        bool    false   do flow control based on carrier"
+.It "nl        bool    false   terminal has (or might have) a newline character"
+.It "np        bool    false   terminal uses no parity (i.e. 8-bit characters)"
+.It "nx        str     default next table (for auto speed selection)"
+.It "o0        num     unused  tty output flags to write messages"
+.It "o1        num     unused  tty output flags to read login name"
+.It "o2        num     unused  tty output flags to leave terminal as"
+.It "op        bool    false   terminal uses odd parity"
+.It "os        num     unused  output speed"
+.It "pc        str" Ta So Li \e0 Sc Ta
+.No "pad character"
+.It "pe        bool    false   use printer (hard copy) erase algorithm"
+.It "pf        num     0       delay"
+between first prompt and following flush (seconds)
+.It "ps        bool    false   line connected to a"
+.Tn MICOM
+port selector
+.It "qu        str" Ta So Li \&^\e Sc Ta
+.No "quit character"
+.It "rp        str" Ta So Li ^R Sc Ta
+.No "line retype character"
+.It "rw        bool    false   do"
+.Tn NOT
+use raw for input, use cbreak
+.It "sp        num     unused  line speed (input and output)"
+.It "su        str" Ta So Li ^Z Sc Ta
+.No "suspend character"
+.It "tc        str     none    table continuation"
+.It "to        num     0       timeout (seconds)"
+.It "tt        str" Ta Dv NULL Ta
+.No "terminal type (for environment)"
+.It "ub        bool    false   do unbuffered output (of prompts etc)"
+.It "we        str" Ta So Li ^W Sc Ta
+.No "word erase character"
+.It "xc        bool    false   do
+.Tn NOT
+echo control chars as
+.Ql ^X
+.It "xf        str" Ta So Li ^S Sc Ta Dv XOFF
+(stop output) character
+.It "xn        str" Ta So Li ^Q Sc Ta Dv XON
+(start output) character
+.El
+.Pp
+The following capabilities are no longer supported by getty(8):
+.Bl -column Namexx /usr/bin/login Default
+.It "bd        num     0       backspace delay"
+.It "cb        bool    false   use crt backspace mode"
+.It "cd        num     0       carriage-return delay"
+.It "fd        num     0       form-feed (vertical motion) delay"
+.It "nd        num     0       newline (line-feed) delay"
+.It "uc        bool    false   terminal is known upper case only"
+.El
+.Pp
+If no line speed is specified, speed will not be altered
+from that which prevails when getty is entered.
+Specifying an input or output speed will override
+line speed for stated direction only.
+.Pp
+Terminal modes to be used for the output of the message,
+for input of the login name,
+and to leave the terminal set as upon completion,
+are derived from the boolean flags specified.
+If the derivation should prove inadequate,
+any (or all) of these three may be overridden
+with one of the
+.Em \&c0 ,
+.Em \&c1 ,
+.Em \&c2 ,
+.Em \&i0 ,
+.Em \&i1 ,
+.Em \&i2 ,
+.Em \&l0 ,
+.Em \&l1 ,
+.Em \&l2 ,
+.Em \&o0 ,
+.Em \&o1 ,
+or
+.Em \&o2
+numeric specifications, which can be used to specify
+(usually in octal, with a leading '0')
+the exact values of the flags.
+These flags correspond to the termios
+.Em c_cflag ,
+.Em c_iflag ,
+.Em c_lflag ,
+and
+.Em c_oflag
+fields, respectively. Each these sets must be completely specified to be
+effective.
+The
+.Em \&f0 ,
+.Em \&f1 ,
+and
+.Em \&f2
+are excepted for backwards compatibility with a previous incarnation of
+the TTY sub-system. In these flags the bottom 16 bits of the (32 bits)
+value contain the sgttyb
+.Em sg_flags
+field, while the top 16 bits represent the local mode word.
+.Pp
+Should
+.Xr getty
+receive a null character
+(presumed to indicate a line break)
+it will restart using the table indicated by the
+.Em nx
+entry. If there is none, it will re-use its original table.
+.Pp
+Delays are specified in milliseconds, the nearest possible
+delay available in the tty driver will be used.
+Should greater certainty be desired, delays
+with values 0, 1, 2, and 3 are interpreted as
+choosing that particular delay algorithm from the driver.
+.Pp
+The
+.Em \&cl
+screen clear string may be preceded by a (decimal) number
+of milliseconds of delay required (a la termcap).
+This delay is simulated by repeated use of the pad character
+.Em \&pc .
+.Pp
+The initial message, and login message,
+.Em \&im
+and
+.Em \&lm
+may include the character sequence
+.Em \&%h
+or
+.Em \&%t
+to obtain
+the hostname or tty name respectively.
+.Pf ( Em %%
+obtains a single '%' character.)
+The hostname is normally obtained from the system,
+but may be set by the
+.Em \&hn
+table entry.
+In either case it may be edited with
+.Em \&he .
+The
+.Em \&he
+string is a sequence of characters, each character that
+is neither '@' nor '#' is copied into the final hostname.
+A '@' in the
+.Em \&he
+string, causes one character from the real hostname to
+be copied to the final hostname.
+A '#' in the
+.Em \&he
+string, causes the next character of the real hostname
+to be skipped.
+Surplus '@' and '#' characters are ignored.
+.Pp
+When getty execs the login process, given
+in the
+.Em \&lo
+string (usually
+.Dq Pa /usr/bin/login ) ,
+it will have set
+the environment to include the terminal type, as indicated
+by the
+.Em \&tt
+string (if it exists).
+The
+.Em \&ev
+string, can be used to enter additional data into
+the environment.
+It is a list of comma separated strings, each of which
+will presumably be of the form
+.Em name=value .
+.Pp
+If a non-zero timeout is specified, with
+.Em \&to ,
+then getty will exit within the indicated
+number of seconds, either having
+received a login name and passed control
+to
+.Xr login ,
+or having received an alarm signal, and exited.
+This may be useful to hangup dial in lines.
+.Pp
+Output from
+.Xr getty
+is even parity unless
+.Em \&op
+or
+.Em \&np
+is specified.
+The
+.Em \&op
+string
+may be specified with
+.Em \&ap
+to allow any parity on input, but generate odd parity output.
+Note: this only applies while getty is being run,
+terminal driver limitations prevent a more complete
+implementation.
+.Xr Getty
+does not check parity of input characters in
+.Dv RAW
+mode.
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr termcap 5 ,
+.Xr getty 8 .
+.Sh BUGS
+The special characters (erase, kill, etc.) are reset to system defaults
+by
+.Xr login 1 .
+In
+.Em all
+cases, '#' or '^H' typed in a login name will be treated as
+an erase character, and '@' will be treated as a kill character.
+.Pp
+The delay stuff is a real crock.
+Apart form its general lack of flexibility, some
+of the delay algorithms are not implemented.
+The terminal driver should support sane delay settings.
+.Pp
+The
+.Em \&he
+capability is stupid.
+.Pp
+The
+.Xr termcap
+format is horrid, something more rational should
+have been chosen.
+.Pp
+This should be converted to use
+.Xr termios 4 .
+.Sh HISTORY
+The
+.Nm gettytab
+file format appeared in 4.2BSD.
diff --git a/getty.tproj/gettytab.h b/getty.tproj/gettytab.h
new file mode 100644 (file)
index 0000000..2fcd79c
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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) 1983, 1993, 1994
+ *     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: @(#)gettytab.h    8.2 (Berkeley) 3/30/94
+ *     $Id: gettytab.h,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $
+ */
+
+/*
+ * Getty description definitions.
+ */
+struct gettystrs {
+       char    *field;         /* name to lookup in gettytab */
+       char    *defalt;        /* value we find by looking in defaults */
+       char    *value;         /* value that we find there */
+};
+
+struct gettynums {
+       char    *field;         /* name to lookup */
+       long    defalt;         /* number we find in defaults */
+       long    value;          /* number we find there */
+       int     set;            /* we actually got this one */
+};
+
+struct gettyflags {
+       char    *field;         /* name to lookup */
+       char    invrt;          /* name existing in gettytab --> false */
+       char    defalt;         /* true/false in defaults */
+       char    value;          /* true/false flag */
+       char    set;            /* we found it */
+};
+
+/*
+ * String values.
+ */
+#define        NX      gettystrs[0].value
+#define        CL      gettystrs[1].value
+#define IM     gettystrs[2].value
+#define        LM      gettystrs[3].value
+#define        ER      gettystrs[4].value
+#define        KL      gettystrs[5].value
+#define        ET      gettystrs[6].value
+#define        PC      gettystrs[7].value
+#define        TT      gettystrs[8].value
+#define        EV      gettystrs[9].value
+#define        LO      gettystrs[10].value
+#define HN     gettystrs[11].value
+#define HE     gettystrs[12].value
+#define IN     gettystrs[13].value
+#define QU     gettystrs[14].value
+#define XN     gettystrs[15].value
+#define XF     gettystrs[16].value
+#define BK     gettystrs[17].value
+#define SU     gettystrs[18].value
+#define DS     gettystrs[19].value
+#define RP     gettystrs[20].value
+#define FL     gettystrs[21].value
+#define WE     gettystrs[22].value
+#define LN     gettystrs[23].value
+
+/*
+ * Numeric definitions.
+ */
+#define        IS      gettynums[0].value
+#define        OS      gettynums[1].value
+#define        SP      gettynums[2].value
+#define        ND      gettynums[3].value
+#define        CD      gettynums[4].value
+#define        TD      gettynums[5].value
+#define        FD      gettynums[6].value
+#define        BD      gettynums[7].value
+#define        TO      gettynums[8].value
+#define        F0      gettynums[9].value
+#define        F0set   gettynums[9].set
+#define        F1      gettynums[10].value
+#define        F1set   gettynums[10].set
+#define        F2      gettynums[11].value
+#define        F2set   gettynums[11].set
+#define        PF      gettynums[12].value
+#define        C0      gettynums[13].value
+#define        C0set   gettynums[13].set
+#define        C1      gettynums[14].value
+#define        C1set   gettynums[14].set
+#define        C2      gettynums[15].value
+#define        C2set   gettynums[15].set
+#define        I0      gettynums[16].value
+#define        I0set   gettynums[16].set
+#define        I1      gettynums[17].value
+#define        I1set   gettynums[17].set
+#define        I2      gettynums[18].value
+#define        I2set   gettynums[18].set
+#define        L0      gettynums[19].value
+#define        L0set   gettynums[19].set
+#define        L1      gettynums[20].value
+#define        L1set   gettynums[20].set
+#define        L2      gettynums[21].value
+#define        L2set   gettynums[21].set
+#define        O0      gettynums[22].value
+#define        O0set   gettynums[22].set
+#define        O1      gettynums[23].value
+#define        O1set   gettynums[23].set
+#define        O2      gettynums[24].value
+#define        O2set   gettynums[24].set
+
+/*
+ * Boolean values.
+ */
+#define        HT      gettyflags[0].value
+#define        NL      gettyflags[1].value
+#define        EP      gettyflags[2].value
+#define        EPset   gettyflags[2].set
+#define        OP      gettyflags[3].value
+#define        OPset   gettyflags[3].set
+#define        AP      gettyflags[4].value
+#define        APset   gettyflags[4].set
+#define        EC      gettyflags[5].value
+#define        CO      gettyflags[6].value
+#define        CB      gettyflags[7].value
+#define        CK      gettyflags[8].value
+#define        CE      gettyflags[9].value
+#define        PE      gettyflags[10].value
+#define        RW      gettyflags[11].value
+#define        XC      gettyflags[12].value
+#define        LC      gettyflags[13].value
+#define        UC      gettyflags[14].value
+#define        IG      gettyflags[15].value
+#define        PS      gettyflags[16].value
+#define        HC      gettyflags[17].value
+#define UB     gettyflags[18].value
+#define AB     gettyflags[19].value
+#define DX     gettyflags[20].value
+#define        NP      gettyflags[21].value
+#define        MB      gettyflags[22].value
+
+int    getent __P((char *, char *));
+long   getnum __P((char *));
+int    getflag __P((char *));
+char   *getstr __P((char *, char **));
+
+extern struct gettyflags gettyflags[];
+extern struct gettynums gettynums[];
+extern struct gettystrs gettystrs[];
+extern int hopcount;
diff --git a/getty.tproj/init.c b/getty.tproj/init.c
new file mode 100644 (file)
index 0000000..99c980a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * 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) 1983, 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 char sccsid[] = "from: @(#)init.c     8.1 (Berkeley) 6/4/93";*/
+static char rcsid[] = "$Id: init.c,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $";
+#endif /* not lint */
+
+/*
+ * Getty table initializations.
+ *
+ * Melbourne getty.
+ */
+#include <termios.h>
+#include "gettytab.h"
+#include "pathnames.h"
+
+extern struct termios tmode;
+extern char hostname[];
+
+struct gettystrs gettystrs[] = {
+       { "nx" },                       /* next table */
+       { "cl" },                       /* screen clear characters */
+       { "im" },                       /* initial message */
+       { "lm", "login: " },            /* login message */
+       { "er", &tmode.c_cc[VERASE] },  /* erase character */
+       { "kl", &tmode.c_cc[VKILL] },   /* kill character */
+       { "et", &tmode.c_cc[VEOF] },    /* eof chatacter (eot) */
+       { "pc", "" },                   /* pad character */
+       { "tt" },                       /* terminal type */
+       { "ev" },                       /* enviroment */
+       { "lo", _PATH_LOGIN },          /* login program */
+       { "hn", hostname },             /* host name */
+       { "he" },                       /* host name edit */
+       { "in", &tmode.c_cc[VINTR] },   /* interrupt char */
+       { "qu", &tmode.c_cc[VQUIT] },   /* quit char */
+       { "xn", &tmode.c_cc[VSTART] },  /* XON (start) char */
+       { "xf", &tmode.c_cc[VSTOP] },   /* XOFF (stop) char */
+       { "bk", &tmode.c_cc[VEOL] },    /* brk char (alt \n) */
+       { "su", &tmode.c_cc[VSUSP] },   /* suspend char */
+       { "ds", &tmode.c_cc[VDSUSP] },  /* delayed suspend */
+       { "rp", &tmode.c_cc[VREPRINT] },/* reprint char */
+       { "fl", &tmode.c_cc[VDISCARD] },/* flush output */
+       { "we", &tmode.c_cc[VWERASE] }, /* word erase */
+       { "ln", &tmode.c_cc[VLNEXT] },  /* literal next */
+       { 0 }
+};
+
+struct gettynums gettynums[] = {
+       { "is" },                       /* input speed */
+       { "os" },                       /* output speed */
+       { "sp" },                       /* both speeds */
+       { "nd" },                       /* newline delay */
+       { "cd" },                       /* carriage-return delay */
+       { "td" },                       /* tab delay */
+       { "fd" },                       /* form-feed delay */
+       { "bd" },                       /* backspace delay */
+       { "to" },                       /* timeout */
+       { "f0" },                       /* output flags */
+       { "f1" },                       /* input flags */
+       { "f2" },                       /* user mode flags */
+       { "pf" },                       /* delay before flush at 1st prompt */
+       { "c0" },                       /* output c_flags */
+       { "c1" },                       /* input c_flags */
+       { "c2" },                       /* user mode c_flags */
+       { "i0" },                       /* output i_flags */
+       { "i1" },                       /* input i_flags */
+       { "i2" },                       /* user mode i_flags */
+       { "l0" },                       /* output l_flags */
+       { "l1" },                       /* input l_flags */
+       { "l2" },                       /* user mode l_flags */
+       { "o0" },                       /* output o_flags */
+       { "o1" },                       /* input o_flags */
+       { "o2" },                       /* user mode o_flags */
+       { 0 }
+};
+
+struct gettyflags gettyflags[] = {
+       { "ht", 0 },                    /* has tabs */
+       { "nl", 1 },                    /* has newline char */
+       { "ep", 0 },                    /* even parity */
+       { "op", 0 },                    /* odd parity */
+       { "ap", 0 },                    /* any parity */
+       { "ec", 1 },                    /* no echo */
+       { "co", 0 },                    /* console special */
+       { "cb", 0 },                    /* crt backspace */
+       { "ck", 0 },                    /* crt kill */
+       { "ce", 0 },                    /* crt erase */
+       { "pe", 0 },                    /* printer erase */
+       { "rw", 1 },                    /* don't use raw */
+       { "xc", 1 },                    /* don't ^X ctl chars */
+       { "lc", 0 },                    /* terminal las lower case */
+       { "uc", 0 },                    /* terminal has no lower case */
+       { "ig", 0 },                    /* ignore garbage */
+       { "ps", 0 },                    /* do port selector speed select */
+       { "hc", 1 },                    /* don't set hangup on close */
+       { "ub", 0 },                    /* unbuffered output */
+       { "ab", 0 },                    /* auto-baud detect with '\r' */
+       { "dx", 0 },                    /* set decctlq */
+       { "np", 0 },                    /* no parity at all (8bit chars) */
+       { "mb", 0 },                    /* do MDMBUF flow control */
+       { 0 }
+};
diff --git a/getty.tproj/main.c b/getty.tproj/main.c
new file mode 100644 (file)
index 0000000..d6c556d
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ * 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) 1980, 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 char copyright[] =
+"@(#) Copyright (c) 1980, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)main.c     8.1 (Berkeley) 6/20/93";*/
+static char rcsid[] = "$Id: main.c,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/termios.h>
+#include <sys/ioctl.h>
+#include <sys/resource.h>
+#include <sys/utsname.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "gettytab.h"
+#include "pathnames.h"
+#include "extern.h"
+
+/*
+ * Set the amount of running time that getty should accumulate
+ * before deciding that something is wrong and exit.
+ */
+#define GETTY_TIMEOUT  60 /* seconds */
+
+struct termios tmode, omode;
+
+int crmod, digit, lower, upper;
+
+char   hostname[MAXHOSTNAMELEN];
+struct utsname kerninfo;
+char   name[16];
+char   dev[] = _PATH_DEV;
+char   ttyn[32];
+char   *portselector();
+char   *ttyname();
+
+#define        OBUFSIZ         128
+#define        TABBUFSIZ       512
+
+char   defent[TABBUFSIZ];
+char   tabent[TABBUFSIZ];
+
+char   *env[128];
+
+char partab[] = {
+       0001,0201,0201,0001,0201,0001,0001,0201,
+       0202,0004,0003,0205,0005,0206,0201,0001,
+       0201,0001,0001,0201,0001,0201,0201,0001,
+       0001,0201,0201,0001,0201,0001,0001,0201,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0200,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0200,0000,0000,0200,0000,0200,0200,0000,
+       0000,0200,0200,0000,0200,0000,0000,0201
+};
+
+#define        ERASE   tmode.c_cc[VERASE]
+#define        KILL    tmode.c_cc[VKILL]
+#define        EOT     tmode.c_cc[VEOF]
+
+jmp_buf timeout;
+
+static void
+dingdong()
+{
+
+       alarm(0);
+       signal(SIGALRM, SIG_DFL);
+       longjmp(timeout, 1);
+}
+
+jmp_buf        intrupt;
+
+static void
+interrupt()
+{
+
+       signal(SIGINT, interrupt);
+       longjmp(intrupt, 1);
+}
+
+/*
+ * Action to take when getty is running too long.
+ */
+void
+timeoverrun(signo)
+       int signo;
+{
+
+       syslog(LOG_ERR, "getty exiting due to excessive running time\n");
+       exit(1);
+}
+
+static int     getname __P((void));
+static void    oflush __P((void));
+static void    prompt __P((void));
+static void    putchr __P((int));
+static void    putf __P((char *));
+static void    putpad __P((char *));
+static void    puts __P((char *));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern char **environ;
+       char *tname;
+       long allflags;
+       int repcnt = 0;
+       struct rlimit limit;
+       int ttyopenmode;
+
+       signal(SIGINT, SIG_IGN);
+/*
+       signal(SIGQUIT, SIG_DFL);
+*/
+       openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH);
+       gethostname(hostname, sizeof(hostname));
+       if (hostname[0] == '\0')
+               strcpy(hostname, "Amnesiac");
+       uname(&kerninfo);
+
+       /*
+        * Limit running time to deal with broken or dead lines.
+        */
+       (void)signal(SIGXCPU, timeoverrun);
+       limit.rlim_max = RLIM_INFINITY;
+       limit.rlim_cur = GETTY_TIMEOUT;
+       (void)setrlimit(RLIMIT_CPU, &limit);
+
+       /*
+        * The following is a work around for vhangup interactions
+        * which cause great problems getting window systems started.
+        * If the tty line is "-", we do the old style getty presuming
+        * that the file descriptors are already set up for us. 
+        * J. Gettys - MIT Project Athena.
+        */
+       if (argc <= 2 || strcmp(argv[2], "-") == 0)
+           strcpy(ttyn, ttyname(0));
+       else {
+           int i;
+
+           strcpy(ttyn, dev);
+           strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev));
+           if (strcmp(argv[0], "+") != 0) {
+               chown(ttyn, 0, 0);
+               chmod(ttyn, 0600);
+               revoke(ttyn);
+               /*
+                * Delay the open so DTR stays down long enough to be detected.
+                */
+               sleep(2);
+#ifdef __APPLE__
+               ttyopenmode = ((strcmp(ttyn, _PATH_CONSOLE)==0)
+                       ? (O_RDWR |O_POPUP): O_RDWR);
+#else /* __APPLE __ */
+               ttyopenmode = O_RDWR;
+#endif /* __APPLE__ */
+
+               while ((i = open(ttyn, ttyopenmode)) == -1) {
+                       if (repcnt % 10 == 0) {
+                               syslog(LOG_ERR, "%s: %m", ttyn);
+                               closelog();
+                       }
+                       repcnt++;
+                       sleep(60);
+               }
+               login_tty(i);
+           }
+       }
+
+       /* Start with default tty settings */
+       if (tcgetattr(0, &tmode) < 0) {
+               syslog(LOG_ERR, "%s: %m", ttyn);
+               exit(1);
+       }
+       omode = tmode;
+
+       gettable("default", defent);
+       gendefaults();
+       tname = "default";
+       if (argc > 1)
+               tname = argv[1];
+       for (;;) {
+               int off;
+
+               gettable(tname, tabent);
+               if (OPset || EPset || APset)
+                       APset++, OPset++, EPset++;
+               setdefaults();
+               off = 0;
+               ioctl(0, TIOCFLUSH, &off);      /* clear out the crap */
+               ioctl(0, FIONBIO, &off);        /* turn off non-blocking mode */
+               ioctl(0, FIOASYNC, &off);       /* ditto for async mode */
+
+               if (IS)
+                       cfsetispeed(&tmode, IS);
+               else if (SP)
+                       cfsetispeed(&tmode, SP);
+               if (OS)
+                       cfsetospeed(&tmode, OS);
+               else if (SP)
+                       cfsetospeed(&tmode, SP);
+               setflags(0);
+               setchars();
+               if (tcsetattr(0, TCSANOW, &tmode) < 0) {
+                       syslog(LOG_ERR, "%s: %m", ttyn);
+                       exit(1);
+               }
+               if (AB) {
+                       extern char *autobaud();
+
+                       tname = autobaud();
+                       continue;
+               }
+               if (PS) {
+                       tname = portselector();
+                       continue;
+               }
+               if (CL && *CL)
+                       putpad(CL);
+               edithost(HE);
+               if (IM && *IM)
+                       putf(IM);
+               if (setjmp(timeout)) {
+                       tmode.c_ispeed = tmode.c_ospeed = 0;
+                       (void)tcsetattr(0, TCSANOW, &tmode);
+                       exit(1);
+               }
+               if (TO) {
+                       signal(SIGALRM, dingdong);
+                       alarm(TO);
+               }
+               if (getname()) {
+                       register int i;
+
+                       oflush();
+                       alarm(0);
+                       signal(SIGALRM, SIG_DFL);
+                       if (name[0] == '-') {
+                               puts("user names may not start with '-'.");
+                               continue;
+                       }
+                       if (!(upper || lower || digit))
+                               continue;
+                       setflags(2);
+                       if (crmod) {
+                               tmode.c_iflag |= ICRNL;
+                               tmode.c_oflag |= ONLCR;
+                       }
+#if XXX
+                       if (upper || UC)
+                               tmode.sg_flags |= LCASE;
+                       if (lower || LC)
+                               tmode.sg_flags &= ~LCASE;
+#endif
+                       if (tcsetattr(0, TCSANOW, &tmode) < 0) {
+                               syslog(LOG_ERR, "%s: %m", ttyn);
+                               exit(1);
+                       }
+                       signal(SIGINT, SIG_DFL);
+                       for (i = 0; environ[i] != (char *)0; i++)
+                               env[i] = environ[i];
+                       makeenv(&env[i]);
+
+                       limit.rlim_max = RLIM_INFINITY;
+                       limit.rlim_cur = RLIM_INFINITY;
+                       (void)setrlimit(RLIMIT_CPU, &limit);
+                       execle(LO, "login", "-p", name, (char *) 0, env);
+                       syslog(LOG_ERR, "%s: %m", LO);
+                       exit(1);
+               }
+               alarm(0);
+               signal(SIGALRM, SIG_DFL);
+               signal(SIGINT, SIG_IGN);
+               if (NX && *NX)
+                       tname = NX;
+       }
+}
+
+static int
+getname()
+{
+       register int c;
+       register char *np;
+       char cs;
+
+       /*
+        * Interrupt may happen if we use CBREAK mode
+        */
+       if (setjmp(intrupt)) {
+               signal(SIGINT, SIG_IGN);
+               return (0);
+       }
+       signal(SIGINT, interrupt);
+       setflags(1);
+       prompt();
+       if (PF > 0) {
+               oflush();
+               sleep(PF);
+               PF = 0;
+       }
+       if (tcsetattr(0, TCSANOW, &tmode) < 0) {
+               syslog(LOG_ERR, "%s: %m", ttyn);
+               exit(1);
+       }
+       crmod = digit = lower = upper = 0;
+       np = name;
+       for (;;) {
+               oflush();
+               if (read(STDIN_FILENO, &cs, 1) <= 0)
+                       exit(0);
+               if ((c = cs&0177) == 0)
+                       return (0);
+               if (c == EOT)
+                       exit(1);
+               if (c == '\r' || c == '\n' || np >= &name[sizeof name]) {
+                       putf("\r\n");
+                       break;
+               }
+               if (islower(c))
+                       lower = 1;
+               else if (isupper(c))
+                       upper = 1;
+               else if (c == ERASE || c == '#' || c == '\b') {
+                       if (np > name) {
+                               np--;
+                               if (cfgetospeed(&tmode) >= 1200)
+                                       puts("\b \b");
+                               else
+                                       putchr(cs);
+                       }
+                       continue;
+               } else if (c == KILL || c == '@') {
+                       putchr(cs);
+                       putchr('\r');
+                       if (cfgetospeed(&tmode) < 1200)
+                               putchr('\n');
+                       /* this is the way they do it down under ... */
+                       else if (np > name)
+                               puts("                                     \r");
+                       prompt();
+                       np = name;
+                       continue;
+               } else if (isdigit(c))
+                       digit++;
+               if (IG && (c <= ' ' || c > 0176))
+                       continue;
+               *np++ = c;
+               putchr(cs);
+       }
+       signal(SIGINT, SIG_IGN);
+       *np = 0;
+       if (c == '\r')
+               crmod = 1;
+       if (upper && !lower && !LC || UC)
+               for (np = name; *np; np++)
+                       if (isupper(*np))
+                               *np = tolower(*np);
+       return (1);
+}
+
+static void
+putpad(s)
+       register char *s;
+{
+       register pad = 0;
+       speed_t ospeed = cfgetospeed(&tmode);
+
+       if (isdigit(*s)) {
+               while (isdigit(*s)) {
+                       pad *= 10;
+                       pad += *s++ - '0';
+               }
+               pad *= 10;
+               if (*s == '.' && isdigit(s[1])) {
+                       pad += s[1] - '0';
+                       s += 2;
+               }
+       }
+
+       puts(s);
+       /*
+        * If no delay needed, or output speed is
+        * not comprehensible, then don't try to delay.
+        */
+       if (pad == 0 || ospeed <= 0)
+               return;
+
+       /*
+        * Round up by a half a character frame, and then do the delay.
+        * Too bad there are no user program accessible programmed delays.
+        * Transmitting pad characters slows many terminals down and also
+        * loads the system.
+        */
+       pad = (pad * ospeed + 50000) / 100000;
+       while (pad--)
+               putchr(*PC);
+}
+
+static void
+puts(s)
+       register char *s;
+{
+       while (*s)
+               putchr(*s++);
+}
+
+char   outbuf[OBUFSIZ];
+int    obufcnt = 0;
+
+static void
+putchr(cc)
+       int cc;
+{
+       char c;
+
+       c = cc;
+       if (!NP) {
+               c |= partab[c&0177] & 0200;
+               if (OP)
+                       c ^= 0200;
+       }
+       if (!UB) {
+               outbuf[obufcnt++] = c;
+               if (obufcnt >= OBUFSIZ)
+                       oflush();
+       } else
+               write(STDOUT_FILENO, &c, 1);
+}
+
+static void
+oflush()
+{
+       if (obufcnt)
+               write(STDOUT_FILENO, outbuf, obufcnt);
+       obufcnt = 0;
+}
+
+static void
+prompt()
+{
+
+       putf(LM);
+       if (CO)
+               putchr('\n');
+}
+
+static void
+putf(cp)
+       register char *cp;
+{
+       extern char editedhost[];
+       time_t t;
+       char *slash, db[100];
+
+       while (*cp) {
+               if (*cp != '%') {
+                       putchr(*cp++);
+                       continue;
+               }
+               switch (*++cp) {
+
+               case 't':
+                       slash = strrchr(ttyn, '/');
+                       if (slash == (char *) 0)
+                               puts(ttyn);
+                       else
+                               puts(&slash[1]);
+                       break;
+
+               case 'h':
+                       puts(editedhost);
+                       break;
+
+               case 'd': {
+                       static char fmt[] = "%l:% %P on %A, %d %B %Y";
+
+                       fmt[4] = 'M';           /* I *hate* SCCS... */
+                       (void)time(&t);
+                       (void)strftime(db, sizeof(db), fmt, localtime(&t));
+                       puts(db);
+                       break;
+
+               case 's':
+                       puts(kerninfo.sysname);
+                       break;
+
+               case 'm':
+                       puts(kerninfo.machine);
+                       break;
+
+               case 'r':
+                       puts(kerninfo.release);
+                       break;
+
+               case 'v':
+                       puts(kerninfo.version);
+                       break;
+               }
+
+               case '%':
+                       putchr('%');
+                       break;
+               }
+               cp++;
+       }
+}
diff --git a/getty.tproj/pathnames.h b/getty.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..909042a
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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) 1989, 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.
+ *
+ *     from: @(#)pathnames.h   8.1 (Berkeley) 6/4/93
+ *     $Id: pathnames.h,v 1.1.1.2 2000/01/11 02:10:14 wsanchez Exp $
+ */
+
+#include <paths.h>
+
+#define        _PATH_GETTYTAB  "/etc/gettytab"
+#define        _PATH_LOGIN     "/usr/bin/login"
diff --git a/getty.tproj/subr.c b/getty.tproj/subr.c
new file mode 100644 (file)
index 0000000..d3322b6
--- /dev/null
@@ -0,0 +1,736 @@
+/*
+ * 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) 1983, 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 char sccsid[] = "from: @(#)subr.c     8.1 (Berkeley) 6/4/93";*/
+static char rcsid[] = "$Id: subr.c,v 1.1.1.2 2000/01/11 02:10:15 wsanchez Exp $";
+#endif /* not lint */
+
+/*
+ * Melbourne getty.
+ */
+#define COMPAT_43 1
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "gettytab.h"
+#include "pathnames.h"
+#include "extern.h"
+
+extern struct termios tmode, omode;
+
+static void    compatflags __P((long));
+
+/*
+ * Get a table entry.
+ */
+void
+gettable(name, buf)
+       char *name, *buf;
+{
+       register struct gettystrs *sp;
+       register struct gettynums *np;
+       register struct gettyflags *fp;
+       long n;
+       char *dba[2];
+       dba[0] = _PATH_GETTYTAB;
+       dba[1] = 0;
+
+       if (cgetent(&buf, dba, name) != 0)
+               return;
+
+       for (sp = gettystrs; sp->field; sp++)
+               cgetstr(buf, sp->field, &sp->value);
+       for (np = gettynums; np->field; np++) {
+               if (cgetnum(buf, np->field, &n) == -1)
+                       np->set = 0;
+               else {
+                       np->set = 1;
+                       np->value = n;
+               }
+       }
+       for (fp = gettyflags; fp->field; fp++) {
+               if (cgetcap(buf, fp->field, ':') == NULL)
+                       fp->set = 0;
+               else {
+                       fp->set = 1;
+                       fp->value = 1 ^ fp->invrt;
+               }
+       }
+#ifdef DEBUG
+       printf("name=\"%s\", buf=\"%s\"\n", name, buf);
+       for (sp = gettystrs; sp->field; sp++)
+               printf("cgetstr: %s=%s\n", sp->field, sp->value);
+       for (np = gettynums; np->field; np++)
+               printf("cgetnum: %s=%d\n", np->field, np->value);
+       for (fp = gettyflags; fp->field; fp++)
+               printf("cgetflags: %s='%c' set='%c'\n", fp->field, 
+                      fp->value + '0', fp->set + '0');
+       exit(1);
+#endif /* DEBUG */
+}
+
+void
+gendefaults()
+{
+       register struct gettystrs *sp;
+       register struct gettynums *np;
+       register struct gettyflags *fp;
+
+       for (sp = gettystrs; sp->field; sp++)
+               if (sp->value)
+                       sp->defalt = sp->value;
+       for (np = gettynums; np->field; np++)
+               if (np->set)
+                       np->defalt = np->value;
+       for (fp = gettyflags; fp->field; fp++)
+               if (fp->set)
+                       fp->defalt = fp->value;
+               else
+                       fp->defalt = fp->invrt;
+}
+
+void
+setdefaults()
+{
+       register struct gettystrs *sp;
+       register struct gettynums *np;
+       register struct gettyflags *fp;
+
+       for (sp = gettystrs; sp->field; sp++)
+               if (!sp->value)
+                       sp->value = sp->defalt;
+       for (np = gettynums; np->field; np++)
+               if (!np->set)
+                       np->value = np->defalt;
+       for (fp = gettyflags; fp->field; fp++)
+               if (!fp->set)
+                       fp->value = fp->defalt;
+}
+
+static char **
+charnames[] = {
+       &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
+       &SU, &DS, &RP, &FL, &WE, &LN, 0
+};
+
+static char *
+charvars[] = {
+       &tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
+       &tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
+       &tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
+       &tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
+       &tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
+};
+
+void
+setchars()
+{
+       register int i;
+       register char *p;
+
+       for (i = 0; charnames[i]; i++) {
+               p = *charnames[i];
+               if (p && *p)
+                       *charvars[i] = *p;
+               else
+                       *charvars[i] = _POSIX_VDISABLE;
+       }
+}
+
+void
+setflags(n)
+       int n;
+{
+       register tcflag_t iflag, oflag, cflag, lflag;
+
+#ifdef COMPAT_43
+       switch (n) {
+       case 0:
+               if (F0set) {
+                       compatflags(F0);
+                       return;
+               }
+               break;
+       case 1:
+               if (F1set) {
+                       compatflags(F1);
+                       return;
+               }
+               break;
+       default:
+               if (F2set) {
+                       compatflags(F2);
+                       return;
+               }
+               break;
+       }
+#endif
+
+       switch (n) {
+       case 0:
+               if (C0set && I0set && L0set && O0set) {
+                       tmode.c_cflag = C0;
+                       tmode.c_iflag = I0;
+                       tmode.c_lflag = L0;
+                       tmode.c_oflag = O0;
+                       return;
+               }
+               break;
+       case 1:
+               if (C1set && I1set && L1set && O1set) {
+                       tmode.c_cflag = C1;
+                       tmode.c_iflag = I1;
+                       tmode.c_lflag = L1;
+                       tmode.c_oflag = O1;
+                       return;
+               }
+               break;
+       default:
+               if (C2set && I2set && L2set && O2set) {
+                       tmode.c_cflag = C2;
+                       tmode.c_iflag = I2;
+                       tmode.c_lflag = L2;
+                       tmode.c_oflag = O2;
+                       return;
+               }
+               break;
+       }
+
+#define BIC(v,c)       (v) &= ~(c)
+#define BIS(v,s)       (v) |= (s)
+#define BICS(v,c,s)    BIC(v,c),BIS(v,s)
+
+       iflag = omode.c_iflag;
+       oflag = omode.c_oflag;
+       cflag = omode.c_cflag;
+       lflag = omode.c_lflag;
+
+       if (NP) {
+               BIC(iflag, ISTRIP|INPCK|IGNPAR);
+               BICS(cflag, CSIZE|PARENB|PARODD, CS8);
+       } else if (OP && !EP) {
+               BIS(iflag, ISTRIP|INPCK|IGNPAR);
+               BICS(cflag, CSIZE, PARENB|PARODD|CS7);
+               if (AP)
+                       BIC(iflag, INPCK);
+       } else if (EP && !OP) {
+               BIS(iflag, ISTRIP|INPCK|IGNPAR);
+               BICS(cflag, CSIZE|PARODD, PARENB|CS7);
+               if (AP)
+                       BIC(iflag, INPCK);
+       } else if (AP || EP && OP) {
+               BICS(iflag, INPCK|IGNPAR, ISTRIP);
+               BICS(cflag, CSIZE|PARODD, PARENB|CS7);
+       } /* else, leave as is */
+
+#if 0
+       if (UC)
+               f |= LCASE;
+#endif
+
+       if (HC)
+               cflag |= HUPCL;
+       else
+               cflag &= ~HUPCL;
+
+       if (NL) {
+               iflag |= ICRNL;
+               oflag |= ONLCR;
+       }
+
+#ifdef XXX_DELAY
+       f |= delaybits();
+#endif
+
+       if (n == 1) {           /* read mode flags */
+               if (RW) {
+                       iflag = 0;
+                       oflag = 0;
+                       cflag = CREAD|CS8;
+                       lflag = 0;
+               } else {
+                       lflag &= ~ICANON;
+               }
+               goto out;
+       }
+
+       if (HT)
+               oflag &= ~OXTABS;
+       else
+               oflag |= OXTABS;
+
+       if (n == 0)
+               goto out;
+
+#if 0
+       if (CB)
+               f |= CRTBS;
+#endif
+
+       if (CE)
+               lflag |= ECHOE;
+
+       if (CK)
+               lflag |= ECHOKE;
+
+       if (PE)
+               lflag |= ECHOPRT;
+
+       if (EC)
+               lflag |= ECHO;
+
+       if (XC)
+               lflag |= ECHOCTL;
+
+       if (DX)
+               lflag |= IXANY;
+
+       if (MB)
+               cflag |= MDMBUF;
+       else
+               cflag &= ~MDMBUF;
+
+out:
+       tmode.c_iflag = iflag;
+       tmode.c_oflag = oflag;
+       tmode.c_cflag = cflag;
+       tmode.c_lflag = lflag;
+}
+
+#ifdef COMPAT_43
+/*
+ * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
+ */
+void
+compatflags(flags)
+register long flags;
+{
+       register tcflag_t iflag, oflag, cflag, lflag;
+
+       iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
+       oflag = (OPOST|ONLCR|OXTABS);
+       cflag = (CREAD);
+       lflag = (ICANON|ISIG|IEXTEN);
+
+       if (flags & TANDEM)
+               iflag |= IXOFF;
+       else
+               iflag &= ~IXOFF;
+       if (flags & ECHO)
+               lflag |= ECHO;
+       else
+               lflag &= ~ECHO;
+       if (flags & CRMOD) {
+               iflag |= ICRNL;
+               oflag |= ONLCR;
+       } else {
+               iflag &= ~ICRNL;
+               oflag &= ~ONLCR;
+       }
+       if (flags & XTABS)
+               oflag |= OXTABS;
+       else
+               oflag &= ~OXTABS;
+
+       if (flags & RAW) {
+               iflag &= IXOFF;
+               lflag &= ~(ISIG|ICANON|IEXTEN);
+       } else {
+               iflag |= BRKINT|IXON|IMAXBEL;
+               lflag |= ISIG|IEXTEN;
+               if (flags & CBREAK)
+                       lflag &= ~ICANON;
+               else
+                       lflag |= ICANON;
+       }
+               
+       switch (flags & ANYP) {
+       case EVENP:
+               iflag |= INPCK;
+               cflag &= ~PARODD;
+               break;
+       case ODDP:
+               iflag |= INPCK;
+               cflag |= PARODD;
+               break;
+       default:
+               iflag &= ~INPCK;
+               break;
+       }
+
+       if (flags & (RAW|LITOUT|PASS8)) {
+               cflag &= ~(CSIZE|PARENB);
+               cflag |= CS8;
+               if ((flags & (RAW|PASS8)) == 0)
+                       iflag |= ISTRIP;
+               else
+                       iflag &= ~ISTRIP;
+               if ((flags & (RAW|LITOUT)) == 0)
+                       oflag |= OPOST;
+               else
+                       oflag &= ~OPOST;
+       } else {
+               cflag &= ~CSIZE;
+               cflag |= CS7|PARENB;
+               iflag |= ISTRIP;
+               oflag |= OPOST;
+       }
+
+       if (flags & PRTERA)
+               lflag |= ECHOPRT;
+       else
+               lflag &= ~ECHOPRT;
+       if (flags & CRTERA)
+               lflag |= ECHOE;
+       else
+               lflag &= ~ECHOE;
+       if (flags & MDMBUF)
+               cflag |= MDMBUF;
+       else
+               cflag &= ~MDMBUF;
+       if (flags & NOHANG)
+               cflag &= ~HUPCL;
+       else
+               cflag |= HUPCL;
+       if (flags & CRTKIL)
+               lflag |= ECHOKE;
+       else
+               lflag &= ~ECHOKE;
+       if (flags & CTLECH)
+               lflag |= ECHOCTL;
+       else
+               lflag &= ~ECHOCTL;
+       if ((flags & DECCTQ) == 0)
+               lflag |= IXANY;
+       else
+               lflag &= ~IXANY;
+       lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
+       lflag |= flags & (TOSTOP|FLUSHO|PENDIN|NOFLSH);
+
+       if (flags & (RAW|LITOUT|PASS8)) {
+               cflag &= ~(CSIZE|PARENB);
+               cflag |= CS8;
+               if ((flags & (RAW|PASS8)) == 0)
+                       iflag |= ISTRIP;
+               else
+                       iflag &= ~ISTRIP;
+               if ((flags & (RAW|LITOUT)) == 0)
+                       oflag |= OPOST;
+               else
+                       oflag &= ~OPOST;
+       } else {
+               cflag &= ~CSIZE;
+               cflag |= CS7|PARENB;
+               iflag |= ISTRIP;
+               oflag |= OPOST;
+       }
+
+       tmode.c_iflag = iflag;
+       tmode.c_oflag = oflag;
+       tmode.c_cflag = cflag;
+       tmode.c_lflag = lflag;
+}
+#endif
+
+#ifdef XXX_DELAY
+struct delayval {
+       unsigned        delay;          /* delay in ms */
+       int             bits;
+};
+
+/*
+ * below are random guesses, I can't be bothered checking
+ */
+
+struct delayval        crdelay[] = {
+       { 1,            CR1 },
+       { 2,            CR2 },
+       { 3,            CR3 },
+       { 83,           CR1 },
+       { 166,          CR2 },
+       { 0,            CR3 },
+};
+
+struct delayval nldelay[] = {
+       { 1,            NL1 },          /* special, calculated */
+       { 2,            NL2 },
+       { 3,            NL3 },
+       { 100,          NL2 },
+       { 0,            NL3 },
+};
+
+struct delayval        bsdelay[] = {
+       { 1,            BS1 },
+       { 0,            0 },
+};
+
+struct delayval        ffdelay[] = {
+       { 1,            FF1 },
+       { 1750,         FF1 },
+       { 0,            FF1 },
+};
+
+struct delayval        tbdelay[] = {
+       { 1,             TAB1 },
+       { 2,             TAB2 },
+       { 3,            XTABS },        /* this is expand tabs */
+       { 100,           TAB1 },
+       { 0,             TAB2 },
+};
+
+int
+delaybits()
+{
+       register int f;
+
+       f  = adelay(CD, crdelay);
+       f |= adelay(ND, nldelay);
+       f |= adelay(FD, ffdelay);
+       f |= adelay(TD, tbdelay);
+       f |= adelay(BD, bsdelay);
+       return (f);
+}
+
+int
+adelay(ms, dp)
+       register ms;
+       register struct delayval *dp;
+{
+       if (ms == 0)
+               return (0);
+       while (dp->delay && ms > dp->delay)
+               dp++;
+       return (dp->bits);
+}
+#endif
+
+char   editedhost[32];
+
+void
+edithost(pat)
+       register char *pat;
+{
+       register char *host = HN;
+       register char *res = editedhost;
+
+       if (!pat)
+               pat = "";
+       while (*pat) {
+               switch (*pat) {
+
+               case '#':
+                       if (*host)
+                               host++;
+                       break;
+
+               case '@':
+                       if (*host)
+                               *res++ = *host++;
+                       break;
+
+               default:
+                       *res++ = *pat;
+                       break;
+
+               }
+               if (res == &editedhost[sizeof editedhost - 1]) {
+                       *res = '\0';
+                       return;
+               }
+               pat++;
+       }
+       if (*host)
+               strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
+       else
+               *res = '\0';
+       editedhost[sizeof editedhost - 1] = '\0';
+}
+
+void
+makeenv(env)
+       char *env[];
+{
+       static char termbuf[128] = "TERM=";
+       register char *p, *q;
+       register char **ep;
+
+       ep = env;
+       if (TT && *TT) {
+               strcat(termbuf, TT);
+               *ep++ = termbuf;
+       }
+       if (p = EV) {
+               q = p;
+               while (q = strchr(q, ',')) {
+                       *q++ = '\0';
+                       *ep++ = p;
+                       p = q;
+               }
+               if (*p)
+                       *ep++ = p;
+       }
+       *ep = (char *)0;
+}
+
+/*
+ * This speed select mechanism is written for the Develcon DATASWITCH.
+ * The Develcon sends a string of the form "B{speed}\n" at a predefined
+ * baud rate. This string indicates the user's actual speed.
+ * The routine below returns the terminal type mapped from derived speed.
+ */
+struct portselect {
+       char    *ps_baud;
+       char    *ps_type;
+} portspeeds[] = {
+       { "B110",       "std.110" },
+       { "B134",       "std.134" },
+       { "B150",       "std.150" },
+       { "B300",       "std.300" },
+       { "B600",       "std.600" },
+       { "B1200",      "std.1200" },
+       { "B2400",      "std.2400" },
+       { "B4800",      "std.4800" },
+       { "B9600",      "std.9600" },
+       { "B19200",     "std.19200" },
+       { 0 }
+};
+
+char *
+portselector()
+{
+       char c, baud[20], *type = "default";
+       register struct portselect *ps;
+       int len;
+
+       alarm(5*60);
+       for (len = 0; len < sizeof (baud) - 1; len++) {
+               if (read(STDIN_FILENO, &c, 1) <= 0)
+                       break;
+               c &= 0177;
+               if (c == '\n' || c == '\r')
+                       break;
+               if (c == 'B')
+                       len = 0;        /* in case of leading garbage */
+               baud[len] = c;
+       }
+       baud[len] = '\0';
+       for (ps = portspeeds; ps->ps_baud; ps++)
+               if (strcmp(ps->ps_baud, baud) == 0) {
+                       type = ps->ps_type;
+                       break;
+               }
+       sleep(2);       /* wait for connection to complete */
+       return (type);
+}
+
+/*
+ * This auto-baud speed select mechanism is written for the Micom 600
+ * portselector. Selection is done by looking at how the character '\r'
+ * is garbled at the different speeds.
+ */
+#include <sys/time.h>
+
+char *
+autobaud()
+{
+       int rfds;
+       struct timeval timeout;
+       char c, *type = "9600-baud";
+       int null = 0;
+
+       ioctl(0, TIOCFLUSH, &null);
+       rfds = 1 << 0;
+       timeout.tv_sec = 5;
+       timeout.tv_usec = 0;
+       if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
+           (fd_set *)NULL, &timeout) <= 0)
+               return (type);
+       if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
+               return (type);
+       timeout.tv_sec = 0;
+       timeout.tv_usec = 20;
+       (void) select(32, (fd_set *)NULL, (fd_set *)NULL,
+           (fd_set *)NULL, &timeout);
+       ioctl(0, TIOCFLUSH, &null);
+       switch (c & 0377) {
+
+       case 0200:              /* 300-baud */
+               type = "300-baud";
+               break;
+
+       case 0346:              /* 1200-baud */
+               type = "1200-baud";
+               break;
+
+       case  015:              /* 2400-baud */
+       case 0215:
+               type = "2400-baud";
+               break;
+
+       default:                /* 4800-baud */
+               type = "4800-baud";
+               break;
+
+       case 0377:              /* 9600-baud */
+               type = "9600-baud";
+               break;
+       }
+       return (type);
+}
diff --git a/getty.tproj/ttys.5 b/getty.tproj/ttys.5
new file mode 100644 (file)
index 0000000..b2f6584
--- /dev/null
@@ -0,0 +1,153 @@
+.\" Copyright (c) 1985, 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.
+.\"
+.\"     from: @(#)ttys.5       8.1 (Berkeley) 6/4/93
+.\"    $Id: ttys.5,v 1.1.1.1 1999/05/02 04:21:29 wsanchez Exp $
+.\"
+.Dd June 4, 1993
+.Dt TTYS 5
+.Os
+.Sh NAME
+.Nm ttys
+.Nd terminal initialization information
+.Sh DESCRIPTION
+The file
+.Nm ttys
+contains information that is used by various routines to initialize
+and control the use of terminal special files.
+This information is read with the
+.Xr getttyent 3
+library routines.
+There is one line in the 
+.Nm ttys
+file per special device file.
+Fields are separated by tabs and/or spaces.
+Fields comprised of more than one word should be enclosed in double
+quotes (``"'').
+Blank lines and comments may appear anywhere in the file; comments
+are delimited by hash marks (``#'') and new lines.
+Any unspecified fields will default to null.
+.Pp
+The first field is the
+name of the terminal special file as it is found in
+.Pa /dev .
+.Pp
+The second field of the file is the command to execute for the line,
+usually
+.Xr getty 8 ,
+which initializes and opens the line, setting the speed, waiting for
+a user name and executing the
+.Xr login 1
+program.
+It can be, however, any desired command, for example
+the start up for a window system terminal emulator or some other
+daemon process, and can contain multiple words if quoted.
+.Pp
+The third field is the type of terminal usually connected to that
+tty line, normally the one found in the
+.Xr termcap 5
+data base file.
+The environment variable
+.Dv TERM
+is initialized with the value by
+either
+.Xr getty 8
+or
+.Xr login 1 .
+.Pp
+The remaining fields set flags in the
+.Fa ty_status
+entry (see
+.Xr getttyent 3 )
+or specify a window system process that
+.Xr init 8
+will maintain for the terminal line.
+.Pp
+As flag values, the strings ``on'' and ``off'' specify that
+.Xr init
+should (should not) execute the command given in the second field,
+while ``secure'' (if ``on'' is also specified) allows users with a
+uid of 0 to login on
+this line.
+The flags ``local'', ``rtscts'', ``mdmbuf'', and ``softcar''
+modify the default behaviour of the terminal line, and their actions
+are driver dependent.
+The ``local'' flag causes the driver to
+treat the line as if it locally connected.
+The ``rtscts'' flag
+instructs the driver to use RTS/CTS hardware flow control, if
+possible.
+The ``mdmbuf'' flag instructs the driver to use
+DTR/DCD flow control, if possible.
+The ``softcar'' flag causes the driver to ignore
+hardware carrier on the line.
+These flag fields should not be quoted.
+.Pp
+The string ``window='' may be followed by a quoted command
+string which
+.Xr init
+will execute
+.Em before
+starting the command specified by the second field.
+.Sh EXAMPLES
+.Bd -literal
+# root login on console at 1200 baud
+console        "/usr/libexec/getty std.1200"   vt100   on secure
+# dialup at 1200 baud, no root logins
+ttyd0  "/usr/libexec/getty d1200"      dialup  on      # 555-1234
+# Mike's terminal: hp2621
+ttyh0  "/usr/libexec/getty std.9600"   hp2621-nl       on      # 457 Evans
+# John's terminal: vt100
+ttyh1  "/usr/libexec/getty std.9600"   vt100   on              # 459 Evans
+# terminal emulate/window system
+ttyv0  "/usr/new/xterm -L :0"          vs100   on window="/usr/new/Xvs100 0"
+# Network pseudo ttys -- don't enable getty
+ttyp0  none    network
+ttyp1  none    network off
+.Ed
+.Sh FILES
+.Bl -tag -width /etc/ttys -compact
+.It Pa /etc/ttys
+.El
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr getttyent 3 ,
+.Xr ttyslot 3 ,
+.Xr gettytab 5 ,
+.Xr termcap 5 ,
+.Xr getty 8 ,
+.Xr init 8 ,
+.Xr ttyflags 8
+.Sh HISTORY
+A
+.Nm
+file appeared in
+.At v6 .
diff --git a/halt.tproj/Makefile b/halt.tproj/Makefile
new file mode 100644 (file)
index 0000000..a731515
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = halt
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = halt.c
+
+OTHERSRCS = Makefile.preamble Makefile halt.8 Makefile.dist
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/halt.tproj/Makefile.dist b/halt.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..52b2af8
--- /dev/null
@@ -0,0 +1,9 @@
+#      from: @(#)Makefile      5.3 (Berkeley) 5/11/90
+#      $Id: Makefile.dist,v 1.1.1.1 1999/05/02 04:21:30 wsanchez Exp $
+
+PROG=  halt
+MAN8=  halt.0
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+
+.include <bsd.prog.mk>
diff --git a/halt.tproj/Makefile.preamble b/halt.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..b7b38d0
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/halt.tproj/PB.project b/halt.tproj/PB.project
new file mode 100644 (file)
index 0000000..0ceaecf
--- /dev/null
@@ -0,0 +1,37 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (halt.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, halt.8, Makefile.dist); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = halt; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/halt.tproj/halt.8 b/halt.tproj/halt.8
new file mode 100644 (file)
index 0000000..a6e5726
--- /dev/null
@@ -0,0 +1,86 @@
+.\" Copyright (c) 1980, 1991 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: @(#)halt.8       6.5 (Berkeley) 3/16/91
+.\"    $Id: halt.8,v 1.1.1.1 1999/05/02 04:21:30 wsanchez Exp $
+.\"
+.Dd March 16, 1991
+.Dt HALT 8
+.Os BSD 4
+.Sh NAME
+.Nm halt
+.Nd stop the processor
+.Sh SYNOPSIS
+.Nm halt
+.Op Fl n
+.Op Fl q
+.Op Fl y
+.Sh DESCRIPTION
+.Nm Halt
+writes out sandbagged information to the disks and then stops
+the processor.  The machine does not reboot, even if the auto-reboot
+switch is set on the console.
+.Pp
+Available options for
+.Nm halt :
+.Bl -tag -width Ds
+.It Fl n
+No sync before stopping.
+.It Fl q
+Quick halt, no graceful shutdown is attempted.
+.It Fl y
+This option is needed if you are trying to halt the system from a dialup.
+.El
+.Pp
+.Nm Halt
+normally logs the shutdown using
+.Xr syslog 8
+and places a shutdown record in the login accounting file
+.Pa /var/log/wtmp.
+These actions are inhibited if the
+.Fl n
+or
+.Fl q
+options are present.
+.Sh SEE ALSO
+.Xr reboot 8 ,
+.Xr shutdown 8 ,
+.Xr syslogd 8
+.Sh BUGS
+It is very difficult to halt a
+.Tn VAX ,
+as the machine wants to then
+reboot itself.  A rather tight loop suffices.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/halt.tproj/halt.c b/halt.tproj/halt.c
new file mode 100644 (file)
index 0000000..8bfd21b
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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) 1980, 1986 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
+char copyright[] =
+"@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+/*static char sccsid[] = "from: @(#)halt.c     5.10 (Berkeley) 4/3/91";*/
+static char rcsid[] = "$Id: halt.c,v 1.1.1.2 2000/01/11 02:10:15 wsanchez Exp $";
+#endif /* not lint */
+
+/*
+ * Halt
+ */
+#include <sys/types.h>
+#include <sys/reboot.h>
+#include <sys/time.h>
+#include <sys/syslog.h>
+#include <sys/signal.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <paths.h>
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       register int i;
+       register int qflag = 0;
+       struct passwd *pw;
+       int ch, howto, needlog = 1;
+       char *user, *ttyn, *getlogin(), *ttyname();
+
+       howto = RB_HALT;
+       ttyn = ttyname(2);
+       while ((ch = getopt(argc, argv, "lnqy")) != EOF)
+               switch((char)ch) {
+               case 'l':               /* undocumented; for shutdown(8) */
+                       needlog = 0;
+                       break;
+               case 'n':
+                       howto |= RB_NOSYNC;
+                       break;
+               case 'q':
+                       qflag++;
+                       break;
+               case 'y':
+                       ttyn = 0;
+                       break;
+               case '?':
+               default:
+                       fprintf(stderr, "usage: halt [-nqy]\n");
+                       exit(1);
+               }
+
+       if (ttyn && ttyn[sizeof(_PATH_TTY) - 1] == 'd') {
+               fprintf(stderr, "halt: dangerous on a dialup; use ``halt -y'' if you are really sure\n");
+               exit(1);
+       }
+
+       if (needlog) {
+               openlog("halt", 0, LOG_AUTH);
+               if ((user = getlogin()) == NULL)
+                       if ((pw = getpwuid(getuid())))
+                               user = pw->pw_name;
+                       else
+                               user = "???";
+               syslog(LOG_CRIT, "halted by %s", user);
+       }
+
+       signal(SIGHUP, SIG_IGN);                /* for network connections */
+       if (kill(1, SIGTSTP) == -1) {
+               fprintf(stderr, "halt: can't idle init\n");
+               exit(1);
+       }
+#if 0
+       sleep(1);
+       (void) kill(-1, SIGTERM);       /* one chance to catch it */
+       sleep(5);
+
+       if (!qflag) for (i = 1; ; i++) {
+               if (kill(-1, SIGKILL) == -1) {
+                       extern int errno;
+
+                       if (errno == ESRCH)
+                               break;
+
+                       perror("halt: kill");
+                       kill(1, SIGHUP);
+                       exit(1);
+               }
+               if (i > 5) {
+                       fprintf(stderr,
+                           "CAUTION: some process(es) wouldn't die\n");
+                       break;
+               }
+               setalarm(2 * i);
+               pause();
+       }
+       if (!qflag && (howto & RB_NOSYNC) == 0) {
+               logwtmp("~", "shutdown", "");
+               sync();
+               setalarm(5);
+               pause();
+       }
+#endif
+       reboot(howto);
+       perror("halt");
+}
+
+void
+dingdong()
+{
+       /* RRRIIINNNGGG RRRIIINNNGGG */
+}
+
+setalarm(n)
+       int n;
+{
+       signal(SIGALRM, dingdong);
+       alarm(n);
+}
diff --git a/hostinfo.tproj/Makefile b/hostinfo.tproj/Makefile
new file mode 100644 (file)
index 0000000..07060a4
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = hostinfo
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = hostinfo.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/hostinfo.tproj/Makefile.postamble b/hostinfo.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..36381d4
--- /dev/null
@@ -0,0 +1,122 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
diff --git a/hostinfo.tproj/Makefile.preamble b/hostinfo.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/hostinfo.tproj/PB.project b/hostinfo.tproj/PB.project
new file mode 100644 (file)
index 0000000..8520b11
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (hostinfo.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = hostinfo; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/hostinfo.tproj/hostinfo.c b/hostinfo.tproj/hostinfo.c
new file mode 100644 (file)
index 0000000..ee9b6dc
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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@
+ */
+/* 
+ * Mach Operating System
+ * Copyright (c) 1990 Carnegie-Mellon University
+ * All rights reserved.  The CMU software License Agreement specifies
+ * the terms and conditions for use and redistribution.
+ */
+/*
+ *     File:   hostinfo.c
+ *     Author: Avadis Tevanian, Jr.
+ *
+ *     Copyright (C) 1987, Avadis Tevanian, Jr.
+ *
+ *     Display information about the host this program is
+ *     execting on.
+ */
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/bootstrap.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+struct host_basic_info hi;
+kernel_version_t       version;
+int                    slots[1024];
+
+int main(int argc, char *argv[])
+{
+       kern_return_t           ret;
+       int                     size;
+       char                    *cpu_name, *cpu_subname;
+       int                     i, count;
+       processor_set_name_port_t               default_pset;
+       host_name_port_t                        host;
+       struct processor_set_basic_info basic_info;
+       struct processor_set_load_info  load_info;
+
+       host = mach_host_self();
+       ret = host_kernel_version(host, version);
+       if (ret != KERN_SUCCESS) {
+               mach_error(argv[0], ret);
+                exit(EXIT_FAILURE);
+       }
+       printf("Mach kernel version:\n\t %s\n", version);
+       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);
+       }
+
+       ret = processor_set_default(host, &default_pset);
+       if (ret != KERN_SUCCESS) {
+               mach_error(argv[0], ret);
+                exit(EXIT_FAILURE);
+       }
+
+       count = PROCESSOR_SET_BASIC_INFO_COUNT;
+       ret = processor_set_info(default_pset, PROCESSOR_SET_BASIC_INFO,
+               &host, (processor_set_info_t)&basic_info, &count);
+       if (ret != KERN_SUCCESS) {
+               mach_error(argv[0], ret);
+                exit(EXIT_FAILURE);
+       }
+
+       count = PROCESSOR_SET_LOAD_INFO_COUNT;
+       ret = processor_set_statistics(default_pset, PROCESSOR_SET_LOAD_INFO,
+               (processor_set_info_t)&load_info, &count);
+       if (ret != KERN_SUCCESS) {
+               mach_error(argv[0], ret);
+                exit(EXIT_FAILURE);
+       }
+       if (hi.max_cpus > 1)
+               printf("Kernel configured for up to %d processors.\n",
+                       hi.max_cpus);
+       else
+               printf("Kernel configured for a single processor only.\n");
+       printf("%d processor%s physically available.\n", hi.avail_cpus,
+               (hi.avail_cpus > 1) ? "s are" : " is");
+
+       printf("Processor type:");
+       slot_name(hi.cpu_type, hi.cpu_subtype, &cpu_name, &cpu_subname);
+       printf(" %s (%s)\n", cpu_name, cpu_subname);
+
+       printf("Processor%s active:", (hi.avail_cpus > 1) ? "s" : "");
+       for (i = 0; i < hi.avail_cpus; i++) 
+               printf(" %d", i);
+       printf("\n");
+
+       printf("Primary memory available: %.2f megabytes.\n",
+                       (float)hi.memory_size/(1024.0*1024.0));
+       printf("Default processor set: %d tasks, %d threads, %d processors\n",
+               load_info.task_count, load_info.thread_count, basic_info.processor_count);
+       printf("Load average: %d.%02d, Mach factor: %d.%02d\n",
+               load_info.load_average/LOAD_SCALE,
+               (load_info.load_average%LOAD_SCALE)/10,
+               load_info.mach_factor/LOAD_SCALE,
+               (load_info.mach_factor%LOAD_SCALE)/10);
+}
+
diff --git a/init.tproj/Makefile b/init.tproj/Makefile
new file mode 100644 (file)
index 0000000..1f5b5d9
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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 = init
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = init.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            NOTES init.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/init.tproj/Makefile.dist b/init.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..1a796a1
--- /dev/null
@@ -0,0 +1,11 @@
+#      @(#)Makefile    8.1 (Berkeley) 7/19/93
+
+PROG=  init
+MAN8=  init.0
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+BINMODE=500
+INSTALLFLAGS=-fschg
+CFLAGS+=-DDEBUGSHELL -DSECURE
+
+.include <bsd.prog.mk>
diff --git a/init.tproj/Makefile.postamble b/init.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..2929636
--- /dev/null
@@ -0,0 +1,5 @@
+INSTALL_PERMISSIONS = 500  # If set, 'install' chmod's executable to this
+#CHFLAGS = /usr/bin/chflags
+#after_install::
+#      $(CHFLAGS) schg  $(DSTROOT)$(INSTALLDIR)/$(NAME)
+
diff --git a/init.tproj/Makefile.preamble b/init.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..3ab1a1d
--- /dev/null
@@ -0,0 +1,4 @@
+# can be added to Compiler Flags to provide Secure login
+# -DSECURE  LIBS = -lutil   
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/init.tproj/NOTES b/init.tproj/NOTES
new file mode 100644 (file)
index 0000000..bf75101
--- /dev/null
@@ -0,0 +1,112 @@
+POSIX and init:
+--------------
+
+POSIX.1 does not define 'init' but it mentions it in a few places.
+
+B.2.2.2, p205 line 873:
+
+       This is part of the extensive 'job control' glossary entry.
+       This specific reference says that 'init' must by default provide
+       protection from job control signals to jobs it starts --
+       it sets SIGTSTP, SIGTTIN and SIGTTOU to SIG_IGN.
+
+B.2.2.2, p206 line 889:
+
+       Here is a reference to 'vhangup'.  It says, 'POSIX.1 does
+       not specify how controlling terminal access is affected by
+       a user logging out (that is, by a controlling process
+       terminating).'  vhangup() is recognized as one way to handle
+       the problem.  I'm not clear what happens in Reno; I have
+       the impression that when the controlling process terminates,
+       references to the controlling terminal are converted to
+       references to a 'dead' vnode.  I don't know whether vhangup()
+       is required.
+
+B.2.2.2, p206 line 921:
+
+       Orphaned process groups bear indirectly on this issue.  A
+       session leader's process group is considered to be orphaned;
+       that is, it's immune to job control signals from the terminal.
+
+B.2.2.2, p233 line 2055:
+
+       'Historically, the implementation-dependent process that
+       inherits children whose parents have terminated without
+       waiting on them is called "init" and has a process ID of 1.'
+
+       It goes on to note that it used to be the case that 'init'
+       was responsible for sending SIGHUP to the foreground process
+       group of a tty whose controlling process has exited, using
+       vhangup().  It is now the responsibility of the kernel to
+       do this when the controlling process calls _exit().  The
+       kernel is also responsible for sending SIGCONT to stopped
+       process groups that become orphaned.  This is like old BSD
+       but entire process groups are signaled instead of individual
+       processes.
+
+       In general it appears that the kernel now automatically
+       takes care of orphans, relieving 'init' of any responsibility.
+       Specifics are listed on the _exit() page (p50).
+
+On setsid():
+-----------
+
+It appears that neither getty nor login call setsid(), so init must
+do this -- seems reasonable.  B.4.3.2 p 248 implies that this is the
+way that 'init' should work; it says that setsid() should be called
+after forking.
+
+Process group leaders cannot call setsid() -- another reason to
+fork!  Of course setsid() causes the current process to become a
+process group leader, so we can only call setsid() once.  Note that
+the controlling terminal acquires the session leader's process
+group when opened.
+
+Controlling terminals:
+---------------------
+
+B.7.1.1.3 p276: 'POSIX.1 does not specify a mechanism by which to
+allocate a controlling terminal.  This is normally done by a system
+utility (such as 'getty') and is considered ... outside the scope
+of POSIX.1.'  It goes on to say that historically the first open()
+of a tty in a session sets the controlling terminal.  P130 has the
+full details; nothing particularly surprising.
+
+The glossary p12 describes a 'controlling process' as the first
+process in a session that acquires a controlling terminal.  Access
+to the terminal from the session is revoked if the controlling
+process exits (see p50, in the discussion of process termination).
+
+Design notes:
+------------
+
+your generic finite state machine
+we are fascist about which signals we elect to receive,
+       even signals purportedly generated by hardware
+handle fatal errors gracefully if possible (we reboot if we goof!!)
+       if we get a segmentation fault etc., print a message on the console
+       and spin for a while before rebooting
+       (this at least decreases the amount of paper consumed :-)
+apply hysteresis to rapidly exiting gettys
+check wait status of children we reap
+       don't wait for stopped children
+don't use SIGCHILD, it's too expensive
+       but it may close windows and avoid races, sigh
+look for EINTR in case we need to change state
+init is responsible for utmp and wtmp maintenance (ick)
+       maybe now we can consider replacements?  maintain them in parallel
+       init only removes utmp and closes out wtmp entries...
+
+necessary states and state transitions (gleaned from the man page):
+       1: single user shell (with password checking?); on exit, go to 2
+       2: rc script: on exit 0, go to 3; on exit N (error), go to 1
+       3: read ttys file: on completion, go to 4
+       4: multi-user operation: on SIGTERM, go to 7; on SIGHUP, go to 5;
+               on SIGTSTP, go to 6
+       5: clean up mode (re-read ttys file, killing off controlling processes
+               on lines that are now 'off', starting them on lines newly 'on')
+               on completion, go to 4
+       6: boring mode (no new sessions); signals as in 4
+       7: death: send SIGHUP to all controlling processes, reap for 30 seconds,
+               then go to 1 (warn if not all processes died, i.e. wait blocks)
+Given the -s flag, we start at state 1; otherwise state 2
diff --git a/init.tproj/PB.project b/init.tproj/PB.project
new file mode 100644 (file)
index 0000000..426d3b6
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (init.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, NOTES, init.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-traditional-cpp"; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = init; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = init; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = init; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = init; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/init.tproj/init.8 b/init.tproj/init.8
new file mode 100644 (file)
index 0000000..8db766d
--- /dev/null
@@ -0,0 +1,295 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley at Berkeley Software Design, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 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.
+.\"
+.\"     @(#)init.8     8.6 (Berkeley) 5/26/95
+.\"
+.Dd May 26, 1995
+.Dt INIT 8
+.Os BSD 4
+.Sh NAME
+.Nm init
+.Nd process control initialization
+.Sh SYNOPSIS
+.Nm init
+.Sh DESCRIPTION
+The
+.Nm init
+program
+is the last stage of the boot process.
+It normally runs the automatic reboot sequence as described in
+.Xr reboot 8 ,
+and if this succeeds, begins multi-user operation.
+If the reboot scripts fail,
+.Nm init
+commences single user operation by giving
+the super-user a shell on the console.
+The
+.Nm init
+program may be passed parameters
+from the boot program to
+prevent the system from going multi-user and to instead execute
+a single user shell without starting the normal daemons.
+The system is then quiescent for maintenance work and may
+later be made to go to multi-user by exiting the
+single-user shell (with ^D).
+This
+causes
+.Nm init
+to run the
+.Pa /etc/rc
+start up command file in fastboot mode (skipping disk checks).
+.Pp
+If the
+.Nm console
+entry in the
+.Xr ttys 5
+file is marked ``insecure'',
+then
+.Nm init
+will require that the superuser password be
+entered before the system will start a single-user shell.
+The password check is skipped if the 
+.Nm console
+is marked as ``secure''.
+.Pp
+The kernel runs with four different levels of security.
+Any superuser process can raise the security level, but only 
+.Nm init
+can lower it.
+Security levels are defined as follows:
+.Bl -tag -width flag
+.It Ic -1
+Permanently insecure mode \- always run system in level 0 mode.
+.It Ic 0
+Insecure mode \- immutable and append-only flags may be turned off.
+All devices may be read or written subject to their permissions.
+.It Ic 1
+Secure mode \- immutable and append-only flags may not be changed;
+disks for mounted filesystems,
+.Pa /dev/mem ,
+and
+.Pa /dev/kmem
+are read-only.
+The
+.Xr settimeofday 2
+system call can only advance the time.
+.It Ic 2
+Highly secure mode \- same as secure mode, plus disks are always
+read-only whether mounted or not.
+This level precludes tampering with filesystems by unmounting them,
+but also inhibits running
+.Xr newfs 8
+while the system is multi-user.
+.El
+.Pp
+Normally, the system runs in level 0 mode while single user
+and in level 1 mode while multiuser.
+If the level 2 mode is desired while running multiuser,
+it can be set in the startup script
+.Pa /etc/rc
+using
+.Xr sysctl 8 .
+If it is desired to run the system in level 0 mode while multiuser,
+the administrator must build a kernel with the variable
+.Nm securelevel
+defined in the file
+.Pa /sys/compile/MACHINE/param.c
+and initialize it to -1.
+.Pp
+In multi-user operation, 
+.Nm init
+maintains
+processes for the terminal ports found in the file
+.Xr ttys 5 .
+.Nm Init
+reads this file, and executes the command found in the second field.
+This command is usually
+.Xr getty 8 ;
+.Xr getty
+opens and initializes the tty line
+and
+executes the
+.Xr login
+program.
+The
+.Xr login
+program, when a valid user logs in,
+executes a shell for that user.  When this shell
+dies, either because the user logged out
+or an abnormal termination occurred (a signal),
+the
+.Nm init
+program wakes up, deletes the user
+from the
+.Xr utmp 5
+file of current users and records the logout in the
+.Xr wtmp
+file.
+The cycle is
+then restarted by
+.Nm init
+executing a new
+.Xr getty
+for the line.
+.pl +1
+.Pp
+Line status (on, off, secure, getty, or window information)
+may be changed in the
+.Xr ttys
+file without a reboot by sending the signal
+.Dv SIGHUP
+to
+.Nm init
+with the command
+.Dq Li "kill \-s HUP 1" .
+On receipt of this signal,
+.Nm init
+re-reads the
+.Xr ttys
+file.
+When a line is turned off in
+.Xr ttys ,
+.Nm init
+will send a SIGHUP signal to the controlling process
+for the session associated with the line.
+For any lines that were previously turned off in the
+.Xr ttys
+file and are now on,
+.Nm init
+executes a new
+.Xr getty
+to enable a new login.
+If the getty or window field for a line is changed,
+the change takes effect at the end of the current
+login session (e.g., the next time 
+.Nm init
+starts a process on the line).
+If a line is commented out or deleted from
+.Xr ttys ,
+.Nm init
+will not do anything at all to that line.
+However, it will complain that the relationship between lines
+in the
+.Xr ttys
+file and records in the
+.Xr utmp
+file is out of sync,
+so this practice is not recommended.
+.Pp
+.Nm Init
+will terminate multi-user operations and resume single-user mode
+if sent a terminate
+.Pq Dv TERM
+signal, for example,
+.Dq Li "kill \-s TERM 1" .
+If there are processes outstanding that are deadlocked (because of
+hardware or software failure),
+.Xr init
+will not wait for them all to die (which might take forever), but
+will time out after 30 seconds and print a warning message.
+.Pp
+.Nm Init
+will cease creating new
+.Xr getty Ns 's
+and allow the system to slowly die away, if it is sent a terminal stop
+.Pq Dv TSTP
+signal, i.e.
+.Dq Li "kill \-s TSTP 1" .
+A later hangup will resume full
+multi-user operations, or a terminate will start a single user shell.
+This hook is used by
+.Xr reboot 8
+and
+.Xr halt 8 .
+.Pp
+The role of
+.Nm init
+is so critical that if it dies, the system will reboot itself
+automatically.
+If, at bootstrap time, the
+.Xr init
+process cannot be located, the system will panic with the message
+``panic: "init died (signal %d, exit %d)''.
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "getty repeating too quickly on port %s, sleeping"
+A process being started to service a line is exiting quickly
+each time it is started.
+This is often caused by a ringing or noisy terminal line.
+.Em "Init will sleep for 10 seconds" ,
+.Em "then continue trying to start the process" .
+.Pp
+.It "some processes would not die; ps axl advised."
+A process
+is hung and could not be killed when the system was shutting down.
+This condition is usually caused by a process
+that is stuck in a device driver because of
+a persistent device error condition.
+.El
+.Sh FILES
+.Bl -tag -width /var/log/wtmp -compact
+.It Pa /dev/console
+System console device.
+.It Pa /dev/tty*
+Terminal ports found in
+.Xr ttys .
+.It Pa /var/run/utmp
+Record of Current users on the system.
+.It Pa /var/log/wtmp
+Record of all logins and logouts.
+.It Pa /etc/ttys
+The terminal initialization information file.
+.It Pa /etc/rc
+System startup commands.
+.El
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr kill 1 ,
+.Xr sh 1 ,
+.Xr ttys 5 ,
+.Xr crash 8 ,
+.Xr getty 8 ,
+.Xr rc 8 ,
+.Xr reboot 8 ,
+.Xr halt 8 ,
+.Xr shutdown 8
+.Sh HISTORY
+A
+.Nm
+command appeared in
+.At v6 .
+.Sh BUGS
+Systems without
+.Xr sysctl
+behave as though they have security level \-1.
diff --git a/init.tproj/init.c b/init.tproj/init.c
new file mode 100644 (file)
index 0000000..a44eb7a
--- /dev/null
@@ -0,0 +1,1598 @@
+/*
+ * 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) 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <ttyent.h>
+#include <unistd.h>
+#include <paths.h>
+
+#include <stdarg.h>
+
+#ifdef SECURE
+#include <pwd.h>
+#endif
+
+#include "pathnames.h"
+
+/*
+ * Until the mythical util.h arrives...
+ */
+extern int login_tty __P((int));
+extern int logout __P((const char *));
+extern void logwtmp __P((const char *, const char *, const char *));
+
+/*
+ * Sleep times; used to prevent thrashing.
+ */
+#define        GETTY_SPACING            5      /* N secs minimum getty spacing */
+#define        GETTY_SLEEP             30      /* sleep N secs after spacing problem */
+#define        WINDOW_WAIT              3      /* wait N secs after starting window */
+#define        STALL_TIMEOUT           30      /* wait N secs after warning */
+#define        DEATH_WATCH             10      /* wait N secs for procs to die */
+#define FAILED_HW_PASS          5      /* wait N secs before croaking user */
+
+void handle __P((sig_t, ...));
+void delset __P((sigset_t *, ...));
+
+void stall __P((char *, ...));
+void warning __P((char *, ...));
+void emergency __P((char *, ...));
+void disaster __P((int));
+void badsys __P((int));
+
+/*
+ * We really need a recursive typedef...
+ * The following at least guarantees that the return type of (*state_t)()
+ * is sufficiently wide to hold a function pointer.
+ */
+typedef long (*state_func_t) __P((void));
+typedef state_func_t (*state_t) __P((void));
+
+state_func_t single_user __P((void));
+state_func_t runcom __P((void));
+state_func_t read_ttys __P((void));
+state_func_t multi_user __P((void));
+state_func_t clean_ttys __P((void));
+state_func_t catatonia __P((void));
+state_func_t death __P((void));
+
+enum { AUTOBOOT, FASTBOOT, BOOT_SCRIPT } runcom_mode = AUTOBOOT;
+int runcom_boot = 1;   /* Run the rc.boot script */
+int runcom_verbose = 0;
+int runcom_safe = 0;
+
+void transition __P((state_t));
+state_t requested_transition = runcom;
+
+void setctty __P((char *, int));
+
+
+// gvdl@next.com 14 Aug 1995
+//   - from ~apps/loginwindow_proj/loginwindow/common.h
+#define REALLY_EXIT_TO_CONSOLE                  229
+
+// From old init.c
+// These flags are used in the se_flags field of the init_session structure
+#define        SE_SHUTDOWN     0x1             /* session won't be restarted */
+
+// The flags below control what sort of getty is launched.
+#define SE_GETTY_LAUNCH        0x30    /* What type of getty to launch */ 
+#define SE_COMMON      0x00    /* Usual command that is run - getty */
+#define SE_ONERROR     0x10    /* Command to run if error condition occurs.
+                                * This will almost always be the windowserver
+                                * and loginwindow.  This is so if the w.s.
+                                * ever dies, that the naive user (stan)
+                                * doesn't ever see the console window. */
+#define SE_ONOPTION    0x20    /* Command to run when loginwindow exits with
+                                * special error code (229).  This signifies
+                                * that the user typed "console" at l.w. and
+                                * l.w. wants to exit and have init run getty
+                                * which will then put up a console window. */
+
+typedef struct _se_command {
+       char    *path;          /* what to run on that port */
+       char    **argv;         /* pre-parsed argument array */
+} se_cmd_t;
+
+typedef struct init_session {
+       int     se_index;               /* index of entry in ttys file */
+       pid_t   se_process;             /* controlling process */
+       time_t  se_started;             /* used to avoid thrashing */
+       int     se_flags;               /* status of session */
+       char    *se_device;             /* filename of port */
+       se_cmd_t se_getty;              /* what to run on that port */
+       se_cmd_t se_window;             /* window system (started only once) */
+       se_cmd_t se_onerror;            /* See SE_ONERROR above */
+       se_cmd_t se_onoption;           /* See SE_ONOPTION above */
+       struct  init_session *se_prev;
+       struct  init_session *se_next;
+} session_t;
+
+void free_session __P((session_t *));
+session_t *new_session __P((session_t *, int, struct ttyent *));
+session_t *sessions;
+
+char **construct_argv __P((char *));
+void collect_child __P((pid_t));
+pid_t start_getty __P((session_t *));
+void transition_handler __P((int));
+void alrm_handler __P((int));
+void setsecuritylevel __P((int));
+int getsecuritylevel __P((void));
+int setupargv __P((session_t *, struct ttyent *));
+int clang;
+
+void clear_session_logs __P((session_t *));
+
+int start_session_db __P((void));
+void add_session __P((session_t *));
+void del_session __P((session_t *));
+session_t *find_session __P((pid_t));
+DB *session_db;
+
+/*
+ * The mother of all processes.
+ */
+int
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       int c;
+       struct sigaction sa;
+       sigset_t mask;
+
+
+       /* Dispose of random users. */
+       if (getuid() != 0) {
+               (void)fprintf(stderr, "init: %s\n", strerror(EPERM));
+               exit (1);
+       }
+
+       /* System V users like to reexec init. */
+       if (getpid() != 1) {
+               (void)fprintf(stderr, "init: already running\n");
+               exit (1);
+       }
+
+       /*
+        * Note that this does NOT open a file...
+        * Does 'init' deserve its own facility number?
+        */
+       openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH);
+
+       /*
+        * Create an initial session.
+        */
+       if (setsid() < 0)
+               warning("initial setsid() failed: %m");
+
+       /*
+        * Establish an initial user so that programs running
+        * single user do not freak out and die (like passwd).
+        */
+       if (setlogin("root") < 0)
+               warning("setlogin() failed: %m");
+
+       /*
+        * This code assumes that we always get arguments through flags,
+        * never through bits set in some random machine register.
+        */
+
+#ifdef DEBUG
+       {
+           int i;
+           for (i = 0; i <= argc; i++) {
+               if (argv[i])
+                   warning("init argument %d: '%s'", i, argv[i]);
+               else
+                   warning("init argument %d: ***NULL***", i);
+           }
+       }
+#endif
+
+       while ((c = getopt(argc, argv, "sfbvx")) != -1) {
+#ifdef DEBUG
+               warning("handling init argument '-%c'", c);
+#endif
+               switch (c) {
+               case 's':
+                       requested_transition = single_user;
+                       break;
+               case 'f':
+                       runcom_mode = FASTBOOT;
+                       break;
+               case 'b':
+                       runcom_boot = 0;        // Don't runcom rc.boot
+                       break;
+               case 'v':
+                       runcom_verbose = 1;
+                       break;
+               case 'x':
+                       runcom_safe = 1;
+                       break;
+               default:
+                       warning("unrecognized flag '-%c'", c);
+                       break;
+               }
+       }
+
+       if (optind != argc)
+               warning("ignoring excess arguments");
+
+       /*
+        * We catch or block signals rather than ignore them,
+        * so that they get reset on exec.
+        */
+       handle(badsys, SIGSYS, 0);
+       handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV,
+              SIGBUS, SIGXCPU, SIGXFSZ, 0);
+       handle(transition_handler, SIGHUP, SIGTERM, SIGTSTP, 0);
+       handle(alrm_handler, SIGALRM, 0);
+       sigfillset(&mask);
+       delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS,
+               SIGXCPU, SIGXFSZ, SIGHUP, SIGTERM, SIGTSTP, SIGALRM, 0);
+       sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
+       sigemptyset(&sa.sa_mask);
+       sa.sa_flags = 0;
+       sa.sa_handler = SIG_IGN;
+       (void) sigaction(SIGTTIN, &sa, (struct sigaction *)0);
+       (void) sigaction(SIGTTOU, &sa, (struct sigaction *)0);
+
+       /*
+        * Paranoia.
+        */
+       close(0);
+       close(1);
+       close(2);
+
+       if (runcom_boot)
+       {
+           int old_rc_mode = runcom_mode;
+
+           runcom_mode = BOOT_SCRIPT;
+           if (runcom() == (state_func_t) single_user)
+               requested_transition = single_user; // Error in script
+           runcom_mode = old_rc_mode;
+       }
+
+       /*
+        * Start the state machine.
+        */
+       transition(requested_transition);
+
+       /*
+        * Should never reach here.
+        */
+       return 1;
+}
+
+/*
+ * Associate a function with a signal handler.
+ */
+void
+handle(sig_t handler, ...)
+{
+       int sig;
+       struct sigaction sa;
+       int mask_everything;
+       va_list ap;
+       va_start(ap, handler);
+
+       sa.sa_handler = handler;
+       sigfillset(&mask_everything);
+
+       while (sig = va_arg(ap, int)) {
+               sa.sa_mask = mask_everything;
+               /* XXX SA_RESTART? */
+               sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0;
+               sigaction(sig, &sa, (struct sigaction *) 0);
+       }
+       va_end(ap);
+}
+
+/*
+ * Delete a set of signals from a mask.
+ */
+void
+delset(sigset_t *maskp, ...)
+{
+       int sig;
+       va_list ap;
+       va_start(ap, maskp);
+
+       while (sig = va_arg(ap, int))
+               sigdelset(maskp, sig);
+       va_end(ap);
+}
+
+/*
+ * Log a message and sleep for a while (to give someone an opportunity
+ * to read it and to save log or hardcopy output if the problem is chronic).
+ * NB: should send a message to the session logger to avoid blocking.
+ */
+void
+stall(char *message, ...)
+{
+       va_list ap;
+       va_start(ap, message);
+
+       vsyslog(LOG_ALERT, message, ap);
+       va_end(ap);
+       sleep(STALL_TIMEOUT);
+}
+
+/*
+ * Like stall(), but doesn't sleep.
+ * If cpp had variadic macros, the two functions could be #defines for another.
+ * NB: should send a message to the session logger to avoid blocking.
+ */
+void
+warning(char *message, ...)
+{
+       va_list ap;
+       va_start(ap, message);
+
+       vsyslog(LOG_ALERT, message, ap);
+       va_end(ap);
+}
+
+/*
+ * Log an emergency message.
+ * NB: should send a message to the session logger to avoid blocking.
+ */
+void
+emergency(char *message, ...)
+{
+       va_list ap;
+       va_start(ap, message);
+
+       vsyslog(LOG_EMERG, message, ap);
+       va_end(ap);
+}
+
+/*
+ * Catch a SIGSYS signal.
+ *
+ * These may arise if a system does not support sysctl.
+ * We tolerate up to 25 of these, then throw in the towel.
+ */
+void
+badsys(sig)
+       int sig;
+{
+       static int badcount = 0;
+
+       if (badcount++ < 25)
+               return;
+       disaster(sig);
+}
+
+/*
+ * Catch an unexpected signal.
+ */
+void
+disaster(sig)
+       int sig;
+{
+       emergency("fatal signal: %s",
+               sig < (unsigned) NSIG ? sys_siglist[sig] : "unknown signal");
+
+       sleep(STALL_TIMEOUT);
+       _exit(sig);             /* reboot */
+}
+
+/*
+ * Get the security level of the kernel.
+ */
+int
+getsecuritylevel()
+{
+#ifdef KERN_SECURELVL
+       int name[2], curlevel;
+       size_t len;
+       extern int errno;
+
+       name[0] = CTL_KERN;
+       name[1] = KERN_SECURELVL;
+       len = sizeof curlevel;
+       if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) {
+               emergency("cannot get kernel security level: %s",
+                   strerror(errno));
+               return (-1);
+       }
+       return (curlevel);
+#else
+       return (-1);
+#endif
+}
+
+/*
+ * Set the security level of the kernel.
+ */
+void
+setsecuritylevel(newlevel)
+       int newlevel;
+{
+#ifdef KERN_SECURELVL
+       int name[2], curlevel;
+       extern int errno;
+
+       curlevel = getsecuritylevel();
+       if (newlevel == curlevel)
+               return;
+       name[0] = CTL_KERN;
+       name[1] = KERN_SECURELVL;
+       if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) {
+               emergency(
+                   "cannot change kernel security level from %d to %d: %s",
+                   curlevel, newlevel, strerror(errno));
+               return;
+       }
+#ifdef SECURE
+       warning("kernel security level changed from %d to %d",
+           curlevel, newlevel);
+#endif
+#endif
+}
+
+/*
+ * Change states in the finite state machine.
+ * The initial state is passed as an argument.
+ */
+void
+transition(s)
+       state_t s;
+{
+       for (;;)
+               s = (state_t) (*s)();
+}
+
+/*
+ * Close out the accounting files for a login session.
+ * NB: should send a message to the session logger to avoid blocking.
+ */
+void
+clear_session_logs(sp)
+       session_t *sp;
+{
+       char *line = sp->se_device + sizeof(_PATH_DEV) - 1;
+
+       if (logout(line))
+               logwtmp(line, "", "");
+}
+
+/*
+ * Start a session and allocate a controlling terminal.
+ * Only called by children of init after forking.
+ */
+void
+setctty(name, flags)
+       char *name;
+       int flags;
+{
+       int fd;
+
+       (void) revoke(name);
+       sleep (2);                      /* leave DTR low */
+       if ((fd = open(name, flags | O_RDWR)) == -1) {
+               stall("can't open %s: %m", name);
+               _exit(1);
+       }
+       if (login_tty(fd) == -1) {
+               stall("can't get %s for controlling terminal: %m", name);
+               _exit(1);
+       }
+}
+
+#if m68k
+/*
+ * Taken from etc/halt/halt.c
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <sgtty.h>
+
+static void shutend(void)
+{
+       register i;
+
+       acct(0);
+       for (i = 0; i < 10; i++)
+               close(i);
+
+       logwtmp("~", "shutdown", "");
+}
+
+static void do_halt(void)
+{
+       char sbuf [40];
+       int halthowto = RB_HALT;
+
+       (void) kill(-1, SIGTERM);       /* one chance to catch it */
+
+       sprintf (sbuf, "Invalid hardware password, halting machine...\n");
+       write (1, sbuf, strlen (sbuf));
+
+       signal(SIGALRM, SIG_DFL);
+       shutend();
+       sync();
+
+       signal(SIGALRM, alrm_handler);
+       alarm(FAILED_HW_PASS);
+       pause();
+
+       syscall(SYS_reboot, halthowto);
+}
+
+/*
+ * Taken from lib/gen/getpass.c
+ */
+
+static char *gethwpasswd(char *prompt)
+{
+    struct termios term;
+    register char *p;
+    register c;
+    static char pbuf[9];
+    int echo;
+
+    (void) tcgetattr(1, &term);
+    if (echo = (term.c_lflag & ECHO))
+    {
+       term.c_lflag &= ~ECHO;
+       (void) tcsetattr(1, TCSAFLUSH|TCSASOFT, &term);
+    }
+
+    write(2, prompt, strlen(prompt));
+
+    for (p = pbuf; (c = getchar()) != '\n' && c != EOF; )
+       if (p < &pbuf[8])
+           *p++ = c;
+    *p = '\0';
+
+    p = "\n";
+    write(2, p, strlen(p));
+
+    if (echo)
+    {
+       term.c_lflag |= ECHO;
+       (void) tcsetattr(1, TCSAFLUSH|TCSASOFT, &term);
+    }
+
+    return(pbuf);
+}
+
+
+static char *hw_passwd (void)
+{
+    char sbuf[40];
+    static char buffer [12];
+    struct nvram_info nvi;
+    int    vidfd, count;
+    
+    if ((vidfd = open ("/dev/vid0", O_RDONLY, 0)) == -1)
+       return NULL;
+    
+    if (ioctl (vidfd, DKIOCGNVRAM, &nvi) == -1)
+       return NULL;
+    
+    if (nvi.ni_hw_pwd != HW_PWD)
+       return NULL;
+    else
+    {
+
+       for (count = 0; count < NVRAM_HW_PASSWD; count++)
+           nvi.ni_ep[count] ^= 'N';
+       strncpy(buffer, nvi.ni_ep, NVRAM_HW_PASSWD);
+       /* ni_ep is not necessarily null terminated */
+
+       // gvdl I sure hope it is 'cause bad things will happen otherwise
+
+       return buffer;
+    }
+}
+
+
+#endif m68k
+
+
+static void
+do_security_check(void)
+{
+#if m68k
+    char sbuf[128];
+    char *try, *passwd;
+    int retries = 0;
+
+    /*
+     * If there is a hardware passwd, we want to 
+     * prompt the user for it.  The write will be 
+     * to the console window because of the O_POPUP flag.
+     */
+    passwd = hw_passwd();
+    write (1, "\n\n", 2);
+
+    if (passwd != NULL)
+    {
+       do
+       {
+           try = gethwpasswd ("Enter hardware password:");
+           if (strncmp (try, passwd, NVRAM_HW_PASSWD) == 0)
+           {
+               execl(shell, minus, (char *)0);
+               exit (0);
+           }
+           else
+           {
+               sprintf (sbuf, "Password incorrect.\n\n");
+               write (1, sbuf, strlen (sbuf));
+           }
+       }
+       while (++retries < 3);
+       do_halt();
+    }
+#elif defined(SECURE)
+    struct ttyent *typ;
+    struct passwd *pp;
+    static const char banner[] =
+           "Enter root password, or ^D to go multi-user\n";
+    char *clear, *password;
+
+    /*
+     * Check the root password.
+     * We don't care if the console is 'on' by default;
+     * it's the only tty that can be 'off' and 'secure'.
+     */
+    typ = getttynam("console");
+    pp = getpwnam("root");
+    if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp)
+    {
+       write(2, banner, sizeof banner - 1);
+       for (;;)
+       {
+           clear = getpass("Password:");
+           if (clear == 0 || *clear == '\0')
+               _exit(0);
+           password = crypt(clear, pp->pw_passwd);
+           memset(clear, 0, _PASSWORD_LEN);
+           if (strcmp(password, pp->pw_passwd) == 0)
+               break;
+           warning("single-user login failed\n");
+       }
+    }
+    endttyent();
+    endpwent();
+#endif /* SECURE */
+}
+
+/*
+ * Bring the system up single user.
+ */
+state_func_t
+single_user()
+{
+       pid_t pid, wpid;
+       int status;
+       sigset_t mask;
+       char *shell = _PATH_BSHELL;
+       char *argv[2];
+       /*
+        * If the kernel is in secure mode, downgrade it to insecure mode.
+        */
+       if (getsecuritylevel() > 0)
+               setsecuritylevel(0);
+
+       if ((pid = fork()) == 0) {
+               /*
+                * Start the single user session.
+                */
+               setctty(_PATH_CONSOLE, O_POPUP);
+
+               do_security_check();
+
+#ifdef DEBUGSHELL
+               {
+                       char altshell[128], *cp = altshell;
+                       int num;
+
+#define        SHREQUEST \
+       "Enter pathname of shell or RETURN for sh: "
+                       (void)write(STDERR_FILENO,
+                           SHREQUEST, sizeof(SHREQUEST) - 1);
+                       while ((num = read(STDIN_FILENO, cp, 1)) != -1 &&
+                           num != 0 && *cp != '\n' && cp < &altshell[127])
+                                       cp++;
+                       *cp = '\0';
+                       if (altshell[0] != '\0')
+                               shell = altshell;
+               }
+#endif /* DEBUGSHELL */
+
+               /*
+                * Unblock signals.
+                * We catch all the interesting ones,
+                * and those are reset to SIG_DFL on exec.
+                */
+               sigemptyset(&mask);
+               sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
+
+                /*
+                 * Set up the PATH to be approriate for the root user.
+                 */
+                setenv("PATH", _PATH_STDPATH, 1);
+
+               /*
+                * We're dropping into the console; set TERM appropriately.
+                */
+                setenv("TERM", "vt100", 1);
+
+               /*
+                * Fire off a shell.
+                * If the default one doesn't work, try the Bourne shell.
+                */
+               argv[0] = "-sh";
+               argv[1] = 0;
+               execv(shell, argv);
+               emergency("can't exec %s for single user: %m", shell);
+               execv(_PATH_BSHELL, argv);
+               emergency("can't exec %s for single user: %m", _PATH_BSHELL);
+               sleep(STALL_TIMEOUT);
+               _exit(1);
+       }
+
+       if (pid == -1) {
+               /*
+                * We are seriously hosed.  Do our best.
+                */
+               emergency("can't fork single-user shell, trying again");
+               while (waitpid(-1, (int *) 0, WNOHANG) > 0)
+                       continue;
+               return (state_func_t) single_user;
+       }
+
+       requested_transition = 0;
+       do {
+               if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
+                       collect_child(wpid);
+               if (wpid == -1) {
+                       if (errno == EINTR)
+                               continue;
+                       warning("wait for single-user shell failed: %m; restarting");
+                       return (state_func_t) single_user;
+               }
+               if (wpid == pid && WIFSTOPPED(status)) {
+                       warning("init: shell stopped, restarting\n");
+                       kill(pid, SIGCONT);
+                       wpid = -1;
+               }
+       } while (wpid != pid && !requested_transition);
+
+       if (requested_transition)
+               return (state_func_t) requested_transition;
+
+       if (!WIFEXITED(status)) {
+               if (WTERMSIG(status) == SIGKILL) { 
+                       /* 
+                        *  reboot(8) killed shell? 
+                        */
+                       warning("single user shell terminated.");
+                       sleep(STALL_TIMEOUT);
+                       _exit(0);
+               } else {        
+                       warning("single user shell terminated, restarting");
+                       return (state_func_t) single_user;
+               }
+       }
+
+       runcom_mode = FASTBOOT;
+       return (state_func_t) runcom;
+}
+
+/*
+ * Run the system startup script.
+ */
+state_func_t
+runcom()
+{
+       pid_t pid, wpid;
+       int status;
+       char *argv[4];
+       char options[4];
+       struct sigaction sa;
+
+       if ((pid = fork()) == 0) {
+               sigemptyset(&sa.sa_mask);
+               sa.sa_flags = 0;
+               sa.sa_handler = SIG_IGN;
+               (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0);
+               (void) sigaction(SIGHUP, &sa, (struct sigaction *)0);
+
+               setctty(_PATH_CONSOLE, 0);
+
+               argv[0] = "sh";
+
+               if (runcom_mode == BOOT_SCRIPT)
+               {
+                   argv[1] = _PATH_RUNCOM_BOOT;
+                   argv[2] = requested_transition == single_user
+                           ? "singleuser" : 0;
+               }
+               else /* runcom_mode != BOOT_SCRIPT */
+               {
+                   argv[1] = _PATH_RUNCOM;
+
+                   switch(runcom_mode) {
+                   case AUTOBOOT:
+                       argv[2] = "autoboot";
+                       break;
+                   default:
+                       argv[2] = "multiuser";
+                       break;
+                   }
+               }
+
+               if (runcom_verbose || runcom_safe)
+               {
+                   int i = 0;
+
+                   options[i++] = '-';
+                   if (runcom_verbose) options[i++] = 'v';
+                   if (runcom_safe   ) options[i++] = 'x';
+                   options[i] = '\0';
+
+                   argv[3] = options;
+               }
+               else
+               {
+                   argv[3] = 0;
+               }
+
+               argv[4] = 0;
+
+#ifdef DEBUG
+               {
+                   int i;
+                   for (i = 0; i <= 4; i++) {
+                       if (argv[i])
+                           warning("%s argument: %s", _PATH_RUNCOM, argv[i]);
+                   }
+               }
+#endif
+
+               sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
+
+               execv(_PATH_BSHELL, argv);
+               stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM);
+               _exit(1);       /* force single user mode */
+       }
+
+       if (pid == -1) {
+               emergency("can't fork for %s on %s: %m",
+                       _PATH_BSHELL, _PATH_RUNCOM);
+               while (waitpid(-1, (int *) 0, WNOHANG) > 0)
+                       continue;
+               sleep(STALL_TIMEOUT);
+               return (state_func_t) single_user;
+       }
+
+       /*
+        * Copied from single_user().  This is a bit paranoid.
+        */
+       do {
+               if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1)
+                       collect_child(wpid);
+               if (wpid == -1) {
+                       if (errno == EINTR)
+                               continue;
+                       warning("wait for %s on %s failed: %m; going to single user mode",
+                               _PATH_BSHELL, _PATH_RUNCOM);
+                       return (state_func_t) single_user;
+               }
+               if (wpid == pid && WIFSTOPPED(status)) {
+                       warning("init: %s on %s stopped, restarting\n",
+                               _PATH_BSHELL, _PATH_RUNCOM);
+                       kill(pid, SIGCONT);
+                       wpid = -1;
+               }
+       } while (wpid != pid);
+
+       if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM &&
+           requested_transition == catatonia) {
+               /* /etc/rc executed /sbin/reboot; wait for the end quietly */
+               sigset_t s;
+
+               sigfillset(&s);
+               for (;;)
+                       sigsuspend(&s);
+       }
+
+       if (!WIFEXITED(status)) {
+               warning("%s on %s terminated abnormally, going to single user mode",
+                       _PATH_BSHELL, _PATH_RUNCOM);
+               return (state_func_t) single_user;
+       }
+
+       if (WEXITSTATUS(status))
+               return (state_func_t) single_user;
+
+       runcom_mode = AUTOBOOT;         /* the default */
+       /* NB: should send a message to the session logger to avoid blocking. */
+       logwtmp("~", "reboot", "");
+       return (state_func_t) read_ttys;
+}
+
+/*
+ * Open the session database.
+ *
+ * NB: We could pass in the size here; is it necessary?
+ */
+int
+start_session_db()
+{
+       if (session_db && (*session_db->close)(session_db))
+               emergency("session database close: %s", strerror(errno));
+       if ((session_db = dbopen(NULL, O_RDWR, 0, DB_HASH, NULL)) == 0) {
+               emergency("session database open: %s", strerror(errno));
+               return (1);
+       }
+       return (0);
+               
+}
+
+/*
+ * Add a new login session.
+ */
+void
+add_session(sp)
+       session_t *sp;
+{
+       DBT key;
+       DBT data;
+
+       key.data = &sp->se_process;
+       key.size = sizeof sp->se_process;
+       data.data = &sp;
+       data.size = sizeof sp;
+
+       if ((*session_db->put)(session_db, &key, &data, 0))
+               emergency("insert %d: %s", sp->se_process, strerror(errno));
+}
+
+/*
+ * Delete an old login session.
+ */
+void
+del_session(sp)
+       session_t *sp;
+{
+       DBT key;
+
+       key.data = &sp->se_process;
+       key.size = sizeof sp->se_process;
+
+       if ((*session_db->del)(session_db, &key, 0))
+               emergency("delete %d: %s", sp->se_process, strerror(errno));
+}
+
+/*
+ * Look up a login session by pid.
+ */
+session_t *
+find_session(pid_t pid)
+{
+       DBT key;
+       DBT data;
+       session_t *ret;
+
+       key.data = &pid;
+       key.size = sizeof pid;
+       if ((*session_db->get)(session_db, &key, &data, 0) != 0)
+               return 0;
+       memmove(&ret, data.data, sizeof(ret));
+       return ret;
+}
+
+/*
+ * Construct an argument vector from a command line.
+ */
+char **
+construct_argv(command)
+       char *command;
+{
+       register int argc = 0;
+       register char **argv = (char **) malloc(((strlen(command) + 1) / 2 + 1)
+                                               * sizeof (char *));
+       static const char separators[] = " \t";
+
+       if ((argv[argc++] = strtok(command, separators)) == 0)
+               return 0;
+       while (argv[argc++] = strtok((char *) 0, separators))
+               continue;
+       return argv;
+}
+
+/*
+ * Deallocate a session descriptor.
+ */
+
+static __inline__ void free_command(se_cmd_t *se_cmd)
+{
+    if (se_cmd->path)
+    {
+       free(se_cmd->path);
+       free(se_cmd->argv);
+    }
+}
+
+void
+free_session(sp)
+       register session_t *sp;
+{
+    free(sp->se_device);
+    free_command(&sp->se_getty);
+    free_command(&sp->se_window);
+    free_command(&sp->se_onerror);
+    free_command(&sp->se_onoption);
+    memset(sp, '\0', sizeof(*sp));     // a bit of defensive programming
+
+    free(sp);
+}
+
+static int setup_command(se_cmd_t *se_cmd, char *command, char *arg )
+{
+
+    char *commandWithArg;
+
+    commandWithArg = malloc( strlen( command) + strlen( arg) + 2);
+    (void) sprintf(commandWithArg, "%s %s", command, arg);
+
+       free_command(se_cmd);
+
+       se_cmd->path = commandWithArg;
+       se_cmd->argv = construct_argv(commandWithArg);
+       if (se_cmd->argv == NULL)
+       {
+               free(se_cmd->path);
+               se_cmd->path = NULL;
+               return 0;
+       }
+       return 1;
+}
+
+/*
+ * Calculate getty and if useful window argv vectors.
+ */
+int
+setupargv(sp, typ)
+       session_t *sp;
+       struct ttyent *typ;
+{
+    char *type;
+
+    if ( !setup_command(&sp->se_getty, typ->ty_getty, typ->ty_name) )
+    {
+       type = "getty";
+       goto bad_args;
+    }
+
+    if (typ->ty_window
+    && !setup_command(&sp->se_window, typ->ty_window, typ->ty_name) )
+    {
+       type = "window";
+       goto bad_args;
+    }
+
+    if (typ->ty_onerror
+    && !setup_command(&sp->se_onerror, typ->ty_onerror, typ->ty_name) )
+    {
+       type = "onerror";
+       goto bad_args;
+    }
+
+    if (typ->ty_onoption
+    && !setup_command(&sp->se_onoption, typ->ty_onoption, typ->ty_name) )
+    {
+       type = "onoption";
+       goto bad_args;
+    }
+
+    return 1;
+
+bad_args:
+    warning("can't parse %s for port %s", type, sp->se_device);
+    return 0;
+}
+
+
+/*
+ * Allocate a new session descriptor.
+ */
+session_t *
+new_session(sprev, session_index, typ)
+       session_t *sprev;
+       int session_index;
+       register struct ttyent *typ;
+{
+       register session_t *sp;
+
+       if ((typ->ty_status & TTY_ON) == 0 ||
+           typ->ty_name == 0 ||
+           typ->ty_getty == 0)
+               return 0;
+
+       sp = (session_t *) malloc(sizeof (session_t));
+       memset(sp, 0, sizeof *sp);
+
+       sp->se_index = session_index;
+
+       sp->se_device = malloc(sizeof(_PATH_DEV) + strlen(typ->ty_name));
+       (void) sprintf(sp->se_device, "%s%s", _PATH_DEV, typ->ty_name);
+
+       if (setupargv(sp, typ) == 0) {
+               free_session(sp);
+               return (0);
+       }
+
+       sp->se_next = 0;
+       if (sprev == 0) {
+               sessions = sp;
+               sp->se_prev = 0;
+       } else {
+               sprev->se_next = sp;
+               sp->se_prev = sprev;
+       }
+
+       return sp;
+}
+
+/*
+ * Walk the list of ttys and create sessions for each active line.
+ */
+state_func_t
+read_ttys()
+{
+       int session_index = 0;
+       register session_t *sp, *snext;
+       register struct ttyent *typ;
+
+       /*
+        * Destroy any previous session state.
+        * There shouldn't be any, but just in case...
+        */
+       for (sp = sessions; sp; sp = snext) {
+               if (sp->se_process)
+                       clear_session_logs(sp);
+               snext = sp->se_next;
+               free_session(sp);
+       }
+       sessions = 0;
+       if (start_session_db())
+               return (state_func_t) single_user;
+
+       /*
+        * Allocate a session entry for each active port.
+        * Note that sp starts at 0.
+        */
+       while (typ = getttyent())
+               if (snext = new_session(sp, ++session_index, typ))
+                       sp = snext;
+
+       endttyent();
+
+       return (state_func_t) multi_user;
+}
+
+/*
+ * Start a window system running.
+ */
+static pid_t
+start_window_system(session_t *sp)
+{
+       pid_t pid;
+       sigset_t mask;
+
+       if ((pid = fork()) == -1) {
+               emergency("can't fork for window system on port %s: %m",
+                       sp->se_device);
+               /* hope that getty fails and we can try again */
+               return -1;
+       }
+
+       if (pid)
+               return pid;
+
+       sigemptyset(&mask);
+       sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
+
+       if (setsid() < 0)
+               emergency("setsid failed (window) %m");
+
+       execv(sp->se_window.argv[0], sp->se_window.argv);
+       stall("can't exec window system '%s' for port %s: %m",
+               sp->se_window.argv[0], sp->se_device);
+       _exit(1);
+}
+
+/*
+ * Start a login session running.
+ */
+pid_t
+start_getty(sp)
+       session_t *sp;
+{
+       pid_t pid;
+       sigset_t mask;
+       se_cmd_t *se_cmd;
+       const char *session_type = NULL;
+       time_t current_time      = time((time_t *) 0);
+
+       // Setup the default values;
+       switch (sp->se_flags & SE_GETTY_LAUNCH)
+       {
+       case SE_ONOPTION:
+           if (sp->se_onoption.path)
+           {
+               se_cmd       = &sp->se_onoption;
+               session_type = "onoption";
+               break;
+           }
+           /* No break */
+
+       case SE_ONERROR:
+           if (sp->se_onerror.path)
+           {
+               se_cmd       = &sp->se_onerror;
+               session_type = "onerror";
+               break;
+           }
+           /* No break */
+
+       case SE_COMMON:
+       default:
+           se_cmd       = &sp->se_getty;
+           session_type = "getty";
+           break;
+       }
+
+       if  (sp->se_window.path
+       && ((sp->se_flags & SE_GETTY_LAUNCH) != SE_ONOPTION))
+       {
+               if (start_window_system(sp) == -1)
+                       return -1;
+       }
+
+       /*
+        * fork(), not vfork() -- we can't afford to block.
+        */
+       if ((pid = fork()) == -1) {
+               emergency("can't fork for %s on port %s: %m",
+                   session_type, sp->se_device);
+               return -1;
+       }
+
+       if (pid)
+               return pid;
+
+       if (current_time > sp->se_started &&
+           current_time - sp->se_started < GETTY_SPACING) {
+               warning("%s repeating too quickly on port %s, sleeping",
+                       session_type, sp->se_device);
+               sleep((unsigned) GETTY_SLEEP);
+       }
+
+       sigemptyset(&mask);
+       sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0);
+
+       execv(se_cmd->argv[0], se_cmd->argv);
+       stall("can't exec %s '%s' for port %s: %m", session_type,
+               se_cmd->argv[0], sp->se_device);
+       _exit(1);
+}
+
+/*
+ * Collect exit status for a child.
+ * If an exiting login, start a new login running.
+ */
+void
+collect_child(pid_t pid)
+{
+       register session_t *sp, *sprev, *snext;
+
+       if ( !sessions)
+               return;
+
+       if ( !(sp = find_session(pid)) )
+               return;
+
+       clear_session_logs(sp);
+       del_session(sp);
+       sp->se_process = 0;
+
+       if (sp->se_flags & SE_SHUTDOWN) {
+               if (sprev = sp->se_prev)
+                       sprev->se_next = sp->se_next;
+               else
+                       sessions = sp->se_next;
+               if (snext = sp->se_next)
+                       snext->se_prev = sp->se_prev;
+               free_session(sp);
+               return;
+       }
+
+       if ((pid = start_getty(sp)) == -1) {
+               /* serious trouble */
+               requested_transition = clean_ttys;
+               return;
+       }
+
+       sp->se_process = pid;
+       sp->se_started = time((time_t *) 0);
+       sp->se_flags  &= ~SE_GETTY_LAUNCH; // clear down getty launch type
+       add_session(sp);
+}
+
+/*
+ * Catch a signal and request a state transition.
+ */
+void
+transition_handler(sig)
+       int sig;
+{
+
+       switch (sig) {
+       case SIGHUP:
+               requested_transition = clean_ttys;
+               break;
+       case SIGTERM:
+               requested_transition = death;
+               break;
+       case SIGTSTP:
+               requested_transition = catatonia;
+               break;
+       default:
+               requested_transition = 0;
+               break;
+       }
+}
+
+/*
+ * Take the system multiuser.
+ */
+state_func_t
+multi_user()
+{
+       pid_t pid;
+       register session_t *sp;
+
+       requested_transition = 0;
+
+       /*
+        * If the administrator has not set the security level to -1
+        * to indicate that the kernel should not run multiuser in secure
+        * mode, and the run script has not set a higher level of security 
+        * than level 1, then put the kernel into secure mode.
+        */
+       if (getsecuritylevel() == 0)
+               setsecuritylevel(1);
+
+       for (sp = sessions; sp; sp = sp->se_next) {
+               if (sp->se_process)
+                       continue;
+               if ((pid = start_getty(sp)) == -1) {
+                       /* serious trouble */
+                       requested_transition = clean_ttys;
+                       break;
+               }
+               sp->se_process = pid;
+               sp->se_started = time((time_t *) 0);
+               add_session(sp);
+       }
+
+       while (!requested_transition)
+       {
+               int status;
+               session_t *sp;
+
+               pid = waitpid(-1, &status, 0);
+               if (!sessions || !(sp = find_session(pid)))
+                       continue;
+
+               if (WIFSIGNALED(status))
+                   sp->se_flags |= SE_ONERROR;
+               else if (WEXITSTATUS(status) == REALLY_EXIT_TO_CONSOLE)
+               { /* WIFEXITED(status) assumed */
+                   sp->se_flags |= SE_ONOPTION;
+               }
+               else
+                   sp->se_flags |= SE_ONERROR;
+
+               if (pid != -1)
+                       collect_child(pid);
+       }
+
+       return (state_func_t) requested_transition;
+}
+
+/*
+ * This is an n-squared algorithm.  We hope it isn't run often...
+ */
+state_func_t
+clean_ttys()
+{
+       register session_t *sp, *sprev;
+       register struct ttyent *typ;
+       register int session_index = 0;
+       register int devlen;
+
+       if (! sessions)
+               return (state_func_t) multi_user;
+
+       devlen = sizeof(_PATH_DEV) - 1;
+       while (typ = getttyent()) {
+               ++session_index;
+
+               for (sprev = 0, sp = sessions; sp; sprev = sp, sp = sp->se_next)
+                       if (strcmp(typ->ty_name, sp->se_device + devlen) == 0)
+                               break;
+
+               if (sp) {
+                       if (sp->se_index != session_index) {
+                               warning("port %s changed utmp index from %d to %d",
+                                      sp->se_device, sp->se_index,
+                                      session_index);
+                               sp->se_index = session_index;
+                       }
+                       if ((typ->ty_status & TTY_ON) == 0 ||
+                           typ->ty_getty == 0) {
+                               sp->se_flags |= SE_SHUTDOWN;
+                               kill(sp->se_process, SIGHUP);
+                               continue;
+                       }
+                       sp->se_flags &= ~SE_SHUTDOWN;
+                       if (setupargv(sp, typ) == 0) {
+                               warning("can't parse getty for port %s",
+                                       sp->se_device);
+                               sp->se_flags |= SE_SHUTDOWN;
+                               kill(sp->se_process, SIGHUP);
+                       }
+                       continue;
+               }
+
+               new_session(sprev, session_index, typ);
+       }
+
+       endttyent();
+
+       return (state_func_t) multi_user;
+}
+
+/*
+ * Block further logins.
+ */
+state_func_t
+catatonia()
+{
+       register session_t *sp;
+
+       for (sp = sessions; sp; sp = sp->se_next)
+               sp->se_flags |= SE_SHUTDOWN;
+
+       return (state_func_t) multi_user;
+}
+
+/*
+ * Note SIGALRM.
+ */
+void
+alrm_handler(sig)
+       int sig;
+{
+       clang = 1;
+}
+
+/*
+ * Bring the system down to single user.
+ */
+state_func_t
+death()
+{
+       register session_t *sp;
+       register int i;
+       pid_t pid;
+       static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL };
+
+       for (sp = sessions; sp; sp = sp->se_next)
+               sp->se_flags |= SE_SHUTDOWN;
+
+       /* NB: should send a message to the session logger to avoid blocking. */
+       logwtmp("~", "shutdown", "");
+
+       for (i = 0; i < 3; ++i) {
+               if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH)
+                       return (state_func_t) single_user;
+
+               clang = 0;
+               alarm(DEATH_WATCH);
+               do
+                       if ((pid = waitpid(-1, (int *)0, 0)) != -1)
+                               collect_child(pid);
+               while (clang == 0 && errno != ECHILD);
+
+               if (errno == ECHILD)
+                       return (state_func_t) single_user;
+       }
+
+       warning("some processes would not die; ps axl advised");
+
+       return (state_func_t) single_user;
+}
diff --git a/init.tproj/pathnames.h b/init.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..777fe14
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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@
+ */
+#include <paths.h>
+
+#define        _PATH_SLOGGER           "/sbin/session_logger"
+#define        _PATH_RUNCOM            "/etc/rc"
+#define        _PATH_RUNCOM_BOOT       _PATH_RUNCOM ".boot"
diff --git a/iostat.tproj/Makefile b/iostat.tproj/Makefile
new file mode 100644 (file)
index 0000000..c18265a
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# 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 = iostat
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = iostat.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble iostat.8\
+            names.c
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/iostat.tproj/Makefile.postamble b/iostat.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..a3733f4
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# 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
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/iostat.tproj/Makefile.preamble b/iostat.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..dd14626
--- /dev/null
@@ -0,0 +1,115 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS =
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
+
diff --git a/iostat.tproj/PB.project b/iostat.tproj/PB.project
new file mode 100644 (file)
index 0000000..9f8d67b
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (iostat.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, iostat.8, names.c); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = iostat; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/iostat.tproj/iostat.8 b/iostat.tproj/iostat.8
new file mode 100644 (file)
index 0000000..48ef627
--- /dev/null
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1985, 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.
+.\"
+.\"    @(#)iostat.8    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt IOSTAT 8
+.Os BSD 4
+.Sh NAME
+.Nm iostat
+.Nd report
+.Tn I/O
+statistics
+.Sh SYNOPSIS
+.Nm iostat
+.Op Fl c Ar count
+.Op Fl M Ar core
+.Op Fl N Ar system
+.Op Fl w Ar wait
+.Op Ar drives
+.Sh DESCRIPTION
+.Nm Iostat
+displays kernel
+.Tn I/O
+statistics on terminal, disk and cpu
+operations.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl c
+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 w
+Pause
+.Ar wait
+seconds between each display.
+If no repeat
+.Ar count
+is specified, the default is infinity.
+.El
+.Pp
+.Nm Iostat
+displays its information in the following format:
+.Bl -tag -width flag
+.It tty
+.Bl -tag -width indent -compact
+.It tin
+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.
+To force
+.Nm iostat
+to display specific drives, their names may be supplied on the command
+line.
+.Pp
+.Bl -tag -width indent -compact
+.It sps
+sectors transferred per second
+.It tps
+transfers per second
+.It msps
+milliseconds per average seek (including implied
+seeks and rotational latency)
+.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 SEE ALSO
+.Xr fstat 1 ,
+.Xr netstat 1 ,
+.Xr nfsstat 1 ,
+.Xr \&ps 1 ,
+.Xr systat 1 ,
+.Xr vmstat 1 ,
+.Xr pstat 8
+.Pp
+The sections starting with ``Interpreting system activity'' in
+.%T "Installing and Operating 4.3BSD" .
diff --git a/iostat.tproj/iostat.c b/iostat.tproj/iostat.c
new file mode 100644 (file)
index 0000000..54cbf1c
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * 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.
+ */
+
+#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 */
+
+#include <sys/param.h>
+#include <sys/buf.h>
+#include <sys/dkstat.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 },
+};
+
+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;
+
+kvm_t   *kd;
+double   etime;
+long    *dk_wpms;
+int      dk_ndrive, *dr_select, hz, kmemfd, ndrives;
+char   **dr_name;
+
+#define nlread(x, v) \
+       kvm_read(kd, namelist[x].n_value, &(v), sizeof(v))
+
+#include "names.c"                             /* XXX */
+
+void cpustats __P((void));
+void dkstats __P((void));
+void phdr __P((int));
+void usage __P((void));
+
+int
+main(argc, argv)
+       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();
+               }
+       argc -= optind;
+       argv += optind;
+
+       /*
+        * Discard setgid privileges if not the running kernel so that bad
+        * guys can't print interesting stuff from kernel memory.
+        */
+       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 (!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 ] ]
+        */
+#define        BACKWARD_COMPATIBILITY
+       for (ndrives = 0; *argv; ++argv) {
+#ifdef BACKWARD_COMPATIBILITY
+               if (isdigit(**argv))
+                       break;
+#endif
+               for (i = 0; i < dk_ndrive; i++) {
+                       if (strcmp(dr_name[i], *argv))
+                               continue;
+                       dr_select[i] = 1;
+                       ++ndrives;
+               }
+       }
+#ifdef BACKWARD_COMPATIBILITY
+       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;
+       }
+
+       (void)signal(SIGCONT, phdr);
+
+       for (hdrcnt = 1;;) {
+               if (!--hdrcnt) {
+                       phdr(0);
+                       hdrcnt = 20;
+               }
+               (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);
+               }
+               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];
+               }
+               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)
+                       break;
+               (void)sleep(interval);
+       }
+       exit(0);
+}
+
+/* ARGUSED */
+void
+phdr(signo)
+       int signo;
+{
+       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");
+}
+
+void
+dkstats()
+{
+       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;
+                       else 
+                               msps = itime * 1000 / cur.dk_xfer[dn];
+               } else
+                       msps = 0;
+               (void)printf("%5.1f ", msps);
+       }
+}
+
+void
+cpustats()
+{
+       register int state;
+       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));
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr,
+"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n");
+       exit(1);
+}
diff --git a/iostat.tproj/names.c b/iostat.tproj/names.c
new file mode 100644 (file)
index 0000000..099ea61
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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/kextd.tproj/GetSymbolFromPEF.h b/kextd.tproj/GetSymbolFromPEF.h
new file mode 100644 (file)
index 0000000..378eca6
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..69f1ccf
--- /dev/null
@@ -0,0 +1,1823 @@
+#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>
+
+
+#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);
+}
+#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);
+
+    // 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);
+
+    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( type == kIOCatalogMatchIdle) {
+
+           mach_timespec_t timeout = { 10, 0 };
+           IOKitWaitQuiet( k->_catPort, &timeout );
+           KEXTdaemonSignal();
+
+        } else 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);
+}
+
+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);
+    } else {
+       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;
+    kern_return_t kr;
+    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: idle\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_timespec_t    waitTime = { 40, 0 };
+
+    kr = semaphore_timedwait( gDaemonSema, waitTime );
+    if( kr != KERN_SUCCESS )
+        syslog(LOG_ERR, "semaphore_timedwait(%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:
+            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)
+#else
+KEXTReturn KEXTDStartMain(KEXTDRef kextd, Boolean beVerbose, Boolean safeBoot, Boolean debug, KEXTBootlevel bootlevel)
+#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) {
+        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;
+
+    // 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);
+
+#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)
+{
+    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);
+                }
+            }
+            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
new file mode 100644 (file)
index 0000000..cdd6088
--- /dev/null
@@ -0,0 +1,65 @@
+
+#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);
+#else
+KEXTReturn     KEXTDStartMain(KEXTDRef kextd, Boolean beVerbose, Boolean safeBoot, Boolean debug, KEXTBootlevel bootlevel);
+#endif
+void           KEXTDScanPaths(KEXTDRef kextd);
+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
new file mode 100644 (file)
index 0000000..0537f47
--- /dev/null
@@ -0,0 +1,113 @@
+#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] [-b bootlevel]\n", arg0);
+    exit(1);
+}
+
+int main (int argc, const char *argv[])
+{
+    KEXTDRef kextd;
+    KEXTReturn error;
+    KEXTBootlevel bootlevel;
+    CFURLRef url;
+    CFArrayRef array;
+    CFIndex period;
+    Boolean safeBoot;
+    Boolean beVerbose;
+    Boolean enableTimer;
+    Boolean debug;
+    const void * vals[1];
+    int c;
+
+    arg0 = argv[0];
+    period = TIMER_PERIOD_S;
+    debug = false;
+    safeBoot = false;
+    beVerbose = false;
+    enableTimer = false;
+    bootlevel = kKEXTBootlevelNormal;
+
+    while ( (c = getopt(argc, (char **)argv, "xvdb:")) != -1 ) {
+        switch ( c ) {
+
+            case 'x':
+                safeBoot = 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;
+
+            default:
+                usage();
+        }
+    }
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0) {
+        usage();
+    }
+
+
+
+    url = CFURLCreateWithFileSystemPath(NULL, CFSTR(DEFAULT_SEARCH_PATH), kCFURLPOSIXPathStyle, true);
+    if ( !url ) {
+        printf("Error opening: %s.\n", DEFAULT_SEARCH_PATH);
+        exit(1);
+    }
+    vals[0] = url;
+    array = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks);
+    CFRelease(url);
+    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);
+#else
+    error = KEXTDStartMain(kextd, beVerbose, safeBoot, debug, bootlevel);
+#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
new file mode 100644 (file)
index 0000000..56510b3
--- /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 = 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
+NEXTSTEP_PB_LDFLAGS = -undefined warning
+FRAMEWORKS = -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
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..6a19916
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (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_LINKEROPTIONS = "-undefined warning"; 
+    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
new file mode 100644 (file)
index 0000000..567f915
--- /dev/null
@@ -0,0 +1,711 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..92316a5
--- /dev/null
@@ -0,0 +1,95 @@
+
+#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
new file mode 100644 (file)
index 0000000..3f18ae5
--- /dev/null
@@ -0,0 +1,25 @@
+
+#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
new file mode 100644 (file)
index 0000000..0e72c07
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# 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 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
new file mode 100644 (file)
index 0000000..b3bd25c
--- /dev/null
@@ -0,0 +1,9 @@
+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
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..bf00197
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (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
new file mode 100644 (file)
index 0000000..e2d34c7
--- /dev/null
@@ -0,0 +1,73 @@
+.\"
+.\" 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
new file mode 100644 (file)
index 0000000..6624995
--- /dev/null
@@ -0,0 +1,629 @@
+
+#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
new file mode 100644 (file)
index 0000000..ab6a55b
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# 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 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
new file mode 100644 (file)
index 0000000..15092aa
--- /dev/null
@@ -0,0 +1,9 @@
+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
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..7089f1b
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (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
new file mode 100644 (file)
index 0000000..f622928
--- /dev/null
@@ -0,0 +1,43 @@
+.\"
+.\"
+.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
new file mode 100644 (file)
index 0000000..852cd2c
--- /dev/null
@@ -0,0 +1,278 @@
+
+#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/kgmon.tproj/Makefile b/kgmon.tproj/Makefile
new file mode 100644 (file)
index 0000000..9436b34
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = kgmon
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = kgmon.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble kgmon.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/kgmon.tproj/Makefile.postamble b/kgmon.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..c2d2690
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#
+# This program may safely be run setuid-root to allow non-root
+# users to start, stop, and reset profiling buffers.
+#
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS = 4555        # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/kgmon.tproj/Makefile.preamble b/kgmon.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..e371f9d
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/kgmon.tproj/PB.project b/kgmon.tproj/PB.project
new file mode 100644 (file)
index 0000000..71ca9e4
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (kgmon.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, kgmon.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = kgmon; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/kgmon.tproj/kgmon.8 b/kgmon.tproj/kgmon.8
new file mode 100644 (file)
index 0000000..060ed2e
--- /dev/null
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1983, 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.
+.\"
+.\"     @(#)kgmon.8    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt KGMON 8
+.Os BSD 4.2
+.Sh NAME
+.Nm kgmon
+.Nd generate a dump of the operating system's profile buffers
+.Sh SYNOPSIS
+.Nm kgmon
+.Op Fl bhpr
+.Op Fl M core
+.Op Fl N system
+.Sh DESCRIPTION
+.Nm Kgmon
+is a tool used when profiling the operating system.
+When no arguments are supplied,
+.Nm kgmon
+indicates the state of operating system profiling as running,
+off, or not configured.
+(see
+.Xr config 8 )
+If the
+.Fl p
+flag is specified,
+.Nm kgmon
+extracts profile data from the operating system and produces a
+.Pa gmon.out
+file suitable for later analysis by
+.Xr gprof 1 .
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl b
+Resume the collection of profile data.
+.It Fl h
+Stop the collection of profile data.
+.It Fl p
+Dump the contents of the profile buffers into a
+.Pa gmon.out
+file.
+.It Fl r
+Reset all the profile buffers. 
+If the
+.Fl p
+flag is also specified, the
+.Pa gmon.out
+file is generated before the buffers are reset.
+.It Fl M
+Extract values associated with the name list from the specified core
+instead of the default ``/dev/kmem''.
+.It Fl N
+Extract the name list from the specified system instead of the
+default ``/vmunix''.
+.El
+.Pp
+If neither 
+.Fl b
+nor
+.Fl h
+is specified, the state of profiling collection remains unchanged.
+For example, if the
+.Fl p
+flag is specified and profile data is being collected,
+profiling will be momentarily suspended,
+the operating system profile buffers will be dumped,
+and profiling will be immediately resumed.
+.Sh FILES
+.Bl -tag -width /dev/kmemx -compact
+.It Pa /vmunix
+the default system
+.It Pa /dev/kmem
+the default memory
+.El
+.Sh SEE ALSO
+.Xr gprof 1 ,
+.Xr config 8
+.Sh DIAGNOSTICS
+Users with only read permission on
+.Pa /dev/kmem
+cannot change the state
+of profiling collection. 
+They can get a 
+.Pa gmon.out
+file with the warning that the data may be
+inconsistent if profiling is in progress.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.2 .
diff --git a/kgmon.tproj/kgmon.c b/kgmon.tproj/kgmon.c
new file mode 100644 (file)
index 0000000..47161c0
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * 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) 1983, 1992, 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 char copyright[] =
+"@(#) Copyright (c) 1983, 1992, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)kgmon.c    8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/sysctl.h>
+#include <sys/gmon.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <nlist.h>
+#include <ctype.h>
+#include <paths.h>
+
+struct nlist nl[] = {
+#define        N_GMONPARAM     0
+       { "__gmonparam" },
+#define        N_PROFHZ        1
+       { "_profhz" },
+       0,
+};
+
+struct kvmvars {
+       kvm_t   *kd;
+       struct gmonparam gpm;
+};
+
+int    bflag, hflag, kflag, rflag, pflag;
+int    debug = 0;
+void   setprof __P((struct kvmvars *kvp, int state));
+void   dumpstate __P((struct kvmvars *kvp));
+void   reset __P((struct kvmvars *kvp));
+
+int
+main(int argc, char **argv)
+{
+       extern char *optarg;
+       extern int optind;
+       int ch, mode, disp, accessmode;
+       struct kvmvars kvmvars;
+       char *system, *kmemf;
+
+       seteuid(getuid());
+       kmemf = NULL;
+       system = NULL;
+       while ((ch = getopt(argc, argv, "M:N:bhpr")) != EOF) {
+               switch((char)ch) {
+
+               case 'M':
+                       kmemf = optarg;
+                       kflag = 1;
+                       break;
+
+               case 'N':
+                       system = optarg;
+                       break;
+
+               case 'b':
+                       bflag = 1;
+                       break;
+
+               case 'h':
+                       hflag = 1;
+                       break;
+
+               case 'p':
+                       pflag = 1;
+                       break;
+
+               case 'r':
+                       rflag = 1;
+                       break;
+
+               default:
+                       (void)fprintf(stderr,
+                           "usage: kgmon [-bhrp] [-M core] [-N system]\n");
+                       exit(1);
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+       if (*argv) {
+               system = *argv;
+               if (*++argv) {
+                       kmemf = *argv;
+                       ++kflag;
+               }
+       }
+#endif
+       if (system == NULL)
+               system = _PATH_UNIX;
+       accessmode = openfiles(system, kmemf, &kvmvars);
+       mode = getprof(&kvmvars);
+       if (hflag)
+               disp = GMON_PROF_OFF;
+       else if (bflag)
+               disp = GMON_PROF_ON;
+       else
+               disp = mode;
+       if (pflag)
+               dumpstate(&kvmvars);
+       if (rflag)
+               reset(&kvmvars);
+       if (accessmode == O_RDWR)
+               setprof(&kvmvars, disp);
+       (void)fprintf(stdout, "kgmon: kernel profiling is %s.\n",
+                     disp == GMON_PROF_OFF ? "off" : "running");
+       return (0);
+}
+
+/*
+ * Check that profiling is enabled and open any ncessary files.
+ */
+openfiles(system, kmemf, kvp)
+       char *system;
+       char *kmemf;
+       struct kvmvars *kvp;
+{
+       int mib[3], state, size, openmode;
+       char errbuf[_POSIX2_LINE_MAX];
+
+       if (!kflag) {
+               mib[0] = CTL_KERN;
+               mib[1] = KERN_PROF;
+               mib[2] = GPROF_STATE;
+               size = sizeof state;
+               if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
+                       (void)fprintf(stderr,
+                           "kgmon: profiling not defined in kernel.\n");
+                       exit(20);
+               }
+               if (!(bflag || hflag || rflag ||
+                   (pflag && state == GMON_PROF_ON)))
+                       return (O_RDONLY);
+               (void)seteuid(0);
+               if (sysctl(mib, 3, NULL, NULL, &state, size) >= 0)
+                       return (O_RDWR);
+               (void)seteuid(getuid());
+               kern_readonly(state);
+               return (O_RDONLY);
+       }
+       openmode = (bflag || hflag || pflag || rflag) ? O_RDWR : O_RDONLY;
+       kvp->kd = kvm_openfiles(system, kmemf, NULL, openmode, errbuf);
+       if (kvp->kd == NULL) {
+               if (openmode == O_RDWR) {
+                       openmode = O_RDONLY;
+                       kvp->kd = kvm_openfiles(system, kmemf, NULL, O_RDONLY,
+                           errbuf);
+               }
+               if (kvp->kd == NULL) {
+                       (void)fprintf(stderr, "kgmon: kvm_openfiles: %s\n",
+                           errbuf);
+                       exit(2);
+               }
+               kern_readonly(GMON_PROF_ON);
+       }
+       if (kvm_nlist(kvp->kd, nl) < 0) {
+               (void)fprintf(stderr, "kgmon: %s: no namelist\n", system);
+               exit(3);
+       }
+       if (!nl[N_GMONPARAM].n_value) {
+               (void)fprintf(stderr,
+                   "kgmon: profiling not defined in kernel.\n");
+               exit(20);
+       }
+       return (openmode);
+}
+
+/*
+ * Suppress options that require a writable kernel.
+ */
+kern_readonly(mode)
+       int mode;
+{
+
+       (void)fprintf(stderr, "kgmon: kernel read-only: ");
+       if (pflag && mode == GMON_PROF_ON)
+               (void)fprintf(stderr, "data may be inconsistent\n");
+       if (rflag)
+               (void)fprintf(stderr, "-r supressed\n");
+       if (bflag)
+               (void)fprintf(stderr, "-b supressed\n");
+       if (hflag)
+               (void)fprintf(stderr, "-h supressed\n");
+       rflag = bflag = hflag = 0;
+}
+
+/*
+ * Get the state of kernel profiling.
+ */
+getprof(kvp)
+       struct kvmvars *kvp;
+{
+       int mib[3], size;
+
+       if (kflag) {
+               size = kvm_read(kvp->kd, nl[N_GMONPARAM].n_value, &kvp->gpm,
+                   sizeof kvp->gpm);
+       } else {
+               mib[0] = CTL_KERN;
+               mib[1] = KERN_PROF;
+               mib[2] = GPROF_GMONPARAM;
+               size = sizeof kvp->gpm;
+               if (sysctl(mib, 3, &kvp->gpm, &size, NULL, 0) < 0)
+                       size = 0;
+       }
+       if (size != sizeof kvp->gpm) {
+               (void)fprintf(stderr, "kgmon: cannot get gmonparam: %s\n",
+                   kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+               exit (4);
+       }
+       return (kvp->gpm.state);
+}
+
+/*
+ * Enable or disable kernel profiling according to the state variable.
+ */
+void
+setprof(kvp, state)
+       struct kvmvars *kvp;
+       int state;
+{
+       struct gmonparam *p = (struct gmonparam *)nl[N_GMONPARAM].n_value;
+       int mib[3], sz, oldstate;
+
+       sz = sizeof(state);
+       if (!kflag) {
+               mib[0] = CTL_KERN;
+               mib[1] = KERN_PROF;
+               mib[2] = GPROF_STATE;
+               if (sysctl(mib, 3, &oldstate, &sz, NULL, 0) < 0)
+                       goto bad;
+               if (oldstate == state)
+                       return;
+               (void)seteuid(0);
+               if (sysctl(mib, 3, NULL, NULL, &state, sz) >= 0) {
+                       (void)seteuid(getuid());
+                       return;
+               }
+               (void)seteuid(getuid());
+       } else if (kvm_write(kvp->kd, (u_long)&p->state, (void *)&state, sz) 
+           == sz)
+               return;
+bad:
+       (void)fprintf(stderr, "kgmon: warning: cannot turn profiling %s\n",
+           state == GMON_PROF_OFF ? "off" : "on");
+}
+
+/*
+ * Build the gmon.out file.
+ */
+void
+dumpstate(kvp)
+       struct kvmvars *kvp;
+{
+       register FILE *fp;
+       struct rawarc rawarc;
+       struct tostruct *tos;
+       u_long frompc, addr;
+       u_short *froms, *tickbuf;
+       int mib[3], i;
+       struct gmonhdr h;
+       int fromindex, endfrom, toindex;
+
+       setprof(kvp, GMON_PROF_OFF);
+       fp = fopen("gmon.out", "w");
+       if (fp == 0) {
+               perror("gmon.out");
+               return;
+       }
+
+       /*
+        * Build the gmon header and write it to a file.
+        */
+       bzero(&h, sizeof(h));
+       h.lpc = kvp->gpm.lowpc;
+       h.hpc = kvp->gpm.highpc;
+       h.ncnt = kvp->gpm.kcountsize + sizeof(h);
+       h.version = GMONVERSION;
+       h.profrate = getprofhz(kvp);
+       fwrite((char *)&h, sizeof(h), 1, fp);
+
+       /*
+        * Write out the tick buffer.
+        */
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROF;
+       if ((tickbuf = (u_short *)malloc(kvp->gpm.kcountsize)) == NULL) {
+               fprintf(stderr, "kgmon: cannot allocate kcount space\n");
+               exit (5);
+       }
+       if (kflag) {
+               i = kvm_read(kvp->kd, (u_long)kvp->gpm.kcount, (void *)tickbuf,
+                   kvp->gpm.kcountsize);
+       } else {
+               mib[2] = GPROF_COUNT;
+               i = kvp->gpm.kcountsize;
+               if (sysctl(mib, 3, tickbuf, &i, NULL, 0) < 0)
+                       i = 0;
+       }
+       if (i != kvp->gpm.kcountsize) {
+               (void)fprintf(stderr, "kgmon: read ticks: read %u, got %d: %s",
+                   kvp->gpm.kcountsize, i,
+                   kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+               exit(6);
+       }
+       if ((fwrite(tickbuf, kvp->gpm.kcountsize, 1, fp)) != 1) {
+               perror("kgmon: writing tocks to gmon.out");
+               exit(7);
+       }
+       free(tickbuf);
+
+       /*
+        * Write out the arc info.
+        */
+       if ((froms = (u_short *)malloc(kvp->gpm.fromssize)) == NULL) {
+               fprintf(stderr, "kgmon: cannot allocate froms space\n");
+               exit (8);
+       }
+       if (kflag) {
+               i = kvm_read(kvp->kd, (u_long)kvp->gpm.froms, (void *)froms,
+                   kvp->gpm.fromssize);
+       } else {
+               mib[2] = GPROF_FROMS;
+               i = kvp->gpm.fromssize;
+               if (sysctl(mib, 3, froms, &i, NULL, 0) < 0)
+                       i = 0;
+       }
+       if (i != kvp->gpm.fromssize) {
+               (void)fprintf(stderr, "kgmon: read froms: read %u, got %d: %s",
+                   kvp->gpm.fromssize, i,
+                   kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+               exit(9);
+       }
+       if ((tos = (struct tostruct *)malloc(kvp->gpm.tossize)) == NULL) {
+               fprintf(stderr, "kgmon: cannot allocate tos space\n");
+               exit(10);
+       }
+       if (kflag) {
+               i = kvm_read(kvp->kd, (u_long)kvp->gpm.tos, (void *)tos,
+                   kvp->gpm.tossize);
+       } else {
+               mib[2] = GPROF_TOS;
+               i = kvp->gpm.tossize;
+               if (sysctl(mib, 3, tos, &i, NULL, 0) < 0)
+                       i = 0;
+       }
+       if (i != kvp->gpm.tossize) {
+               (void)fprintf(stderr, "kgmon: read tos: read %u, got %d: %s",
+                   kvp->gpm.tossize, i,
+                   kflag ? kvm_geterr(kvp->kd) : strerror(errno));
+               exit(11);
+       }
+       if (debug)
+               (void)fprintf(stderr, "kgmon: lowpc 0x%x, textsize 0x%x\n",
+                             kvp->gpm.lowpc, kvp->gpm.textsize);
+       endfrom = kvp->gpm.fromssize / sizeof(*froms);
+       for (fromindex = 0; fromindex < endfrom; ++fromindex) {
+               if (froms[fromindex] == 0)
+                       continue;
+               frompc = (u_long)kvp->gpm.lowpc +
+                   (fromindex * kvp->gpm.hashfraction * sizeof(*froms));
+               for (toindex = froms[fromindex]; toindex != 0;
+                  toindex = tos[toindex].link) {
+                       if (debug)
+                           (void)fprintf(stderr,
+                           "%s: [mcleanup] frompc 0x%x selfpc 0x%x count %d\n",
+                           "kgmon", frompc, tos[toindex].selfpc,
+                           tos[toindex].count);
+                       rawarc.raw_frompc = frompc;
+                       rawarc.raw_selfpc = (u_long)tos[toindex].selfpc;
+                       rawarc.raw_count = tos[toindex].count;
+                       fwrite((char *)&rawarc, sizeof(rawarc), 1, fp);
+               }
+       }
+       fclose(fp);
+}
+
+/*
+ * Get the profiling rate.
+ */
+int
+getprofhz(kvp)
+       struct kvmvars *kvp;
+{
+       int mib[2], size, profrate;
+       struct clockinfo clockrate;
+
+       if (kflag) {
+               profrate = 1;
+               if (kvm_read(kvp->kd, nl[N_PROFHZ].n_value, &profrate,
+                   sizeof profrate) != sizeof profrate)
+                       (void)fprintf(stderr, "kgmon: get clockrate: %s\n",
+                               kvm_geterr(kvp->kd));
+               return (profrate);
+       }
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_CLOCKRATE;
+       clockrate.profhz = 1;
+       size = sizeof clockrate;
+       if (sysctl(mib, 2, &clockrate, &size, NULL, 0) < 0)
+               (void)fprintf(stderr, "kgmon: get clockrate: %s\n",
+                       strerror(errno));
+       return (clockrate.profhz);
+}
+
+/*
+ * Reset the kernel profiling date structures.
+ */
+void
+reset(kvp)
+       struct kvmvars *kvp;
+{
+       char *zbuf;
+       u_long biggest;
+       int mib[3];
+
+       setprof(kvp, GMON_PROF_OFF);
+
+       biggest = kvp->gpm.kcountsize;
+       if (kvp->gpm.fromssize > biggest)
+               biggest = kvp->gpm.fromssize;
+       if (kvp->gpm.tossize > biggest)
+               biggest = kvp->gpm.tossize;
+       if ((zbuf = (char *)malloc(biggest)) == NULL) {
+               fprintf(stderr, "kgmon: cannot allocate zbuf space\n");
+               exit(12);
+       }
+       bzero(zbuf, biggest);
+       if (kflag) {
+               if (kvm_write(kvp->kd, (u_long)kvp->gpm.kcount, zbuf,
+                   kvp->gpm.kcountsize) != kvp->gpm.kcountsize) {
+                       (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
+                           kvm_geterr(kvp->kd));
+                       exit(13);
+               }
+               if (kvm_write(kvp->kd, (u_long)kvp->gpm.froms, zbuf,
+                   kvp->gpm.fromssize) != kvp->gpm.fromssize) {
+                       (void)fprintf(stderr, "kgmon: froms zero: %s\n",
+                           kvm_geterr(kvp->kd));
+                       exit(14);
+               }
+               if (kvm_write(kvp->kd, (u_long)kvp->gpm.tos, zbuf,
+                   kvp->gpm.tossize) != kvp->gpm.tossize) {
+                       (void)fprintf(stderr, "kgmon: tos zero: %s\n",
+                           kvm_geterr(kvp->kd));
+                       exit(15);
+               }
+               return;
+       }
+       (void)seteuid(0);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROF;
+       mib[2] = GPROF_COUNT;
+       if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.kcountsize) < 0) {
+               (void)fprintf(stderr, "kgmon: tickbuf zero: %s\n",
+                   strerror(errno));
+               exit(13);
+       }
+       mib[2] = GPROF_FROMS;
+       if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.fromssize) < 0) {
+               (void)fprintf(stderr, "kgmon: froms zero: %s\n",
+                   strerror(errno));
+               exit(14);
+       }
+       mib[2] = GPROF_TOS;
+       if (sysctl(mib, 3, NULL, NULL, zbuf, kvp->gpm.tossize) < 0) {
+               (void)fprintf(stderr, "kgmon: tos zero: %s\n",
+                   strerror(errno));
+               exit(15);
+       }
+       (void)seteuid(getuid());
+       free(zbuf);
+}
diff --git a/kmodload.tproj/Makefile b/kmodload.tproj/Makefile
new file mode 100644 (file)
index 0000000..3704c8f
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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
+
+CFILES = 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)
+
+
+HEADER_PATHS =\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
+
+
+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
new file mode 100644 (file)
index 0000000..b5254fc
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..b8fba6b
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        HEADERSEARCH = ("$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders"); 
+        OTHER_LIBS = (kld); 
+        OTHER_LINKED = (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/kmodload.8 b/kmodload.tproj/kmodload.8
new file mode 100644 (file)
index 0000000..a5e6914
--- /dev/null
@@ -0,0 +1,93 @@
+.\"
+.\" 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
new file mode 100644 (file)
index 0000000..4976944
--- /dev/null
@@ -0,0 +1,740 @@
+/*
+ * 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.7 2001/02/05 19:53:16 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 <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>
+
+#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
+
+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;
+#define v_printf       if (verbose) printf
+
+// must not be static; kld library calls
+void                           kld_error_vprintf(const char *format, va_list ap);
+
+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                    cleanup_kernel_memory();
+static void                    link_base(const char *base,
+                                         const char **dependency_paths,
+                                         const vm_address_t *dependency_addrs);
+static void                    clear_globals(void);
+static void                    map_module(char *module_path, char **object_addr,
+                                          long *object_size, kmod_info_t **kinfo);
+static struct mach_header      *link_module(const char *filename, 
+                                            const char *output);
+static vm_address_t            patch_module(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: kmodsyms [-v] [-k kernelfile] [-d dependencyfile] -o symbolfile modulefile\n");
+               fprintf(stderr, "       kmodsyms [-v]  -k kernelfile  [-d dependencyfile@address] -o symbolfile modulefile@address\n");
+       } else {
+               fprintf(stderr, "usage: kmodload [-v] [-k kernelfile] [-d dependencyfile] [-o symbolfile] modulefile\n");
+       }
+       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;
+       char *module_addr = 0;
+       long module_size = 0;
+       vm_address_t module_faked_address = 0;
+       kmod_t module_id = 0;
+       kmod_info_t *file_kinfo;
+
+       if ((progname = rindex(argv[0], '/')) == NULL)
+               progname = argv[0];
+       else
+               ++progname;
+
+       kmodsyms = !strcmp(progname, "kmodsyms");
+
+       // 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:o:k:v")) != -1)
+               switch (c) {
+               case 'd':
+                       dependencies[dependency_count] = optarg;
+                       if (kmodsyms) {
+                               char *address;
+                               if ((address = rindex(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) {
+                               fprintf(stderr, "%s: internal error, dependency count overflow.\n", progname); 
+                               exit(KMOD_ERROR_INTERNAL);
+                       }
+                       break;
+               case 'o':
+                       gdbfile = optarg;
+                       break;
+               case 'k':
+                       kernel_set++;
+                       kernel = optarg;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       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 = rindex(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 module and then check if it has been loaded
+       map_module(module_path, &module_addr, &module_size, &file_kinfo);
+
+       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 (r) {
+                       fprintf(stderr, "%s: You must be running as root to load/check modules in the kernel.\n", progname);
+                       exit(KMOD_ERROR_PERMS);
+               }
+
+               //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) {
+                                       fprintf(stderr, "%s: the module named '%s' is already loaded.\n", progname, k->name); 
+                                       exit(KMOD_ERROR_ALREADY);
+                               } else {
+                                       module_faked_address = k->address;
+                               }
+                               break;
+                       }
+                       k = (k->next) ? (k + 1) : 0;
+               }
+
+               if (kmodsyms && !module_faked_address) {
+                       fprintf(stderr, "%s: the module named '%s' has not been loaded.\n", progname, file_kinfo->name); 
+                       exit(KMOD_ERROR_USAGE);
+               }
+               
+               //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)
+       }
+
+       // 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) {
+               fprintf(stderr, "%s: internal error, fell thru without setting module load address.\n", progname); 
+               exit(KMOD_ERROR_INTERNAL);
+           }
+       }
+
+       rld_header = link_module(module_path, gdbfile);
+       module_info = patch_module(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 (error == KERN_SUCCESS) return;
+       fprintf(stderr, "%s: %s: %s\n", progname, message, mach_error_string(error));
+}
+
+static void
+macherr(int error, const char *message)
+{
+       if (error == KERN_SUCCESS) return;
+       fprintf(stderr, "%s: %s: %s\n", progname, message, mach_error_string(error));
+
+       cleanup_kernel_memory();
+
+       exit(KMOD_ERROR_INTERNAL);
+}
+
+static void
+map_module(char *module_path, char **object_addr, long *object_size, kmod_info_t **kinfo)
+{
+       int fd;
+       struct stat stat_buf;
+       struct mach_header *mh;
+       char *p;
+
+       struct nlist nl[] = {
+               { "_kmod_info" },
+               { "" },
+       };
+
+       if((fd = open(module_path, O_RDONLY)) == -1){
+           fprintf(stderr, "%s: Can't open: %s\n", progname, module_path);
+           exit(KMOD_ERROR_USAGE);
+       }
+       if (nlist(module_path, nl)) {
+               fprintf(stderr, "%s: %s is not a valid kernel module.\n", progname, module_path);
+               exit(KMOD_ERROR_USAGE);
+       }
+       if(fstat(fd, &stat_buf) == -1){
+           fprintf(stderr, "%s: Can't stat file: %s\n", progname, module_path);
+           exit(KMOD_ERROR_PERMS);
+       }
+       *object_size = stat_buf.st_size;
+       if(map_fd(fd, 0, (vm_offset_t *)object_addr, TRUE, *object_size) != KERN_SUCCESS){
+           fprintf(stderr, "%s: Can't map file: %s\n", progname, module_path);
+           exit(KMOD_ERROR_INTERNAL);
+       }
+       close(fd);
+
+       if (NXSwapBigLongToHost(*((long *)*object_addr)) == FAT_MAGIC) {
+               struct host_basic_info hbi;
+               struct fat_header *fh;
+               struct fat_arch *fat_archs, *fap;
+               unsigned i, nfat_arch;
+
+               /* Get our host info */
+               i = HOST_BASIC_INFO_COUNT;
+               if (host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)(&hbi), &i) != KERN_SUCCESS) {
+                   fprintf(stderr, "%s: Can't get host's basic info\n", progname);
+                   exit(KMOD_ERROR_INTERNAL);
+               }
+
+               // get number of architectures
+               fh = (struct fat_header *)*object_addr;
+               nfat_arch = NXSwapBigLongToHost(fh->nfat_arch);
+
+               // find beginning of fat_arch struct
+               fat_archs = (struct fat_arch *)((char *)fh + sizeof(struct fat_header));
+
+               /*
+                * Convert archs to host byte ordering (a constraint of
+                * cpusubtype_getbestarch()
+                */
+               for (i = 0; i < nfat_arch; i++) {
+                       fat_archs[i].cputype =
+                               NXSwapBigLongToHost(fat_archs[i].cputype);
+                       fat_archs[i].cpusubtype =
+                             NXSwapBigLongToHost(fat_archs[i].cpusubtype);
+                       fat_archs[i].offset =
+                               NXSwapBigLongToHost(fat_archs[i].offset);
+                       fat_archs[i].size =
+                               NXSwapBigLongToHost(fat_archs[i].size);
+                       fat_archs[i].align =
+                               NXSwapBigLongToHost(fat_archs[i].align);
+               }
+
+// this code was lifted from Darwin/Libraries/NeXT/libc/gen.subproj/nlist.c
+// when cpusubtype_getbestarch exists this code should also be changed.
+#define        CPUSUBTYPE_SUPPORT      0
+
+#if    CPUSUBTYPE_SUPPORT
+               fap = cpusubtype_getbestarch(hbi.cpu_type, hbi.cpu_subtype,
+                                            fat_archs, nfat_arch);
+#else  CPUSUBTYPE_SUPPORT
+#warning       Use the cpusubtype functions!!!
+               fap = NULL;
+               for (i = 0; i < nfat_arch; i++) {
+                       if (fat_archs[i].cputype == hbi.cpu_type) {
+                               fap = &fat_archs[i];
+                               break;
+                       }
+               }
+#endif CPUSUBTYPE_SUPPORT
+               if (!fap) {
+                   fprintf(stderr, "%s: could not find the correct architecture in %s.\n", progname, module_path);
+                   exit(KMOD_ERROR_USAGE);
+               }
+               
+               *object_addr += fap->offset;
+               *object_size = fap->size;
+       }
+
+       mh = (struct mach_header *)*object_addr;
+       if (*((long *)mh) != MH_MAGIC) {
+           fprintf(stderr, "%s: invalid file format for file: %s\n", progname, module_path);
+           exit(KMOD_ERROR_USAGE);
+       }
+       p = *object_addr + sizeof(struct mach_header) + mh->sizeofcmds + nl->n_value;
+       *kinfo = (kmod_info_t *)p;
+}
+
+static void
+link_base(const char *base,
+         const char **dependency_paths,
+         const vm_address_t *dependency_addrs)
+{
+       struct mach_header *rld_header;
+       int ok;
+
+       ok = kld_load_basefile(base);
+       fflush(stdout);
+       if (!ok) {
+               fprintf(stderr, "%s: kld_load_basefile(%s) failed.\n", progname, base); 
+               exit(KMOD_ERROR_LOADING);
+       }
+
+       if (*dependency_paths) {
+               char **dependency = dependency_paths;
+               const vm_address_t *load_addr = dependency_addrs;
+
+               while (*dependency) {
+                       char *object_addr;
+                       long object_size;
+                       kmod_info_t *file_kinfo;
+
+                       map_module(*dependency, &object_addr, &object_size, &file_kinfo);
+
+                       // 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)) {
+                                                       fprintf(stderr, "%s: loaded kernel module '%s' version differs.\n",
+                                                               progname, *dependency);
+                                                       fprintf(stderr, "%s: loaded version '%s', file version '%s'.\n",
+                                                               progname, k->version, file_kinfo->version);
+                                                       exit(KMOD_ERROR_LOADING);
+                                               }
+                                               found_it++;
+                                               break;
+                                       }
+                                       k = (k->next) ? (k + 1) : 0;
+                               }
+                               if (!found_it) {
+                                       fprintf(stderr, "%s: kernel module '%s' is not loaded.\n", 
+                                               progname, *dependency);
+                                       exit(KMOD_ERROR_USAGE);
+                               }       
+                       
+                                tmp = malloc(sizeof(kmod_info_t));
+                               if (!tmp) {
+                                       fprintf(stderr, "%s: no memory.\n", progname);
+                                       exit(KMOD_ERROR_LOADING);
+                               }       
+                                *tmp = *k;
+                               tmp->next = module_dependencies;
+                               module_dependencies = tmp;
+
+                               faked_kernel_load_address = k->address;
+                       }
+
+                       rld_header = link_module(*dependency, 0);
+
+                       (void)patch_module(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("%s: Returning fake load address of 0x%8x\n",
+            progname, kernel_load_address);
+        return kernel_load_address;
+    }
+    if (kmodsyms) {
+        fprintf(stderr, "%s: internal error, almost tried to alloc kernel memory.\n", progname); 
+        exit(KMOD_ERROR_INTERNAL);
+    }
+
+    r = vm_allocate(kernel_port, &kernel_alloc_address, 
+        kernel_alloc_size, TRUE);
+    macherr(r, "unable to allocate kernel memory");
+
+    v_printf("%s: allocated %ld bytes in kernel space at 0x%8x\n",
+        progname, kernel_alloc_size, kernel_alloc_address);
+
+    kernel_load_address = kernel_alloc_address + kernel_hdr_pad;
+
+    v_printf("%s: Returning load address of 0x%x\n",
+        progname, kernel_load_address);
+
+    return kernel_load_address;
+}
+
+static void
+cleanup_kernel_memory()
+{
+       int r;
+
+       if (faked_kernel_load_address) return;  
+
+       if (kernel_alloc_address || kernel_alloc_size) {        
+               v_printf("%s: freeing %ld bytes in kernel space at 0x%x\n",
+                        progname, kernel_alloc_size, kernel_alloc_address);
+               r = vm_deallocate(kernel_port, kernel_alloc_address, kernel_alloc_size);
+                clear_globals();
+               kernel_load_address = kernel_load_size = 0;
+               machwarn(r, "unable to cleanup kernel memory");
+       }
+}
+
+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;
+       int ok;
+
+       kld_address_func(linkedit_address);
+
+       ok = kld_load(&rld_header, filename, output);
+       fflush(stdout);
+       if (!ok) {
+               fprintf(stderr, "%s: kld_load() failed.\n", progname);
+               cleanup_kernel_memory();
+               exit(KMOD_ERROR_LOADING);
+       }
+
+       return rld_header;
+}
+
+vm_address_t
+patch_module(struct mach_header *mach_header)
+{
+       char * symbol = "_kmod_info";
+       kmod_info_t *info;
+       unsigned long value;
+       int ok;
+
+       ok = kld_lookup(symbol, &value);
+       fflush(stdout);
+       if (!ok) {
+               fprintf(stderr, "%s: kld_lookup(%s) failed.\n", progname, symbol);
+               cleanup_kernel_memory();
+               exit(KMOD_ERROR_LOADING);
+       }
+
+       ok = kld_forget_symbol(symbol);
+       fflush(stdout);
+       if (!ok) {
+               fprintf(stderr, "%s: kld_forget_symbol(%s) failed.\n", progname, symbol);
+               cleanup_kernel_memory();
+               exit(KMOD_ERROR_INTERNAL);
+       }
+
+       /* 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("%s: kmod name: %s\n", progname, info->name);
+       v_printf("%s: kmod start @ 0x%x\n", progname, (vm_address_t)info->start);
+       v_printf("%s: kmod stop  @ 0x%x\n", progname, (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) {
+               fprintf(stderr, "%s: invalid start address?\n", progname);
+               cleanup_kernel_memory();
+               exit(KMOD_ERROR_LOADING);
+       }
+       if (!info->stop) {
+               fprintf(stderr, "%s: invalid stop address?\n", progname);
+               cleanup_kernel_memory();
+               exit(KMOD_ERROR_LOADING);
+       }
+
+       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("%s: kmod id %d successfully created at 0x%x size %ld.\n", 
+        progname, 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");
+                       exit(KMOD_ERROR_INTERNAL);
+               }
+
+               v_printf("%s: kmod id %d reference count was sucessfully incremented.\n", progname, 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");
+               exit(KMOD_ERROR_INTERNAL);
+       }
+
+       v_printf("%s: kmod id %d successfully started.\n", progname, id);
+}
+
+void
+kld_error_vprintf(const char *format, va_list ap){
+    vfprintf(stderr, format, ap);
+    return;
+}
diff --git a/kmodload.tproj/kmodsyms.8 b/kmodload.tproj/kmodsyms.8
new file mode 100644 (file)
index 0000000..f3f18cf
--- /dev/null
@@ -0,0 +1,105 @@
+.\"
+.\" 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
new file mode 100644 (file)
index 0000000..2c9f9ed
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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
new file mode 100644 (file)
index 0000000..5d1130d
--- /dev/null
@@ -0,0 +1,106 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..8e9b705
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    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
new file mode 100644 (file)
index 0000000..2353406
--- /dev/null
@@ -0,0 +1,64 @@
+.\"
+.\" 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
new file mode 100644 (file)
index 0000000..2f39c73
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..1700393
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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
new file mode 100644 (file)
index 0000000..c2d62c5
--- /dev/null
@@ -0,0 +1,106 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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
new file mode 100644 (file)
index 0000000..7d909c1
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    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
new file mode 100644 (file)
index 0000000..358030c
--- /dev/null
@@ -0,0 +1,69 @@
+.\"
+.\" 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
new file mode 100644 (file)
index 0000000..4fb96b0
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * 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;
+}
+
diff --git a/ktrace.tproj/Makefile b/ktrace.tproj/Makefile
new file mode 100644 (file)
index 0000000..6369360
--- /dev/null
@@ -0,0 +1,55 @@
+#
+# 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 = ktrace
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = ktrace.h
+
+CFILES = ktrace.c subr.c
+
+OTHERSRCS = Makefile.preamble Makefile ktrace.1
+
+
+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)
+
+
+NEXTSTEP_PB_CFLAGS = -DMACH_USER_API
+WINDOWS_PB_CFLAGS = -DMACH_USER_API
+PDO_UNIX_PB_CFLAGS = -DMACH_USER_API
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/ktrace.tproj/Makefile.preamble b/ktrace.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/ktrace.tproj/PB.project b/ktrace.tproj/PB.project
new file mode 100644 (file)
index 0000000..c0b395a
--- /dev/null
@@ -0,0 +1,38 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        CLASSES = (); 
+        FRAMEWORKS = (); 
+        HEADERSEARCH = (); 
+        H_FILES = (ktrace.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (ktrace.c, subr.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, ktrace.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DMACH_USER_API"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = ktrace; 
+    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 = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = ktrace; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = ktrace; 
+    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 = ktrace; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/ktrace.tproj/ktrace.1 b/ktrace.tproj/ktrace.1
new file mode 100644 (file)
index 0000000..d080b4e
--- /dev/null
@@ -0,0 +1,163 @@
+.\" 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.
+.\"
+.\"    @(#)ktrace.1    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt KTRACE 1
+.Os BSD 4.4
+.Sh NAME
+.Nm ktrace
+.Nd enable kernel process tracing
+.Sh SYNOPSIS
+.Nm ktrace
+.Op Fl aCcdi
+.Op Fl f Ar trfile
+.Op Fl g Ar pgrp
+.Op Fl p Ar pid
+.Op Fl t Ar trstr
+.Nm ktrace
+.Op Fl adi
+.Op Fl f Ar trfile
+.Op Fl t Ar trstr
+command
+.Sh DESCRIPTION
+.Nm Ktrace
+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
+translations, signal processing, and
+.Tn I/O .
+.Pp
+Once tracing is enabled on a process, trace data will be logged until
+either the process exits or the trace point is cleared.
+A traced process can generate enormous amounts of log data quickly;
+It is strongly suggested that users memorize how to disable tracing before
+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
+.Pp
+The trace file is not human readable; use
+.Xr kdump 1
+to decode it.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl a
+Append to the trace file instead of truncating it.
+.It Fl C
+Disable tracing on all user owned processes, and, if executed by root, all
+processes in the system.
+.It Fl c
+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 
+Log trace records to
+.Ar file
+instead of
+.Pa ktrace.out .
+.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 
+Enable (disable) tracing on the indicated process id (only one
+.Fl p
+flag is permitted).
+.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
+.Bl -tag -width flag -compact
+.It Cm c
+trace system calls
+.It Cm n
+trace namei translations
+.It Cm i
+trace
+.Tn I/O
+.It Cm s
+trace signal processing
+.El
+.It Ar command
+Execute
+.Ar command
+with the specified trace flags.
+.El
+.Pp
+The
+.Fl p ,
+.Fl g ,
+and
+.Ar command
+options are mutually exclusive.
+.Sh EXAMPLES
+# trace all kernel operations of process id 34
+.Dl $ ktrace -p 34
+.Pp
+# trace all kernel operations of processes in process group 15 and
+# pass the trace flags to all current and future children
+.Dl $ ktrace -idg 15
+.Pp
+# disable all tracing of process 65
+.Dl $ ktrace -cp 65
+.Pp
+# disable tracing signals on process 70 and all current children
+.Dl $ ktrace -t s -cdp 70
+.Pp
+# enable tracing of
+.Tn I/O
+on process 67
+.Dl $ ktrace -ti -p 67
+.Pp
+# run the command "w", tracing only system calls
+.Dl $ ktrace -tc w
+.Pp
+# disable all tracing to the file "tracedata"
+.Dl $ ktrace -c -f tracedata
+.Pp
+# disable tracing of all processes owned by the user
+.Dl $ ktrace -C
+.Sh SEE ALSO
+.Xr kdump 1
+.Sh HISTORY
+The
+.Nm ktrace
+command appears in
+.Bx 4.4 .
diff --git a/ktrace.tproj/ktrace.c b/ktrace.tproj/ktrace.c
new file mode 100644 (file)
index 0000000..188e9ba
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <sys/uio.h>
+#include <sys/ktrace.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "ktrace.h"
+
+void no_ktrace __P((int));
+void usage __P((void));
+
+main(argc, argv)
+       int argc;
+       char **argv;
+{
+       enum { NOTSET, CLEAR, CLEARALL } clear;
+       int append, ch, fd, inherit, ops, pid, pidset, trpoints;
+       char *tracefile;
+
+       clear = NOTSET;
+       append = ops = pidset = inherit = 0;
+       trpoints = DEF_POINTS;
+       tracefile = DEF_TRACEFILE;
+       while ((ch = getopt(argc,argv,"aCcdf:g:ip:t:")) != EOF)
+               switch((char)ch) {
+               case 'a':
+                       append = 1;
+                       break;
+               case 'C':
+                       clear = CLEARALL;
+                       pidset = 1;
+                       break;
+               case 'c':
+                       clear = CLEAR;
+                       break;
+               case 'd':
+                       ops |= KTRFLAG_DESCEND;
+                       break;
+               case 'f':
+                       tracefile = optarg;
+                       break;
+               case 'g':
+                       pid = -rpid(optarg);
+                       pidset = 1;
+                       break;
+               case 'i':
+                       inherit = 1;
+                       break;
+               case 'p':
+                       pid = rpid(optarg);
+                       pidset = 1;
+                       break;
+               case 't':
+                       trpoints = getpoints(optarg);
+                       if (trpoints < 0) {
+                               warnx("unknown facility in %s", optarg);
+                               usage();
+                       }
+                       break;
+               default:
+                       usage();
+               }
+       argv += optind;
+       argc -= optind;
+       
+       if (pidset && *argv || !pidset && !*argv)
+               usage();
+                       
+       if (inherit)
+               trpoints |= KTRFAC_INHERIT;
+
+       (void)signal(SIGSYS, no_ktrace);
+       if (clear != NOTSET) {
+               if (clear == CLEARALL) {
+                       ops = KTROP_CLEAR | KTRFLAG_DESCEND;
+                       trpoints = ALL_POINTS;
+                       pid = 1;
+               } else
+                       ops |= pid ? KTROP_CLEAR : KTROP_CLEARFILE;
+
+               if (ktrace(tracefile, ops, trpoints, pid) < 0)
+                       err(1, tracefile);
+               exit(0);
+       }
+
+       if ((fd = open(tracefile, O_CREAT | O_WRONLY | (append ? 0 : O_TRUNC),
+           DEFFILEMODE)) < 0)
+               err(1, tracefile);
+       (void)close(fd);
+
+       if (*argv) { 
+               if (ktrace(tracefile, ops, trpoints, getpid()) < 0)
+                       err(1, 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);
+       exit(0);
+}
+
+rpid(p)
+       char *p;
+{
+       static int first;
+
+       if (first++) {
+               warnx("only one -g or -p flag is permitted.");
+               usage();
+       }
+       if (!*p) {
+               warnx("illegal process id.");
+               usage();
+       }
+       return(atoi(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");
+       exit(1);
+}
+
+void
+no_ktrace(sig)
+        int sig;
+{
+        (void)fprintf(stderr,
+"error:\tktrace() system call not supported in the running kernel\n\tre-compile kernel with 'options KTRACE'\n");
+        exit(1);
+}
diff --git a/ktrace.tproj/ktrace.h b/ktrace.tproj/ktrace.h
new file mode 100644 (file)
index 0000000..75c4eab
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ *
+ *     @(#)ktrace.h    8.1 (Berkeley) 6/6/93
+ */
+
+#define DEF_POINTS (KTRFAC_SYSCALL | KTRFAC_SYSRET | KTRFAC_NAMEI | \
+                 KTRFAC_GENIO | KTRFAC_PSIG)
+
+#define ALL_POINTS (DEF_POINTS | KTRFAC_CSW)
+
+#define DEF_TRACEFILE  "ktrace.out"
diff --git a/ktrace.tproj/subr.c b/ktrace.tproj/subr.c
new file mode 100644 (file)
index 0000000..08be415
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/user.h>
+#include <sys/proc.h>
+#include <sys/time.h>
+#include <sys/ktrace.h>
+
+#include <stdio.h>
+
+#include "ktrace.h"
+
+getpoints(s)
+       char *s;
+{
+       int facs = 0;
+
+       while (*s) {
+               switch(*s) {
+               case 'c':
+                       facs |= KTRFAC_SYSCALL | KTRFAC_SYSRET;
+                       break;
+               case 'n':
+                       facs |= KTRFAC_NAMEI;
+                       break;
+               case 'i':
+                       facs |= KTRFAC_GENIO;
+                       break;
+               case 's':
+                       facs |= KTRFAC_PSIG;
+                       break;
+               case 'w':
+                       facs |= KTRFAC_CSW;
+                       break;
+               case '+':
+                       facs |= DEF_POINTS;
+                       break;
+               default:
+                       return (-1);
+               }
+               s++;
+       }
+       return (facs);
+}
+
+timevaladd(t1, t2)
+       struct timeval *t1, *t2;
+{
+       t1->tv_sec += t2->tv_sec;
+       t1->tv_usec += t2->tv_usec;
+       timevalfix(t1);
+}
+
+timevalsub(t1, t2)
+       struct timeval *t1, *t2;
+{
+       t1->tv_sec -= t2->tv_sec;
+       t1->tv_usec -= t2->tv_usec;
+       timevalfix(t1);
+}
+
+timevalfix(t1)
+       struct timeval *t1;
+{
+       if (t1->tv_usec < 0) {
+               t1->tv_sec--;
+               t1->tv_usec += 1000000;
+       }
+       if (t1->tv_usec >= 1000000) {
+               t1->tv_sec++;
+               t1->tv_usec -= 1000000;
+       }
+}
diff --git a/latency.tproj/Makefile b/latency.tproj/Makefile
new file mode 100644 (file)
index 0000000..b647e65
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = latency
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = latency.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble latency.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I$(NEXT_ROOT)/System/Library/System.framework/\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd\
+               -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd
+
+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/latency.tproj/Makefile.postamble b/latency.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..13c3721
--- /dev/null
@@ -0,0 +1,105 @@
+###############################################################################
+#  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/man1
+       install -c -m 444 latency.1 $(DSTROOT)/usr/share/man/man1/latency.1
+
diff --git a/latency.tproj/Makefile.preamble b/latency.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..a4606c6
--- /dev/null
@@ -0,0 +1,140 @@
+###############################################################################
+#  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)
+
+AFTER_INSTALL += install-man-page
+
diff --git a/latency.tproj/PB.project b/latency.tproj/PB.project
new file mode 100644 (file)
index 0000000..4774afa
--- /dev/null
@@ -0,0 +1,31 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        HEADERSEARCH = (
+            "$(NEXT_ROOT)/System/Library/System.framework/", 
+            "$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders", 
+            "$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd", 
+            "$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd"
+        ); 
+        H_FILES = (); 
+        OTHER_LINKED = (latency.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, latency.1); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    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 = latency; 
+    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/latency.tproj/latency.1 b/latency.tproj/latency.1
new file mode 100644 (file)
index 0000000..40b23d6
--- /dev/null
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2000, Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd March 28, 2000
+.Dt LATENCY 1
+.Os "Mac OS X"
+.Sh NAME
+.Nm latency
+.Nd monitors scheduling and interrupt latency
+.Sh SYNOPSIS
+.Nm latency
+.Op Fl rt
+.Op Fl c Ar codefile
+.Op Fl l Ar logfile
+.Op Fl st Ar threshold
+.Op Fl it Ar threshold
+.Op Fl s Ar sleep_in_usecs
+.Op Fl d Ar decrementer_in_usecs
+.Op Fl n Ar kernel
+.Sh DESCRIPTION
+.Nm latency
+provides scheduling and interrupt latency statistics.
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl rt
+Set real time scheduling policy. Default policy is timeshare.
+.It Fl c
+When the
+.Fl c
+option is specified, it takes a path to a 
+.Ar codefile 
+that
+contains the mappings for the system calls.  This option
+overrides the default location of the system call codefile
+which is found in /usr/share/misc/trace.codes.
+.It Fl l
+Specifies a
+.Ar logfile
+that is written to when either the interrupt or scheduling
+latency is exceeded.
+.It Fl st
+Set the scheduler latency threshold in microseconds.  If latency
+exceeds this, and a logfile has been specified, a record
+of what occurred during this time is recorded.
+.It Fl it
+Set the interrupt latency threshold in microseconds.  If latency
+exceeds this, and a logfile has been specified, a record
+of what occurred during this time is recorded.
+.It Fl s
+The
+.Fl s
+option sets the timer.  It takes microseconds as an argument,
+the default timer is set to 1000 microseconds.
+.It Fl d
+The
+.Fl d
+option sets the decrementer.  It takes microseconds as an argument.
+The decrementer is set back to the system default on exit.
+.It Fl n
+By default,
+.Nm latency
+acts on the default /mach_kernel.  This option
+allows you to specify an alternate booted kernel.
+.El
+.Pp
+The data columns displayed are as follows:
+.Bl -tag -width LAST_PATHNAME_WAITED_FOR -compact
+.Pp
+.It SCHEDULER
+The number of context switches that fall
+within the described delay.
+.It INTERRUPTS
+The number of interrupts that fall
+within the described delay.
+.El
+.Pp
+The
+.Nm latency
+command is also SIGWINCH savvy, so adjusting your window geometry will change
+the list of delay values displayed.
+.Sh SAMPLE USAGE
+.Pp
+latency -rt -st 20000 -it 1000 -l /var/tmp/latency.log
+.Pp
+.Nm latency
+will set the realtime scheduling policy.  The threshold for the scheduler is set to
+20000 microseconds.  The threshold for interrupts is set to 1000
+microseconds.  Latencies that exceed these thresholds will be logged
+in /var/tmp/latency.log.
+.Sh SEE ALSO
+.Xr top 1
+.Xr fs_usage 1
+.Xr sc_usage 1
diff --git a/latency.tproj/latency.c b/latency.tproj/latency.c
new file mode 100644 (file)
index 0000000..16ef9e7
--- /dev/null
@@ -0,0 +1,2150 @@
+/*
+ * 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@
+ */
+
+
+/* 
+   cc -I. -DKERNEL_PRIVATE -O -o latency latency.c
+*/
+
+#include <mach/mach.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <nlist.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <libc.h>
+#include <termios.h>
+#include <bsd/curses.h>
+#include <sys/ioctl.h>
+
+#ifndef KERNEL_PRIVATE
+#define KERNEL_PRIVATE
+#include <sys/kdebug.h>
+#undef KERNEL_PRIVATE
+#else
+#include <sys/kdebug.h>
+#endif /*KERNEL_PRIVATE*/
+
+#include <sys/sysctl.h>
+#include <errno.h>
+#include <err.h>
+
+#include <mach/host_info.h>
+#include <mach/mach_error.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/mach_syscalls.h>
+#include <mach/clock.h>
+#include <mach/clock_types.h>
+
+#include <libkern/OSTypes.h>
+
+extern mach_port_t clock_port;
+
+#define KERN_KDPIDEX    14
+
+
+int      s_usec_10_bins[10];
+int      s_usec_100_bins[10];
+int      s_msec_1_bins[10];
+int      s_msec_10_bins[5];
+int      s_too_slow;
+int      s_max_latency;
+int      s_min_latency = 0;
+long long s_total_latency = 0;
+int      s_total_samples;
+long     s_thresh_hold;
+int      s_exceeded_threshold = 0;
+
+int      i_usec_10_bins[10];
+int      i_usec_100_bins[10];
+int      i_msec_1_bins[10];
+int      i_msec_10_bins[5];
+int      i_too_slow;
+int      i_max_latency;
+int      i_min_latency = 0;
+long long i_total_latency = 0;
+int      i_total_samples;
+long     i_thresh_hold;
+int      i_exceeded_threshold = 0;
+
+long     start_time;
+long     curr_time;
+long     refresh_time;
+
+char     *policy_name;
+int      my_policy;
+int      my_pri = -1;
+int      num_of_usecs_to_sleep = 1000;
+
+char *kernelpath = (char *)0;
+char *code_file = (char *)0;
+
+typedef struct {
+  u_long  k_sym_addr;       /* kernel symbol address from nm */
+  u_int   k_sym_len;        /* length of kernel symbol string */
+  char   *k_sym_name;       /* kernel symbol string from nm */
+} kern_sym_t;
+
+kern_sym_t *kern_sym_tbl;      /* pointer to the nm table       */
+int        kern_sym_count;    /* number of entries in nm table */
+char       pcstring[128];
+
+#define UNKNOWN "Can't find symbol name"
+
+
+double   divisor;
+int      gotSIGWINCH = 0;
+int      trace_enabled = 0;
+
+#define SAMPLE_SIZE 300000
+
+int mib[6];
+size_t needed;
+char  *my_buffer;
+
+kbufinfo_t bufinfo = {0, 0, 0};
+
+FILE *log_fp = (FILE *)0;
+int num_of_codes = 0;
+int need_new_map = 0;
+int total_threads = 0;
+kd_threadmap *mapptr = 0;
+
+#define MAX_ENTRIES 1024
+struct ct {
+        int type;
+        char name[32];
+} codes_tab[MAX_ENTRIES];
+
+
+struct th_info {
+        int  thread;
+        int  type;
+        int  child_thread;
+        int  vfslookup;
+        int  arg1;
+        double stime;
+        char pathname[32];
+};
+
+#define MAX_THREADS 512
+struct th_info th_state[MAX_THREADS];
+
+int  cur_max = 0;
+
+#define TRACE_DATA_NEWTHREAD   0x07000004
+#define TRACE_STRING_NEWTHREAD 0x07010004
+#define TRACE_STRING_EXEC      0x07010008
+
+#define INTERRUPT         0x01050000
+#define DECR_TRAP         0x01090000
+#define DECR_SET          0x01090004
+#define MACH_vmfault      0x01300000
+#define MACH_sched        0x01400000
+#define MACH_stkhandoff   0x01400008
+#define VFS_LOOKUP        0x03010090
+#define BSC_exit          0x040C0004
+#define IES_action        0x050b0018
+#define IES_filter        0x050b001c
+#define TES_action        0x050c0010
+#define CQ_action         0x050d0018
+
+
+#define DBG_FUNC_ALL   (DBG_FUNC_START | DBG_FUNC_END)
+#define DBG_FUNC_MASK  0xfffffffc
+
+#define DBG_ZERO_FILL_FAULT   1
+#define DBG_PAGEIN_FAULT      2
+#define DBG_COW_FAULT         3
+#define DBG_CACHE_HIT_FAULT   4
+
+char *fault_name[5] = {
+        "",
+       "ZeroFill",
+       "PageIn",
+       "COW",
+       "CacheHit",
+};
+
+char *pc_to_string();
+static kern_return_t   set_time_constraint_policy(void);
+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 */
+
+/* raw read of the timebase register */
+void clock_get_uptime( register AbsoluteTime *result)
+{
+#ifdef __ppc__
+
+        register UInt32  hic;
+        do {
+         asm volatile("  mftbu %0" : "=r" (result->hi));
+         asm volatile("  mftb  %0" : "=r" (result->lo));
+         asm volatile("  mftbu %0" : "=r" (hic));
+        } while (hic != result->hi);
+
+#else
+        result->lo = 0;
+        result->hi = 0;
+#endif /* __ppc__ */
+
+}
+
+typedef unsigned long long  abstime_scalar_t;
+
+#define AbsoluteTime_to_scalar(x)   \
+                        (*(abstime_scalar_t *)(x))
+
+/* t1 += t2 */
+#define ADD_ABSOLUTETIME(t1, t2)                \
+       (AbsoluteTime_to_scalar(t1) +=              \
+                               AbsoluteTime_to_scalar(t2))
+
+/* t1 -= t2 */
+#define SUB_ABSOLUTETIME(t1, t2)                \
+       (AbsoluteTime_to_scalar(t1) -=              \
+                               AbsoluteTime_to_scalar(t2))
+
+int
+quit(s)
+char *s;
+{
+        void set_enable();
+       void set_rtcdec();
+       void set_remove();
+
+        if (trace_enabled)
+               set_enable(0);
+
+       /* 
+          This flag is turned off when calling
+          quit() due to a set_remove() failure.
+       */
+       if (set_remove_flag)
+         set_remove();
+
+       if (decrementer_val)
+         set_rtcdec(0);
+
+        printf("latency: ");
+       if (s)
+               printf("%s", s);
+
+       exit(1);
+}
+
+void
+set_enable(int val) 
+{
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDENABLE;         /* protocol */
+       mib[3] = val;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+
+       if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDENABLE\n");
+}
+
+void
+set_numbufs(int nbufs) 
+{
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETBUF;
+       mib[3] = nbufs;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETBUF\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+
+}
+
+void
+set_pidexclude(int pid, int on_off) 
+{
+        kd_regtype kr;
+
+       kr.type = KDBG_TYPENONE;
+       kr.value1 = pid;
+       kr.value2 = on_off;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDPIDEX;
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;
+
+       sysctl(mib, 3, &kr, &needed, NULL, 0);
+}
+
+set_rtcdec(decval)
+int decval;
+{kd_regtype kr;
+ int ret;
+ extern int errno;
+
+       kr.type = KDBG_TYPENONE;
+       kr.value1 = decval;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETRTCDEC;              /* protocol */
+       mib[3] = 0;             /* wildcard address family */
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       errno = 0;
+
+       if ((ret=sysctl(mib, 3, &kr, &needed, NULL, 0)) < 0)
+         {
+           decrementer_val = 0;
+           quit("trace facility failure, KERN_KDSETRTCDEC\n");
+         }
+}
+
+
+void
+get_bufinfo(kbufinfo_t *val)
+{
+        needed = sizeof (*val);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDGETBUF;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
+               quit("trace facility failure, KERN_KDGETBUF\n");
+
+}
+
+void
+set_remove() 
+{
+  extern int errno;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDREMOVE;         /* protocol */
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       errno = 0;
+
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+         {
+             set_remove_flag = 0;
+             if(errno == EBUSY)
+                 quit("the trace facility is currently in use...\n         fs_usage, sc_usage, and latency use this feature.\n\n");
+             else
+                 quit("trace facility failure, KERN_KDREMOVE\n");
+         }
+}
+
+void
+set_init_nologging()
+{
+        /* When we aren't logging, only collect the DECR_TRAP trace points */
+        kd_regtype kr;
+        kr.type = KDBG_VALCHECK;
+        kr.value1 = DECR_TRAP;
+       kr.value2 = 0;
+        kr.value3 = 0;
+        kr.value4 = 0;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETREG;
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETREG\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+}
+
+void
+set_init_logging() 
+{       kd_regtype kr;
+
+       kr.type = KDBG_RANGETYPE;
+       kr.value1 = 0;  
+       kr.value2 = -1;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETREG;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETREG\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+}
+
+
+void sigwinch()
+{
+        gotSIGWINCH = 1;
+}
+
+void sigintr()
+{
+        void screen_update();
+
+        set_enable(0);
+       set_pidexclude(getpid(), 0);
+        screen_update(log_fp);
+       set_rtcdec(0);
+       set_remove();
+       
+        exit(1);
+}
+
+void sigquit()
+{
+        set_enable(0);
+       set_pidexclude(getpid(), 0);
+       set_rtcdec(0);
+       set_remove();
+       
+        exit(1);
+}
+
+void sigterm()
+{
+        set_enable(0);
+       set_pidexclude(getpid(), 0);
+       set_rtcdec(0);
+       set_remove();
+       
+        exit(1);
+}
+
+
+void
+screen_update(FILE *fp)
+{
+        int  i;
+       int  itotal, stotal;
+       int  elapsed_secs;
+       int  elapsed_mins;
+       int  elapsed_hours;
+       unsigned int average_s_latency;
+       unsigned int average_i_latency;
+       char tbuf[256];
+
+       if (fp == (FILE *)0) {
+               erase();
+               move(0, 0);
+       } else
+               fprintf(fp,"\n\n===================================================================================================\n");
+       /*
+        *  Display the current time.
+        *  "ctime" always returns a string that looks like this:
+        *  
+        *      Sun Sep 16 01:03:52 1973
+        *      012345678901234567890123
+        *                1         2
+        *
+        *  We want indices 11 thru 18 (length 8).
+        */
+       elapsed_secs = curr_time - start_time;
+       elapsed_hours = elapsed_secs / 3600;
+       elapsed_secs -= elapsed_hours * 3600;
+       elapsed_mins = elapsed_secs / 60;
+       elapsed_secs -= elapsed_mins * 60;
+
+       sprintf(tbuf, "%-19.19s                            %2ld:%02ld:%02ld\n", &(ctime(&curr_time)[0]),
+               elapsed_hours, elapsed_mins, elapsed_secs);
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       sprintf(tbuf, "                     SCHEDULER     INTERRUPTS\n");
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+       sprintf(tbuf, "---------------------------------------------\n");
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       sprintf(tbuf, "total_samples       %10d     %10d\n\n", s_total_samples, i_total_samples);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       for (itotal = 0, stotal = 0, i = 0; i < 10; i++) {
+               sprintf(tbuf, "delays < %3d usecs  %10d     %10d\n", (i + 1) * 10, s_usec_10_bins[i], i_usec_10_bins[i]);
+
+               if (fp)
+                       fprintf(fp, "%s", tbuf);
+               else
+                       printw(tbuf);
+
+               stotal += s_usec_10_bins[i];
+               itotal += i_usec_10_bins[i];
+       }
+       sprintf(tbuf, "total  < 100 usecs  %10d     %10d\n\n", stotal, itotal);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       for (itotal = 0, stotal = 0, i = 1; i < 10; i++) {
+               if (i < 9)
+                       sprintf(tbuf, "delays < %3d usecs  %10d     %10d\n", (i + 1) * 100, s_usec_100_bins[i], i_usec_100_bins[i]);
+               else
+                       sprintf(tbuf, "delays <   1 msec   %10d     %10d\n", s_usec_100_bins[i], i_usec_100_bins[i]);
+
+               if (fp)
+                       fprintf(fp, "%s", tbuf);
+               else
+                       printw(tbuf);
+
+               stotal += s_usec_100_bins[i];
+               itotal += i_usec_100_bins[i];
+       }
+       sprintf(tbuf, "total  <   1 msec   %10d     %10d\n\n", stotal, itotal);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       for (itotal = 0, stotal = 0, i = 1; i < 10; i++) {
+               sprintf(tbuf, "delays < %3d msecs  %10d     %10d\n", (i + 1), s_msec_1_bins[i], i_msec_1_bins[i]);
+
+               if (fp)
+                       fprintf(fp, "%s", tbuf);
+               else
+                       printw(tbuf);
+
+               stotal += s_msec_1_bins[i];
+               itotal += i_msec_1_bins[i];
+       }
+       sprintf(tbuf, "total  <  10 msecs  %10d     %10d\n\n", stotal, itotal);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+
+       for (itotal = 0, stotal = 0, i = 1; i < 5; i++) {
+               sprintf(tbuf, "delays < %3d msecs  %10d     %10d\n", (i + 1)*10, s_msec_10_bins[i], i_msec_10_bins[i]);
+
+               if (fp)
+                       fprintf(fp, "%s", tbuf);
+               else
+                       printw(tbuf);
+
+               stotal += s_msec_10_bins[i];
+               itotal += i_msec_10_bins[i];
+       }
+       sprintf(tbuf, "total  <  50 msecs  %10d     %10d\n\n", stotal, itotal);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+       sprintf(tbuf, "delays >  50 msecs  %10d     %10d\n", s_too_slow, i_too_slow);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       sprintf(tbuf, "\nminimum latency(usecs) %7d        %7d\n", s_min_latency, i_min_latency);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+       sprintf(tbuf, "maximum latency(usecs) %7d        %7d\n", s_max_latency, i_max_latency);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+       if (s_total_samples)
+         average_s_latency = (unsigned int)(s_total_latency/s_total_samples);
+       else
+         average_s_latency = 0;
+
+       if (i_total_samples)
+         average_i_latency = (unsigned int)(i_total_latency/i_total_samples);
+       else
+         average_i_latency = 0;
+
+       sprintf(tbuf, "average latency(usecs) %7d        %7d\n", average_s_latency, average_i_latency);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+       sprintf(tbuf, "exceeded threshold     %7d        %7d\n", s_exceeded_threshold, i_exceeded_threshold);
+
+       if (fp)
+               fprintf(fp, "%s", tbuf);
+       else
+               printw(tbuf);
+
+       if (fp == (FILE *)0)
+               refresh();
+       else
+               fflush(fp);
+}
+
+int
+exit_usage()
+{
+
+        fprintf(stderr, "Usage: latency [-rt] [-c codefile] [-l logfile] [-st threshold]\n");
+       fprintf(stderr, "               [-it threshold] [-s sleep_in_usecs]\n");
+       fprintf(stderr, "               [-d decrementer_in_usecs] [-n kernel]\n\n");
+
+       fprintf(stderr, "  -rt   Set realtime scheduling policy.  Default is timeshare.\n");
+       fprintf(stderr, "  -c    specify name of codes file\n");
+       fprintf(stderr, "  -l    specify name of file to log trace entries to when threshold is exceeded\n");
+       fprintf(stderr, "  -st   set scheduler latency threshold in microseconds... if latency exceeds this, then log trace\n");
+       fprintf(stderr, "  -it   set interrupt latency threshold in microseconds... if latency exceeds this, then log trace\n");
+       fprintf(stderr, "  -s    set sleep time in microseconds\n");
+       fprintf(stderr, "  -d    set decrementer in microseconds.\n");
+       fprintf(stderr, "  -n    specify kernel, default is /mach_kernel\n");   
+
+       fprintf(stderr, "\nlatency must be run as root\n\n");
+
+       exit(1);
+}
+
+
+
+main(argc, argv)
+int  argc;
+char *argv[];
+{
+        mach_timespec_t remain;
+       unsigned long long start, stop;
+       AbsoluteTime timestamp1;
+       AbsoluteTime timestamp2;
+       AbsoluteTime adeadline, adelay;
+       double fdelay;
+       int      elapsed_usecs;
+       double   nanosecs_to_sleep;
+       int      loop_cnt, sample_sc_now;
+       int      decrementer_usec = 0;
+       void     getdivisor();
+       void     sample_sc();
+       void     init_code_file();
+       void     do_kernel_nm();
+       void     open_logfile();
+
+       my_policy = THREAD_STANDARD_POLICY;
+       policy_name = "TIMESHARE";
+
+       while (argc > 1) {
+               if (strcmp(argv[1], "-rt") == 0) {
+                       my_policy = THREAD_TIME_CONSTRAINT_POLICY;   /* the real time band */
+                       policy_name = "REALTIME";
+
+               } else if (strcmp(argv[1], "-st") == 0) {
+                       argc--;
+                       argv++;
+
+                       if (argc > 1)
+                         s_thresh_hold = atoi(argv[1]);
+                       else
+                         exit_usage();
+                       
+               } else if (strcmp(argv[1], "-it") == 0) {
+                       argc--;
+                       argv++;
+                       
+                       if (argc > 1)
+                         i_thresh_hold = atoi(argv[1]);
+                       else
+                         exit_usage();
+               } else if (strcmp(argv[1], "-c") == 0) {
+                       argc--;
+                       argv++;
+                       
+                       if (argc > 1)
+                         code_file = argv[1];
+                       else
+                         exit_usage();
+               } else if (strcmp(argv[1], "-l") == 0) {
+                       argc--;
+                       argv++;
+                       
+                       if (argc > 1)
+                         open_logfile(argv[1]);
+                       else
+                         exit_usage();
+
+               } else if (strcmp(argv[1], "-s") == 0) {
+                       argc--;
+                       argv++;
+
+                       if (argc > 1)
+                         num_of_usecs_to_sleep = atoi(argv[1]);
+                       else
+                         exit_usage();
+               } else if (strcmp(argv[1], "-d") == 0) {
+                       argc--;
+                       argv++;
+
+                       if (argc > 1)
+                         decrementer_usec = atoi(argv[1]);
+                       else
+                         exit_usage();
+               } else if (strcmp(argv[1], "-n") == 0) {
+                       argc--;
+                       argv++;
+
+                       if (argc > 1)
+                         kernelpath = argv[1];
+                       else
+                         exit_usage();
+               } else
+                       exit_usage();
+
+               argc--;
+               argv++;
+       }
+
+        if ( geteuid() != 0 ) {
+         printf("'latency' must be run as root...\n");
+         exit(1);
+        }
+
+       if (kernelpath == (char *) 0)
+         kernelpath = "/mach_kernel";
+
+       if (code_file == (char *) 0)
+          code_file = "/usr/share/misc/trace.codes";
+
+       do_kernel_nm();
+
+       sample_sc_now = 25000 / num_of_usecs_to_sleep;
+
+       getdivisor();
+       decrementer_val = decrementer_usec * divisor;
+
+       nanosecs_to_sleep = (double)(num_of_usecs_to_sleep * 1000);
+       fdelay = nanosecs_to_sleep * (divisor /1000);
+       AbsoluteTime_to_scalar(&adelay) = (abstime_scalar_t)fdelay;
+
+       init_code_file();
+
+       /* 
+          When the decrementer isn't set in the options,
+          decval will be zero and this call will reset
+          the system default ...
+       */
+       set_rtcdec(decrementer_val);
+
+       initscr();
+       clear();
+       refresh();
+       signal(SIGWINCH, sigwinch);
+       signal(SIGINT, sigintr);
+       signal(SIGQUIT, sigquit);
+       signal(SIGTERM, sigterm);
+
+
+       if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
+               quit("can't allocate memory for tracing info\n");
+       set_remove();
+       set_numbufs(SAMPLE_SIZE);
+       set_enable(0);
+       if(log_fp)
+         set_init_logging();
+       else
+         set_init_nologging();
+       set_pidexclude(getpid(), 1);
+       set_enable(1);
+       trace_enabled = 1;
+       need_new_map = 1;
+
+       loop_cnt = 0;
+       start_time = time((long *)0);
+       refresh_time = start_time;
+
+       if (my_policy == THREAD_TIME_CONSTRAINT_POLICY)
+         {
+           /* the realtime band */
+           if(set_time_constraint_policy() != KERN_SUCCESS)
+             quit("Failed to set realtime policy.\n");
+         }
+
+       for (;;) {
+               curr_time = time((long *)0);
+
+               if (curr_time >= refresh_time) {
+                      if (my_policy == THREAD_TIME_CONSTRAINT_POLICY)
+                      {
+                         /* set standard timeshare policy during screen update */
+                         if(set_standard_policy() != KERN_SUCCESS)
+                           quit("Failed to set standard policy.\n");
+                       }
+                       screen_update((FILE *)0);
+                       if (my_policy == THREAD_TIME_CONSTRAINT_POLICY)
+                       {
+                         /* set back to realtime band */
+                         if(set_time_constraint_policy() != KERN_SUCCESS)
+                           quit("Failed to set time_constraint policy.\n");
+                       }
+                       refresh_time = curr_time + 1;
+               }
+
+               clock_get_uptime(&timestamp1);
+               adeadline = timestamp1;
+               ADD_ABSOLUTETIME(&adeadline, &adelay);
+               mk_wait_until(adeadline);
+               clock_get_uptime(&timestamp2);
+
+               start = (((unsigned long long)timestamp1.hi) << 32) |
+                         (unsigned long long)((unsigned int)(timestamp1.lo));
+
+               stop = (((unsigned long long)timestamp2.hi) << 32) |
+                        (unsigned long long)((unsigned int)(timestamp2.lo));
+
+               elapsed_usecs = (int)(((double)(stop - start)) / divisor);
+
+               if ((elapsed_usecs -= num_of_usecs_to_sleep) <= 0)
+                       continue;
+
+               if (elapsed_usecs < 100)
+                       s_usec_10_bins[elapsed_usecs/10]++;
+               if (elapsed_usecs < 1000)
+                       s_usec_100_bins[elapsed_usecs/100]++;
+               else if (elapsed_usecs < 10000)
+                       s_msec_1_bins[elapsed_usecs/1000]++;
+               else if (elapsed_usecs < 50000)
+                       s_msec_10_bins[elapsed_usecs/10000]++;
+               else 
+                       s_too_slow++;
+
+               if (elapsed_usecs > s_max_latency)
+                       s_max_latency = elapsed_usecs;
+               if (elapsed_usecs < s_min_latency || s_total_samples == 0)
+                       s_min_latency = elapsed_usecs;
+               s_total_latency += elapsed_usecs;
+               s_total_samples++;
+
+               if (s_thresh_hold && elapsed_usecs > s_thresh_hold)
+                       s_exceeded_threshold++;
+               loop_cnt++;
+
+               if (log_fp && s_thresh_hold && elapsed_usecs > s_thresh_hold)
+                       sample_sc(start, stop);
+               else {
+                       if (loop_cnt >= sample_sc_now) {
+                               sample_sc((long long)0, (long long)0);
+                               loop_cnt = 0;
+                       }
+               }
+               if (gotSIGWINCH) {
+                       initscr();
+                       clear();
+                       refresh();
+
+                       gotSIGWINCH = 0;
+               }
+       }
+       }
+
+
+
+void getdivisor()
+{
+
+    unsigned int delta;
+    unsigned int abs_to_ns_num;
+    unsigned int abs_to_ns_denom;
+    unsigned int proc_to_abs_num;
+    unsigned int proc_to_abs_denom;
+
+    (void)MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
+                      &proc_to_abs_num,  &proc_to_abs_denom);
+
+    divisor = ((double)abs_to_ns_denom / (double)abs_to_ns_num) * 1000;
+}
+
+/* This is the realtime band */
+static kern_return_t
+set_time_constraint_policy()
+{
+       kern_return_t                           result;
+       thread_time_constraint_policy_data_t    info;
+       mach_msg_type_number_t                  count;  
+       boolean_t                               get_default;
+
+       get_default = TRUE;
+       count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
+       result = thread_policy_get(mach_thread_self(), THREAD_TIME_CONSTRAINT_POLICY,
+                                  (thread_policy_t)&info, &count, &get_default);
+       if (result != KERN_SUCCESS)
+               return (result);
+
+       result = thread_policy_set(mach_thread_self(),  THREAD_TIME_CONSTRAINT_POLICY,
+                                  (thread_policy_t)&info, THREAD_TIME_CONSTRAINT_POLICY_COUNT);
+
+       return (result);
+}
+
+/* This is the timeshare mode */
+static kern_return_t
+set_standard_policy()
+{
+       kern_return_t                   result;
+       thread_standard_policy_data_t   info;
+       mach_msg_type_number_t          count;  
+       boolean_t                       get_default;
+
+       get_default = TRUE;
+       count = THREAD_STANDARD_POLICY_COUNT;
+       result = thread_policy_get(mach_thread_self(), THREAD_STANDARD_POLICY,
+                                  (thread_policy_t)&info, &count, &get_default);
+       if (result != KERN_SUCCESS)
+               return (result);
+
+       result = thread_policy_set(mach_thread_self(),  THREAD_STANDARD_POLICY,
+                                  (thread_policy_t)&info, THREAD_STANDARD_POLICY_COUNT);
+
+       return (result);
+}
+
+                                                                                                 
+void read_command_map()
+{
+    size_t size;
+    int mib[6];
+  
+    if (mapptr) {
+       free(mapptr);
+       mapptr = 0;
+    }
+    total_threads = bufinfo.nkdthreads;
+    size = bufinfo.nkdthreads * sizeof(kd_threadmap);
+    if (size)
+    {
+        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 */
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_KDEBUG;
+    mib[2] = KERN_KDTHRMAP;
+    mib[3] = 0;
+    mib[4] = 0;
+    mib[5] = 0;                /* no flags */
+    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;
+}
+
+
+void create_map_entry(int thread, char *command)
+{
+    int i, n;
+    kd_threadmap *map;
+
+    if (!mapptr)
+        return;
+
+    for (i = 0, map = 0; !map && i < total_threads; i++)
+    {
+        if (mapptr[i].thread == thread )       
+           map = &mapptr[i];   /* Reuse this entry, the thread has been reassigned */
+    }
+
+    if (!map)   /* look for invalid entries that I can reuse*/
+    {
+        for (i = 0, map = 0; !map && i < total_threads; i++)
+       {
+           if (mapptr[i].valid == 0 )  
+               map = &mapptr[i];   /* Reuse this invalid entry */
+       }
+    }
+  
+    if (!map)
+    {
+        /* If reach here, then this is a new thread and 
+        * there are no invalid entries to reuse
+        * Double the size of the thread map table.
+        */
+
+        n = total_threads * 2;
+       mapptr = (kd_threadmap *) realloc(mapptr, n * sizeof(kd_threadmap));
+       bzero(&mapptr[total_threads], total_threads*sizeof(kd_threadmap));
+       map = &mapptr[total_threads];
+       total_threads = n;
+#if 0
+       if (log_fp)
+         fprintf(log_fp, "MAP: increasing thread map to %d entries\n", total_threads);
+#endif
+    }
+#if 0
+    if (log_fp)
+      fprintf(log_fp, "MAP: adding thread %x with name %s\n", thread, command);
+#endif
+    map->valid = 1;
+    map->thread = thread;
+    (void)strncpy (map->command, command, sizeof(map->command));
+    map->command[sizeof(map->command)-1] = '\0';
+}
+
+
+kd_threadmap *find_thread_map(int thread)
+{
+    int i;
+    kd_threadmap *map;
+
+    if (!mapptr)
+        return((kd_threadmap *)0);
+
+    for (i = 0; i < total_threads; i++)
+    {
+        map = &mapptr[i];
+       if (map->valid && (map->thread == thread))
+       {
+           return(map);
+       }
+    }
+    return ((kd_threadmap *)0);
+}
+
+void
+kill_thread_map(int thread)
+{
+    kd_threadmap *map;
+
+    if (map = find_thread_map(thread)) {
+
+#if 0
+      if (log_fp)
+        fprintf(log_fp, "MAP: deleting thread %x with name %s\n", thread, map->command);
+#endif
+        map->valid = 0;
+       map->thread = 0;
+       map->command[0] = '\0';
+    }
+}
+
+
+struct th_info *find_thread(int thread, int type1, int type2) {
+       struct th_info *ti;
+
+       for (ti = th_state; ti < &th_state[cur_max]; ti++) {
+              if (ti->thread == thread) {
+                      if (type1 == 0)
+                              return(ti);
+                      if (type1 == ti->type)
+                              return(ti);
+                      if (type2 == ti->type)
+                              return(ti);
+              }
+       }
+       return ((struct th_info *)0);
+}
+
+
+char *find_code(type)
+{
+        int i;
+
+       for (i = 0; i < num_of_codes; i++) {
+               if (codes_tab[i].type == type)
+                       return(codes_tab[i].name);
+       }
+       return ((char *)0);
+}
+
+
+void sample_sc(long long start, long long stop)
+{
+       kd_buf   *kd, *last_mach_sched, *last_decrementer_kd, *start_kd, *end_of_sample;
+       unsigned long long now;
+       int count;
+       int first_entry = 1;
+       char   command[32];
+       double timestamp, last_timestamp, delta, start_bias;
+       void read_command_map();
+
+       if (log_fp && (my_policy == THREAD_TIME_CONSTRAINT_POLICY))
+         {
+           /* set standard timeshare policy when logging */
+           if(set_standard_policy() != KERN_SUCCESS)
+             quit("Failed to set standard policy.\n");
+         }
+
+        /* Get kernel buffer information */
+       get_bufinfo(&bufinfo);
+
+       if (need_new_map) {
+               read_command_map();
+               need_new_map = 0;
+       }
+       needed = bufinfo.nkdbufs * sizeof(kd_buf);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDREADTR;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDREADTR\n");
+
+       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;
+                       th_state[i].vfslookup = 0;
+                       th_state[i].pathname[0] = 0;
+               }
+               cur_max = 0;
+               need_new_map = 1;
+               
+               set_enable(0);
+               set_enable(1);
+
+               if (log_fp) {
+                       double latency;
+
+                       latency = (double)(stop - start) / divisor;
+                       latency -= (double)num_of_usecs_to_sleep;
+
+                       fprintf(log_fp, "\n\n%-19.19s   scheduling latency = %.1fus  num_of_traces = %d <<<<<<< trace buffer wrapped >>>>>>>\n\n",
+                               &(ctime(&curr_time)[0]), latency, count);
+               }
+       }
+       end_of_sample = &((kd_buf *)my_buffer)[count];
+       last_decrementer_kd = (kd_buf *)my_buffer;
+       last_mach_sched = (kd_buf *)0;
+
+       for (kd = (kd_buf *)my_buffer; kd < end_of_sample; kd++) {
+               int debugid, thread, cpunum;
+               int type, clen, mode;
+               char *p;
+               long *sargptr;
+               double i_latency;
+               struct th_info *ti;
+               char   command1[32];
+               char   sched_info[64];
+               kd_threadmap *map;
+               kd_threadmap *find_thread_map();
+               double handle_decrementer();
+               kd_buf *log_decrementer();
+               int check_for_thread_update();
+               void enter_syscall();
+               void exit_syscall();
+               void print_entry();
+
+               thread  = kd->arg5 & KDBG_THREAD_MASK;
+               cpunum =  (kd->arg5 & KDBG_CPU_MASK) ? 1: 0;
+               debugid = kd->debugid;
+               type    = kd->debugid & DBG_FUNC_MASK;
+
+               if (check_for_thread_update(thread, type, kd))
+                       continue;
+
+               if (type == DECR_TRAP)
+                       i_latency = handle_decrementer(kd);
+
+               now = (((unsigned long long)kd->timestamp.tv_sec) << 32) |
+                       (unsigned long long)((unsigned int)(kd->timestamp.tv_nsec));
+
+               timestamp = ((double)now) / divisor;
+
+               if (now < start || now > stop) {
+                       if (debugid & DBG_FUNC_START)
+                               enter_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 0);
+                       else if (debugid & DBG_FUNC_END)
+                               exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 0);
+                       else if (type == DECR_TRAP) {
+                               if (log_fp && i_thresh_hold && (int)i_latency > i_thresh_hold) {
+                                       start_kd = last_decrementer_kd;
+                                       kd = log_decrementer(start_kd, kd, end_of_sample, i_latency);
+
+                                       if (kd >= end_of_sample)
+                                               break;
+                               }
+                               last_decrementer_kd = kd;
+                       }
+                       continue;
+               }
+               if (first_entry) {
+                       double latency;
+                       char buf1[128];
+                       char buf2[128];
+
+                       latency = (double)(stop - start) / divisor;
+                       latency -= (double)num_of_usecs_to_sleep;
+
+                       if (my_pri == -1)
+                               sprintf(buf2, "default");
+                       else
+                               sprintf(buf2, "%d", my_pri);
+                       sprintf(buf1, "%-19.19s     scheduling latency = %.1fus    sleep_request = %dus     policy = %s     priority = %s",
+                               &(ctime(&curr_time)[0]), latency, num_of_usecs_to_sleep, policy_name, buf2);
+                       clen = strlen(buf1);
+                       memset(buf2, '-', clen);
+                       buf2[clen] = 0;
+                       
+                       if (log_fp) {
+                         fprintf(log_fp, "\n\n%s\n", buf2);
+                         fprintf(log_fp, "%s\n\n", buf1);
+                         fprintf(log_fp, "RelTime(Us)  Delta              debugid                      arg1       arg2       arg3      arg4       thread   cpu  command\n\n");
+                       }
+                       start_bias = ((double)start) / divisor;
+                       last_timestamp = timestamp;
+                       first_entry = 0;
+               }
+               delta = timestamp - last_timestamp;
+
+               if (map = find_thread_map(thread))
+                       strcpy(command, map->command);
+               else
+                       command[0] = 0;
+
+               switch (type) {
+
+               case CQ_action:
+                   if (log_fp) {
+                       fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-59.59s %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, pc_to_string(kd->arg1, 59, 1) , thread, cpunum, command);
+                   }
+                   last_timestamp = timestamp;
+                   break;
+
+               case TES_action:
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f\t\tTES_action @ %-58.58s %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, pc_to_string(kd->arg1, 58, 1) , thread, cpunum, command);
+                   }
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case IES_action:
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f\t\tIES_action @ %-58.58s %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, pc_to_string(kd->arg1, 58, 1) , thread, cpunum, command);
+                   }
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case IES_filter:
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f\t\tIES_filter @ %-58.58s %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, pc_to_string(kd->arg1, 58, 1) , thread, cpunum, command);
+                   }
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case DECR_TRAP:
+                   last_decrementer_kd = kd;
+
+                   if (i_thresh_hold && (int)i_latency > i_thresh_hold)
+                           p = "*";
+                   else
+                           p = " ";
+
+                   mode = 1;
+
+                   if (ti = find_thread((kd->arg5 & KDBG_THREAD_MASK), 0, 0)) {
+                           if (ti->type == -1 && strcmp(command, "kernel_task"))
+                                   mode = 0;
+                   }
+
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-59.59s %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, i_latency, p, pc_to_string(kd->arg2, 59, mode) , thread, cpunum, command);
+                   }
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case DECR_SET:
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f[%.1f]  \t%-28.28s                                            %-8x  %d  %s\n",
+                             timestamp - start_bias, delta, (double)kd->arg1/divisor, "DECR_SET", thread, cpunum, command);
+                   }
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case MACH_sched:
+               case MACH_stkhandoff:
+                   last_mach_sched = kd;
+
+                   if (map = find_thread_map(kd->arg2))
+                           strcpy(command1, map->command);
+                   else
+                           sprintf(command1, "%-8x", kd->arg2);
+
+                   if (ti = find_thread(kd->arg2, 0, 0)) {
+                           if (ti->type == -1 && strcmp(command1, "kernel_task"))
+                                   p = "U";
+                           else
+                                   p = "K";
+                   } else
+                           p = "*";
+                   memset(sched_info, ' ', sizeof(sched_info));
+
+                   sprintf(sched_info, "%14.14s", command);
+                   clen = strlen(sched_info);
+                   sched_info[clen] = ' ';
+
+                   sprintf(&sched_info[14],  " @ pri %3d  -->  %14.14s", kd->arg3, command1);
+                   clen = strlen(sched_info);
+                   sched_info[clen] = ' ';
+
+                   sprintf(&sched_info[45], " @ pri %3d%s", kd->arg4, p);
+
+                   if (log_fp) {
+                     fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s  %s    %-8x  %d\n",
+                                   timestamp - start_bias, delta, "MACH_SCHED", sched_info, thread, cpunum);
+                   }
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case VFS_LOOKUP:
+                   if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) {
+                           if (cur_max >= MAX_THREADS)
+                                   continue;
+                           ti = &th_state[cur_max++];
+
+                           ti->thread = thread;
+                           ti->type   = -1;
+                           ti->vfslookup = 0;
+                           ti->child_thread = 0;
+                   }
+                   if (ti->vfslookup == 0) {
+                           ti->vfslookup = 1;
+                           ti->arg1 = kd->arg1;
+                           memset(&ti->pathname[0], 0, 32);
+                           sargptr = (long *)&ti->pathname[0];
+                               
+                           *sargptr++ = kd->arg2;
+                           *sargptr++ = kd->arg3;
+                           *sargptr++ = kd->arg4;
+
+                   } else if (ti->vfslookup == 1) {
+                           ti->vfslookup = 0;
+         
+                           sargptr = (long *)&ti->pathname[12];
+                           *sargptr++ = kd->arg1;
+                           *sargptr++ = kd->arg2;
+                           *sargptr++ = kd->arg3;
+                           *sargptr++ = kd->arg4;
+                           
+                           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, ti->arg1, thread, cpunum, command);
+                           }
+                   }
+                   last_timestamp = timestamp;
+                   break;
+
+               default:
+                   if (debugid & DBG_FUNC_START)
+                           enter_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1);
+                   else if (debugid & DBG_FUNC_END)
+                           exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1);
+                   else
+                           print_entry(log_fp, kd, thread, type, command, timestamp, delta, start_bias);
+
+                   last_timestamp = timestamp;
+                   break;
+               }
+       }
+       if (last_mach_sched && log_fp)
+               fprintf(log_fp, "\nblocked by %s @ priority %d\n", command, last_mach_sched->arg3);
+#if 0
+       if (first_entry == 0 && log_fp)
+               fprintf(log_fp, "\n   start = %qd   stop = %qd    count = %d    now = %qd\n", start, stop, count, now);
+#endif
+       if (log_fp)
+               fflush(log_fp);
+
+       if (log_fp && (my_policy == THREAD_TIME_CONSTRAINT_POLICY))
+         {
+           /* set back to realtime band */
+           if(set_time_constraint_policy() != KERN_SUCCESS)
+             quit("Failed to set time_constraint policy.\n");
+         }
+}
+
+void
+enter_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double timestamp, double delta, double bias, int print_info)
+{
+       struct th_info *ti;
+       int    i;
+       int    cpunum;
+       char  *p;
+
+       cpunum =  (kd->arg5 & KDBG_CPU_MASK) ? 1: 0;
+
+       if (print_info && fp) {
+              if (p = find_code(type)) {
+                      if (type == INTERRUPT) {
+                              int mode = 1;
+
+                              if (ti = find_thread((kd->arg5 & KDBG_THREAD_MASK), 0, 0)) {
+                                      if (ti->type == -1 && strcmp(command, "kernel_task"))
+                                              mode = 0;
+                              }
+
+                              fprintf(fp, "%9.1f %8.1f\t\tINTERRUPT @ %-59.59s %-8x  %d  %s\n",
+                                      timestamp - bias, delta, pc_to_string(kd->arg2, 59, mode), thread, cpunum, command);
+                      } else if (type == MACH_vmfault) {
+                              fprintf(fp, "%9.1f %8.1f\t\t%-28.28s                                            %-8x  %d  %s\n",
+                                      timestamp - bias, delta, p, thread, cpunum, command);
+                      } else {
+                              fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8x   %-8x   %-8x  %-8x   %-8x  %d  %s\n",
+                                      timestamp - bias, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, 
+                                      thread, cpunum, command);
+                      }
+              } else {
+                      fprintf(fp, "%9.1f %8.1f\t\t%-8x                     %-8x   %-8x   %-8x  %-8x   %-8x  %d  %s\n",
+                              timestamp - bias, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, 
+                              thread, cpunum, command);
+              }
+       }
+       if ((ti = find_thread(thread, -1, type)) == (struct th_info *)0) {
+              if (cur_max >= MAX_THREADS) {
+                      static int do_this_once = 1;
+
+                      if (do_this_once) {
+                              for (i = 0; i < cur_max; i++) {
+                                      if (!fp)
+                                            break;
+                                      fprintf(fp, "thread = %x, type = %x\n", 
+                                              th_state[i].thread, th_state[i].type);
+                              }
+                              do_this_once = 0;
+                      }
+                      return;
+
+              }
+              ti = &th_state[cur_max++];
+
+              ti->thread = thread;
+              ti->child_thread = 0;
+       }
+       if (type != BSC_exit)
+              ti->type = type;
+       else
+              ti->type = -1;
+       ti->stime  = timestamp;
+       ti->vfslookup = 0;
+#if 0
+       if (print_info && fp)
+              fprintf(fp, "cur_max = %d,  ti = %x,  type = %x,  thread = %x\n", cur_max, ti, ti->type, ti->thread);
+#endif
+}
+
+
+void
+exit_syscall(FILE *fp, kd_buf *kd, int thread, int type, char *command, double timestamp, double delta, double bias, int print_info)
+{
+       struct th_info *ti;
+       int    cpunum;
+       char   *p;
+
+       cpunum =  (kd->arg5 & KDBG_CPU_MASK) ? 1: 0;
+       ti = find_thread(thread, type, type);
+#if 0
+       if (print_info && fp)
+              fprintf(fp, "cur_max = %d,  ti = %x,  type = %x,  thread = %x\n", cur_max, ti, type, thread);
+#endif
+       if (print_info && fp) {
+              if (ti)
+                      fprintf(fp, "%9.1f %8.1f(%.1f) \t", timestamp - bias, delta, timestamp - ti->stime);
+              else
+                      fprintf(fp, "%9.1f %8.1f()      \t", timestamp - bias, delta);
+
+              if (p = find_code(type)) {
+                      if (type == INTERRUPT) {
+                              fprintf(fp, "INTERRUPT                                                               %-8x  %d  %s\n", thread, cpunum, command);
+                      } else if (type == MACH_vmfault && kd->arg2 <= DBG_CACHE_HIT_FAULT) {
+                              fprintf(fp, "%-28.28s %-8.8s   %-8x                        %-8x  %d  %s\n",
+                                      p, fault_name[kd->arg2], kd->arg1,
+                                      thread, cpunum, command);
+                      } else {
+                              fprintf(fp, "%-28.28s %-8x   %-8x                        %-8x  %d  %s\n",
+                                      p, kd->arg1, kd->arg2,
+                                      thread, cpunum, command);
+                      }
+              } else {
+                      fprintf(fp, "%-8x                     %-8x   %-8x                        %-8x  %d  %s\n",
+                              type, kd->arg1, kd->arg2,
+                              thread, cpunum, command);
+              }
+       }
+       if (ti == (struct th_info *)0) {
+              if ((ti = find_thread(thread, -1, -1)) == (struct th_info *)0) {
+                      if (cur_max >= MAX_THREADS)
+                              return;
+                      ti = &th_state[cur_max++];
+
+                      ti->thread = thread;
+                      ti->child_thread = 0;
+                      ti->vfslookup = 0;
+              }
+       }
+       ti->type = -1;
+}
+
+void
+print_entry(FILE *fp, kd_buf *kd, int thread, int type, char *command, double timestamp, double delta, double bias)
+{
+       char  *p;
+       int cpunum;
+
+       if (!fp)
+        return;
+
+       cpunum =  (kd->arg5 & KDBG_CPU_MASK) ? 1: 0;
+
+#if 0
+       fprintf(fp, "cur_max = %d, type = %x,  thread = %x, cpunum = %d\n", cur_max, type, thread, cpunum);
+#endif
+       if (p = find_code(type)) {
+              fprintf(fp, "%9.1f %8.1f\t\t%-28.28s %-8x   %-8x   %-8x  %-8x   %-8x  %d  %s\n",
+                      timestamp - bias, delta, p, kd->arg1, kd->arg2, kd->arg3, kd->arg4, 
+                      thread, cpunum, command);
+       } else {
+              fprintf(fp, "%9.1f %8.1f\t\t%-8x                     %-8x   %-8x   %-8x  %-8x   %-8x  %d  %s\n",
+                      timestamp - bias, delta, type, kd->arg1, kd->arg2, kd->arg3, kd->arg4, 
+                      thread, cpunum, command);
+       }
+}
+
+int
+check_for_thread_update(int thread, int type, kd_buf *kd)
+{
+        struct th_info *ti;
+       void create_map_entry();
+
+        switch (type) {
+
+       case TRACE_DATA_NEWTHREAD:
+           if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) {
+                   if (cur_max >= MAX_THREADS)
+                           return (1);
+                   ti = &th_state[cur_max++];
+
+                   ti->thread = thread;
+                   ti->type   = -1;
+                   ti->vfslookup = 0;
+           }
+           ti->child_thread = kd->arg1;
+           return (1);
+
+       case TRACE_STRING_NEWTHREAD:
+           if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0)
+                   return (1);
+           if (ti->child_thread == 0)
+                   return (1);
+           create_map_entry(ti->child_thread, (char *)&kd->arg1);
+
+           ti->child_thread = 0;
+           return (1);
+
+       case TRACE_STRING_EXEC:
+           create_map_entry(thread, (char *)&kd->arg1);
+           return (1);
+
+       }
+       return (0);
+}
+
+
+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;
+       double timestamp, last_timestamp, delta, start_bias;
+       int thread, cpunum;
+       int debugid, type, clen;
+       unsigned long long now;
+       struct th_info *ti;
+       long  *sargptr;
+       char  *p;
+       char   command[32];
+       char   command1[32];
+       char   sched_info[64];
+       char   buf1[128];
+       char   buf2[128];
+       kd_threadmap *map;
+       kd_threadmap *find_thread_map();
+
+       sprintf(buf1, "%-19.19s     interrupt latency = %.1fus", &(ctime(&curr_time)[0]), i_latency);
+       clen = strlen(buf1);
+       memset(buf2, '-', clen);
+       buf2[clen] = 0;
+       fprintf(log_fp, "\n\n%s\n", buf2);
+       fprintf(log_fp, "%s\n\n", buf1);
+
+       fprintf(log_fp, "RelTime(Us)  Delta              debugid                      arg1       arg2       arg3      arg4       thread   cpu   command\n\n");
+
+       thread = kd_beg->arg5 & KDBG_THREAD_MASK;
+
+       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)
+                       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)
+                       break;
+       }
+       if (kd_stop >= end_of_sample)
+               kd_stop = end_of_sample - 1;
+
+       now = (((unsigned long long)kd_start->timestamp.tv_sec) << 32) |
+               (unsigned long long)((unsigned int)(kd_start->timestamp.tv_nsec));
+       timestamp = ((double)now) / divisor;
+
+       for (kd = kd_start; kd <= kd_stop; kd++) {
+               type = kd->debugid & DBG_FUNC_MASK;
+
+               if (ti = find_thread((kd->arg5 & KDBG_THREAD_MASK), type, type)) {
+                       if (ti->stime >= timestamp)
+                               ti->type = -1;
+               }
+       }
+       for (kd = kd_start; kd <= kd_stop; kd++) {
+               int    mode;
+
+               thread  = kd->arg5 & KDBG_THREAD_MASK;
+               cpunum =  (kd->arg5 & KDBG_CPU_MASK) ? 1: 0;
+               debugid = kd->debugid;
+               type    = kd->debugid & DBG_FUNC_MASK;
+
+               now = (((unsigned long long)kd->timestamp.tv_sec) << 32) |
+                       (unsigned long long)((unsigned int)(kd->timestamp.tv_nsec));
+
+               timestamp = ((double)now) / divisor;
+
+               if (kd == kd_start) {
+                       start_bias = timestamp;
+                       last_timestamp = timestamp;
+               }
+               delta = timestamp - last_timestamp;
+
+               if (map = find_thread_map(thread))
+                       strcpy(command, map->command);
+               else
+                       command[0] = 0;
+
+
+               switch (type) {
+
+               case CQ_action:
+                   fprintf(log_fp, "%9.1f %8.1f\t\tCQ_action @ %-59.59s %-8x  %d  %s\n",
+                           timestamp - start_bias, delta, pc_to_string(kd->arg1, 59, 1) , thread, cpunum, command);
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case DECR_TRAP:
+                   if ((int)(kd->arg1) >= 0)
+                           i_latency = 0;
+                   else
+                           i_latency = (((double)(-1 - kd->arg1)) / divisor);
+
+                   if (i_thresh_hold && (int)i_latency > i_thresh_hold)
+                           p = "*";
+                   else
+                           p = " ";
+
+                   mode = 1;
+
+                   if (ti = find_thread((kd->arg5 & KDBG_THREAD_MASK), 0, 0)) {
+                           if (ti->type == -1 && strcmp(command, "kernel_task"))
+                                   mode = 0;
+                   }
+                   fprintf(log_fp, "%9.1f %8.1f[%.1f]%s\tDECR_TRAP @ %-59.59s %-8x  %d  %s\n",
+                           timestamp - start_bias, delta, i_latency, p, pc_to_string(kd->arg2, 59, mode) , thread, cpunum, command);
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case DECR_SET:
+                   fprintf(log_fp, "%9.1f %8.1f[%.1f]  \t%-28.28s                                            %-8x  %d  %s\n",
+                           timestamp - start_bias, delta, (double)kd->arg1/divisor,
+                           "DECR_SET", thread, cpunum, command);
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case MACH_sched:
+               case MACH_stkhandoff:
+                   if (map = find_thread_map(kd->arg2))
+                           strcpy(command1, map->command);
+                   else
+                           sprintf(command1, "%-8x", kd->arg2);
+
+                   if (ti = find_thread(kd->arg2, 0, 0)) {
+                           if (ti->type == -1 && strcmp(command1, "kernel_task"))
+                                   p = "U";
+                           else
+                                   p = "K";
+                   } else
+                           p = "*";
+                   memset(sched_info, ' ', sizeof(sched_info));
+
+                   sprintf(sched_info, "%14.14s", command);
+                   clen = strlen(sched_info);
+                   sched_info[clen] = ' ';
+
+                   sprintf(&sched_info[14],  " @ pri %3d  -->  %14.14s", kd->arg3, command1);
+                   clen = strlen(sched_info);
+                   sched_info[clen] = ' ';
+
+                   sprintf(&sched_info[45], " @ pri %3d%s", kd->arg4, p);
+
+                   fprintf(log_fp, "%9.1f %8.1f\t\t%-10.10s  %s    %-8x  %d\n",
+                                   timestamp - start_bias, delta, "MACH_SCHED", sched_info, thread, cpunum);
+
+                   last_timestamp = timestamp;
+                   break;
+
+               case VFS_LOOKUP:
+                   if ((ti = find_thread(thread, 0, 0)) == (struct th_info *)0) {
+                           if (cur_max >= MAX_THREADS)
+                                   continue;
+                           ti = &th_state[cur_max++];
+
+                           ti->thread = thread;
+                           ti->type   = -1;
+                           ti->vfslookup = 0;
+                           ti->child_thread = 0;
+                   }
+                   if (ti->vfslookup == 0) {
+                           ti->vfslookup = 1;
+                           ti->arg1 = kd->arg1;
+                           memset(&ti->pathname[0], 0, 32);
+                           sargptr = (long *)&ti->pathname[0];
+                               
+                           *sargptr++ = kd->arg2;
+                           *sargptr++ = kd->arg3;
+                           *sargptr++ = kd->arg4;
+
+                   } else if (ti->vfslookup == 1) {
+                           ti->vfslookup = 0;
+         
+                           sargptr = (long *)&ti->pathname[12];
+                           *sargptr++ = kd->arg1;
+                           *sargptr++ = kd->arg2;
+                           *sargptr++ = kd->arg3;
+                           *sargptr++ = kd->arg4;
+                           
+                           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, ti->arg1, thread, cpunum, command);
+                   }
+                   last_timestamp = timestamp;
+                   break;
+
+               default:
+                   if (debugid & DBG_FUNC_START)
+                           enter_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1);
+                   else if (debugid & DBG_FUNC_END)
+                           exit_syscall(log_fp, kd, thread, type, command, timestamp, delta, start_bias, 1);
+                   else
+                           print_entry(log_fp, kd, thread, type, command, timestamp, delta, start_bias);
+
+                   last_timestamp = timestamp;
+                   break;
+               }
+       }
+       return(kd_stop);
+}
+
+
+double handle_decrementer(kd_buf *kd)
+{
+        double latency;
+       int    elapsed_usecs;
+
+       if ((int)(kd->arg1) >= 0)
+              latency = 1;
+       else
+              latency = (((double)(-1 - kd->arg1)) / divisor);
+       elapsed_usecs = (int)latency;
+
+       if (elapsed_usecs < 100)
+               i_usec_10_bins[elapsed_usecs/10]++;
+       if (elapsed_usecs < 1000)
+               i_usec_100_bins[elapsed_usecs/100]++;
+       else if (elapsed_usecs < 10000)
+               i_msec_1_bins[elapsed_usecs/1000]++;
+       else if (elapsed_usecs < 50000)
+               i_msec_10_bins[elapsed_usecs/10000]++;
+       else 
+               i_too_slow++;
+
+       if (i_thresh_hold && elapsed_usecs > i_thresh_hold)
+               i_exceeded_threshold++;
+       if (elapsed_usecs > i_max_latency)
+               i_max_latency = elapsed_usecs;
+       if (elapsed_usecs < i_min_latency || i_total_samples == 0)
+               i_min_latency = elapsed_usecs;
+       i_total_latency += elapsed_usecs;
+       i_total_samples++;
+
+       return (latency);
+}
+
+
+void init_code_file()
+{
+        FILE *fp;
+       int   i, n, cnt, code;
+       char name[128];
+
+       if ((fp = fopen(code_file, "r")) == (FILE *)0) {
+               if (log_fp)
+                       fprintf(log_fp, "open of %s failed\n", code_file);
+               return;
+       }
+       n = fscanf(fp, "%d\n", &cnt);
+
+       if (n != 1) {
+               if (log_fp)
+                       fprintf(log_fp, "bad format found in %s\n", code_file);
+               return;
+       }
+       for (i = 0; i < MAX_ENTRIES; i++) {
+               n = fscanf(fp, "%x%s\n", &code, name);
+
+               if (n != 2)
+                       break;
+
+               strncpy(codes_tab[i].name, name, 32);
+               codes_tab[i].type = code;
+       }
+       num_of_codes = i;
+
+       fclose(fp);
+}
+
+
+void
+do_kernel_nm()
+{
+  int i, len;
+  FILE *fp = (FILE *)0;
+  char tmp_nm_file[128];
+  char tmpstr[1024];
+  int inchr;
+
+  bzero(tmp_nm_file, 128);
+  bzero(tmpstr, 1024);
+
+  /* Build the temporary nm file path */
+  sprintf(tmp_nm_file, "/tmp/knm.out.%d", getpid());
+
+  /* Build the nm command and create a tmp file with the output*/
+  sprintf (tmpstr, "/usr/bin/nm -f -n -s __TEXT __text %s > %s",
+          kernelpath, tmp_nm_file);
+  system(tmpstr);
+  
+  /* Parse the output from the nm command */
+  if ((fp=fopen(tmp_nm_file, "r")) == (FILE *)0)
+    {
+      /* Hmmm, let's not treat this as fatal */
+      fprintf(stderr, "Failed to open nm symbol file [%s]\n", tmp_nm_file);
+      return;
+    }
+
+  /* Count the number of symbols in the nm symbol table */
+  kern_sym_count=0;
+  while ( (inchr = getc(fp)) != -1)
+    {
+      if (inchr == '\n')
+       kern_sym_count++;
+    }
+
+  rewind(fp);
+
+  /* Malloc the space for symbol table */
+  if (kern_sym_count > 0)
+    {
+       kern_sym_tbl = (kern_sym_t *)malloc(kern_sym_count * sizeof (kern_sym_t));
+       if (!kern_sym_tbl)
+        {
+          /* Hmmm, lets not treat this as fatal */
+          fprintf(stderr, "Can't allocate memory for kernel symbol table\n");
+        }
+       else
+        bzero(kern_sym_tbl, (kern_sym_count * sizeof(kern_sym_t)));
+    }
+  else
+    {
+      /* Hmmm, lets not treat this as fatal */
+      fprintf(stderr, "No kernel symbol table \n");
+    }
+
+  for (i=0; i<kern_sym_count; i++)
+    {
+      bzero(tmpstr, 1024);
+      if (fscanf(fp, "%x %c %s", &kern_sym_tbl[i].k_sym_addr, &inchr, tmpstr) != 3)
+       break;
+      else
+       {
+         len = strlen(tmpstr);
+         kern_sym_tbl[i].k_sym_name = malloc(len + 1);
+
+         if (kern_sym_tbl[i].k_sym_name == (char *)0)
+           {
+             fprintf(stderr, "Can't allocate memory for symbol name [%s]\n", tmpstr);
+             kern_sym_tbl[i].k_sym_name = (char *)0;
+             len = 0;
+           }
+         else
+           strcpy(kern_sym_tbl[i].k_sym_name, tmpstr);
+
+         kern_sym_tbl[i].k_sym_len = len;
+       }
+    } /* end for */
+
+  if (i != kern_sym_count)
+    {
+      /* Hmmm, didn't build up entire table from nm */
+      /* scrap the entire thing */
+      if (kern_sym_tbl)
+       free (kern_sym_tbl);
+      kern_sym_tbl = (kern_sym_t *)0;
+      kern_sym_count = 0;
+    }
+
+  fclose(fp);
+
+  /* Remove the temporary nm file */
+  unlink(tmp_nm_file);
+
+#if 0
+  /* Dump the kernel symbol table */
+  for (i=0; i < kern_sym_count; i++)
+    {
+      if (kern_sym_tbl[i].k_sym_name)
+         printf ("[%d] 0x%x    %s\n", i, 
+                 kern_sym_tbl[i].k_sym_addr, kern_sym_tbl[i].k_sym_name);
+      else
+         printf ("[%d] 0x%x    %s\n", i, 
+                 kern_sym_tbl[i].k_sym_addr, "No symbol name");
+    }
+#endif
+}
+
+char *
+pc_to_string(unsigned int pc, int max_len, int mode)
+{
+  int ret;
+  int len;
+
+  int binary_search();
+
+  if (mode == 0)
+    {
+      sprintf(pcstring, "0x%-8x [usermode addr]", pc);
+      return(pcstring);
+    }
+
+  ret=0;
+  ret = binary_search(kern_sym_tbl, 0, kern_sym_count-1, pc);
+
+  if (ret == -1)
+    {
+      sprintf(pcstring, "0x%x", pc);
+      return(pcstring);
+    }
+  else if (kern_sym_tbl[ret].k_sym_name == (char *)0)
+    {
+      sprintf(pcstring, "0x%x", pc);
+      return(pcstring);
+    }
+  else
+    {
+      if ((len = kern_sym_tbl[ret].k_sym_len) > (max_len - 8))
+           len = max_len - 8;
+
+      memcpy(pcstring, kern_sym_tbl[ret].k_sym_name, len);
+      sprintf(&pcstring[len], "+0x%-5x", pc - kern_sym_tbl[ret].k_sym_addr);
+
+      return (pcstring);
+    }
+}
+
+
+/* Return -1 if not found, else return index */
+int binary_search(list, low, high, addr)
+kern_sym_t *list;
+int low, high;
+unsigned int  addr;
+{
+  int mid;
+  
+  mid = (low + high) / 2;
+  
+  if (low > high)
+    return (-1);   /* failed */
+  else if (low + 1 == high)
+    { 
+      if (list[low].k_sym_addr <= addr &&
+          addr < list[high].k_sym_addr)
+       {
+         /* We have a range match */
+         return(low);
+       }
+      else if (list[high].k_sym_addr <= addr)
+       {
+         return(high);
+       }
+      else
+       return(-1);   /* Failed */
+    }      
+  else if (addr < list[mid].k_sym_addr)
+    {
+      return(binary_search (list, low, mid, addr));
+    }
+  else
+    {
+      return(binary_search (list, mid, high, addr));
+    }
+}
+
+void
+open_logfile(char *path)
+{
+    log_fp = fopen(path, "a");
+
+    if (!log_fp)
+      {
+       /* failed to open path */
+       fprintf(stderr, "latency: failed to open logfile [%s]\n", path);
+       exit_usage();
+      }
+}
diff --git a/login.tproj/Makefile b/login.tproj/Makefile
new file mode 100644 (file)
index 0000000..a148d4b
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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 = login
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = klogin.c login.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble login.1
+
+
+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)
+
+
+
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/login.tproj/Makefile.postamble b/login.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..ec7f60d
--- /dev/null
@@ -0,0 +1,6 @@
+INSTALL_AS_USER =      root
+INSTALL_PERMISSIONS = 4555
+#CHFLAGS = /usr/bin/chflags
+
+#after_install::
+#      $(CHFLAGS) schg  $(DSTROOT)$(INSTALLDIR)/$(NAME)
diff --git a/login.tproj/Makefile.preamble b/login.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..b7b38d0
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/login.tproj/PB.project b/login.tproj/PB.project
new file mode 100644 (file)
index 0000000..5ee51ca
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pathnames.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (klogin.c, login.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, login.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = login; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/login.tproj/klogin.c b/login.tproj/klogin.c
new file mode 100644 (file)
index 0000000..3426d9c
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * 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) 1990, 1993, 1994
+ *      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.
+ */
+
+#ifdef KERBEROS
+#include <sys/param.h>
+#include <sys/syslog.h>
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define        INITIAL_TICKET  "krbtgt"
+#define        VERIFY_SERVICE  "rcmd"
+
+extern int notickets;
+extern char *krbtkfile_env;
+
+/*
+ * Attempt to log the user in using Kerberos authentication
+ *
+ * return 0 on success (will be logged in)
+ *       1 if Kerberos failed (try local password in login)
+ */
+int
+klogin(pw, instance, localhost, password)
+       struct passwd *pw;
+       char *instance, *localhost, *password;
+{
+       int kerror;
+       AUTH_DAT authdata;
+       KTEXT_ST ticket;
+       struct hostent *hp;
+       unsigned long faddr;
+       char realm[REALM_SZ], savehost[MAXHOSTNAMELEN];
+       char tkt_location[MAXPATHLEN];
+       char *krb_get_phost();
+
+       /*
+        * Root logins don't use Kerberos.
+        * If we have a realm, try getting a ticket-granting ticket
+        * and using it to authenticate.  Otherwise, return
+        * failure so that we can try the normal passwd file
+        * for a password.  If that's ok, log the user in
+        * without issuing any tickets.
+        */
+       if (strcmp(pw->pw_name, "root") == 0 ||
+           krb_get_lrealm(realm, 0) != KSUCCESS)
+               return (1);
+
+       /*
+        * get TGT for local realm
+        * tickets are stored in a file named TKT_ROOT plus uid
+        * except for user.root tickets.
+        */
+
+       if (strcmp(instance, "root") != 0)
+               (void)sprintf(tkt_location, "%s%d", TKT_ROOT, pw->pw_uid);
+       else {
+               (void)sprintf(tkt_location, "%s_root_%d", TKT_ROOT, pw->pw_uid);
+               krbtkfile_env = tkt_location;
+       }
+       (void)krb_set_tkt_string(tkt_location);
+
+       /*
+        * Set real as well as effective ID to 0 for the moment,
+        * to make the kerberos library do the right thing.
+        */
+       if (setuid(0) < 0) {
+               warnx("setuid");
+               return (1);
+       }
+       kerror = krb_get_pw_in_tkt(pw->pw_name, instance,
+                   realm, INITIAL_TICKET, realm, DEFAULT_TKT_LIFE, password);
+       /*
+        * If we got a TGT, get a local "rcmd" ticket and check it so as to
+        * ensure that we are not talking to a bogus Kerberos server.
+        *
+        * There are 2 cases where we still allow a login:
+        *      1: the VERIFY_SERVICE doesn't exist in the KDC
+        *      2: local host has no srvtab, as (hopefully) indicated by a
+        *         return value of RD_AP_UNDEC from krb_rd_req().
+        */
+       if (kerror != INTK_OK) {
+               if (kerror != INTK_BADPW && kerror != KDC_PR_UNKNOWN) {
+                       syslog(LOG_ERR, "Kerberos intkt error: %s",
+                           krb_err_txt[kerror]);
+                       dest_tkt();
+               }
+               return (1);
+       }
+
+       if (chown(TKT_FILE, pw->pw_uid, pw->pw_gid) < 0)
+               syslog(LOG_ERR, "chown tkfile (%s): %m", TKT_FILE);
+
+       (void)strncpy(savehost, krb_get_phost(localhost), sizeof(savehost));
+       savehost[sizeof(savehost)-1] = NULL;
+
+       /*
+        * if the "VERIFY_SERVICE" doesn't exist in the KDC for this host,
+        * still allow login with tickets, but log the error condition.
+        */
+
+       kerror = krb_mk_req(&ticket, VERIFY_SERVICE, savehost, realm, 33);
+       if (kerror == KDC_PR_UNKNOWN) {
+               syslog(LOG_NOTICE,
+                   "warning: TGT not verified (%s); %s.%s not registered, or srvtab is wrong?",
+                   krb_err_txt[kerror], VERIFY_SERVICE, savehost);
+               notickets = 0;
+               return (0);
+       }
+
+       if (kerror != KSUCCESS) {
+               warnx("unable to use TGT: (%s)", krb_err_txt[kerror]);
+               syslog(LOG_NOTICE, "unable to use TGT: (%s)",
+                   krb_err_txt[kerror]);
+               dest_tkt();
+               return (1);
+       }
+
+       if (!(hp = gethostbyname(localhost))) {
+               syslog(LOG_ERR, "couldn't get local host address");
+               dest_tkt();
+               return (1);
+       }
+
+       memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr));
+
+       kerror = krb_rd_req(&ticket, VERIFY_SERVICE, savehost, faddr,
+           &authdata, "");
+
+       if (kerror == KSUCCESS) {
+               notickets = 0;
+               return (0);
+       }
+
+       /* undecipherable: probably didn't have a srvtab on the local host */
+       if (kerror = RD_AP_UNDEC) {
+               syslog(LOG_NOTICE, "krb_rd_req: (%s)\n", krb_err_txt[kerror]);
+               dest_tkt();
+               return (1);
+       }
+       /* failed for some other reason */
+       warnx("unable to verify %s ticket: (%s)", VERIFY_SERVICE,
+           krb_err_txt[kerror]);
+       syslog(LOG_NOTICE, "couldn't verify %s ticket: %s", VERIFY_SERVICE,
+           krb_err_txt[kerror]);
+       dest_tkt();
+       return (1);
+}
+#endif
diff --git a/login.tproj/login.1 b/login.tproj/login.1
new file mode 100644 (file)
index 0000000..6c78b23
--- /dev/null
@@ -0,0 +1,148 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"    @(#)login.1     8.2 (Berkeley) 5/5/94
+.\"
+.Dd May 5, 1994
+.Dt LOGIN 1
+.Os BSD 4
+.Sh NAME
+.Nm login
+.Nd log into the computer
+.Sh SYNOPSIS
+.Nm login
+.Op Fl fp
+.Op Fl h Ar hostname
+.Op Ar user
+.Sh DESCRIPTION
+The
+.Nm login
+utility logs users (and pseudo-users) into the computer system.
+.Pp
+If no user is specified, or if a user is specified and authentication
+of the user fails,
+.Nm login
+prompts for a user name.
+Authentication of users is done via passwords.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl f
+The
+.Fl f
+option is used when a user name is specified to indicate that proper
+authentication has already been done and that no password need be
+requested.
+This option may only be used by the super-user or when an already
+logged in user is logging in as themselves.
+.It Fl h
+The
+.Fl h
+option specifies the host from which the connection was received.
+It is used by various daemons such as
+.Xr telnetd  8 .
+This option may only be used by the super-user.
+.It Fl p
+By default,
+.Nm login
+discards any previous environment.
+The
+.Fl p
+option disables this behavior.
+.El
+.Pp
+If the file
+.Pa /etc/nologin
+exists,
+.Nm login
+dislays its contents to the user and exits.
+This is used by
+.Xr shutdown  8
+to prevent users from logging in when the system is about to go down.
+.Pp
+Immediately after logging a user in,
+.Nm login
+displays the system copyright notice, the date and time the user last
+logged in, the message of the day as well as other information.
+If the file
+.Dq Pa .hushlogin
+exists in the user's home directory, all of these messages are suppressed.
+This is to simplify logins for non-human users, such as
+.Xr uucp 1 .
+.Nm Login
+then records an entry in the
+.Xr wtmp 5
+and
+.Xr utmp 5
+files and executes the user's command interpretor.
+.Pp
+Login enters information into the environment (see
+.Xr environ 7 )
+specifying the user's home directory (HOME), command interpreter (SHELL),
+search path (PATH), terminal type (TERM) and user name (both LOGNAME and
+USER).
+.Pp
+The standard shells,
+.Xr csh 1
+and
+.Xr sh 1 ,
+do not fork before executing the
+.Nm login
+utility.
+.Sh FILES
+.Bl -tag -width /var/mail/userXXX -compact
+.It Pa /etc/motd
+message-of-the-day
+.It Pa /etc/nologin
+disallows logins
+.It Pa /var/run/utmp
+current logins
+.It Pa /var/log/lastlog
+last login account records
+.It Pa /var/log/wtmp
+login account records
+.It Pa /var/mail/user
+system mailboxes
+.It Pa \&.hushlogin
+makes login quieter
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr passwd 1 ,
+.Xr rlogin 1 ,
+.Xr getpass 3 ,
+.Xr utmp 5 ,
+.Xr environ 7 ,
+.Sh HISTORY
+A
+.Nm login
+appeared in
+.At v6 .
diff --git a/login.tproj/login.c b/login.tproj/login.c
new file mode 100644 (file)
index 0000000..9a48977
--- /dev/null
@@ -0,0 +1,608 @@
+/*
+ * 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) 1980, 1987, 1988, 1991, 1993, 1994
+ *      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 char copyright[] =
+"@(#) Copyright (c) Apple Computer, Inc. 1997\n\n";
+#endif /* not lint */
+
+/*
+ * login [ name ]
+ * login -h hostname   (for telnetd, etc.)
+ * login -f name       (for pre-authenticated login: datakit, xterm, etc.)
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/file.h>
+
+#include <err.h>
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <ttyent.h>
+#include <tzfile.h>
+#include <unistd.h>
+#include <utmp.h>
+
+#include "pathnames.h"
+
+void    badlogin __P((char *));
+void    checknologin __P((void));
+void    dolastlog __P((int));
+void    getloginname __P((void));
+void    motd __P((void));
+int     rootterm __P((char *));
+void    sigint __P((int));
+void    sleepexit __P((int));
+char   *stypeof __P((char *));
+void    timedout __P((int));
+#ifdef KERBEROS
+int     klogin __P((struct passwd *, char *, char *, char *));
+#endif
+
+extern void login __P((struct utmp *));
+
+#define        TTYGRPNAME      "tty"           /* name of group to own ttys */
+
+/*
+ * This bounds the time given to login.  Not a define so it can
+ * be patched on machines where it's too small.
+ */
+u_int  timeout = 300;
+
+#ifdef KERBEROS
+int    notickets = 1;
+char   *instance;
+char   *krbtkfile_env;
+int    authok;
+#endif
+
+struct passwd *pwd;
+int    failures;
+char   term[64], *envinit[1], *hostname, *username, *tty;
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern char **environ;
+       struct group *gr;
+       struct stat st;
+       struct timeval tp;
+       struct utmp utmp;
+       int ask, ch, cnt, fflag, hflag, pflag, quietlog, rootlogin, rval;
+       uid_t uid;
+       char *domain, *p, *salt, *ttyn;
+       char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10];
+       char localhost[MAXHOSTNAMELEN];
+
+       (void)signal(SIGALRM, timedout);
+       (void)alarm(timeout);
+       (void)signal(SIGQUIT, SIG_IGN);
+       (void)signal(SIGINT, SIG_IGN);
+       (void)setpriority(PRIO_PROCESS, 0, 0);
+
+       openlog("login", LOG_ODELAY, LOG_AUTH);
+
+       /*
+        * -p is used by getty to tell login not to destroy the environment
+        * -f is used to skip a second login authentication
+        * -h is used by other servers to pass the name of the remote
+        *    host to login so that it may be placed in utmp and wtmp
+        */
+       domain = NULL;
+       if (gethostname(localhost, sizeof(localhost)) < 0)
+               syslog(LOG_ERR, "couldn't get local hostname: %m");
+       else
+               domain = strchr(localhost, '.');
+
+       fflag = hflag = pflag = 0;
+       uid = getuid();
+       while ((ch = getopt(argc, argv, "fh:p")) != EOF)
+               switch (ch) {
+               case 'f':
+                       fflag = 1;
+                       break;
+               case 'h':
+                       if (uid)
+                               errx(1, "-h option: %s", strerror(EPERM));
+                       hflag = 1;
+                       if (domain && (p = strchr(optarg, '.')) &&
+                           strcasecmp(p, domain) == 0)
+                               *p = 0;
+                       hostname = optarg;
+                       break;
+               case 'p':
+                       pflag = 1;
+                       break;
+               case '?':
+               default:
+                       if (!uid)
+                               syslog(LOG_ERR, "invalid flag %c", ch);
+                       (void)fprintf(stderr,
+                           "usage: login [-fp] [-h hostname] [username]\n");
+                       exit(1);
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (*argv) {
+               username = *argv;
+               ask = 0;
+       } else
+               ask = 1;
+
+       for (cnt = getdtablesize(); cnt > 2; cnt--)
+               (void)close(cnt);
+
+       ttyn = ttyname(STDIN_FILENO);
+       if (ttyn == NULL || *ttyn == '\0') {
+               (void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
+               ttyn = tname;
+       }
+       if (tty = strrchr(ttyn, '/'))
+               ++tty;
+       else
+               tty = ttyn;
+
+       for (cnt = 0;; ask = 1) {
+               if (ask) {
+                       fflag = 0;
+                       getloginname();
+               }
+               rootlogin = 0;
+#ifdef KERBEROS
+               if ((instance = strchr(username, '.')) != NULL) {
+                       if (strncmp(instance, ".root", 5) == 0)
+                               rootlogin = 1;
+                       *instance++ = '\0';
+               } else
+                       instance = "";
+#endif
+               if (strlen(username) > UT_NAMESIZE)
+                       username[UT_NAMESIZE] = '\0';
+
+               /*
+                * Note if trying multiple user names; log failures for
+                * previous user name, but don't bother logging one failure
+                * for nonexistent name (mistyped username).
+                */
+               if (failures && strcmp(tbuf, username)) {
+                       if (failures > (pwd ? 0 : 1))
+                               badlogin(tbuf);
+                       failures = 0;
+               }
+               (void)strcpy(tbuf, username);
+
+               if (pwd = getpwnam(username))
+                       salt = pwd->pw_passwd;
+               else
+                       salt = "xx";
+
+               /*
+                * if we have a valid account name, and it doesn't have a
+                * password, or the -f option was specified and the caller
+                * is root or the caller isn't changing their uid, don't
+                * authenticate.
+                */
+               if (pwd && (*pwd->pw_passwd == '\0' ||
+                   fflag && (uid == 0 || uid == pwd->pw_uid)))
+                       break;
+               fflag = 0;
+               if (pwd && pwd->pw_uid == 0)
+                       rootlogin = 1;
+
+               (void)setpriority(PRIO_PROCESS, 0, -4);
+
+               p = getpass("Password:");
+
+               if (pwd) {
+#ifdef KERBEROS
+                       rval = klogin(pwd, instance, localhost, p);
+                       if (rval != 0 && rootlogin && pwd->pw_uid != 0)
+                               rootlogin = 0;
+                       if (rval == 0)
+                               authok = 1;
+                       else if (rval == 1)
+                               rval = strcmp(crypt(p, salt), pwd->pw_passwd);
+#else
+                       rval = strcmp(crypt(p, salt), pwd->pw_passwd);
+#endif
+               }
+               memset(p, 0, strlen(p));
+
+               (void)setpriority(PRIO_PROCESS, 0, 0);
+
+               /*
+                * If trying to log in as root without Kerberos,
+                * but with insecure terminal, refuse the login attempt.
+                */
+#ifdef KERBEROS
+               if (authok == 0)
+#endif
+               if (pwd && rootlogin && !rootterm(tty)) {
+                       (void)fprintf(stderr,
+                           "%s login refused on this terminal.\n",
+                           pwd->pw_name);
+                       if (hostname)
+                               syslog(LOG_NOTICE,
+                                   "LOGIN %s REFUSED FROM %s ON TTY %s",
+                                   pwd->pw_name, hostname, tty);
+                       else
+                               syslog(LOG_NOTICE,
+                                   "LOGIN %s REFUSED ON TTY %s",
+                                    pwd->pw_name, tty);
+                       continue;
+               }
+
+               if (pwd && !rval)
+                       break;
+
+               (void)printf("Login incorrect\n");
+               failures++;
+               /* we allow 10 tries, but after 3 we start backing off */
+               if (++cnt > 3) {
+                       if (cnt >= 10) {
+                               badlogin(username);
+                               sleepexit(1);
+                       }
+                       sleep((u_int)((cnt - 3) * 5));
+               }
+       }
+
+       /* committed to login -- turn off timeout */
+       (void)alarm((u_int)0);
+
+       endpwent();
+
+       /* if user not super-user, check for disabled logins */
+       if (!rootlogin)
+               checknologin();
+
+       if (chdir(pwd->pw_dir) < 0) {
+               (void)printf("No home directory %s!\n", pwd->pw_dir);
+               if (chdir("/"))
+                       exit(0);
+               pwd->pw_dir = "/";
+               (void)printf("Logging in with home = \"/\".\n");
+       }
+
+       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);
+       (void)strncpy(utmp.ut_name, username, sizeof(utmp.ut_name));
+       if (hostname)
+               (void)strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host));
+       (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
+       login(&utmp);
+
+       dolastlog(quietlog);
+
+       (void)chown(ttyn, pwd->pw_uid,
+           (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
+       (void)setgid(pwd->pw_gid);
+
+       initgroups(username, pwd->pw_gid);
+
+       if (*pwd->pw_shell == '\0')
+               pwd->pw_shell = _PATH_BSHELL;
+
+       /* Destroy environment unless user has requested its preservation. */
+       if (!pflag)
+               environ = envinit;
+       (void)setenv("HOME", pwd->pw_dir, 1);
+       (void)setenv("SHELL", pwd->pw_shell, 1);
+       if (term[0] == '\0')
+               (void)strncpy(term, stypeof(tty), sizeof(term));
+       (void)setenv("TERM", term, 0);
+       (void)setenv("LOGNAME", pwd->pw_name, 1);
+       (void)setenv("USER", pwd->pw_name, 1);
+       (void)setenv("PATH", _PATH_DEFPATH, 0);
+#ifdef KERBEROS
+       if (krbtkfile_env)
+               (void)setenv("KRBTKFILE", krbtkfile_env, 1);
+#endif
+
+       if (tty[sizeof("tty")-1] == 'd')
+               syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
+
+       /* If fflag is on, assume caller/authenticator has logged root login. */
+       if (rootlogin && fflag == 0)
+               if (hostname)
+                       syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s FROM %s",
+                           username, tty, hostname);
+               else
+                       syslog(LOG_NOTICE, "ROOT LOGIN (%s) ON %s", username, tty);
+
+#ifdef KERBEROS
+       if (!quietlog && notickets == 1)
+               (void)printf("Warning: no Kerberos tickets issued.\n");
+#endif
+
+       if (!quietlog) {
+               motd();
+               (void)snprintf(tbuf,
+                   sizeof(tbuf), "%s/%s", _PATH_MAILDIR, pwd->pw_name);
+               if (stat(tbuf, &st) == 0 && st.st_size != 0)
+                       (void)printf("You have %smail.\n",
+                           (st.st_mtime > st.st_atime) ? "new " : "");
+       }
+
+       (void)signal(SIGALRM, SIG_DFL);
+       (void)signal(SIGQUIT, SIG_DFL);
+       (void)signal(SIGINT, SIG_DFL);
+       (void)signal(SIGTSTP, SIG_IGN);
+
+       tbuf[0] = '-';
+       (void)strcpy(tbuf + 1, (p = strrchr(pwd->pw_shell, '/')) ?
+           p + 1 : pwd->pw_shell);
+
+       if (setlogin(pwd->pw_name) < 0)
+               syslog(LOG_ERR, "setlogin() failure: %m");
+
+       /* Discard permissions last so can't get killed and drop core. */
+       if (rootlogin)
+               (void) setuid(0);
+       else
+               (void) setuid(pwd->pw_uid);
+
+       execlp(pwd->pw_shell, tbuf, 0);
+       err(1, "%s", pwd->pw_shell);
+}
+
+#ifdef KERBEROS
+#define        NBUFSIZ         (UT_NAMESIZE + 1 + 5)   /* .root suffix */
+#else
+#define        NBUFSIZ         (UT_NAMESIZE + 1)
+#endif
+
+void
+getloginname()
+{
+       int ch;
+       char *p;
+       static char nbuf[NBUFSIZ];
+
+       for (;;) {
+               (void)printf("login: ");
+               for (p = nbuf; (ch = getchar()) != '\n'; ) {
+                       if (ch == EOF) {
+                               badlogin(username);
+                               exit(0);
+                       }
+                       if (p < nbuf + (NBUFSIZ - 1))
+                               *p++ = ch;
+               }
+               if (p > nbuf)
+                       if (nbuf[0] == '-')
+                               (void)fprintf(stderr,
+                                   "login names may not start with '-'.\n");
+                       else {
+                               *p = '\0';
+                               username = nbuf;
+                               break;
+                       }
+       }
+}
+
+int
+rootterm(ttyn)
+       char *ttyn;
+{
+       struct ttyent *t;
+
+       return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
+}
+
+jmp_buf motdinterrupt;
+
+void
+motd()
+{
+       int fd, nchars;
+       sig_t oldint;
+       char tbuf[8192];
+
+       if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0)
+               return;
+       oldint = signal(SIGINT, sigint);
+       if (setjmp(motdinterrupt) == 0)
+               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+                       (void)write(fileno(stdout), tbuf, nchars);
+       (void)signal(SIGINT, oldint);
+       (void)close(fd);
+}
+
+/* ARGSUSED */
+void
+sigint(signo)
+       int signo;
+{
+
+       longjmp(motdinterrupt, 1);
+}
+
+/* ARGSUSED */
+void
+timedout(signo)
+       int signo;
+{
+
+       (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout);
+       exit(0);
+}
+
+void
+checknologin()
+{
+       int fd, nchars;
+       char tbuf[8192];
+
+       if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) {
+               while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0)
+                       (void)write(fileno(stdout), tbuf, nchars);
+               sleepexit(0);
+       }
+}
+
+void
+dolastlog(quiet)
+       int quiet;
+{
+       struct lastlog ll;
+       int fd;
+
+       if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
+               (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
+               if (!quiet) {
+                       if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) &&
+                           ll.ll_time != 0) {
+                               (void)printf("Last login: %.*s ",
+                                   24-5, (char *)ctime(&ll.ll_time));
+                               if (*ll.ll_host != '\0')
+                                       (void)printf("from %.*s\n",
+                                           (int)sizeof(ll.ll_host),
+                                           ll.ll_host);
+                               else
+                                       (void)printf("on %.*s\n",
+                                           (int)sizeof(ll.ll_line),
+                                           ll.ll_line);
+                       }
+                       (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET);
+               }
+               memset((void *)&ll, 0, sizeof(ll));
+               (void)time(&ll.ll_time);
+               (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
+               if (hostname)
+                       (void)strncpy(ll.ll_host, hostname, sizeof(ll.ll_host));
+               (void)write(fd, (char *)&ll, sizeof(ll));
+               (void)close(fd);
+       }
+}
+
+void
+badlogin(name)
+       char *name;
+{
+
+       if (failures == 0)
+               return;
+       if (hostname) {
+               syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s",
+                   failures, failures > 1 ? "S" : "", hostname);
+               syslog(LOG_AUTHPRIV|LOG_NOTICE,
+                   "%d LOGIN FAILURE%s FROM %s, %s",
+                   failures, failures > 1 ? "S" : "", hostname, name);
+       } else {
+               syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s",
+                   failures, failures > 1 ? "S" : "", tty);
+               syslog(LOG_AUTHPRIV|LOG_NOTICE,
+                   "%d LOGIN FAILURE%s ON %s, %s",
+                   failures, failures > 1 ? "S" : "", tty, name);
+       }
+}
+
+#undef UNKNOWN
+#define        UNKNOWN "su"
+
+char *
+stypeof(ttyid)
+       char *ttyid;
+{
+       struct ttyent *t;
+
+       return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN);
+}
+
+void
+sleepexit(eval)
+       int eval;
+{
+
+       (void)sleep(5);
+       exit(eval);
+}
diff --git a/login.tproj/pathnames.h b/login.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..b83bb9b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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@
+ */
+#include <paths.h>
+
+#define        _PATH_HUSHLOGIN ".hushlogin"
+#define        _PATH_MOTDFILE  "/etc/motd"
diff --git a/mach_init.tproj/Makefile b/mach_init.tproj/Makefile
new file mode 100644 (file)
index 0000000..706d04c
--- /dev/null
@@ -0,0 +1,56 @@
+#
+# 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 = mach_init
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = bootstrap_internal.h error_log.h lists.h parser.h
+
+CFILES = bootstrap.c error_log.c lists.c parser.c rpc_services.c
+
+OTHERSRCS = Makefile.preamble Makefile initConf Notes testConfig\
+            testConfig2 bootstrap.defs testServer
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+NEXTSTEP_PB_CFLAGS = -DMACH_USER_API
+WINDOWS_PB_CFLAGS = -DMACH_USER_API
+PDO_UNIX_PB_CFLAGS = -DMACH_USER_API
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/mach_init.tproj/Makefile.preamble b/mach_init.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..ef0b259
--- /dev/null
@@ -0,0 +1,4 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+BEFORE_BUILD += bootstrap.h
+OTHER_OFILES = bootstrapServer.o
+
diff --git a/mach_init.tproj/Notes b/mach_init.tproj/Notes
new file mode 100644 (file)
index 0000000..4c09847
--- /dev/null
@@ -0,0 +1,71 @@
+# 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.
+
diff --git a/mach_init.tproj/PB.project b/mach_init.tproj/PB.project
new file mode 100644 (file)
index 0000000..d937124
--- /dev/null
@@ -0,0 +1,49 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        BUNDLES = (); 
+        CLASSES = (); 
+        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, 
+            Makefile, 
+            initConf, 
+            Notes, 
+            testConfig, 
+            testConfig2, 
+            bootstrap.defs, 
+            testServer
+        ); 
+        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; 
+    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"; 
+}
diff --git a/mach_init.tproj/bootstrap.c b/mach_init.tproj/bootstrap.c
new file mode 100644 (file)
index 0000000..f55d191
--- /dev/null
@@ -0,0 +1,1027 @@
+/*
+ * 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.
+ *
+ * bootstrap.c -- implementation of bootstrap main service loop
+ */
+
+/*
+ * Imports
+ */
+#import        <mach/mach.h>
+#import        <mach/boolean.h>
+#import        <mach/message.h>
+#import <mach/notify.h>
+#import <mach/mig_errors.h>
+#include <mach/mach_traps.h>
+#include <mach/mach_interface.h>
+#include <mach/bootstrap.h>
+#include <mach/host_info.h>
+#include <mach/mach_host.h>
+#include <mach/exception.h>
+
+#import <sys/ioctl.h>
+#import        <string.h>
+#import        <ctype.h>
+#import        <stdio.h>
+#import <libc.h>
+
+#include "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);
+
+/*
+ * Exports
+ */
+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;";
+       
+mach_port_t inherited_bootstrap_port = MACH_PORT_NULL;
+boolean_t forward_ok = 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;
+
+#ifndef ASSERT
+#define ASSERT(p)
+#endif
+
+/*
+ * Private macros
+ */
+#define        NELEM(x)                (sizeof(x)/sizeof(x[0]))
+#define        END_OF(x)               (&(x)[NELEM(x)])
+#define        streq(a,b)              (strcmp(a,b) == 0)
+
+/*
+ * 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 exec_server(server_t *serverp);
+static char **argvize(const char *string);
+static void server_loop(void);
+static void msg_destroy(mach_msg_header_t *m);
+
+/*
+ * Private ports we hold receive rights for.  We also hold receive rights
+ * for all the privileged ports.  Those are maintained in the server
+ * structs.
+ */
+mach_port_t bootstrap_port_set;
+mach_port_t notify_port;
+
+static int init_pid;
+static int running_servers;
+static char init_args[BOOTSTRAP_MAX_CMD_LEN];
+
+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[])
+{
+       const char *argp;
+       char c;
+       server_t *init_serverp;
+       server_t *serverp;
+       mach_port_t init_notify_port;
+       kern_return_t result;
+       int pid;
+       int force_fork = FALSE;
+       mach_port_t prev_port;
+#if defined(__APPLE__)
+        extern void exit(int);
+       
+       /* signal (SIGUSR2, _myExit); */
+#endif
+
+       /* Initialize error handling */
+       program_name = rindex(*argv, '/');
+       if (program_name)
+               program_name++;
+       else
+               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++) {
+                       case 'd':
+                               debugging = TRUE;
+                               break;
+                       case 'D':
+                               debugging = FALSE;
+                               break;
+                       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) {
+                                       register_name = *argv++; argc--;
+                               } else
+                                       fatal("-r requires name");
+                               break;
+                       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 ((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) {
+               pid = fork();
+               if (pid < 0)
+                       unix_fatal("fork");
+       } else
+               pid = 0;
+       
+       /* 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();
+
+            /* 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 (result != KERN_SUCCESS)
+                               kern_error(result, "task_priority %d",
+                                       init_priority);
+               }
+#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);
+               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));
+}
+
+static void
+wait_for_go(mach_port_t init_notify_port)
+{
+        struct {
+            mach_msg_header_t hdr;
+            mach_msg_trailer_t trailer;
+        } 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()");
+        }
+}
+
+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);
+       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;
+       
+       /* 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, "port_set_allocate");
+       /* Create notify port and add to server port set */
+       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,
+                                               bootstrap_self,
+                                               MACH_NOTIFY_DEAD_NAME,
+                                               0,
+                                               notify_port,
+                                               MACH_MSG_TYPE_MAKE_SEND_ONCE,
+                                               &pport);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "task_set_notify_port");
+
+       result = mach_port_move_member(bootstrap_self,
+                                  notify_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);
+       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);
+       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.
+        */
+       for (  servicep = FIRST(services)
+            ; ! IS_END(servicep, services)
+            ; servicep = NEXT(servicep))
+       {
+               switch (servicep->servicetype) {
+               case DECLARED:
+                       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);
+                       if (result != KERN_SUCCESS)
+                               kern_fatal(result, "mach_port_insert_right");
+                       debug("Declared port %d 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 */
+                       break;
+               case SELF:
+                       servicep->port = bootstraps.bootstrap_port;
+                       servicep->server = new_server(MACHINIT,
+                               program_name, init_priority);
+                       info("Set port %d for self port",
+                             bootstraps.bootstrap_port);
+                       break;
+               case REGISTERED:
+                       fatal("Can't allocate REGISTERED port!?!");
+                       break;
+               }
+       }
+}
+
+static void
+start_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);
+       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");
+       /* Add privileged server port to bootstrap port set */
+       result = mach_port_move_member(mach_task_self(),
+                                  serverp->port,
+                                  bootstrap_port_set);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "mach_port_move_member");
+
+       /*
+        * 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 RESTARTABLE:
+               /* Give trusted service a unique bootstrap port */
+               result = task_set_bootstrap_port(mach_task_self(), serverp->port);
+               if (result != KERN_SUCCESS)
+                       kern_fatal(result, "task_set_bootstrap_port");
+
+               pid = fork();
+               if (pid < 0)
+                       unix_error("fork");
+               else if (pid == 0) {    /* CHILD */
+                       exec_server(serverp);
+                       exit(1);
+               } else {                /* PARENT */
+                       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;
+               }
+               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;
+       
+       /*
+        * 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();
+       }
+
+        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);
+       }
+
+        execv(argv[0], argv);
+       unix_error("Can't exec %s", argv[0]);
+}      
+
+static char **
+argvize(const char *string)
+{
+       static char *argv[100], args[1000];
+       const char *cp;
+       char *argp, term;
+       int nargs;
+       
+       /*
+        * Convert a command line into an argv for execv
+        */
+       nargs = 0;
+       argp = args;
+       
+       for (cp = string; *cp;) {
+               while (isspace(*cp))
+                       cp++;
+               term = (*cp == '"') ? *cp++ : '\0';
+               if (nargs < NELEM(argv))
+                       argv[nargs++] = argp;
+               while (*cp && (term ? *cp != term : !isspace(*cp))
+                && argp < END_OF(args)) {
+                       if (*cp == '\\')
+                               cp++;
+                       *argp++ = *cp;
+                       if (*cp)
+                               cp++;
+               }
+               *argp++ = '\0';
+       }
+       argv[nargs] = NULL;
+       return argv;
+}
+
+/*
+ * server_loop -- pick requests off our service port and process them
+ * Also handles notifications
+ */
+#define        bootstrapMaxRequestSize 1024
+#define        bootstrapMaxReplySize   1024
+
+static void
+server_loop(void)
+{
+    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;
+        
+    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;
+       }
+
+#if    DEBUG
+       debug("received message on port %d\n", msg.hdr.msgh_local_port);
+#endif DEBUG
+
+       /*
+        * 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;
+               }
+               
+               /*
+                * 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_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, 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.
+                        */
+                       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;
+                   }
+               }
+               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;
+
+       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);
+               } else {
+                       type = mtp->msg_type_name;
+                       size = mtp->msg_type_size;
+                       num = mtp->msg_type_number;
+                       dp = (void *)(mtp + 1);
+               }
+               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");
+               }
+       }
+#endif /* notyet ] */
+}
+
+/*
+ * msg_destroy_port -- deallocate port if it's not important to bootstrap
+ * Bad name, this is used for things other than msg_destroy.
+ */
+void
+msg_destroy_port(mach_port_t p)
+{
+       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);
+}
+
+boolean_t
+canReceive(mach_port_t port)
+{
+       mach_port_type_t p_type;
+       kern_return_t result;
+       
+       result = mach_port_type(mach_task_self(), port, &p_type);
+       if (result != KERN_SUCCESS) {
+               kern_error(result, "port_type");
+               return FALSE;
+       }
+       return ((p_type & MACH_PORT_TYPE_RECEIVE) != 0);
+}
+
+
+boolean_t
+canSend(mach_port_t port)
+{
+       mach_port_type_t p_type;
+       kern_return_t result;
+       
+       result = mach_port_type(mach_task_self(), port, &p_type);
+       if (result != KERN_SUCCESS) {
+               kern_error(result, "port_type");
+               return FALSE;
+       }
+       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
+}
diff --git a/mach_init.tproj/bootstrap.defs b/mach_init.tproj/bootstrap.defs
new file mode 100644 (file)
index 0000000..99af0cc
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * 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.
+ *
+ * bootstrap.defs -- Mig interface definition
+ */
+
+subsystem bootstrap 400;
+
+/*
+ *     Interface:      Bootstrap server
+ *
+ *  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.
+ *
+ *  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
+ *  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
+ *  bound port will be queued until a server has checked-in and can satisfy the
+ *  request.
+ *
+ *  2.  Bindings can be established dynamically via a "register" request.  In
+ *  this case, the register request provides bootstrap with a name and send
+ *  rights for a port.  Bootstrap will provide send rights for the bound port
+ *  to any requestor via the lookup request.
+ *
+ *  Bootstrap provides its service port to descendant tasks via the Mach
+ *  "bootstrap" special task port.  All direct descendants of bootstrap receive
+ *  a "privileged" bootstrap service port.  System services that initiate
+ *  untrusted tasks should replace the Mach bootstrap task special port with
+ *  a subset bootstrap port to prevent them from infecting the namespace.
+ *
+ *  The bootstrap server creates a "backup" port for each service that it
+ *  creates.  This is used to detect when a checked out service is no longer
+ *  being served.  The bootstrap server regains all rights to the port and
+ *  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.
+ *
+ *  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.
+ */
+
+#include <mach/std_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;
+
+serverprefix x_;
+
+/*  old service_checkin */
+skip;
+/*  old service_status */
+skip;
+
+/*
+ * kern_return_t
+ * bootstrap_check_in(mach_port_t bootstrap_port,
+ *                  name_t service_name,
+ *                  port_all_t *service_port)
+ *
+ * Returns all rights to service_port of service named by service_name.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ *             Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
+ *                     bootstrap port without privilege.
+ *             Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
+ *                     registered or checked-in.
+ */
+routine bootstrap_check_in(
+                       bootstrap_port  : mach_port_t;
+                       service_name    : name_t;
+               out     service_port    : mach_port_move_receive_t);
+
+/*
+ * kern_return_t
+ * bootstrap_register(mach_port_t bootstrap_port,
+ *                   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.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
+ *                     bootstrap port without privilege.
+ *             Returns BOOTSTRAP_NAME_IN_USE, if service has already been
+ *                     register or checked-in.
+ */
+routine bootstrap_register(
+               bootstrap_port  : mach_port_t;
+               service_name    : name_t;
+               service_port    : mach_port_t);
+
+/*
+ * kern_return_t
+ * bootstrap_look_up(mach_port_t bootstrap_port,
+ *                 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.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ */
+routine bootstrap_look_up(
+               bootstrap_port  : mach_port_t;
+               service_name    : name_t;
+       out     service_port    : mach_port_t);
+
+/*
+ * kern_return_t
+ * bootstrap_look_up_array(mach_port_t bootstrap_port,
+ *                       name_array_t service_names,
+ *                       int service_names_cnt,
+ *                       port_array_t *service_port,
+ *                       int *service_ports_cnt,
+ *                       boolean_t *all_services_known)
+ *
+ * Returns port send rights in corresponding entries of the array service_ports
+ * for all services named in the array service_names.  Service_ports_cnt is
+ * returned and will always equal service_names_cnt (assuming service_names_cnt
+ * is greater than or equal to zero).
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NO_MEMORY, if server couldn't obtain memory
+ *                     for response.
+ *             Unknown service names have the corresponding service port set
+ *                     to PORT_NULL.
+ *             If all services are known, all_services_known is true on
+ *                     return, if any service is unknown, it's false.
+ */
+routine bootstrap_look_up_array(
+               bootstrap_port  : mach_port_t;
+               service_names   : name_array_t;
+       out     service_ports   : mach_port_array_t;
+       out     all_services_known: boolean_t);
+
+/*  old bootstrap_get_unpriv_port */
+skip;
+
+/*
+ * kern_return_t
+ * bootstrap_status(mach_port_t bootstrap_port,
+ *                 name_t service_name,
+ *                 boolean_t *service_active);
+ *
+ * Returns: service_active is true if service is available.
+ *                     
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ */
+routine bootstrap_status(
+               bootstrap_port  :       mach_port_t;
+               service_name    :       name_t;
+       out     service_active  :       boolean_t);
+
+/*
+ * kern_return_t
+ * bootstrap_info(port_t bootstrap_port,
+ *               name_array_t *service_names,
+ *               int *service_names_cnt,
+ *               name_array_t *server_names,
+ *               int *server_names_cnt,
+ *               bool_array_t *service_active,
+ *               int *service_active_cnt);
+ *                     
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ */
+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);
+
+/*
+ * kern_return_t
+ * bootstrap_subset(mach_port_t bootstrap_port,
+ *                 mach_port_t requestor_port,
+ *                 mach_port_t *subset_port);
+ *
+ * Returns a new port to use as a bootstrap port.  This port behaves
+ * exactly like the previous bootstrap_port, except that ports dynamically
+ * registered via bootstrap_register() are available only to users of this
+ * specific subset_port.  Lookups on the subset_port will return ports
+ * registered with this port specifically, and ports registered with
+ * ancestors of this subset_port.  Duplications of services already
+ * 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
+ * port and all services advertized by it are destroied as well.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ */
+routine bootstrap_subset(
+               bootstrap_port  : mach_port_t;
+               requestor_port  : mach_port_t;
+       out     subset_port     : mach_port_t);
+
+/*
+ * kern_return_t
+ * bootstrap_create_service(mach_port_t bootstrap_port,
+ *                   name_t service_name,
+ *                   mach_port_t *service_port)
+ *
+ * Creates a service named "service_name" and returns send rights to that
+ * port in "service_port."  The port may later be checked in as if this
+ * port were configured in the bootstrap configuration file.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_SERVICE_ACTIVE, if service already exists.
+ */
+routine bootstrap_create_service(
+               bootstrap_port  : mach_port_t;
+               service_name    : name_t;
+       out     service_port    : mach_port_t);
diff --git a/mach_init.tproj/bootstrap_internal.h b/mach_init.tproj/bootstrap_internal.h
new file mode 100644 (file)
index 0000000..b494e93
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ * bootstrap_internal.h -- global internal data definitions
+ */
+
+#import <mach/mach.h>
+#import <mach/boolean.h>
+
+#define BASEPRI_USER   10      /* AOF Thu Feb 16 14:42:57 PST 1995 */
+
+#define        BITS_PER_BYTE   8       /* this SHOULD be a well defined constant */
+#define        ANYWHERE        TRUE    /* For use with vm_allocate() */
+
+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 boolean_t canReceive(mach_port_t port);
+extern boolean_t canSend(mach_port_t port);
+
+extern void msg_destroy_port(mach_port_t p);
diff --git a/mach_init.tproj/error_log.c b/mach_init.tproj/error_log.c
new file mode 100644 (file)
index 0000000..599e4d9
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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.
+ *
+ * error_log.c -- implementation of logging routines
+ *
+ * Routines may be safely invoked from multiple threads
+ */
+
+#import <pthread.h>
+#import <mach/mach_error.h>
+#import <stdio.h>
+#import <syslog.h>
+#import <sys/syslimits.h>
+#import <libc.h>
+#import        <errno.h>
+
+#import "bootstrap_internal.h"
+#import "error_log.h"
+
+static pthread_mutex_t errlog_lock = PTHREAD_MUTEX_INITIALIZER;
+
+void
+init_errlog(boolean_t is_init)
+{
+       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);
+       }
+
+       nfds = getdtablesize();
+       for (fd = 3; fd < nfds; fd++)
+               close(fd);
+       openlog((char *)program_name, LOG_PID, LOG_DAEMON);
+       setlogmask(LOG_UPTO(LOG_INFO));
+}
+
+void
+close_errlog(void)
+{
+       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);
+       }
+       pthread_mutex_unlock(&errlog_lock);
+}
+
+void debug(const char *format, ...)
+{
+    if (debugging) {
+       va_list ap;
+       
+       va_start(ap, format);
+       do_log(LOG_DEBUG, format, ap);
+       va_end(ap);
+    }
+}
+
+void info(const char *format, ...)
+{
+       va_list ap;
+       
+       va_start(ap, format);
+       do_log(LOG_INFO, format, ap);
+       va_end(ap);
+}
+
+__private_extern__ void log(const char *format, ...)
+{
+       va_list ap;
+       
+       va_start(ap, format);
+       do_log(LOG_NOTICE, format, ap);
+       va_end(ap);
+}
+
+void error(const char *format, ...)
+{
+       va_list ap;
+       
+       va_start(ap, format);
+       do_log(LOG_CRIT, format, ap);
+       va_end(ap);
+}
+
+void kern_error(kern_return_t result, const char *format, ...)
+{
+       va_list ap;
+       char buf[1000];
+       
+       sprintf(buf, "%s: %s(%d)", format, mach_error_string(result), result);
+
+       va_start(ap, format);
+       do_log(LOG_CRIT, buf, ap);
+       va_end(ap);
+}
+
+void unix_error(const char *format, ...)
+{
+       va_list ap;
+       char buf[1000];
+       
+       sprintf(buf, "%s: %s(%d)", format, strerror(errno), errno);
+
+       va_start(ap, format);
+       do_log(LOG_CRIT, buf, ap);
+       va_end(ap);
+}
+
+void parse_error(const char *token_string, const char *format, ...)
+{
+       va_list ap;
+       char buf[1000];
+
+       sprintf(buf, "%s unexpected: %s", token_string, format);
+
+       va_start(ap, format);
+       do_log(LOG_CRIT, buf, ap);
+       va_end(ap);
+}
+
+void fatal(const char *format, ...)
+{
+       va_list ap;
+       
+       va_start(ap, format);
+       do_log(LOG_ALERT, format, ap);
+       va_end(ap);
+       exit(1);
+}
+
+void kern_fatal(kern_return_t result, const char *format, ...)
+{
+       va_list ap;
+       char buf[1000];
+       
+       sprintf(buf, "%s: %s(%d)", format, mach_error_string(result), result);
+
+       va_start(ap, format);
+       do_log(LOG_ALERT, buf, ap);
+       va_end(ap);
+       exit(1);
+}
+
+void unix_fatal(const char *format, ...)
+{
+       va_list ap;
+       char buf[1000];
+       
+       sprintf(buf, "%s: %s(%d)", format, strerror(errno), errno);
+
+       va_start(ap, format);
+       do_log(LOG_ALERT, buf, ap);
+       va_end(ap);
+       exit(1);
+}
diff --git a/mach_init.tproj/error_log.h b/mach_init.tproj/error_log.h
new file mode 100644 (file)
index 0000000..027ab75
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * error_log.h -- interface to logging routines
+ */
+
+#import <mach/mach.h>
+
+extern void init_errlog(boolean_t is_init);
+extern void debug(const char *format, ...);
+extern void info(const char *format, ...);
+extern void log(const char *format, ...);
+extern void error(const char *format, ...);
+extern void kern_error(kern_return_t result, const char *format, ...);
+extern void parse_error(const char *token_string, const char *format, ...);
+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
new file mode 100644 (file)
index 0000000..b52c7e9
--- /dev/null
@@ -0,0 +1,7 @@
+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;
+
+
diff --git a/mach_init.tproj/lists.c b/mach_init.tproj/lists.c
new file mode 100644 (file)
index 0000000..9f371a1
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * 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.
+ *
+ * lists.c -- implementation of list handling routines
+ */
+
+#import <mach/boolean.h>
+#import <mach/mach_error.h>
+
+#import <stdlib.h>
+#import <string.h>
+
+#import "bootstrap_internal.h"
+#import "lists.h"
+#import "error_log.h"
+
+/*
+ * Exports
+ */
+bootstrap_info_t bootstraps;           /* head of list of all bootstrap ports */
+server_t servers;              /* head of list of all servers */
+service_t services;            /* head of list of all services */
+unsigned nservices;            /* number of services in list */
+
+#ifndef ASSERT
+#define ASSERT(p)
+#endif
+
+/*
+ * Private macros
+ */
+#define        NEW(type, num)  ((type *)ckmalloc(sizeof(type) * num))
+#define        STREQ(a, b)             (strcmp(a, b) == 0)
+#define        NELEM(x)                        (sizeof(x)/sizeof((x)[0]))
+#define        LAST_ELEMENT(x)         ((x)[NELEM(x)-1])
+
+void
+init_lists(void)
+{
+       bootstraps.next = bootstraps.prev = &bootstraps;
+       servers.next = servers.prev = &servers;
+       services.next = services.prev = &services;
+       nservices = 0;
+}
+
+server_t *
+new_server(
+       servertype_t    servertype,
+       const char      *cmd,
+       int             priority)
+{
+       server_t *serverp;
+
+       debug("adding new server \"%s\" with priority %d\n", cmd, priority);    
+       serverp = NEW(server_t, 1);
+       if (serverp != NULL) {
+               /* Doubly linked list */
+               servers.prev->next = serverp;
+               serverp->prev = servers.prev;
+               serverp->next = &servers;
+               servers.prev = serverp;
+
+               serverp->port = MACH_PORT_NULL;
+               serverp->servertype = servertype;
+               serverp->priority = priority;
+               strncpy(serverp->cmd, cmd, sizeof serverp->cmd);
+               LAST_ELEMENT(serverp->cmd) = '\0';
+       }
+       return serverp;
+}
+                       
+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)
+{
+       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) {
+               /* Doubly linked list */
+               services.prev->next = servicep;
+               servicep->prev = services.prev;
+               servicep->next = &services;
+               services.prev = servicep;
+               
+               nservices += 1;
+               
+               strncpy(servicep->name, name, sizeof servicep->name);
+               LAST_ELEMENT(servicep->name) = '\0';
+               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;
+       }
+       return servicep;
+}
+
+bootstrap_info_t *
+new_bootstrap(
+       bootstrap_info_t        *parent,
+       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) {
+               /* Doubly linked list */
+               bootstraps.prev->next = bootstrap;
+               bootstrap->prev = bootstraps.prev;
+               bootstrap->next = &bootstraps;
+               bootstraps.prev = 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));
+                }
+
+       }
+       return bootstrap;
+}
+
+bootstrap_info_t *
+lookup_bootstrap_by_port(mach_port_t port)
+{
+       bootstrap_info_t *bootstrap;
+
+       for (  bootstrap = FIRST(bootstraps)
+            ; !IS_END(bootstrap, bootstraps)
+            ; bootstrap = NEXT(bootstrap))
+       {
+               if (bootstrap->bootstrap_port == port)
+                       return bootstrap;
+       }
+
+       return &bootstraps;
+}
+
+bootstrap_info_t *
+lookup_bootstrap_req_by_port(mach_port_t port)
+{
+       bootstrap_info_t *bootstrap;
+
+       for (  bootstrap = FIRST(bootstraps)
+            ; !IS_END(bootstrap, bootstraps)
+            ; bootstrap = NEXT(bootstrap))
+       {
+               if (bootstrap->requestor_port == port)
+                       return bootstrap;
+       }
+
+       return NULL;
+}
+
+service_t *
+lookup_service_by_name(bootstrap_info_t *bootstrap, name_t name)
+{
+       service_t *servicep;
+
+       while (bootstrap) {
+               for (  servicep = FIRST(services)
+                    ; !IS_END(servicep, services)
+                    ; servicep = NEXT(servicep))
+               {
+                       if (!STREQ(name, servicep->name))
+                               continue;
+                       if (bootstrap && servicep->bootstrap != bootstrap)
+                               continue;
+                       return servicep;
+               }
+               bootstrap = bootstrap->parent;
+       }
+
+       return NULL;
+}
+
+void
+unlink_service(service_t *servicep)
+{
+       ASSERT(servicep->prev->next == servicep);
+       ASSERT(servicep->next->prev == servicep);
+       servicep->prev->next = servicep->next;
+       servicep->next->prev = servicep->prev;
+       servicep->prev = servicep->next = servicep;     // idempotent
+}
+
+void
+delete_service(service_t *servicep)
+{
+       unlink_service(servicep);
+       free(servicep);
+       nservices -= 1;
+}
+
+void
+destroy_services(bootstrap_info_t *bootstrap)
+{
+       service_t *servicep;
+       service_t *next;
+       
+       for (  servicep = FIRST(services)
+            ; !IS_END(servicep, services)
+            ; servicep = next)
+       {
+               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);
+                       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;
+               }
+       }
+}
+
+service_t *
+lookup_service_by_port(mach_port_t port)
+{
+       service_t *servicep;
+       
+        for (  servicep = FIRST(services)
+            ; !IS_END(servicep, services)
+            ; servicep = NEXT(servicep))
+       {
+               if (port == servicep->port)
+                       return servicep;
+       }
+        return NULL;
+}
+
+server_t *
+lookup_server_by_task_port(mach_port_t port)
+{
+       server_t *serverp;
+       
+       for (  serverp = FIRST(servers)
+            ; !IS_END(serverp, servers)
+            ; serverp = NEXT(serverp))
+       {
+               if (port == serverp->task_port)
+                       return serverp;
+       }
+       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)
+{
+       server_t *serverp;
+       
+       for (  serverp = FIRST(servers)
+            ; !IS_END(serverp, servers)
+            ; serverp = NEXT(serverp))
+       {
+               if (port == serverp->port)
+                       return serverp;
+       }
+       return NULL;
+}
+
+server_t *
+find_init_server(void)
+{
+       server_t *serverp;
+       
+       for (  serverp = FIRST(servers)
+            ; !IS_END(serverp, servers)
+            ; serverp = NEXT(serverp))
+       {
+               if (serverp->servertype == ETCINIT)
+                       return serverp;
+       }
+       return NULL;
+}
+
+void *
+ckmalloc(unsigned nbytes)
+{
+       void *cp;
+       
+       if ((cp = malloc(nbytes)) == NULL)
+               fatal("Out of memory");
+       return cp;
+}
+
+
diff --git a/mach_init.tproj/lists.h b/mach_init.tproj/lists.h
new file mode 100644 (file)
index 0000000..99e5478
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ *
+ * lists.h -- interface to list routines
+ */
+
+#import <mach/mach.h>
+#import <mach/boolean.h>
+#import <servers/bootstrap_defs.h>
+
+#ifndef NULL
+#define        NULL    ((void *)0)
+#endif NULL
+
+typedef struct bootstrap bootstrap_info_t;
+typedef struct service service_t;
+typedef struct server server_t;
+
+/* Bootstrap info */
+struct bootstrap {
+       bootstrap_info_t                *next;          /* list of all bootstraps */
+       bootstrap_info_t                *prev;
+       bootstrap_info_t                *parent;
+       mach_port_name_t                bootstrap_port;
+       mach_port_name_t                requestor_port;
+};
+
+/* Service types */
+typedef enum {
+       DECLARED,       /* Declared in config file */
+       REGISTERED,     /* Registered dynamically */
+       SELF            /* Name bound bootstrap service itself */
+} servicetype_t;
+
+struct service {
+       service_t       *next;          /* list of all services */
+       service_t       *prev;
+       name_t          name;           /* service name */
+       mach_port_name_t        port;           /* service port,
+                                          may have all rights if inactive */
+       bootstrap_info_t        *bootstrap;     /* bootstrap port(s) used at this
+                                        * level. */
+       boolean_t       isActive;       /* server is running */
+       servicetype_t   servicetype;    /* Declared, Registered, or Machport */
+       server_t        *server;        /* server, declared services only */
+};
+
+/* Server types */
+typedef enum {
+       SERVER,         /* Launchable server */
+       RESTARTABLE,    /* Restartable server */
+       ETCINIT,        /* Special processing for /etc/init */
+       MACHINIT        /* mach_init doesn't get launched. */
+} servertype_t;
+
+#define        NULL_SERVER     NULL
+#define        ACTIVE          TRUE
+
+struct server {
+       server_t        *next;          /* list of all servers */
+       server_t        *prev;
+       servertype_t    servertype;
+       cmd_t           cmd;            /* server command to exec */
+       int             priority;       /* priority to give server */
+       mach_port_t     port;           /* server's priv bootstrap port */
+       mach_port_name_t        task_port;      /* server's task port */
+};
+
+#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      *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,
+       mach_port_name_t        requestor_port);
+
+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 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 void *ckmalloc(unsigned nbytes);
+
+extern bootstrap_info_t bootstraps;            /* head of list of bootstrap ports */
+extern server_t servers;               /* head of list of all servers */
+extern service_t services;             /* head of list of all services */
+extern unsigned nservices;             /* number of services in list */
+
+#define        FIRST(q)                ((q).next)
+#define        NEXT(qe)                ((qe)->next)
+#define        PREV(qe)                ((qe)->prev)
+#define        IS_END(qe, q)           ((qe) == &(q))
diff --git a/mach_init.tproj/parser.c b/mach_init.tproj/parser.c
new file mode 100644 (file)
index 0000000..e20f194
--- /dev/null
@@ -0,0 +1,495 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..079ec7b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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);
+
+
diff --git a/mach_init.tproj/rpc_services.c b/mach_init.tproj/rpc_services.c
new file mode 100644 (file)
index 0000000..6c08bbe
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * 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.
+ *
+ * rpc_services.c -- implementation of bootstrap rpc services
+ */
+
+#import <mach/mach.h>
+#import <string.h>
+
+#import "bootstrap_internal.h"
+#import "error_log.h"
+#import "lists.h"
+#import "bootstrap.h"
+
+#ifndef ASSERT
+#define ASSERT(p)
+#endif
+
+#ifndef NULL
+#define        NULL    ((void *)0)
+#endif NULL
+/* extern port_all_t backup_port; */
+
+/*
+ * kern_return_t
+ * bootstrap_check_in(mach_port_t bootstrap_port,
+ *      name_t service_name,
+ *      mach_port_t *service_portp)
+ *
+ * Returns receive rights to service_port of service named by service_name.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ *             Returns BOOTSTRAP_SERVICE_NOT_DECLARED, if service not declared
+ *                     in /etc/bootstrap.conf.
+ *             Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
+ *                     registered or checked-in.
+ */
+kern_return_t
+x_bootstrap_check_in(
+       mach_port_t     bootstrap_port,
+       name_t          service_name,
+       mach_port_t     *service_portp)
+{
+       kern_return_t result;
+       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;
+       }
+       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;
+       }
+       if (servicep->server != NULL && servicep->server != serverp) {
+               debug("bootstrap_check_in service %s not privileged",
+                       service_name);
+                return BOOTSTRAP_NOT_PRIVILEGED;
+       }
+       if (servicep->servicetype == SELF || !canReceive(servicep->port)) {
+               ASSERT(servicep->isActive);
+               debug("bootstrap_check_in service %s already active",
+                       service_name);
+               return BOOTSTRAP_SERVICE_ACTIVE;
+       }
+       log("Checkin service %s", service_name);
+       ASSERT(servicep->isActive == FALSE);
+       servicep->isActive = TRUE;
+       *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;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_register(mach_port_t bootstrap_port,
+ *     name_t service_name,
+ *     mach_port_t service_port)
+ *
+ * Registers send rights for the port service_port for the service named by
+ * service_name.  Registering a declared service or registering a service for
+ * which bootstrap has receive rights via a port backup notification is
+ * allowed.
+ * The previous service port will be deallocated.  Restarting services wishing
+ * to resume service for previous clients must first attempt to checkin to the
+ * service.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NOT_PRIVILEGED, if request directed to
+ *                     unprivileged bootstrap port.
+ *             Returns BOOTSTRAP_SERVICE_ACTIVE, if service has already been
+ *                     register or checked-in.
+ */
+kern_return_t
+x_bootstrap_register(
+       mach_port_t     bootstrap_port,
+       name_t  service_name,
+       mach_port_t     service_port)
+{
+       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",
+             service_name, service_port);
+
+       /*
+        * If this bootstrap port is for a server, or it's an unprivileged
+        * bootstrap can't register the port.
+        */
+       serverp = lookup_server_by_port(bootstrap_port);
+       servicep = lookup_service_by_name(bootstrap, service_name);
+       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,
+                                      service_port,
+                                      ACTIVE,
+                                      REGISTERED,
+                                      NULL_SERVER);
+               debug("Registered new service %s", service_name);
+       } else {
+            if (servicep->isActive) {
+                       debug("Register: service %s already active, port %d",
+                             servicep->name, servicep->port);
+                       ASSERT(!canReceive(servicep->port));
+                       return BOOTSTRAP_SERVICE_ACTIVE;
+               }
+            old_port = servicep->port;
+               servicep->port = service_port;
+               msg_destroy_port(old_port);
+               servicep->isActive = TRUE;
+               log("Re-registered inactive service %s", service_name);
+       }
+       debug("Registering port %d for service %s\n",
+             servicep->port,
+             servicep->name);
+       return BOOTSTRAP_SUCCESS;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_look_up(mach_port_t bootstrap_port,
+ *     name_t service_name,
+ *     mach_port_t *service_portp)
+ *
+ * Returns send rights for the service port of the service named by
+ * service_name in *service_portp.  Service is not guaranteed to be active.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_UNKNOWN_SERVICE, if service does not exist.
+ */
+kern_return_t
+x_bootstrap_look_up(
+       mach_port_t     bootstrap_port,
+       name_t  service_name,
+       mach_port_t     *service_portp)
+{
+       service_t *servicep;
+       bootstrap_info_t *bootstrap;
+
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       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",
+             servicep->port,
+             servicep->name);
+#endif DEBUG
+       return BOOTSTRAP_SUCCESS;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_look_up_array(mach_port_t bootstrap_port,
+ *     name_array_t    service_names,
+ *     int             service_names_cnt,
+ *     mach_port_array_t       *service_ports,
+ *     int             *service_ports_cnt,
+ *     boolean_t       *all_services_known)
+ *
+ * Returns port send rights in corresponding entries of the array service_ports
+ * for all services named in the array service_names.  Service_ports_cnt is
+ * returned and will always equal service_names_cnt (assuming service_names_cnt
+ * is greater than or equal to zero).
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NO_MEMORY, if server couldn't obtain memory
+ *                     for response.
+ *             Unknown service names have the corresponding service
+ *                     port set to MACH_PORT_NULL.
+ *             If all services are known, all_services_known is true on
+ *                     return,
+ *             if any service is unknown, it's false.
+ */
+kern_return_t
+x_bootstrap_look_up_array(
+       mach_port_t     bootstrap_port,
+       name_array_t    service_names,
+       unsigned int    service_names_cnt,
+       mach_port_array_t       *service_portsp,
+       unsigned int    *service_ports_cnt,
+       boolean_t       *all_services_known)
+{
+       unsigned int i;
+       static mach_port_t service_ports[BOOTSTRAP_MAX_LOOKUP_COUNT];
+       
+       if (service_names_cnt > BOOTSTRAP_MAX_LOOKUP_COUNT)
+               return BOOTSTRAP_BAD_COUNT;
+       *service_ports_cnt = service_names_cnt;
+       *all_services_known = TRUE;
+       for (i = 0; i < service_names_cnt; i++) {
+               if (   x_bootstrap_look_up(bootstrap_port,
+                                         service_names[i],
+                                         &service_ports[i])
+                   != BOOTSTRAP_SUCCESS)
+               {
+                       *all_services_known = FALSE;
+                       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_status(mach_port_t bootstrap_port,
+ *     name_t service_name,
+ *     boolean_t *service_active);
+ *
+ * Returns: service_active is true 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)
+{
+       service_t *servicep;
+       bootstrap_info_t *bootstrap;
+
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+       servicep = lookup_service_by_name(bootstrap, service_name);
+       if (servicep == NULL) {
+               if (forward_ok) {
+                       debug("bootstrap_status forwarding status, server %s",
+                               service_name);
+                       return bootstrap_status(inherited_bootstrap_port,
+                                               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
+       debug("bootstrap_status server %s %sactive", service_name,
+               servicep->isActive ? "" : "in");
+#endif DEBUG
+       return BOOTSTRAP_SUCCESS;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_info(mach_port_t bootstrap_port,
+ *     name_array_t *service_names,
+ *     int *service_names_cnt,
+ *     name_array_t *server_names,
+ *     int *server_names_cnt,
+ *     bool_array_t *service_actives,
+ *     int *service_active_cnt);
+ *
+ * Returns bootstrap status for all known services.
+ *                     
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ */
+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)
+{
+       kern_return_t result;
+       unsigned int i, cnt;
+       service_t *servicep;
+       server_t *serverp;
+       bootstrap_info_t *bootstrap;
+       name_array_t service_names;
+       name_array_t server_names;
+       bool_array_t service_actives;
+
+       bootstrap = lookup_bootstrap_by_port(bootstrap_port);
+
+       for (   cnt = i = 0, servicep = services.next
+            ; i < nservices
+            ; servicep = servicep->next, i++)
+       {
+           if (lookup_service_by_name(bootstrap, servicep->name) == servicep)
+           {
+               cnt++;
+           }
+       }
+       result = vm_allocate(mach_task_self(),
+                            (vm_address_t *)&service_names,
+                            cnt * sizeof(service_names[0]),
+                            ANYWHERE);
+       if (result != KERN_SUCCESS)
+               return BOOTSTRAP_NO_MEMORY;
+
+       result = vm_allocate(mach_task_self(),
+                            (vm_address_t *)&server_names,
+                            cnt * sizeof(server_names[0]),
+                            ANYWHERE);
+       if (result != KERN_SUCCESS) {
+               (void)vm_deallocate(mach_task_self(),
+                                   (vm_address_t)service_names,
+                                   cnt * sizeof(service_names[0]));
+               return BOOTSTRAP_NO_MEMORY;
+       }
+       result = vm_allocate(mach_task_self(),
+                            (vm_address_t *)&service_actives,
+                            cnt * sizeof(service_actives[0]),
+                            ANYWHERE);
+       if (result != KERN_SUCCESS) {
+               (void)vm_deallocate(mach_task_self(),
+                                   (vm_address_t)service_names,
+                                   cnt * sizeof(service_names[0]));
+               (void)vm_deallocate(mach_task_self(),
+                                   (vm_address_t)server_names,
+                                   cnt * sizeof(server_names[0]));
+               return BOOTSTRAP_NO_MEMORY;
+       }
+
+       for (  i = 0, servicep = services.next
+            ; i < nservices
+            ; servicep = servicep->next)
+       {
+           if (   lookup_service_by_name(bootstrap, servicep->name)
+               != servicep)
+               continue;
+           strncpy(service_names[i],
+                   servicep->name,
+                   sizeof(service_names[0]));
+           service_names[i][sizeof(service_names[0]) - 1] = '\0';
+           if (servicep->server) {
+                   serverp = servicep->server;
+                   strncpy(server_names[i],
+                           serverp->cmd,
+                           sizeof(server_names[0]));
+                   server_names[i][sizeof(server_names[0]) - 1] = '\0';
+                   debug("bootstrap info service %s server %s %sactive",
+                       servicep->name,
+                       serverp->cmd, servicep->isActive ? "" : "in"); 
+           } else {
+                   server_names[i][0] = '\0';
+                   debug("bootstrap info service %s %sactive",
+                       servicep->name, servicep->isActive ? "" : "in"); 
+           }
+           service_actives[i] = servicep->isActive;
+           i++;
+       }
+       *service_namesp = service_names;
+       *server_namesp = server_names;
+       *service_activesp = service_actives;
+       *service_names_cnt = *server_names_cnt =
+               *service_actives_cnt = cnt;
+
+       return BOOTSTRAP_SUCCESS;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_subset(mach_port_t bootstrap_port,
+ *                 mach_port_t requestor_port,
+ *                 mach_port_t *subset_port);
+ *
+ * Returns a new port to use as a bootstrap port.  This port behaves
+ * exactly like the previous bootstrap_port, except that ports dynamically
+ * registered via bootstrap_register() are available only to users of this
+ * specific subset_port.  Lookups on the subset_port will return ports
+ * registered with this port specifically, and ports registered with
+ * ancestors of this subset_port.  Duplications of services already
+ * registered with an ancestor port may be registered with the subset port
+ * are allowed.  Services already advertised may then be effectively removed
+ * by registering MACH_PORT_NULL for the service.
+ * When it is detected that the requestor_port is destroied the subset
+ * port and all services advertized by it are destroied as well.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ */
+kern_return_t
+x_bootstrap_subset(
+       mach_port_t     bootstrap_port,
+       mach_port_t     requestor_port,
+       mach_port_t     *subset_port)
+{
+       kern_return_t result;
+       bootstrap_info_t *bootstrap;
+       bootstrap_info_t *subset;
+       mach_port_t new_bootstrap_port;
+
+       bootstrap = lookup_bootstrap_by_port(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);
+       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);
+       if (result != KERN_SUCCESS)
+               kern_fatal(result, "port_set_add");
+
+       subset = new_bootstrap(bootstrap, new_bootstrap_port, requestor_port);
+       *subset_port = new_bootstrap_port;
+       debug("bootstrap_subset new bootstrap %d", new_bootstrap_port);
+       return BOOTSTRAP_SUCCESS;
+}
+
+/*
+ * kern_return_t
+ * bootstrap_create_service(mach_port_t bootstrap_port,
+ *                   name_t service_name,
+ *                   mach_port_t *service_port)
+ *
+ * Creates a service named "service_name" and returns send rights to that
+ * port in "service_port."  The port may later be checked in as if this
+ * port were configured in the bootstrap configuration file.
+ *
+ * Errors:     Returns appropriate kernel errors on rpc failure.
+ *             Returns BOOTSTRAP_NAME_IN_USE, if service already exists.
+ */
+kern_return_t
+x_bootstrap_create_service(
+       mach_port_t bootstrap_port,
+       name_t  service_name,
+       mach_port_t *service_port)
+{
+       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);
+
+       servicep = lookup_service_by_name(bootstrap, service_name);
+       if (servicep) {
+               debug("Service creation attempt for service %s failed, "
+                       "service already exists", service_name);
+               return BOOTSTRAP_NAME_IN_USE;
+       }
+
+       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 */
+
+       servicep = new_service(bootstrap,
+                               service_name,
+                               *service_port,
+                               !ACTIVE,
+                               DECLARED,
+                               NULL_SERVER);
+
+       log("Created new service %s", service_name);
+
+       return BOOTSTRAP_SUCCESS;
+}
diff --git a/mach_init.tproj/testConfig b/mach_init.tproj/testConfig
new file mode 100644 (file)
index 0000000..893009e
--- /dev/null
@@ -0,0 +1,7 @@
+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
new file mode 100644 (file)
index 0000000..fbb72de
--- /dev/null
@@ -0,0 +1 @@
+services foobar;
diff --git a/mach_init.tproj/testServer/Makefile b/mach_init.tproj/testServer/Makefile
new file mode 100644 (file)
index 0000000..25019ea
--- /dev/null
@@ -0,0 +1,19 @@
+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
new file mode 100644 (file)
index 0000000..75c67a7
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..cc2073d
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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
new file mode 100644 (file)
index 0000000..8fc640a
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * 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);
+}
+
+
+
diff --git a/makekey.tproj/Makefile b/makekey.tproj/Makefile
new file mode 100644 (file)
index 0000000..15c58ae
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = makekey
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = makekey.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble makekey.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/libexec
+WINDOWS_INSTALLDIR = /usr/libexec
+PDO_UNIX_INSTALLDIR = /usr/libexec
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/makekey.tproj/Makefile.postamble b/makekey.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..cb09ed6
--- /dev/null
@@ -0,0 +1,110 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES    # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+#COMPATIBILITY_PROJECT_VERSION = 1
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wall
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S   # for .a archives
+#DYNAMIC_STRIP_OPTS = -S   # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+
diff --git a/makekey.tproj/Makefile.preamble b/makekey.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..5741d84
--- /dev/null
@@ -0,0 +1,119 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS = 
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set all three of these if you want a precomp to be built as part of
+# installation.  The cc -precomp will be run in the specified dir on the
+# specified public header files with the specified additional flags.  Don't put
+# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you.
+PUBLIC_HEADER_DIR = 
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+
diff --git a/makekey.tproj/PB.project b/makekey.tproj/PB.project
new file mode 100644 (file)
index 0000000..3bb03d4
--- /dev/null
@@ -0,0 +1,39 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (makekey.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, makekey.8); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/libexec; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/libexec; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = makekey; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/libexec; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/makekey.tproj/makekey.8 b/makekey.tproj/makekey.8
new file mode 100644 (file)
index 0000000..c6ded2d
--- /dev/null
@@ -0,0 +1,59 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"     @(#)makekey.8  8.2 (Berkeley) 12/11/93
+.\"
+.Dd December 11, 1993
+.Dt MAKEKEY 8
+.Os
+.Sh NAME
+.Nm makekey
+.Nd make encrypted keys or passwords
+.Sh SYNOPSIS
+.Nm makekey
+.Sh DESCRIPTION
+.Nm Makekey
+encrypts a key and salt which it reads from the standard input
+and writes the result to the standard output.
+The key is expected to be
+ten bytes; the salt is expected to be two bytes.
+See
+.Xr crypt 3
+for more information on what characters the key and salt can contain
+and how the encrypted value is calculated.
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr crypt 1 ,
+.Xr crypt 3
+.Sh HISTORY
+A
+.Nm
+command appeared in Version 7 AT&T UNIX.
diff --git a/makekey.tproj/makekey.c b/makekey.tproj/makekey.c
new file mode 100644 (file)
index 0000000..487cfaa
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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) 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)makekey.c  8.1 (Berkeley) 6/4/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void get __P((char *, int));
+
+int
+main()
+{
+       int len;
+       char *r, key[9], salt[3];
+       
+       get(key, sizeof(key) - 1);
+       get(salt, sizeof(salt) - 1);
+       len = strlen(r = crypt(key, salt));
+       if (write(STDOUT_FILENO, r, len) != len)
+               err(1, "stdout");
+       exit(0);
+}
+
+static void
+get(bp, len)
+       char *bp;
+       register int len;
+{
+       register int nr;
+
+       bp[len] = '\0';
+       if ((nr = read(STDIN_FILENO, bp, len)) == len)
+               return;
+       if (nr >= 0)
+               errno = EFTYPE;
+       err(1, "stdin");
+}
diff --git a/mkfile.tproj/Makefile b/mkfile.tproj/Makefile
new file mode 100644 (file)
index 0000000..9a46e78
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = mkfile
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = mkfile.c
+
+OTHERSRCS = Makefile.preamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/mkfile.tproj/Makefile.preamble b/mkfile.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..b7b38d0
--- /dev/null
@@ -0,0 +1,3 @@
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/mkfile.tproj/PB.project b/mkfile.tproj/PB.project
new file mode 100644 (file)
index 0000000..3dceb20
--- /dev/null
@@ -0,0 +1,36 @@
+{
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (mkfile.c); 
+        OTHER_SOURCES = (Makefile.preamble); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = mkfile; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/mkfile.tproj/mkfile.c b/mkfile.tproj/mkfile.c
new file mode 100644 (file)
index 0000000..4aff548
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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 Apple Computer, Inc. All Rights Reserved 
+ *     
+ * HISTORY
+ * 29-Aug-97 Daniel Wade (danielw) at Apple
+ *     Created.
+ *
+ */ 
+
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#define BF_SZ  512     /* Size of write chunks */
+
+extern void usage(char *, char *);
+extern void create_file(char *, quad_t, int, int);
+extern void err_rm(char *, char *);
+
+int
+main (argc, argv)
+       int argc;
+       char **argv;
+{
+       char *b_num, *prog_name;
+       char *options = "nv";
+       char c;
+       quad_t multiplier = 1;
+       quad_t file_size;
+       int len;
+       int empty = 0;
+       int verbose = 0;
+
+       prog_name = argv[0];    /* Get program name */
+    if (1 == argc)
+               usage(prog_name, options);
+
+       /* Get options */
+       opterr=1;
+       
+       while ((c=getopt(argc, argv, options)) != EOF)
+               switch (c) {
+               case 'v':   /* Turn on verbose setting */
+                       verbose = 1;
+                       break;
+               case 'n':   /* Create an empty file */
+                       empty = 1;
+                       break;
+               default:
+                       usage(prog_name, options);
+                       break;
+               }
+
+       /* Stop getting options
+       */
+       argv += optind;
+       if (*argv == NULL)              /* Is there a size given? */
+               usage(prog_name, options);
+       
+       b_num = *argv++;                /* Size of file and byte multiplier */
+       len = strlen(b_num) - 1;
+
+       if (!isdigit(b_num[len])) {
+                switch(b_num[len]) {   /* Figure out multiplier */
+                       case 'B':
+                        case 'b':
+                                multiplier = 512;
+                                break;
+                       case 'K':
+                        case 'k':
+                                multiplier = 1024;
+                               break;
+                       case 'M':
+                        case 'm':
+                                multiplier = 1024 * 1024;
+                                break;
+                       case 'G':
+                        case 'g':
+                                multiplier = 1024 * 1024 * 1024;
+                                break;
+                        default:
+                               usage(prog_name, options);
+                }
+       }
+       
+       if (*argv == NULL)              /* Was a file name given? */
+               usage(prog_name, options);      
+
+       if ((file_size = strtoq(b_num, NULL, 10)) == 0 )
+               err(1, "Bad file size!");
+
+       while ( *argv != NULL ) {       /* Create file for each file_name */
+               create_file(*argv, file_size*multiplier, empty, verbose);
+               argv++;
+       }
+
+       return (0);
+
+}
+
+
+/* Create a file and make it empty (lseek) or zero'd */
+
+void 
+create_file(file_name, size, empty, verbose)
+       char *file_name;
+       quad_t size;
+       int empty;
+       int verbose;
+{
+       char buff[BF_SZ];
+       int fd, bytes_written = BF_SZ;
+       quad_t i;
+    mode_t     mode;
+
+       if ((fd = open(file_name, O_RDWR | O_CREAT | O_TRUNC )) == -1)
+                err(1, NULL);
+
+
+        if (empty) {                   /* Create an empty file */
+                lseek(fd, (off_t)size-1, SEEK_SET);
+                if ( 1 != write(fd, "\0", 1))
+                       err_rm(file_name, "Write Error");
+        }
+       else {
+               bzero(buff, BF_SZ);
+
+               /*
+                * First loop: write BF_SZ chunks until you have
+                * less then BF_SZ bytes to write.
+                * Second loop: write the remaining bytes.
+                * ERRORS in the write process will cause the
+                * file to be removed before the error is
+                * reported.
+                */
+               for (i = size; i > BF_SZ; i -= bytes_written) {
+                       bytes_written = write (fd, buff, BF_SZ);
+                       if ( bytes_written == -1 )
+                                err_rm (file_name, "Write Error");
+               }
+               for (; i > 0; i -= bytes_written) {
+                       bytes_written = write (fd, buff, i);
+                        if ( bytes_written == -1 )
+                                err_rm (file_name, "Write Error");
+               }
+       }
+
+
+       mode = S_IRUSR | S_IWUSR;
+       /* If superuser, then set sticky bit */
+    if (! geteuid())
+               mode |= S_ISVTX;
+
+    if (fchmod(fd, mode))      /* Change permissions */
+        err_rm(file_name, NULL);
+
+    if ((close(fd)) == -1)
+            err_rm(file_name, NULL);
+
+       if (verbose)
+               (void)fprintf(stderr, "%s %qd bytes\n", file_name, size);
+
+}
+
+/* On error remove the file */
+
+void
+err_rm(filename, msg)
+       char *filename;
+       char *msg;
+{
+       unlink(filename);
+       err(1, "(%s removed) %s", filename, msg); 
+}
+
+
+/* Print usage string */
+void 
+usage (prog_name, options)
+       char *prog_name;
+       char *options;
+{
+       (void)fprintf(stderr, 
+               "usage: %s [-%s] size[b|k|m|g] filename ...\n", prog_name,  options);
+       exit(1);
+
+}
diff --git a/nologin.tproj/Makefile b/nologin.tproj/Makefile
new file mode 100644 (file)
index 0000000..78df5c1
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# 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 = nologin
+
+PROJECTVERSION = 2.6
+PROJECT_TYPE = Legacy
+LANGUAGE = English
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            nologin.8 nologin.sh
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = common.make
+NEXTSTEP_INSTALLDIR = /sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/nologin.tproj/Makefile.dist b/nologin.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..84e9f0c
--- /dev/null
@@ -0,0 +1,14 @@
+#      @(#)Makefile    8.2 (Berkeley) 4/22/94
+
+MAN8=  nologin.0
+
+nologin clean depend lint tags:
+
+beforeinstall:
+       install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+           ${.CURDIR}/nologin.sh ${DESTDIR}/sbin/nologin
+
+cleandir:
+       rm -f nologin.0
+
+.include <bsd.prog.mk>
diff --git a/nologin.tproj/Makefile.postamble b/nologin.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..6979d87
--- /dev/null
@@ -0,0 +1,129 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+nologin: nologin.sh
+       $(CP) nologin.sh ${SYM_DIR}/nologin
+
+after_install::
+       $(CP) -p ${SYM_DIR}/nologin $(DSTROOT)$(INSTALLDIR)/nologin
+       $(CHMOD) 555 $(DSTROOT)$(INSTALLDIR)/nologin
diff --git a/nologin.tproj/Makefile.preamble b/nologin.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..8940ec4
--- /dev/null
@@ -0,0 +1,132 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
+OTHER_INITIAL_TARGETS = nologin
diff --git a/nologin.tproj/PB.project b/nologin.tproj/PB.project
new file mode 100644 (file)
index 0000000..b6bd0a8
--- /dev/null
@@ -0,0 +1,45 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        M_FILES = (); 
+        OTHER_LINKED = (); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            Makefile.dist, 
+            nologin.sh, 
+            nologin.8
+        ); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = "# Set in Makefile"; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_MAINNIB = nologin; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = "# Set in Makefile"; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_MAINNIB = nologin; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = nologin; 
+    PROJECTTYPE = Legacy; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = "# Set in Makefile"; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_MAINNIB = nologin; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/nologin.tproj/nologin.8 b/nologin.tproj/nologin.8
new file mode 100644 (file)
index 0000000..32a7e73
--- /dev/null
@@ -0,0 +1,54 @@
+.\" Copyright (c) 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.
+.\"
+.\"     @(#)nologin.8  8.1 (Berkeley) 6/19/93
+.\"
+.Dd June 19, 1993
+.Dt NOLOGIN 8
+.Os BSD 4.4
+.Sh NAME
+.Nm nologin
+.Nd politely refuse a login 
+.Sh SYNOPSIS
+.Nm nologin
+.Sh DESCRIPTION
+.Nm Nologin
+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.
+.Sh SEE ALSO
+.Xr login 1
+.Sh HISTORY
+The
+.Nm nologin
+command appeared in
+.Bx 4.4 .
diff --git a/nologin.tproj/nologin.sh b/nologin.tproj/nologin.sh
new file mode 100644 (file)
index 0000000..8ad87fb
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh -
+#
+# Copyright (c) 1992, 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.
+#
+#      @(#)nologin.sh  8.1 (Berkeley) 6/5/93
+#
+
+echo 'This account is currently not available.'
+exit 1
diff --git a/nvram.tproj/Makefile b/nvram.tproj/Makefile
new file mode 100644 (file)
index 0000000..aed70c0
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# 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 = nvram
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = nvram.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble nvram.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+FRAMEWORKS = -framework IOKit
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/nvram.tproj/Makefile.postamble b/nvram.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..0c1d774
--- /dev/null
@@ -0,0 +1,146 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+IMPLICIT_SOURCE_FILES += nvram
+
+PAX = /bin/pax
+SHAREDIR = /usr/share
+MANDIR   = $(SHAREDIR)/man/man8
+MANPAGE  = nvram.8
+NVRAMDIR = $(SHAREDIR)/nvram
+
+after_install::
+       $(MKDIRS) $(DSTROOT)$(MANDIR)
+       $(CP) -f $(MANPAGE) $(DSTROOT)$(MANDIR)/$(MANPAGE)
+       $(CHMOD) og-w $(DSTROOT)$(MANDIR)/$(MANPAGE)
+       $(PAX) -rw nvram $(DSTROOT)$(SHAREDIR)
+       $(CHOWN) -R root.wheel $(DSTROOT)$(NVRAMDIR)
+       $(LN) -fs PowerSurge $(DSTROOT)$(NVRAMDIR)/7300
+       $(LN) -fs PowerSurge $(DSTROOT)$(NVRAMDIR)/7500
+       $(LN) -fs PowerSurge $(DSTROOT)$(NVRAMDIR)/8500
+       $(LN) -fs PowerSurge $(DSTROOT)$(NVRAMDIR)/9500
+       $(LN) -fs PowerExpress $(DSTROOT)$(NVRAMDIR)/9700
+       $(LN) -fs Hooper $(DSTROOT)$(NVRAMDIR)/3400-2400
+       $(LN) -fs Kanga $(DSTROOT)$(NVRAMDIR)/3500
+       $(LN) -fs Silk $(DSTROOT)$(NVRAMDIR)/PowerMac-G3
+       $(LN) -fs Wallstreet $(DSTROOT)$(NVRAMDIR)/PowerBook1998
diff --git a/nvram.tproj/Makefile.preamble b/nvram.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/nvram.tproj/PB.project b/nvram.tproj/PB.project
new file mode 100644 (file)
index 0000000..25536c7
--- /dev/null
@@ -0,0 +1,30 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        BUNDLES = (); 
+        FRAMEWORKS = (IOKit.framework); 
+        H_FILES = (); 
+        LIBS = (); 
+        OTHER_LINKED = (nvram.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, nvram.8); 
+        SUBPROJECTS = (); 
+        TOOLS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    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_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = nvram; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/nvram.tproj/nvram.8 b/nvram.tproj/nvram.8
new file mode 100644 (file)
index 0000000..7392f2e
--- /dev/null
@@ -0,0 +1,89 @@
+.\"
+.\" Copyright (c) 2000 Apple Computer, Inc.  All rights reserved.
+.\"
+.TH nvram 8 "December 12, 2000"
+.SH NAME
+nvram \- manipulate Open Firmware NVRAM variables
+.SH SYNOPSIS
+.B nvram
+[
+.B -p
+] [
+.B -f 
+.IR filename
+] [
+.IR name
+] [=
+.IR value
+] ...
+.SH DESCRIPTION
+The
+.I nvram
+command allows manipulation of Open Firmware NVRAM variables.  It
+can be used to get or set a variable.  It can also be used to print
+all of the variables or set a list of variables from a file.
+.LP
+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.
+.LP
+The given
+.IR value
+must match the data type required for
+.IR name .
+Binary data can be set using the %xx notation, where xx is the hex
+value of the byte.  The type for new variables is always binary
+data.
+.LP
+Two Open Firmware variables have special treatment on old world
+machines:
+.IR boot-command
+and
+.IR boot-args .
+As long as
+.IR boot-command
+starts with "# bootr," the
+.IR boot-args
+variable will be present.  Getting or setting
+.IR boot-args
+will get or set the
+.IR boot-command
+while preserving the "# bootr".  In most cases when setting boot arguments 
+for the kernel, there is no need to test for old world and set
+.IR boot-command .
+Instead set
+.IR boot-args
+with the desired arguments.
+.SH OPTIONS
+.TP
+.B \-p
+Print all of the Open Firmware variables.
+.TP
+.BI \-f " filename"
+Set Open Firmware variables from a text file.  The file must be a
+list name=value statements.  If the last character of a line is
+\\, the value will be continued to the next line.
+.SH EXAMPLES
+.LP
+.RS
+example% nvram boot-args="-s rd=*hd:10"
+.RE
+.LP
+Set the boot-args variable to "-s rd=*hd:10".  This would specifiy
+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
+C-strings that is terminated by a NUL.
+.SH FILES
+.PD 0
+.TP 30
+.B /usr/share/nvram
+Files containing patches for old world machines.
+.PD
diff --git a/nvram.tproj/nvram.c b/nvram.tproj/nvram.c
new file mode 100644 (file)
index 0000000..d23b79c
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * 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@
+ */
+/*
+cc -o nvram nvram.c -framework IOKit -Wall
+*/
+
+#include <stdio.h>
+#include <IOKit/IOKitLib.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+// Prototypes
+static void Error(char *format, long item);
+static void FatalError(long exitValue, char *format, long item);
+static void UsageMessage(char *message);
+static void ParseFile(char *fileName);
+static void SetOrGetOFVariable(char *str);
+static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef,
+                                  CFTypeRef *valueRef);
+static kern_return_t SetOFVariable(char *name, char *value);
+static void PrintOFVariables(void);
+static void PrintOFVariable(const void *key,const void *value,void *context);
+static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value);
+
+// Global Variables
+static char                *gToolName;
+static io_registry_entry_t gOptionsRef;
+
+
+int main(int argc, char **argv)
+{
+  long                cnt;
+  char                *str, errorMessage[256];
+  kern_return_t       result;
+  mach_port_t         masterPort;
+  
+  // Get the name of the command.
+  gToolName = strrchr(argv[0], '/');
+  if (gToolName != 0) gToolName++;
+  else gToolName = argv[0];
+  
+  result = IOMasterPort(bootstrap_port, &masterPort);
+  if (result != KERN_SUCCESS) {
+    FatalError(-1, "Error (%d) getting the IOMaster port", result);
+    exit(-1);
+  }
+  
+  gOptionsRef = IORegistryEntryFromPath(masterPort, "IODeviceTree:/options");
+  if (gOptionsRef == 0) {
+    FatalError(-1, "Error (%d) getting a reference to /options", -1);
+    exit(-1);
+  }
+  
+  for (cnt = 1; cnt < argc; cnt++) {
+    str = argv[cnt];
+    if (str[0] == '-' && str[1] != 0) {
+      // Parse the options.
+      for (str += 1 ; *str; str++) {
+       switch (*str) {
+       case 'p' :
+         PrintOFVariables();
+         break;
+         
+       case 'f':
+         cnt++;
+         if (cnt < argc && *argv[cnt] != '-') {
+           ParseFile(argv[cnt]);
+         } else {
+           UsageMessage("missing filename");
+         }
+         break;
+         
+       default:
+         strcpy(errorMessage, "no such option as --");
+         errorMessage[strlen(errorMessage)-1] = *str;
+         UsageMessage(errorMessage);
+       }
+      }
+    } else {
+      // Other arguments will be Open Firmware variable requests.
+      SetOrGetOFVariable(str);
+    }
+  }
+  
+  IOObjectRelease(gOptionsRef);
+  
+  return 0;
+}
+
+
+// Error(format, item)
+//
+//   Print a message on standard error.
+//
+static void Error(char *format, long item)
+{
+  fprintf(stderr, "%s: ", gToolName);
+  fprintf(stderr, format, item);
+  fprintf(stderr, "\n");
+}
+
+
+// FatalError(exitValue, format, item)
+//
+//   Print a message on standard error and exit with value.
+//
+static void FatalError(long exitValue, char *format, long item)
+{
+  fprintf(stderr, "%s: ", gToolName);
+  fprintf(stderr, format, item);
+  fprintf(stderr, "\n");
+  
+  exit(exitValue);
+}
+
+
+// UsageMessage(message)
+//
+//   Print the usage information and exit.
+//
+static void UsageMessage(char *message)
+{
+  Error("(usage: %s)", (long)message);
+  
+  printf("%s [-p] [-f filename] name[=value] ...\n", gToolName);
+  printf("\t-p         print all Open Firmware variables\n");
+  printf("\t-f         set Open Firmware variables from a text file\n");
+  printf("\tname=value set named variable\n");
+  printf("\tname       print variable\n");
+  printf("Note that arguments and options are executed in order.\n");
+  
+  exit(1);
+}
+
+
+// States for ParseFile.
+enum {
+  kFirstColumn = 0,
+  kScanComment,
+  kFindName,
+  kCollectName,
+  kFindValue,
+  kCollectValue,
+  kContinueValue,
+  kSetenv,
+  
+  kMaxStringSize = 0x800,
+  kMaxNameSize = 0x100
+};
+
+
+// ParseFile(fileName)
+//
+//   Open and parse the specified file.
+//
+static void ParseFile(char *fileName)
+{
+  long state, tc, ni = 0, vi = 0;
+  char name[kMaxNameSize];
+  char value[kMaxStringSize];
+  FILE *patches;
+  
+  patches = fopen(fileName, "r");
+  if (patches == 0) {
+    FatalError(errno, "Couldn't open patch file - '%s'", (long)fileName);
+  }
+  
+  state = kFirstColumn;
+  while ((tc = getc(patches)) != EOF) {
+    switch (state) {
+    case kFirstColumn :
+      ni = 0;
+      vi = 0;
+      if (tc == '#') {
+       state = kScanComment;
+      } else if (tc == '\n') {
+       // state stays kFirstColumn.
+      } else if (isspace(tc)) {
+       state = kFindName;
+      } else {
+       state = kCollectName;
+       name[ni++] = tc;
+      }
+      break;
+      
+    case kScanComment :
+      if (tc == '\n') {
+       state = kFirstColumn;
+      } else {
+       // state stays kScanComment.
+      }
+      break;
+      
+    case kFindName :
+      if (tc == '\n') {
+       state = kFirstColumn;
+      } else if (isspace(tc)) {
+       // state stays kFindName.
+      } else {
+       state = kCollectName;
+       name[ni++] = tc;
+      }
+      break;
+      
+    case kCollectName :
+      if (tc == '\n') {
+       name[ni] = 0;
+       Error("Name must be followed by white space - '%s'", (long)name);
+       state = kFirstColumn;
+      } else if (isspace(tc)) {
+       state = kFindValue;
+      } else {
+       name[ni++] = tc;
+       // state staus kCollectName.
+      }
+      break;
+      
+    case kFindValue :
+    case kContinueValue :
+      if (tc == '\n') {
+       state = kSetenv;
+      } else if (isspace(tc)) {
+       // state stays kFindValue or kContinueValue.
+      } else {
+       state = kCollectValue;
+       value[vi++] = tc;
+      }
+      break;
+      
+    case kCollectValue :
+      if (tc == '\n') {
+       if (value[vi-1] == '\\') {
+         value[vi-1] = '\r';
+         state = kContinueValue;
+       } else {
+         state = kSetenv;
+       }
+      } else {
+       // state stays kCollectValue.
+       value[vi++] = tc;
+      }
+      break;
+    }
+    
+    if (state == kSetenv) {
+      name[ni] = 0;
+      value[vi] = 0;
+      if (SetOFVariable(name, value) != KERN_SUCCESS) {
+       FatalError(-1, "Error (-1) setting variable - '%s'", (long)name);
+      }
+      state = kFirstColumn;
+    }
+  }
+  
+  if (state != kFirstColumn) {
+    FatalError(-1, "Last line ended abruptly", 0);
+  }
+}
+
+
+// SetOrGetOFVariable(str)
+//
+//   Parse the input string the set or get the specified
+//   Open Firmware variable.
+//
+static void SetOrGetOFVariable(char *str)
+{
+  long          set = 0;
+  char          *name;
+  char          *value;
+  CFStringRef   nameRef;
+  CFTypeRef     valueRef;
+  kern_return_t result;
+  
+  // OF variable name is first.
+  name = str;
+  
+  // Find the equal sign for set
+  while (*str) {
+    if (*str == '=') {
+      set = 1;
+      *str++ = '\0';
+      break;
+    }
+    str++;
+  }
+  
+  if (set == 1) {
+    // On sets, the OF variable's value follows the equal sign.
+    value = str;
+    
+    result = SetOFVariable(name, value);
+    if (result != KERN_SUCCESS) {
+      FatalError(-1, "Error (-1) setting variable - '%s'", (long)name);
+    }
+  } else {
+    result = GetOFVariable(name, &nameRef, &valueRef);
+    if (result != KERN_SUCCESS) {
+      FatalError(-1, "Error (-1) getting variable - '%s'", (long)name);
+    }
+    
+    PrintOFVariable(nameRef, valueRef, 0);
+    CFRelease(nameRef);
+    CFRelease(valueRef);
+  }
+}
+
+
+// GetOFVariable(name, nameRef, valueRef)
+//
+//   Get the named Open Firmware variable.
+//   Return it and it's symbol in valueRef and nameRef.
+//
+static kern_return_t GetOFVariable(char *name, CFStringRef *nameRef,
+                                  CFTypeRef *valueRef)
+{
+  *nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name,
+                                      kCFStringEncodingMacRoman);
+  if (*nameRef == 0) {
+    FatalError(-1, "Error CFString for key %s", (long)name);
+  }
+  
+  *valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, *nameRef, 0, 0);
+  if (*valueRef == 0) return -1;
+  
+  return KERN_SUCCESS;
+}
+
+
+// SetOFVariable(name, value)
+//
+//   Set or create an Open Firmware variable with name and value.
+//
+static kern_return_t SetOFVariable(char *name, char *value)
+{
+  CFStringRef   nameRef;
+  CFTypeRef     valueRef;
+  CFTypeID      typeID;
+  kern_return_t result;
+  
+  nameRef = CFStringCreateWithCString(kCFAllocatorDefault, name,
+                                     kCFStringEncodingMacRoman);
+  if (nameRef == 0) {
+    FatalError(-1, "Error (-1) creating CFString for key %s", (long)name);
+  }
+  
+  valueRef = IORegistryEntryCreateCFProperty(gOptionsRef, nameRef, 0, 0);
+  if (valueRef) {
+    typeID = CFGetTypeID(valueRef);
+    CFRelease(valueRef);
+  } else typeID = CFDataGetTypeID();
+  
+  valueRef = ConvertValueToCFTypeRef(typeID, value);
+  if (valueRef == 0) {
+    FatalError(-1, "Error (-1) creating CFTypeRef for value %s",(long)value);
+  }
+  
+  result = IORegistryEntrySetCFProperty(gOptionsRef, nameRef, valueRef);
+  
+  CFRelease(nameRef);
+  
+  return result;
+}
+
+
+// PrintOFVariables()
+//
+//   Print all of the Open Firmware variables.
+//
+static void PrintOFVariables()
+{
+  kern_return_t          result;
+  CFMutableDictionaryRef dict;
+  
+  result = IORegistryEntryCreateCFProperties(gOptionsRef, &dict, 0, 0);
+  if (result != KERN_SUCCESS) {
+    FatalError(-1, "Error (%d) getting the Open Firmware variables", result);
+  }
+  CFDictionaryApplyFunction(dict, &PrintOFVariable, 0);
+  
+  CFRelease(dict);
+}
+
+
+// PrintOFVariable(key, value, context)
+//
+//   Print the given Open Firmware variable.
+//
+static void PrintOFVariable(const void *key, const void *value, void *context)
+{
+  long          cnt, cnt2;
+  const char    *nameString;
+  char          numberBuffer[10];
+  char          *dataPtr, dataChar;
+  char          *dataBuffer = 0;
+  char          *valueString = 0;
+  unsigned long number, length;
+  CFTypeID      typeID;
+  
+  // Get the OF variable's name.
+  nameString = CFStringGetCStringPtr(key, kCFStringEncodingMacRoman);
+  
+  // Get the OF variable's type.
+  typeID = CFGetTypeID(value);
+  
+  if        (typeID == CFBooleanGetTypeID()) {
+    if (CFBooleanGetValue(value)) valueString = "true";
+    else valueString = "false";
+  } else if (typeID == CFNumberGetTypeID()) {
+    CFNumberGetValue(value, kCFNumberSInt32Type, &number);
+    if (number == 0xFFFFFFFF) sprintf(numberBuffer, "-1");
+    else if (number < 1000) sprintf(numberBuffer, "%d", number);
+    else sprintf(numberBuffer, "0x%x", number);
+    valueString = numberBuffer;
+  } else if (typeID == CFStringGetTypeID()) {
+    valueString = CFStringGetCStringPtr(value, kCFStringEncodingMacRoman);
+  } else if (typeID == CFDataGetTypeID()) {
+    length = CFDataGetLength(value);
+    if (length == 0) valueString = "";
+    else {
+      dataBuffer = malloc(length * 3 + 1);
+      if (dataBuffer != 0) {
+       dataPtr = CFDataGetBytePtr(value);
+       for (cnt = cnt2 = 0; cnt < length; cnt++) {
+         dataChar = dataPtr[cnt];
+         if (isprint(dataChar)) dataBuffer[cnt2++] = dataChar;
+         else {
+           sprintf(dataBuffer + cnt2, "%%%02x", dataChar);
+           cnt2 += 3;
+         }
+       }
+       dataBuffer[cnt2] = '\0';
+       valueString = dataBuffer;
+      }
+    }
+  } else return;
+  
+  if ((nameString != 0) && (valueString != 0))
+    printf("%s\t%s\n", nameString, valueString);
+  
+  if (dataBuffer != 0) free(dataBuffer);
+}
+
+
+// ConvertValueToCFTypeRef(typeID, value)
+//
+//   Convert the value into a CFType given the typeID.
+//
+static CFTypeRef ConvertValueToCFTypeRef(CFTypeID typeID, char *value)
+{
+  CFTypeRef     valueRef = 0;
+  long          cnt, cnt2, length;
+  unsigned long number, tmp;
+  
+  if (typeID == CFBooleanGetTypeID()) {
+    if (!strcmp("true", value)) valueRef = kCFBooleanTrue;
+    else if (!strcmp("false", value)) valueRef = kCFBooleanFalse;
+  } else if (typeID == CFNumberGetTypeID()) {
+    number = strtol(value, 0, 0);
+    valueRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type,
+                             &number);
+  } else if (typeID == CFStringGetTypeID()) {
+    valueRef = CFStringCreateWithCString(kCFAllocatorDefault, value,
+                                        kCFStringEncodingMacRoman);
+  } else if (typeID == CFDataGetTypeID()) {
+    length = strlen(value);
+    for (cnt = cnt2 = 0; cnt < length; cnt++, cnt2++) {
+      if (value[cnt] == '%') {
+       if (!ishexnumber(value[cnt + 1]) ||
+           !ishexnumber(value[cnt + 2])) return 0;
+       number = toupper(value[++cnt]) - '0';
+       if (number > 9) number -= 7;
+       tmp = toupper(value[++cnt]) - '0';
+       if (tmp > 9) tmp -= 7;
+       number = (number << 4) + tmp;
+       value[cnt2] = number;
+      } else value[cnt2] = value[cnt];
+    }
+    valueRef = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, value,
+                                          cnt2, kCFAllocatorDefault);
+  } else return 0;
+  
+  return valueRef;
+}
diff --git a/nvram.tproj/nvram/Alchemy b/nvram.tproj/nvram/Alchemy
new file mode 100644 (file)
index 0000000..2024734
--- /dev/null
@@ -0,0 +1,64 @@
+##
+# 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@
+##
+# Version: 1.2.0  Date: 8-17-2000
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev /packages/mac-parts\
+: $M -7E9408 $X 8000 alloc-mem 7F00 + 4 -7E9408 $X ;\
+' load 268 - ' $M $L\
+' load 168 + ' 0 $L\
+$E\
+dev ata\
+d encode-int 2 encode-int encode+ " AAPL,interrupts" $p\
+$E\
+dev scsi\
+: $M ['] open 888 - + ;\
+: $M1 -E48 $M $X ;\
+: $M2 begin 1 ms $M1 1 and -1068 $M $X or until $M1 case 0 of -1 endof 1 of 1 -E08 $M $X false endof dup endcase ;\
+: $M3 -F68 $M f over $X $X ;\
+: $M4 1 ms ;\
+2C $M ' 2 $L\
+-A18 $M ' $M2 $R\
+-788 $M ' $M3 $L\
+-768 $M ' $M4 $L\
+-764 $M ' 1 $L\
+$E\
+unselect-dev
diff --git a/nvram.tproj/nvram/Gossamer b/nvram.tproj/nvram/Gossamer
new file mode 100644 (file)
index 0000000..78fb571
--- /dev/null
@@ -0,0 +1,93 @@
+##
+# 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@
+##
+# Version: 1.2.0  Date: 8-17-2000
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+: &c " ata-enable" $call-parent ;\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev enet\
+' open constant $M\
+: $M2 $M 710 - $X ;\
+: rl@ -7D9D40 $X ;\
+: chstat begin $M2 $M 14f8 - $X -7D6C20 $X rl@ 400 and 0= until ;\
+: bmstat begin $M2 $M 13F0 - $X rl@ 100 and until ;\
+: xmt1 get-msecs $M 720 - ! chstat $M A00 - $X bmstat chstat ;\
+' xmt1 ' WRITE 10 + l!\
+62 ' READ 7 - c!\
+: READ { _p _n ; _a } begin _p _n bead -> _a _a 2+\
+if _p c@ 80 and 0= else 1 then until _a ;\
+$E\
+dev /packages/obp-tftp\
+: $M over + ['] noop $L ;\
+: $O ['] open + ;\
+: $M1 dup 24 - -1720 $O $X 6 move 14 + ;\
+-5BC $O ' $M1 $L\
+0 $O E8 $M EC $M F0 $M F4 $M F8 + ' true $L\
+$E\
+dev /packages/mac-parts\
+: $M -7E89E0 $X 8000 alloc-mem 7F00 + 4 -7E89E0 $X ;\
+' load 268 - ' $M $L\
+' load 160 + ' 0 $L\
+$E\
+dev ide0\
+: open use-ata-interface 0 &c -1 ;\
+: set-device-ID set-drive-select ;\
+: reset-atapi-bus reset-ata-bus ;\
+' reset-ata-bus 2c + ' 2 $L\
+$E\
+dev ide1\
+: open use-ata-interface 0 &c -1 ;\
+: set-device-ID set-drive-select ;\
+: reset-atapi-bus reset-ata-bus ;\
+' reset-ata-bus 2c + ' 2 $L\
+$E\
+dev scsi\
+: $M ['] do-cmd + ;\
+: $M2 5 us -5f0 $M $X ;\
+: $M3 -710 $M f over $X $X ;\
+: $M4 1 ms ;\
+-1AC $M ' $M2 $L\
+100 $M ' $M3 $L\
+120 $M ' $M4 $L\
+124 $M ' 1 $L\
+$E\
+ff000000 dup dup 400 28 do-map 4+ w@ 10 and 0=\
+if 90b7 f3000032 w! then\
+unselect-dev
diff --git a/nvram.tproj/nvram/Hooper b/nvram.tproj/nvram/Hooper
new file mode 100644 (file)
index 0000000..c5e5aca
--- /dev/null
@@ -0,0 +1,60 @@
+##
+# 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@
+##
+# Version: 1.2.1  Date: 1-30-2001
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+: helpb " backlight-on" _pmu-ihandle $call-method ;\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else helpb 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev /packages/mac-parts\
+: $M -7E8DD8 $X 8000 alloc-mem 7F00 + 4 -7E8DD8 $X ;\
+' load 268 - ' $M $L\
+' load 160 + ' 0 $L\
+$E\
+dev scsi\
+: $M ['] do-cmd + ;\
+: $M2 1 ms -5F0 $M $X ;\
+: $M3 -710 $M f over $X $X ;\
+: $M4 1 ms ;\
+-1AC $M ' $M2 $L\
+100 $M ' $M3 $L\
+120 $M ' $M4 $L\
+124 $M ' 1 $L\
+$E\
+unselect-dev
diff --git a/nvram.tproj/nvram/Kanga b/nvram.tproj/nvram/Kanga
new file mode 100644 (file)
index 0000000..72d9bd8
--- /dev/null
@@ -0,0 +1,57 @@
+##
+# 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@
+##
+# Version: 1.2.1  Date: 1-30-2001
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+: helpb " backlight-on" _pmu-ihandle $call-method ;\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else helpb 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev /packages/mac-parts\
+: $M -7E8D88 $X 8000 alloc-mem 7F00 + 4 -7E8D88 $X ;\
+' load 268 - ' $M $L\
+' load 160 + ' 0 $L\
+$E\
+dev scsi\
+: $M ['] do-cmd + ;\
+: $M2 1 ms -608 $M $X ;\
+: $M3 -728 $M f over $X $X ;\
+-1B4 $M ' $M2 $L\
+100 $M ' $M3 $L\
+$E\
+unselect-dev
diff --git a/nvram.tproj/nvram/Mainstreet b/nvram.tproj/nvram/Mainstreet
new file mode 100644 (file)
index 0000000..2f8fbd9
--- /dev/null
@@ -0,0 +1,103 @@
+##
+# 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@
+##
+# Version: 1.2.1  Date: 1-30-2001
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $P 0 to my-self property ;\
+: &a " /chosen" $D $P $E ;\
+: &c " ata-enable" $call-parent ;\
+: helpb " backlight-on" _pmu-ihandle $call-method\
+0 0 " "(70)" 40 " pmu-op" _pmu-ihandle $call-method drop ;\
+10 buffer: km\
+devalias ide0 /pci/@10/ata0\
+devalias ide1 /pci/@10/@34/ata1\
+devalias ide4 /pci/@d/@34/ata4\
+dev /aliases\
+: $M delete-property ;\
+" ata-int" $M\
+" ata0" $M\
+" ata1" $M\
+" ata4" $M\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" &a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else helpb 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev enet\
+62 ' READ 7 - c!\
+: READ { _p _n ; _a } begin _p _n bead -> _a _a 2+\
+if _p c@ 80 and 0= else 1 then until _a ;\
+$E\
+dev /packages/obp-tftp\
+: $M over + ['] noop $L ;\
+: $O ['] open + ;\
+: $M1 dup 24 - -1720 $O $X 6 move 14 + ;\
+-5BC $O ' $M1 $L\
+0 $O E8 $M EC $M F0 $M F4 $M F8 + ' true $L\
+$E\
+dev /packages/mac-parts\
+: $M -7E86F0 $X 8000 alloc-mem 7F00 + 4 -7E86F0 $X ;\
+' load 268 - ' $M $L\
+' load 160 + ' 0 $L\
+dev ide0\
+: open use-ata-interface 0 &c -1 ;\
+: set-device-ID set-drive-select ;\
+$E\
+dev mac-io/@34\
+1 value &f\
+: ata-enable &f if 1000 ms &c 1000 ms 0 to &f else drop then ;\
+$E\
+dev ide1\
+: open use-ata-interface 1 &c -1 ;\
+: set-device-ID set-drive-select ;\
+: reset-atapi-bus reset-ata-bus ;\
+$E\
+dev pci1/@d/@34\
+: ata-enable &c ;\
+$E\
+dev ide4\
+: open use-ata-interface 1 &c -1 ;\
+: set-device-ID set-drive-select ;\
+: reset-atapi-bus reset-ata-bus ;\
+$E\
+dev scsi\
+: $M ['] do-cmd + ;\
+: $M2 5 us -5f0 $M $X ;\
+: $M3 -710 $M f over $X $X ;\
+: $M4 1 ms ;\
+-1AC $M ' $M2 $L\
+100 $M ' $M3 $L\
+120 $M ' $M4 $L\
+124 $M ' 1 $L\
+$E\
+unselect-dev
diff --git a/nvram.tproj/nvram/PowerExpress b/nvram.tproj/nvram/PowerExpress
new file mode 100644 (file)
index 0000000..3038a25
--- /dev/null
@@ -0,0 +1,61 @@
+##
+# 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@
+##
+# Version: 1.2.0  Date: 8-17-2000
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+: helpb " scsi" find-device 0 to my-self\
+d# 5300 encode-int " AAPL,load-priority" property\
+unselect-dev ;\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev /packages/mac-parts\
+: $M 7F00 - 4 ;\
+' my-init-program 34 + ' $M $L\
+' load-partition dup\
+80 + ' 2drop $L\
+104 + ' 0 $L\
+' load 15C + ' 0 $L\
+$E\
+dev /packages/obp-tftp\
+: $M dup 24 - HIS-ENET-HA 6 move 14 + ;\
+' open 66C - ' $M $L\
+$E\
+" /chaos" ['] find-device catch if 2drop else\
+0 to my-self 0 0 " AAPL,ignore" property then\
+unselect-dev
diff --git a/nvram.tproj/nvram/PowerSurge b/nvram.tproj/nvram/PowerSurge
new file mode 100644 (file)
index 0000000..10696c5
--- /dev/null
@@ -0,0 +1,103 @@
+##
+# 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@
+##
+# Version: 1.2.0  Date: 8-17-2000
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $C $call-method ;\
+: $D find-device ;\
+: $E device-end ;\
+: $x execute ;\
+: $F $D " open" $find drop ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+: R BRpatch ; : L BLpatch ;\
+: q over + ;\
+: g code! ;\
+: & get-token drop ;\
+6ED & $x\
+0 value mi\
+: mmr " map-range" mi if my-self $C else $call-parent then ;\
+89B & ' mmr R\
+: mcm -1 to mi $C 0 to mi ;\
+8CB & 1E na+ ' mcm L\
+: maa -1 to mi 1D swap ;\
+8C9 & 5 na+ ' maa L\
+8C9 & 134 + ' 1 L\
+8CD & 184 + 14 q dup @ 6 << 6 >>a -4 and + R\
+8C6 & 7C + ' u< L\
+0 value yn\
+: y yn 0= if dup @ to yn then ;\
+8CB & ' y R\
+' y 28 + 8CB & 8 + R\
+: z yn ?dup if over ! 0 to yn then ;\
+8CC & ' z R\
+' z 2C + 8CC & 8 + R\
+@startvec BC + @ 40820014 over 88 + g 41820010 swap E0 + g\
+0 @startvec 5C + @ 1D8 + g\
+dev /packages/mac-parts\
+400000 ' load 14 + g\
+: m1 400000 do-unmap ;\
+' load 8 + ' m1 L\
+' load 160 + ' 0 L\
+: &r1 4+ dup 8000 alloc-mem 7F00 + swap ! 4+ F8 ;\
+' load 2AC - ' &r1 L\
+$E\
+4180FFF0 ' msr! 44 + g\
+dev /packages/xcoff-loader\
+: p&+ ['] open 600 - + ;\
+: p1 { _a _s } _a -1000 and _a _s + over - FFF ;\
+60000000 dup 8 p&+ g C p&+ g\
+18 p&+ ' p1 L\
+$E\
+" enet" $F dup\
+1D8 - 24 q ['] or L $x\
+248 - @ 6 encode-bytes 2dup\
+" local-mac-address" $p\
+$E\
+" mac-address" $a\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: &SI\
+" scsi-int" open-dev\
+" open" 2 pick 4+ @ find-method drop\
+2c q ['] 2 L 848 -\
+8 q 1C q R\
+88 q 4 q R\
+$x " close" rot $C ;\
+&SI\
+dev /packages/obp-tftp\
+: O ['] open + ;\
+: M dup 24 - -18E0 O $X 6 move 14 + ;\
+684 O ['] drop L\
+-63C O ' M L\
+$E\
+unselect-dev
diff --git a/nvram.tproj/nvram/Silk b/nvram.tproj/nvram/Silk
new file mode 100644 (file)
index 0000000..e1bdc32
--- /dev/null
@@ -0,0 +1,63 @@
+##
+# 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@
+##
+# Version: 1.2.1  Date: 1-30-2001
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $p 0 to my-self property ;\
+: $a " /chosen" $D $p $E ;\
+: helpb ['] install-interrupt-vectors ['] noop $R\
+0 4000 release-mem 8000 2000 release-mem ;\
+10 buffer: km\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" $a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else helpb 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev /packages/mac-parts\
+: $M 7F00 - 4 ;\
+' my-init-program 34 + ' $M $L\
+' load-partition dup\
+80 + ' 2drop $L\
+104 + ' 0 $L\
+' load 15C + ' 0 $L\
+$E\
+dev /packages/obp-tftp\
+: $M dup 24 - HIS-ENET-HA 6 move 14 + ;\
+' open 66C - ' $M $L\
+$E\
+dev mac-io\
+: decode-unit parse-1hex ;\
+$E\
+ff000000 dup dup 400 28 do-map 4+ w@ 10 and 0=\
+if 90b7 f3000032 w! then\
+unselect-dev
diff --git a/nvram.tproj/nvram/Wallstreet b/nvram.tproj/nvram/Wallstreet
new file mode 100644 (file)
index 0000000..a3c8fdf
--- /dev/null
@@ -0,0 +1,102 @@
+##
+# 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@
+##
+# Version: 1.2.1  Date: 1-30-2001
+use-nvramrc? true
+load-base 600000
+diag-device 
+nvramrc hex\
+: $D find-device ;\
+: $E device-end ;\
+: $L BLpatch ; : $R BRpatch ;\
+: $X execute ;\
+: $P 0 to my-self property ;\
+: &a " /chosen" $D $P $E ;\
+: &c " ata-enable" $call-parent ;\
+: helpb " backlight-on" _pmu-ihandle $call-method ;\
+10 buffer: km\
+devalias ide0 /pci/@10/ata0\
+devalias ide1 /pci/@10/@34/ata1\
+devalias ide4 /pci/@d/@34/ata4\
+dev /aliases\
+: $M delete-property ;\
+" ata-int" $M\
+" ata0" $M\
+" ata1" $M\
+" ata4" $M\
+dev kbd\
+get-key-map km swap move\
+$E\
+: ck 0 do swap dup 3 >> km + c@ 1 rot 7 and << and or loop ;\
+: bootr 0d word count encode-string " machargs" &a\
+0 0 1 ck if 0 and else dup 1 = if 3d 0 1 else f 3d 0 2 then ck if 40 or then then\
+40 and if bye else helpb 1e 0 do ['] boot catch drop 1f4 ms loop then bye ;\
+: myboot boot-command eval ;\
+dev enet\
+62 ' READ 7 - c!\
+: READ { _p _n ; _a } begin _p _n bead -> _a _a 2+\
+if _p c@ 80 and 0= else 1 then until _a ;\
+$E\
+dev /packages/obp-tftp\
+: $M over + ['] noop $L ;\
+: $O ['] open + ;\
+: $M1 dup 24 - -1720 $O $X 6 move 14 + ;\
+-5BC $O ' $M1 $L\
+0 $O E8 $M EC $M F0 $M F4 $M F8 + ' true $L\
+$E\
+dev /packages/mac-parts\
+: $M -7E86F0 $X 8000 alloc-mem 7F00 + 4 -7E86F0 $X ;\
+' load 268 - ' $M $L\
+' load 160 + ' 0 $L\
+dev ide0\
+: open use-ata-interface 0 &c -1 ;\
+: set-device-ID set-drive-select ;\
+$E\
+dev mac-io/@34\
+1 value &f\
+: ata-enable &f if 1000 ms &c 1000 ms 0 to &f else drop then ;\
+$E\
+dev ide1\
+: open use-ata-interface 1 &c -1 ;\
+: set-device-ID set-drive-select ;\
+: reset-atapi-bus reset-ata-bus ;\
+$E\
+dev pci1/@d/@34\
+: ata-enable &c ;\
+$E\
+dev ide4\
+: open use-ata-interface 1 &c -1 ;\
+: set-device-ID set-drive-select ;\
+: reset-atapi-bus reset-ata-bus ;\
+$E\
+dev scsi\
+: $M ['] do-cmd + ;\
+: $M2 5 us -5f0 $M $X ;\
+: $M3 -710 $M f over $X $X ;\
+: $M4 1 ms ;\
+-1AC $M ' $M2 $L\
+100 $M ' $M3 $L\
+120 $M ' $M4 $L\
+124 $M ' 1 $L\
+$E\
+unselect-dev
diff --git a/pagesize.tproj/Makefile b/pagesize.tproj/Makefile
new file mode 100644 (file)
index 0000000..3037610
--- /dev/null
@@ -0,0 +1,41 @@
+#
+# 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 = pagesize
+
+PROJECTVERSION = 2.6
+PROJECT_TYPE = Legacy
+LANGUAGE = English
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            pagesize.1 pagesize.sh
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = common.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/pagesize.tproj/Makefile.dist b/pagesize.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..0a4d652
--- /dev/null
@@ -0,0 +1,17 @@
+#      @(#)Makefile    8.2 (Berkeley) 4/3/94
+
+MAN1=  pagesize.0
+
+all pagesize: ${MAN1}
+
+clean depend lint tags:
+
+cleandir:
+       rm -f ${MAN1}
+
+install: maninstall
+       install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
+           ${.CURDIR}/pagesize.sh ${DESTDIR}/${BINDIR}/pagesize
+
+.include <bsd.prog.mk>
+.include <bsd.man.mk>
diff --git a/pagesize.tproj/Makefile.postamble b/pagesize.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..89cd0ea
--- /dev/null
@@ -0,0 +1,129 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+pagesize: pagesize.sh
+       $(CP) pagesize.sh ${SYM_DIR}/pagesize
+
+after_install::
+       $(CP) -p ${SYM_DIR}/pagesize $(DSTROOT)$(INSTALLDIR)/pagesize
+       $(CHMOD) 555 $(DSTROOT)$(INSTALLDIR)/pagesize
diff --git a/pagesize.tproj/Makefile.preamble b/pagesize.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..e69a9b5
--- /dev/null
@@ -0,0 +1,132 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+-include ../Makefile.include
+OTHER_INITIAL_TARGETS = pagesize
diff --git a/pagesize.tproj/PB.project b/pagesize.tproj/PB.project
new file mode 100644 (file)
index 0000000..726e726
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        CLASSES = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            Makefile.dist, 
+            pagesize.sh, 
+            pagesize.1
+        ); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_DOCUMENTEXTENSIONS = (); 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = pagesize; 
+    PROJECTTYPE = Legacy; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/pagesize.tproj/pagesize.1 b/pagesize.tproj/pagesize.1
new file mode 100644 (file)
index 0000000..4beec29
--- /dev/null
@@ -0,0 +1,56 @@
+.\" Copyright (c) 1983, 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.
+.\"
+.\"    @(#)pagesize.1  8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt PAGESIZE 1
+.Os BSD 4.2
+.Sh NAME
+.Nm pagesize
+.Nd print system page size
+.Sh SYNOPSIS
+.Nm pagesize
+.Sh DESCRIPTION
+.Nm Pagesize
+prints the size of a page of memory in bytes, as
+returned by
+.Xr getpagesize 2 .
+This program is useful in constructing portable
+shell scripts.
+.Sh SEE ALSO
+.Xr getpagesize 2
+.Sh HISTORY
+The
+.Nm pagesize
+command
+appeared in
+.Bx 4.2 .
diff --git a/pagesize.tproj/pagesize.sh b/pagesize.tproj/pagesize.sh
new file mode 100644 (file)
index 0000000..da22179
--- /dev/null
@@ -0,0 +1,40 @@
+#!/bin/sh -
+#
+# Copyright (c) 1994
+#      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.
+#
+#      @(#)pagesize.sh 8.1 (Berkeley) 4/3/94
+#
+
+PATH=/bin:/usr/bin:/usr/sbin
+export PATH
+
+sysctl -n hw.pagesize
diff --git a/passwd.tproj/Makefile b/passwd.tproj/Makefile
new file mode 100644 (file)
index 0000000..53850dc
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# 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 = passwd
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = stringops.h
+
+CFILES = nis_passwd.c file_passwd.c netinfo_passwd.c passwd.c\
+         stringops.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble passwd.1
+
+
+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)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/passwd.tproj/Makefile.postamble b/passwd.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..4d8d2c7
--- /dev/null
@@ -0,0 +1,8 @@
+VPATH += :../chpass.tproj:../vipw.tproj
+
+INSTALL_AS_USER =      root
+INSTALL_PERMISSIONS =  4555
+#CHFLAGS = /usr/bin/chflags
+
+#after_install::
+#      $(CHFLAGS) schg  $(DSTROOT)$(INSTALLDIR)/$(NAME)
diff --git a/passwd.tproj/Makefile.preamble b/passwd.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..f4bc80f
--- /dev/null
@@ -0,0 +1,3 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+CLEAN_ALL_SUBPROJECTS = YES
+
diff --git a/passwd.tproj/PB.project b/passwd.tproj/PB.project
new file mode 100644 (file)
index 0000000..909cd74
--- /dev/null
@@ -0,0 +1,28 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        CLASSES = (); 
+        C_FILES = (); 
+        H_FILES = (stringops.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (nis_passwd.c, file_passwd.c, netinfo_passwd.c, passwd.c, stringops.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, passwd.1); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = passwd; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /usr/bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/passwd.tproj/file_passwd.c b/passwd.tproj/file_passwd.c
new file mode 100644 (file)
index 0000000..0cff1d4
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * 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@
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include "stringops.h"
+
+#define TEMP_FILE "/tmp/.pwtmp"
+
+#define _PASSWD_FILE "/etc/master.passwd"
+#define _COMPAT_FILE "/etc/passwd"
+#define _PASSWD_FIELDS 10
+#define BUFSIZE 8192
+
+extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
+
+static int do_compat = 1;
+
+char *
+getline(FILE *fp)
+{
+       static char s[BUFSIZE];
+       int len;
+
+    s[0] = '\0';
+
+    fgets(s, BUFSIZE, fp);
+    if (s == NULL || s[0] == '\0') return NULL;
+
+       if (s[0] == '#') return s;
+
+       len = strlen(s) - 1;
+       s[len] = '\0';
+
+       return s;
+}
+
+struct passwd *
+parse_user(char *line)
+{
+       static struct passwd pw = {0};
+       char **tokens;
+       int i, len;
+
+       if (pw.pw_name != NULL) free(pw.pw_name);
+       pw.pw_name = NULL;
+       if (pw.pw_passwd != NULL) free(pw.pw_passwd);
+       pw.pw_passwd = NULL;
+       if (pw.pw_gecos != NULL) free(pw.pw_gecos);
+       pw.pw_gecos = NULL;
+       if (pw.pw_dir != NULL) free(pw.pw_dir);
+       pw.pw_dir = NULL;
+       if (pw.pw_shell != NULL) free(pw.pw_shell);
+       pw.pw_shell = NULL;
+
+       if (pw.pw_class != NULL) free(pw.pw_class);
+       pw.pw_class = NULL;
+
+       if (line == NULL) return (struct passwd *)NULL;
+       tokens = explode(line, ':');
+       len = listLength(tokens);
+
+       if (len != _PASSWD_FIELDS)
+       {
+               freeList(tokens);
+               return (struct passwd *)NULL;
+       }
+
+       i = 0;
+       pw.pw_name = tokens[i++];
+       pw.pw_passwd = tokens[i++];
+       pw.pw_uid = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_gid = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_class = tokens[i++];
+       pw.pw_change = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_expire = atoi(tokens[i]);
+       free(tokens[i++]);
+       pw.pw_gecos = tokens[i++];
+       pw.pw_dir = tokens[i++];
+       pw.pw_shell = tokens[i++];
+
+       return &pw;
+}
+
+struct passwd *
+find_user(char *uname, FILE *fp)
+{
+       char *line;
+       struct passwd *pw;
+
+       rewind(fp);
+
+       while (NULL != (line = getline(fp)))
+       {
+               if (line[0] == '#') continue;
+               pw = parse_user(line);
+               if (pw == (struct passwd *)NULL) continue;
+               if (!strcmp(uname, pw->pw_name)) return pw;
+       }
+
+       pw = parse_user(NULL);
+       return (struct passwd *)NULL;
+}
+
+void
+rewrite_file(char *pwname, FILE *fp, struct passwd *newpw)
+{
+       char *line;
+       struct passwd *pw;
+       FILE *tfp, *cfp;
+       char fname[256];
+       
+       sprintf(fname, "%s.%d", TEMP_FILE, getpid());
+
+       tfp = fopen(fname, "w+");
+       if (tfp == NULL)
+       {
+               fprintf(stderr, "can't write temporary file \"%s\": ", fname);
+               perror("");
+               exit(1);
+       }
+
+       cfp = NULL;
+       if (!strcmp(pwname, _PASSWD_FILE))
+       {
+               cfp = fopen(_COMPAT_FILE, "w");
+               if (cfp == NULL)
+               {
+                       fprintf(stderr, "warning: can't write compatability file \"%s\": ",
+                               _COMPAT_FILE);
+                       perror("");
+               }
+       }
+
+       if (cfp != NULL)
+       {
+               fprintf(cfp, "#\n");
+               fprintf(cfp, "# 4.3BSD-compatable User Database\n");
+               fprintf(cfp, "#\n");
+               fprintf(cfp, "# Note that this file is not consulted for login.\n");
+               fprintf(cfp, "# It only exisits for compatability with 4.3BSD utilities.\n");
+               fprintf(cfp, "#\n");
+               fprintf(cfp, "# This file is automatically re-written by various system utilities.\n");
+               fprintf(cfp, "# Do not edit this file.  Changes will be lost.\n");
+               fprintf(cfp, "#\n");
+       }
+
+       rewind(fp);
+
+       while (NULL != (line = getline(fp)))
+       {
+               if (line[0] == '#')
+               {
+                       fprintf(tfp, "%s", line);
+                       continue;
+               }
+
+               pw = parse_user(line);
+               if (pw == (struct passwd *)NULL)
+               {
+                       fprintf(stderr, "warning: bad format for entry: \"%s\"\n", line);
+                       fprintf(tfp, "%s\n", line);
+                       if (cfp != NULL) fprintf(cfp, "%s\n", line);
+                       continue;
+               }
+
+               if (strcmp(newpw->pw_name, pw->pw_name))
+               {
+                       fprintf(tfp, "%s\n", line);
+                       if (cfp != NULL) fprintf(cfp, "%s\n", line);
+                       continue;
+               }
+
+               fprintf(tfp, "%s:%s:%d:%d:%s:%d:%d:%s:%s:%s\n",
+                       newpw->pw_name, newpw->pw_passwd, newpw->pw_uid, newpw->pw_gid,
+                       newpw->pw_class, newpw->pw_change, newpw->pw_expire,
+                       newpw->pw_gecos, newpw->pw_dir, newpw->pw_shell);
+               if (cfp != NULL)
+               {
+                       fprintf(cfp, "%s:",newpw->pw_name);
+                       if ((newpw->pw_passwd == NULL) || (newpw->pw_passwd[0] == '\0'))
+                               fprintf(cfp, ":");
+                       else
+                               fprintf(cfp, "*:");
+                       fprintf(cfp, "%d:%d:%s:%s:%s\n",
+                               newpw->pw_uid, newpw->pw_gid, newpw->pw_gecos,
+                               newpw->pw_dir, newpw->pw_shell);
+               }
+       }
+
+       if (cfp != NULL) fclose(cfp);
+       fclose(fp);
+       if (unlink(pwname)  < 0)
+       {
+               fprintf(stderr, "can't update \"%s\": ", pwname);
+               perror("");
+       }
+
+       rewind(tfp);
+
+       fp = fopen(pwname, "w");
+       if (fp == NULL)
+       {
+               fprintf(stderr, "ERROR: lost file \"%s\"\n", pwname);
+               fprintf(stderr, "new passwd file is \"%s\"\n", fname);
+               perror("open");
+               exit(1);
+       }
+
+       while (NULL != (line = getline(tfp)))
+       {
+               fprintf(fp, "%s", line);
+               if (line[0] != '#') fprintf(fp, "\n");
+       }
+       fclose(fp);
+       fclose(tfp);
+       unlink(fname);
+}
+
+int
+file_passwd(char *uname, char *locn)
+{
+       char *ne, *oc, *nc;
+       FILE *fp;
+       char *fname;
+       struct passwd *pw;
+       struct passwd newpw;
+       int uid;
+
+       fname = _PASSWD_FILE;
+       if (locn != NULL) fname = locn;
+
+       fp = fopen(fname, "a+");
+       if (fp == NULL)
+       {
+               fprintf(stderr, "can't write to file \"%s\": ", fname);
+               perror("");
+               exit(1);
+       }
+
+
+       pw = find_user(uname, fp);
+       if (pw == (struct passwd *)NULL)
+       {
+               fprintf(stderr, "user %s not found in file %s\n", uname, fname);
+               exit(1);
+       }
+
+       uid = getuid();
+       if ((uid != 0) && (uid != pw->pw_uid))
+       {
+               fprintf(stderr, "Permission denied\n");
+               exit(1);
+       }
+
+       /*
+        * Get the new password
+        */
+       getpasswd(uname, (uid == 0), 5, 0, 0, pw->pw_passwd, &ne, &oc, &nc);
+
+       newpw.pw_name = copyString(pw->pw_name);
+       newpw.pw_passwd = copyString(ne);
+       newpw.pw_uid = pw->pw_uid;
+       newpw.pw_gid = pw->pw_gid;
+       newpw.pw_class = copyString(pw->pw_class);
+       newpw.pw_change = pw->pw_change;
+       newpw.pw_expire = pw->pw_expire;
+       newpw.pw_gecos = copyString(pw->pw_gecos);
+       newpw.pw_dir = copyString(pw->pw_dir);
+       newpw.pw_shell = copyString(pw->pw_shell);
+
+       /*
+        * Re-write the file
+        */
+       rewrite_file(fname, fp, &newpw);
+
+       /*
+        * Clean up memory
+        */
+       pw = parse_user(NULL);
+       free(newpw.pw_name);
+       free(newpw.pw_passwd);
+       free(newpw.pw_gecos);
+       free(newpw.pw_dir);
+       free(newpw.pw_shell);
+       free(newpw.pw_class);
+
+       fclose(fp);
+
+       return 0;
+}
diff --git a/passwd.tproj/netinfo_passwd.c b/passwd.tproj/netinfo_passwd.c
new file mode 100644 (file)
index 0000000..6abdd39
--- /dev/null
@@ -0,0 +1,434 @@
+/*
+ * 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@
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <pwd.h>
+#include <netdb.h>
+#include <ctype.h>
+#include <string.h>
+#include <netinfo/ni.h>
+
+extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
+
+static int
+sys_ismyaddress(unsigned long addr)
+{
+       struct ifconf ifc;
+       struct ifreq *ifr;
+       char buf[1024]; /* XXX */
+       int offset;
+       int sock;
+       struct sockaddr_in *sin;
+       int i, len;
+
+       if (addr == htonl(INADDR_LOOPBACK)) return 1;
+
+       sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+       if (sock < 0) return 0;
+
+       ifc.ifc_len = sizeof(buf);
+       ifc.ifc_buf = buf;
+
+       if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0)
+       {
+               close(sock);
+               return 0;
+       }
+
+       offset = 0;
+
+       while (offset <= ifc.ifc_len)
+       {
+               ifr = (struct ifreq *)(ifc.ifc_buf + offset);
+               offset += IFNAMSIZ + ifr->ifr_addr.sa_len;
+
+               if (ifr->ifr_addr.sa_family != AF_INET) continue;
+               if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue;
+
+               sin = (struct sockaddr_in *)&ifr->ifr_addr;
+               if ((ifr->ifr_flags & IFF_UP) &&
+                       (!(ifr->ifr_flags & IFF_LOOPBACK)) &&
+                       (sin->sin_addr.s_addr == addr))
+               {
+                       close(sock);
+                       return 1;
+               }
+       }
+
+       close(sock);
+       return 0;
+}
+
+static int
+is_root_on_master(void *d)
+{
+       int uid;
+       char myhostname[MAXHOSTNAMELEN + 1];
+       char *p;
+       ni_index where;
+       ni_proplist     pl;
+       int status;
+       ni_id dir;
+       struct sockaddr_in addr;
+       char *tag;
+
+       uid = getuid();
+       if (uid != 0) return 0;
+
+       gethostname(myhostname, MAXHOSTNAMELEN);
+       p = strchr(myhostname, '.');
+       if (p != NULL) *p = '\0';
+
+       status = ni_root(d, &dir);
+       if (status != NI_OK) return 0;
+
+       status = ni_read(d, &dir, &pl);
+       if (status != NI_OK) return 0;
+
+       where = ni_proplist_match(pl, "master", NULL);
+       if (where == NI_INDEX_NULL)
+       {
+               ni_proplist_free(&pl);
+               return 0;
+       }
+
+       if (pl.ni_proplist_val[where].nip_val.ni_namelist_len == 0)
+       {
+               ni_proplist_free(&pl);
+               fprintf(stderr, "No value for NetInfo master property\n");
+               return 0;
+       }
+
+       p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '/');
+       if (p != NULL) *p = '\0';
+       
+       p = strchr(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], '.');
+       if (p != NULL) *p = '\0';
+       
+       if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], myhostname))
+       {
+               ni_proplist_free(&pl);
+               return 1;
+       }
+
+       if (!strcmp(pl.ni_proplist_val[where].nip_val.ni_namelist_val[0], "localhost"))
+       {
+               ni_proplist_free(&pl);
+               ni_addrtag(d, &addr, &tag);
+               if (sys_ismyaddress(addr.sin_addr.s_addr)) return 1;
+       }
+
+       ni_proplist_free(&pl);
+       return 0;
+}
+
+static int
+secure_passwords()
+{
+       void *d, *d1;
+       int status;
+       ni_index where;
+       ni_id dir;
+       ni_namelist nl;
+
+       status = ni_open(NULL, ".", &d);
+       while (status == NI_OK)
+       {
+               dir.nii_object = 0;
+               status = ni_lookupprop(d, &dir, "security_options", &nl);
+               if (status == NI_OK) 
+               {
+                       where = ni_namelist_match(nl, "secure_passwords");
+                       if (where != NI_INDEX_NULL)
+                       {
+                               ni_free(d);
+                               return 1;
+                       }
+               }
+
+               d1 = d;
+               status = ni_open(d1, "..", &d);
+               ni_free(d1);
+       }
+
+       return 0;
+}
+
+static void
+parse_server_tag(char *str, struct sockaddr_in *server, char **t)
+{
+       /* utility to parse a server/tag string */
+
+       int len, i;
+       char *host, *tag, *slash;
+       struct hostent *hent;
+
+       len = strlen(str);
+
+       /* find the "/" character */
+       slash = index(str, '/');
+
+       /* check to see if the "/" is missing */
+       if (slash == NULL)
+       {
+               fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
+               exit(1);
+       }               
+
+       /* find the location of the '/' */
+       i = slash - str;
+
+       /* check if host string is empty */
+       if (i == 0)
+       {
+               fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
+               fprintf(stderr, "no server name specified\n");
+               exit(1);
+       }
+
+       /* check if tag string is empty */
+       if (i == (len - 1)) 
+       {
+               fprintf(stderr, "incorrect format \"%s\" for domain name\n", str);
+               fprintf(stderr, "no tag specified\n");
+               exit(1);
+       }
+
+       /* allocate some space for the host and tag */
+       host = (char *)malloc(i + 1);
+       *t = (char *)malloc(len - i);
+       tag = *t;
+
+       /* copy out the host */
+       strncpy(host, str, i);
+       host[i] = '\0';
+
+       /* copy out the tag */
+       strcpy(tag, slash + 1);
+
+       /* try interpreting the host portion as an address */
+       server->sin_addr.s_addr = inet_addr(host);
+
+       if (server->sin_addr.s_addr == -1)
+       {
+               /* This isn't a valid address.  Is it a known hostname? */
+               hent = gethostbyname(host);
+               if (hent != NULL)
+               {
+                       /* found a host with that name */
+                       bcopy(hent->h_addr, &server->sin_addr, hent->h_length);
+               }
+               else
+               {
+                       fprintf(stderr, "Can't find address for %s\n", host);
+                       free(host);
+                       free(tag);
+                       exit(1);
+               }
+   }
+
+       free(host);
+}
+
+static void *
+domain_for_user(char *uname, char *locn, ni_id *dir)
+{
+       char *upath;
+       int status;
+       void *d, *d1;
+       struct sockaddr_in server;
+       char *tag;
+       int bytag;
+
+       /*
+        * Find the user in NetInfo.
+        */
+       upath = malloc(8 + strlen(uname));
+       sprintf(upath, "/users/%s", uname);
+
+       if (locn != NULL)
+       {
+               bytag = 1;
+
+               if (locn[0] == '/') bytag = 0;
+               else if (!strncmp(locn, "./", 2)) bytag = 0;
+               else if (!strncmp(locn, "../", 3)) bytag = 0;
+
+               if (bytag == 1)
+               {
+                       parse_server_tag(locn, &server, &tag);
+                       d = ni_connect(&server, tag);
+                       if (d == (void *)NULL) return (void *)NULL;
+               }
+               else status = ni_open(NULL, locn, &d);
+               status = ni_pathsearch(d, dir, upath);
+               free(upath);
+
+               if (status == NI_OK) return d;
+
+               ni_free(d);
+               return (void *)NULL;
+       }
+
+       status = ni_open(NULL, ".", &d);
+       while (status == NI_OK)
+       {
+               status = ni_pathsearch(d, dir, upath);
+               if (status == NI_OK) break;
+               d1 = d;
+               status = ni_open(d1, "..", &d);
+               ni_free(d1);
+       }
+
+       free(upath);
+
+       if (status == NI_OK) return d;
+       return (void *)NULL;
+}
+
+int
+netinfo_passwd(char *uname, char *locn)
+{
+       char *oldpw;
+       char *newpw;
+       char *oc, *nc;
+       void *d;
+       int status, isroot;
+       ni_id dir;
+       ni_proplist     pl;
+       ni_property p;
+       ni_namelist     nl;
+       int ni_uid, uid, secure, minlen;
+       ni_index where;
+
+       d = domain_for_user(uname, locn, &dir);
+       if (d == (void *)NULL)
+       {
+               fprintf(stderr, "user %s not found in NetInfo\n", uname);
+               exit(1);
+       }
+
+       /*
+        * Read the passwd and uid from NetInfo.
+        */
+       status = ni_lookupprop(d, &dir, "passwd", &nl);
+       if (status == NI_NOPROP) nl.ni_namelist_len = 0;
+       else if (status != NI_OK)
+       {
+               ni_free(d);
+               fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
+               exit(1);
+       }
+
+       oldpw = NULL;
+       if (nl.ni_namelist_len > 0) oldpw = nl.ni_namelist_val[0];
+
+       status = ni_lookupprop(d, &dir, "uid", &nl);
+       if (status != NI_OK)
+       {
+               ni_free(d);
+               fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
+               exit(1);
+       }
+
+       ni_uid = -2;
+       if (nl.ni_namelist_len > 0) ni_uid = atoi(nl.ni_namelist_val[0]);
+
+       /*
+        * See if I'm uid 0 on the master host for the user's NetInfo domain.
+        */
+       isroot = is_root_on_master(d);
+       uid = getuid();
+       if ((isroot == 0) && (uid != ni_uid))
+       {
+               ni_free(d);
+               fprintf(stderr, "Permission denied\n");
+               exit(1);
+       }
+
+       /*
+        * Lock onto the master server.
+        */
+       ni_needwrite(d, 1);
+
+       /*
+        * Get the new password
+        */
+       secure = secure_passwords();
+       minlen = 5;
+       if (secure == 1) minlen = 8;
+       getpasswd(uname, isroot, minlen, 0, secure, oldpw, &newpw, &oc, &nc);
+
+       /*
+        * Authenticate if necessary
+        */
+       if (isroot == 0)
+       {
+               ni_setuser(d, uname);
+               ni_setpassword(d, oc);
+       }
+
+       /*
+        * Change the password in NetInfo.
+        */
+       status = ni_read(d, &dir, &pl);
+       if (status != NI_OK)
+       {
+               ni_free(d);
+               fprintf(stderr, "NetInfo read failed: %s\n", ni_error(status));
+               exit(1);
+       }
+
+       p.nip_name = "passwd";
+       p.nip_val.ni_namelist_len = 1;
+       p.nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
+       p.nip_val.ni_namelist_val[0] = newpw;
+
+       where = ni_proplist_match(pl, p.nip_name, NULL);
+       if (where == NI_INDEX_NULL)
+               status = ni_createprop(d, &dir, p, NI_INDEX_NULL);
+       else
+               status = ni_writeprop(d, &dir, where, p.nip_val);
+
+       free(p.nip_val.ni_namelist_val);
+
+       if (status != NI_OK)
+       {
+               ni_free(d);
+               fprintf(stderr, "NetInfo write failed: %s\n", ni_error(status));
+               exit(1);
+       }
+
+       ni_free(d);
+       return (0);
+}
diff --git a/passwd.tproj/nis_passwd.c b/passwd.tproj/nis_passwd.c
new file mode 100644 (file)
index 0000000..9043e92
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * 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@
+ */
+/* 
+ * Portions Copyright (c) 1998 by Apple Computer, Inc.
+ * Portions Copyright (c) 1988 by Sun Microsystems, Inc.
+ * Portions Copyright (c) 1988 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.
+ */
+
+
+/* update a user's password in NIS. This was based on the Sun implementation
+ * we used in NEXTSTEP, although I've added some stuff from OpenBSD. And
+ * it uses the API to support Rhapsody's proprietry infosystem switch.
+ * lukeh
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yppasswd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <errno.h>
+
+extern int getrpcport(char *, int, int, int);
+extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
+
+static struct passwd *ypgetpwnam(char *name, char *domain);
+
+int nis_passwd(char *uname, char *domain)
+{      
+       int ans, port, ok = -1;
+       char *master;
+       char *ne;       /* new encrypted password */
+       char *oc;       /* old cleartext password */
+       char *nc;       /* new cleartext password */
+       static struct yppasswd  yppasswd;
+       struct passwd *pwd;
+       int uid;
+       struct timeval tv;
+       CLIENT *cl;
+
+       if (domain == NULL)
+       {
+               if (yp_get_default_domain(&domain) != 0)
+               {
+                       (void)fprintf(stderr, "can't get domain\n");
+                       exit(1);
+               }
+       }
+       
+       if (yp_master(domain, "passwd.byname", &master) != 0)
+       {
+               (void)fprintf(stderr, "can't get master for passwd file\n");
+               exit(1);
+       }
+       
+       port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
+               IPPROTO_UDP);
+       if (port == 0)
+       {
+               (void)fprintf(stderr, "%s is not running yppasswd daemon\n",
+                             master);
+               exit(1);
+       }
+       if (port >= IPPORT_RESERVED)
+       {
+               (void)fprintf(stderr,
+                   "yppasswd daemon is not running on privileged port\n");
+               exit(1);
+       }
+
+       pwd = ypgetpwnam(uname, domain);
+       if (pwd == NULL)
+       {
+               (void)fprintf(stderr, "user %s not found\n", uname);
+               exit(1);
+       }
+       
+       uid = getuid();
+       if (uid != 0 && uid != pwd->pw_uid)
+       {
+               (void)fprintf(stderr, "you may only change your own password\n");
+               exit(1);
+       }
+       
+       getpasswd(uname, 0, 5, 0, 0, pwd->pw_passwd, &ne, &oc, &nc);
+               
+       yppasswd.oldpass = oc;
+       yppasswd.newpw.pw_name = pwd->pw_name;
+       yppasswd.newpw.pw_passwd = ne;
+       yppasswd.newpw.pw_uid = pwd->pw_uid;
+       yppasswd.newpw.pw_gid = pwd->pw_gid;
+       yppasswd.newpw.pw_gecos = pwd->pw_gecos;
+       yppasswd.newpw.pw_dir = pwd->pw_dir;
+       yppasswd.newpw.pw_shell = pwd->pw_shell;        
+       
+       cl = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
+       if (cl == NULL)
+       {
+               (void)fprintf(stderr, "could not contact yppasswdd on %s\n", master);
+               exit(1);
+       }
+       cl->cl_auth = authunix_create_default();
+       tv.tv_sec = 2;
+       tv.tv_usec = 0;
+       ans = clnt_call(cl, YPPASSWDPROC_UPDATE,
+               xdr_yppasswd, &yppasswd, xdr_int, &ok, tv);
+
+       if (ans != 0)
+       {
+               clnt_perrno(ans);
+               (void)fprintf(stderr, "\n");
+               (void)fprintf(stderr, "couldn't change passwd\n");
+               exit(1);
+       }
+       if (ok != 0)
+       {
+               (void)fprintf(stderr, "couldn't change passwd\n");
+               exit(1);
+       }
+       return(0);
+}
+
+static char *
+pwskip(register char *p)
+{
+       while (*p && *p != ':' && *p != '\n')
+               ++p;
+       if (*p)
+               *p++ = 0;
+       return (p);
+}
+
+struct passwd *
+interpret(struct passwd *pwent, char *line)
+{
+       register char   *p = line;
+
+       pwent->pw_passwd = "*";
+       pwent->pw_uid = 0;
+       pwent->pw_gid = 0;
+       pwent->pw_gecos = "";
+       pwent->pw_dir = "";
+       pwent->pw_shell = "";
+#ifndef __SLICK__
+       pwent->pw_change = 0;
+       pwent->pw_expire = 0;
+       pwent->pw_class = "";
+#endif
+
+       /* line without colon separators is no good, so ignore it */
+       if(!strchr(p, ':'))
+               return(NULL);
+
+       pwent->pw_name = p;
+       p = pwskip(p);
+       pwent->pw_passwd = p;
+       p = pwskip(p);
+       pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
+       p = pwskip(p);
+       pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
+       p = pwskip(p);
+       pwent->pw_gecos = p;
+       p = pwskip(p);
+       pwent->pw_dir = p;
+       p = pwskip(p);
+       pwent->pw_shell = p;
+       while (*p && *p != '\n')
+               p++;
+       *p = '\0';
+       return (pwent);
+}
+
+
+static struct passwd *
+ypgetpwnam(char *nam, char *domain)
+{
+       static struct passwd pwent;
+       char *val;
+       int reason, vallen;
+       static char *__yplin = NULL;
+
+       reason = yp_match(domain, "passwd.byname", nam, strlen(nam),
+           &val, &vallen);
+       switch(reason) {
+       case 0:
+               break;
+       default:
+               return (NULL);
+               break;
+       }
+       val[vallen] = '\0';
+       if (__yplin)
+               free(__yplin);
+       __yplin = (char *)malloc(vallen + 1);
+       strcpy(__yplin, val);
+       free(val);
+
+       return(interpret(&pwent, __yplin));
+}
diff --git a/passwd.tproj/passwd.1 b/passwd.tproj/passwd.1
new file mode 100644 (file)
index 0000000..4b07f93
--- /dev/null
@@ -0,0 +1,107 @@
+.\" 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.
+.\"
+.\"    @(#)passwd.1    8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt PASSWD 1
+.Os BSD 4
+.Sh NAME
+.Nm passwd
+.Nd modify a user's password
+.Sh SYNOPSIS
+.Nm passwd
+.Op Fl l
+.Op Ar user
+.Sh DESCRIPTION
+.Nm Passwd
+changes the user's Kerberos password.  First, the user is prompted for their
+current password.
+If the current password is correctly typed, a new password is
+requested.
+The new password must be entered twice to avoid typing errors.
+.Pp
+The new password should be at least six characters long and not
+purely alphabetic.
+Its total length must be less than
+.Dv _PASSWORD_LEN
+(currently 128 characters).
+Numbers, upper case letters and meta characters
+are encouraged.
+.Pp
+Once the password has been verified,
+.Nm passwd
+communicates the new password information to
+the Kerberos authenticating host.
+.Bl -tag -width flag
+.It Fl l
+This option causes the password to be updated only in the local
+password file, and not with the Kerberos database.
+When changing only the local password,
+.Xr pwd_mkdb  8
+is used to update the password databases.
+.El
+.Pp
+To change another user's Kerberos password, one must first
+run
+.Xr kinit 1
+followed by
+.Xr passwd 1 .
+The super-user is not required to provide a user's current password
+if only the local password is modified.
+.Sh FILES
+.Bl -tag -width /etc/master.passwd -compact
+.It Pa /etc/master.passwd
+The user database
+.It Pa /etc/passwd 
+A Version 7 format password file
+.It Pa /etc/passwd.XXXXXX
+Temporary copy of the password file
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr kerberos 1 ,
+.Xr kinit 1 ,
+.Xr login 1 ,
+.Xr passwd 5 ,
+.Xr kpasswdd 8 ,
+.Xr pwd_mkdb 8 ,
+.Xr vipw 8
+.Rs
+.%A Robert Morris
+.%A Ken Thompson
+.%T "UNIX password security"
+.Re
+.Sh HISTORY
+A
+.Nm passwd
+command appeared in
+.At v6 .
diff --git a/passwd.tproj/passwd.c b/passwd.tproj/passwd.c
new file mode 100644 (file)
index 0000000..a98b117
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * 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@
+ */
+#define INFO_NETINFO 0
+#define INFO_FILE 1
+#define INFO_NIS 2
+
+#ifndef __SLICK__
+#define _PASSWD_FILE "/etc/master.passwd"
+#else
+#define _PASSWD_FILE "/etc/passwd"
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <pwd.h>
+#include <libc.h>
+#include <ctype.h>
+#include <string.h>
+#include <netinfo/ni.h>
+#include "stringops.h"
+
+#ifdef __SLICK__
+#define _PASSWORD_LEN 8
+#endif
+
+static char *saltchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
+
+extern int file_passwd(char *, char *);
+extern int netinfo_passwd(char *, char *);
+extern int nis_passwd(char *, char *);
+
+void
+getpasswd(char *name, int isroot, int minlen, int mixcase, int nonalpha,
+       char *old_pw, char **new_pw, char **old_clear, char **new_clear)
+{
+       int i, tries, len, pw_ok, upper, lower, alpha, notalpha;
+       int isNull;
+       char *p;
+       static char obuf[_PASSWORD_LEN+1];
+       static char nbuf[_PASSWORD_LEN+1];
+       char salt[9];
+
+       printf("Changing password for %s.\n", name);
+
+       p = "";
+       isNull = 0;
+       if (old_pw == NULL) isNull = 1;
+       if ((isNull == 0) && (old_pw[0] == '\0')) isNull = 1;
+       if ((isroot == 0) && (isNull == 0))
+       {
+               p = getpass("Old password:");
+               if (strcmp(crypt(p, old_pw), old_pw))
+               {
+                       errno = EACCES;
+                       fprintf(stderr, "Sorry\n");
+                       exit(1);
+               }
+       }
+       strcpy(obuf, p);
+
+       tries = 0;
+       nbuf[0] = '\0';
+       for (;;)
+       {
+               p = getpass("New password:");
+               if (!*p)
+               {
+                       printf("Password unchanged.\n");
+                       exit(0);
+               }
+
+               tries++;
+               len = strlen(p);
+               upper = 0;
+               lower = 0;
+               alpha = 0;
+               notalpha = 0;
+               for (i = 0; i < len; i++)
+               {
+                       if (isupper(p[i])) upper++;
+                       if (islower(p[i])) lower++;
+                       if (isalpha(p[i])) alpha++;
+                       else notalpha++;
+               }
+
+
+               pw_ok = 1;
+               if (len < minlen) pw_ok = 0;
+               if ((mixcase == 1) && ((upper == 0) || (lower == 0))) pw_ok = 0;
+               if ((nonalpha == 1) && (notalpha == 0)) pw_ok = 0;
+
+               /*
+                * An insistent root may override security options.
+                */
+               if ((isroot == 1) && (tries > 2)) pw_ok = 1;
+       
+               /*
+                * A very insistent user may override security options.
+                */
+               if (tries > 4) pw_ok = 1;
+       
+               if (pw_ok == 0)
+               {
+                       if (len < minlen)
+                               printf("Password must be at least %d characters long.\n", minlen);
+                       if ((mixcase == 1) && ((upper == 0) || (lower == 0)))
+                               printf("Password must contain both upper and lower case characters.\n");
+                       if ((nonalpha == 1) && (notalpha == 0))
+                               printf("Password must contain non-alphabetic characters.\n");
+                       continue;
+               }
+
+               strcpy(nbuf, p);
+               if (!strcmp(nbuf, getpass("Retype new password:"))) break;
+
+               printf("Mismatch; try again, EOF to quit.\n");
+       }
+
+       /*
+        * Create a random salt
+        */
+       srandom((int)time((time_t *)NULL));
+       salt[0] = saltchars[random() % strlen(saltchars)];
+       salt[1] = saltchars[random() % strlen(saltchars)];
+       salt[2] = '\0';
+       *new_pw = crypt(nbuf, salt);
+
+       *old_clear = obuf;
+       *new_clear = nbuf;
+       return;
+}
+
+void
+usage()
+{
+       fprintf(stderr, "usage: passwd [-i infosystem] [-l location] [name]\n");
+       fprintf(stderr, "supported infosystems are:\n");
+       fprintf(stderr, "    netinfo\n");
+       fprintf(stderr, "    file\n");
+       fprintf(stderr, "    nis\n");
+       fprintf(stderr, "for netinfo, location may be a domain name or server/tag\n");
+       fprintf(stderr, "for file, location may be a file name (%s is the default)\n",
+               _PASSWD_FILE);
+       fprintf(stderr, "for nis, location may be a NIS domainname\n");
+       exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+       char *user, *locn;
+       int i, infosystem;
+
+       infosystem = INFO_NETINFO;
+       user = NULL;
+       locn = NULL;
+
+       for (i = 1; i < argc; i++)
+       {
+               if (!strcmp(argv[i], "-i"))
+               {
+                       if (++i >= argc)
+                       {
+                               fprintf(stderr, "no argument for -i option\n");
+                               usage();
+                       }
+
+                       if (!strcmp(argv[i], "NetInfo")) infosystem = INFO_NETINFO;
+                       else if (!strcmp(argv[i], "netinfo")) infosystem = INFO_NETINFO;
+                       else if (!strcmp(argv[i], "File")) infosystem = INFO_FILE;
+                       else if (!strcmp(argv[i], "file")) infosystem = INFO_FILE;
+                       else if (!strcmp(argv[i], "NIS")) infosystem = INFO_NIS;
+                       else if (!strcmp(argv[i], "nis")) infosystem = INFO_NIS;
+                       else if (!strcmp(argv[i], "YP")) infosystem = INFO_NIS;
+                       else if (!strcmp(argv[i], "yp")) infosystem = INFO_NIS;
+                       else
+                       {
+                               fprintf(stderr, "unknown info system \"%s\"\n", argv[i]);
+                               usage();
+                       }
+               }
+
+               else if (!strcmp(argv[i], "-l"))
+               {
+                       if (++i >= argc)
+                       {
+                               fprintf(stderr, "no argument for -l option\n");
+                               usage();
+                       }
+                       locn = argv[i];
+               }
+               else if (user == NULL) user = argv[i];
+               else usage();
+       }
+
+       if (user == NULL)
+       {
+               /*
+                * Verify that the login name exists.
+                * lukeh 24 Dec 1997
+                */
+               if ((user = getlogin()) == NULL)
+               {
+                       fprintf(stderr, "you don't have a login name\n");
+                       exit(1);
+               }
+       }
+       
+       switch (infosystem)
+       {
+               case INFO_NETINFO:
+                       netinfo_passwd(user, locn);
+                       break;
+               case INFO_FILE:
+                       file_passwd(user, locn);
+                       break;
+               case INFO_NIS:
+                       nis_passwd(user, locn);
+                       break;
+       }
+
+       exit(0);
+}
+
diff --git a/passwd.tproj/stringops.c b/passwd.tproj/stringops.c
new file mode 100644 (file)
index 0000000..568a025
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * 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 <string.h>
+#import <stdlib.h>
+#import <stdio.h>
+#import <varargs.h>
+#import "stringops.h"
+
+char *copyString(char *s)
+{
+       int len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       len = strlen(s) + 1;
+       t = malloc(len);
+       bcopy(s, t, len);
+       return t;
+}
+
+char *concatString(char *s, char *t)
+{
+       int len;
+
+       if (t == NULL) return s;
+
+       len = strlen(s) + strlen(t) + 1;
+       s = realloc(s, len);
+       strcat(s, t);
+       return s;
+}
+
+char **insertString(char *s, char **l, unsigned int x)
+{
+       int i, len;
+
+       if (s == NULL) return l;
+       if (l == NULL) 
+       {
+               l = (char **)malloc(2 * sizeof(char *));
+               l[0] = copyString(s);
+               l[1] = NULL;
+               return l;
+       }
+
+       for (i = 0; l[i] != NULL; i++);
+       len = i + 1; /* count the NULL on the end of the list too! */
+
+       l = (char **)realloc(l, (len + 1) * sizeof(char *));
+
+       if ((x >= (len - 1)) || (x == IndexNull))
+       {
+               l[len - 1] = copyString(s);
+               l[len] = NULL;
+               return l;
+       }
+
+       for (i = len; i > x; i--) l[i] = l[i - 1];
+       l[x] = copyString(s);
+       return l;
+}
+
+char **appendString(char *s, char **l)
+{
+       return insertString(s, l, IndexNull);
+}
+
+void freeList(char **l)
+{
+       int i;
+
+       if (l == NULL) return;
+       for (i = 0; l[i] != NULL; i++)
+       {
+               if (l[i] != NULL) free(l[i]);
+               l[i] = NULL;
+       }
+       if (l != NULL) free(l);
+}
+
+void freeString(char *s)
+{
+       if (s == NULL) return;
+       free(s);
+}
+
+unsigned int listLength(char **l)
+{
+       int i;
+
+       if (l == NULL) return 0;
+       for (i = 0; l[i] != NULL; i++);
+       return i;
+}
+
+unsigned int listIndex(char *s,char **l)
+{
+       int i;
+
+       if (l == NULL) return IndexNull;
+       for (i = 0; l[i] != NULL; i++)
+       {
+               if (strcmp(s, l[i]) == 0) return i;
+       }
+       return IndexNull;
+}
+
+char *prefix(char *s, char c)
+{
+       int i;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++);
+       if (i == 0) return NULL;
+       if (s[i] == '\0') return copyString(s);
+
+       t = malloc(i + 1);
+       bcopy(s, t, i);
+       t[i] = '\0';
+       return t;
+}
+
+char *postfix(char *s, char c)
+{
+       int i, len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       for (i = 0; ((s[i] != '\0') && (s[i] != c)); i++);
+       if (s[i] == '\0') return NULL;
+       len = strlen(s) - i;
+       if (len == 1) return NULL;
+
+       t = malloc(len);
+       len--;
+       bcopy((s + i + 1), t, len);
+       t[len] = '\0';
+       return t;
+}
+       
+char *presuffix(char *s, char c)
+{
+       int i, len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       len = strlen(s);
+       for (i = len - 1; ((i >= 0) && (s[i] != c)); i--);
+       if (i == 0) return NULL;
+       if (s[0] == '\0') return NULL;
+
+       t = malloc(i + 1);
+       bcopy(s, t, i);
+       t[i] = '\0';
+       return t;
+}
+
+char *suffix(char *s, char c)
+{
+       int i, len;
+       char *t;
+
+       if (s == NULL) return NULL;
+
+       len = strlen(s);
+       for (i = len - 1; ((i >= 0) && (s[i] != c)); i--);
+       if (i == 0) return NULL;
+       len -= i;
+       if (len == 1) return NULL;
+       t = malloc(len);
+       len--;
+       bcopy((s + i + 1), t, len);
+       t[len] = '\0';
+       return t;
+}
+
+char *lowerCase(char *s)
+{
+       int i;
+       char *t;
+
+       if (s == NULL) return NULL;
+       t = malloc(strlen(s) + 1);
+
+       for (i = 0; s[i] != '\0'; i++) 
+       {
+               if ((s[i] >= 'A') && (s[i] <= 'Z')) t[i] = s[i] + 32;
+               else t[i] = s[i];
+       }
+       t[i] = '\0';
+       return t;
+}
+
+char **explode(char *s, char c)
+{
+       char **l = NULL;
+       char *p, *t;
+       int i, n;
+
+       if (s == NULL) return NULL;
+
+       p = s;
+       while (p[0] != '\0')
+       {
+               for (i = 0; ((p[i] != '\0') && p[i] != c); i++);
+               n = i;
+               t = malloc(n + 1);
+               for (i = 0; i < n; i++) t[i] = p[i];
+               t[n] = '\0';
+               l = appendString(t, l);
+               free(t);
+               t = NULL;
+               if (p[i] == '\0') return l;
+               if (p[i + 1] == '\0') l = appendString("", l);
+               p = p + i + 1;
+       }
+       return l;
+}
+
+char *itoa(int n)
+{
+       char s[32];
+
+       sprintf(s, "%d", n);
+       return copyString(s);
+}
diff --git a/passwd.tproj/stringops.h b/passwd.tproj/stringops.h
new file mode 100644 (file)
index 0000000..417a167
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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@
+ */
+#define streq(A, B) (strcmp(A, B) == 0)
+#define IndexNull (unsigned int)-1
+char *copyString(char *);
+char *concatString(char *, char *);
+char **insertString(char *, char **, unsigned int);
+char **appendString(char *, char **);
+void freeList(char **);
+void freeString(char *);
+unsigned int listLength(char **);
+unsigned int listIndex(char *,char **);
+char *prefix(char *, char);
+char *postfix(char *, char);
+char *presuffix(char *, char);
+char *suffix(char *, char);
+char *lowerCase(char *);
+char **explode(char *, char);
+char *itoa(int);
diff --git a/pwd_mkdb.tproj/Makefile b/pwd_mkdb.tproj/Makefile
new file mode 100644 (file)
index 0000000..2ff74a3
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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 = pwd_mkdb
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pw_scan.h
+
+CFILES = pwd_mkdb.c pw_scan.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble pwd_mkdb.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/pwd_mkdb.tproj/Makefile.postamble b/pwd_mkdb.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..70b747f
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/pwd_mkdb.tproj/Makefile.preamble b/pwd_mkdb.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..e371f9d
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/pwd_mkdb.tproj/PB.project b/pwd_mkdb.tproj/PB.project
new file mode 100644 (file)
index 0000000..71b7d6f
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pw_scan.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (pwd_mkdb.c, pw_scan.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, pwd_mkdb.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = pwd_mkdb; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/pwd_mkdb.tproj/pw_scan.c b/pwd_mkdb.tproj/pw_scan.c
new file mode 100644 (file)
index 0000000..7e627de
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * 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) 1990, 1993, 1994
+ *     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 char sccsid[] = "@(#)pw_scan.c  8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+/*
+ * This module is used to "verify" password entries by chpass(1) and
+ * pwd_mkdb(8).
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+int
+pw_scan(bp, pw)
+       char *bp;
+       struct passwd *pw;
+{
+       long id;
+       int root;
+       char *p, *sh;
+
+       if (!(pw->pw_name = strsep(&bp, ":")))          /* login */
+               goto fmt;
+       root = !strcmp(pw->pw_name, "root");
+
+       if (!(pw->pw_passwd = strsep(&bp, ":")))        /* passwd */
+               goto fmt;
+
+       if (!(p = strsep(&bp, ":")))                    /* uid */
+               goto fmt;
+       id = atol(p);
+       if (root && id) {
+               warnx("root uid should be 0");
+               return (0);
+       }
+       if (id > USHRT_MAX) {
+               warnx("%s > max uid value (%d)", p, USHRT_MAX);
+               return (0);
+       }
+       pw->pw_uid = id;
+
+       if (!(p = strsep(&bp, ":")))                    /* gid */
+               goto fmt;
+       id = atol(p);
+       if (id > USHRT_MAX) {
+               warnx("%s > max gid value (%d)", p, USHRT_MAX);
+               return (0);
+       }
+       pw->pw_gid = id;
+
+       pw->pw_class = strsep(&bp, ":");                /* class */
+       if (!(p = strsep(&bp, ":")))                    /* change */
+               goto fmt;
+       pw->pw_change = atol(p);
+       if (!(p = strsep(&bp, ":")))                    /* expire */
+               goto fmt;
+       pw->pw_expire = atol(p);
+       pw->pw_gecos = strsep(&bp, ":");                /* gecos */
+       pw->pw_dir = strsep(&bp, ":");                  /* directory */
+       if (!(pw->pw_shell = strsep(&bp, ":")))         /* shell */
+               goto fmt;
+
+       p = pw->pw_shell;
+       if (root && *p)                                 /* empty == /bin/sh */
+               for (setusershell();;) {
+                       if (!(sh = getusershell())) {
+                               warnx("warning, unknown root shell");
+                               break;
+                       }
+                       if (!strcmp(p, sh))
+                               break;  
+               }
+
+       if (p = strsep(&bp, ":")) {                     /* too many */
+fmt:           warnx("corrupted entry");
+               return (0);
+       }
+       return (1);
+}
diff --git a/pwd_mkdb.tproj/pw_scan.h b/pwd_mkdb.tproj/pw_scan.h
new file mode 100644 (file)
index 0000000..55754b6
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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) 1994
+ *     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.
+ *
+ *     @(#)pw_scan.h   8.1 (Berkeley) 4/1/94
+ */
+
+extern int     pw_scan __P((char *, struct passwd *));
diff --git a/pwd_mkdb.tproj/pwd_mkdb.8 b/pwd_mkdb.tproj/pwd_mkdb.8
new file mode 100644 (file)
index 0000000..3d012e3
--- /dev/null
@@ -0,0 +1,128 @@
+.\" Copyright (c) 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.
+.\"
+.\"    @(#)pwd_mkdb.8  8.2 (Berkeley) 4/27/95
+.\"
+.Dd April 27, 1995
+.Dt PWD_MKDB 8
+.Os
+.Sh NAME
+.Nm pwd_mkdb
+.Nd "generate the password databases"
+.Sh SYNOPSIS
+.Nm pwd_mkdb
+.Op Fl p
+.Ar file
+.Sh DESCRIPTION
+.Nm Pwd_mkdb
+creates
+.Xr db 3
+style secure and insecure databases for the specified file.
+These databases are then installed into
+.Dq Pa /etc/spwd.db
+and
+.Dq Pa /etc/pwd.db
+respectively.
+The file is installed into
+.Dq Pa /etc/master.passwd .
+The file must be in the correct format (see
+.Xr passwd 5 ) .
+It is important to note that the format used in this system is
+different from the historic Version 7 style format.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl p
+Create a Version 7 style password file and install it into
+.Dq Pa /etc/passwd .
+.El
+.Pp
+The two databases differ in that the secure version contains the user's 
+encrypted password and the insecure version has an asterisk (``*'')
+.Pp
+The databases are used by the C library password routines (see
+.Xr getpwent 3 ) .
+.Pp
+.Nm Pwd_mkdb
+exits zero on success, non-zero on failure.
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /etc/master.passwd
+The current password file.
+.It Pa /etc/passwd
+A Version 7 format password file.
+.It Pa /etc/pwd.db
+The insecure password database file.
+.It Pa /etc/pwd.db.tmp
+A temporary file.
+.It Pa /etc/spwd.db
+The secure password database file.
+.It Pa /etc/spwd.db.tmp
+A temporary file.
+.El
+.Sh BUGS
+Because of the necessity for atomic update of the password files,
+.Nm pwd_mkdb
+uses
+.Xr rename 2
+to install them.
+This, however, requires that the file specified on the command line live
+on the same file system as the
+.Dq Pa /etc
+directory.
+.Pp
+There are the obvious races with multiple people running
+.Nm pwd_mkdb
+on different password files at the same time.
+The front-ends to 
+.Nm pwd_mkdb ,
+.Xr chpass 1 ,
+.Xr passwd 1
+and
+.Xr vipw 8 ,
+handle the locking necessary to avoid this problem.
+.Sh COMPATIBILITY
+Previous versions of the system had a program similar to
+.Nm pwd_mkdb ,
+.Xr mkpasswd 8 ,
+which built
+.Xr dbm 3
+style databases for the password file but depended on the calling programs
+to install them.
+The program was renamed in order that previous users of the program
+not be surprised by the changes in functionality.
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr passwd 1 ,
+.Xr db 3 ,
+.Xr getpwent 3 ,
+.Xr passwd 5 ,
+.Xr vipw 8
diff --git a/pwd_mkdb.tproj/pwd_mkdb.c b/pwd_mkdb.tproj/pwd_mkdb.c
new file mode 100644 (file)
index 0000000..b9acefa
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * 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) 1991, 1993, 1994
+ *     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 char copyright[] =
+"@(#) Copyright (c) 1991, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)pwd_mkdb.c 8.5 (Berkeley) 4/20/94";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <db.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+#define        INSECURE        1
+#define        SECURE          2
+#define        PERM_INSECURE   (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
+#define        PERM_SECURE     (S_IRUSR|S_IWUSR)
+
+HASHINFO openinfo = {
+       4096,           /* bsize */
+       32,             /* ffactor */
+       256,            /* nelem */
+       2048 * 1024,    /* cachesize */
+       NULL,           /* hash() */
+       0               /* lorder */
+};
+
+static enum state { FILE_INSECURE, FILE_SECURE, FILE_ORIG } clean;
+static struct passwd pwd;                      /* password structure */
+static char *pname;                            /* password file name */
+
+void   cleanup __P((void));
+void   error __P((char *));
+void   mv __P((char *, char *));
+int    scan __P((FILE *, struct passwd *));
+void   usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       DB *dp, *edp;
+       DBT data, key;
+       FILE *fp, *oldfp;
+       sigset_t set;
+       int ch, cnt, len, makeold, tfd;
+       char *p, *t;
+       char buf[MAX(MAXPATHLEN, LINE_MAX * 2)], tbuf[1024];
+
+       makeold = 0;
+       while ((ch = getopt(argc, argv, "pv")) != EOF)
+               switch(ch) {
+               case 'p':                       /* create V7 "file.orig" */
+                       makeold = 1;
+                       break;
+               case 'v':                       /* backward compatible */
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 1)
+               usage();
+
+       /*
+        * This could be changed to allow the user to interrupt.
+        * Probably not worth the effort.
+        */
+       sigemptyset(&set);
+       sigaddset(&set, SIGTSTP);
+       sigaddset(&set, SIGHUP);
+       sigaddset(&set, SIGINT);
+       sigaddset(&set, SIGQUIT);
+       sigaddset(&set, SIGTERM);
+       (void)sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
+
+       /* We don't care what the user wants. */
+       (void)umask(0);
+
+       pname = *argv;
+       /* Open the original password file */
+       if (!(fp = fopen(pname, "r")))
+               error(pname);
+
+       /* Open the temporary insecure password database. */
+       (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB);
+       dp = dbopen(buf,
+           O_RDWR|O_CREAT|O_EXCL, PERM_INSECURE, DB_HASH, &openinfo);
+       if (dp == NULL)
+               error(buf);
+       clean = FILE_INSECURE;
+
+       /*
+        * Open file for old password file.  Minor trickiness -- don't want to
+        * chance the file already existing, since someone (stupidly) might
+        * still be using this for permission checking.  So, open it first and
+        * fdopen the resulting fd.  The resulting file should be readable by
+        * everyone.
+        */
+       if (makeold) {
+               (void)snprintf(buf, sizeof(buf), "%s.orig", pname);
+               if ((tfd = open(buf,
+                   O_WRONLY|O_CREAT|O_EXCL, PERM_INSECURE)) < 0)
+                       error(buf);
+               if ((oldfp = fdopen(tfd, "w")) == NULL)
+                       error(buf);
+               clean = FILE_ORIG;
+       }
+
+       /*
+        * The databases actually contain three copies of the original data.
+        * Each password file entry is converted into a rough approximation
+        * of a ``struct passwd'', with the strings placed inline.  This
+        * object is then stored as the data for three separate keys.  The
+        * first key * is the pw_name field prepended by the _PW_KEYBYNAME
+        * character.  The second key is the pw_uid field prepended by the
+        * _PW_KEYBYUID character.  The third key is the line number in the
+        * original file prepended by the _PW_KEYBYNUM character.  (The special
+        * characters are prepended to ensure that the keys do not collide.)
+        */
+       data.data = (u_char *)buf;
+       key.data = (u_char *)tbuf;
+       for (cnt = 1; scan(fp, &pwd); ++cnt) {
+#define        COMPACT(e)      t = e; while (*p++ = *t++);
+               /* Create insecure data. */
+               p = buf;
+               COMPACT(pwd.pw_name);
+               COMPACT("*");
+               memmove(p, &pwd.pw_uid, sizeof(int));
+               p += sizeof(int);
+               memmove(p, &pwd.pw_gid, sizeof(int));
+               p += sizeof(int);
+               memmove(p, &pwd.pw_change, sizeof(time_t));
+               p += sizeof(time_t);
+               COMPACT(pwd.pw_class);
+               COMPACT(pwd.pw_gecos);
+               COMPACT(pwd.pw_dir);
+               COMPACT(pwd.pw_shell);
+               memmove(p, &pwd.pw_expire, sizeof(time_t));
+               p += sizeof(time_t);
+               data.size = p - buf;
+
+               /* Store insecure by name. */
+               tbuf[0] = _PW_KEYBYNAME;
+               len = strlen(pwd.pw_name);
+               memmove(tbuf + 1, pwd.pw_name, len);
+               key.size = len + 1;
+               if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
+                       error("put");
+
+               /* Store insecure by number. */
+               tbuf[0] = _PW_KEYBYNUM;
+               memmove(tbuf + 1, &cnt, sizeof(cnt));
+               key.size = sizeof(cnt) + 1;
+               if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
+                       error("put");
+
+               /* Store insecure by uid. */
+               tbuf[0] = _PW_KEYBYUID;
+               memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
+               key.size = sizeof(pwd.pw_uid) + 1;
+               if ((dp->put)(dp, &key, &data, R_NOOVERWRITE) == -1)
+                       error("put");
+
+               /* Create original format password file entry */
+               if (makeold)
+                       (void)fprintf(oldfp, "%s:*:%d:%d:%s:%s:%s\n",
+                           pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_gecos,
+                           pwd.pw_dir, pwd.pw_shell);
+       }
+       (void)(dp->close)(dp);
+       if (makeold) {
+               (void)fflush(oldfp);
+               (void)fclose(oldfp);
+       }
+
+       /* Open the temporary encrypted password database. */
+       (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB);
+       edp = dbopen(buf,
+           O_RDWR|O_CREAT|O_EXCL, PERM_SECURE, DB_HASH, &openinfo);
+       if (!edp)
+               error(buf);
+       clean = FILE_SECURE;
+
+       rewind(fp);
+       for (cnt = 1; scan(fp, &pwd); ++cnt) {
+
+               /* Create secure data. */
+               p = buf;
+               COMPACT(pwd.pw_name);
+               COMPACT(pwd.pw_passwd);
+               memmove(p, &pwd.pw_uid, sizeof(int));
+               p += sizeof(int);
+               memmove(p, &pwd.pw_gid, sizeof(int));
+               p += sizeof(int);
+               memmove(p, &pwd.pw_change, sizeof(time_t));
+               p += sizeof(time_t);
+               COMPACT(pwd.pw_class);
+               COMPACT(pwd.pw_gecos);
+               COMPACT(pwd.pw_dir);
+               COMPACT(pwd.pw_shell);
+               memmove(p, &pwd.pw_expire, sizeof(time_t));
+               p += sizeof(time_t);
+               data.size = p - buf;
+
+               /* Store secure by name. */
+               tbuf[0] = _PW_KEYBYNAME;
+               len = strlen(pwd.pw_name);
+               memmove(tbuf + 1, pwd.pw_name, len);
+               key.size = len + 1;
+               if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
+                       error("put");
+
+               /* Store secure by number. */
+               tbuf[0] = _PW_KEYBYNUM;
+               memmove(tbuf + 1, &cnt, sizeof(cnt));
+               key.size = sizeof(cnt) + 1;
+               if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
+                       error("put");
+
+               /* Store secure by uid. */
+               tbuf[0] = _PW_KEYBYUID;
+               memmove(tbuf + 1, &pwd.pw_uid, sizeof(pwd.pw_uid));
+               key.size = sizeof(pwd.pw_uid) + 1;
+               if ((edp->put)(edp, &key, &data, R_NOOVERWRITE) == -1)
+                       error("put");
+       }
+
+       (void)(edp->close)(edp);
+
+       /* Set master.passwd permissions, in case caller forgot. */
+       (void)fchmod(fileno(fp), S_IRUSR|S_IWUSR);
+       (void)fclose(fp);
+
+       /* Install as the real password files. */
+       (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB);
+       mv(buf, _PATH_MP_DB);
+       (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB);
+       mv(buf, _PATH_SMP_DB);
+       if (makeold) {
+               (void)snprintf(buf, sizeof(buf), "%s.orig", pname);
+               mv(buf, _PATH_PASSWD);
+       }
+       /*
+        * Move the master password LAST -- chpass(1), passwd(1) and vipw(8)
+        * all use flock(2) on it to block other incarnations of themselves.
+        * The rename means that everything is unlocked, as the original file
+        * can no longer be accessed.
+        */
+       mv(pname, _PATH_MASTERPASSWD);
+       exit(0);
+}
+
+int
+scan(fp, pw)
+       FILE *fp;
+       struct passwd *pw;
+{
+       static int lcnt;
+       static char line[LINE_MAX];
+       char *p;
+
+#if defined(__APPLE__)
+       do {
+               if (!fgets(line, sizeof(line), fp))
+                   return (0);
+       } while (line[0] == '#');
+#else
+       if (!fgets(line, sizeof(line), fp))
+               return (0);
+#endif
+       ++lcnt;
+       /*
+        * ``... if I swallow anything evil, put your fingers down my
+        * throat...''
+        *      -- The Who
+        */
+       if (!(p = strchr(line, '\n'))) {
+               warnx("line too long");
+               goto fmt;
+
+       }
+       *p = '\0';
+       if (!pw_scan(line, pw)) {
+               warnx("at line #%d", lcnt);
+fmt:           errno = EFTYPE; /* XXX */
+               error(pname);
+       }
+
+       return (1);
+}
+
+void
+mv(from, to)
+       char *from, *to;
+{
+       char buf[MAXPATHLEN];
+
+       if (rename(from, to)) {
+               int sverrno = errno;
+               (void)snprintf(buf, sizeof(buf), "%s to %s", from, to);
+               errno = sverrno;
+               error(buf);
+       }
+}
+
+void
+error(name)
+       char *name;
+{
+
+       warn(name);
+       cleanup();
+       exit(1);
+}
+
+void
+cleanup()
+{
+       char buf[MAXPATHLEN];
+
+       switch(clean) {
+       case FILE_ORIG:
+               (void)snprintf(buf, sizeof(buf), "%s.orig", pname);
+               (void)unlink(buf);
+               /* FALLTHROUGH */
+       case FILE_SECURE:
+               (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_SMP_DB);
+               (void)unlink(buf);
+               /* FALLTHROUGH */
+       case FILE_INSECURE:
+               (void)snprintf(buf, sizeof(buf), "%s.tmp", _PATH_MP_DB);
+               (void)unlink(buf);
+       }
+}
+
+void
+usage()
+{
+
+       (void)fprintf(stderr, "usage: pwd_mkdb [-p] file\n");
+       exit(1);
+}
diff --git a/reboot.tproj/Makefile b/reboot.tproj/Makefile
new file mode 100644 (file)
index 0000000..74f27bc
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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 = reboot
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = reboot.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            boot_hp300.8 boot_i386.8 boot_sparc.8 boot_tahoe.8\
+            boot_vax.8 reboot.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/reboot.tproj/Makefile.dist b/reboot.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..f4e1a55
--- /dev/null
@@ -0,0 +1,18 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  reboot
+DPADD= ${LIBUTIL}
+LDADD= -lutil
+MAN8=  reboot.0 boot_hp300.0 boot_i386.0 boot_sparc.0 boot_tahoe.0 boot_vax.0
+MLINKS=        reboot.8 halt.8
+LINKS= ${BINDIR}/reboot ${BINDIR}/halt
+
+afterinstall:
+       ${MINSTALL} boot_hp300.0 ${DESTDIR}${MANDIR}8/hp300/boot.0
+       ${MINSTALL} boot_i386.0 ${DESTDIR}${MANDIR}8/i386/boot.0
+       ${MINSTALL} boot_sparc.0 ${DESTDIR}${MANDIR}8/sparc/boot.0
+       ${MINSTALL} boot_tahoe.0 ${DESTDIR}${MANDIR}8/tahoe/boot.0
+       ${MINSTALL} boot_vax.0 ${DESTDIR}${MANDIR}8/vax/boot.0
+
+.include <bsd.man.mk>
+.include <bsd.prog.mk>
diff --git a/reboot.tproj/Makefile.postamble b/reboot.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..374a705
--- /dev/null
@@ -0,0 +1,3 @@
+#we already have a halt?
+#after_install::
+#      $(LN) $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/halt
diff --git a/reboot.tproj/Makefile.preamble b/reboot.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/reboot.tproj/PB.project b/reboot.tproj/PB.project
new file mode 100644 (file)
index 0000000..f8ce3d8
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (reboot.c); 
+        OTHER_SOURCES = (
+            Makefile.preamble, 
+            Makefile, 
+            Makefile.postamble, 
+            Makefile.dist, 
+            boot_hp300.8, 
+            boot_i386.8, 
+            boot_sparc.8, 
+            boot_tahoe.8, 
+            boot_vax.8, 
+            reboot.8
+        ); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = reboot; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = reboot; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = reboot; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = reboot; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/reboot.tproj/boot_hp300.8 b/reboot.tproj/boot_hp300.8
new file mode 100644 (file)
index 0000000..0303542
--- /dev/null
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the Systems Programming Group of the University of Utah Computer
+.\" Science Department.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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.
+.\"
+.\"    @(#)boot_hp300.8        8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt BOOT_HP300 8 hp300
+.Os
+.Sh NAME
+.Nm boot
+.Nd
+system bootstrapping procedures
+.Sh DESCRIPTION
+.Sy Power fail and crash recovery.
+Normally, the system will reboot itself at power-up or after crashes.
+An automatic consistency check of the file systems will be performed,
+and unless this fails, the system will resume multi-user operations.
+.Pp
+.Sy Cold starts.
+On an HP300, the boot procedure uses the boot ROM to load a boot program
+from an
+.Tn LIF
+format directory at the beginning of an attached disk.
+The
+.Pa /usr/mdec
+directory contains a disk boot programs which should be placed in a
+new pack automatically by
+.Xr newfs 8
+when the ``a'' partition file system on the pack is created.
+.Pp
+This
+.Em boot
+program
+finds the corresponding file on the given device 
+.Pf ( Ar vmunix
+by default),
+loads that file into memory,
+and starts the program at the entry address specified in the program header.
+.Pp
+The boot program can be interrupted by typing `^C' (ctrl-C).
+This will force the boot program to interactively prompt for a system to boot.
+If not interrupted, it will boot from the device from which the boot
+program itself was loaded.
+.Pp
+The file specifications used for an interactive boot are of the form:
+.Pp
+.Dl device(unit, minor)
+.Pp
+where
+.Ar device
+is the type of the device to be searched,
+.Ar unit
+is 8 * the hpib number plus the unit number of the disk or tape,
+and
+.Ar minor
+is the disk partition or tape file number.
+Normal line editing characters can be used when typing the file specification.
+Currently, ``rd'' and ``sd'' are the only valid
+.Ar device
+specifiers.
+.Pp
+For example,
+to boot from the `a' file system of unit 0 on HP-IB 2,
+type
+.Ql rd(16, 0)vmunix
+to the boot prompt.
+For tapes, the minor device number gives a file offset.
+.Pp
+In an emergency, the bootstrap methods described in the paper
+.%T Installing 4.3bsd on the HP300
+can be used to boot from a distribution tape.
+.Sh FILES
+.Bl -tag -width /usr/mdec/installboot -compact
+.It Pa /vmunix
+system code
+.It Pa /usr/mdec/bootrd
+.Tn LIF
+format boot block
+.It Pa /usr/mdec/installboot
+program to install boot blocks
+.El
+.Sh SEE ALSO
+.Xr halt 8 ,
+.Xr reboot 8 ,
+.Xr shutdown 8
diff --git a/reboot.tproj/boot_i386.8 b/reboot.tproj/boot_i386.8
new file mode 100644 (file)
index 0000000..0dc3e0b
--- /dev/null
@@ -0,0 +1,126 @@
+.\" Copyright (c) 1991, 1993
+.\"    The Regents of the University of California.  All rights reserved.
+.\"
+.\" This code is derived from software written and contributed
+.\" to Berkeley by William Jolitz.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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.
+.\"
+.\"     @(#)boot_i386.8        8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt BOOT 8 i386
+.Os
+.Sh NAME
+.Nm boot
+.Nd
+system bootstrapping procedures
+.Sh DESCRIPTION
+.Sy Power fail and crash recovery.
+Normally, the system will reboot itself at power-up or after crashes.
+An automatic consistency check of the file systems will be performed,
+and unless this fails, the system will resume multi-user operations.
+.Pp
+.Sy Cold starts.
+The 386
+.Tn "PC AT"
+clones attempt to boot the floppy disk drive A (otherwise known as drive
+0) first, and failing that, attempt to boot the hard disk C (otherwise
+known as hard disk controller 1, drive 0).
+The automatic boot will attempt to load
+.Pa vmunix
+from partition A of either the floppy or the hard disk.
+This boot may be aborted by typing any character on the keyboard repeatedly
+(four or five times at least) during the operating system load phase, after
+which the bootstrap will prompt for the file that you wish to load instead.
+.Pp
+One exception to this is the
+.Ql d
+key, which will not abort the load but instead silently force the
+.Dv DEBUG
+boot flags.
+The boot flags for an autoboot are 0, and 3 for the successive boot after
+an aborted autoboot sequence.
+No other provison is made for setting boot flags (yet).
+A specific device or bootstrap file may be used; for example,
+.Pp
+The file specifications used for the boostrap
+when loaded with the
+.Dq askme
+flag
+(e.g. an aborted autoboot)
+are of the form:
+.Pp
+.Dl device unit partition:
+.Pp
+where
+.Ar device
+is the type of the device, assumed to be on the ISA bus, to be searched,
+.Ar unit
+is the unit number of the disk or tape,
+and
+.Ar partition
+is the disk partition or tape file number.
+Normal line editing characters can be used when typing the file specification.
+The following list of supported devices may vary from installation to
+installation:
+.Bd -unfilled -offset indent
+wd     ST506, IDE, ESDI, RLL disks on a WD100[2367] or lookalike
+       controller
+fd     5 1/4" or 3 1/2" High density floppies
+.Ed
+.Pp
+For example,
+to boot from a file system which starts at cylinder 0
+of unit 0 of an IDE disk, type
+.Dq Li wd0a:vmunix
+to the boot prompt;
+.Dq Li fd0a:vmunix
+would specify a 3 1/2" floppy drive 0 .
+.Pp
+In an emergency, the bootstrap methods described in the paper
+.%T "Installing and Operating 4.3 BSD-Reno UNIX on the AT/386"
+can be used
+to boot from a distribution tape.
+.Sh FILES
+.Bl -tag -width /vmunixxx -compact
+.It Pa /vmunix
+system code
+.It Pa /boot
+system bootstrap
+.El
+.Sh SEE ALSO
+.Xr halt 8 ,
+.Xr reboot 8 ,
+.Xr shutdown 8
+.Sh BUGS
+The disklabel format used by this version of
+.Bx
+is quite
+different from that of other architectures.
diff --git a/reboot.tproj/boot_sparc.8 b/reboot.tproj/boot_sparc.8
new file mode 100644 (file)
index 0000000..72e57b0
--- /dev/null
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1992, 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.
+.\"
+.\"     @(#)boot_sparc.8       8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt REBOOT 8 sparc
+.Os
+.Sh NAME
+.Nm reboot
+.Nd
+.Tn UNIX
+bootstrapping procedures
+.Sh SYNOPSIS
+.Nm reboot
+.Op Fl n
+.Op Fl q
+.Sh DESCRIPTION
+.Sy Power fail and crash recovery.
+Normally, the system will reboot itself at power-up or after crashes.
+An automatic consistency check of the file systems will be performed
+as described in
+.Xr fsck 8 .
+and unless this fails, the system will resume multi-user operations.
+.Pp
+.Sy Cold starts
+The SPARC system currently uses the SunOS bootstrap loaders.
+This will be changed in a future version of the system.
+The SunOS boot will attempt to load
+.Pa vmunix
+from partition A of the boot device,
+which must currently be an ``sd'' disk.
+.Pp
+The
+.Op Fl s
+flag to the SunOS boot loader will being the system up in single-user mode.
+The
+.Op Fl d
+flag to the SunOS boot loader will bring the system up in debug mode.
+Here it waits for a kernel debugger connect; see
+.Xr kgdb 8 .
+Other flags are currently ignored.
+.Sh FILES
+.Bl -tag -width /vmunixxx -compact
+.It Pa /vmunix
+system code
+.It Pa /boot
+system bootstrap
+.El
+.Sh SEE ALSO
+.Xr crash 8 ,
+.Xr disklabel 8 ,
+.Xr fsck 8 ,
+.Xr halt 8 ,
+.Xr init 8 ,
+.Xr rc 8 ,
+.Xr shutdown 8 ,
+.Xr syslogd 8
+.Sh BUGS
+The use of Sun disk labels, without the ability to write them,
+is problematic.
diff --git a/reboot.tproj/boot_tahoe.8 b/reboot.tproj/boot_tahoe.8
new file mode 100644 (file)
index 0000000..01c7f81
--- /dev/null
@@ -0,0 +1,152 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"     @(#)boot_tahoe.8       8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt BOOT 8 tahoe
+.Os
+.Sh NAME
+.Nm boot
+.Nd
+system bootstrapping procedures
+.Sh DESCRIPTION
+.Sy Power fail and crash recovery.
+Normally, the system will reboot itself at power-up or after crashes.
+An automatic consistency check of the file systems will be performed,
+and unless this fails, the system will resume multi-user operations.
+.Pp
+.Sy Cold starts.
+These are processor-type dependent.
+On the
+.Tn CCI
+Power 6/32 and related processors,
+the system will do a standard autoboot from drive 0
+upon power-up or reset.
+This automatic boot may be cancelled by typing a
+.Ql \&#
+in the first few seconds after reset.
+This enters console mode; the console prompt is
+.Ql >
+or
+.Ql \&# .
+The boot flags can be set to any hexadecimal value
+.Fl n
+with the command
+.Pp
+.Bd -filled -offset indent -compact
+.Li \&#> p23
+.Ar n .
+.Ed
+.Pp
+The default device may be examined or set; see the Diagnostics and Debugging
+manual for the processor for details on device naming and syntax.
+After setting the boot flags and/or device,
+a bootstrap sequence can be initiated with
+.Pp
+.Dl #> fb
+.Pp
+A specific device or bootstrap file may be used; for example,
+.Pp
+.Dl \&#> \&fb xfd(1,0)
+.Pp
+would boot from the `a' partition on
+.Tn XFD
+drive 1.
+.Pp
+The file specifications used for the boostrap
+when loaded with the
+.Dq askme
+flag
+(register 23 set to 1 or 3)
+are of the form:
+.Pp
+.Dl device(adaptor,controller,unit,minor)
+.Pp
+where
+.Ar device
+is the type of the device to be searched,
+.Ar adaptor
+is number of the
+.Tn VERSAbus
+(or
+.Tn VMEbus )
+to which the device is attached,
+.Ar controller
+is the unit number of the controller on that buss,
+.Ar unit
+is the unit number of the disk or tape,
+and
+.Ar minor
+is the disk partition or tape file number.
+Leading adaptor or controller numbers default to 0.
+Normal line editing characters can be used when typing the file specification.
+The following list of supported devices may vary from installation to
+installation:
+.Pp
+.Bd -unfilled -offset indent -compact
+dk     SMD or ESDI disks on VDDC or SMD-E
+cy     tape on Ciprico Tapemaster controller
+.Ed
+.Pp
+For example,
+to boot from a file system which starts at cylinder 0
+of unit 0 of an
+.Tn SMD-E
+disk, type
+.Ql dk(0,0)vmunix
+to the boot prompt;
+.Ql dk(2,1,0)vmunix
+would specify drive 1 on
+.Tn SMD-E
+controller 2.
+.Pp
+In an emergency, the bootstrap methods described in the paper
+.%T "Installing and Operating 4.3 BSD-tahoe UNIX on the Tahoe"
+can be used
+to boot from a distribution tape.
+.Sh FILES
+.Bl -tag -width /vmunix -compact
+.It Pa /vmunix
+system code
+.It Pa /boot
+system bootstrap
+.El
+.Sh SEE ALSO
+.Xr halt 8 ,
+.Xr reboot 8 ,
+.Xr shutdown 8
+.Sh BUGS
+The disklabel format used by some versions of the console processor
+is different than the format used by
+.Tn UNIX
+and the bootstrap.
+.Sh HISTORY
diff --git a/reboot.tproj/boot_vax.8 b/reboot.tproj/boot_vax.8
new file mode 100644 (file)
index 0000000..dce6b69
--- /dev/null
@@ -0,0 +1,322 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"     @(#)boot_vax.8 8.2 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt BOOT 8 vax
+.Os
+.Sh NAME
+.Nm boot
+.Nd
+system bootstrapping procedures
+.Sh DESCRIPTION
+.Sy Power fail and crash recovery.
+Normally, the system will reboot itself at power-up or after crashes.
+Provided the auto-restart is enabled on the machine front panel,
+an automatic consistency check of the file systems will be performed,
+and unless this fails, the system will resume multi-user operations.
+.Pp
+.Sy Cold starts.
+These are processor-type dependent.
+On an 11/780, there are two floppy files for each disk controller,
+both of which cause boots from unit 0 of the root file system
+of a controller located on mba0 or uba0.
+One gives a single user shell, while the other invokes the multi-user
+automatic reboot.
+Thus these files are
+.Tn HPS
+and
+.Tn HPM
+for the single
+and multi-user boot from
+.Tn MASSBUS
+RP06/RM03/RM05 disks,
+.Tn UPS
+and
+.Tn UPM
+for
+.Tn UNIBUS
+storage module controller and disks
+such as the
+.Tn EMULEX
+SC-21
+and
+.Tn AMPEX
+9300 pair,
+.Tn RAS
+and
+.Tn RAM
+to boot from
+.Tn MSCP
+controllers and disks such as the RA81,
+or
+.Tn HKS
+and
+.Tn HKM
+for RK07 disks.
+There is also a script for booting from the default device,
+which is normally a copy of one of the standard multi-user boot scripts,
+but which may be modified to perform other actions
+or to boot from a different unit.
+The situation on the 8600 is similar, with scripts loaded from the console RL02.
+.Pp
+Giving the command
+.Pp
+.Dl >>>BOOT HPM
+.Pp
+would boot the system from (e.g.) an RP06 and run the automatic consistency
+check as described in
+.Xr fsck 8 .
+(Note that it may
+be necessary to type control-P
+and halt the processor
+to gain the attention of the
+.Tn LSI-11
+before getting the >>> prompt.)
+The command
+.Pp
+.Dl >>>BOOT ANY
+.Pp
+invokes a version of the boot program in a way which allows you to
+specify any system as the system to be booted.
+It reads from the console a device specification (see below) followed
+immediately by a pathname.
+.Pp
+The scripts may be modified for local configuration if necessary.
+The flags are placed in register 11 (as defined in
+.Aq Pa sys/reboot.h ) .
+The boot device is specified in register 10.
+The encoding of this register is also defined in
+.Aq Pa sys/reboot.h .
+The current encoding has a historical basis, and is shown in the following
+table:
+.Pp
+.Bd -unfilled -offset indent -compact
+bits   usage
+0-7    boot device type (the device major number)
+8-15   disk partition
+16-19  drive unit
+20-23  controller number
+24-27  adaptor number (UNIBUS or MASSBUS as appropriate)
+.Ed
+.Pp
+The adaptor number corresponds to the normal configuration on the 11/750,
+and to the order in which adaptors are found on the 11/780 and 8600
+(generally the same as the numbers used by
+.Tn UNIX ) .
+.Pp
+On an 11/750, the reset button will boot from the device
+selected by the front panel boot device switch.  In systems
+with RK07's, position B normally selects the RK07 for boot.
+This will boot multi-user.  To boot from RK07 with boot flags you
+may specify
+.Pp
+.Bd -unfilled -offset indent -compact
+.Li \&>>>B/ Ns Fl n No DMA0
+.Ed
+.Pp
+where, giving a
+.Ar n
+of 1 causes the boot program
+to ask for the name of the system to be bootstrapped,
+giving a
+.Ar n
+of 2 causes the boot program to come up single
+user, and a
+.Ar n
+of 3 causes both of these actions to occur.
+The ``DM'' specifies RK07, the ``A'' represents the adaptor number
+.Pf ( Tn UNIBUS
+or
+.Tn MASSBUS ) ,
+and the ``0'' is the drive unit number.
+Other disk types which may be used are DB
+.Pq Tn MASSBUS ,
+DD (TU58),
+and DU
+.Pf ( Tn UDA-50/RA
+disk).
+A non-zero disk partition can be used by adding (partition times 1000 hex)
+to
+.Ar  n .
+.Pp
+The boot procedure on the Micro
+.Tn VAX
+II
+is similar.
+A switch on the back panel sets the power-up action
+to autoboot or to halt.
+When halted, the processor may be booted using the same syntax
+as on the 11/750.
+.Pp
+The 11/750 boot procedure uses the boot roms to load block 0 off of
+the specified device.  The /usr/mdec directory contains a number
+of bootstrap programs for the various disks which should be placed
+in a new pack by
+.Xr disklabel 8 .
+Similarly, the Micro
+.Tn VAX
+II boot procedure loads a boot parameter block
+from block 0 of the disk.
+The
+.Xr rdboot
+.Dq bootstrap
+contains the correct parameters for an
+.Tn MSCP
+disk such
+as the RD53.
+.Pp
+On any processor, the 
+.Em boot
+program
+finds the corresponding file on the given device 
+.Pf ( Pa vmunix
+by default), loads that file
+into memory location zero, and starts the program at the entry address
+specified in the program header (after clearing off the high bit
+of the specified entry address).
+.Pp
+The file specifications used with
+.Dq BOOT ANY
+or
+.Dq \&B/3
+are of the form:
+.Pp
+.Dl device(adaptor,controller,unit,minor)
+.Pp
+where
+.Ar device
+is the type of the device to be searched,
+.Ar adaptor
+is the
+.Tn UNIBUS
+or
+.Tn MASSBUS
+number of the adaptor to which the device is attached,
+.Ar controller
+is the unit number of the controller or
+.Tn MASSBUS
+tape formatter on that adaptor,
+.Ar unit
+is the unit number of the disk or transport slave unit of the tape,
+and
+.Ar minor
+is the disk partition or tape file number.
+Leading adaptor or controller numbers default to 0.
+Normal line editing characters can be used when typing the file specification.
+The following list of supported devices may vary from installation to
+installation:
+.Pp
+.Bd -unfilled -offset indent -compact
+hp     MASSBUS disk drive
+up     UNIBUS storage module drive
+ht     TE16,TU45,TU77 on MASSBUS
+kra    storage module on a KDB50
+mt     TU78 on MASSBUS
+hk     RK07 on UNIBUS
+ra     storage module on a MSCP-compatible UNIBUS controller
+rb     storage module on a 730 IDC
+rl     RL02 on UNIBUS
+tm     TM11 emulation tape drives on UNIBUS
+tms    TMSCP-compatible tape
+ts     TS11 on UNIBUS
+ut     UNIBUS TU45 emulator
+.Ed
+.Pp
+For example,
+to boot from a file system which starts at cylinder 0
+of unit 0 of a
+.Tn MASSBUS
+disk, type
+.Ql hp(0,0)vmunix
+to the boot prompt;
+.Ql hp(2,0,1,0)vmunix
+would specify drive 1 on
+.Tn MASSBUS
+adaptor 2;
+.Ql up(0,0)vmunix
+would specify a
+.Tn UNIBUS
+drive,
+.Ql hk(0,0)vmunix
+would specify
+an RK07 disk drive,
+.Ql ra(1,0,0,0)vmunix
+would specify a
+.Tn UDA50
+disk drive on a second
+.Tn UNIBUS ,
+and
+.Ql rb(0,0)vmunix
+would specify a
+disk on a 730
+.Tn IDC .
+For tapes, the minor device number gives a file offset;
+.Ql mt(1,2,3,4)
+would specify the fifth file on slave 3 of the formatter
+at
+.Ql drive
+2 on mba 1.
+.Pp
+On an 11/750 with patchable control store,
+microcode patches will be installed by
+.Em boot
+if the file
+.Pa psc750.bin
+exists in the root of the filesystem from which the system is booted.
+.Pp
+In an emergency, the bootstrap methods described in the paper
+.%T Installing and Operating 4.3bsd
+can be used to boot from a distribution tape.
+.Sh FILES
+.Bl -tag -width /usr/mdec/xxboot -compact
+.It Pa /vmunix
+system code
+.It Pa /boot
+system bootstrap
+.It Pa /usr/mdec/xxboot
+sector-0 boot block for 750, xx is disk type
+.It Pa /usr/mdec/bootxx
+second-stage boot for 750, xx is disk type
+.It Pa /pcs750.bin
+microcode patch file on 750
+.El
+.Sh SEE ALSO
+.Xr arff 8 ,
+.Xr halt 8 ,
+.Xr reboot 8 ,
+.Xr shutdown 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/reboot.tproj/reboot.8 b/reboot.tproj/reboot.8
new file mode 100644 (file)
index 0000000..2fd2abb
--- /dev/null
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1990, 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.
+.\"
+.\"    @(#)reboot.8    8.1 (Berkeley) 6/9/93
+.\"
+.Dd June 9, 1993
+.Dt REBOOT 8
+.Os
+.Sh NAME
+.Nm reboot ,
+.Nm halt
+.Nd
+stopping and restarting the system
+.Sh SYNOPSIS
+.Nm halt
+.Op Fl nq
+.Nm reboot
+.Op Fl nq
+.Sh DESCRIPTION
+The
+.Nm halt
+and
+.Nm reboot
+utilities flush the file system cache to disk, send all running processes
+a SIGTERM (and subsequently a SIGKILL) and, respectively, halt or restart
+the system.
+The action is logged, including entering a shutdown record into the login
+accounting file.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl n
+If the
+.Fl n
+option is specified,
+the file system cache is not flushed.
+This option should probably not be used.
+.It Fl q
+If the
+.Fl q
+option is specified,
+the system is halted or restarted quickly and ungracefully, and only
+the flushing of the file system cache is performed.
+This option should probably not be used.
+.El
+.Pp
+Normally, the
+.Xr shutdown 8
+utility is used when the system needs to be halted or restarted, giving
+users advance warning of their impending doom.
+.Sh SEE ALSO
+.Xr sync 1 ,
+.Xr utmp 5 ,
+.Xr boot 8 ,
+.Xr shutdown 8
+.Sh HISTORY
+A
+.Nm reboot
+command appeared in
+.At v6 .
diff --git a/reboot.tproj/reboot.c b/reboot.tproj/reboot.c
new file mode 100644 (file)
index 0000000..93bb084
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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) 1980, 1986, 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.
+ */
+
+#include <sys/reboot.h>
+#include <signal.h>
+#include <pwd.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void err __P((const char *fmt, ...));
+void usage __P((void));
+
+int dohalt;
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register int i;
+       struct passwd *pw;
+       int ch, howto, lflag, nflag, qflag, sverrno;
+       char *p, *user;
+
+       if (!strcmp((p = rindex(*argv, '/')) ? p + 1 : *argv, "halt")) {
+               dohalt = 1;
+               howto = RB_HALT;
+       } else
+               howto = 0;
+       lflag = nflag = qflag = 0;
+       while ((ch = getopt(argc, argv, "lnq")) != EOF)
+               switch(ch) {
+               case 'l':               /* Undocumented; used by shutdown. */
+                       lflag = 1;
+                       break;
+               case 'n':
+                       nflag = 1;
+                       howto |= RB_NOSYNC;
+                       break;
+               case 'q':
+                       qflag = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (geteuid())
+               err("%s", strerror(EPERM));
+
+       if (qflag) {
+               reboot(howto);
+               err("%s", strerror(errno));
+       }
+
+       /* Log the reboot. */
+       if (!lflag)  {
+               if ((user = getlogin()) == NULL)
+                       user = (pw = getpwuid(getuid())) ?
+                           pw->pw_name : "???";
+               if (dohalt) {
+                       openlog("halt", 0, LOG_AUTH | LOG_CONS);
+                       syslog(LOG_CRIT, "halted by %s", user);
+               } else {
+                       openlog("reboot", 0, LOG_AUTH | LOG_CONS);
+                       syslog(LOG_CRIT, "rebooted by %s", user);
+               }
+       }
+       logwtmp("~", "shutdown", "");
+
+       /*
+        * Do a sync early on, so disks start transfers while we're off
+        * killing processes.  Don't worry about writes done before the
+        * processes die, the reboot system call syncs the disks.
+        */
+       if (!nflag)
+               sync();
+
+       /* Just stop init -- if we fail, we'll restart it. */
+       if (kill(1, SIGTSTP) == -1)
+               err("SIGTSTP init: %s", strerror(errno));
+
+       /* Ignore the SIGHUP we get when our parent shell dies. */
+       (void)signal(SIGHUP, SIG_IGN);
+
+#if 0
+       /* Send a SIGTERM first, a chance to save the buffers. */
+       if (kill(-1, SIGTERM) == -1)
+               err("SIGTERM processes: %s", strerror(errno));
+
+       /*
+        * After the processes receive the signal, start the rest of the
+        * buffers on their way.  Wait 5 seconds between the SIGTERM and
+        * the SIGKILL to give everybody a chance.
+        */
+       sleep(2);
+       if (!nflag)
+               sync();
+       sleep(3);
+
+       for (i = 1;; ++i) {
+               if (kill(-1, SIGKILL) == -1) {
+                       if (errno == ESRCH)
+                               break;
+                       goto restart;
+               }
+               if (i > 5) {
+                       (void)fprintf(stderr,
+                           "WARNING: some process(es) wouldn't die\n");
+                       break;
+               }
+               (void)sleep(2 * i);
+       }
+#endif
+       reboot(howto);
+       /* FALLTHROUGH */
+
+restart:
+       sverrno = errno;
+       err("%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
+           strerror(sverrno));
+       /* NOTREACHED */
+}
+
+void
+usage()
+{
+       (void)fprintf(stderr, "usage: %s [-nq]\n", dohalt ? "halt" : "reboot");
+       exit(1);
+}
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+void
+#if __STDC__
+err(const char *fmt, ...)
+#else
+err(fmt, va_alist)
+       char *fmt;
+        va_dcl
+#endif
+{
+       va_list ap;
+#if __STDC__
+       va_start(ap, fmt);
+#else
+       va_start(ap);
+#endif
+       (void)fprintf(stderr, "%s: ", dohalt ? "halt" : "reboot");
+       (void)vfprintf(stderr, fmt, ap);
+       va_end(ap);
+       (void)fprintf(stderr, "\n");
+       exit(1);
+       /* NOTREACHED */
+}
diff --git a/sc_usage.tproj/Makefile b/sc_usage.tproj/Makefile
new file mode 100644 (file)
index 0000000..6f57646
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# 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 = sc_usage
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = sc_usage.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sc_usage.1\
+            trace.codes
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+HEADER_PATHS = -I$(NEXT_ROOT)/System/Library/System.framework/\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders\
+               -I$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd\
+               -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd
+
+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/sc_usage.tproj/Makefile.postamble b/sc_usage.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..952893a
--- /dev/null
@@ -0,0 +1,108 @@
+###############################################################################
+#  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/man1
+       install -c -m 444 sc_usage.1 $(DSTROOT)/usr/share/man/man1/sc_usage.1
+
+after_install::
+       install -d $(DSTROOT)/usr/share/misc
+       install -c -m 444 trace.codes $(DSTROOT)/usr/share/misc
diff --git a/sc_usage.tproj/Makefile.preamble b/sc_usage.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..a4606c6
--- /dev/null
@@ -0,0 +1,140 @@
+###############################################################################
+#  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)
+
+AFTER_INSTALL += install-man-page
+
diff --git a/sc_usage.tproj/PB.project b/sc_usage.tproj/PB.project
new file mode 100644 (file)
index 0000000..0a8d16d
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        HEADERSEARCH = ("$(NEXT_ROOT)/System/Library/Frameworks/System.framework/PrivateHeaders/bsd"); 
+        OTHER_LINKED = (sc_usage.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, sc_usage.1, trace.codes); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_COMPILEROPTIONS = "-DKERNEL_PRIVATE"; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    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 = sc_usage; 
+    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/sc_usage.tproj/sc_usage.1 b/sc_usage.tproj/sc_usage.1
new file mode 100644 (file)
index 0000000..85c4907
--- /dev/null
@@ -0,0 +1,125 @@
+.\" Copyright (c) 2000, Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd March 28, 2000
+.Dt SC_USAGE 1
+.Os "Mac OS X"
+.Sh NAME
+.Nm sc_usage
+.Nd show system call usage statistics
+.Sh SYNOPSIS
+.Nm sc_usage
+.Op Fl c Ar codefile
+.Op Fl e
+.Op Fl l
+.Op Fl s Ar interval
+pid | cmd | -E execute
+.Sh DESCRIPTION
+.Nm sc_usage
+displays an ongoing sample of system call and
+page fault usage statistics for a given process,
+in a 'top' like fashion.
+.Pp
+Page faults can be of the following types:
+.Bl -tag -width CACHEHITTT -compact
+.It PAGE_IN
+page had to read from disk
+.It ZERO_FILL
+page was created and zero filled
+.It COW
+page was copied from another page
+.It CACHE_HIT
+page was found in the cache
+.El
+.Pp
+The arguments are as follows:
+.Bl -tag -width Ds
+.It Fl c
+When the
+.Fl c
+option is specified, it expects a path to a 
+.Ar codefile 
+that
+contains the mappings for the system calls.  This option
+overrides the default location of the system call codefile
+which is found in /usr/share/misc/trace.codes.
+.It Fl e
+Specifying the
+.Fl e
+option generates output that is sorted by call count.
+This overrides the default sort by time.
+.It Fl l
+The
+.Fl l
+option causes
+.Nm sc_usage
+to turn off it's continuous window updating style of
+output and instead output as a continuous scrolling
+of data.
+.It Fl s
+By default,
+.Nm sc_usage
+updates its output at one second intervals. This sampling
+interval may be changed by specifying the
+.Fl s
+option.  Enter the
+.Ar interval
+in seconds.
+.It  pid | cmd | -E execute
+The last argument must be a process id, a running command
+name, or using the -E option, an execution path followed
+by optional arguments.
+The system call usage data for the process or command
+is displayed.
+If the -E flag is used, sc_usage will launch the executable,
+pass along any optional arguments and display system call
+usage date for that executable.
+.El
+.Pp
+The data columns displayed are as follows:
+.Bl -tag -width LAST_PATHNAME_WAITED_FOR -compact
+.Pp
+.It TYPE
+the system call type
+.It NUMBER
+the system call count
+.It CPU_TIME
+the amount of cpu time consumed
+.It WAIT_TIME
+the absolute time the process is waiting
+.It CURRENT_TYPE
+the current system call type
+.It LAST_PATHNAME_WAITED_FOR
+for each active thread, the last pathname
+that was referenced by a system call that blocked
+.It CUR_WAIT_TIME
+the cumulative time that a thread has been blocked
+.It THRD#
+the thread number
+.It PRI
+current scheduling priority
+.El
+.Pp
+The
+.Nm sc_usage
+command also displays some global state in the first few lines of output,
+including the number of preemptions, context switches, threads, faults
+and system calls, found during the sampling period.  The current time
+and the elapsed time that the command has been running is also
+displayed here.
+The
+.Nm sc_usage
+command is also SIGWINCH savvy, so adjusting your window geometry may change
+the list of system calls being displayed.  Typing a 'q' will cause sc_usage to
+exit immediately.  Typing any other character will cause sc_usage to reset its
+counters and the display.
+.Sh SAMPLE USAGE
+.Pp
+sc_usage Finder -e -s2
+.Pp
+.Nm sc_usage
+will sort the Finder process usage data according to system call count
+and update the output at 2 second intervals.
+.Sh SEE ALSO
+.Xr top 1
+.Xr fs_usage 1
+.Xr latency 1
diff --git a/sc_usage.tproj/sc_usage.c b/sc_usage.tproj/sc_usage.c
new file mode 100644 (file)
index 0000000..86ed491
--- /dev/null
@@ -0,0 +1,1790 @@
+/*
+ * 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@
+ */
+
+/*
+cc -I. -DKERNEL_PRIVATE -O -o sc_usage sc_usage.c
+*/
+
+#define        Default_DELAY   1       /* default delay interval */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <nlist.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+
+#include <libc.h>
+#include <termios.h>
+#include <bsd/curses.h>
+
+#include <sys/ioctl.h>
+
+#ifndef KERNEL_PRIVATE
+#define KERNEL_PRIVATE
+#include <sys/kdebug.h>
+#undef KERNEL_PRIVATE
+#else
+#include <sys/kdebug.h>
+#endif /*KERNEL_PRIVATE*/
+
+#include <sys/sysctl.h>
+#include <errno.h>
+#import <mach/clock_types.h>
+#include <err.h>
+
+
+/* Number of lines of header information on the standard screen */
+#define        HEADER_LINES    5
+
+int    newLINES = 0;
+int    Header_lines = HEADER_LINES;
+
+int    how_to_sort = 0;
+int    no_screen_refresh = 0;
+int    execute_flag = 0;
+int    topn = 0;
+int    pid;
+int    called = 0;
+int    sort_now = 0;
+int    waiting_index = 0;
+FILE   *dfp = 0;  /*Debug output file */
+long   start_time = 0;
+
+#define SAMPLE_SIZE 20000
+
+#define DBG_ZERO_FILL_FAULT   1
+#define DBG_PAGEIN_FAULT      2
+#define DBG_COW_FAULT         3
+#define DBG_CACHE_HIT_FAULT   4
+
+#define MAX_SC 1024
+#define MAX_THREADS 16
+#define MAX_NESTED  8
+#define MAX_FAULTS  5
+
+
+char *state_name[] = {
+        "Dont Know",
+       "Running S",
+       "Running U",
+       "Waiting",
+       "Pre-empted",
+};
+
+#define DONT_KNOW   0
+#define KERNEL_MODE 1
+#define USER_MODE   2
+#define WAITING     3
+#define PREEMPTED   4
+
+typedef struct {
+        natural_t hi;
+        natural_t lo;
+} AbsoluteTime;
+
+
+struct entry {
+        int  sc_state;
+        int  type;
+        int  code;
+        double otime;
+        double stime;
+        double ctime;
+        double wtime;
+};
+
+struct th_info {
+        int  thread;
+        int  depth;
+        int  vfslookup;
+        int  curpri;
+        char pathname[32];
+        struct entry th_entry[MAX_NESTED];
+};
+
+struct sc_entry {
+        char name[32];
+        int  delta_count;
+        int  total_count;
+        int  waiting;
+        unsigned int stime_secs;
+        double       stime_usecs;
+        unsigned int wtime_secs;
+        double       wtime_usecs;
+        unsigned int delta_wtime_secs;
+        double       delta_wtime_usecs;
+};
+
+struct th_info th_state[MAX_THREADS];
+struct sc_entry faults[MAX_FAULTS];
+
+struct sc_entry *sc_tab;
+int  *msgcode_tab;
+int    msgcode_cnt;          /* number of MSG_ codes */
+
+int    num_of_threads = 0;
+int    now_collect_cpu_time = 0;
+
+unsigned int utime_secs;
+double       utime_usecs;
+
+int          in_idle = 0;
+unsigned int itime_secs;
+double       itime_usecs;
+unsigned int delta_itime_secs;
+double       delta_itime_usecs;
+double       idle_start;
+
+int          in_other = 0;
+unsigned int otime_secs;
+double       otime_usecs;
+unsigned int delta_otime_secs;
+double       delta_otime_usecs;
+double       other_start;
+
+int    max_sc = 0;
+int    bsc_base = 0;
+int    msc_base = 0;
+int    mach_sched = 0;
+int    mach_stkhandoff = 0;
+int    vfs_lookup = 0;
+int    mach_vmfault = 0;
+int    bsc_exit = 0;
+int    *sort_by_count;
+int    *sort_by_wtime;
+
+char   proc_name[32];
+
+#define DBG_FUNC_ALL   (DBG_FUNC_START | DBG_FUNC_END)
+#define DBG_FUNC_MASK  0xfffffffc
+
+int    preempted;
+int    csw;
+int    total_faults;
+int    scalls;
+
+/* Default divisor */
+#define DIVISOR 16.6666        /* Trace divisor converts to microseconds */
+double divisor = DIVISOR;
+
+struct termios tmode, omode;
+
+int mib[6];
+size_t needed;
+char  *my_buffer;
+
+kbufinfo_t bufinfo = {0, 0, 0, 0};
+
+int trace_enabled = 0;
+int set_remove_flag = 1;
+
+struct kinfo_proc *kp_buffer = 0;
+int kp_nentries = 0;
+
+extern char **environ;
+
+void set_enable();
+void set_pidcheck();
+void set_remove();
+void set_numbufs();
+void set_init();
+
+
+/*
+ *  signal handlers
+ */
+
+void leave()                   /* exit under normal conditions -- INT handler */
+{
+
+        if (no_screen_refresh == 0) {
+               move(LINES - 1, 0);
+               refresh();
+               endwin();
+
+               tcsetattr(0, TCSANOW, &omode);
+       }
+       set_enable(0);
+       set_pidcheck(pid, 0);
+       set_remove();
+       exit(0);
+}
+
+void err_leave(s)      /* exit under error conditions */
+char *s;
+{
+
+        if (no_screen_refresh == 0) {
+               move(LINES - 1, 0);
+               refresh();
+               endwin();
+
+               tcsetattr(0, TCSANOW, &omode);
+       }
+
+        printf("sc_usage: ");
+       if (s)
+               printf("%s ", s);
+
+       set_enable(0);
+       set_pidcheck(pid, 0);
+       set_remove();
+
+       exit(1);
+}
+
+void sigwinch()
+{
+        if (no_screen_refresh == 0)
+               newLINES = 1;
+}
+
+
+/* raw read of the timebase register */
+void clock_get_uptime(
+        AbsoluteTime    *result)
+{
+#ifdef __ppc__
+
+        natural_t       hi, lo, hic;
+
+        do {
+         asm volatile("  mftbu %0" : "=r" (hi));
+         asm volatile("  mftb %0" : "=r" (lo));
+         asm volatile("  mftbu %0" : "=r" (hic));
+        } while (hic != hi);
+
+        result->lo = lo;
+        result->hi = hi;
+#else
+        result->lo = 0;
+        result->hi = 0;
+#endif /* __ppc__ */
+}
+
+int
+exit_usage(myname) {
+
+        fprintf(stderr, "Usage: %s [-c codefile] [-e] [-l] [-sn] pid | cmd | -E execute path\n", myname);
+       fprintf(stderr, "  -c         name of codefile containing mappings for syscalls\n");
+       fprintf(stderr, "             Default is /usr/share/misc/trace.codes\n");
+       fprintf(stderr, "  -e         enable sort by call count\n");
+       fprintf(stderr, "  -l         turn off top style output\n");
+       fprintf(stderr, "  -sn        change sample rate to every n seconds\n");
+       fprintf(stderr, "  pid        selects process to sample\n");
+       fprintf(stderr, "  cmd        selects command to sample\n");
+       fprintf(stderr, "  -E         Execute the given path and optional arguments\n");
+
+       exit(1);
+}
+
+
+#define usec_to_1000ths(t)       ((t) / 1000)
+
+void print_time(char *p, unsigned int useconds, unsigned int seconds)
+{
+       long    minutes, hours;
+
+       minutes = seconds / 60;
+       hours = minutes / 60;
+
+       if (minutes < 100) { // up to 100 minutes
+               sprintf(p, "%2ld:%02ld.%03ld", minutes, seconds % 60,
+                       usec_to_1000ths(useconds));
+       }
+       else if (hours < 100) { // up to 100 hours
+               sprintf(p, "%2ld:%02ld:%02ld ", hours, minutes % 60,
+                               seconds % 60);
+       }
+       else {
+               sprintf(p, "%4ld hrs ", hours);
+       }
+}
+
+
+main(argc, argv)
+       int     argc;
+       char    *argv[];
+{
+       char    *myname   = "sc_usage";
+       char    *codefile = "/usr/share/misc/trace.codes";
+       char    ch;
+       char    *ptr;
+       int     delay = Default_DELAY;
+       int     length;
+        void screen_update();
+       void sort_scalls();
+       void sc_tab_init();
+       void getdivisor();
+       void reset_counters();
+       int argtopid();
+       int argtoi();
+       int quit();
+
+       if ( geteuid() != 0 ) {
+             printf("'sc_usage' must be run as root...\n");
+             exit(1);
+       }
+
+       /* get our name */
+       if (argc > 0) {
+               if ((myname = rindex(argv[0], '/')) == 0) {
+                       myname = argv[0];
+               }
+               else {
+                       myname++;
+               }
+       }
+
+       while ((ch = getopt(argc, argv, "c:els:d:E")) != EOF) {
+              switch(ch) {
+               case 's':
+                       delay = argtoi('s', "decimal number", optarg, 10);
+                       break;
+               case 'e':
+                       how_to_sort = 1;
+                       break;
+               case 'l':
+                       no_screen_refresh = 1;
+                       break;
+               case 'c':
+                       codefile = optarg;
+                       break;
+               case 'E':
+                       execute_flag = 1;
+                       break;
+               default:
+                 /*                    exit_usage(myname);*/
+                 exit_usage("default");
+              }
+       }
+       argc -= optind;
+       //argv += optind;
+
+       sc_tab_init(codefile);
+
+       if (argc)
+         {
+           if (!execute_flag)
+             {
+               /* parse a pid or a command */
+               if((pid = argtopid(argv[optind])) < 0 )
+                 exit_usage(myname);
+             }
+           else
+             { /* execute this command */
+
+               uid_t uid, euid;
+               gid_t gid, egid;
+               
+               ptr = strrchr(argv[optind], '/');
+               if (ptr)
+                 ptr++;
+               else
+                 ptr = argv[optind];
+
+               strncpy(proc_name, ptr, sizeof(proc_name)-1);
+               proc_name[sizeof(proc_name)-1] = '\0';
+
+               uid= getuid();
+               gid= getgid();
+               euid= geteuid();
+               egid= getegid();
+
+               seteuid(uid);
+               setegid(gid);
+
+               fprintf(stderr, "Starting program: %s\n", argv[optind]);
+               fflush(stdout);
+               fflush(stderr);
+               switch ((pid = vfork()))
+                 {
+                 case -1:
+                   perror("vfork: ");
+                   exit(1);
+                 case 0: /* child */
+                   setsid();
+                   ptrace(0,0,0,0); /* PT_TRACE_ME */
+                   execve(argv[optind], &argv[optind], environ);
+                   perror("execve:");
+                   exit(1);
+                 }
+
+               seteuid(euid);
+               setegid(egid);
+             }
+         }
+       else
+         {
+           exit_usage(myname);
+         }
+
+
+       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();
+               clear();
+               refresh();
+       }
+
+
+       /* set up signal handlers */
+       signal(SIGINT, leave);
+       signal(SIGQUIT, leave);
+       signal(SIGWINCH, sigwinch);
+
+        if (no_screen_refresh == 0)
+               topn = LINES - Header_lines;
+       else {
+               topn = 1024;
+               COLS = 80;
+       }
+       if ((my_buffer = malloc(SAMPLE_SIZE * sizeof(kd_buf))) == (char *)0)
+           quit("can't allocate memory for tracing info\n");
+
+       set_remove();
+       set_numbufs(SAMPLE_SIZE);
+       set_init();
+       set_pidcheck(pid, 1);
+       set_enable(1);
+       if (execute_flag)
+         ptrace(7, pid, 1, 0);  /* PT_CONTINUE */
+       getdivisor();
+
+       if (delay == 0)
+               delay = 1;
+       if ((sort_now = 10 / delay) < 2)
+               sort_now = 2;
+
+       (void)sort_scalls();
+       (void)screen_update();
+
+       /* main loop */
+
+       while (1) {
+               int     i;
+               int     cnt;
+               char    ibuf[128];
+               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;
+                               }
+                       } else
+                               usleep(100000);
+                       sample_sc();
+               }
+               (void)sort_scalls();
+
+               if (newLINES) {
+                       initscr();
+                       clear();
+                       refresh();
+
+                       topn = LINES - Header_lines;
+                       newLINES = 0;
+               }
+               (void)screen_update();
+       }
+}
+
+void
+print_row(struct sc_entry *se, int no_wtime) {
+       char    tbuf[256];
+       int     clen;
+
+       if (se->delta_count)
+               sprintf(tbuf, "%-23.23s    %8d(%d)", se->name, se->total_count, se->delta_count);
+       else
+               sprintf(tbuf, "%-23.23s    %8d", se->name, se->total_count);
+       clen = strlen(tbuf);
+
+       memset(&tbuf[clen], ' ', 45 - clen);
+
+       print_time(&tbuf[45], (unsigned long)(se->stime_usecs), se->stime_secs);
+       clen = strlen(tbuf);
+
+       if (no_wtime == 0 && (se->wtime_usecs || se->wtime_secs)) {
+               sprintf(&tbuf[clen], "  ");
+               clen += strlen(&tbuf[clen]);
+
+               print_time(&tbuf[clen], (unsigned long)(se->wtime_usecs), se->wtime_secs);
+               clen += strlen(&tbuf[clen]);
+
+               if (se->waiting || se->delta_wtime_usecs || se->delta_wtime_secs) {
+
+                       sprintf(&tbuf[clen], "(");
+                       clen += strlen(&tbuf[clen]);
+
+                       print_time(&tbuf[clen], (unsigned long)(se->delta_wtime_usecs),
+                                                               se->delta_wtime_secs);
+                       clen += strlen(&tbuf[clen]);
+
+                       sprintf(&tbuf[clen], ")");
+                       clen += strlen(&tbuf[clen]);
+
+                       if (se->waiting) {
+                               if (se->waiting == 1)
+                                       sprintf(&tbuf[clen], " W");
+                               else
+                                       sprintf(&tbuf[clen], " %d", se->waiting);
+                               clen += strlen(&tbuf[clen]);
+                       }
+               }
+       }
+       sprintf(&tbuf[clen], "\n");
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+}
+
+
+void screen_update()
+{
+        char    *p1, *p2, *p3;
+       char    tbuf[256];
+       int     clen;
+       int     n, i, rows;
+       long    curr_time;
+       long    elapsed_secs;
+       int     hours;
+       int     minutes;
+       struct  sc_entry *se;
+       int     output_lf;
+       int     max_rows;
+       struct th_info *ti;
+       
+       if (no_screen_refresh == 0) {
+               /* clear for new display */
+               erase();
+               move(0, 0);
+       }
+       rows = 0;
+
+       sprintf(tbuf, "%-14.14s", proc_name);
+       clen = strlen(tbuf);
+       
+       if (preempted == 1)
+               p1 = "preemption ";
+       else
+               p1 = "preemptions";
+       if (csw == 1)
+               p2 = "context switch  ";
+       else
+               p2 = "context switches";
+       if (num_of_threads == 1)
+               p3 = "thread ";
+       else
+               p3 = "threads";
+
+       sprintf(&tbuf[clen], " %4d %s %4d %s %4d %s",
+               preempted, p1, csw, p2, num_of_threads, p3);
+       clen += strlen(&tbuf[clen]);
+
+       /*
+        *  Display the current time.
+        *  "ctime" always returns a string that looks like this:
+        *  
+        *      Sun Sep 16 01:03:52 1973
+        *      012345678901234567890123
+        *                1         2
+        *
+        *  We want indices 11 thru 18 (length 8).
+        */
+       curr_time = time((long *)0);
+
+       if (start_time == 0)
+         start_time = curr_time;
+
+       elapsed_secs = curr_time - start_time;
+       minutes = elapsed_secs / 60;
+       hours = minutes / 60;
+
+       memset(&tbuf[clen], ' ', 78 - clen);
+
+       clen = 78 - 8;
+
+       sprintf(&tbuf[clen], "%-8.8s\n", &(ctime(&curr_time)[11]));
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+
+       if (total_faults == 1)
+               p1 = "fault ";
+       else
+               p1 = "faults";
+       if (scalls == 1)
+               p2 = "system call ";
+       else
+               p2 = "system calls";
+       sprintf(tbuf, "               %4d %s      %4d %s",
+               total_faults, p1, scalls, p2);
+
+       clen = strlen(tbuf);
+       sprintf(&tbuf[clen], "                    %3ld:%02ld:%02ld\n", 
+               hours, minutes % 60, elapsed_secs % 60);
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+
+
+
+       sprintf(tbuf, "\nTYPE                            NUMBER        CPU_TIME   WAIT_TIME\n");
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+
+       sprintf(tbuf, "------------------------------------------------------------------------------\n");
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+       rows = 0;
+
+
+
+       sprintf(tbuf, "System         Idle                                     ");
+       clen = strlen(tbuf);
+
+       print_time(&tbuf[clen], (unsigned long)(itime_usecs), itime_secs);
+       clen += strlen(&tbuf[clen]);
+
+       if (delta_itime_usecs || delta_itime_secs) {
+
+               sprintf(&tbuf[clen], "(");
+               clen += strlen(&tbuf[clen]);
+
+               print_time(&tbuf[clen], (unsigned long)(delta_itime_usecs), delta_itime_secs);
+               clen += strlen(&tbuf[clen]);
+
+               sprintf(&tbuf[clen], ")");
+               clen += strlen(&tbuf[clen]);
+       }
+        sprintf(&tbuf[clen], "\n");
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+       rows++;
+
+
+
+       sprintf(tbuf, "System         Busy                                     ");
+       clen = strlen(tbuf);
+
+       print_time(&tbuf[clen], (unsigned long)(otime_usecs), otime_secs);
+       clen += strlen(&tbuf[clen]);
+
+       if (delta_otime_usecs || delta_otime_secs) {
+
+               sprintf(&tbuf[clen], "(");      
+       clen += strlen(&tbuf[clen]);
+
+               print_time(&tbuf[clen], (unsigned long)(delta_otime_usecs), delta_otime_secs);
+               clen += strlen(&tbuf[clen]);
+
+               sprintf(&tbuf[clen], ")");
+               clen += strlen(&tbuf[clen]);
+       }
+        sprintf(&tbuf[clen], "\n");
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+       rows++;
+
+
+       sprintf(tbuf, "%-14.14s Usermode                      ", proc_name);
+       clen = strlen(tbuf);
+
+       print_time(&tbuf[clen], (unsigned long)(utime_usecs), utime_secs);
+       clen += strlen(&tbuf[clen]);
+        sprintf(&tbuf[clen], "\n");
+
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+       rows++;
+
+       if (num_of_threads)
+               max_rows = topn - (num_of_threads + 3);
+       else
+               max_rows = topn;
+
+       for (output_lf = 1, n = 1; rows < max_rows && n < MAX_FAULTS; n++) {
+               se = &faults[n];
+
+               if (se->total_count == 0)
+                       continue;
+               if (output_lf == 1) {
+                       sprintf(tbuf, "\n");
+                       if (no_screen_refresh)
+                               printf("%s", tbuf);
+                       else
+                               printw(tbuf);
+                       rows++;
+
+                       if (rows >= max_rows)
+                               break;
+                       output_lf = 0;
+               }
+               print_row(se, 0);
+               rows++;
+       }
+       sprintf(tbuf, "\n");
+
+       if (no_screen_refresh)
+               printf("%s", tbuf);
+       else
+               printw(tbuf);
+       rows++;
+
+       for (i = 0; rows < max_rows; i++) {
+               if (how_to_sort)
+                      n = sort_by_count[i];
+               else
+                      n = sort_by_wtime[i];
+               if (n == -1)
+                       break;
+               print_row(&sc_tab[n], 0);
+               rows++;
+       }
+       if (no_screen_refresh == 0) {
+               sprintf(tbuf, "\n");
+
+               while (rows++ < max_rows)
+                       printw(tbuf);
+       } else
+               printf("\n");
+
+       if (num_of_threads) {
+               sprintf(tbuf, "\nCURRENT_TYPE              LAST_PATHNAME_WAITED_FOR   CUR_WAIT_TIME  THRD#  PRI\n");
+
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (no_screen_refresh)
+                       printf("%s", tbuf);
+               else
+                       printw(tbuf);
+
+               sprintf(tbuf, "------------------------------------------------------------------------------\n");
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (no_screen_refresh)
+                       printf("%s", tbuf);
+               else
+                       printw(tbuf);
+       }
+       ti = &th_state[0];
+               
+       for (i = 0; i < num_of_threads; i++, ti++) {
+               struct entry *te;
+               unsigned long long now;
+               AbsoluteTime timestamp;
+               int      secs, time_secs, time_usecs;
+
+               clock_get_uptime(&timestamp);
+
+               now = (((unsigned long long)timestamp.hi) << 32) |
+                       (unsigned long long)((unsigned int)(timestamp.lo));
+
+               while (ti->thread == 0 && ti < &th_state[MAX_THREADS])
+                       ti++;
+               if (ti == &th_state[MAX_THREADS])
+                       break;
+
+               if (ti->depth) {
+                       te = &ti->th_entry[ti->depth - 1];
+
+                       if (te->sc_state == WAITING) {
+                               if (te->code)
+                                       sprintf(tbuf, "%-23.23s", sc_tab[te->code].name);
+                               else
+                                       sprintf(tbuf, "%-23.23s", "vm_fault");
+                       } else 
+                               sprintf(tbuf, "%-23.23s", state_name[te->sc_state]);
+               } else {
+                       te = &ti->th_entry[0];
+                       sprintf(tbuf, "%-23.23s", state_name[te->sc_state]);
+               }
+               clen = strlen(tbuf);
+               
+               sprintf(&tbuf[clen], "   %-28.28s  ", ti->pathname);
+
+               clen += strlen(&tbuf[clen]);
+
+               time_usecs = (unsigned long)(((double)now - te->otime) / divisor);
+               secs = time_usecs / 1000000;
+               time_usecs -= secs * 1000000;
+               time_secs = secs;
+
+               print_time(&tbuf[clen], time_usecs, time_secs);
+               clen += strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "      %2d  %3d\n", i, ti->curpri);
+
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (no_screen_refresh)
+                       printf("%s", tbuf);
+               else
+                       printw(tbuf);
+       }
+       if (no_screen_refresh == 0) {
+               move(0, 0);
+               refresh();
+       } else
+               printf("\n=================\n");
+
+
+
+       for (i = 0; i < (MAX_SC + msgcode_cnt); i++) {
+               if ((n = sort_by_count[i]) == -1)
+                       break;
+               sc_tab[n].delta_count = 0;
+               sc_tab[n].waiting = 0;
+               sc_tab[n].delta_wtime_usecs = 0;
+               sc_tab[n].delta_wtime_secs = 0;
+       }
+       for (i = 1; i < MAX_FAULTS; i++) {
+               faults[i].delta_count = 0;
+               faults[i].waiting = 0;
+               faults[i].delta_wtime_usecs = 0;
+               faults[i].delta_wtime_secs = 0;
+       }
+       preempted = 0;
+       csw = 0;
+       total_faults = 0;
+       scalls = 0;
+       delta_itime_secs = 0;
+       delta_itime_usecs = 0;
+       delta_otime_secs = 0;
+       delta_otime_usecs = 0;
+}
+
+void
+reset_counters() {
+        int   i;
+
+       for (i = 0; i < (MAX_SC + msgcode_cnt) ; i++) {
+               sc_tab[i].delta_count = 0;
+               sc_tab[i].total_count = 0;
+               sc_tab[i].waiting = 0;
+               sc_tab[i].delta_wtime_usecs = 0;
+               sc_tab[i].delta_wtime_secs = 0;
+               sc_tab[i].wtime_usecs = 0;
+               sc_tab[i].wtime_secs = 0;
+               sc_tab[i].stime_usecs = 0;
+               sc_tab[i].stime_secs = 0;
+       }
+       for (i = 1; i < MAX_FAULTS; i++) {
+               faults[i].delta_count = 0;
+               faults[i].total_count = 0;
+               faults[i].waiting = 0;
+               faults[i].delta_wtime_usecs = 0;
+               faults[i].delta_wtime_secs = 0;
+               faults[i].wtime_usecs = 0;
+               faults[i].wtime_secs = 0;
+               faults[i].stime_usecs = 0;
+               faults[i].stime_secs = 0;
+       }
+       preempted = 0;
+       csw = 0;
+       total_faults = 0;
+       scalls = 0;
+       called = 0;
+       
+       utime_secs = 0;
+       utime_usecs = 0;
+       itime_secs = 0;
+       itime_usecs = 0;
+       delta_itime_secs = 0;
+       delta_itime_usecs = 0;
+       otime_secs = 0;
+       otime_usecs = 0;
+       delta_otime_secs = 0;
+       delta_otime_usecs = 0;
+}
+
+void
+sc_tab_init(char *codefile) {
+        int  code;
+       int  n, cnt;
+       int msgcode_indx=0;
+       char name[56];
+        FILE *fp;
+       int quit();
+
+       if ((fp = fopen(codefile,"r")) == (FILE *)0) {
+               printf("Failed to open code description file %s\n", codefile);
+               exit(1);
+       }
+
+       n = fscanf(fp, "%d\n", &cnt);
+       if (n != 1)
+               return;
+
+       /* Count Mach message MSG_ codes */
+       for (msgcode_cnt=0;;) {
+               n = fscanf(fp, "%x%s\n", &code, &name[0]);
+               if (n != 2)
+                 break;
+               if (strncmp ("MSG_", &name[0], 4) == 0)
+                 msgcode_cnt++;
+               if (strcmp("USER_TEST", &name[0]) == 0)
+                       break;
+       }
+
+       sc_tab = (struct sc_entry *)malloc((MAX_SC+msgcode_cnt) * sizeof (struct sc_entry));
+        if(!sc_tab)
+           quit("can't allocate memory for system call table\n");
+       bzero(sc_tab,(MAX_SC+msgcode_cnt) * sizeof (struct sc_entry));
+
+       msgcode_tab = (int *)malloc(msgcode_cnt * sizeof(int));
+        if (!msgcode_tab)
+           quit("can't allocate memory for msgcode table\n");
+       bzero(msgcode_tab,(msgcode_cnt * sizeof(int)));
+
+       sort_by_count = (int *)malloc((MAX_SC + msgcode_cnt + 1) * sizeof(int));
+        if (!sort_by_count)
+           quit("can't allocate memory for sort_by_count table\n");
+       bzero(sort_by_count,(MAX_SC + msgcode_cnt + 1) * sizeof(int));
+
+       sort_by_wtime = (int *)malloc((MAX_SC + msgcode_cnt + 1) * sizeof(int));
+        if (!sort_by_wtime)
+           quit("can't allocate memory for sort_by_wtime table\n");
+       bzero(sort_by_wtime, (MAX_SC + msgcode_cnt + 1) * sizeof(int));
+
+
+       rewind(fp);
+
+       n = fscanf(fp, "%d\n", &cnt);
+
+       if (n != 1)
+               return;
+
+       for (;;) {
+               n = fscanf(fp, "%x%s\n", &code, &name[0]);
+
+               if (n != 2)
+                       break;
+
+               if (strcmp("MACH_vmfault", &name[0]) == 0) {
+                       mach_vmfault = code;
+                       continue;
+               }
+               if (strcmp("MACH_SCHED", &name[0]) == 0) {
+                       mach_sched = code;
+                       continue;
+               }
+               if (strcmp("MACH_STKHANDOFF", &name[0]) == 0) {
+                       mach_stkhandoff = code;
+                       continue;
+               }
+               if (strcmp("VFS_LOOKUP", &name[0]) == 0) {
+                       vfs_lookup = code;
+                       continue;
+               }
+               if (strcmp("BSC_SysCall", &name[0]) == 0) {
+                       bsc_base = code;
+                       continue;
+               }
+               if (strcmp("MACH_SysCall", &name[0]) == 0) {
+                       msc_base = code;
+                       continue;
+               }
+               if (strcmp("BSC_exit", &name[0]) == 0) {
+                       bsc_exit = code;
+                       continue;
+               }
+               if (strncmp("MSG_", &name[0], 4) == 0) {
+                       msgcode_tab[msgcode_indx] = ((code & 0x00ffffff) >>2);
+                       n = MAX_SC + msgcode_indx;
+                       strncpy(&sc_tab[n].name[0], &name[4], 31 );
+                       msgcode_indx++;
+                       continue;
+               }
+               if (strncmp("MSC_", &name[0], 4) == 0) {
+                       n = 512 + ((code>>2) & 0x1ff);
+                       strcpy(&sc_tab[n].name[0], &name[4]);
+                       continue;
+               }
+               if (strncmp("BSC_", &name[0], 4) == 0) {
+                       n = (code>>2) & 0x1ff;
+                       strcpy(&sc_tab[n].name[0], &name[4]);
+                       continue;
+               }
+               if (strcmp("USER_TEST", &name[0]) == 0)
+                       break;
+       }
+       strcpy(&faults[1].name[0], "zero_fill");
+       strcpy(&faults[2].name[0], "pagein");
+       strcpy(&faults[3].name[0], "copy_on_write");
+       strcpy(&faults[4].name[0], "cache_hit");
+}
+
+void
+find_proc_names()
+{
+       size_t                  bufSize = 0;
+       struct kinfo_proc       *kp;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROC;
+       mib[2] = KERN_PROC_ALL;
+       mib[3] = 0;
+
+       if (sysctl(mib, 4, NULL, &bufSize, NULL, 0) < 0)
+               quit("trace facility failure, KERN_PROC_ALL\n");
+
+       if((kp = (struct kinfo_proc *)malloc(bufSize)) == (struct kinfo_proc *)0)
+           quit("can't allocate memory for proc buffer\n");
+       
+       if (sysctl(mib, 4, kp, &bufSize, NULL, 0) < 0)
+               quit("trace facility failure, KERN_PROC_ALL\n");
+
+        kp_nentries = bufSize/ sizeof(struct kinfo_proc);
+       kp_buffer = kp;
+}
+
+struct th_info *find_thread(int thread) {
+       struct th_info *ti;
+
+       for (ti = th_state; ti < &th_state[MAX_THREADS]; ti++) {
+              if (ti->thread == thread)
+                      return(ti);
+       }
+       return ((struct th_info *)0);
+}
+
+
+int
+cmp_wtime(struct sc_entry *s1, struct sc_entry *s2) {
+
+        if (s1->wtime_secs < s2->wtime_secs)
+               return 0;
+        if (s1->wtime_secs > s2->wtime_secs)
+               return 1;
+        if (s1->wtime_usecs <= s2->wtime_usecs)
+               return 0;
+       return 1;
+}
+
+
+void
+sort_scalls() {
+        int  i, n, k, cnt, secs;
+       struct th_info *ti;
+       struct sc_entry *se;
+       struct entry *te;
+       unsigned long long now;
+       AbsoluteTime timestamp;
+
+       clock_get_uptime(&timestamp);
+
+       now = (((unsigned long long)timestamp.hi) << 32) |
+               (unsigned long long)((unsigned int)(timestamp.lo));
+
+       for (ti = th_state; ti < &th_state[MAX_THREADS]; ti++) {
+               if (ti->thread == 0)
+                       continue;
+
+               if (ti->depth) {
+                       te = &ti->th_entry[ti->depth-1];
+
+                       if (te->sc_state == WAITING) {
+                               if (te->code)
+                                       se = &sc_tab[te->code];
+                               else
+                                       se = &faults[DBG_PAGEIN_FAULT];
+                               se->waiting++;
+                               se->wtime_usecs += ((double)now - te->stime) / divisor;
+                               se->delta_wtime_usecs += ((double)now - te->stime) / divisor;
+                               te->stime = (double)now;
+
+                               secs = se->wtime_usecs / 1000000;
+                               se->wtime_usecs -= secs * 1000000;
+                               se->wtime_secs += secs;
+
+                               secs = se->delta_wtime_usecs / 1000000;
+                               se->delta_wtime_usecs -= secs * 1000000;
+                               se->delta_wtime_secs += secs;
+                       }
+               } else {
+                       te = &ti->th_entry[0];
+
+                       if (te->sc_state == PREEMPTED) {
+                               if ((unsigned long)(((double)now - te->otime) / divisor) > 5000000) {
+                                       ti->thread = 0;
+                                       ti->vfslookup = 0;
+                                       ti->pathname[0] = 0;
+                                       num_of_threads--;
+                               }
+                       }
+               }
+       }
+        if ((called % sort_now) == 0) {
+               sort_by_count[0] = -1;
+               sort_by_wtime[0] = -1;
+               for (cnt = 1, n = 1; n < (MAX_SC + msgcode_cnt); n++) {
+                       if (sc_tab[n].total_count) {
+                               for (i = 0; i < cnt; i++) {
+                                       if ((k = sort_by_count[i]) == -1 ||
+                                               sc_tab[n].total_count > sc_tab[k].total_count) {
+
+                                               for (k = cnt - 1; k >= i; k--)
+                                                       sort_by_count[k+1] = sort_by_count[k];
+                                               sort_by_count[i] = n;
+                                               break;
+                                       }
+                               }
+                               if (how_to_sort == 0) {
+                                       for (i = 0; i < cnt; i++) {
+                                               if ((k = sort_by_wtime[i]) == -1 ||
+                                                       cmp_wtime(&sc_tab[n], &sc_tab[k])) {
+
+                                                       for (k = cnt - 1; k >= i; k--)
+                                                               sort_by_wtime[k+1] = sort_by_wtime[k];
+                                                       sort_by_wtime[i] = n;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               cnt++;
+                       }
+               }
+       }
+       called++;
+}
+
+void
+set_enable(int val) 
+{
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDENABLE;         /* protocol */
+       mib[3] = val;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDENABLE\n");
+
+       if (val)
+         trace_enabled = 1;
+       else
+         trace_enabled = 0;
+}
+
+void
+set_numbufs(int nbufs) 
+{
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETBUF;
+       mib[3] = nbufs;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 4, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETBUF\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;                     /* no flags */
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+
+}
+
+void
+set_pidcheck(int pid, int on_off) 
+{
+        kd_regtype kr;
+
+       kr.type = KDBG_TYPENONE;
+       kr.value1 = pid;
+       kr.value2 = on_off;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDPIDTR;
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0) {
+               if (on_off == 1) { 
+                       printf("pid %d does not exist\n", pid);
+                       set_remove();
+                       exit(2);
+                }
+       }
+}
+
+void
+get_bufinfo(kbufinfo_t *val)
+{
+        needed = sizeof (*val);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDGETBUF;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 3, val, &needed, 0, 0) < 0)
+               quit("trace facility failure, KERN_KDGETBUF\n");
+
+}
+
+void
+set_remove() 
+{
+        extern int errno;
+
+        errno = 0;
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDREMOVE;         /* protocol */
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+         {
+           set_remove_flag = 0;
+
+           if (errno == EBUSY)
+               quit("the trace facility is currently in use...\n          fs_usage, sc_usage, and latency use this feature.\n\n");
+           else
+               quit("trace facility failure, KERN_KDREMOVE\n");
+         }
+}
+
+void
+set_init() 
+{       kd_regtype kr;
+
+       kr.type = KDBG_RANGETYPE;
+       kr.value1 = 0;
+       kr.value2 = -1;
+       needed = sizeof(kd_regtype);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETREG;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 3, &kr, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETREG\n");
+
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDSETUP;          
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 3, NULL, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDSETUP\n");
+
+}
+
+void
+sample_sc()
+{
+       kd_buf *kd;
+       int i, count;
+       int secs;
+       int find_msgcode();
+       
+        /* Get kernel buffer information */
+       get_bufinfo(&bufinfo);
+#ifdef OLD_KDEBUG
+       set_enable(0);
+#endif
+       needed = bufinfo.nkdbufs * sizeof(kd_buf);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_KDEBUG;
+       mib[2] = KERN_KDREADTR;         
+       mib[3] = 0;
+       mib[4] = 0;
+       mib[5] = 0;             /* no flags */
+       if (sysctl(mib, 3, my_buffer, &needed, NULL, 0) < 0)
+               quit("trace facility failure, KERN_KDREADTR\n");
+       count = needed;
+
+       if (bufinfo.flags & KDBG_WRAPPED) {
+               for (i = 0; i < MAX_THREADS; i++) {
+                       th_state[i].depth = 0;
+                       th_state[i].thread = 0;
+                       th_state[i].vfslookup = 0;
+                       th_state[i].pathname[0] = 0;
+               }
+               num_of_threads = 0;
+       }
+#ifdef OLD_KDEBUG
+       set_remove();
+       set_init();
+       set_pidcheck(pid, 1);
+       set_enable(1);          /* re-enable kernel logging */
+#endif
+       kd = (kd_buf *)my_buffer;
+
+       for (i = 0; i < count; i++) {
+               int debugid, baseid, thread;
+               int type, code;
+               unsigned long long now;
+               struct th_info *ti, *switched_out, *switched_in;
+               struct sc_entry *se;
+               struct entry *te;
+
+               thread  = kd[i].arg5 & KDBG_THREAD_MASK;
+               debugid = kd[i].debugid;
+               type    = kd[i].debugid & DBG_FUNC_MASK;
+
+               code = 0;
+               switched_out = (struct th_info *)0;
+               switched_in  = (struct th_info *)0;
+
+               now = (((unsigned long long)kd[i].timestamp.tv_sec) << 32) |
+                       (unsigned long long)((unsigned int)(kd[i].timestamp.tv_nsec));
+               baseid = debugid & 0xffff0000;
+
+               if (debugid == vfs_lookup) {
+                       long *sargptr;
+
+                       if ((ti = find_thread(thread)) == (struct th_info *)0)
+                               continue;
+                       if (ti->vfslookup == 1) {
+                               ti->vfslookup = 2;
+                               memset(&ti->pathname[0], 0, 32);
+                               sargptr = (long *)&ti->pathname[0];
+                               
+                               *sargptr++ = kd[i].arg2;
+                               *sargptr++ = kd[i].arg3;
+                               *sargptr++ = kd[i].arg4;
+
+                       } else if (ti->vfslookup == 2) {
+                               ti->vfslookup = 3;
+         
+                               sargptr = (long *)&ti->pathname[12];
+                               *sargptr++ = kd[i].arg1;
+                               *sargptr++ = kd[i].arg2;
+                               *sargptr++ = kd[i].arg3;
+                               *sargptr++ = kd[i].arg4;
+                       }
+                       continue;
+
+               } else if (baseid == bsc_base)
+                       code = (debugid >> 2) & 0x1ff;
+               else if (baseid == msc_base)
+                       code = 512 + ((debugid >> 2) & 0x1ff);
+               else if (baseid == mach_sched || baseid == mach_stkhandoff) {
+                       switched_out = find_thread(kd[i].arg1);
+                       switched_in  = find_thread(kd[i].arg2);
+
+                       if (in_idle) {
+                               itime_usecs += ((double)now - idle_start) / divisor;
+                               delta_itime_usecs += ((double)now - idle_start) / divisor;
+                               in_idle = 0;
+                       } else if (in_other) {
+                               otime_usecs += ((double)now - other_start) / divisor;
+                               delta_otime_usecs += ((double)now - other_start) / divisor;
+                               in_other = 0;
+                       }
+                       if ( !switched_in) {
+                               /*
+                                * not one of the target proc's threads
+                                */
+                               if (now_collect_cpu_time) {
+                                       if (kd[i].arg4 == 0) {
+                                               in_idle = 1;
+                                               idle_start = (double)now;
+                                       } else {
+                                               in_other = 1;
+                                               other_start = (double)now;
+                                       }
+                               }
+                       }
+                       if ( !switched_in && !switched_out)
+                               continue;
+
+               }
+               else if ((baseid & 0xff000000) == 0xff000000) {
+                       code = find_msgcode (debugid);
+                       if (!code)
+                         continue;
+               } else if (baseid != mach_vmfault)
+                       continue;
+
+               if (switched_out || switched_in) {
+                       if (switched_out) {
+                               ti = switched_out;
+                               ti->curpri = kd[i].arg3;
+
+                               if (ti->depth) {
+                                       te = &ti->th_entry[ti->depth-1];
+
+                                       if (te->sc_state == KERNEL_MODE)
+                                               te->ctime += (double)now - te->stime;
+                                       te->sc_state = WAITING; 
+
+                                       ti->vfslookup = 1;
+
+                               } else {
+                                       te = &ti->th_entry[0];
+
+                                       if (te->sc_state == USER_MODE)
+                                               utime_usecs += ((double)now - te->stime) / divisor;
+                                       te->sc_state = PREEMPTED;
+                                       preempted++;
+                               }
+                               te->stime = (double)now;
+                               te->otime = (double)now;
+                               now_collect_cpu_time = 1;
+                               csw++;
+                       }
+                       if (switched_in) {
+                               ti = switched_in;
+                               ti->curpri = kd[i].arg4;
+
+                               if (ti->depth) {
+                                       te = &ti->th_entry[ti->depth-1];
+
+                                       if (te->sc_state == WAITING)
+                                               te->wtime += (double)now - te->stime;
+                                       te->sc_state = KERNEL_MODE; 
+                               } else {
+                                       te = &ti->th_entry[0];
+
+                                       te->sc_state = USER_MODE;
+                               }
+                               te->stime = (double)now;
+                               te->otime = (double)now;
+                       }
+                       continue;
+               } 
+               if ((ti = find_thread(thread)) == (struct th_info *)0) {
+                       for (ti = &th_state[0]; ti < &th_state[MAX_THREADS]; ti++) {
+                               if (ti->thread == 0) {
+                                       ti->thread = thread;
+                                       num_of_threads++;
+                                       break;
+                               }
+                       }
+                       if (ti == &th_state[MAX_THREADS])
+                               continue;
+               }
+               if (debugid & DBG_FUNC_START) {
+                       ti->vfslookup = 0;
+
+                       if (ti->depth) {
+                               te = &ti->th_entry[ti->depth-1];
+
+                               if (te->sc_state == KERNEL_MODE)
+                                       te->ctime += (double)now - te->stime;
+                       } else {
+                               te = &ti->th_entry[0];
+
+                               if (te->sc_state == USER_MODE)
+                                       utime_usecs += ((double)now - te->stime) / divisor;
+                       }
+                       te->stime = (double)now;
+                       te->otime = (double)now;
+
+                       if (ti->depth < MAX_NESTED) {
+                               te = &ti->th_entry[ti->depth];
+
+                               te->sc_state = KERNEL_MODE;
+                               te->type = type;
+                               te->code = code;
+                               te->stime = (double)now;
+                               te->otime = (double)now;
+                               te->ctime = (double)0;
+                               te->wtime = (double)0;
+                               ti->depth++;
+                       }
+
+               } else if (debugid & DBG_FUNC_END) {
+                       if (code) {
+                               se = &sc_tab[code];
+                               scalls++;
+                       } else {
+                               se = &faults[kd[i].arg2];
+                               total_faults++;
+                       }
+                       if (se->total_count == 0)
+                               called = 0;
+                       se->delta_count++;
+                       se->total_count++;
+
+                       if (ti->depth) {
+                               te = &ti->th_entry[ti->depth-1];
+
+                               if (te->type == type) {
+                                       se->stime_usecs += te->ctime / divisor;
+                                       se->stime_usecs += ((double)now - te->stime) / divisor;
+
+                                       se->wtime_usecs += te->wtime / divisor;
+                                       se->delta_wtime_usecs += te->wtime / divisor;
+
+                                       secs = se->stime_usecs / 1000000;
+                                       se->stime_usecs -= secs * 1000000;
+                                       se->stime_secs += secs;
+
+                                       secs = se->wtime_usecs / 1000000;
+                                       se->wtime_usecs -= secs * 1000000;
+                                       se->wtime_secs += secs;
+
+                                       secs = se->delta_wtime_usecs / 1000000;
+                                       se->delta_wtime_usecs -= secs * 1000000;
+                                       se->delta_wtime_secs += secs;
+
+                                       ti->depth--;
+
+                                       if (ti->depth == 0) {
+                                               /* 
+                                                * headed back to user mode
+                                                * start the time accumulation
+                                                */
+                                               te = &ti->th_entry[0];
+                                               te->sc_state = USER_MODE;
+                                       } else
+                                               te = &ti->th_entry[ti->depth-1];
+
+                                       te->stime = (double)now;
+                                       te->otime = (double)now;
+                               }
+                       }
+               }
+       }
+       secs = utime_usecs / 1000000;
+       utime_usecs -= secs * 1000000;
+       utime_secs += secs;
+
+       secs = itime_usecs / 1000000;
+       itime_usecs -= secs * 1000000;
+       itime_secs += secs;
+
+       secs = delta_itime_usecs / 1000000;
+       delta_itime_usecs -= secs * 1000000;
+       delta_itime_secs += secs;
+
+       secs = otime_usecs / 1000000;
+       otime_usecs -= secs * 1000000;
+       otime_secs += secs;
+
+       secs = delta_otime_usecs / 1000000;
+       delta_otime_usecs -= secs * 1000000;
+       delta_otime_secs += secs;
+}
+
+
+quit(s)
+char *s;
+{
+        if (trace_enabled)
+               set_enable(0);
+
+       /* 
+          This flag is turned off when calling
+          quit() due to a set_remove() failure.
+       */
+       if (set_remove_flag)
+               set_remove();
+
+        printf("sc_usage: ");
+       if (s)
+               printf("%s ", s);
+
+       exit(1);
+}
+
+
+void getdivisor()
+{
+
+    unsigned int delta;
+    unsigned int abs_to_ns_num;
+    unsigned int abs_to_ns_denom;
+    unsigned int proc_to_abs_num;
+    unsigned int proc_to_abs_denom;
+
+    MKGetTimeBaseInfo (&delta, &abs_to_ns_num, &abs_to_ns_denom,
+                      &proc_to_abs_num,  &proc_to_abs_denom);
+
+    divisor = ((double)abs_to_ns_denom / (double)abs_to_ns_num) * 1000;
+}
+
+
+argtopid(str)
+        char *str;
+{
+        char *cp;
+        int ret;
+       int i;
+
+       if (!kp_buffer)
+               find_proc_names();
+
+        ret = (int)strtol(str, &cp, 10);
+        if (cp == str || *cp) {
+         /* Assume this is a command string and find first matching pid */
+               for (i=0; i < kp_nentries; i++) {
+                     if(kp_buffer[i].kp_proc.p_stat == 0)
+                         continue;
+                     else {
+                         if(!strcmp(str, kp_buffer[i].kp_proc.p_comm))
+                           {
+                             strncpy(proc_name, kp_buffer[i].kp_proc.p_comm, sizeof(proc_name)-1);
+                             proc_name[sizeof(proc_name)-1] = '\0';
+                             return(kp_buffer[i].kp_proc.p_pid);
+                           }
+                     }
+               }
+       }
+       else
+         {
+           for (i=0; i < kp_nentries; i++)
+             {
+               if(kp_buffer[i].kp_proc.p_stat == 0)
+                 continue;
+               else if (kp_buffer[i].kp_proc.p_pid == ret) {
+                   strncpy(proc_name, kp_buffer[i].kp_proc.p_comm, sizeof(proc_name)-1);
+                   proc_name[sizeof(proc_name)-1] = '\0';
+                   return(kp_buffer[i].kp_proc.p_pid);               
+               }
+             }
+         }
+        return(-1);
+}
+
+
+/* Returns index into sc_tab for a mach msg entry */
+int
+find_msgcode(int debugid)
+{
+
+  int indx;
+
+  for (indx=0; indx< msgcode_cnt; indx++)
+    {
+      if (msgcode_tab[indx] == ((debugid & 0x00ffffff) >>2))
+         return (MAX_SC+indx);
+    }
+  return (0);
+}
+  
+argtoi(flag, req, str, base)
+       int flag;
+       char *req, *str;
+       int base;
+{
+       char *cp;
+       int ret;
+
+       ret = (int)strtol(str, &cp, base);
+       if (cp == str || *cp)
+               errx(EINVAL, "-%c flag requires a %s", flag, req);
+       return (ret);
+}
+
diff --git a/sc_usage.tproj/trace.codes b/sc_usage.tproj/trace.codes
new file mode 100644 (file)
index 0000000..8a46599
--- /dev/null
@@ -0,0 +1,774 @@
+772
+0xff000104     MSG_mach_notify_port_deleted
+0xff000114     MSG_mach_notify_port_destroyed
+0xff000118     MSG_mach_notify_no_senders
+0xff00011c     MSG_mach_notify_send_once
+0xff000120     MSG_mach_notify_dead_name
+0xff000320     MSG_host_info
+0xff000324     MSG_host_kernel_version
+0xff000328     MSG_host_page_size
+0xff00032c     MSG_mach_memory_object_memory_entry
+0xff000330     MSG_host_processor_info
+0xff000334     MSG_host_get_io_master
+0xff000338     MSG_host_get_clock_service
+0xff00033c     MSG_kmod_get_info
+0xff000340     MSG_host_zone_info
+0xff000344     MSG_host_virtual_physical_table_info
+0xff000348     MSG_host_ipc_hash_info
+0xff00034c     MSG_enable_bluebox
+0xff000350     MSG_disable_bluebox
+0xff000354     MSG_processor_set_default
+0xff000358     MSG_processor_set_create
+0xff00035c     MSG_mach_memory_object_memory_entry_64
+0xff000360     MSG_host_statistics
+0xff000640     MSG_host_get_boot_info
+0xff000644     MSG_host_reboot
+0xff000648     MSG_host_priv_statistics
+0xff00064c     MSG_host_default_memory_manager
+0xff000650     MSG_vm_wire
+0xff000654     MSG_thread_wire
+0xff000658     MSG_vm_allocate_cpm
+0xff00065c     MSG_host_processors
+0xff000660     MSG_host_get_clock_control
+0xff000664     MSG_kmod_create
+0xff000668     MSG_kmod_destroy
+0xff00066c     MSG_kmod_control
+0xff000670     MSG_host_get_special_port
+0xff000674     MSG_host_set_special_port
+0xff000678     MSG_host_set_exception_ports
+0xff00067c     MSG_host_get_exception_ports
+0xff000680     MSG_host_swap_exception_ports
+0xff000684     MSG_host_load_symbol_table
+0xff000688     MSG_task_swappable
+0xff00068c     MSG_host_processor_sets
+0xff000690     MSG_host_processor_set_priv
+0xff000694     MSG_set_dp_control_port
+0xff000698     MSG_get_dp_control_port
+0xff00069c     MSG_host_set_UNDServer
+0xff0006a0     MSG_host_get_UNDServer
+0xff000960     MSG_host_security_create_task_token
+0xff000964     MSG_host_security_set_task_token
+0xff000fa0     MSG_clock_get_time
+0xff000fa4     MSG_clock_get_attributes
+0xff000fa8     MSG_clock_alarm
+0xff0012c0     MSG_clock_set_time
+0xff0012c4     MSG_clock_set_attributes
+0xff001f40     MSG_memory_object_get_attributes
+0xff001f44     MSG_memory_object_change_attributes
+0xff001f48     MSG_memory_object_synchronize_completed
+0xff001f50     MSG_memory_object_lock_request
+0xff001f58     MSG_memory_object_destroy
+0xff001f64     MSG_vm_object_upl_request
+0xff001f68     MSG_vm_pager_upl_request
+0xff001f6c     MSG_vm_upl_map
+0xff001f70     MSG_vm_upl_unmap
+0xff001f74     MSG_vm_upl_abort
+0xff001f78     MSG_vm_upl_commit
+0xff001f7c     MSG_vm_upl_commit_range
+0xff002008     MSG_vm_object_upl_request
+0xff00200c     MSG_vm_pager_upl_request
+0xff002010     MSG_vm_upl_abort
+0xff002014     MSG_vm_upl_abort_range
+0xff002018     MSG_vm_upl_commit
+0xff00201c     MSG_vm_upl_commit_range
+0xff002260     MSG_memory_object_init
+0xff002264     MSG_memory_object_terminate
+0xff002268     MSG_memory_object_data_request
+0xff00226c     MSG_memory_object_data_unlock
+0xff002270     MSG_memory_object_lock_completed
+0xff002278     MSG_memory_object_data_return
+0xff00227c     MSG_memory_object_synchronize
+0xff002280     MSG_memory_object_change_completed
+0xff002328     MSG_memory_object_create
+0xff00232c     MSG_memory_object_data_initialize
+0xff00238c     MSG_default_pager_object_create
+0xff002390     MSG_default_pager_info
+0xff002394     MSG_default_pager_objects
+0xff002398     MSG_default_pager_object_pages
+0xff0023a0     MSG_default_pager_backing_store_create
+0xff0023a4     MSG_default_pager_backing_store_delete
+0xff0023a8     MSG_default_pager_backing_store_info
+0xff0023ac     MSG_default_pager_add_file
+0xff0023b0     MSG_default_pager_triggers
+0xff0023dc     MSG_default_pager_space_alert
+0xff002584     MSG_exception_raise
+0xff002588     MSG_exception_raise_state
+0xff00258c     MSG_exception_raise_state_identity
+0xff002bc0     MSG_io_object_get_class
+0xff002bc4     MSG_io_object_conforms_to
+0xff002bc8     MSG_io_iterator_next
+0xff002bcc     MSG_io_iterator_reset
+0xff002bd0     MSG_io_service_get_matching_services
+0xff002bd4     MSG_io_service_add_notification_old
+0xff002bd8     MSG_io_registry_create_iterator
+0xff002bdc     MSG_io_registry_iterator_enter_entry
+0xff002be0     MSG_io_registry_iterator_exit_entry
+0xff002be4     MSG_io_registry_entry_from_path
+0xff002be8     MSG_io_registry_entry_get_name
+0xff002bec     MSG_io_registry_entry_get_properties
+0xff002bf0     MSG_io_registry_entry_get_property
+0xff002bf4     MSG_io_registry_entry_get_child_iterator
+0xff002bf8     MSG_io_registry_entry_get_parent_iterator
+0xff002bfc     MSG_io_service_open
+0xff002c00     MSG_io_service_close
+0xff002c04     MSG_io_connect_get_service
+0xff002c08     MSG_io_connect_set_notification_port
+0xff002c0c     MSG_io_connect_map_memory
+0xff002c10     MSG_io_connect_add_client
+0xff002c14     MSG_io_connect_set_properties
+0xff002c18     MSG_io_connect_method_scalarI_scalarO
+0xff002c1c     MSG_io_connect_method_scalarI_structureO
+0xff002c20     MSG_io_connect_method_scalarI_structureI
+0xff002c24     MSG_io_connect_method_structureI_structureO
+0xff002c28     MSG_io_registry_entry_get_path
+0xff002c2c     MSG_io_registry_get_root_entry
+0xff002c30     MSG_io_registry_entry_set_properties
+0xff002c34     MSG_io_registry_entry_in_plane
+0xff002c38     MSG_io_object_get_retain_count
+0xff002c3c     MSG_io_service_get_busy_state
+0xff002c40     MSG_io_service_wait_quiet
+0xff002c44     MSG_io_registry_entry_create_iterator
+0xff002c48     MSG_io_iterator_is_valid
+0xff002c4c     MSG_io_make_matching
+0xff002c50     MSG_io_catalog_send_data
+0xff002c54     MSG_io_catalog_terminate
+0xff002c58     MSG_io_catalog_get_data
+0xff002c5c     MSG_io_catalog_get_gen_count
+0xff002c60     MSG_io_catalog_module_loaded
+0xff002c64     MSG_io_catalog_reset
+0xff002c68     MSG_io_service_request_probe
+0xff002c6c     MSG_io_registry_entry_get_name_in_plane
+0xff002c70     MSG_io_service_match_property_table
+0xff002c74     MSG_io_async_method_scalarI_scalarO
+0xff002c78     MSG_io_async_method_scalarI_structureO
+0xff002c7c     MSG_io_async_method_scalarI_structureI
+0xff002c80     MSG_io_async_method_structureI_structureO
+0xff002c84     MSG_io_service_add_notification
+0xff002c88     MSG_io_service_add_interest_notification
+0xff002c8c     MSG_io_service_acknowledge_notification
+0xff002c90     MSG_io_connect_get_notification_semaphore
+0xff002c94     MSG_io_connect_unmap_memory
+0xff002ee0     MSG_processor_start
+0xff002ee4     MSG_processor_exit
+0xff002ee8     MSG_processor_info
+0xff002eec     MSG_processor_control
+0xff002ef0     MSG_processor_assign
+0xff002ef4     MSG_processor_get_assignment
+0xff003200     MSG_mach_port_names
+0xff003204     MSG_mach_port_type
+0xff003208     MSG_mach_port_rename
+0xff00320c     MSG_mach_port_allocate_name
+0xff003210     MSG_mach_port_allocate
+0xff003214     MSG_mach_port_destroy
+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
+0xff003234     MSG_mach_port_request_notification
+0xff003238     MSG_mach_port_insert_right
+0xff00323c     MSG_mach_port_extract_right
+0xff003240     MSG_mach_port_set_seqno
+0xff003244     MSG_mach_port_get_attributes
+0xff003248     MSG_mach_port_set_attributes
+0xff00324c     MSG_mach_port_allocate_qos
+0xff003250     MSG_mach_port_allocate_full
+0xff003254     MSG_task_set_port_space
+0xff003258     MSG_mach_port_get_srights
+0xff00325c     MSG_mach_port_space_info
+0xff003260     MSG_mach_port_dnrequest_info
+0xff003264     MSG_mach_port_kernel_object
+0xff003268     MSG_mach_port_insert_member
+0xff00326c     MSG_mach_port_extract_member
+0xff003520     MSG_task_create
+0xff003524     MSG_task_terminate
+0xff003528     MSG_task_threads
+0xff00352c     MSG_mach_ports_register
+0xff003530     MSG_mach_ports_lookup
+0xff003534     MSG_task_info
+0xff003538     MSG_task_set_info
+0xff00353c     MSG_task_suspend
+0xff003540     MSG_task_resume
+0xff003544     MSG_task_get_special_port
+0xff003548     MSG_task_set_special_port
+0xff00354c     MSG_thread_create
+0xff003550     MSG_thread_create_running
+0xff003554     MSG_task_set_exception_ports
+0xff003558     MSG_task_get_exception_ports
+0xff00355c     MSG_task_swap_exception_ports
+0xff003560     MSG_lock_set_create
+0xff003564     MSG_lock_set_destroy
+0xff003568     MSG_semaphore_create
+0xff00356c     MSG_semaphore_destroy
+0xff003570     MSG_task_policy_set
+0xff003574     MSG_task_policy_get
+0xff003578     MSG_task_sample
+0xff00357c     MSG_task_policy
+0xff003580     MSG_task_set_emulation
+0xff003584     MSG_task_get_emulation_vector
+0xff003588     MSG_task_set_emulation_vector
+0xff00358c     MSG_task_set_ras_pc
+0xff003590     MSG_kernel_task_create
+0xff003594     MSG_task_assign
+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
+0xff00384c     MSG_thread_get_state
+0xff003850     MSG_thread_set_state
+0xff003854     MSG_thread_suspend
+0xff003858     MSG_thread_resume
+0xff00385c     MSG_thread_abort
+0xff003860     MSG_thread_abort_safely
+0xff003864     MSG_thread_depress_abort
+0xff003868     MSG_thread_get_special_port
+0xff00386c     MSG_thread_set_special_port
+0xff003870     MSG_thread_info
+0xff003874     MSG_thread_set_exception_ports
+0xff003878     MSG_thread_get_exception_ports
+0xff00387c     MSG_thread_swap_exception_ports
+0xff003880     MSG_thread_policy
+0xff003884     MSG_thread_policy_set
+0xff003888     MSG_thread_policy_get
+0xff00388c     MSG_thread_sample
+0xff003890     MSG_etap_trace_thread
+0xff003894     MSG_thread_assign
+0xff003898     MSG_thread_assign_default
+0xff00389c     MSG_thread_get_assignment
+0xff0038a0     MSG_thread_set_policy
+0xff003b60     MSG_vm_region
+0xff003b64     MSG_vm_allocate
+0xff003b68     MSG_vm_deallocate
+0xff003b6c     MSG_vm_protect
+0xff003b70     MSG_vm_inherit
+0xff003b74     MSG_vm_read
+0xff003b78     MSG_vm_read_list
+0xff003b7c     MSG_vm_write
+0xff003b80     MSG_vm_copy
+0xff003b84     MSG_vm_read_overwrite
+0xff003b88     MSG_vm_msync
+0xff003b8c     MSG_vm_behavior_set
+0xff003b90     MSG_vm_map
+0xff003b94     MSG_vm_machine_attribute
+0xff003b98     MSG_vm_remap
+0xff003b9c     MSG_task_wire
+0xff003ba0     MSG_mach_make_memory_entry
+0xff003ba4     MSG_vm_map_page_query
+0xff003ba8     MSG_mach_vm_region_info
+0xff003bac     MSG_vm_mapped_pages_info
+0xff003bb0     MSG_vm_region_object_create
+0xff003bb4     MSG_vm_region_recurse
+0xff003bb8     MSG_vm_region_recurse_64
+0xff003bbc     MSG_mach_vm_region_info_64
+0xff003bc0     MSG_vm_region_64
+0xff003bc4     MSG_mach_make_memory_entry_64
+0xff003bc8     MSG_vm_map_64
+0xff003e80     MSG_processor_set_statistics
+0xff003e84     MSG_processor_set_destroy
+0xff003e88     MSG_processor_set_max_priority
+0xff003e8c     MSG_processor_set_policy_enable
+0xff003e90     MSG_processor_set_policy_disable
+0xff003e94     MSG_processor_set_tasks
+0xff003e98     MSG_processor_set_threads
+0xff003e9c     MSG_processor_set_policy_control
+0xff003ea0     MSG_processor_set_stack_usage
+0xff003ea4     MSG_processor_set_info
+0xff004e20     MSG_ledger_create
+0xff004e24     MSG_ledger_terminate
+0xff004e28     MSG_ledger_transfer
+0xff004e2c     MSG_ledger_read
+0xff005dc0     MSG_UNDExecute_rpc
+0xff005dc4     MSG_UNDDisplayNoticeFromBundle_rpc
+0xff005dc8     MSG_UNDDisplayAlertFromBundle_rpc
+0xff005dcc     MSG_UNDDisplayCustomFromBundle_rpc
+0xff005dd0     MSG_UNDDisplayCustomFromDictionary_rpc
+0xff005dd4     MSG_UNDCancelNotification_rpc
+0xff005dd8     MSG_UNDDisplayNoticeSimple_rpc
+0xff005ddc     MSG_UNDDisplayAlertSimple_rpc
+0xff0060e0     MSG_UNDAlertCompletedWithResult_rpc
+0xff0060e4     MSG_UNDNotificationCreated_rpc
+0xff25a8a0     MSG_lock_acquire
+0xff25a8a4     MSG_lock_release
+0xff25a8a8     MSG_lock_try
+0xff25a8ac     MSG_lock_make_stable
+0xff25a8b0     MSG_lock_handoff
+0xff25a8b4     MSG_lock_handoff_accept
+0xff3d0904     MSG_bootstrap_ports
+0xff3d0908     MSG_bootstrap_arguments
+0xff3d090c     MSG_bootstrap_environment
+0xff3d0910     MSG_bootstrap_completed
+0x1300000      MACH_vmfault
+0x1400000      MACH_SCHED
+0x1400008      MACH_STKHANDOFF
+0x1500000      MACH_MSGID_INVALID
+0x1090000      DecrTrap
+0x1090004      DecrSet
+0x10c0000      MACH_SysCall
+0x10c0004      MSC_kern_invalid_#1
+0x10c0008      MSC_kern_invalid_#2
+0x10c000c      MSC_kern_invalid_#3
+0x10c0010      MSC_kern_invalid_#4
+0x10c0014      MSC_kern_invalid_#5
+0x10c0018      MSC_kern_invalid_#6
+0x10c001c      MSC_kern_invalid_#7
+0x10c0020      MSC_kern_invalid_#8
+0x10c0024      MSC_kern_invalid_#9
+0x10c0028      MSC_kern_invalid_#10
+0x10c002c      MSC_kern_invalid_#11
+0x10c0030      MSC_kern_invalid_#12
+0x10c0034      MSC_kern_invalid_#13
+0x10c0038      MSC_kern_invalid_#14
+0x10c003c      MSC_kern_invalid_#15
+0x10c0040      MSC_kern_invalid_#16
+0x10c0044      MSC_kern_invalid_#17
+0x10c0048      MSC_kern_invalid_#18
+0x10c004c      MSC_kern_invalid_#19
+0x10c0050      MSC_kern_invalid_#20
+0x10c0054      MSC_kern_invalid_#21
+0x10c0058      MSC_kern_invalid_#22
+0x10c005c      MSC_kern_invalid_#23
+0x10c0060      MSC_kern_invalid_#24
+0x10c0064      MSC_kern_invalid_#25
+0x10c0068      MSC_mach_reply_port
+0x10c006c      MSC_thread_self_trap
+0x10c0070      MSC_task_self_trap
+0x10c0074      MSC_host_self_trap
+0x10c0078      MSC_kern_invalid_#30
+0x10c007c      MSC_kern_invalid_#31
+0x10c0080      MSC_mach_msg_overwrite_trap
+0x10c0084      MSC_semaphore_signal_trap
+0x10c0088      MSC_semaphore_signal_all_trap
+0x10c008c      MSC_semaphore_signal_thread_trap
+0x10c0090      MSC_semaphore_wait_trap
+0x10c0094      MSC_semaphore_wait_signal_trap
+0x10c0098      MSC_semaphore_timedwait_trap
+0x10c009c      MSC_semaphore_timedwait_signal_trap
+0x10c00a0      MSC_kern_invalid_#40
+0x10c00a4      MSC_init_process
+0x10c00a8      MSC_kern_invalid_#42
+0x10c00ac      MSC_map_fd
+0x10c00b0      MSC_kern_invalid_#44
+0x10c00b4      MSC_task_for_pid
+0x10c00b8      MSC_pid_for_task
+0x10c00bc      MSC_kern_invalid_#47
+0x10c00c0      MSC_macx_swapon
+0x10c00c4      MSC_macx_swapoff
+0x10c00c8      MSC_kern_invalid_#50
+0x10c00cc      MSC_macx_triggers
+0x10c00d0      MSC_kern_invalid_#52
+0x10c00d4      MSC_kern_invalid_#53
+0x10c00d8      MSC_kern_invalid_#54
+0x10c00dc      MSC_kern_invalid_#55
+0x10c00e0      MSC_kern_invalid_#56
+0x10c00e4      MSC_kern_invalid_#57
+0x10c00e8      MSC_kern_invalid_#58
+0x10c00ec      MSC_swtch_pri
+0x10c00f0      MSC_swtch
+0x10c00f4      MSC_thread_switch
+0x10c00f8      MSC_clock_sleep_trap
+0x10c00fc      MSC_kern_invalid_#63
+0x10c0100      MSC_kern_invalid_#64
+0x10c0104      MSC_kern_invalid_#65
+0x10c0108      MSC_kern_invalid_#66
+0x10c010c      MSC_kern_invalid_#67
+0x10c0110      MSC_kern_invalid_#68
+0x10c0114      MSC_kern_invalid_#69
+0x10c0118      MSC_kern_invalid_#70
+0x10c011c      MSC_kern_invalid_#71
+0x10c0120      MSC_kern_invalid_#72
+0x10c0124      MSC_kern_invalid_#73
+0x10c0128      MSC_kern_invalid_#74
+0x10c012c      MSC_kern_invalid_#75
+0x10c0130      MSC_kern_invalid_#76
+0x10c0134      MSC_kern_invalid_#77
+0x10c0138      MSC_kern_invalid_#78
+0x10c013c      MSC_kern_invalid_#79
+0x10c0140      MSC_kern_invalid_#80
+0x10c0144      MSC_kern_invalid_#81
+0x10c0148      MSC_kern_invalid_#82
+0x10c014c      MSC_kern_invalid_#83
+0x10c0150      MSC_kern_invalid_#84
+0x10c0154      MSC_kern_invalid_#85
+0x10c0158      MSC_kern_invalid_#86
+0x10c015c      MSC_kern_invalid_#87
+0x10c0160      MSC_kern_invalid_#88
+0x10c0164      MSC_kern_invalid_#89
+0x10c0168      MSC_mk_wait_until
+0x10c016c      MSC_mk_timer_create
+0x10c0170      MSC_mk_timer_destroy
+0x10c0174      MSC_mk_timer_arm
+0x10c0178      MSC_mk_timer_cancel
+0x10c017c      MSC_mk_timebase_info
+0x10c0180      MSC_kern_invalid_#96
+0x10c0184      MSC_kern_invalid_#97
+0x10c0188      MSC_kern_invalid_#98
+0x10c018c      MSC_kern_invalid_#99
+0x10c0190      MSC_iokit_user_client_trap
+0x10c0194      MSC_kern_invalid_#101
+0x10c0198      MSC_kern_invalid_#102
+0x10c019c      MSC_kern_invalid_#103
+0x10c01a0      MSC_kern_invalid_#104
+0x10c01a4      MSC_kern_invalid_#105
+0x10c01a8      MSC_kern_invalid_#106
+0x10c01ac      MSC_kern_invalid_#107
+0x10c01b0      MSC_kern_invalid_#108
+0x10c01b4      MSC_kern_invalid_#109
+0x10c01b8      MSC_kern_invalid_#110
+0x10c01bc      MSC_kern_invalid_#111
+0x10c01c0      MSC_kern_invalid_#112
+0x10c01c4      MSC_kern_invalid_#113
+0x10c01c8      MSC_kern_invalid_#114
+0x10c01cc      MSC_kern_invalid_#115
+0x10c01d0      MSC_kern_invalid_#116
+0x10c01d4      MSC_kern_invalid_#117
+0x10c01d8      MSC_kern_invalid_#118
+0x10c01dc      MSC_kern_invalid_#119
+0x10c01e0      MSC_kern_invalid_#120
+0x10c01e4      MSC_kern_invalid_#121
+0x10c01e8      MSC_kern_invalid_#122
+0x10c01ec      MSC_kern_invalid_#123
+0x10c01f0      MSC_kern_invalid_#124
+0x10c01f4      MSC_kern_invalid_#125
+0x10c01f8      MSC_kern_invalid_#126
+0x10c01fc      MSC_kern_invalid_#127
+0x1050000      INTERRUPT
+0x3010090      VFS_LOOKUP
+0x40c0000      BSC_SysCall
+0x40c0004      BSC_exit
+0x40c0008      BSC_fork
+0x40c000c      BSC_read
+0x40c0010      BSC_write
+0x40c0014      BSC_open
+0x40c0018      BSC_close
+0x40c001c      BSC_wait4
+0x40c0020      BSC_old_creat
+0x40c0024      BSC_link
+0x40c0028      BSC_unlink
+0x40c002c      BSC_obs_execv
+0x40c0030      BSC_chdir
+0x40c0034      BSC_fchdir
+0x40c0038      BSC_mknod
+0x40c003c      BSC_chmod
+0x40c0040      BSC_chown
+0x40c0044      BSC_sbreak
+0x40c0048      BSC_getfsstat
+0x40c004c      BSC_old_lseek
+0x40c0050      BSC_getpid
+0x40c0054      BSC_obs_mount
+0x40c0058      BSC_obs_unmount
+0x40c005c      BSC_setuid
+0x40c0060      BSC_getuid
+0x40c0064      BSC_geteuid
+0x40c0068      BSC_ptrace
+0x40c006c      BSC_recvmsg
+0x40c0070      BSC_sendmsg
+0x40c0074      BSC_recvfrom
+0x40c0078      BSC_accept
+0x40c007c      BSC_getpeername
+0x40c0080      BSC_getsockname
+0x40c0084      BSC_access
+0x40c0088      BSC_chflags
+0x40c008c      BSC_fchflags
+0x40c0090      BSC_sync
+0x40c0094      BSC_kill
+0x40c0098      BSC_old_stat
+0x40c009c      BSC_getppid
+0x40c00a0      BSC_old_lstat
+0x40c00a4      BSC_dup
+0x40c00a8      BSC_pipe
+0x40c00ac      BSC_getegid
+0x40c00b0      BSC_profil
+0x40c00b4      BSC_ktrace
+0x40c00b8      BSC_sigaction
+0x40c00bc      BSC_getgid
+0x40c00c0      BSC_sigprocmask
+0x40c00c4      BSC_getlogin
+0x40c00c8      BSC_setlogin
+0x40c00cc      BSC_acct
+0x40c00d0      BSC_sigpending
+0x40c00d4      BSC_sigaltstack
+0x40c00d8      BSC_ioctl
+0x40c00dc      BSC_reboot
+0x40c00e0      BSC_revoke
+0x40c00e4      BSC_symlink
+0x40c00e8      BSC_readlink
+0x40c00ec      BSC_execve
+0x40c00f0      BSC_umask
+0x40c00f4      BSC_chroot
+0x40c00f8      BSC_old_fstat
+0x40c00fc      BSC_old_getkerninfo
+0x40c0100      BSC_old_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
+0x40c0120      BSC_obs_vadvise
+0x40c0124      BSC_munmap
+0x40c0128      BSC_mprotect
+0x40c012c      BSC_madvise
+0x40c0130      BSC_obs_vhangup
+0x40c0134      BSC_obs_vlimit
+0x40c0138      BSC_mincore
+0x40c013c      BSC_getgroups
+0x40c0140      BSC_setgroups
+0x40c0144      BSC_getpgrp
+0x40c0148      BSC_setpgid
+0x40c014c      BSC_setitimer
+0x40c0150      BSC_old_wait
+0x40c0154      BSC_swapon
+0x40c0158      BSC_getitimer
+0x40c015c      BSC_old_gethostname
+0x40c0160      BSC_old_sethostname
+0x40c0164      BSC_getdtablesize
+0x40c0168      BSC_dup2
+0x40c016c      BSC_#91
+0x40c0170      BSC_fcntl
+0x40c0174      BSC_select
+0x40c0178      BSC_#94
+0x40c017c      BSC_fsync
+0x40c0180      BSC_setpriority
+0x40c0184      BSC_socket
+0x40c0188      BSC_connect
+0x40c018c      BSC_old_accept
+0x40c0190      BSC_getpriority
+0x40c0194      BSC_old_send
+0x40c0198      BSC_old_recv
+0x40c019c      BSC_sigreturn
+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
+0x40c01bc      BSC_sigsuspend
+0x40c01c0      BSC_old_sigstack
+0x40c01c4      BSC_old_recvmsg
+0x40c01c8      BSC_old_sendmsg
+0x40c01cc      BSC_obs_vtrace
+0x40c01d0      BSC_gettimeofday
+0x40c01d4      BSC_getrusage
+0x40c01d8      BSC_getsockopt
+0x40c01dc      BSC_#119
+0x40c01e0      BSC_readv
+0x40c01e4      BSC_writev
+0x40c01e8      BSC_settimeofday
+0x40c01ec      BSC_fchown
+0x40c01f0      BSC_fchmod
+0x40c01f4      BSC_old_recvfrom
+0x40c01f8      BSC_old_setreuid
+0x40c01fc      BSC_old_setregid
+0x40c0200      BSC_rename
+0x40c0204      BSC_old_truncate
+0x40c0208      BSC_old_ftruncate
+0x40c020c      BSC_flock
+0x40c0210      BSC_mkfifo
+0x40c0214      BSC_sendto
+0x40c0218      BSC_shutdown
+0x40c021c      BSC_socketpair
+0x40c0220      BSC_mkdir
+0x40c0224      BSC_rmdir
+0x40c0228      BSC_utimes
+0x40c022c      BSC_#139
+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
+0x40c024c      BSC_setsid
+0x40c0250      BSC_obs_setquota
+0x40c0254      BSC_obs_quota
+0x40c0258      BSC_old_getsockname
+0x40c025c      BSC_#151
+0x40c0260      BSC_setprivexec
+0x40c0264      BSC_#153
+0x40c0268      BSC_#154
+0x40c026c      BSC_nfssvc
+0x40c0270      BSC_getdirentries
+0x40c0274      BSC_statfs
+0x40c0278      BSC_fstatfs
+0x40c027c      BSC_unmount
+0x40c0280      BSC_obs_async_daemon
+0x40c0284      BSC_getfh
+0x40c0288      BSC_old_getdomainname
+0x40c028c      BSC_old_setdomainname
+0x40c0290      BSC_obs_pcfs_mount
+0x40c0294      BSC_quotactl
+0x40c0298      BSC_obs_exportfs
+0x40c029c      BSC_mount
+0x40c02a0      BSC_obs_ustat
+0x40c02a4      BSC_#169
+0x40c02a8      BSC_obs_table
+0x40c02ac      BSC_old_wait_3
+0x40c02b0      BSC_obs_rpause
+0x40c02b4      BSC_#173
+0x40c02b8      BSC_obs_getdents
+0x40c02bc      BSC_#175
+0x40c02c0      BSC_add_profil
+0x40c02c4      BSC_#177
+0x40c02c8      BSC_#178
+0x40c02cc      BSC_#179
+0x40c02d0      BSC_kdebug
+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
+0x40c02f0      BSC_stat
+0x40c02f4      BSC_fstat
+0x40c02f8      BSC_lstat
+0x40c02fc      BSC_pathconf
+0x40c0300      BSC_fpathconf
+0x40c0304      BSC_getfsstat
+0x40c0308      BSC_getrlimit
+0x40c030c      BSC_setrlimit
+0x40c0310      BSC_getdirentries
+0x40c0314      BSC_mmap
+0x40c0318      BSC___syscall
+0x40c031c      BSC_lseek
+0x40c0320      BSC_truncate
+0x40c0324      BSC_ftruncate
+0x40c0328      BSC___sysctl
+0x40c032c      BSC_mlock
+0x40c0330      BSC_munlock
+0x40c0334      BSC_undelete
+0x40c0338      BSC_ATsocket
+0x40c033c      BSC_ATgetmsg
+0x40c0340      BSC_ATputmsg
+0x40c0344      BSC_ATPsndreq
+0x40c0348      BSC_ATPsndrsp
+0x40c034c      BSC_ATPgetreq
+0x40c0350      BSC_ATPgetrsp
+0x40c0354      BSC_#213
+0x40c0358      BSC_#214
+0x40c035c      BSC_#215
+0x40c0360      BSC_mkcomplex
+0x40c0364      BSC_statv
+0x40c0368      BSC_lstatv
+0x40c036c      BSC_fstatv
+0x40c0370      BSC_getattrlist
+0x40c0374      BSC_setattrlist
+0x40c0378      BSC_getdirentriesattr
+0x40c037c      BSC_exchangedata
+0x40c0380      BSC_checkuseraccess
+0x40c0384      BSC_searchfs
+0x40c0388      BSC_#226
+0x40c038c      BSC_#227
+0x40c0390      BSC_#228
+0x40c0394      BSC_#229
+0x40c0398      BSC_#230
+0x40c039c      BSC_watchevent
+0x40c03a0      BSC_waitevent
+0x40c03a4      BSC_modwatch
+0x40c03a8      BSC_#234
+0x40c03ac      BSC_#235
+0x40c03b0      BSC_#236
+0x40c03b4      BSC_#237
+0x40c03b8      BSC_#238
+0x40c03bc      BSC_#239
+0x40c03c0      BSC_#240
+0x40c03c4      BSC_#241
+0x40c03c8      BSC_#242
+0x40c03cc      BSC_#243
+0x40c03d0      BSC_#244
+0x40c03d4      BSC_#245
+0x40c03d8      BSC_#246
+0x40c03dc      BSC_#247
+0x40c03e0      BSC_#248
+0x40c03e4      BSC_#249
+0x40c03e8      BSC_minherit
+0x40c03ec      BSC_semsys
+0x40c03f0      BSC_msgsys
+0x40c03f4      BSC_shmsys
+0x40c03f8      BSC_semctl
+0x40c03fc      BSC_semget
+0x40c0400      BSC_semop
+0x40c0404      BSC_semconfig
+0x40c0408      BSC_msgctl
+0x40c040c      BSC_msgget
+0x40c0410      BSC_msgsnd
+0x40c0414      BSC_msgrcv
+0x40c0418      BSC_shmat
+0x40c041c      BSC_shmctl
+0x40c0420      BSC_shmdt
+0x40c0424      BSC_shmget
+0x40c0428      BSC_shm_open
+0x40c042c      BSC_shm_unlink
+0x40c0430      BSC_sem_open
+0x40c0434      BSC_sem_close
+0x40c0438      BSC_sem_unlink
+0x40c043c      BSC_sem_wait
+0x40c0440      BSC_sem_trywait
+0x40c0444      BSC_sem_post
+0x40c0448      BSC_sem_getvalue
+0x40c044c      BSC_sem_init
+0x40c0450      BSC_sem_destroy
+0x40c0454      BSC_#277
+0x40c0458      BSC_#278
+0x40c045c      BSC_#279
+0x40c0460      BSC_#280
+0x40c0464      BSC_#281
+0x40c0468      BSC_#282
+0x40c046c      BSC_#283
+0x40c0470      BSC_#284
+0x40c0474      BSC_#285
+0x40c0478      BSC_#286
+0x40c047c      BSC_#287
+0x40c0480      BSC_#288
+0x40c0484      BSC_#289
+0x40c0488      BSC_#290
+0x40c048c      BSC_#291
+0x40c0490      BSC_#292
+0x40c0494      BSC_#293
+0x40c0498      BSC_#294
+0x40c049c      BSC_#295
+0x40c04a0      BSC_load_shared_file
+0x40c04a4      BSC_reset_shared_file
+0x40c04a8      BSC_#298
+0x40c04ac      BSC_#299
+0x40c04b0      BSC_#300
+0x40c04b4      BSC_#301
+0x40c04b8      BSC_#302
+0x40c04bc      BSC_#303
+0x40c04c0      BSC_#304
+0x40c04c4      BSC_#305
+0x40c04c8      BSC_#306
+0x40c04cc      BSC_#307
+0x40c04d0      BSC_#308
+0x40c04d4      BSC_#309
+0x40c04d8      BSC_#310
+0x40c04dc      BSC_#311
+0x40c04e0      BSC_#312
+0x40c04e4      BSC_#313
+0x40c04e8      BSC_#314
+0x40c04ec      BSC_#315
+0x40c04f0      BSC_#316
+0x40c04f4      BSC_#317
+0x40c04f8      BSC_#318
+0x40c04fc      BSC_#319
+0x40c0500      BSC_#320
+0x40c0504      BSC_#321
+0x40c0508      BSC_#322
+0x40c050c      BSC_#323
+0x40c0510      BSC_mlockall
+0x40c0514      BSC_munlockall
+0x50b0018      IES_action
+0x50b001c      IES_filter
+0x50c0010      TES_action
+0x50d0018      CQ_action
+0x7000004      TRACE_DATA_NEWTHREAD
+0x7010004      TRACE_STRING_NEWTHREAD
+0x7010008      TRACE_STRING_EXEC
+0x8000000      USER_TEST
diff --git a/shutdown.tproj/Makefile b/shutdown.tproj/Makefile
new file mode 100644 (file)
index 0000000..73d25a8
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = shutdown
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pathnames.h
+
+CFILES = shutdown.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\
+            shutdown.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /sbin
+WINDOWS_INSTALLDIR = /sbin
+PDO_UNIX_INSTALLDIR = /sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/shutdown.tproj/Makefile.dist b/shutdown.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..19122f2
--- /dev/null
@@ -0,0 +1,9 @@
+#      @(#)Makefile    8.1 (Berkeley) 6/5/93
+
+PROG=  shutdown
+MAN8=  shutdown.0
+BINOWN=        root
+BINGRP=        operator
+BINMODE=4550
+
+.include <bsd.prog.mk>
diff --git a/shutdown.tproj/Makefile.postamble b/shutdown.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..29865de
--- /dev/null
@@ -0,0 +1,2 @@
+INSTALL_AS_GROUP = operator      # (probably want to set both of these) 
+INSTALL_PERMISSIONS = 4550    # If set, 'install' chmod's executable to this
diff --git a/shutdown.tproj/Makefile.preamble b/shutdown.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/shutdown.tproj/PB.project b/shutdown.tproj/PB.project
new file mode 100644 (file)
index 0000000..87cbc03
--- /dev/null
@@ -0,0 +1,32 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (pathnames.h); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (shutdown.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, shutdown.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_INSTALLDIR = /sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = shutdown; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = shutdown; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = shutdown; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = shutdown; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/shutdown.tproj/pathnames.h b/shutdown.tproj/pathnames.h
new file mode 100644 (file)
index 0000000..2bb5f01
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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@
+ */
+#include <paths.h>
+
+#define        _PATH_FASTBOOT  "/fastboot"
+#define        _PATH_HALT      "/sbin/halt"
+#define        _PATH_REBOOT    "/sbin/reboot"
+#define        _PATH_WALL      "/usr/bin/wall"
diff --git a/shutdown.tproj/shutdown.8 b/shutdown.tproj/shutdown.8
new file mode 100644 (file)
index 0000000..74126f8
--- /dev/null
@@ -0,0 +1,162 @@
+.\" Copyright (c) 1988, 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.
+.\"
+.\"     @(#)shutdown.8 8.2 (Berkeley) 4/27/95
+.\"
+.Dd April 27, 1995
+.Dt SHUTDOWN 8
+.Os BSD 4
+.Sh NAME
+.Nm shutdown
+.Nd "close down the system at a given time"
+.Sh SYNOPSIS
+.Nm shutdown
+.Op Fl 
+.Op Fl fhkrn
+.Ar time
+.Op Ar warning-message ...
+.Sh DESCRIPTION
+.Nm Shutdown
+provides an automated shutdown procedure for super-users
+to nicely notify users when the system is shutting down,
+saving them from system administrators, hackers, and gurus, who
+would otherwise not bother with such niceties.
+.Pp
+Available friendlinesses:
+.Bl -tag -width time
+.It Fl f
+.Nm Shutdown
+arranges, in the manner of
+.Xr fastboot 8 ,
+for the file systems
+.Em not to be
+checked on reboot.
+.It Fl h
+The system is halted at the specified
+.Ar time
+when
+.Nm shutdown
+execs
+.Xr halt 8 .
+.It Fl k
+Kick everybody off.
+The
+.Fl k
+option
+does not actually halt the system, but leaves the
+system multi-user with logins disabled (for all but super-user).
+.It Fl n
+Prevent the normal
+.Xr sync 2
+before stopping.
+.It Fl r 
+.Nm Shutdown
+execs
+.Xr reboot 8
+at the specified
+.Ar time .
+.It Ar time
+.Ar Time
+is the time at which
+.Nm shutdown
+will bring the system down and
+may be the word
+.Ar now
+(indicating an immediate shutdown) or
+specify a future time in one of two formats:
+.Ar +number ,
+or
+.Ar yymmddhhmm ,
+where the year, month, and day may be defaulted
+to the current system values.  The first form brings the system down in
+.Ar number
+minutes and the second at the absolute time specified.
+.It Ar warning-message
+Any other arguments comprise the warning message that is broadcast
+to users currently logged into the system.
+.It Fl
+If
+.Ql Fl
+is supplied as an option, the warning message is read from the standard
+input.
+.El
+.Pp
+At intervals, becoming more frequent as apocalypse approaches
+and starting at ten hours before shutdown, warning messages are displayed
+on the terminals of all users logged in.  Five minutes before
+shutdown, or immediately if shutdown is in less than 5 minutes,
+logins are disabled by creating
+.Pa /etc/nologin
+and copying the
+warning message there.  If this file exists when a user attempts to
+log in,
+.Xr login 1
+prints its contents and exits.  The file is
+removed just before
+.Nm shutdown
+exits.
+.Pp
+At shutdown time a message is written in the system log, containing the
+time of shutdown, who initiated the shutdown and the reason.
+A terminate
+signal is then sent to
+.Xr init
+to bring the system down to single-user state (depending on above
+options).
+The time of the shutdown and the warning message
+are placed in
+.Pa /etc/nologin
+and should be used to
+inform the users about when the system will be back up
+and why it is going down (or anything else).
+.Sh FILES
+.Bl -tag -width /etc/nologin -compact
+.It Pa /etc/nologin
+tells login not to let anyone log in
+.It Pa /fastboot
+tells
+.Xr rc 8
+not to run fsck when rebooting
+.El
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr wall 1 ,
+.Xr fastboot 8 ,
+.Xr halt 8 ,
+.Xr reboot 8
+.Sh BACKWARD COMPATIBILITY
+The hours and minutes in the second time format may be separated by
+a colon (``:'') for backward compatibility.
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/shutdown.tproj/shutdown.c b/shutdown.tproj/shutdown.c
new file mode 100644 (file)
index 0000000..889b0a0
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * 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, 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.
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/syslog.h>
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tzfile.h>
+#include <unistd.h>
+
+#include "pathnames.h"
+
+#ifdef DEBUG
+#undef _PATH_NOLOGIN
+#define        _PATH_NOLOGIN   "./nologin"
+#undef _PATH_FASTBOOT
+#define        _PATH_FASTBOOT  "./fastboot"
+#endif
+
+#define        H               *60*60
+#define        M               *60
+#define        S               *1
+#define        NOLOG_TIME      5*60
+struct interval {
+       int timeleft, timetowait;
+} tlist[] = {
+       10 H,  5 H,      5 H,  3 H,      2 H,  1 H,     1 H, 30 M,
+       30 M, 10 M,     20 M, 10 M,     10 M,  5 M,     5 M,  3 M,
+        2 M,  1 M,      1 M, 30 S,     30 S, 30 S,
+        0, 0,
+};
+#undef H
+#undef M
+#undef S
+
+static time_t offset, shuttime;
+static int dofast, dohalt, doreboot, killflg, mbuflen;
+static char *nosync, *whom, mbuf[BUFSIZ];
+
+void badtime __P((void));
+void die_you_gravy_sucking_pig_dog __P((void));
+void doitfast __P((void));
+void finish __P((int));
+void getoffset __P((char *));
+void loop __P((void));
+void nolog __P((void));
+void timeout __P((int));
+void timewarn __P((int));
+void usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       extern int optind;
+       register char *p, *endp;
+       struct passwd *pw;
+       int arglen, ch, len, readstdin;
+
+#ifndef DEBUG
+       if (geteuid()) {
+               (void)fprintf(stderr, "shutdown: NOT super-user\n");
+               exit(1);
+       }
+#endif
+       nosync = NULL;
+       readstdin = 0;
+       while ((ch = getopt(argc, argv, "-fhknr")) != EOF)
+               switch (ch) {
+               case '-':
+                       readstdin = 1;
+                       break;
+               case 'f':
+                       dofast = 1;
+                       break;
+               case 'h':
+                       dohalt = 1;
+                       break;
+               case 'k':
+                       killflg = 1;
+                       break;
+               case 'n':
+                       nosync = "-n";
+                       break;
+               case 'r':
+                       doreboot = 1;
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       argc -= optind;
+       argv += optind;
+
+       if (argc < 1)
+               usage();
+
+       if (dofast && nosync) {
+               (void)fprintf(stderr,
+                   "shutdown: incompatible switches -f and -n.\n");
+               usage();
+       }
+       if (doreboot && dohalt) {
+               (void)fprintf(stderr,
+                   "shutdown: incompatible switches -h and -r.\n");
+               usage();
+       }
+       getoffset(*argv++);
+
+       if (*argv) {
+               for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) {
+                       arglen = strlen(*argv);
+                       if ((len -= arglen) <= 2)
+                               break;
+                       if (p != mbuf)
+                               *p++ = ' ';
+                       memmove(p, *argv, arglen);
+                       p += arglen;
+               }
+               *p = '\n';
+               *++p = '\0';
+       }
+
+       if (readstdin) {
+               p = mbuf;
+               endp = mbuf + sizeof(mbuf) - 2;
+               for (;;) {
+                       if (!fgets(p, endp - p + 1, stdin))
+                               break;
+                       for (; *p &&  p < endp; ++p);
+                       if (p == endp) {
+                               *p = '\n';
+                               *++p = '\0';
+                               break;
+                       }
+               }
+       }
+       mbuflen = strlen(mbuf);
+
+       if (offset)
+               (void)printf("Shutdown at %.24s.\n", ctime(&shuttime));
+       else
+               (void)printf("Shutdown NOW!\n");
+
+       if (!(whom = getlogin()))
+               whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
+
+#ifdef DEBUG
+       (void)putc('\n', stdout);
+#else
+       (void)setpriority(PRIO_PROCESS, 0, PRIO_MIN);
+       {
+               int forkpid;
+
+               forkpid = fork();
+               if (forkpid == -1) {
+                       perror("shutdown: fork");
+                       exit(1);
+               }
+               if (forkpid) {
+                       (void)printf("shutdown: [pid %d]\n", forkpid);
+                       exit(0);
+               }
+       }
+#endif
+       openlog("shutdown", LOG_CONS, LOG_AUTH);
+       loop();
+       /* NOTREACHED */
+}
+
+void
+loop()
+{
+       struct interval *tp;
+       u_int sltime;
+       int logged;
+
+       if (offset <= NOLOG_TIME) {
+               logged = 1;
+               nolog();
+       }
+       else
+               logged = 0;
+       tp = tlist;
+       if (tp->timeleft < offset)
+               (void)sleep((u_int)(offset - tp->timeleft));
+       else {
+               while (offset < tp->timeleft)
+                       ++tp;
+               /*
+                * Warn now, if going to sleep more than a fifth of
+                * the next wait time.
+                */
+               if (sltime = offset - tp->timeleft) {
+                       if (sltime > tp->timetowait / 5)
+                               timewarn(offset);
+                       (void)sleep(sltime);
+               }
+       }
+       for (;; ++tp) {
+               timewarn(tp->timeleft);
+               if (!logged && tp->timeleft <= NOLOG_TIME) {
+                       logged = 1;
+                       nolog();
+               }
+               (void)sleep((u_int)tp->timetowait);
+               if (!tp->timeleft)
+                       break;
+       }
+       die_you_gravy_sucking_pig_dog();
+}
+
+static jmp_buf alarmbuf;
+
+void
+timewarn(timeleft)
+       int timeleft;
+{
+       static int first;
+       static char hostname[MAXHOSTNAMELEN + 1];
+       FILE *pf;
+       char wcmd[MAXPATHLEN + 4];
+
+       if (!first++)
+               (void)gethostname(hostname, sizeof(hostname));
+
+       /* undoc -n option to wall suppresses normal wall banner */
+       (void)snprintf(wcmd, sizeof(wcmd), "%s -n", _PATH_WALL);
+       if (!(pf = popen(wcmd, "w"))) {
+               syslog(LOG_ERR, "shutdown: can't find %s: %m", _PATH_WALL);
+               return;
+       }
+
+       (void)fprintf(pf,
+           "\007*** %sSystem shutdown message from %s@%s ***\007\n",
+           timeleft ? "": "FINAL ", whom, hostname);
+
+       if (timeleft > 10*60)
+               (void)fprintf(pf, "System going down at %5.5s\n\n",
+                   ctime(&shuttime) + 11);
+       else if (timeleft > 59)
+               (void)fprintf(pf, "System going down in %d minute%s\n\n",
+                   timeleft / 60, (timeleft > 60) ? "s" : "");
+       else if (timeleft)
+               (void)fprintf(pf, "System going down in 30 seconds\n\n");
+       else
+               (void)fprintf(pf, "System going down IMMEDIATELY\n\n");
+
+       if (mbuflen)
+               (void)fwrite(mbuf, sizeof(*mbuf), mbuflen, pf);
+
+       /*
+        * play some games, just in case wall doesn't come back
+        * probably unecessary, given that wall is careful.
+        */
+       if (!setjmp(alarmbuf)) {
+               (void)signal(SIGALRM, timeout);
+               (void)alarm((u_int)30);
+               (void)pclose(pf);
+               (void)alarm((u_int)0);
+               (void)signal(SIGALRM, SIG_DFL);
+       }
+}
+
+void
+timeout(signo)
+       int signo;
+{
+       longjmp(alarmbuf, 1);
+}
+
+void
+die_you_gravy_sucking_pig_dog()
+{
+
+       syslog(LOG_NOTICE, "%s by %s: %s",
+           doreboot ? "reboot" : dohalt ? "halt" : "shutdown", whom, mbuf);
+       (void)sleep(2);
+
+       (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
+       if (killflg) {
+               (void)printf("\rbut you'll have to do it yourself\r\n");
+               finish(0);
+       }
+       if (dofast)
+               doitfast();
+#ifdef DEBUG
+       if (doreboot)
+               (void)printf("reboot");
+       else if (dohalt)
+               (void)printf("halt");
+       if (nosync)
+               (void)printf(" no sync");
+       if (dofast)
+               (void)printf(" no fsck");
+       (void)printf("\nkill -HUP 1\n");
+#else
+       if (doreboot) {
+               execle(_PATH_REBOOT, "reboot", "-l", nosync, 0);
+               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_REBOOT);
+               perror("shutdown");
+       }
+       else if (dohalt) {
+               execle(_PATH_HALT, "halt", "-l", nosync, 0);
+               syslog(LOG_ERR, "shutdown: can't exec %s: %m.", _PATH_HALT);
+               perror("shutdown");
+       }
+       (void)kill(1, SIGTERM);         /* to single user */
+#endif
+       finish(0);
+}
+
+#define        ATOI2(p)        (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
+
+void
+getoffset(timearg)
+       register char *timearg;
+{
+       register struct tm *lt;
+       register char *p;
+       time_t now;
+
+       if (!strcasecmp(timearg, "now")) {              /* now */
+               offset = 0;
+               return;
+       }
+
+       (void)time(&now);
+       if (*timearg == '+') {                          /* +minutes */
+               if (!isdigit(*++timearg))
+                       badtime();
+               offset = atoi(timearg) * 60;
+               shuttime = now + offset;
+               return;
+       }
+
+       /* handle hh:mm by getting rid of the colon */
+       for (p = timearg; *p; ++p)
+               if (!isascii(*p) || !isdigit(*p))
+                       if (*p == ':' && strlen(p) == 3) {
+                               p[0] = p[1];
+                               p[1] = p[2];
+                               p[2] = '\0';
+                       }
+                       else
+                               badtime();
+
+       unsetenv("TZ");                                 /* OUR timezone */
+       lt = localtime(&now);                           /* current time val */
+
+       switch(strlen(timearg)) {
+       case 10:
+               lt->tm_year = ATOI2(timearg);
+               /* FALLTHROUGH */
+       case 8:
+               lt->tm_mon = ATOI2(timearg);
+               if (--lt->tm_mon < 0 || lt->tm_mon > 11)
+                       badtime();
+               /* FALLTHROUGH */
+       case 6:
+               lt->tm_mday = ATOI2(timearg);
+               if (lt->tm_mday < 1 || lt->tm_mday > 31)
+                       badtime();
+               /* FALLTHROUGH */
+       case 4:
+               lt->tm_hour = ATOI2(timearg);
+               if (lt->tm_hour < 0 || lt->tm_hour > 23)
+                       badtime();
+               lt->tm_min = ATOI2(timearg);
+               if (lt->tm_min < 0 || lt->tm_min > 59)
+                       badtime();
+               lt->tm_sec = 0;
+               if ((shuttime = mktime(lt)) == -1)
+                       badtime();
+               if ((offset = shuttime - now) < 0) {
+                       (void)fprintf(stderr,
+                           "shutdown: that time is already past.\n");
+                       exit(1);
+               }
+               break;
+       default:
+               badtime();
+       }
+}
+
+#define        FSMSG   "fastboot file for fsck\n"
+void
+doitfast()
+{
+       int fastfd;
+
+       if ((fastfd = open(_PATH_FASTBOOT, O_WRONLY|O_CREAT|O_TRUNC,
+           0664)) >= 0) {
+               (void)write(fastfd, FSMSG, sizeof(FSMSG) - 1);
+               (void)close(fastfd);
+       }
+}
+
+#define        NOMSG   "\n\nNO LOGINS: System going down at "
+void
+nolog()
+{
+       int logfd;
+       char *ct;
+
+       (void)unlink(_PATH_NOLOGIN);    /* in case linked to another file */
+       (void)signal(SIGINT, finish);
+       (void)signal(SIGHUP, finish);
+       (void)signal(SIGQUIT, finish);
+       (void)signal(SIGTERM, finish);
+       if ((logfd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT|O_TRUNC,
+           0664)) >= 0) {
+               (void)write(logfd, NOMSG, sizeof(NOMSG) - 1);
+               ct = ctime(&shuttime);
+               (void)write(logfd, ct + 11, 5);
+               (void)write(logfd, "\n\n", 2);
+               (void)write(logfd, mbuf, strlen(mbuf));
+               (void)close(logfd);
+       }
+}
+
+void
+finish(signo)
+       int signo;
+{
+       if (!killflg)
+               (void)unlink(_PATH_NOLOGIN);
+       exit(0);
+}
+
+void
+badtime()
+{
+       (void)fprintf(stderr, "shutdown: bad time format.\n");
+       exit(1);
+}
+
+void
+usage()
+{
+       fprintf(stderr, "usage: shutdown [-fhknr] shutdowntime [ message ]\n");
+       exit(1);
+}
diff --git a/sync.tproj/Makefile b/sync.tproj/Makefile
new file mode 100644 (file)
index 0000000..ea9c493
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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 = sync
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = sync.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.dist sync.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /bin
+WINDOWS_INSTALLDIR = /bin
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/sync.tproj/Makefile.dist b/sync.tproj/Makefile.dist
new file mode 100644 (file)
index 0000000..b3f08be
--- /dev/null
@@ -0,0 +1,6 @@
+#      @(#)Makefile    8.1 (Berkeley) 5/31/93
+
+PROG=  sync
+MAN8=  sync.0
+
+.include <bsd.prog.mk>
diff --git a/sync.tproj/Makefile.preamble b/sync.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..d5059b1
--- /dev/null
@@ -0,0 +1,2 @@
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
diff --git a/sync.tproj/PB.project b/sync.tproj/PB.project
new file mode 100644 (file)
index 0000000..980a04c
--- /dev/null
@@ -0,0 +1,34 @@
+{
+    APPCLASS = NSApplication; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        M_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (sync.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, sync.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_MAINNIB = sync; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_INSTALLDIR = /bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_MAINNIB = sync; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = sync; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_INSTALLDIR = /bin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_MAINNIB = sync; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/sync.tproj/sync.8 b/sync.tproj/sync.8
new file mode 100644 (file)
index 0000000..049007e
--- /dev/null
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1980, 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.
+.\"
+.\"    @(#)sync.8      8.1 (Berkeley) 5/31/93
+.\"
+.Dd May 31, 1993
+.Dt SYNC 8
+.Os BSD 4
+.Sh NAME
+.Nm sync
+.Nd force completion of pending disk writes (flush cache)
+.Sh SYNOPSIS
+.Nm sync
+.Sh DESCRIPTION
+.Nm Sync
+can be called to insure that all disk writes have been completed before the
+processor is halted in a way not suitably done by
+.Xr reboot 8
+or
+.Xr halt 8 .
+Generally, it is preferable to use
+.Xr reboot
+or
+.Xr halt
+to shut down the system,
+as they may perform additional actions
+such as resynchronizing the hardware clock
+and flushing internal caches before performing a final
+.Nm sync .
+.Pp
+.Nm Sync
+utilizes the
+.Xr sync 2
+function call.
+.Sh SEE ALSO
+.Xr sync 2 ,
+.Xr fsync 2 ,
+.Xr halt 8 ,
+.Xr reboot 8 ,
+.Xr update 8
+.Sh HISTORY
+A
+.Nm sync
+command appeared in
+.At v6 .
diff --git a/sync.tproj/sync.c b/sync.tproj/sync.c
new file mode 100644 (file)
index 0000000..9a242f3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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) 1987, 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.
+ */
+
+main()
+{
+       sync();
+       exit(0);
+}
diff --git a/sysctl.tproj/Makefile b/sysctl.tproj/Makefile
new file mode 100644 (file)
index 0000000..fc19331
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = sysctl
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = sysctl.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sysctl.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/sysctl.tproj/Makefile.postamble b/sysctl.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..70b747f
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/sysctl.tproj/Makefile.preamble b/sysctl.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..e371f9d
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/sysctl.tproj/PB.project b/sysctl.tproj/PB.project
new file mode 100644 (file)
index 0000000..b4c60b3
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (sysctl.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, sysctl.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = sysctl; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/sysctl.tproj/sysctl.8 b/sysctl.tproj/sysctl.8
new file mode 100644 (file)
index 0000000..bc348a9
--- /dev/null
@@ -0,0 +1,229 @@
+.\" Copyright (c) 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.
+.\"
+.\"    @(#)sysctl.8    8.2 (Berkeley) 5/9/95
+.\"
+.Dd "May 9, 1995"
+.Dt SYSCTL 8
+.Os
+.Sh NAME
+.Nm sysctl
+.Nd get or set kernel state
+.Sh SYNOPSIS
+.Nm sysctl
+.Op Fl n
+.Ar name ...
+.Nm sysctl
+.Op Fl n
+.Fl w
+.Ar name=value ...
+.Nm sysctl
+.Op Fl n
+.Fl aA
+.Sh DESCRIPTION
+The
+.Nm sysctl
+utility retrieves kernel state and allows processes with
+appropriate privilege to set kernel state.
+The state to be retrieved or set is described using a
+``Management Information Base'' (``MIB'') style name,
+described as a dotted set of components.
+The
+.Fl a
+flag can be used to list all the currently available string or integer values.
+The
+.Fl A
+flag will list all the known MIB names including tables.
+Those with string or integer values will be printed as with the
+.Fl a
+flag; for the table values,
+the name of the utility to retrieve them is given.
+.Pp
+The
+.Fl n
+flag specifies that the printing of the field name should be
+suppressed and that only its value should be output.
+This flag is useful for setting shell variables.
+For example, to save the pagesize in variable psize, use:
+.Bd -literal -offset indent -compact
+set psize=`sysctl -n hw.pagesize`
+.Ed
+.Pp
+If just a MIB style name is given,
+the corresponding value is retrieved.
+If a value is to be set, the
+.Fl w
+flag must be specified and the MIB name followed
+by an equal sign and the new value to be used.
+.Pp
+The information available from
+.Nm sysctl
+consists of integers, strings, and tables.
+The tabular information can only be retrieved by special
+purpose programs such as
+.Nm ps ,
+.Nm systat ,
+and
+.Nm netstat .
+The string and integer information is summaried below.
+For a detailed description of these variable see
+.Xr sysctl 3 .
+The changeable column indicates whether a process with appropriate
+privilege can change the value.
+.Bl -column net.inet.ip.forwardingxxxxxx integerxxx
+.It Sy Name    Type    Changeable
+.It kern.ostype        string  no
+.It kern.osrelease     string  no
+.It kern.osrevision    integer no
+.It kern.version       string  no
+.It kern.maxvnodes     integer yes
+.It kern.maxproc       integer yes
+.It kern.maxfiles      integer yes
+.It kern.argmax        integer no
+.It kern.securelevel   integer raise only
+.It kern.hostname      string  yes
+.It kern.hostid        integer yes
+.It kern.clockrate     struct  no
+.It kern.posix1version integer no
+.It kern.ngroups       integer no
+.It kern.job_control   integer no
+.It kern.saved_ids     integer no
+.It kern.link_max      integer no
+.It kern.max_canon     integer no
+.It kern.max_input     integer no
+.It kern.name_max      integer no
+.It kern.path_max      integer no
+.It kern.pipe_buf      integer no
+.It kern.chown_restricted      integer no
+.It kern.no_trunc      integer no
+.It kern.vdisable      integer no
+.It kern.boottime      struct  no
+.It vm.loadavg struct  no
+.It machdep.console_device     dev_t   no
+.It net.inet.ip.forwarding     integer yes
+.It net.inet.ip.redirect       integer yes
+.It net.inet.ip.ttl    integer yes
+.It net.inet.icmp.maskrepl     integer yes
+.It net.inet.udp.checksum      integer yes
+.It hw.machine string  no
+.It hw.model   string  no
+.It hw.ncpu    integer no
+.It hw.byteorder       integer no
+.It hw.physmem integer no
+.It hw.usermem integer no
+.It hw.pagesize        integer no
+.It user.cs_path       string  no
+.It user.bc_base_max   integer no
+.It user.bc_dim_max    integer no
+.It user.bc_scale_max  integer no
+.It user.bc_string_max integer no
+.It user.coll_weights_max      integer no
+.It user.expr_nest_max integer no
+.It user.line_max      integer no
+.It user.re_dup_max    integer no
+.It user.posix2_version        integer no
+.It user.posix2_c_bind integer no
+.It user.posix2_c_dev  integer no
+.It user.posix2_char_term      integer no
+.It user.posix2_fort_dev       integer no
+.It user.posix2_fort_run       integer no
+.It user.posix2_localedef      integer no
+.It user.posix2_sw_dev integer no
+.It user.posix2_upe    integer no
+.El
+.Pp
+The
+.Nm sysctl
+program can get or set debugging variables
+that have been identified for its display.
+This information can be obtained by using the command:
+.Bd -literal -offset indent
+sysctl debug
+.Ed
+In addition,
+.Nm sysctl
+can extract information about the filesystems that have been compiled
+into the running system.
+This information can be obtained by using the command:
+.Bd -literal -offset indent
+sysctl vfs
+.Ed
+By default, only filesystems that are actively being used are listed.
+Use of the
+.Fl A
+flag lists all the filesystems compiled into the running kernel.
+.Sh EXAMPLES
+.Pp
+For example, to retrieve the maximum number of processes allowed
+in the system, one would use the follow request:
+.Bd -literal -offset indent -compact
+sysctl kern.maxproc
+.Ed
+.Pp
+To set the maximum number of processes allowed
+in the system to 1000, one would use the follow request:
+.Bd -literal -offset indent -compact
+sysctl -w kern.maxproc=1000
+.Ed
+.Pp
+Information about the system clock rate may be obtained with:
+.Bd -literal -offset indent -compact
+sysctl kern.clockrate
+.Ed
+.Pp
+Information about the load average history may be obtained with
+.Bd -literal -offset indent -compact
+sysctl vm.loadavg
+.Ed
+.Sh FILES
+.Bl -tag -width <netinet/icmpXvar.h> -compact
+.It Pa <sys/sysctl.h>
+definitions for top level identifiers, second level kernel and hardware
+identifiers, and user level identifiers
+.It Pa <sys/socket.h>
+definitions for second level network identifiers
+.It Pa <sys/gmon.h>
+definitions for third level profiling identifiers
+.It Pa <vm/vm_param.h>
+definitions for second level virtual memory identifiers
+.It Pa <netinet/in.h>
+definitions for third level Internet identifiers and
+fourth level IP identifiers
+.It Pa <netinet/icmp_var.h>
+definitions for fourth level ICMP identifiers
+.It Pa <netinet/udp_var.h>
+definitions for fourth level UDP identifiers
+.El
+.Sh SEE ALSO
+.Xr sysctl 3
+.Sh HISTORY
+.Nm sysctl
+first appeared in 4.4BSD.
diff --git a/sysctl.tproj/sysctl.c b/sysctl.tproj/sysctl.c
new file mode 100644 (file)
index 0000000..fb0dbb4
--- /dev/null
@@ -0,0 +1,1053 @@
+/*
+ * 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) 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.
+ */
+
+ /*
+ Modified November 1, 2000, by Ryan Rempel, ryan.rempel@utoronto.ca
+ The Darwin sysctl mechanism is in a state of flux. Parts of the kernel use the old
+ style of BSD sysctl definition, and other parts use the new style. The sysctl (8)
+ command that shipped with Darwin 1.2 (OS X PB) did not allow you to access
+ all possible sysctl values. In particular, it did not permit access to sysctl values
+ created by kernel extensions--hence my particular interest. The freeBSD sysctl (8)
+ command compiled and ran under Darwin 1.2, and it did permit access to 
+ sysctl values created by kernel extensions, as well as several others. However, it 
+ did not permit access to many other values which the Darwin 1.2 sysctl could access.
+ What I have done is merge the Darwin 1.2 sysctl and the freeBSD sysctl. Essentially,
+ there are two points of merger. When showing all values (i.e. -a, -A, or -X), sysctl now
+ runs the Darwin 1.2 routine to show all values, and then the freeBSD routine. This does
+ result in some duplication. When getting or setting a particular value, sysctl now tries
+ the freeBSD way first. If it cannot find the value, then it tries the Darwin 1.2 way.
+ There are a few oddities which this creates (aside from some duplication with -a, -A,
+ and -X). The freeBSD version of sysctl now supports two extra options, -b and -X. 
+ In this syctl, those options are supported where the value is retrieved by the freeBSD
+ routine, and have no effect where the value is retrieved by the Darwin 1.2 routine.
+ The freeBSD sysctl uses a ':' to separate the name and the value, whereas Darwin 1.2's
+ sysctl uses a '='. I have left this way, as it lets you know which routine was used,
+ should it matter.
+ I have also fixed several lines which gave warnings previously, one of which appears
+ to have been an actual bug (bufp was dereferenced when it shouldn't have been).
+ I have also incoporated my previous patch to permit setting kern.hostid as an unsigned 
+ integer. In the freeBSD side of the code, I have incorporated a general fix for
+ setting values where the format is specified as unsigned integer.
+ */
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)sysctl.c   8.5 (Berkeley) 5/9/95";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/gmon.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#ifdef __APPLE__
+#include <mach/machine/vm_param.h>
+#include <mach/machine/vm_types.h>
+#include <mach/mach_types.h>
+#else
+#include <vm/vm_param.h>
+#endif /* __APPLE__ */
+#include <machine/cpu.h>
+
+#include <errno.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/resource.h>
+#include <err.h>
+
+struct ctlname topname[] = CTL_NAMES;
+struct ctlname kernname[] = CTL_KERN_NAMES;
+struct ctlname vmname[] = CTL_VM_NAMES;
+struct ctlname hwname[] = CTL_HW_NAMES;
+struct ctlname username[] = CTL_USER_NAMES;
+struct ctlname debugname[CTL_DEBUG_MAXID];
+struct ctlname *vfsname;
+#ifdef CTL_MACHDEP_NAMES
+struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
+#endif
+char names[BUFSIZ];
+int lastused;
+
+struct list {
+       struct  ctlname *list;
+       int     size;
+};
+struct list toplist = { topname, CTL_MAXID };
+struct list secondlevel[] = {
+       { 0, 0 },                       /* CTL_UNSPEC */
+       { kernname, KERN_MAXID },       /* CTL_KERN */
+       { vmname, VM_MAXID },           /* CTL_VM */
+       { 0, 0 },                       /* CTL_VFS */
+    { 0, 0 },          /* CTL_NET */
+       { 0, CTL_DEBUG_MAXID },         /* CTL_DEBUG */
+       { hwname, HW_MAXID },           /* CTL_HW */
+#ifdef CTL_MACHDEP_NAMES
+       { machdepname, CPU_MAXID },     /* CTL_MACHDEP */
+#else
+       { 0, 0 },                       /* CTL_MACHDEP */
+#endif
+       { username, USER_MAXID },       /* CTL_USER_NAMES */
+};
+
+static int     Aflag, aflag, bflag, nflag, wflag, Xflag;
+static int     foundSome = 0;
+
+void listall(char *prefix, struct list *lp);
+void old_parse(char *string, int flags);
+void debuginit();
+void vfsinit();
+int  findname(char *string, char *level, char **bufp, struct list *namelist);
+void usage();
+
+static void    parse(char *string, int flags);
+static int     oidfmt(int *, int, char *, u_int *);
+static int     show_var(int *, int);
+static int     sysctl_all (int *oid, int len);
+static int     name2oid(char *, int *);
+
+/*
+ * Variables requiring special processing.
+ */
+#define        CLOCK           0x00000001
+#define        BOOTTIME        0x00000002
+#define        CONSDEV         0x00000004
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+//     extern char *optarg;   // unused
+       extern int optind;
+       int ch, lvl1;
+
+       while ((ch = getopt(argc, argv, "AabnwX")) != EOF) {
+               switch (ch) {
+                       case 'A': Aflag = 1; break;
+                       case 'a': aflag = 1; break;
+                       case 'b': bflag = 1; break;
+                       case 'n': nflag = 1; break;
+                       case 'w': wflag = 1; break;
+                       case 'X': Xflag = Aflag = 1; break;
+                       default: usage();
+               }
+       }
+       argc -= optind;
+       argv += optind;
+
+       if (argc == 0 && (Aflag || aflag)) {
+               debuginit();
+               vfsinit();
+               for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
+                       listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
+               exit (sysctl_all(0, 0));
+       }
+       if (argc == 0)
+               usage();
+       for (; *argv != NULL; ++argv)
+               parse(*argv, 1);
+       exit(0);
+}
+
+/*
+ * List all variables known to the system.
+ */
+void
+listall(prefix, lp)
+       char *prefix;
+       struct list *lp;
+{
+       int lvl2;
+       char *cp, name[BUFSIZ];
+
+       if (lp->list == 0)
+               return;
+       strcpy(name, prefix);
+       cp = &name[strlen(name)];
+       *cp++ = '.';
+       for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
+               if (lp->list[lvl2].ctl_name == 0)
+                       continue;
+               strcpy(cp, lp->list[lvl2].ctl_name);
+               old_parse(name, Aflag);
+       }
+}
+
+/*
+ * Parse a name into a MIB entry.
+ * Lookup and print out the MIB entry if it exists.
+ * Set a new value if requested.
+ */
+void
+old_parse(string, flags)
+       char *string;
+       int flags;
+{
+       int indx, type, state, len;
+       size_t size;
+       int special = 0;
+       void *newval = 0;
+       int intval, newsize = 0;
+       unsigned int uintval;
+       int useUnsignedInt = 0;
+       quad_t quadval;
+       struct list *lp;
+       struct vfsconf vfc;
+       int mib[CTL_MAXNAME];
+       char *cp, *bufp, buf[BUFSIZ] /*, strval[BUFSIZ] */ ;
+
+       bufp = buf;
+       snprintf(buf, BUFSIZ, "%s", string);
+       if ((cp = strchr(string, '=')) != NULL) {
+               if (!wflag) {
+                       fprintf(stderr, "Must specify -w to set variables\n");
+                       exit(2);
+               }
+               *strchr(buf, '=') = '\0';
+               *cp++ = '\0';
+               while (isspace(*cp))
+                       cp++;
+               newval = cp;
+               newsize = strlen(cp);
+       }
+       if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
+               return;
+       mib[0] = indx;
+       if (indx == CTL_VFS)
+               vfsinit();
+       if (indx == CTL_DEBUG)
+               debuginit();
+       lp = &secondlevel[indx];
+       if (lp->list == 0) {
+               if (!foundSome) fprintf(stderr, "%s: class is not implemented\n",
+                   topname[indx].ctl_name);
+               return;
+       }
+       if (bufp == NULL) {
+               listall(topname[indx].ctl_name, lp);
+               return;
+       }
+       if ((indx = findname(string, "second", &bufp, lp)) == -1)
+               return;
+       mib[1] = indx;
+       type = lp->list[indx].ctl_type;
+       len = 2;
+       switch (mib[0]) {
+
+       case CTL_KERN:
+               switch (mib[1]) {
+               case KERN_PROF:
+                       mib[2] = GPROF_STATE;
+                       size = sizeof state;
+                       if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
+                               if (flags == 0)
+                                       return;
+                               if (!nflag)
+                                       fprintf(stdout, "%s: ", string);
+                               fprintf(stderr,
+                                   "kernel is not compiled for profiling\n");
+                               return;
+                       }
+                       if (!nflag)
+                               fprintf(stdout, "%s: %s\n", string,
+                                   state == GMON_PROF_OFF ? "off" : "running");
+                       return;
+               case KERN_VNODE:
+               case KERN_FILE:
+                       if (flags == 0)
+                               return;
+                       fprintf(stderr,
+                           "Use pstat to view %s information\n", string);
+                       return;
+               case KERN_PROC:
+                       if (flags == 0)
+                               return;
+                       fprintf(stderr,
+                           "Use ps to view %s information\n", string);
+                       return;
+               case KERN_CLOCKRATE:
+                       special |= CLOCK;
+                       break;
+               case KERN_BOOTTIME:
+                       special |= BOOTTIME;
+                       break;
+               case KERN_HOSTID:
+                       useUnsignedInt = 1;
+                       break;
+               }
+               break;
+
+       case CTL_HW:
+               break;
+
+       case CTL_VM:
+               if (mib[1] == VM_LOADAVG) {
+                       double loads[3];
+
+                       getloadavg(loads, 3);
+                       if (!nflag)
+                               fprintf(stdout, "%s: ", string);
+                       fprintf(stdout, "%.2f %.2f %.2f\n", 
+                           loads[0], loads[1], loads[2]);
+                       return;
+               }
+               if (flags == 0)
+                       return;
+               fprintf(stderr,
+                   "Use vmstat or systat to view %s information\n", string);
+               return;
+        
+       case CTL_DEBUG:
+               mib[2] = CTL_DEBUG_VALUE;
+               len = 3;
+               break;
+
+       case CTL_MACHDEP:
+#ifdef CPU_CONSDEV
+               if (mib[1] == CPU_CONSDEV)
+                       special |= CONSDEV;
+#endif
+               break;
+
+       case CTL_VFS:
+               mib[3] = mib[1];
+               mib[1] = VFS_GENERIC;
+               mib[2] = VFS_CONF;
+               len = 4;
+               size = sizeof vfc;
+               if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
+                       perror("vfs print");
+                       return;
+               }
+               if (flags == 0 && vfc.vfc_refcount == 0)
+                       return;
+               if (!nflag)
+                       fprintf(stdout, "%s has %d mounted instance%s\n",
+                           string, vfc.vfc_refcount,
+                           vfc.vfc_refcount != 1 ? "s" : "");
+               else
+                       fprintf(stdout, "%d\n", vfc.vfc_refcount);
+               return;
+
+       case CTL_USER:
+               break;
+
+       default:
+               fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
+               return;
+       
+       }
+       if (bufp) {
+               fprintf(stderr, "name %s in %s is unknown\n", bufp, string);
+               return;
+       }
+       if (newsize > 0) {
+               switch (type) {
+               case CTLTYPE_INT:
+                       if (useUnsignedInt) {   
+                               uintval = strtoul(newval, 0, 0);
+                               newval = &uintval;
+                               newsize = sizeof uintval;
+                       } else {
+                       intval = atoi(newval);
+                       newval = &intval;
+                       newsize = sizeof intval;
+                       }
+                       break;
+
+               case CTLTYPE_QUAD:
+                       sscanf(newval, "%qd", &quadval);
+                       newval = &quadval;
+                       newsize = sizeof quadval;
+                       break;
+               }
+       }
+       size = BUFSIZ;
+       if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
+               if (flags == 0)
+                       return;
+               switch (errno) {
+               case EOPNOTSUPP:
+                       fprintf(stderr, "%s: value is not available\n", string);
+                       return;
+               case ENOTDIR:
+                       fprintf(stderr, "%s: specification is incomplete\n",
+                           string);
+                       return;
+               case ENOMEM:
+                       fprintf(stderr, "%s: type is unknown to this program\n",
+                           string);
+                       return;
+               default:
+                       perror(string);
+                       return;
+               }
+       }
+       if (special & CLOCK) {
+               struct clockinfo *clkp = (struct clockinfo *)buf;
+
+               if (!nflag)
+                       fprintf(stdout, "%s: ", string);
+               fprintf(stdout,
+                   "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
+                   clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
+               return;
+       }
+       if (special & BOOTTIME) {
+               struct timeval *btp = (struct timeval *)buf;
+
+               if (!nflag)
+                       fprintf(stdout, "%s = %s\n", string,
+                           ctime((time_t *) &btp->tv_sec));
+               else
+                       fprintf(stdout, "%d\n", btp->tv_sec);
+               return;
+       }
+       if (special & CONSDEV) {
+               dev_t dev = *(dev_t *)buf;
+
+               if (!nflag)
+                       fprintf(stdout, "%s = %s\n", string,
+                           devname(dev, S_IFCHR));
+               else
+                       fprintf(stdout, "0x%x\n", dev);
+               return;
+       }
+       switch (type) {
+       case CTLTYPE_INT:
+               if (newsize == 0) {
+                       if (!nflag)
+                               fprintf(stdout, "%s = ", string);
+                       fprintf(stdout, useUnsignedInt ? "%u\n" : "%d\n", *(int *)buf);
+               } else {
+                       if (!nflag)
+                               fprintf(stdout, useUnsignedInt ? "%s: %u -> " : "%s: %d -> ", 
+                                       string, *(int *)buf);
+                       fprintf(stdout, useUnsignedInt ? "%u\n" : "%d\n", *(int *)newval);
+               }
+               return;
+
+       case CTLTYPE_STRING:
+               if (newsize == 0) {
+                       if (!nflag)
+                               fprintf(stdout, "%s = ", string);
+                       fprintf(stdout, "%s\n", buf);
+               } else {
+                       if (!nflag)
+                               fprintf(stdout, "%s: %s -> ", string, buf);
+                       fprintf(stdout, "%s\n", (char *) newval);
+               }
+               return;
+
+       case CTLTYPE_QUAD:
+               if (newsize == 0) {
+                       if (!nflag)
+                               fprintf(stdout, "%s = ", string);
+                       fprintf(stdout, "%qd\n", *(quad_t *)buf);
+               } else {
+                       if (!nflag)
+                               fprintf(stdout, "%s: %qd -> ", string,
+                                   *(quad_t *)buf);
+                       fprintf(stdout, "%qd\n", *(quad_t *)newval);
+               }
+               return;
+
+       case CTLTYPE_STRUCT:
+               return;
+
+       default:
+       case CTLTYPE_NODE:
+               fprintf(stderr, "%s: unknown type returned\n",
+                   string);
+               return;
+       }
+}
+
+/*
+ * Initialize the set of debugging names
+ */
+void debuginit()
+{
+       int mib[3], loc, i;
+       size_t size;
+
+       if (secondlevel[CTL_DEBUG].list != 0)
+               return;
+       secondlevel[CTL_DEBUG].list = debugname;
+       mib[0] = CTL_DEBUG;
+       mib[2] = CTL_DEBUG_NAME;
+       for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
+               mib[1] = i;
+               size = BUFSIZ - loc;
+               if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
+                       continue;
+               debugname[i].ctl_name = &names[loc];
+               debugname[i].ctl_type = CTLTYPE_INT;
+               loc += size;
+       }
+       lastused = loc;
+}
+
+/*
+ * Initialize the set of filesystem names
+ */
+void vfsinit()
+{
+       int mib[4], maxtypenum, cnt, loc, size;
+       struct vfsconf vfc;
+       size_t buflen;
+
+       if (secondlevel[CTL_VFS].list != 0)
+               return;
+       mib[0] = CTL_VFS;
+       mib[1] = VFS_GENERIC;
+       mib[2] = VFS_MAXTYPENUM;
+       buflen = 4;
+       if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
+               return;
+       if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0)
+               return;
+       memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
+       mib[2] = VFS_CONF;
+       buflen = sizeof vfc;
+       for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) {
+               mib[3] = cnt;
+               if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
+                       if (errno == EOPNOTSUPP)
+                               continue;
+                       perror("vfsinit");
+                       free(vfsname);
+                       return;
+               }
+               strcat(&names[loc], vfc.vfc_name);
+               vfsname[cnt].ctl_name = &names[loc];
+               vfsname[cnt].ctl_type = CTLTYPE_INT;
+               size = strlen(vfc.vfc_name) + 1;
+               loc += size;
+       }
+       lastused = loc;
+       secondlevel[CTL_VFS].list = vfsname;
+       secondlevel[CTL_VFS].size = maxtypenum;
+       return;
+}
+
+/*
+ * Scan a list of names searching for a particular name.
+ */
+int
+findname(string, level, bufp, namelist)
+       char *string;
+       char *level;
+       char **bufp;
+       struct list *namelist;
+{
+       char *name;
+       int i;
+
+       if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
+               fprintf(stderr, "%s: incomplete specification\n", string);
+               return (-1);
+       }
+       for (i = 0; i < namelist->size; i++)
+               if (namelist->list[i].ctl_name != NULL &&
+                   strcmp(name, namelist->list[i].ctl_name) == 0)
+                       break;
+       if (i == namelist->size) {
+               fprintf(stderr, "%s level name %s in %s is invalid\n",
+                   level, name, string);
+               return (-1);
+       }
+       return (i);
+}
+
+void usage()
+{
+
+       (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n",
+               "usage: sysctl [-bn] variable ...",
+               "       sysctl [-bn] -w variable=value ...",
+               "       sysctl [-bn] -a",
+               "       sysctl [-bn] -A",
+               "       sysctl [-bn] -X");
+       exit(1);
+}
+
+/*
+ * Parse a name into a MIB entry.
+ * Lookup and print out the MIB entry if it exists.
+ * Set a new value if requested.
+ */
+static void
+parse(char *string, int flags)
+{
+       int len, i, j;
+       void *newval = 0;
+       int intval, newsize = 0;
+       unsigned int uintval;
+       quad_t quadval;
+       int mib[CTL_MAXNAME];
+       char *cp, *bufp, buf[BUFSIZ], fmt[BUFSIZ];
+       u_int kind;
+
+       bufp = buf;
+       snprintf(buf, BUFSIZ, "%s", string);
+       if ((cp = strchr(string, '=')) != NULL) {
+               if (!wflag)
+                       errx(2, "must specify -w to set variables");
+               *strchr(buf, '=') = '\0';
+               *cp++ = '\0';
+               while (isspace(*cp))
+                       cp++;
+               newval = cp;
+               newsize = strlen(cp);
+       } else {
+               if (wflag)
+                       usage();
+       }
+       len = name2oid(bufp, mib);
+
+       if (len < 0) {
+               if (cp != NULL) {
+                       while (*cp != '\0') cp--;
+                       *cp = '=';
+               }
+               old_parse (string, flags);
+               return;
+       }
+
+       if (oidfmt(mib, len, fmt, &kind))
+               err(1, "couldn't find format of oid '%s'", bufp);
+
+       if (!wflag) {
+               if ((kind & CTLTYPE) == CTLTYPE_NODE) {
+                       sysctl_all(mib, len);
+                       foundSome = 1;
+                       old_parse (string, flags);
+               } else {
+                       i = show_var(mib, len);
+                       if (!i && !bflag)
+                               putchar('\n');
+               }
+       } else {
+               if ((kind & CTLTYPE) == CTLTYPE_NODE)
+                       errx(1, "oid '%s' isn't a leaf node", bufp);
+
+               if (!(kind&CTLFLAG_WR))
+                       errx(1, "oid '%s' is read only", bufp);
+       
+               switch (kind & CTLTYPE) {
+                       case CTLTYPE_INT:
+                               if ((*fmt == 'I') && (*(fmt + 1) == 'U')) {
+                                       uintval = (unsigned int) strtoul (newval, NULL, 0);
+                                       newval = &uintval;
+                                       newsize = sizeof uintval;
+                               } else {
+                                       intval = (int) strtol(newval, NULL, 0);
+                                       newval = &intval;
+                                       newsize = sizeof intval;
+                               }
+                               break;
+                       case CTLTYPE_STRING:
+                               break;
+                       case CTLTYPE_QUAD:
+                               break;
+                               sscanf(newval, "%qd", &quadval);
+                               newval = &quadval;
+                               newsize = sizeof quadval;
+                               break;
+                       default:
+                               errx(1, "oid '%s' is type %d,"
+                                       " cannot set that", bufp,
+                                       kind & CTLTYPE);
+               }
+
+               i = show_var(mib, len);
+               if (sysctl(mib, len, 0, 0, newval, newsize) == -1) {
+                       if (!i && !bflag)
+                               putchar('\n');
+                       switch (errno) {
+                       case EOPNOTSUPP:
+                               errx(1, "%s: value is not available", 
+                                       string);
+                       case ENOTDIR:
+                               errx(1, "%s: specification is incomplete", 
+                                       string);
+                       case ENOMEM:
+                               errx(1, "%s: type is unknown to this program", 
+                                       string);
+                       default:
+                               warn("%s", string);
+                               return;
+                       }
+               }
+               if (!bflag)
+                       printf(" -> ");
+               i = nflag;
+               nflag = 1;
+               j = show_var(mib, len);
+               if (!j && !bflag)
+                       putchar('\n');
+               nflag = i;
+       }
+}
+
+/* These functions will dump out various interesting structures. */
+
+static int
+S_clockinfo(int l2, void *p)
+{
+       struct clockinfo *ci = (struct clockinfo*)p;
+       if (l2 != sizeof *ci)
+               err(1, "S_clockinfo %d != %d", l2, sizeof *ci);
+       printf("{ hz = %d, tick = %d, tickadj = %d, profhz = %d, stathz = %d }",
+               ci->hz, ci->tick, ci->tickadj, ci->profhz, ci->stathz);
+       return (0);
+}
+
+static int
+S_loadavg(int l2, void *p)
+{
+       struct loadavg *tv = (struct loadavg*)p;
+
+       if (l2 != sizeof *tv)
+               err(1, "S_loadavg %d != %d", l2, sizeof *tv);
+
+       printf("{ %.2f %.2f %.2f }",
+               (double)tv->ldavg[0]/(double)tv->fscale,
+               (double)tv->ldavg[1]/(double)tv->fscale,
+               (double)tv->ldavg[2]/(double)tv->fscale);
+       return (0);
+}
+
+static int
+S_timeval(int l2, void *p)
+{
+       struct timeval *tv = (struct timeval*)p;
+       time_t tv_sec;
+       char *p1, *p2;
+
+       if (l2 != sizeof *tv)
+               err(1, "S_timeval %d != %d", l2, sizeof *tv);
+       printf("{ sec = %ld, usec = %ld } ",
+               (long) tv->tv_sec, (long) tv->tv_usec);
+       tv_sec = tv->tv_sec;
+       p1 = strdup(ctime(&tv_sec));
+       for (p2=p1; *p2 ; p2++)
+               if (*p2 == '\n')
+                       *p2 = '\0';
+       fputs(p1, stdout);
+       return (0);
+}
+
+static int
+T_dev_t(int l2, void *p)
+{
+       dev_t *d = (dev_t *)p;
+       if (l2 != sizeof *d)
+               err(1, "T_dev_T %d != %d", l2, sizeof *d);
+       if ((int)(*d) != -1) {
+               if (minor(*d) > 255 || minor(*d) < 0)
+                       printf("{ major = %d, minor = 0x%x }",
+                               major(*d), minor(*d));
+               else
+                       printf("{ major = %d, minor = %d }",
+                               major(*d), minor(*d));
+       }
+       return (0);
+}
+
+/*
+ * These functions uses a presently undocumented interface to the kernel
+ * to walk the tree and get the type so it can print the value.
+ * This interface is under work and consideration, and should probably
+ * be killed with a big axe by the first person who can find the time.
+ * (be aware though, that the proper interface isn't as obvious as it
+ * may seem, there are various conflicting requirements.
+ */
+
+static int
+name2oid(char *name, int *oidp)
+{
+       int oid[2];
+       int i;
+       size_t j;
+
+       oid[0] = 0;
+       oid[1] = 3;
+
+       j = CTL_MAXNAME * sizeof (int);
+       i = sysctl(oid, 2, oidp, &j, name, strlen(name));
+       if (i < 0) 
+               return i;
+       j /= sizeof (int);
+       return (j);
+}
+
+static int
+oidfmt(int *oid, int len, char *fmt, u_int *kind)
+{
+       int qoid[CTL_MAXNAME+2];
+       u_char buf[BUFSIZ];
+       int i;
+       size_t j;
+
+       qoid[0] = 0;
+       qoid[1] = 4;
+       memcpy(qoid + 2, oid, len * sizeof(int));
+
+       j = sizeof buf;
+       i = sysctl(qoid, len + 2, buf, &j, 0, 0);
+       if (i)
+               err(1, "sysctl fmt %d %d %d", i, j, errno);
+
+       if (kind)
+               *kind = *(u_int *)buf;
+
+       if (fmt)
+               strcpy(fmt, (char *)(buf + sizeof(u_int)));
+       return 0;
+}
+
+/*
+ * This formats and outputs the value of one variable
+ *
+ * Returns zero if anything was actually output.
+ * Returns one if didn't know what to do with this.
+ * Return minus one if we had errors.
+ */
+
+static int
+show_var(int *oid, int nlen)
+{
+       u_char buf[BUFSIZ], *val, *p;
+       char name[BUFSIZ], /* descr[BUFSIZ], */ *fmt;
+       int qoid[CTL_MAXNAME+2];
+       int i;
+       size_t j, len;
+       u_int kind;
+       int (*func)(int, void *) = 0;
+
+       qoid[0] = 0;
+       memcpy(qoid + 2, oid, nlen * sizeof(int));
+
+       qoid[1] = 1;
+       j = sizeof name;
+       i = sysctl(qoid, nlen + 2, name, &j, 0, 0);
+       if (i || !j)
+               err(1, "sysctl name %d %d %d", i, j, errno);
+
+       /* find an estimate of how much we need for this var */
+       j = 0;
+       i = sysctl(oid, nlen, 0, &j, 0, 0);
+       j += j; /* we want to be sure :-) */
+
+       val = alloca(j);
+       len = j;
+       i = sysctl(oid, nlen, val, &len, 0, 0);
+       if (i || !len)
+               return (1);
+
+       if (bflag) {
+               fwrite(val, 1, len, stdout);
+               return (0);
+       }
+
+       qoid[1] = 4;
+       j = sizeof buf;
+       i = sysctl(qoid, nlen + 2, buf, &j, 0, 0);
+       if (i || !j)
+               err(1, "sysctl fmt %d %d %d", i, j, errno);
+
+       kind = *(u_int *)buf;
+
+       fmt = (char *)(buf + sizeof(u_int));
+
+       p = val;
+       switch (*fmt) {
+       case 'A':
+               if (!nflag)
+                       printf("%s: ", name);
+               printf("%s", p);
+               return (0);
+               
+       case 'I':
+               if (!nflag)
+                       printf("%s: ", name);
+               fmt++;
+               val = "";
+               while (len >= sizeof(int)) {
+                       if(*fmt == 'U')
+                               printf("%s%u", val, *(unsigned int *)p);
+                       else
+                               printf("%s%d", val, *(int *)p);
+                       val = " ";
+                       len -= sizeof (int);
+                       p += sizeof (int);
+               }
+               return (0);
+
+       case 'L':
+               if (!nflag)
+                       printf("%s: ", name);
+               fmt++;
+               val = "";
+               while (len >= sizeof(long)) {
+                       if(*fmt == 'U')
+                               printf("%s%lu", val, *(unsigned long *)p);
+                       else
+                               printf("%s%ld", val, *(long *)p);
+                       val = " ";
+                       len -= sizeof (long);
+                       p += sizeof (long);
+               }
+               return (0);
+
+       case 'P':
+               if (!nflag)
+                       printf("%s: ", name);
+               printf("%p", *(void **)p);
+               return (0);
+
+       case 'T':
+       case 'S':
+               i = 0;
+               if (!strcmp(fmt, "S,clockinfo"))        func = S_clockinfo;
+               else if (!strcmp(fmt, "S,timeval"))     func = S_timeval;
+               else if (!strcmp(fmt, "S,loadavg"))     func = S_loadavg;
+               else if (!strcmp(fmt, "T,dev_t"))       func = T_dev_t;
+               if (func) {
+                       if (!nflag)
+                               printf("%s: ", name);
+                       return ((*func)(len, p));
+               }
+               /* FALL THROUGH */
+       default:
+               if (!Aflag)
+                       return (1);
+               if (!nflag)
+                       printf("%s: ", name);
+               printf("Format:%s Length:%ld Dump:0x", fmt, len);
+               while (len--) {
+                       printf("%02x", *p++);
+                       if (Xflag || p < val+16)
+                               continue;
+                       printf("...");
+                       break;
+               }
+               return (0);
+       }
+       return (1);
+}
+
+static int
+sysctl_all (int *oid, int len)
+{
+       int name1[22], name2[22];
+       int i, j;
+       size_t l1, l2;
+
+       name1[0] = 0;
+       name1[1] = 2;
+       l1 = 2;
+       if (len) {
+               memcpy(name1+2, oid, len*sizeof (int));
+               l1 += len;
+       } else {
+               name1[2] = 1;
+               l1++;
+       }
+       while (1) {
+               l2 = sizeof name2;
+               j = sysctl(name1, l1, name2, &l2, 0, 0);
+               if (j < 0) {
+                       if (errno == ENOENT)
+                               return 0;
+                       else
+                               err(1, "sysctl(getnext) %d %d", j, l2);
+               }
+
+               l2 /= sizeof (int);
+
+               if (l2 < len)
+                       return 0;
+
+               for (i = 0; i < len; i++)
+                       if (name2[i] != oid[i])
+                               return 0;
+
+               i = show_var(name2, l2);
+               if (!i && !bflag)
+                       putchar('\n');
+
+               memcpy(name1+2, name2, l2*sizeof (int));
+               l1 = 2 + l2;
+       }
+}
diff --git a/top.tproj/Makefile b/top.tproj/Makefile
new file mode 100644 (file)
index 0000000..8dbfac9
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# 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 = top
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = top.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble top.1
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /usr/bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+FRAMEWORKS = -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/top.tproj/Makefile.postamble b/top.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..5b674d4
--- /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/man1
+       install -c -m 444 top.1 $(DSTROOT)/usr/share/man/man1/top.1
diff --git a/top.tproj/Makefile.preamble b/top.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..44fbaaa
--- /dev/null
@@ -0,0 +1,139 @@
+###############################################################################
+#  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)
+
+AFTER_INSTALL += install-man-page
diff --git a/top.tproj/PB.project b/top.tproj/PB.project
new file mode 100644 (file)
index 0000000..b1fcde6
--- /dev/null
@@ -0,0 +1,26 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (IOKit.framework); 
+        H_FILES = (); 
+        OTHER_LINKED = (top.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, top.1); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = /bin/gnumake; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = top; 
+    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/top.tproj/top.1 b/top.tproj/top.1
new file mode 100644 (file)
index 0000000..aee3997
--- /dev/null
@@ -0,0 +1,194 @@
+.\" Copyright (c) 1999, Apple Computer, Inc.  All rights reserved.
+.\"
+.Dd September 30, 1999
+.Dt TOP 1
+.Os "Mac OS X"
+.Sh NAME
+.Nm top
+.Nd show system usage statistics
+.Sh SYNOPSIS
+.Nm top
+.Op Fl u
+.Op Fl w
+.Op Fl k
+.Op Fl s Ar interval
+.Op Fl e | Fl d | Fl a
+.Op Fl l Ar samples
+.Op Ar number
+.Sh DESCRIPTION
+.Nm top 
+displays an ongoing sample of system usage statistics.  It operates
+in various modes, but by default shows cpu utilization and
+memory usage for each process in the system.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl u
+When the
+.Fl u
+option is specified, processes are first sorted by cpu usage 
+and then displayed starting with the highest consumers.
+.It Fl w
+Specifying the
+.Fl w
+option generates additional columns in the output producing
+a much wider display of data. The additional columns include
+VPRVT, along with the delta information for #PRTS,
+RPRVT, RSHRD, RSIZE and VSIZE (see descriptions following).
+.It Fl k
+The
+.Fl k
+option causes
+.Nm top
+to traverse and report the memory object map for pid 0
+(the kernel task).  It is optional because it is fairly
+expensive to traverse the object maps and the kernel
+task may have a huge number of entries.
+.It Fl s
+By default,
+.Nm top
+updates its output at one second intervals. This sampling
+interval may be changed by specifying the
+.Fl s
+option.  Enter the
+.Ar interval
+in seconds.
+.It Fl e
+Using the
+.Fl e
+option switches from the default output to an event counting
+mode where the counts reported are absolute counters.  The
+.Fl w
+and
+.Fl k
+options are ignored when running in event counting mode.
+.It Fl d
+Using the
+.Fl d
+option switches from the default output to an event counting
+mode where the counts are reported as deltas relative to
+the previous sample.
+The
+.Fl w
+and
+.Fl k
+options are ignored when running in event counting, delta mode.
+.It Fl a
+Using the
+.Fl a
+option switches from the default output to an event counting
+mode where the counts are reported as cumulative counters relative to
+when top was launched.
+The
+.Fl w
+and
+.Fl k
+options are ignored when running in event counting, accumulate mode.
+.It Fl l
+Using the
+.Fl l
+option switches from the default screen mode to a logging mode suitable for
+saving the output to a file.  You may specify the number of samples to be
+output before top exits, the default is 1 sample.
+.It number
+If you wish to limit the number of processes displayed by
+.Nm top,
+specify the desired 
+.Ar number
+of output lines in this last argument.
+.El
+.Pp
+The columns displayed in the default data mode are as follows:
+.Bl -tag -width VSIZE(deltadelta) -compact
+.Pp
+.It PID
+the Unix process id.
+.It COMMAND
+the Unix command name.
+.It %CPU
+the percentage of cpu consumed (kernel and user).
+.It TIME
+the absolute cpu consumption (min:secs.hundreths).
+.It #TH
+the number of threads.
+.It #PRTS(delta)
+the number of mach ports.
+.It #MREG
+the number of memory regions.
+.It VPRVT(-w only)
+the private address space currently allocated.
+.It RPRVT(delta)
+the resident private memory.
+.It RSHRD(delta)
+the resident shared memory (as represented by the
+resident page count of each shared memory object).
+.It RSIZE(delta)
+the total resident memory (real pages that this
+process currently has associated with it.  Some
+may be shared by other processes).
+.It VSIZE(delta)
+the total address space currently allocated (including shared).
+.El
+.Pp
+The delta columns are enabled by the
+.Fl w
+option.  The deltas for #PRTS and VSIZE are relative
+to the numbers observed when
+.Nm top
+was launched.  The deltas for RPRVT, RSHRD and RSIZE are relative to
+the previous sample.  If the 
+.Fl w
+option was not specified, 
+.Nm top
+will append either a '+' or a '-' to the RPRVT, RSHRD, RSIZE or VSIZE
+columns indicating either a gain or a loss relative to the previous sample.
+.Pp
+The columns displayed in the event counting modes (ie: -e | -d | -a options) 
+are as follows:
+.Bl -tag -width MACHSYSCALL -compact
+.Pp
+.It PID
+the Unix process id.
+.It COMMAND
+the Unix command name.
+.It %CPU
+the percentage of cpu consumed (kernel and user).
+.It TIME
+the absolute cpu consumption (min:secs.hundreths).
+.It FAULTS
+the number of page faults.
+.It PAGEINS
+the number of requests for pages from a pager.
+.It COW_FAULTS
+the number of faults that caused a page to be copied.
+.It MSGS_SENT
+the number of mach messages sent by the process.
+.It MSGS_RCVD
+the number of mach messages received by the process.
+.It BSDSYSCALL
+the number of BSD system calls made by the process.
+.It MACHSYSCALL
+the number of MACH system calls made by the process.
+.It CSWITCH
+the number of context switches to this process.
+.El
+.Pp
+The
+.Nm top
+command also displays some global state in the first few lines of output,
+including load averages, cpu utilization and idleness, process and thread counts and memory breakdowns
+for shared libraries and processes.
+The
+.Nm top
+command is SIGWINCH savvy, so adjusting your window geometry may change
+the number of processes and number of columns displayed.  Typing a 'q' will cause top to exit
+immediately. Typing any other character will cause top to immediately update it's display.
+.Sh SAMPLE USAGE
+.Pp
+top -u -s5 20
+.Pp
+.Nm top
+will sort the processes according to cpu usage, update the output at 5 
+second intervals, and limit the display to the top 20 processes.
+.Sh SEE ALSO
+.Xr vm_stat 1
diff --git a/top.tproj/top.c b/top.tproj/top.c
new file mode 100644 (file)
index 0000000..3907ed8
--- /dev/null
@@ -0,0 +1,2297 @@
+/*
+ *  Top users display for Berkeley Unix
+ *  Version 1.8
+ *
+ *  This program may be freely redistributed to other Unix sites, but this
+ *  entire comment MUST remain intact.
+ *
+ *  Copyright (c) 1984, William LeFebvre, Rice University
+ *
+ *  This program is designed to run on either Berkeley 4.1 or 4.2 Unix.
+ *  Compile with the preprocessor constant "FOUR_ONE" set to get an
+ *  executable that will run on Berkeley 4.1 Unix.
+ *
+ *  The Sun kernel uses scaled integers instead of floating point so compile
+ *  with the preprocessor variable "SUN" to get an executable that will run
+ *  on Sun Unix version 1.1 or later.
+ *
+ *  Fixes and enhancements since version 1.5:
+ *
+ *  Jonathon Feiber at sun:
+ *     added "#ifdef SUN" code to make top work on a Sun,
+ *     fixed race bug in getkval for getting user structure,
+ *     efficiency improvements:  added register variables and
+ *     removed the function hashit
+ *
+ *     added real and virtual memory status line
+ *
+ *     added second "key" to the qsort comparisn function "proc_compar"
+ *     which sorts by on cpu ticks if percentage is equal
+ *
+ **********************************************************************
+ * HISTORY
+ * 22-Apr-99  Avadis Tevanian (avie) at Apple
+ *     Another rewrite for Mach 3.0
+ *
+ * 21-Apr-90  Avadis Tevanian (avie) at NeXT
+ *     Completely rewritten again for processor sets.
+ *
+ *  6-May-88  David Golub (dbg) at Carnegie-Mellon University
+ *     Completely rewritten for MACH.  This version will NOT run on any
+ *     other version of BSD.
+ *
+ */
+
+#define        Default_TOPN    16      /* default number of lines */
+#define        Default_DELAY   1       /* default delay interval */
+#define IOKIT 1                        /* for io_name_t in device_types.h */
+
+#include <mach/mach.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <nlist.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <mach/bootstrap.h>
+#include <mach/host_info.h>
+#include <mach/mach_error.h>
+#include <mach/mach_types.h>
+#include <mach/message.h>
+#include <mach/vm_region.h>
+#include <mach/vm_map.h>
+#include <mach/vm_types.h>
+#include <mach/vm_prot.h>
+
+#include <device/device_types.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOBlockStorageDriver.h>
+
+#include <kvm.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_var.h>
+
+#include <libc.h>
+#include <termios.h>
+#include <bsd/curses.h>
+
+/* Number of lines of header information on the standard screen */
+#define        HEADER_LINES    8
+
+#define sec_to_minutes(t)       ((t) / 60)
+#define sec_to_seconds(t)       ((t) % 60)
+#define usec_to_100ths(t)       ((t) / 10000)
+
+#ifndef        TH_USAGE_SCALE
+#define        TH_USAGE_SCALE  1000
+#endif TH_USAGE_SCALE
+#define usage_to_percent(u)    ((u*100)/TH_USAGE_SCALE)
+#define usage_to_tenths(u)     (((u*1000)/TH_USAGE_SCALE) % 10)
+
+
+#define time_value_sub(tvp, uvp, vvp)                                   \
+  do {                                                                  \
+     (vvp)->seconds = (tvp)->seconds - (uvp)->seconds;                  \
+     (vvp)->microseconds = (tvp)->microseconds - (uvp)->microseconds;   \
+     if ((vvp)->microseconds < 0) {                                     \
+         (vvp)->seconds--;                                              \
+         (vvp)->microseconds += 1000000;                                \
+     }                                                                  \
+  } while (0)
+     
+
+
+/* From libcurses */
+int wclear(WINDOW *win);
+int wmove(WINDOW *win, int y, int x);
+int wrefresh(WINDOW *win);
+int endwin(void);
+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;
+double userticks, systicks, idleticks, totalticks;
+
+struct timeval cur_tod;
+struct timeval start_tod;
+struct timeval last_tod;
+struct timeval elapsed_tod;
+int    elapsed_milliseconds;
+int    newLINES = 0;
+int    Header_lines = HEADER_LINES;
+
+int do_proc0_vm;
+int sort_by_usage;
+int wide_output;
+int oneshot;
+int logcnt;
+int events_only;
+int events_delta;
+int events_accumulate;
+long start_time = 0;
+
+
+struct io_stats {
+        UInt64  io_accum;
+        UInt64  io_prev;
+        UInt64  io;
+        UInt64  kbytes_accum;
+        UInt64  kbytes_prev;
+        UInt64  kbytes;
+};
+
+struct io_stats i_net, o_net;
+struct io_stats i_dsk, o_dsk;
+struct io_stats i_vm,  o_vm;
+
+
+io_iterator_t       drivelist  = 0;  /* needs release */
+mach_port_t         masterPort = 0;
+
+
+struct proc_info {
+       uid_t                   uid;
+       short                   pid;
+       short                   ppid;
+       short                   pgrp;
+       int                     status;
+       int                     flag;
+
+       int                     state;
+       int                     pri;
+       int                     base_pri;
+       boolean_t               all_swapped;
+        boolean_t               has_idle_thread;
+       time_value_t            total_time;
+       time_value_t            idle_time;
+       time_value_t            beg_total_time;
+       time_value_t            beg_idle_time;
+
+       vm_size_t               virtual_size;
+       vm_size_t               resident_size;
+       vm_size_t               orig_virtual_size;
+       vm_offset_t             drsize, dvsize;
+       vm_offset_t             drprvt, drshrd;
+        vm_offset_t            rvsize;
+        unsigned int            shared;
+        unsigned int            private;
+        unsigned int            vprivate;
+        int                     obj_count;
+       int                     cpu_usage;
+       int                     cpu_idle;
+
+       char                    command[20];
+
+       int                     num_ports;
+        int                     orig_num_ports;
+        int                     dnum_ports;
+       int                     num_threads;
+       thread_basic_info_t     threads;        /* array */
+        task_events_info_data_t tei;
+        task_events_info_data_t deltatei;
+        task_events_info_data_t accumtei;
+};
+
+typedef        struct proc_info        *proc_info_t;
+
+mach_port_t host_priv_port, host_port;
+
+struct object_info {
+        int                id;
+        int                 pid;
+        int                 share_type;
+        int                 resident_page_count;
+        int                 ref_count;
+        int                 task_ref_count;
+        int                 size;
+        struct object_info  *next;
+};
+
+#define OBJECT_TABLE_SIZE      537
+#define OT_HASH(object) (((unsigned)object)%OBJECT_TABLE_SIZE)
+
+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
+ *     entire task, the lower-numbered state dominates.
+ */
+#define        STATE_MAX       7
+
+int
+mach_state_order(s, sleep_time)
+        int s;
+        long sleep_time;
+ {
+       switch (s) {
+       case TH_STATE_RUNNING:          return(1);
+       case TH_STATE_UNINTERRUPTIBLE:
+                                       return(2);
+       case TH_STATE_WAITING:          return((sleep_time > 20) ? 4 : 3);
+       case TH_STATE_STOPPED:          return(5);
+       case TH_STATE_HALTED:           return(6);
+       default:                        return(7);
+       }
+}
+                           /*01234567 */
+char   mach_state_table[] = "ZRUSITH?";
+
+char * state_name[] = {
+               "zombie",
+               "running",
+               "stuck",
+               "sleeping",
+               "idle",
+               "stopped",
+               "halted",
+               "unknown",
+};
+int            state_breakdown[STATE_MAX+1];
+
+
+char *state_to_string(pi)
+       proc_info_t     pi;
+{
+       static char     s[5];           /* STATIC! */
+
+       s[0] = mach_state_table[pi->state];
+       s[1] = (pi->all_swapped) ? 'W' : ' ';
+       s[2] = (pi->base_pri > 50) ? 'N' :
+                       (pi->base_pri < 40) ? '<' : ' ';
+       s[3] = ' ';
+       s[4] = '\0';
+       return(s);
+}
+
+void print_time(char *p, time_value_t t)
+{
+       long    seconds, useconds, minutes, hours;
+
+       seconds = t.seconds;
+       useconds = t.microseconds;
+       minutes = seconds / 60;
+       hours = minutes / 60;
+
+       if (minutes < 100) { // up to 100 minutes
+               sprintf(p, "%2ld:%02ld.%02ld", minutes, seconds % 60,
+                       usec_to_100ths(useconds));
+       }
+       else if (hours < 100) { // up to 100 hours
+               sprintf(p, "%2ld:%02ld:%02ld", hours, minutes % 60,
+                               seconds % 60);
+       }
+       else {
+               sprintf(p, "%4ld hrs", hours);
+       }
+}
+
+
+void
+print_usage(char *p, int cpu_usage)
+{
+        int left_of_decimal;
+        int right_of_decimal; 
+
+       if (elapsed_milliseconds) {
+               left_of_decimal = (cpu_usage * 100) / elapsed_milliseconds;
+       
+               right_of_decimal = (((cpu_usage * 100) - (left_of_decimal * elapsed_milliseconds)) * 10) /
+                                  elapsed_milliseconds;
+       } else {
+               left_of_decimal = 0;
+               right_of_decimal = 0;
+       }
+       sprintf(p, "%3d.%01d%%%%", left_of_decimal, right_of_decimal);  /* %cpu */
+}
+
+
+
+char *
+digits(n)
+       float   n;
+{
+       static char     tmp[10];        /* STATIC! */
+
+       if ((n > 0) && (n < 10))
+               sprintf(tmp, "%4.2f", n);
+       else if ((n > 0) && (n < 100))
+               sprintf(tmp, "%4.1f", n);
+       else if ((n < 0) && (n > -10))
+               sprintf(tmp, "%4.1f", n);
+       else
+               sprintf(tmp, "%4.0f", n);
+       return(tmp);
+}
+
+char *
+mem_to_string(n)
+       unsigned long long  n;
+{
+       static char     s[10];          /* STATIC! */
+
+       /* convert to kilobytes */
+       n /= 1024;
+
+       if (n > 1024*1024)
+               sprintf(s, "%sG", digits(((float)n)/(1024.0*1024.0)));
+       else if (n > 1024)
+               sprintf(s, "%sM", digits((float)n/(1024.0)));
+       else
+               sprintf(s, "%dK", (int)n);
+
+       return(s);
+}
+
+char *
+offset_to_string(n)
+       int             n;
+{
+       static char     s[10];          /* STATIC! */
+       int             an;
+
+       /* convert to kilobytes */
+       n /= 1024;
+       an = abs(n);
+
+       if (an > 1024*1024)
+               sprintf(s, "%sG", digits(((float)n)/(1024.0*1024.0)));
+       else if (an > 1024)
+               sprintf(s, "%sM", digits((float)n/(1024.0)));
+       else
+               sprintf(s, "%dK", n);
+
+       return(s);
+}
+
+mach_port_t get_host_priv()
+{
+       return(mach_host_self());
+}
+
+mach_port_t get_host_port()
+{
+       return(mach_host_self());
+}
+
+void
+shared_hash_enter(int obj_id, int share_type, int resident_page_count, int ref_count, int size, int pid)
+{
+        register struct object_info **bucket;
+        register struct object_info *of;
+
+       of = shared_hash_table[OT_HASH(obj_id/OBJECT_TABLE_SIZE)];
+       while (of) {
+               if (of->id == obj_id) {
+                       of->size += size;
+                       of->task_ref_count++;
+                       of->pid = pid;
+                       return;
+               }
+               of = of->next;
+       }
+       bucket = &shared_hash_table[OT_HASH(obj_id/OBJECT_TABLE_SIZE)];
+
+       if (of = of_free_list)
+               of_free_list = of->next;
+       else
+               of = (struct object_info *) malloc(sizeof(*of));
+
+       of->resident_page_count = resident_page_count;
+       of->id = obj_id;
+       of->share_type = share_type;
+       of->ref_count = ref_count;
+       of->task_ref_count = 1;
+       of->pid = pid;
+       of->size = size;
+
+       of->next = *bucket;
+       *bucket = of;
+}
+
+void
+pmem_doit(task_port_t task, int pid, int *shared, int *private, int *aliased, int *obj_count, int *vprivate, vm_size_t *vsize, unsigned long long *fw_private)
+{
+       vm_address_t    address = 0;
+       kern_return_t   err = 0;
+       register int    i;
+       int             split = 0;
+
+       *obj_count = *aliased = *shared = *private = *vprivate = 0;
+
+       while (1) {
+               mach_port_t             object_name;
+               vm_region_top_info_data_t info;
+               mach_msg_type_number_t  count;
+               vm_size_t               size;
+
+               if ( !split && (address >= FW_CODE_BEG_ADDR && address < FW_DATA_END_ADDR)) {
+                       vm_region_basic_info_data_64_t    b_info;
+                         
+                       count = VM_REGION_BASIC_INFO_COUNT_64;
+                       if (err = vm_region_64(task, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)&b_info,
+                                           &count, &object_name))
+                               break;
+
+                       if (b_info.reserved)
+                               split = 1;
+               }
+               count = VM_REGION_TOP_INFO_COUNT;
+
+               if (err = vm_region(task, &address, &size, VM_REGION_TOP_INFO, (vm_region_info_t)&info,
+                                   &count, &object_name))
+                       break;
+
+               if (address >= FW_CODE_BEG_ADDR && address < FW_DATA_END_ADDR) {
+
+                       *fw_private += info.private_pages_resident * vm_page_size;
+
+                       if (info.share_mode != SM_PRIVATE) {
+                               address += size;
+                               continue;
+                       }
+               }
+               address += size;
+
+               *obj_count += 1;
+
+               switch (info.share_mode) {
+
+               case SM_PRIVATE:
+                       *private  += info.private_pages_resident * vm_page_size;
+                       *vprivate += size;
+                       break;
+
+               case SM_COW:
+                       if (info.ref_count == 1)
+                               info.share_mode = SM_PRIVATE;
+                       if (pid && info.share_mode == SM_COW)
+                                shared_hash_enter(info.obj_id, SM_COW, info.shared_pages_resident,
+                                                 info.ref_count, size, pid);
+                       if (info.share_mode == SM_PRIVATE)
+                               *private += info.shared_pages_resident * vm_page_size;
+                       *private  += info.private_pages_resident * vm_page_size;
+                       
+                       if (info.share_mode == SM_PRIVATE)
+                               *vprivate += size;
+                       else
+                               *vprivate += info.private_pages_resident * vm_page_size;
+                       break;
+
+               case SM_SHARED:
+                       if (pid)
+                                shared_hash_enter(info.obj_id, SM_SHARED, info.shared_pages_resident,
+                                                 info.ref_count, size, pid);
+                       break;
+               }
+        }
+        for (i = 0; i < OBJECT_TABLE_SIZE; i++) {
+               register struct object_info *sl;
+
+               sl = shared_hash_table[i];
+               
+               while (sl) {
+                       if (sl->pid == pid) {
+                               if (sl->share_type == SM_SHARED) {
+                                       if (sl->ref_count == sl->task_ref_count) {
+                                               sl->share_type = SM_PRIVATE_ALIASED;
+                               
+                                               *aliased  += sl->resident_page_count * vm_page_size;
+                                               *vprivate += sl->size;
+                                       }
+                               }
+                               if (sl->share_type != SM_PRIVATE_ALIASED)
+                                       *shared += sl->resident_page_count * vm_page_size;
+                       }
+                       sl->task_ref_count = 0;
+
+                       sl = sl->next;
+               }
+       }
+       if (split)
+               *vsize -= (FW_DATA_END_ADDR - FW_CODE_BEG_ADDR);
+}
+
+
+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;
+       kern_return_t   err = 0;
+       int             state = 0;
+
+       *vsize  = 0;
+        *num_fw = 0; 
+        *code_size = 0;
+        *data_size = 0;
+        *linkedit_size = 0;
+
+       while (address < FW_DATA_END_ADDR) {
+               vm_region_submap_info_data_64_t   s_info;
+               mach_msg_type_number_t         count;
+               vm_size_t       size;
+               int             nesting_depth;
+
+                nesting_depth = 1;
+               count = VM_REGION_SUBMAP_INFO_COUNT_64;
+
+               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)
+                       break;
+               if (address < FW_DATA_BEG_ADDR) {
+
+                       if (s_info.share_mode == SM_SHARED || s_info.share_mode == SM_COW) {
+                               if (s_info.max_protection & VM_PROT_EXECUTE) {
+                                       *code_size += (s_info.pages_resident * vm_page_size);
+
+                                       if (state == 0)
+                                               *num_fw += 1;
+                                       state = 1;
+
+                               } else {
+                                       *linkedit_size += (s_info.pages_resident * vm_page_size);
+                                       
+                                       state = 0;
+                               }
+                       }
+
+               } else {
+                       if (s_info.share_mode == SM_SHARED || s_info.share_mode == SM_COW || s_info.share_mode == SM_TRUESHARED)
+                               *data_size += (s_info.pages_resident * vm_page_size);
+               }
+               *vsize += size;
+
+               address += size;
+       }
+}
+
+
+
+
+void
+pmem_shared_resident(unsigned long long *total, int *number)
+{       register int i;
+        register int total_size;
+       register int total_num;
+       register struct object_info *sl, *next;
+  
+       total_size = total_num = 0;
+
+        for (i = 0; i < OBJECT_TABLE_SIZE; i++) {
+               sl = shared_hash_table[i];
+               shared_hash_table[i] = 0;
+               
+               while (sl) {
+                       if (sl->share_type != SM_PRIVATE_ALIASED) {
+                               total_size += sl->resident_page_count;
+                               total_num++;
+                       }
+                       next = sl->next;
+
+                       sl->next = of_free_list;
+                       of_free_list = sl;
+
+                       sl = next;
+               }
+       }
+       *number = total_num;
+       *total  = total_size * vm_page_size;
+}
+
+
+int
+get_real_command_name(int pid, char *cbuf, int csize)
+{
+        /*
+        *      Get command and arguments.
+        */
+       volatile int   *ip, *savedip;
+       volatile char  *cp;
+       char            c;
+       char           *end_argc;
+       int             mib[4];
+       char           *arguments;
+       int             arguments_size = 4096;
+       volatile unsigned int *valuep;
+       unsigned int    value;
+       int             blahlen=0, skiplen=0;
+
+       /*
+        * A sysctl() is made to find out the full path that the command
+        * was called with.
+        */
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROCARGS;
+       mib[2] = pid;
+       mib[3] = 0;
+
+       arguments = (char *) malloc(arguments_size);
+       if (sysctl(mib, 3, arguments, (size_t *)&arguments_size, NULL, 0) < 0) {
+               free(arguments);
+               return(0);
+       }
+       end_argc = &arguments[arguments_size];
+
+       ip = (int *)end_argc;
+       ip -= 2;                /* last arg word and .long 0 */
+       while (*--ip) {
+               if (ip == (int *)arguments) {
+                       free(arguments);
+                       return(0);
+               }
+       }        
+       savedip = ip;
+       savedip++;
+       cp = (char *)savedip;
+       while (*--ip) {
+               if (ip == (int *)arguments) {
+                       free(arguments);
+                       return(0);
+               }
+       }        
+       ip++;
+        valuep = (unsigned int *)ip;
+        value = *valuep;
+
+        if ((value & 0xbfff0000) == 0xbfff0000) {
+               ip++; ip++;
+               valuep = ip;
+               blahlen = strlen((char *)ip);
+               skiplen = (blahlen +3 ) /4 ;
+               valuep += skiplen;
+               cp = (char *)valuep;
+               while (!*cp)
+                       cp++;
+               savedip = (int *)cp;
+        }
+        for (cp = (char *)savedip; cp < (end_argc-1); cp++) {
+               c = *cp & 0177;
+
+               if (c == 0)
+                       break;
+        }
+        *cp = 0;
+
+       if (cp > (char *)savedip)
+               cp--;
+
+       while (cp > (char *)savedip) {
+               if (*cp == '/') {
+                       cp++;
+                       break;
+               }
+               cp--;
+       }
+        if (cp[0] == '-' || cp[0] == '?' || cp[0] <= ' ') {
+               /*
+                *  Not enough information
+                */
+               free(arguments);
+               return(0);
+        }
+       (void) strncpy(cbuf, (char *)cp, csize);
+       cbuf[csize] = '\0';
+
+       free(arguments);
+       return(1);
+}
+
+
+/* All of this should come out of the process manager... */
+
+void get_proc_info(kpb, pi)
+       struct kinfo_proc       *kpb;
+       struct proc_info        *pi;
+{
+       task_port_t     task;
+       mach_port_array_t       names, types;
+       unsigned int    ncnt, tcnt;
+
+       pi->uid = kpb->kp_eproc.e_ucred.cr_uid;
+       pi->pid = kpb->kp_proc.p_pid;
+       pi->ppid        = kpb->kp_eproc.e_ppid;
+       pi->pgrp        = kpb->kp_eproc.e_pgid;
+       pi->status      = kpb->kp_proc.p_stat;
+       pi->flag        = kpb->kp_proc.p_flag;
+
+       /*
+        *      Find the other stuff
+        */
+       if (task_for_pid(mach_task_self(), pi->pid, &task) != KERN_SUCCESS) {
+               pi->status = SZOMB;
+       }
+
+       else {
+               task_basic_info_data_t  ti;
+               unsigned int            count;
+               unsigned int            aliased;
+               thread_array_t          thread_table;
+               unsigned int            table_size;
+               thread_basic_info_t     thi;
+               thread_basic_info_data_t thi_data;
+               int                     i, t_state;
+
+               count = TASK_BASIC_INFO_COUNT;
+               if (task_info(task, TASK_BASIC_INFO, (task_info_t)&ti,
+                               &count) != KERN_SUCCESS) {
+                       pi->status = SZOMB;
+               } else {
+                       pi->virtual_size = ti.virtual_size;
+
+                       pi->resident_size = ti.resident_size;
+
+                       if ((pi->pid || do_proc0_vm) && (!events_only)) {
+                               pmem_doit(task, pi->pid, &pi->shared, &pi->private, &aliased, &pi->obj_count, &pi->vprivate, &pi->virtual_size, &total_fw_private);
+                               pi->private += aliased;
+                       } else {
+                               pi->shared    = 0;
+                               pi->private   = 0;
+                               pi->vprivate  = 0;
+                               pi->obj_count = 0;
+                       }
+                       pi->orig_virtual_size = pi->virtual_size;
+                       pi->total_time = ti.user_time;
+                       time_value_add(&pi->total_time, &ti.system_time);
+                       
+                       pi->idle_time.seconds = 0;
+                       pi->idle_time.microseconds = 0;
+
+                       if (task_threads(task, &thread_table, &table_size) != KERN_SUCCESS)
+                               pi->status = SZOMB;
+                       else {
+                               pi->state = STATE_MAX;
+                               pi->pri = 255;
+                               pi->base_pri = 255;
+                               pi->all_swapped = TRUE;
+                               pi->has_idle_thread = FALSE;
+
+                               thi = &thi_data;
+
+                               pi->num_threads = table_size;
+                               total_threads += table_size;
+
+                               for (i = 0; i < table_size; i++) {
+                                       count = THREAD_BASIC_INFO_COUNT;
+                                       if (thread_info(thread_table[i], THREAD_BASIC_INFO,
+                                                       (thread_info_t)thi, &count) == KERN_SUCCESS) {
+
+                                               if (thi->flags & TH_FLAGS_IDLE) {
+                                                       pi->has_idle_thread = TRUE;
+                                                   
+                                                       time_value_add(&pi->idle_time, 
+                                                                      &thi->user_time);
+                                                       time_value_add(&pi->idle_time,
+                                                                      &thi->system_time);
+                                               } else {
+                                                       time_value_add(&pi->total_time, 
+                                                                      &thi->user_time);
+                                                       time_value_add(&pi->total_time,
+                                                                      &thi->system_time);
+                                               }
+                                               t_state = mach_state_order(thi->run_state,
+                                                                          thi->sleep_time);
+                                               if (t_state < pi->state)
+                                                       pi->state = t_state;
+// update priority info based on schedule policy
+//                                             if (thi->cur_priority < pi->pri)
+//                                                     pi->pri = thi->cur_priority;
+//                                             if (thi->base_priority < pi->base_pri)
+//                                                     pi->base_pri = thi->base_priority;
+                                               if ((thi->flags & TH_FLAGS_SWAPPED) == 0)
+                                                       pi->all_swapped = FALSE;
+
+                                       }
+                                       if (task != mach_task_self()) {
+                                               mach_port_deallocate(mach_task_self(),
+                                                                    thread_table[i]);
+                                       }
+                               }
+                               (void) vm_deallocate(mach_task_self(), (vm_offset_t)thread_table,
+                                                    table_size * sizeof(*thread_table));
+
+                               if (mach_port_names(task, &names, &ncnt,
+                                                   &types, &tcnt) == KERN_SUCCESS) {
+                                       pi->num_ports = ncnt;
+                                       pi->orig_num_ports = ncnt;
+                                       (void) vm_deallocate(mach_task_self(),
+                                                            (vm_offset_t) names,
+                                                            ncnt * sizeof(*names));
+                                       (void) vm_deallocate(mach_task_self(),
+                                                            (vm_offset_t) types,
+                                                            tcnt * sizeof(*types));
+                               } else {
+                                       pi->num_ports = -1;
+                               }
+                       
+                               if (events_only) {
+                                       task_events_info_data_t tei;
+
+                                       count = TASK_EVENTS_INFO_COUNT;
+                                       if (task_info(task, TASK_EVENTS_INFO, (task_info_t)&tei,
+                                                     &count) != KERN_SUCCESS) {
+                                               pi->status = SZOMB;
+                                       } else {
+                                               pi->tei = tei;
+                                               
+                                       }
+                               }
+                       }
+               }
+               if (task != mach_task_self()) {
+                       mach_port_deallocate(mach_task_self(), task);
+               }
+       }
+       if ( strncmp (kpb->kp_proc.p_comm, "LaunchCFMA", 10) ||
+            !get_real_command_name(pi->pid, pi->command, sizeof(kpb->kp_proc.p_comm)-1)) {
+               (void) strncpy(pi->command, kpb->kp_proc.p_comm,
+                              sizeof(kpb->kp_proc.p_comm)-1);
+               pi->command[sizeof(kpb->kp_proc.p_comm)-1] = '\0';
+       }
+}
+
+
+/*
+ *  signal handlers
+ */
+
+void leave()                   /* exit under normal conditions -- INT handler */
+{
+        if (!oneshot) {
+               move(LINES - 1, 0);
+               refresh();
+               endwin();
+
+               tcsetattr(0, TCSANOW, &omode);
+       }
+       exit(0);
+}
+
+void quit(status)              /* exit under duress */
+       int status;
+{
+        if (!oneshot) {
+               endwin();
+               tcsetattr(0, TCSANOW, &omode);
+       }
+       exit(status);
+}
+
+void sigwinch()
+{
+        newLINES = 1;
+}
+
+
+/*
+ *  comparison function for "qsort"
+ *  Do first order sort based on cpu percentage computed by kernel and
+ *  second order sort based on total time for the process.
+ */
+int proc_compar(p1, p2)
+       register struct proc_info **p1;
+       register struct proc_info **p2;
+{
+       if (sort_by_usage) {
+               if ((*p1)->cpu_usage < (*p2)->cpu_usage)
+                       return(1);
+               else if ((*p1)->cpu_usage > (*p2)->cpu_usage)
+                       return(-1);
+               else {
+                       if ((*p1)->total_time.seconds < (*p2)->total_time.seconds)
+                               return(1);
+                       else
+                               return(-1);
+               }
+       }
+       else {
+               if ((*p1)->pid < (*p2)->pid)
+                       return(1);
+               else
+                       return(-1);
+       }
+}
+
+
+int                    nproc, total_procs, old_procs;
+struct kinfo_proc      *kbase, *kpb;
+struct proc_info       *proc,  *pp, *oldproc;
+struct proc_info       **pref, **prefp;
+
+int            topn  = 0;
+int             wanted_topn = 0;
+vm_size_t      pagesize;
+
+
+
+void grab_task(task)
+       task_t  task;
+{
+       int                     pid;
+       size_t                  size;
+       kern_return_t           ret;
+       struct kinfo_proc       ki;
+       int                     mib[4];
+
+       ret = pid_for_task(task, &pid);
+       if (ret != KERN_SUCCESS)
+               return;
+       size = sizeof(ki);
+       mib[0] = CTL_KERN;
+       mib[1] = KERN_PROC;
+       mib[2] = KERN_PROC_PID;
+       mib[3] = pid;
+
+       if (sysctl(mib, 4, &ki, &size, NULL, 0) < 0) {
+               perror("failure calling sysctl");
+               exit(1);
+       }
+       if (ki.kp_proc.p_stat == 0) {
+               state_breakdown[0]++;
+               return;
+       }
+       if (total_procs == nproc) {
+               nproc *= 2;
+               kbase = (struct kinfo_proc *) realloc(kbase,
+                                                     nproc*sizeof(struct kinfo_proc));
+               bzero(&kbase[total_procs], total_procs*sizeof(struct kinfo_proc));
+               proc  = (struct proc_info *) realloc(proc,
+                                                    nproc*sizeof(struct proc_info));
+               bzero(&proc[total_procs], total_procs*sizeof(struct proc_info));
+               oldproc  = (struct proc_info *) realloc(oldproc,
+                                                       nproc*sizeof(struct proc_info));
+               bzero(&oldproc[total_procs], total_procs*sizeof(struct proc_info));
+               pref  = (struct proc_info **) realloc(pref,
+                                                     nproc*sizeof(struct proc_info *));
+               bzero(&pref[total_procs], total_procs*sizeof(struct proc_info *));
+       }
+       kbase[total_procs] = ki;
+       total_procs++;
+}
+
+void update_histdata()
+{
+       struct proc_info        *pp, *oldp;
+       int                     i, j, pid;
+       time_value_t            elapsed_time;
+
+       i = 0;
+       pp = proc;
+
+       // XXX use linear search since list is usually small
+
+       while (i < total_procs) {
+               j = 0;
+               oldp = oldproc;
+               pid = pp->pid;
+
+               while (j < old_procs) {
+                       if (oldp->pid == pid) {
+                               pp->drprvt = pp->private - oldp->private;
+                               pp->drshrd = pp->shared  - oldp->shared;
+                               pp->drsize = pp->resident_size - oldp->resident_size;
+                               pp->dvsize = pp->virtual_size - oldp->virtual_size;
+
+                               pp->rvsize = pp->virtual_size - oldp->orig_virtual_size;
+                               pp->orig_virtual_size = oldp->orig_virtual_size;
+
+                               pp->dnum_ports = pp->num_ports - oldp->orig_num_ports;
+                               pp->orig_num_ports = oldp->orig_num_ports;
+
+                               if (pp->has_idle_thread == TRUE) {
+                                       if (events_accumulate) {
+                                               time_value_sub(&pp->idle_time, &oldp->beg_idle_time, &elapsed_time);
+                                               pp->beg_idle_time = oldp->beg_idle_time;
+                                               pp->idle_time = elapsed_time;
+                                       } else
+                                               time_value_sub(&pp->idle_time, &oldp->idle_time, &elapsed_time);
+
+                                       pp->cpu_idle = (elapsed_time.seconds * 1000) + (elapsed_time.microseconds / 1000);
+                               }
+                               if (events_accumulate) {
+                                       time_value_sub(&pp->total_time, &oldp->beg_total_time, &elapsed_time);
+                                       pp->beg_total_time = oldp->beg_total_time;
+                                       pp->total_time = elapsed_time;
+                               } else
+                                       time_value_sub(&pp->total_time, &oldp->total_time, &elapsed_time);
+
+                               pp->cpu_usage = (elapsed_time.seconds * 1000) + (elapsed_time.microseconds / 1000);
+
+                               if (events_delta)
+                               {
+                                   pp->deltatei.pageins = pp->tei.pageins - oldp->tei.pageins;
+                                   pp->deltatei.faults = pp->tei.faults - oldp->tei.faults;
+                                   pp->deltatei.cow_faults = pp->tei.cow_faults - oldp->tei.cow_faults;
+                                   pp->deltatei.messages_sent = pp->tei.messages_sent - oldp->tei.messages_sent;
+                                   pp->deltatei.messages_received = pp->tei.messages_received - oldp->tei.messages_received;
+                                   pp->deltatei.syscalls_unix = pp->tei.syscalls_unix - oldp->tei.syscalls_unix;
+                                   pp->deltatei.syscalls_mach = pp->tei.syscalls_mach - oldp->tei.syscalls_mach;
+                                   pp->deltatei.csw = pp->tei.csw - oldp->tei.csw;
+                               }
+                               if (events_accumulate)
+                               {
+                                   pp->deltatei.pageins = pp->tei.pageins - oldp->accumtei.pageins;
+                                   pp->deltatei.faults = pp->tei.faults - oldp->accumtei.faults;
+                                   pp->deltatei.cow_faults = pp->tei.cow_faults - oldp->accumtei.cow_faults;
+                                   pp->deltatei.messages_sent = pp->tei.messages_sent - oldp->accumtei.messages_sent;
+                                   pp->deltatei.messages_received = pp->tei.messages_received - oldp->accumtei.messages_received;
+                                   pp->deltatei.syscalls_unix = pp->tei.syscalls_unix - oldp->accumtei.syscalls_unix;
+                                   pp->deltatei.syscalls_mach = pp->tei.syscalls_mach - oldp->accumtei.syscalls_mach;
+                                   pp->deltatei.csw = pp->tei.csw - oldp->accumtei.csw;
+
+                                   pp->accumtei = oldp->accumtei;
+                               }
+                               break;
+                       }
+                       j++;
+                       oldp++;
+               }
+               if (j >= old_procs) {
+                       if (events_accumulate) {
+                               pp->accumtei = pp->tei;
+                               pp->beg_total_time = pp->total_time;
+                               pp->beg_idle_time = pp->idle_time;
+
+                               pp->idle_time.seconds = 0;
+                               pp->idle_time.microseconds = 0;
+                               pp->total_time.seconds = 0;
+                               pp->total_time.microseconds = 0;
+                       }
+                       bzero(&pp->deltatei, sizeof (task_events_info_data_t));
+
+                       pp->drprvt = 0;
+                       pp->drshrd = 0;
+                       pp->drsize = 0;
+                       pp->dvsize = 0;
+                       pp->rvsize = 0;
+                       pp->dnum_ports = 0;
+                       pp->cpu_usage = 0;
+                       pp->cpu_idle = 0;
+               }
+               i++;
+               pp++;
+       }
+       bcopy(proc, oldproc, total_procs*sizeof(struct proc_info));
+       old_procs = total_procs;
+}
+
+void read_proc_table()
+{
+       mach_port_t     host;
+       processor_set_t *psets;
+       task_t          *tasks;
+       unsigned int    pcount, tcount;
+       kern_return_t   ret;
+       processor_set_t p;
+       int             i, j;
+
+       total_procs = 0;
+       total_threads = 0;
+
+       host = host_priv_port;
+
+       if (host == MACH_PORT_NULL) {
+               printf("Insufficient privileges.\n");
+               exit(0);
+       }
+       ret = host_processor_sets(host, &psets, &pcount);
+       if (ret != KERN_SUCCESS) {
+               mach_error("host_processor_sets", ret);
+               exit(0);
+       }
+       for (i = 0; i < pcount; i++) {
+               ret = host_processor_set_priv(host, psets[i], &p);
+               if (ret != KERN_SUCCESS) {
+                       mach_error("host_processor_set_priv", ret);
+                       exit(0);       
+               }
+               
+               ret = processor_set_tasks(p, &tasks, &tcount);
+               if (ret != KERN_SUCCESS) {
+                       mach_error("processor_set_tasks", ret);
+                       exit(0);
+               }
+               for (j = 0; j < tcount; j++) {
+                       grab_task(tasks[j]);
+                       // don't delete our own task port
+                       if (tasks[j] != mach_task_self())
+                               mach_port_deallocate(mach_task_self(),  
+                               tasks[j]);
+               }
+               vm_deallocate(mach_task_self(), (vm_address_t)tasks,
+                             tcount * sizeof(task_t));
+               mach_port_deallocate(mach_task_self(), p);
+               mach_port_deallocate(mach_task_self(), psets[i]);
+       }
+       vm_deallocate(mach_task_self(), (vm_address_t)psets,
+                pcount * sizeof(processor_set_t));
+}
+
+kern_return_t getCPU(cpucounters)
+     host_cpu_load_info_t cpucounters;
+{
+     mach_msg_type_number_t count;
+     kern_return_t kr;
+
+     count = HOST_CPU_LOAD_INFO_COUNT;
+     kr = host_statistics (host_priv_port, HOST_CPU_LOAD_INFO,
+                         (host_info_t)cpucounters, &count);
+
+     return(kr);
+}
+
+updateCPU()
+{
+
+        if (events_accumulate) {
+               userticks = curcounters.cpu_ticks[CPU_STATE_USER]-
+                         startcounters.cpu_ticks[CPU_STATE_USER];
+
+               systicks = curcounters.cpu_ticks[CPU_STATE_SYSTEM]-
+                        startcounters.cpu_ticks[CPU_STATE_SYSTEM];
+
+               idleticks = curcounters.cpu_ticks[CPU_STATE_IDLE]-
+                         startcounters.cpu_ticks[CPU_STATE_IDLE];
+       } else if (events_only && !events_delta) {
+
+               userticks = curcounters.cpu_ticks[CPU_STATE_USER];
+
+               systicks = curcounters.cpu_ticks[CPU_STATE_SYSTEM];
+
+               idleticks = curcounters.cpu_ticks[CPU_STATE_IDLE];
+       } else {
+               userticks = curcounters.cpu_ticks[CPU_STATE_USER]-
+                 lastcounters.cpu_ticks[CPU_STATE_USER];
+
+               systicks = curcounters.cpu_ticks[CPU_STATE_SYSTEM]-
+                 lastcounters.cpu_ticks[CPU_STATE_SYSTEM];
+
+               idleticks = curcounters.cpu_ticks[CPU_STATE_IDLE]-
+                 lastcounters.cpu_ticks[CPU_STATE_IDLE];
+
+               lastcounters = curcounters;
+       }
+       totalticks = userticks + systicks + idleticks;
+}
+
+
+
+main(argc, argv)
+       int     argc;
+       char    *argv[];
+{
+       char    *myname = "top";
+       int     delay = Default_DELAY;
+       kern_return_t   error;
+
+        void screen_update();
+
+       /* get our name */
+       if (argc > 0) {
+               if ((myname = rindex(argv[0], '/')) == 0) {
+                       myname = argv[0];
+               }
+               else {
+                       myname++;
+               }
+       }
+
+       /* check for options */
+       sort_by_usage = 0;
+       wide_output = 0;
+       do_proc0_vm = 0;
+       events_only = 0;
+       events_delta = 0;
+       events_accumulate = 0;
+
+       while (argc > 1 && argv[1][0] == '-') {
+               switch (argv[1][1]) {
+               case 's':
+                       if (argv[1][2])
+                               delay = atoi(&argv[1][2]);
+                       else {
+                               argc--;
+                               argv++;
+
+                               if (argc > 1)
+                                       delay = atoi(&argv[1][0]);
+                       }
+                       break;
+               case 'u':
+                       sort_by_usage = 1;
+                       break;
+               case 'w':
+                       wide_output = 1;
+                       break;
+               case 'k':
+                       do_proc0_vm = 1;
+                       break;
+               case 'e':
+                       events_only = 1;
+                       break;
+               case 'd':
+                       events_only = 1;
+                       events_delta = 1;
+                       break;
+               case 'a':
+                       events_only = 1;
+                       events_accumulate = 1;
+                       break;
+               case 'l':
+                       if (argv[1][2])
+                               logcnt = atoi(&argv[1][2]);
+                       else {
+                               argc--;
+                               argv++;
+
+                               if (argc > 1)
+                                       logcnt = atoi(&argv[1][0]);
+                       }
+                       oneshot = 1;
+                       LINES = 80;
+                       COLS  = 132;
+                       break;
+               default:
+                       fprintf(stderr, "Usage: %s [-u] [-w] [-k] [-sn] [-e] [-d] [number]\n", myname);
+                       fprintf(stderr, "  -u      enables sort by usage\n");
+                       fprintf(stderr, "  -w      enables wide output of additional info\n");
+                       fprintf(stderr, "  -k      generate vm info for kernel(proc 0)... expensive\n");
+                       fprintf(stderr, "  -sn     change sample rate to every n seconds\n");
+                       fprintf(stderr, "  -e      switch to events info counter mode\n");
+                       fprintf(stderr, "  -d      switch to events info counter delta mode\n");
+                       fprintf(stderr, "  -a      switch to events info counter accumulate mode\n");
+                       fprintf(stderr, "  -ln     log n samples\n");
+                       fprintf(stderr, "  number  limit number of processes monitored\n");
+
+                       exit(1);
+               }
+               argc--;
+               argv++;
+       }
+       if (events_only)
+         {
+           if ( wide_output || do_proc0_vm)
+             {
+               fprintf(stderr, " The -w and -k flag have no effect in event mode.\n");
+               wide_output = 0;
+               do_proc0_vm = 0;
+             }
+         }
+
+       host_priv_port = get_host_priv();
+       host_port = get_host_port();
+
+       /* get count of top processes to display (if any) */
+       if (argc > 1) {
+               wanted_topn = topn = atoi(argv[1]);
+       } else
+               wanted_topn = -1;
+
+       /* allocate space for proc structure array and array of pointers */
+       nproc = 50;             /* starting point */
+       kbase = (struct kinfo_proc *) malloc(nproc*sizeof(struct kinfo_proc));
+       bzero(kbase, nproc*sizeof(struct kinfo_proc));
+       proc  = (struct proc_info *) malloc(nproc*sizeof(struct proc_info));
+       bzero(proc, nproc*sizeof(struct proc_info));
+       oldproc  = (struct proc_info *) malloc(nproc*sizeof(struct proc_info));
+       bzero(oldproc, nproc*sizeof(struct proc_info));
+       pref  = (struct proc_info **) malloc(nproc*sizeof(struct proc_info *));
+       bzero(pref, nproc*sizeof(struct proc_info *));
+
+       (void) host_page_size(host_port, &pagesize);
+       /* 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();
+               erase();
+               clear();
+               refresh();
+       }
+       /* set up signal handlers */
+       signal(SIGINT, leave);
+       signal(SIGQUIT, leave);
+       signal(SIGWINCH, sigwinch);
+       
+       /* can only display (LINES - Header_lines) processes */
+       if (topn > LINES - Header_lines) {
+               if (!oneshot)
+                       printw("Warning: this terminal can only display %d processes...\n",
+                               LINES - Header_lines);
+               else
+                       printf("Warning: this terminal can only display %d processes...\n",
+                               LINES - Header_lines);
+
+               if (!oneshot)
+                       refresh();
+               sleep(2);
+               topn = LINES - Header_lines;
+               if (!oneshot)
+                       clear();
+       }
+       if (topn == 0) {        // use default
+               // leave one blank line at bottom
+
+               topn = LINES - Header_lines - 1;
+       }
+
+       /* prime the pump for gathering networking stats */
+       kread(0, 0, 0);
+
+       /**************************************************/
+       /* get ports and services for drive stats */
+       /* Obtain the I/O Kit communication handle */
+
+       error = IOMasterPort(bootstrap_port, &masterPort);
+
+       /* Obtain the list of all drive objects */
+       
+       error = IOServiceGetMatchingServices(masterPort,
+                                            IOServiceMatching("IOBlockStorageDriver"),
+                                            &drivelist);
+       getCPU(&lastcounters);
+       startcounters = lastcounters;
+
+       gettimeofday(&cur_tod, NULL);
+       start_tod = cur_tod;
+       elapsed_milliseconds = -1;
+
+       /* main loop */
+
+       while (1) {
+               int   n;
+
+               if (newLINES) {
+
+                       if (!oneshot) {
+                               initscr();
+                               erase();
+                               clear();
+                               refresh();
+                       }
+                       n = LINES - Header_lines;
+
+                       if (topn >= n)
+                               topn = n;
+                       else {
+                               if (wanted_topn == -1)
+                                       topn = n;
+                               else if (topn < wanted_topn) {
+                                       if (wanted_topn < n)
+                                               topn = wanted_topn;
+                                       else
+                                               topn = n;
+                               }
+                       }
+                       newLINES = 0;
+               }
+               (void)screen_update();
+
+               if (!oneshot) {
+
+                       if ((n = read(0, &bytesread, 128)) > 0) {
+                               int   i;
+
+                               for (i = 0; i < n; i++)
+                                       if (bytesread[i] == 'q')
+                                               leave();
+                       }
+               } else
+                       sleep(delay);
+       }
+}
+
+void screen_update()
+{
+       char    c;
+       int     i, n, mpid;
+       int     active_procs;
+       int     avenrun[3];
+       long    curr_time;
+       long    elapsed_secs;
+       unsigned long long      total_fw_vsize;
+       unsigned long long      total_virtual_size;
+       unsigned long long      total_private_size;
+       unsigned long long      total_shared_size;
+       unsigned int            total_memory_regions;
+       unsigned int            total_shared_objects;
+       unsigned int            total_fw_code_size;
+       unsigned int            total_fw_data_size;
+       unsigned int            total_fw_linkedit_size;
+       unsigned int            total_frameworks;
+       vm_statistics_data_t    vm_stat;
+       struct host_load_info load_data;
+       int     host_count;
+       kern_return_t   error;
+       char    tbuf[256];
+       char    *dp;
+       int     clen;
+
+       bzero((char *)state_breakdown, sizeof(state_breakdown));
+
+       if (!oneshot) {
+               /* clear for new display */
+               erase();
+       }
+       /* read all of the process information */
+       read_proc_table();
+
+       /* get the load averages */
+        host_count = sizeof(load_data)/sizeof(integer_t);
+       error = host_statistics(host_priv_port, HOST_LOAD_INFO,
+                       (host_info_t)&load_data, &host_count);
+       if (error != KERN_SUCCESS) {
+               mach_error("host_statistics", error);
+               exit(EXIT_FAILURE);
+       }
+
+       avenrun[0] = load_data.avenrun[0];
+       avenrun[1] = load_data.avenrun[1];
+       avenrun[2] = load_data.avenrun[2];
+
+       /* get total - systemwide main memory usage structure */
+       host_count = sizeof(vm_stat)/sizeof(integer_t);
+       error = host_statistics(host_priv_port, HOST_VM_INFO,
+                       (host_info_t)&vm_stat, &host_count);
+       if (error != KERN_SUCCESS) {
+               mach_error("host_info", error);
+               exit(EXIT_FAILURE);
+       }
+       getNETWORKcounters();
+       getDISKcounters();
+
+       /* count up process states and get pointers to interesting procs */
+
+       mpid = 0;
+       active_procs = 0;
+       total_virtual_size = 0;
+       total_private_size = 0;
+       total_fw_private   = 0;
+
+       prefp = pref;
+       for (kpb = kbase, pp = proc, i = 0;
+                               i < total_procs;
+                               kpb++, pp++, i++) {
+
+               /* place pointers to each valid proc structure in pref[] */
+               get_proc_info(kpb, pp);
+
+               if (kpb->kp_proc.p_stat != 0) {
+                       *prefp++ = pp;
+                       active_procs++;
+                       if (pp->pid > mpid)
+                               mpid = pp->pid;
+                       
+                       if ((unsigned int)pp->state > (unsigned int)STATE_MAX)
+                               pp->state = STATE_MAX;
+                       state_breakdown[pp->state]++;
+                       total_virtual_size += pp->virtual_size;
+                       total_private_size += pp->private;
+                       total_memory_regions += pp->obj_count;
+               }
+               else
+                       state_breakdown[0]++;
+       }
+       /* get the cpu counters */
+       getCPU(&curcounters);
+       updateCPU();
+
+       if (elapsed_milliseconds != -1) {
+               last_tod = cur_tod;
+               gettimeofday(&cur_tod, NULL);
+
+               if (events_accumulate)
+                       timersub(&cur_tod, &start_tod, &elapsed_tod);
+               else
+                       timersub(&cur_tod, &last_tod, &elapsed_tod);
+
+               elapsed_milliseconds = (elapsed_tod.tv_sec * 1000) + (elapsed_tod.tv_usec / 1000);
+       } else
+               elapsed_milliseconds = 0;
+
+       if (!events_only) {
+               pmem_fw_resident(&total_frameworks, &total_fw_vsize, &total_fw_code_size, &total_fw_data_size, &total_fw_linkedit_size);
+
+               pmem_shared_resident(&total_shared_size, &total_shared_objects);
+       }
+       if (!oneshot)
+               move(0,0);
+
+       /* display process state breakdown */
+       sprintf(tbuf, "Processes:  %d total", total_procs);
+       clen = strlen(tbuf);
+
+
+       for (i = 0; i <= STATE_MAX; i++) {
+           if (state_breakdown[i] != 0) {
+               sprintf(&tbuf[clen], ", %d %s%s",
+                       state_breakdown[i],
+                       state_name[i],
+                       (i == 0 && state_breakdown[0] > 1) ? "s" : ""
+                     );
+
+               clen = clen + strlen(&tbuf[clen]);
+           }
+       }
+       sprintf(&tbuf[clen], "... %d threads", total_threads);
+       
+       clen = clen + strlen(&tbuf[clen]);
+       /*
+        *  Display the current time.
+        *  "ctime" always returns a string that looks like this:
+        *  
+        *      Sun Sep 16 01:03:52 1973
+        *      012345678901234567890123
+        *                1         2
+        *
+        *  We want indices 11 thru 18 (length 8).
+        */
+       curr_time = time((long *)0);
+
+       if (start_time == 0)
+               start_time = curr_time;
+
+       memset(&tbuf[clen], ' ', 111 - clen);
+
+       if (wide_output)
+               clen = 118 - 8;
+       else if (events_accumulate)
+               clen = 103 - 8;
+       else if (events_only && !events_delta)
+               clen = 115 - 8;
+       else
+               clen = 79 - 8;
+
+       sprintf(&tbuf[clen], "%-8.8s", &(ctime(&curr_time)[11]));
+       clen = clen + strlen(&tbuf[clen]);
+
+       if (events_accumulate) {
+               int hours;
+               int minutes;
+
+               elapsed_secs = curr_time - start_time;
+               minutes = elapsed_secs / 60;
+               hours = minutes / 60;
+
+               sprintf(&tbuf[clen], "   %3ld:%02ld:%02ld\n", hours, minutes % 60, elapsed_secs % 60);
+       } else {
+               sprintf(&tbuf[clen], "\n");
+       }
+               
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (!oneshot)
+               printw(tbuf);
+       else
+               printf(tbuf);
+
+       /* display the load averages */
+       sprintf(tbuf, "Load Avg");
+       clen = strlen(tbuf);
+
+       for (i = 0; i < 3; i++) {
+               sprintf(&tbuf[clen], "%s %4.2f", i == 0 ? ": " : ",",
+                       (double)avenrun[i] / LOAD_SCALE);
+               clen = clen + strlen(&tbuf[clen]);
+       }
+       if (totalticks) {
+               sprintf(&tbuf[clen], "     CPU usage:  %.1f%%%% user, %.1f%%%% sys, %.1f%%%% idle\n",
+                       (100*userticks)/totalticks, (100*systicks)/totalticks, (100*idleticks)/totalticks);
+               clen = clen + strlen(&tbuf[clen]);
+       }
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (!oneshot)
+               printw(tbuf);
+       else
+               printf(tbuf);
+
+       if (!events_only) {
+               sprintf(tbuf, "SharedLibs: num = %4d, ", total_frameworks);
+               clen = strlen(tbuf);
+               sprintf(&tbuf[clen], "resident = %s code, ", mem_to_string((unsigned long long)total_fw_code_size));
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "%s data, ", mem_to_string((unsigned long long)total_fw_data_size));
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "%s LinkEdit\n", mem_to_string((unsigned long long)total_fw_linkedit_size));
+
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (!oneshot)
+                       printw(tbuf);
+               else
+                       printf(tbuf);
+
+               sprintf(tbuf, "MemRegions: num = %4d, ", total_memory_regions);
+               clen = strlen(tbuf);
+               sprintf(&tbuf[clen], "resident = %s + ", mem_to_string(total_private_size - total_fw_private));
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "%s private, ", mem_to_string(total_fw_private));
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "%s shared\n", mem_to_string(total_shared_size));
+
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (!oneshot)
+                       printw(tbuf);
+               else
+                       printf(tbuf);
+
+               /* display main memory statistics */
+               {
+                       unsigned long long  total_resident_size,
+                                       active_resident_size,
+                                       inactive_resident_size,
+                                       wire_resident_size,
+                                       free_size;
+
+                       active_resident_size = vm_stat.active_count * pagesize;
+                       inactive_resident_size = vm_stat.inactive_count * pagesize;
+                       wire_resident_size = vm_stat.wire_count * pagesize;
+                       total_resident_size = (vm_stat.active_count + vm_stat.inactive_count +
+                                               vm_stat.wire_count) * pagesize;
+                       free_size = vm_stat.free_count   * pagesize;
+
+                       sprintf(tbuf, "PhysMem:  ");
+                       clen = strlen(tbuf);
+                       sprintf(&tbuf[clen], "%s wired, ", mem_to_string(wire_resident_size));
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "%s active, ", mem_to_string(active_resident_size));
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "%s inactive, ", mem_to_string(inactive_resident_size));
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "%s used, ", mem_to_string(total_resident_size));
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "%s free\n", mem_to_string(free_size));
+
+                       if (tbuf[COLS-2] != '\n') {
+                               tbuf[COLS-1] = '\n';
+                               tbuf[COLS] = 0;
+                       }
+                       if (!oneshot)
+                               printw(tbuf);
+                       else
+                               printf(tbuf);
+               }
+       } else {
+               int  i_io, o_io, i_kbytes, o_kbytes;
+
+               i_io = o_io = i_kbytes = o_kbytes = 0;
+
+               if (events_delta) {
+                       if (i_net.io_prev || o_net.io_prev) {
+                               i_io = i_net.io - i_net.io_prev;
+                               o_io = o_net.io - o_net.io_prev;
+                               i_kbytes = i_net.kbytes - i_net.kbytes_prev;
+                               o_kbytes = o_net.kbytes - o_net.kbytes_prev;
+                       }
+               } else if (events_accumulate) {
+                       if (i_net.io_prev || o_net.io_prev) {
+                               i_net.io_accum += i_net.io - i_net.io_prev;
+                               o_net.io_accum += o_net.io - o_net.io_prev;
+                               i_net.kbytes_accum += i_net.kbytes - i_net.kbytes_prev;
+                               o_net.kbytes_accum += o_net.kbytes - o_net.kbytes_prev;
+
+                               i_io = i_net.io_accum;
+                               o_io = o_net.io_accum;
+                               i_kbytes = i_net.kbytes_accum;
+                               o_kbytes = o_net.kbytes_accum;
+                       }
+               } else {
+                       i_io = i_net.io;
+                       o_io = o_net.io;
+                       i_kbytes = i_net.kbytes;
+                       o_kbytes = o_net.kbytes;
+               }
+               sprintf(tbuf, "en0:   %10d ipkts/%dK", i_io, i_kbytes);
+               clen = strlen(tbuf);
+               memset(&tbuf[clen], ' ', 36 - clen);
+               sprintf(&tbuf[36], "%10d opkts /%dK\n", o_io, o_kbytes);
+               
+               i_net.io_prev = i_net.io;
+               o_net.io_prev = o_net.io;
+               i_net.kbytes_prev = i_net.kbytes;
+               o_net.kbytes_prev = o_net.kbytes;
+
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (!oneshot)
+                       printw(tbuf);
+               else
+                       printf(tbuf);
+
+               i_io = o_io = i_kbytes = o_kbytes = 0;
+
+               if (events_delta) {
+                       if (i_dsk.io_prev || o_dsk.io_prev) {
+                               i_io = i_dsk.io - i_dsk.io_prev;
+                               o_io = o_dsk.io - o_dsk.io_prev;
+                               i_kbytes = i_dsk.kbytes - i_dsk.kbytes_prev;
+                               o_kbytes = o_dsk.kbytes - o_dsk.kbytes_prev;
+                       }
+               } else if (events_accumulate) {
+                       if (i_dsk.io_prev || o_dsk.io_prev) {
+                               i_dsk.io_accum += i_dsk.io - i_dsk.io_prev;
+                               o_dsk.io_accum += o_dsk.io - o_dsk.io_prev;
+                               i_dsk.kbytes_accum += i_dsk.kbytes - i_dsk.kbytes_prev;
+                               o_dsk.kbytes_accum += o_dsk.kbytes - o_dsk.kbytes_prev;
+
+                               i_io = i_dsk.io_accum;
+                               o_io = o_dsk.io_accum;
+                               i_kbytes = i_dsk.kbytes_accum;
+                               o_kbytes = o_dsk.kbytes_accum;
+                       }
+               } else {
+                       i_io = i_dsk.io;
+                       o_io = o_dsk.io;
+                       i_kbytes = i_dsk.kbytes;
+                       o_kbytes = o_dsk.kbytes;
+               }
+               sprintf(tbuf, "Disks: %10d reads/%dK", i_io, i_kbytes);
+               clen = strlen(tbuf);
+               memset(&tbuf[clen], ' ', 36 - clen);
+               sprintf(&tbuf[36], "%10d writes/%dK\n", o_io, o_kbytes);
+
+               i_dsk.io_prev = i_dsk.io;
+               o_dsk.io_prev = o_dsk.io;
+               i_dsk.kbytes_prev = i_dsk.kbytes;
+               o_dsk.kbytes_prev = o_dsk.kbytes;
+
+               if (tbuf[COLS-2] != '\n') {
+                       tbuf[COLS-1] = '\n';
+                       tbuf[COLS] = 0;
+               }
+               if (!oneshot)
+                       printw(tbuf);
+               else
+                       printf(tbuf);
+       }
+
+       /* display paging statistics */
+       if (events_only) {
+               int pageins, pageouts;
+               
+               pageins = pageouts = 0;
+
+               if (events_delta) {
+                       if (i_vm.io_prev || o_vm.io_prev) {
+                               pageins = vm_stat.pageins - i_vm.io_prev;
+                               pageouts = vm_stat.pageouts - o_vm.io_prev;
+                       }
+               } else if (events_accumulate) {
+                       if (i_vm.io_prev || o_vm.io_prev) {
+                               i_vm.io_accum += vm_stat.pageins - i_vm.io_prev;
+                               o_vm.io_accum += vm_stat.pageouts - o_vm.io_prev;
+                               
+                               pageins = i_vm.io_accum;
+                               pageouts = o_vm.io_accum;
+                       }
+               } else {
+                       pageins = vm_stat.pageins;
+                       pageouts = vm_stat.pageouts;
+               }
+               sprintf(tbuf, "VM:    %10d pageins", pageins);
+               clen = strlen(tbuf);
+               memset(&tbuf[clen], ' ', 36 - clen);
+               sprintf(&tbuf[36], "%10d pageouts\n", pageouts);
+       } else {
+               sprintf(tbuf, "VM: %5.5s + ", mem_to_string(total_virtual_size));
+               clen = strlen(tbuf);
+               sprintf(&tbuf[clen], "%5.5s   ", mem_to_string(total_fw_vsize));
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "%d(%d) pageins, ", vm_stat.pageins, vm_stat.pageins - (int)i_vm.io_prev);
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], "%d(%d) pageouts\n", vm_stat.pageouts, vm_stat.pageouts - (int)o_vm.io_prev);
+       }
+       if (tbuf[COLS-2] != '\n') {
+               tbuf[COLS-1] = '\n';
+               tbuf[COLS] = 0;
+       }
+       if (!oneshot)
+               printw(tbuf);
+       else
+               printf(tbuf);
+
+       i_vm.io_prev = vm_stat.pageins;
+       o_vm.io_prev = vm_stat.pageouts;
+
+       
+       /* display the processes */
+       if (topn > 0) {
+           if (events_delta)
+                   sprintf(tbuf, "\n  PID COMMAND      %%%%CPU   TIME   FAULTS PGINS/COWS MSENT/MRCVD  BSD/MACH    CSW\n");
+           else if (events_only)
+                   sprintf(tbuf, "\n  PID COMMAND      %%%%CPU   TIME    FAULTS   PAGEINS  COW_FAULTS MSGS_SENT  MSGS_RCVD  BSDSYSCALL MACHSYSCALL CSWITCH\n");
+           else if (wide_output)
+                   sprintf(tbuf, "\n  PID COMMAND      %%%%CPU   TIME   #TH #PRTS(delta) #MREGS VPRVT  RPRVT(delta)  RSHRD(delta)  RSIZE(delta)  VSIZE(delta)\n");
+           else
+                   sprintf(tbuf, "\n  PID COMMAND      %%%%CPU   TIME   #TH #PRTS #MREGS RPRVT  RSHRD  RSIZE  VSIZE\n");
+
+
+           if (tbuf[COLS] != '\n') {
+                   tbuf[COLS+1] = '\n';
+                   tbuf[COLS+2] = 0;
+           }
+           if (!oneshot)
+                   printw(tbuf);
+           else
+                   printf(tbuf);
+
+           update_histdata();
+
+           /* sort */
+           qsort((char *)pref,
+                 active_procs,
+                 sizeof(struct proc_info *),
+                 proc_compar);
+    
+           /* now, show the top whatever */
+           if (active_procs > topn)
+           {
+               /* adjust for too many processes */
+               active_procs = topn;
+           }
+
+           for (prefp = pref, i = 0; i < active_procs; prefp++, i++)
+           {
+               pp = *prefp;
+
+               sprintf(tbuf, "%5d", pp->pid);                  /* pid */
+               clen = strlen(tbuf);
+               sprintf(&tbuf[clen], " %-10.10s ", pp->command); /* command */
+               clen = clen + strlen(&tbuf[clen]);
+
+               print_usage(&tbuf[clen], pp->cpu_usage);
+               clen = clen + strlen(&tbuf[clen]);
+
+               sprintf(&tbuf[clen], " ");
+               clen++;
+
+               print_time(&tbuf[clen], pp->total_time);        /* cputime */
+               clen = clen + strlen(&tbuf[clen]);
+
+
+               if (events_only) {
+                   if (events_delta) {
+                       sprintf(&tbuf[clen], " %6d", pp->deltatei.faults);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %5d", pp->deltatei.pageins);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "/%-4d", pp->deltatei.cow_faults);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %5d", pp->deltatei.messages_sent);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "/%-4d", pp->deltatei.messages_received);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %5d", pp->deltatei.syscalls_unix);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "/%-5d", pp->deltatei.syscalls_mach);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], "%6d", pp->deltatei.csw);
+                       clen = clen + strlen(&tbuf[clen]);
+                   } else if (events_accumulate) {
+                       sprintf(&tbuf[clen], "  %-8d", pp->deltatei.faults);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-8d", pp->deltatei.pageins);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->deltatei.cow_faults);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->deltatei.messages_sent);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->deltatei.messages_received);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->deltatei.syscalls_unix);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-11d", pp->deltatei.syscalls_mach);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-8d", pp->deltatei.csw);
+                       clen = clen + strlen(&tbuf[clen]);
+                   } else {
+                       sprintf(&tbuf[clen], "  %-8d", pp->tei.faults);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-8d", pp->tei.pageins);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->tei.cow_faults);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->tei.messages_sent);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->tei.messages_received);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-10d", pp->tei.syscalls_unix);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-11d", pp->tei.syscalls_mach);
+                       clen = clen + strlen(&tbuf[clen]);
+                       sprintf(&tbuf[clen], " %-8d", pp->tei.csw);
+                       clen = clen + strlen(&tbuf[clen]);
+                   }
+               } else {
+
+               sprintf(&tbuf[clen], " %3d", pp->num_threads);  /* # of threads */
+               clen = clen + strlen(&tbuf[clen]);
+               sprintf(&tbuf[clen], " %5d", pp->num_ports);    /* # of ports */
+               clen = clen + strlen(&tbuf[clen]);
+       
+               if (wide_output) {
+                       if (pp->dnum_ports)
+                               sprintf(&tbuf[clen], "(%5d)", pp->dnum_ports);
+                       else
+                               sprintf(&tbuf[clen], "       ");
+                       clen = clen + strlen(&tbuf[clen]);
+               }
+               if (pp->pid || do_proc0_vm)
+                       sprintf(&tbuf[clen], "  %4d", pp->obj_count);
+               else
+                       sprintf(&tbuf[clen], "     -");
+               clen = clen + strlen(&tbuf[clen]);
+
+               if (wide_output) {
+                       if (pp->pid || do_proc0_vm) {
+                               sprintf(&tbuf[clen], "  %5.5s", mem_to_string((unsigned long long)pp->vprivate));       /* res size */
+                               clen = clen + strlen(&tbuf[clen]);
+                               sprintf(&tbuf[clen], "  %5.5s", mem_to_string((unsigned long long)pp->private));        /* res size */
+                               clen = clen + strlen(&tbuf[clen]);
+
+                               if (pp->drprvt)
+                                       sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drprvt));
+                               else
+                                       sprintf(&tbuf[clen], "       ");
+                       } else
+                               sprintf(&tbuf[clen], "      -      -       ");
+               } else {
+                       if (pp->drprvt == 0)
+                               dp = " ";
+                       else if ((int)pp->drprvt > 0)
+                               dp = "+";
+                       else
+                               dp = "-";
+
+                       if (pp->pid || do_proc0_vm)
+                               sprintf(&tbuf[clen], "  %5.5s%s", mem_to_string((unsigned long long)pp->private), dp);        /* res size */
+                       else
+                               sprintf(&tbuf[clen], "      -");
+               }
+               clen = clen + strlen(&tbuf[clen]);
+
+               if (wide_output) {
+                       if (pp->pid || do_proc0_vm) {
+                               sprintf(&tbuf[clen], "  %5.5s", mem_to_string((unsigned long long)pp->shared));
+                               clen = clen + strlen(&tbuf[clen]);
+
+                               if (pp->drshrd)
+                                       sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drshrd));
+                               else
+                                       sprintf(&tbuf[clen], "       ");
+                       } else
+                               sprintf(&tbuf[clen], "      -       ");
+               } else {
+                       if (pp->drshrd == 0)
+                               dp = " ";
+                       else if ((int)pp->drshrd > 0)
+                               dp = "+";
+                       else
+                               dp = "-";
+
+                       if (pp->pid || do_proc0_vm)
+                               sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->shared), dp);
+                       else
+                               sprintf(&tbuf[clen], "      - ");
+               }
+               clen = clen + strlen(&tbuf[clen]);
+
+               if (wide_output) {
+                       sprintf(&tbuf[clen], "  %5.5s", mem_to_string((unsigned long long)pp->resident_size));  /* res size */
+                       clen = clen + strlen(&tbuf[clen]);
+
+                       if (pp->drsize)
+                               sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->drsize));
+                       else
+                               sprintf(&tbuf[clen], "       ");
+               } else {
+                       if (pp->drsize == 0)
+                               dp = " ";
+                       else if ((int)pp->drsize > 0)
+                               dp = "+";
+                       else
+                               dp = "-";
+
+                       sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->resident_size), dp);     /* res size */
+               }
+               clen = clen + strlen(&tbuf[clen]);
+
+               if (wide_output) {
+                       sprintf(&tbuf[clen], "  %5.5s", mem_to_string((unsigned long long)pp->virtual_size));   /* size */
+                       clen = clen + strlen(&tbuf[clen]);
+
+                       if (pp->rvsize)
+                               sprintf(&tbuf[clen], "(%5.5s)", offset_to_string(pp->rvsize));
+                       else
+                               sprintf(&tbuf[clen], "       ");
+               } else {
+                       if (pp->dvsize == 0)
+                               dp = " ";
+                       else if ((int)pp->dvsize > 0)
+                               dp = "+";
+                       else
+                               dp = "-";
+
+                       sprintf(&tbuf[clen], " %5.5s%s", mem_to_string((unsigned long long)pp->virtual_size), dp);      /* size */
+               }
+               clen = clen + strlen(&tbuf[clen]);
+
+               } /* else not events only */
+
+               sprintf(&tbuf[clen], "\n");
+
+               if (tbuf[COLS-1] != '\n') {
+                       tbuf[COLS] = '\n';
+                       tbuf[COLS+1] = 0;
+               }
+               if (!oneshot)
+                       printw(tbuf);
+               else
+                       printf(tbuf);
+           }
+
+           for (n = 0, prefp = pref; n < total_procs && i < topn; prefp++, n++)
+           {
+                   pp = *prefp;
+
+                   if (pp->has_idle_thread == TRUE) {
+                           sprintf(tbuf, "%5d", pp->pid);
+                           clen = strlen(tbuf);
+                           sprintf(&tbuf[clen], " %-10.10s ", "idle_thread");
+                           clen = clen + strlen(&tbuf[clen]);
+
+                           print_usage(&tbuf[clen], pp->cpu_idle);
+                           clen = clen + strlen(&tbuf[clen]);
+                           sprintf(&tbuf[clen], " ");
+                           clen++;
+                           print_time(&tbuf[clen], pp->idle_time);
+                           clen = clen + strlen(&tbuf[clen]);
+                           sprintf(&tbuf[clen], "\n");
+
+                           if (tbuf[COLS-1] != '\n') {
+                                   tbuf[COLS] = '\n';
+                                   tbuf[COLS+1] = 0;
+                           }
+                           if (!oneshot)
+                                   printw(tbuf);
+                           else
+                                   printf(tbuf);
+                           i++;
+                   }
+           }             
+        }
+       if (oneshot) {
+               printf("\n");
+               
+               if (--logcnt <= 0)
+                       leave();
+       } else
+               refresh();
+}
+
+
+void
+update_eventsdata()
+{
+  /*  unimplemented */
+}
+
+
+static struct nlist nl_net[] = {
+#define N_IFNET         0
+  { "_ifnet" },
+  { "" },
+};
+
+
+
+/*
+ * Read kernel memory, return 0 on success.
+ */
+int
+kread(addr, buf, size)
+        u_long addr;
+       char *buf;
+       int size;
+{
+        static kvm_t *kvmd = 0;
+
+        if (kvmd == 0) {
+               /*
+                * XXX.
+                */
+               kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf);
+               if (kvmd != NULL) {
+                       if (kvm_nlist(kvmd, nl_net) < 0)
+                               errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
+
+                       if (nl_net[0].n_type == 0)
+                               errx(1, "no namelist");
+               } else {
+                       return(-1);
+               }
+       }
+       if (!buf)
+               return (0);
+       if (kvm_read(kvmd, addr, buf, size) != size) {
+               warnx("%s", kvm_geterr(kvmd));
+               return (-1);
+       }
+       return (0);
+}
+
+
+getNETWORKcounters()
+{
+        struct ifnet ifnet;
+       struct ifnethead ifnethead;
+       u_long off;
+
+       if (nl_net[N_IFNET].n_value == 0)
+              return;
+       if (kread(nl_net[N_IFNET].n_value, (char *)&ifnethead, sizeof ifnethead))
+              return;
+
+       for (off = (u_long)ifnethead.tqh_first; off; ) {
+                  char name[16], tname[16];
+
+                 if (kread(off, (char *)&ifnet, sizeof ifnet))
+                         break;
+                 if (kread((u_long)ifnet.if_name, tname, 16))
+                         break;
+                  tname[15] = '\0';
+
+                 snprintf(name, 16, "%s%d", tname, ifnet.if_unit);
+
+                 if (strcmp(name, "en0") == 0) {
+                         i_net.io = ifnet.if_ipackets;
+                         o_net.io = ifnet.if_opackets;
+                         
+                         i_net.kbytes = ifnet.if_ibytes/1024;
+                         o_net.kbytes = ifnet.if_obytes/1024;
+
+                         return;
+                 }
+                 off = (u_long) ifnet.if_link.tqe_next;
+       }
+       return;
+}
+
+
+getDISKcounters()
+{
+       io_registry_entry_t drive      = 0;  /* needs release */
+       UInt64         totalReadBytes  = 0;
+       UInt64         totalReadCount  = 0;
+        UInt64         totalWriteBytes = 0;
+       UInt64         totalWriteCount = 0;
+
+       kern_return_t status = 0;
+
+       while ( (drive = IOIteratorNext(drivelist)) )
+       {
+               CFNumberRef number          = 0;  /* don't release */
+               CFDictionaryRef properties  = 0;  /* needs release */
+               CFDictionaryRef statistics  = 0;  /* don't release */
+               UInt64 value                = 0;
+
+               /* Obtain the properties for this drive object */
+
+               status = IORegistryEntryCreateCFProperties (drive,
+                                                            (CFMutableDictionaryRef *) &properties,
+                                                           kCFAllocatorDefault,
+                                                           kNilOptions);
+
+               /* Obtain the statistics from the drive properties */
+               statistics = (CFDictionaryRef) CFDictionaryGetValue(properties, CFSTR(kIOBlockStorageDriverStatisticsKey));
+
+               if (statistics) {
+                       /* Obtain the number of bytes read from the drive statistics */
+                       number = (CFNumberRef) CFDictionaryGetValue (statistics,
+                                                                    CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey));
+                       if (number) {
+                               status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               totalReadBytes += value;
+                       }
+                       /* Obtain the number of reads from the drive statistics */
+                       number = (CFNumberRef) CFDictionaryGetValue (statistics,
+                                                                    CFSTR(kIOBlockStorageDriverStatisticsReadsKey));
+                       if (number) {
+                               status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               totalReadCount += value;
+                       }
+
+                       /* Obtain the number of writes from the drive statistics */
+                       number = (CFNumberRef) CFDictionaryGetValue (statistics,
+                                                                    CFSTR(kIOBlockStorageDriverStatisticsWritesKey));
+                       if (number) {
+                               status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               totalWriteCount += value;
+                       }
+                       /* Obtain the number of bytes written from the drive statistics */
+                       number = (CFNumberRef) CFDictionaryGetValue (statistics,
+                                                                    CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey));
+                       if (number) {
+                               status = CFNumberGetValue(number, kCFNumberSInt64Type, &value);
+                               totalWriteBytes += value;
+                       }
+               }
+               /* Release resources */
+
+               CFRelease(properties); properties = 0;
+               IOObjectRelease(drive); drive = 0;
+       }
+       IOIteratorReset(drivelist);
+         
+       i_dsk.io = (int)totalReadCount;
+       o_dsk.io = (int)totalWriteCount; 
+       i_dsk.kbytes = (int)(totalReadBytes / 1024);
+       o_dsk.kbytes = (int)(totalWriteBytes / 1024);
+}
diff --git a/update.tproj/Makefile b/update.tproj/Makefile
new file mode 100644 (file)
index 0000000..8ba41ff
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = update
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = update.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble update.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/update.tproj/Makefile.postamble b/update.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..70b747f
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/update.tproj/Makefile.preamble b/update.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..e371f9d
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/update.tproj/PB.project b/update.tproj/PB.project
new file mode 100644 (file)
index 0000000..91c587b
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (update.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, update.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = update; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/update.tproj/update.8 b/update.tproj/update.8
new file mode 100644 (file)
index 0000000..78665fa
--- /dev/null
@@ -0,0 +1,74 @@
+.\" Copyright (c) 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.
+.\"
+.\"    @(#)update.8    8.3 (Berkeley) 4/19/94
+.\"
+.Dd April 19, 1994
+.Dt UPDATE 8
+.Os
+.Sh NAME
+.Nm update
+.Nd flush internal filesystem caches to disk frequently
+.Sh SYNOPSIS
+.Nm update
+.Sh DESCRIPTION
+The
+.Nm update
+command helps protect the integrity of disk volumes
+by flushing
+volatile cached filesystem data
+to disk at thirty second intervals.
+.Nm Update
+uses the
+.Xr sync 2
+function call to do the task.
+.Pp
+.Nm Update
+is commonly invoked at startup time by
+.Xr rc 8
+when the system goes multi-user.
+.Sh SEE ALSO
+.Xr sync 2 ,
+.Xr fsck 8 ,
+.Xr init 8 ,
+.Xr rc 8 ,
+.Xr sync 8
+.Sh BUGS
+It is possible on some systems that a
+.Xr sync
+occurring simultaneously with a crash may cause
+file system damage. See
+.Xr fsck 8 .
+.Sh HISTORY
+An
+.Nm update
+command appeared in
+.At v6 .
diff --git a/update.tproj/update.c b/update.tproj/update.c
new file mode 100644 (file)
index 0000000..980a7da
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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) 1987, 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.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1990, 1993\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)update.c   8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/time.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+main()
+{
+       struct itimerval value;
+       void mysync();
+
+       daemon(0, 0);
+
+       (void)signal(SIGALRM, mysync);
+
+       value.it_interval.tv_sec = 30;
+       value.it_interval.tv_usec = 0;
+       value.it_value = value.it_interval;
+       if (setitimer(ITIMER_REAL, &value, NULL)) {
+               perror("update: setitimer");
+               exit(1);
+       }
+       for (;;)
+               sigpause(sigblock(0L));
+       /* NOTREACHED */
+}
+
+void
+mysync()
+{
+       (void)sync();
+}
diff --git a/vipw.tproj/Makefile b/vipw.tproj/Makefile
new file mode 100644 (file)
index 0000000..7dd9aea
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# 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 = vipw
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = pw_util.h
+
+CFILES = pw_util.c vipw.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble vipw.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+WINDOWS_INSTALLDIR = /usr/sbin
+PDO_UNIX_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+PROJECT_HEADERS = pw_util.h
+
+
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/vipw.tproj/Makefile.postamble b/vipw.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..70b747f
--- /dev/null
@@ -0,0 +1,109 @@
+###############################################################################
+#  NeXT Makefile.postamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app)
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      ENGLISH - boolean flag set iff $(LANGUAGE) = "English"
+#      JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese"
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder that output Makefile
+#      APPICON - application icon file
+#      DOCICONS - dock icon files
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+
+
+# Change defaults assumed by the standard app makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if
+# you would like changes to them to invalidate previous builds.  The project
+# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build.
+#MAKEFILES = Makefile 
+
+# Optimization flag passed to compiler:
+#OPTIMIZATION_CFLAG = -O
+
+# Flags always passed to compiler:
+#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall  
+
+# Flags passed to compiler in normal 'app' compiles:
+#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG)
+
+# Flags passed to compiler in 'debug' compiles:
+#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG
+
+# Flags passed to compiler in 'profile' compiles
+#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Ownership and permissions of files installed by 'install' target
+#INSTALL_AS_USER = root        # User to chown app to
+#INSTALL_AS_GROUP = wheel      # Group to chgrp app to 
+#INSTALL_PERMISSIONS =         # If set, 'install' chmod's executable to this
+
+# Options to strip for bundles, apps with bundles, and apps without bundles, 
+# respectively.
+#RELOCATABLE_STRIP_OPTS = -x -u
+#DYLD_APP_STRIP_OPTS = -A -n
+#APP_STRIP_OPTS = 
+#TOOL_STRIP_OPTS = 
+#LIBRARY_STRIP_OPTS = -x -S   # Note: -S strips debugging symbols
+# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but
+#  developers doing their own dynamic loading should set this to 
+#  $(DYLD_APP_STRIP_OPTS)).
+
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  Typical 
+# user-defined rules are before_install and after_install (please don't 
+# redefine things like install or app, as they are owned by the top-level 
+# 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.
diff --git a/vipw.tproj/Makefile.preamble b/vipw.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..e371f9d
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#  NeXT Makefile.preamble Template
+#  Copyright 1993, NeXT Computer, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags here.  To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+
+BUNDLELDFLAGS =            # use iff project is a bundle
+PALETTELDFLAGS =           # use iff project is a palette
+
+## Specify which headers in this project should be published to the outside 
+## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be 
+## prepended by DSTROOT, below.  Any subset of these public headers can be
+## precompiled automatically after installation, with extra user-defined flags.
+PUBLIC_HEADER_DIR = 
+PUBLIC_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+## Configure what is linked in at each level here.  Libraries are only used in
+## the final 'app' linking step.  Final 'app' linking is only done via the
+## 'app', 'debug', and 'profile' targets when they are invoked for
+## the top-level app.
+
+# Additional relocatables to be linked in at this level
+OTHER_OFILES = 
+# Additional libs to link apps against ('app' target)
+#OTHER_LIBS = 
+# Additional libs to link apps against ('debug' target)
+OTHER_DEBUG_LIBS = 
+# Additional libs to link apps against ('profile' target)
+OTHER_PROF_LIBS = 
+
+# More 'app' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_LIBS = 
+# More 'debug' libraries when $(JAPANESE) = "YES"
+OTHER_JAPANESE_DEBUG_LIBS = 
+# More 'profile' libs when $(JAPANESE) = "YES"
+OTHER_JAPANESE_PROF_LIBS = 
+
+# If this is a bundle, and you *know* the enclosing application will not
+# be linking with a library which you require in your bundle code, then
+# mention it here so that it gets linked into the bundle.  Note that this
+# is wasteful but sometimes necessary.
+BUNDLE_LIBS = 
+
+## Configure how things get built here.  Additional dependencies, sourcefiles, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+# Precompiled headers to be built before any compilation occurs (e.g., draw.p)
+PRECOMPS = 
+
+# Targets to be built before installation
+OTHER_INSTALL_DEPENDS =        
+
+# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) 
+# passed from ProjectBuilder.
+DSTROOT = 
+
+# Set the following to "YES" if you want the old behavior of recursively
+# cleaning all nested subprojects during 'make clean'.
+CLEAN_ALL_SUBPROJECTS =
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+# 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)
+
diff --git a/vipw.tproj/PB.project b/vipw.tproj/PB.project
new file mode 100644 (file)
index 0000000..f4e6310
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    DOCICONFILES = (); 
+    FILESTABLE = {
+        C_FILES = (); 
+        H_FILES = (pw_util.h); 
+        OTHER_LIBS = (); 
+        OTHER_LINKED = (pw_util.c, vipw.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, vipw.8); 
+        PRECOMPILED_HEADERS = (); 
+        PROJECT_HEADERS = (pw_util.h); 
+        PUBLIC_HEADERS = (); 
+        SUBPROJECTS = (); 
+    }; 
+    GENERATEMAIN = YES; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    NEXTSTEP_BUILDDIR = ""; 
+    NEXTSTEP_BUILDTOOL = /bin/make; 
+    NEXTSTEP_COMPILEROPTIONS = ""; 
+    NEXTSTEP_INSTALLDIR = /usr/sbin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_LINKEROPTIONS = ""; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDDIR = ""; 
+    PDO_UNIX_BUILDTOOL = /bin/make; 
+    PDO_UNIX_COMPILEROPTIONS = ""; 
+    PDO_UNIX_INSTALLDIR = /usr/sbin; 
+    PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_LINKEROPTIONS = ""; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = vipw; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDDIR = ""; 
+    WINDOWS_BUILDTOOL = /bin/make; 
+    WINDOWS_COMPILEROPTIONS = ""; 
+    WINDOWS_INSTALLDIR = /usr/sbin; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_LINKEROPTIONS = ""; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/vipw.tproj/pw_util.c b/vipw.tproj/pw_util.c
new file mode 100644 (file)
index 0000000..e0514a0
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * 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) 1990, 1993, 1994
+ *     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 char sccsid[] = "@(#)pw_util.c  8.4 (Berkeley) 4/28/95";
+#endif /* not lint */
+
+/*
+ * This file is used by all the "password" programs; vipw(8), chpass(1),
+ * and passwd(1).
+ */
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_util.h"
+
+extern char *tempname;
+static pid_t editpid = -1;
+static int lockfd;
+
+void
+pw_cont(sig)
+       int sig;
+{
+
+       if (editpid != -1)
+               kill(editpid, sig);
+}
+
+void
+pw_init()
+{
+       struct rlimit rlim;
+
+       /* Unlimited resource limits. */
+       rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+       (void)setrlimit(RLIMIT_CPU, &rlim);
+       (void)setrlimit(RLIMIT_FSIZE, &rlim);
+       (void)setrlimit(RLIMIT_STACK, &rlim);
+       (void)setrlimit(RLIMIT_DATA, &rlim);
+       (void)setrlimit(RLIMIT_RSS, &rlim);
+
+       /* Don't drop core (not really necessary, but GP's). */
+       rlim.rlim_cur = rlim.rlim_max = 0;
+       (void)setrlimit(RLIMIT_CORE, &rlim);
+
+       /* Turn off signals. */
+       (void)signal(SIGALRM, SIG_IGN);
+       (void)signal(SIGHUP, SIG_IGN);
+       (void)signal(SIGINT, SIG_IGN);
+       (void)signal(SIGPIPE, SIG_IGN);
+       (void)signal(SIGQUIT, SIG_IGN);
+       (void)signal(SIGTERM, SIG_IGN);
+       (void)signal(SIGCONT, pw_cont);
+
+       /* Create with exact permissions. */
+       (void)umask(0);
+}
+
+int
+pw_lock()
+{
+       /* 
+        * If the master password file doesn't exist, the system is hosed.
+        * Might as well try to build one.  Set the close-on-exec bit so
+        * that users can't get at the encrypted passwords while editing.
+        * Open should allow flock'ing the file; see 4.4BSD.    XXX
+        */
+       lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
+       if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
+               err(1, "%s", _PATH_MASTERPASSWD);
+       if (flock(lockfd, LOCK_EX|LOCK_NB))
+               errx(1, "the password db file is busy");
+       return (lockfd);
+}
+
+int
+pw_tmp()
+{
+       static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
+       int fd;
+       char *p;
+
+       if (p = strrchr(path, '/'))
+               ++p;
+       else
+               p = path;
+       strcpy(p, "pw.XXXXXX");
+       if ((fd = mkstemp(path)) == -1)
+               err(1, "%s", path);
+       tempname = path;
+       return (fd);
+}
+
+int
+pw_mkdb()
+{
+       int pstat;
+       pid_t pid;
+
+       warnx("rebuilding the database...");
+       (void)fflush(stderr);
+       if (!(pid = vfork())) {
+               execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
+               pw_error(_PATH_PWD_MKDB, 1, 1);
+       }
+       pid = waitpid(pid, &pstat, 0);
+       if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
+               return (1);
+       warnx("done");
+       return (0);
+}
+
+void
+pw_edit(notsetuid)
+       int notsetuid;
+{
+       int pstat;
+       char *p, *editor;
+
+       if (!(editor = getenv("EDITOR")))
+               editor = _PATH_VI;
+       if (p = strrchr(editor, '/'))
+               ++p;
+       else 
+               p = editor;
+
+       if (!(editpid = vfork())) {
+               if (notsetuid) {
+                       (void)setgid(getgid());
+                       (void)setuid(getuid());
+               }
+               execlp(editor, p, tempname, NULL);
+               _exit(1);
+       }
+       for (;;) {
+               editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
+               if (editpid == -1)
+                       pw_error(editor, 1, 1);
+               else if (WIFSTOPPED(pstat))
+                       raise(WSTOPSIG(pstat));
+               else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
+                       break;
+               else
+                       pw_error(editor, 1, 1);
+       }
+       editpid = -1;
+}
+
+void
+pw_prompt()
+{
+       int c;
+
+       (void)printf("re-edit the password file? [y]: ");
+       (void)fflush(stdout);
+       c = getchar();
+       if (c != EOF && c != '\n')
+               while (getchar() != '\n');
+       if (c == 'n')
+               pw_error(NULL, 0, 0);
+}
+
+void
+pw_error(name, err, eval)
+       char *name;
+       int err, eval;
+{
+       if (err)
+               warn(name);
+
+       warnx("%s: unchanged", _PATH_MASTERPASSWD);
+       (void)unlink(tempname);
+       exit(eval);
+}
diff --git a/vipw.tproj/pw_util.h b/vipw.tproj/pw_util.h
new file mode 100644 (file)
index 0000000..b5811b0
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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) 1994
+ *     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.
+ *
+ *     @(#)pw_util.h   8.2 (Berkeley) 4/1/94
+ */
+
+void   pw_edit __P((int));
+void   pw_error __P((char *, int, int));
+void   pw_init __P((void));
+int    pw_lock __P((void));
+int    pw_mkdb __P((void));
+void   pw_prompt __P((void));
+int    pw_tmp __P((void));
diff --git a/vipw.tproj/vipw.8 b/vipw.tproj/vipw.8
new file mode 100644 (file)
index 0000000..18ef5ed
--- /dev/null
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1983, 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.
+.\"
+.\"     @(#)vipw.8     8.1 (Berkeley) 6/6/93
+.\"
+.Dd June 6, 1993
+.Dt VIPW 8
+.Os BSD 4
+.Sh NAME
+.Nm vipw
+.Nd edit the password file
+.Sh SYNOPSIS
+.Nm vipw
+.Sh DESCRIPTION
+.Nm Vipw
+edits the password file after setting the appropriate locks,
+and does any necessary processing after the password file is unlocked.
+If the password file is already locked for editing by another user,
+.Nm vipw
+will ask you
+to try again later. The default editor for
+.Nm vipw
+is
+.Xr vi 1 .
+.Pp
+.Nm Vipw
+performs a number of consistency checks on the password entries,
+and will not allow a password file with a
+.Dq mangled
+entry to be
+installed.
+If
+.Nm vipw
+rejects the new password file, the user is prompted to re-enter
+the edit session.
+.Pp
+Once the information has been verified,
+.Nm vipw
+uses
+.Xr pwd_mkdb 8
+to update the user database.  This is run in the background, and,
+at very large sites could take several minutes.  Until this update
+is completed, the password file is unavailable for other updates
+and the new information is not available to programs.
+.Sh ENVIRONMENT
+If the following environment variable exists it will be utilized by
+.Nm vipw :
+.Bl -tag -width EDITOR
+.It Ev EDITOR
+The editor specified by the string
+.Ev EDITOR
+will be invoked instead of the default editor
+.Xr vi 1 .
+.El
+.Sh SEE ALSO
+.Xr chpass 1 ,
+.Xr passwd 1 ,
+.Xr passwd 5 ,
+.Xr adduser 8 ,
+.Xr pwd_mkdb 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.0 .
diff --git a/vipw.tproj/vipw.c b/vipw.tproj/vipw.c
new file mode 100644 (file)
index 0000000..d15932b
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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) 1987, 1993, 1994
+ *     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 char copyright[] =
+"@(#) Copyright (c) 1987, 1993, 1994\n\
+       The Regents of the University of California.  All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)vipw.c     8.3 (Berkeley) 4/2/94";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pw_util.h"
+
+char *tempname;
+
+void   copyfile __P((int, int));
+void   usage __P((void));
+
+int
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int pfd, tfd;
+       struct stat begin, end;
+       int ch;
+
+       while ((ch = getopt(argc, argv, "")) != EOF)
+               switch (ch) {
+               case '?':
+               default:
+                       usage();
+               }
+       
+       argc -= optind;
+       argv += optind;
+
+       if (argc != 0)
+               usage();
+
+       pw_init();
+       pfd = pw_lock();
+       tfd = pw_tmp();
+       copyfile(pfd, tfd);
+       (void)close(tfd);
+
+       for (;;) {
+               if (stat(tempname, &begin))
+                       pw_error(tempname, 1, 1);
+               pw_edit(0);
+               if (stat(tempname, &end))
+                       pw_error(tempname, 1, 1);
+               if (begin.st_mtime == end.st_mtime) {
+                       warnx("no changes made");
+                       pw_error((char *)NULL, 0, 0);
+               }
+               if (pw_mkdb())
+                       break;
+               pw_prompt();
+       }
+       exit(0);
+}
+
+void
+copyfile(from, to)
+       int from, to;
+{
+       int nr, nw, off;
+       char buf[8*1024];
+       
+       while ((nr = read(from, buf, sizeof(buf))) > 0)
+               for (off = 0; off < nr; nr -= nw, off += nw)
+                       if ((nw = write(to, buf + off, nr)) < 0)
+                               pw_error(tempname, 1, 1);
+       if (nr < 0)
+               pw_error(_PATH_MASTERPASSWD, 1, 1);
+}
+
+void
+usage()
+{
+
+       (void)fprintf(stderr, "usage: vipw\n");
+       exit(1);
+}
diff --git a/vm_stat.tproj/Makefile b/vm_stat.tproj/Makefile
new file mode 100644 (file)
index 0000000..4b21a74
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = vm_stat
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = vm_stat.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\
+            h.template
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /bin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD
+
+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/vm_stat.tproj/Makefile.postamble b/vm_stat.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..411cde6
--- /dev/null
@@ -0,0 +1,100 @@
+###############################################################################
+#  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.
+#
diff --git a/vm_stat.tproj/Makefile.preamble b/vm_stat.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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/vm_stat.tproj/PB.project b/vm_stat.tproj/PB.project
new file mode 100644 (file)
index 0000000..7a909f4
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        OTHER_LINKED = (vm_stat.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    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 = vm_stat; 
+    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/vm_stat.tproj/h.template b/vm_stat.tproj/h.template
new file mode 100644 (file)
index 0000000..f3c1b04
--- /dev/null
@@ -0,0 +1,11 @@
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
diff --git a/vm_stat.tproj/m.template b/vm_stat.tproj/m.template
new file mode 100644 (file)
index 0000000..1216fe5
--- /dev/null
@@ -0,0 +1,18 @@
+$$ Lines starting with $$ are not inserted into newly created files
+$$ The following substitutions are made:
+$$
+$$ $FILENAME$                e.g. foo.m
+$$ $FILENAMESANSEXTENSION$   e.g. foo
+$$ $DIRECTORY$               e.g. /tmp/MyNewApp
+$$ $PROJECTNAME$             e.g. MyNewApp
+$$ $SUBPROJECTNAME$          e.g. TheGoodPart.subproj
+$$ $USERNAME$                e.g. mwagner
+$$ $DATE$                    e.g. Jan-1-1994
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import "$FILENAMESANSEXTENSION$.h"
+
+@implementation $FILENAMESANSEXTENSION$
+
+@end
diff --git a/vm_stat.tproj/vm_stat.c b/vm_stat.tproj/vm_stat.c
new file mode 100644 (file)
index 0000000..6bad7ca
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * 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@
+ */
+/*
+ *     File:   vm_stat.c
+ *     Author: Avadis Tevanian, Jr.
+ *
+ *     Copyright (C) 1986, Avadis Tevanian, Jr.
+ *
+ *
+ *     Display Mach VM statistics.
+ *
+ ************************************************************************
+ * HISTORY
+ *  6-Jun-86  Avadis Tevanian, Jr. (avie) at Carnegie-Mellon University
+ *     Use official Mach interface.
+ *
+ *  25-mar-99  A.Ramesh at Apple
+ *             Ported to MacOS X
+ ************************************************************************
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+
+#include <mach/mach.h>
+
+vm_statistics_data_t   vm_stat, last;
+int    percent;
+int    delay;
+char   *pgmname;
+mach_port_t myHost;
+int pageSize = 4096;   /* set to 4k default */
+
+void usage();
+void banner();
+void snapshot();
+void pstat(char *str, int n);
+void print_stats();
+void get_stats(struct vm_statistics *stat);
+
+int
+main(argc, argv)
+       int     argc;
+       char    *argv[];
+{
+
+       pgmname = argv[0];
+       delay = 0;
+
+
+       setlinebuf (stdout);
+
+       if (argc == 2) {
+               if (sscanf(argv[1], "%d", &delay) != 1)
+                       usage();
+               if (delay < 0)
+                       usage();
+       }
+
+       myHost = mach_host_self();
+
+       if(host_page_size(mach_host_self(), &pageSize) != KERN_SUCCESS) {
+               fprintf(stderr, "%s: failed to get pagesize; defaulting to 4K.\n", pgmname);
+               pageSize = 4096;
+       }       
+
+       if (delay == 0) {
+               snapshot();
+       }
+       else {
+               while (1) {
+                       print_stats();
+                       sleep(delay);
+               }
+       }
+       exit(0);
+}
+
+void
+usage()
+{
+       fprintf(stderr, "usage: %s [ repeat-interval ]\n", pgmname);
+       exit(1);
+}
+
+void
+banner()
+{
+       get_stats(&vm_stat);
+       printf("Mach Virtual Memory Statistics: ");
+       printf("(page size of %d bytes, cache hits %d%%)\n",
+                               pageSize, percent);
+       printf("%6s %6s %4s %4s %8s %8s %8s %8s %8s %8s\n",
+               "free",
+               "active",
+               "inac",
+               "wire",
+               "faults",
+               "copy",
+               "zerofill",
+               "reactive",
+               "pageins",
+               "pageout");
+       bzero(&last, sizeof(last));
+}
+
+void
+snapshot()
+{
+
+       get_stats(&vm_stat);
+       printf("Mach Virtual Memory Statistics: (page size of %d bytes)\n",
+                               pageSize);
+
+       pstat("Pages free:", vm_stat.free_count);
+       pstat("Pages active:", vm_stat.active_count);
+       pstat("Pages inactive:", vm_stat.inactive_count);
+       pstat("Pages wired down:", vm_stat.wire_count);
+       pstat("\"Translation faults\":", vm_stat.faults);
+       pstat("Pages copy-on-write:", vm_stat.cow_faults);
+       pstat("Pages zero filled:", vm_stat.zero_fill_count);
+       pstat("Pages reactivated:", vm_stat.reactivations);
+       pstat("Pageins:", vm_stat.pageins);
+       pstat("Pageouts:", vm_stat.pageouts);
+       printf("Object cache: %d hits of %d lookups (%d%% hit rate)\n",
+                       vm_stat.hits, vm_stat.lookups, percent);
+}
+
+void
+pstat(str, n)
+       char    *str;
+       int     n;
+{
+       printf("%-25s %10d.\n", str, n);
+}
+
+void
+print_stats()
+{
+       static count = 0;
+
+       if (count++ == 0)
+               banner();
+
+       if (count > 20)
+               count = 0;
+
+       get_stats(&vm_stat);
+       printf("%6d %6d %4d %4d %8d %8d %8d %8d %8d %8d\n",
+               vm_stat.free_count,
+               vm_stat.active_count,
+               vm_stat.inactive_count,
+               vm_stat.wire_count,
+               vm_stat.faults - last.faults,
+               vm_stat.cow_faults - last.cow_faults,
+               vm_stat.zero_fill_count - last.zero_fill_count,
+               vm_stat.reactivations - last.reactivations,
+               vm_stat.pageins - last.pageins,
+               vm_stat.pageouts - last.pageouts);
+       last = vm_stat;
+}
+
+void
+get_stats(stat)
+       struct vm_statistics    *stat;
+{
+       int count = HOST_VM_INFO_COUNT;
+       if (host_statistics(myHost, HOST_VM_INFO, stat,&count) != KERN_SUCCESS) {
+               fprintf(stderr, "%s: failed to get statistics.\n", pgmname);
+               exit(2);
+       }
+       if (stat->lookups == 0)
+               percent = 0;
+       else
+               percent = (stat->hits*100)/stat->lookups;
+}
diff --git a/zdump.tproj/Makefile b/zdump.tproj/Makefile
new file mode 100644 (file)
index 0000000..d704d7f
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = zdump
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = zdump.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble zdump.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/zdump.tproj/Makefile.postamble b/zdump.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..590f9a6
--- /dev/null
@@ -0,0 +1,125 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+
+VPATH += :../zic.tproj
\ No newline at end of file
diff --git a/zdump.tproj/Makefile.preamble b/zdump.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..b1c570c
--- /dev/null
@@ -0,0 +1,131 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
+OTHER_OFILES = ialloc.o
diff --git a/zdump.tproj/PB.project b/zdump.tproj/PB.project
new file mode 100644 (file)
index 0000000..cd4da71
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (); 
+        OTHER_LINKED = (zdump.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, zdump.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    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_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = zdump; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/zdump.tproj/zdump.8 b/zdump.tproj/zdump.8
new file mode 100644 (file)
index 0000000..7126d4e
--- /dev/null
@@ -0,0 +1,40 @@
+.\"    $OpenBSD: zdump.8,v 1.3 1997/01/14 03:16:54 millert Exp $
+.TH ZDUMP 8
+.SH NAME
+zdump \- time zone dumper
+.SH SYNOPSIS
+.B zdump
+[
+.B \-v
+] [
+.B \-c
+cutoffyear ] [ zonename ... ]
+.SH DESCRIPTION
+.I Zdump
+prints the current time in each
+.I zonename
+named on the command line.
+.PP
+These options are available:
+.TP
+.B \-v
+For each
+.I zonename
+on the command line,
+print the time at the lowest possible time value,
+the time one day after the lowest possible time value,
+the times both one second before and exactly at
+each detected time discontinuity,
+the time at one day less than the highest possible time value,
+and the time at the highest possible time value,
+Each line ends with
+.B isdst=1
+if the given time is Daylight Saving Time or
+.B isdst=0
+otherwise.
+.TP
+.BI "\-c " cutoffyear
+Cut off the verbose output near the start of the given year.
+.SH "SEE ALSO"
+ctime(3), tzfile(5), zic(8)
+.\" @(#)zdump.8        7.3
diff --git a/zdump.tproj/zdump.c b/zdump.tproj/zdump.c
new file mode 100644 (file)
index 0000000..ce849c4
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * 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@
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char    elsieid[] = "@(#)zdump.c        7.24";
+#else
+static char rcsid[] = "$OpenBSD: zdump.c,v 1.5 1997/01/21 04:52:45 millert Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+** This code has been made independent of the rest of the time
+** conversion package to increase confidence in the verification it provides.
+** You can use this code to help in verifying other implementations.
+*/
+
+#include "stdio.h"     /* for stdout, stderr, perror */
+#include "string.h"    /* for strcpy */
+#include "sys/types.h" /* for time_t */
+#include "time.h"      /* for struct tm */
+#include "stdlib.h"    /* for exit, malloc, atoi */
+
+#ifndef MAX_STRING_LENGTH
+#define MAX_STRING_LENGTH      1024
+#endif /* !defined MAX_STRING_LENGTH */
+
+#ifndef TRUE
+#define TRUE           1
+#endif /* !defined TRUE */
+
+#ifndef FALSE
+#define FALSE          0
+#endif /* !defined FALSE */
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS   0
+#endif /* !defined EXIT_SUCCESS */
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE   1
+#endif /* !defined EXIT_FAILURE */
+
+#ifndef SECSPERMIN
+#define SECSPERMIN     60
+#endif /* !defined SECSPERMIN */
+
+#ifndef MINSPERHOUR
+#define MINSPERHOUR    60
+#endif /* !defined MINSPERHOUR */
+
+#ifndef SECSPERHOUR
+#define SECSPERHOUR    (SECSPERMIN * MINSPERHOUR)
+#endif /* !defined SECSPERHOUR */
+
+#ifndef HOURSPERDAY
+#define HOURSPERDAY    24
+#endif /* !defined HOURSPERDAY */
+
+#ifndef EPOCH_YEAR
+#define EPOCH_YEAR     1970
+#endif /* !defined EPOCH_YEAR */
+
+#ifndef TM_YEAR_BASE
+#define TM_YEAR_BASE   1900
+#endif /* !defined TM_YEAR_BASE */
+
+#ifndef DAYSPERNYEAR
+#define DAYSPERNYEAR   365
+#endif /* !defined DAYSPERNYEAR */
+
+#ifndef isleap
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+#endif /* !defined isleap */
+
+#if HAVE_GETTEXT - 0
+#include "locale.h"    /* for setlocale */
+#include "libintl.h"
+#endif /* HAVE_GETTEXT - 0 */
+
+#ifndef GNUC_or_lint
+#ifdef lint
+#define GNUC_or_lint
+#endif /* defined lint */
+#ifndef lint
+#ifdef __GNUC__
+#define GNUC_or_lint
+#endif /* defined __GNUC__ */
+#endif /* !defined lint */
+#endif /* !defined GNUC_or_lint */
+
+#ifndef INITIALIZE
+#ifdef GNUC_or_lint
+#define INITIALIZE(x)  ((x) = 0)
+#endif /* defined GNUC_or_lint */
+#ifndef GNUC_or_lint
+#define INITIALIZE(x)
+#endif /* !defined GNUC_or_lint */
+#endif /* !defined INITIALIZE */
+
+/*
+** For the benefit of GNU folk...
+** `_(MSGID)' uses the current locale's message library string for MSGID.
+** The default is to use gettext if available, and use MSGID otherwise.
+*/
+
+#ifndef _
+#if HAVE_GETTEXT - 0
+#define _(msgid) gettext(msgid)
+#else /* !(HAVE_GETTEXT - 0) */
+#define _(msgid) msgid
+#endif /* !(HAVE_GETTEXT - 0) */
+#endif /* !defined _ */
+
+#ifndef TZ_DOMAIN
+#define TZ_DOMAIN "tz"
+#endif /* !defined TZ_DOMAIN */
+
+extern char ** environ;
+extern int     getopt();
+extern char *  optarg;
+extern int     optind;
+extern time_t  time();
+extern char *  tzname[2];
+
+static char *  abbr();
+static long    delta();
+static time_t  hunt();
+static int     longest;
+static char *  progname;
+static void    show();
+
+int
+main(argc, argv)
+int    argc;
+char * argv[];
+{
+       register int            i;
+       register int            c;
+       register int            vflag;
+       register char *         cutoff;
+       register int            cutyear;
+       register long           cuttime;
+       char **                 fakeenv;
+       time_t                  now;
+       time_t                  t;
+       time_t                  newt;
+       time_t                  hibit;
+       struct tm               tm;
+       struct tm               newtm;
+
+       INITIALIZE(cuttime);
+#if HAVE_GETTEXT - 0
+       (void) setlocale(LC_MESSAGES, "");
+#ifdef TZ_DOMAINDIR
+       (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
+#endif /* defined(TEXTDOMAINDIR) */
+       (void) textdomain(TZ_DOMAIN);
+#endif /* HAVE_GETTEXT - 0 */
+       progname = argv[0];
+       vflag = 0;
+       cutoff = NULL;
+       while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
+               if (c == 'v')
+                       vflag = 1;
+               else    cutoff = optarg;
+       if (c != EOF ||
+               (optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
+                       (void) fprintf(stderr,
+_("%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n"),
+                               argv[0], argv[0]);
+                       (void) exit(EXIT_FAILURE);
+       }
+       if (cutoff != NULL) {
+               int     y;
+
+               cutyear = atoi(cutoff);
+               cuttime = 0;
+               for (y = EPOCH_YEAR; y < cutyear; ++y)
+                       cuttime += DAYSPERNYEAR + isleap(y);
+               cuttime *= SECSPERHOUR * HOURSPERDAY;
+       }
+       (void) time(&now);
+       longest = 0;
+       for (i = optind; i < argc; ++i)
+               if (strlen(argv[i]) > longest)
+                       longest = strlen(argv[i]);
+       for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
+               continue;
+       {
+               register int    from;
+               register int    to;
+
+               for (i = 0;  environ[i] != NULL;  ++i)
+                       continue;
+               fakeenv = (char **) malloc((size_t) ((i + 2) *
+                       sizeof *fakeenv));
+               if (fakeenv == NULL ||
+                       (fakeenv[0] = (char *) malloc((size_t) (longest +
+                               4))) == NULL) {
+                                       (void) perror(progname);
+                                       (void) exit(EXIT_FAILURE);
+               }
+               to = 0;
+               (void) strcpy(fakeenv[to++], "TZ=");
+               for (from = 0; environ[from] != NULL; ++from)
+                       if (strncmp(environ[from], "TZ=", 3) != 0)
+                               fakeenv[to++] = environ[from];
+               fakeenv[to] = NULL;
+               environ = fakeenv;
+       }
+       for (i = optind; i < argc; ++i) {
+               static char     buf[MAX_STRING_LENGTH];
+
+               (void) strcpy(&fakeenv[0][3], argv[i]);
+               show(argv[i], now, FALSE);
+               if (!vflag)
+                       continue;
+               /*
+               ** Get lowest value of t.
+               */
+               t = hibit;
+               if (t > 0)              /* time_t is unsigned */
+                       t = 0;
+               show(argv[i], t, TRUE);
+               t += SECSPERHOUR * HOURSPERDAY;
+               show(argv[i], t, TRUE);
+               tm = *localtime(&t);
+               (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
+               for ( ; ; ) {
+                       if (cutoff != NULL && t >= cuttime)
+                               break;
+                       newt = t + SECSPERHOUR * 12;
+                       if (cutoff != NULL && newt >= cuttime)
+                               break;
+                       if (newt <= t)
+                               break;
+                       newtm = *localtime(&newt);
+                       if (delta(&newtm, &tm) != (newt - t) ||
+                               newtm.tm_isdst != tm.tm_isdst ||
+                               strcmp(abbr(&newtm), buf) != 0) {
+                                       newt = hunt(argv[i], t, newt);
+                                       newtm = *localtime(&newt);
+                                       (void) strncpy(buf, abbr(&newtm),
+                                               (sizeof buf) - 1);
+                       }
+                       t = newt;
+                       tm = newtm;
+               }
+               /*
+               ** Get highest value of t.
+               */
+               t = ~((time_t) 0);
+               if (t < 0)              /* time_t is signed */
+                       t &= ~hibit;
+               t -= SECSPERHOUR * HOURSPERDAY;
+               show(argv[i], t, TRUE);
+               t += SECSPERHOUR * HOURSPERDAY;
+               show(argv[i], t, TRUE);
+       }
+       if (fflush(stdout) || ferror(stdout)) {
+               (void) fprintf(stderr, _("%s: Error writing standard output "),
+                       argv[0]);
+               (void) perror(_("standard output"));
+               (void) exit(EXIT_FAILURE);
+       }
+       exit(EXIT_SUCCESS);
+
+       /* gcc -Wall pacifier */
+       for ( ; ; )
+               continue;
+}
+
+static time_t
+hunt(name, lot, hit)
+char * name;
+time_t lot;
+time_t hit;
+{
+       time_t          t;
+       struct tm       lotm;
+       struct tm       tm;
+       static char     loab[MAX_STRING_LENGTH];
+
+       lotm = *localtime(&lot);
+       (void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
+       loab[(sizeof loab) - 1] = '\0';
+       while ((hit - lot) >= 2) {
+               t = lot / 2 + hit / 2;
+               if (t <= lot)
+                       ++t;
+               else if (t >= hit)
+                       --t;
+               tm = *localtime(&t);
+               if (delta(&tm, &lotm) == (t - lot) &&
+                       tm.tm_isdst == lotm.tm_isdst &&
+                       strcmp(abbr(&tm), loab) == 0) {
+                               lot = t;
+                               lotm = tm;
+               } else  hit = t;
+       }
+       show(name, lot, TRUE);
+       show(name, hit, TRUE);
+       return hit;
+}
+
+/*
+** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
+*/
+
+static long
+delta(newp, oldp)
+struct tm *    newp;
+struct tm *    oldp;
+{
+       long    result;
+       int     tmy;
+
+       if (newp->tm_year < oldp->tm_year)
+               return -delta(oldp, newp);
+       result = 0;
+       for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
+               result += DAYSPERNYEAR + isleap(tmy + TM_YEAR_BASE);
+       result += newp->tm_yday - oldp->tm_yday;
+       result *= HOURSPERDAY;
+       result += newp->tm_hour - oldp->tm_hour;
+       result *= MINSPERHOUR;
+       result += newp->tm_min - oldp->tm_min;
+       result *= SECSPERMIN;
+       result += newp->tm_sec - oldp->tm_sec;
+       return result;
+}
+
+extern struct tm *     localtime();
+
+static void
+show(zone, t, v)
+char * zone;
+time_t t;
+int    v;
+{
+       struct tm *     tmp;
+
+       (void) printf("%-*s  ", longest, zone);
+       if (v)
+               (void) printf("%.24s GMT = ", asctime(gmtime(&t)));
+       tmp = localtime(&t);
+       (void) printf("%.24s", asctime(tmp));
+       if (*abbr(tmp) != '\0')
+               (void) printf(" %s", abbr(tmp));
+       if (v) {
+               (void) printf(" isdst=%d", tmp->tm_isdst);
+#ifdef TM_GMTOFF
+               (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
+#endif /* defined TM_GMTOFF */
+       }
+       (void) printf("\n");
+}
+
+static char *
+abbr(tmp)
+struct tm *    tmp;
+{
+       register char * result;
+       static char     nada;
+
+       if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
+               return &nada;
+       result = tzname[tmp->tm_isdst];
+       return (result == NULL) ? &nada : result;
+}
diff --git a/zic.tproj/HACK/Africa/Abidjan b/zic.tproj/HACK/Africa/Abidjan
new file mode 100644 (file)
index 0000000..d4a349c
Binary files /dev/null and b/zic.tproj/HACK/Africa/Abidjan differ
diff --git a/zic.tproj/HACK/Africa/Accra b/zic.tproj/HACK/Africa/Accra
new file mode 100644 (file)
index 0000000..7465291
Binary files /dev/null and b/zic.tproj/HACK/Africa/Accra differ
diff --git a/zic.tproj/HACK/Africa/Addis_Ababa b/zic.tproj/HACK/Africa/Addis_Ababa
new file mode 100644 (file)
index 0000000..d2a9220
Binary files /dev/null and b/zic.tproj/HACK/Africa/Addis_Ababa differ
diff --git a/zic.tproj/HACK/Africa/Algiers b/zic.tproj/HACK/Africa/Algiers
new file mode 100644 (file)
index 0000000..1e3312f
Binary files /dev/null and b/zic.tproj/HACK/Africa/Algiers differ
diff --git a/zic.tproj/HACK/Africa/Asmera b/zic.tproj/HACK/Africa/Asmera
new file mode 100644 (file)
index 0000000..d2a9220
Binary files /dev/null and b/zic.tproj/HACK/Africa/Asmera differ
diff --git a/zic.tproj/HACK/Africa/Bamako b/zic.tproj/HACK/Africa/Bamako
new file mode 100644 (file)
index 0000000..fdd951f
Binary files /dev/null and b/zic.tproj/HACK/Africa/Bamako differ
diff --git a/zic.tproj/HACK/Africa/Bangui b/zic.tproj/HACK/Africa/Bangui
new file mode 100644 (file)
index 0000000..bac5dee
Binary files /dev/null and b/zic.tproj/HACK/Africa/Bangui differ
diff --git a/zic.tproj/HACK/Africa/Banjul b/zic.tproj/HACK/Africa/Banjul
new file mode 100644 (file)
index 0000000..2db62fa
Binary files /dev/null and b/zic.tproj/HACK/Africa/Banjul differ
diff --git a/zic.tproj/HACK/Africa/Bissau b/zic.tproj/HACK/Africa/Bissau
new file mode 100644 (file)
index 0000000..dd3c9dc
Binary files /dev/null and b/zic.tproj/HACK/Africa/Bissau differ
diff --git a/zic.tproj/HACK/Africa/Blantyre b/zic.tproj/HACK/Africa/Blantyre
new file mode 100644 (file)
index 0000000..6a98f87
Binary files /dev/null and b/zic.tproj/HACK/Africa/Blantyre differ
diff --git a/zic.tproj/HACK/Africa/Brazzaville b/zic.tproj/HACK/Africa/Brazzaville
new file mode 100644 (file)
index 0000000..9cd21e9
Binary files /dev/null and b/zic.tproj/HACK/Africa/Brazzaville differ
diff --git a/zic.tproj/HACK/Africa/Bujumbura b/zic.tproj/HACK/Africa/Bujumbura
new file mode 100644 (file)
index 0000000..9471cff
Binary files /dev/null and b/zic.tproj/HACK/Africa/Bujumbura differ
diff --git a/zic.tproj/HACK/Africa/Cairo b/zic.tproj/HACK/Africa/Cairo
new file mode 100644 (file)
index 0000000..a084b0a
Binary files /dev/null and b/zic.tproj/HACK/Africa/Cairo differ
diff --git a/zic.tproj/HACK/Africa/Casablanca b/zic.tproj/HACK/Africa/Casablanca
new file mode 100644 (file)
index 0000000..75cae56
Binary files /dev/null and b/zic.tproj/HACK/Africa/Casablanca differ
diff --git a/zic.tproj/HACK/Africa/Ceuta b/zic.tproj/HACK/Africa/Ceuta
new file mode 100644 (file)
index 0000000..d24b1ce
Binary files /dev/null and b/zic.tproj/HACK/Africa/Ceuta differ
diff --git a/zic.tproj/HACK/Africa/Conakry b/zic.tproj/HACK/Africa/Conakry
new file mode 100644 (file)
index 0000000..eb111e3
Binary files /dev/null and b/zic.tproj/HACK/Africa/Conakry differ
diff --git a/zic.tproj/HACK/Africa/Dakar b/zic.tproj/HACK/Africa/Dakar
new file mode 100644 (file)
index 0000000..358db8b
Binary files /dev/null and b/zic.tproj/HACK/Africa/Dakar differ
diff --git a/zic.tproj/HACK/Africa/Dar_es_Salaam b/zic.tproj/HACK/Africa/Dar_es_Salaam
new file mode 100644 (file)
index 0000000..c040d42
Binary files /dev/null and b/zic.tproj/HACK/Africa/Dar_es_Salaam differ
diff --git a/zic.tproj/HACK/Africa/Djibouti b/zic.tproj/HACK/Africa/Djibouti
new file mode 100644 (file)
index 0000000..59e8837
Binary files /dev/null and b/zic.tproj/HACK/Africa/Djibouti differ
diff --git a/zic.tproj/HACK/Africa/Douala b/zic.tproj/HACK/Africa/Douala
new file mode 100644 (file)
index 0000000..026ade8
Binary files /dev/null and b/zic.tproj/HACK/Africa/Douala differ
diff --git a/zic.tproj/HACK/Africa/El_Aaiun b/zic.tproj/HACK/Africa/El_Aaiun
new file mode 100644 (file)
index 0000000..3d399be
Binary files /dev/null and b/zic.tproj/HACK/Africa/El_Aaiun differ
diff --git a/zic.tproj/HACK/Africa/Freetown b/zic.tproj/HACK/Africa/Freetown
new file mode 100644 (file)
index 0000000..edf47b0
Binary files /dev/null and b/zic.tproj/HACK/Africa/Freetown differ
diff --git a/zic.tproj/HACK/Africa/Gaborone b/zic.tproj/HACK/Africa/Gaborone
new file mode 100644 (file)
index 0000000..33adc15
Binary files /dev/null and b/zic.tproj/HACK/Africa/Gaborone differ
diff --git a/zic.tproj/HACK/Africa/Harare b/zic.tproj/HACK/Africa/Harare
new file mode 100644 (file)
index 0000000..149b559
Binary files /dev/null and b/zic.tproj/HACK/Africa/Harare differ
diff --git a/zic.tproj/HACK/Africa/Johannesburg b/zic.tproj/HACK/Africa/Johannesburg
new file mode 100644 (file)
index 0000000..efefe93
Binary files /dev/null and b/zic.tproj/HACK/Africa/Johannesburg differ
diff --git a/zic.tproj/HACK/Africa/Kampala b/zic.tproj/HACK/Africa/Kampala
new file mode 100644 (file)
index 0000000..b8cc2ee
Binary files /dev/null and b/zic.tproj/HACK/Africa/Kampala differ
diff --git a/zic.tproj/HACK/Africa/Khartoum b/zic.tproj/HACK/Africa/Khartoum
new file mode 100644 (file)
index 0000000..68cd5f6
Binary files /dev/null and b/zic.tproj/HACK/Africa/Khartoum differ
diff --git a/zic.tproj/HACK/Africa/Kigali b/zic.tproj/HACK/Africa/Kigali
new file mode 100644 (file)
index 0000000..ec75652
Binary files /dev/null and b/zic.tproj/HACK/Africa/Kigali differ
diff --git a/zic.tproj/HACK/Africa/Kinshasa b/zic.tproj/HACK/Africa/Kinshasa
new file mode 100644 (file)
index 0000000..7f152e0
Binary files /dev/null and b/zic.tproj/HACK/Africa/Kinshasa differ
diff --git a/zic.tproj/HACK/Africa/Lagos b/zic.tproj/HACK/Africa/Lagos
new file mode 100644 (file)
index 0000000..5c7f503
Binary files /dev/null and b/zic.tproj/HACK/Africa/Lagos differ
diff --git a/zic.tproj/HACK/Africa/Libreville b/zic.tproj/HACK/Africa/Libreville
new file mode 100644 (file)
index 0000000..8acf927
Binary files /dev/null and b/zic.tproj/HACK/Africa/Libreville differ
diff --git a/zic.tproj/HACK/Africa/Lome b/zic.tproj/HACK/Africa/Lome
new file mode 100644 (file)
index 0000000..12f8cc8
Binary files /dev/null and b/zic.tproj/HACK/Africa/Lome differ
diff --git a/zic.tproj/HACK/Africa/Luanda b/zic.tproj/HACK/Africa/Luanda
new file mode 100644 (file)
index 0000000..e831304
Binary files /dev/null and b/zic.tproj/HACK/Africa/Luanda differ
diff --git a/zic.tproj/HACK/Africa/Lubumbashi b/zic.tproj/HACK/Africa/Lubumbashi
new file mode 100644 (file)
index 0000000..9471cff
Binary files /dev/null and b/zic.tproj/HACK/Africa/Lubumbashi differ
diff --git a/zic.tproj/HACK/Africa/Lusaka b/zic.tproj/HACK/Africa/Lusaka
new file mode 100644 (file)
index 0000000..d78dd00
Binary files /dev/null and b/zic.tproj/HACK/Africa/Lusaka differ
diff --git a/zic.tproj/HACK/Africa/Malabo b/zic.tproj/HACK/Africa/Malabo
new file mode 100644 (file)
index 0000000..a193c4b
Binary files /dev/null and b/zic.tproj/HACK/Africa/Malabo differ
diff --git a/zic.tproj/HACK/Africa/Maputo b/zic.tproj/HACK/Africa/Maputo
new file mode 100644 (file)
index 0000000..c4ba1e5
Binary files /dev/null and b/zic.tproj/HACK/Africa/Maputo differ
diff --git a/zic.tproj/HACK/Africa/Maseru b/zic.tproj/HACK/Africa/Maseru
new file mode 100644 (file)
index 0000000..6b60d5b
Binary files /dev/null and b/zic.tproj/HACK/Africa/Maseru differ
diff --git a/zic.tproj/HACK/Africa/Mbabane b/zic.tproj/HACK/Africa/Mbabane
new file mode 100644 (file)
index 0000000..18f011a
Binary files /dev/null and b/zic.tproj/HACK/Africa/Mbabane differ
diff --git a/zic.tproj/HACK/Africa/Mogadishu b/zic.tproj/HACK/Africa/Mogadishu
new file mode 100644 (file)
index 0000000..bac76c9
Binary files /dev/null and b/zic.tproj/HACK/Africa/Mogadishu differ
diff --git a/zic.tproj/HACK/Africa/Monrovia b/zic.tproj/HACK/Africa/Monrovia
new file mode 100644 (file)
index 0000000..d912dcd
Binary files /dev/null and b/zic.tproj/HACK/Africa/Monrovia differ
diff --git a/zic.tproj/HACK/Africa/Nairobi b/zic.tproj/HACK/Africa/Nairobi
new file mode 100644 (file)
index 0000000..a4bf865
Binary files /dev/null and b/zic.tproj/HACK/Africa/Nairobi differ
diff --git a/zic.tproj/HACK/Africa/Ndjamena b/zic.tproj/HACK/Africa/Ndjamena
new file mode 100644 (file)
index 0000000..6bb9451
Binary files /dev/null and b/zic.tproj/HACK/Africa/Ndjamena differ
diff --git a/zic.tproj/HACK/Africa/Niamey b/zic.tproj/HACK/Africa/Niamey
new file mode 100644 (file)
index 0000000..2d0febb
Binary files /dev/null and b/zic.tproj/HACK/Africa/Niamey differ
diff --git a/zic.tproj/HACK/Africa/Nouakchott b/zic.tproj/HACK/Africa/Nouakchott
new file mode 100644 (file)
index 0000000..002c7e5
Binary files /dev/null and b/zic.tproj/HACK/Africa/Nouakchott differ
diff --git a/zic.tproj/HACK/Africa/Ouagadougou b/zic.tproj/HACK/Africa/Ouagadougou
new file mode 100644 (file)
index 0000000..87ab7f2
Binary files /dev/null and b/zic.tproj/HACK/Africa/Ouagadougou differ
diff --git a/zic.tproj/HACK/Africa/Porto-Novo b/zic.tproj/HACK/Africa/Porto-Novo
new file mode 100644 (file)
index 0000000..7494497
Binary files /dev/null and b/zic.tproj/HACK/Africa/Porto-Novo differ
diff --git a/zic.tproj/HACK/Africa/Sao_Tome b/zic.tproj/HACK/Africa/Sao_Tome
new file mode 100644 (file)
index 0000000..adfec36
Binary files /dev/null and b/zic.tproj/HACK/Africa/Sao_Tome differ
diff --git a/zic.tproj/HACK/Africa/Timbuktu b/zic.tproj/HACK/Africa/Timbuktu
new file mode 100644 (file)
index 0000000..0e0af5e
Binary files /dev/null and b/zic.tproj/HACK/Africa/Timbuktu differ
diff --git a/zic.tproj/HACK/Africa/Tripoli b/zic.tproj/HACK/Africa/Tripoli
new file mode 100644 (file)
index 0000000..4ca7448
Binary files /dev/null and b/zic.tproj/HACK/Africa/Tripoli differ
diff --git a/zic.tproj/HACK/Africa/Tunis b/zic.tproj/HACK/Africa/Tunis
new file mode 100644 (file)
index 0000000..2884d0c
Binary files /dev/null and b/zic.tproj/HACK/Africa/Tunis differ
diff --git a/zic.tproj/HACK/Africa/Windhoek b/zic.tproj/HACK/Africa/Windhoek
new file mode 100644 (file)
index 0000000..8897d05
Binary files /dev/null and b/zic.tproj/HACK/Africa/Windhoek differ
diff --git a/zic.tproj/HACK/America/Adak b/zic.tproj/HACK/America/Adak
new file mode 100644 (file)
index 0000000..8ecd096
Binary files /dev/null and b/zic.tproj/HACK/America/Adak differ
diff --git a/zic.tproj/HACK/America/Anchorage b/zic.tproj/HACK/America/Anchorage
new file mode 100644 (file)
index 0000000..f3ffb58
Binary files /dev/null and b/zic.tproj/HACK/America/Anchorage differ
diff --git a/zic.tproj/HACK/America/Anguilla b/zic.tproj/HACK/America/Anguilla
new file mode 100644 (file)
index 0000000..91fdd9d
Binary files /dev/null and b/zic.tproj/HACK/America/Anguilla differ
diff --git a/zic.tproj/HACK/America/Antigua b/zic.tproj/HACK/America/Antigua
new file mode 100644 (file)
index 0000000..43b0607
Binary files /dev/null and b/zic.tproj/HACK/America/Antigua differ
diff --git a/zic.tproj/HACK/America/Aruba b/zic.tproj/HACK/America/Aruba
new file mode 100644 (file)
index 0000000..e2ecedc
Binary files /dev/null and b/zic.tproj/HACK/America/Aruba differ
diff --git a/zic.tproj/HACK/America/Asuncion b/zic.tproj/HACK/America/Asuncion
new file mode 100644 (file)
index 0000000..5ec5c8b
Binary files /dev/null and b/zic.tproj/HACK/America/Asuncion differ
diff --git a/zic.tproj/HACK/America/Atka b/zic.tproj/HACK/America/Atka
new file mode 100644 (file)
index 0000000..8ecd096
Binary files /dev/null and b/zic.tproj/HACK/America/Atka differ
diff --git a/zic.tproj/HACK/America/Barbados b/zic.tproj/HACK/America/Barbados
new file mode 100644 (file)
index 0000000..287748e
Binary files /dev/null and b/zic.tproj/HACK/America/Barbados differ
diff --git a/zic.tproj/HACK/America/Belize b/zic.tproj/HACK/America/Belize
new file mode 100644 (file)
index 0000000..98e4f94
Binary files /dev/null and b/zic.tproj/HACK/America/Belize differ
diff --git a/zic.tproj/HACK/America/Bogota b/zic.tproj/HACK/America/Bogota
new file mode 100644 (file)
index 0000000..0074a1d
Binary files /dev/null and b/zic.tproj/HACK/America/Bogota differ
diff --git a/zic.tproj/HACK/America/Boise b/zic.tproj/HACK/America/Boise
new file mode 100644 (file)
index 0000000..19ec977
Binary files /dev/null and b/zic.tproj/HACK/America/Boise differ
diff --git a/zic.tproj/HACK/America/Buenos_Aires b/zic.tproj/HACK/America/Buenos_Aires
new file mode 100644 (file)
index 0000000..5d4eefd
Binary files /dev/null and b/zic.tproj/HACK/America/Buenos_Aires differ
diff --git a/zic.tproj/HACK/America/Caracas b/zic.tproj/HACK/America/Caracas
new file mode 100644 (file)
index 0000000..eeba277
Binary files /dev/null and b/zic.tproj/HACK/America/Caracas differ
diff --git a/zic.tproj/HACK/America/Catamarca b/zic.tproj/HACK/America/Catamarca
new file mode 100644 (file)
index 0000000..438fd94
Binary files /dev/null and b/zic.tproj/HACK/America/Catamarca differ
diff --git a/zic.tproj/HACK/America/Cayenne b/zic.tproj/HACK/America/Cayenne
new file mode 100644 (file)
index 0000000..b979bd1
Binary files /dev/null and b/zic.tproj/HACK/America/Cayenne differ
diff --git a/zic.tproj/HACK/America/Cayman b/zic.tproj/HACK/America/Cayman
new file mode 100644 (file)
index 0000000..2db1564
Binary files /dev/null and b/zic.tproj/HACK/America/Cayman differ
diff --git a/zic.tproj/HACK/America/Chicago b/zic.tproj/HACK/America/Chicago
new file mode 100644 (file)
index 0000000..7ffb1d8
Binary files /dev/null and b/zic.tproj/HACK/America/Chicago differ
diff --git a/zic.tproj/HACK/America/Cordoba b/zic.tproj/HACK/America/Cordoba
new file mode 100644 (file)
index 0000000..fd2d768
Binary files /dev/null and b/zic.tproj/HACK/America/Cordoba differ
diff --git a/zic.tproj/HACK/America/Costa_Rica b/zic.tproj/HACK/America/Costa_Rica
new file mode 100644 (file)
index 0000000..06abc05
Binary files /dev/null and b/zic.tproj/HACK/America/Costa_Rica differ
diff --git a/zic.tproj/HACK/America/Cuiaba b/zic.tproj/HACK/America/Cuiaba
new file mode 100644 (file)
index 0000000..bd16396
Binary files /dev/null and b/zic.tproj/HACK/America/Cuiaba differ
diff --git a/zic.tproj/HACK/America/Curacao b/zic.tproj/HACK/America/Curacao
new file mode 100644 (file)
index 0000000..0ea02cd
Binary files /dev/null and b/zic.tproj/HACK/America/Curacao differ
diff --git a/zic.tproj/HACK/America/Dawson b/zic.tproj/HACK/America/Dawson
new file mode 100644 (file)
index 0000000..17a1b81
Binary files /dev/null and b/zic.tproj/HACK/America/Dawson differ
diff --git a/zic.tproj/HACK/America/Dawson_Creek b/zic.tproj/HACK/America/Dawson_Creek
new file mode 100644 (file)
index 0000000..d964845
Binary files /dev/null and b/zic.tproj/HACK/America/Dawson_Creek differ
diff --git a/zic.tproj/HACK/America/Denver b/zic.tproj/HACK/America/Denver
new file mode 100644 (file)
index 0000000..fc45907
Binary files /dev/null and b/zic.tproj/HACK/America/Denver differ
diff --git a/zic.tproj/HACK/America/Detroit b/zic.tproj/HACK/America/Detroit
new file mode 100644 (file)
index 0000000..7eac631
Binary files /dev/null and b/zic.tproj/HACK/America/Detroit differ
diff --git a/zic.tproj/HACK/America/Dominica b/zic.tproj/HACK/America/Dominica
new file mode 100644 (file)
index 0000000..3cfb60a
Binary files /dev/null and b/zic.tproj/HACK/America/Dominica differ
diff --git a/zic.tproj/HACK/America/Edmonton b/zic.tproj/HACK/America/Edmonton
new file mode 100644 (file)
index 0000000..308bcae
Binary files /dev/null and b/zic.tproj/HACK/America/Edmonton differ
diff --git a/zic.tproj/HACK/America/El_Salvador b/zic.tproj/HACK/America/El_Salvador
new file mode 100644 (file)
index 0000000..08a5d9c
Binary files /dev/null and b/zic.tproj/HACK/America/El_Salvador differ
diff --git a/zic.tproj/HACK/America/Ensenada b/zic.tproj/HACK/America/Ensenada
new file mode 100644 (file)
index 0000000..f9da0ee
Binary files /dev/null and b/zic.tproj/HACK/America/Ensenada differ
diff --git a/zic.tproj/HACK/America/Fort_Wayne b/zic.tproj/HACK/America/Fort_Wayne
new file mode 100644 (file)
index 0000000..3961e65
Binary files /dev/null and b/zic.tproj/HACK/America/Fort_Wayne differ
diff --git a/zic.tproj/HACK/America/Fortaleza b/zic.tproj/HACK/America/Fortaleza
new file mode 100644 (file)
index 0000000..ed1327b
Binary files /dev/null and b/zic.tproj/HACK/America/Fortaleza differ
diff --git a/zic.tproj/HACK/America/Glace_Bay b/zic.tproj/HACK/America/Glace_Bay
new file mode 100644 (file)
index 0000000..eec6e75
Binary files /dev/null and b/zic.tproj/HACK/America/Glace_Bay differ
diff --git a/zic.tproj/HACK/America/Godthab b/zic.tproj/HACK/America/Godthab
new file mode 100644 (file)
index 0000000..6af0fb3
Binary files /dev/null and b/zic.tproj/HACK/America/Godthab differ
diff --git a/zic.tproj/HACK/America/Goose_Bay b/zic.tproj/HACK/America/Goose_Bay
new file mode 100644 (file)
index 0000000..56102d8
Binary files /dev/null and b/zic.tproj/HACK/America/Goose_Bay differ
diff --git a/zic.tproj/HACK/America/Grand_Turk b/zic.tproj/HACK/America/Grand_Turk
new file mode 100644 (file)
index 0000000..4cd05a2
Binary files /dev/null and b/zic.tproj/HACK/America/Grand_Turk differ
diff --git a/zic.tproj/HACK/America/Grenada b/zic.tproj/HACK/America/Grenada
new file mode 100644 (file)
index 0000000..5eb4e19
Binary files /dev/null and b/zic.tproj/HACK/America/Grenada differ
diff --git a/zic.tproj/HACK/America/Guadeloupe b/zic.tproj/HACK/America/Guadeloupe
new file mode 100644 (file)
index 0000000..8bb10fd
Binary files /dev/null and b/zic.tproj/HACK/America/Guadeloupe differ
diff --git a/zic.tproj/HACK/America/Guatemala b/zic.tproj/HACK/America/Guatemala
new file mode 100644 (file)
index 0000000..c2d5ae8
Binary files /dev/null and b/zic.tproj/HACK/America/Guatemala differ
diff --git a/zic.tproj/HACK/America/Guayaquil b/zic.tproj/HACK/America/Guayaquil
new file mode 100644 (file)
index 0000000..ad7bb79
Binary files /dev/null and b/zic.tproj/HACK/America/Guayaquil differ
diff --git a/zic.tproj/HACK/America/Guyana b/zic.tproj/HACK/America/Guyana
new file mode 100644 (file)
index 0000000..138b0e7
Binary files /dev/null and b/zic.tproj/HACK/America/Guyana differ
diff --git a/zic.tproj/HACK/America/Halifax b/zic.tproj/HACK/America/Halifax
new file mode 100644 (file)
index 0000000..92d441b
Binary files /dev/null and b/zic.tproj/HACK/America/Halifax differ
diff --git a/zic.tproj/HACK/America/Havana b/zic.tproj/HACK/America/Havana
new file mode 100644 (file)
index 0000000..50fd5db
Binary files /dev/null and b/zic.tproj/HACK/America/Havana differ
diff --git a/zic.tproj/HACK/America/Indiana/Indianapolis b/zic.tproj/HACK/America/Indiana/Indianapolis
new file mode 100644 (file)
index 0000000..3961e65
Binary files /dev/null and b/zic.tproj/HACK/America/Indiana/Indianapolis differ
diff --git a/zic.tproj/HACK/America/Indiana/Knox b/zic.tproj/HACK/America/Indiana/Knox
new file mode 100644 (file)
index 0000000..5c1ec16
Binary files /dev/null and b/zic.tproj/HACK/America/Indiana/Knox differ
diff --git a/zic.tproj/HACK/America/Indiana/Marengo b/zic.tproj/HACK/America/Indiana/Marengo
new file mode 100644 (file)
index 0000000..6bc8d13
Binary files /dev/null and b/zic.tproj/HACK/America/Indiana/Marengo differ
diff --git a/zic.tproj/HACK/America/Indiana/Vevay b/zic.tproj/HACK/America/Indiana/Vevay
new file mode 100644 (file)
index 0000000..fcd224f
Binary files /dev/null and b/zic.tproj/HACK/America/Indiana/Vevay differ
diff --git a/zic.tproj/HACK/America/Indianapolis b/zic.tproj/HACK/America/Indianapolis
new file mode 100644 (file)
index 0000000..3961e65
Binary files /dev/null and b/zic.tproj/HACK/America/Indianapolis differ
diff --git a/zic.tproj/HACK/America/Inuvik b/zic.tproj/HACK/America/Inuvik
new file mode 100644 (file)
index 0000000..7ce69b6
Binary files /dev/null and b/zic.tproj/HACK/America/Inuvik differ
diff --git a/zic.tproj/HACK/America/Iqaluit b/zic.tproj/HACK/America/Iqaluit
new file mode 100644 (file)
index 0000000..d5bf97a
Binary files /dev/null and b/zic.tproj/HACK/America/Iqaluit differ
diff --git a/zic.tproj/HACK/America/Jamaica b/zic.tproj/HACK/America/Jamaica
new file mode 100644 (file)
index 0000000..a77982e
Binary files /dev/null and b/zic.tproj/HACK/America/Jamaica differ
diff --git a/zic.tproj/HACK/America/Jujuy b/zic.tproj/HACK/America/Jujuy
new file mode 100644 (file)
index 0000000..d101bd1
Binary files /dev/null and b/zic.tproj/HACK/America/Jujuy differ
diff --git a/zic.tproj/HACK/America/Juneau b/zic.tproj/HACK/America/Juneau
new file mode 100644 (file)
index 0000000..a9d6784
Binary files /dev/null and b/zic.tproj/HACK/America/Juneau differ
diff --git a/zic.tproj/HACK/America/Knox_IN b/zic.tproj/HACK/America/Knox_IN
new file mode 100644 (file)
index 0000000..5c1ec16
Binary files /dev/null and b/zic.tproj/HACK/America/Knox_IN differ
diff --git a/zic.tproj/HACK/America/La_Paz b/zic.tproj/HACK/America/La_Paz
new file mode 100644 (file)
index 0000000..12a7f6f
Binary files /dev/null and b/zic.tproj/HACK/America/La_Paz differ
diff --git a/zic.tproj/HACK/America/Lima b/zic.tproj/HACK/America/Lima
new file mode 100644 (file)
index 0000000..0df607d
Binary files /dev/null and b/zic.tproj/HACK/America/Lima differ
diff --git a/zic.tproj/HACK/America/Los_Angeles b/zic.tproj/HACK/America/Los_Angeles
new file mode 100644 (file)
index 0000000..458d9b7
Binary files /dev/null and b/zic.tproj/HACK/America/Los_Angeles differ
diff --git a/zic.tproj/HACK/America/Louisville b/zic.tproj/HACK/America/Louisville
new file mode 100644 (file)
index 0000000..8bad9db
Binary files /dev/null and b/zic.tproj/HACK/America/Louisville differ
diff --git a/zic.tproj/HACK/America/Maceio b/zic.tproj/HACK/America/Maceio
new file mode 100644 (file)
index 0000000..27af65e
Binary files /dev/null and b/zic.tproj/HACK/America/Maceio differ
diff --git a/zic.tproj/HACK/America/Managua b/zic.tproj/HACK/America/Managua
new file mode 100644 (file)
index 0000000..f2cb9cb
Binary files /dev/null and b/zic.tproj/HACK/America/Managua differ
diff --git a/zic.tproj/HACK/America/Manaus b/zic.tproj/HACK/America/Manaus
new file mode 100644 (file)
index 0000000..27325b7
Binary files /dev/null and b/zic.tproj/HACK/America/Manaus differ
diff --git a/zic.tproj/HACK/America/Martinique b/zic.tproj/HACK/America/Martinique
new file mode 100644 (file)
index 0000000..7b39049
Binary files /dev/null and b/zic.tproj/HACK/America/Martinique differ
diff --git a/zic.tproj/HACK/America/Mazatlan b/zic.tproj/HACK/America/Mazatlan
new file mode 100644 (file)
index 0000000..affdb69
Binary files /dev/null and b/zic.tproj/HACK/America/Mazatlan differ
diff --git a/zic.tproj/HACK/America/Mendoza b/zic.tproj/HACK/America/Mendoza
new file mode 100644 (file)
index 0000000..3071e15
Binary files /dev/null and b/zic.tproj/HACK/America/Mendoza differ
diff --git a/zic.tproj/HACK/America/Menominee b/zic.tproj/HACK/America/Menominee
new file mode 100644 (file)
index 0000000..aad6bb0
Binary files /dev/null and b/zic.tproj/HACK/America/Menominee differ
diff --git a/zic.tproj/HACK/America/Mexico_City b/zic.tproj/HACK/America/Mexico_City
new file mode 100644 (file)
index 0000000..3e953e2
Binary files /dev/null and b/zic.tproj/HACK/America/Mexico_City differ
diff --git a/zic.tproj/HACK/America/Miquelon b/zic.tproj/HACK/America/Miquelon
new file mode 100644 (file)
index 0000000..5911e99
Binary files /dev/null and b/zic.tproj/HACK/America/Miquelon differ
diff --git a/zic.tproj/HACK/America/Montevideo b/zic.tproj/HACK/America/Montevideo
new file mode 100644 (file)
index 0000000..50e66fc
Binary files /dev/null and b/zic.tproj/HACK/America/Montevideo differ
diff --git a/zic.tproj/HACK/America/Montreal b/zic.tproj/HACK/America/Montreal
new file mode 100644 (file)
index 0000000..0bbe44a
Binary files /dev/null and b/zic.tproj/HACK/America/Montreal differ
diff --git a/zic.tproj/HACK/America/Montserrat b/zic.tproj/HACK/America/Montserrat
new file mode 100644 (file)
index 0000000..f7c8280
Binary files /dev/null and b/zic.tproj/HACK/America/Montserrat differ
diff --git a/zic.tproj/HACK/America/Nassau b/zic.tproj/HACK/America/Nassau
new file mode 100644 (file)
index 0000000..5407653
Binary files /dev/null and b/zic.tproj/HACK/America/Nassau differ
diff --git a/zic.tproj/HACK/America/New_York b/zic.tproj/HACK/America/New_York
new file mode 100644 (file)
index 0000000..2ddcd42
Binary files /dev/null and b/zic.tproj/HACK/America/New_York differ
diff --git a/zic.tproj/HACK/America/Nipigon b/zic.tproj/HACK/America/Nipigon
new file mode 100644 (file)
index 0000000..46c2a36
Binary files /dev/null and b/zic.tproj/HACK/America/Nipigon differ
diff --git a/zic.tproj/HACK/America/Nome b/zic.tproj/HACK/America/Nome
new file mode 100644 (file)
index 0000000..1764415
Binary files /dev/null and b/zic.tproj/HACK/America/Nome differ
diff --git a/zic.tproj/HACK/America/Noronha b/zic.tproj/HACK/America/Noronha
new file mode 100644 (file)
index 0000000..0a9ae0d
Binary files /dev/null and b/zic.tproj/HACK/America/Noronha differ
diff --git a/zic.tproj/HACK/America/Panama b/zic.tproj/HACK/America/Panama
new file mode 100644 (file)
index 0000000..898e9c8
Binary files /dev/null and b/zic.tproj/HACK/America/Panama differ
diff --git a/zic.tproj/HACK/America/Pangnirtung b/zic.tproj/HACK/America/Pangnirtung
new file mode 100644 (file)
index 0000000..c6c4a17
Binary files /dev/null and b/zic.tproj/HACK/America/Pangnirtung differ
diff --git a/zic.tproj/HACK/America/Paramaribo b/zic.tproj/HACK/America/Paramaribo
new file mode 100644 (file)
index 0000000..0147927
Binary files /dev/null and b/zic.tproj/HACK/America/Paramaribo differ
diff --git a/zic.tproj/HACK/America/Phoenix b/zic.tproj/HACK/America/Phoenix
new file mode 100644 (file)
index 0000000..d684fb3
Binary files /dev/null and b/zic.tproj/HACK/America/Phoenix differ
diff --git a/zic.tproj/HACK/America/Port-au-Prince b/zic.tproj/HACK/America/Port-au-Prince
new file mode 100644 (file)
index 0000000..4401144
Binary files /dev/null and b/zic.tproj/HACK/America/Port-au-Prince differ
diff --git a/zic.tproj/HACK/America/Port_of_Spain b/zic.tproj/HACK/America/Port_of_Spain
new file mode 100644 (file)
index 0000000..f75940e
Binary files /dev/null and b/zic.tproj/HACK/America/Port_of_Spain differ
diff --git a/zic.tproj/HACK/America/Porto_Acre b/zic.tproj/HACK/America/Porto_Acre
new file mode 100644 (file)
index 0000000..801849e
Binary files /dev/null and b/zic.tproj/HACK/America/Porto_Acre differ
diff --git a/zic.tproj/HACK/America/Puerto_Rico b/zic.tproj/HACK/America/Puerto_Rico
new file mode 100644 (file)
index 0000000..fe15994
Binary files /dev/null and b/zic.tproj/HACK/America/Puerto_Rico differ
diff --git a/zic.tproj/HACK/America/Rainy_River b/zic.tproj/HACK/America/Rainy_River
new file mode 100644 (file)
index 0000000..4129d90
Binary files /dev/null and b/zic.tproj/HACK/America/Rainy_River differ
diff --git a/zic.tproj/HACK/America/Rankin_Inlet b/zic.tproj/HACK/America/Rankin_Inlet
new file mode 100644 (file)
index 0000000..a5afa3d
Binary files /dev/null and b/zic.tproj/HACK/America/Rankin_Inlet differ
diff --git a/zic.tproj/HACK/America/Regina b/zic.tproj/HACK/America/Regina
new file mode 100644 (file)
index 0000000..a62958a
Binary files /dev/null and b/zic.tproj/HACK/America/Regina differ
diff --git a/zic.tproj/HACK/America/Rosario b/zic.tproj/HACK/America/Rosario
new file mode 100644 (file)
index 0000000..0a58464
Binary files /dev/null and b/zic.tproj/HACK/America/Rosario differ
diff --git a/zic.tproj/HACK/America/Santiago b/zic.tproj/HACK/America/Santiago
new file mode 100644 (file)
index 0000000..cc1139f
Binary files /dev/null and b/zic.tproj/HACK/America/Santiago differ
diff --git a/zic.tproj/HACK/America/Santo_Domingo b/zic.tproj/HACK/America/Santo_Domingo
new file mode 100644 (file)
index 0000000..3f6951f
Binary files /dev/null and b/zic.tproj/HACK/America/Santo_Domingo differ
diff --git a/zic.tproj/HACK/America/Sao_Paulo b/zic.tproj/HACK/America/Sao_Paulo
new file mode 100644 (file)
index 0000000..e504ee8
Binary files /dev/null and b/zic.tproj/HACK/America/Sao_Paulo differ
diff --git a/zic.tproj/HACK/America/Scoresbysund b/zic.tproj/HACK/America/Scoresbysund
new file mode 100644 (file)
index 0000000..57a53ce
Binary files /dev/null and b/zic.tproj/HACK/America/Scoresbysund differ
diff --git a/zic.tproj/HACK/America/Shiprock b/zic.tproj/HACK/America/Shiprock
new file mode 100644 (file)
index 0000000..fc45907
Binary files /dev/null and b/zic.tproj/HACK/America/Shiprock differ
diff --git a/zic.tproj/HACK/America/St_Johns b/zic.tproj/HACK/America/St_Johns
new file mode 100644 (file)
index 0000000..2409d71
Binary files /dev/null and b/zic.tproj/HACK/America/St_Johns differ
diff --git a/zic.tproj/HACK/America/St_Kitts b/zic.tproj/HACK/America/St_Kitts
new file mode 100644 (file)
index 0000000..aed21c4
Binary files /dev/null and b/zic.tproj/HACK/America/St_Kitts differ
diff --git a/zic.tproj/HACK/America/St_Lucia b/zic.tproj/HACK/America/St_Lucia
new file mode 100644 (file)
index 0000000..ff85195
Binary files /dev/null and b/zic.tproj/HACK/America/St_Lucia differ
diff --git a/zic.tproj/HACK/America/St_Thomas b/zic.tproj/HACK/America/St_Thomas
new file mode 100644 (file)
index 0000000..cdd324d
Binary files /dev/null and b/zic.tproj/HACK/America/St_Thomas differ
diff --git a/zic.tproj/HACK/America/St_Vincent b/zic.tproj/HACK/America/St_Vincent
new file mode 100644 (file)
index 0000000..a8ea029
Binary files /dev/null and b/zic.tproj/HACK/America/St_Vincent differ
diff --git a/zic.tproj/HACK/America/Swift_Current b/zic.tproj/HACK/America/Swift_Current
new file mode 100644 (file)
index 0000000..63f5172
Binary files /dev/null and b/zic.tproj/HACK/America/Swift_Current differ
diff --git a/zic.tproj/HACK/America/Tegucigalpa b/zic.tproj/HACK/America/Tegucigalpa
new file mode 100644 (file)
index 0000000..d50da94
Binary files /dev/null and b/zic.tproj/HACK/America/Tegucigalpa differ
diff --git a/zic.tproj/HACK/America/Thule b/zic.tproj/HACK/America/Thule
new file mode 100644 (file)
index 0000000..a82ecf7
Binary files /dev/null and b/zic.tproj/HACK/America/Thule differ
diff --git a/zic.tproj/HACK/America/Thunder_Bay b/zic.tproj/HACK/America/Thunder_Bay
new file mode 100644 (file)
index 0000000..1bef65a
Binary files /dev/null and b/zic.tproj/HACK/America/Thunder_Bay differ
diff --git a/zic.tproj/HACK/America/Tijuana b/zic.tproj/HACK/America/Tijuana
new file mode 100644 (file)
index 0000000..e23f80b
Binary files /dev/null and b/zic.tproj/HACK/America/Tijuana differ
diff --git a/zic.tproj/HACK/America/Tortola b/zic.tproj/HACK/America/Tortola
new file mode 100644 (file)
index 0000000..5867b2f
Binary files /dev/null and b/zic.tproj/HACK/America/Tortola differ
diff --git a/zic.tproj/HACK/America/Vancouver b/zic.tproj/HACK/America/Vancouver
new file mode 100644 (file)
index 0000000..6d6ce95
Binary files /dev/null and b/zic.tproj/HACK/America/Vancouver differ
diff --git a/zic.tproj/HACK/America/Virgin b/zic.tproj/HACK/America/Virgin
new file mode 100644 (file)
index 0000000..cdd324d
Binary files /dev/null and b/zic.tproj/HACK/America/Virgin differ
diff --git a/zic.tproj/HACK/America/Whitehorse b/zic.tproj/HACK/America/Whitehorse
new file mode 100644 (file)
index 0000000..5d86e0f
Binary files /dev/null and b/zic.tproj/HACK/America/Whitehorse differ
diff --git a/zic.tproj/HACK/America/Winnipeg b/zic.tproj/HACK/America/Winnipeg
new file mode 100644 (file)
index 0000000..0676968
Binary files /dev/null and b/zic.tproj/HACK/America/Winnipeg differ
diff --git a/zic.tproj/HACK/America/Yakutat b/zic.tproj/HACK/America/Yakutat
new file mode 100644 (file)
index 0000000..476ab58
Binary files /dev/null and b/zic.tproj/HACK/America/Yakutat differ
diff --git a/zic.tproj/HACK/America/Yellowknife b/zic.tproj/HACK/America/Yellowknife
new file mode 100644 (file)
index 0000000..44f1e5b
Binary files /dev/null and b/zic.tproj/HACK/America/Yellowknife differ
diff --git a/zic.tproj/HACK/Antarctica/Casey b/zic.tproj/HACK/Antarctica/Casey
new file mode 100644 (file)
index 0000000..54fa174
Binary files /dev/null and b/zic.tproj/HACK/Antarctica/Casey differ
diff --git a/zic.tproj/HACK/Antarctica/Mawson b/zic.tproj/HACK/Antarctica/Mawson
new file mode 100644 (file)
index 0000000..d9c019c
Binary files /dev/null and b/zic.tproj/HACK/Antarctica/Mawson differ
diff --git a/zic.tproj/HACK/Antarctica/McMurdo b/zic.tproj/HACK/Antarctica/McMurdo
new file mode 100644 (file)
index 0000000..8a2d81e
Binary files /dev/null and b/zic.tproj/HACK/Antarctica/McMurdo differ
diff --git a/zic.tproj/HACK/Antarctica/Palmer b/zic.tproj/HACK/Antarctica/Palmer
new file mode 100644 (file)
index 0000000..0e4d3e5
Binary files /dev/null and b/zic.tproj/HACK/Antarctica/Palmer differ
diff --git a/zic.tproj/HACK/Antarctica/South_Pole b/zic.tproj/HACK/Antarctica/South_Pole
new file mode 100644 (file)
index 0000000..8a2d81e
Binary files /dev/null and b/zic.tproj/HACK/Antarctica/South_Pole differ
diff --git a/zic.tproj/HACK/Arctic/Longyearbyen b/zic.tproj/HACK/Arctic/Longyearbyen
new file mode 100644 (file)
index 0000000..8e8060d
Binary files /dev/null and b/zic.tproj/HACK/Arctic/Longyearbyen differ
diff --git a/zic.tproj/HACK/Asia/Aden b/zic.tproj/HACK/Asia/Aden
new file mode 100644 (file)
index 0000000..0a3c20f
Binary files /dev/null and b/zic.tproj/HACK/Asia/Aden differ
diff --git a/zic.tproj/HACK/Asia/Alma-Ata b/zic.tproj/HACK/Asia/Alma-Ata
new file mode 100644 (file)
index 0000000..436a9e1
Binary files /dev/null and b/zic.tproj/HACK/Asia/Alma-Ata differ
diff --git a/zic.tproj/HACK/Asia/Amman b/zic.tproj/HACK/Asia/Amman
new file mode 100644 (file)
index 0000000..6e44712
Binary files /dev/null and b/zic.tproj/HACK/Asia/Amman differ
diff --git a/zic.tproj/HACK/Asia/Anadyr b/zic.tproj/HACK/Asia/Anadyr
new file mode 100644 (file)
index 0000000..49b918b
Binary files /dev/null and b/zic.tproj/HACK/Asia/Anadyr differ
diff --git a/zic.tproj/HACK/Asia/Aqtau b/zic.tproj/HACK/Asia/Aqtau
new file mode 100644 (file)
index 0000000..6c320d2
Binary files /dev/null and b/zic.tproj/HACK/Asia/Aqtau differ
diff --git a/zic.tproj/HACK/Asia/Aqtobe b/zic.tproj/HACK/Asia/Aqtobe
new file mode 100644 (file)
index 0000000..6ff4400
Binary files /dev/null and b/zic.tproj/HACK/Asia/Aqtobe differ
diff --git a/zic.tproj/HACK/Asia/Ashkhabad b/zic.tproj/HACK/Asia/Ashkhabad
new file mode 100644 (file)
index 0000000..2859f3c
Binary files /dev/null and b/zic.tproj/HACK/Asia/Ashkhabad differ
diff --git a/zic.tproj/HACK/Asia/Baghdad b/zic.tproj/HACK/Asia/Baghdad
new file mode 100644 (file)
index 0000000..a6ff7b3
Binary files /dev/null and b/zic.tproj/HACK/Asia/Baghdad differ
diff --git a/zic.tproj/HACK/Asia/Bahrain b/zic.tproj/HACK/Asia/Bahrain
new file mode 100644 (file)
index 0000000..dbd08f8
Binary files /dev/null and b/zic.tproj/HACK/Asia/Bahrain differ
diff --git a/zic.tproj/HACK/Asia/Baku b/zic.tproj/HACK/Asia/Baku
new file mode 100644 (file)
index 0000000..8efd48a
Binary files /dev/null and b/zic.tproj/HACK/Asia/Baku differ
diff --git a/zic.tproj/HACK/Asia/Bangkok b/zic.tproj/HACK/Asia/Bangkok
new file mode 100644 (file)
index 0000000..1206ce5
Binary files /dev/null and b/zic.tproj/HACK/Asia/Bangkok differ
diff --git a/zic.tproj/HACK/Asia/Beirut b/zic.tproj/HACK/Asia/Beirut
new file mode 100644 (file)
index 0000000..40a523b
Binary files /dev/null and b/zic.tproj/HACK/Asia/Beirut differ
diff --git a/zic.tproj/HACK/Asia/Bishkek b/zic.tproj/HACK/Asia/Bishkek
new file mode 100644 (file)
index 0000000..c5fe2fe
Binary files /dev/null and b/zic.tproj/HACK/Asia/Bishkek differ
diff --git a/zic.tproj/HACK/Asia/Brunei b/zic.tproj/HACK/Asia/Brunei
new file mode 100644 (file)
index 0000000..7a43240
Binary files /dev/null and b/zic.tproj/HACK/Asia/Brunei differ
diff --git a/zic.tproj/HACK/Asia/Calcutta b/zic.tproj/HACK/Asia/Calcutta
new file mode 100644 (file)
index 0000000..6f64b8d
Binary files /dev/null and b/zic.tproj/HACK/Asia/Calcutta differ
diff --git a/zic.tproj/HACK/Asia/Chungking b/zic.tproj/HACK/Asia/Chungking
new file mode 100644 (file)
index 0000000..c9e99cd
Binary files /dev/null and b/zic.tproj/HACK/Asia/Chungking differ
diff --git a/zic.tproj/HACK/Asia/Colombo b/zic.tproj/HACK/Asia/Colombo
new file mode 100644 (file)
index 0000000..d7340a0
Binary files /dev/null and b/zic.tproj/HACK/Asia/Colombo differ
diff --git a/zic.tproj/HACK/Asia/Dacca b/zic.tproj/HACK/Asia/Dacca
new file mode 100644 (file)
index 0000000..63b355f
Binary files /dev/null and b/zic.tproj/HACK/Asia/Dacca differ
diff --git a/zic.tproj/HACK/Asia/Damascus b/zic.tproj/HACK/Asia/Damascus
new file mode 100644 (file)
index 0000000..2087aeb
Binary files /dev/null and b/zic.tproj/HACK/Asia/Damascus differ
diff --git a/zic.tproj/HACK/Asia/Dubai b/zic.tproj/HACK/Asia/Dubai
new file mode 100644 (file)
index 0000000..89be26a
Binary files /dev/null and b/zic.tproj/HACK/Asia/Dubai differ
diff --git a/zic.tproj/HACK/Asia/Dushanbe b/zic.tproj/HACK/Asia/Dushanbe
new file mode 100644 (file)
index 0000000..4ed1882
Binary files /dev/null and b/zic.tproj/HACK/Asia/Dushanbe differ
diff --git a/zic.tproj/HACK/Asia/Gaza b/zic.tproj/HACK/Asia/Gaza
new file mode 100644 (file)
index 0000000..010c8b9
Binary files /dev/null and b/zic.tproj/HACK/Asia/Gaza differ
diff --git a/zic.tproj/HACK/Asia/Harbin b/zic.tproj/HACK/Asia/Harbin
new file mode 100644 (file)
index 0000000..9f59126
Binary files /dev/null and b/zic.tproj/HACK/Asia/Harbin differ
diff --git a/zic.tproj/HACK/Asia/Hong_Kong b/zic.tproj/HACK/Asia/Hong_Kong
new file mode 100644 (file)
index 0000000..ad523a5
Binary files /dev/null and b/zic.tproj/HACK/Asia/Hong_Kong differ
diff --git a/zic.tproj/HACK/Asia/Irkutsk b/zic.tproj/HACK/Asia/Irkutsk
new file mode 100644 (file)
index 0000000..944623f
Binary files /dev/null and b/zic.tproj/HACK/Asia/Irkutsk differ
diff --git a/zic.tproj/HACK/Asia/Ishigaki b/zic.tproj/HACK/Asia/Ishigaki
new file mode 100644 (file)
index 0000000..46af0d9
Binary files /dev/null and b/zic.tproj/HACK/Asia/Ishigaki differ
diff --git a/zic.tproj/HACK/Asia/Istanbul b/zic.tproj/HACK/Asia/Istanbul
new file mode 100644 (file)
index 0000000..b05d65a
Binary files /dev/null and b/zic.tproj/HACK/Asia/Istanbul differ
diff --git a/zic.tproj/HACK/Asia/Jakarta b/zic.tproj/HACK/Asia/Jakarta
new file mode 100644 (file)
index 0000000..63116e2
Binary files /dev/null and b/zic.tproj/HACK/Asia/Jakarta differ
diff --git a/zic.tproj/HACK/Asia/Jayapura b/zic.tproj/HACK/Asia/Jayapura
new file mode 100644 (file)
index 0000000..697c6fa
Binary files /dev/null and b/zic.tproj/HACK/Asia/Jayapura differ
diff --git a/zic.tproj/HACK/Asia/Jerusalem b/zic.tproj/HACK/Asia/Jerusalem
new file mode 100644 (file)
index 0000000..b604803
Binary files /dev/null and b/zic.tproj/HACK/Asia/Jerusalem differ
diff --git a/zic.tproj/HACK/Asia/Kabul b/zic.tproj/HACK/Asia/Kabul
new file mode 100644 (file)
index 0000000..e497d00
Binary files /dev/null and b/zic.tproj/HACK/Asia/Kabul differ
diff --git a/zic.tproj/HACK/Asia/Kamchatka b/zic.tproj/HACK/Asia/Kamchatka
new file mode 100644 (file)
index 0000000..e33ab59
Binary files /dev/null and b/zic.tproj/HACK/Asia/Kamchatka differ
diff --git a/zic.tproj/HACK/Asia/Karachi b/zic.tproj/HACK/Asia/Karachi
new file mode 100644 (file)
index 0000000..1571d2b
Binary files /dev/null and b/zic.tproj/HACK/Asia/Karachi differ
diff --git a/zic.tproj/HACK/Asia/Kashgar b/zic.tproj/HACK/Asia/Kashgar
new file mode 100644 (file)
index 0000000..424ffbc
Binary files /dev/null and b/zic.tproj/HACK/Asia/Kashgar differ
diff --git a/zic.tproj/HACK/Asia/Katmandu b/zic.tproj/HACK/Asia/Katmandu
new file mode 100644 (file)
index 0000000..97780af
Binary files /dev/null and b/zic.tproj/HACK/Asia/Katmandu differ
diff --git a/zic.tproj/HACK/Asia/Krasnoyarsk b/zic.tproj/HACK/Asia/Krasnoyarsk
new file mode 100644 (file)
index 0000000..2e51185
Binary files /dev/null and b/zic.tproj/HACK/Asia/Krasnoyarsk differ
diff --git a/zic.tproj/HACK/Asia/Kuala_Lumpur b/zic.tproj/HACK/Asia/Kuala_Lumpur
new file mode 100644 (file)
index 0000000..f503dd8
Binary files /dev/null and b/zic.tproj/HACK/Asia/Kuala_Lumpur differ
diff --git a/zic.tproj/HACK/Asia/Kuching b/zic.tproj/HACK/Asia/Kuching
new file mode 100644 (file)
index 0000000..8f9575c
Binary files /dev/null and b/zic.tproj/HACK/Asia/Kuching differ
diff --git a/zic.tproj/HACK/Asia/Kuwait b/zic.tproj/HACK/Asia/Kuwait
new file mode 100644 (file)
index 0000000..eb229c6
Binary files /dev/null and b/zic.tproj/HACK/Asia/Kuwait differ
diff --git a/zic.tproj/HACK/Asia/Macao b/zic.tproj/HACK/Asia/Macao
new file mode 100644 (file)
index 0000000..4bf5ce1
Binary files /dev/null and b/zic.tproj/HACK/Asia/Macao differ
diff --git a/zic.tproj/HACK/Asia/Magadan b/zic.tproj/HACK/Asia/Magadan
new file mode 100644 (file)
index 0000000..fe9851e
Binary files /dev/null and b/zic.tproj/HACK/Asia/Magadan differ
diff --git a/zic.tproj/HACK/Asia/Manila b/zic.tproj/HACK/Asia/Manila
new file mode 100644 (file)
index 0000000..0abb850
Binary files /dev/null and b/zic.tproj/HACK/Asia/Manila differ
diff --git a/zic.tproj/HACK/Asia/Muscat b/zic.tproj/HACK/Asia/Muscat
new file mode 100644 (file)
index 0000000..b46c0c0
Binary files /dev/null and b/zic.tproj/HACK/Asia/Muscat differ
diff --git a/zic.tproj/HACK/Asia/Nicosia b/zic.tproj/HACK/Asia/Nicosia
new file mode 100644 (file)
index 0000000..6d5dd04
Binary files /dev/null and b/zic.tproj/HACK/Asia/Nicosia differ
diff --git a/zic.tproj/HACK/Asia/Novosibirsk b/zic.tproj/HACK/Asia/Novosibirsk
new file mode 100644 (file)
index 0000000..f920772
Binary files /dev/null and b/zic.tproj/HACK/Asia/Novosibirsk differ
diff --git a/zic.tproj/HACK/Asia/Omsk b/zic.tproj/HACK/Asia/Omsk
new file mode 100644 (file)
index 0000000..1c09845
Binary files /dev/null and b/zic.tproj/HACK/Asia/Omsk differ
diff --git a/zic.tproj/HACK/Asia/Phnom_Penh b/zic.tproj/HACK/Asia/Phnom_Penh
new file mode 100644 (file)
index 0000000..5bb46ae
Binary files /dev/null and b/zic.tproj/HACK/Asia/Phnom_Penh differ
diff --git a/zic.tproj/HACK/Asia/Pyongyang b/zic.tproj/HACK/Asia/Pyongyang
new file mode 100644 (file)
index 0000000..c96feaf
Binary files /dev/null and b/zic.tproj/HACK/Asia/Pyongyang differ
diff --git a/zic.tproj/HACK/Asia/Qatar b/zic.tproj/HACK/Asia/Qatar
new file mode 100644 (file)
index 0000000..b685b18
Binary files /dev/null and b/zic.tproj/HACK/Asia/Qatar differ
diff --git a/zic.tproj/HACK/Asia/Rangoon b/zic.tproj/HACK/Asia/Rangoon
new file mode 100644 (file)
index 0000000..e2ca4b8
Binary files /dev/null and b/zic.tproj/HACK/Asia/Rangoon differ
diff --git a/zic.tproj/HACK/Asia/Riyadh b/zic.tproj/HACK/Asia/Riyadh
new file mode 100644 (file)
index 0000000..1efd826
Binary files /dev/null and b/zic.tproj/HACK/Asia/Riyadh differ
diff --git a/zic.tproj/HACK/Asia/Riyadh87 b/zic.tproj/HACK/Asia/Riyadh87
new file mode 100644 (file)
index 0000000..1dac2ae
Binary files /dev/null and b/zic.tproj/HACK/Asia/Riyadh87 differ
diff --git a/zic.tproj/HACK/Asia/Riyadh88 b/zic.tproj/HACK/Asia/Riyadh88
new file mode 100644 (file)
index 0000000..ee7474e
Binary files /dev/null and b/zic.tproj/HACK/Asia/Riyadh88 differ
diff --git a/zic.tproj/HACK/Asia/Riyadh89 b/zic.tproj/HACK/Asia/Riyadh89
new file mode 100644 (file)
index 0000000..6f12699
Binary files /dev/null and b/zic.tproj/HACK/Asia/Riyadh89 differ
diff --git a/zic.tproj/HACK/Asia/Saigon b/zic.tproj/HACK/Asia/Saigon
new file mode 100644 (file)
index 0000000..f5255d8
Binary files /dev/null and b/zic.tproj/HACK/Asia/Saigon differ
diff --git a/zic.tproj/HACK/Asia/Seoul b/zic.tproj/HACK/Asia/Seoul
new file mode 100644 (file)
index 0000000..9a2cd24
Binary files /dev/null and b/zic.tproj/HACK/Asia/Seoul differ
diff --git a/zic.tproj/HACK/Asia/Shanghai b/zic.tproj/HACK/Asia/Shanghai
new file mode 100644 (file)
index 0000000..2f0c5ec
Binary files /dev/null and b/zic.tproj/HACK/Asia/Shanghai differ
diff --git a/zic.tproj/HACK/Asia/Singapore b/zic.tproj/HACK/Asia/Singapore
new file mode 100644 (file)
index 0000000..41cfd62
Binary files /dev/null and b/zic.tproj/HACK/Asia/Singapore differ
diff --git a/zic.tproj/HACK/Asia/Taipei b/zic.tproj/HACK/Asia/Taipei
new file mode 100644 (file)
index 0000000..aa2b3f0
Binary files /dev/null and b/zic.tproj/HACK/Asia/Taipei differ
diff --git a/zic.tproj/HACK/Asia/Tashkent b/zic.tproj/HACK/Asia/Tashkent
new file mode 100644 (file)
index 0000000..d89d832
Binary files /dev/null and b/zic.tproj/HACK/Asia/Tashkent differ
diff --git a/zic.tproj/HACK/Asia/Tbilisi b/zic.tproj/HACK/Asia/Tbilisi
new file mode 100644 (file)
index 0000000..eb308e2
Binary files /dev/null and b/zic.tproj/HACK/Asia/Tbilisi differ
diff --git a/zic.tproj/HACK/Asia/Tehran b/zic.tproj/HACK/Asia/Tehran
new file mode 100644 (file)
index 0000000..0b3a6ae
Binary files /dev/null and b/zic.tproj/HACK/Asia/Tehran differ
diff --git a/zic.tproj/HACK/Asia/Tel_Aviv b/zic.tproj/HACK/Asia/Tel_Aviv
new file mode 100644 (file)
index 0000000..b604803
Binary files /dev/null and b/zic.tproj/HACK/Asia/Tel_Aviv differ
diff --git a/zic.tproj/HACK/Asia/Thimbu b/zic.tproj/HACK/Asia/Thimbu
new file mode 100644 (file)
index 0000000..9b5d053
Binary files /dev/null and b/zic.tproj/HACK/Asia/Thimbu differ
diff --git a/zic.tproj/HACK/Asia/Tokyo b/zic.tproj/HACK/Asia/Tokyo
new file mode 100644 (file)
index 0000000..5494fd2
Binary files /dev/null and b/zic.tproj/HACK/Asia/Tokyo differ
diff --git a/zic.tproj/HACK/Asia/Ujung_Pandang b/zic.tproj/HACK/Asia/Ujung_Pandang
new file mode 100644 (file)
index 0000000..cfb66cc
Binary files /dev/null and b/zic.tproj/HACK/Asia/Ujung_Pandang differ
diff --git a/zic.tproj/HACK/Asia/Ulan_Bator b/zic.tproj/HACK/Asia/Ulan_Bator
new file mode 100644 (file)
index 0000000..cc8c101
Binary files /dev/null and b/zic.tproj/HACK/Asia/Ulan_Bator differ
diff --git a/zic.tproj/HACK/Asia/Urumqi b/zic.tproj/HACK/Asia/Urumqi
new file mode 100644 (file)
index 0000000..82075b1
Binary files /dev/null and b/zic.tproj/HACK/Asia/Urumqi differ
diff --git a/zic.tproj/HACK/Asia/Vientiane b/zic.tproj/HACK/Asia/Vientiane
new file mode 100644 (file)
index 0000000..963a7c9
Binary files /dev/null and b/zic.tproj/HACK/Asia/Vientiane differ
diff --git a/zic.tproj/HACK/Asia/Vladivostok b/zic.tproj/HACK/Asia/Vladivostok
new file mode 100644 (file)
index 0000000..98c9163
Binary files /dev/null and b/zic.tproj/HACK/Asia/Vladivostok differ
diff --git a/zic.tproj/HACK/Asia/Yakutsk b/zic.tproj/HACK/Asia/Yakutsk
new file mode 100644 (file)
index 0000000..6cc45a6
Binary files /dev/null and b/zic.tproj/HACK/Asia/Yakutsk differ
diff --git a/zic.tproj/HACK/Asia/Yekaterinburg b/zic.tproj/HACK/Asia/Yekaterinburg
new file mode 100644 (file)
index 0000000..52a071e
Binary files /dev/null and b/zic.tproj/HACK/Asia/Yekaterinburg differ
diff --git a/zic.tproj/HACK/Asia/Yerevan b/zic.tproj/HACK/Asia/Yerevan
new file mode 100644 (file)
index 0000000..1d3c5ee
Binary files /dev/null and b/zic.tproj/HACK/Asia/Yerevan differ
diff --git a/zic.tproj/HACK/Atlantic/Azores b/zic.tproj/HACK/Atlantic/Azores
new file mode 100644 (file)
index 0000000..537e535
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Azores differ
diff --git a/zic.tproj/HACK/Atlantic/Bermuda b/zic.tproj/HACK/Atlantic/Bermuda
new file mode 100644 (file)
index 0000000..bb0bb77
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Bermuda differ
diff --git a/zic.tproj/HACK/Atlantic/Canary b/zic.tproj/HACK/Atlantic/Canary
new file mode 100644 (file)
index 0000000..801f309
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Canary differ
diff --git a/zic.tproj/HACK/Atlantic/Cape_Verde b/zic.tproj/HACK/Atlantic/Cape_Verde
new file mode 100644 (file)
index 0000000..363cef5
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Cape_Verde differ
diff --git a/zic.tproj/HACK/Atlantic/Faeroe b/zic.tproj/HACK/Atlantic/Faeroe
new file mode 100644 (file)
index 0000000..79d1ba3
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Faeroe differ
diff --git a/zic.tproj/HACK/Atlantic/Jan_Mayen b/zic.tproj/HACK/Atlantic/Jan_Mayen
new file mode 100644 (file)
index 0000000..36490f1
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Jan_Mayen differ
diff --git a/zic.tproj/HACK/Atlantic/Madeira b/zic.tproj/HACK/Atlantic/Madeira
new file mode 100644 (file)
index 0000000..7de0f2a
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Madeira differ
diff --git a/zic.tproj/HACK/Atlantic/Reykjavik b/zic.tproj/HACK/Atlantic/Reykjavik
new file mode 100644 (file)
index 0000000..d810ba4
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Reykjavik differ
diff --git a/zic.tproj/HACK/Atlantic/South_Georgia b/zic.tproj/HACK/Atlantic/South_Georgia
new file mode 100644 (file)
index 0000000..529be32
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/South_Georgia differ
diff --git a/zic.tproj/HACK/Atlantic/St_Helena b/zic.tproj/HACK/Atlantic/St_Helena
new file mode 100644 (file)
index 0000000..f31fe55
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/St_Helena differ
diff --git a/zic.tproj/HACK/Atlantic/Stanley b/zic.tproj/HACK/Atlantic/Stanley
new file mode 100644 (file)
index 0000000..7b33dd3
Binary files /dev/null and b/zic.tproj/HACK/Atlantic/Stanley differ
diff --git a/zic.tproj/HACK/Australia/ACT b/zic.tproj/HACK/Australia/ACT
new file mode 100644 (file)
index 0000000..f9dca84
Binary files /dev/null and b/zic.tproj/HACK/Australia/ACT differ
diff --git a/zic.tproj/HACK/Australia/Adelaide b/zic.tproj/HACK/Australia/Adelaide
new file mode 100644 (file)
index 0000000..3a4d27e
Binary files /dev/null and b/zic.tproj/HACK/Australia/Adelaide differ
diff --git a/zic.tproj/HACK/Australia/Brisbane b/zic.tproj/HACK/Australia/Brisbane
new file mode 100644 (file)
index 0000000..6798e97
Binary files /dev/null and b/zic.tproj/HACK/Australia/Brisbane differ
diff --git a/zic.tproj/HACK/Australia/Broken_Hill b/zic.tproj/HACK/Australia/Broken_Hill
new file mode 100644 (file)
index 0000000..46aff75
Binary files /dev/null and b/zic.tproj/HACK/Australia/Broken_Hill differ
diff --git a/zic.tproj/HACK/Australia/Canberra b/zic.tproj/HACK/Australia/Canberra
new file mode 100644 (file)
index 0000000..f9dca84
Binary files /dev/null and b/zic.tproj/HACK/Australia/Canberra differ
diff --git a/zic.tproj/HACK/Australia/Darwin b/zic.tproj/HACK/Australia/Darwin
new file mode 100644 (file)
index 0000000..ba8b16a
Binary files /dev/null and b/zic.tproj/HACK/Australia/Darwin differ
diff --git a/zic.tproj/HACK/Australia/Hobart b/zic.tproj/HACK/Australia/Hobart
new file mode 100644 (file)
index 0000000..d6825f5
Binary files /dev/null and b/zic.tproj/HACK/Australia/Hobart differ
diff --git a/zic.tproj/HACK/Australia/LHI b/zic.tproj/HACK/Australia/LHI
new file mode 100644 (file)
index 0000000..843ef4c
Binary files /dev/null and b/zic.tproj/HACK/Australia/LHI differ
diff --git a/zic.tproj/HACK/Australia/Lindeman b/zic.tproj/HACK/Australia/Lindeman
new file mode 100644 (file)
index 0000000..ef15cf0
Binary files /dev/null and b/zic.tproj/HACK/Australia/Lindeman differ
diff --git a/zic.tproj/HACK/Australia/Lord_Howe b/zic.tproj/HACK/Australia/Lord_Howe
new file mode 100644 (file)
index 0000000..843ef4c
Binary files /dev/null and b/zic.tproj/HACK/Australia/Lord_Howe differ
diff --git a/zic.tproj/HACK/Australia/Melbourne b/zic.tproj/HACK/Australia/Melbourne
new file mode 100644 (file)
index 0000000..fa307b5
Binary files /dev/null and b/zic.tproj/HACK/Australia/Melbourne differ
diff --git a/zic.tproj/HACK/Australia/NSW b/zic.tproj/HACK/Australia/NSW
new file mode 100644 (file)
index 0000000..f9dca84
Binary files /dev/null and b/zic.tproj/HACK/Australia/NSW differ
diff --git a/zic.tproj/HACK/Australia/North b/zic.tproj/HACK/Australia/North
new file mode 100644 (file)
index 0000000..ba8b16a
Binary files /dev/null and b/zic.tproj/HACK/Australia/North differ
diff --git a/zic.tproj/HACK/Australia/Perth b/zic.tproj/HACK/Australia/Perth
new file mode 100644 (file)
index 0000000..bf5a03e
Binary files /dev/null and b/zic.tproj/HACK/Australia/Perth differ
diff --git a/zic.tproj/HACK/Australia/Queensland b/zic.tproj/HACK/Australia/Queensland
new file mode 100644 (file)
index 0000000..6798e97
Binary files /dev/null and b/zic.tproj/HACK/Australia/Queensland differ
diff --git a/zic.tproj/HACK/Australia/South b/zic.tproj/HACK/Australia/South
new file mode 100644 (file)
index 0000000..3a4d27e
Binary files /dev/null and b/zic.tproj/HACK/Australia/South differ
diff --git a/zic.tproj/HACK/Australia/Sydney b/zic.tproj/HACK/Australia/Sydney
new file mode 100644 (file)
index 0000000..f9dca84
Binary files /dev/null and b/zic.tproj/HACK/Australia/Sydney differ
diff --git a/zic.tproj/HACK/Australia/Tasmania b/zic.tproj/HACK/Australia/Tasmania
new file mode 100644 (file)
index 0000000..d6825f5
Binary files /dev/null and b/zic.tproj/HACK/Australia/Tasmania differ
diff --git a/zic.tproj/HACK/Australia/Victoria b/zic.tproj/HACK/Australia/Victoria
new file mode 100644 (file)
index 0000000..fa307b5
Binary files /dev/null and b/zic.tproj/HACK/Australia/Victoria differ
diff --git a/zic.tproj/HACK/Australia/West b/zic.tproj/HACK/Australia/West
new file mode 100644 (file)
index 0000000..bf5a03e
Binary files /dev/null and b/zic.tproj/HACK/Australia/West differ
diff --git a/zic.tproj/HACK/Australia/Yancowinna b/zic.tproj/HACK/Australia/Yancowinna
new file mode 100644 (file)
index 0000000..46aff75
Binary files /dev/null and b/zic.tproj/HACK/Australia/Yancowinna differ
diff --git a/zic.tproj/HACK/Brazil/Acre b/zic.tproj/HACK/Brazil/Acre
new file mode 100644 (file)
index 0000000..801849e
Binary files /dev/null and b/zic.tproj/HACK/Brazil/Acre differ
diff --git a/zic.tproj/HACK/Brazil/DeNoronha b/zic.tproj/HACK/Brazil/DeNoronha
new file mode 100644 (file)
index 0000000..0a9ae0d
Binary files /dev/null and b/zic.tproj/HACK/Brazil/DeNoronha differ
diff --git a/zic.tproj/HACK/Brazil/East b/zic.tproj/HACK/Brazil/East
new file mode 100644 (file)
index 0000000..e504ee8
Binary files /dev/null and b/zic.tproj/HACK/Brazil/East differ
diff --git a/zic.tproj/HACK/Brazil/West b/zic.tproj/HACK/Brazil/West
new file mode 100644 (file)
index 0000000..27325b7
Binary files /dev/null and b/zic.tproj/HACK/Brazil/West differ
diff --git a/zic.tproj/HACK/CET b/zic.tproj/HACK/CET
new file mode 100644 (file)
index 0000000..f810b03
Binary files /dev/null and b/zic.tproj/HACK/CET differ
diff --git a/zic.tproj/HACK/CST6CDT b/zic.tproj/HACK/CST6CDT
new file mode 100644 (file)
index 0000000..7ffb1d8
Binary files /dev/null and b/zic.tproj/HACK/CST6CDT differ
diff --git a/zic.tproj/HACK/Canada/Atlantic b/zic.tproj/HACK/Canada/Atlantic
new file mode 100644 (file)
index 0000000..92d441b
Binary files /dev/null and b/zic.tproj/HACK/Canada/Atlantic differ
diff --git a/zic.tproj/HACK/Canada/Central b/zic.tproj/HACK/Canada/Central
new file mode 100644 (file)
index 0000000..0676968
Binary files /dev/null and b/zic.tproj/HACK/Canada/Central differ
diff --git a/zic.tproj/HACK/Canada/East-Saskatchewan b/zic.tproj/HACK/Canada/East-Saskatchewan
new file mode 100644 (file)
index 0000000..a62958a
Binary files /dev/null and b/zic.tproj/HACK/Canada/East-Saskatchewan differ
diff --git a/zic.tproj/HACK/Canada/Eastern b/zic.tproj/HACK/Canada/Eastern
new file mode 100644 (file)
index 0000000..0bbe44a
Binary files /dev/null and b/zic.tproj/HACK/Canada/Eastern differ
diff --git a/zic.tproj/HACK/Canada/Mountain b/zic.tproj/HACK/Canada/Mountain
new file mode 100644 (file)
index 0000000..308bcae
Binary files /dev/null and b/zic.tproj/HACK/Canada/Mountain differ
diff --git a/zic.tproj/HACK/Canada/Newfoundland b/zic.tproj/HACK/Canada/Newfoundland
new file mode 100644 (file)
index 0000000..2409d71
Binary files /dev/null and b/zic.tproj/HACK/Canada/Newfoundland differ
diff --git a/zic.tproj/HACK/Canada/Pacific b/zic.tproj/HACK/Canada/Pacific
new file mode 100644 (file)
index 0000000..6d6ce95
Binary files /dev/null and b/zic.tproj/HACK/Canada/Pacific differ
diff --git a/zic.tproj/HACK/Canada/Saskatchewan b/zic.tproj/HACK/Canada/Saskatchewan
new file mode 100644 (file)
index 0000000..a62958a
Binary files /dev/null and b/zic.tproj/HACK/Canada/Saskatchewan differ
diff --git a/zic.tproj/HACK/Canada/Yukon b/zic.tproj/HACK/Canada/Yukon
new file mode 100644 (file)
index 0000000..5d86e0f
Binary files /dev/null and b/zic.tproj/HACK/Canada/Yukon differ
diff --git a/zic.tproj/HACK/Chile/Continental b/zic.tproj/HACK/Chile/Continental
new file mode 100644 (file)
index 0000000..cc1139f
Binary files /dev/null and b/zic.tproj/HACK/Chile/Continental differ
diff --git a/zic.tproj/HACK/Chile/EasterIsland b/zic.tproj/HACK/Chile/EasterIsland
new file mode 100644 (file)
index 0000000..d003e68
Binary files /dev/null and b/zic.tproj/HACK/Chile/EasterIsland differ
diff --git a/zic.tproj/HACK/Cuba b/zic.tproj/HACK/Cuba
new file mode 100644 (file)
index 0000000..50fd5db
Binary files /dev/null and b/zic.tproj/HACK/Cuba differ
diff --git a/zic.tproj/HACK/EET b/zic.tproj/HACK/EET
new file mode 100644 (file)
index 0000000..b023342
Binary files /dev/null and b/zic.tproj/HACK/EET differ
diff --git a/zic.tproj/HACK/EST b/zic.tproj/HACK/EST
new file mode 100644 (file)
index 0000000..3961e65
Binary files /dev/null and b/zic.tproj/HACK/EST differ
diff --git a/zic.tproj/HACK/EST5EDT b/zic.tproj/HACK/EST5EDT
new file mode 100644 (file)
index 0000000..2ddcd42
Binary files /dev/null and b/zic.tproj/HACK/EST5EDT differ
diff --git a/zic.tproj/HACK/Egypt b/zic.tproj/HACK/Egypt
new file mode 100644 (file)
index 0000000..a084b0a
Binary files /dev/null and b/zic.tproj/HACK/Egypt differ
diff --git a/zic.tproj/HACK/Eire b/zic.tproj/HACK/Eire
new file mode 100644 (file)
index 0000000..fab6a19
Binary files /dev/null and b/zic.tproj/HACK/Eire differ
diff --git a/zic.tproj/HACK/Etc/GMT b/zic.tproj/HACK/Etc/GMT
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT differ
diff --git a/zic.tproj/HACK/Etc/GMT+0 b/zic.tproj/HACK/Etc/GMT+0
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+0 differ
diff --git a/zic.tproj/HACK/Etc/GMT+1 b/zic.tproj/HACK/Etc/GMT+1
new file mode 100644 (file)
index 0000000..ee1e3cb
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+1 differ
diff --git a/zic.tproj/HACK/Etc/GMT+10 b/zic.tproj/HACK/Etc/GMT+10
new file mode 100644 (file)
index 0000000..8e9a406
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+10 differ
diff --git a/zic.tproj/HACK/Etc/GMT+11 b/zic.tproj/HACK/Etc/GMT+11
new file mode 100644 (file)
index 0000000..f19fa2c
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+11 differ
diff --git a/zic.tproj/HACK/Etc/GMT+12 b/zic.tproj/HACK/Etc/GMT+12
new file mode 100644 (file)
index 0000000..b806dfe
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+12 differ
diff --git a/zic.tproj/HACK/Etc/GMT+2 b/zic.tproj/HACK/Etc/GMT+2
new file mode 100644 (file)
index 0000000..a1c462e
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+2 differ
diff --git a/zic.tproj/HACK/Etc/GMT+3 b/zic.tproj/HACK/Etc/GMT+3
new file mode 100644 (file)
index 0000000..1dd1aa2
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+3 differ
diff --git a/zic.tproj/HACK/Etc/GMT+4 b/zic.tproj/HACK/Etc/GMT+4
new file mode 100644 (file)
index 0000000..acecb85
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+4 differ
diff --git a/zic.tproj/HACK/Etc/GMT+5 b/zic.tproj/HACK/Etc/GMT+5
new file mode 100644 (file)
index 0000000..b70cacb
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+5 differ
diff --git a/zic.tproj/HACK/Etc/GMT+6 b/zic.tproj/HACK/Etc/GMT+6
new file mode 100644 (file)
index 0000000..c580628
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+6 differ
diff --git a/zic.tproj/HACK/Etc/GMT+7 b/zic.tproj/HACK/Etc/GMT+7
new file mode 100644 (file)
index 0000000..80c1254
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+7 differ
diff --git a/zic.tproj/HACK/Etc/GMT+8 b/zic.tproj/HACK/Etc/GMT+8
new file mode 100644 (file)
index 0000000..4e049ee
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+8 differ
diff --git a/zic.tproj/HACK/Etc/GMT+9 b/zic.tproj/HACK/Etc/GMT+9
new file mode 100644 (file)
index 0000000..fa3eddb
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT+9 differ
diff --git a/zic.tproj/HACK/Etc/GMT-0 b/zic.tproj/HACK/Etc/GMT-0
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-0 differ
diff --git a/zic.tproj/HACK/Etc/GMT-1 b/zic.tproj/HACK/Etc/GMT-1
new file mode 100644 (file)
index 0000000..49a0ea8
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-1 differ
diff --git a/zic.tproj/HACK/Etc/GMT-10 b/zic.tproj/HACK/Etc/GMT-10
new file mode 100644 (file)
index 0000000..eecf42d
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-10 differ
diff --git a/zic.tproj/HACK/Etc/GMT-11 b/zic.tproj/HACK/Etc/GMT-11
new file mode 100644 (file)
index 0000000..1324887
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-11 differ
diff --git a/zic.tproj/HACK/Etc/GMT-12 b/zic.tproj/HACK/Etc/GMT-12
new file mode 100644 (file)
index 0000000..bf30d4a
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-12 differ
diff --git a/zic.tproj/HACK/Etc/GMT-13 b/zic.tproj/HACK/Etc/GMT-13
new file mode 100644 (file)
index 0000000..b02b234
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-13 differ
diff --git a/zic.tproj/HACK/Etc/GMT-14 b/zic.tproj/HACK/Etc/GMT-14
new file mode 100644 (file)
index 0000000..17fc3c3
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-14 differ
diff --git a/zic.tproj/HACK/Etc/GMT-2 b/zic.tproj/HACK/Etc/GMT-2
new file mode 100644 (file)
index 0000000..cf6cbf0
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-2 differ
diff --git a/zic.tproj/HACK/Etc/GMT-3 b/zic.tproj/HACK/Etc/GMT-3
new file mode 100644 (file)
index 0000000..6e86aac
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-3 differ
diff --git a/zic.tproj/HACK/Etc/GMT-4 b/zic.tproj/HACK/Etc/GMT-4
new file mode 100644 (file)
index 0000000..b7a6a86
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-4 differ
diff --git a/zic.tproj/HACK/Etc/GMT-5 b/zic.tproj/HACK/Etc/GMT-5
new file mode 100644 (file)
index 0000000..43fa873
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-5 differ
diff --git a/zic.tproj/HACK/Etc/GMT-6 b/zic.tproj/HACK/Etc/GMT-6
new file mode 100644 (file)
index 0000000..8af873c
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-6 differ
diff --git a/zic.tproj/HACK/Etc/GMT-7 b/zic.tproj/HACK/Etc/GMT-7
new file mode 100644 (file)
index 0000000..d0a2dc4
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-7 differ
diff --git a/zic.tproj/HACK/Etc/GMT-8 b/zic.tproj/HACK/Etc/GMT-8
new file mode 100644 (file)
index 0000000..8e25023
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-8 differ
diff --git a/zic.tproj/HACK/Etc/GMT-9 b/zic.tproj/HACK/Etc/GMT-9
new file mode 100644 (file)
index 0000000..18255bf
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT-9 differ
diff --git a/zic.tproj/HACK/Etc/GMT0 b/zic.tproj/HACK/Etc/GMT0
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/Etc/GMT0 differ
diff --git a/zic.tproj/HACK/Etc/Greenwich b/zic.tproj/HACK/Etc/Greenwich
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/Etc/Greenwich differ
diff --git a/zic.tproj/HACK/Etc/UCT b/zic.tproj/HACK/Etc/UCT
new file mode 100644 (file)
index 0000000..c9b6275
Binary files /dev/null and b/zic.tproj/HACK/Etc/UCT differ
diff --git a/zic.tproj/HACK/Etc/UTC b/zic.tproj/HACK/Etc/UTC
new file mode 100644 (file)
index 0000000..fa05d4b
Binary files /dev/null and b/zic.tproj/HACK/Etc/UTC differ
diff --git a/zic.tproj/HACK/Etc/Universal b/zic.tproj/HACK/Etc/Universal
new file mode 100644 (file)
index 0000000..fa05d4b
Binary files /dev/null and b/zic.tproj/HACK/Etc/Universal differ
diff --git a/zic.tproj/HACK/Etc/Zulu b/zic.tproj/HACK/Etc/Zulu
new file mode 100644 (file)
index 0000000..fa05d4b
Binary files /dev/null and b/zic.tproj/HACK/Etc/Zulu differ
diff --git a/zic.tproj/HACK/Europe/Amsterdam b/zic.tproj/HACK/Europe/Amsterdam
new file mode 100644 (file)
index 0000000..eb44c23
Binary files /dev/null and b/zic.tproj/HACK/Europe/Amsterdam differ
diff --git a/zic.tproj/HACK/Europe/Andorra b/zic.tproj/HACK/Europe/Andorra
new file mode 100644 (file)
index 0000000..37e9979
Binary files /dev/null and b/zic.tproj/HACK/Europe/Andorra differ
diff --git a/zic.tproj/HACK/Europe/Athens b/zic.tproj/HACK/Europe/Athens
new file mode 100644 (file)
index 0000000..4c69035
Binary files /dev/null and b/zic.tproj/HACK/Europe/Athens differ
diff --git a/zic.tproj/HACK/Europe/Belfast b/zic.tproj/HACK/Europe/Belfast
new file mode 100644 (file)
index 0000000..ba4a4d9
Binary files /dev/null and b/zic.tproj/HACK/Europe/Belfast differ
diff --git a/zic.tproj/HACK/Europe/Belgrade b/zic.tproj/HACK/Europe/Belgrade
new file mode 100644 (file)
index 0000000..2c5053b
Binary files /dev/null and b/zic.tproj/HACK/Europe/Belgrade differ
diff --git a/zic.tproj/HACK/Europe/Berlin b/zic.tproj/HACK/Europe/Berlin
new file mode 100644 (file)
index 0000000..eedf74e
Binary files /dev/null and b/zic.tproj/HACK/Europe/Berlin differ
diff --git a/zic.tproj/HACK/Europe/Bratislava b/zic.tproj/HACK/Europe/Bratislava
new file mode 100644 (file)
index 0000000..ff27e2c
Binary files /dev/null and b/zic.tproj/HACK/Europe/Bratislava differ
diff --git a/zic.tproj/HACK/Europe/Brussels b/zic.tproj/HACK/Europe/Brussels
new file mode 100644 (file)
index 0000000..bbbbf04
Binary files /dev/null and b/zic.tproj/HACK/Europe/Brussels differ
diff --git a/zic.tproj/HACK/Europe/Bucharest b/zic.tproj/HACK/Europe/Bucharest
new file mode 100644 (file)
index 0000000..d493abb
Binary files /dev/null and b/zic.tproj/HACK/Europe/Bucharest differ
diff --git a/zic.tproj/HACK/Europe/Budapest b/zic.tproj/HACK/Europe/Budapest
new file mode 100644 (file)
index 0000000..c79336b
Binary files /dev/null and b/zic.tproj/HACK/Europe/Budapest differ
diff --git a/zic.tproj/HACK/Europe/Chisinau b/zic.tproj/HACK/Europe/Chisinau
new file mode 100644 (file)
index 0000000..9421034
Binary files /dev/null and b/zic.tproj/HACK/Europe/Chisinau differ
diff --git a/zic.tproj/HACK/Europe/Copenhagen b/zic.tproj/HACK/Europe/Copenhagen
new file mode 100644 (file)
index 0000000..8ee5abd
Binary files /dev/null and b/zic.tproj/HACK/Europe/Copenhagen differ
diff --git a/zic.tproj/HACK/Europe/Dublin b/zic.tproj/HACK/Europe/Dublin
new file mode 100644 (file)
index 0000000..fab6a19
Binary files /dev/null and b/zic.tproj/HACK/Europe/Dublin differ
diff --git a/zic.tproj/HACK/Europe/Gibraltar b/zic.tproj/HACK/Europe/Gibraltar
new file mode 100644 (file)
index 0000000..6e6dce7
Binary files /dev/null and b/zic.tproj/HACK/Europe/Gibraltar differ
diff --git a/zic.tproj/HACK/Europe/Helsinki b/zic.tproj/HACK/Europe/Helsinki
new file mode 100644 (file)
index 0000000..a9f0787
Binary files /dev/null and b/zic.tproj/HACK/Europe/Helsinki differ
diff --git a/zic.tproj/HACK/Europe/Istanbul b/zic.tproj/HACK/Europe/Istanbul
new file mode 100644 (file)
index 0000000..b05d65a
Binary files /dev/null and b/zic.tproj/HACK/Europe/Istanbul differ
diff --git a/zic.tproj/HACK/Europe/Kaliningrad b/zic.tproj/HACK/Europe/Kaliningrad
new file mode 100644 (file)
index 0000000..36c4ea2
Binary files /dev/null and b/zic.tproj/HACK/Europe/Kaliningrad differ
diff --git a/zic.tproj/HACK/Europe/Kiev b/zic.tproj/HACK/Europe/Kiev
new file mode 100644 (file)
index 0000000..f4c073c
Binary files /dev/null and b/zic.tproj/HACK/Europe/Kiev differ
diff --git a/zic.tproj/HACK/Europe/Lisbon b/zic.tproj/HACK/Europe/Lisbon
new file mode 100644 (file)
index 0000000..84933f9
Binary files /dev/null and b/zic.tproj/HACK/Europe/Lisbon differ
diff --git a/zic.tproj/HACK/Europe/Ljubljana b/zic.tproj/HACK/Europe/Ljubljana
new file mode 100644 (file)
index 0000000..2c5053b
Binary files /dev/null and b/zic.tproj/HACK/Europe/Ljubljana differ
diff --git a/zic.tproj/HACK/Europe/London b/zic.tproj/HACK/Europe/London
new file mode 100644 (file)
index 0000000..ce1bd2e
Binary files /dev/null and b/zic.tproj/HACK/Europe/London differ
diff --git a/zic.tproj/HACK/Europe/Luxembourg b/zic.tproj/HACK/Europe/Luxembourg
new file mode 100644 (file)
index 0000000..497a9b7
Binary files /dev/null and b/zic.tproj/HACK/Europe/Luxembourg differ
diff --git a/zic.tproj/HACK/Europe/Madrid b/zic.tproj/HACK/Europe/Madrid
new file mode 100644 (file)
index 0000000..ac2bd27
Binary files /dev/null and b/zic.tproj/HACK/Europe/Madrid differ
diff --git a/zic.tproj/HACK/Europe/Malta b/zic.tproj/HACK/Europe/Malta
new file mode 100644 (file)
index 0000000..6454a6d
Binary files /dev/null and b/zic.tproj/HACK/Europe/Malta differ
diff --git a/zic.tproj/HACK/Europe/Minsk b/zic.tproj/HACK/Europe/Minsk
new file mode 100644 (file)
index 0000000..6f61d4d
Binary files /dev/null and b/zic.tproj/HACK/Europe/Minsk differ
diff --git a/zic.tproj/HACK/Europe/Monaco b/zic.tproj/HACK/Europe/Monaco
new file mode 100644 (file)
index 0000000..92ccb02
Binary files /dev/null and b/zic.tproj/HACK/Europe/Monaco differ
diff --git a/zic.tproj/HACK/Europe/Moscow b/zic.tproj/HACK/Europe/Moscow
new file mode 100644 (file)
index 0000000..af292f7
Binary files /dev/null and b/zic.tproj/HACK/Europe/Moscow differ
diff --git a/zic.tproj/HACK/Europe/Oslo b/zic.tproj/HACK/Europe/Oslo
new file mode 100644 (file)
index 0000000..8e8060d
Binary files /dev/null and b/zic.tproj/HACK/Europe/Oslo differ
diff --git a/zic.tproj/HACK/Europe/Paris b/zic.tproj/HACK/Europe/Paris
new file mode 100644 (file)
index 0000000..da4bd18
Binary files /dev/null and b/zic.tproj/HACK/Europe/Paris differ
diff --git a/zic.tproj/HACK/Europe/Prague b/zic.tproj/HACK/Europe/Prague
new file mode 100644 (file)
index 0000000..ff27e2c
Binary files /dev/null and b/zic.tproj/HACK/Europe/Prague differ
diff --git a/zic.tproj/HACK/Europe/Riga b/zic.tproj/HACK/Europe/Riga
new file mode 100644 (file)
index 0000000..e929f20
Binary files /dev/null and b/zic.tproj/HACK/Europe/Riga differ
diff --git a/zic.tproj/HACK/Europe/Rome b/zic.tproj/HACK/Europe/Rome
new file mode 100644 (file)
index 0000000..ccee931
Binary files /dev/null and b/zic.tproj/HACK/Europe/Rome differ
diff --git a/zic.tproj/HACK/Europe/Samara b/zic.tproj/HACK/Europe/Samara
new file mode 100644 (file)
index 0000000..8384fb5
Binary files /dev/null and b/zic.tproj/HACK/Europe/Samara differ
diff --git a/zic.tproj/HACK/Europe/San_Marino b/zic.tproj/HACK/Europe/San_Marino
new file mode 100644 (file)
index 0000000..ccee931
Binary files /dev/null and b/zic.tproj/HACK/Europe/San_Marino differ
diff --git a/zic.tproj/HACK/Europe/Sarajevo b/zic.tproj/HACK/Europe/Sarajevo
new file mode 100644 (file)
index 0000000..2c5053b
Binary files /dev/null and b/zic.tproj/HACK/Europe/Sarajevo differ
diff --git a/zic.tproj/HACK/Europe/Simferopol b/zic.tproj/HACK/Europe/Simferopol
new file mode 100644 (file)
index 0000000..8d1224e
Binary files /dev/null and b/zic.tproj/HACK/Europe/Simferopol differ
diff --git a/zic.tproj/HACK/Europe/Skopje b/zic.tproj/HACK/Europe/Skopje
new file mode 100644 (file)
index 0000000..2c5053b
Binary files /dev/null and b/zic.tproj/HACK/Europe/Skopje differ
diff --git a/zic.tproj/HACK/Europe/Sofia b/zic.tproj/HACK/Europe/Sofia
new file mode 100644 (file)
index 0000000..44c670e
Binary files /dev/null and b/zic.tproj/HACK/Europe/Sofia differ
diff --git a/zic.tproj/HACK/Europe/Stockholm b/zic.tproj/HACK/Europe/Stockholm
new file mode 100644 (file)
index 0000000..f0a2963
Binary files /dev/null and b/zic.tproj/HACK/Europe/Stockholm differ
diff --git a/zic.tproj/HACK/Europe/Tallinn b/zic.tproj/HACK/Europe/Tallinn
new file mode 100644 (file)
index 0000000..7361b7a
Binary files /dev/null and b/zic.tproj/HACK/Europe/Tallinn differ
diff --git a/zic.tproj/HACK/Europe/Tirane b/zic.tproj/HACK/Europe/Tirane
new file mode 100644 (file)
index 0000000..56e6cfe
Binary files /dev/null and b/zic.tproj/HACK/Europe/Tirane differ
diff --git a/zic.tproj/HACK/Europe/Vaduz b/zic.tproj/HACK/Europe/Vaduz
new file mode 100644 (file)
index 0000000..2caec2d
Binary files /dev/null and b/zic.tproj/HACK/Europe/Vaduz differ
diff --git a/zic.tproj/HACK/Europe/Vatican b/zic.tproj/HACK/Europe/Vatican
new file mode 100644 (file)
index 0000000..ccee931
Binary files /dev/null and b/zic.tproj/HACK/Europe/Vatican differ
diff --git a/zic.tproj/HACK/Europe/Vienna b/zic.tproj/HACK/Europe/Vienna
new file mode 100644 (file)
index 0000000..503c1de
Binary files /dev/null and b/zic.tproj/HACK/Europe/Vienna differ
diff --git a/zic.tproj/HACK/Europe/Vilnius b/zic.tproj/HACK/Europe/Vilnius
new file mode 100644 (file)
index 0000000..c8f5461
Binary files /dev/null and b/zic.tproj/HACK/Europe/Vilnius differ
diff --git a/zic.tproj/HACK/Europe/Warsaw b/zic.tproj/HACK/Europe/Warsaw
new file mode 100644 (file)
index 0000000..c6ea4cd
Binary files /dev/null and b/zic.tproj/HACK/Europe/Warsaw differ
diff --git a/zic.tproj/HACK/Europe/Zagreb b/zic.tproj/HACK/Europe/Zagreb
new file mode 100644 (file)
index 0000000..2c5053b
Binary files /dev/null and b/zic.tproj/HACK/Europe/Zagreb differ
diff --git a/zic.tproj/HACK/Europe/Zurich b/zic.tproj/HACK/Europe/Zurich
new file mode 100644 (file)
index 0000000..861606f
Binary files /dev/null and b/zic.tproj/HACK/Europe/Zurich differ
diff --git a/zic.tproj/HACK/Factory b/zic.tproj/HACK/Factory
new file mode 100644 (file)
index 0000000..bc3e2e4
Binary files /dev/null and b/zic.tproj/HACK/Factory differ
diff --git a/zic.tproj/HACK/GB b/zic.tproj/HACK/GB
new file mode 100644 (file)
index 0000000..ce1bd2e
Binary files /dev/null and b/zic.tproj/HACK/GB differ
diff --git a/zic.tproj/HACK/GMT b/zic.tproj/HACK/GMT
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/GMT differ
diff --git a/zic.tproj/HACK/GMT+0 b/zic.tproj/HACK/GMT+0
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/GMT+0 differ
diff --git a/zic.tproj/HACK/GMT-0 b/zic.tproj/HACK/GMT-0
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/GMT-0 differ
diff --git a/zic.tproj/HACK/GMT0 b/zic.tproj/HACK/GMT0
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/GMT0 differ
diff --git a/zic.tproj/HACK/Greenwich b/zic.tproj/HACK/Greenwich
new file mode 100644 (file)
index 0000000..653697b
Binary files /dev/null and b/zic.tproj/HACK/Greenwich differ
diff --git a/zic.tproj/HACK/HST b/zic.tproj/HACK/HST
new file mode 100644 (file)
index 0000000..47e56dd
Binary files /dev/null and b/zic.tproj/HACK/HST differ
diff --git a/zic.tproj/HACK/Hongkong b/zic.tproj/HACK/Hongkong
new file mode 100644 (file)
index 0000000..ad523a5
Binary files /dev/null and b/zic.tproj/HACK/Hongkong differ
diff --git a/zic.tproj/HACK/Iceland b/zic.tproj/HACK/Iceland
new file mode 100644 (file)
index 0000000..d810ba4
Binary files /dev/null and b/zic.tproj/HACK/Iceland differ
diff --git a/zic.tproj/HACK/Indian/Antananarivo b/zic.tproj/HACK/Indian/Antananarivo
new file mode 100644 (file)
index 0000000..2ab643c
Binary files /dev/null and b/zic.tproj/HACK/Indian/Antananarivo differ
diff --git a/zic.tproj/HACK/Indian/Chagos b/zic.tproj/HACK/Indian/Chagos
new file mode 100644 (file)
index 0000000..020c37f
Binary files /dev/null and b/zic.tproj/HACK/Indian/Chagos differ
diff --git a/zic.tproj/HACK/Indian/Christmas b/zic.tproj/HACK/Indian/Christmas
new file mode 100644 (file)
index 0000000..1c2ac20
Binary files /dev/null and b/zic.tproj/HACK/Indian/Christmas differ
diff --git a/zic.tproj/HACK/Indian/Cocos b/zic.tproj/HACK/Indian/Cocos
new file mode 100644 (file)
index 0000000..e775684
Binary files /dev/null and b/zic.tproj/HACK/Indian/Cocos differ
diff --git a/zic.tproj/HACK/Indian/Comoro b/zic.tproj/HACK/Indian/Comoro
new file mode 100644 (file)
index 0000000..977cd04
Binary files /dev/null and b/zic.tproj/HACK/Indian/Comoro differ
diff --git a/zic.tproj/HACK/Indian/Mahe b/zic.tproj/HACK/Indian/Mahe
new file mode 100644 (file)
index 0000000..a908e47
Binary files /dev/null and b/zic.tproj/HACK/Indian/Mahe differ
diff --git a/zic.tproj/HACK/Indian/Maldives b/zic.tproj/HACK/Indian/Maldives
new file mode 100644 (file)
index 0000000..d74aa5b
Binary files /dev/null and b/zic.tproj/HACK/Indian/Maldives differ
diff --git a/zic.tproj/HACK/Indian/Mauritius b/zic.tproj/HACK/Indian/Mauritius
new file mode 100644 (file)
index 0000000..098d460
Binary files /dev/null and b/zic.tproj/HACK/Indian/Mauritius differ
diff --git a/zic.tproj/HACK/Indian/Mayotte b/zic.tproj/HACK/Indian/Mayotte
new file mode 100644 (file)
index 0000000..cca9e10
Binary files /dev/null and b/zic.tproj/HACK/Indian/Mayotte differ
diff --git a/zic.tproj/HACK/Indian/Reunion b/zic.tproj/HACK/Indian/Reunion
new file mode 100644 (file)
index 0000000..2e4665f
Binary files /dev/null and b/zic.tproj/HACK/Indian/Reunion differ
diff --git a/zic.tproj/HACK/Iran b/zic.tproj/HACK/Iran
new file mode 100644 (file)
index 0000000..0b3a6ae
Binary files /dev/null and b/zic.tproj/HACK/Iran differ
diff --git a/zic.tproj/HACK/Israel b/zic.tproj/HACK/Israel
new file mode 100644 (file)
index 0000000..b604803
Binary files /dev/null and b/zic.tproj/HACK/Israel differ
diff --git a/zic.tproj/HACK/Jamaica b/zic.tproj/HACK/Jamaica
new file mode 100644 (file)
index 0000000..a77982e
Binary files /dev/null and b/zic.tproj/HACK/Jamaica differ
diff --git a/zic.tproj/HACK/Japan b/zic.tproj/HACK/Japan
new file mode 100644 (file)
index 0000000..5494fd2
Binary files /dev/null and b/zic.tproj/HACK/Japan differ
diff --git a/zic.tproj/HACK/Kwajalein b/zic.tproj/HACK/Kwajalein
new file mode 100644 (file)
index 0000000..8faa262
Binary files /dev/null and b/zic.tproj/HACK/Kwajalein differ
diff --git a/zic.tproj/HACK/Libya b/zic.tproj/HACK/Libya
new file mode 100644 (file)
index 0000000..4ca7448
Binary files /dev/null and b/zic.tproj/HACK/Libya differ
diff --git a/zic.tproj/HACK/MET b/zic.tproj/HACK/MET
new file mode 100644 (file)
index 0000000..f3bcecb
Binary files /dev/null and b/zic.tproj/HACK/MET differ
diff --git a/zic.tproj/HACK/MST b/zic.tproj/HACK/MST
new file mode 100644 (file)
index 0000000..d684fb3
Binary files /dev/null and b/zic.tproj/HACK/MST differ
diff --git a/zic.tproj/HACK/MST7MDT b/zic.tproj/HACK/MST7MDT
new file mode 100644 (file)
index 0000000..fc45907
Binary files /dev/null and b/zic.tproj/HACK/MST7MDT differ
diff --git a/zic.tproj/HACK/Mexico/BajaNorte b/zic.tproj/HACK/Mexico/BajaNorte
new file mode 100644 (file)
index 0000000..e23f80b
Binary files /dev/null and b/zic.tproj/HACK/Mexico/BajaNorte differ
diff --git a/zic.tproj/HACK/Mexico/BajaSur b/zic.tproj/HACK/Mexico/BajaSur
new file mode 100644 (file)
index 0000000..affdb69
Binary files /dev/null and b/zic.tproj/HACK/Mexico/BajaSur differ
diff --git a/zic.tproj/HACK/Mexico/General b/zic.tproj/HACK/Mexico/General
new file mode 100644 (file)
index 0000000..3e953e2
Binary files /dev/null and b/zic.tproj/HACK/Mexico/General differ
diff --git a/zic.tproj/HACK/Mideast/Riyadh87 b/zic.tproj/HACK/Mideast/Riyadh87
new file mode 100644 (file)
index 0000000..1dac2ae
Binary files /dev/null and b/zic.tproj/HACK/Mideast/Riyadh87 differ
diff --git a/zic.tproj/HACK/Mideast/Riyadh88 b/zic.tproj/HACK/Mideast/Riyadh88
new file mode 100644 (file)
index 0000000..ee7474e
Binary files /dev/null and b/zic.tproj/HACK/Mideast/Riyadh88 differ
diff --git a/zic.tproj/HACK/Mideast/Riyadh89 b/zic.tproj/HACK/Mideast/Riyadh89
new file mode 100644 (file)
index 0000000..6f12699
Binary files /dev/null and b/zic.tproj/HACK/Mideast/Riyadh89 differ
diff --git a/zic.tproj/HACK/NZ b/zic.tproj/HACK/NZ
new file mode 100644 (file)
index 0000000..6cb49bb
Binary files /dev/null and b/zic.tproj/HACK/NZ differ
diff --git a/zic.tproj/HACK/NZ-CHAT b/zic.tproj/HACK/NZ-CHAT
new file mode 100644 (file)
index 0000000..32ce242
Binary files /dev/null and b/zic.tproj/HACK/NZ-CHAT differ
diff --git a/zic.tproj/HACK/Navajo b/zic.tproj/HACK/Navajo
new file mode 100644 (file)
index 0000000..fc45907
Binary files /dev/null and b/zic.tproj/HACK/Navajo differ
diff --git a/zic.tproj/HACK/PRC b/zic.tproj/HACK/PRC
new file mode 100644 (file)
index 0000000..2f0c5ec
Binary files /dev/null and b/zic.tproj/HACK/PRC differ
diff --git a/zic.tproj/HACK/PST8PDT b/zic.tproj/HACK/PST8PDT
new file mode 100644 (file)
index 0000000..458d9b7
Binary files /dev/null and b/zic.tproj/HACK/PST8PDT differ
diff --git a/zic.tproj/HACK/Pacific/Apia b/zic.tproj/HACK/Pacific/Apia
new file mode 100644 (file)
index 0000000..d6b7cd8
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Apia differ
diff --git a/zic.tproj/HACK/Pacific/Auckland b/zic.tproj/HACK/Pacific/Auckland
new file mode 100644 (file)
index 0000000..6cb49bb
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Auckland differ
diff --git a/zic.tproj/HACK/Pacific/Chatham b/zic.tproj/HACK/Pacific/Chatham
new file mode 100644 (file)
index 0000000..32ce242
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Chatham differ
diff --git a/zic.tproj/HACK/Pacific/Easter b/zic.tproj/HACK/Pacific/Easter
new file mode 100644 (file)
index 0000000..d003e68
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Easter differ
diff --git a/zic.tproj/HACK/Pacific/Efate b/zic.tproj/HACK/Pacific/Efate
new file mode 100644 (file)
index 0000000..b3b859e
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Efate differ
diff --git a/zic.tproj/HACK/Pacific/Enderbury b/zic.tproj/HACK/Pacific/Enderbury
new file mode 100644 (file)
index 0000000..d655d53
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Enderbury differ
diff --git a/zic.tproj/HACK/Pacific/Fakaofo b/zic.tproj/HACK/Pacific/Fakaofo
new file mode 100644 (file)
index 0000000..48065aa
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Fakaofo differ
diff --git a/zic.tproj/HACK/Pacific/Fiji b/zic.tproj/HACK/Pacific/Fiji
new file mode 100644 (file)
index 0000000..ac94c56
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Fiji differ
diff --git a/zic.tproj/HACK/Pacific/Funafuti b/zic.tproj/HACK/Pacific/Funafuti
new file mode 100644 (file)
index 0000000..fb4ccbe
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Funafuti differ
diff --git a/zic.tproj/HACK/Pacific/Galapagos b/zic.tproj/HACK/Pacific/Galapagos
new file mode 100644 (file)
index 0000000..33d5e70
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Galapagos differ
diff --git a/zic.tproj/HACK/Pacific/Gambier b/zic.tproj/HACK/Pacific/Gambier
new file mode 100644 (file)
index 0000000..ff76fc1
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Gambier differ
diff --git a/zic.tproj/HACK/Pacific/Guadalcanal b/zic.tproj/HACK/Pacific/Guadalcanal
new file mode 100644 (file)
index 0000000..fe7cd22
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Guadalcanal differ
diff --git a/zic.tproj/HACK/Pacific/Guam b/zic.tproj/HACK/Pacific/Guam
new file mode 100644 (file)
index 0000000..dfa4a0b
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Guam differ
diff --git a/zic.tproj/HACK/Pacific/Honolulu b/zic.tproj/HACK/Pacific/Honolulu
new file mode 100644 (file)
index 0000000..47e56dd
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Honolulu differ
diff --git a/zic.tproj/HACK/Pacific/Johnston b/zic.tproj/HACK/Pacific/Johnston
new file mode 100644 (file)
index 0000000..5f3ab4c
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Johnston differ
diff --git a/zic.tproj/HACK/Pacific/Kiritimati b/zic.tproj/HACK/Pacific/Kiritimati
new file mode 100644 (file)
index 0000000..2293dbe
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Kiritimati differ
diff --git a/zic.tproj/HACK/Pacific/Kosrae b/zic.tproj/HACK/Pacific/Kosrae
new file mode 100644 (file)
index 0000000..4164144
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Kosrae differ
diff --git a/zic.tproj/HACK/Pacific/Kwajalein b/zic.tproj/HACK/Pacific/Kwajalein
new file mode 100644 (file)
index 0000000..8faa262
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Kwajalein differ
diff --git a/zic.tproj/HACK/Pacific/Majuro b/zic.tproj/HACK/Pacific/Majuro
new file mode 100644 (file)
index 0000000..9b1233f
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Majuro differ
diff --git a/zic.tproj/HACK/Pacific/Marquesas b/zic.tproj/HACK/Pacific/Marquesas
new file mode 100644 (file)
index 0000000..548b18b
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Marquesas differ
diff --git a/zic.tproj/HACK/Pacific/Midway b/zic.tproj/HACK/Pacific/Midway
new file mode 100644 (file)
index 0000000..5418104
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Midway differ
diff --git a/zic.tproj/HACK/Pacific/Nauru b/zic.tproj/HACK/Pacific/Nauru
new file mode 100644 (file)
index 0000000..b22fe2b
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Nauru differ
diff --git a/zic.tproj/HACK/Pacific/Niue b/zic.tproj/HACK/Pacific/Niue
new file mode 100644 (file)
index 0000000..b72112e
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Niue differ
diff --git a/zic.tproj/HACK/Pacific/Norfolk b/zic.tproj/HACK/Pacific/Norfolk
new file mode 100644 (file)
index 0000000..afa6adf
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Norfolk differ
diff --git a/zic.tproj/HACK/Pacific/Noumea b/zic.tproj/HACK/Pacific/Noumea
new file mode 100644 (file)
index 0000000..6c97421
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Noumea differ
diff --git a/zic.tproj/HACK/Pacific/Pago_Pago b/zic.tproj/HACK/Pacific/Pago_Pago
new file mode 100644 (file)
index 0000000..dd0d3e8
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Pago_Pago differ
diff --git a/zic.tproj/HACK/Pacific/Palau b/zic.tproj/HACK/Pacific/Palau
new file mode 100644 (file)
index 0000000..83acadc
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Palau differ
diff --git a/zic.tproj/HACK/Pacific/Pitcairn b/zic.tproj/HACK/Pacific/Pitcairn
new file mode 100644 (file)
index 0000000..f641bc0
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Pitcairn differ
diff --git a/zic.tproj/HACK/Pacific/Ponape b/zic.tproj/HACK/Pacific/Ponape
new file mode 100644 (file)
index 0000000..421fb79
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Ponape differ
diff --git a/zic.tproj/HACK/Pacific/Port_Moresby b/zic.tproj/HACK/Pacific/Port_Moresby
new file mode 100644 (file)
index 0000000..b568445
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Port_Moresby differ
diff --git a/zic.tproj/HACK/Pacific/Rarotonga b/zic.tproj/HACK/Pacific/Rarotonga
new file mode 100644 (file)
index 0000000..8b90662
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Rarotonga differ
diff --git a/zic.tproj/HACK/Pacific/Saipan b/zic.tproj/HACK/Pacific/Saipan
new file mode 100644 (file)
index 0000000..018b301
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Saipan differ
diff --git a/zic.tproj/HACK/Pacific/Samoa b/zic.tproj/HACK/Pacific/Samoa
new file mode 100644 (file)
index 0000000..dd0d3e8
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Samoa differ
diff --git a/zic.tproj/HACK/Pacific/Tahiti b/zic.tproj/HACK/Pacific/Tahiti
new file mode 100644 (file)
index 0000000..ededc22
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Tahiti differ
diff --git a/zic.tproj/HACK/Pacific/Tarawa b/zic.tproj/HACK/Pacific/Tarawa
new file mode 100644 (file)
index 0000000..0bca707
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Tarawa differ
diff --git a/zic.tproj/HACK/Pacific/Tongatapu b/zic.tproj/HACK/Pacific/Tongatapu
new file mode 100644 (file)
index 0000000..e1803fb
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Tongatapu differ
diff --git a/zic.tproj/HACK/Pacific/Truk b/zic.tproj/HACK/Pacific/Truk
new file mode 100644 (file)
index 0000000..66e429f
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Truk differ
diff --git a/zic.tproj/HACK/Pacific/Wake b/zic.tproj/HACK/Pacific/Wake
new file mode 100644 (file)
index 0000000..10c6dd6
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Wake differ
diff --git a/zic.tproj/HACK/Pacific/Wallis b/zic.tproj/HACK/Pacific/Wallis
new file mode 100644 (file)
index 0000000..e130fc2
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Wallis differ
diff --git a/zic.tproj/HACK/Pacific/Yap b/zic.tproj/HACK/Pacific/Yap
new file mode 100644 (file)
index 0000000..9490fe2
Binary files /dev/null and b/zic.tproj/HACK/Pacific/Yap differ
diff --git a/zic.tproj/HACK/Poland b/zic.tproj/HACK/Poland
new file mode 100644 (file)
index 0000000..c6ea4cd
Binary files /dev/null and b/zic.tproj/HACK/Poland differ
diff --git a/zic.tproj/HACK/Portugal b/zic.tproj/HACK/Portugal
new file mode 100644 (file)
index 0000000..84933f9
Binary files /dev/null and b/zic.tproj/HACK/Portugal differ
diff --git a/zic.tproj/HACK/ROC b/zic.tproj/HACK/ROC
new file mode 100644 (file)
index 0000000..aa2b3f0
Binary files /dev/null and b/zic.tproj/HACK/ROC differ
diff --git a/zic.tproj/HACK/ROK b/zic.tproj/HACK/ROK
new file mode 100644 (file)
index 0000000..9a2cd24
Binary files /dev/null and b/zic.tproj/HACK/ROK differ
diff --git a/zic.tproj/HACK/Singapore b/zic.tproj/HACK/Singapore
new file mode 100644 (file)
index 0000000..41cfd62
Binary files /dev/null and b/zic.tproj/HACK/Singapore differ
diff --git a/zic.tproj/HACK/SystemV/AST4 b/zic.tproj/HACK/SystemV/AST4
new file mode 100644 (file)
index 0000000..2fd8b84
Binary files /dev/null and b/zic.tproj/HACK/SystemV/AST4 differ
diff --git a/zic.tproj/HACK/SystemV/AST4ADT b/zic.tproj/HACK/SystemV/AST4ADT
new file mode 100644 (file)
index 0000000..91f7b54
Binary files /dev/null and b/zic.tproj/HACK/SystemV/AST4ADT differ
diff --git a/zic.tproj/HACK/SystemV/CST6 b/zic.tproj/HACK/SystemV/CST6
new file mode 100644 (file)
index 0000000..e15d3eb
Binary files /dev/null and b/zic.tproj/HACK/SystemV/CST6 differ
diff --git a/zic.tproj/HACK/SystemV/CST6CDT b/zic.tproj/HACK/SystemV/CST6CDT
new file mode 100644 (file)
index 0000000..2428c24
Binary files /dev/null and b/zic.tproj/HACK/SystemV/CST6CDT differ
diff --git a/zic.tproj/HACK/SystemV/EST5 b/zic.tproj/HACK/SystemV/EST5
new file mode 100644 (file)
index 0000000..c21337a
Binary files /dev/null and b/zic.tproj/HACK/SystemV/EST5 differ
diff --git a/zic.tproj/HACK/SystemV/EST5EDT b/zic.tproj/HACK/SystemV/EST5EDT
new file mode 100644 (file)
index 0000000..a2c15f9
Binary files /dev/null and b/zic.tproj/HACK/SystemV/EST5EDT differ
diff --git a/zic.tproj/HACK/SystemV/HST10 b/zic.tproj/HACK/SystemV/HST10
new file mode 100644 (file)
index 0000000..5f3ab4c
Binary files /dev/null and b/zic.tproj/HACK/SystemV/HST10 differ
diff --git a/zic.tproj/HACK/SystemV/MST7 b/zic.tproj/HACK/SystemV/MST7
new file mode 100644 (file)
index 0000000..caeedb3
Binary files /dev/null and b/zic.tproj/HACK/SystemV/MST7 differ
diff --git a/zic.tproj/HACK/SystemV/MST7MDT b/zic.tproj/HACK/SystemV/MST7MDT
new file mode 100644 (file)
index 0000000..acb336c
Binary files /dev/null and b/zic.tproj/HACK/SystemV/MST7MDT differ
diff --git a/zic.tproj/HACK/SystemV/PST8 b/zic.tproj/HACK/SystemV/PST8
new file mode 100644 (file)
index 0000000..891dc92
Binary files /dev/null and b/zic.tproj/HACK/SystemV/PST8 differ
diff --git a/zic.tproj/HACK/SystemV/PST8PDT b/zic.tproj/HACK/SystemV/PST8PDT
new file mode 100644 (file)
index 0000000..4645452
Binary files /dev/null and b/zic.tproj/HACK/SystemV/PST8PDT differ
diff --git a/zic.tproj/HACK/SystemV/YST9 b/zic.tproj/HACK/SystemV/YST9
new file mode 100644 (file)
index 0000000..554d032
Binary files /dev/null and b/zic.tproj/HACK/SystemV/YST9 differ
diff --git a/zic.tproj/HACK/SystemV/YST9YDT b/zic.tproj/HACK/SystemV/YST9YDT
new file mode 100644 (file)
index 0000000..f72c457
Binary files /dev/null and b/zic.tproj/HACK/SystemV/YST9YDT differ
diff --git a/zic.tproj/HACK/Turkey b/zic.tproj/HACK/Turkey
new file mode 100644 (file)
index 0000000..b05d65a
Binary files /dev/null and b/zic.tproj/HACK/Turkey differ
diff --git a/zic.tproj/HACK/UCT b/zic.tproj/HACK/UCT
new file mode 100644 (file)
index 0000000..c9b6275
Binary files /dev/null and b/zic.tproj/HACK/UCT differ
diff --git a/zic.tproj/HACK/US/Alaska b/zic.tproj/HACK/US/Alaska
new file mode 100644 (file)
index 0000000..f3ffb58
Binary files /dev/null and b/zic.tproj/HACK/US/Alaska differ
diff --git a/zic.tproj/HACK/US/Aleutian b/zic.tproj/HACK/US/Aleutian
new file mode 100644 (file)
index 0000000..8ecd096
Binary files /dev/null and b/zic.tproj/HACK/US/Aleutian differ
diff --git a/zic.tproj/HACK/US/Arizona b/zic.tproj/HACK/US/Arizona
new file mode 100644 (file)
index 0000000..d684fb3
Binary files /dev/null and b/zic.tproj/HACK/US/Arizona differ
diff --git a/zic.tproj/HACK/US/Central b/zic.tproj/HACK/US/Central
new file mode 100644 (file)
index 0000000..7ffb1d8
Binary files /dev/null and b/zic.tproj/HACK/US/Central differ
diff --git a/zic.tproj/HACK/US/East-Indiana b/zic.tproj/HACK/US/East-Indiana
new file mode 100644 (file)
index 0000000..3961e65
Binary files /dev/null and b/zic.tproj/HACK/US/East-Indiana differ
diff --git a/zic.tproj/HACK/US/Eastern b/zic.tproj/HACK/US/Eastern
new file mode 100644 (file)
index 0000000..2ddcd42
Binary files /dev/null and b/zic.tproj/HACK/US/Eastern differ
diff --git a/zic.tproj/HACK/US/Hawaii b/zic.tproj/HACK/US/Hawaii
new file mode 100644 (file)
index 0000000..47e56dd
Binary files /dev/null and b/zic.tproj/HACK/US/Hawaii differ
diff --git a/zic.tproj/HACK/US/Indiana-Starke b/zic.tproj/HACK/US/Indiana-Starke
new file mode 100644 (file)
index 0000000..5c1ec16
Binary files /dev/null and b/zic.tproj/HACK/US/Indiana-Starke differ
diff --git a/zic.tproj/HACK/US/Michigan b/zic.tproj/HACK/US/Michigan
new file mode 100644 (file)
index 0000000..7eac631
Binary files /dev/null and b/zic.tproj/HACK/US/Michigan differ
diff --git a/zic.tproj/HACK/US/Mountain b/zic.tproj/HACK/US/Mountain
new file mode 100644 (file)
index 0000000..fc45907
Binary files /dev/null and b/zic.tproj/HACK/US/Mountain differ
diff --git a/zic.tproj/HACK/US/Pacific b/zic.tproj/HACK/US/Pacific
new file mode 100644 (file)
index 0000000..458d9b7
Binary files /dev/null and b/zic.tproj/HACK/US/Pacific differ
diff --git a/zic.tproj/HACK/US/Pacific-New b/zic.tproj/HACK/US/Pacific-New
new file mode 100644 (file)
index 0000000..458d9b7
Binary files /dev/null and b/zic.tproj/HACK/US/Pacific-New differ
diff --git a/zic.tproj/HACK/US/Samoa b/zic.tproj/HACK/US/Samoa
new file mode 100644 (file)
index 0000000..dd0d3e8
Binary files /dev/null and b/zic.tproj/HACK/US/Samoa differ
diff --git a/zic.tproj/HACK/UTC b/zic.tproj/HACK/UTC
new file mode 100644 (file)
index 0000000..fa05d4b
Binary files /dev/null and b/zic.tproj/HACK/UTC differ
diff --git a/zic.tproj/HACK/Universal b/zic.tproj/HACK/Universal
new file mode 100644 (file)
index 0000000..fa05d4b
Binary files /dev/null and b/zic.tproj/HACK/Universal differ
diff --git a/zic.tproj/HACK/W-SU b/zic.tproj/HACK/W-SU
new file mode 100644 (file)
index 0000000..af292f7
Binary files /dev/null and b/zic.tproj/HACK/W-SU differ
diff --git a/zic.tproj/HACK/WET b/zic.tproj/HACK/WET
new file mode 100644 (file)
index 0000000..2424808
Binary files /dev/null and b/zic.tproj/HACK/WET differ
diff --git a/zic.tproj/HACK/Zulu b/zic.tproj/HACK/Zulu
new file mode 100644 (file)
index 0000000..fa05d4b
Binary files /dev/null and b/zic.tproj/HACK/Zulu differ
diff --git a/zic.tproj/Makefile b/zic.tproj/Makefile
new file mode 100644 (file)
index 0000000..7b908e2
--- /dev/null
@@ -0,0 +1,51 @@
+#
+# 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 = zic
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+HFILES = private.h tzfile.h
+
+CFILES = ialloc.c scheck.c zic.c
+
+OTHERSRCS = HACK Makefile.preamble Makefile Makefile.postamble\
+            datfiles zic.8
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/sbin
+LIBS = 
+DEBUG_LIBS = $(LIBS)
+PROF_LIBS = $(LIBS)
+
+
+
+
+NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD
+
+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 = $(NEXTDEV_BIN)/javac
+
+include $(MAKEFILEDIR)/platform.make
+
+-include Makefile.preamble
+
+include $(MAKEFILEDIR)/$(MAKEFILE)
+
+-include Makefile.postamble
+
+-include Makefile.dependencies
diff --git a/zic.tproj/Makefile.postamble b/zic.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..4db6c70
--- /dev/null
@@ -0,0 +1,201 @@
+###############################################################################
+#  NeXT Makefile.postamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project, sub-project, bundle, or
+#  palette.  Each node in the project's tree of sub-projects and bundles 
+#  should have it's own Makefile.preamble and Makefile.postamble.  Additional
+#  rules (e.g., after_install) that are defined by the developer should be
+#  defined in this file.
+#
+###############################################################################
+# 
+# Here are the variables exported by the common "app" makefiles that can be 
+# used in any customizations you make to the template below:
+# 
+#      PRODUCT_ROOT - Name of the directory to which resources are copied.
+#      OFILE_DIR - Directory into which .o object files are generated.
+#                  (Note that this name is calculated based on the target 
+#                   architectures specified in Project Builder).
+#      DERIVED_SRC_DIR - Directory used for all other derived files
+#      ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations
+#
+#      NAME - name of application, bundle, subproject, palette, etc.
+#      LANGUAGE - langage in which the project is written (default "English")
+#      LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project
+#      GLOBAL_RESOURCES - non-localized resources of project
+#      PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0)
+#      ICONSECTIONS - Specifies icon sections when linking executable 
+#
+#      CLASSES - Class implementation files in project.
+#      HFILES - Header files in project.
+#      MFILES - Other Objective-C source files in project. 
+#      CFILES - Other C source files in project. 
+#      PSWFILES - .psw files in the project
+#      PSWMFILES - .pswm files in the project
+#      SUBPROJECTS - Subprojects of this project
+#      BUNDLES - Bundle subprojects of this project
+#      OTHERSRCS - Other miscellaneous sources of this project
+#      OTHERLINKED - Source files not matching a standard source extention
+#
+#      LIBS - Libraries to link with when making app target
+#      DEBUG_LIBS - Libraries to link with when making debug target
+#      PROF_LIBS - Libraries to link with when making profile target
+#      OTHERLINKEDOFILES - Other relocatable files to (always) link in.
+#
+#      APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles
+#      MAKEFILEDIR - Directory in which to find $(MAKEFILE)
+#      MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make)
+#      INSTALLDIR - Directory app will be installed into by 'install' target
+#
+###############################################################################
+
+
+# Change defaults assumed by the standard makefiles here.  Edit the 
+# following default values as appropriate. (Note that if no Makefile.postamble 
+# exists, these values will have defaults set in common.make).
+
+# Versioning of frameworks, libraries, bundles, and palettes:
+#CURRENTLY_ACTIVE_VERSION = YES
+       # Set to "NO" to produce a compatibility binary
+#DEPLOY_WITH_VERSION_NAME = A
+       # This should be incremented as your API changes.
+#COMPATIBILITY_PROJECT_VERSION = 1
+       # This should be incremented as your API grows.
+#CURRENT_PROJECT_VERSION = 1       
+       # Defaults to using the "vers_string" hack.
+
+# Some compiler flags can be easily overridden here, but onlytake effect at 
+# the top-level:
+#OPTIMIZATION_CFLAG = -O
+#DEBUG_SYMBOLS_CFLAG = -g
+#WARNING_CFLAGS = -Wmost
+#DEBUG_BUILD_CFLAGS = -DDEBUG
+#PROFILE_BUILD_CFLAGS = -pg -DPROFILE
+
+# This definition will suppress stripping of debug symbols when an executable
+# is installed.  By default it is YES.
+# STRIP_ON_INSTALL = NO
+
+# Flags passed to yacc
+#YFLAGS = -d
+
+# Library and Framework projects only:
+# 1. If you want something other than the default .dylib name, override it here
+#DYLIB_INSTALL_NAME = lib$(NAME).dylib
+
+# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here.  One good choice is the installation directory.  Another one might be none at all.
+#DYLIB_INSTALL_DIR = $(INSTALLDIR)
+
+# 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 for various project types. Note: -S strips debugging symbols
+#    (executables can be stripped down further with -x or, if they load no bundles, with no
+#     options at all).
+#APP_STRIP_OPTS = -S
+#TOOL_STRIP_OPTS = -S
+#LIBRARY_STRIP_OPTS = -S
+        # for .a archives
+#DYNAMIC_STRIP_OPTS = -S
+        # for bundles and shared libraries
+
+#########################################################################
+# Put rules to extend the behavior of the standard Makefiles here.  "Official" 
+# user-defined rules are:
+#   * before_install
+#   * after_install
+#   * after_installhdrs
+# 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.
+#
+# Note: on MS Windows, executables, have an extension, so rules and dependencies
+#       for generated tools should use $(EXECUTABLE_EXT) on the end.
+
+###############################################################################
+# Install /usr/share/zoneinfo files
+###############################################################################
+
+VPATH += :datfiles
+
+# If you always want time values interpreted as "seconds since the epoch
+# (not counting leap seconds)", use
+#      REDO=           posix_only
+# below.  If you always want right time values interpreted as "seconds since
+# the epoch" (counting leap seconds)", use
+#      REDO=           right_only
+# below.  If you want both sets of data available, with leap seconds not
+# counted normally, use
+#      REDO=           posix_right
+# below.  If you want both sets of data available, with leap seconds counted
+# normally, use
+#      REDO=           right_posix
+# below.
+
+REDO=          posix_only
+
+TZDIR=         ${DSTROOT}/usr/share/zoneinfo
+LOCALTIME=     US/Pacific
+POSIXRULES=    US/Pacific
+
+YEARISTYPE=    datfiles/yearistype.sh
+YEARISTYPECOPY=        ${SYM_DIR}/yearistypecopy
+
+YDATA=         africa antarctica asia australasia \
+               europe northamerica southamerica pacificnew etcetera factory \
+               backward
+NDATA=         systemv
+SDATA=         solar87 solar88 solar89
+TDATA=         $(YDATA) $(NDATA) $(SDATA)
+DATA=          $(YDATA) $(NDATA) $(SDATA) leapseconds # yearistype.sh
+USNO=          usno1988 usno1989
+
+ZIC=zic
+
+${YEARISTYPECOPY}:
+       cp ${YEARISTYPE} ${YEARISTYPECOPY}
+       chmod u+x ${YEARISTYPECOPY}
+
+posix_only: ${TDATA} ${YEARISTYPECOPY}
+       (cd datfiles; \
+           ${ZIC} -y ${YEARISTYPECOPY} -d ${TZDIR} -L /dev/null ${TDATA})
+
+right_only: leapseconds ${TDATA} ${YEARISTYPECOPY}
+       (cd datfiles; \
+           ${ZIC} -y ${YEARISTYPECOPY} -d ${TZDIR} -L leapseconds ${TDATA})
+
+other_two: leapseconds ${TDATA} ${YEARISTYPECOPY}
+       (cd datfiles; \
+           ${ZIC} -y ${YEARISTYPECOPY} -d ${TZDIR}/posix -L /dev/null ${TDATA})
+       (cd datfiles; \
+           ${ZIC} -y ${YEARISTYPECOPY} -d ${TZDIR}/right -L leapseconds ${TDATA})
+
+posix_right: posix_only other_two
+
+right_posix: right_only other_two
+
+#after_install:: ${DATA} ${REDO} ${YEARISTYPECOPY}
+#      ${ZIC} -y ${YEARISTYPECOPY} -d ${TZDIR} -p ${POSIXRULES}
+#      chown -R ${BINOWN}:${BINGRP} ${TZDIR}
+#      find ${TZDIR} -type f | xargs chmod a=r
+#      -rm -f ${DSTROOT}/etc/localtime
+#      ln -s ${TZDIR}/${LOCALTIME} ${DSTROOT}/etc/localtime
+
+#since we are not doing native builds ... hack hack hack
+after_install::
+       -mkdir -p ${DSTROOT}/usr/share
+       -rm -rf ${DSTROOT}/usr/share/zoneinfo
+       cp -r HACK ${DSTROOT}/usr/share/zoneinfo
+       chmod -R og-w ${DSTROOT}/usr/share/zoneinfo
+       -mkdir -p ${DSTROOT}/private/etc
+       -rm -f ${DSTROOT}/private/etc/localtime
+       ln -fs /usr/share/zoneinfo/${LOCALTIME} ${DSTROOT}/private/etc/localtime
diff --git a/zic.tproj/Makefile.preamble b/zic.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..74ce95a
--- /dev/null
@@ -0,0 +1,130 @@
+###############################################################################
+#  NeXT Makefile.preamble
+#  Copyright 1996, NeXT Software, Inc.
+#
+#  This Makefile is used for configuring the standard app makefiles associated
+#  with ProjectBuilder.  
+#  
+#  Use this template to set attributes for a project.  Each node in a project
+#  tree of sub-projects, tools, etc. should have its own Makefile.preamble and 
+#  Makefile.postamble.
+#
+###############################################################################
+## Configure the flags passed to $(CC) here.  These flags will also be 
+## inherited by all nested sub-projects and bundles.  Put your -I, -D, -U, and
+## -L flags in ProjectBuilder's Build Options inspector if at all possible.
+## To change the default flags that get passed to ${CC} 
+## (e.g. change -O to -O2), see Makefile.postamble.
+
+# Flags passed to compiler (in addition to -g, -O, etc)
+OTHER_CFLAGS = 
+# Flags passed to ld (in addition to -ObjC, etc.)
+OTHER_LDFLAGS =        
+# Flags passed to libtool when building libraries
+OTHER_LIBTOOL_FLAGS =
+# For ordering named sections on NEXTSTEP (see ld(1))
+SECTORDER_FLAGS =
+
+# If you do not want any headers exported before compilations begin,
+# uncomment the following line.  This can be a big time saver.
+#SKIP_EXPORTING_HEADERS = YES
+
+# Stuff related to exporting headers from this project that isn't already 
+# handled by PB.
+OTHER_PUBLIC_HEADERS =
+OTHER_PROJECT_HEADERS =
+OTHER_PRIVATE_HEADERS =
+
+# Set these two macros if you want a precomp to be built as part of
+# installation. The cc -precomp will be run in the public header directory
+# on the specified public header files with the specified additional flags.
+PUBLIC_PRECOMPILED_HEADERS =
+PUBLIC_PRECOMPILED_HEADERS_CFLAGS =
+
+# Set this for library projects if you want to publish header files.  If your 
+# app or tool project exports headers  Don't
+# include $(DSTROOT); this is added for you automatically.
+PUBLIC_HEADER_DIR =
+PRIVATE_HEADER_DIR =
+
+# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# 
+# (say, to add a subdirectory like "/sys"), you can use:
+PUBLIC_HEADER_DIR_SUFFIX = 
+PRIVATE_HEADER_DIR_SUFFIX = 
+
+# Set this for dynamic library projects on platforms where code which references
+# a dynamic library must link against an import library (i.e., Windows NT)
+# Don't include $(DSTROOT); this is added for you automatically.
+IMPORT_LIBRARY_DIR = 
+
+# Additional (non-localized) resources for this project, which can be generated
+OTHER_RESOURCES = 
+
+# Uncomment this to produce a static archive-style (.a) library
+#LIBRARY_STYLE = STATIC
+
+# Set this to YES if you don't want a final libtool call for a library/framework.
+BUILD_OFILES_LIST_ONLY = 
+
+# Additional relocatables to be linked into this project
+OTHER_OFILES = 
+# Additional libraries to link against
+OTHER_LIBS = 
+# 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)
+
+## Configure how things get built here.  Additional dependencies, source files, 
+## derived files, and build order should be specified here.
+
+# Other dependencies of this project
+OTHER_PRODUCT_DEPENDS =        
+# Built *before* building subprojects/bundles
+OTHER_INITIAL_TARGETS = 
+# Other source files maintained by .pre/postamble
+OTHER_SOURCEFILES = 
+# Additional files to be removed by `make clean' 
+OTHER_GARBAGE = 
+
+# Targets to build before installation
+OTHER_INSTALL_DEPENDS =        
+
+# More obscure flags you might want to set for pswrap, yacc, lex, etc.
+PSWFLAGS = 
+YFLAGS = 
+LFLAGS = 
+
+## Delete this line if you want fast and loose cleans that will not remove 
+## things like precomps and user-defined OTHER_GARBAGE in subprojects.
+CLEAN_ALL_SUBPROJECTS = YES
+
+## Add more obscure source files here to cause them to be automatically 
+## processed by the appropriate tool.  Note that these files should also be
+## added to "Supporting Files" in ProjectBuilder.  The desired .o files that 
+## result from these files should also be added to OTHER_OFILES above so they
+## will be linked in.
+
+# .msg files that should have msgwrap run on them
+MSGFILES = 
+# .defs files that should have mig run on them
+DEFSFILES = 
+# .mig files (no .defs files) that should have mig run on them
+MIGFILES = 
+# .x files that should have rpcgen run on them
+RPCFILES =
+
+## Add additional Help directories here (add them to the project as "Other 
+## Resources" in Project Builder) so that they will be compressed into .store
+## files and copied into the app wrapper.  If the help directories themselves
+## need to also be in the app wrapper, then a cp command will need to be added
+## in an after_install target.
+OTHER_HELP_DIRS = 
+
+# After you have saved your project using the 4.0 PB, you will automatically 
+# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project.  If you should 
+# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to
+# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app.
+
+# Don't add more rules here unless you want the first one to be the default
+# target for make!  Put all your targets in Makefile.postamble.
+
diff --git a/zic.tproj/PB.project b/zic.tproj/PB.project
new file mode 100644 (file)
index 0000000..b20b6db
--- /dev/null
@@ -0,0 +1,27 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        H_FILES = (private.h, tzfile.h); 
+        OTHER_LINKED = (ialloc.c, scheck.c, zic.c); 
+        OTHER_SOURCES = (HACK, Makefile.preamble, Makefile, Makefile.postamble, datfiles, zic.8); 
+        SUBPROJECTS = (); 
+    }; 
+    LANGUAGE = English; 
+    LOCALIZABLE_FILES = {}; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; 
+    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_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = zic; 
+    PROJECTTYPE = Tool; 
+    PROJECTVERSION = 2.8; 
+    WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; 
+    WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; 
+    WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; 
+}
diff --git a/zic.tproj/datfiles/africa b/zic.tproj/datfiles/africa
new file mode 100644 (file)
index 0000000..1a601c9
--- /dev/null
@@ -0,0 +1,671 @@
+#      $OpenBSD: africa,v 1.4 1997/01/14 04:36:47 millert Exp $
+# @(#)africa   7.16
+
+# 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):
+#
+# 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).
+#
+# Gwillim Law <LAW@encmail.encompass.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.
+#
+# 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.
+#
+# 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:
+#
+#      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'.
+#
+# For time zone abbreviations like `EST' I used the following rules,
+# in decreasing order of importance:
+#
+#      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:
+#
+#              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
+#       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.
+
+
+# Algeria
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Algeria 1916    only    -       Jun     14      23:00s  1:00    S
+Rule   Algeria 1916    1919    -       Oct     Sun<=7  23:00s  0       -
+Rule   Algeria 1917    only    -       Mar     24      23:00s  1:00    S
+Rule   Algeria 1918    only    -       Mar      9      23:00s  1:00    S
+Rule   Algeria 1919    only    -       Mar      1      23:00s  1:00    S
+Rule   Algeria 1920    only    -       Feb     14      23:00s  1:00    S
+Rule   Algeria 1920    only    -       Oct     23      23:00s  0       -
+Rule   Algeria 1921    only    -       Mar     14      23:00s  1:00    S
+Rule   Algeria 1921    only    -       Jun     21      23:00s  0       -
+Rule   Algeria 1939    only    -       Sep     11      23:00s  1:00    S
+Rule   Algeria 1939    only    -       Nov     19       1:00   0       -
+Rule   Algeria 1944    1945    -       Apr     Mon<=7   2:00   1:00    S
+Rule   Algeria 1944    only    -       Oct      8       2:00   0       -
+Rule   Algeria 1945    only    -       Sep     16       1:00   0       -
+Rule   Algeria 1971    only    -       Apr     25      23:00s  1:00    S
+Rule   Algeria 1971    only    -       Sep     26      23:00s  0       -
+Rule   Algeria 1977    only    -       May      6       0:00   1:00    S
+Rule   Algeria 1977    only    -       Oct     21       0:00   0       -
+Rule   Algeria 1978    only    -       Mar     24       1:00   1:00    S
+Rule   Algeria 1978    only    -       Sep     22       3:00   0       -
+Rule   Algeria 1980    only    -       Apr     25       0:00   1:00    S
+Rule   Algeria 1980    only    -       Oct     31       2:00   0       -
+# Shanks gives 0:09 for Paris Mean Time; go with Howse's more precise 0:09:21.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Algiers  0:12:12 -       LMT     1891 Mar 15 0:01
+                       0:09:21 -       PMT     1911 Mar 11    # Paris Mean Time
+                       0:00    Algeria WE%sT   1940 Feb 25 2:00
+                       1:00    Algeria CE%sT   1946 Oct  7
+                       0:00    -       WET     1956 Jan 29
+                       1:00    -       CET     1963 Apr 14
+                       0:00    Algeria WE%sT   1977 Oct 21
+                       1:00    Algeria CE%sT   1979 Oct 26
+                       0:00    Algeria WE%sT   1981 May
+                       1:00    -       CET
+
+# Angola
+# 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
+
+# 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
+
+# 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
+
+# Burkina Faso
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Ouagadougou        -0:06:04 -      LMT     1912
+                        0:00   -       WAT
+
+# Burundi
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Bujumbura  1:57:28 -       LMT     1890
+                       2:00    -       SAT
+
+# 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
+
+# Cape Verde
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Atlantic/Cape_Verde -1:34:04 -    LMT     1907                    # Praia
+                       -2:00   -       CVT     1942 Sep
+                       -2:00   1:00    CVST    1945 Oct 15
+                       -2:00   -       CVT     1975 Nov 25 2:00
+                       -1:00   -       CVT
+
+# Central African Republic
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Bangui   1:14:20 -       LMT     1912
+                       1:00    -       CAT
+
+# 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
+
+# Comoros
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Comoro   2:53:04 -       LMT     1911 Jul   # Moroni, Gran Comoro
+                       3:00    -       EAT
+
+# Congo
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Brazzaville        1:01:08 -       LMT     1912
+                       1:00    -       CAT
+
+# Cote D'Ivoire
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Abidjan  -0:16:08 -      LMT     1912
+                        0:00   -       WAT
+
+# Djibouti
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Djibouti 2:52:36 -       LMT     1911 Jul
+                       3:00    -       EAT
+
+###############################################################################
+
+# 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       -
+Rule   Egypt   1941    only    -       Apr     15      0:00    1:00    S
+Rule   Egypt   1941    only    -       Sep     16      0:00    0       -
+Rule   Egypt   1942    1944    -       Apr      1      0:00    1:00    S
+Rule   Egypt   1942    only    -       Oct     27      0:00    0       -
+Rule   Egypt   1943    1945    -       Nov      1      0:00    0       -
+Rule   Egypt   1945    only    -       Apr     16      0:00    1:00    S
+Rule   Egypt   1957    only    -       May     10      0:00    1:00    S
+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   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       -
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Cairo    2:05:00 -       LMT     1900 Oct
+                       2:00    Egypt   EE%sT
+
+# 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
+
+# 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?
+                       3:00    -       EAT
+
+# Ethiopia
+# 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?
+                       3:00    -       EAT
+
+# Europa Island
+# uninhabited
+
+# Gabon
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Libreville 0:37:48 -       LMT     1912
+                       1:00    -       CAT
+
+# 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
+
+# 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
+# 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
+
+# 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
+
+# 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    -       BEAT    1960
+                       3:00    -       EAT
+
+# Lesotho
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Maseru   1:50:00 -       LMT     1903 Mar
+                       2:00    -       SAT     1943 Sep 19 2:00
+                       2:00    1:00    SAST    1944 Mar 19 2:00
+                       2:00    -       SAT
+
+# 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.
+# 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
+
+###############################################################################
+
+# 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       -
+Rule   Libya   1953    only    -       Oct      9      2:00    1:00    S
+Rule   Libya   1954    only    -       Jan      1      0:00    0       -
+Rule   Libya   1955    only    -       Sep     30      0:00    1:00    S
+Rule   Libya   1956    only    -       Jan      1      0:00    0       -
+Rule   Libya   1982    1984    -       Apr      1      0:00    1:00    S
+Rule   Libya   1982    1985    -       Oct      1      0:00    0       -
+Rule   Libya   1985    only    -       Apr      6      0:00    1:00    S
+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
+
+# Madagascar
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Indian/Antananarivo 3:10:04 -     LMT     1911 Jul
+                       3:00    -       EAT     1954 Feb 27 23:00s
+                       3:00    1:00    EAST    1954 May 29 23:00s
+                       3:00    -       EAT
+
+# Malawi
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Blantyre 2:20:00 -       LMT     1903 Mar
+                       2:00    -       SAT
+
+# 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
+# no longer different from Bamako, but too famous to omit
+Zone   Africa/Timbuktu -0:12:04 -      LMT     1912
+                        0:00   -       WAT
+
+# 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
+
+# Mauritius
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Indian/Mauritius  3:50:00 -       LMT     1907            # Port Louis
+                       4:00    -       MUT     # Mauritius Time
+# Agalega Is, Rodriguez
+# no information; probably like Indian/Mauritius
+
+# Mayotte
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Mayotte  3:00:56 -       LMT     1911 Jul        # Mamoutzou
+                       3:00    -       EAT
+
+# Morocco
+# 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       -
+Rule   Morocco 1940    only    -       Feb     25       0:00   1:00    S
+Rule   Morocco 1945    only    -       Nov     18       0:00   0       -
+Rule   Morocco 1950    only    -       Jun     11       0:00   1:00    S
+Rule   Morocco 1950    only    -       Oct     29       0:00   0       -
+Rule   Morocco 1967    only    -       Jun      3      12:00   1:00    S
+Rule   Morocco 1967    only    -       Oct      1       0:00   0       -
+Rule   Morocco 1974    only    -       Jun     24       0:00   1:00    S
+Rule   Morocco 1974    only    -       Sep      1       0:00   0       -
+Rule   Morocco 1976    1977    -       May      1       0:00   1:00    S
+Rule   Morocco 1976    only    -       Aug      1       0:00   0       -
+Rule   Morocco 1977    only    -       Sep     28       0:00   0       -
+Rule   Morocco 1978    only    -       Jun      1       0:00   1:00    S
+Rule   Morocco 1978    only    -       Aug      4       0:00   0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Casablanca -0:30:20 -      LMT     1913 Oct 26
+                        0:00   Morocco WE%sT   1984 Mar 16
+                        1:00   -       CET     1986
+                        0:00   -       WET
+# Western Sahara
+Zone Africa/El_Aaiun   -0:52:48 -      LMT     1934 Jan
+                       -1:00   -       AAT     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
+
+# Namibia
+# 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    -       SAT     1942 Sep 20 2:00
+                       2:00    1:00    SAST    1943 Mar 21 2:00
+                       2:00    Namibia SA%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
+
+# Nigeria
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Lagos    0:13:36 -       LMT     1919 Sep
+                       1:00    -       CAT
+
+# Reunion
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Reunion  3:41:52 -       LMT     1911 Jun        # Saint-Denis
+                       4:00    -       RET     # Reunion Time
+
+# Rwanda
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Kigali   2:00:16 -       LMT     1935 Jun
+                       2:00    -       SAT
+
+# 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: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
+
+# 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
+
+# Senegal
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Dakar    -1:09:44 -      LMT     1912
+                       -1:00   -       AAT     1941 Jun
+                        0:00   -       WAT
+
+# Seychelles
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Mahe     3:41:48 -       LMT     1906 Jun        # Victoria
+                       4:00    -       SCT     # Seychelles Time
+
+# 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       -
+# 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
+
+# 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
+                       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      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
+# 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
+# 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       -
+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
+
+# Swaziland
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Mbabane  2:04:24 -       LMT     1903 Mar
+                       2:00    -       SAT
+
+# Tanzania
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Africa/Dar_es_Salaam 2:37:08 -    LMT     1931
+                       3:00    -       EAT     1948
+                       2:45    -       BEAT    1961
+                       3:00    -       EAT
+
+# Togo
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Lome     0:04:52 -       LMT     1893
+                       0:00    -       WAT
+
+# Tromelin
+# uninhabited
+
+# Tunisia
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Tunisia 1939    only    -       Apr     15      23:00s  1:00    S
+Rule   Tunisia 1939    only    -       Nov     18      23:00s  0       -
+Rule   Tunisia 1940    only    -       Feb     25      23:00s  1:00    S
+Rule   Tunisia 1941    only    -       Oct      6       0:00   0       -
+Rule   Tunisia 1942    only    -       Mar      9       0:00   1:00    S
+Rule   Tunisia 1942    only    -       Nov      2       3:00   0       -
+Rule   Tunisia 1943    only    -       Mar     29       2:00   1:00    S
+Rule   Tunisia 1943    only    -       Apr     17       2:00   0       -
+Rule   Tunisia 1943    only    -       Apr     25       2:00   1:00    S
+Rule   Tunisia 1943    only    -       Oct      4       2:00   0       -
+Rule   Tunisia 1944    1945    -       Apr     Mon>=1   2:00   1:00    S
+Rule   Tunisia 1944    only    -       Oct      8       0:00   0       -
+Rule   Tunisia 1945    only    -       Sep     16       0:00   0       -
+Rule   Tunisia 1977    only    -       Apr     30       0:00s  1:00    S
+Rule   Tunisia 1977    only    -       Sep     24       0:00s  0       -
+Rule   Tunisia 1978    only    -       May      1       0:00s  1:00    S
+Rule   Tunisia 1978    only    -       Oct      1       0:00s  0       -
+Rule   Tunisia 1988    only    -       Jun      1       0:00s  1:00    S
+Rule   Tunisia 1988    1990    -       Sep     lastSun  0:00s  0       -
+Rule   Tunisia 1989    only    -       Mar     26       0:00s  1:00    S
+Rule   Tunisia 1990    only    -       May      1       0:00s  1:00    S
+# Shanks gives 0:09 for Paris Mean Time; go with Howse's more precise 0:09:21.
+# Shanks says the 1911 switch occurred on Mar 9; go with Howse's Mar 11.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Tunis    0:40:44 -       LMT     1881 May 12
+                       0:09:21 -       PMT     1911 Mar 11    # Paris Mean Time
+                       1:00    Tunisia CE%sT
+
+# Uganda
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Kampala  2:09:40 -       LMT     1928 Jul
+                       3:00    -       EAT     1930
+                       2:30    -       BEAT    1948
+                       2:45    -       BEAT    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
+
+# Zimbabwe
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Africa/Harare   2:04:12 -       LMT     1903 Mar
+                       2:00    -       SAT
diff --git a/zic.tproj/datfiles/antarctica b/zic.tproj/datfiles/antarctica
new file mode 100644 (file)
index 0000000..01262d7
--- /dev/null
@@ -0,0 +1,180 @@
+#      $OpenBSD: antarctica,v 1.3 1997/01/14 04:36:48 millert Exp $
+# @(#)antarctica       7.5
+
+# 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).
+# Unless otherwise specified, we have no time zone information.
+#
+# I made up all time zone abbreviations mentioned here; corrections welcome!
+# FORMAT is `___' and GMTOFF is 0 for locations while uninhabited.
+
+# These rules are stolen from the `southamerica' file.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   ArgAQ   1964    1966    -       Mar      1      0:00    0       -
+Rule   ArgAQ   1964    1966    -       Oct     15      0:00    1:00    S
+Rule   ArgAQ   1967    only    -       Apr      1      0:00    0       -
+Rule   ArgAQ   1967    1968    -       Oct     Sun<=7  0:00    1:00    S
+Rule   ArgAQ   1968    1969    -       Apr     Sun<=7  0:00    0       -
+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       -
+
+
+# Argentina - 6 year-round bases
+# General Belgrano II
+# 5 others
+
+# Australia - territories
+# Heard Island, McDonald Islands
+#
+# 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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Antarctica/Casey  0       -       ___     1969
+                       8:00    -       WST     # Western (Aus) Standard Time
+#Zone Antartica/Davis  unknown
+Zone Antarctica/Mawson 0       -       ___     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)
+
+# Brazil - year-round base
+# Ferraz, King George Island, since 1983/4
+
+# Chile - 4 year-round bases
+
+# 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
+#
+# 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
+
+# Germany - year-round base
+# Georg von Neumayer
+
+# India - year-round base
+# Dakshin Gangotri
+
+# Japan - year-round bases
+# Dome Fuji
+# Syowa
+
+# S Korea - year-round base
+# King Sejong, King George Island, since 1988
+
+# New Zealand - claims
+# Balleny Islands
+# Scott Island
+#
+# year-round base
+# Scott, Ross Island, since 1957-01, is like Antarctica/McMurdo.
+#
+# These rules for New Zealand are stolen from the `australasia' file.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   NZAQ    1974    only    -       Nov      3      2:00s   1:00    D
+Rule   NZAQ    1975    1988    -       Oct     lastSun 2:00s   1:00    D
+Rule   NZAQ    1989    only    -       Oct      8      2:00s   1:00    D
+Rule   NZAQ    1990    max     -       Oct     Sun>=1  2:00s   1:00    D
+Rule   NZAQ    1975    only    -       Feb     23      2:00s   0       S
+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)
+#
+# claims
+# Peter I Island (uninhabited)
+
+# Poland - year-round base
+# Arctowski, King George Island, since 1977
+
+# Russia - year-round bases
+# Bellingshausen, King George Island
+# Mirny
+# Molodezhnaya
+# Novolazarevskaya
+# Vostok
+
+# S Africa - year-round bases
+# Marion Island
+# Sanae
+
+# UK
+#
+# British Antarctic Territories (BAT) claims
+# South Orkney Islands
+# South Shetland Islands
+#
+# year-round bases
+# Halley, Coates Land, -7535-2619, since 1956-01-06
+# Rothera, Adelaide Island, -6734-6808, since 1976-12-01
+
+# Uruguay - year round base
+# Artigas, King George Island
+
+# USA - year-round bases
+#
+# Palmer, Anvers Island, since 1965 (moved 2 miles in 1968)
+#
+# From Ethan Dicks <erd@mcmsun5.mcmurdo.gov> (1996-10-06):
+# It keeps the same time as Punta Arenas, Chile, because, just like us
+# and the South Pole, that's the other end of their supply line....
+# I verified with someone who was there that since 1980,
+# Palmer has followed Chile.  Prior to that, before the Falklands War,
+# Palmer used to be supplied from Argentina.
+#
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Antarctica/Palmer 0       -       ___     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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Antarctica/McMurdo        0       -       ___     1956
+                       12:00   NZAQ    NZ%sT
+#
+# Amundsen-Scott, South Pole, since 1957-01-23
+# 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.
+#
+# From Chris Carrier <72157.3334@CompuServe.COM> (1996-06-27):
+# Siple, the first commander of the South Pole station,
+# stated that he would have liked to have kept GMT at the station,
+# but that he found it more convenient to keep GMT+12
+# as supplies for the station were coming from McMurdo Sound,
+# 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.
+# And they use the same time as Christchurch, NZ does....
+# One last quirk about South Pole time.
+# All the electric clocks are usually wrong.
+# Something about the generators running at 60.1hertz or something
+# makes all of the clocks run fast.  So every couple of days,
+# we have to go around and set them back 5 minutes or so.
+# Maybe if we let them run fast all of the time, we'd get to leave here sooner!!
+#
+Link   Antarctica/McMurdo      Antarctica/South_Pole
diff --git a/zic.tproj/datfiles/asia b/zic.tproj/datfiles/asia
new file mode 100644 (file)
index 0000000..f921fb0
--- /dev/null
@@ -0,0 +1,990 @@
+#      $OpenBSD: asia,v 1.5 1997/01/14 04:36:48 millert Exp $
+# @(#)asia     7.27
+
+# 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):
+#
+# 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.
+#
+# Gwillim Law <LAW@encmail.encompass.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.
+#
+# 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.
+#
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and the discovery of the longitude,
+# Oxford University Press (1980).
+#
+# I invented the abbreviations marked `*' in the following table;
+# the rest are from earlier versions of this file, or from other sources.
+# Corrections are welcome!
+#              std dst
+#              LMT     Local Mean Time
+#      2:00    EET EEST Eastern European Time
+#      2:00    IST IDT Israel
+#      3:00    AST ADT Arabia*
+#      4:00    GST     Gulf*
+#      5:30    IST     India
+#      7:00    ICT     Indochina*
+#      8:00    CST     China
+#      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
+# additional information from Tom Yap, Sun Microsystems Intercontinental
+# Technical Support (including a page from the Official Airline Guide -
+# Worldwide Edition).  The names for time zones are guesses.
+
+###############################################################################
+
+# These rules are stolen from the `europe' file.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   EUAsia  1981    max     -       Mar     lastSun  1:00u  1:00    S
+Rule   EUAsia  1996    max     -       Oct     lastSun  1:00u  0       -
+Rule E-EurAsia 1981    max     -       Mar     lastSun  0:00   1:00    S
+Rule E-EurAsia 1979    1995    -       Sep     lastSun  0:00   0       -
+Rule E-EurAsia 1996    max     -       Oct     lastSun  0:00   0       -
+Rule RussiaAsia        1981    1984    -       Apr     1        0:00   1:00    S
+Rule RussiaAsia        1981    1983    -       Oct     1        0:00   0       -
+Rule RussiaAsia        1984    1991    -       Sep     lastSun  2:00s  0       -
+Rule RussiaAsia        1985    1991    -       Mar     lastSun  2:00s  1:00    S
+Rule RussiaAsia        1992    only    -       Mar     lastSat 23:00   1:00    S
+Rule RussiaAsia        1992    only    -       Sep     lastSat 23:00   0       -
+Rule RussiaAsia        1993    max     -       Mar     lastSun  2:00s  1:00    S
+Rule RussiaAsia        1993    1995    -       Sep     lastSun  2:00s  0       -
+Rule RussiaAsia        1996    max     -       Oct     lastSun  2:00s  0       -
+
+# Afghanistan
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Kabul      4:36:48 -       LMT     1890
+                       4:00    -       AFT     1945
+                       4:30    -       AFT
+
+# Armenia
+# From Paul Eggert (1996-05-04):
+# 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       -
+# 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
+
+# Azerbaijan
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Baku       3:19:24 -       LMT     1924 May  2
+                       3:00    -       BAKT    1957 Mar    # Baku Time
+                       4:00 RussiaAsia BAK%sT  1991 Mar 31 2:00s
+                       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
+
+# Bahrain
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+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
+                       5:53:20 -       HMT     1941 Oct    # Howrah Mean Time?
+                       6:30    -       BURT    1942 May 15 # Burma Time
+                       5:30    -       IST     1942 Sep
+                       6:30    -       BURT    1951 Sep 30
+                       6:00    -       DACT    1971 Mar 26 # Dacca Time
+                       6:00    -       BDT     # Bangladesh Time
+
+# Bhutan
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Thimbu     5:58:36 -       LMT     1947 Aug 15
+                       5:30    -       IST     1987 Oct
+                       6:00    -       BTT     # Bhutan Time
+
+# British Indian Ocean Territory
+# From Whitman:
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Chagos   5:00    -       IOT     # BIOT Time
+
+# Brunei
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Brunei     7:39:40 -       LMT     1926 Mar   # Bandar Seri Begawan
+                       7:30    -       BNT     1933
+                       8:00    -       BNT
+
+# Burma / Myanmar
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Rangoon    6:24:40 -       LMT     1880            # or Yangon
+                       6:24:36 -       RMT     1920       # Rangoon Mean Time?
+                       6:30    -       BURT    1942 May   # Burma Time
+                       9:00    -       JST     1945 May 3
+                       6:30    -       MMT                # Myanmar Time
+
+# Cambodia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Phnom_Penh 6:59:40 -       LMT     1906 Jun  9
+                       7:06:20 -       SMT     1911 Mar 11 0:01 # Saigon MT?
+                       7:00    -       ICT     1912 May
+                       8:00    -       ICT     1931 May
+                       7:00    -       ICT
+
+# People's Republic of China
+
+# From Guy Harris:
+# People's Republic of China.  Yes, they really have only one time zone.
+
+# From Bob Devine (1988-01-28):
+# No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
+# China is across 4 physical time zones, before Feb 1, 1986 only the
+# Peking (Bejing) time zone was recognized.  Since that date, China
+# has two of 'em -- Peking's and Urumqi (named after the capital of
+# the Xinjiang Uighur Autonomous Region).  I don't know about DST for it.
+#
+# . . .I just deleted the DST table and this editor makes it too
+# painful to suck in another copy..  So, here is what I have for
+# DST start/end dates for Peking's time zone (info from AP):
+#
+#     1986 May 4 - Sept 14
+#     1987 mid-April - ??
+
+# From U. S. Naval Observatory (1989-01-19):
+# CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
+# CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
+
+# From Paul Eggert <eggert@twinsun.com> (1995-12-19):
+# Shanks writes that China has had a single time zone since 1980 May 1,
+# observing summer DST from 1986 through 1991; this contradicts Devine's
+# 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):
+# 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
+Rule   Shang   1941    only    -       Mar     16      0:00    1:00    D
+Rule   PRC     1949    only    -       Jan      1      0:00    0       S
+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
+                       8:30    -       HART    1932 Mar # Harbin Time
+                       8:00    -       CST     1940
+                       9:00    -       HART    1966 May
+                       8:30    -       HART    1980 May
+                       8:00    PRC     C%sT
+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
+                       7:00    -       CHUT    1980 May # Chungking Time
+                       8:00    PRC     C%sT
+Zone   Asia/Urumqi     5:50:20 -       LMT     1928
+                       6:00    -       URUT    1980 May # Urumqi Time
+                       8:00    PRC     C%sT
+Zone   Asia/Kashgar    5:03:56 -       LMT     1928
+                       5:30    -       KAST    1940     # Kashgar Time
+                       5:00    -       KAST    1980 May
+                       8:00    PRC     C%sT
+
+###############################################################################
+
+# Republic of China
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Taiwan  1945    1951    -       May     1       0:00    1:00    D
+Rule   Taiwan  1945    1951    -       Oct     1       0:00    0       S
+Rule   Taiwan  1952    only    -       Mar     1       0:00    1:00    D
+Rule   Taiwan  1952    1954    -       Nov     1       0:00    0       S
+Rule   Taiwan  1953    1959    -       Apr     1       0:00    1:00    D
+Rule   Taiwan  1955    1961    -       Oct     1       0:00    0       S
+Rule   Taiwan  1960    1961    -       Jun     1       0:00    1:00    D
+Rule   Taiwan  1974    1975    -       Apr     1       0:00    1:00    D
+Rule   Taiwan  1974    1975    -       Oct     1       0:00    0       S
+Rule   Taiwan  1980    only    -       Jun     30      0:00    1:00    D
+Rule   Taiwan  1980    only    -       Sep     30      0:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+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
+# 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       -
+Rule   Macao   1963    only    -       Mar     Sun>=16 0:00    1:00    S
+Rule   Macao   1964    only    -       Mar     Sun>=16 3:30    1:00    S
+Rule   Macao   1965    only    -       Mar     Sun>=16 0:00    1:00    S
+Rule   Macao   1965    only    -       Oct     31      0:00    0       -
+Rule   Macao   1966    1971    -       Apr     Sun>=16 3:30    1:00    S
+Rule   Macao   1966    1971    -       Oct     Sun>=16 3:30    0       -
+Rule   Macao   1972    1974    -       Apr     Sun>=15 0:00    1:00    S
+Rule   Macao   1972    1973    -       Oct     Sun>=15 0:00    0       -
+Rule   Macao   1974    1977    -       Oct     Sun>=15 3:30    0       -
+Rule   Macao   1975    1977    -       Apr     Sun>=15 3:30    1:00    S
+Rule   Macao   1978    1980    -       Apr     Sun>=15 0:00    1:00    S
+Rule   Macao   1978    1980    -       Oct     Sun>=15 0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Macao      7:34:20 -       LMT     1912
+                       8:00    Macao   MO%sT   1999 Dec 20 # return to China
+                       8:00    PRC     C%sT
+
+
+###############################################################################
+
+# Cyprus
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Cyprus  1975    only    -       Apr     13      0:00    1:00    S
+Rule   Cyprus  1975    only    -       Oct     12      0:00    0       -
+Rule   Cyprus  1976    only    -       May     15      0:00    1:00    S
+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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Nicosia    2:13:28 -       LMT     1921 Nov 14
+                       2:00    Cyprus  EE%sT
+
+# Georgia
+# From Paul Eggert <eggert@twinsun.com> (1994-11-19):
+# Today's _Economist_ (p 60) reports that Georgia moved its clocks forward
+# an hour recently, due to a law proposed by Zurab Murvanidze,
+# an MP who went on a hunger strike for 11 days to force discussion about it!
+# We have no details, but we'll guess they didn't move the clocks back in fall.
+#
+# From Mathew Englander <mathew@io.org>, quoting AP (1996-10-23 13:05-04):
+# Instead of putting back clocks at the end of October, Georgia
+# will stay on daylight savings time this winter to save energy,
+# President Eduard Shevardnadze decreed Wednesday.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Tbilisi    2:59:16 -       LMT     1880
+                       2:59:16 -       TBMT    1924 May  2 # Tbilisi Mean Time
+                       3:00    -       TBIT    1957 Mar    # Tbilisi Time
+                       4:00 RussiaAsia TBI%sT  1991 Mar 31 2:00s
+                       3:00    1:00    TBIST   1991 Apr  9 # independence
+                       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
+
+# India
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Calcutta   5:53:28 -       LMT     1880
+                       5:53:20 -       HMT     1941 Oct    # Howrah Mean Time?
+                       6:30    -       BURT    1942 May 15 # Burma Time
+                       5:30    -       IST     1942 Sep
+                       5:30    1:00    IST     1945 Oct 15
+                       5:30    -       IST
+# The following are like Asia/Calcutta:
+#      Andaman Is
+#      Lakshadweep (Laccadive, Minicoy and Amindivi Is)
+#      Nicobar Is
+
+# 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
+                       7:20    -       JAVT    1932 Nov         # Java Time
+                       7:30    -       JAVT    1942 Mar 23
+                       9:00    -       JST     1945 Aug
+                       7:30    -       JAVT    1948 May
+                       8:00    -       JAVT    1950 May
+                       7:30    -       JAVT    1964
+                       7:00    -       JAVT
+Zone Asia/Ujung_Pandang 7:57:36 -      LMT     1920
+                       7:57:36 -       MMT     1932 Nov    # Macassar MT
+                       8:00    -       BORT    1942 Feb  9 # Borneo Time
+                       9:00    -       JST     1945 Aug
+                       8:00    -       BORT
+Zone Asia/Jayapura     9:22:48 -       LMT     1932 Nov
+                       9:00    -       JAYT    1944        # Jayapura Time
+                       9:30    -       CST     1964
+                       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
+# of Farvardin and ends the first day of Mehr.''  This disagrees with the SSIM:
+#
+#                 DST start       DST end
+#      year    SSIM    Alavi   SSIM    Alavi
+#      1991    05-03!= 03-21   09-20!= 09-23
+#      1992    03-22!= 03-21   09-23   09-23
+#      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
+#
+# Go with Alavi starting with 1992.
+# I used Ed Reingold's cal-persia in GNU Emacs 19.34 to compute Persian dates.
+# The Persian calendar is based on the sun, and dates after around 2050
+# are approximate; stop after 2037 when 32-bit time_t's overflow.
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Iran    1978    1980    -       Mar     21      0:00    1:00    S
+Rule   Iran    1978    only    -       Oct     21      0:00    0       -
+Rule   Iran    1979    only    -       Sep     19      0:00    0       -
+Rule   Iran    1980    only    -       Sep     23      0:00    0       -
+Rule   Iran    1991    only    -       May      3      0:00s   1:00    S
+Rule   Iran    1991    only    -       Sep     20      0:00s   0       -
+Rule   Iran    1992    1995    -       Mar     21      0:00    1:00    S
+Rule   Iran    1992    1995    -       Sep     23      0:00    0       -
+Rule   Iran    1996    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    1996    only    -       Sep     22      0:00    0       -
+Rule   Iran    1997    1999    -       Mar     21      0:00    1:00    S
+Rule   Iran    1997    1999    -       Sep     23      0:00    0       -
+Rule   Iran    2000    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    2000    only    -       Sep     22      0:00    0       -
+Rule   Iran    2001    2003    -       Mar     21      0:00    1:00    S
+Rule   Iran    2001    2003    -       Sep     23      0:00    0       -
+Rule   Iran    2004    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    2004    only    -       Sep     22      0:00    0       -
+Rule   Iran    2005    2007    -       Mar     21      0:00    1:00    S
+Rule   Iran    2005    2007    -       Sep     23      0:00    0       -
+Rule   Iran    2008    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    2008    only    -       Sep     22      0:00    0       -
+Rule   Iran    2009    2011    -       Mar     21      0:00    1:00    S
+Rule   Iran    2009    2011    -       Sep     23      0:00    0       -
+Rule   Iran    2012    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    2012    only    -       Sep     22      0:00    0       -
+Rule   Iran    2013    2015    -       Mar     21      0:00    1:00    S
+Rule   Iran    2013    2015    -       Sep     23      0:00    0       -
+Rule   Iran    2016    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    2016    only    -       Sep     22      0:00    0       -
+Rule   Iran    2017    2019    -       Mar     21      0:00    1:00    S
+Rule   Iran    2017    2019    -       Sep     23      0:00    0       -
+Rule   Iran    2020    only    -       Mar     20      0:00    1:00    S
+Rule   Iran    2020    only    -       Sep     22      0:00    0       -
+Rule   Iran    2021    2023    -       Mar     21      0:00    1:00    S
+Rule   Iran    2021    2023    -       Sep     23      0:00    0       -
+Rule   Iran    2024    2025    -       Mar     20      0:00    1:00    S
+Rule   Iran    2024    2025    -       Sep     22      0:00    0       -
+Rule   Iran    2026    2027    -       Mar     21      0:00    1:00    S
+Rule   Iran    2026    2027    -       Sep     23      0:00    0       -
+Rule   Iran    2028    2029    -       Mar     20      0:00    1:00    S
+Rule   Iran    2028    2029    -       Sep     22      0:00    0       -
+Rule   Iran    2030    2031    -       Mar     21      0:00    1:00    S
+Rule   Iran    2030    2031    -       Sep     23      0:00    0       -
+Rule   Iran    2032    2033    -       Mar     20      0:00    1:00    S
+Rule   Iran    2032    2033    -       Sep     22      0:00    0       -
+Rule   Iran    2034    2035    -       Mar     21      0:00    1:00    S
+Rule   Iran    2034    2035    -       Sep     23      0:00    0       -
+Rule   Iran    2036    2037    -       Mar     20      0:00    1:00    S
+Rule   Iran    2036    2037    -       Sep     22      0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Tehran     3:25:44 -       LMT     1916
+                       3:25:44 -       TMT     1946    # Tehran Mean Time
+                       3:30    -       IRT     1977 Nov
+                       4:00    Iran    IR%sT   1979
+                       3:30    Iran    IR%sT
+
+# Iraq
+# 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
+Rule   Iraq    1983    only    -       Mar     31      0:00    1:00    D
+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.
+Rule   Iraq    1991    max     -       Apr      1      3:00s   1:00    D
+Rule   Iraq    1991    max     -       Oct      1      3:00s   0       D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Baghdad    2:57:40 -       LMT     1890
+                       2:57:36 -       BMT     1918        # Baghdad Mean Time?
+                       3:00    -       AST     1982 May
+                       3:00    Iraq    A%sT
+
+
+###############################################################################
+
+# 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):
+#
+# Shanks gives the following rules for Jerusalem from 1918 through 1991.
+# After 1989 Shanks often disagrees with Silverberg; we go with Silverberg.
+
+# From Shanks (1991):
+# 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
+Rule   Zion    1943    only    -       Apr      1      2:00    1:00    D
+Rule   Zion    1944    only    -       Apr      1      0:00    1:00    D
+Rule   Zion    1945    only    -       Apr     16      0:00    1:00    D
+Rule   Zion    1945    only    -       Nov      1      2:00    0       S
+Rule   Zion    1946    only    -       Apr     16      2:00    1:00    D
+Rule   Zion    1946    only    -       Nov      1      0:00    0       S
+Rule   Zion    1948    only    -       May     23      0:00    2:00    DD
+Rule   Zion    1948    only    -       Sep      1      0:00    1:00    D
+Rule   Zion    1948    1949    -       Nov      1      2:00    0       S
+Rule   Zion    1949    only    -       May      1      0:00    1:00    D
+Rule   Zion    1950    only    -       Apr     16      0:00    1:00    D
+Rule   Zion    1950    only    -       Sep     15      3:00    0       S
+Rule   Zion    1951    only    -       Apr      1      0:00    1:00    D
+Rule   Zion    1951    only    -       Nov     11      3:00    0       S
+Rule   Zion    1952    only    -       Apr     20      2:00    1:00    D
+Rule   Zion    1952    only    -       Oct     19      3:00    0       S
+Rule   Zion    1953    only    -       Apr     12      2:00    1:00    D
+Rule   Zion    1953    only    -       Sep     13      3:00    0       S
+Rule   Zion    1954    only    -       Jun     13      0:00    1:00    D
+Rule   Zion    1954    only    -       Sep     12      0:00    0       S
+Rule   Zion    1955    only    -       Jun     11      2:00    1:00    D
+Rule   Zion    1955    only    -       Sep     11      0:00    0       S
+Rule   Zion    1956    only    -       Jun      3      0:00    1:00    D
+Rule   Zion    1956    only    -       Sep     30      3:00    0       S
+Rule   Zion    1957    only    -       Apr     29      2:00    1:00    D
+Rule   Zion    1957    only    -       Sep     22      0:00    0       S
+Rule   Zion    1974    only    -       Jul      7      0:00    1:00    D
+Rule   Zion    1974    only    -       Oct     13      0:00    0       S
+Rule   Zion    1975    only    -       Apr     20      0:00    1:00    D
+Rule   Zion    1975    only    -       Aug     31      0:00    0       S
+Rule   Zion    1985    only    -       Apr     14      0:00    1:00    D
+Rule   Zion    1985    only    -       Sep     15      0:00    0       S
+Rule   Zion    1986    only    -       May     18      0:00    1:00    D
+Rule   Zion    1986    only    -       Sep      7      0:00    0       S
+Rule   Zion    1987    only    -       Apr     15      0:00    1:00    D
+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):
+#
+# 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.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Zion    1989    only    -       Apr     30      0:00    1:00    D
+Rule   Zion    1989    only    -       Sep      3      0:00    0       S
+Rule   Zion    1990    only    -       Mar     25      0:00    1:00    D
+Rule   Zion    1990    only    -       Aug     26      0:00    0       S
+Rule   Zion    1991    only    -       Mar     24      0:00    1:00    D
+Rule   Zion    1991    only    -       Sep      1      0:00    0       S
+Rule   Zion    1992    only    -       Mar     29      0:00    1:00    D
+Rule   Zion    1992    only    -       Sep      6      0:00    0       S
+Rule   Zion    1993    only    -       Apr      2      0:00    1:00    D
+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.
+
+# 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:
+#
+#   ftp://ftp.huji.ac.il/pub/misc/timezones/announcements/1996-1998.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.
+
+# 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    -       Sep     16      0:00    0       S
+Rule   Zion    1997    1998    -       Oct     Sun>=14 0:00    0       S
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Jerusalem  2:20:56 -       LMT     1880
+                       2:20:40 -       JMT     1918    # Jerusalem Mean Time?
+                       2:00    Zion    I%sT
+
+
+###############################################################################
+
+# Japan
+
+# `9:00' and `JST' is from Guy Harris.
+
+# From Paul Eggert <eggert@twinsun.com> (1995-03-06):
+# Today's _Asahi Evening News_ (page 4) reports that Japan had
+# daylight saving between 1948 and 1951, but ``the system was discontinued
+# because the public believed it would lead to longer working hours.''
+# Shanks writes that daylight saving in Japan during those years was as follows:
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+#Rule  Japan   1948    only    -       May     Sun>=1  2:00    1:00    D
+#Rule  Japan   1948    1951    -       Sep     Sat>=8  2:00    0       S
+#Rule  Japan   1949    only    -       Apr     Sun>=1  2:00    1:00    D
+#Rule  Japan   1950    1951    -       May     Sun>=1  2:00    1:00    D
+# but the only locations using it were US military bases.
+# We go with Shanks and omit daylight saving in those years for Asia/Tokyo.
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Tokyo      9:19:04 -       LMT     1896
+                       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.
+
+# Jordan
+# 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       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Amman      2:23:44 -       LMT     1931
+                       2:00    Jordan  EE%sT
+
+# Kazakhstan
+# From Paul Eggert (1996-11-22):
+# Andrew Evtichov <evti@chevron.com> (1996-04-13) writes that Kazakhstan
+# stayed in sync with Moscow after 1990, and that Aqtobe (formerly Aktyubinsk)
+# and Aqtau (formerly Shevchenko) are the largest cities in their zones.
+# Guess that Aqtau and Aqtobe diverged in 1995, since that's the first time
+# 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
+                       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
+                       5:00    -       ALMT    1992 Jan 19 2:00s
+                       6:00 E-EurAsia  ALM%sT
+Zone   Asia/Aqtobe     3:48:40 -       LMT     1924 May  2
+                       4:00    -       AKT     1957 Mar # Aktyubinsk Time
+                       5:00 RussiaAsia AK%sT   1991 Mar 31 2:00s
+                       4:00    1:00    AKTST   1991 Sep 29 2:00s
+                       4:00    -       AQTT    1992 Jan 19 2:00s # Aqtobe Time
+                       5:00 E-EurAsia  AQT%sT
+Zone   Asia/Aqtau      3:21:04 -       LMT     1924 May  2 # or Aktau
+                       4:00    -       SHET    1957 Mar # Fort Shevchenko Time
+                       5:00 RussiaAsia SHE%sT  1991 Mar 31 2:00s
+                       4:00    1:00    AQTST   1991 Sep 29 2:00s
+                       4:00    -       AQTT    1992 Jan 19 2:00s # Aqtau Time
+                       5:00 E-EurAsia  AQT%sT  1995 Sep lastSun
+                       4:00 E-EurAsia  AQT%sT
+
+# Kirgizstan
+# 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       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Bishkek    4:58:24 -       LMT     1924 May  2
+                       5:00    -       FRUT    1957 Mar    # Frunze Time
+                       6:00 RussiaAsia FRU%sT  1991 Mar 31 2:00s
+                       5:00    1:00    FRUST   1991 Aug 31 # independence
+                       5:00    Kirgiz  KG%sT               # Kirgizstan Time
+
+###############################################################################
+
+# Korea
+
+# 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):
+# 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
+Rule   ROK     1987    1988    -       May     Sun<=14 0:00    1:00    D
+Rule   ROK     1987    1988    -       Oct     Sun<=14 0:00    0       S
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Seoul      8:27:52 -       LMT     1890
+                       8:30    -       KST     1904 Dec
+                       9:00    -       KST     1928
+                       8:30    -       KST     1932
+                       9:00    -       KST     1954 Mar 21
+                       8:00    ROK     K%sT    1961 Aug 10
+                       8:30    -       KST     1968 Oct
+                       9:00    ROK     K%sT
+Zone   Asia/Pyongyang  8:23:00 -       LMT     1890
+                       8:30    -       KST     1904 Dec
+                       9:00    -       KST     1928
+                       8:30    -       KST     1932
+                       9:00    -       KST     1954 Mar 21
+                       8:00    -       KST     1961 Aug 10
+                       9:00    -       KST
+
+###############################################################################
+
+# Kuwait
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Kuwait     3:11:56 -       LMT     1950
+                       3:00    -       AST
+
+# Laos
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Vientiane  6:50:24 -       LMT     1906 Jun  9
+                       7:06:20 -       SMT     1911 Mar 11 0:01 # Saigon MT?
+                       7:00    -       ICT     1912 May
+                       8:00    -       ICT     1931 May
+                       7:00    -       ICT
+
+# Lebanon
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Lebanon 1920    only    -       Mar     28      0:00    1:00    S
+Rule   Lebanon 1920    only    -       Oct     25      0:00    0       -
+Rule   Lebanon 1921    only    -       Apr     3       0:00    1:00    S
+Rule   Lebanon 1921    only    -       Oct     3       0:00    0       -
+Rule   Lebanon 1922    only    -       Mar     26      0:00    1:00    S
+Rule   Lebanon 1922    only    -       Oct     8       0:00    0       -
+Rule   Lebanon 1923    only    -       Apr     22      0:00    1:00    S
+Rule   Lebanon 1923    only    -       Sep     16      0:00    0       -
+Rule   Lebanon 1957    1961    -       May     1       0:00    1:00    S
+Rule   Lebanon 1957    1961    -       Oct     1       0:00    0       -
+Rule   Lebanon 1972    only    -       Jun     22      0:00    1:00    S
+Rule   Lebanon 1972    1977    -       Oct     1       0:00    0       -
+Rule   Lebanon 1973    1977    -       May     1       0:00    1:00    S
+Rule   Lebanon 1978    only    -       Apr     30      0:00    1:00    S
+Rule   Lebanon 1978    only    -       Sep     30      0:00    0       -
+Rule   Lebanon 1984    1987    -       May     1       0:00    1:00    S
+Rule   Lebanon 1984    1991    -       Oct     16      0:00    0       -
+Rule   Lebanon 1988    only    -       Jun     1       0:00    1:00    S
+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       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Beirut     2:22:00 -       LMT     1880
+                       2:00    Lebanon EE%sT
+
+# Malaysia
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   NBorneo 1935    1941    -       Sep     14      0:00    0:20    TS
+Rule   NBorneo 1935    1941    -       Dec     14      0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Asia/Kuala_Lumpur 6:46:48 -       LMT     1880
+                       6:55:24 -       SMT     1905 Jun # Singapore Mean Time
+                       7:00    -       MALT    1933     # Malaya Time
+                       7:20    -       MALT    1942 Feb 15
+                       9:00    -       JST     1945 Sep 2
+                       7:20    -       MALT    1950
+                       7:30    -       MALT    1982 May
+                       8:00    -       MYT     # Malaysia Time
+Zone Asia/Kuching      7:21:20 -       LMT     1926 Mar
+                       7:30    -       BORT    1933    # Borneo Time
+                       8:00    NBorneo BOR%sT  1942
+                       9:00    -       JST     1945 Sep 2
+                       8:00    -       BORT    1982 May
+                       8:00    -       MYT
+
+# Maldives
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Maldives 4:54:00 -       LMT     1880    # Male
+                       4:54:00 -       MMT     1960    # Male Mean Time
+                       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)
+# 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.
+# 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    1995    -       Sep     lastSun 0:00    0       -
+Rule   Mongol  1996    max     -       Oct     Fri>=22 0:00    0       -
+# 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
+                       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
+
+# Nepal
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Katmandu   5:41:16 -       LMT     1920
+                       5:30    -       IST     1986
+                       5:45    -       NPT     # Nepal Time
+
+# Oman
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Muscat     3:54:20 -       LMT     1920
+                       4:00    -       GST
+
+# Pakistan
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Karachi    4:28:12 -       LMT     1907
+                       5:30    -       IST     1942 Sep
+                       5:30    1:00    IST     1945 Oct 15
+                       5:30    -       IST     1951 Sep 30
+                       5:00    -       KART    1971 Mar 26 # Karachi Time
+                       5:00    -       PKT     # Pakistan Time
+
+# Palestine
+# These 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       -
+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       -
+# 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
+
+# Paracel Is
+# no information
+
+# Philippines
+# Howse writes (p 162) that until 1844 the Philippines kept American date.
+# 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
+Rule   Phil    1937    only    -       Feb     1       0:00    0       -
+Rule   Phil    1954    only    -       Apr     12      0:00    1:00    S
+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
+                       8:04:00 -       LMT     1899 May 11
+                       8:00    Phil    PH%sT   1942 May
+                       9:00    -       JST     1944 Nov
+                       8:00    Phil    PH%sT
+
+# Qatar
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Qatar      3:26:08 -       LMT     1920            # Al Dawhah
+                       4:00    -       GST     1972 Jun
+                       3:00    -       AST
+
+# Saudi Arabia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Riyadh     3:06:52 -       LMT     1950
+                       3:00    -       AST
+
+# Singapore
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Singapore  6:55:24 -       LMT     1880
+                       6:55:24 -       SMT     1905 Jun # Singapore Mean Time
+                       7:00    -       MALT    1933     # Malaya Time
+                       7:20    -       MALT    1942 Feb 15
+                       9:00    -       JST     1945 Sep  2
+                       7:20    -       MALT    1950
+                       7:30    -       MALT    1965 Aug  9 # independence
+                       7:30    -       SGT     1982 May # Singapore Time
+                       8:00    -       SGT
+
+# Spratly Is
+# no information
+
+# Sri Lanka
+# From Paul Eggert (1996-09-03):
+# <URL:http://www.virtual-pc.com/lankaweb/news/items/240596-2.html> (1996-05-24)
+# 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).
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Colombo    5:19:24 -       LMT     1880
+                       5:20    -       CEYT    1906    # Ceylon 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
+
+# Syria
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Syria   1920    1923    -       Apr     Sun>=15 2:00    1:00    S
+Rule   Syria   1920    1923    -       Oct     Sun>=1  2:00    0       -
+Rule   Syria   1962    only    -       Apr     29      2:00    1:00    S
+Rule   Syria   1962    only    -       Oct     1       2:00    0       -
+Rule   Syria   1963    1965    -       May     1       2:00    1:00    S
+Rule   Syria   1963    only    -       Sep     30      2:00    0       -
+Rule   Syria   1964    only    -       Oct     1       2:00    0       -
+Rule   Syria   1965    only    -       Sep     30      2:00    0       -
+Rule   Syria   1966    only    -       Apr     24      2:00    1:00    S
+Rule   Syria   1966    1976    -       Oct     1       2:00    0       -
+Rule   Syria   1967    1978    -       May     1       2:00    1:00    S
+Rule   Syria   1977    1978    -       Sep     1       2:00    0       -
+Rule   Syria   1983    1984    -       Apr     9       2:00    1:00    S
+Rule   Syria   1983    1984    -       Oct     1       2:00    0       -
+Rule   Syria   1986    only    -       Feb     16      2:00    1:00    S
+Rule   Syria   1986    only    -       Oct     9       2:00    0       -
+Rule   Syria   1987    only    -       Mar     1       2:00    1:00    S
+Rule   Syria   1987    1988    -       Oct     31      2:00    0       -
+Rule   Syria   1988    only    -       Mar     15      2:00    1:00    S
+Rule   Syria   1989    only    -       Mar     31      2:00    1:00    S
+Rule   Syria   1989    only    -       Oct     1       2:00    0       -
+Rule   Syria   1990    only    -       Apr     1       2:00    1:00    S
+Rule   Syria   1990    only    -       Sep     30      2:00    0       -
+Rule   Syria   1991    only    -       Apr      1      0:00    1:00    S
+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
+Rule   Syria   1994    max     -       Oct      1      0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Damascus   2:25:12 -       LMT     1920
+                       2:00    Syria   EE%sT
+
+# Tajikistan
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Dushanbe   4:35:12 -       LMT     1924 May  2
+                       5:00    -       DUST    1957 Mar    # 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    -       TJT                 # Tajikistan Time
+
+# Thailand
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Bangkok    6:42:04 -       LMT     1880
+                       6:42:04 -       BMT     1920 Apr # Bangkok Mean Time
+                       7:00    -       ICT
+
+# Turkmenistan
+# 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
+
+# United Arab Emirates
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Dubai      3:41:12 -       LMT     1920
+                       4:00    -       GST
+
+# Uzbekistan
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Tashkent   4:37:12 -       LMT     1924 May  2
+                       5:00    -       TAST    1957 Mar    # 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.
+
+# 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):
+# 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?
+                       7:00    -       ICT     1912 May
+                       8:00    -       ICT     1931 May
+                       7:00    -       ICT
+
+# Yemen
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Asia/Aden       3:00:48 -       LMT     1950
+                       3:00    -       AST
diff --git a/zic.tproj/datfiles/australasia b/zic.tproj/datfiles/australasia
new file mode 100644 (file)
index 0000000..e1e567a
--- /dev/null
@@ -0,0 +1,890 @@
+#      $OpenBSD: australasia,v 1.5 1997/01/14 04:36:50 millert Exp $
+# @(#)australasia      7.31
+# This file also includes Pacific islands.
+
+# Notes are at the end of this file
+
+###############################################################################
+
+# 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    -       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.
+
+# 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: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   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
+                        8:00   -       WST     1991 Nov 17 2:00s
+                        8:00   1:00    WST     1992 Mar Sun>=1 2:00s
+                        8:00   -       WST
+# Queensland
+#
+# From Alex Livingston <alex@agsm.unsw.edu.au> (1996-11-01):
+# I have heard or read more than once that some resort islands off the coast
+# of Queensland chose to keep observing daylight-saving time even after
+# Queensland ceased to.
+#
+# From Paul Eggert (1996-11-22):
+# IATA SSIM (1993-02/1994-09) say that the Holiday Islands (Hayman, Lindeman,
+# Hamilton) observed DST for two years after the rest of Queensland stopped.
+# Hamilton is the largest, but there is also a Hamilton in Victoria,
+# so use Lindeman.
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+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       -
+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   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   Holiday EST
+
+# South Australia
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   AS      1971    1985    -       Oct     lastSun 2:00s   1:00    -
+Rule   AS      1986    only    -       Oct     19      2:00s   1:00    -
+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      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    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      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      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      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      1991    max     -       Mar     lastSun 2:00s   0       -
+# 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   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      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      1991    1994    -       Mar     Sun>=1  2:00s   0       -
+Rule   AV      1995    max     -       Mar     lastSun 2:00s   0       -
+# 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   AV      EST
+
+# New South Wales
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   AN      1971    1985    -       Oct     lastSun 2:00s   1:00    -
+Rule   AN      1972    only    -       Feb     27      2:00s   0       -
+Rule   AN      1973    1981    -       Mar     Sun>=1  2:00s   0       -
+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      1990    1995    -       Mar     Sun>=1  2:00s   0       -
+Rule   AN      1996    max     -       Mar     lastSun 2:00s   0       -
+# 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   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
+
+# 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       -
+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
+#
+# Coral Sea Is
+# no indigenous inhabitants; only meteorologists
+# no information
+#
+# Macquarie, Manihiki, Penrhyn, Rakehanga
+# no information
+
+
+# Cook Is
+# 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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Rarotonga -10:39:04 -     LMT     1901            # Avarua
+                       -10:30  -       CKT     1978 Nov 12     # Cook Is Time
+                       -10:00  Cook    CK%sT
+
+# Cocos
+# From USNO (1989):
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Indian/Cocos    6:30    -       CCT     # Cocos Islands Time
+
+# Fiji
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Fiji    11:53:40 -      LMT     1915 Oct 26     # Suva
+                       12:00   -       FJT     # Fiji Time
+
+# French Polynesia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Gambier  -8:59:48 -     LMT     1912 Oct        # Rikitea
+                        -9:00  -       GAMT    # Gambier Time
+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
+
+# 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
+
+# Kiribati
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Tarawa     11:32:04 -     LMT     1901            # Bairiki
+                        12:00  -       GILT             # Gilbert Is Time
+Zone Pacific/Enderbury -11:24:20 -     LMT     1901
+                       -12:00  -       PHOT    1979 Oct # Phoenix Is Time
+                       -11:00  -       PHOT    1995
+                        13:00  -       PHOT
+Zone Pacific/Kiritimati        -10:29:20 -     LMT     1901
+                       -10:40  -       LINT    1979 Oct # Line Is Time
+                       -10:00  -       LINT    1995
+                        14:00  -       LINT
+
+# N Mariana Is
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Saipan     9:43:00 -      LMT     1901
+                        9:00   -       MPT     1969 Oct # N Mariana Is Time
+                       10:00   -       MPT
+
+# Marshall Is
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Majuro    11:24:48 -      LMT     1901
+                       11:00   -       MHT     1969 Oct # Marshall Islands Time
+                       12:00   -       MHT
+Zone Pacific/Kwajalein 11:09:20 -      LMT     1901
+                       11:00   -       MHT     1969 Oct
+                       -12:00  -       KWAT    1993 Aug 20     # Kwajalein Time
+                       12:00   -       MHT
+
+# Micronesia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Yap       9:12:32 -       LMT     1901            # Colonia
+                       9:00    -       YAPT    1969 Oct        # Yap Time
+                       10:00   -       YAPT
+Zone Pacific/Truk      10:07:08 -      LMT     1901
+                       10:00   -       TRUT                    # Truk Time
+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
+
+# Nauru
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Nauru   11:07:40 -      LMT     1921 Jan 15     # Uaobe
+                       11:30   -       NRT     1942 Mar 15     # Nauru Time
+                       9:00    -       JST     1944 Aug 15
+                       11:30   -       NRT     1979 May
+                       12:00   -       NRT
+
+# New Caledonia
+# 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       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Noumea  11:05:48 -      LMT     1912 Jan 13
+                       11:00   NC      NC%sT
+
+
+###############################################################################
+
+# New Zealand
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# Shanks gives 1927 Nov 6 - 1928 Mar 4, 1928 Oct 14 - 1929 Mar 17,
+# 1929 Oct 13 - 1930 Mar 16; go with Whitman.
+Rule   NZ      1927    only    -       Nov     26      2:00    0:30    HD
+Rule   NZ      1928    1929    -       Mar     Sun>=1  2:00    0       S
+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
+# 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
+Rule   NZ      1974    only    -       Nov      3      2:00s   1:00    D
+Rule   NZ      1975    1988    -       Oct     lastSun 2:00s   1:00    D
+Rule   NZ      1989    only    -       Oct      8      2:00s   1:00    D
+Rule   NZ      1990    max     -       Oct     Sun>=1  2:00s   1:00    D
+Rule   NZ      1975    only    -       Feb     23      2:00s   0       S
+Rule   NZ      1976    1989    -       Mar     Sun>=1  2:00s   0       S
+Rule   NZ      1990    max     -       Mar     Sun>=15 2:00s   0       S
+Rule   Chatham 1990    max     -       Oct     Sun>=1  2:45s   1:00    D
+Rule   Chatham 1991    max     -       Mar     Sun>=15 2:45s   0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Auckland  11:39:04 -      LMT     1868
+                       11:30   NZ      NZ%sT   1940 Sep 29 2:00
+                       12:00   NZ      NZ%sT
+Zone Pacific/Chatham   12:45   Chatham CHA%sT
+
+
+# Antipodes Is, Kermadec Is
+# uninhabited except by research personnel; probably like Pacific/Auckland
+
+###############################################################################
+
+
+# Niue
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Niue    -11:19:40 -     LMT     1901            # Alofi
+                       -11:20  -       NUT     1951    # Niue Time
+                       -11:30  -       NUT     1978 Oct 1
+                       -11:00  -       NUT
+
+# Norfolk
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Norfolk 11:11:52 -      LMT     1901            # Kingston
+                       11:12   -       NMT     1951    # Norfolk Mean Time
+                       11:30   -       NFT             # Norfolk Time
+
+# Palau
+# 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
+                       9:48:40 -       PMMT    1895    # Port Moresby Mean Time
+                       10:00   -       PGT             # Papua New Guinea Time
+
+# Pitcairn
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Pitcairn  -8:40:20 -      LMT     1901            # Adamstown
+                       -8:30   -       PNT     # Pitcairn Time
+
+# American Samoa
+Zone Pacific/Pago_Pago  12:37:12 -     LMT     1879 Jul  5
+                       -11:22:48 -     LMT     1911
+                       -11:30  -       SAMT    1950            # Samoa Time
+                       -11:00  -       NST     1967 Apr        # N=Nome
+                       -11:00  -       BST     1983 Nov 30     # B=Bering
+                       -11:00  -       SST                     # S=Samoa
+
+# W Samoa
+Zone Pacific/Apia       12:33:04 -     LMT     1879 Jul  5
+                       -11:26:56 -     LMT     1911
+                       -11:30  -       SAMT    1950            # Samoa Time
+                       -11:00  -       WST                     # W Samoa Time
+
+# Solomon Is
+# excludes Bougainville, for which see Papua New Guinea
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Guadalcanal 10:39:48 -    LMT     1912 Oct        # Honiara
+                       11:00   -       SBT     # Solomon Is Time
+
+# Tokelau Is
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Pacific/Fakaofo -11:24:56 -     LMT     1901
+                       -10:00  -       TKT     # Tokelau Time
+
+# Tonga
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Tongatapu 12:19:20 -      LMT     1901
+                       12:20   -       TOT     1968 Oct # Tonga Time
+                       13:00   -       TOT
+
+# Tuvalu
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Pacific/Funafuti  11:56:52 -      LMT     1901
+                       12:00   -       TVT     # Tuvalu Time
+
+# Vanuatu
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Vanuatu 1983    only    -       Sep     25      0:00    1:00    S
+Rule   Vanuatu 1984    1991    -       Mar     Sun>=23 0:00    0       -
+Rule   Vanuatu 1984    only    -       Oct     23      0:00    1:00    S
+Rule   Vanuatu 1985    1991    -       Sep     Sun>=23 0:00    1:00    S
+Rule   Vanuatu 1992    1993    -       Jan     Sun>=23 0:00    0       -
+Rule   Vanuatu 1992    only    -       Oct     Sun>=23 0:00    1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+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
+                       12:00   -       WFT     # Wallis & Futuna Time
+
+###############################################################################
+
+# NOTES
+
+# 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):
+# 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).
+#
+# Gwillim Law <LAW@encmail.encompass.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.
+#
+# 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.
+#
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and the discovery of the longitude,
+# Oxford University Press (1980).
+#
+# I invented the abbreviations marked `*' in the following table;
+# the rest are from earlier versions of this file, or from other sources.
+# Corrections are welcome!
+#              std dst
+#              LMT     Local Mean Time
+#        8:00  WST WST Western Australia
+#        9:00  JST     Japan
+#        9:30  CST CST Central Australia
+#       10:00  EST EST Eastern Australia
+#       10:00  GST     Guam
+#       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
+#
+# 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
+
+# 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'
+# and `standard' happen to start with the same letter; hence, the
+# abbreviation does _not_ change...
+# The legislation does not actually define abbreviations, at least
+# in this State, but the abbreviation is just commonly taken to be the
+# initials of the phrase, and the legislation here uniformly uses
+# the phrase `summer time' and does not use the phrase `daylight
+# time'.
+# Announcers on the Commonwealth radio network, the ABC (for Australian
+# Broadcasting Commission), use the phrases `Eastern Standard Time'
+# or `Eastern Summer Time'.  (Note, though, that as I say in the
+# current australasia file, there is really no such thing.)  Announcers
+# on its overseas service, Radio Australia, use the same phrases
+# prefixed by the word `Australian' when referring to local times;
+# time announcements on that service, naturally enough, are made in UTC.
+
+# From Arthur David Olson (March 8 1992):
+# Given the above, what's chosen for year-round use is:
+#      CST     for any place operating at a GMTOFF of 9:30
+#      WST     for any place operating at a GMTOFF of 8:00
+#      EST     for any place operating at a GMTOFF of 10:00
+
+# From Paul Eggert (1995-12-19):
+# Shanks reports 2:00 for all autumn changes in Australia and New Zealand.
+# Mark Prior <mrp@itd.adelaide.edu.au> writes that his newspaper
+# reports that NSW's fall 1995 change will occur at 2:00,
+# but Robert Elz says it's been 3:00 in Victoria since 1970
+# 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.
+
+# Northern Territory
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The NORTHERN TERRITORY..  [ Courtesy N.T. Dept of the Chief Minister ]
+# #                                    [ Nov 1990 ]
+# #    N.T. have never utilised any DST due to sub-tropical/tropical location.
+# ...
+# Zone        Australia/North         9:30    -       CST
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# the Northern Territory do[es] not have daylight saving.
+
+# Western Australia
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# #  The state of WESTERN AUSTRALIA..  [ Courtesy W.A. dept Premier+Cabinet ]
+# #                                            [ Nov 1990 ]
+# #    W.A. suffers from a great deal of public and political opposition to
+# #    DST in principle. A bill is brought before parliament in most years, but
+# #    usually defeated either in the upper house, or in party caucus
+# #    before reaching parliament.
+# ...
+# Zone Australia/West          8:00    AW      %sST
+# ...
+# Rule AW      1974    only    -       Oct     lastSun 2:00    1:00    D
+# Rule AW      1975    only    -       Mar     Sun>=1  3:00    0       W
+# Rule AW      1983    only    -       Oct     lastSun 2:00    1:00    D
+# Rule AW      1984    only    -       Mar     Sun>=1  3:00    0       W
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# Western Australia...do[es] not have daylight saving.
+
+# From John D. Newman via Bradley White (1991-11-02):
+# Western Australia is still on "winter time". Some DH in Sydney
+# rang me at home a few days ago at 6.00am. (He had just arrived at
+# work at 9.00am.)
+# W.A. is switching to Summer Time on Nov 17th just to confuse
+# everybody again.
+
+# From Arthur David Olson (1992-03-08):
+# The 1992 ending date used in the rules is a best guess;
+# it matches what was used in the past.
+
+# Queensland
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# #   The state of QUEENSLAND.. [ Courtesy Qld. Dept Premier Econ&Trade Devel ]
+# #                                            [ Dec 1990 ]
+# ...
+# Zone Australia/Queensland    10:00   AQ      %sST
+# ...
+# Rule AQ      1971    only    -       Oct     lastSun 2:00    1:00    D
+# Rule AQ      1972    only    -       Feb     lastSun 3:00    0       E
+# Rule AQ      1989    max     -       Oct     lastSun 2:00    1:00    D
+# Rule AQ      1990    max     -       Mar     Sun>=1  3:00    0       E
+
+# From Bradley White (1989-12-24):
+# "Australia/Queensland" now observes daylight time (i.e. from
+# October 1989).
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# ...Queensland...[has] agreed to end daylight saving
+# at 3am tomorrow (March 3)...
+
+# From John Mackin (1991-03-06):
+# I can certainly confirm for my part that Daylight Saving in NSW did in fact
+# end on Sunday, 3 March.  I don't know at what hour, though.  (It surprised
+# me.)
+
+# From Bradley White (1992-03-08):
+# ...there was recently a referendum in Queensland which resulted
+# in the experimental daylight saving system being abandoned. So, ...
+# ...
+# Rule QLD     1989    1991    -       Oct     lastSun 2:00    1:00    D
+# Rule QLD     1990    1992    -       Mar     Sun>=1  3:00    0       S
+# ...
+
+# From Arthur David Olson (1992-03-08):
+# The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
+
+# South Australia, Tasmania, Victoria
+
+# From Arthur David Olson (1992-03-08):
+# The rules from version 7.1 follow.
+# There are lots of differences between these rules and
+# the Shepherd et al. rules.  Since the Shepherd et al. rules
+# and Bradley White's newspaper article are in agreement on
+# current DST ending dates, no worries.
+#
+# Rule Oz      1971    1985    -       Oct     lastSun 2:00    1:00    -
+# Rule Oz      1986    max     -       Oct     Sun<=24 2:00    1:00    -
+# Rule Oz      1972    only    -       Feb     27      3:00    0       -
+# Rule Oz      1973    1986    -       Mar     Sun>=1  3:00    0       -
+# Rule Oz      1987    max     -       Mar     Sun<=21 3:00    0       -
+# Zone Australia/Tasmania      10:00   Oz      EST
+# Zone Australia/South         9:30    Oz      CST
+# Zone Australia/Victoria      10:00   Oz      EST     1985 Oct lastSun 2:00
+#                              10:00   1:00    EST     1986 Mar Sun<=21 3:00
+#                              10:00   Oz      EST
+
+# From Robert Elz (1991-03-06):
+# I believe that the current start date for DST is "lastSun" in Oct...
+# that changed Oct 89.  That is, we're back to the
+# original rule, and that rule currently applies in all the states
+# that have dst, incl Qld.  (Certainly it was true in Vic).
+# The file I'm including says that happened in 1988, I think
+# that's incorrect, but I'm not 100% certain.
+
+# South Australia
+
+# From Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# ...South Australia...[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 SOUTH AUSTRALIA....[ Courtesy of S.A. Dept of Labour ]
+# #                                            [ Nov 1990 ]
+# ...
+# Zone Australia/South         9:30    AS      %sST
+# ...
+# Rule  AS     1971    max     -       Oct     lastSun 2:00    1:00    D
+# Rule  AS     1972    1985    -       Mar     Sun>=1  3:00    0       C
+# Rule  AS     1986    1990    -       Mar     Sun<=21 3:00    0       C
+# Rule  AS     1991    max     -       Mar     Sun>=1  3:00    0       C
+
+# From Bradley White (1992-03-11):
+# Recent correspondence with a friend in Adelaide
+# contained the following exchange:  "Due to the Adelaide Festival,
+# South Australia delays setting back our clocks for a few weeks."
+
+# From Robert Elz (1992-03-13):
+# I heard that apparently (or at least, it appears that)
+# South Aus will have an extra 3 weeks daylight saving every even
+# numbered year (from 1990).  That's when the Adelaide Festival
+# is on...
+
+# From Robert Elz (1992-03-16, 00:57:07 +1000):
+# DST didn't end in Adelaide today (yesterday)....
+# But whether it's "4th Sunday" or "2nd last Sunday" I have no idea whatever...
+# (it's just as likely to be "the Sunday we pick for this year"...).
+
+# From Bradley White (1994-04-11):
+# If Sun, 15 March, 1992 was at +1030 as kre asserts, but yet Sun, 20 March,
+# 1994 was at +0930 as John Connolly's customer seems to assert, then I can
+# only conclude that the actual rule is more complicated....
+
+# From John Warburton <jwarb@SACBH.com.au> (1994-10-07):
+# The new Daylight Savings dates for South Australia ...
+# was gazetted in the Government Hansard on Sep 26 1994....
+# start on last Sunday in October and end in last sunday in March.
+
+# 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 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 Bradley White (1991-03-04):
+# A recent excerpt from an Australian newspaper...
+# ...Victoria...[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 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
+
+# From Arthur David Olson:
+# New South Wales and subjurisdictions have their own ideas of a fun time.
+# Based on law library research by John Mackin (john@basser.cs.su.oz),
+# who notes:
+#      In Australia, time is not legislated federally, but rather by the
+#      individual states.  Thus, while such terms as ``Eastern Standard Time''
+#      [I mean, of course, Australian EST, not any other kind] are in common
+#      use, _they have NO REAL MEANING_, as they are not defined in the
+#      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 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.
+
+# 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.
+
+# Yancowinna
+
+# From John Basser (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
+# # 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
+# # been years when this did not apply, but the historical data is not
+# # presently available.
+# Zone Australia/Yancowinna    9:30     AY     %sST
+# ...
+# Rule  AY     1971    1985    -       Oct     lastSun 2:00    1:00    D
+# Rule  AY     1972    only    -       Feb     lastSun 3:00    0       C
+# [followed by other Rules]
+
+# Lord Howe Island
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# LHI...               [ Courtesy of Pauline Van Winsen.. pauline@Aus ]
+#                                      [ Dec 1990 ]
+# 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.
+
+###############################################################################
+
+# New Zealand, from Elz' asia 1.1
+# Elz says "no guarantees"
+
+# From Mark Davies (1990-10-03):
+# the 1989/90 year was a trial of an extended "daylight saving" period.
+# This trial was deemed successful and the extended period adopted for
+# subsequent years (with the addition of a further week at the start).
+# source -- phone call to Ministry of Internal Affairs Head Office.
+
+# From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
+# # The Country of New Zealand   (Australia's east island -) Gee they hate that!
+# #                               or is Australia the west island of N.Z.
+# #    [ courtesy of Geoff Tribble.. Geofft@Aus.. Auckland N.Z. ]
+# #                            [ Nov 1990 ]
+# ...
+# Rule NZ      1974    1988    -       Oct     lastSun 2:00    1:00    D
+# Rule NZ      1989    max     -       Oct     Sun>=1  2:00    1:00    D
+# Rule NZ      1975    1989    -       Mar     Sun>=1  3:00    0       S
+# Rule NZ      1990    max     -       Mar     lastSun 3:00    0       S
+# ...
+# Zone NZ                      12:00   NZ              NZ%sT   # New Zealand
+# Zone NZ-CHAT                 12:45   -               NZ-CHAT # Chatham Island
+
+# From Arthur David Olson (1992-03-08):
+# The chosen rules use the Davies October 8 values for the start of DST in 1989
+# rather than the October 1 value.
+
+# From Paul Eggert (1995-12-19);
+# Shanks reports 2:00 for all autumn changes in Australia and New Zealand.
+# Robert Uzgalis <buz@cs.aukuni.ac.nz> writes that the New Zealand Daylight
+# Savings Time Order in Council dated 1990-06-18 specifies 2:00 standard
+# 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)
+# gives the NZ rules but with transitions at 2:45 local standard time.
+# Guess that they adopted DST in 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.
+
+# Johnston
+
+# Johnston data is from usno1995.
+
+# Kiribati
+
+# From Paul Eggert (1996-01-22):
+# Today's _Wall Street Journal_ (page 1) reports that Kiribati
+# ``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:
+# I wonder what happened in Kwajalein, where there was NO Friday,
+# 1993-08-20.  Thursday night at midnight Kwajalein switched sides with
+# 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
+# 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.
+
+# Micronesia
+
+# Alan Eugene Davis <adavis@kuentos.guam.net> writes (1996-03-16),
+# ``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;
+# ignore this for now.
+
+# Samoa
+
+# Howse writes 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.
diff --git a/zic.tproj/datfiles/backward b/zic.tproj/datfiles/backward
new file mode 100644 (file)
index 0000000..793d37b
--- /dev/null
@@ -0,0 +1,85 @@
+#      $OpenBSD: backward,v 1.4 1997/01/14 04:36:50 millert Exp $
+# @(#)backward 7.13
+
+# 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/Indianapolis    America/Fort_Wayne
+Link   America/Indiana/Knox    America/Knox_IN
+Link   America/St_Thomas       America/Virgin
+Link   Asia/Jerusalem          Asia/Tel_Aviv
+Link   Australia/Sydney        Australia/ACT
+Link   Australia/Sydney        Australia/Canberra
+Link   Australia/Lord_Howe     Australia/LHI
+Link   Australia/Sydney        Australia/NSW
+Link   Australia/Darwin        Australia/North
+Link   Australia/Brisbane      Australia/Queensland
+Link   Australia/Adelaide      Australia/South
+Link   Australia/Hobart        Australia/Tasmania
+Link   Australia/Melbourne     Australia/Victoria
+Link   Australia/Perth         Australia/West
+Link   Australia/Broken_Hill   Australia/Yancowinna
+Link   America/Porto_Acre      Brazil/Acre
+Link   America/Noronha         Brazil/DeNoronha
+Link   America/Sao_Paulo       Brazil/East
+Link   America/Manaus          Brazil/West
+Link   America/Halifax         Canada/Atlantic
+Link   America/Winnipeg        Canada/Central
+Link   America/Regina          Canada/East-Saskatchewan
+Link   America/Montreal        Canada/Eastern
+Link   America/Edmonton        Canada/Mountain
+Link   America/St_Johns        Canada/Newfoundland
+Link   America/Vancouver       Canada/Pacific
+Link   America/Regina          Canada/Saskatchewan
+Link   America/Whitehorse      Canada/Yukon
+Link   America/Santiago        Chile/Continental
+Link   Pacific/Easter          Chile/EasterIsland
+Link   America/Havana          Cuba
+Link   Africa/Cairo            Egypt
+Link   Europe/Dublin           Eire
+Link   Europe/London           GB
+Link   Etc/GMT                 GMT
+Link   Etc/GMT+0               GMT+0
+Link   Etc/GMT-0               GMT-0
+Link   Etc/GMT0                GMT0
+Link   Etc/Greenwich           Greenwich
+Link   Asia/Hong_Kong          Hongkong
+Link   Atlantic/Reykjavik      Iceland
+Link   Asia/Tehran             Iran
+Link   Asia/Jerusalem          Israel
+Link   America/Jamaica         Jamaica
+Link   Asia/Tokyo              Japan
+Link   Pacific/Kwajalein       Kwajalein
+Link   Africa/Tripoli          Libya
+Link   America/Tijuana         Mexico/BajaNorte
+Link   America/Mazatlan        Mexico/BajaSur
+Link   America/Mexico_City     Mexico/General
+Link   America/Denver          Navajo
+Link   Pacific/Auckland        NZ
+Link   Pacific/Chatham         NZ-CHAT
+Link   Pacific/Pago_Pago       Pacific/Samoa
+Link   Asia/Shanghai           PRC
+Link   Europe/Warsaw           Poland
+Link   Europe/Lisbon           Portugal
+Link   Asia/Taipei             ROC
+Link   Asia/Seoul              ROK
+Link   Asia/Singapore          Singapore
+Link   Europe/Istanbul         Turkey
+Link   Etc/UCT                 UCT
+Link   America/Anchorage       US/Alaska
+Link   America/Adak            US/Aleutian
+Link   America/Phoenix         US/Arizona
+Link   America/Chicago         US/Central
+Link   America/Indianapolis    US/East-Indiana
+Link   America/New_York        US/Eastern
+Link   Pacific/Honolulu        US/Hawaii
+Link   America/Indiana/Knox    US/Indiana-Starke
+Link   America/Detroit         US/Michigan
+Link   America/Denver          US/Mountain
+Link   America/Los_Angeles     US/Pacific
+Link   Pacific/Pago_Pago       US/Samoa
+Link   Etc/UTC                 UTC
+Link   Etc/Universal           Universal
+Link   Europe/Moscow           W-SU
+Link   Etc/Zulu                Zulu
diff --git a/zic.tproj/datfiles/etcetera b/zic.tproj/datfiles/etcetera
new file mode 100644 (file)
index 0000000..8786abe
--- /dev/null
@@ -0,0 +1,60 @@
+#      $OpenBSD: etcetera,v 1.3 1997/01/14 04:36:51 millert Exp $
+# @(#)etcetera 7.6
+
+# These entries are mostly present for historical reasons, so that
+# people in areas not otherwise covered by the tz files could "zic -l"
+# to a time zone that was right for their area.  These days, the
+# tz files cover almost all the inhabited world, so there's little
+# need now for the entries that are not on UTC.
+
+Zone   Etc/GMT         0       -       GMT
+Zone   Etc/UTC         0       -       UTC
+Zone   Etc/UCT         0       -       UCT
+
+Link   Etc/UTC                         Etc/Universal
+Link   Etc/UTC                         Etc/Zulu
+
+Link   Etc/GMT                         Etc/Greenwich
+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.
+
+# Earlier incarnations of this package were not POSIX-compliant,
+# and had lines such as
+#              Zone    GMT-12          -12     -       GMT-1200
+# We did not want things to change quietly if someone accustomed to the old
+# way does a
+#              zic -l GMT-12
+# so we moved the names into the Etc subdirectory.
+
+Zone   Etc/GMT-14      14      -       GMT-14  # 14 hours ahead of GMT
+Zone   Etc/GMT-13      13      -       GMT-13
+Zone   Etc/GMT-12      12      -       GMT-12
+Zone   Etc/GMT-11      11      -       GMT-11
+Zone   Etc/GMT-10      10      -       GMT-10
+Zone   Etc/GMT-9       9       -       GMT-9
+Zone   Etc/GMT-8       8       -       GMT-8
+Zone   Etc/GMT-7       7       -       GMT-7
+Zone   Etc/GMT-6       6       -       GMT-6
+Zone   Etc/GMT-5       5       -       GMT-5
+Zone   Etc/GMT-4       4       -       GMT-4
+Zone   Etc/GMT-3       3       -       GMT-3
+Zone   Etc/GMT-2       2       -       GMT-2
+Zone   Etc/GMT-1       1       -       GMT-1
+Zone   Etc/GMT+1       -1      -       GMT+1
+Zone   Etc/GMT+2       -2      -       GMT+2
+Zone   Etc/GMT+3       -3      -       GMT+3
+Zone   Etc/GMT+4       -4      -       GMT+4
+Zone   Etc/GMT+5       -5      -       GMT+5
+Zone   Etc/GMT+6       -6      -       GMT+6
+Zone   Etc/GMT+7       -7      -       GMT+7
+Zone   Etc/GMT+8       -8      -       GMT+8
+Zone   Etc/GMT+9       -9      -       GMT+9
+Zone   Etc/GMT+10      -10     -       GMT+10
+Zone   Etc/GMT+11      -11     -       GMT+11
+Zone   Etc/GMT+12      -12     -       GMT+12
diff --git a/zic.tproj/datfiles/europe b/zic.tproj/datfiles/europe
new file mode 100644 (file)
index 0000000..ac1aec1
--- /dev/null
@@ -0,0 +1,2289 @@
+#      $OpenBSD: europe,v 1.5 1997/01/14 04:36:52 millert Exp $
+# @(#)europe   7.42
+
+# 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):
+# 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).
+#
+# Gwillim Law <LAW@encmail.encompass.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.
+#
+# 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.
+#
+# I invented the abbreviations marked `*' in the following table;
+# the rest are from earlier versions of this file, or from other sources.
+# Corrections are welcome!
+#              std dst
+#              LMT     Local Mean Time
+#      -4:00   AST     Atlantic
+#      -3:00   WGT WGST Western Greenland*
+#      -1:00   EGT EGST Eastern Greenland*
+#       0:00   GMT BST Greenwich, British Summer
+#       0:00   GMT IST Greenwich, Irish Summer
+#       0:00   WET WEST Western Europe
+#       1:00   CET CEST Central Europe
+#       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).
+
+# From Peter Ilieve <peter@memex.co.uk> (1994-12-04),
+# The original six [EU members]: Belgium, France, (West) Germany, Italy,
+# Luxembourg, the Netherlands.
+# Plus, from 1 Jan 73: Denmark, Ireland, United Kingdom.
+# Plus, from 1 Jan 81: Greece.
+# Plus, from 1 Jan 86: Spain, Portugal.
+# Plus, from 1 Jan 95: Austria, Finland, Sweden. (Norway negotiated terms for
+# entry but in a referendum on 28 Nov 94 the people voted No by 52.2% to 47.8%
+# on a turnout of 88.6%. This was almost the same result as Norway's previous
+# referendum in 1972, they are the only country to have said No twice.
+# Referendums in the other three countries voted Yes.)
+# ...
+# Estonia ... uses EU dates but not at 01:00 GMT, they use midnight GMT.
+# I don't think they know yet what they will do from 1996 onwards.
+# ...
+# There shouldn't be any [current members who are not using EU rules].
+# A Directive has the force of law, member states are obliged to enact
+# national law to implement it. The only contentious issue was the
+# different end date for the UK and Ireland, and this was always allowed
+# in the Directive.
+
+
+###############################################################################
+
+# United Kingdom
+# The UK and its colonies adopted the Gregorian calendar on 1752-09-14.
+
+# From Peter Ilieve <peter@memex.co.uk> (1994-07-06):
+#
+# On 17 Jan 1994 the Independent, a UK quality newspaper, had a piece about
+# historical vistas along the Thames in west London. There was a photo
+# and a sketch map showing some of the sightlines involved. One paragraph
+# of the text said:
+#
+# `An old stone obelisk marking a forgotten terrestrial meridian stands
+# beside the river at Kew. In the 18th century, before time and longitude
+# was standardised by the Royal Observatory in Greenwich, scholars observed
+# this stone and the movement of stars from Kew Observatory nearby. They
+# made their calculations and set the time for the Horse Guards and Parliament,
+# but now the stone is obscured by scrubwood and can only be seen by walking
+# along the towpath within a few yards of it.'
+#
+# I have a one inch to one mile map of London and my estimate of the stone's
+# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
+# be within about +-2". The Ordnance Survey grid reference is TQ172761.
+#
+# [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
+
+# From Paul Eggert <eggert@twinsun.com> (1993-11-18):
+#
+# 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 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
+# Railway Clearing House, an industry standards body, recommended that GMT be
+# adopted at all stations; the January 1848 Bradshaw's lists most major
+# 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,
+# 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.
+#
+# 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.
+
+# From Paul Eggert (1996-06-12):
+# Summer Time was first seriously proposed by William Willett (1857-1915),
+# a London builder who circulated a pamphlet ``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.
+
+# From Paul Eggert (1996-09-03):
+# The OED Supplement says that the English originally said ``Daylight Saving''
+# when they were debating the adoption of DST in 1908; but by 1916 this
+# term appears only in quotes taken from DST's opponents, whereas the
+# proponents (who eventually won the argument) are quoted as using ``Summer''.
+
+# From Arthur David Olson (1989-01-19):
+#
+# A source at the British Information Office in New York avers that it's
+# known as "British" Summer Time in all parts of the United Kingdom.
+
+# Date: 4 Jan 89 08:57:25 GMT (Wed)
+# From: Jonathan Leffler <nih-csl!uunet!mcvax!sphinx.co.uk!john>
+# [British Summer Time] is fixed annually by Act of Parliament.
+# 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
+#      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.
+# 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.
+#     * Jersey, Guernsey, and the Isle of Man did not switch from GMT
+#      to daylight savings time until 1921 Apr 3, when they began to
+#      conform with Great Britain.
+#     * 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 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.
+# Under this directive, the Minister for Justice in Ireland makes appropriate
+# regulations. I spoke this morning with the Secretary of the Department of
+# Justice (tel +353 1 678 9711) who confirmed to me that the correct name is
+# "Irish Summer Time", abbreviated to "IST".
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# 1916 to 1925--irregular
+Rule   GB-Eire 1916    only    -       May     21      2:00s   1:00    BST
+Rule   GB-Eire 1916    only    -       Oct      1      2:00s   0       GMT
+Rule   GB-Eire 1917    only    -       Apr      8      2:00s   1:00    BST
+Rule   GB-Eire 1917    only    -       Sep     17      2:00s   0       GMT
+Rule   GB-Eire 1918    only    -       Mar     24      2:00s   1:00    BST
+Rule   GB-Eire 1918    only    -       Sep     30      2:00s   0       GMT
+Rule   GB-Eire 1919    only    -       Mar     30      2:00s   1:00    BST
+Rule   GB-Eire 1919    only    -       Sep     29      2:00s   0       GMT
+Rule   GB-Eire 1920    only    -       Mar     28      2:00s   1:00    BST
+Rule   GB-Eire 1920    only    -       Oct     25      2:00s   0       GMT
+Rule   GB-Eire 1921    only    -       Apr      3      2:00s   1:00    BST
+Rule   GB-Eire 1921    only    -       Oct      3      2:00s   0       GMT
+Rule   GB-Eire 1922    only    -       Mar     26      2:00s   1:00    BST
+Rule   GB-Eire 1922    only    -       Oct      8      2:00s   0       GMT
+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 1925    1926    -       Apr     Sun>=16 2:00s   1:00    BST
+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 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 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 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 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 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
+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
+Rule   GB-Eire 1942    1944    -       Apr     Sun>=2  1:00s   2:00    BDST
+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
+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.
+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 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 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
+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 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 1961    1963    -       Mar     lastSun 2:00s   1:00    BST
+Rule   GB-Eire 1964    1967    -       Mar     Sun>=19 2:00s   1:00    BST
+Rule   GB-Eire 1968    only    -       Feb     18      2:00s   1:00    BST
+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
+Rule   GB-Eire 1981    1995    -       Mar     lastSun 1:00u   1:00    BST
+Rule   GB-Eire 1981    1989    -       Oct     Sun>=23 1:00u   0       GMT
+Rule   GB-Eire 1990    1995    -       Oct     Sun>=22 1:00u   0       GMT
+# See EU for rules starting in 1996.
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/London   -0:01:15 -      LMT     1847 Sep 22
+                        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: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: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
+                        0:00   -       GMT     1947 Mar 16 2:00
+                        0:00   1:00    IST     1947 Nov  2 2:00
+                        0:00   -       GMT     1948 Apr 18 2:00
+                        0:00   GB-Eire GMT/IST 1968 Oct 27
+                        1:00   -       IST     1971 Oct 31 2:00u
+                        0:00   GB-Eire GMT/IST 1996
+                        0:00   EU      GMT/IST
+
+###############################################################################
+
+# Continental Europe
+
+# EU rules are for the European Union, previously known as the EC, EEC,
+# Common Market, etc.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   EU      1977    1980    -       Apr     Sun>=1   1:00u  1:00    S
+Rule   EU      1977    only    -       Sep     lastSun  1:00u  0       -
+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       -
+
+# 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
+Rule   W-Eur   1977    only    -       Sep     lastSun  1:00s  0       -
+Rule   W-Eur   1978    only    -       Oct      1       1:00s  0       -
+Rule   W-Eur   1979    1995    -       Sep     lastSun  1:00s  0       -
+Rule   W-Eur   1981    max     -       Mar     lastSun  1:00s  1:00    S
+Rule   W-Eur   1996    max     -       Oct     lastSun  1:00s  0       -
+
+# Older C-Eur rules are for convenience in the tables.
+# From 1977 on, C-Eur differs from EU only in that C-Eur uses standard time.
+Rule   C-Eur   1916    only    -       Apr     30      23:00   1:00    S
+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       -
+Rule   C-Eur   1944    only    -       Apr      3       2:00s  1:00    S
+# Whitman gives 1944 Oct 7; go with Shanks.
+Rule   C-Eur   1944    only    -       Oct      2       2:00s  0       -
+Rule   C-Eur   1977    1980    -       Apr     Sun>=1   2:00s  1:00    S
+Rule   C-Eur   1977    only    -       Sep     lastSun  2:00s  0       -
+Rule   C-Eur   1978    only    -       Oct      1       2:00s  0       -
+Rule   C-Eur   1979    1995    -       Sep     lastSun  2:00s  0       -
+Rule   C-Eur   1981    max     -       Mar     lastSun  2:00s  1:00    S
+Rule   C-Eur   1996    max     -       Oct     lastSun  2:00s  0       -
+
+# E-Eur differs from EU only in that E-Eur switches at midnight local time.
+Rule   E-Eur   1977    1980    -       Apr     Sun>=1   0:00   1:00    S
+Rule   E-Eur   1977    only    -       Sep     lastSun  0:00   0       -
+Rule   E-Eur   1978    only    -       Oct      1       0:00   0       -
+Rule   E-Eur   1979    1995    -       Sep     lastSun  0:00   0       -
+Rule   E-Eur   1981    max     -       Mar     lastSun  0:00   1:00    S
+Rule   E-Eur   1996    max     -       Oct     lastSun  0:00   0       -
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+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  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    -       Sep      1       0:00   1:00    S
+Rule   Russia  1921    only    -       Oct      1       0:00   0       -
+Rule   Russia  1981    1984    -       Apr      1       0:00   1:00    S
+Rule   Russia  1981    1983    -       Oct      1       0:00   0       -
+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
+Rule   Russia  1993    1995    -       Sep     lastSun  2:00s  0       -
+Rule   Russia  1996    max     -       Oct     lastSun  2:00s  0       -
+
+# These are for backward compatibility with older versions.
+
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   WET             0:00    EU      WE%sT
+Zone   CET             1:00    C-Eur   CE%sT
+Zone   MET             1:00    C-Eur   ME%sT
+Zone   EET             2:00    EU      EE%sT
+
+# Previous editions of this database used abbreviations like MET DST
+# for Central European Summer Time, but this didn't agree with common usage.
+
+# From Markus Kuhn <mskuhn@unrza3.dialin.rrze.uni-erlangen.de> (1996-07-12):
+# The official German names ... are
+#
+#      Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
+#      Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
+#
+# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
+# 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
+# I wrote ... to the German Federal Physical-Technical Institution
+#
+#      Physikalisch-Technische Bundesanstalt (PTB)
+#      Laboratorium 4.41 "Zeiteinheit"
+#      Postfach 3345
+#      D-38023 Braunschweig
+#      phone: +49 531 592-0
+#
+# ... I received today an answer letter from Dr. Peter Hetzel, head of the PTB
+# department for time and frequency transmission.  He explained that the
+# PTB translates MEZ and MESZ into English as
+#
+#      Central European Time (CET)         = UTC+01:00
+#      Central European Summer Time (CEST) = UTC+02:00
+
+
+# Albania
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Albania 1940    only    -       Jun     16      0:00    1:00    S
+Rule   Albania 1942    only    -       Nov      2      3:00    0       -
+Rule   Albania 1943    only    -       Mar     29      2:00    1:00    S
+Rule   Albania 1943    only    -       Apr     10      3:00    0       -
+Rule   Albania 1974    only    -       May      4      0:00    1:00    S
+Rule   Albania 1974    only    -       Oct      2      0:00    0       -
+Rule   Albania 1975    only    -       May      1      0:00    1:00    S
+Rule   Albania 1975    only    -       Oct      2      0:00    0       -
+Rule   Albania 1976    only    -       May      2      0:00    1:00    S
+Rule   Albania 1976    only    -       Oct      3      0:00    0       -
+Rule   Albania 1977    only    -       May      8      0:00    1:00    S
+Rule   Albania 1977    only    -       Oct      2      0:00    0       -
+Rule   Albania 1978    only    -       May      6      0:00    1:00    S
+Rule   Albania 1978    only    -       Oct      1      0:00    0       -
+Rule   Albania 1979    only    -       May      5      0:00    1:00    S
+Rule   Albania 1979    only    -       Sep     30      0:00    0       -
+Rule   Albania 1980    only    -       May      3      0:00    1:00    S
+Rule   Albania 1980    only    -       Oct      4      0:00    0       -
+Rule   Albania 1981    only    -       Apr     26      0:00    1:00    S
+Rule   Albania 1981    only    -       Sep     27      0:00    0       -
+Rule   Albania 1982    only    -       May      2      0:00    1:00    S
+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    EU      CE%sT
+
+# Andorra
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Andorra  0:06:04 -       LMT     1901
+                       0:00    -       WET     1946 Sep 30
+                       1:00    -       CET     1985 Mar 31 2:00
+                       1:00    EU      CE%sT
+
+# Austria
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Austria 1920    only    -       Apr      5      2:00s   1:00    S
+Rule   Austria 1920    only    -       Sep     13      2:00s   0       -
+Rule   Austria 1945    only    -       Apr      2      2:00s   1:00    S
+Rule   Austria 1945    only    -       Nov     18      2:00s   0       -
+Rule   Austria 1946    only    -       Apr     14      2:00s   1:00    S
+Rule   Austria 1946    1948    -       Oct     Sun>=1  2:00s   0       -
+Rule   Austria 1947    only    -       Apr      6      2:00s   1:00    S
+Rule   Austria 1948    only    -       Apr     18      2:00s   1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Vienna   1:05:20 -       LMT     1893 Apr
+                       1:00    C-Eur   CE%sT   1918 Jun 16 3:00
+                       1:00    Austria CE%sT   1940 Apr  1 2:00
+                       1:00    C-Eur   CE%sT   1945 Apr  2 2:00
+                       1:00    Austria CE%sT   1981
+                       1:00    EU      CE%sT
+
+# 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
+                       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 Mar 29 0:00
+                       2:00    1:00    EEST    1992 Sep 27 0:00
+                       2:00    Russia  EE%sT
+
+# Belgium
+# Whitman and Shanks disagree; go with Shanks, usually.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# From Whitman:
+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    -       Oct     23      23:00s  0       -
+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 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
+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 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 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 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
+                       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
+
+# Bulgaria
+# 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       -
+Rule   Bulg    1980    1982    -       Apr     Sat<=7  23:00   1:00    S
+Rule   Bulg    1980    only    -       Sep     29       1:00   0       -
+Rule   Bulg    1981    only    -       Sep     27       2:00   0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Sofia    1:33:16 -       LMT     1880
+                       1:56:56 -       IMT     1894 Nov 30 # Istanbul MT?
+                       2:00    -       EET     1942 Nov  2  3:00
+                       1:00    C-Eur   CE%sT   1945 Apr  2  3:00
+                       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
+
+# 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
+
+# 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       -
+Rule   Czech   1946    only    -       May      6      2:00s   1:00    S
+Rule   Czech   1946    1949    -       Oct     Sun>=1  2:00s   0       -
+Rule   Czech   1947    only    -       Apr     20      2:00s   1:00    S
+Rule   Czech   1948    only    -       Apr     18      2:00s   1:00    S
+Rule   Czech   1949    only    -       Apr      9      2:00s   1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Prague   0:57:44 -       LMT     1850
+                       0:57:44 -       PMT     1891 Oct     # Prague Mean Time
+                       1:00    C-Eur   CE%sT   1944 Sep 17 2:00s
+                       1:00    Czech   CE%sT   1979
+                       1:00    EU      CE%sT
+
+# Denmark
+# Gregorian calendar adopted 1700-03-01.
+# 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       -
+Rule   Denmark 1940    only    -       May     15       0:00   1:00    S
+Rule   Denmark 1945    only    -       Apr      2       2:00s  1:00    S
+Rule   Denmark 1945    only    -       Aug     15       2:00s  0       -
+Rule   Denmark 1946    only    -       May      1       2:00s  1:00    S
+Rule   Denmark 1946    only    -       Sep      1       2:00s  0       -
+Rule   Denmark 1947    only    -       May      4       2:00s  1:00    S
+Rule   Denmark 1947    only    -       Aug     10       2:00s  0       -
+Rule   Denmark 1948    only    -       May      9       2:00s  1:00    S
+Rule   Denmark 1948    only    -       Aug      8       2:00s  0       -
+# Whitman also gives 1949 Apr 9 to 1949 Oct 1, and disagrees in minor ways
+# about many of the above dates; go with Shanks.
+#
+# For 1894, Shanks says Jan, Whitman Apr; go with Whitman.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Europe/Copenhagen  0:50:20 -      LMT     1890
+                        0:50:20 -      CMT     1894 Apr  # Copenhagen Mean Time
+                        1:00   Denmark CE%sT   1942 Nov  2 2:00s
+                        1:00   C-Eur   CE%sT   1945 Apr  2 2:00
+                        1:00   Denmark CE%sT   1980
+                        1:00   EU      CE%sT
+Zone Atlantic/Faeroe   -0:27:04 -      LMT     1908 Jan 11     # Torshavn
+                        0:00   -       WET     1981
+                        0:00   EU      WE%sT
+#
+# From Paul Eggert (1996-11-22):
+# Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
+# and left the EU on 1985-02-01.  It therefore should have been using EU
+# rules at least through 1984.  Shanks says Scoresbysund and Godthab
+# used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
+# rules since at least 1991.  Assume EU rules since 1980.
+
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+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
+                       -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
+                       -4:00   Thule   A%sT
+
+# Estonia
+# From Peter Ilieve <peter@memex.co.uk> (1994-10-15):
+# A relative in Tallinn confirms the accuracy of the data for 1989 onwards
+# [through 1994] and gives the legal authority for it,
+# a regulation of the Government of Estonia, No. 111 of 1989....
+#
+# From Peter Ilieve <peter@aldie.co.uk> (1996-10-28):
+# [IATA SSIM (1992/1996) claims that the Baltic republics switch at 01:00s,
+# but a relative confirms that Estonia still switches at 02:00s, writing:]
+# ``I do not [know] exactly but there are some little different
+# (confusing) rules for International Air and Railway Transport Schedules
+# conversion in Sunday connected with end of summer time in Estonia....
+# 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.''
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Tallinn  1:39:00 -       LMT     1880
+                       1:39:00 -       TMT     1918 Feb # Tallinn Mean Time
+                       1:00    C-Eur   CE%sT   1919 Jul
+                       1:39:00 -       TMT     1921 May
+                       2:00    -       EET     1940 Aug  6
+                       3:00    -       MSK     1941 Sep 15
+                       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
+
+# 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,
+# and it's supposed to change at 4am...
+#
+# From Paul Eggert <eggert@twinsun.com> (25 Sep 1994):
+# Shanks says Finland has switched at 02:00 standard time since 1981.
+# Go with Strang instead.
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Finland 1942    only    -       Apr     3       0:00    1:00    S
+Rule   Finland 1942    only    -       Oct     3       0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Helsinki 1:39:52 -       LMT     1878 May 31
+                       1:39:52 -       HMT     1921 May    # Helsinki Mean Time
+                       2:00    Finland EE%sT   1981 Mar 29 2:00
+                       2:00    EU      EE%sT
+
+# France
+# Gregorian calendar adopted 1582-12-20.
+# French Revolutionary calendar used 1792-09-22 - 1805-12-31.
+#
+# 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  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
+Rule   France  1920    only    -       Feb     14      23:00s  1:00    S
+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
+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
+Rule   France  1925    only    -       Apr      4      23:00s  1:00    S
+Rule   France  1926    only    -       Apr     17      23:00s  1:00    S
+Rule   France  1927    only    -       Apr      9      23:00s  1:00    S
+Rule   France  1928    only    -       Apr     14      23:00s  1:00    S
+Rule   France  1929    only    -       Apr     20      23:00s  1:00    S
+Rule   France  1930    only    -       Apr     12      23:00s  1:00    S
+Rule   France  1931    only    -       Apr     18      23:00s  1:00    S
+Rule   France  1932    only    -       Apr      2      23:00s  1:00    S
+Rule   France  1933    only    -       Mar     25      23:00s  1:00    S
+Rule   France  1934    only    -       Apr      7      23:00s  1:00    S
+Rule   France  1935    only    -       Mar     30      23:00s  1:00    S
+Rule   France  1936    only    -       Apr     18      23:00s  1:00    S
+Rule   France  1937    only    -       Apr      3      23:00s  1:00    S
+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
+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  1944    only    -       Oct      8       1:00   1:00    S
+Rule   France  1945    only    -       Apr      2       2:00   2:00    DS
+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 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
+                       1:00    C-Eur   CE%sT   1944 Aug 25
+                       0:00    France  WE%sT   1945 Sep 16 3:00
+                       1:00    France  CE%sT   1977
+                       1:00    EU      CE%sT
+
+# Germany
+
+# 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
+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 1947    only    -       Apr      6      2:00s   1:00    S
+Rule   Germany 1947    only    -       May     11      2:00s   2:00    DS
+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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Berlin   0:53:28 -       LMT     1893 Apr
+                       1:00    C-Eur   CE%sT   1945 Apr 2 2:00
+                       1:00    Germany CE%sT   1980
+                       1:00    EU      CE%sT
+
+# Gibraltar
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Europe/Gibraltar  -0:21:24 -      LMT     1880 Aug  2
+                       0:00    GB-Eire %s      1957 Apr 14 2:00
+                       1:00    -       CET     1982
+                       1:00    EU      CE%sT
+
+# Greece
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# Whitman gives 1932 Jul 5 - Nov 1; go with Shanks.
+Rule   Greece  1932    only    -       Jul      7      0:00    1:00    S
+Rule   Greece  1932    only    -       Sep      1      0:00    0       -
+# Whitman gives 1941 Apr 25 - ?; go with Shanks.
+Rule   Greece  1941    only    -       Apr      7      0:00    1:00    S
+# Whitman gives 1942 Feb 2 - ?; go with Shanks.
+Rule   Greece  1942    only    -       Nov      2      3:00    0       -
+Rule   Greece  1943    only    -       Mar     30      0:00    1:00    S
+Rule   Greece  1943    only    -       Oct      4      0:00    0       -
+# Whitman gives 1944 Oct 3 - Oct 31; go with Shanks.
+Rule   Greece  1952    only    -       Jul      1      0:00    1:00    S
+Rule   Greece  1952    only    -       Nov      2      0:00    0       -
+Rule   Greece  1975    only    -       Apr     12      0:00s   1:00    S
+Rule   Greece  1975    only    -       Nov     26      0:00s   0       -
+Rule   Greece  1976    only    -       Apr     11      2:00s   1:00    S
+Rule   Greece  1976    only    -       Oct     10      2:00s   0       -
+Rule   Greece  1977    1978    -       Apr     Sun>=1  2:00s   1:00    S
+Rule   Greece  1977    only    -       Sep     26      2:00s   0       -
+Rule   Greece  1978    only    -       Sep     24      4:00    0       -
+Rule   Greece  1979    only    -       Apr      1      9:00    1:00    S
+Rule   Greece  1979    only    -       Sep     29      2:00    0       -
+Rule   Greece  1980    only    -       Apr      1      0:00    1:00    S
+Rule   Greece  1980    only    -       Sep     28      0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Athens   1:34:52 -       LMT     1895 Sep 14
+                       1:34:52 -       AMT     1916 Jul 28 0:01     # Athens MT
+                       2:00    Greece  EE%sT   1941 Apr 30
+                       1:00    Greece  CE%sT   1944 Apr  4
+                       2:00    Greece  EE%sT   1981
+                       # Shanks says they switched to C-Eur in 1981;
+                       # go with EU instead, since Greece joined it on Jan 1.
+                       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       -
+Rule   Hungary 1919    only    -       Apr     15       3:00   1:00    S
+Rule   Hungary 1919    only    -       Sep     15       3:00   0       -
+Rule   Hungary 1920    only    -       Apr      5       3:00   1:00    S
+Rule   Hungary 1920    only    -       Sep     30       3:00   0       -
+Rule   Hungary 1945    only    -       May      1      23:00   1:00    S
+Rule   Hungary 1945    only    -       Nov      3       0:00   0       -
+Rule   Hungary 1946    only    -       Mar     31       2:00s  1:00    S
+Rule   Hungary 1946    1949    -       Oct     Sun>=1   2:00s  0       -
+Rule   Hungary 1947    1949    -       Apr     Sun>=4   2:00s  1:00    S
+Rule   Hungary 1950    only    -       Apr     17       2:00s  1:00    S
+Rule   Hungary 1950    only    -       Oct     23       2:00s  0       -
+Rule   Hungary 1954    1955    -       May     23       0:00   1:00    S
+Rule   Hungary 1954    1955    -       Oct      3       0:00   0       -
+Rule   Hungary 1956    only    -       Jun     Sun>=1   0:00   1:00    S
+Rule   Hungary 1956    only    -       Sep     lastSun  0:00   0       -
+Rule   Hungary 1957    only    -       Jun     Sun>=1   1:00   1:00    S
+Rule   Hungary 1957    only    -       Sep     lastSun  3:00   0       -
+Rule   Hungary 1980    only    -       Apr      6       1:00   1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Budapest 1:16:20 -       LMT     1890 Oct
+                       1:00    C-Eur   CE%sT   1918
+                       1:00    Hungary CE%sT   1941 Apr  6  2:00
+                       1:00    C-Eur   CE%sT   1945 May  1 23:00
+                       1:00    Hungary CE%sT   1980 Sep 28  2:00s
+                       1:00    EU      CE%sT
+
+# Iceland
+#
+# From Adam David <adam@veda.is> (1993-11-06):
+# The name of the timezone in Iceland for system / mail / news purposes is GMT.
+#
+# (1993-12-05):
+# This material is paraphrased from the 1988 edition of the University of
+# Iceland Almanak.
+#
+# From January 1st, 1908 the whole of Iceland was standardised at 1 hour
+# behind GMT. Previously, local mean solar time was used in different parts
+# of Iceland, the almanak had been based on Reykjavik mean solar time which
+# was 1 hour and 28 minutes behind GMT.
+#
+# "first day of winter" referred to [below] means the first day of the 26 weeks
+# of winter, according to the old icelandic calendar that dates back to the
+# time the norsemen first settled Iceland.  The first day of winter is always
+# Saturday, but is not dependent on the Julian or Gregorian calendars.
+#
+# (1993-12-10):
+# I have a reference from the Oxford Icelandic-English dictionary for the
+# beginning of winter, which ties it to the ecclesiastical calendar (and thus
+# to the julian/gregorian calendar) over the period in question.
+#      the winter begins on the Saturday next before St. Luke's day
+#      (old style), or on St. Luke's day, if a Saturday.
+# St. Luke's day ought to be traceable from ecclesiastical sources. "old style"
+# 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):
+# 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.
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Iceland 1917    1918    -       Feb     19      23:00   1:00    S
+Rule   Iceland 1917    only    -       Oct     21       1:00   0       -
+Rule   Iceland 1918    only    -       Nov     16       1:00   0       -
+Rule   Iceland 1939    only    -       Apr     29      23:00   1:00    S
+Rule   Iceland 1939    only    -       Nov     29       2:00   0       -
+Rule   Iceland 1940    only    -       Feb     25       2:00   1:00    S
+Rule   Iceland 1940    only    -       Nov      3       2:00   0       -
+Rule   Iceland 1941    only    -       Mar      2       1:00s  1:00    S
+Rule   Iceland 1941    only    -       Nov      2       1:00s  0       -
+Rule   Iceland 1942    only    -       Mar      8       1:00s  1:00    S
+Rule   Iceland 1942    only    -       Oct     25       1:00s  0       -
+# 1943-1946 - first Sunday in March until first Sunday in winter
+Rule   Iceland 1943    1946    -       Mar     Sun>=1   1:00s  1:00    S
+Rule   Iceland 1943    1948    -       Oct     Sun>=22  1:00s  0       -
+# 1947-1967 - first Sunday in April until first Sunday in winter
+Rule   Iceland 1947    1967    -       Apr     Sun>=1   1:00s  1:00    S
+# 1949 Oct transition delayed by 1 week
+Rule   Iceland 1949    only    -       Oct     30       1:00s  0       -
+Rule   Iceland 1950    1966    -       Oct     Sun>=22  1:00s  0       -
+Rule   Iceland 1967    only    -       Oct     29       1:00s  0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Atlantic/Reykjavik        -1:27:24 -      LMT     1837
+                       -1:27:48 -      RMT     1908 # Reykjavik Mean Time?
+                       -1:00   Iceland IS%sT   1968 Apr 7 1:00s
+                        0:00   -       GMT
+
+# Italy
+# Gregorian calendar adopted 1582-10-15.
+#
+# 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:
+#
+# year FP      Shanks (S)      Whitman (W)     Go with:
+# 1916 06-03   06-03 24:00     06-03 00:00     FP & W
+#      09-30   09-30 24:00     09-30 01:00     FP; guess 24:00s
+# 1917 04-01   03-31 24:00     03-31 00:00     FP & S
+#      09-30   09-29 24:00     09-30 01:00     FP & W
+# 1918 03-09   03-09 24:00     03-09 00:00     FP & S
+#      10-06   10-05 24:00     10-06 01:00     FP & W
+# 1919 03-01   03-01 24:00     03-01 00:00     FP & S
+#      10-04   10-04 24:00     10-04 01:00     FP; guess 24:00s
+# 1920 03-20   03-20 24:00     03-20 00:00     FP & S
+#      09-18   09-18 24:00     10-01 01:00     FP; guess 24:00s
+# 1944 04-02   04-03 02:00                     S (see C-Eur)
+#      09-16   10-02 03:00                     FP; guess 24:00s
+# 1945 09-14   09-16 24:00                     FP; guess 24:00s
+# 1970 05-21   05-31 00:00                     S
+#      09-20   09-27 00:00                     S
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Italy   1916    only    -       Jun      3      0:00s   1:00    S
+Rule   Italy   1916    only    -       Oct      1      0:00s   0       -
+Rule   Italy   1917    only    -       Apr      1      0:00s   1:00    S
+Rule   Italy   1917    only    -       Sep     30      0:00s   0       -
+Rule   Italy   1918    only    -       Mar     10      0:00s   1:00    S
+Rule   Italy   1918    1919    -       Oct     Sun>=1  0:00s   0       -
+Rule   Italy   1919    only    -       Mar      2      0:00s   1:00    S
+Rule   Italy   1920    only    -       Mar     21      0:00s   1:00    S
+Rule   Italy   1920    only    -       Sep     19      0:00s   0       -
+Rule   Italy   1940    only    -       Jun     15      0:00s   1:00    S
+Rule   Italy   1944    only    -       Sep     17      0:00s   0       -
+Rule   Italy   1945    only    -       Apr      2      2:00    1:00    S
+Rule   Italy   1945    only    -       Sep     15      0:00s   0       -
+Rule   Italy   1946    only    -       Mar     17      2:00s   1:00    S
+Rule   Italy   1946    only    -       Oct      6      2:00s   0       -
+Rule   Italy   1947    only    -       Mar     16      0:00s   1:00    S
+Rule   Italy   1947    only    -       Oct      5      0:00s   0       -
+Rule   Italy   1948    only    -       Feb     29      2:00s   1:00    S
+Rule   Italy   1948    only    -       Oct      3      2:00s   0       -
+Rule   Italy   1966    1968    -       May     Sun>=22 0:00    1:00    S
+Rule   Italy   1966    1969    -       Sep     Sun>=22 0:00    0       -
+Rule   Italy   1969    only    -       Jun      1      0:00    1:00    S
+Rule   Italy   1970    only    -       May     31      0:00    1:00    S
+Rule   Italy   1970    only    -       Sep     lastSun 0:00    0       -
+Rule   Italy   1971    1972    -       May     Sun>=22 0:00    1:00    S
+Rule   Italy   1971    only    -       Sep     lastSun 1:00    0       -
+Rule   Italy   1972    only    -       Oct      1      0:00    0       -
+Rule   Italy   1973    only    -       Jun      3      0:00    1:00    S
+Rule   Italy   1973    1974    -       Sep     lastSun 0:00    0       -
+Rule   Italy   1974    only    -       May     26      0:00    1:00    S
+Rule   Italy   1975    only    -       Jun      1      0:00s   1:00    S
+Rule   Italy   1975    1977    -       Sep     lastSun 0:00s   0       -
+Rule   Italy   1976    only    -       May     30      0:00s   1:00    S
+Rule   Italy   1977    1979    -       May     Sun>=22 0:00s   1:00    S
+Rule   Italy   1978    only    -       Oct      1      0:00s   0       -
+Rule   Italy   1979    only    -       Sep     30      0:00s   0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Rome     0:49:56 -       LMT     1866 Sep 22
+                       0:49:56 -       RMT     1893 Nov        # Rome Mean Time
+                       1:00    Italy   CE%sT   1942 Nov  2 2:00s
+                       1:00    C-Eur   CE%sT   1944 Jul
+                       1:00    Italy   CE%sT   1980
+                       1:00    EU      CE%sT
+
+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.
+# 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       -
+# 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
+                       1:36:24 1:00    LST     1918 Sep 16 3:00 #Latvian Summer
+                       1:36:24 -       RMT     1919 Apr  1 2:00
+                       1:36:24 1:00    LST     1919 May 22 3:00
+                       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
+
+# Liechtenstein
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Vaduz    0:38:04 -       LMT     1894 Jun
+                       1:00    -       CET     1981
+                       1:00    EU      CE%sT
+
+# Lithuania
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Vilnius  1:41:16 -       LMT     1880
+                       1:24:00 -       WMT     1917        # Warsaw Mean Time
+                       1:35:36 -       KMT     1919 Oct 10 # Kaunas Mean Time
+                       1:00    -       CET     1920 Jul 12
+                       2:00    -       EET     1920 Oct  9
+                       1:00    -       CET     1940 Aug  3
+                       3:00    -       MSK     1941 Jun 24
+                       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.
+
+# Luxembourg
+# Whitman disagrees with most of these dates in minor ways; go with Shanks.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Lux     1916    only    -       May     14      23:00   1:00    S
+Rule   Lux     1916    only    -       Oct      1       1:00   0       -
+Rule   Lux     1917    only    -       Apr     28      23:00   1:00    S
+Rule   Lux     1917    only    -       Sep     17       1:00   0       -
+Rule   Lux     1918    only    -       Apr     Mon>=15  2:00s  1:00    S
+Rule   Lux     1918    only    -       Sep     Mon>=15  2:00s  0       -
+Rule   Lux     1919    only    -       Mar      1      23:00   1:00    S
+Rule   Lux     1919    only    -       Oct      5       3:00   0       -
+Rule   Lux     1920    only    -       Feb     14      23:00   1:00    S
+Rule   Lux     1920    only    -       Oct     24       2:00   0       -
+Rule   Lux     1921    only    -       Mar     14      23:00   1:00    S
+Rule   Lux     1921    only    -       Oct     26       2:00   0       -
+Rule   Lux     1922    only    -       Mar     25      23:00   1:00    S
+Rule   Lux     1922    only    -       Oct     Sun>=2   1:00   0       -
+Rule   Lux     1923    only    -       Apr     21      23:00   1:00    S
+Rule   Lux     1923    only    -       Oct     Sun>=2   2:00   0       -
+Rule   Lux     1924    only    -       Mar     29      23:00   1:00    S
+Rule   Lux     1924    1928    -       Oct     Sun>=2   1:00   0       -
+Rule   Lux     1925    only    -       Apr      5      23:00   1:00    S
+Rule   Lux     1926    only    -       Apr     17      23:00   1:00    S
+Rule   Lux     1927    only    -       Apr      9      23:00   1:00    S
+Rule   Lux     1928    only    -       Apr     14      23:00   1:00    S
+Rule   Lux     1929    only    -       Apr     20      23:00   1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Europe/Luxembourg 0:24:36 -       LMT     1904 Jun
+                       1:00    Lux     CE%sT   1918 Nov 25
+                       0:00    Lux     WE%sT   1929 Oct  6 2:00s
+                       0:00    Belgium WE%sT   1940 May 14 3:00
+                       1:00    C-Eur   WE%sT   1944 Sep 18 3:00
+                       1:00    Belgium CE%sT   1977
+                       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
+
+# Malta
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Malta   1973    only    -       Mar     31      0:00s   1:00    S
+Rule   Malta   1973    only    -       Sep     29      0:00s   0       -
+Rule   Malta   1974    only    -       Apr     21      0:00s   1:00    S
+Rule   Malta   1974    only    -       Sep     16      0:00s   0       -
+Rule   Malta   1975    1979    -       Apr     Sun>=15 2:00    1:00    S
+Rule   Malta   1975    1980    -       Sep     Sun>=15 2:00    0       -
+Rule   Malta   1980    only    -       Mar     31      2:00    1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Malta    0:58:04 -       LMT     1893 Nov  2     # Valletta
+                       1:00    Italy   CE%sT   1942 Nov  2 2:00s
+                       1:00    C-Eur   CE%sT   1945 Apr  2 2:00s
+                       1:00    Italy   CE%sT   1973 Mar 31
+                       1:00    Malta   CE%sT   1981
+                       1:00    EU      CE%sT
+
+# Moldova
+# 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
+
+# Monaco
+# Shanks gives 0:09 for Paris Mean Time; go with Howse's more precise 0:09:21.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Monaco   0:29:32 -       LMT     1891 Mar 15
+                       0:09:21 -       PMT     1911 Mar 11    # Paris Mean Time
+                       0:00    France  WE%sT   1945 Sep 16 3:00
+                       1:00    France  CE%sT   1977
+                       1:00    EU      CE%sT
+
+# Netherlands
+# Howse writes that the Netherlands' railways used GMT between 1892 and 1940,
+# but for other purposes the Netherlands used Amsterdam mean time.
+# 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    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    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    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.
+# 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
+                       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.
+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
+Rule   Norway  1959    1965    -       Sep     Sun>=15 2:00s   0       -
+Rule   Norway  1965    only    -       Apr     25      2:00s   1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Oslo     0:43:00 -       LMT     1895
+                       1:00    Norway  CE%sT   1940 Aug 10 23:00
+                       1:00    C-Eur   CE%sT   1945 Apr  2  2:00
+                       1:00    Norway  CE%sT   1980
+                       1:00    EU      CE%sT
+#
+# Svalbard
+Link   Europe/Oslo     Arctic/Longyearbyen
+#
+# Jan Mayen
+# From Whitman:
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Atlantic/Jan_Mayen        -1:00   -       EGT
+
+# Poland
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Poland  1918    1919    -       Sep     16      2:00s   0       -
+Rule   Poland  1919    only    -       Apr     15      2:00s   1:00    S
+# Whitman gives 1944 Nov 30; go with Shanks.
+Rule   Poland  1944    only    -       Oct      4      2:00    0       -
+# For 1944-1948 Whitman gives the previous day; go with Shanks.
+Rule   Poland  1945    only    -       Apr     29      0:00    1:00    S
+Rule   Poland  1945    only    -       Nov      1      0:00    0       -
+Rule   Poland  1946    only    -       Apr     14      0:00    1:00    S
+Rule   Poland  1946    only    -       Sep      7      0:00    0       -
+Rule   Poland  1947    only    -       May      4      0:00    1:00    S
+Rule   Poland  1947    1948    -       Oct     Sun>=1  0:00    0       -
+Rule   Poland  1948    only    -       Apr     18      0:00    1:00    S
+# Whitman also gives 1949 Apr 9 - 1949 Oct 1; go with Shanks.
+Rule   Poland  1957    only    -       Jun      2      1:00s   1:00    S
+Rule   Poland  1957    1958    -       Sep     lastSun 1:00s   0       -
+Rule   Poland  1958    only    -       Mar     30      1:00s   1:00    S
+Rule   Poland  1959    only    -       May     31      1:00s   1:00    S
+Rule   Poland  1959    1961    -       Oct     Sun>=1  1:00s   0       -
+Rule   Poland  1960    only    -       Apr      3      1:00s   1:00    S
+Rule   Poland  1961    1964    -       May     Sun>=25 1:00s   1:00    S
+Rule   Poland  1962    1964    -       Sep     lastSun 1:00s   0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Warsaw   1:24:00 -       LMT     1880
+                       1:24:00 -       WMT     1915 Aug  5   # Warsaw Mean Time
+                       1:00    C-Eur   CE%sT   1918 Sep 16 3:00
+                       2:00    Poland  EE%sT   1922 Jun
+                       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
+# 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.
+# Stick with W-Eur for now.
+
+# 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
+# (from WET to MET or CET) to harmonize with EEC.
+#
+# Martin Bruckmann <martin@ua.pt> (1996-02-29) reports via Peter Ilieve
+# that Portugal is reverting to 0:00 by not moving its clocks this spring.
+# The new Prime Minister was fed up with getting up in the dark in the winter.
+#
+# From Paul Eggert (1996-11-12):
+# IATA SSIM (1991-09) reports several 1991-09 and 1992-09 transitions
+# at 02:00u, not 01:00u.  Assume that these are typos.
+# IATA SSIM (1991/1992) reports that the Azores were at -1:00.
+# IATA SSIM (1993-02) says +0:00; later issues (through 1996-09) say -1:00.
+# Guess that the Azores changed to EU rules in 1992 (since that's when Portugal
+# harmonized with the EU), and that they stayed +0:00 that winter.
+#
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+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       -
+Rule   Port    1917    only    -       Feb     28      23:00s  1:00    S
+Rule   Port    1917    1921    -       Oct     14      23:00s  0       -
+Rule   Port    1918    only    -       Mar      1      23:00s  1:00    S
+Rule   Port    1919    only    -       Feb     28      23:00s  1:00    S
+Rule   Port    1920    only    -       Feb     29      23:00s  1:00    S
+Rule   Port    1921    only    -       Feb     28      23:00s  1:00    S
+Rule   Port    1924    only    -       Apr     16      23:00s  1:00    S
+Rule   Port    1924    only    -       Oct     14      23:00s  0       -
+Rule   Port    1926    only    -       Apr     17      23:00s  1:00    S
+Rule   Port    1926    1929    -       Oct     Sat>=1  23:00s  0       -
+Rule   Port    1927    only    -       Apr      9      23:00s  1:00    S
+Rule   Port    1928    only    -       Apr     14      23:00s  1:00    S
+Rule   Port    1929    only    -       Apr     20      23:00s  1:00    S
+Rule   Port    1931    only    -       Apr     18      23:00s  1:00    S
+# Whitman gives 1931 Oct 8; go with Shanks.
+Rule   Port    1931    1932    -       Oct     Sat>=1  23:00s  0       -
+Rule   Port    1932    only    -       Apr      2      23:00s  1:00    S
+# Shanks gives 1934 Apr 4; go with Whitman.
+Rule   Port    1934    only    -       Apr      7      23:00s  1:00    S
+# Whitman gives 1934 Oct 5; go with Shanks.
+Rule   Port    1934    1938    -       Oct     Sat>=1  23:00s  0       -
+# Shanks gives 1935 Apr 30; go with Whitman.
+Rule   Port    1935    only    -       Mar     30      23:00s  1:00    S
+Rule   Port    1936    only    -       Apr     18      23:00s  1:00    S
+# Whitman gives 1937 Apr 2; go with Shanks.
+Rule   Port    1937    only    -       Apr      3      23:00s  1:00    S
+Rule   Port    1938    only    -       Mar     26      23:00s  1:00    S
+Rule   Port    1939    only    -       Apr     15      23:00s  1:00    S
+# Whitman gives 1939 Oct 7; go with Shanks.
+Rule   Port    1939    only    -       Nov     18      23:00s  0       -
+Rule   Port    1940    only    -       Feb     24      23:00s  1:00    S
+# Shanks gives 1940 Oct 7; go with Whitman.
+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    -       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    1945    -       Aug     Sat>=25 22:00s  1:00    S
+Rule   Port    1944    1945    -       Apr     Sat>=21 22:00s  2:00    DS
+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
+Rule   Port    1947    1949    -       Oct     Sun>=1   2:00s  0       -
+# Shanks says DST was observed in 1950; go with Whitman.
+# Whitman gives Oct lastSun for 1952 on; go with Shanks.
+Rule   Port    1951    1965    -       Apr     Sun>=1   2:00s  1:00    S
+Rule   Port    1951    1965    -       Oct     Sun>=1   2:00s  0       -
+Rule   Port    1977    only    -       Mar     27       0:00s  1:00    S
+Rule   Port    1977    only    -       Sep     25       0:00s  0       -
+Rule   Port    1978    1979    -       Apr     Sun>=1   0:00s  1:00    S
+Rule   Port    1978    only    -       Oct      1       0:00s  0       -
+Rule   Port    1979    1982    -       Sep     lastSun  1:00s  0       -
+Rule   Port    1980    only    -       Mar     lastSun  0:00s  1:00    S
+Rule   Port    1981    1982    -       Mar     lastSun  1:00s  1:00    S
+Rule   Port    1983    only    -       Mar     lastSun  2:00s  1:00    S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Lisbon   -0:36:32 -      LMT     1884
+                       -0:36:32 -      LMT     1911 May 24   # Lisbon Mean Time
+                        0:00   Port    WE%sT   1966 Apr  3 2:00
+                        1:00   -       CET     1976 Sep 26 1:00
+                        0:00   Port    WE%sT   1983 Sep 25 1:00s
+                        0:00   W-Eur   WE%sT   1992 Sep 27 1:00s
+                        1:00   EU      CE%sT   1996 Mar 31 1:00u
+                        0:00   EU      WE%sT
+Zone Atlantic/Azores   -1:42:40 -      LMT     1884            # Ponta Delgada
+                       -1:55   -       HMT     1911 May 24  # Horta Mean Time
+                       -2:00   Port    AZO%sT  1966 Apr  3 2:00 # Azores Time
+                       -1:00   Port    AZO%sT  1983 Sep 25 1:00s
+                       -1:00   W-Eur   AZO%sT  1992 Sep 27 1:00s
+                        0:00   EU      WE%sT   1993 Mar 28 1:00u
+                       -1:00   EU      AZO%sT
+Zone Atlantic/Madeira  -1:07:36 -      LMT     1884            # Funchal
+                       -1:08   -       FMT     1911 May 24  # Funchal Mean Time
+                       -1:00   Port    MAD%sT  1966 Apr  3 2:00 # Madeira Time
+                        0:00   Port    WE%sT   1983 Sep 25 1:00s
+                        0:00   EU      WE%sT
+
+# Romania
+# 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       -
+Rule   Romania 1933    1939    -       Apr     Sun>=2   0:00s  1:00    S
+Rule   Romania 1979    only    -       May     27       0:00   1:00    S
+Rule   Romania 1979    only    -       Sep     lastSun  0:00   0       -
+Rule   Romania 1980    only    -       Apr      5      23:00   1:00    S
+Rule   Romania 1980    only    -       Sep     lastSun  1:00   0       -
+Rule   Romania 1991    1993    -       Mar     lastSun  0:00s  1:00    S
+Rule   Romania 1991    1993    -       Sep     lastSun  0:00s  0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Europe/Bucharest  1:44:24 -       LMT     1891 Oct
+                       1:44:24 -       BMT     1931 Jul 24     # Bucharest MT
+                       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
+
+# 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.
+# 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.
+#
+# From Andrey A. Chernov <ache@nagual.ru> (1996-10-04):
+# `MSK' and `MSD' were born and used initially on Moscow computers with
+# Unix-like OSes by several developer groups (e.g. Demos group, Kiae group)....
+# The next step was the UUCP network, the Relcom predecessor
+# (used mainly for mail), and MSK/MSD was actively used there.
+#
+# From Chris Carrier <72157.3334@CompuServe.COM> (1996-10-30):
+# According to a friend of mine who rode the Trans-Siberian Railroad from
+# Moscow to Irkutsk in 1995, public air and rail transport in Russia ...
+# still follows Moscow time, no matter where in Russia it is located.
+#
+# 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
+                        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
+                        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
+                        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
+                        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
+                        5:00   Russia  YEK%sT  # Yekaterinburg Time
+Zone Asia/Omsk          4:53:36 -      LMT     1924 May  2
+                        5:00   -       OMST    1957 Mar # 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
+                        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
+                        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
+Zone Asia/Krasnoyarsk   6:11:20 -      LMT     1924 May  2
+                        6:00   -       KRAT    1957 Mar # 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
+                        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
+                        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
+                        8:00   Russia  IRK%sT
+Zone Asia/Yakutsk       8:38:40 -      LMT     1924 May  2
+                        8:00   -       YAKT    1957 Mar # 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
+                        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
+                       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
+                       10:00   Russia  VLA%sT
+Zone Asia/Magadan      10:03:12 -      LMT     1924 May  2
+                       10:00   -       MAGT    1957 Mar # 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
+                       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
+                       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
+                       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
+
+# 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
+
+# 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
+Rule   Spain   1917    1919    -       Oct      6      23:00s  0       -
+Rule   Spain   1918    only    -       Apr     15      23:00s  1:00    S
+Rule   Spain   1919    only    -       Apr      5      23:00s  1:00    S
+# Whitman gives 1921 Feb 28 - Oct 14; go with Shanks.
+Rule   Spain   1924    only    -       Apr     16      23:00s  1:00    S
+# Whitman gives 1924 Oct 14; go with Shanks.
+Rule   Spain   1924    only    -       Oct      4      23:00s  0       -
+Rule   Spain   1926    only    -       Apr     17      23:00s  1:00    S
+# Whitman says no DST in 1929; go with Shanks.
+Rule   Spain   1926    1929    -       Oct     Sat>=1  23:00s  0       -
+Rule   Spain   1927    only    -       Apr      9      23:00s  1:00    S
+Rule   Spain   1928    only    -       Apr     14      23:00s  1:00    S
+Rule   Spain   1929    only    -       Apr     20      23:00s  1:00    S
+# Whitman gives 1937 Jun 16, 1938 Apr 16, 1940 Apr 13; go with Shanks.
+Rule   Spain   1937    only    -       May     22      23:00s  1:00    S
+Rule   Spain   1937    1939    -       Oct     Sat>=1  23:00s  0       -
+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    -       Sep      1      22:00s  1:00    S
+Rule   Spain   1943    1946    -       Apr     Sat>=13 22:00s  2:00    DS
+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
+Rule   Spain   1946    only    -       Sep     30       0:00   0       -
+Rule   Spain   1949    only    -       Apr     30      23:00   1:00    S
+Rule   Spain   1949    only    -       Sep     30       1:00   0       -
+Rule   Spain   1974    1975    -       Apr     Sat>=13 23:00   1:00    S
+Rule   Spain   1974    1975    -       Oct     Sun>=1   1:00   0       -
+Rule   Spain   1976    only    -       Mar     27      23:00   1:00    S
+Rule   Spain   1976    1977    -       Sep     lastSun  1:00   0       -
+Rule   Spain   1977    1978    -       Apr      2      23:00   1:00    S
+Rule   Spain   1978    only    -       Oct      1       1:00   0       -
+# The following rules are copied from Morocco from 1967 through 1978.
+Rule SpainAfrica 1967  only    -       Jun      3      12:00   1:00    S
+Rule SpainAfrica 1967  only    -       Oct      1       0:00   0       -
+Rule SpainAfrica 1974  only    -       Jun     24       0:00   1:00    S
+Rule SpainAfrica 1974  only    -       Sep      1       0:00   0       -
+Rule SpainAfrica 1976  1977    -       May      1       0:00   1:00    S
+Rule SpainAfrica 1976  only    -       Aug      1       0:00   0       -
+Rule SpainAfrica 1977  only    -       Sep     28       0:00   0       -
+Rule SpainAfrica 1978  only    -       Jun      1       0:00   1:00    S
+Rule SpainAfrica 1978  only    -       Aug      4       0:00   0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Madrid   -0:14:44 -      LMT     1901
+                        0:00   Spain   WE%sT   1946 Sep 30
+                        1:00   Spain   CE%sT   1979
+                        1:00   EU      CE%sT
+Zone   Africa/Ceuta    -0:21:16 -      LMT     1901
+                        0:00   -       WET     1918 May  6 23:00
+                        0:00   1:00    WEST    1918 Oct  7 23:00
+                        0:00   -       WET     1924
+                        0:00   Spain   WE%sT   1929
+                        0:00 SpainAfrica WE%sT 1984 Mar 16
+                        1:00   -       CET     1986
+                        1:00   EU      CE%sT
+Zone   Atlantic/Canary -1:01:36 -      LMT     1922 Mar # Las Palmas de Gran C.
+                       -1:00   -       CANT    1946 Sep 30 1:00 # Canaries Time
+                        0:00   -       WET     1980 Apr  6 0:00s
+                        0:00   1:00    WEST    1980 Sep 28 0:00s
+                        0:00   EU      WE%sT
+# IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
+# 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
+                       1:00    -       CET     1916 Apr 14 23:00s
+                       1:00    1:00    CEST    1916 Sep 30 23:00s
+                       1:00    -       CET     1980
+                       1:00    EU      CE%sT
+
+# Switzerland
+# From Howse (1988), p 82:
+# 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 ....
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+# 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):
+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]
+Zone   Europe/Zurich   0:34:08 -       LMT     1848 Sep 12
+                       0:29:44 -       BMT     1894 Jun # Bern Mean Time
+                       1:00    Swiss   CE%sT   1981
+                       1:00    EU      CE%sT
+
+# Turkey
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Turkey  1916    only    -       May      1      0:00    1:00    S
+Rule   Turkey  1916    only    -       Oct      1      0:00    0       -
+Rule   Turkey  1920    only    -       Mar     28      0:00    1:00    S
+Rule   Turkey  1920    only    -       Oct     25      0:00    0       -
+Rule   Turkey  1921    only    -       Apr      3      0:00    1:00    S
+Rule   Turkey  1921    only    -       Oct      3      0:00    0       -
+Rule   Turkey  1922    only    -       Mar     26      0:00    1:00    S
+Rule   Turkey  1922    only    -       Oct      8      0:00    0       -
+# Whitman gives 1923 Apr 28 - Sep 16 and no DST in 1924-1925; go with Shanks.
+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
+Rule   Turkey  1941    only    -       Sep     21      0:00    0       -
+Rule   Turkey  1942    only    -       Apr      1      0:00    1:00    S
+# Whitman omits the next two transition and gives 1945 Oct 1; go with Shanks.
+Rule   Turkey  1942    only    -       Nov      1      0:00    0       -
+Rule   Turkey  1945    only    -       Apr      2      0:00    1:00    S
+Rule   Turkey  1945    only    -       Oct      8      0:00    0       -
+Rule   Turkey  1946    only    -       Jun      1      0:00    1:00    S
+Rule   Turkey  1946    only    -       Oct      1      0:00    0       -
+Rule   Turkey  1947    1948    -       Apr     Sun>=16 0:00    1:00    S
+Rule   Turkey  1947    1950    -       Oct     Sun>=2  0:00    0       -
+Rule   Turkey  1949    only    -       Apr     10      0:00    1:00    S
+Rule   Turkey  1950    only    -       Apr     19      0:00    1:00    S
+Rule   Turkey  1951    only    -       Apr     22      0:00    1:00    S
+Rule   Turkey  1951    only    -       Oct      8      0:00    0       -
+Rule   Turkey  1962    only    -       Jul     15      0:00    1:00    S
+Rule   Turkey  1962    only    -       Oct      8      0:00    0       -
+Rule   Turkey  1964    only    -       May     15      0:00    1:00    S
+Rule   Turkey  1964    only    -       Oct      1      0:00    0       -
+Rule   Turkey  1970    1972    -       May     Sun>=2  0:00    1:00    S
+Rule   Turkey  1970    1972    -       Oct     Sun>=2  0:00    0       -
+Rule   Turkey  1973    only    -       Jun      3      1:00    1:00    S
+Rule   Turkey  1973    only    -       Nov      4      3:00    0       -
+Rule   Turkey  1974    only    -       Mar     31      2:00    1:00    S
+Rule   Turkey  1974    only    -       Nov      3      5:00    0       -
+Rule   Turkey  1975    only    -       Mar     30      0:00    1:00    S
+Rule   Turkey  1975    1976    -       Oct     lastSun 0:00    0       -
+Rule   Turkey  1976    only    -       Jun      1      0:00    1:00    S
+Rule   Turkey  1977    1978    -       Apr     Sun>=1  0:00    1:00    S
+Rule   Turkey  1977    only    -       Oct     16      0:00    0       -
+Rule   Turkey  1979    1980    -       Apr     Sun>=1  3:00    1:00    S
+Rule   Turkey  1979    1982    -       Oct     Mon>=11 0:00    0       -
+Rule   Turkey  1981    1982    -       Mar     lastSun 3:00    1:00    S
+Rule   Turkey  1983    only    -       Jul     31      0:00    1:00    S
+Rule   Turkey  1983    only    -       Oct      2      0:00    0       -
+Rule   Turkey  1985    only    -       Apr     20      0:00    1:00    S
+Rule   Turkey  1985    only    -       Sep     28      0:00    0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   Europe/Istanbul 1:55:52 -       LMT     1880
+                       1:56:56 -       IMT     1910 Oct # Istanbul Mean Time?
+                       2:00    Turkey  EE%sT   1978 Oct 15
+                       3:00    Turkey  TR%sT   1985 Apr 20 # Turkey Time
+                       2:00    Turkey  EE%sT   1986
+                       2:00    C-Eur   EE%sT   1991
+                       2:00    EU      EE%sT
+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]
+Zone Europe/Kiev       2:02:04 -       LMT     1880
+                       2:02:04 Ukraine %s      1924 May  2
+                       2:00    -       EET     1930 Jun 21
+                       3:00    Russia  MSK/MSD 1990 Jul 17
+                       2:00    E-Eur   EE%sT   1996
+                       2:00    EU      EE%sT
+Zone Europe/Simferopol 2:16:24 -       LMT     1880
+                       2:08:00 Crimea  %s      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
+# From Paul Eggert <eggert@twinsun.com> (1996-10-21):
+# The _Economist_ (1994-05-28, p 45) reports that most of 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
+
+# Yugoslavia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+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
+                       1:00    EU      CE%sT
+
+###############################################################################
+
+# One source shows that Bulgaria, Cyprus, Finland, and Greece observe DST from
+# the last Sunday in March to the last Sunday in September in 1986.
+# The source shows Romania changing a day later than everybody else.
+#
+# According to Bernard Sieloff's source, Poland is in the MET time zone but
+# uses the WE DST rules.  The Western USSR uses EET+1 and ME DST rules.
+# Bernard Sieloff's source claims Romania switches on the same day, but at
+# 00:00 standard time (i.e., 01:00 DST).  It also claims that Turkey
+# switches on the same day, but switches on at 01:00 standard time
+# and off at 00:00 standard time (i.e., 01:00 DST)
+
+# ...
+# Date: Wed, 28 Jan 87 16:56:27 -0100
+# From: seismo!mcvax!cgcha!wtho (Tom Hofmann)
+# Message-Id: <8701281556.AA22174@cgcha.uucp>
+# ...
+#
+# ...the European time rules are...standardized since 1981, when
+# most European coun[tr]ies started DST.  Before that year, only
+# a few countries (UK, France, Italy) had DST, each according
+# to own national rules.  In 1981, however, DST started on
+# 'Apr firstSun', and not on 'Mar lastSun' as in the following
+# years...
+# But also since 1981 there are some more national exceptions
+# than listed in 'europe': Switzerland, for example, joined DST
+# one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
+# lastSun' in 1981---I don't know how they handle now.
+#
+# Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
+# Soviet Union (as far as I know).
+#
+# Tom Hofmann, Scientific Computer Center, CIBA-GEIGY AG,
+# 4002 Basle, Switzerland
+# UUCP: ...!mcvax!cernvax!cgcha!wtho
+
+# ...
+# Date: Wed, 4 Feb 87 22:35:22 +0100
+# From: seismo!mcvax!cwi.nl!dik (Dik T. Winter)
+# ...
+#
+# The information from Tom Hofmann is (as far as I know) not entirely correct.
+# After a request from chongo at amdahl I tried to retrieve all information
+# about DST in Europe.  I was able to find all from about 1969.
+#
+# ...standardization on DST in Europe started in about 1977 with switches on
+# first Sunday in April and last Sunday in September...
+# In 1981 UK joined Europe insofar that
+# the starting day for both shifted to last Sunday in March.  And from 1982
+# the whole of Europe used DST, with switch dates April 1 and October 1 in
+# the Sov[i]et Union.  In 1985 the SU reverted to standard Europe[a]n switch
+# dates...
+#
+# It should also be remembered that time-zones are not constants; e.g.
+# Portugal switched in 1976 from MET (or CET) to WET with DST...
+# Note also that though there were rules for switch dates not
+# all countries abided to these dates, and many individual deviations
+# occurred, though not since 1982 I believe.  Another note: it is always
+# assumed that DST is 1 hour ahead of normal time, this need not be the
+# case; at least in the Netherlands there have been times when DST was 2 hours
+# in advance of normal time.
+#
+# ...
+# dik t. winter, cwi, amsterdam, nederland
+# INTERNET   : dik@cwi.nl
+# BITNET/EARN: dik@mcvax
+
+# From Bob Devine (1988-01-28):
+# ...
+# Greece: Last Sunday in April to last Sunday in September (iffy on dates).
+# Since 1978.  Change at midnight.
+# ...
+# 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.
diff --git a/zic.tproj/datfiles/factory b/zic.tproj/datfiles/factory
new file mode 100644 (file)
index 0000000..9d24283
--- /dev/null
@@ -0,0 +1,9 @@
+#      $OpenBSD: factory,v 1.2 1997/01/14 04:36:53 millert Exp $
+# @(#)factory  7.1
+
+# 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"
diff --git a/zic.tproj/datfiles/leapseconds b/zic.tproj/datfiles/leapseconds
new file mode 100644 (file)
index 0000000..279d6bb
--- /dev/null
@@ -0,0 +1,43 @@
+#      $OpenBSD: leapseconds,v 1.2 1997/01/14 04:36:54 millert Exp $
+# @(#)leapseconds      7.8
+
+# 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
+# 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
+# accounting for the discrepancy between atomic time and the earth's rotation
+# did not exist until the early 1970s.
+
+# The correction (+ or -) is made at the given time, so lines
+# will typically look like:
+#      Leap    YEAR    MON     DAY     23:59:60        +       R/S
+# or
+#      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
+
+# Leap YEAR    MONTH   DAY     HH:MM:SS        CORR    R/S
+Leap   1972    Jun     30      23:59:60        +       S
+Leap   1972    Dec     31      23:59:60        +       S
+Leap   1973    Dec     31      23:59:60        +       S
+Leap   1974    Dec     31      23:59:60        +       S
+Leap   1975    Dec     31      23:59:60        +       S
+Leap   1976    Dec     31      23:59:60        +       S
+Leap   1977    Dec     31      23:59:60        +       S
+Leap   1978    Dec     31      23:59:60        +       S
+Leap   1979    Dec     31      23:59:60        +       S
+Leap   1981    Jun     30      23:59:60        +       S
+Leap   1982    Jun     30      23:59:60        +       S
+Leap   1983    Jun     30      23:59:60        +       S
+Leap   1985    Jun     30      23:59:60        +       S
+Leap   1987    Dec     31      23:59:60        +       S
+Leap   1989    Dec     31      23:59:60        +       S
+Leap   1990    Dec     31      23:59:60        +       S
+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
diff --git a/zic.tproj/datfiles/northamerica b/zic.tproj/datfiles/northamerica
new file mode 100644 (file)
index 0000000..ee484cb
--- /dev/null
@@ -0,0 +1,1330 @@
+#      $OpenBSD: northamerica,v 1.5 1997/01/14 04:36:54 millert Exp $
+# @(#)northamerica     7.30
+# also includes Central America and the Caribbean
+
+# 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):
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and the discovery of the longitude,
+# Oxford University Press (1980).
+
+###############################################################################
+
+# United States
+
+# 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),
+# San Diego: ACS Publications, Inc. (1991).
+# 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):
+# Daylight Saving Time was first suggested as a joke by Benjamin Franklin
+# in his whimsical essay ``Turkey vs Eagle, McCauley is my Beagle'' (1784).
+# Not everyone is happy with the results:
+#
+#      I don't really care how time is reckoned so long as there is some
+#      agreement about it, but I object to being told that I am saving
+#      daylight when my reason tells me that I am doing nothing of the kind.
+#      I even object to the implication that I am wasting something
+#      valuable if I stay in bed after the sun has risen.  As an admirer
+#      of moonlight I resent the bossy insistence of those who want to
+#      reduce my time for enjoying it.  At the back of the Daylight Saving
+#      scheme I detect the bony, blue-fingered hand of Puritanism, eager
+#      to push people into bed earlier, and get them up earlier, to make
+#      them healthy, wealthy and wise in spite of themselves.
+#
+#      -- Robertson Davies, The Diary of Samuel Marchbanks (1947), XIX, Sunday
+
+# From Arthur David Olson:
+# US Daylight Saving Time ended on the last Sunday of *October* in 1974.
+# See, for example, the front page of the Saturday, 1974-10-26
+# and Sunday, 1974-10-27 editions of the Washington Post.
+
+# From Arthur David Olson:
+# 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.
+
+# 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    -       Oct     lastSun 2:00    0       S
+Rule   US      1942    only    -       Feb     9       2:00    1:00    W # War
+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
+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
+
+# From Bob Devine (1988-01-28):
+# ...Alaska (and Hawaii) had the timezone names changed in 1967.
+#    old                        new
+#    Pacific Standard Time(PST)  -same-
+#    Yukon Standard Time(YST)    -same-
+#    Central Alaska S.T. (CAT)   Alaska-Hawaii St[an]dard Time (AHST)
+#    Nome Standard Time (NT)     Bering Standard Time (BST)
+#
+# ...Alaska's timezone lines were redrawn in 1983 to give only 2 tz.
+#    The YST zone now covers nearly all of the state, AHST just part
+#    of the Aleutian islands.   No DST.
+
+# From Paul Eggert (1995-12-19):
+# The tables below use `NST', not `NT', for Nome Standard Time.
+# I invented `CAWT' for Central Alaska War Time.
+
+# From U. S. Naval Observatory (1989-01-19):
+# USA  EASTERN       5 H  BEHIND UTC    NEW YORK, WASHINGTON
+# USA  EASTERN       4 H  BEHIND UTC    APR 3 - OCT 30
+# USA  CENTRAL       6 H  BEHIND UTC    CHICAGO, HOUSTON
+# USA  CENTRAL       5 H  BEHIND UTC    APR 3 - OCT 30
+# USA  MOUNTAIN      7 H  BEHIND UTC    DENVER
+# USA  MOUNTAIN      6 H  BEHIND UTC    APR 3 - OCT 30
+# USA  PACIFIC       8 H  BEHIND UTC    L.A., SAN FRANCISCO
+# USA  PACIFIC       7 H  BEHIND UTC    APR 3 - OCT 30
+# USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
+# USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
+# USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
+# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
+# USA  HAWAII       10 H  BEHIND UTC
+# USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
+
+# From Arthur David Olson (1989-01-21):
+# The above dates are for 1988.
+# Note the "AKST" and "AKDT" abbreviations, the claim that there's
+# no DST in Samoa, and the claim that there is DST in Alaska and the
+# Aleutians.
+
+# From Arthur David Olson (1988-02-13):
+# Legal standard time zone names, from United States Code (1982 Edition and
+# Supplement III), Title 15, Chapter 6, Section 260 and forward.  First, names
+# up to 1967-04-01 (when most provisions of the Uniform Time Act of 1966
+# took effect), as explained in sections 263 and 261:
+#      (none)
+#      United States standard eastern time
+#      United States standard mountain time
+#      United States standard central time
+#      United States standard Pacific time
+#      (none)
+#      United States standard Alaska time
+#      (none)
+# Next, names from 1967-04-01 until 1983-11-30 (the date for
+# public law 98-181):
+#      Atlantic standard time
+#      eastern standard time
+#      central standard time
+#      mountain standard time
+#      Pacific standard time
+#      Yukon standard time
+#      Alaska-Hawaii standard time
+#      Bering standard time
+# And after 1983-11-30:
+#      Atlantic standard time
+#      eastern standard time
+#      central standard time
+#      mountain standard time
+#      Pacific standard time
+#      Alaska standard time
+#      Hawaii-Aleutian standard time
+#      Samoa standard time
+# The law doesn't give abbreviations.
+#
+# From Paul Eggert (1995-12-19):
+# Shanks uses 1983-10-30, not 1983-11-30, for the 1983 transitions.
+# Go with Shanks.
+
+# US Eastern time, represented by New York
+# 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
+Rule   NYC     1921    1966    -       Apr     lastSun 2:00    1:00    D
+Rule   NYC     1921    1954    -       Sep     lastSun 2:00    0       S
+Rule   NYC     1955    1966    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/New_York  -4:56:02 -      LMT     1883 Nov 18 12:00
+                       -5:00   US      E%sT    1920
+                       -5:00   NYC     E%sT    1942
+                       -5:00   US      E%sT    1946
+                       -5:00   NYC     E%sT    1967
+                       -5:00   US      E%sT
+
+# US Central time, represented by Chicago
+# 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
+Rule   Chicago 1921    only    -       Mar     lastSun 2:00    1:00    D
+Rule   Chicago 1922    1966    -       Apr     lastSun 2:00    1:00    D
+Rule   Chicago 1922    1954    -       Sep     lastSun 2:00    0       S
+Rule   Chicago 1955    1966    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Chicago   -5:50:36 -      LMT     1883 Nov 18 12:00
+                       -6:00   US      C%sT    1920
+                       -6:00   Chicago C%sT    1936 Mar  1 2:00
+                       -5:00   -       EST     1936 Nov 15 2:00
+                       -6:00   Chicago C%sT    1942
+                       -6:00   US      C%sT    1946
+                       -6:00   Chicago C%sT    1967
+                       -6:00   US      C%sT
+
+# US Mountain time, represented by Denver
+# 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
+Rule   Denver  1921    only    -       May     22      2:00    0       S
+Rule   Denver  1965    1966    -       Apr     lastSun 2:00    1:00    D
+Rule   Denver  1965    1966    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Denver    -6:59:56 -      LMT     1883 Nov 18 12:00
+                       -7:00   US      M%sT    1920
+                       -7:00   Denver  M%sT    1942
+                       -7:00   US      M%sT    1946
+                       -7:00   Denver  M%sT    1967
+                       -7:00   US      M%sT
+
+# US Pacific time, represented by Los Angeles
+# 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
+Rule   CA      1950    1966    -       Apr     lastSun 2:00    1:00    D
+Rule   CA      1950    1961    -       Sep     lastSun 2:00    0       S
+Rule   CA      1962    1966    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Los_Angeles -7:52:58 -    LMT     1883 Nov 18 12:00
+                       -8:00   US      P%sT    1946
+                       -8:00   CA      P%sT    1967
+                       -8:00   US      P%sT
+
+# Alaska
+# AK%sT is the modern abbreviation for -9:00 per USNO.
+#
+# From Paul Eggert (1995-12-19):
+# 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.
+#
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Juneau     -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
+                        -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
+                       -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
+                       -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
+                       -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
+                       -10:00  US      HA%sT
+# Shanks writes that part of southwest Alaska (e.g. Aniak)
+# switched from -11:00 to -10:00 on 1968-09-22 at 02:00,
+# and another part (e.g. Akiak) made the same switch five weeks later.
+# These switches don't quite make our 1970 cutoff.
+
+# Hawaii
+#
+# From Arthur David Olson:
+# And then there's Hawaii.
+# DST was observed for one day in 1933;
+# standard time was changed by half an hour in 1947;
+# it's always standard as of 1986.
+#
+# From Paul Eggert:
+# Shanks says the 1933 experiment lasted for three weeks.  Go with Shanks.
+#
+Zone Pacific/Honolulu  -10:31:26 -     LMT     1900 Jan  1 12:00
+                       -10:30  -       HST     1933 Apr 30 2:00
+                       -10:30  1:00    HDT     1933 May 21 2: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.
+Zone America/Phoenix   -7:28:18 -      LMT     1883 Nov 18 12:00
+                       -7:00   US      M%sT    1944 Jan  1 00:01
+                       -7:00   -       MST     1944 Mar 17 00:01
+                       -7:00   US      M%sT    1944 Oct  1 00:01
+                       -7:00   -       MST     1967
+                       -7:00   US      M%sT    1968
+                       -7:00   -       MST
+# From Arthur David Olson (1988-02-13):
+# A writer from the Inter Tribal Council of Arizona, Inc.,
+# notes in private correspondence dated 12/28/87 that "Presently, only the
+# Navajo Nation participates in the Daylight Saving Time policy, due to its
+# large size and location in three states."  (The "only" means that other
+# tribal nations don't use DST.)
+
+Link America/Denver America/Shiprock
+
+# Southern Idaho and eastern Oregon switched four weeks late in 1974.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Boise     -7:44:49 -      LMT     1883 Nov 18 12:00
+                       -8:00   US      P%sT    1923 May 13 2:00
+                       -7:00   US      M%sT    1974
+                       -7:00   -       MST     1974 Feb  3 2:00
+                       -7:00   US      M%sT
+
+# Indiana
+#
+# 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
+# and in 1969 and 1970 the whole state observed daylight time;
+# and there are other exceptions as noted below.
+# Shanks partitions Indiana into 345 regions, each with its own time history,
+# and writes ``Even newspaper reports present contradictory information.''
+# Fortunately, most of the complexity occurred before our cutoff date of 1970.
+#
+# Since 1970, EST-only Indiana has been like America/Indianapolis,
+# with exceptions noted below for Crawford, Starke, and Switzerland counties.
+# The parts of Indiana not listed below have been like America/Chicago,
+# America/Louisville, or America/New_York.
+#
+# Other than Indianapolis, the Indiana place names are so nondescript
+# that they would be ambiguous if we left them at the `America' level.
+# So we reluctantly put them all in a subdirectory `America/Indiana'.
+#
+# Most of EST-only Indiana last observed DST in 1970.
+# 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
+Rule Indianapolis 1946 1954    -       Apr     lastSun 2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:00
+                       -6:00   US      C%sT    1920
+                       -6:00 Indianapolis C%sT 1942
+                       -6:00   US      C%sT    1946
+                       -6:00 Indianapolis C%sT 1955 Apr 24 2:00
+                       -5:00   -       EST     1957 Sep 29 2:00
+                       -6:00   -       CST     1958 Apr 27 2:00
+                       -5:00   -       EST     1969
+                       -5:00   US      E%sT    1971
+                       -5:00   -       EST
+Link America/Indianapolis America/Indiana/Indianapolis
+#
+# Part of Crawford County, Indiana, last observed DST in 1975,
+# and left its clocks alone in 1974.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
+Rule   Marengo 1951    only    -       Apr     lastSun 2:00    1:00    D
+Rule   Marengo 1951    only    -       Sep     lastSun 2:00    0       S
+Rule   Marengo 1954    1960    -       Apr     lastSun 2:00    1:00    D
+Rule   Marengo 1954    1960    -       Sep     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Indiana/Marengo -5:45:23 -        LMT     1883 Nov 18 12:00
+                       -6:00   US      C%sT    1951
+                       -6:00   Marengo C%sT    1961 Apr 30 2:00
+                       -5:00   -       EST     1969
+                       -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    1976
+                       -5:00   -       EST
+#
+# Starke County, Indiana
+# From Arthur David Olson (1991-10-28):
+# An article on page A3 of the Sunday, 1991-10-27 Washington Post
+# notes that Starke County switched from Central time to Eastern time as of
+# 1991-10-27.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
+Rule   Starke  1947    1961    -       Apr     lastSun 2:00    1:00    D
+Rule   Starke  1947    1954    -       Sep     lastSun 2:00    0       S
+Rule   Starke  1955    1956    -       Oct     lastSun 2:00    0       S
+Rule   Starke  1957    1958    -       Sep     lastSun 2:00    0       S
+Rule   Starke  1959    1961    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Indiana/Knox -5:46:30 -   LMT     1883 Nov 18 12:00
+                       -6:00   US      C%sT    1947
+                       -6:00   Starke  C%sT    1962 Apr 29 2:00
+                       -5:00   -       EST     1963 Oct 27 2:00
+                       -6:00   US      C%sT    1991 Oct 27 2:00
+                       -5:00   -       EST
+#
+# Switzerland County, Indiana, last observed DST in 1972.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Indiana/Vevay -5:40:16 -  LMT     1883 Nov 18 12:00
+                       -6:00   US      C%sT    1954 Apr 25 2:00
+                       -5:00   -       EST     1969
+                       -5:00   US      E%sT    1973
+                       -5:00   -       EST
+
+# Part of Kentucky left its clocks alone in 1974.
+# 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
+Rule Louisville        1941    1961    -       Apr     lastSun 2:00    1:00    D
+Rule Louisville        1941    only    -       Sep     lastSun 2:00    0       S
+Rule Louisville        1946    only    -       Jun     2       2:00    0       S
+Rule Louisville        1950    1955    -       Sep     lastSun 2:00    0       S
+Rule Louisville        1956    1960    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Louisville        -5:43:02 -      LMT     1883 Nov 18 12:00
+                       -6:00   US      C%sT    1921
+                       -6:00 Louisville C%sT   1942
+                       -6:00   US      C%sT    1946
+                       -6:00 Louisville C%sT   1961 Jul 23 2:00
+                       -5:00   -       EST     1968
+                       -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
+
+# 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
+#
+#      local time until 1900 when the City Council decreed that clocks should
+#      be put back twenty-eight minutes to Central Standard Time.  Half the
+#      city obeyed, half refused.  After considerable debate, the decision
+#      was rescinded and the city reverted to Sun time.  A derisive offer to
+#      erect a sundial in front of the city hall was referred to the
+#      Committee on Sewers.  Then, in 1905, Central time was adopted
+#      by city vote.
+#
+# This story is too entertaining to be false, so go with Howse over Shanks.
+#
+# 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
+Rule   Detroit 1948    only    -       Sep     lastSun 2:00    0       S
+Rule   Detroit 1967    only    -       Jun     14      2:00    1:00    D
+Rule   Detroit 1967    only    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Detroit   -5:32:11 -      LMT     1905
+                       -6:00   -       CST     1915 May 15 2:00
+                       -5:00   -       EST     1942
+                       -5:00   US      E%sT    1946
+                       -5:00   Detroit E%sT    1973
+                       -5:00   US      E%sT    1975
+                       -5:00   -       EST     1975 Apr 27 2:00
+                       -5:00   US      E%sT
+#
+# The Michigan border with Wisconsin switched from EST to CST/CDT in 1973.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
+Rule Menominee 1946    only    -       Apr     lastSun 2:00    1:00    D
+Rule Menominee 1946    only    -       Sep     lastSun 2:00    0       S
+Rule Menominee 1966    only    -       Apr     lastSun 2:00    1:00    D
+Rule Menominee 1966    only    -       Oct     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Menominee -5:50:27 -      LMT     1885 Sep 18 12:00
+                       -6:00   US      C%sT    1946
+                       -6:00 Menominee C%sT    1969 Apr 27 2:00
+                       -5:00   -       EST     1973 Apr 29 2:00
+                       -6:00   US      C%sT
+
+# Navassa
+# uninhabited
+
+
+# Old names, for S5 users
+
+# Link LINK-FROM               LINK-TO
+Link   America/New_York        EST5EDT
+Link   America/Chicago         CST6CDT
+Link   America/Denver          MST7MDT
+Link   America/Los_Angeles     PST8PDT
+Link   America/Indianapolis    EST
+Link   America/Phoenix         MST
+Link   Pacific/Honolulu        HST
+
+################################################################################
+
+
+# From Paul Eggert <eggert@twinsun.com> (1996-11-22):
+# 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).
+#
+# Gwillim Law <LAW@encmail.encompass.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.
+#
+# 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.
+#
+# See the `europe' file for Greenland.
+#
+# See the `africa' file for time zone naming and abbreviation conventions.
+
+# Canada
+
+# From Alain LaBont<e'> <ALB@immedia.ca> (1994-11-14):
+# I post here the time zone abbreviations standardized in Canada
+# for both English and French in the CAN/CSA-Z234.4-89 standard....
+#
+#      UTC     Standard time   Daylight savings time
+#      offset  French  English French  English
+#      -2:30   -       -       HAT     NDT
+#      -3      -       -       HAA     ADT
+#      -3:30   HNT     NST     -       -
+#      -4      HNA     AST     HAE     EDT
+#      -5      HNE     EST     HAC     CDT
+#      -6      HNC     CST     HAR     MDT
+#      -7      HNR     MST     HAP     PDT
+#      -8      HNP     PST     HAY     YDT
+#      -9      HNY     YST     -       -
+#
+#      HN: Heure Normale       ST: Standard Time
+#      HA: Heure Avanc<e'>e    DT: Daylight saving Time
+#
+#      A: de l'Atlantique      Atlantic
+#      C: du Centre            Central
+#      E: de l'Est             Eastern
+#      M:                      Mountain
+#      N:                      Newfoundland
+#      P: du Pacifique         Pacific
+#      R: des Rocheuses
+#      T: de Terre-Neuve
+#      Y: du Yukon             Yukon
+#
+# 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).
+
+
+# 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  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)
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   StJohns 1917    1918    -       Apr     Sun>=8  2:00    1:00    D
+Rule   StJohns 1917    only    -       Sep     17      2:00    0       S
+Rule   StJohns 1918    only    -       Oct     31      2:00    0       S
+# Whitman gives 1919 Apr 5 and 1920 Apr 5; go with Shanks.
+Rule   StJohns 1919    only    -       May      5      23:00   1:00    D
+Rule   StJohns 1919    only    -       Aug     12      23:00   0       S
+# For 1931-1935 Whitman gives Apr same date; go with Shanks.
+Rule   StJohns 1920    1935    -       May     Sun>=1  23:00   1:00    D
+Rule   StJohns 1920    1935    -       Oct     lastSun 23:00   0       S
+# For 1936-1941 Shanks gives May Mon>=9 and Oct Mon>=2; go with Whitman.
+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    -       Dec     31      0:00    0       S
+Rule   StJohns 1943    only    -       May     30      0:00    1:00    D
+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    -       Sep      2      0:00    0       S
+Rule   StJohns 1945    only    -       Jan      1      0:00    1:00    D
+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.
+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
+# 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
+                       -3:30:52 StJohns N%sT   1935 Mar 30
+                       -3:30   StJohns N%sT
+
+
+# east Labrador
+
+# The name `Happy Valley-Goose Bay' is too long; use `Goose Bay'.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Goose_Bay -4:01:40 -      LMT     1884 # Happy Valley-Goose Bay
+                       -3:30:52 StJohns NST    1919
+                       -3:30:52 -      NST     1935 Mar 30
+                       -3:30   -       NST     1936
+                       -3:30   StJohns N%sT    1966 Mar 15 2:00
+                       -4:00   StJohns A%sT
+
+
+# west Labrador, New Brunswick, Nova Scotia, Prince Edward I
+
+# From Paul Eggert (1996-06-12):
+# Shanks writes that since 1970 most of this region has been like Halifax.
+# Many locales did not observe peacetime DST until 1972;
+# Glace Bay, NS is the largest that we know of.
+# 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.
+
+# 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
+Rule Halifax   1918    only    -       Apr     14      2:00    1:00    D
+Rule Halifax   1918    only    -       Oct     31      2:00    0       S
+Rule Halifax   1920    only    -       May      9      0:00    1:00    D
+Rule Halifax   1920    only    -       Aug     29      0:00    0       S
+Rule Halifax   1921    only    -       May      6      0:00    1:00    D
+Rule Halifax   1921    1922    -       Sep      5      0:00    0       S
+Rule Halifax   1922    only    -       Apr     30      0:00    1:00    D
+Rule Halifax   1923    1925    -       May     Sun>=1  0:00    1:00    D
+Rule Halifax   1923    only    -       Sep      4      0:00    0       S
+Rule Halifax   1924    only    -       Sep     15      0:00    0       S
+Rule Halifax   1925    only    -       Sep     28      0:00    0       S
+Rule Halifax   1926    only    -       May     16      0:00    1:00    D
+Rule Halifax   1926    only    -       Sep     13      0:00    0       S
+Rule Halifax   1927    only    -       May      1      0:00    1:00    D
+Rule Halifax   1927    only    -       Sep     26      0:00    0       S
+Rule Halifax   1928    1931    -       May     Sun>=8  0:00    1:00    D
+Rule Halifax   1928    only    -       Sep      9      0:00    0       S
+Rule Halifax   1929    only    -       Sep      3      0:00    0       S
+Rule Halifax   1930    only    -       Sep     15      0:00    0       S
+Rule Halifax   1931    1932    -       Sep     Mon>=24 0:00    0       S
+Rule Halifax   1933    only    -       Apr     30      0:00    1:00    D
+Rule Halifax   1933    only    -       Oct      2      0:00    0       S
+Rule Halifax   1934    only    -       May     20      0:00    1:00    D
+Rule Halifax   1934    only    -       Sep     16      0:00    0       S
+Rule Halifax   1935    only    -       Jun      2      0:00    1:00    D
+Rule Halifax   1935    only    -       Sep     30      0:00    0       S
+Rule Halifax   1936    only    -       Jun      1      0:00    1:00    D
+Rule Halifax   1936    only    -       Sep     14      0:00    0       S
+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   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
+Rule Halifax   1962    max     -       Oct     lastSun 2:00    0       S
+Rule Halifax   1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Halifax   -4:14:24 -      LMT     1902 Jun 15
+                       -4:00   Halifax A%sT
+Zone America/Glace_Bay -3:59:48 -      LMT     1902 Jun 15
+                       -4:00   Canada  A%sT    1953
+                       -4:00   Halifax A%sT    1954
+                       -4:00   -       AST     1972
+                       -4:00   Halifax A%sT
+
+
+# Ontario, Quebec
+
+# From Paul Eggert (1996-06-12):
+# Shanks writes that since 1970 most of this region has been like Montreal.
+# Thunder Bay skipped DST in 1973.
+# Many smaller locales did not observe peacetime DST until 1974;
+# 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.
+
+# 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
+Rule   Mont    1918    only    -       Apr     14      2:00    1:00    D
+Rule   Mont    1918    only    -       Oct     31      2:00    0       S
+Rule   Mont    1919    only    -       Mar     31      2:30    1:00    D
+Rule   Mont    1919    only    -       Oct     25      2:30    0       S
+Rule   Mont    1920    only    -       May      2      2:30    1:00    D
+Rule   Mont    1920    only    -       Oct      3      2:30    0       S
+Rule   Mont    1921    only    -       May      1      2:00    1:00    D
+Rule   Mont    1921    only    -       Oct      2      2:30    0       S
+Rule   Mont    1922    only    -       Apr     30      2:00    1:00    D
+Rule   Mont    1922    only    -       Oct      1      2:30    0       S
+Rule   Mont    1924    only    -       May     17      2:00    1:00    D
+Rule   Mont    1924    1926    -       Sep     lastSun 2:30    0       S
+Rule   Mont    1925    1926    -       May     Sun>=1  2:00    1:00    D
+Rule   Mont    1927    only    -       May      1      0:00    1:00    D
+Rule   Mont    1927    1932    -       Sep     Sun>=25 0:00    0       S
+Rule   Mont    1928    1931    -       Apr     Sun>=25 0:00    1:00    D
+Rule   Mont    1932    only    -       May      1      0:00    1:00    D
+Rule   Mont    1933    1940    -       Apr     Sun>=24 0:00    1:00    D
+Rule   Mont    1933    only    -       Oct      1      0:00    0       S
+Rule   Mont    1934    1939    -       Sep     Sun>=24 0:00    0       S
+Rule   Mont    1945    1948    -       Sep     lastSun 2:00    0       S
+Rule   Mont    1946    1986    -       Apr     lastSun 2:00    1:00    D
+Rule   Mont    1949    1950    -       Oct     lastSun 2:00    0       S
+Rule   Mont    1951    1956    -       Sep     lastSun 2:00    0       S
+Rule   Mont    1957    max     -       Oct     lastSun 2:00    0       S
+Rule   Mont    1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Montreal  -4:54:16 -      LMT     1884
+                       -5:00   Mont    E%sT
+Zone America/Thunder_Bay -5:57:00 -    LMT     1895
+                       -5:00   Canada  E%sT    1970
+                       -5:00   Mont    E%sT    1973
+                       -5:00   -       EST     1974
+                       -5:00   Canada  E%sT
+Zone America/Nipigon   -5:53:04 -      LMT     1895
+                       -5:00   Canada  E%sT
+Zone America/Rainy_River -6:17:56 -    LMT     1895
+                       -6:00   Canada  C%sT
+
+
+# Manitoba
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Winn    1916    only    -       Apr     23      0:00    1:00    D
+Rule   Winn    1916    only    -       Sep     17      0:00    0       S
+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    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
+Rule   Winn    1947    1949    -       Apr     lastSun 2:00    1:00    D
+Rule   Winn    1947    1949    -       Sep     lastSun 2:00    0       S
+Rule   Winn    1950    only    -       May      1      2:00    1:00    D
+Rule   Winn    1950    only    -       Sep     30      2:00    0       S
+Rule   Winn    1951    1960    -       Apr     lastSun 2:00    1:00    D
+Rule   Winn    1951    1958    -       Sep     lastSun 2:00    0       S
+Rule   Winn    1959    only    -       Oct     lastSun 2:00    0       S
+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    1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Winnipeg  -6:28:36 -      LMT     1887 Jul 16
+                       -6:00   Winn    C%sT
+
+
+# Saskatchewan
+
+# From Paul Eggert (1996-06-12):
+# 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.
+
+# From W. Jones <jones@skdad.usask.ca> (1992-11-06):
+# The. . .below is based on information I got from our law library, the
+# provincial archives, and the provincial Community Services department.
+# A precise history would require digging through newspaper archives, and
+# since you didn't say what you wanted, I didn't bother.
+#
+# Saskatchewan is split by a time zone meridian (105W) and over the years
+# the boundary became pretty ragged as communities near it reevaluated
+# their affiliations in one direction or the other.  In 1965 a provincial
+# referendum favoured legislating common time practices.
+#
+# On 15 April 1966 the Time Act (c. T-14, Revised Statutes of
+# Saskatchewan 1978) was proclaimed, and established that the eastern
+# part of Saskatchewan would use CST year round, that districts in
+# northwest Saskatchewan would by default follow CST but could opt to
+# follow Mountain Time rules (thus 1 hour difference in the winter and
+# zero in the summer), and that districts in southwest Saskatchewan would
+# by default follow MT but could opt to follow CST.
+#
+# It took a few years for the dust to settle (I know one story of a town
+# on one time zone having its school in another, such that a mom had to
+# serve her family lunch in two shifts), but presently it seems that only
+# a few towns on the border with Alberta (e.g. Lloydminster) follow MT
+# rules any more; all other districts appear to have used CST year round
+# since sometime in the 1960s.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Regina  1918    only    -       Apr     14      2:00    1:00    D
+Rule   Regina  1918    only    -       Oct     31      2:00    0       S
+Rule   Regina  1930    1934    -       May     Sun>=1  0:00    1:00    D
+Rule   Regina  1930    1934    -       Oct     Sun>=1  0:00    0       S
+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  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
+Rule   Regina  1947    1959    -       Apr     lastSun 2:00    1:00    D
+Rule   Regina  1947    1958    -       Sep     lastSun 2:00    0       S
+Rule   Regina  1959    only    -       Oct     lastSun 2:00    0       S
+#
+Rule   Swift   1957    only    -       Apr     lastSun 2:00    1:00    D
+Rule   Swift   1957    only    -       Oct     lastSun 2:00    0       S
+Rule   Swift   1959    1961    -       Apr     lastSun 2:00    1:00    D
+Rule   Swift   1959    only    -       Oct     lastSun 2:00    0       S
+Rule   Swift   1960    1961    -       Sep     lastSun 2:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Regina    -6:58:36 -      LMT     1905 Sep
+                       -7:00   Regina  M%sT    1960 Apr lastSun 2:00
+                       -6:00   -       CST
+Zone America/Swift_Current -7:11:20 -  LMT     1905 Sep
+                       -7:00   Canada  M%sT    1946 Apr lastSun 2:00
+                       -7:00   Regina  M%sT    1950
+                       -7:00   Swift   M%sT    1972 Apr lastSun 2:00
+                       -6:00   -       CST
+
+
+# Alberta
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Edm     1918    1919    -       Apr     Sun>=8  2:00    1:00    D
+Rule   Edm     1918    only    -       Oct     31      2:00    0       S
+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     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
+Rule   Edm     1967    only    -       Apr     lastSun 2:00    1:00    D
+Rule   Edm     1967    only    -       Oct     lastSun 2:00    0       S
+Rule   Edm     1969    only    -       Apr     lastSun 2:00    1:00    D
+Rule   Edm     1969    only    -       Oct     lastSun 2:00    0       S
+Rule   Edm     1972    1986    -       Apr     lastSun 2:00    1:00    D
+Rule   Edm     1972    max     -       Oct     lastSun 2:00    0       S
+Rule   Edm     1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Edmonton  -7:33:52 -      LMT     1906 Sep
+                       -7:00   Edm     M%sT
+
+
+# British Columbia
+
+# From Paul Eggert (1996-06-12):
+# Shanks writes that since 1970 most of this region has been like Vancouver.
+# Dawswon Creek uses MST.  Much of east BC is like Edmonton.
+
+# 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    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
+Rule   Vanc    1947    1961    -       Sep     lastSun 2:00    0       S
+Rule   Vanc    1962    max     -       Oct     lastSun 2:00    0       S
+Rule   Vanc    1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Vancouver -8:12:28 -      LMT     1884
+                       -8:00   Vanc    P%sT
+Zone America/Dawson_Creek -8:00:56 -   LMT     1884
+                       -8:00   Canada  P%sT    1947
+                       -8:00   Vanc    P%sT    1972 Aug 30 2:00
+                       -7:00   -       MST
+
+
+# Northwest Territories, Yukon
+
+# From Paul Eggert (1996-10-07):
+# 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;
+#      see Interpretation Act, R.S.C. 1985, c. I-21, s. 35(1).
+#      * C.O. 1973/214 switched Yukon to PST on 1973-10-28 00:00.
+#      * O.I.C. 1980/02 established DST.
+#      * 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.
+
+# 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   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
+Rule   NT_YK   1980    1986    -       Apr     lastSun 2:00    1:00    D
+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
+Zone America/Rankin_Inlet -6:08:40 -   LMT     1884
+                       -6:00   NT_YK   C%sT
+Zone America/Yellowknife -7:37:24 -    LMT     1884
+                       -7:00   NT_YK   M%sT
+Zone America/Inuvik    -8:54:00 -      LMT     1884
+                       -8:00   NT_YK   P%sT    1979 Apr lastSun 2:00
+                       -7:00   NT_YK   M%sT
+Zone America/Whitehorse        -9:00:12 -      LMT     1900 Aug 20
+                       -9:00   NT_YK   Y%sT    1966 Jul 1 2:00
+                       -8:00   NT_YK   P%sT
+Zone America/Dawson    -9:17:40 -      LMT     1900 Aug 20
+                       -9:00   NT_YK   Y%sT    1973 Oct 28 0:00
+                       -8:00   NT_YK   P%sT
+
+
+###############################################################################
+
+# 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?).
+#
+# 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.
+
+# 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).
+
+# 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  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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+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
+                       -6:00   Mexico  C%sT
+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     1949 Jan 14
+                       -8:00   -       PST     1970
+                       -7:00   Mexico  M%sT
+Zone America/Tijuana   -7:48:04 -      LMT     1922 Jan  1  0:11:56
+                       -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
+                       -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
+#
+# Revillagigedo Is
+# no information
+
+###############################################################################
+
+# Anguilla
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Anguilla  -4:12:16 -      LMT     1912 Mar 2
+                       -4:00   -       AST
+
+# Antigua and Barbuda
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Antigua -4:07:12 -      LMT     1912 Mar 2
+                       -5:00   -       EST     1951
+                       -4:00   -       AST
+
+# Bahamas
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Bahamas 1964    max     -       Oct     lastSun 2:00    0       S
+Rule   Bahamas 1964    1986    -       Apr     lastSun 2:00    1:00    D
+Rule   Bahamas 1987    max     -       Apr     Sun>=1  2:00    1:00    D
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Nassau  -5:09:24 -      LMT     1912 Mar 2
+                       -5:00   Bahamas E%sT
+
+# Barbados
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Barb    1977    only    -       Jun     12      2:00    1:00    D
+Rule   Barb    1977    1978    -       Oct     Sun>=1  2:00    0       S
+Rule   Barb    1978    1980    -       Apr     Sun>=15 2:00    1:00    D
+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
+                       -4:00   Barb    A%sT
+
+# Belize
+# Whitman entirely disagrees with Shanks; go with Shanks.
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Belize  1918    1942    -       Oct     Sun>=2  0:00    0:30    HD
+Rule   Belize  1919    1943    -       Feb     Sun>=9  0:00    0       S
+Rule   Belize  1973    only    -       Dec      5      0:00    1:00    D
+Rule   Belize  1974    only    -       Feb      9      0:00    0       S
+Rule   Belize  1982    only    -       Dec     18      0:00    1:00    D
+Rule   Belize  1983    only    -       Feb     12      0:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Belize  -5:52:48 -      LMT     1912 Apr
+                       -6:00   Belize  C%sT
+
+# Bermuda
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Atlantic/Bermuda  -4:19:04 -      LMT     1930 Jan  1 2:00    # Hamilton
+                       -4:00   -       AST     1974 Apr 28 2:00
+                       -4:00   Bahamas A%sT
+
+# 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: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
+Rule   CR      1991    1992    -       Jan     Sat>=15 0:00    1:00    D
+# IATA SSIM (1991-09) says the following was at 1:00; go with Shanks.
+Rule   CR      1991    only    -       Jul      1      0:00    0       S
+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
+                       -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 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
+Rule   Cuba    1940    1942    -       Jun     Sun>=1  0:00    1:00    D
+Rule   Cuba    1940    1942    -       Sep     Sun>=1  0:00    0       S
+Rule   Cuba    1945    1946    -       Jun     Sun>=1  0:00    1:00    D
+Rule   Cuba    1945    1946    -       Sep     Sun>=1  0:00    0       S
+Rule   Cuba    1965    only    -       Jun     1       0:00    1:00    D
+Rule   Cuba    1965    only    -       Sep     30      0:00    0       S
+Rule   Cuba    1966    only    -       May     29      0:00    1:00    D
+Rule   Cuba    1966    only    -       Oct     2       0:00    0       S
+Rule   Cuba    1967    only    -       Apr     8       0:00    1:00    D
+Rule   Cuba    1967    1968    -       Sep     Sun>=8  0:00    0       S
+Rule   Cuba    1968    only    -       Apr     14      0:00    1:00    D
+Rule   Cuba    1969    1977    -       Apr     lastSun 0:00    1:00    D
+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    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    1991    1995    -       Oct     Sun>=8  0:00s   0       S
+Rule   Cuba    1996    max     -       Oct     Sun>=1  0:00s   0       S
+
+# 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:00   Cuba    C%sT
+
+# Dominica
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Dominica  -4:05:36 -      LMT     1911 Jul 1 0:01         # Roseau
+                       -4:00   -       AST
+
+# Dominican Republic
+# 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
+Rule   DR      1969    1973    -       Oct     lastSun 0:00    0:30    HD
+Rule   DR      1970    only    -       Feb     21      0:00    0       S
+Rule   DR      1971    only    -       Jan     20      0:00    0       S
+Rule   DR      1972    1974    -       Jan     21      0:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+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
+
+# El Salvador
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Salv    1987    1988    -       May     Sun>=1  0:00    1:00    D
+Rule   Salv    1987    1988    -       Sep     lastSun 0:00    0       S
+# There are too many San Salvadors elsewhere, so we'll use `El Salvador'.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/El_Salvador -5:56:48 -    LMT     1921            # San Salvador
+                       -6:00   Salv    C%sT
+
+# Grenada
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Grenada -4:07:00 -      LMT     1911 Jul        # St George's
+                       -4:00   -       AST
+
+# Guadeloupe
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Guadeloupe        -4:06:08 -      LMT     1911 Jun 8      # Pointe a Pitre
+                       -4:00   -       AST
+
+# Guatemala
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Guat    1973    only    -       Nov     25      0:00    1:00    D
+Rule   Guat    1974    only    -       Feb     24      0:00    0       S
+Rule   Guat    1983    only    -       May     21      0:00    1:00    D
+Rule   Guat    1983    only    -       Sep     22      0:00    0       S
+Rule   Guat    1991    only    -       Mar     23      0:00    1:00    D
+Rule   Guat    1991    only    -       Sep      7      0:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Guatemala -6:02:04 -      LMT     1918 Oct 5
+                       -6:00   Guat    C%sT
+
+# Haiti
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+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
+# 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
+                       -5:00   Haiti   E%sT
+
+# Honduras
+# Shanks says 1921 Jan 1; go with Whitman's more precise Apr 1.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Tegucigalpa -5:48:52 -    LMT     1921 Apr
+                       -6:00   Salv    C%sT
+
+# Jamaica
+
+# From Bob Devine (1988-01-28):
+# Follows US rules.
+
+# From U. S. Naval Observatory (1989-01-19):
+# JAMAICA             5 H  BEHIND UTC
+
+# From Shanks (1991):
+# 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:00   US      E%sT    1984
+                       -5:00   -       EST
+
+# Martinique
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Martinique        -4:04:20 -      LMT     1890            # Fort-de-France
+                       -4:04   -       FFMT    1911 May     # Fort-de-France MT
+                       -4:00   -       AST     1980 Apr  6
+                       -4:00   1:00    ADT     1980 Sep 28
+                       -4:00   -       AST
+
+# Montserrat
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Montserrat        -4:08:52 -      LMT     1911 Jul 1 0:01   # Plymouth
+                       -4:00   -       AST
+
+# Nicaragua
+# 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
+Rule   Nic     1992    only    -       Jan     1       4:00    1:00    D
+Rule   Nic     1992    only    -       Sep     24      0:00    0       S
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Managua -5:45:08 -      LMT     1890
+                       -5:45   -       MMT     1934 Jun 23  # Managua Mean Time
+                       -6:00   -       CST     1973 May
+                       -5:00   -       EST     1975 Feb 16
+                       -6:00   Nic     C%sT    1993 Jan 1 4:00
+                       -5:00   -       EST
+
+# Panama
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Panama  -5:18:08 -      LMT     1890
+                       -5:20   -       PMT     1908 Apr 22   # Panama Mean Time
+                       -5:00   -       EST
+
+# Puerto Rico
+# There are too many San Juans elsewhere, so we'll use `Puerto_Rico'.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Puerto_Rico -4:24:25 -    LMT     1899 Mar 28 12:00    # San Juan
+                       -4:00   -       AST     1942 May  3
+                       -4:00   1:00    AWT     1945 Sep 30  2:00
+                       -4:00   -       AST
+
+# St Kitts-Nevis
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/St_Kitts  -4:10:52 -      LMT     1912 Mar 2      # Basseterre
+                       -4:00   -       AST
+
+# St Lucia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/St_Lucia  -4:04:00 -      LMT     1890            # Castries
+                       -4:04   -       CMT     1912        # Castries Mean Time
+                       -4:00   -       AST
+
+# St Pierre and Miquelon
+# There are too many St Pierres elsewhere, so we'll use `Miquelon'.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Miquelon  -3:44:40 -      LMT     1911 May 15     # St Pierre
+                       -4:00   -       AST     1980 May
+                       -3:00   Mont    PM%sT   # Pierre & Miquelon Time
+
+# 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:00   -       AST
+
+# Turks and Caicos
+# From Paul Eggert (1996-11-22):
+# Shanks says they use US DST rules, but IATA SSIM (1991/1996)
+# 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
+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:00   TC      E%sT
+
+# British Virgin Is
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Tortola   -4:18:28 -      LMT     1911 Jul    # Road Town
+                       -4:00   -       AST
+
+# Virgin Is
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/St_Thomas -4:19:44 -      LMT     1911 Jul    # Charlotte Amalie
+                       -4:00   -       AST
diff --git a/zic.tproj/datfiles/pacificnew b/zic.tproj/datfiles/pacificnew
new file mode 100644 (file)
index 0000000..ede90db
--- /dev/null
@@ -0,0 +1,27 @@
+#      $OpenBSD: pacificnew,v 1.3 1997/01/14 04:36:55 millert Exp $
+# @(#)pacificnew       7.9
+
+# From Arthur David Olson (1989-04-05):
+# On 1989-04-05, the U. S. House of Representatives passed (238-154) a bill
+# establishing "Pacific Presidential Election Time"; it was not acted on
+# by the Senate or signed into law by the President.
+# You might want to change the "PE" (Presidential Election) below to
+# "Q" (Quadrennial) to maintain three-character zone abbreviations.
+# If you're really conservative, you might want to change it to "D".
+# Avoid "L" (Leap Year), which won't be true in 2100.
+
+# If Presidential Election Time is ever established, replace "XXXX" below
+# with the year the law takes effect and uncomment the "##" lines.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+## Rule        Twilite XXXX    max     -       Apr     Sun>=1  2:00    1:00    D
+## Rule        Twilite XXXX    max     uspres  Oct     lastSun 2:00    1:00    PE
+## Rule        Twilite XXXX    max     uspres  Nov     Sun>=7  2:00    0       S
+## Rule        Twilite XXXX    max     nonpres Oct     lastSun 2:00    0       S
+
+# Zone NAME                    GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
+## Zone        America/Los_Angeles-PET -8:00   US              P%sT    XXXX
+##                             -8:00   Twilite         P%sT
+
+# For now...
+Link   America/Los_Angeles     US/Pacific-New  ##
diff --git a/zic.tproj/datfiles/solar87 b/zic.tproj/datfiles/solar87
new file mode 100644 (file)
index 0000000..b985f3b
--- /dev/null
@@ -0,0 +1,389 @@
+#      $OpenBSD: solar87,v 1.3 1997/01/14 04:36:56 millert Exp $
+# @(#)solar87  7.3
+
+# So much for footnotes about Saudi Arabia.
+# Apparent noon times below are for Riyadh; your mileage will vary.
+# Times were computed using formulas in the U.S. Naval Observatory's
+# Almanac for Computers 1987; the formulas "will give EqT to an accuracy of
+# [plus or minus two] seconds during the current year."
+#
+# Rounding to the nearest five seconds results in fewer than
+# 256 different "time types"--a limit that's faced because time types are
+# stored on disk as unsigned chars.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   sol87   1987    only    -       Jan     1       12:03:20s -0:03:20 -
+Rule   sol87   1987    only    -       Jan     2       12:03:50s -0:03:50 -
+Rule   sol87   1987    only    -       Jan     3       12:04:15s -0:04:15 -
+Rule   sol87   1987    only    -       Jan     4       12:04:45s -0:04:45 -
+Rule   sol87   1987    only    -       Jan     5       12:05:10s -0:05:10 -
+Rule   sol87   1987    only    -       Jan     6       12:05:40s -0:05:40 -
+Rule   sol87   1987    only    -       Jan     7       12:06:05s -0:06:05 -
+Rule   sol87   1987    only    -       Jan     8       12:06:30s -0:06:30 -
+Rule   sol87   1987    only    -       Jan     9       12:06:55s -0:06:55 -
+Rule   sol87   1987    only    -       Jan     10      12:07:20s -0:07:20 -
+Rule   sol87   1987    only    -       Jan     11      12:07:45s -0:07:45 -
+Rule   sol87   1987    only    -       Jan     12      12:08:10s -0:08:10 -
+Rule   sol87   1987    only    -       Jan     13      12:08:30s -0:08:30 -
+Rule   sol87   1987    only    -       Jan     14      12:08:55s -0:08:55 -
+Rule   sol87   1987    only    -       Jan     15      12:09:15s -0:09:15 -
+Rule   sol87   1987    only    -       Jan     16      12:09:35s -0:09:35 -
+Rule   sol87   1987    only    -       Jan     17      12:09:55s -0:09:55 -
+Rule   sol87   1987    only    -       Jan     18      12:10:15s -0:10:15 -
+Rule   sol87   1987    only    -       Jan     19      12:10:35s -0:10:35 -
+Rule   sol87   1987    only    -       Jan     20      12:10:55s -0:10:55 -
+Rule   sol87   1987    only    -       Jan     21      12:11:10s -0:11:10 -
+Rule   sol87   1987    only    -       Jan     22      12:11:30s -0:11:30 -
+Rule   sol87   1987    only    -       Jan     23      12:11:45s -0:11:45 -
+Rule   sol87   1987    only    -       Jan     24      12:12:00s -0:12:00 -
+Rule   sol87   1987    only    -       Jan     25      12:12:15s -0:12:15 -
+Rule   sol87   1987    only    -       Jan     26      12:12:30s -0:12:30 -
+Rule   sol87   1987    only    -       Jan     27      12:12:40s -0:12:40 -
+Rule   sol87   1987    only    -       Jan     28      12:12:55s -0:12:55 -
+Rule   sol87   1987    only    -       Jan     29      12:13:05s -0:13:05 -
+Rule   sol87   1987    only    -       Jan     30      12:13:15s -0:13:15 -
+Rule   sol87   1987    only    -       Jan     31      12:13:25s -0:13:25 -
+Rule   sol87   1987    only    -       Feb     1       12:13:35s -0:13:35 -
+Rule   sol87   1987    only    -       Feb     2       12:13:40s -0:13:40 -
+Rule   sol87   1987    only    -       Feb     3       12:13:50s -0:13:50 -
+Rule   sol87   1987    only    -       Feb     4       12:13:55s -0:13:55 -
+Rule   sol87   1987    only    -       Feb     5       12:14:00s -0:14:00 -
+Rule   sol87   1987    only    -       Feb     6       12:14:05s -0:14:05 -
+Rule   sol87   1987    only    -       Feb     7       12:14:10s -0:14:10 -
+Rule   sol87   1987    only    -       Feb     8       12:14:10s -0:14:10 -
+Rule   sol87   1987    only    -       Feb     9       12:14:15s -0:14:15 -
+Rule   sol87   1987    only    -       Feb     10      12:14:15s -0:14:15 -
+Rule   sol87   1987    only    -       Feb     11      12:14:15s -0:14:15 -
+Rule   sol87   1987    only    -       Feb     12      12:14:15s -0:14:15 -
+Rule   sol87   1987    only    -       Feb     13      12:14:15s -0:14:15 -
+Rule   sol87   1987    only    -       Feb     14      12:14:15s -0:14:15 -
+Rule   sol87   1987    only    -       Feb     15      12:14:10s -0:14:10 -
+Rule   sol87   1987    only    -       Feb     16      12:14:10s -0:14:10 -
+Rule   sol87   1987    only    -       Feb     17      12:14:05s -0:14:05 -
+Rule   sol87   1987    only    -       Feb     18      12:14:00s -0:14:00 -
+Rule   sol87   1987    only    -       Feb     19      12:13:55s -0:13:55 -
+Rule   sol87   1987    only    -       Feb     20      12:13:50s -0:13:50 -
+Rule   sol87   1987    only    -       Feb     21      12:13:45s -0:13:45 -
+Rule   sol87   1987    only    -       Feb     22      12:13:35s -0:13:35 -
+Rule   sol87   1987    only    -       Feb     23      12:13:30s -0:13:30 -
+Rule   sol87   1987    only    -       Feb     24      12:13:20s -0:13:20 -
+Rule   sol87   1987    only    -       Feb     25      12:13:10s -0:13:10 -
+Rule   sol87   1987    only    -       Feb     26      12:13:00s -0:13:00 -
+Rule   sol87   1987    only    -       Feb     27      12:12:50s -0:12:50 -
+Rule   sol87   1987    only    -       Feb     28      12:12:40s -0:12:40 -
+Rule   sol87   1987    only    -       Mar     1       12:12:30s -0:12:30 -
+Rule   sol87   1987    only    -       Mar     2       12:12:20s -0:12:20 -
+Rule   sol87   1987    only    -       Mar     3       12:12:05s -0:12:05 -
+Rule   sol87   1987    only    -       Mar     4       12:11:55s -0:11:55 -
+Rule   sol87   1987    only    -       Mar     5       12:11:40s -0:11:40 -
+Rule   sol87   1987    only    -       Mar     6       12:11:25s -0:11:25 -
+Rule   sol87   1987    only    -       Mar     7       12:11:15s -0:11:15 -
+Rule   sol87   1987    only    -       Mar     8       12:11:00s -0:11:00 -
+Rule   sol87   1987    only    -       Mar     9       12:10:45s -0:10:45 -
+Rule   sol87   1987    only    -       Mar     10      12:10:30s -0:10:30 -
+Rule   sol87   1987    only    -       Mar     11      12:10:15s -0:10:15 -
+Rule   sol87   1987    only    -       Mar     12      12:09:55s -0:09:55 -
+Rule   sol87   1987    only    -       Mar     13      12:09:40s -0:09:40 -
+Rule   sol87   1987    only    -       Mar     14      12:09:25s -0:09:25 -
+Rule   sol87   1987    only    -       Mar     15      12:09:10s -0:09:10 -
+Rule   sol87   1987    only    -       Mar     16      12:08:50s -0:08:50 -
+Rule   sol87   1987    only    -       Mar     17      12:08:35s -0:08:35 -
+Rule   sol87   1987    only    -       Mar     18      12:08:15s -0:08:15 -
+Rule   sol87   1987    only    -       Mar     19      12:08:00s -0:08:00 -
+Rule   sol87   1987    only    -       Mar     20      12:07:40s -0:07:40 -
+Rule   sol87   1987    only    -       Mar     21      12:07:25s -0:07:25 -
+Rule   sol87   1987    only    -       Mar     22      12:07:05s -0:07:05 -
+Rule   sol87   1987    only    -       Mar     23      12:06:50s -0:06:50 -
+Rule   sol87   1987    only    -       Mar     24      12:06:30s -0:06:30 -
+Rule   sol87   1987    only    -       Mar     25      12:06:10s -0:06:10 -
+Rule   sol87   1987    only    -       Mar     26      12:05:55s -0:05:55 -
+Rule   sol87   1987    only    -       Mar     27      12:05:35s -0:05:35 -
+Rule   sol87   1987    only    -       Mar     28      12:05:15s -0:05:15 -
+Rule   sol87   1987    only    -       Mar     29      12:05:00s -0:05:00 -
+Rule   sol87   1987    only    -       Mar     30      12:04:40s -0:04:40 -
+Rule   sol87   1987    only    -       Mar     31      12:04:25s -0:04:25 -
+Rule   sol87   1987    only    -       Apr     1       12:04:05s -0:04:05 -
+Rule   sol87   1987    only    -       Apr     2       12:03:45s -0:03:45 -
+Rule   sol87   1987    only    -       Apr     3       12:03:30s -0:03:30 -
+Rule   sol87   1987    only    -       Apr     4       12:03:10s -0:03:10 -
+Rule   sol87   1987    only    -       Apr     5       12:02:55s -0:02:55 -
+Rule   sol87   1987    only    -       Apr     6       12:02:35s -0:02:35 -
+Rule   sol87   1987    only    -       Apr     7       12:02:20s -0:02:20 -
+Rule   sol87   1987    only    -       Apr     8       12:02:05s -0:02:05 -
+Rule   sol87   1987    only    -       Apr     9       12:01:45s -0:01:45 -
+Rule   sol87   1987    only    -       Apr     10      12:01:30s -0:01:30 -
+Rule   sol87   1987    only    -       Apr     11      12:01:15s -0:01:15 -
+Rule   sol87   1987    only    -       Apr     12      12:00:55s -0:00:55 -
+Rule   sol87   1987    only    -       Apr     13      12:00:40s -0:00:40 -
+Rule   sol87   1987    only    -       Apr     14      12:00:25s -0:00:25 -
+Rule   sol87   1987    only    -       Apr     15      12:00:10s -0:00:10 -
+Rule   sol87   1987    only    -       Apr     16      11:59:55s 0:00:05 -
+Rule   sol87   1987    only    -       Apr     17      11:59:45s 0:00:15 -
+Rule   sol87   1987    only    -       Apr     18      11:59:30s 0:00:30 -
+Rule   sol87   1987    only    -       Apr     19      11:59:15s 0:00:45 -
+Rule   sol87   1987    only    -       Apr     20      11:59:05s 0:00:55 -
+Rule   sol87   1987    only    -       Apr     21      11:58:50s 0:01:10 -
+Rule   sol87   1987    only    -       Apr     22      11:58:40s 0:01:20 -
+Rule   sol87   1987    only    -       Apr     23      11:58:25s 0:01:35 -
+Rule   sol87   1987    only    -       Apr     24      11:58:15s 0:01:45 -
+Rule   sol87   1987    only    -       Apr     25      11:58:05s 0:01:55 -
+Rule   sol87   1987    only    -       Apr     26      11:57:55s 0:02:05 -
+Rule   sol87   1987    only    -       Apr     27      11:57:45s 0:02:15 -
+Rule   sol87   1987    only    -       Apr     28      11:57:35s 0:02:25 -
+Rule   sol87   1987    only    -       Apr     29      11:57:25s 0:02:35 -
+Rule   sol87   1987    only    -       Apr     30      11:57:15s 0:02:45 -
+Rule   sol87   1987    only    -       May     1       11:57:10s 0:02:50 -
+Rule   sol87   1987    only    -       May     2       11:57:00s 0:03:00 -
+Rule   sol87   1987    only    -       May     3       11:56:55s 0:03:05 -
+Rule   sol87   1987    only    -       May     4       11:56:50s 0:03:10 -
+Rule   sol87   1987    only    -       May     5       11:56:45s 0:03:15 -
+Rule   sol87   1987    only    -       May     6       11:56:40s 0:03:20 -
+Rule   sol87   1987    only    -       May     7       11:56:35s 0:03:25 -
+Rule   sol87   1987    only    -       May     8       11:56:30s 0:03:30 -
+Rule   sol87   1987    only    -       May     9       11:56:25s 0:03:35 -
+Rule   sol87   1987    only    -       May     10      11:56:25s 0:03:35 -
+Rule   sol87   1987    only    -       May     11      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     12      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     13      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     14      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     15      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     16      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     17      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     18      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       May     19      11:56:25s 0:03:35 -
+Rule   sol87   1987    only    -       May     20      11:56:25s 0:03:35 -
+Rule   sol87   1987    only    -       May     21      11:56:30s 0:03:30 -
+Rule   sol87   1987    only    -       May     22      11:56:35s 0:03:25 -
+Rule   sol87   1987    only    -       May     23      11:56:40s 0:03:20 -
+Rule   sol87   1987    only    -       May     24      11:56:45s 0:03:15 -
+Rule   sol87   1987    only    -       May     25      11:56:50s 0:03:10 -
+Rule   sol87   1987    only    -       May     26      11:56:55s 0:03:05 -
+Rule   sol87   1987    only    -       May     27      11:57:00s 0:03:00 -
+Rule   sol87   1987    only    -       May     28      11:57:10s 0:02:50 -
+Rule   sol87   1987    only    -       May     29      11:57:15s 0:02:45 -
+Rule   sol87   1987    only    -       May     30      11:57:25s 0:02:35 -
+Rule   sol87   1987    only    -       May     31      11:57:30s 0:02:30 -
+Rule   sol87   1987    only    -       Jun     1       11:57:40s 0:02:20 -
+Rule   sol87   1987    only    -       Jun     2       11:57:50s 0:02:10 -
+Rule   sol87   1987    only    -       Jun     3       11:58:00s 0:02:00 -
+Rule   sol87   1987    only    -       Jun     4       11:58:10s 0:01:50 -
+Rule   sol87   1987    only    -       Jun     5       11:58:20s 0:01:40 -
+Rule   sol87   1987    only    -       Jun     6       11:58:30s 0:01:30 -
+Rule   sol87   1987    only    -       Jun     7       11:58:40s 0:01:20 -
+Rule   sol87   1987    only    -       Jun     8       11:58:50s 0:01:10 -
+Rule   sol87   1987    only    -       Jun     9       11:59:05s 0:00:55 -
+Rule   sol87   1987    only    -       Jun     10      11:59:15s 0:00:45 -
+Rule   sol87   1987    only    -       Jun     11      11:59:30s 0:00:30 -
+Rule   sol87   1987    only    -       Jun     12      11:59:40s 0:00:20 -
+Rule   sol87   1987    only    -       Jun     13      11:59:50s 0:00:10 -
+Rule   sol87   1987    only    -       Jun     14      12:00:05s -0:00:05 -
+Rule   sol87   1987    only    -       Jun     15      12:00:15s -0:00:15 -
+Rule   sol87   1987    only    -       Jun     16      12:00:30s -0:00:30 -
+Rule   sol87   1987    only    -       Jun     17      12:00:45s -0:00:45 -
+Rule   sol87   1987    only    -       Jun     18      12:00:55s -0:00:55 -
+Rule   sol87   1987    only    -       Jun     19      12:01:10s -0:01:10 -
+Rule   sol87   1987    only    -       Jun     20      12:01:20s -0:01:20 -
+Rule   sol87   1987    only    -       Jun     21      12:01:35s -0:01:35 -
+Rule   sol87   1987    only    -       Jun     22      12:01:50s -0:01:50 -
+Rule   sol87   1987    only    -       Jun     23      12:02:00s -0:02:00 -
+Rule   sol87   1987    only    -       Jun     24      12:02:15s -0:02:15 -
+Rule   sol87   1987    only    -       Jun     25      12:02:25s -0:02:25 -
+Rule   sol87   1987    only    -       Jun     26      12:02:40s -0:02:40 -
+Rule   sol87   1987    only    -       Jun     27      12:02:50s -0:02:50 -
+Rule   sol87   1987    only    -       Jun     28      12:03:05s -0:03:05 -
+Rule   sol87   1987    only    -       Jun     29      12:03:15s -0:03:15 -
+Rule   sol87   1987    only    -       Jun     30      12:03:30s -0:03:30 -
+Rule   sol87   1987    only    -       Jul     1       12:03:40s -0:03:40 -
+Rule   sol87   1987    only    -       Jul     2       12:03:50s -0:03:50 -
+Rule   sol87   1987    only    -       Jul     3       12:04:05s -0:04:05 -
+Rule   sol87   1987    only    -       Jul     4       12:04:15s -0:04:15 -
+Rule   sol87   1987    only    -       Jul     5       12:04:25s -0:04:25 -
+Rule   sol87   1987    only    -       Jul     6       12:04:35s -0:04:35 -
+Rule   sol87   1987    only    -       Jul     7       12:04:45s -0:04:45 -
+Rule   sol87   1987    only    -       Jul     8       12:04:55s -0:04:55 -
+Rule   sol87   1987    only    -       Jul     9       12:05:05s -0:05:05 -
+Rule   sol87   1987    only    -       Jul     10      12:05:15s -0:05:15 -
+Rule   sol87   1987    only    -       Jul     11      12:05:20s -0:05:20 -
+Rule   sol87   1987    only    -       Jul     12      12:05:30s -0:05:30 -
+Rule   sol87   1987    only    -       Jul     13      12:05:40s -0:05:40 -
+Rule   sol87   1987    only    -       Jul     14      12:05:45s -0:05:45 -
+Rule   sol87   1987    only    -       Jul     15      12:05:50s -0:05:50 -
+Rule   sol87   1987    only    -       Jul     16      12:06:00s -0:06:00 -
+Rule   sol87   1987    only    -       Jul     17      12:06:05s -0:06:05 -
+Rule   sol87   1987    only    -       Jul     18      12:06:10s -0:06:10 -
+Rule   sol87   1987    only    -       Jul     19      12:06:15s -0:06:15 -
+Rule   sol87   1987    only    -       Jul     20      12:06:15s -0:06:15 -
+Rule   sol87   1987    only    -       Jul     21      12:06:20s -0:06:20 -
+Rule   sol87   1987    only    -       Jul     22      12:06:25s -0:06:25 -
+Rule   sol87   1987    only    -       Jul     23      12:06:25s -0:06:25 -
+Rule   sol87   1987    only    -       Jul     24      12:06:25s -0:06:25 -
+Rule   sol87   1987    only    -       Jul     25      12:06:30s -0:06:30 -
+Rule   sol87   1987    only    -       Jul     26      12:06:30s -0:06:30 -
+Rule   sol87   1987    only    -       Jul     27      12:06:30s -0:06:30 -
+Rule   sol87   1987    only    -       Jul     28      12:06:30s -0:06:30 -
+Rule   sol87   1987    only    -       Jul     29      12:06:25s -0:06:25 -
+Rule   sol87   1987    only    -       Jul     30      12:06:25s -0:06:25 -
+Rule   sol87   1987    only    -       Jul     31      12:06:25s -0:06:25 -
+Rule   sol87   1987    only    -       Aug     1       12:06:20s -0:06:20 -
+Rule   sol87   1987    only    -       Aug     2       12:06:15s -0:06:15 -
+Rule   sol87   1987    only    -       Aug     3       12:06:10s -0:06:10 -
+Rule   sol87   1987    only    -       Aug     4       12:06:05s -0:06:05 -
+Rule   sol87   1987    only    -       Aug     5       12:06:00s -0:06:00 -
+Rule   sol87   1987    only    -       Aug     6       12:05:55s -0:05:55 -
+Rule   sol87   1987    only    -       Aug     7       12:05:50s -0:05:50 -
+Rule   sol87   1987    only    -       Aug     8       12:05:40s -0:05:40 -
+Rule   sol87   1987    only    -       Aug     9       12:05:35s -0:05:35 -
+Rule   sol87   1987    only    -       Aug     10      12:05:25s -0:05:25 -
+Rule   sol87   1987    only    -       Aug     11      12:05:15s -0:05:15 -
+Rule   sol87   1987    only    -       Aug     12      12:05:05s -0:05:05 -
+Rule   sol87   1987    only    -       Aug     13      12:04:55s -0:04:55 -
+Rule   sol87   1987    only    -       Aug     14      12:04:45s -0:04:45 -
+Rule   sol87   1987    only    -       Aug     15      12:04:35s -0:04:35 -
+Rule   sol87   1987    only    -       Aug     16      12:04:25s -0:04:25 -
+Rule   sol87   1987    only    -       Aug     17      12:04:10s -0:04:10 -
+Rule   sol87   1987    only    -       Aug     18      12:04:00s -0:04:00 -
+Rule   sol87   1987    only    -       Aug     19      12:03:45s -0:03:45 -
+Rule   sol87   1987    only    -       Aug     20      12:03:30s -0:03:30 -
+Rule   sol87   1987    only    -       Aug     21      12:03:15s -0:03:15 -
+Rule   sol87   1987    only    -       Aug     22      12:03:00s -0:03:00 -
+Rule   sol87   1987    only    -       Aug     23      12:02:45s -0:02:45 -
+Rule   sol87   1987    only    -       Aug     24      12:02:30s -0:02:30 -
+Rule   sol87   1987    only    -       Aug     25      12:02:15s -0:02:15 -
+Rule   sol87   1987    only    -       Aug     26      12:02:00s -0:02:00 -
+Rule   sol87   1987    only    -       Aug     27      12:01:40s -0:01:40 -
+Rule   sol87   1987    only    -       Aug     28      12:01:25s -0:01:25 -
+Rule   sol87   1987    only    -       Aug     29      12:01:05s -0:01:05 -
+Rule   sol87   1987    only    -       Aug     30      12:00:50s -0:00:50 -
+Rule   sol87   1987    only    -       Aug     31      12:00:30s -0:00:30 -
+Rule   sol87   1987    only    -       Sep     1       12:00:10s -0:00:10 -
+Rule   sol87   1987    only    -       Sep     2       11:59:50s 0:00:10 -
+Rule   sol87   1987    only    -       Sep     3       11:59:35s 0:00:25 -
+Rule   sol87   1987    only    -       Sep     4       11:59:15s 0:00:45 -
+Rule   sol87   1987    only    -       Sep     5       11:58:55s 0:01:05 -
+Rule   sol87   1987    only    -       Sep     6       11:58:35s 0:01:25 -
+Rule   sol87   1987    only    -       Sep     7       11:58:15s 0:01:45 -
+Rule   sol87   1987    only    -       Sep     8       11:57:55s 0:02:05 -
+Rule   sol87   1987    only    -       Sep     9       11:57:30s 0:02:30 -
+Rule   sol87   1987    only    -       Sep     10      11:57:10s 0:02:50 -
+Rule   sol87   1987    only    -       Sep     11      11:56:50s 0:03:10 -
+Rule   sol87   1987    only    -       Sep     12      11:56:30s 0:03:30 -
+Rule   sol87   1987    only    -       Sep     13      11:56:10s 0:03:50 -
+Rule   sol87   1987    only    -       Sep     14      11:55:45s 0:04:15 -
+Rule   sol87   1987    only    -       Sep     15      11:55:25s 0:04:35 -
+Rule   sol87   1987    only    -       Sep     16      11:55:05s 0:04:55 -
+Rule   sol87   1987    only    -       Sep     17      11:54:45s 0:05:15 -
+Rule   sol87   1987    only    -       Sep     18      11:54:20s 0:05:40 -
+Rule   sol87   1987    only    -       Sep     19      11:54:00s 0:06:00 -
+Rule   sol87   1987    only    -       Sep     20      11:53:40s 0:06:20 -
+Rule   sol87   1987    only    -       Sep     21      11:53:15s 0:06:45 -
+Rule   sol87   1987    only    -       Sep     22      11:52:55s 0:07:05 -
+Rule   sol87   1987    only    -       Sep     23      11:52:35s 0:07:25 -
+Rule   sol87   1987    only    -       Sep     24      11:52:15s 0:07:45 -
+Rule   sol87   1987    only    -       Sep     25      11:51:55s 0:08:05 -
+Rule   sol87   1987    only    -       Sep     26      11:51:35s 0:08:25 -
+Rule   sol87   1987    only    -       Sep     27      11:51:10s 0:08:50 -
+Rule   sol87   1987    only    -       Sep     28      11:50:50s 0:09:10 -
+Rule   sol87   1987    only    -       Sep     29      11:50:30s 0:09:30 -
+Rule   sol87   1987    only    -       Sep     30      11:50:10s 0:09:50 -
+Rule   sol87   1987    only    -       Oct     1       11:49:50s 0:10:10 -
+Rule   sol87   1987    only    -       Oct     2       11:49:35s 0:10:25 -
+Rule   sol87   1987    only    -       Oct     3       11:49:15s 0:10:45 -
+Rule   sol87   1987    only    -       Oct     4       11:48:55s 0:11:05 -
+Rule   sol87   1987    only    -       Oct     5       11:48:35s 0:11:25 -
+Rule   sol87   1987    only    -       Oct     6       11:48:20s 0:11:40 -
+Rule   sol87   1987    only    -       Oct     7       11:48:00s 0:12:00 -
+Rule   sol87   1987    only    -       Oct     8       11:47:45s 0:12:15 -
+Rule   sol87   1987    only    -       Oct     9       11:47:25s 0:12:35 -
+Rule   sol87   1987    only    -       Oct     10      11:47:10s 0:12:50 -
+Rule   sol87   1987    only    -       Oct     11      11:46:55s 0:13:05 -
+Rule   sol87   1987    only    -       Oct     12      11:46:40s 0:13:20 -
+Rule   sol87   1987    only    -       Oct     13      11:46:25s 0:13:35 -
+Rule   sol87   1987    only    -       Oct     14      11:46:10s 0:13:50 -
+Rule   sol87   1987    only    -       Oct     15      11:45:55s 0:14:05 -
+Rule   sol87   1987    only    -       Oct     16      11:45:45s 0:14:15 -
+Rule   sol87   1987    only    -       Oct     17      11:45:30s 0:14:30 -
+Rule   sol87   1987    only    -       Oct     18      11:45:20s 0:14:40 -
+Rule   sol87   1987    only    -       Oct     19      11:45:05s 0:14:55 -
+Rule   sol87   1987    only    -       Oct     20      11:44:55s 0:15:05 -
+Rule   sol87   1987    only    -       Oct     21      11:44:45s 0:15:15 -
+Rule   sol87   1987    only    -       Oct     22      11:44:35s 0:15:25 -
+Rule   sol87   1987    only    -       Oct     23      11:44:25s 0:15:35 -
+Rule   sol87   1987    only    -       Oct     24      11:44:20s 0:15:40 -
+Rule   sol87   1987    only    -       Oct     25      11:44:10s 0:15:50 -
+Rule   sol87   1987    only    -       Oct     26      11:44:05s 0:15:55 -
+Rule   sol87   1987    only    -       Oct     27      11:43:55s 0:16:05 -
+Rule   sol87   1987    only    -       Oct     28      11:43:50s 0:16:10 -
+Rule   sol87   1987    only    -       Oct     29      11:43:45s 0:16:15 -
+Rule   sol87   1987    only    -       Oct     30      11:43:45s 0:16:15 -
+Rule   sol87   1987    only    -       Oct     31      11:43:40s 0:16:20 -
+Rule   sol87   1987    only    -       Nov     1       11:43:40s 0:16:20 -
+Rule   sol87   1987    only    -       Nov     2       11:43:35s 0:16:25 -
+Rule   sol87   1987    only    -       Nov     3       11:43:35s 0:16:25 -
+Rule   sol87   1987    only    -       Nov     4       11:43:35s 0:16:25 -
+Rule   sol87   1987    only    -       Nov     5       11:43:35s 0:16:25 -
+Rule   sol87   1987    only    -       Nov     6       11:43:40s 0:16:20 -
+Rule   sol87   1987    only    -       Nov     7       11:43:40s 0:16:20 -
+Rule   sol87   1987    only    -       Nov     8       11:43:45s 0:16:15 -
+Rule   sol87   1987    only    -       Nov     9       11:43:50s 0:16:10 -
+Rule   sol87   1987    only    -       Nov     10      11:43:55s 0:16:05 -
+Rule   sol87   1987    only    -       Nov     11      11:44:00s 0:16:00 -
+Rule   sol87   1987    only    -       Nov     12      11:44:05s 0:15:55 -
+Rule   sol87   1987    only    -       Nov     13      11:44:15s 0:15:45 -
+Rule   sol87   1987    only    -       Nov     14      11:44:20s 0:15:40 -
+Rule   sol87   1987    only    -       Nov     15      11:44:30s 0:15:30 -
+Rule   sol87   1987    only    -       Nov     16      11:44:40s 0:15:20 -
+Rule   sol87   1987    only    -       Nov     17      11:44:50s 0:15:10 -
+Rule   sol87   1987    only    -       Nov     18      11:45:05s 0:14:55 -
+Rule   sol87   1987    only    -       Nov     19      11:45:15s 0:14:45 -
+Rule   sol87   1987    only    -       Nov     20      11:45:30s 0:14:30 -
+Rule   sol87   1987    only    -       Nov     21      11:45:45s 0:14:15 -
+Rule   sol87   1987    only    -       Nov     22      11:46:00s 0:14:00 -
+Rule   sol87   1987    only    -       Nov     23      11:46:15s 0:13:45 -
+Rule   sol87   1987    only    -       Nov     24      11:46:30s 0:13:30 -
+Rule   sol87   1987    only    -       Nov     25      11:46:50s 0:13:10 -
+Rule   sol87   1987    only    -       Nov     26      11:47:10s 0:12:50 -
+Rule   sol87   1987    only    -       Nov     27      11:47:25s 0:12:35 -
+Rule   sol87   1987    only    -       Nov     28      11:47:45s 0:12:15 -
+Rule   sol87   1987    only    -       Nov     29      11:48:05s 0:11:55 -
+Rule   sol87   1987    only    -       Nov     30      11:48:30s 0:11:30 -
+Rule   sol87   1987    only    -       Dec     1       11:48:50s 0:11:10 -
+Rule   sol87   1987    only    -       Dec     2       11:49:10s 0:10:50 -
+Rule   sol87   1987    only    -       Dec     3       11:49:35s 0:10:25 -
+Rule   sol87   1987    only    -       Dec     4       11:50:00s 0:10:00 -
+Rule   sol87   1987    only    -       Dec     5       11:50:25s 0:09:35 -
+Rule   sol87   1987    only    -       Dec     6       11:50:50s 0:09:10 -
+Rule   sol87   1987    only    -       Dec     7       11:51:15s 0:08:45 -
+Rule   sol87   1987    only    -       Dec     8       11:51:40s 0:08:20 -
+Rule   sol87   1987    only    -       Dec     9       11:52:05s 0:07:55 -
+Rule   sol87   1987    only    -       Dec     10      11:52:30s 0:07:30 -
+Rule   sol87   1987    only    -       Dec     11      11:53:00s 0:07:00 -
+Rule   sol87   1987    only    -       Dec     12      11:53:25s 0:06:35 -
+Rule   sol87   1987    only    -       Dec     13      11:53:55s 0:06:05 -
+Rule   sol87   1987    only    -       Dec     14      11:54:25s 0:05:35 -
+Rule   sol87   1987    only    -       Dec     15      11:54:50s 0:05:10 -
+Rule   sol87   1987    only    -       Dec     16      11:55:20s 0:04:40 -
+Rule   sol87   1987    only    -       Dec     17      11:55:50s 0:04:10 -
+Rule   sol87   1987    only    -       Dec     18      11:56:20s 0:03:40 -
+Rule   sol87   1987    only    -       Dec     19      11:56:50s 0:03:10 -
+Rule   sol87   1987    only    -       Dec     20      11:57:20s 0:02:40 -
+Rule   sol87   1987    only    -       Dec     21      11:57:50s 0:02:10 -
+Rule   sol87   1987    only    -       Dec     22      11:58:20s 0:01:40 -
+Rule   sol87   1987    only    -       Dec     23      11:58:50s 0:01:10 -
+Rule   sol87   1987    only    -       Dec     24      11:59:20s 0:00:40 -
+Rule   sol87   1987    only    -       Dec     25      11:59:50s 0:00:10 -
+Rule   sol87   1987    only    -       Dec     26      12:00:20s -0:00:20 -
+Rule   sol87   1987    only    -       Dec     27      12:00:45s -0:00:45 -
+Rule   sol87   1987    only    -       Dec     28      12:01:15s -0:01:15 -
+Rule   sol87   1987    only    -       Dec     29      12:01:45s -0:01:45 -
+Rule   sol87   1987    only    -       Dec     30      12:02:15s -0:02:15 -
+Rule   sol87   1987    only    -       Dec     31      12:02:45s -0:02:45 -
+
+# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
+# Before and after 1987, we'll operate on local mean solar time.
+
+# Zone NAME            GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
+Zone   Asia/Riyadh87   3:07:04 -               ??      1987
+                       3:07:04 sol87           ??      1988
+                       3:07:04 -               ??
+# For backward compatibility...
+Link   Asia/Riyadh87   Mideast/Riyadh87
diff --git a/zic.tproj/datfiles/solar88 b/zic.tproj/datfiles/solar88
new file mode 100644 (file)
index 0000000..917fe5a
--- /dev/null
@@ -0,0 +1,389 @@
+#      $OpenBSD: solar88,v 1.3 1997/01/14 04:36:56 millert Exp $
+# @(#)solar88  7.3
+
+# Apparent noon times below are for Riyadh; they're a bit off for other places.
+# Times were computed using formulas in the U.S. Naval Observatory's
+# Almanac for Computers 1988; the formulas "will give EqT to an accuracy of
+# [plus or minus two] seconds during the current year."
+#
+# Rounding to the nearest five seconds results in fewer than
+# 256 different "time types"--a limit that's faced because time types are
+# stored on disk as unsigned chars.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   sol88   1988    only    -       Jan     1       12:03:15s -0:03:15 -
+Rule   sol88   1988    only    -       Jan     2       12:03:40s -0:03:40 -
+Rule   sol88   1988    only    -       Jan     3       12:04:10s -0:04:10 -
+Rule   sol88   1988    only    -       Jan     4       12:04:40s -0:04:40 -
+Rule   sol88   1988    only    -       Jan     5       12:05:05s -0:05:05 -
+Rule   sol88   1988    only    -       Jan     6       12:05:30s -0:05:30 -
+Rule   sol88   1988    only    -       Jan     7       12:06:00s -0:06:00 -
+Rule   sol88   1988    only    -       Jan     8       12:06:25s -0:06:25 -
+Rule   sol88   1988    only    -       Jan     9       12:06:50s -0:06:50 -
+Rule   sol88   1988    only    -       Jan     10      12:07:15s -0:07:15 -
+Rule   sol88   1988    only    -       Jan     11      12:07:40s -0:07:40 -
+Rule   sol88   1988    only    -       Jan     12      12:08:05s -0:08:05 -
+Rule   sol88   1988    only    -       Jan     13      12:08:25s -0:08:25 -
+Rule   sol88   1988    only    -       Jan     14      12:08:50s -0:08:50 -
+Rule   sol88   1988    only    -       Jan     15      12:09:10s -0:09:10 -
+Rule   sol88   1988    only    -       Jan     16      12:09:30s -0:09:30 -
+Rule   sol88   1988    only    -       Jan     17      12:09:50s -0:09:50 -
+Rule   sol88   1988    only    -       Jan     18      12:10:10s -0:10:10 -
+Rule   sol88   1988    only    -       Jan     19      12:10:30s -0:10:30 -
+Rule   sol88   1988    only    -       Jan     20      12:10:50s -0:10:50 -
+Rule   sol88   1988    only    -       Jan     21      12:11:05s -0:11:05 -
+Rule   sol88   1988    only    -       Jan     22      12:11:25s -0:11:25 -
+Rule   sol88   1988    only    -       Jan     23      12:11:40s -0:11:40 -
+Rule   sol88   1988    only    -       Jan     24      12:11:55s -0:11:55 -
+Rule   sol88   1988    only    -       Jan     25      12:12:10s -0:12:10 -
+Rule   sol88   1988    only    -       Jan     26      12:12:25s -0:12:25 -
+Rule   sol88   1988    only    -       Jan     27      12:12:40s -0:12:40 -
+Rule   sol88   1988    only    -       Jan     28      12:12:50s -0:12:50 -
+Rule   sol88   1988    only    -       Jan     29      12:13:00s -0:13:00 -
+Rule   sol88   1988    only    -       Jan     30      12:13:10s -0:13:10 -
+Rule   sol88   1988    only    -       Jan     31      12:13:20s -0:13:20 -
+Rule   sol88   1988    only    -       Feb     1       12:13:30s -0:13:30 -
+Rule   sol88   1988    only    -       Feb     2       12:13:40s -0:13:40 -
+Rule   sol88   1988    only    -       Feb     3       12:13:45s -0:13:45 -
+Rule   sol88   1988    only    -       Feb     4       12:13:55s -0:13:55 -
+Rule   sol88   1988    only    -       Feb     5       12:14:00s -0:14:00 -
+Rule   sol88   1988    only    -       Feb     6       12:14:05s -0:14:05 -
+Rule   sol88   1988    only    -       Feb     7       12:14:10s -0:14:10 -
+Rule   sol88   1988    only    -       Feb     8       12:14:10s -0:14:10 -
+Rule   sol88   1988    only    -       Feb     9       12:14:15s -0:14:15 -
+Rule   sol88   1988    only    -       Feb     10      12:14:15s -0:14:15 -
+Rule   sol88   1988    only    -       Feb     11      12:14:15s -0:14:15 -
+Rule   sol88   1988    only    -       Feb     12      12:14:15s -0:14:15 -
+Rule   sol88   1988    only    -       Feb     13      12:14:15s -0:14:15 -
+Rule   sol88   1988    only    -       Feb     14      12:14:15s -0:14:15 -
+Rule   sol88   1988    only    -       Feb     15      12:14:10s -0:14:10 -
+Rule   sol88   1988    only    -       Feb     16      12:14:10s -0:14:10 -
+Rule   sol88   1988    only    -       Feb     17      12:14:05s -0:14:05 -
+Rule   sol88   1988    only    -       Feb     18      12:14:00s -0:14:00 -
+Rule   sol88   1988    only    -       Feb     19      12:13:55s -0:13:55 -
+Rule   sol88   1988    only    -       Feb     20      12:13:50s -0:13:50 -
+Rule   sol88   1988    only    -       Feb     21      12:13:45s -0:13:45 -
+Rule   sol88   1988    only    -       Feb     22      12:13:40s -0:13:40 -
+Rule   sol88   1988    only    -       Feb     23      12:13:30s -0:13:30 -
+Rule   sol88   1988    only    -       Feb     24      12:13:20s -0:13:20 -
+Rule   sol88   1988    only    -       Feb     25      12:13:15s -0:13:15 -
+Rule   sol88   1988    only    -       Feb     26      12:13:05s -0:13:05 -
+Rule   sol88   1988    only    -       Feb     27      12:12:55s -0:12:55 -
+Rule   sol88   1988    only    -       Feb     28      12:12:45s -0:12:45 -
+Rule   sol88   1988    only    -       Feb     29      12:12:30s -0:12:30 -
+Rule   sol88   1988    only    -       Mar     1       12:12:20s -0:12:20 -
+Rule   sol88   1988    only    -       Mar     2       12:12:10s -0:12:10 -
+Rule   sol88   1988    only    -       Mar     3       12:11:55s -0:11:55 -
+Rule   sol88   1988    only    -       Mar     4       12:11:45s -0:11:45 -
+Rule   sol88   1988    only    -       Mar     5       12:11:30s -0:11:30 -
+Rule   sol88   1988    only    -       Mar     6       12:11:15s -0:11:15 -
+Rule   sol88   1988    only    -       Mar     7       12:11:00s -0:11:00 -
+Rule   sol88   1988    only    -       Mar     8       12:10:45s -0:10:45 -
+Rule   sol88   1988    only    -       Mar     9       12:10:30s -0:10:30 -
+Rule   sol88   1988    only    -       Mar     10      12:10:15s -0:10:15 -
+Rule   sol88   1988    only    -       Mar     11      12:10:00s -0:10:00 -
+Rule   sol88   1988    only    -       Mar     12      12:09:45s -0:09:45 -
+Rule   sol88   1988    only    -       Mar     13      12:09:30s -0:09:30 -
+Rule   sol88   1988    only    -       Mar     14      12:09:10s -0:09:10 -
+Rule   sol88   1988    only    -       Mar     15      12:08:55s -0:08:55 -
+Rule   sol88   1988    only    -       Mar     16      12:08:40s -0:08:40 -
+Rule   sol88   1988    only    -       Mar     17      12:08:20s -0:08:20 -
+Rule   sol88   1988    only    -       Mar     18      12:08:05s -0:08:05 -
+Rule   sol88   1988    only    -       Mar     19      12:07:45s -0:07:45 -
+Rule   sol88   1988    only    -       Mar     20      12:07:30s -0:07:30 -
+Rule   sol88   1988    only    -       Mar     21      12:07:10s -0:07:10 -
+Rule   sol88   1988    only    -       Mar     22      12:06:50s -0:06:50 -
+Rule   sol88   1988    only    -       Mar     23      12:06:35s -0:06:35 -
+Rule   sol88   1988    only    -       Mar     24      12:06:15s -0:06:15 -
+Rule   sol88   1988    only    -       Mar     25      12:06:00s -0:06:00 -
+Rule   sol88   1988    only    -       Mar     26      12:05:40s -0:05:40 -
+Rule   sol88   1988    only    -       Mar     27      12:05:20s -0:05:20 -
+Rule   sol88   1988    only    -       Mar     28      12:05:05s -0:05:05 -
+Rule   sol88   1988    only    -       Mar     29      12:04:45s -0:04:45 -
+Rule   sol88   1988    only    -       Mar     30      12:04:25s -0:04:25 -
+Rule   sol88   1988    only    -       Mar     31      12:04:10s -0:04:10 -
+Rule   sol88   1988    only    -       Apr     1       12:03:50s -0:03:50 -
+Rule   sol88   1988    only    -       Apr     2       12:03:35s -0:03:35 -
+Rule   sol88   1988    only    -       Apr     3       12:03:15s -0:03:15 -
+Rule   sol88   1988    only    -       Apr     4       12:03:00s -0:03:00 -
+Rule   sol88   1988    only    -       Apr     5       12:02:40s -0:02:40 -
+Rule   sol88   1988    only    -       Apr     6       12:02:25s -0:02:25 -
+Rule   sol88   1988    only    -       Apr     7       12:02:05s -0:02:05 -
+Rule   sol88   1988    only    -       Apr     8       12:01:50s -0:01:50 -
+Rule   sol88   1988    only    -       Apr     9       12:01:35s -0:01:35 -
+Rule   sol88   1988    only    -       Apr     10      12:01:15s -0:01:15 -
+Rule   sol88   1988    only    -       Apr     11      12:01:00s -0:01:00 -
+Rule   sol88   1988    only    -       Apr     12      12:00:45s -0:00:45 -
+Rule   sol88   1988    only    -       Apr     13      12:00:30s -0:00:30 -
+Rule   sol88   1988    only    -       Apr     14      12:00:15s -0:00:15 -
+Rule   sol88   1988    only    -       Apr     15      12:00:00s 0:00:00 -
+Rule   sol88   1988    only    -       Apr     16      11:59:45s 0:00:15 -
+Rule   sol88   1988    only    -       Apr     17      11:59:30s 0:00:30 -
+Rule   sol88   1988    only    -       Apr     18      11:59:20s 0:00:40 -
+Rule   sol88   1988    only    -       Apr     19      11:59:05s 0:00:55 -
+Rule   sol88   1988    only    -       Apr     20      11:58:55s 0:01:05 -
+Rule   sol88   1988    only    -       Apr     21      11:58:40s 0:01:20 -
+Rule   sol88   1988    only    -       Apr     22      11:58:30s 0:01:30 -
+Rule   sol88   1988    only    -       Apr     23      11:58:15s 0:01:45 -
+Rule   sol88   1988    only    -       Apr     24      11:58:05s 0:01:55 -
+Rule   sol88   1988    only    -       Apr     25      11:57:55s 0:02:05 -
+Rule   sol88   1988    only    -       Apr     26      11:57:45s 0:02:15 -
+Rule   sol88   1988    only    -       Apr     27      11:57:35s 0:02:25 -
+Rule   sol88   1988    only    -       Apr     28      11:57:30s 0:02:30 -
+Rule   sol88   1988    only    -       Apr     29      11:57:20s 0:02:40 -
+Rule   sol88   1988    only    -       Apr     30      11:57:10s 0:02:50 -
+Rule   sol88   1988    only    -       May     1       11:57:05s 0:02:55 -
+Rule   sol88   1988    only    -       May     2       11:56:55s 0:03:05 -
+Rule   sol88   1988    only    -       May     3       11:56:50s 0:03:10 -
+Rule   sol88   1988    only    -       May     4       11:56:45s 0:03:15 -
+Rule   sol88   1988    only    -       May     5       11:56:40s 0:03:20 -
+Rule   sol88   1988    only    -       May     6       11:56:35s 0:03:25 -
+Rule   sol88   1988    only    -       May     7       11:56:30s 0:03:30 -
+Rule   sol88   1988    only    -       May     8       11:56:25s 0:03:35 -
+Rule   sol88   1988    only    -       May     9       11:56:25s 0:03:35 -
+Rule   sol88   1988    only    -       May     10      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     11      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     12      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     13      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     14      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     15      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     16      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     17      11:56:20s 0:03:40 -
+Rule   sol88   1988    only    -       May     18      11:56:25s 0:03:35 -
+Rule   sol88   1988    only    -       May     19      11:56:25s 0:03:35 -
+Rule   sol88   1988    only    -       May     20      11:56:30s 0:03:30 -
+Rule   sol88   1988    only    -       May     21      11:56:35s 0:03:25 -
+Rule   sol88   1988    only    -       May     22      11:56:40s 0:03:20 -
+Rule   sol88   1988    only    -       May     23      11:56:45s 0:03:15 -
+Rule   sol88   1988    only    -       May     24      11:56:50s 0:03:10 -
+Rule   sol88   1988    only    -       May     25      11:56:55s 0:03:05 -
+Rule   sol88   1988    only    -       May     26      11:57:00s 0:03:00 -
+Rule   sol88   1988    only    -       May     27      11:57:05s 0:02:55 -
+Rule   sol88   1988    only    -       May     28      11:57:15s 0:02:45 -
+Rule   sol88   1988    only    -       May     29      11:57:20s 0:02:40 -
+Rule   sol88   1988    only    -       May     30      11:57:30s 0:02:30 -
+Rule   sol88   1988    only    -       May     31      11:57:40s 0:02:20 -
+Rule   sol88   1988    only    -       Jun     1       11:57:50s 0:02:10 -
+Rule   sol88   1988    only    -       Jun     2       11:57:55s 0:02:05 -
+Rule   sol88   1988    only    -       Jun     3       11:58:05s 0:01:55 -
+Rule   sol88   1988    only    -       Jun     4       11:58:15s 0:01:45 -
+Rule   sol88   1988    only    -       Jun     5       11:58:30s 0:01:30 -
+Rule   sol88   1988    only    -       Jun     6       11:58:40s 0:01:20 -
+Rule   sol88   1988    only    -       Jun     7       11:58:50s 0:01:10 -
+Rule   sol88   1988    only    -       Jun     8       11:59:00s 0:01:00 -
+Rule   sol88   1988    only    -       Jun     9       11:59:15s 0:00:45 -
+Rule   sol88   1988    only    -       Jun     10      11:59:25s 0:00:35 -
+Rule   sol88   1988    only    -       Jun     11      11:59:35s 0:00:25 -
+Rule   sol88   1988    only    -       Jun     12      11:59:50s 0:00:10 -
+Rule   sol88   1988    only    -       Jun     13      12:00:00s 0:00:00 -
+Rule   sol88   1988    only    -       Jun     14      12:00:15s -0:00:15 -
+Rule   sol88   1988    only    -       Jun     15      12:00:25s -0:00:25 -
+Rule   sol88   1988    only    -       Jun     16      12:00:40s -0:00:40 -
+Rule   sol88   1988    only    -       Jun     17      12:00:55s -0:00:55 -
+Rule   sol88   1988    only    -       Jun     18      12:01:05s -0:01:05 -
+Rule   sol88   1988    only    -       Jun     19      12:01:20s -0:01:20 -
+Rule   sol88   1988    only    -       Jun     20      12:01:30s -0:01:30 -
+Rule   sol88   1988    only    -       Jun     21      12:01:45s -0:01:45 -
+Rule   sol88   1988    only    -       Jun     22      12:02:00s -0:02:00 -
+Rule   sol88   1988    only    -       Jun     23      12:02:10s -0:02:10 -
+Rule   sol88   1988    only    -       Jun     24      12:02:25s -0:02:25 -
+Rule   sol88   1988    only    -       Jun     25      12:02:35s -0:02:35 -
+Rule   sol88   1988    only    -       Jun     26      12:02:50s -0:02:50 -
+Rule   sol88   1988    only    -       Jun     27      12:03:00s -0:03:00 -
+Rule   sol88   1988    only    -       Jun     28      12:03:15s -0:03:15 -
+Rule   sol88   1988    only    -       Jun     29      12:03:25s -0:03:25 -
+Rule   sol88   1988    only    -       Jun     30      12:03:40s -0:03:40 -
+Rule   sol88   1988    only    -       Jul     1       12:03:50s -0:03:50 -
+Rule   sol88   1988    only    -       Jul     2       12:04:00s -0:04:00 -
+Rule   sol88   1988    only    -       Jul     3       12:04:10s -0:04:10 -
+Rule   sol88   1988    only    -       Jul     4       12:04:25s -0:04:25 -
+Rule   sol88   1988    only    -       Jul     5       12:04:35s -0:04:35 -
+Rule   sol88   1988    only    -       Jul     6       12:04:45s -0:04:45 -
+Rule   sol88   1988    only    -       Jul     7       12:04:55s -0:04:55 -
+Rule   sol88   1988    only    -       Jul     8       12:05:05s -0:05:05 -
+Rule   sol88   1988    only    -       Jul     9       12:05:10s -0:05:10 -
+Rule   sol88   1988    only    -       Jul     10      12:05:20s -0:05:20 -
+Rule   sol88   1988    only    -       Jul     11      12:05:30s -0:05:30 -
+Rule   sol88   1988    only    -       Jul     12      12:05:35s -0:05:35 -
+Rule   sol88   1988    only    -       Jul     13      12:05:45s -0:05:45 -
+Rule   sol88   1988    only    -       Jul     14      12:05:50s -0:05:50 -
+Rule   sol88   1988    only    -       Jul     15      12:05:55s -0:05:55 -
+Rule   sol88   1988    only    -       Jul     16      12:06:00s -0:06:00 -
+Rule   sol88   1988    only    -       Jul     17      12:06:05s -0:06:05 -
+Rule   sol88   1988    only    -       Jul     18      12:06:10s -0:06:10 -
+Rule   sol88   1988    only    -       Jul     19      12:06:15s -0:06:15 -
+Rule   sol88   1988    only    -       Jul     20      12:06:20s -0:06:20 -
+Rule   sol88   1988    only    -       Jul     21      12:06:25s -0:06:25 -
+Rule   sol88   1988    only    -       Jul     22      12:06:25s -0:06:25 -
+Rule   sol88   1988    only    -       Jul     23      12:06:25s -0:06:25 -
+Rule   sol88   1988    only    -       Jul     24      12:06:30s -0:06:30 -
+Rule   sol88   1988    only    -       Jul     25      12:06:30s -0:06:30 -
+Rule   sol88   1988    only    -       Jul     26      12:06:30s -0:06:30 -
+Rule   sol88   1988    only    -       Jul     27      12:06:30s -0:06:30 -
+Rule   sol88   1988    only    -       Jul     28      12:06:30s -0:06:30 -
+Rule   sol88   1988    only    -       Jul     29      12:06:25s -0:06:25 -
+Rule   sol88   1988    only    -       Jul     30      12:06:25s -0:06:25 -
+Rule   sol88   1988    only    -       Jul     31      12:06:20s -0:06:20 -
+Rule   sol88   1988    only    -       Aug     1       12:06:15s -0:06:15 -
+Rule   sol88   1988    only    -       Aug     2       12:06:15s -0:06:15 -
+Rule   sol88   1988    only    -       Aug     3       12:06:10s -0:06:10 -
+Rule   sol88   1988    only    -       Aug     4       12:06:05s -0:06:05 -
+Rule   sol88   1988    only    -       Aug     5       12:05:55s -0:05:55 -
+Rule   sol88   1988    only    -       Aug     6       12:05:50s -0:05:50 -
+Rule   sol88   1988    only    -       Aug     7       12:05:45s -0:05:45 -
+Rule   sol88   1988    only    -       Aug     8       12:05:35s -0:05:35 -
+Rule   sol88   1988    only    -       Aug     9       12:05:25s -0:05:25 -
+Rule   sol88   1988    only    -       Aug     10      12:05:20s -0:05:20 -
+Rule   sol88   1988    only    -       Aug     11      12:05:10s -0:05:10 -
+Rule   sol88   1988    only    -       Aug     12      12:05:00s -0:05:00 -
+Rule   sol88   1988    only    -       Aug     13      12:04:50s -0:04:50 -
+Rule   sol88   1988    only    -       Aug     14      12:04:35s -0:04:35 -
+Rule   sol88   1988    only    -       Aug     15      12:04:25s -0:04:25 -
+Rule   sol88   1988    only    -       Aug     16      12:04:15s -0:04:15 -
+Rule   sol88   1988    only    -       Aug     17      12:04:00s -0:04:00 -
+Rule   sol88   1988    only    -       Aug     18      12:03:50s -0:03:50 -
+Rule   sol88   1988    only    -       Aug     19      12:03:35s -0:03:35 -
+Rule   sol88   1988    only    -       Aug     20      12:03:20s -0:03:20 -
+Rule   sol88   1988    only    -       Aug     21      12:03:05s -0:03:05 -
+Rule   sol88   1988    only    -       Aug     22      12:02:50s -0:02:50 -
+Rule   sol88   1988    only    -       Aug     23      12:02:35s -0:02:35 -
+Rule   sol88   1988    only    -       Aug     24      12:02:20s -0:02:20 -
+Rule   sol88   1988    only    -       Aug     25      12:02:00s -0:02:00 -
+Rule   sol88   1988    only    -       Aug     26      12:01:45s -0:01:45 -
+Rule   sol88   1988    only    -       Aug     27      12:01:30s -0:01:30 -
+Rule   sol88   1988    only    -       Aug     28      12:01:10s -0:01:10 -
+Rule   sol88   1988    only    -       Aug     29      12:00:50s -0:00:50 -
+Rule   sol88   1988    only    -       Aug     30      12:00:35s -0:00:35 -
+Rule   sol88   1988    only    -       Aug     31      12:00:15s -0:00:15 -
+Rule   sol88   1988    only    -       Sep     1       11:59:55s 0:00:05 -
+Rule   sol88   1988    only    -       Sep     2       11:59:35s 0:00:25 -
+Rule   sol88   1988    only    -       Sep     3       11:59:20s 0:00:40 -
+Rule   sol88   1988    only    -       Sep     4       11:59:00s 0:01:00 -
+Rule   sol88   1988    only    -       Sep     5       11:58:40s 0:01:20 -
+Rule   sol88   1988    only    -       Sep     6       11:58:20s 0:01:40 -
+Rule   sol88   1988    only    -       Sep     7       11:58:00s 0:02:00 -
+Rule   sol88   1988    only    -       Sep     8       11:57:35s 0:02:25 -
+Rule   sol88   1988    only    -       Sep     9       11:57:15s 0:02:45 -
+Rule   sol88   1988    only    -       Sep     10      11:56:55s 0:03:05 -
+Rule   sol88   1988    only    -       Sep     11      11:56:35s 0:03:25 -
+Rule   sol88   1988    only    -       Sep     12      11:56:15s 0:03:45 -
+Rule   sol88   1988    only    -       Sep     13      11:55:50s 0:04:10 -
+Rule   sol88   1988    only    -       Sep     14      11:55:30s 0:04:30 -
+Rule   sol88   1988    only    -       Sep     15      11:55:10s 0:04:50 -
+Rule   sol88   1988    only    -       Sep     16      11:54:50s 0:05:10 -
+Rule   sol88   1988    only    -       Sep     17      11:54:25s 0:05:35 -
+Rule   sol88   1988    only    -       Sep     18      11:54:05s 0:05:55 -
+Rule   sol88   1988    only    -       Sep     19      11:53:45s 0:06:15 -
+Rule   sol88   1988    only    -       Sep     20      11:53:25s 0:06:35 -
+Rule   sol88   1988    only    -       Sep     21      11:53:00s 0:07:00 -
+Rule   sol88   1988    only    -       Sep     22      11:52:40s 0:07:20 -
+Rule   sol88   1988    only    -       Sep     23      11:52:20s 0:07:40 -
+Rule   sol88   1988    only    -       Sep     24      11:52:00s 0:08:00 -
+Rule   sol88   1988    only    -       Sep     25      11:51:40s 0:08:20 -
+Rule   sol88   1988    only    -       Sep     26      11:51:15s 0:08:45 -
+Rule   sol88   1988    only    -       Sep     27      11:50:55s 0:09:05 -
+Rule   sol88   1988    only    -       Sep     28      11:50:35s 0:09:25 -
+Rule   sol88   1988    only    -       Sep     29      11:50:15s 0:09:45 -
+Rule   sol88   1988    only    -       Sep     30      11:49:55s 0:10:05 -
+Rule   sol88   1988    only    -       Oct     1       11:49:35s 0:10:25 -
+Rule   sol88   1988    only    -       Oct     2       11:49:20s 0:10:40 -
+Rule   sol88   1988    only    -       Oct     3       11:49:00s 0:11:00 -
+Rule   sol88   1988    only    -       Oct     4       11:48:40s 0:11:20 -
+Rule   sol88   1988    only    -       Oct     5       11:48:25s 0:11:35 -
+Rule   sol88   1988    only    -       Oct     6       11:48:05s 0:11:55 -
+Rule   sol88   1988    only    -       Oct     7       11:47:50s 0:12:10 -
+Rule   sol88   1988    only    -       Oct     8       11:47:30s 0:12:30 -
+Rule   sol88   1988    only    -       Oct     9       11:47:15s 0:12:45 -
+Rule   sol88   1988    only    -       Oct     10      11:47:00s 0:13:00 -
+Rule   sol88   1988    only    -       Oct     11      11:46:45s 0:13:15 -
+Rule   sol88   1988    only    -       Oct     12      11:46:30s 0:13:30 -
+Rule   sol88   1988    only    -       Oct     13      11:46:15s 0:13:45 -
+Rule   sol88   1988    only    -       Oct     14      11:46:00s 0:14:00 -
+Rule   sol88   1988    only    -       Oct     15      11:45:45s 0:14:15 -
+Rule   sol88   1988    only    -       Oct     16      11:45:35s 0:14:25 -
+Rule   sol88   1988    only    -       Oct     17      11:45:20s 0:14:40 -
+Rule   sol88   1988    only    -       Oct     18      11:45:10s 0:14:50 -
+Rule   sol88   1988    only    -       Oct     19      11:45:00s 0:15:00 -
+Rule   sol88   1988    only    -       Oct     20      11:44:45s 0:15:15 -
+Rule   sol88   1988    only    -       Oct     21      11:44:40s 0:15:20 -
+Rule   sol88   1988    only    -       Oct     22      11:44:30s 0:15:30 -
+Rule   sol88   1988    only    -       Oct     23      11:44:20s 0:15:40 -
+Rule   sol88   1988    only    -       Oct     24      11:44:10s 0:15:50 -
+Rule   sol88   1988    only    -       Oct     25      11:44:05s 0:15:55 -
+Rule   sol88   1988    only    -       Oct     26      11:44:00s 0:16:00 -
+Rule   sol88   1988    only    -       Oct     27      11:43:55s 0:16:05 -
+Rule   sol88   1988    only    -       Oct     28      11:43:50s 0:16:10 -
+Rule   sol88   1988    only    -       Oct     29      11:43:45s 0:16:15 -
+Rule   sol88   1988    only    -       Oct     30      11:43:40s 0:16:20 -
+Rule   sol88   1988    only    -       Oct     31      11:43:40s 0:16:20 -
+Rule   sol88   1988    only    -       Nov     1       11:43:35s 0:16:25 -
+Rule   sol88   1988    only    -       Nov     2       11:43:35s 0:16:25 -
+Rule   sol88   1988    only    -       Nov     3       11:43:35s 0:16:25 -
+Rule   sol88   1988    only    -       Nov     4       11:43:35s 0:16:25 -
+Rule   sol88   1988    only    -       Nov     5       11:43:40s 0:16:20 -
+Rule   sol88   1988    only    -       Nov     6       11:43:40s 0:16:20 -
+Rule   sol88   1988    only    -       Nov     7       11:43:45s 0:16:15 -
+Rule   sol88   1988    only    -       Nov     8       11:43:45s 0:16:15 -
+Rule   sol88   1988    only    -       Nov     9       11:43:50s 0:16:10 -
+Rule   sol88   1988    only    -       Nov     10      11:44:00s 0:16:00 -
+Rule   sol88   1988    only    -       Nov     11      11:44:05s 0:15:55 -
+Rule   sol88   1988    only    -       Nov     12      11:44:10s 0:15:50 -
+Rule   sol88   1988    only    -       Nov     13      11:44:20s 0:15:40 -
+Rule   sol88   1988    only    -       Nov     14      11:44:30s 0:15:30 -
+Rule   sol88   1988    only    -       Nov     15      11:44:40s 0:15:20 -
+Rule   sol88   1988    only    -       Nov     16      11:44:50s 0:15:10 -
+Rule   sol88   1988    only    -       Nov     17      11:45:00s 0:15:00 -
+Rule   sol88   1988    only    -       Nov     18      11:45:15s 0:14:45 -
+Rule   sol88   1988    only    -       Nov     19      11:45:25s 0:14:35 -
+Rule   sol88   1988    only    -       Nov     20      11:45:40s 0:14:20 -
+Rule   sol88   1988    only    -       Nov     21      11:45:55s 0:14:05 -
+Rule   sol88   1988    only    -       Nov     22      11:46:10s 0:13:50 -
+Rule   sol88   1988    only    -       Nov     23      11:46:30s 0:13:30 -
+Rule   sol88   1988    only    -       Nov     24      11:46:45s 0:13:15 -
+Rule   sol88   1988    only    -       Nov     25      11:47:05s 0:12:55 -
+Rule   sol88   1988    only    -       Nov     26      11:47:20s 0:12:40 -
+Rule   sol88   1988    only    -       Nov     27      11:47:40s 0:12:20 -
+Rule   sol88   1988    only    -       Nov     28      11:48:00s 0:12:00 -
+Rule   sol88   1988    only    -       Nov     29      11:48:25s 0:11:35 -
+Rule   sol88   1988    only    -       Nov     30      11:48:45s 0:11:15 -
+Rule   sol88   1988    only    -       Dec     1       11:49:05s 0:10:55 -
+Rule   sol88   1988    only    -       Dec     2       11:49:30s 0:10:30 -
+Rule   sol88   1988    only    -       Dec     3       11:49:55s 0:10:05 -
+Rule   sol88   1988    only    -       Dec     4       11:50:15s 0:09:45 -
+Rule   sol88   1988    only    -       Dec     5       11:50:40s 0:09:20 -
+Rule   sol88   1988    only    -       Dec     6       11:51:05s 0:08:55 -
+Rule   sol88   1988    only    -       Dec     7       11:51:35s 0:08:25 -
+Rule   sol88   1988    only    -       Dec     8       11:52:00s 0:08:00 -
+Rule   sol88   1988    only    -       Dec     9       11:52:25s 0:07:35 -
+Rule   sol88   1988    only    -       Dec     10      11:52:55s 0:07:05 -
+Rule   sol88   1988    only    -       Dec     11      11:53:20s 0:06:40 -
+Rule   sol88   1988    only    -       Dec     12      11:53:50s 0:06:10 -
+Rule   sol88   1988    only    -       Dec     13      11:54:15s 0:05:45 -
+Rule   sol88   1988    only    -       Dec     14      11:54:45s 0:05:15 -
+Rule   sol88   1988    only    -       Dec     15      11:55:15s 0:04:45 -
+Rule   sol88   1988    only    -       Dec     16      11:55:45s 0:04:15 -
+Rule   sol88   1988    only    -       Dec     17      11:56:15s 0:03:45 -
+Rule   sol88   1988    only    -       Dec     18      11:56:40s 0:03:20 -
+Rule   sol88   1988    only    -       Dec     19      11:57:10s 0:02:50 -
+Rule   sol88   1988    only    -       Dec     20      11:57:40s 0:02:20 -
+Rule   sol88   1988    only    -       Dec     21      11:58:10s 0:01:50 -
+Rule   sol88   1988    only    -       Dec     22      11:58:40s 0:01:20 -
+Rule   sol88   1988    only    -       Dec     23      11:59:10s 0:00:50 -
+Rule   sol88   1988    only    -       Dec     24      11:59:40s 0:00:20 -
+Rule   sol88   1988    only    -       Dec     25      12:00:10s -0:00:10 -
+Rule   sol88   1988    only    -       Dec     26      12:00:40s -0:00:40 -
+Rule   sol88   1988    only    -       Dec     27      12:01:10s -0:01:10 -
+Rule   sol88   1988    only    -       Dec     28      12:01:40s -0:01:40 -
+Rule   sol88   1988    only    -       Dec     29      12:02:10s -0:02:10 -
+Rule   sol88   1988    only    -       Dec     30      12:02:35s -0:02:35 -
+Rule   sol88   1988    only    -       Dec     31      12:03:05s -0:03:05 -
+
+# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
+# Before and after 1988, we'll operate on local mean solar time.
+
+# Zone NAME            GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
+Zone   Asia/Riyadh88   3:07:04 -               ??      1988
+                       3:07:04 sol88           ??      1989
+                       3:07:04 -               ??
+# For backward compatibility...
+Link   Asia/Riyadh88   Mideast/Riyadh88
diff --git a/zic.tproj/datfiles/solar89 b/zic.tproj/datfiles/solar89
new file mode 100644 (file)
index 0000000..2d47f4c
--- /dev/null
@@ -0,0 +1,394 @@
+#      $OpenBSD: solar89,v 1.4 1997/01/14 04:36:57 millert Exp $
+# @(#)solar89  7.4
+
+# Apparent noon times below are for Riyadh; they're a bit off for other places.
+# Times were computed using a formula provided by the U. S. Naval Observatory:
+#      eqt = -105.8 * sin(l) + 596.2 * sin(2 * l) + 4.4 * sin(3 * l)
+#              -12.7 * sin(4 * l) - 429.0 * cos(l) - 2.1 * cos (2 * l)
+#              + 19.3 * cos(3 * l);
+# where l is the "mean longitude of the Sun" given by
+#      l = 279.642 degrees + 0.985647 * d
+# and d is the interval in days from January 0, 0 hours Universal Time
+# (equaling the day of the year plus the fraction of a day from zero hours).
+# The accuracy of the formula is plus or minus three seconds.
+#
+# Rounding to the nearest five seconds results in fewer than
+# 256 different "time types"--a limit that's faced because time types are
+# stored on disk as unsigned chars.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   sol89   1989    only    -       Jan     1       12:03:35s -0:03:35 -
+Rule   sol89   1989    only    -       Jan     2       12:04:05s -0:04:05 -
+Rule   sol89   1989    only    -       Jan     3       12:04:30s -0:04:30 -
+Rule   sol89   1989    only    -       Jan     4       12:05:00s -0:05:00 -
+Rule   sol89   1989    only    -       Jan     5       12:05:25s -0:05:25 -
+Rule   sol89   1989    only    -       Jan     6       12:05:50s -0:05:50 -
+Rule   sol89   1989    only    -       Jan     7       12:06:15s -0:06:15 -
+Rule   sol89   1989    only    -       Jan     8       12:06:45s -0:06:45 -
+Rule   sol89   1989    only    -       Jan     9       12:07:10s -0:07:10 -
+Rule   sol89   1989    only    -       Jan     10      12:07:35s -0:07:35 -
+Rule   sol89   1989    only    -       Jan     11      12:07:55s -0:07:55 -
+Rule   sol89   1989    only    -       Jan     12      12:08:20s -0:08:20 -
+Rule   sol89   1989    only    -       Jan     13      12:08:45s -0:08:45 -
+Rule   sol89   1989    only    -       Jan     14      12:09:05s -0:09:05 -
+Rule   sol89   1989    only    -       Jan     15      12:09:25s -0:09:25 -
+Rule   sol89   1989    only    -       Jan     16      12:09:45s -0:09:45 -
+Rule   sol89   1989    only    -       Jan     17      12:10:05s -0:10:05 -
+Rule   sol89   1989    only    -       Jan     18      12:10:25s -0:10:25 -
+Rule   sol89   1989    only    -       Jan     19      12:10:45s -0:10:45 -
+Rule   sol89   1989    only    -       Jan     20      12:11:05s -0:11:05 -
+Rule   sol89   1989    only    -       Jan     21      12:11:20s -0:11:20 -
+Rule   sol89   1989    only    -       Jan     22      12:11:35s -0:11:35 -
+Rule   sol89   1989    only    -       Jan     23      12:11:55s -0:11:55 -
+Rule   sol89   1989    only    -       Jan     24      12:12:10s -0:12:10 -
+Rule   sol89   1989    only    -       Jan     25      12:12:20s -0:12:20 -
+Rule   sol89   1989    only    -       Jan     26      12:12:35s -0:12:35 -
+Rule   sol89   1989    only    -       Jan     27      12:12:50s -0:12:50 -
+Rule   sol89   1989    only    -       Jan     28      12:13:00s -0:13:00 -
+Rule   sol89   1989    only    -       Jan     29      12:13:10s -0:13:10 -
+Rule   sol89   1989    only    -       Jan     30      12:13:20s -0:13:20 -
+Rule   sol89   1989    only    -       Jan     31      12:13:30s -0:13:30 -
+Rule   sol89   1989    only    -       Feb     1       12:13:40s -0:13:40 -
+Rule   sol89   1989    only    -       Feb     2       12:13:45s -0:13:45 -
+Rule   sol89   1989    only    -       Feb     3       12:13:55s -0:13:55 -
+Rule   sol89   1989    only    -       Feb     4       12:14:00s -0:14:00 -
+Rule   sol89   1989    only    -       Feb     5       12:14:05s -0:14:05 -
+Rule   sol89   1989    only    -       Feb     6       12:14:10s -0:14:10 -
+Rule   sol89   1989    only    -       Feb     7       12:14:10s -0:14:10 -
+Rule   sol89   1989    only    -       Feb     8       12:14:15s -0:14:15 -
+Rule   sol89   1989    only    -       Feb     9       12:14:15s -0:14:15 -
+Rule   sol89   1989    only    -       Feb     10      12:14:20s -0:14:20 -
+Rule   sol89   1989    only    -       Feb     11      12:14:20s -0:14:20 -
+Rule   sol89   1989    only    -       Feb     12      12:14:20s -0:14:20 -
+Rule   sol89   1989    only    -       Feb     13      12:14:15s -0:14:15 -
+Rule   sol89   1989    only    -       Feb     14      12:14:15s -0:14:15 -
+Rule   sol89   1989    only    -       Feb     15      12:14:10s -0:14:10 -
+Rule   sol89   1989    only    -       Feb     16      12:14:10s -0:14:10 -
+Rule   sol89   1989    only    -       Feb     17      12:14:05s -0:14:05 -
+Rule   sol89   1989    only    -       Feb     18      12:14:00s -0:14:00 -
+Rule   sol89   1989    only    -       Feb     19      12:13:55s -0:13:55 -
+Rule   sol89   1989    only    -       Feb     20      12:13:50s -0:13:50 -
+Rule   sol89   1989    only    -       Feb     21      12:13:40s -0:13:40 -
+Rule   sol89   1989    only    -       Feb     22      12:13:35s -0:13:35 -
+Rule   sol89   1989    only    -       Feb     23      12:13:25s -0:13:25 -
+Rule   sol89   1989    only    -       Feb     24      12:13:15s -0:13:15 -
+Rule   sol89   1989    only    -       Feb     25      12:13:05s -0:13:05 -
+Rule   sol89   1989    only    -       Feb     26      12:12:55s -0:12:55 -
+Rule   sol89   1989    only    -       Feb     27      12:12:45s -0:12:45 -
+Rule   sol89   1989    only    -       Feb     28      12:12:35s -0:12:35 -
+Rule   sol89   1989    only    -       Mar     1       12:12:25s -0:12:25 -
+Rule   sol89   1989    only    -       Mar     2       12:12:10s -0:12:10 -
+Rule   sol89   1989    only    -       Mar     3       12:12:00s -0:12:00 -
+Rule   sol89   1989    only    -       Mar     4       12:11:45s -0:11:45 -
+Rule   sol89   1989    only    -       Mar     5       12:11:35s -0:11:35 -
+Rule   sol89   1989    only    -       Mar     6       12:11:20s -0:11:20 -
+Rule   sol89   1989    only    -       Mar     7       12:11:05s -0:11:05 -
+Rule   sol89   1989    only    -       Mar     8       12:10:50s -0:10:50 -
+Rule   sol89   1989    only    -       Mar     9       12:10:35s -0:10:35 -
+Rule   sol89   1989    only    -       Mar     10      12:10:20s -0:10:20 -
+Rule   sol89   1989    only    -       Mar     11      12:10:05s -0:10:05 -
+Rule   sol89   1989    only    -       Mar     12      12:09:50s -0:09:50 -
+Rule   sol89   1989    only    -       Mar     13      12:09:30s -0:09:30 -
+Rule   sol89   1989    only    -       Mar     14      12:09:15s -0:09:15 -
+Rule   sol89   1989    only    -       Mar     15      12:09:00s -0:09:00 -
+Rule   sol89   1989    only    -       Mar     16      12:08:40s -0:08:40 -
+Rule   sol89   1989    only    -       Mar     17      12:08:25s -0:08:25 -
+Rule   sol89   1989    only    -       Mar     18      12:08:05s -0:08:05 -
+Rule   sol89   1989    only    -       Mar     19      12:07:50s -0:07:50 -
+Rule   sol89   1989    only    -       Mar     20      12:07:30s -0:07:30 -
+Rule   sol89   1989    only    -       Mar     21      12:07:15s -0:07:15 -
+Rule   sol89   1989    only    -       Mar     22      12:06:55s -0:06:55 -
+Rule   sol89   1989    only    -       Mar     23      12:06:35s -0:06:35 -
+Rule   sol89   1989    only    -       Mar     24      12:06:20s -0:06:20 -
+Rule   sol89   1989    only    -       Mar     25      12:06:00s -0:06:00 -
+Rule   sol89   1989    only    -       Mar     26      12:05:40s -0:05:40 -
+Rule   sol89   1989    only    -       Mar     27      12:05:25s -0:05:25 -
+Rule   sol89   1989    only    -       Mar     28      12:05:05s -0:05:05 -
+Rule   sol89   1989    only    -       Mar     29      12:04:50s -0:04:50 -
+Rule   sol89   1989    only    -       Mar     30      12:04:30s -0:04:30 -
+Rule   sol89   1989    only    -       Mar     31      12:04:10s -0:04:10 -
+Rule   sol89   1989    only    -       Apr     1       12:03:55s -0:03:55 -
+Rule   sol89   1989    only    -       Apr     2       12:03:35s -0:03:35 -
+Rule   sol89   1989    only    -       Apr     3       12:03:20s -0:03:20 -
+Rule   sol89   1989    only    -       Apr     4       12:03:00s -0:03:00 -
+Rule   sol89   1989    only    -       Apr     5       12:02:45s -0:02:45 -
+Rule   sol89   1989    only    -       Apr     6       12:02:25s -0:02:25 -
+Rule   sol89   1989    only    -       Apr     7       12:02:10s -0:02:10 -
+Rule   sol89   1989    only    -       Apr     8       12:01:50s -0:01:50 -
+Rule   sol89   1989    only    -       Apr     9       12:01:35s -0:01:35 -
+Rule   sol89   1989    only    -       Apr     10      12:01:20s -0:01:20 -
+Rule   sol89   1989    only    -       Apr     11      12:01:05s -0:01:05 -
+Rule   sol89   1989    only    -       Apr     12      12:00:50s -0:00:50 -
+Rule   sol89   1989    only    -       Apr     13      12:00:35s -0:00:35 -
+Rule   sol89   1989    only    -       Apr     14      12:00:20s -0:00:20 -
+Rule   sol89   1989    only    -       Apr     15      12:00:05s -0:00:05 -
+Rule   sol89   1989    only    -       Apr     16      11:59:50s 0:00:10 -
+Rule   sol89   1989    only    -       Apr     17      11:59:35s 0:00:25 -
+Rule   sol89   1989    only    -       Apr     18      11:59:20s 0:00:40 -
+Rule   sol89   1989    only    -       Apr     19      11:59:10s 0:00:50 -
+Rule   sol89   1989    only    -       Apr     20      11:58:55s 0:01:05 -
+Rule   sol89   1989    only    -       Apr     21      11:58:45s 0:01:15 -
+Rule   sol89   1989    only    -       Apr     22      11:58:30s 0:01:30 -
+Rule   sol89   1989    only    -       Apr     23      11:58:20s 0:01:40 -
+Rule   sol89   1989    only    -       Apr     24      11:58:10s 0:01:50 -
+Rule   sol89   1989    only    -       Apr     25      11:58:00s 0:02:00 -
+Rule   sol89   1989    only    -       Apr     26      11:57:50s 0:02:10 -
+Rule   sol89   1989    only    -       Apr     27      11:57:40s 0:02:20 -
+Rule   sol89   1989    only    -       Apr     28      11:57:30s 0:02:30 -
+Rule   sol89   1989    only    -       Apr     29      11:57:20s 0:02:40 -
+Rule   sol89   1989    only    -       Apr     30      11:57:15s 0:02:45 -
+Rule   sol89   1989    only    -       May     1       11:57:05s 0:02:55 -
+Rule   sol89   1989    only    -       May     2       11:57:00s 0:03:00 -
+Rule   sol89   1989    only    -       May     3       11:56:50s 0:03:10 -
+Rule   sol89   1989    only    -       May     4       11:56:45s 0:03:15 -
+Rule   sol89   1989    only    -       May     5       11:56:40s 0:03:20 -
+Rule   sol89   1989    only    -       May     6       11:56:35s 0:03:25 -
+Rule   sol89   1989    only    -       May     7       11:56:30s 0:03:30 -
+Rule   sol89   1989    only    -       May     8       11:56:30s 0:03:30 -
+Rule   sol89   1989    only    -       May     9       11:56:25s 0:03:35 -
+Rule   sol89   1989    only    -       May     10      11:56:25s 0:03:35 -
+Rule   sol89   1989    only    -       May     11      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     12      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     13      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     14      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     15      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     16      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     17      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       May     18      11:56:25s 0:03:35 -
+Rule   sol89   1989    only    -       May     19      11:56:25s 0:03:35 -
+Rule   sol89   1989    only    -       May     20      11:56:30s 0:03:30 -
+Rule   sol89   1989    only    -       May     21      11:56:35s 0:03:25 -
+Rule   sol89   1989    only    -       May     22      11:56:35s 0:03:25 -
+Rule   sol89   1989    only    -       May     23      11:56:40s 0:03:20 -
+Rule   sol89   1989    only    -       May     24      11:56:45s 0:03:15 -
+Rule   sol89   1989    only    -       May     25      11:56:55s 0:03:05 -
+Rule   sol89   1989    only    -       May     26      11:57:00s 0:03:00 -
+Rule   sol89   1989    only    -       May     27      11:57:05s 0:02:55 -
+Rule   sol89   1989    only    -       May     28      11:57:15s 0:02:45 -
+Rule   sol89   1989    only    -       May     29      11:57:20s 0:02:40 -
+Rule   sol89   1989    only    -       May     30      11:57:30s 0:02:30 -
+Rule   sol89   1989    only    -       May     31      11:57:35s 0:02:25 -
+Rule   sol89   1989    only    -       Jun     1       11:57:45s 0:02:15 -
+Rule   sol89   1989    only    -       Jun     2       11:57:55s 0:02:05 -
+Rule   sol89   1989    only    -       Jun     3       11:58:05s 0:01:55 -
+Rule   sol89   1989    only    -       Jun     4       11:58:15s 0:01:45 -
+Rule   sol89   1989    only    -       Jun     5       11:58:25s 0:01:35 -
+Rule   sol89   1989    only    -       Jun     6       11:58:35s 0:01:25 -
+Rule   sol89   1989    only    -       Jun     7       11:58:45s 0:01:15 -
+Rule   sol89   1989    only    -       Jun     8       11:59:00s 0:01:00 -
+Rule   sol89   1989    only    -       Jun     9       11:59:10s 0:00:50 -
+Rule   sol89   1989    only    -       Jun     10      11:59:20s 0:00:40 -
+Rule   sol89   1989    only    -       Jun     11      11:59:35s 0:00:25 -
+Rule   sol89   1989    only    -       Jun     12      11:59:45s 0:00:15 -
+Rule   sol89   1989    only    -       Jun     13      12:00:00s 0:00:00 -
+Rule   sol89   1989    only    -       Jun     14      12:00:10s -0:00:10 -
+Rule   sol89   1989    only    -       Jun     15      12:00:25s -0:00:25 -
+Rule   sol89   1989    only    -       Jun     16      12:00:35s -0:00:35 -
+Rule   sol89   1989    only    -       Jun     17      12:00:50s -0:00:50 -
+Rule   sol89   1989    only    -       Jun     18      12:01:05s -0:01:05 -
+Rule   sol89   1989    only    -       Jun     19      12:01:15s -0:01:15 -
+Rule   sol89   1989    only    -       Jun     20      12:01:30s -0:01:30 -
+Rule   sol89   1989    only    -       Jun     21      12:01:40s -0:01:40 -
+Rule   sol89   1989    only    -       Jun     22      12:01:55s -0:01:55 -
+Rule   sol89   1989    only    -       Jun     23      12:02:10s -0:02:10 -
+Rule   sol89   1989    only    -       Jun     24      12:02:20s -0:02:20 -
+Rule   sol89   1989    only    -       Jun     25      12:02:35s -0:02:35 -
+Rule   sol89   1989    only    -       Jun     26      12:02:45s -0:02:45 -
+Rule   sol89   1989    only    -       Jun     27      12:03:00s -0:03:00 -
+Rule   sol89   1989    only    -       Jun     28      12:03:10s -0:03:10 -
+Rule   sol89   1989    only    -       Jun     29      12:03:25s -0:03:25 -
+Rule   sol89   1989    only    -       Jun     30      12:03:35s -0:03:35 -
+Rule   sol89   1989    only    -       Jul     1       12:03:45s -0:03:45 -
+Rule   sol89   1989    only    -       Jul     2       12:04:00s -0:04:00 -
+Rule   sol89   1989    only    -       Jul     3       12:04:10s -0:04:10 -
+Rule   sol89   1989    only    -       Jul     4       12:04:20s -0:04:20 -
+Rule   sol89   1989    only    -       Jul     5       12:04:30s -0:04:30 -
+Rule   sol89   1989    only    -       Jul     6       12:04:40s -0:04:40 -
+Rule   sol89   1989    only    -       Jul     7       12:04:50s -0:04:50 -
+Rule   sol89   1989    only    -       Jul     8       12:05:00s -0:05:00 -
+Rule   sol89   1989    only    -       Jul     9       12:05:10s -0:05:10 -
+Rule   sol89   1989    only    -       Jul     10      12:05:20s -0:05:20 -
+Rule   sol89   1989    only    -       Jul     11      12:05:25s -0:05:25 -
+Rule   sol89   1989    only    -       Jul     12      12:05:35s -0:05:35 -
+Rule   sol89   1989    only    -       Jul     13      12:05:40s -0:05:40 -
+Rule   sol89   1989    only    -       Jul     14      12:05:50s -0:05:50 -
+Rule   sol89   1989    only    -       Jul     15      12:05:55s -0:05:55 -
+Rule   sol89   1989    only    -       Jul     16      12:06:00s -0:06:00 -
+Rule   sol89   1989    only    -       Jul     17      12:06:05s -0:06:05 -
+Rule   sol89   1989    only    -       Jul     18      12:06:10s -0:06:10 -
+Rule   sol89   1989    only    -       Jul     19      12:06:15s -0:06:15 -
+Rule   sol89   1989    only    -       Jul     20      12:06:20s -0:06:20 -
+Rule   sol89   1989    only    -       Jul     21      12:06:20s -0:06:20 -
+Rule   sol89   1989    only    -       Jul     22      12:06:25s -0:06:25 -
+Rule   sol89   1989    only    -       Jul     23      12:06:25s -0:06:25 -
+Rule   sol89   1989    only    -       Jul     24      12:06:30s -0:06:30 -
+Rule   sol89   1989    only    -       Jul     25      12:06:30s -0:06:30 -
+Rule   sol89   1989    only    -       Jul     26      12:06:30s -0:06:30 -
+Rule   sol89   1989    only    -       Jul     27      12:06:30s -0:06:30 -
+Rule   sol89   1989    only    -       Jul     28      12:06:30s -0:06:30 -
+Rule   sol89   1989    only    -       Jul     29      12:06:25s -0:06:25 -
+Rule   sol89   1989    only    -       Jul     30      12:06:25s -0:06:25 -
+Rule   sol89   1989    only    -       Jul     31      12:06:20s -0:06:20 -
+Rule   sol89   1989    only    -       Aug     1       12:06:20s -0:06:20 -
+Rule   sol89   1989    only    -       Aug     2       12:06:15s -0:06:15 -
+Rule   sol89   1989    only    -       Aug     3       12:06:10s -0:06:10 -
+Rule   sol89   1989    only    -       Aug     4       12:06:05s -0:06:05 -
+Rule   sol89   1989    only    -       Aug     5       12:06:00s -0:06:00 -
+Rule   sol89   1989    only    -       Aug     6       12:05:50s -0:05:50 -
+Rule   sol89   1989    only    -       Aug     7       12:05:45s -0:05:45 -
+Rule   sol89   1989    only    -       Aug     8       12:05:35s -0:05:35 -
+Rule   sol89   1989    only    -       Aug     9       12:05:30s -0:05:30 -
+Rule   sol89   1989    only    -       Aug     10      12:05:20s -0:05:20 -
+Rule   sol89   1989    only    -       Aug     11      12:05:10s -0:05:10 -
+Rule   sol89   1989    only    -       Aug     12      12:05:00s -0:05:00 -
+Rule   sol89   1989    only    -       Aug     13      12:04:50s -0:04:50 -
+Rule   sol89   1989    only    -       Aug     14      12:04:40s -0:04:40 -
+Rule   sol89   1989    only    -       Aug     15      12:04:30s -0:04:30 -
+Rule   sol89   1989    only    -       Aug     16      12:04:15s -0:04:15 -
+Rule   sol89   1989    only    -       Aug     17      12:04:05s -0:04:05 -
+Rule   sol89   1989    only    -       Aug     18      12:03:50s -0:03:50 -
+Rule   sol89   1989    only    -       Aug     19      12:03:35s -0:03:35 -
+Rule   sol89   1989    only    -       Aug     20      12:03:25s -0:03:25 -
+Rule   sol89   1989    only    -       Aug     21      12:03:10s -0:03:10 -
+Rule   sol89   1989    only    -       Aug     22      12:02:55s -0:02:55 -
+Rule   sol89   1989    only    -       Aug     23      12:02:40s -0:02:40 -
+Rule   sol89   1989    only    -       Aug     24      12:02:20s -0:02:20 -
+Rule   sol89   1989    only    -       Aug     25      12:02:05s -0:02:05 -
+Rule   sol89   1989    only    -       Aug     26      12:01:50s -0:01:50 -
+Rule   sol89   1989    only    -       Aug     27      12:01:30s -0:01:30 -
+Rule   sol89   1989    only    -       Aug     28      12:01:15s -0:01:15 -
+Rule   sol89   1989    only    -       Aug     29      12:00:55s -0:00:55 -
+Rule   sol89   1989    only    -       Aug     30      12:00:40s -0:00:40 -
+Rule   sol89   1989    only    -       Aug     31      12:00:20s -0:00:20 -
+Rule   sol89   1989    only    -       Sep     1       12:00:00s 0:00:00 -
+Rule   sol89   1989    only    -       Sep     2       11:59:45s 0:00:15 -
+Rule   sol89   1989    only    -       Sep     3       11:59:25s 0:00:35 -
+Rule   sol89   1989    only    -       Sep     4       11:59:05s 0:00:55 -
+Rule   sol89   1989    only    -       Sep     5       11:58:45s 0:01:15 -
+Rule   sol89   1989    only    -       Sep     6       11:58:25s 0:01:35 -
+Rule   sol89   1989    only    -       Sep     7       11:58:05s 0:01:55 -
+Rule   sol89   1989    only    -       Sep     8       11:57:45s 0:02:15 -
+Rule   sol89   1989    only    -       Sep     9       11:57:20s 0:02:40 -
+Rule   sol89   1989    only    -       Sep     10      11:57:00s 0:03:00 -
+Rule   sol89   1989    only    -       Sep     11      11:56:40s 0:03:20 -
+Rule   sol89   1989    only    -       Sep     12      11:56:20s 0:03:40 -
+Rule   sol89   1989    only    -       Sep     13      11:56:00s 0:04:00 -
+Rule   sol89   1989    only    -       Sep     14      11:55:35s 0:04:25 -
+Rule   sol89   1989    only    -       Sep     15      11:55:15s 0:04:45 -
+Rule   sol89   1989    only    -       Sep     16      11:54:55s 0:05:05 -
+Rule   sol89   1989    only    -       Sep     17      11:54:35s 0:05:25 -
+Rule   sol89   1989    only    -       Sep     18      11:54:10s 0:05:50 -
+Rule   sol89   1989    only    -       Sep     19      11:53:50s 0:06:10 -
+Rule   sol89   1989    only    -       Sep     20      11:53:30s 0:06:30 -
+Rule   sol89   1989    only    -       Sep     21      11:53:10s 0:06:50 -
+Rule   sol89   1989    only    -       Sep     22      11:52:45s 0:07:15 -
+Rule   sol89   1989    only    -       Sep     23      11:52:25s 0:07:35 -
+Rule   sol89   1989    only    -       Sep     24      11:52:05s 0:07:55 -
+Rule   sol89   1989    only    -       Sep     25      11:51:45s 0:08:15 -
+Rule   sol89   1989    only    -       Sep     26      11:51:25s 0:08:35 -
+Rule   sol89   1989    only    -       Sep     27      11:51:05s 0:08:55 -
+Rule   sol89   1989    only    -       Sep     28      11:50:40s 0:09:20 -
+Rule   sol89   1989    only    -       Sep     29      11:50:20s 0:09:40 -
+Rule   sol89   1989    only    -       Sep     30      11:50:00s 0:10:00 -
+Rule   sol89   1989    only    -       Oct     1       11:49:45s 0:10:15 -
+Rule   sol89   1989    only    -       Oct     2       11:49:25s 0:10:35 -
+Rule   sol89   1989    only    -       Oct     3       11:49:05s 0:10:55 -
+Rule   sol89   1989    only    -       Oct     4       11:48:45s 0:11:15 -
+Rule   sol89   1989    only    -       Oct     5       11:48:30s 0:11:30 -
+Rule   sol89   1989    only    -       Oct     6       11:48:10s 0:11:50 -
+Rule   sol89   1989    only    -       Oct     7       11:47:50s 0:12:10 -
+Rule   sol89   1989    only    -       Oct     8       11:47:35s 0:12:25 -
+Rule   sol89   1989    only    -       Oct     9       11:47:20s 0:12:40 -
+Rule   sol89   1989    only    -       Oct     10      11:47:00s 0:13:00 -
+Rule   sol89   1989    only    -       Oct     11      11:46:45s 0:13:15 -
+Rule   sol89   1989    only    -       Oct     12      11:46:30s 0:13:30 -
+Rule   sol89   1989    only    -       Oct     13      11:46:15s 0:13:45 -
+Rule   sol89   1989    only    -       Oct     14      11:46:00s 0:14:00 -
+Rule   sol89   1989    only    -       Oct     15      11:45:50s 0:14:10 -
+Rule   sol89   1989    only    -       Oct     16      11:45:35s 0:14:25 -
+Rule   sol89   1989    only    -       Oct     17      11:45:20s 0:14:40 -
+Rule   sol89   1989    only    -       Oct     18      11:45:10s 0:14:50 -
+Rule   sol89   1989    only    -       Oct     19      11:45:00s 0:15:00 -
+Rule   sol89   1989    only    -       Oct     20      11:44:50s 0:15:10 -
+Rule   sol89   1989    only    -       Oct     21      11:44:40s 0:15:20 -
+Rule   sol89   1989    only    -       Oct     22      11:44:30s 0:15:30 -
+Rule   sol89   1989    only    -       Oct     23      11:44:20s 0:15:40 -
+Rule   sol89   1989    only    -       Oct     24      11:44:10s 0:15:50 -
+Rule   sol89   1989    only    -       Oct     25      11:44:05s 0:15:55 -
+Rule   sol89   1989    only    -       Oct     26      11:44:00s 0:16:00 -
+Rule   sol89   1989    only    -       Oct     27      11:43:50s 0:16:10 -
+Rule   sol89   1989    only    -       Oct     28      11:43:45s 0:16:15 -
+Rule   sol89   1989    only    -       Oct     29      11:43:40s 0:16:20 -
+Rule   sol89   1989    only    -       Oct     30      11:43:40s 0:16:20 -
+Rule   sol89   1989    only    -       Oct     31      11:43:35s 0:16:25 -
+Rule   sol89   1989    only    -       Nov     1       11:43:35s 0:16:25 -
+Rule   sol89   1989    only    -       Nov     2       11:43:35s 0:16:25 -
+Rule   sol89   1989    only    -       Nov     3       11:43:30s 0:16:30 -
+Rule   sol89   1989    only    -       Nov     4       11:43:35s 0:16:25 -
+Rule   sol89   1989    only    -       Nov     5       11:43:35s 0:16:25 -
+Rule   sol89   1989    only    -       Nov     6       11:43:35s 0:16:25 -
+Rule   sol89   1989    only    -       Nov     7       11:43:40s 0:16:20 -
+Rule   sol89   1989    only    -       Nov     8       11:43:45s 0:16:15 -
+Rule   sol89   1989    only    -       Nov     9       11:43:50s 0:16:10 -
+Rule   sol89   1989    only    -       Nov     10      11:43:55s 0:16:05 -
+Rule   sol89   1989    only    -       Nov     11      11:44:00s 0:16:00 -
+Rule   sol89   1989    only    -       Nov     12      11:44:05s 0:15:55 -
+Rule   sol89   1989    only    -       Nov     13      11:44:15s 0:15:45 -
+Rule   sol89   1989    only    -       Nov     14      11:44:25s 0:15:35 -
+Rule   sol89   1989    only    -       Nov     15      11:44:35s 0:15:25 -
+Rule   sol89   1989    only    -       Nov     16      11:44:45s 0:15:15 -
+Rule   sol89   1989    only    -       Nov     17      11:44:55s 0:15:05 -
+Rule   sol89   1989    only    -       Nov     18      11:45:10s 0:14:50 -
+Rule   sol89   1989    only    -       Nov     19      11:45:20s 0:14:40 -
+Rule   sol89   1989    only    -       Nov     20      11:45:35s 0:14:25 -
+Rule   sol89   1989    only    -       Nov     21      11:45:50s 0:14:10 -
+Rule   sol89   1989    only    -       Nov     22      11:46:05s 0:13:55 -
+Rule   sol89   1989    only    -       Nov     23      11:46:25s 0:13:35 -
+Rule   sol89   1989    only    -       Nov     24      11:46:40s 0:13:20 -
+Rule   sol89   1989    only    -       Nov     25      11:47:00s 0:13:00 -
+Rule   sol89   1989    only    -       Nov     26      11:47:20s 0:12:40 -
+Rule   sol89   1989    only    -       Nov     27      11:47:35s 0:12:25 -
+Rule   sol89   1989    only    -       Nov     28      11:47:55s 0:12:05 -
+Rule   sol89   1989    only    -       Nov     29      11:48:20s 0:11:40 -
+Rule   sol89   1989    only    -       Nov     30      11:48:40s 0:11:20 -
+Rule   sol89   1989    only    -       Dec     1       11:49:00s 0:11:00 -
+Rule   sol89   1989    only    -       Dec     2       11:49:25s 0:10:35 -
+Rule   sol89   1989    only    -       Dec     3       11:49:50s 0:10:10 -
+Rule   sol89   1989    only    -       Dec     4       11:50:15s 0:09:45 -
+Rule   sol89   1989    only    -       Dec     5       11:50:35s 0:09:25 -
+Rule   sol89   1989    only    -       Dec     6       11:51:00s 0:09:00 -
+Rule   sol89   1989    only    -       Dec     7       11:51:30s 0:08:30 -
+Rule   sol89   1989    only    -       Dec     8       11:51:55s 0:08:05 -
+Rule   sol89   1989    only    -       Dec     9       11:52:20s 0:07:40 -
+Rule   sol89   1989    only    -       Dec     10      11:52:50s 0:07:10 -
+Rule   sol89   1989    only    -       Dec     11      11:53:15s 0:06:45 -
+Rule   sol89   1989    only    -       Dec     12      11:53:45s 0:06:15 -
+Rule   sol89   1989    only    -       Dec     13      11:54:10s 0:05:50 -
+Rule   sol89   1989    only    -       Dec     14      11:54:40s 0:05:20 -
+Rule   sol89   1989    only    -       Dec     15      11:55:10s 0:04:50 -
+Rule   sol89   1989    only    -       Dec     16      11:55:40s 0:04:20 -
+Rule   sol89   1989    only    -       Dec     17      11:56:05s 0:03:55 -
+Rule   sol89   1989    only    -       Dec     18      11:56:35s 0:03:25 -
+Rule   sol89   1989    only    -       Dec     19      11:57:05s 0:02:55 -
+Rule   sol89   1989    only    -       Dec     20      11:57:35s 0:02:25 -
+Rule   sol89   1989    only    -       Dec     21      11:58:05s 0:01:55 -
+Rule   sol89   1989    only    -       Dec     22      11:58:35s 0:01:25 -
+Rule   sol89   1989    only    -       Dec     23      11:59:05s 0:00:55 -
+Rule   sol89   1989    only    -       Dec     24      11:59:35s 0:00:25 -
+Rule   sol89   1989    only    -       Dec     25      12:00:05s -0:00:05 -
+Rule   sol89   1989    only    -       Dec     26      12:00:35s -0:00:35 -
+Rule   sol89   1989    only    -       Dec     27      12:01:05s -0:01:05 -
+Rule   sol89   1989    only    -       Dec     28      12:01:35s -0:01:35 -
+Rule   sol89   1989    only    -       Dec     29      12:02:00s -0:02:00 -
+Rule   sol89   1989    only    -       Dec     30      12:02:30s -0:02:30 -
+Rule   sol89   1989    only    -       Dec     31      12:03:00s -0:03:00 -
+
+# Riyadh is at about 46 degrees 46 minutes East:  3 hrs, 7 mins, 4 secs
+# Before and after 1989, we'll operate on local mean solar time.
+
+# Zone NAME            GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
+Zone   Asia/Riyadh89   3:07:04 -               ??      1989
+                       3:07:04 sol89           ??      1990
+                       3:07:04 -               ??
+# For backward compatibility...
+Link   Asia/Riyadh89   Mideast/Riyadh89
diff --git a/zic.tproj/datfiles/southamerica b/zic.tproj/datfiles/southamerica
new file mode 100644 (file)
index 0000000..2e27ed0
--- /dev/null
@@ -0,0 +1,547 @@
+#      $OpenBSD: southamerica,v 1.4 1997/01/14 04:36:57 millert Exp $
+# @(#)southamerica     7.16
+
+# 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):
+# 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).
+#
+# Gwillim Law <LAW@encmail.encompass.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.
+#
+# 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).
+#      I suggest the use of _Summer time_ instead of the more cumbersome
+#      _daylight-saving time_.  _Summer time_ seems to be in general use
+#      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.
+
+###############################################################################
+
+###############################################################################
+
+# Argentina
+
+# From Bob Devine (1988-01-28):
+# Argentina: first Sunday in October to first Sunday in April since 1976.
+# Double Summer time from 1969 to 1974.  Switches at midnight.
+
+# From U. S. Naval Observatory (1988-01-199):
+# ARGENTINA           3 H BEHIND   UTC
+
+# From Hernan G. Otero <hernan@isoft.com.ar> (1995-06-26):
+# I am sending modifications to the Argentine time zone table...
+# AR was chosen because they are the ISO letters that represent Argentina.
+
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Arg     1930    only    -       Dec      1      0:00    1:00    S
+Rule   Arg     1931    only    -       Apr      1      0:00    0       -
+Rule   Arg     1931    only    -       Oct     15      0:00    1:00    S
+Rule   Arg     1932    1940    -       Mar      1      0:00    0       -
+Rule   Arg     1932    1939    -       Nov      1      0:00    1:00    S
+Rule   Arg     1940    only    -       Jul      1      0:00    1:00    S
+Rule   Arg     1941    only    -       Jun     15      0:00    0       -
+Rule   Arg     1941    only    -       Oct     15      0:00    1:00    S
+Rule   Arg     1943    only    -       Aug      1      0:00    0       -
+Rule   Arg     1943    only    -       Oct     15      0:00    1:00    S
+Rule   Arg     1946    only    -       Mar      1      0:00    0       -
+Rule   Arg     1946    only    -       Oct      1      0:00    1:00    S
+Rule   Arg     1963    only    -       Oct      1      0:00    0       -
+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     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     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
+Rule   Arg     1987    only    -       Feb     13      0:00    0       -
+Rule   Arg     1988    only    -       Feb      7      0:00    0       -
+Rule   Arg     1988    only    -       Dec      1      0:00    1:00    S
+#
+# From Hernan G. Otero <hernan@isoft.com.ar> (1995-06-26):
+# These corrections were contributed by InterSoft Argentina S.A.,
+# obtaining the data from the:
+# Talleres de Hidrografia Naval Argentina
+# (Argentine Naval Hydrography Institute)
+#
+# Shanks gives 1989 Mar 16 and stops after 1990 Mar 4; 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
+#
+# From Hernan G. Otero <hernan@isoft.com.ar> (1995-06-26):
+# From this moment on, the law that mandated the daylight saving
+# time corrections was derogated and no more modifications
+# to the time zones (for daylight saving) are now made.
+#
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+#
+# Buenos Aires (BA), Distrito Federal (DF), Santa Cruz (SC),
+# Tierra del Fuego (TF) & Antartida e Islas
+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
+#
+# 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
+                       -3:00   Arg     AR%sT   1991 Jul
+                       -3:00   -       ART
+#
+# Cordoba (CB), Santiago del Estero (SE), Salta (SA), Tucuman (TM), La Rioja (LR), San Juan (SJ), San Luis (SL),
+# Neuquen (NQ), Rio Negro (RN)
+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
+                       -3:00   Arg     AR%sT   1990 Jul
+                       -3:00   -       ART
+#
+# Jujuy (JY)
+Zone America/Jujuy     -4:21:12 -      LMT     1894 Nov
+                       -4:16:44 -      CMT     1920 May
+                       -4:00   -       ART     1930 Dec
+                       -4:00   Arg     AR%sT   1969 Oct  5
+                       -3:00   Arg     AR%sT   1991 Mar  3
+                       -4:00   -       WART    1991 Oct  6
+                       -4:00   1:00    WARST   1992 Mar 15
+                       -4:00   -       WART    1992 Oct 18
+                       -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
+                       -3:00   Arg     AR%sT   1990 Jul
+                       -3:00   -       ART     1991 Jul
+                       -3:00   Arg     AR%sT   1992 Jul
+                       -3:00   -       ART
+#
+# Mendoza (MZ)
+Zone America/Mendoza   -4:35:16 -      LMT     1894 Nov
+                       -4:16:44 -      CMT     1920 May
+                       -4:00   -       ART     1930 Dec
+                       -4:00   Arg     AR%sT   1969 Oct  5
+                       -3:00   Arg     AR%sT   1991 Mar  3
+                       -4:00   -       WART    1991 Oct 15
+                       -4:00   1:00    WARST   1992 Mar  1
+                       -4:00   -       WART    1992 Oct 18
+                       -3:00   -       ART
+
+# Aruba
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Aruba   -4:40:24 -      LMT     1912 Feb 12     # Oranjestad
+                       -4:30   -       ANT     1965 # Netherlands Antilles Time
+                       -4:00   -       AST
+
+# Bolivia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/La_Paz  -4:32:36 -      LMT     1890
+                       -4:32:36 -      LPMT    1931 Oct 15 # La Paz Mean Time
+                       -4:32:36 1:00   BOST    1932 Mar 21 # Bolivia ST
+                       -4:00   -       BOT     # Bolivia Time
+
+# 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.
+# The rule change lasted only part of the day;
+# the federal government refused to follow the city's rules, and business
+# was in a chaos, so the mayor backed down that afternoon.
+
+# From IATA SSIM (1996-02):
+# _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
+# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
+# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
+# Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
+# [The last three states are new to this issue of the IATA SSIM.]
+
+# From Gwillim Law (1996-10-07):
+# Geography, history (Tocantins was part of Goias until 1989), and other
+# sources of time zone information lead me to believe that AL, SE, and TO were
+# always in BR1, and so the only change was whether or not they observed DST....
+# The earliest issue of the SSIM I have is 2/91.  Each issue from then until
+# 9/95 says that DST is observed only in the ten states I quoted from 9/95,
+# along with Mato Grosso (MT) and Mato Grosso do Sul (MS), which are in BR2
+# (UTC-4)....  The other two time zones given for Brazil are BR3, which is
+# UTC-5, no DST, and applies only in the state of Acre (AC); and BR4, which is
+# UTC-2, and applies to Fernando de Noronha (formerly FN, but I believe it's
+# become part of the state of Pernambuco).  The boundary between BR1 and BR2
+# has never been clearly stated.  They've simply been called East and West.
+# However, some conclusions can be drawn from another IATA manual: the Airline
+# Coding Directory, which lists close to 400 airports in Brazil.  For each
+# airport it gives a time zone which is coded to the SSIM.  From that
+# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
+# 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:
+#
+# * 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.
+#
+# Under these assumptions Brazil needs 7 entries to cover all the distinct
+# time zone histories since 1970:
+#
+# 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.
+
+# 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
+Zone America/Noronha   -2:09:40 -      LMT     1914
+                       -2:00   -       FST     1963 Dec 9
+                       -2:00   Brazil  F%sT    1990 Jul
+                       -2:00   -       FST
+#
+# Amapa, east Para, Maranhao, Piaui, Ceara, Rio Grande do Norte, Paraiba,
+# Pernambuco (except Fernando de Noronha)
+Zone America/Fortaleza -2:34:00 -      LMT     1914
+                       -3:00   -       EST     1963 Dec 9
+                       -3:00   Brazil  E%sT    1990 Jul
+                       -3:00   -       EST
+#
+# Alagoas, Sergipe, Tocantins
+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
+#
+# Bahia, Goias, Distrito Federal, Minas Gerais, Espirito Santo, Rio de Janeiro,
+# Sao Paulo, Parana, Santa Catarina, Rio Grande do Sul
+Zone America/Sao_Paulo -3:06:28 -      LMT     1914
+                       -3:00   Brazil  E%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
+#
+# Roraima, west Para, Amazonas, Rondonia
+Zone America/Manaus    -4:00:04 -      LMT     1914
+                       -4:00   -       WST     1963 Dec 9
+                       -4:00   Brazil  W%sT    1990 Jul
+                       -4:00   -       WST
+#
+# 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
+#
+# Martin Vaz and Trinidade are like America/Noronha.
+
+
+# Chile
+
+# 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.
+
+# 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       -
+# 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.
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Santiago  -4:42:40 -      LMT     1890
+                       -4:42:40 -      SMT     1910        # Santiago Mean Time
+                       -5:00   Chile   CL%sT   1932 Sep    # Chile Time
+                       -4:00   Chile   CL%sT
+Zone Pacific/Easter    -7:17:28 -      LMT     1890        # Mataveri
+                       -7:17:28 -      MMT     1932 Sep    # Mataveri Mean Time
+                       -7:00   Chile   EAS%sT  1982 Mar 14 # Easter I Time
+                       -6:00   Chile   EAS%sT
+#
+# Whitman says Juan Fernandez Is are like America/Santiago.
+# San Ambrosio, San Felix
+# no information; probably like America/Santiago
+
+
+# Colombia
+# 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       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Bogota  -4:56:20 -      LMT     1884 Mar 13
+                       -4:56:20 -      BMT     1914 Nov 23 # Bogota Mean Time
+                       -5:00   CO      CO%sT   # Colombia Time
+# Malpelo, Providencia, San Andres
+# no information; probably like America/Bogota
+
+# Curacao
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Curacao -4:35:44 -      LMT     1912 Feb 12     # Willemstad
+                       -4:30   -       ANT     1965 # Netherlands Antilles Time
+                       -4:00   -       AST
+
+# Ecuador
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Guayaquil -5:19:20 -      LMT     1890
+                       -5:14:00 -      QMT     1931 # Quito Mean Time
+                       -5:00   -       ECT          # Ecuador Time
+Zone Pacific/Galapagos -5:58:24 -      LMT     1931 # Puerto Baquerizo Moreno
+                       -5:00   -       ECT     1986
+                       -6:00   -       GALT         # Galapagos Time
+
+# Falklands
+# 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       -
+Rule   Falk    1939    only    -       Oct     1       0:00    1:00    S
+Rule   Falk    1940    1942    -       Sep     lastSun 0:00    1:00    S
+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
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Atlantic/Stanley  -3:51:24 -      LMT     1890
+                       -3:51:24 -      SMT     1912 Mar 12  # Stanley Mean Time
+                       -4:00   Falk    FK%sT   1983 May     # Falkland Is Time
+                       -3:00   Falk    FK%sT   1985 Sep 15
+                       -4:00   Falk    FK%sT
+
+# French Guiana
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Cayenne   -3:29:20 -      LMT     1911 Jul
+                       -4:00   -       GFT     1967 Oct # French Guiana Time
+                       -3:00   -       GFT
+
+# Guyana
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Guyana  -3:52:40 -      LMT     1915 Mar        # Georgetown
+                       -3:45   -       GBGT    1966 May 26 # Br Guiana Time
+                       -3:45   -       GYT     1975 Jul 31 # Guyana Time
+                       -3:00   -       GYT     1991
+# IATA SSIM (1996-06) says -4:00.  Assume a 1991 switch.
+                       -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):
+# 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    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    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    1994    1995    -       Feb     lastSun 0:00    0       -
+Rule   Para    1996    max     -       Mar      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
+                       -4:00   -       PYT     1972 Oct # Paraguay Time
+                       -3:00   -       PYT     1974 Apr
+                       -4:00   Para    PY%sT
+
+# Peru
+# Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+Rule   Peru    1938    only    -       Jan      1      0:00    1:00    S
+Rule   Peru    1938    only    -       Apr      1      0:00    0       -
+Rule   Peru    1938    1939    -       Sep     lastSun 0:00    1:00    S
+Rule   Peru    1939    1940    -       Mar     Sun>=24 0:00    0       -
+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       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Lima    -5:08:12 -      LMT     1890
+                       -5:09   -       LMT     1908 Jul 28 # Lima Mean Time
+                       -5:00   Peru    PE%sT   # Peru Time
+
+# South Georgia
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone Atlantic/South_Georgia -2:26:08 - LMT     1890            # Grytviken
+                       -2:00   -       GST     # South Georgia Time
+
+# South Sandwich Is
+# uninhabited
+
+# Suriname
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Paramaribo        -3:40:40 -      LMT     1911
+                       -3:40:52 -      PMT     1935     # Paramaribo Mean Time
+                       -3:40:36 -      PMT     1945 Oct # The capital moved?
+                       -3:30   -       NEGT    1975 Nov 20 # Dutch Guiana Time
+                       -3:30   -       SRT     1984 Oct # Suriname Time
+                       -3:00   -       SRT
+
+# Trinidad and Tobago
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Port_of_Spain -4:06:04 -  LMT     1912 Mar 2
+                       -4:00   -       AST
+
+# 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):
+# 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
+Rule   Uruguay 1924    1926    -       Apr      1       0:00   0       -
+Rule   Uruguay 1924    1925    -       Oct      1       0:00   0:30    HS
+Rule   Uruguay 1933    1935    -       Oct     lastSun  0:00   0:30    HS
+# Shanks gives 1935 Apr 1 0:00 and 1936 Mar 30 0:00; go with Whitman.
+Rule   Uruguay 1934    1936    -       Mar     Sat>=25 23:30s  0       -
+Rule   Uruguay 1936    only    -       Nov      1       0:00   0:30    HS
+Rule   Uruguay 1937    1941    -       Mar     lastSun  0:00   0       -
+# Whitman gives 1937 Oct 3; go with Shanks.
+Rule   Uruguay 1937    1940    -       Oct     lastSun  0:00   0:30    HS
+# Whitman gives 1941 Oct 24 - 1942 Mar 27, 1942 Dec 14 - 1943 Apr 13,
+# and 1943 Apr 13 ``to present time''; go with Shanks.
+Rule   Uruguay 1941    only    -       Aug      1       0:00   0       -
+Rule   Uruguay 1942    only    -       Jan      1       0:00   0:30    HS
+Rule   Uruguay 1942    only    -       Dec     14       0:00   1:00    S
+Rule   Uruguay 1943    only    -       Mar     14       0:00   0       -
+Rule   Uruguay 1959    only    -       May     24       0:00   1:00    S
+Rule   Uruguay 1959    only    -       Nov     15       0:00   0       -
+Rule   Uruguay 1960    only    -       Jan     17       0:00   1:00    S
+Rule   Uruguay 1960    only    -       Mar      6       0:00   0       -
+Rule   Uruguay 1965    1967    -       Apr     Sun>=1   0:00   1:00    S
+Rule   Uruguay 1965    only    -       Sep     26       0:00   0       -
+Rule   Uruguay 1966    1967    -       Oct     31       0:00   0       -
+Rule   Uruguay 1968    1970    -       May     27       0:00   0:30    HS
+Rule   Uruguay 1968    1970    -       Dec      2       0:00   0       -
+Rule   Uruguay 1972    only    -       Apr     24       0:00   1:00    S
+Rule   Uruguay 1972    only    -       Aug     15       0:00   0       -
+Rule   Uruguay 1974    only    -       Mar     10       0:00   0:30    HS
+Rule   Uruguay 1974    only    -       Dec     22       0:00   1:00    S
+Rule   Uruguay 1976    only    -       Oct      1       0:00   0       -
+Rule   Uruguay 1977    only    -       Dec      4       0:00   1:00    S
+Rule   Uruguay 1978    only    -       Apr      1       0:00   0       -
+Rule   Uruguay 1979    only    -       Oct      1       0:00   1:00    S
+Rule   Uruguay 1980    only    -       May      1       0:00   0       -
+Rule   Uruguay 1987    only    -       Dec     14       0:00   1:00    S
+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
+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 1993    only    -       Feb     28       0:00   0       -
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone America/Montevideo        -3:44:44 -      LMT     1898 Jun 28
+                       -3:44:44 -      MMT     1920 May  1     # Montevideo MT
+                       -3:30   Uruguay UY%sT   1942 Dec 14     # Uruguay Time
+                       -3:00   Uruguay UY%sT
+
+# Venezuela
+# Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
+Zone   America/Caracas -4:27:44 -      LMT     1890
+                       -4:27:44 -      CMT     1912 Feb 12  # Caracas Mean Time
+                       -4:30   -       VET     1965         # Venezuela Time
+                       -4:00   -       VET
diff --git a/zic.tproj/datfiles/systemv b/zic.tproj/datfiles/systemv
new file mode 100644 (file)
index 0000000..05a939d
--- /dev/null
@@ -0,0 +1,36 @@
+#      $OpenBSD: systemv,v 1.2 1997/01/14 04:36:58 millert Exp $
+# @(#)systemv  7.2
+
+# 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)
+#
+# Be sure to 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
+
+# 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
diff --git a/zic.tproj/datfiles/yearistype.sh b/zic.tproj/datfiles/yearistype.sh
new file mode 100755 (executable)
index 0000000..7a29a99
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/sh
+#       $OpenBSD: yearistype.sh,v 1.3 1997/01/14 04:36:58 millert Exp $
+
+: '@(#)yearistype.sh   7.4'
+
+case $#-$2 in
+       2-even)         case $1 in
+                               *[24680])                       exit 0 ;;
+                               *)                              exit 1 ;;
+                       esac ;;
+       2-nonpres)      case $1 in
+                               *[02468][048]|*[13579][26])     exit 1 ;;
+                               *)                              exit 0 ;;
+                       esac ;;
+       2-odd)          case $1 in
+                               *[13579])                       exit 0 ;;
+                               *)                              exit 1 ;;
+                       esac ;;
+       2-uspres)       case $1 in
+                               *[02468][048]|*[13579][26])     exit 0 ;;
+                               *)                              exit 1 ;;
+                       esac ;;
+       2-*)            echo "$0: wild type - $2" >&2
+                       exit 1 ;;
+       *)              echo "$0: usage is $0 year type" >&2
+                       exit 1 ;;
+esac
diff --git a/zic.tproj/ialloc.c b/zic.tproj/ialloc.c
new file mode 100644 (file)
index 0000000..490d2fa
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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@
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char    elsieid[] = "@(#)ialloc.c       8.28";
+#else
+static char rcsid[] = "$OpenBSD: ialloc.c,v 1.3 1997/01/14 03:16:45 millert Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+
+#define nonzero(n)     (((n) == 0) ? 1 : (n))
+
+char * icalloc P((int nelem, int elsize));
+char * icatalloc P((char * old, const char * new));
+char * icpyalloc P((const char * string));
+char * imalloc P((int n));
+void * irealloc P((void * pointer, int size));
+void   ifree P((char * pointer));
+
+char *
+imalloc(n)
+const int      n;
+{
+       return malloc((size_t) nonzero(n));
+}
+
+char *
+icalloc(nelem, elsize)
+int    nelem;
+int    elsize;
+{
+       if (nelem == 0 || elsize == 0)
+               nelem = elsize = 1;
+       return calloc((size_t) nelem, (size_t) elsize);
+}
+
+void *
+irealloc(pointer, size)
+void * const   pointer;
+const int      size;
+{
+       if (pointer == NULL)
+               return imalloc(size);
+       return realloc((void *) pointer, (size_t) nonzero(size));
+}
+
+char *
+icatalloc(old, new)
+char * const           old;
+const char * const     new;
+{
+       register char * result;
+       register int    oldsize, newsize;
+
+       newsize = (new == NULL) ? 0 : strlen(new);
+       if (old == NULL)
+               oldsize = 0;
+       else if (newsize == 0)
+               return old;
+       else    oldsize = strlen(old);
+       if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
+               if (new != NULL)
+                       (void) strcpy(result + oldsize, new);
+       return result;
+}
+
+char *
+icpyalloc(string)
+const char * const     string;
+{
+       return icatalloc((char *) NULL, string);
+}
+
+void
+ifree(p)
+char * const   p;
+{
+       if (p != NULL)
+               (void) free(p);
+}
+
+void
+icfree(p)
+char * const   p;
+{
+       if (p != NULL)
+               (void) free(p);
+}
diff --git a/zic.tproj/private.h b/zic.tproj/private.h
new file mode 100644 (file)
index 0000000..db7990d
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * 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@
+ */
+/*     $OpenBSD: private.h,v 1.6 1997/01/14 03:16:48 millert Exp $     */
+
+#ifndef PRIVATE_H
+
+#define PRIVATE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/* OpenBSD defaults */
+#define TM_GMTOFF              tm_gmtoff
+#define TM_ZONE                        tm_zone
+#define PCTS                   1
+#define STD_INSPIRED           1
+#define HAVE_LONG_DOUBLE       1
+#define HAVE_STRERROR          1
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#if 0
+#ifndef lint
+#ifndef NOID
+static char    privatehid[] = "@(#)private.h   7.44";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+#endif
+
+/*
+** Defaults for preprocessor symbols.
+** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+*/
+
+#ifndef HAVE_ADJTIME
+#define HAVE_ADJTIME           1
+#endif /* !defined HAVE_ADJTIME */
+
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT           0
+#endif /* !defined HAVE_GETTEXT */
+
+#ifndef HAVE_SETTIMEOFDAY
+#define HAVE_SETTIMEOFDAY      3
+#endif /* !defined HAVE_SETTIMEOFDAY */
+
+#ifndef HAVE_STRERROR
+#define HAVE_STRERROR          0
+#endif /* !defined HAVE_STRERROR */
+
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H          1
+#endif /* !defined HAVE_UNISTD_H */
+
+#ifndef HAVE_UTMPX_H
+#define HAVE_UTMPX_H           0
+#endif /* !defined HAVE_UTMPX_H */
+
+#ifndef LOCALE_HOME
+#define LOCALE_HOME            "/usr/lib/locale"
+#endif /* !defined LOCALE_HOME */
+
+/*
+** Nested includes
+*/
+
+#include "sys/types.h" /* for time_t */
+#include "stdio.h"
+#include "errno.h"
+#include "string.h"
+#include "limits.h"    /* for CHAR_BIT */
+#include "time.h"
+#include "stdlib.h"
+
+#if HAVE_GETTEXT - 0
+#include "libintl.h"
+#endif /* HAVE_GETTEXT - 0 */
+
+#if HAVE_UNISTD_H - 0
+#include "unistd.h"    /* for F_OK and R_OK */
+#endif /* HAVE_UNISTD_H - 0 */
+
+#if !(HAVE_UNISTD_H - 0)
+#ifndef F_OK
+#define F_OK   0
+#endif /* !defined F_OK */
+#ifndef R_OK
+#define R_OK   4
+#endif /* !defined R_OK */
+#endif /* !(HAVE_UNISTD_H - 0) */
+
+/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
+#define is_digit(c) ((unsigned)(c) - '0' <= 9)
+
+/*
+** Workarounds for compilers/systems.
+*/
+
+/*
+** SunOS 4.1.1 cc lacks const.
+*/
+
+#ifndef const
+#ifndef __STDC__
+#define const
+#endif /* !defined __STDC__ */
+#endif /* !defined const */
+
+/*
+** SunOS 4.1.1 cc lacks prototypes.
+*/
+
+#ifndef P
+#ifdef __STDC__
+#define P(x)   x
+#endif /* defined __STDC__ */
+#ifndef __STDC__
+#define P(x)   ()
+#endif /* !defined __STDC__ */
+#endif /* !defined P */
+
+/*
+** SunOS 4.1.1 headers lack EXIT_SUCCESS.
+*/
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS   0
+#endif /* !defined EXIT_SUCCESS */
+
+/*
+** SunOS 4.1.1 headers lack EXIT_FAILURE.
+*/
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE   1
+#endif /* !defined EXIT_FAILURE */
+
+/*
+** SunOS 4.1.1 headers lack FILENAME_MAX.
+*/
+
+#ifndef FILENAME_MAX
+
+#ifndef MAXPATHLEN
+#ifdef unix
+#include "sys/param.h"
+#endif /* defined unix */
+#endif /* !defined MAXPATHLEN */
+
+#ifdef MAXPATHLEN
+#define FILENAME_MAX   MAXPATHLEN
+#endif /* defined MAXPATHLEN */
+#ifndef MAXPATHLEN
+#define FILENAME_MAX   1024            /* Pure guesswork */
+#endif /* !defined MAXPATHLEN */
+
+#endif /* !defined FILENAME_MAX */
+
+/*
+** SunOS 4.1.1 libraries lack remove.
+*/
+
+#ifndef remove
+extern int     unlink P((const char * filename));
+#define remove unlink
+#endif /* !defined remove */
+
+#if 0
+/*
+** Some ancient errno.h implementations don't declare errno.
+** But some newer errno.h implementations define it as a macro.
+** Fix the former without affecting the latter.
+*/
+#ifndef errno
+extern int errno;
+#endif /* !defined errno */
+#endif
+
+/*
+** Finally, some convenience items.
+*/
+
+#ifndef TRUE
+#define TRUE   1
+#endif /* !defined TRUE */
+
+#ifndef FALSE
+#define FALSE  0
+#endif /* !defined FALSE */
+
+#ifndef TYPE_BIT
+#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+    ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 100 + 1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
+/*
+** INITIALIZE(x)
+*/
+
+#ifndef GNUC_or_lint
+#ifdef lint
+#define GNUC_or_lint
+#endif /* defined lint */
+#ifndef lint
+#ifdef __GNUC__
+#define GNUC_or_lint
+#endif /* defined __GNUC__ */
+#endif /* !defined lint */
+#endif /* !defined GNUC_or_lint */
+
+#ifndef INITIALIZE
+#ifdef GNUC_or_lint
+#define INITIALIZE(x)  ((x) = 0)
+#endif /* defined GNUC_or_lint */
+#ifndef GNUC_or_lint
+#define INITIALIZE(x)
+#endif /* !defined GNUC_or_lint */
+#endif /* !defined INITIALIZE */
+
+/*
+** For the benefit of GNU folk...
+** `_(MSGID)' uses the current locale's message library string for MSGID.
+** The default is to use gettext if available, and use MSGID otherwise.
+*/
+
+#ifndef _
+#if HAVE_GETTEXT - 0
+#define _(msgid) gettext(msgid)
+#else /* !(HAVE_GETTEXT - 0) */
+#define _(msgid) msgid
+#endif /* !(HAVE_GETTEXT - 0) */
+#endif /* !defined _ */
+
+#ifndef TZ_DOMAIN
+#define TZ_DOMAIN "tz"
+#endif /* !defined TZ_DOMAIN */
+
+/*
+** UNIX was a registered trademark of UNIX System Laboratories in 1993.
+*/
+
+#endif /* !defined PRIVATE_H */
diff --git a/zic.tproj/scheck.c b/zic.tproj/scheck.c
new file mode 100644 (file)
index 0000000..8407656
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * 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@
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char    elsieid[] = "@(#)scheck.c       8.13";
+#else
+static char rcsid[] = "$OpenBSD: scheck.c,v 1.4 1997/01/14 03:16:49 millert Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*LINTLIBRARY*/
+
+#include "private.h"
+
+extern char *  imalloc P((int n));
+extern void    ifree P((char * p));
+
+char *
+scheck(string, format)
+const char * const     string;
+char * const           format;
+{
+       register char *         fbuf;
+       register const char *   fp;
+       register char *         tp;
+       register int            c;
+       register char *         result;
+       char                    dummy;
+       static char             nada;
+
+       result = &nada;
+       if (string == NULL || format == NULL)
+               return result;
+       fbuf = imalloc((int) (2 * strlen(format) + 4));
+       if (fbuf == NULL)
+               return result;
+       fp = format;
+       tp = fbuf;
+       while ((*tp++ = c = *fp++) != '\0') {
+               if (c != '%')
+                       continue;
+               if (*fp == '%') {
+                       *tp++ = *fp++;
+                       continue;
+               }
+               *tp++ = '*';
+               if (*fp == '*')
+                       ++fp;
+               while (is_digit(*fp))
+                       *tp++ = *fp++;
+               if (*fp == 'l' || *fp == 'h')
+                       *tp++ = *fp++;
+               else if (*fp == '[')
+                       do *tp++ = *fp++;
+                               while (*fp != '\0' && *fp != ']');
+               if ((*tp++ = *fp++) == '\0')
+                       break;
+       }
+       *(tp - 1) = '%';
+       *tp++ = 'c';
+       *tp = '\0';
+       if (sscanf(string, fbuf, &dummy) != 1)
+               result = (char *) format;
+       ifree(fbuf);
+       return result;
+}
diff --git a/zic.tproj/tzfile.h b/zic.tproj/tzfile.h
new file mode 100644 (file)
index 0000000..25220c6
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * 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@
+ */
+/*     $OpenBSD: tzfile.h,v 1.4 1997/01/14 03:16:52 millert Exp $      */
+
+#ifndef TZFILE_H
+
+#define TZFILE_H
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** ID
+*/
+
+#if 0
+#ifndef lint
+#ifndef NOID
+static char    tzfilehid[] = "@(#)tzfile.h     7.9";
+#endif /* !defined NOID */
+#endif /* !defined lint */
+#endif
+
+/*
+** Information about time zone files.
+*/
+
+#ifndef TZDIR
+#define TZDIR  "/usr/share/zoneinfo" /* Time zone object file directory */
+#endif /* !defined TZDIR */
+
+#ifndef TZDEFAULT
+#define TZDEFAULT      "/etc/localtime"
+#endif /* !defined TZDEFAULT */
+
+#ifndef TZDEFRULES
+#define TZDEFRULES     "posixrules"
+#endif /* !defined TZDEFRULES */
+
+/*
+** Each file begins with. . .
+*/
+
+struct tzhead {
+       char    tzh_reserved[20];       /* reserved for future use */
+       char    tzh_ttisgmtcnt[4];      /* coded number of trans. time flags */
+       char    tzh_ttisstdcnt[4];      /* coded number of trans. time flags */
+       char    tzh_leapcnt[4];         /* coded number of leap seconds */
+       char    tzh_timecnt[4];         /* coded number of transition times */
+       char    tzh_typecnt[4];         /* coded number of local time types */
+       char    tzh_charcnt[4];         /* coded number of abbr. chars */
+};
+
+/*
+** . . .followed by. . .
+**
+**     tzh_timecnt (char [4])s         coded transition times a la time(2)
+**     tzh_timecnt (unsigned char)s    types of local time starting at above
+**     tzh_typecnt repetitions of
+**             one (char [4])          coded GMT offset in seconds
+**             one (unsigned char)     used to set tm_isdst
+**             one (unsigned char)     that's an abbreviation list index
+**     tzh_charcnt (char)s             '\0'-terminated zone abbreviations
+**     tzh_leapcnt repetitions of
+**             one (char [4])          coded leap second transition times
+**             one (char [4])          total correction after above
+**     tzh_ttisstdcnt (char)s          indexed by type; if TRUE, transition
+**                                     time is standard time, if FALSE,
+**                                     transition time is wall clock time
+**                                     if absent, transition times are
+**                                     assumed to be wall clock time
+**     tzh_ttisgmtcnt (char)s          indexed by type; if TRUE, transition
+**                                     time is GMT, if FALSE,
+**                                     transition time is local time
+**                                     if absent, transition times are
+**                                     assumed to be local time
+*/
+
+/*
+** In the current implementation, "tzset()" refuses to deal with files that
+** exceed any of the limits below.
+*/
+
+#ifndef TZ_MAX_TIMES
+/*
+** The TZ_MAX_TIMES value below is enough to handle a bit more than a
+** year's worth of solar time (corrected daily to the nearest second) or
+** 138 years of Pacific Presidential Election time
+** (where there are three time zone transitions every fourth year).
+*/
+#define TZ_MAX_TIMES   370
+#endif /* !defined TZ_MAX_TIMES */
+
+#ifndef TZ_MAX_TYPES
+#ifndef NOSOLAR
+#define TZ_MAX_TYPES   256 /* Limited by what (unsigned char)'s can hold */
+#endif /* !defined NOSOLAR */
+#ifdef NOSOLAR
+/*
+** Must be at least 14 for Europe/Riga as of Jan 12 1995,
+** as noted by Earl Chew <earl@hpato.aus.hp.com>.
+*/
+#define TZ_MAX_TYPES   20      /* Maximum number of local time types */
+#endif /* !defined NOSOLAR */
+#endif /* !defined TZ_MAX_TYPES */
+
+#ifndef TZ_MAX_CHARS
+#define TZ_MAX_CHARS   50      /* Maximum number of abbreviation characters */
+                               /* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
+
+#ifndef TZ_MAX_LEAPS
+#define TZ_MAX_LEAPS   50      /* Maximum number of leap second corrections */
+#endif /* !defined TZ_MAX_LEAPS */
+
+#define SECSPERMIN     60
+#define MINSPERHOUR    60
+#define HOURSPERDAY    24
+#define DAYSPERWEEK    7
+#define DAYSPERNYEAR   365
+#define DAYSPERLYEAR   366
+#define SECSPERHOUR    (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY     ((long) SECSPERHOUR * HOURSPERDAY)
+#define MONSPERYEAR    12
+
+#define TM_SUNDAY      0
+#define TM_MONDAY      1
+#define TM_TUESDAY     2
+#define TM_WEDNESDAY   3
+#define TM_THURSDAY    4
+#define TM_FRIDAY      5
+#define TM_SATURDAY    6
+
+#define TM_JANUARY     0
+#define TM_FEBRUARY    1
+#define TM_MARCH       2
+#define TM_APRIL       3
+#define TM_MAY         4
+#define TM_JUNE                5
+#define TM_JULY                6
+#define TM_AUGUST      7
+#define TM_SEPTEMBER   8
+#define TM_OCTOBER     9
+#define TM_NOVEMBER    10
+#define TM_DECEMBER    11
+
+#define TM_YEAR_BASE   1900
+
+#define EPOCH_YEAR     1970
+#define EPOCH_WDAY     TM_THURSDAY
+
+/*
+** Accurate only for the past couple of centuries;
+** that will probably do.
+*/
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+#ifndef USG
+
+/*
+** Use of the underscored variants may cause problems if you move your code to
+** certain System-V-based systems; for maximum portability, use the
+** underscore-free variants.  The underscored variants are provided for
+** backward compatibility only; they may disappear from future versions of
+** this file.
+*/
+
+#define SECS_PER_MIN   SECSPERMIN
+#define MINS_PER_HOUR  MINSPERHOUR
+#define HOURS_PER_DAY  HOURSPERDAY
+#define DAYS_PER_WEEK  DAYSPERWEEK
+#define DAYS_PER_NYEAR DAYSPERNYEAR
+#define DAYS_PER_LYEAR DAYSPERLYEAR
+#define SECS_PER_HOUR  SECSPERHOUR
+#define SECS_PER_DAY   SECSPERDAY
+#define MONS_PER_YEAR  MONSPERYEAR
+
+#endif /* !defined USG */
+
+#endif /* !defined TZFILE_H */
diff --git a/zic.tproj/zic.8 b/zic.tproj/zic.8
new file mode 100644 (file)
index 0000000..004ff09
--- /dev/null
@@ -0,0 +1,412 @@
+.\"    $OpenBSD: zic.8,v 1.4 1997/01/14 03:16:57 millert Exp $
+.TH ZIC 8
+.SH NAME
+zic \- time zone compiler
+.SH SYNOPSIS
+.B zic
+[
+.B \-v
+] [
+.B \-d
+.I directory
+] [
+.B \-l
+.I localtime
+] [
+.B \-p
+.I posixrules
+] [
+.B \-L
+.I leapsecondfilename
+] [
+.B \-s
+] [
+.B \-y
+.I command
+] [
+.I filename
+\&... ]
+.SH DESCRIPTION
+.if t .ds lq ``
+.if t .ds rq ''
+.if n .ds lq \&"\"
+.if n .ds rq \&"\"
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
+.I Zic
+reads text from the file(s) named on the command line
+and creates the time conversion information files specified in this input.
+If a
+.I filename
+is
+.BR \- ,
+the standard input is read.
+.PP
+These options are available:
+.TP
+.BI "\-d " directory
+Create time conversion information files in the named directory rather than
+in the standard directory named below.
+.TP
+.BI "\-l " timezone
+Use the given time zone as local time.
+.I Zic
+will act as if the input contained a link line of the form
+.sp
+.ti +.5i
+Link   \fItimezone\fP          localtime
+.TP
+.BI "\-p " timezone
+Use the given time zone's rules when handling POSIX-format
+time zone environment variables.
+.I Zic
+will act as if the input contained a link line of the form
+.sp
+.ti +.5i
+Link   \fItimezone\fP          posixrules
+.TP
+.BI "\-L " leapsecondfilename
+Read leap second information from the file with the given name.
+If this option is not used,
+no leap second information appears in output files.
+.TP
+.B \-v
+Complain if a year that appears in a data file is outside the range
+of years representable by
+.IR time (3)
+values.
+.TP
+.B \-s
+Limit time values stored in output files to values that are the same
+whether they're taken to be signed or unsigned.
+You can use this option to generate SVVS-compatible files.
+.TP
+.BI "\-y " command
+Use the given
+.I command
+rather than
+.B yearistype
+when checking year types (see below).
+.PP
+Input lines are made up of fields.
+Fields are separated from one another by any number of white space characters.
+Leading and trailing white space on input lines is ignored.
+An unquoted sharp character (#) in the input introduces a comment which extends
+to the end of the line the sharp character appears on.
+White space characters and sharp characters may be enclosed in double quotes
+(") if they're to be used as part of a field.
+Any line that is blank (after comment stripping) is ignored.
+Non-blank lines are expected to be of one of three types:
+rule lines, zone lines, and link lines.
+.PP
+A rule line has the form
+.nf
+.ti +.5i
+.ta \w'Rule\0\0'u +\w'NAME\0\0'u +\w'FROM\0\0'u +\w'1973\0\0'u +\w'TYPE\0\0'u +\w'Apr\0\0'u +\w'lastSun\0\0'u +\w'2:00\0\0'u +\w'SAVE\0\0'u
+.sp
+Rule   NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
+.sp
+For example:
+.ti +.5i
+.sp
+Rule   US      1967    1973    \-      Apr     lastSun 2:00    1:00    D
+.sp
+.fi
+The fields that make up a rule line are:
+.TP "\w'LETTER/S'u"
+.B NAME
+Gives the (arbitrary) name of the set of rules this rule is part of.
+.TP
+.B FROM
+Gives the first year in which the rule applies.
+Any integer year can be supplied; the Gregorian calendar is assumed.
+The word
+.B minimum
+(or an abbreviation) means the minimum year representable as an integer.
+The word
+.B maximum
+(or an abbreviation) means the maximum year representable as an integer.
+Rules can describe times that are not representable as time values,
+with the unrepresentable times ignored; this allows rules to be portable
+among hosts with differing time value types.
+.TP
+.B TO
+Gives the final year in which the rule applies.
+In addition to
+.B minimum
+and
+.B maximum
+(as above),
+the word
+.B only
+(or an abbreviation)
+may be used to repeat the value of the
+.B FROM
+field.
+.TP
+.B TYPE
+Gives the type of year in which the rule applies.
+If
+.B TYPE
+is
+.B \-
+then the rule applies in all years between
+.B FROM
+and
+.B TO
+inclusive.
+If
+.B TYPE
+is something else, then
+.I zic
+executes the command
+.ti +.5i
+\fByearistype\fP \fIyear\fP \fItype\fP
+.br
+to check the type of a year:
+an exit status of zero is taken to mean that the year is of the given type;
+an exit status of one is taken to mean that the year is not of the given type.
+.TP
+.B IN
+Names the month in which the rule takes effect.
+Month names may be abbreviated.
+.TP
+.B ON
+Gives the day on which the rule takes effect.
+Recognized forms include:
+.nf
+.in +.5i
+.sp
+.ta \w'Sun<=25\0\0'u
+5      the fifth of the month
+lastSun        the last Sunday in the month
+lastMon        the last Monday in the month
+Sun>=8 first Sunday on or after the eighth
+Sun<=25        last Sunday on or before the 25th
+.fi
+.in -.5i
+.sp
+Names of days of the week may be abbreviated or spelled out in full.
+Note that there must be no spaces within the
+.B ON
+field.
+.TP
+.B AT
+Gives the time of day at which the rule takes effect.
+Recognized forms include:
+.nf
+.in +.5i
+.sp
+.ta \w'1:28:13\0\0'u
+2      time in hours
+2:00   time in hours and minutes
+15:00  24-hour format time (for times after noon)
+1:28:14        time in hours, minutes, and seconds
+.fi
+.in -.5i
+.sp
+Any of these forms may be followed by the letter
+.B w
+if the given time is local
+.q "wall clock"
+time,
+.B s
+if the given time is local
+.q standard
+time, or
+.B u
+(or
+.B g
+or
+.BR z )
+if the given time is universal time;
+in the absence of an indicator,
+wall clock time is assumed.
+.TP
+.B SAVE
+Gives the amount of time to be added to local standard time when the rule is in
+effect.
+This field has the same format as the
+.B AT
+field
+(although, of course, the
+.B w
+and
+.B s
+suffixes are not used).
+.TP
+.B LETTER/S
+Gives the
+.q "variable part"
+(for example, the
+.q S
+or
+.q D
+in
+.q EST
+or
+.q EDT )
+of time zone abbreviations to be used when this rule is in effect.
+If this field is
+.BR \- ,
+the variable part is null.
+.PP
+A zone line has the form
+.sp
+.nf
+.ti +.5i
+.ta \w'Zone\0\0'u +\w'Australia/Adelaide\0\0'u +\w'GMTOFF\0\0'u +\w'RULES/SAVE\0\0'u +\w'FORMAT\0\0'u
+Zone   NAME    GMTOFF  RULES/SAVE      FORMAT  [UNTIL]
+.sp
+For example:
+.sp
+.ti +.5i
+Zone   Australia/Adelaide      9:30    Aus     CST     1971 Oct 31 2:00
+.sp
+.fi
+The fields that make up a zone line are:
+.TP "\w'GMTOFF'u"
+.B NAME
+The name of the time zone.
+This is the name used in creating the time conversion information file for the
+zone.
+.TP
+.B GMTOFF
+The amount of time to add to GMT to get standard time in this zone.
+This field has the same format as the
+.B AT
+and
+.B SAVE
+fields of rule lines;
+begin the field with a minus sign if time must be subtracted from GMT.
+.TP
+.B RULES/SAVE
+The name of the rule(s) that apply in the time zone or,
+alternately, an amount of time to add to local standard time.
+If this field is
+.B \-
+then standard time always applies in the time zone.
+.TP
+.B FORMAT
+The format for time zone abbreviations in this time zone.
+The pair of characters
+.B %s
+is used to show where the
+.q "variable part"
+of the time zone abbreviation goes.
+Alternately,
+a slash (/)
+separates standard and daylight abbreviations.
+.TP
+.B UNTIL
+The time at which the GMT offset or the rule(s) change for a location.
+It is specified as a year, a month, a day, and a time of day.
+If this is specified,
+the time zone information is generated from the given GMT offset
+and rule change until the time specified.
+The month, day, and time of day have the same format as the IN, ON, and AT
+columns of a rule; trailing columns can be omitted, and default to the
+earliest possible value for the missing columns.
+.IP
+The next line must be a
+.q continuation
+line; this has the same form as a zone line except that the
+string
+.q Zone
+and the name are omitted, as the continuation line will
+place information starting at the time specified as the
+.B UNTIL
+field in the previous line in the file used by the previous line.
+Continuation lines may contain an
+.B UNTIL
+field, just as zone lines do, indicating that the next line is a further
+continuation.
+.PP
+A link line has the form
+.sp
+.nf
+.ti +.5i
+.ta \w'Link\0\0'u +\w'Europe/Istanbul\0\0'u
+Link   LINK-FROM       LINK-TO
+.sp
+For example:
+.sp
+.ti +.5i
+Link   Europe/Istanbul Asia/Istanbul
+.sp
+.fi
+The
+.B LINK-FROM
+field should appear as the
+.B NAME
+field in some zone line;
+the
+.B LINK-TO
+field is used as an alternate name for that zone.
+.PP
+Except for continuation lines,
+lines may appear in any order in the input.
+.PP
+Lines in the file that describes leap seconds have the following form:
+.nf
+.ti +.5i
+.ta \w'Leap\0\0'u +\w'YEAR\0\0'u +\w'MONTH\0\0'u +\w'DAY\0\0'u +\w'HH:MM:SS\0\0'u +\w'CORR\0\0'u
+.sp
+Leap   YEAR    MONTH   DAY     HH:MM:SS        CORR    R/S
+.sp
+For example:
+.ti +.5i
+.sp
+Leap   1974    Dec     31      23:59:60        +       S
+.sp
+.fi
+The
+.BR YEAR ,
+.BR MONTH ,
+.BR DAY ,
+and
+.B HH:MM:SS
+fields tell when the leap second happened.
+The
+.B CORR
+field
+should be
+.q +
+if a second was added
+or
+.q -
+if a second was skipped.
+.\" There's no need to document the following, since it's impossible for more
+.\" than one leap second to be inserted or deleted at a time.
+.\" The C Standard is in error in suggesting the possibility.
+.\" See Terry J Quinn, The BIPM and the accurate measure of time,
+.\" Proc IEEE 79, 7 (July 1991), 894-905.
+.\"    or
+.\"    .q ++
+.\"    if two seconds were added
+.\"    or
+.\"    .q --
+.\"    if two seconds were skipped.
+The
+.B R/S
+field
+should be (an abbreviation of)
+.q Stationary
+if the leap second time given by the other fields should be interpreted as GMT
+or
+(an abbreviation of)
+.q Rolling
+if the leap second time given by the other fields should be interpreted as
+local wall clock time.
+.SH NOTE
+For areas with more than two types of local time,
+you may need to use local standard time in the
+.B AT
+field of the earliest transition time's rule to ensure that
+the earliest transition time recorded in the compiled file is correct.
+.SH FILE
+/usr/share/zoneinfo    standard directory used for created files
+.SH "SEE ALSO"
+ctime(3), tzfile(5), zdump(8)
+.\" @(#)zic.8  7.14
diff --git a/zic.tproj/zic.c b/zic.tproj/zic.c
new file mode 100644 (file)
index 0000000..a381bd4
--- /dev/null
@@ -0,0 +1,2189 @@
+/*
+ * 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@
+ */
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char    elsieid[] = "@(#)zic.c  7.80";
+#else
+static char rcsid[] = "$OpenBSD: zic.c,v 1.6 1997/01/15 23:40:55 millert Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include "private.h"
+#include "locale.h"
+#include "tzfile.h"
+#ifdef unix
+#include "sys/stat.h"                  /* for umask manifest constants */
+#endif /* defined unix */
+
+/*
+** On some ancient hosts, predicates like `isspace(C)' are defined
+** only if isascii(C) || C == EOF.  Modern hosts obey the C Standard,
+** which says they are defined only if C == ((unsigned char) C) || C == EOF.
+** Neither the C Standard nor Posix require that `isascii' exist.
+** For portability, we check both ancient and modern requirements.
+** If isascii is not defined, the isascii check succeeds trivially.
+*/
+#include "ctype.h"
+#ifndef isascii
+#define isascii(x) 1
+#endif
+
+struct rule {
+       const char *    r_filename;
+       int             r_linenum;
+       const char *    r_name;
+
+       int             r_loyear;       /* for example, 1986 */
+       int             r_hiyear;       /* for example, 1986 */
+       const char *    r_yrtype;
+
+       int             r_month;        /* 0..11 */
+
+       int             r_dycode;       /* see below */
+       int             r_dayofmonth;
+       int             r_wday;
+
+       long            r_tod;          /* time from midnight */
+       int             r_todisstd;     /* above is standard time if TRUE */
+                                       /* or wall clock time if FALSE */
+       int             r_todisgmt;     /* above is GMT if TRUE */
+                                       /* or local time if FALSE */
+       long            r_stdoff;       /* offset from standard time */
+       const char *    r_abbrvar;      /* variable part of abbreviation */
+
+       int             r_todo;         /* a rule to do (used in outzone) */
+       time_t          r_temp;         /* used in outzone */
+};
+
+/*
+**     r_dycode                r_dayofmonth    r_wday
+*/
+
+#define DC_DOM         0       /* 1..31 */     /* unused */
+#define DC_DOWGEQ      1       /* 1..31 */     /* 0..6 (Sun..Sat) */
+#define DC_DOWLEQ      2       /* 1..31 */     /* 0..6 (Sun..Sat) */
+
+struct zone {
+       const char *    z_filename;
+       int             z_linenum;
+
+       const char *    z_name;
+       long            z_gmtoff;
+       const char *    z_rule;
+       const char *    z_format;
+
+       long            z_stdoff;
+
+       struct rule *   z_rules;
+       int             z_nrules;
+
+       struct rule     z_untilrule;
+       time_t          z_untiltime;
+};
+
+extern int     getopt P((int argc, char * const argv[],
+                       const char * options));
+extern char *  icatalloc P((char * old, const char * new));
+extern char *  icpyalloc P((const char * string));
+extern void    ifree P((char * p));
+extern char *  imalloc P((int n));
+extern void *  irealloc P((void * old, int n));
+extern int     link P((const char * fromname, const char * toname));
+extern char *  optarg;
+extern int     optind;
+extern char *  scheck P((const char * string, const char * format));
+
+static void    addtt P((time_t starttime, int type));
+static int     addtype P((long gmtoff, const char * abbr, int isdst,
+                               int ttisstd, int ttisgmt));
+static void    leapadd P((time_t t, int positive, int rolling, int count));
+static void    adjleap P((void));
+static void    associate P((void));
+static int     ciequal P((const char * ap, const char * bp));
+static void    convert P((long val, char * buf));
+static void    dolink P((const char * fromfile, const char * tofile));
+static void    doabbr P((char * abbr, const char * format,
+                       const char * letters, int isdst));
+static void    eat P((const char * name, int num));
+static void    eats P((const char * name, int num,
+                       const char * rname, int rnum));
+static long    eitol P((int i));
+static void    error P((const char * message));
+static char ** getfields P((char * buf));
+static long    gethms P((const char * string, const char * errstrng,
+                       int signable));
+static void    infile P((const char * filename));
+static void    inleap P((char ** fields, int nfields));
+static void    inlink P((char ** fields, int nfields));
+static void    inrule P((char ** fields, int nfields));
+static int     inzcont P((char ** fields, int nfields));
+static int     inzone P((char ** fields, int nfields));
+static int     inzsub P((char ** fields, int nfields, int iscont));
+static int     itsabbr P((const char * abbr, const char * word));
+static int     itsdir P((const char * name));
+static int     lowerit P((int c));
+static char *  memcheck P((char * tocheck));
+static int     mkdirs P((char * filename));
+static void    newabbr P((const char * abbr));
+static long    oadd P((long t1, long t2));
+static void    outzone P((const struct zone * zp, int ntzones));
+static void    puttzcode P((long code, FILE * fp));
+static int     rcomp P((const void * leftp, const void * rightp));
+static time_t  rpytime P((const struct rule * rp, int wantedy));
+static void    rulesub P((struct rule * rp,
+                       const char * loyearp, const char * hiyearp,
+                       const char * typep, const char * monthp,
+                       const char * dayp, const char * timep));
+static void    setboundaries P((void));
+static time_t  tadd P((time_t t1, long t2));
+static void    usage P((void));
+static void    writezone P((const char * name));
+static int     yearistype P((int year, const char * type));
+
+#if !(HAVE_STRERROR - 0)
+static char *  strerror P((int));
+#endif /* !(HAVE_STRERROR - 0) */
+
+static int             charcnt;
+static int             errors;
+static const char *    filename;
+static int             leapcnt;
+static int             linenum;
+static time_t          max_time;
+static int             max_year;
+static time_t          min_time;
+static int             min_year;
+static int             noise;
+static const char *    rfilename;
+static int             rlinenum;
+static const char *    progname;
+static int             timecnt;
+static int             typecnt;
+
+/*
+** Line codes.
+*/
+
+#define LC_RULE                0
+#define LC_ZONE                1
+#define LC_LINK                2
+#define LC_LEAP                3
+
+/*
+** Which fields are which on a Zone line.
+*/
+
+#define ZF_NAME                1
+#define ZF_GMTOFF      2
+#define ZF_RULE                3
+#define ZF_FORMAT      4
+#define ZF_TILYEAR     5
+#define ZF_TILMONTH    6
+#define ZF_TILDAY      7
+#define ZF_TILTIME     8
+#define ZONE_MINFIELDS 5
+#define ZONE_MAXFIELDS 9
+
+/*
+** Which fields are which on a Zone continuation line.
+*/
+
+#define ZFC_GMTOFF     0
+#define ZFC_RULE       1
+#define ZFC_FORMAT     2
+#define ZFC_TILYEAR    3
+#define ZFC_TILMONTH   4
+#define ZFC_TILDAY     5
+#define ZFC_TILTIME    6
+#define ZONEC_MINFIELDS        3
+#define ZONEC_MAXFIELDS        7
+
+/*
+** Which files are which on a Rule line.
+*/
+
+#define RF_NAME                1
+#define RF_LOYEAR      2
+#define RF_HIYEAR      3
+#define RF_COMMAND     4
+#define RF_MONTH       5
+#define RF_DAY         6
+#define RF_TOD         7
+#define RF_STDOFF      8
+#define RF_ABBRVAR     9
+#define RULE_FIELDS    10
+
+/*
+** Which fields are which on a Link line.
+*/
+
+#define LF_FROM                1
+#define LF_TO          2
+#define LINK_FIELDS    3
+
+/*
+** Which fields are which on a Leap line.
+*/
+
+#define LP_YEAR                1
+#define LP_MONTH       2
+#define LP_DAY         3
+#define LP_TIME                4
+#define LP_CORR                5
+#define LP_ROLL                6
+#define LEAP_FIELDS    7
+
+/*
+** Year synonyms.
+*/
+
+#define YR_MINIMUM     0
+#define YR_MAXIMUM     1
+#define YR_ONLY                2
+
+static struct rule *   rules;
+static int             nrules; /* number of rules */
+
+static struct zone *   zones;
+static int             nzones; /* number of zones */
+
+struct link {
+       const char *    l_filename;
+       int             l_linenum;
+       const char *    l_from;
+       const char *    l_to;
+};
+
+static struct link *   links;
+static int             nlinks;
+
+struct lookup {
+       const char *    l_word;
+       const int       l_value;
+};
+
+static struct lookup const *   byword P((const char * string,
+                                       const struct lookup * lp));
+
+static struct lookup const     line_codes[] = {
+       { "Rule",       LC_RULE },
+       { "Zone",       LC_ZONE },
+       { "Link",       LC_LINK },
+       { "Leap",       LC_LEAP },
+       { NULL,         0}
+};
+
+static struct lookup const     mon_names[] = {
+       { "January",    TM_JANUARY },
+       { "February",   TM_FEBRUARY },
+       { "March",      TM_MARCH },
+       { "April",      TM_APRIL },
+       { "May",        TM_MAY },
+       { "June",       TM_JUNE },
+       { "July",       TM_JULY },
+       { "August",     TM_AUGUST },
+       { "September",  TM_SEPTEMBER },
+       { "October",    TM_OCTOBER },
+       { "November",   TM_NOVEMBER },
+       { "December",   TM_DECEMBER },
+       { NULL,         0 }
+};
+
+static struct lookup const     wday_names[] = {
+       { "Sunday",     TM_SUNDAY },
+       { "Monday",     TM_MONDAY },
+       { "Tuesday",    TM_TUESDAY },
+       { "Wednesday",  TM_WEDNESDAY },
+       { "Thursday",   TM_THURSDAY },
+       { "Friday",     TM_FRIDAY },
+       { "Saturday",   TM_SATURDAY },
+       { NULL,         0 }
+};
+
+static struct lookup const     lasts[] = {
+       { "last-Sunday",        TM_SUNDAY },
+       { "last-Monday",        TM_MONDAY },
+       { "last-Tuesday",       TM_TUESDAY },
+       { "last-Wednesday",     TM_WEDNESDAY },
+       { "last-Thursday",      TM_THURSDAY },
+       { "last-Friday",        TM_FRIDAY },
+       { "last-Saturday",      TM_SATURDAY },
+       { NULL,                 0 }
+};
+
+static struct lookup const     begin_years[] = {
+       { "minimum",    YR_MINIMUM },
+       { "maximum",    YR_MAXIMUM },
+       { NULL,         0 }
+};
+
+static struct lookup const     end_years[] = {
+       { "minimum",    YR_MINIMUM },
+       { "maximum",    YR_MAXIMUM },
+       { "only",       YR_ONLY },
+       { NULL,         0 }
+};
+
+static struct lookup const     leap_types[] = {
+       { "Rolling",    TRUE },
+       { "Stationary", FALSE },
+       { NULL,         0 }
+};
+
+static const int       len_months[2][MONSPERYEAR] = {
+       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int       len_years[2] = {
+       DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+static struct attype {
+       time_t          at;
+       unsigned char   type;
+}                      attypes[TZ_MAX_TIMES];
+static long            gmtoffs[TZ_MAX_TYPES];
+static char            isdsts[TZ_MAX_TYPES];
+static unsigned char   abbrinds[TZ_MAX_TYPES];
+static char            ttisstds[TZ_MAX_TYPES];
+static char            ttisgmts[TZ_MAX_TYPES];
+static char            chars[TZ_MAX_CHARS];
+static time_t          trans[TZ_MAX_LEAPS];
+static long            corr[TZ_MAX_LEAPS];
+static char            roll[TZ_MAX_LEAPS];
+
+/*
+** Memory allocation.
+*/
+
+static char *
+memcheck(ptr)
+char * const   ptr;
+{
+       if (ptr == NULL) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Memory exhausted: %s\n"),
+                       progname, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       return ptr;
+}
+
+#define emalloc(size)          memcheck(imalloc(size))
+#define erealloc(ptr, size)    memcheck(irealloc((ptr), (size)))
+#define ecpyalloc(ptr)         memcheck(icpyalloc(ptr))
+#define ecatalloc(oldp, newp)  memcheck(icatalloc((oldp), (newp)))
+
+/*
+** Error handling.
+*/
+
+#if !(HAVE_STRERROR - 0)
+static char *
+strerror(errnum)
+int    errnum;
+{
+       extern char *   sys_errlist[];
+       extern int      sys_nerr;
+
+       return (errnum > 0 && errnum <= sys_nerr) ?
+               sys_errlist[errnum] : "Unknown system error";
+}
+#endif /* !(HAVE_STRERROR - 0) */
+
+static void
+eats(name, num, rname, rnum)
+const char * const     name;
+const int              num;
+const char * const     rname;
+const int              rnum;
+{
+       filename = name;
+       linenum = num;
+       rfilename = rname;
+       rlinenum = rnum;
+}
+
+static void
+eat(name, num)
+const char * const     name;
+const int              num;
+{
+       eats(name, num, (char *) NULL, -1);
+}
+
+static void
+error(string)
+const char * const     string;
+{
+       /*
+       ** Match the format of "cc" to allow sh users to
+       **      zic ... 2>&1 | error -t "*" -v
+       ** on BSD systems.
+       */
+       (void) fprintf(stderr, _("\"%s\", line %d: %s"),
+               filename, linenum, string);
+       if (rfilename != NULL)
+               (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"),
+                       rfilename, rlinenum);
+       (void) fprintf(stderr, "\n");
+       ++errors;
+}
+
+static void
+warning(string)
+const char * const     string;
+{
+       char *  cp;
+
+       cp = ecpyalloc("warning: ");
+       cp = ecatalloc(cp, string);
+       error(string);
+       ifree(cp);
+       --errors;
+}
+
+static void
+usage P((void))
+{
+       (void) fprintf(stderr, _("%s: usage is %s [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ] [ -d directory ]\n\t[ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n"),
+               progname, progname);
+       (void) exit(EXIT_FAILURE);
+}
+
+static const char *    psxrules;
+static const char *    lcltime;
+static const char *    directory;
+static const char *    leapsec;
+static const char *    yitcommand;
+static int             sflag = FALSE;
+
+int
+main(argc, argv)
+int    argc;
+char * argv[];
+{
+       register int    i;
+       register int    j;
+       register int    c;
+
+#ifdef unix
+       (void) umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
+#endif /* defined unix */
+#if HAVE_GETTEXT - 0
+       (void) setlocale(LC_MESSAGES, "");
+#ifdef TZ_DOMAINDIR
+       (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
+#endif /* defined TEXTDOMAINDIR */
+       (void) textdomain(TZ_DOMAIN);
+#endif /* HAVE_GETTEXT - 0 */
+       progname = argv[0];
+       while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != -1)
+               switch (c) {
+                       default:
+                               usage();
+                       case 'd':
+                               if (directory == NULL)
+                                       directory = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -d option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'l':
+                               if (lcltime == NULL)
+                                       lcltime = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -l option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'p':
+                               if (psxrules == NULL)
+                                       psxrules = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -p option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'y':
+                               if (yitcommand == NULL)
+                                       yitcommand = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -y option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'L':
+                               if (leapsec == NULL)
+                                       leapsec = optarg;
+                               else {
+                                       (void) fprintf(stderr,
+_("%s: More than one -L option specified\n"),
+                                               progname);
+                                       (void) exit(EXIT_FAILURE);
+                               }
+                               break;
+                       case 'v':
+                               noise = TRUE;
+                               break;
+                       case 's':
+                               sflag = TRUE;
+                               break;
+               }
+       if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
+               usage();        /* usage message by request */
+       if (directory == NULL)
+               directory = TZDIR;
+       if (yitcommand == NULL)
+               yitcommand = "yearistype";
+
+       setboundaries();
+
+       if (optind < argc && leapsec != NULL) {
+               infile(leapsec);
+               adjleap();
+       }
+
+       for (i = optind; i < argc; ++i)
+               infile(argv[i]);
+       if (errors)
+               (void) exit(EXIT_FAILURE);
+       associate();
+       for (i = 0; i < nzones; i = j) {
+               /*
+               ** Find the next non-continuation zone entry.
+               */
+               for (j = i + 1; j < nzones && zones[j].z_name == NULL; ++j)
+                       continue;
+               outzone(&zones[i], j - i);
+       }
+       /*
+       ** Make links.
+       */
+       for (i = 0; i < nlinks; ++i)
+               dolink(links[i].l_from, links[i].l_to);
+       if (lcltime != NULL)
+               dolink(lcltime, TZDEFAULT);
+       if (psxrules != NULL)
+               dolink(psxrules, TZDEFRULES);
+       return (errors == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+static void
+dolink(fromfile, tofile)
+const char * const     fromfile;
+const char * const     tofile;
+{
+       register char * fromname;
+       register char * toname;
+
+       if (fromfile[0] == '/')
+               fromname = ecpyalloc(fromfile);
+       else {
+               fromname = ecpyalloc(directory);
+               fromname = ecatalloc(fromname, "/");
+               fromname = ecatalloc(fromname, fromfile);
+       }
+       if (tofile[0] == '/')
+               toname = ecpyalloc(tofile);
+       else {
+               toname = ecpyalloc(directory);
+               toname = ecatalloc(toname, "/");
+               toname = ecatalloc(toname, tofile);
+       }
+       /*
+       ** We get to be careful here since
+       ** there's a fair chance of root running us.
+       */
+       if (!itsdir(toname))
+               (void) remove(toname);
+       if (link(fromname, toname) != 0) {
+               if (mkdirs(toname) != 0)
+                       (void) exit(EXIT_FAILURE);
+               if (link(fromname, toname) != 0) {
+                       const char *e = strerror(errno);
+
+                       (void) fprintf(stderr,
+                               _("%s: Can't link from %s to %s: %s\n"),
+                               progname, fromname, toname, e);
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       ifree(fromname);
+       ifree(toname);
+}
+
+#ifndef INT_MAX
+#define INT_MAX        ((int) (((unsigned)~0)>>1))
+#endif /* !defined INT_MAX */
+
+#ifndef INT_MIN
+#define INT_MIN        ((int) ~(((unsigned)~0)>>1))
+#endif /* !defined INT_MIN */
+
+/*
+** The tz file format currently allows at most 32-bit quantities.
+** This restriction should be removed before signed 32-bit values
+** wrap around in 2038, but unfortunately this will require a
+** change to the tz file format.
+*/
+
+#define MAX_BITS_IN_FILE       32
+#define TIME_T_BITS_IN_FILE    ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
+
+static void
+setboundaries P((void))
+{
+       if (TYPE_SIGNED(time_t)) {
+               min_time = ~ (time_t) 0;
+               min_time <<= TIME_T_BITS_IN_FILE - 1;
+               max_time = ~ (time_t) 0 - min_time;
+               if (sflag)
+                       min_time = 0;
+       } else {
+               min_time = 0;
+               max_time = 2 - sflag;
+               max_time <<= TIME_T_BITS_IN_FILE - 1;
+               --max_time;
+       }
+       min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
+       max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
+}
+
+static int
+itsdir(name)
+const char * const     name;
+{
+       register char * myname;
+       register int    accres;
+
+       myname = ecpyalloc(name);
+       myname = ecatalloc(myname, "/.");
+       accres = access(myname, F_OK);
+       ifree(myname);
+       return accres == 0;
+}
+
+/*
+** Associate sets of rules with zones.
+*/
+
+/*
+** Sort by rule name.
+*/
+
+static int
+rcomp(cp1, cp2)
+const void *   cp1;
+const void *   cp2;
+{
+       return strcmp(((const struct rule *) cp1)->r_name,
+               ((const struct rule *) cp2)->r_name);
+}
+
+static void
+associate P((void))
+{
+       register struct zone *  zp;
+       register struct rule *  rp;
+       register int            base, out;
+       register int            i, j;
+
+       if (nrules != 0) {
+               (void) qsort((void *) rules, (size_t) nrules,
+                       (size_t) sizeof *rules, rcomp);
+               for (i = 0; i < nrules - 1; ++i) {
+                       if (strcmp(rules[i].r_name,
+                               rules[i + 1].r_name) != 0)
+                                       continue;
+                       if (strcmp(rules[i].r_filename,
+                               rules[i + 1].r_filename) == 0)
+                                       continue;
+                       eat(rules[i].r_filename, rules[i].r_linenum);
+                       warning(_("same rule name in multiple files"));
+                       eat(rules[i + 1].r_filename, rules[i + 1].r_linenum);
+                       warning(_("same rule name in multiple files"));
+                       for (j = i + 2; j < nrules; ++j) {
+                               if (strcmp(rules[i].r_name,
+                                       rules[j].r_name) != 0)
+                                               break;
+                               if (strcmp(rules[i].r_filename,
+                                       rules[j].r_filename) == 0)
+                                               continue;
+                               if (strcmp(rules[i + 1].r_filename,
+                                       rules[j].r_filename) == 0)
+                                               continue;
+                               break;
+                       }
+                       i = j - 1;
+               }
+       }
+       for (i = 0; i < nzones; ++i) {
+               zp = &zones[i];
+               zp->z_rules = NULL;
+               zp->z_nrules = 0;
+       }
+       for (base = 0; base < nrules; base = out) {
+               rp = &rules[base];
+               for (out = base + 1; out < nrules; ++out)
+                       if (strcmp(rp->r_name, rules[out].r_name) != 0)
+                               break;
+               for (i = 0; i < nzones; ++i) {
+                       zp = &zones[i];
+                       if (strcmp(zp->z_rule, rp->r_name) != 0)
+                               continue;
+                       zp->z_rules = rp;
+                       zp->z_nrules = out - base;
+               }
+       }
+       for (i = 0; i < nzones; ++i) {
+               zp = &zones[i];
+               if (zp->z_nrules == 0) {
+                       /*
+                       ** Maybe we have a local standard time offset.
+                       */
+                       eat(zp->z_filename, zp->z_linenum);
+                       zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"),
+                                             TRUE);
+                       /*
+                       ** Note, though, that if there's no rule,
+                       ** a '%s' in the format is a bad thing.
+                       */
+                       if (strchr(zp->z_format, '%') != 0)
+                               error(_("%s in ruleless zone"));
+               }
+       }
+       if (errors)
+               (void) exit(EXIT_FAILURE);
+}
+
+static void
+infile(name)
+const char *   name;
+{
+       register FILE *                 fp;
+       register char **                fields;
+       register char *                 cp;
+       register const struct lookup *  lp;
+       register int                    nfields;
+       register int                    wantcont;
+       register int                    num;
+       char                            buf[BUFSIZ];
+
+       if (strcmp(name, "-") == 0) {
+               name = _("standard input");
+               fp = stdin;
+       } else if ((fp = fopen(name, "r")) == NULL) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Can't open %s: %s\n"),
+                       progname, name, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       wantcont = FALSE;
+       for (num = 1; ; ++num) {
+               eat(name, num);
+               if (fgets(buf, (int) sizeof buf, fp) != buf)
+                       break;
+               cp = strchr(buf, '\n');
+               if (cp == NULL) {
+                       error(_("line too long"));
+                       (void) exit(EXIT_FAILURE);
+               }
+               *cp = '\0';
+               fields = getfields(buf);
+               nfields = 0;
+               while (fields[nfields] != NULL) {
+                       static char     nada;
+
+                       if (strcmp(fields[nfields], "-") == 0)
+                               fields[nfields] = &nada;
+                       ++nfields;
+               }
+               if (nfields == 0) {
+                       /* nothing to do */
+               } else if (wantcont) {
+                       wantcont = inzcont(fields, nfields);
+               } else {
+                       lp = byword(fields[0], line_codes);
+                       if (lp == NULL)
+                               error(_("input line of unknown type"));
+                       else switch ((int) (lp->l_value)) {
+                               case LC_RULE:
+                                       inrule(fields, nfields);
+                                       wantcont = FALSE;
+                                       break;
+                               case LC_ZONE:
+                                       wantcont = inzone(fields, nfields);
+                                       break;
+                               case LC_LINK:
+                                       inlink(fields, nfields);
+                                       wantcont = FALSE;
+                                       break;
+                               case LC_LEAP:
+                                       if (name != leapsec)
+                                               (void) fprintf(stderr,
+_("%s: Leap line in non leap seconds file %s\n"),
+                                                       progname, name);
+                                       else    inleap(fields, nfields);
+                                       wantcont = FALSE;
+                                       break;
+                               default:        /* "cannot happen" */
+                                       (void) fprintf(stderr,
+_("%s: panic: Invalid l_value %d\n"),
+                                               progname, lp->l_value);
+                                       (void) exit(EXIT_FAILURE);
+                       }
+               }
+               ifree((char *) fields);
+       }
+       if (ferror(fp)) {
+               (void) fprintf(stderr, _("%s: Error reading %s\n"),
+                       progname, filename);
+               (void) exit(EXIT_FAILURE);
+       }
+       if (fp != stdin && fclose(fp)) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Error closing %s: %s\n"),
+                       progname, filename, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       if (wantcont)
+               error(_("expected continuation line not found"));
+}
+
+/*
+** Convert a string of one of the forms
+**     h       -h      hh:mm   -hh:mm  hh:mm:ss        -hh:mm:ss
+** into a number of seconds.
+** A null string maps to zero.
+** Call error with errstring and return zero on errors.
+*/
+
+static long
+gethms(string, errstring, signable)
+const char *           string;
+const char * const     errstring;
+const int              signable;
+{
+       int     hh, mm, ss, sign;
+
+       if (string == NULL || *string == '\0')
+               return 0;
+       if (!signable)
+               sign = 1;
+       else if (*string == '-') {
+               sign = -1;
+               ++string;
+       } else  sign = 1;
+       if (sscanf(string, scheck(string, "%d"), &hh) == 1)
+               mm = ss = 0;
+       else if (sscanf(string, scheck(string, "%d:%d"), &hh, &mm) == 2)
+               ss = 0;
+       else if (sscanf(string, scheck(string, "%d:%d:%d"),
+               &hh, &mm, &ss) != 3) {
+                       error(errstring);
+                       return 0;
+       }
+       if (hh < 0 || hh >= HOURSPERDAY ||
+               mm < 0 || mm >= MINSPERHOUR ||
+               ss < 0 || ss > SECSPERMIN) {
+                       error(errstring);
+                       return 0;
+       }
+       return eitol(sign) *
+               (eitol(hh * MINSPERHOUR + mm) *
+               eitol(SECSPERMIN) + eitol(ss));
+}
+
+static void
+inrule(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       static struct rule      r;
+
+       if (nfields != RULE_FIELDS) {
+               error(_("wrong number of fields on Rule line"));
+               return;
+       }
+       if (*fields[RF_NAME] == '\0') {
+               error(_("nameless rule"));
+               return;
+       }
+       r.r_filename = filename;
+       r.r_linenum = linenum;
+       r.r_stdoff = gethms(fields[RF_STDOFF], _("invalid saved time"), TRUE);
+       rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND],
+               fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]);
+       r.r_name = ecpyalloc(fields[RF_NAME]);
+       r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]);
+       rules = (struct rule *) (void *) erealloc((char *) rules,
+               (int) ((nrules + 1) * sizeof *rules));
+       rules[nrules++] = r;
+}
+
+static int
+inzone(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       register int    i;
+       static char *   buf;
+
+       if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
+               error(_("wrong number of fields on Zone line"));
+               return FALSE;
+       }
+       if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) {
+               buf = erealloc(buf, (int) (132 + strlen(TZDEFAULT)));
+               (void) sprintf(buf,
+_("\"Zone %s\" line and -l option are mutually exclusive"),
+                       TZDEFAULT);
+               error(buf);
+               return FALSE;
+       }
+       if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
+               buf = erealloc(buf, (int) (132 + strlen(TZDEFRULES)));
+               (void) sprintf(buf,
+_("\"Zone %s\" line and -p option are mutually exclusive"),
+                       TZDEFRULES);
+               error(buf);
+               return FALSE;
+       }
+       for (i = 0; i < nzones; ++i)
+               if (zones[i].z_name != NULL &&
+                       strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
+                               buf = erealloc(buf, (int) (132 +
+                                       strlen(fields[ZF_NAME]) +
+                                       strlen(zones[i].z_filename)));
+                               (void) sprintf(buf,
+_("duplicate zone name %s (file \"%s\", line %d)"),
+                                       fields[ZF_NAME],
+                                       zones[i].z_filename,
+                                       zones[i].z_linenum);
+                               error(buf);
+                               return FALSE;
+               }
+       return inzsub(fields, nfields, FALSE);
+}
+
+static int
+inzcont(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
+               error(_("wrong number of fields on Zone continuation line"));
+               return FALSE;
+       }
+       return inzsub(fields, nfields, TRUE);
+}
+
+static int
+inzsub(fields, nfields, iscont)
+register char ** const fields;
+const int              nfields;
+const int              iscont;
+{
+       register char *         cp;
+       static struct zone      z;
+       register int            i_gmtoff, i_rule, i_format;
+       register int            i_untilyear, i_untilmonth;
+       register int            i_untilday, i_untiltime;
+       register int            hasuntil;
+
+       if (iscont) {
+               i_gmtoff = ZFC_GMTOFF;
+               i_rule = ZFC_RULE;
+               i_format = ZFC_FORMAT;
+               i_untilyear = ZFC_TILYEAR;
+               i_untilmonth = ZFC_TILMONTH;
+               i_untilday = ZFC_TILDAY;
+               i_untiltime = ZFC_TILTIME;
+               z.z_name = NULL;
+       } else {
+               i_gmtoff = ZF_GMTOFF;
+               i_rule = ZF_RULE;
+               i_format = ZF_FORMAT;
+               i_untilyear = ZF_TILYEAR;
+               i_untilmonth = ZF_TILMONTH;
+               i_untilday = ZF_TILDAY;
+               i_untiltime = ZF_TILTIME;
+               z.z_name = ecpyalloc(fields[ZF_NAME]);
+       }
+       z.z_filename = filename;
+       z.z_linenum = linenum;
+       z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid GMT offset"), TRUE);
+       if ((cp = strchr(fields[i_format], '%')) != 0) {
+               if (*++cp != 's' || strchr(cp, '%') != 0) {
+                       error(_("invalid abbreviation format"));
+                       return FALSE;
+               }
+       }
+       z.z_rule = ecpyalloc(fields[i_rule]);
+       z.z_format = ecpyalloc(fields[i_format]);
+       hasuntil = nfields > i_untilyear;
+       if (hasuntil) {
+               z.z_untilrule.r_filename = filename;
+               z.z_untilrule.r_linenum = linenum;
+               rulesub(&z.z_untilrule,
+                       fields[i_untilyear],
+                       "only",
+                       "",
+                       (nfields > i_untilmonth) ?
+                       fields[i_untilmonth] : "Jan",
+                       (nfields > i_untilday) ? fields[i_untilday] : "1",
+                       (nfields > i_untiltime) ? fields[i_untiltime] : "0");
+               z.z_untiltime = rpytime(&z.z_untilrule,
+                       z.z_untilrule.r_loyear);
+               if (iscont && nzones > 0 &&
+                       z.z_untiltime > min_time &&
+                       z.z_untiltime < max_time &&
+                       zones[nzones - 1].z_untiltime > min_time &&
+                       zones[nzones - 1].z_untiltime < max_time &&
+                       zones[nzones - 1].z_untiltime >= z.z_untiltime) {
+                               error(_("Zone continuation line end time is not after end time of previous line"));
+                               return FALSE;
+               }
+       }
+       zones = (struct zone *) (void *) erealloc((char *) zones,
+               (int) ((nzones + 1) * sizeof *zones));
+       zones[nzones++] = z;
+       /*
+       ** If there was an UNTIL field on this line,
+       ** there's more information about the zone on the next line.
+       */
+       return hasuntil;
+}
+
+static void
+inleap(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       register const char *           cp;
+       register const struct lookup *  lp;
+       register int                    i, j;
+       int                             year, month, day;
+       long                            dayoff, tod;
+       time_t                          t;
+
+       if (nfields != LEAP_FIELDS) {
+               error(_("wrong number of fields on Leap line"));
+               return;
+       }
+       dayoff = 0;
+       cp = fields[LP_YEAR];
+       if (sscanf(cp, scheck(cp, "%d"), &year) != 1) {
+                       /*
+                        * Leapin' Lizards!
+                        */
+                       error(_("invalid leaping year"));
+                       return;
+       }
+       j = EPOCH_YEAR;
+       while (j != year) {
+               if (year > j) {
+                       i = len_years[isleap(j)];
+                       ++j;
+               } else {
+                       --j;
+                       i = -len_years[isleap(j)];
+               }
+               dayoff = oadd(dayoff, eitol(i));
+       }
+       if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
+               error(_("invalid month name"));
+               return;
+       }
+       month = lp->l_value;
+       j = TM_JANUARY;
+       while (j != month) {
+               i = len_months[isleap(year)][j];
+               dayoff = oadd(dayoff, eitol(i));
+               ++j;
+       }
+       cp = fields[LP_DAY];
+       if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
+               day <= 0 || day > len_months[isleap(year)][month]) {
+                       error(_("invalid day of month"));
+                       return;
+       }
+       dayoff = oadd(dayoff, eitol(day - 1));
+       if (dayoff < 0 && !TYPE_SIGNED(time_t)) {
+               error(_("time before zero"));
+               return;
+       }
+       t = (time_t) dayoff * SECSPERDAY;
+       /*
+       ** Cheap overflow check.
+       */
+       if (t / SECSPERDAY != dayoff) {
+               error(_("time overflow"));
+               return;
+       }
+       tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
+       cp = fields[LP_CORR];
+       {
+               register int    positive;
+               int             count;
+
+               if (strcmp(cp, "") == 0) { /* infile() turns "-" into "" */
+                       positive = FALSE;
+                       count = 1;
+               } else if (strcmp(cp, "--") == 0) {
+                       positive = FALSE;
+                       count = 2;
+               } else if (strcmp(cp, "+") == 0) {
+                       positive = TRUE;
+                       count = 1;
+               } else if (strcmp(cp, "++") == 0) {
+                       positive = TRUE;
+                       count = 2;
+               } else {
+                       error(_("illegal CORRECTION field on Leap line"));
+                       return;
+               }
+               if ((lp = byword(fields[LP_ROLL], leap_types)) == NULL) {
+                       error(_("illegal Rolling/Stationary field on Leap line"));
+                       return;
+               }
+               leapadd(tadd(t, tod), positive, lp->l_value, count);
+       }
+}
+
+static void
+inlink(fields, nfields)
+register char ** const fields;
+const int              nfields;
+{
+       struct link     l;
+
+       if (nfields != LINK_FIELDS) {
+               error(_("wrong number of fields on Link line"));
+               return;
+       }
+       if (*fields[LF_FROM] == '\0') {
+               error(_("blank FROM field on Link line"));
+               return;
+       }
+       if (*fields[LF_TO] == '\0') {
+               error(_("blank TO field on Link line"));
+               return;
+       }
+       l.l_filename = filename;
+       l.l_linenum = linenum;
+       l.l_from = ecpyalloc(fields[LF_FROM]);
+       l.l_to = ecpyalloc(fields[LF_TO]);
+       links = (struct link *) (void *) erealloc((char *) links,
+               (int) ((nlinks + 1) * sizeof *links));
+       links[nlinks++] = l;
+}
+
+static void
+rulesub(rp, loyearp, hiyearp, typep, monthp, dayp, timep)
+register struct rule * const   rp;
+const char * const             loyearp;
+const char * const             hiyearp;
+const char * const             typep;
+const char * const             monthp;
+const char * const             dayp;
+const char * const             timep;
+{
+       register const struct lookup *  lp;
+       register const char *           cp;
+       register char *                 dp;
+       register char *                 ep;
+
+       if ((lp = byword(monthp, mon_names)) == NULL) {
+               error(_("invalid month name"));
+               return;
+       }
+       rp->r_month = lp->l_value;
+       rp->r_todisstd = FALSE;
+       rp->r_todisgmt = FALSE;
+       dp = ecpyalloc(timep);
+       if (*dp != '\0') {
+               ep = dp + strlen(dp) - 1;
+               switch (lowerit(*ep)) {
+                       case 's':       /* Standard */
+                               rp->r_todisstd = TRUE;
+                               rp->r_todisgmt = FALSE;
+                               *ep = '\0';
+                               break;
+                       case 'w':       /* Wall */
+                               rp->r_todisstd = FALSE;
+                               rp->r_todisgmt = FALSE;
+                               *ep = '\0';
+                       case 'g':       /* Greenwich */
+                       case 'u':       /* Universal */
+                       case 'z':       /* Zulu */
+                               rp->r_todisstd = TRUE;
+                               rp->r_todisgmt = TRUE;
+                               *ep = '\0';
+                               break;
+               }
+       }
+       rp->r_tod = gethms(dp, _("invalid time of day"), FALSE);
+       ifree(dp);
+       /*
+       ** Year work.
+       */
+       cp = loyearp;
+       lp = byword(cp, begin_years);
+       if (lp != NULL) switch ((int) lp->l_value) {
+               case YR_MINIMUM:
+                       rp->r_loyear = INT_MIN;
+                       break;
+               case YR_MAXIMUM:
+                       rp->r_loyear = INT_MAX;
+                       break;
+               default:        /* "cannot happen" */
+                       (void) fprintf(stderr,
+                               _("%s: panic: Invalid l_value %d\n"),
+                               progname, lp->l_value);
+                       (void) exit(EXIT_FAILURE);
+       } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_loyear) != 1) {
+               error(_("invalid starting year"));
+               return;
+       }
+       cp = hiyearp;
+       if ((lp = byword(cp, end_years)) != NULL) switch ((int) lp->l_value) {
+               case YR_MINIMUM:
+                       rp->r_hiyear = INT_MIN;
+                       break;
+               case YR_MAXIMUM:
+                       rp->r_hiyear = INT_MAX;
+                       break;
+               case YR_ONLY:
+                       rp->r_hiyear = rp->r_loyear;
+                       break;
+               default:        /* "cannot happen" */
+                       (void) fprintf(stderr,
+                               _("%s: panic: Invalid l_value %d\n"),
+                               progname, lp->l_value);
+                       (void) exit(EXIT_FAILURE);
+       } else if (sscanf(cp, scheck(cp, "%d"), &rp->r_hiyear) != 1) {
+               error(_("invalid ending year"));
+               return;
+       }
+       if (rp->r_loyear > rp->r_hiyear) {
+               error(_("starting year greater than ending year"));
+               return;
+       }
+       if (*typep == '\0')
+               rp->r_yrtype = NULL;
+       else {
+               if (rp->r_loyear == rp->r_hiyear) {
+                       error(_("typed single year"));
+                       return;
+               }
+               rp->r_yrtype = ecpyalloc(typep);
+       }
+       /*
+       ** Day work.
+       ** Accept things such as:
+       **      1
+       **      last-Sunday
+       **      Sun<=20
+       **      Sun>=7
+       */
+       dp = ecpyalloc(dayp);
+       if ((lp = byword(dp, lasts)) != NULL) {
+               rp->r_dycode = DC_DOWLEQ;
+               rp->r_wday = lp->l_value;
+               rp->r_dayofmonth = len_months[1][rp->r_month];
+       } else {
+               if ((ep = strchr(dp, '<')) != 0)
+                       rp->r_dycode = DC_DOWLEQ;
+               else if ((ep = strchr(dp, '>')) != 0)
+                       rp->r_dycode = DC_DOWGEQ;
+               else {
+                       ep = dp;
+                       rp->r_dycode = DC_DOM;
+               }
+               if (rp->r_dycode != DC_DOM) {
+                       *ep++ = 0;
+                       if (*ep++ != '=') {
+                               error(_("invalid day of month"));
+                               ifree(dp);
+                               return;
+                       }
+                       if ((lp = byword(dp, wday_names)) == NULL) {
+                               error(_("invalid weekday name"));
+                               ifree(dp);
+                               return;
+                       }
+                       rp->r_wday = lp->l_value;
+               }
+               if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
+                       rp->r_dayofmonth <= 0 ||
+                       (rp->r_dayofmonth > len_months[1][rp->r_month])) {
+                               error(_("invalid day of month"));
+                               ifree(dp);
+                               return;
+               }
+       }
+       ifree(dp);
+}
+
+static void
+convert(val, buf)
+const long     val;
+char * const   buf;
+{
+       register int    i;
+       register long   shift;
+
+       for (i = 0, shift = 24; i < 4; ++i, shift -= 8)
+               buf[i] = val >> shift;
+}
+
+static void
+puttzcode(val, fp)
+const long     val;
+FILE * const   fp;
+{
+       char    buf[4];
+
+       convert(val, buf);
+       (void) fwrite((void *) buf, (size_t) sizeof buf, (size_t) 1, fp);
+}
+
+static int
+atcomp(avp, bvp)
+void * avp;
+void * bvp;
+{
+       if (((struct attype *) avp)->at < ((struct attype *) bvp)->at)
+               return -1;
+       else if (((struct attype *) avp)->at > ((struct attype *) bvp)->at)
+               return 1;
+       else    return 0;
+}
+
+static void
+writezone(name)
+const char * const     name;
+{
+       register FILE *         fp;
+       register int            i, j;
+       static char *           fullname;
+       static struct tzhead    tzh;
+       time_t                  ats[TZ_MAX_TIMES];
+       unsigned char           types[TZ_MAX_TIMES];
+
+       /*
+       ** Sort.
+       */
+       if (timecnt > 1)
+               (void) qsort((void *) attypes, (size_t) timecnt,
+                       (size_t) sizeof *attypes, atcomp);
+       /*
+       ** Optimize.
+       */
+       {
+               int     fromi;
+               int     toi;
+
+               toi = 0;
+               fromi = 0;
+               if (isdsts[0] == 0)
+                       while (attypes[fromi].type == 0)
+                               ++fromi;        /* handled by default rule */
+               for ( ; fromi < timecnt; ++fromi) {
+                       if (toi != 0
+                           && ((attypes[fromi].at
+                                + gmtoffs[attypes[toi - 1].type])
+                               <= (attypes[toi - 1].at
+                                   + gmtoffs[toi == 1 ? 0
+                                             : attypes[toi - 2].type]))) {
+                               attypes[toi - 1].type = attypes[fromi].type;
+                               continue;
+                       }
+                       if (toi == 0 ||
+                               attypes[toi - 1].type != attypes[fromi].type)
+                                       attypes[toi++] = attypes[fromi];
+               }
+               timecnt = toi;
+       }
+       /*
+       ** Transfer.
+       */
+       for (i = 0; i < timecnt; ++i) {
+               ats[i] = attypes[i].at;
+               types[i] = attypes[i].type;
+       }
+       fullname = erealloc(fullname,
+               (int) (strlen(directory) + 1 + strlen(name) + 1));
+       (void) sprintf(fullname, "%s/%s", directory, name);
+       /*
+       ** Remove old file, if any, to snap links.
+       */
+       if (!itsdir(fullname) && remove(fullname) != 0 && errno != ENOENT) {
+               const char *e = strerror(errno);
+
+               (void) fprintf(stderr, _("%s: Can't remove %s: %s\n"),
+                       progname, fullname, e);
+               (void) exit(EXIT_FAILURE);
+       }
+       if ((fp = fopen(fullname, "wb")) == NULL) {
+               if (mkdirs(fullname) != 0)
+                       (void) exit(EXIT_FAILURE);
+               if ((fp = fopen(fullname, "wb")) == NULL) {
+                       const char *e = strerror(errno);
+
+                       (void) fprintf(stderr, _("%s: Can't create %s: %s\n"),
+                               progname, fullname, e);
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       convert(eitol(typecnt), tzh.tzh_ttisgmtcnt);
+       convert(eitol(typecnt), tzh.tzh_ttisstdcnt);
+       convert(eitol(leapcnt), tzh.tzh_leapcnt);
+       convert(eitol(timecnt), tzh.tzh_timecnt);
+       convert(eitol(typecnt), tzh.tzh_typecnt);
+       convert(eitol(charcnt), tzh.tzh_charcnt);
+#define DO(field)      (void) fwrite((void *) tzh.field, (size_t) sizeof tzh.field, (size_t) 1, fp)
+       DO(tzh_reserved);
+       DO(tzh_ttisgmtcnt);
+       DO(tzh_ttisstdcnt);
+       DO(tzh_leapcnt);
+       DO(tzh_timecnt);
+       DO(tzh_typecnt);
+       DO(tzh_charcnt);
+#undef DO
+       for (i = 0; i < timecnt; ++i) {
+               j = leapcnt;
+               while (--j >= 0)
+                       if (ats[i] >= trans[j]) {
+                               ats[i] = tadd(ats[i], corr[j]);
+                               break;
+                       }
+               puttzcode((long) ats[i], fp);
+       }
+       if (timecnt > 0)
+               (void) fwrite((void *) types, (size_t) sizeof types[0],
+                       (size_t) timecnt, fp);
+       for (i = 0; i < typecnt; ++i) {
+               puttzcode((long) gmtoffs[i], fp);
+               (void) putc(isdsts[i], fp);
+               (void) putc(abbrinds[i], fp);
+       }
+       if (charcnt != 0)
+               (void) fwrite((void *) chars, (size_t) sizeof chars[0],
+                       (size_t) charcnt, fp);
+       for (i = 0; i < leapcnt; ++i) {
+               if (roll[i]) {
+                       if (timecnt == 0 || trans[i] < ats[0]) {
+                               j = 0;
+                               while (isdsts[j])
+                                       if (++j >= typecnt) {
+                                               j = 0;
+                                               break;
+                                       }
+                       } else {
+                               j = 1;
+                               while (j < timecnt && trans[i] >= ats[j])
+                                       ++j;
+                               j = types[j - 1];
+                       }
+                       puttzcode((long) tadd(trans[i], -gmtoffs[j]), fp);
+               } else  puttzcode((long) trans[i], fp);
+               puttzcode((long) corr[i], fp);
+       }
+       for (i = 0; i < typecnt; ++i)
+               (void) putc(ttisstds[i], fp);
+       for (i = 0; i < typecnt; ++i)
+               (void) putc(ttisgmts[i], fp);
+       if (ferror(fp) || fclose(fp)) {
+               (void) fprintf(stderr, _("%s: Error writing %s\n"),
+                       progname, fullname);
+               (void) exit(EXIT_FAILURE);
+       }
+}
+
+static void
+doabbr(abbr, format, letters, isdst)
+char * const           abbr;
+const char * const     format;
+const char * const     letters;
+const int              isdst;
+{
+       if (strchr(format, '/') == NULL) {
+               if (letters == NULL)
+                       (void) strcpy(abbr, format);
+               else    (void) sprintf(abbr, format, letters);
+       } else if (isdst)
+               (void) strcpy(abbr, strchr(format, '/') + 1);
+       else {
+               (void) strcpy(abbr, format);
+               *strchr(abbr, '/') = '\0';
+       }
+}
+
+static void
+outzone(zpfirst, zonecount)
+const struct zone * const      zpfirst;
+const int                      zonecount;
+{
+       register const struct zone *    zp;
+       register struct rule *          rp;
+       register int                    i, j;
+       register int                    usestart, useuntil;
+       register time_t                 starttime, untiltime;
+       register long                   gmtoff;
+       register long                   stdoff;
+       register int                    year;
+       register long                   startoff;
+       register int                    startttisstd;
+       register int                    startttisgmt;
+       register int                    type;
+       char                            startbuf[BUFSIZ];
+
+       INITIALIZE(untiltime);
+       INITIALIZE(starttime);
+       /*
+       ** Now. . .finally. . .generate some useful data!
+       */
+       timecnt = 0;
+       typecnt = 0;
+       charcnt = 0;
+       /*
+       ** A guess that may well be corrected later.
+       */
+       stdoff = 0;
+       /*
+       ** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)
+       ** for noting the need to unconditionally initialize startttisstd.
+       */
+       startttisstd = FALSE;
+       startttisgmt = FALSE;
+       for (i = 0; i < zonecount; ++i) {
+               zp = &zpfirst[i];
+               usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
+               useuntil = i < (zonecount - 1);
+               if (useuntil && zp->z_untiltime <= min_time)
+                       continue;
+               gmtoff = zp->z_gmtoff;
+               eat(zp->z_filename, zp->z_linenum);
+               *startbuf = '\0';
+               startoff = zp->z_gmtoff;
+               if (zp->z_nrules == 0) {
+                       stdoff = zp->z_stdoff;
+                       doabbr(startbuf, zp->z_format,
+                               (char *) NULL, stdoff != 0);
+                       type = addtype(oadd(zp->z_gmtoff, stdoff),
+                               startbuf, stdoff != 0, startttisstd,
+                               startttisgmt);
+                       if (usestart) {
+                               addtt(starttime, type);
+                               usestart = FALSE;
+                       }
+                       else if (stdoff != 0)
+                               addtt(min_time, type);
+               } else for (year = min_year; year <= max_year; ++year) {
+                       if (useuntil && year > zp->z_untilrule.r_hiyear)
+                               break;
+                       /*
+                       ** Mark which rules to do in the current year.
+                       ** For those to do, calculate rpytime(rp, year);
+                       */
+                       for (j = 0; j < zp->z_nrules; ++j) {
+                               rp = &zp->z_rules[j];
+                               eats(zp->z_filename, zp->z_linenum,
+                                       rp->r_filename, rp->r_linenum);
+                               rp->r_todo = year >= rp->r_loyear &&
+                                               year <= rp->r_hiyear &&
+                                               yearistype(year, rp->r_yrtype);
+                               if (rp->r_todo)
+                                       rp->r_temp = rpytime(rp, year);
+                       }
+                       for ( ; ; ) {
+                               register int    k;
+                               register time_t jtime, ktime;
+                               register long   offset;
+                               char            buf[BUFSIZ];
+
+                               INITIALIZE(ktime);
+                               if (useuntil) {
+                                       /*
+                                       ** Turn untiltime into GMT
+                                       ** assuming the current gmtoff and
+                                       ** stdoff values.
+                                       */
+                                       untiltime = zp->z_untiltime;
+                                       if (!zp->z_untilrule.r_todisgmt)
+                                               untiltime = tadd(untiltime,
+                                                       -gmtoff);
+                                       if (!zp->z_untilrule.r_todisstd)
+                                               untiltime = tadd(untiltime,
+                                                       -stdoff);
+                               }
+                               /*
+                               ** Find the rule (of those to do, if any)
+                               ** that takes effect earliest in the year.
+                               */
+                               k = -1;
+                               for (j = 0; j < zp->z_nrules; ++j) {
+                                       rp = &zp->z_rules[j];
+                                       if (!rp->r_todo)
+                                               continue;
+                                       eats(zp->z_filename, zp->z_linenum,
+                                               rp->r_filename, rp->r_linenum);
+                                       offset = rp->r_todisgmt ? 0 : gmtoff;
+                                       if (!rp->r_todisstd)
+                                               offset = oadd(offset, stdoff);
+                                       jtime = rp->r_temp;
+                                       if (jtime == min_time ||
+                                               jtime == max_time)
+                                                       continue;
+                                       jtime = tadd(jtime, -offset);
+                                       if (k < 0 || jtime < ktime) {
+                                               k = j;
+                                               ktime = jtime;
+                                       }
+                               }
+                               if (k < 0)
+                                       break;  /* go on to next year */
+                               rp = &zp->z_rules[k];
+                               rp->r_todo = FALSE;
+                               if (useuntil && ktime >= untiltime)
+                                       break;
+                               stdoff = rp->r_stdoff;
+                               if (usestart && ktime == starttime)
+                                       usestart = FALSE;
+                               if (usestart) {
+                                       if (ktime < starttime) {
+                                               startoff = oadd(zp->z_gmtoff,
+                                                       stdoff);
+                                               doabbr(startbuf, zp->z_format,
+                                                       rp->r_abbrvar,
+                                                       rp->r_stdoff != 0);
+                                               continue;
+                                       }
+                                       if (*startbuf == '\0' &&
+                                           startoff == oadd(zp->z_gmtoff,
+                                           stdoff)) {
+                                               doabbr(startbuf, zp->z_format,
+                                                       rp->r_abbrvar,
+                                                       rp->r_stdoff != 0);
+                                       }
+                               }
+                               eats(zp->z_filename, zp->z_linenum,
+                                       rp->r_filename, rp->r_linenum);
+                               doabbr(buf, zp->z_format, rp->r_abbrvar,
+                                       rp->r_stdoff != 0);
+                               offset = oadd(zp->z_gmtoff, rp->r_stdoff);
+                               type = addtype(offset, buf, rp->r_stdoff != 0,
+                                       rp->r_todisstd, rp->r_todisgmt);
+                               addtt(ktime, type);
+                       }
+               }
+               if (usestart) {
+                       if (*startbuf == '\0' &&
+                               zp->z_format != NULL &&
+                               strchr(zp->z_format, '%') == NULL &&
+                               strchr(zp->z_format, '/') == NULL)
+                                       (void) strcpy(startbuf, zp->z_format);
+                       eat(zp->z_filename, zp->z_linenum);
+                       if (*startbuf == '\0')
+error(_("can't determine time zone abbreviation to use just after until time"));
+                       else    addtt(starttime,
+                                       addtype(startoff, startbuf,
+                                               startoff != zp->z_gmtoff,
+                                               startttisstd,
+                                               startttisgmt));
+               }
+               /*
+               ** Now we may get to set starttime for the next zone line.
+               */
+               if (useuntil) {
+                       startttisstd = zp->z_untilrule.r_todisstd;
+                       startttisgmt = zp->z_untilrule.r_todisgmt;
+                       starttime = zp->z_untiltime;
+                       if (!startttisstd)
+                               starttime = tadd(starttime, -stdoff);
+                       if (!startttisgmt)
+                               starttime = tadd(starttime, -gmtoff);
+               }
+       }
+       writezone(zpfirst->z_name);
+}
+
+static void
+addtt(starttime, type)
+const time_t   starttime;
+const int      type;
+{
+       if (timecnt >= TZ_MAX_TIMES) {
+               error(_("too many transitions?!"));
+               (void) exit(EXIT_FAILURE);
+       }
+       attypes[timecnt].at = starttime;
+       attypes[timecnt].type = type;
+       ++timecnt;
+}
+
+static int
+addtype(gmtoff, abbr, isdst, ttisstd, ttisgmt)
+const long             gmtoff;
+const char * const     abbr;
+const int              isdst;
+const int              ttisstd;
+const int              ttisgmt;
+{
+       register int    i, j;
+
+       if (isdst != TRUE && isdst != FALSE) {
+               error(_("internal error - addtype called with bad isdst"));
+               (void) exit(EXIT_FAILURE);
+       }
+       if (ttisstd != TRUE && ttisstd != FALSE) {
+               error(_("internal error - addtype called with bad ttisstd"));
+               (void) exit(EXIT_FAILURE);
+       }
+       if (ttisgmt != TRUE && ttisgmt != FALSE) {
+               error(_("internal error - addtype called with bad ttisgmt"));
+               (void) exit(EXIT_FAILURE);
+       }
+       /*
+       ** See if there's already an entry for this zone type.
+       ** If so, just return its index.
+       */
+       for (i = 0; i < typecnt; ++i) {
+               if (gmtoff == gmtoffs[i] && isdst == isdsts[i] &&
+                       strcmp(abbr, &chars[abbrinds[i]]) == 0 &&
+                       ttisstd == ttisstds[i] &&
+                       ttisgmt == ttisgmts[i])
+                               return i;
+       }
+       /*
+       ** There isn't one; add a new one, unless there are already too
+       ** many.
+       */
+       if (typecnt >= TZ_MAX_TYPES) {
+               error(_("too many local time types"));
+               (void) exit(EXIT_FAILURE);
+       }
+       gmtoffs[i] = gmtoff;
+       isdsts[i] = isdst;
+       ttisstds[i] = ttisstd;
+       ttisgmts[i] = ttisgmt;
+
+       for (j = 0; j < charcnt; ++j)
+               if (strcmp(&chars[j], abbr) == 0)
+                       break;
+       if (j == charcnt)
+               newabbr(abbr);
+       abbrinds[i] = j;
+       ++typecnt;
+       return i;
+}
+
+static void
+leapadd(t, positive, rolling, count)
+const time_t   t;
+const int      positive;
+const int      rolling;
+int            count;
+{
+       register int    i, j;
+
+       if (leapcnt + (positive ? count : 1) > TZ_MAX_LEAPS) {
+               error(_("too many leap seconds"));
+               (void) exit(EXIT_FAILURE);
+       }
+       for (i = 0; i < leapcnt; ++i)
+               if (t <= trans[i]) {
+                       if (t == trans[i]) {
+                               error(_("repeated leap second moment"));
+                               (void) exit(EXIT_FAILURE);
+                       }
+                       break;
+               }
+       do {
+               for (j = leapcnt; j > i; --j) {
+                       trans[j] = trans[j - 1];
+                       corr[j] = corr[j - 1];
+                       roll[j] = roll[j - 1];
+               }
+               trans[i] = t;
+               corr[i] = positive ? 1L : eitol(-count);
+               roll[i] = rolling;
+               ++leapcnt;
+       } while (positive && --count != 0);
+}
+
+static void
+adjleap P((void))
+{
+       register int    i;
+       register long   last = 0;
+
+       /*
+       ** propagate leap seconds forward
+       */
+       for (i = 0; i < leapcnt; ++i) {
+               trans[i] = tadd(trans[i], last);
+               last = corr[i] += last;
+       }
+}
+
+static int
+yearistype(year, type)
+const int              year;
+const char * const     type;
+{
+       static char *   buf;
+       int             result;
+
+       if (type == NULL || *type == '\0')
+               return TRUE;
+       buf = erealloc(buf, (int) (132 + strlen(yitcommand) + strlen(type)));
+       (void) sprintf(buf, "%s %d %s", yitcommand, year, type);
+       result = system(buf);
+       if (result == 0)
+               return TRUE;
+       if (result == (1 << 8))
+               return FALSE;
+       error(_("Wild result from command execution"));
+       (void) fprintf(stderr, _("%s: command was '%s', result was %d\n"),
+               progname, buf, result);
+       for ( ; ; )
+               (void) exit(EXIT_FAILURE);
+}
+
+static int
+lowerit(a)
+int    a;
+{
+       a = (unsigned char) a;
+       return (isascii(a) && isupper(a)) ? tolower(a) : a;
+}
+
+static int
+ciequal(ap, bp)                /* case-insensitive equality */
+register const char *  ap;
+register const char *  bp;
+{
+       while (lowerit(*ap) == lowerit(*bp++))
+               if (*ap++ == '\0')
+                       return TRUE;
+       return FALSE;
+}
+
+static int
+itsabbr(abbr, word)
+register const char *  abbr;
+register const char *  word;
+{
+       if (lowerit(*abbr) != lowerit(*word))
+               return FALSE;
+       ++word;
+       while (*++abbr != '\0')
+               do {
+                       if (*word == '\0')
+                               return FALSE;
+               } while (lowerit(*word++) != lowerit(*abbr));
+       return TRUE;
+}
+
+static const struct lookup *
+byword(word, table)
+register const char * const            word;
+register const struct lookup * const   table;
+{
+       register const struct lookup *  foundlp;
+       register const struct lookup *  lp;
+
+       if (word == NULL || table == NULL)
+               return NULL;
+       /*
+       ** Look for exact match.
+       */
+       for (lp = table; lp->l_word != NULL; ++lp)
+               if (ciequal(word, lp->l_word))
+                       return lp;
+       /*
+       ** Look for inexact match.
+       */
+       foundlp = NULL;
+       for (lp = table; lp->l_word != NULL; ++lp)
+               if (itsabbr(word, lp->l_word))
+                       if (foundlp == NULL)
+                               foundlp = lp;
+                       else    return NULL;    /* multiple inexact matches */
+       return foundlp;
+}
+
+static char **
+getfields(cp)
+register char *        cp;
+{
+       register char *         dp;
+       register char **        array;
+       register int            nsubs;
+
+       if (cp == NULL)
+               return NULL;
+       array = (char **) (void *)
+               emalloc((int) ((strlen(cp) + 1) * sizeof *array));
+       nsubs = 0;
+       for ( ; ; ) {
+               while (isascii(*cp) && isspace((unsigned char) *cp))
+                       ++cp;
+               if (*cp == '\0' || *cp == '#')
+                       break;
+               array[nsubs++] = dp = cp;
+               do {
+                       if ((*dp = *cp++) != '"')
+                               ++dp;
+                       else while ((*dp = *cp++) != '"')
+                               if (*dp != '\0')
+                                       ++dp;
+                               else    error(_("Odd number of quotation marks"));
+               } while (*cp != '\0' && *cp != '#' &&
+                       (!isascii(*cp) || !isspace((unsigned char) *cp)));
+               if (isascii(*cp) && isspace((unsigned char) *cp))
+                       ++cp;
+               *dp = '\0';
+       }
+       array[nsubs] = NULL;
+       return array;
+}
+
+static long
+oadd(t1, t2)
+const long     t1;
+const long     t2;
+{
+       register long   t;
+
+       t = t1 + t2;
+       if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
+               error(_("time overflow"));
+               (void) exit(EXIT_FAILURE);
+       }
+       return t;
+}
+
+static time_t
+tadd(t1, t2)
+const time_t   t1;
+const long     t2;
+{
+       register time_t t;
+
+       if (t1 == max_time && t2 > 0)
+               return max_time;
+       if (t1 == min_time && t2 < 0)
+               return min_time;
+       t = t1 + t2;
+       if ((t2 > 0 && t <= t1) || (t2 < 0 && t >= t1)) {
+               error(_("time overflow"));
+               (void) exit(EXIT_FAILURE);
+       }
+       return t;
+}
+
+/*
+** Given a rule, and a year, compute the date - in seconds since January 1,
+** 1970, 00:00 LOCAL time - in that year that the rule refers to.
+*/
+
+static time_t
+rpytime(rp, wantedy)
+register const struct rule * const     rp;
+register const int                     wantedy;
+{
+       register int    y, m, i;
+       register long   dayoff;                 /* with a nod to Margaret O. */
+       register time_t t;
+
+       if (wantedy == INT_MIN)
+               return min_time;
+       if (wantedy == INT_MAX)
+               return max_time;
+       dayoff = 0;
+       m = TM_JANUARY;
+       y = EPOCH_YEAR;
+       while (wantedy != y) {
+               if (wantedy > y) {
+                       i = len_years[isleap(y)];
+                       ++y;
+               } else {
+                       --y;
+                       i = -len_years[isleap(y)];
+               }
+               dayoff = oadd(dayoff, eitol(i));
+       }
+       while (m != rp->r_month) {
+               i = len_months[isleap(y)][m];
+               dayoff = oadd(dayoff, eitol(i));
+               ++m;
+       }
+       i = rp->r_dayofmonth;
+       if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
+               if (rp->r_dycode == DC_DOWLEQ)
+                       --i;
+               else {
+                       error(_("use of 2/29 in non leap-year"));
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       --i;
+       dayoff = oadd(dayoff, eitol(i));
+       if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
+               register long   wday;
+
+#define LDAYSPERWEEK   ((long) DAYSPERWEEK)
+               wday = eitol(EPOCH_WDAY);
+               /*
+               ** Don't trust mod of negative numbers.
+               */
+               if (dayoff >= 0)
+                       wday = (wday + dayoff) % LDAYSPERWEEK;
+               else {
+                       wday -= ((-dayoff) % LDAYSPERWEEK);
+                       if (wday < 0)
+                               wday += LDAYSPERWEEK;
+               }
+               while (wday != eitol(rp->r_wday))
+                       if (rp->r_dycode == DC_DOWGEQ) {
+                               dayoff = oadd(dayoff, (long) 1);
+                               if (++wday >= LDAYSPERWEEK)
+                                       wday = 0;
+                               ++i;
+                       } else {
+                               dayoff = oadd(dayoff, (long) -1);
+                               if (--wday < 0)
+                                       wday = LDAYSPERWEEK - 1;
+                               --i;
+                       }
+               if (i < 0 || i >= len_months[isleap(y)][m]) {
+                       error(_("no day in month matches rule"));
+                       (void) exit(EXIT_FAILURE);
+               }
+       }
+       if (dayoff < 0 && !TYPE_SIGNED(time_t))
+               return min_time;
+       t = (time_t) dayoff * SECSPERDAY;
+       /*
+       ** Cheap overflow check.
+       */
+       if (t / SECSPERDAY != dayoff)
+               return (dayoff > 0) ? max_time : min_time;
+       return tadd(t, rp->r_tod);
+}
+
+static void
+newabbr(string)
+const char * const     string;
+{
+       register int    i;
+
+       i = strlen(string) + 1;
+       if (charcnt + i > TZ_MAX_CHARS) {
+               error(_("too many, or too long, time zone abbreviations"));
+               (void) exit(EXIT_FAILURE);
+       }
+       (void) strcpy(&chars[charcnt], string);
+       charcnt += eitol(i);
+}
+
+static int
+mkdirs(argname)
+char * const   argname;
+{
+       register char * name;
+       register char * cp;
+
+       if (argname == NULL || *argname == '\0')
+               return 0;
+       cp = name = ecpyalloc(argname);
+       while ((cp = strchr(cp + 1, '/')) != 0) {
+               *cp = '\0';
+#ifndef unix
+               /*
+               ** DOS drive specifier?
+               */
+               if (isalpha((unsigned char) name[0]) &&
+                       name[1] == ':' && name[2] == '\0') {
+                               *cp = '/';
+                               continue;
+               }
+#endif /* !defined unix */
+               if (!itsdir(name)) {
+                       /*
+                       ** It doesn't seem to exist, so we try to create it.
+                       */
+                       if (mkdir(name, 0755) != 0) {
+                               const char *e = strerror(errno);
+
+                               (void) fprintf(stderr,
+                                   _("%s: Can't create directory %s: %s\n"),
+                                   progname, name, e);
+                               ifree(name);
+                               return -1;
+                       }
+               }
+               *cp = '/';
+       }
+       ifree(name);
+       return 0;
+}
+
+static long
+eitol(i)
+const int      i;
+{
+       long    l;
+
+       l = i;
+       if ((i < 0 && l >= 0) || (i == 0 && l != 0) || (i > 0 && l <= 0)) {
+               (void) fprintf(stderr,
+                       _("%s: %d did not sign extend correctly\n"),
+                       progname, i);
+               (void) exit(EXIT_FAILURE);
+       }
+       return l;
+}
+
+/*
+** UNIX was a registered trademark of UNIX System Laboratories in 1993.
+*/
diff --git a/zprint.tproj/Makefile b/zprint.tproj/Makefile
new file mode 100644 (file)
index 0000000..b857921
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# 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 = zprint
+
+PROJECTVERSION = 2.8
+PROJECT_TYPE = Tool
+
+CFILES = zprint.c
+
+OTHERSRCS = Makefile.preamble Makefile Makefile.postamble
+
+
+MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles
+CODE_GEN_STYLE = DYNAMIC
+MAKEFILE = tool.make
+NEXTSTEP_INSTALLDIR = /usr/bin
+WINDOWS_INSTALLDIR = /Library/Executables
+PDO_UNIX_INSTALLDIR = /usr/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/zprint.tproj/Makefile.postamble b/zprint.tproj/Makefile.postamble
new file mode 100644 (file)
index 0000000..411cde6
--- /dev/null
@@ -0,0 +1,100 @@
+###############################################################################
+#  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.
+#
diff --git a/zprint.tproj/Makefile.preamble b/zprint.tproj/Makefile.preamble
new file mode 100644 (file)
index 0000000..c1624b4
--- /dev/null
@@ -0,0 +1,137 @@
+###############################################################################
+#  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/zprint.tproj/PB.project b/zprint.tproj/PB.project
new file mode 100644 (file)
index 0000000..e474b78
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    DYNAMIC_CODE_GEN = YES; 
+    FILESTABLE = {
+        FRAMEWORKS = (); 
+        OTHER_LINKED = (zprint.c); 
+        OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); 
+    }; 
+    LANGUAGE = English; 
+    MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; 
+    NEXTSTEP_BUILDTOOL = /bin/gnumake; 
+    NEXTSTEP_INSTALLDIR = /usr/bin; 
+    NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; 
+    NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; 
+    PDO_UNIX_BUILDTOOL = /bin/gnumake; 
+    PDO_UNIX_INSTALLDIR = /usr/bin; 
+    PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; 
+    PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; 
+    PROJECTNAME = zprint; 
+    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/zprint.tproj/zprint.c b/zprint.tproj/zprint.c
new file mode 100644 (file)
index 0000000..1d030ae
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+ * @OSF_COPYRIGHT@
+ */
+/* 
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ * 
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ * 
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 
+ * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ * 
+ * Carnegie Mellon requests users of this software to return to
+ * 
+ *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
+ *  School of Computer Science
+ *  Carnegie Mellon University
+ *  Pittsburgh PA 15213-3890
+ * 
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+/*
+ *     zprint.c
+ *
+ *     utility for printing out zone structures
+ *
+ *     With no arguments, prints information on all zone structures.
+ *     With an argument, prints information only on those zones for
+ *     which the given name is a substring of the zone's name.
+ *     With a "-w" flag, calculates how much much space is allocated
+ *     to zones but not currently in use.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <mach/mach.h>
+#include <mach_debug/mach_debug.h>
+#include <mach/mach_error.h>
+
+#define streql(a, b)           (strcmp((a), (b)) == 0)
+#define strneql(a, b, n)       (strncmp((a), (b), (n)) == 0)
+
+static void printzone();
+static void colprintzone();
+static void colprintzoneheader();
+static void printk();
+static int strnlen();
+static boolean_t substr();
+
+static char *program;
+
+static boolean_t ShowWasted = FALSE;
+static boolean_t SortZones = FALSE;
+static boolean_t ColFormat = TRUE;
+static boolean_t PrintHeader = TRUE;
+
+static unsigned int totalsize = 0;
+static unsigned int totalused = 0;
+
+static void
+usage()
+{
+       fprintf(stderr, "usage: %s [-w] [-s] [-c] [-h] [name]\n", program);
+       exit(1);
+}
+
+main(argc, argv)
+       int     argc;
+       char    *argv[];
+{
+       zone_name_t name_buf[1024];
+       zone_name_t *name = name_buf;
+       unsigned int nameCnt = sizeof name_buf/sizeof name_buf[0];
+       zone_info_t info_buf[1024];
+       zone_info_t *info = info_buf;
+       unsigned int infoCnt = sizeof info_buf/sizeof info_buf[0];
+
+       char            *zname = NULL;
+       int             znamelen;
+
+       kern_return_t   kr;
+       int             i, j;
+
+       program = strrchr(argv[0], '/');
+       if (program == NULL)
+               program = argv[0];
+       else
+               program++;
+
+       for (i = 1; i < argc; i++) {
+               if (streql(argv[i], "-w"))
+                       ShowWasted = TRUE;
+               else if (streql(argv[i], "-W"))
+                       ShowWasted = FALSE;
+               else if (streql(argv[i], "-s"))
+                       SortZones = TRUE;
+               else if (streql(argv[i], "-S"))
+                       SortZones = FALSE;
+               else if (streql(argv[i], "-c"))
+                       ColFormat = TRUE;
+               else if (streql(argv[i], "-C"))
+                       ColFormat = FALSE;
+               else if (streql(argv[i], "-H"))
+                       PrintHeader = FALSE;
+               else if (streql(argv[i], "--")) {
+                       i++;
+                       break;
+               } else if (argv[i][0] == '-')
+                       usage();
+               else
+                       break;
+       }
+
+       switch (argc - i) {
+           case 0:
+               zname = "";
+               znamelen = 0;
+               break;
+
+           case 1:
+               zname = argv[i];
+               znamelen = strlen(zname);
+               break;
+
+           default:
+               usage();
+       }
+
+       kr = host_zone_info(mach_host_self(),
+                           &name, &nameCnt, &info, &infoCnt);
+       if (kr != KERN_SUCCESS) {
+               fprintf(stderr, "%s: host_zone_info: %s\n",
+                    program, mach_error_string(kr));
+               exit(1);
+       }
+       else if (nameCnt != infoCnt) {
+               fprintf(stderr, "%s: host_zone_info: counts not equal?\n",
+                       program);
+               exit(1);
+       }
+
+       if (SortZones) {
+               for (i = 0; i < nameCnt-1; i++)
+                       for (j = i+1; j < nameCnt; j++) {
+                               int wastei, wastej;
+
+                               wastei = (info[i].zi_cur_size -
+                                         (info[i].zi_elem_size *
+                                          info[i].zi_count));
+                               wastej = (info[j].zi_cur_size -
+                                         (info[j].zi_elem_size *
+                                          info[j].zi_count));
+
+                               if (wastej > wastei) {
+                                       zone_info_t tinfo;
+                                       zone_name_t tname;
+
+                                       tinfo = info[i];
+                                       info[i] = info[j];
+                                       info[j] = tinfo;
+
+                                       tname = name[i];
+                                       name[i] = name[j];
+                                       name[j] = tname;
+                               }
+                       }
+       }
+
+       if (ColFormat) {
+               colprintzoneheader();
+       }
+       for (i = 0; i < nameCnt; i++)
+               if (substr(zname, znamelen, name[i].zn_name,
+                          strnlen(name[i].zn_name, sizeof name[i].zn_name)))
+                       if (ColFormat)
+                               colprintzone(&name[i], &info[i]);
+                       else
+                               printzone(&name[i], &info[i]);
+
+       if ((name != name_buf) && (nameCnt != 0)) {
+               kr = vm_deallocate(mach_task_self(), (vm_address_t) name,
+                                  (vm_size_t) (nameCnt * sizeof *name));
+               if (kr != KERN_SUCCESS) {
+                       fprintf(stderr, "%s: vm_deallocate: %s\n",
+                            program, mach_error_string(kr));
+                       exit(1);
+               }
+       }
+
+       if ((info != info_buf) && (infoCnt != 0)) {
+               kr = vm_deallocate(mach_task_self(), (vm_address_t) info,
+                                  (vm_size_t) (infoCnt * sizeof *info));
+               if (kr != KERN_SUCCESS) {
+                       fprintf(stderr, "%s: vm_deallocate: %s\n",
+                            program, mach_error_string(kr));
+                       exit(1);
+               }
+       }
+
+       if (ShowWasted && PrintHeader) {
+               printf("TOTAL SIZE   = %u\n", totalsize);
+               printf("TOTAL USED   = %u\n", totalused);
+               printf("TOTAL WASTED = %d\n", totalsize - totalused);
+       }
+
+       exit(0);
+}
+
+static int
+strnlen(s, n)
+       char *s;
+       int n;
+{
+       int len = 0;
+
+       while ((len < n) && (*s++ != '\0'))
+               len++;
+
+       return len;
+}
+
+static boolean_t
+substr(a, alen, b, blen)
+       char *a;
+       int alen;
+       char *b;
+       int blen;
+{
+       int i;
+
+       for (i = 0; i <= blen - alen; i++)
+               if (strneql(a, b+i, alen))
+                       return TRUE;
+
+       return FALSE;
+}
+
+static void
+printzone(name, info)
+       zone_name_t *name;
+       zone_info_t *info;
+{
+       unsigned int used, size;
+
+       printf("%.*s zone:\n", sizeof name->zn_name, name->zn_name);
+       printf("\tcur_size:    %dK bytes (%d elements)\n",
+              info->zi_cur_size/1024,
+              info->zi_cur_size/info->zi_elem_size);
+       printf("\tmax_size:    %dK bytes (%d elements)\n",
+              info->zi_max_size/1024,
+              info->zi_max_size/info->zi_elem_size);
+       printf("\telem_size:   %d bytes\n",
+              info->zi_elem_size);
+       printf("\t# of elems:  %d\n",
+              info->zi_count);
+       printf("\talloc_size:  %dK bytes (%d elements)\n",
+              info->zi_alloc_size/1024,
+              info->zi_alloc_size/info->zi_elem_size);
+       if (info->zi_pageable)
+               printf("\tPAGEABLE\n");
+       if (info->zi_collectable)
+               printf("\tCOLLECTABLE\n");
+
+       if (ShowWasted) {
+               totalused += used = info->zi_elem_size * info->zi_count;
+               totalsize += size = info->zi_cur_size;
+               printf("\t\t\t\t\tWASTED: %d\n", size - used);
+       }
+}
+
+static void
+printk(fmt, i)
+       char *fmt;
+       int i;
+{
+       printf(fmt, i / 1024);
+       putchar('K');
+}
+
+static void
+colprintzone(zone_name, info)
+       zone_name_t *zone_name;
+       zone_info_t *info;
+{
+       char *name = zone_name->zn_name;
+       int j, namewidth, retval;
+       unsigned int used, size;
+
+       namewidth = 25;
+       if (ShowWasted) {
+               namewidth -= 7;
+       }
+       for (j = 0; j < namewidth - 1 && name[j]; j++) {
+               if (name[j] == ' ') {
+                       putchar('.');
+               } else {
+                       putchar(name[j]);
+               }
+       }
+       if (j == namewidth - 1) {
+               if (name[j]) {
+                       putchar('$');
+               } else {
+                       putchar(' ');
+               }
+       } else {
+               for (; j < namewidth; j++) {
+                       putchar(' ');
+               }
+       }
+       printf("%5d", info->zi_elem_size);
+       printk("%6d", info->zi_cur_size);
+       if (info->zi_max_size >= 99999 * 1024) {
+               printf("   ----");
+       } else {
+               printk("%6d", info->zi_max_size);
+       }
+       printf("%7d", info->zi_cur_size / info->zi_elem_size);
+       if (info->zi_max_size >= 99999 * 1024) {
+               printf("   ----");
+       } else {
+               printf("%7d", info->zi_max_size / info->zi_elem_size);
+       }
+       printf("%6d", info->zi_count);
+       printk("%5d", info->zi_alloc_size);
+       printf("%6d", info->zi_alloc_size / info->zi_elem_size);
+
+       totalused += used = info->zi_elem_size * info->zi_count;
+       totalsize += size = info->zi_cur_size;
+       if (ShowWasted) {
+               printf("%7d", size - used);
+       }
+
+       printf("%c%c\n",
+              (info->zi_pageable ? 'P' : ' '),
+              (info->zi_collectable ? 'C' : ' '));
+}
+
+static void
+colprintzoneheader()
+{
+       if (! PrintHeader) {
+               return;
+       }
+       if (ShowWasted) {
+               printf("                   elem    cur    max    cur    max%s",
+                      "   cur alloc alloc\n");
+               printf("zone name          size   size   size  #elts  #elts%s",
+                      " inuse  size count wasted\n");
+       } else {
+               printf("                          elem    cur    max    cur%s",
+                      "    max   cur alloc alloc\n");
+               printf("zone name                 size   size   size  #elts%s",
+                      "  #elts inuse  size count\n");
+       }
+       printf("-----------------------------------------------%s",
+              "--------------------------------\n");
+}