--- /dev/null
+ 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."
--- /dev/null
+#
+# 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
--- /dev/null
+CLEAN_ALL_SUBPROJECTS = YES
+SUBPROJECTS =
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+{\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\
+
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+after_install::
+ @-$(RM) -f $(DSTROOT)$(INSTALLDIR)/machine
+ ln $(DSTROOT)$(INSTALLDIR)/arch $(DSTROOT)$(INSTALLDIR)/machine
\ No newline at end of file
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#
+# 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
--- /dev/null
+# $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>
--- /dev/null
+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
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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.
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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));
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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));
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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();
--- /dev/null
+/*
+ * 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
--- /dev/null
+#
+# 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
--- /dev/null
+# $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>
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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.
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+#
+# 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
--- /dev/null
+
+INSTALL_AS_USER = root
+INSTALL_PERMISSIONS = 4555
+#CHFLAGS = /usr/bin/chflags
+#after_install::
+# $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+CLEAN_ALL_SUBPROJECTS = YES
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)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>
--- /dev/null
+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)
+
--- /dev/null
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_OFILES = pw_scan.o pw_util.o
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 *));
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 *));
--- /dev/null
+/*
+ * 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, },
+};
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)Makefile 8.1 (Berkeley) 6/5/93
+
+PROG= dmesg
+MAN8= dmesg.0
+BINGRP= kmem
+BINMODE=2555
+LDADD= -lkvm
+DPADD= ${LIBKVM}
+
+.include <bsd.prog.mk>
--- /dev/null
+INSTALL_AS_GROUP = kmem # (probably want to set both of these)
+INSTALL_PERMISSIONS = 2555 # If set, 'install' chmod's executable to this
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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)";
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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);
--- /dev/null
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
--- /dev/null
+$$ 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
--- /dev/null
+#
+# 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
--- /dev/null
+#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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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);
--- /dev/null
+#include <default_pager/default_pager_alerts.defs>
--- /dev/null
+/* 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)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>
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+#!/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 $*
--- /dev/null
+#!/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 $*
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+
+.\" 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
--- /dev/null
+/*
+ * 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;
+}
+
+
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
+
--- /dev/null
+###############################################################################
+# 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.
+
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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. */
--- /dev/null
+.\" 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 .
--- /dev/null
+.\" 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.
--- /dev/null
+/*
+ * 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;
--- /dev/null
+/*
+ * 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 }
+};
--- /dev/null
+/*
+ * 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++;
+ }
+}
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+#
+# 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
--- /dev/null
+# 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>
--- /dev/null
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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.
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)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>
--- /dev/null
+INSTALL_PERMISSIONS = 500 # If set, 'install' chmod's executable to this
+#CHFLAGS = /usr/bin/chflags
+#after_install::
+# $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
+
--- /dev/null
+# can be added to Compiler Flags to provide Secure login
+# -DSECURE LIBS = -lutil
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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"
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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" .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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
--- /dev/null
+#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);
+}
+
+
--- /dev/null
+
+#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_
+
--- /dev/null
+#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;
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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 );
+}
+
+
+
--- /dev/null
+
+#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;
+}
+
--- /dev/null
+
+#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_
+
--- /dev/null
+#
+# 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
--- /dev/null
+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)
+
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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
--- /dev/null
+
+#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.
+}
--- /dev/null
+#
+# 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
--- /dev/null
+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)
+
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\"
+.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
--- /dev/null
+
+#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.
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+.\"
+.\" 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
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#
+# 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
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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"
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
+
--- /dev/null
+###############################################################################
+# 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
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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
--- /dev/null
+/*
+ * 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(×tamp1);
+ adeadline = timestamp1;
+ ADD_ABSOLUTETIME(&adeadline, &adelay);
+ mk_wait_until(adeadline);
+ clock_get_uptime(×tamp2);
+
+ 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();
+ }
+}
--- /dev/null
+#
+# 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
--- /dev/null
+INSTALL_AS_USER = root
+INSTALL_PERMISSIONS = 4555
+#CHFLAGS = /usr/bin/chflags
+
+#after_install::
+# $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
--- /dev/null
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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"
--- /dev/null
+#
+# 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
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+BEFORE_BUILD += bootstrap.h
+OTHER_OFILES = bootstrapServer.o
+
--- /dev/null
+# 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.
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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,
+ ¬ify_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
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+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;
+
+
--- /dev/null
+/*
+ * 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;
+}
+
+
--- /dev/null
+/*
+ * 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))
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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);
+
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+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;
--- /dev/null
+services foobar;
--- /dev/null
+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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
+
+
+
+
--- /dev/null
+/*
+ * 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);
+}
+
+
+
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
+
--- /dev/null
+###############################################################################
+# 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.
+
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/*
+ * 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");
+}
--- /dev/null
+#
+# 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
--- /dev/null
+CLEAN_ALL_SUBPROJECTS = YES
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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);
+
+}
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)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>
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+#!/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
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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.
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\"
+.\" 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+##
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)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>
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+#!/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
--- /dev/null
+#
+# 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
--- /dev/null
+VPATH += :../chpass.tproj:../vipw.tproj
+
+INSTALL_AS_USER = root
+INSTALL_PERMISSIONS = 4555
+#CHFLAGS = /usr/bin/chflags
+
+#after_install::
+# $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME)
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+CLEAN_ALL_SUBPROJECTS = YES
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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));
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 *));
--- /dev/null
+.\" 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)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>
--- /dev/null
+#we already have a halt?
+#after_install::
+# $(LN) $(INSTALLED_PRODUCTS) $(DSTROOT)$(INSTALLDIR)/halt
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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
--- /dev/null
+.\" 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.
--- /dev/null
+.\" 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.
--- /dev/null
+.\" 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
--- /dev/null
+.\" 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 .
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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 */
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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
--- /dev/null
+/*
+ * 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(×tamp);
+
+ 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(×tamp);
+
+ 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);
+}
+
--- /dev/null
+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
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)Makefile 8.1 (Berkeley) 6/5/93
+
+PROG= shutdown
+MAN8= shutdown.0
+BINOWN= root
+BINGRP= operator
+BINMODE=4550
+
+.include <bsd.prog.mk>
--- /dev/null
+INSTALL_AS_GROUP = operator # (probably want to set both of these)
+INSTALL_PERMISSIONS = 4550 # If set, 'install' chmod's executable to this
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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"
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+# @(#)Makefile 8.1 (Berkeley) 5/31/93
+
+PROG= sync
+MAN8= sync.0
+
+.include <bsd.prog.mk>
--- /dev/null
+OTHER_GENERATED_OFILES = $(VERS_OFILE)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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.
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
--- /dev/null
+###############################################################################
+# 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)
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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));
--- /dev/null
+.\" 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 .
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
+#
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+$$
+/* $FILENAME$ created by $USERNAME$ on $DATE$ */
+
+#import <Foundation/Foundation.h>
+
+@interface $FILENAMESANSEXTENSION$ : NSObject
+{
+
+}
+
+@end
--- /dev/null
+$$ 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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+.\" $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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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
--- /dev/null
+###############################################################################
+# 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.
+
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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.
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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.
--- /dev/null
+# $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"
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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 ##
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+# $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
--- /dev/null
+#! /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
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+.\" $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
--- /dev/null
+/*
+ * 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.
+*/
--- /dev/null
+#
+# 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
--- /dev/null
+###############################################################################
+# 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.
+#
--- /dev/null
+###############################################################################
+# 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)
--- /dev/null
+{
+ 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";
+}
--- /dev/null
+/*
+ * @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");
+}