-[Please note that the latest fdisk is "v2.0a (>2GB)" and the latest cfdisk
-is "0.8a BETA (>2GB)". The cannonical versions of both are in this
-package, and both should work with disks > 2GB if you have Linux 1.1.46 or
-above.]
-
-util-linux-2.2.tar.gz (source distribution)
-util-linux-2.2.bin.tar.gz (binary distribution)
+util-linux-2.5.tar.gz (source distribution only)
WARNING: THIS COLLECTION DOES *NOT* SUPPORT SHADOW PASSWORDS.
WARNING: THIS COLLECTION DOES *NOT* SUPPORT SYSTEM V INITTAB.
- WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY!
-
WARNING: DO *NOT* INSTALL WITHOUT THINKING.
- WARNING: *READ* the util-linux-2.2.bin.Notes file *BEFORE* and *AFTER*
- installation: there are a few links you must make by hand.
-
This is a collection of many assorted utilities for Linux. Some are
system utilities that are not easily available anywhere elsewhere
- (e.g., mkfs.minix, mkswap); others are BSD ports of common utilities
- that are not yet contained in any FSF package (e.g., col); others are
- non-System-V alternatives to common utilities (e.g., simpleinit,
- agetty, login, passwd).
+ (e.g., mkfs.minix, mkswap, cfdisk, fdisk); others are BSD ports of
+ common utilities that are not yet contained in any FSF package (e.g.,
+ col); others are non-System-V alternatives to common utilities (e.g.,
+ simpleinit, agetty, login, passwd).
The arrangement, as nearly as I can determine, conforms to the Linux
- Filesystem Structure, Interim Release 1.1, October 9, 1994, with *NO*
+ Filesystem Structure, Interim Release 1.2, March 28, 1995, with *NO*
exceptions. A copy of the standards document can be found at
tsx-11.mit.edu:/pub/linux/docs/linux-standards/fsstnd/*.
Many people provided patches and suggestions. I deeply appreciate
this.
-
-HIGHLIGHTS for version 2.2:
-1) This is primarily a quick bug-fix release for version 2.1
-2) mkfs wrapper added back in, since e2fsprogs only supplies an fsck wrapper
-3) selection removed, since someone appears to be maintaining it now. See
- sunsite.unc.edu:/pub/linux/kernel/patches/console for recent sources.
- For the time being, I'm keeping a copy in the historic subdirectory of
- util-linux. A "make install" should work find from within that
- directory.
-4) Note that other floppy utilities are available from:
- ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.1.src.tar.gz
- sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.1.src.tar.gz
- tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.1.src.tar.gz
-
-
-HIGHLIGHTS for version 2.1:
-
-1) Directory structure rearrange, with configuration support for those who
- use shadow passwords and System V init (no support is provided for these
- things, but your utilities won't get overwritten if you do a "make
- install" after you properly edit MCONFIG).
-2) fdisk and cfdisk should work as expected with 2GB+ disk drives
-3) As usual, lots of stuff was updated and added, including mount, vipw,
- readprofile
-4) Some stuff was also deleted, and can now be found elsewhere:
- fsck wrapper: tsx-11.mit.edu:/pub/linux/ALPHA/ext2fs/e2fsprogs*
- pwd, su: prep.ai.mit.edu:/pub/gnu/sh-utils*
- ed: prep.ai.mit.edu:/pub/gnu/ed*
- od: prep.ai.mit.edu:/pub/gnu/textutils*
- uudecode/uuencode: prep.ai.mit.edu:/pub/gnu/sharutils*
- bdflush/update: ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/v1.1/bdflush*
-
+ This product includes software developed by the University of
+ California, Berkeley and its contributors.
+
+ IN THE FUTURE, SEND UPDATES AND PATCHES TO: util-linux@math.uio.no
+
+
+
+HIGHLIGHTS for version 2.5:
+
+0) Nicolai Langfeldt is taking over maintenance of util-linux, with the
+ help of a few others (Michael K. Johnson, Andries Brouwer, and Rik
+ Faith).
+
+ PLEASE SEND PATCHES AND UPDATES TO: util-linux@math.uio.no
+
+1) The following packages have been removed. Please use the up-to-date,
+ canonical versions of these packages from the listed places:
+
+ timezone support (/usr/lib/zoneinfo, libz.a, zic, zdump):
+ elsie.nci.nih.gov:/pub/tzcode95d.tar.gz
+ elsie.nci.nih.gov:/pub/tzdata95h.tar.gz
+ MAKEDEV-C:
+ sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-C-1.5.tar.gz
+ MAKEDEV:
+ sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-2.2.tar.gz
+ md5sum:
+ prep.ai.mit.edu:/pub/gnu/textutils-1.3.tar.gz
+ [The GNU version is now compatible with the Plumb/Lankester
+ version.]
+ ksymoops:
+ Now bundled with the kernel in linux/scripts.
+
+2) update_state has been removed
+3) fdisk now supports NetBSD disklabels courtesy of Bernhard Fastenrath
+ <fasten@athene.informatik.uni-bonn.de> (and > 8GB disks, courtesy of
+ Andries Brouwer)
+4) mount improved -- many patches from Andries Brouwer for greatly improved
+ error reporting
+5) ddate, chkdupexe, and other programs have been improved and bug fixed
+6) util-linux is now a source-only distribution
+7) mcookie generates better random numbers and will use /dev/random or
+ /dev/audio if available
+8) chfn, chsh, passwd, and vipw have been updated with security patches
+ from Zefram <A.Main@dcs.warwick.ac.uk>. Now, they all use the same
+ locking, and several security holes have been patched. Further, chsh
+ and chfn can be configured at compile time to require a password before
+ updates and chsh can be configured to only use shells from /etc/shells.
Begin3
Title: util-linux: Miscellaneous utilities for Linux
-Version: 2.2
-Entered-date: Sun Feb 26 16:05:47 1995
-Description: reboot shutdown simpleinit sln swapoff swapon cal chfn chsh
- clear col colcrt colrm column dnsdomainname domainname
- dsplit fdformat getopt hexdump hostid hostname ipcrm ipcs
- last logger look lpcntl mcookie md5sum mesg namei newgrp
- passwd ramsize rdev readprofile renice reset rev rootflags
- script selection setfdprm setsid setterm strings swapdev
- tsort tunelp ul vidmode wall whereis write chroot
- ctrlaltdel frag syslogd update_state vipw zdump zic
+Version: 2.5
+Entered-date: Thu Oct 12 15:20:00 1995
+Description: agetty arch cal cat cfdisk chfn chkdupexe chroot chsh clear
+ clock col colcrt colrm column ctrlaltdel cytune ddate dmesg
+ dnsdomainname domainname dsplit fastboot fasthalt fdformat
+ fdisk fsck.minix getopt halt hexdump hostid hostname ipcrm
+ ipcs kbdrate kill last logger login look mcookie mesg mkfs
+ mkfs.minix mkswap more mount namei passwd ramsize rdev
+ readprofile reboot renice reset rev rootflags script
+ setfdprm setserial setsid setterm shutdown simpleinit sln
+ strings swapdev swapoff swapon sync syslogd tsort tunelp ul
+ umount vidmode vipw wall whereis write
Keywords: essential utilities
Author: several
-Maintained-by: faith@cs.unc.edu (Rik Faith)
-Primary-site: ftp.cs.unc.edu /pub/users/faith/linux
- 592k util-linux-2.2.tar.gz
- 571k util-linux-2.2.bin.tar.gz
-Alternate-site: tsx-11.mit.edu /pub/linux/packages/utils
+Maintained-by: Nicolai Langfeldt <util-linux@math.uio.no>
+Primary-site: tsx-11.mit.edu /pub/linux/packages/utils
+ 487k util-linux-2.5.tar.gz
Alternate-site: sunsite.unc.edu /pub/Linux/system/Misc
-Platforms: Linux 1.1.9x, GNU tar
+Platforms: Linux 1.2.x/1.3.x
Copying-policy: GPL, BSD, others
End
# MCONFIG -- Configuration stuff for util-linux
# Created: Sat Feb 4 15:50:30 1995
-# Revised: Sun Feb 26 21:33:32 1995 by faith@cs.unc.edu
+# Revised: Thu Oct 12 10:11:33 1995 by r.faith@ieee.org
# Copyright 1995 Rickard E. Faith (faith@cs.unc.edu)
#
-# If HAVE_SHADOW is set to "yes", then login, chfn, chsh, newgrp, passwd, and
-# vipw will not be built or installed from the login-utils subdirectory.
+# If HAVE_SHADOW is set to "yes", then login, chfn, chsh, newgrp, passwd,
+# and vipw will not be built or installed from the login-utils
+# subdirectory.
HAVE_SHADOW=no
#HAVE_SHADOW=yes
-# If HAVE_SYSVINIT is set to "yes", then agetty, simpleinit, shutdown,
-# last, mesg, and wall will not be built or installed from the login-utils
-# subdirectory.
+# If you use chfn and chsh from this package, REQUIRE_PASSWORD will require
+# non-root users to enter the account password before updating /etc/passwd.
+REQUIRE_PASSWORD=yes
+#REQUIRE_PASSWORD=no
+
+# If you use chsh from this package, ONLY_LISTED_SHELLS will require that
+# the selected shell be listed in /etc/shells -- otherwise only a warning is
+# printed. This prevents someone from setting their shell to /bin/false.
+ONLY_LISTED_SHELLS=yes
+#ONLY_LISTED_SHELLS=no
+
+
+# If HAVE_PASSWD is set to "yes", then passwd will not be built or
+# installed from the login-utils subdirectory (but login, chfn, chsh,
+# newgrp, and vipw *will* be installed).
+HAVE_PASSWD=no
+#HAVE_PASSWD=yes
+
+# If HAVE_SYSVINIT is set to "yes", then simpleinit and shutdown will not
+# be built or installed from the login-utils subdirectory. (The shutdown
+# and halt that come with the SysVinit package should be used with the init
+# found in that package.)
HAVE_SYSVINIT=no
#HAVE_SYSVINIT=yes
+# If HAVE_SYSVINIT_UTILS is set to "yes", then last, mesg, and wall will
+# not be built or installed from the login-utils subdirectory. (The
+# shutdown and init from the SysVinit package do not depend on the last,
+# mesg, and wall from that package.)
+HAVE_SYSVINIT_UTILS=no
+#HAVE_SYSVINIT_UTILS=yes
+
+# If HAVE_ANOTHER_GETTY is set to "yes", then agetty will not be built or
+# installed from the login-utils subdirectory. Note that agetty can
+# co-exist with other gettys, so this option should never be used.
+HAVE_GETTY=no
+#HAVE_GETTY=yes
+
+# If USE_TTY_GROUP is set to "yes", then wall and write will be installed
+# setgid to the "tty" group, and mesg will only set the group write bit.
+# Note that this is only useful if login/xterm/etc. change the group of the
+# user's tty to "tty" [The login in util-linux does this correctly, and
+# xterm will do it correctly if X is compiled with USE_TTY_GROUP set
+# properly.]
+USE_TTY_GROUP=yes
+#USE_TTY_GROUP=no
+
# If HAVE_STRINGS is set to "yes", then strings won't be installed. This
# is the quick fix until the strings in GNU binutils is in wide use and has
-# international support.
+# internationalization support.
HAVE_STRINGS=no
#HAVE_STRINGS=yes
+# If HAVE_CLEAR is set to "yes", then clear won't be installed, since a
+# version of clear comes with the ncurses package.
+HAVE_CLEAR=no
+#HAVE_CLEAR=yes
+
+# If HAVE_SYSLOGD is set to "yes", then syslogd will not be built or
+# installed from the syslogd subdirectory.
+HAVE_SYSLOGD=no
+#HAVE_SYSLOGD=yes
+
+# If HAVE_ANOTHER_FDISK is set to "yes", then fdisk will not be built or
+# installed from the disk-utils subdirectory. This anticipates the
+# replacement of fdisk 2.x by fdisk 3.x, which will be distributed
+# separately.
+HAVE_FDISK=no
+#HAVE_FDISK=yes
+
CC= gcc
OPT= -pipe -O2 -m486 -fomit-frame-pointer
-WFLAGS= -Wall
LDFLAGS= -s -N
CFLAGS= $(OPT) -I. -I$(BSD) \
-DSBINDIR=\"$(SBINDIR)\" \
ETCDIR= $(DESTDIR)/etc
SBINDIR= $(DESTDIR)/sbin
USRSBINDIR= $(DESTDIR)/usr/sbin
+USRLIBDIR= $(DESTDIR)/usr/lib
USRBINDIR= $(DESTDIR)/usr/bin
USRGAMESDIR= $(DESTDIR)/usr/games
BINDIR= $(DESTDIR)/bin
VARPATH= $(DESTDIR)/var
-LOGDIR= $(DESTDIR)/var/adm
+LOGDIR= $(DESTDIR)/var/log
MANDIR= $(DESTDIR)/usr/man
MAN1DIR= $(DESTDIR)/usr/man/man1
MAN3DIR= $(DESTDIR)/usr/man/man3
# Directory for fsck
FSCKDIR= $(SBINDIR)
-# Directory for rdev, vidmode, etc.
-RDEVDIR= $(USRBINDIR)
-
# Directory for passwd
PASSWDDIR= $(USRBINDIR)
INSTALLSUID= $(INSTALL) -m $(SUIDMODE) -o root
BSD= ../bsd
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+%: %.cc
+ $(CXX) $(CFLAGS) $< -o $@
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Sun Feb 26 17:29:25 1995 by faith@cs.unc.edu
+# Revised: Fri Oct 6 21:37:30 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
+# May be distributed under the terms of the GNU GPL.
#
-VERSION=2.2
-include MCONFIG
+VERSION=2.5
+
+include ./MCONFIG
SUBDIRS= bsd \
disk-utils \
games \
login-utils \
- makedev-1.4.1 \
misc-utils \
mount \
sys-utils \
- syslogd \
- text-utils \
- time
+ text-utils
+ifeq "$(HAVE_SYSLOGD)" "no"
+SUBDIRS:=$(SUBDIRS) syslogd
+endif
.PHONEY: all install clean
all:
rm -rf /tmp/util-linux-$(VERSION); \
cvs export -fNd util-linux-$(VERSION) -r HEAD util-linux; \
cd util-linux-$(VERSION); \
- ln -s README util-linux-$(VERSION).bin.Notes; \
find -type d | xargs chmod 755; \
find -type f | xargs chmod 644; \
find -type d | xargs chown root:root; \
find -type f | xargs chown root:root; \
cd ..; \
- tar zcvvf util-linux-$(VERSION).tar.gz util-linux-$(VERSION); \
- cp -p util-linux-$(VERSION)/README util-linux-$(VERSION).bin.Notes; \
+ tar cvvf util-linux-$(VERSION).tar util-linux-$(VERSION); \
+ gzip -9 util-linux-$(VERSION).tar; \
+ cp -p util-linux-$(VERSION)/LSM util-linux-$(VERSION).lsm; \
+ cp -p util-linux-$(VERSION)/ANNOUNCE util-linux-$(VERSION).Announce; \
echo Done.)
-util-linux: Miscellaneous utilities for Linux
-%n util-linux
-%v 2.2
-%c *
-%l *
-%b *
-%d *
-%f ftp.cs.unc.edu:/pub/users/faith/linux
-%t util-linux-2.2.tar.gz
-%w utils
-%%
-# These lines describe an automated build procedure, please ignore them.
-%setup
-make
-%doc ANNOUNCE LSM README
-%doc COPYING.GPL COPYING.UCB
-%doc ./time/README.time ./disk-utils/README.cfdisk
-%doc ./disk-utils/README.fdisk ./disk-utils/README.bootutils-0.1
-%doc ./sys-utils/README.setserial ./makedev-1.4.1/README.MAKEDEV-C
-%doc ./misc-utils/README.script ./misc-utils/README.hostname
-%doc ./misc-utils/README.namei ./misc-utils/README.cal
-%doc ./misc-utils/README1.namei ./text-utils/README.col
-%doc ./mount/README.mount
-%doc ./login-utils/README.getty ./login-utils/README.admutil
-%doc ./login-utils/README.poeigl
-cp -a $BUILDDIR/$NAME-$VERSION/example.files /usr/doc/$WHERE/$NAME-$VERSION
-* rm -rf /usr/lib/zoneinfo
-* make install
-%i set -x
-%i /usr/sbin/zic -l US/Eastern
-%i /usr/sbin/zic -p America/New_York
-%i set +x
-%i echo 'WARNING: Check time zone! (If necessary, change with zic).'
-%i echo 'WARNING: Check /etc/rc for initalization of /var/adm/utmp'
-%i echo 'WARNING: /etc/rc should run /sbin/update, *NOT* /sbin/bdflush'
-exit
-# Please ignore the previous lines. . .
-# The informative part of the notes file starts here:
+util-linux 2.5
WARNING: THE PROGRAMS IN THIS SUITE DO *NOT* SUPPORT SHADOW PASSWORD FILES!
WARNING: DO *NOT* INSTALL WITHOUT THINKING.
-WARNING: Read the util-linux-2.2.bin.Notes file *BEFORE* and *AFTER*
- installation: there are a few links you must make by hand.
-
WARNING: The agetty, simpleinit, login, passwd, and other programs in this
package are *NOT* System V compliant. These utilities are meant
to be used by people who build their own systems. If you are not
prevent you from logging into your system. Have a boot floppy
ready, especially if you don't know what you are doing.
-WARNING: The binary distribution was tarred using GNU TAR AND THE -S OPTION!
- This means that holes will be preserved, but that ONLY GNU TAR
- WILL WORK ON THE BINARY DISTRIBUTION (in fact, other, inferior,
- tar programs will fail silently). YOU HAVE BEEN WARNED!
-
-WARNING: localtime and posixtime default to US/Eastern -- change these now.
-
-
-
-To install from the binary distribution:
-
-1) Get binary distribution (see the .lsm file for locations)
-2) cd /
-3) gtar zpxvf util-linux-2.2.bin.tar.gz
- (or: pms -i util-linux-2.2.bin.tar.gz)
-4) *IF* you want to use agetty and simpleinit, then make softlinks from
- /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure
- that your /etc/inittab is set up right (this is *NOT* the System V
- compatible init!), or you will be hosed.
-5) Run zic -l and/or zic -p to set your timezone. The distribution is set
- up to use /usr/lib/zoneinfo/US/Eastern as the default. This was
- installed with "zic -l US/Eastern"
-6) Remove all the old binaries from previous locations.
-
To install from source:
1) Get source distribution (see the .lsm file for locations)
-2) Untar util-linux-2.2.tar.gz in /usr/src
-3) cd util-linux-2.2
-4) Edit MCONFIG:
-
- If you use the shadow password suite and do _not_ want to install
- programs like login and passwd that do not support shadow passwords,
- then set HAVE_SHADOW to yes
-
- If you use the System V init suite and do _not_ want to install programs
- like agetty, simpleinit, and shutdown, then set HAVE_SYSVINIT to yes
+2) Untar util-linux-2.5.tar.gz in /usr/src
+3) cd util-linux-2.5
+4) Edit MCONFIG
+5) make
- If you don't like the compile-time options or the directories, then
- change them. Note that you also can say something like "make OPT=-g
- LDFLAGS=" in order to make a complete debugging version without editing
- the MCONFIG at all.
+ Note that libc 4.5.26 headers need a small patch to be used with
+ recent kernels. See the file uio.h-diff for the patch, if necessary.
-5) make
6) make install
7) If you want to use simpleinit and agetty, then make softlinks from
/sbin/init to simpleinit and from /sbin/getty to agetty, but make sure
that your /etc/inittab is set up right (this is *NOT* the System V
compatible init!), or you will be hosed. If you are using the SysV
init and/or some other getty, they you can keep using those.
-8) Run zic -l and/or zic -p to set your timezone. The distribution is set
- up to use /usr/lib/zoneinfo/US/Eastern as the default. This was
- installed with "zic -l US/Eastern"
-9) Remove all the old binaries from previous locations.
-
-
+8) Remove all the old binaries from previous locations.
+9) See the HIGHLIGHTS below for links you need to make for the new FSSTND
+ compliance.
+
+
+HIGHLIGHTS for version 2.5:
+0) Nicolai Langfeldt is taking over maintenance of util-linux, with the
+ help of a few others (Michael K. Johnson, Andries Brouwer, and Rik
+ Faith).
+
+ PLEASE SEND PATCHES AND UPDATES TO: util-linux@math.uio.no
+
+1) The following packages have been removed. Please use the up-to-date,
+ canonical versions of these packages from the listed places:
+
+ timezone support (/usr/lib/zoneinfo, libz.a, zic, zdump):
+ elsie.nci.nih.gov:/pub/tzcode95d.tar.gz
+ elsie.nci.nih.gov:/pub/tzdata95h.tar.gz
+ MAKEDEV-C:
+ sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-C-1.5.tar.gz
+ MAKEDEV:
+ sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-2.2.tar.gz
+ md5sum:
+ prep.ai.mit.edu:/pub/gnu/textutils-1.3.tar.gz
+ [The GNU version is now compatible with the Plumb/Lankester
+ version.]
+ ksymoops:
+ Now bundled with the kernel in linux/scripts.
+
+2) update_state has been removed
+3) fdisk now supports NetBSD disklabels courtesy of Bernhard Fastenrath
+ <fasten@athene.informatik.uni-bonn.de> (and > 8GB disks, courtesy of
+ Andries Brouwer)
+4) mount improved -- many patches from Andries Brouwer for greatly improved
+ error reporting
+5) ddate, chkdupexe, and other programs have been improved and bug fixed
+6) util-linux is now a source-only distribution
+7) mcookie generates better random numbers and will use /dev/random or
+ /dev/audio if available
+8) chfn, chsh, passwd, and vipw have been updated with security patches
+ from Zefram <A.Main@dcs.warwick.ac.uk>. Now, they all use the same
+ locking, and several security holes have been patched. Further, chsh
+ and chfn can be configured at compile time to require a password before
+ updates and chsh can be configured to only use shells from /etc/shells.
+
+
+HIGHLIGHTS for version 2.4 (2.3 was never released):
+0) Michael K. Johnson <johnsonm@nigel.vnet.net> is the interim maintainer
+ while Rik Faith is working on PhD work.
+1) login now makes the login tty mode 600 and places it in group "tty"
+2) wall, and write will not write dangerous escape sequences
+3) wall and write can be run setgid "tty". If util-linux is compiled for
+ this option, "mesg y" will only set group write instead of group/other
+ write.
+4) fdisk and cfdisk have been patched with the latest llseek.c. Although I
+ had a lot of bug reports about fdisk from util-linux-2.2, I was unable
+ to reproduce any of the problems. Some of the problems appeared to be
+ releated to a failure to reboot the machine after changing the partition
+ table, and some may have been due to a specific kernel revision problem.
+ However, this doesn't seem to account for all of the bug reports -- if
+ this version gives you problem, please send as complete a bug report as
+ possible.
+5) chkdupexe from Nicolai Langfeldt (janl@ifi.uio.no)
+6) ctrlaltdel now installs into /sbin instead of /usr/sbin
+7) mkfs replacement from Ron Sommeling (sommel@sci.kun.nl)
+8) lpcntl removed. Use tunelp instead.
+9) ksymoops from Greg McGary <gkm@magilla.cichlid.com>
+10) mkfs.minix now clears the first 512 bytes of the file system so that
+ Minix disks won't be confused with MSDOS disks (Daniel Quinlan
+ (quinlan@yggdrasil.com))
+11) mkswap should now work on an Alpha running Linux
+12) frag removed. See
+ sunsite.unc.edu:/pub/Linux/system/Filesystems/defrag-0.6.tar.gz for the
+ latest version.
+13) mount patches from Andries.Brouwer@cwi.nl and Dan Quinlan
+ (quinlan@yggdrasil.com).
+14) MAKEDEV and MAKEDEV-C updated to the latest versions.
+15) Paths updated for FSSTND 1.2. This means that you may need to make
+ some links. The links you need to make we system dependent. The
+ ultimate goal is to rename /var/adm to /var/log and have a symbolic
+ link from /var/adm to /var/log during the transition period. If you
+ are running an ELF system, you probably won't have to do anything. The
+ bottom line is that the following files must exist or be pointers to
+ the old version (used internally by the a.out libraries):
+
+ New Old
+
+ /var/log/wtmp /var/adm/wtmp
+ /var/log/lastlog /var/adm/lastlog
+ /var/run/utmp /var/adm/utmp
HIGHLIGHTS for version 2.2:
1) This is primarily a quick bug-fix release for version 2.1
fdisk: A. V. Le Blanc (LeBlanc@mcc.ac.uk) fdisk 1.5 release, with
patched from Kevin Martin for DOS and OS/2 compatibility (1.5a);
Rik Faith (1.5b, 2.0).
- frag: Werner Almesberger (1.0), Steffen Zahn (1.1), Rob Hooft (1.2),
- Steffen Zahn (szahn%masterix@emndev.siemens.co.at) (1.3), Michael
- Bischoff <mbi@mo.math.nat.tu-bs.de> (1.4).
fsck.minix, mkfs.minix: Linus Torvalds, with modifications by: Rik
Faith (faith@cs.unc.edu), Scott Heavner
(sdh@po.cwru.edu), Dr. Wettstein
(greg%wind.uucp@plains.nodak.edu), Daniel
Quinlan (quinlan@yggdrasil.com).
+ mkfs: David Engel (david@ods.com) and Fred N. van Kempen
+ (waltje@uWalt.NL.Mugnet.ORG)
+ Version 1.9 from Ron Sommeling (sommel@sci.kun.nl)
mkswap: Linus Torvalds, with modifications by Mike Jagdis
(jaggy@purplet.demon.co.uk. )
+ Version for Alpha from
+ cage.cs.arizona.edu:/pub/davidm/linux/mkswap-axp-950503.tar.gz
setfdprm: Werner Almesberger (almesber@nessie.cs.id.ethz.ch)
Note that more floppy utilities are available from:
ftp.imag.fr:pub/Linux/ZLIBC/fdutils/fdutils-4.1.src.tar.gz
sunsite.unc.edu:/pub/Linux/system/Misc/fdutils-4.1.src.tar.gz
tsx-11.mit.edu:/pub/linux/sources/sbin/fdutils-4.1.src.tar.gz
- llseek.c: from Remy Card's e2fsprogs-0.5b-WIP.tar.gz
+ llseek.c: from Remy Card's e2fsprogs-0.5b.tar.gz (21Mar95 version) from:
+ sunsite.unc.edu:/pub/Linux/system/Filesystems/ext2
games:
banner: (8.3 (Berkeley) 4/2/94)
- ddate: Druel the Chaotic aka Jeremy Johnson aka mpython@gnu.ai.mit.edu,
- with modifications by Lee Harvey Oswald Smith, K.S.C.
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
login-utils:
agetty: W. Z. Venema, ported by Peter Orbaek <poe@daimi.aau.dk>.
- ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.37.tar.gz
chfn: Salvatore Valente <svalente@athena.mit.edu>
chsh: Salvatore Valente <svalente@athena.mit.edu>
last: 5.11 w/year (Berkeley) 6/29/88; Port by Michael Haardt with
changes by Peter Orbaek.
- ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.16.tar.gz
login: 5.40 (Berkeley) 5/9/89; with ports by Michael Glad and Peter Orbaek
- ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
- mesg: Miquel van Smoorenburg (miquels@htsa.aha.nl,
- miquels@drinkel.nl.mugnet.org). From his sysvinit.tar.Z package.
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.37.tar.gz
+ mesg: 8.2 (Berkeley) 1/21/94
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
newgrp: Michael Haardt, with modifications by Peter Orbaek.
- ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.16.tar.gz
passwd: Peter Orbaek, with yp modifications by Alvaro Martinez
Echevarria (alvaro@enano.etsit.upm.es)
- ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.16.tar.gz
shutdown: Peter Orbaek, with new modifications by Stephen Tweedie, Rik
Faith, and Dave (gentzel@nova.enet.dec.com).
- ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.16.tar.gz
simpleinit: Peter Orbaek
- ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.37.tar.gz
vipw: 5.16 (Berkeley) 3/3/91, with modifications by Mike Grupenhoff
<kashmir@umiacs.UMD.EDU>
- wall: 5.14 (Berkeley) 3/2/91 [From the BSD NET-2 (4.3bsd-reno)
- distribution at wuarchive.wustl.edu:/mirrors/4.3-reno]
-
-makedev-1.4:
- MAKEDEV-C: David A. Holland (dholland@husc.harvard.edu)
- This version MODIFIED by Rik Faith (faith@cs.unc.edu)
- sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-C-1.4.tar.gz
+ wall: 8.2 (Berkeley) 11/16/93 (With changes so that damaging escape
+ sequences cannot be sent.
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
misc-utils:
cal: 8.4 (Berkeley) 4/2/94, with modifications by Rik Faith and
Hein@student.tu-clausthal.de (Jochen Hein).
ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ chkdupexe: Version 1.2 from "Nicolai Langfeldt" <janl@ifi.uio.no>
clear: Rik Faith
+ ddate: Druel the Chaotic aka Jeremy Johnson aka mpython@gnu.ai.mit.edu,
+ with modifications by Lee Harvey Oswald Smith, K.S.C. and
+ substantial updates from Rev. Bro. Lee H:. O:. Smith, KYTP
domainname: Peter Orbaek
- ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.37.tar.gz
dsplit: David Arnstein (arnstein@netcom.com)
gatekeeper.dec.com:/pub/usenet/comp.sources.misc/volume40/dsplit
getopt (getoptprog): jhunix.hcf.jhu.edu:
/pub/public_domain_software/NetBSD/usr/src/usr.bin/getopt
hostid: Mitch DSouza (m.dsouza@mrc-apu.cam.ac.uk)
- ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.37.tar.gz
hostname/dnsdomainname: Peter Tobias <tobias@server.et-inf.fho-emden.de>
This version (1.6) should also be available soon in:
nic.funet.fi:/pub/OS/Linux/PEOPLE/Linus/net-source/base/NetKit-A*
wuarchive.wustl.edu:/mirrors/4.3-reno
whereis: 5.5 (Berkeley) 4/18/91
wuarchive.wustl.edu:/mirrors/4.3-reno
- write: 4.22 (Berkeley) 6/1/90, with modifications by Mike Grupenhoff
- (kashmir@umiacs.umd.edu) .
- wuarchive.wustl.edu:/mirrors/4.3-reno
+ write: 8.1 (Berkeley) 6/6/93, with modifications by Mike Grupenhoff
+ (kashmir@umiacs.umd.edu). With changes so that damaging escape
+ sequences cannot be sent.
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+
mount:
mount, umount, swapon
before /proc/filesystems is checked. Andries.Brouwer@cwi.nl fixed up
error reporting.
+ Updated with patches from Andries.Brouwer@cwi.nl and Dan Quinlan
+ (quinlan@yggdrasil.com). And more patches from Andries and others.
+
historic/selection: The complete selection-1.5 package, by Andrew Haylett
<ajh@gec-mrc.co.uk>, 17th June 1993, is included in the historic tree.
Kernel patches are no longer necessary for modern kernels, but these
modified for this distribution. With changes from Rick Sladkey.
sys-utils:
- MAKEDEV: Nick Holloway <Nick.Holloway@alfie.demon.co.uk>
arch: Rik Faith <faith@cs.unc.edu>
chroot: Rick Sladkey <jrs@world.std.com>
clock: Originally from the timesrc-1.2.tar.Z package, Charles Hedrick,
(hamish@zot.apana.org.au) (V1.2a); Alan Modra
(alan@spri.levels.unisa.edu.au (V1.3, V1.4).
ctrlaltdel: Peter Orbaek <poe@daimi.aau.dk>
- ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.16.tar.gz
+ cytune: Nick Simicish (njs@scifi.emi.net) and Rik Faith (faith@cs.unc.edu)
dmesg: Theodore Ts'o (tytso@athena.mit.edu); Rick Sladkey
(jrs@world.std.com)
ipcrm: From the ipcdelta.tar.z distribution by krishna
kbdrate: Rik Faith (faith@cs.unc.edu), with patches from
Andries.Brouwer@cwi.nl and John Bowman
(bowman@hagar.ph.utexas.edu)
- lpcntl: Nigel Gamble (nigel@gate.net)
+ ksymoops: 1.7 from Greg McGary <gkm@magilla.cichlid.com>
rdev: almesber@nessie.cs.id.ethz.ch (Werner Almesberger), with
modifications from Peter MacDonald, Stephen Tweedie
(sct@dcs.ed.ac.uk), and Dave (gentzel@nova.enet.dec.com)
sln: Mike Parker and David MacKenzie (from Linux's libc)
sync: Nick Holloway, with thanks to James Bonfield
tunelp: Michael K. Johnson (johnsonm@nigel.vnet.net)
- update_state: Rik Faith (faith@cs.unc.edu)
+
syslogd:
5.45 (Berkeley) 3/2/91
ul: 8.1 (Berkeley) 6/6/93
ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
-time:
- elsie.nci.nih.gov:/pub/classictzcode.tar.gz
- elsie.nci.nih.gov:/pub/classictzdata.tar.gz
- (The zoneinfo database was updated Dec 1994.)
-
-%%
-* bin/arch
-* bin/dmesg
-* bin/dnsdomainname
-* bin/domainname
-* bin/hostname
-* bin/kill
-* bin/login
-* bin/more
-* bin/mount
-* bin/setserial
-* bin/sync
-* bin/umount
-* dev/MAKEDEV
-* dev/MAKEDEV-C
-* etc/devinfo
-* etc/makedev.cfg
-* etc/fdprm
-* sbin/agetty
-* sbin/cfdisk
-* sbin/clock
-* sbin/fastboot
-* sbin/fasthalt
-* sbin/fdisk
-* sbin/fsck.minix
-* sbin/halt
-* sbin/kbdrate
-* sbin/mkfs
-* sbin/mkfs.minix
-* sbin/mkswap
-* sbin/reboot
-* sbin/shutdown
-* sbin/simpleinit
-* sbin/sln
-* sbin/swapoff
-* sbin/swapon
-* usr/bin/cal
-* usr/bin/chfn
-* usr/bin/chsh
-* usr/bin/clear
-* usr/bin/col
-* usr/bin/colcrt
-* usr/bin/colrm
-* usr/bin/column
-* usr/bin/dsplit
-* usr/bin/fdformat
-* usr/bin/getopt
-* usr/bin/hexdump
-* usr/bin/hostid
-* usr/bin/ipcrm
-* usr/bin/ipcs
-* usr/bin/last
-* usr/bin/logger
-* usr/bin/look
-* usr/bin/lpcntl
-* usr/bin/mcookie
-* usr/bin/md5sum
-* usr/bin/mesg
-* usr/bin/namei
-* usr/bin/newgrp
-* usr/bin/passwd
-* usr/bin/ramsize
-* usr/bin/rdev
-* usr/bin/readprofile
-* usr/bin/renice
-* usr/bin/reset
-* usr/bin/rev
-* usr/bin/rootflags
-* usr/bin/script
-* usr/bin/setfdprm
-* usr/bin/setsid
-* usr/bin/setterm
-* usr/bin/strings
-* usr/bin/swapdev
-* usr/bin/tsort
-* usr/bin/tunelp
-* usr/bin/ul
-* usr/bin/vidmode
-* usr/bin/wall
-* usr/bin/whereis
-* usr/bin/write
-* usr/info/ipc.info
-* usr/lib/libz.a
-* usr/lib/more.help
-* usr/lib/zoneinfo
-* usr/man/man1/arch.1
-* usr/man/man1/cal.1
-* usr/man/man1/chfn.1
-* usr/man/man1/chsh.1
-* usr/man/man1/clear.1
-* usr/man/man1/col.1
-* usr/man/man1/colcrt.1
-* usr/man/man1/colrm.1
-* usr/man/man1/column.1
-* usr/man/man1/dnsdomainname.1
-* usr/man/man1/domainname.1
-* usr/man/man1/dsplit.1
-* usr/man/man1/getopt.1
-* usr/man/man1/hexdump.1
-* usr/man/man1/hostid.1
-* usr/man/man1/hostname.1
-* usr/man/man1/kill.1
-* usr/man/man1/last.1
-* usr/man/man1/logger.1
-* usr/man/man1/login.1
-* usr/man/man1/look.1
-* usr/man/man1/md5sum.1
-* usr/man/man1/mesg.1
-* usr/man/man1/more.1
-* usr/man/man1/namei.1
-* usr/man/man1/newgrp.1
-* usr/man/man1/passwd.1
-* usr/man/man1/readprofile.1
-* usr/man/man1/reset.1
-* usr/man/man1/rev.1
-* usr/man/man1/script.1
-* usr/man/man1/setterm.1
-* usr/man/man1/strings.1
-* usr/man/man1/tsort.1
-* usr/man/man1/ul.1
-* usr/man/man1/wall.1
-* usr/man/man1/whereis.1
-* usr/man/man1/write.1
-* usr/man/man3/newctime.3
-* usr/man/man3/newtzset.3
-* usr/man/man5/devinfo.5
-* usr/man/man5/fstab.5
-* usr/man/man5/makedev.cfg.5
-* usr/man/man5/nfs.5
-* usr/man/man5/syslog.conf.5
-* usr/man/man5/tzfile.5
-* usr/man/man6/banner.6
-* usr/man/man6/ddate.6
-* usr/man/man8/MAKEDEV-C.8
-* usr/man/man8/MAKEDEV.8
-* usr/man/man8/agetty.8
-* usr/man/man8/cfdisk.8
-* usr/man/man8/chroot.8
-* usr/man/man8/clock.8
-* usr/man/man8/ctrlaltdel.8
-* usr/man/man8/dmesg.8
-* usr/man/man8/fastboot.8
-* usr/man/man8/fasthalt.8
-* usr/man/man8/fdformat.8
-* usr/man/man8/fdisk.8
-* usr/man/man8/frag.8
-* usr/man/man8/fsck.minix.8
-* usr/man/man8/halt.8
-* usr/man/man8/ipcrm.8
-* usr/man/man8/ipcs.8
-* usr/man/man8/kbdrate.8
-* usr/man/man8/lpcntl.8
-* usr/man/man8/mkfs.8
-* usr/man/man8/mkfs.minix.8
-* usr/man/man8/mkswap.8
-* usr/man/man8/mount.8
-* usr/man/man8/ramsize.8
-* usr/man/man8/rdev.8
-* usr/man/man8/reboot.8
-* usr/man/man8/renice.8
-* usr/man/man8/rootflags.8
-* usr/man/man8/setfdprm.8
-* usr/man/man8/setserial.8
-* usr/man/man8/setsid.8
-* usr/man/man8/shutdown.8
-* usr/man/man8/simpleinit.8
-* usr/man/man8/swapdev.8
-* usr/man/man8/swapoff.8
-* usr/man/man8/swapon.8
-* usr/man/man8/sync.8
-* usr/man/man8/syslogd.8
-* usr/man/man8/tunelp.8
-* usr/man/man8/umount.8
-* usr/man/man8/update_state.8
-* usr/man/man8/vidmode.8
-* usr/man/man8/vipw.8
-* usr/man/man8/zdump.8
-* usr/man/man8/zic.8
-* usr/sbin/chroot
-* usr/sbin/ctrlaltdel
-* usr/sbin/frag
-* usr/sbin/syslogd
-* usr/sbin/update_state
-* usr/sbin/vipw
-* usr/sbin/zdump
-* usr/sbin/zic
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Sat Feb 4 19:35:59 1995 by faith@cs.unc.edu
+# Revised: Fri Mar 10 21:20:41 1995 by faith@cs.unc.edu
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
include ../MCONFIG
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
all: err.o getopt.o
err.o: err.c
getopt.o: getopt.c
#undef _PATH_MAILDIR
#ifndef SBINDIR
-#define SBINDIR "/etc"
+#define SBINDIR "/sbin"
#endif
#ifndef USRSBINDIR
-#define USRSBINDIR "/etc"
+#define USRSBINDIR "/usr/sbin"
#endif
#ifndef LOGDIR
-#define LOGDIR "/etc"
+#define LOGDIR "/var/log"
#endif
#ifndef VARPATH
-#define VARPATH "/usr"
+#define VARPATH "/var"
#endif
#define _PATH_BSHELL "/bin/sh"
#define _PATH_TTY "/dev/tty"
#define TTYTYPES "/etc/ttytype"
#define SECURETTY "/etc/securetty"
-#define _PATH_UTMP LOGDIR "/utmp"
+#define _PATH_UTMP "/var/run/utmp"
#define _PATH_WTMP LOGDIR "/wtmp"
#define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin:."
#define _PATH_MTAB "/etc/mtab"
#define _PATH_UMOUNT "/bin/umount"
#define UMOUNT_ARGS "umount", "-a"
+#define SWAPOFF_ARGS "swapoff", "-a"
#define _PATH_PASSWD "/etc/passwd"
#define _PATH_PTMP "/etc/ptmp"
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Wed Feb 22 16:09:35 1995 by faith@cs.unc.edu
+# Revised: Fri Oct 6 21:02:21 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
# Where to put man pages?
-MAN8= cfdisk.8 fdformat.8 fdisk.8 frag.8 fsck.minix.8 \
- mkfs.8 mkfs.minix.8 mkswap.8 setfdprm.8
+MAN8= cfdisk.8 fdformat.8 fsck.minix.8 \
+ mkfs.8 mkfs.minix.8 mkswap.8 setfdprm.8
+
+MAN8.FDISK= fdisk.8
# Where to put binaries?
# See the "install" rule for the links. . .
-SBIN= cfdisk fdisk fsck.minix mkfs mkfs.minix mkswap
+SBIN= cfdisk fsck.minix mkfs mkfs.minix mkswap
-USRSBIN= frag
+SBIN.FDISK= fdisk
USRBIN= fdformat setfdprm
ETC= fdprm
-all: $(SBIN) $(USRSBIN) $(USRBIN)
+ifeq "$(HAVE_FDISK)" "no"
+SBIN:=$(SBIN) $(SBIN.FDISK)
+MAN8:=$(MAN8) $(MAN8.FDISK)
+endif
-cfdisk: cfdisk.c llseek.o
- $(CC) $(CFLAGS) $(LDFLAGS) $< llseek.o -o $@ -lcurses -ltermcap -lm
+all: $(SBIN) $(USRBIN)
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
+cfdisk: cfdisk.o llseek.o
+ $(CC) $(LDFLAGS) $^ -o $@ -lcurses -ltermcap -lm
# Rules for everything else
fdformat: fdformat.o
-fdisk: fdisk.o llseek.o
-frag: frag.o
+fdisk: fdisk.o fdisklabel.o llseek.o
fsck.minix: fsck.minix.o
mkfs: mkfs.o
mkfs.minix: mkfs.minix.o
mkswap: mkswap.o
setfdprm: setfdprm.o
+fdisk.o: fdisk.c fdisk.h
+fdisklabel.o: fdisklabel.c fdisk.h
install: all
- $(INSTALLDIR) $(SBINDIR) $(USRSBINDIR) $(ETCDIR)
+ $(INSTALLDIR) $(SBINDIR) $(USRBINDIR) $(ETCDIR)
$(INSTALLBIN) $(SBIN) $(SBINDIR)
- $(INSTALLBIN) $(USRSBIN) $(USRSBINDIR)
$(INSTALLBIN) $(USRBIN) $(USRBINDIR)
$(INSTALLDAT) $(ETC) $(ETCDIR)
$(INSTALLDIR) $(MAN8DIR)
.PHONY: clean
clean:
- -rm -f *.o *~ core $(SBIN) $(USRSBIN) $(USRBIN)
+ -rm -f *.o *~ core $(SBIN) $(USRBIN)
It is a good idea to plan ahead before you start creating partitions
on your disk. If you set aside a partition for some purpose, it is not
-easy to change its size: you must all the data from the partition,
+easy to change its size: you must backup all the data from the partition,
whether to floppies, to another partition, to another hard disk, or
somewhere else; then you must edit the table which describes this
partition, so changing its size; then you must reboot and initialise
The Verify command is useful because
- 1. It warns you if anything is wrong. *Always* give a Verify command
- before writing any changes to disk.
+ 1. It warns you if anything is wrong. *Always* do a Verify command
+ to check your work before writing any changes to disk.
2. It reports how many unallocated sectors there are on the disk.
If space is available, you are prompted for the first cylinder:
- First sector (237-977): _
+ First sector ([237]-977): _
The limits are the lowest and the highest cylinders in which sectors
-are available in the appropriate part of the disk. Not all numbers in
+are available in the appropriate part of the disk. The square-bracketed
+number is what you'll get if you simply press enter. Not all numbers in
this range are necessarily available: they may fall inside an existing
partition. If you select a cylinder which is already in use, you are
told off and prompted again for the first cylinder. After selecting the
first cylinder, you are prompted again:
- Last cylinder or +size or +sizeM or +sizeK (237-836): _
+ Last cylinder or +size or +sizeM or +sizeK (237-[836]): _
The limits are the cylinder you have chosen as the first cylinder,
and the highest cylinder which contains a legitimate upper boundary for
-the new partition. In other words, all numbers in the given range are
+the new partition. The square-bracketed number is what you'll get if
+you simply press enter. In other words, all numbers in the given range are
legitimate, unlike those in the first range of cylinders. You may also
specify the size of a partition in megabytes, kilobytes, or in the
current units (cylinders or sectors). A plus sign `+' indicates that
Make cylinder 700 the last cylinder in the partition.
+300
- Make cylinder 537 the last cylinder in the partition.
+ Make cylinder 237 + 300 = 537 the last cylinder in the partition.
+15m
Make the partition at least 15 megabytes in size.
Make the partition at least 12,500 kilobytes in size.
If you specify a size which is too large or an end which is out of
-range, the prompt is simply repeated.
+range, fdisk complains and repeats the prompt.
Adding or deleting partitions has no effect unless you subsequently
give the Write command. Please remember to give the Verify command
In general, you should not use this `fdisk' program to create
partitions for other operating systems, only for Linux. Nor should you
-use `fdisk' commands from other operating systems do create partitions
+use `fdisk' commands from other operating systems to create partitions
for Linux.
DR-DOS 5.0 and 6.0 are reported to have difficulties with partition
--- /dev/null
+
+There are some things which have to be done for the alpha version:
+- LABELSECTOR, LABELOFFSET, BBSIZE & SBSIZE are undefined in fdisklabel.h
+ These values are different for different versions of NetBSD and I don't
+ have the alpha source tree for NetBSD yet (It's not in 1.0 but in current).
+ I guess Linux/Alpha uses the same values.
+- The alpha fdisklabel.c requires a few functions from fdisk.c.
+ ("make test" shows the undefined symbols when fdisk.c is missing)
+ All the other functions/variables shouldn't be declared. I didn't do
+ that because I didn't want to change much in fdisk.c.
+- The disklabel in fdisklabel.c is the NetBSD disklabel which might
+ differ from the Linux/Alpha disklabel in some parts.
+- bselect () should be called from main () immediately. Under Linux/Alpha
+ it's the main menu and not a submenu.
+
+fasten@informatik.uni-bonn.de
--- /dev/null
+
+All changes in fdisk.c are marked with this comment: /* bf */
+
+I added some explanatory comments to make it easier to see what
+changed and why. You'll probably want to remove them.
+
+There's a function sync_disks() in fdisklabel.c which could be called
+from write_table() in fdisk.c (line 1216) (and be moved to fdisk.c)
+to save a few bytes.
+
+There's a function edit_int() in fdisklabel.c which I added because read_int()
+had no default value. In fdisk v2.0d it has so edit_int could be replaces by
+read_int(). The function which uses edit_int() (bsd_edit_disklabel ()) is a
+bit crufty anyhow:
+- The disklabel contains some values which are probably meaningless for IDE or
+ SCSI drives, I made them editable but I don't know any sensible range of
+ values (bad for read_int()). (interleave, trackskew, cylskew)
+- I made the values secsize/nsectors/ntracks/ncylinders editable for Linux/Alpha
+ but not for Linux/i386 because under Linux/i386 the disklabel is inside a
+ DOS partition so the disklabel was written by an OS which got along with the
+ disk and should have left the correct values there.
+
+I've put the BSD copyright (which applies to fdisklabel.h and
+alpha_bootblock_checksum, bsd_dkcksum, bsd_print_disklabel in fdisklabel.c)
+into a separate man page. This way all Linux versions of BSD programs can refer
+to ths bsd.<n> man page.
+
+fasten@informatik.uni-bonn.de
.\" permission notice identical to this one.
.\"
.\" " for hilit mode
-.TH CFDISK 8 "25 April 1994" "The BOGUS Linux Release" "Linux Programmer's Manual"
+.TH CFDISK 8 "3 June 1995" "The BOGUS Linux Release" "Linux Programmer's Manual"
.SH NAME
cfdisk \- Curses based disk partition table manipulator for Linux
.SH SYNOPSIS
--- /dev/null
+.\" cfdisk.8 -- man page for cfdisk
+.\" Copyright 1994 Kevin E. Martin (martin@cs.unc.edu)
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one.
+.\"
+.\" " for hilit mode
+.TH CFDISK 8 "25 April 1994" "The BOGUS Linux Release" "Linux Programmer's Manual"
+.SH NAME
+cfdisk \- Curses based disk partition table manipulator for Linux
+.SH SYNOPSIS
+.BI "cfdisk [ \-avz ] [ \-c " cylinders " ] [ \-h " heads " ]"
+.BI "[ \-s " sectors-per-track " ] [ -P " opt " ] [ " device " ]"
+.SH DESCRIPTION
+.B cfdisk
+is a curses based program for partitioning a hard disk drive. The
+.I device
+can be any one of the following:
+.sp
+.nf
+.RS
+/dev/hda [default]
+/dev/hdb
+/dev/sda
+/dev/sdb
+/dev/sdc
+/dev/sdd
+.RE
+.fi
+
+.B cfdisk
+first tries to read the geometry of the hard disk. If it fails, an
+error message is displayed and
+.B cfdisk
+exits. This should only happen when partitioning a SCSI drive on an
+adapter without a BIOS. To correct this problem, you can set the
+.IR cylinders ", " heads " and " sectors-per-track
+on the command line. Next,
+.B cfdisk
+tries to read the current partition table from the disk drive. If it
+is unable to figure out the partition table, an error is displayed and
+the program will exit. This might also be caused by incorrect
+geometry information, and can be overridden on the command line.
+Another way around this problem is with the
+.B \-z
+option. This will ignore the partition table on the disk.
+
+The main display is composed of four sections, from top to bottom: the
+header, the partitions, the command line and a warning line. The
+header contains the program name and version number followed by the
+disk drive and its geometry. The partitions section always displays
+the current partition table. The command line is the place where
+commands and text are entered. The available commands are usually
+displayed in brackets. The warning line is usually empty except when
+there is important information to be displayed. The current partition
+is highlighted with reverse video (or an arrow if the
+.B \-a
+option is given). All partition specific commands apply to the
+current partition.
+
+The format of the partition table in the partitions section is, from
+left to right: Name, Flags, Partition Type, Filesystem Type and Size.
+The name is the partition device name. The flags can be
+.IR Boot ,
+which designates a bootable partition or
+.IR NC ,
+which stands for "Not Compatible with DOS or OS/2". DOS, OS/2 and
+possibly other operating systems require the first sector of the first
+partition on the disk and all logical partitions to begin on the
+second head. This wastes the second through the last sector of the
+first track of the first head (the first sector is taken by the
+partition table itself).
+.B cfdisk
+allows you to recover these "lost" sectors with the maximize command
+.RB ( m ).
+.I Note:
+.BR fdisk (8)
+and some early versions of DOS create all partitions with the number
+of sectors already maximized. For more information, see the maximize
+command below. The partition type can be one of
+.IR Primary " or " Logical .
+For unallocated space on the drive, the partition type can also be
+.IR Pri/Log ,
+or empty (if the space is unusable). The filesystem type section
+displays the name of the filesystem used on the partition, if known.
+If it is unknown, then
+.I Unknown
+and the hex value of the filesystem type are displayed. A special
+case occurs when there are sections of the disk drive that cannot be
+used (because all of the primary partitions are used). When this is
+detected, the filesystem type is displayed as
+.IR Unusable .
+The size field displays the size of the partition in megabytes (by
+default). It can also display the size in sectors and cylinders (see
+the change units command below). If an asterisks
+.RB ( * )
+appears after the size, this means that the partition is not aligned
+on cylinder boundaries.
+.SH "DOS 6.x WARNING"
+
+The DOS 6.x FORMAT command looks for some information in the first
+sector of the data area of the partition, and treats this information
+as more reliable than the information in the partition table. DOS
+FORMAT expects DOS FDISK to clear the first 512 bytes of the data area
+of a partition whenever a size change occurs. DOS FORMAT will look at
+this extra information even if the /U flag is given -- we consider
+this a bug in DOS FORMAT and DOS FDISK.
+
+The bottom line is that if you use cfdisk or fdisk to change the size of a
+DOS partition table entry, then you must also use
+.B dd
+to zero the first 512 bytes of that partition before using DOS FORMAT to
+format the partition. For example, if you were using cfdisk to make a DOS
+partition table entry for /dev/hda1, then (after exiting fdisk or cfdisk
+and rebooting Linux so that the partition table information is valid) you
+would use the command "dd if=/dev/zero of=/dev/hda1 bs=512 count=1" to zero
+the first 512 bytes of the partition.
+.B BE EXTREMELY CAREFUL
+if you use the
+.B dd
+command, since a small typo can make all of the data on your disk useless.
+
+.B BE EXTREMELY CAREFUL
+if you use the
+.B dd
+command, since a small typo can make all of the data on your disk useless.
+
+For best resutls, you should always use an OS-specific partition table
+program. For example, you should make DOS partitions with the DOS FDISK
+program and Linux partitions with the Linux fdisk or Linux cfdisk program.
+
+.SH COMMANDS
+.B cfdisk
+commands can be entered by pressing the desired key (pressing
+.I Enter
+after the command is not necessary). Here is a list of the available
+commands:
+.TP
+.B b
+Toggle bootable flag of the current partition. This allows you to
+select which primary partition is bootable on the drive.
+.TP
+.B d
+Delete the current partition. This will convert the current partition
+into free space and merge it with any free space immediately
+surrounding the current partition. A partition already marked as free
+space or marked as unusable cannot be deleted.
+.TP
+.B g
+Change the disk geometry (cylinders, heads, or sectors-per-track).
+.B WARNING:
+This option should only be used by people who know what they are
+doing. A command line option is also available to change the disk
+geometry. While at the change disk geometry command line, you can
+choose to change cylinders
+.RB ( c ),
+heads
+.RB ( h ),
+and sectors per track
+.RB ( s ).
+The default value will be printed at the prompt which you can accept
+by simply pressing the
+.I Enter
+key, or you can exit without changes by pressing the
+.I ESC
+key. If you want to change the default value, simply enter the
+desired value and press
+.IR Enter .
+The altered disk parameter values do not take effect until you return
+the main menu (by pressing
+.IR Enter " or " ESC
+at the change disk geometry command line. If you change the geometry
+such that the disk appears larger, the extra sectors are added at the
+end of the disk as free space. If the disk appears smaller, the
+partitions that are beyond the new last sector are deleted and the
+last partition on the drive (or the free space at the end of the
+drive) is made to end at the new last sector.
+.TP
+.B h
+Print the help screen.
+.TP
+.B m
+Maximize disk usage of the current partition. This command will
+recover the the unused space between the partition table and the
+beginning of the partition, but at the cost of making the partition
+incompatible with DOS, OS/2 and possibly other operating systems.
+This option will toggle between maximal disk usage and DOS, OS/2,
+etc. compatible disk usage. The default when creating a partition is
+to create DOS, OS/2, etc. compatible partitions.
+.TP
+.B n
+Create new partition from free space. If the partition type is
+.IR Primary " or " Logical ,
+a partition of that type will be created, but if the partition type is
+.IR Pri/Log ,
+you will be prompted for the type you want to create. Be aware that
+(1) there are only four slots available for primary partitions and (2)
+since there can be only one extended partition, which contains all of
+the logical drives, all of the logical drives must be contiguous (with
+no intervening primary partition).
+.B cfdisk
+next prompts you for the size of the partition you want to create.
+The default size, equal to the entire free space of the current
+partition, is display in megabytes. You can either press the
+.I Enter
+key to accept the default size or enter a different size at the
+prompt.
+.B cfdisk
+accepts size entries in megabytes
+.RB ( M )
+[default], kilobytes
+.RB ( K ),
+cylinders
+.RB ( C )
+and sectors
+.RB ( S )
+by entering the number immediately followed by one of
+.RB ( M ", " K ", " C " or " S ).
+If the partition fills the free space available, the partition is
+created and you are returned to the main command line. Otherwise, the
+partition can be created at the beginning or the end of the free
+space, and
+.B cfdisk
+will ask you to choose where to place the partition. After the
+partition is created,
+.B cfdisk
+automatically adjusts the other partition's partition types if all of
+the primary partitions are used.
+.TP
+.B p
+Print the partition table to the screen or to a file. There are
+several different formats for the partition that you can choose from:
+.sp
+.RS
+.TP
+.B r
+Raw data format (exactly what would be written to disk)
+.TP
+.B s
+Partition table in sector order format
+.TP
+.B t
+Partition table in raw format
+.RE
+
+.RS
+The
+.I raw data format
+will print the sectors that would be written to disk if a
+.BR w rite
+command is selected. First, the primary partition table is printed,
+followed by the partition tables associated with each logical
+partition. The data is printed in hex byte by byte with 16 bytes per
+line.
+
+The
+.I partition table in sector order format
+will print the partition table ordered by sector number. The fields,
+from left to right, are the number of the partition, the partition
+type, the first sector, the last sector, the offset from the first
+sector of the partition to the start of the data, the length of the
+partition, the filesystem type (with the hex value in parenthesis),
+and the flags (with the hex value in parenthesis). In addition to the
+primary and logical partitions, free and unusable space is printed and
+the extended partition is printed before the first logical partition.
+
+If a partition does not start or end on a cylinder boundary or if the
+partition length is not divisible by the cylinder size, an asterisks
+.RB ( * )
+is printed after the non-aligned sector number/count. This usually
+indicates that a partition was created by an operating system that
+either does not align partitions to cylinder boundaries or that used
+different disk geometry information. If you know the disk geometry of
+the other operating system, you could enter the geometry information
+with the change geometry command
+.RB ( g ).
+
+For the first partition on the disk and for all logical partitions, if
+the offset from the beginning of the partition is not equal to the
+number of sectors per track (i.e., the data does not start on the
+first head), a number sign
+.RB ( # )
+is printed after the offset. For the remaining partitions, if the
+offset is not zero, a number sign will be printed after the offset.
+This corresponds to the
+.I NC
+flag in the partitions section of the main display.
+
+The
+.I partition table in raw format
+will print the partition table ordered by partition number. It will
+leave out all free and unusable space. The fields, from left to
+right, are the number of the partition, the flags (in hex), the
+starting head, sector and cylinder, the filesystem ID (in hex), the
+ending head, sector and cylinder, the starting sector in the partition
+and the number of sectors in the partition. The information in this
+table can be directly translated to the
+.IR "raw data format" .
+
+The partition table entries only have 10 bits available to represent
+the starting and ending cylinders. Thus, when the absolute starting
+(ending) sector number is on a cylinder greater than 1023, the maximal
+values for starting (ending) head, sector and cylinder are printed.
+This is the method used by OS/2, and thus fixes the problems
+associated with OS/2's fdisk rewriting the partition table when it is
+not in this format. Since Linux and OS/2 use absolute sector counts,
+the values in the starting and ending head, sector and cylinder are
+not used.
+.RE
+.TP
+.B q
+Quit program. This will exit the program without writing any data to
+disk.
+.TP
+.B t
+Change the filesystem type. By default, new partitions are created as
+.I Linux
+partitions, but since
+.B cfdisk
+can create partitions for other operating systems, change partition
+type allows you to enter the hex value of the filesystem you desire.
+A list of the know filesystem types is displayed. You can type in the
+filesystem type at the prompt or accept the default filesystem type
+.RI [ Linux ].
+.TP
+.B u
+Change units of the partition size display. It will rotate through
+megabytes, sectors and cylinders.
+.TP
+.B W
+Write partition table to disk (must enter an upper case W). Since
+this might destroy data on the disk, you must either confirm or deny
+the write by entering `yes' or `no'. If you enter `yes',
+.B cfdisk
+will write the partition table to disk and the tell the kernel to
+re-read the partition table from the disk. The re-reading of the
+partition table works is most cases, but I have seen it fail. Don't
+panic. It will be correct after you reboot the system. In all cases,
+I still recommend rebooting the system--just to be safe.
+.TP
+.I Up Arrow
+.TP
+.I Down Arrow
+Move cursor to the previous or next partition. If there are more
+partitions than can be displayed on a screen, you can display the next
+(previous) set of partitions by moving down (up) at the last (first)
+partition displayed on the screen.
+.TP
+.I CTRL-L
+Redraws the screen. In case something goes wrong and you cannot read
+anything, you can refresh the screen from the main command line.
+.TP
+.B ?
+Print the help screen.
+
+.RE
+All of the commands can be entered with either upper or lower case
+letters (except for
+.BR W rites).
+When in a sub-menu or at a prompt to enter a filename, you can hit the
+.I ESC
+key to return to the main command line.
+.SH OPTIONS
+.TP
+.B \-a
+Use an arrow cursor instead of reverse video for highlighting the
+current partition.
+.TP
+.B \-v
+Print the version number and copyright.
+.TP
+.B \-z
+Start with zeroed partition table. This option is useful when you
+want to repartition your entire disk.
+.I Note:
+this option does not zero the partition table on the disk; rather, it
+simply starts the program without reading the existing partition
+table.
+.TP
+.BI \-c " cylinders"
+.TP
+.BI \-h " heads"
+.TP
+.BI \-s " sectors-per-track"
+Override the number of cylinders, heads and sectors per track read
+from the BIOS. If your BIOS or adapter does not supply this
+information or if it supplies incorrect information, use these options
+to set the disk geometry values.
+.TP
+.BI \-P " opt"
+Prints the partition table in specified formats.
+.I opt
+can be one or more of "r", "s" or "t". See the
+.BR p rint
+command (above) for more information on the print formats.
+.SH "SEE ALSO"
+fdisk(8)
+.SH BUGS
+The current version does not support multiple disks (future addition).
+.SH AUTHOR
+Kevin E. Martin (martin@cs.unc.edu)
#include <curses.h>
#include <signal.h>
#include <math.h>
+#include <string.h>
#include <sys/ioctl.h>
#include <linux/genhd.h>
#include <linux/hdreg.h>
unsigned int origin);
-#define VERSION "0.8a BETA (>2GB)"
+#define VERSION "0.8d BETA (>2GB)"
#define DEFAULT_DEVICE "/dev/hda"
#define ALTERNATE_DEVICE "/dev/sda"
/* The rest of these are taken from A. V. Le Blanc's (LeBlanc@mcc.ac.uk)
* fdisk program. I do not know where they came from, but I include
- * them for completeness.
+ * them for completeness. (With additions.)
*/
[0x02] = "XENIX root",
[0x51] = "Novell?",
[0x52] = "Microport",
[0x63] = "GNU HURD",
- [0x64] = "Novell",
+ [0x64] = "Novell Netware 286",
+ [0x65] = "Novell Netware 386",
[0x75] = "PC/IX",
[0x80] = "Old MINIX",
[0x93] = "Amoeba",
--- /dev/null
+/****************************************************************************
+ *
+ * CFDISK
+ *
+ * cfdisk is a curses based disk drive partitioning program that can
+ * create partitions for a wide variety of operating systems including
+ * Linux, MS-DOS and OS/2.
+ *
+ * cfdisk was inspired by the fdisk program, by A. V. Le Blanc
+ * (LeBlanc@mcc.ac.uk).
+ *
+ * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu)
+ *
+ * cfdisk is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * cfdisk is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with cfdisk; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <curses.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/ioctl.h>
+#include <linux/genhd.h>
+#include <linux/hdreg.h>
+#include <linux/fs.h> /* for BLKRRPART */
+
+typedef long ext2_loff_t;
+extern ext2_loff_t ext2_llseek(unsigned int fd,
+ ext2_loff_t offset,
+ unsigned int origin);
+
+#define VERSION "0.8 BETA (>2GB)"
+
+#define DEFAULT_DEVICE "/dev/hda"
+#define ALTERNATE_DEVICE "/dev/sda"
+
+#define LINE_LENGTH 80
+#define MAXIMUM_PARTS 60
+
+#define SECTOR_SIZE 512
+
+#define MAX_CYLINDERS 65535
+#define MAX_HEADS 255
+#define MAX_SECTORS 63
+
+#define ACTIVE_FLAG 0x80
+#define PART_TABLE_FLAG 0xAA55
+
+#define UNUSABLE -1
+#define FREE_SPACE 0x00
+#define EXTENDED 0x05
+#define LINUX_MINIX 0x81
+#define LINUX_SWAP 0x82
+#define LINUX 0x83
+
+#define ADD_EXISTS "This partition is already in use"
+#define ADD_UNUSABLE "This partition is unusable"
+#define DEL_EMPTY "Cannot delete an empty partition"
+#define ID_EMPTY "Cannot change FS Type to empty"
+#define ID_EXT "Cannot change FS Type to extended"
+#define NEED_EXT "No room to create the extended partition"
+#define NO_FLAGS "Cannot make this partition bootable"
+#define NO_MORE_PARTS "No more partitions"
+#define PRINT_OPEN_ERR "Cannot open file '%s'"
+#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions"
+#define TYPE_EMPTY "Cannot change the type of an empty partition"
+#define BAD_COMMAND "Illegal command"
+#define MAX_UNMAXABLE "Cannot maximize this partition"
+#define BAD_OPEN "Cannot open disk drive"
+#define BAD_SEEK "Cannot seek on disk drive"
+#define BAD_READ "Cannot read disk drive"
+#define BAD_WRITE "Cannot write disk drive"
+#define BAD_GEOMETRY "Cannot read disk drive geometry"
+#define BAD_PRIMARY "Bad primary partition"
+#define BAD_LOGICAL "Bad logical partition"
+#define BAD_CYLINDERS "Illegal cylinders value"
+#define BAD_HEADS "Illegal heads value"
+#define BAD_SECTORS "Illegal sectors value"
+#define WRITE_WARN "Warning!! This may destroy data on your disk!"
+#define YES_NO "Please enter `yes' or `no'"
+#define WRITING_PART "Writing partition table to disk..."
+#define YES_WRITE "Wrote partition table to disk"
+#define NO_WRITE "Did not write partition table to disk"
+#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table."
+
+#define PRI_OR_LOG -1
+#define PRIMARY -2
+#define LOGICAL -3
+
+#define COL_ID_WIDTH 20
+
+#define CR '\015'
+#define ESC '\033'
+#define DEL '\177'
+#define BELL '\007'
+/* '\014' == ^L */
+#define REDRAWKEY '\014'
+
+/* Display units */
+#define MEGABYTES 1
+#define SECTORS 2
+#define CYLINDERS 3
+
+#define GS_DEFAULT -1
+#define GS_ESCAPE -2
+
+#define PRINT_RAW_TABLE 1
+#define PRINT_SECTOR_TABLE 2
+#define PRINT_PARTITION_TABLE 4
+
+#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4)
+#define IS_LOGICAL(p) ((p) > 3)
+
+#define round_int(d) ((double)((int)(d+0.5)))
+#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d)))
+
+#define set_hsc(h,s,c,sector) \
+{ \
+ s = sector % sectors + 1; \
+ sector /= sectors; \
+ h = sector % heads; \
+ sector /= heads; \
+ c = sector & 0xFF; \
+ s |= (sector >> 2) & 0xC0;\
+}
+
+#define ALIGNMENT 2
+typedef union {
+ struct {
+ unsigned char align[ALIGNMENT];
+ unsigned char b[SECTOR_SIZE];
+ } c;
+ struct {
+ unsigned char align[ALIGNMENT];
+ unsigned char buffer[0x1BE];
+ struct partition part[4];
+ unsigned short flag;
+ } p;
+} partition_table;
+
+typedef struct {
+ int first_sector; /* first sector in partition */
+ int last_sector; /* last sector in partition */
+ int offset; /* offset from first sector to start of data */
+ int flags; /* active == 0x80 */
+ int id; /* filesystem type */
+ int num; /* number of partition -- primary vs. logical */
+} partition_info;
+
+char *disk_device = DEFAULT_DEVICE;
+int fd;
+int heads = 0;
+int sectors = 0;
+int cylinders = 0;
+int changed = FALSE;
+int opened = FALSE;
+
+partition_info p_info[MAXIMUM_PARTS];
+partition_info ext_info;
+int num_parts = 0;
+
+int logical = 0;
+int logical_sectors[MAXIMUM_PARTS];
+
+__sighandler_t old_SIGINT, old_SIGTERM;
+
+int arrow_cursor = FALSE;
+int display_units = MEGABYTES;
+int zero_table = FALSE;
+int print_only = 0;
+
+/* Curses screen information */
+int cur_part = 0;
+int warning_last_time = FALSE;
+int defined = FALSE;
+int COLUMNS = 80;
+int NUM_ON_SCREEN = 1;
+
+/* Y coordinates */
+int HEADER_START = 0;
+int DISK_TABLE_START = 5;
+int WARNING_START = 23;
+int COMMAND_LINE_Y = 21;
+
+/* X coordinates */
+int NAME_START = 4;
+int FLAGS_START = 16;
+int PTYPE_START = 30;
+int FSTYPE_START = 45;
+int SIZE_START = 70;
+int COMMAND_LINE_X = 5;
+
+#define NUM_PART_TYPES 256
+char *partition_type[NUM_PART_TYPES] = {
+ [LINUX_MINIX] = "Linux/MINIX",
+ [LINUX_SWAP] = "Linux Swap",
+ [LINUX] = "Linux",
+ [FREE_SPACE] = "Free Space",
+ [EXTENDED] = "Extended",
+ [0x01] = "DOS 12-bit FAT",
+ [0x04] = "DOS 16-bit < 32Mb",
+ [0x06] = "DOS 16-bit >=32Mb",
+ [0x07] = "OS/2 HPFS",
+ [0x0A] = "OS/2 Boot Manager",
+ [0xA5] = "BSD/386",
+
+/* The rest of these are taken from A. V. Le Blanc's (LeBlanc@mcc.ac.uk)
+ * fdisk program. I do not know where they came from, but I include
+ * them for completeness.
+ */
+
+ [0x02] = "XENIX root",
+ [0x03] = "XENIX usr",
+ [0x08] = "AIX",
+ [0x09] = "AIX bootable",
+ [0x40] = "Venix 80286",
+ [0x51] = "Novell?",
+ [0x52] = "Microport",
+ [0x63] = "GNU HURD",
+ [0x64] = "Novell",
+ [0x75] = "PC/IX",
+ [0x80] = "Old MINIX",
+ [0x93] = "Amoeba",
+ [0x94] = "Amoeba BBT",
+ [0xB7] = "BSDI fs",
+ [0xB8] = "BSDI swap",
+ [0xC7] = "Syrinx",
+ [0xDB] = "CP/M",
+ [0xE1] = "DOS access",
+ [0xE3] = "DOS R/O",
+ [0xF2] = "DOS secondary",
+ [0xFF] = "BBT"
+};
+
+void fdexit(int ret)
+{
+ if (opened)
+ close(fd);
+
+ if (changed) {
+ fprintf(stderr, "Disk has been changed.\n");
+ fprintf(stderr, "Reboot the system to ensure the partition "
+ "table is correctly updated.\n");
+
+ fprintf( stderr, "\nWARNING: If you have created or modified any\n"
+ "DOS 6.x partitions, please see the cfdisk manual\n"
+ "page for additional information.\n" );
+ }
+
+
+ exit(ret);
+}
+
+int get_string(char *str, int len, char *def)
+{
+ char c;
+ int i = 0;
+ int x, y;
+ int use_def = FALSE;
+
+ getyx(stdscr, y, x);
+ clrtoeol();
+
+ str[i] = 0;
+
+ if (def != NULL) {
+ mvaddstr(y, x, def);
+ move(y, x);
+ use_def = TRUE;
+ }
+
+ refresh();
+ while ((c = getch()) != '\n' && c != CR) {
+ switch (c) {
+ case ESC:
+ move(y, x);
+ clrtoeol();
+ refresh();
+ return GS_ESCAPE;
+ case DEL:
+ case '\b':
+ if (i > 0) {
+ str[--i] = 0;
+ mvaddch(y, x+i, ' ');
+ move(y, x+i);
+ } else if (use_def) {
+ clrtoeol();
+ use_def = FALSE;
+ } else
+ putchar(BELL);
+ break;
+ default:
+ if (i < len && isprint(c)) {
+ mvaddch(y, x+i, c);
+ if (use_def) {
+ clrtoeol();
+ use_def = FALSE;
+ }
+ str[i++] = c;
+ str[i] = 0;
+ } else
+ putchar(BELL);
+ }
+ refresh();
+ }
+
+ if (use_def)
+ return GS_DEFAULT;
+ else
+ return i;
+}
+
+void clear_warning(void)
+{
+ int i;
+
+ if (!warning_last_time)
+ return;
+
+ move(WARNING_START,0);
+ for (i = 0; i < COLS; i++)
+ addch(' ');
+
+ warning_last_time = FALSE;
+}
+
+void print_warning(char *s)
+{
+ mvaddstr(WARNING_START, (COLS-strlen(s))/2, s);
+ putchar(BELL); /* CTRL-G */
+
+ warning_last_time = TRUE;
+}
+
+void fatal(char *s)
+{
+ char str[LINE_LENGTH];
+
+ sprintf(str, "FATAL ERROR: %s", s);
+ mvaddstr(WARNING_START, (COLS-strlen(str))/2, str);
+ sprintf(str, "Press any key to exit fdisk");
+ mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str);
+ putchar(BELL); /* CTRL-G */
+
+ refresh();
+
+ (void)getch();
+
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+ mvcur(0, COLS-1, LINES-1, 0);
+ nl();
+ endwin();
+ fdexit(1);
+}
+
+void read_sector(char *buffer, int sect_num)
+{
+ if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0)
+ fatal(BAD_SEEK);
+ if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE)
+ fatal(BAD_READ);
+}
+
+void write_sector(char *buffer, int sect_num)
+{
+ if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0)
+ fatal(BAD_SEEK);
+ if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE)
+ fatal(BAD_WRITE);
+}
+
+void check_part_info(void)
+{
+ int i, pri = 0, log = 0;
+
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
+ pri++;
+ else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num))
+ log++;
+ if (ext_info.id == EXTENDED)
+ if (log > 0)
+ pri++;
+ else {
+ ext_info.first_sector = 0;
+ ext_info.last_sector = 0;
+ ext_info.offset = 0;
+ ext_info.flags = 0;
+ ext_info.id = FREE_SPACE;
+ ext_info.num = PRIMARY;
+ }
+
+ if (pri >= 4)
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE)
+ if (ext_info.id == EXTENDED)
+ if (p_info[i].first_sector >= ext_info.first_sector &&
+ p_info[i].last_sector <= ext_info.last_sector) {
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = LOGICAL;
+ } else if (i > 0 &&
+ p_info[i-1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i-1].last_sector <=
+ ext_info.last_sector) {
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = LOGICAL;
+ } else if (i < num_parts-1 &&
+ p_info[i+1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i+1].last_sector <=
+ ext_info.last_sector) {
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = LOGICAL;
+ } else
+ p_info[i].id = UNUSABLE;
+ else /* if (ext_info.id != EXTENDED) */
+ p_info[i].id = UNUSABLE;
+ else /* if (p_info[i].id > 0) */
+ while (0); /* Leave these alone */
+ else /* if (pri < 4) */
+ for (i = 0; i < num_parts; i++) {
+ if (p_info[i].id == UNUSABLE)
+ p_info[i].id = FREE_SPACE;
+ if (p_info[i].id == FREE_SPACE)
+ if (ext_info.id == EXTENDED)
+ if (p_info[i].first_sector >= ext_info.first_sector &&
+ p_info[i].last_sector <= ext_info.last_sector)
+ p_info[i].num = LOGICAL;
+ else if (i > 0 &&
+ p_info[i-1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i-1].last_sector <=
+ ext_info.last_sector)
+ p_info[i].num = PRI_OR_LOG;
+ else if (i < num_parts-1 &&
+ p_info[i+1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i+1].last_sector <=
+ ext_info.last_sector)
+ p_info[i].num = PRI_OR_LOG;
+ else
+ p_info[i].num = PRIMARY;
+ else /* if (ext_info.id != EXTENDED) */
+ p_info[i].num = PRI_OR_LOG;
+ else /* if (p_info[i].id > 0) */
+ while (0); /* Leave these alone */
+ }
+}
+
+void remove_part(int i)
+{
+ int p;
+
+ for (p = i; p < num_parts; p++)
+ p_info[p] = p_info[p+1];
+
+ num_parts--;
+}
+
+void insert_part(int i, int num, int id, int flags, int first, int last,
+ int offset)
+{
+ int p;
+
+ for (p = num_parts; p > i; p--)
+ p_info[p] = p_info[p-1];
+
+ p_info[i].first_sector = first;
+ p_info[i].last_sector = last;
+ p_info[i].offset = offset;
+ p_info[i].flags = flags;
+ p_info[i].id = id;
+ p_info[i].num = num;
+
+ num_parts++;
+}
+
+void del_part(int i)
+{
+ int num = p_info[i].num;
+
+ if (i > 0 && (p_info[i-1].id == FREE_SPACE ||
+ p_info[i-1].id == UNUSABLE)) {
+ /* Merge with previous partition */
+ p_info[i-1].last_sector = p_info[i].last_sector;
+ remove_part(i--);
+ }
+
+ if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE ||
+ p_info[i+1].id == UNUSABLE)) {
+ /* Merge with next partition */
+ p_info[i+1].first_sector = p_info[i].first_sector;
+ remove_part(i);
+ }
+
+ if (i > 0)
+ p_info[i].first_sector = p_info[i-1].last_sector + 1;
+ else
+ p_info[i].first_sector = 0;
+
+ if (i < num_parts - 1)
+ p_info[i].last_sector = p_info[i+1].first_sector - 1;
+ else
+ p_info[i].last_sector = sectors*heads*cylinders - 1;
+
+ p_info[i].offset = 0;
+ p_info[i].flags = 0;
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = PRI_OR_LOG;
+
+ if (IS_LOGICAL(num)) {
+ /* We have a logical partition --> shrink the extended partition
+ * if (1) this is the first logical drive, or (2) this is the
+ * last logical drive; and if there are any other logical drives
+ * then renumber the ones after "num".
+ */
+ if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num)))
+ ext_info.first_sector = p_info[i].last_sector + 1;
+ if (i == num_parts-1 ||
+ (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)))
+ ext_info.last_sector = p_info[i].first_sector - 1;
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].num > num)
+ p_info[i].num--;
+ }
+
+ /* Clean up the rest of the partitions */
+ check_part_info();
+}
+
+int add_part(int num, int id, int flags, int first, int last, int offset)
+{
+ int i, pri = 0, log = 0;
+
+ if (num_parts == MAXIMUM_PARTS ||
+ first < 0 ||
+ first >= cylinders*heads*sectors ||
+ last < 0 ||
+ last >= cylinders*heads*sectors)
+ return -1;
+
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
+ pri++;
+ else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num))
+ log++;
+ if (ext_info.id == EXTENDED && log > 0)
+ pri++;
+
+ if (IS_PRIMARY(num))
+ if (pri >= 4)
+ return -1;
+ else
+ pri++;
+
+ for (i = 0; p_info[i].last_sector < first; i++);
+
+ if (p_info[i].id != FREE_SPACE || last > p_info[i].last_sector)
+ return -1;
+
+ if (id == EXTENDED)
+ if (ext_info.id != FREE_SPACE)
+ return -1;
+ else if (IS_PRIMARY(num)) {
+ ext_info.first_sector = first;
+ ext_info.last_sector = last;
+ ext_info.offset = offset;
+ ext_info.flags = flags;
+ ext_info.id = EXTENDED;
+ ext_info.num = num;
+
+ return 0;
+ } else
+ return -1;
+
+ if (IS_LOGICAL(num)) {
+ if (ext_info.id != EXTENDED) {
+ print_warning("!!!! Internal error creating logical "
+ "drive with no extended partition !!!!");
+ } else {
+ /* We might have a logical partition outside of the extended
+ * partition's range --> we have to extend the extended
+ * partition's range to encompass this new partition, but we
+ * must make sure that there are no primary partitions between
+ * it and the closest logical drive in extended partition.
+ */
+ if (first < ext_info.first_sector) {
+ if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) {
+ print_warning(TWO_EXTENDEDS);
+ return -1;
+ } else {
+ if (first == 0) {
+ ext_info.first_sector = 0;
+ ext_info.offset = first = offset;
+ } else
+ ext_info.first_sector = first;
+ }
+ } else if (last > ext_info.last_sector) {
+ if (i > 0 && IS_PRIMARY(p_info[i-1].num)) {
+ print_warning(TWO_EXTENDEDS);
+ return -1;
+ } else
+ ext_info.last_sector = last;
+ }
+ }
+ }
+
+ if (first != p_info[i].first_sector &&
+ !(IS_LOGICAL(num) && first == offset)) {
+ insert_part(i, PRI_OR_LOG, FREE_SPACE, 0,
+ p_info[i].first_sector, first-1, 0);
+ i++;
+ }
+
+ if (last != p_info[i].last_sector)
+ insert_part(i+1, PRI_OR_LOG, FREE_SPACE, 0,
+ last+1, p_info[i].last_sector, 0);
+
+ p_info[i].first_sector = first;
+ p_info[i].last_sector = last;
+ p_info[i].offset = offset;
+ p_info[i].flags = flags;
+ p_info[i].id = id;
+ p_info[i].num = num;
+
+ check_part_info();
+
+ return 0;
+}
+
+int find_primary(void)
+{
+ int num = 0, cur = 0;
+
+ while (cur < num_parts && IS_PRIMARY(num))
+ if ((p_info[cur].id > 0 && p_info[cur].num == num) ||
+ (ext_info.id == EXTENDED && ext_info.num == num)) {
+ num++;
+ cur = 0;
+ } else
+ cur++;
+
+ if (!IS_PRIMARY(num))
+ return -1;
+ else
+ return num;
+}
+
+int find_logical(int i)
+{
+ int num = -1;
+ int j;
+
+ for (j = i; j < num_parts && num == -1; j++)
+ if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num))
+ num = p_info[j].num;
+
+ if (num == -1) {
+ num = 4;
+ for (j = 0; j < num_parts; j++)
+ if (p_info[j].id > 0 && p_info[j].num == num)
+ num++;
+ }
+
+ return num;
+}
+
+void inc_logical(int i)
+{
+ int j;
+
+ for (j = i; j < num_parts; j++)
+ if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num))
+ p_info[j].num++;
+}
+
+void new_part(int i)
+{
+ char response[LINE_LENGTH], def[LINE_LENGTH];
+ char c;
+ int first = p_info[i].first_sector;
+ int last = p_info[i].last_sector;
+ int offset = 0;
+ int flags = 0;
+ int id = LINUX;
+ int num = -1;
+ int num_sects = last - first + 1;
+ int len, ext, j;
+
+ if (p_info[i].num == PRI_OR_LOG) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Primary or logical [pl]: ");
+ clrtoeol();
+ refresh();
+ while (toupper(c = getch()) != 'P' && toupper(c) != 'L' && c != ESC);
+ if (toupper(c) == 'P')
+ num = find_primary();
+ else if (toupper(c) == 'L')
+ num = find_logical(i);
+ else
+ return;
+ } else if (p_info[i].num == PRIMARY)
+ num = find_primary();
+ else if (p_info[i].num == LOGICAL)
+ num = find_logical(i);
+ else
+ print_warning("!!! Internal error !!!");
+
+ sprintf(def, "%.2f", ceiling(num_sects/20.48)/100);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): ");
+ if ((len = get_string(response, LINE_LENGTH, def)) <= 0 &&
+ len != GS_DEFAULT)
+ return;
+ else if (len > 0) {
+#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads)))
+ for (j = 0;
+ j < len-1 && (isdigit(response[j]) || response[j] == '.');
+ j++);
+ if (toupper(response[j]) == 'K') {
+ num_sects = num_cyls(atof(response)*1024)*sectors*heads;
+ } else if (toupper(response[j]) == 'M') {
+ num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads;
+ } else if (toupper(response[j]) == 'C') {
+ num_sects = round_int(atof(response))*sectors*heads;
+ } else if (toupper(response[j]) == 'S') {
+ num_sects = round_int(atof(response));
+ } else {
+ num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads;
+ }
+ }
+
+ if (num_sects <= 0 ||
+ num_sects > p_info[i].last_sector - p_info[i].first_sector + 1)
+ return;
+
+ if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) {
+ /* Determine where inside free space to put partition.
+ */
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Add partition at beginning or end of free space [be]: ");
+ clrtoeol();
+ refresh();
+ while (toupper(c = getch()) != 'B' && toupper(c) != 'E' && c != ESC);
+ if (toupper(c) == 'B')
+ last = first + num_sects - 1;
+ else if (toupper(c) == 'E')
+ first = last - num_sects + 1;
+ else
+ return;
+ }
+
+ if (IS_LOGICAL(num) && ext_info.id != EXTENDED) {
+ /* We want to add a logical partition, but need to create an
+ * extended partition first.
+ */
+ if ((ext = find_primary()) < 0) {
+ print_warning(NEED_EXT);
+ return;
+ }
+ (void)add_part(ext, EXTENDED, 0, first, last,
+ (first == 0 ? sectors : 0));
+ }
+
+ if (IS_LOGICAL(num))
+ inc_logical(i);
+
+ /* Now we have a complete partition to ourselves */
+ if (first == 0 || IS_LOGICAL(num))
+ offset = sectors;
+
+ (void)add_part(num, id, flags, first, last, offset);
+}
+
+void clear_p_info(void)
+{
+ num_parts = 1;
+ p_info[0].first_sector = 0;
+ p_info[0].last_sector = sectors*heads*cylinders - 1;
+ p_info[0].offset = 0;
+ p_info[0].flags = 0;
+ p_info[0].id = FREE_SPACE;
+ p_info[0].num = PRI_OR_LOG;
+
+ ext_info.first_sector = 0;
+ ext_info.last_sector = 0;
+ ext_info.offset = 0;
+ ext_info.flags = 0;
+ ext_info.id = FREE_SPACE;
+ ext_info.num = PRIMARY;
+}
+
+void fill_p_info(void)
+{
+ int p, i;
+ struct hd_geometry geometry;
+ partition_table buffer;
+ partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY };
+
+ if ((fd = open(disk_device, O_RDWR)) < 0)
+ fatal(BAD_OPEN);
+ read_sector(buffer.c.b, 0);
+
+ if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+ if (!heads)
+ heads = geometry.heads;
+ if (!sectors)
+ sectors = geometry.sectors;
+ if (!cylinders)
+ cylinders = geometry.cylinders;
+ }
+
+ if (!heads || !sectors || !cylinders)
+ fatal(BAD_GEOMETRY);
+
+ clear_p_info();
+
+ if (!zero_table) {
+ for (i = 0; i < 4; i++) {
+ if (buffer.p.part[i].sys_ind > 0 &&
+ add_part(i,
+ buffer.p.part[i].sys_ind,
+ buffer.p.part[i].boot_ind,
+ ((buffer.p.part[i].start_sect <= sectors) ?
+ 0 : buffer.p.part[i].start_sect),
+ buffer.p.part[i].start_sect +
+ buffer.p.part[i].nr_sects - 1,
+ ((buffer.p.part[i].start_sect <= sectors) ?
+ buffer.p.part[i].start_sect : 0))) {
+ fatal(BAD_PRIMARY);
+ }
+ if (buffer.p.part[i].sys_ind == EXTENDED)
+ tmp_ext = ext_info;
+ }
+
+ if (tmp_ext.id == EXTENDED) {
+ ext_info = tmp_ext;
+ logical_sectors[logical] = ext_info.first_sector;
+ read_sector(buffer.c.b, logical_sectors[logical++]);
+ i = 4;
+ do {
+ for (p = 0;
+ p < 4 && (!buffer.p.part[p].sys_ind ||
+ buffer.p.part[p].sys_ind == 5);
+ p++);
+ if (p > 3)
+ fatal(BAD_LOGICAL);
+
+ if (add_part(i++,
+ buffer.p.part[p].sys_ind,
+ buffer.p.part[p].boot_ind,
+ logical_sectors[logical-1],
+ logical_sectors[logical-1] +
+ buffer.p.part[p].start_sect +
+ buffer.p.part[p].nr_sects - 1,
+ buffer.p.part[p].start_sect)) {
+ fatal(BAD_LOGICAL);
+ }
+
+ for (p = 0;
+ p < 4 && buffer.p.part[p].sys_ind != 5;
+ p++);
+ if (p < 4) {
+ logical_sectors[logical] =
+ ext_info.first_sector + buffer.p.part[p].start_sect;
+ read_sector(buffer.c.b, logical_sectors[logical++]);
+ }
+ } while (p < 4 && logical < MAXIMUM_PARTS-4);
+ }
+ }
+}
+
+void fill_part_table(struct partition *p, partition_info *pi)
+{
+ int sects;
+
+ p->boot_ind = pi->flags;
+ p->sys_ind = pi->id;
+ if (IS_LOGICAL(pi->num))
+ p->start_sect = pi->offset;
+ else
+ p->start_sect = pi->first_sector + pi->offset;
+ p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1;
+ sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->first_sector+pi->offset);
+ set_hsc(p->head, p->sector, p->cyl, sects);
+ sects = ((pi->last_sector/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->last_sector);
+ set_hsc(p->end_head, p->end_sector, p->end_cyl, sects);
+}
+
+void fill_primary_table(partition_table *buffer)
+{
+ int i;
+
+ /* Zero out existing table */
+ for (i = 0x1BE; i < SECTOR_SIZE; i++)
+ buffer->c.b[i] = 0;
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_PRIMARY(p_info[i].num))
+ fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i]));
+
+ if (ext_info.id == EXTENDED)
+ fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info);
+
+ buffer->p.flag = PART_TABLE_FLAG;
+}
+
+void fill_logical_table(partition_table *buffer, partition_info *pi)
+{
+ struct partition *p;
+ int i, sects;
+
+ for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++);
+ if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG)
+ for (i = 0; i < SECTOR_SIZE; i++)
+ buffer->c.b[i] = 0;
+
+ /* Zero out existing table */
+ for (i = 0x1BE; i < SECTOR_SIZE; i++)
+ buffer->c.b[i] = 0;
+
+ fill_part_table(&(buffer->p.part[0]), pi);
+
+ for (i = 0;
+ i < num_parts && pi->num != p_info[i].num - 1;
+ i++);
+
+ if (i < num_parts) {
+ p = &(buffer->p.part[1]);
+ pi = &(p_info[i]);
+
+ p->boot_ind = 0;
+ p->sys_ind = 5;
+ p->start_sect = pi->first_sector - ext_info.first_sector;
+ p->nr_sects = pi->last_sector - pi->first_sector + 1;
+ sects = ((pi->first_sector/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->first_sector);
+ set_hsc(p->head, p->sector, p->cyl, sects);
+ sects = ((pi->last_sector/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->last_sector);
+ set_hsc(p->end_head, p->end_sector, p->end_cyl, sects);
+ }
+
+ buffer->p.flag = PART_TABLE_FLAG;
+}
+
+void write_part_table(void)
+{
+ int i, done = FALSE, len;
+ partition_table buffer;
+ char response[LINE_LENGTH];
+
+ print_warning(WRITE_WARN);
+
+ while (!done) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Are you sure you want write the partition table to disk? (yes or no): ");
+
+ len = get_string(response, LINE_LENGTH, NULL);
+
+ clear_warning();
+
+ if (len == GS_ESCAPE)
+ return;
+ else if (len == 2 &&
+ toupper(response[0]) == 'N' &&
+ toupper(response[1]) == 'O') {
+ print_warning(NO_WRITE);
+ return;
+ } else if (len == 3 &&
+ toupper(response[0]) == 'Y' &&
+ toupper(response[1]) == 'E' &&
+ toupper(response[2]) == 'S')
+ done = TRUE;
+ else
+ print_warning(YES_NO);
+ }
+
+ clear_warning();
+ print_warning(WRITING_PART);
+ refresh();
+
+ read_sector(buffer.c.b, 0);
+ fill_primary_table(&buffer);
+ write_sector(buffer.c.b, 0);
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_LOGICAL(p_info[i].num)) {
+ /* Read the extended partition table from disk ??? KEM */
+ read_sector(buffer.c.b, p_info[i].first_sector);
+ fill_logical_table(&buffer, &(p_info[i]));
+ write_sector(buffer.c.b, p_info[i].first_sector);
+ }
+
+ sync();
+ sleep(2);
+ if (!ioctl(fd,BLKRRPART))
+ changed = TRUE;
+ sync();
+ sleep(4);
+
+ clear_warning();
+ if (changed)
+ print_warning(YES_WRITE);
+ else
+ print_warning(RRPART_FAILED);
+}
+
+void fp_printf(FILE *fp, char *format, ...)
+{
+ va_list args;
+ char buf[1024];
+ int y, x;
+
+ va_start(args, format);
+ vsprintf(buf, format, args);
+ va_end(args);
+
+ if (fp == NULL) {
+ /* The following works best if the string to be printed has at
+ most only one newline. */
+ printw("%s", buf);
+ getyx(stdscr, y, x);
+ if (y >= COMMAND_LINE_Y-2) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ erase();
+ move(0, 0);
+ }
+ } else
+ fprintf(fp, "%s", buf);
+}
+
+#define MAX_PER_LINE 16
+void print_file_buffer(FILE *fp, char *buffer)
+{
+ int i,l;
+
+ for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) {
+ if (l == 0)
+ fp_printf(fp, "0x%03X:", i);
+ fp_printf(fp, " %02X", (unsigned char) buffer[i]);
+ if (l == MAX_PER_LINE - 1) {
+ fp_printf(fp, "\n");
+ l = -1;
+ }
+ }
+ if (l > 0)
+ fp_printf(fp, "\n");
+ fp_printf(fp, "\n");
+}
+
+void print_raw_table(void)
+{
+ int i, to_file;
+ partition_table buffer;
+ char fname[LINE_LENGTH];
+ FILE *fp;
+
+ if (print_only) {
+ fp = stdout;
+ to_file = TRUE;
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter filename or press RETURN to display on screen: ");
+
+ if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
+ return;
+
+ if (to_file) {
+ if ((fp = fopen(fname, "w")) == NULL) {
+ char errstr[LINE_LENGTH];
+ sprintf(errstr, PRINT_OPEN_ERR, fname);
+ print_warning(errstr);
+ return;
+ }
+ } else {
+ fp = NULL;
+ erase();
+ move(0, 0);
+ }
+ }
+
+ fp_printf(fp, "Disk Drive: %s\n", disk_device);
+
+ read_sector(buffer.c.b, 0);
+ fill_primary_table(&buffer);
+ print_file_buffer(fp, buffer.c.b);
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_LOGICAL(p_info[i].num)) {
+ read_sector(buffer.c.b, p_info[i].first_sector);
+ fill_logical_table(&buffer, &(p_info[i]));
+ print_file_buffer(fp, buffer.c.b);
+ }
+
+ if (to_file) {
+ if (!print_only)
+ fclose(fp);
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ }
+}
+
+void print_p_info_entry(FILE *fp, partition_info *p)
+{
+ int size;
+ char part_str[21];
+
+ if (p->id == UNUSABLE)
+ fp_printf(fp, " None ");
+ else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG)
+ fp_printf(fp, " Pri/Log");
+ else if (p->id == FREE_SPACE && p->num == PRIMARY)
+ fp_printf(fp, " Primary");
+ else if (p->id == FREE_SPACE && p->num == LOGICAL)
+ fp_printf(fp, " Logical");
+ else
+ fp_printf(fp, "%2d %-7.7s", p->num+1,
+ IS_LOGICAL(p->num) ? "Logical" : "Primary");
+
+ fp_printf(fp, " ");
+
+ fp_printf(fp, "%7d%c", p->first_sector,
+ ((p->first_sector/(sectors*heads)) !=
+ ((float)p->first_sector/(sectors*heads)) ?
+ '*' : ' '));
+
+ fp_printf(fp, " ");
+
+ fp_printf(fp, "%7d%c", p->last_sector,
+ (((p->last_sector+1)/(sectors*heads)) !=
+ ((float)(p->last_sector+1)/(sectors*heads)) ?
+ '*' : ' '));
+
+ fp_printf(fp, " ");
+
+ fp_printf(fp, "%6d%c", p->offset,
+ ((((p->first_sector == 0 || IS_LOGICAL(p->num)) &&
+ (p->offset != sectors)) ||
+ (p->first_sector != 0 && IS_PRIMARY(p->num) &&
+ p->offset != 0)) ?
+ '#' : ' '));
+
+ fp_printf(fp, " ");
+
+ size = p->last_sector - p->first_sector + 1;
+ fp_printf(fp, "%7d%c", size,
+ ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ?
+ '*' : ' '));
+
+ fp_printf(fp, " ");
+
+ if (p->id == UNUSABLE)
+ sprintf(part_str, "%.16s", "Unusable");
+ else if (p->id == FREE_SPACE)
+ sprintf(part_str, "%.16s", "Free Space");
+ else if (partition_type[p->id])
+ sprintf(part_str, "%.16s (%02X)", partition_type[p->id], p->id);
+ else
+ sprintf(part_str, "%.16s (%02X)", "Unknown", p->id);
+ fp_printf(fp, "%-21.21s", part_str);
+
+ fp_printf(fp, " ");
+
+ if (p->flags == ACTIVE_FLAG)
+ fp_printf(fp, "Boot (%02X)", p->flags);
+ else if (p->flags != 0)
+ fp_printf(fp, "Unknown (%02X)", p->flags);
+ else
+ fp_printf(fp, "None (%02X)", p->flags);
+
+ fp_printf(fp, "\n");
+}
+
+void print_p_info(void)
+{
+ char fname[LINE_LENGTH];
+ FILE *fp;
+ int i, to_file, pext = (ext_info.id == EXTENDED);
+
+ if (print_only) {
+ fp = stdout;
+ to_file = TRUE;
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter filename or press RETURN to display on screen: ");
+
+ if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
+ return;
+
+ if (to_file) {
+ if ((fp = fopen(fname, "w")) == NULL) {
+ char errstr[LINE_LENGTH];
+ sprintf(errstr, PRINT_OPEN_ERR, fname);
+ print_warning(errstr);
+ return;
+ }
+ } else {
+ fp = NULL;
+ erase();
+ move(0, 0);
+ }
+ }
+
+ fp_printf(fp, "Partition Table for %s\n", disk_device);
+ fp_printf(fp, "\n");
+ fp_printf(fp, " First Last\n");
+ fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n");
+ fp_printf(fp, "-- ------- -------- -------- ------- -------- --------------------- ---------\n");
+
+ for (i = 0; i < num_parts; i++) {
+ if (pext && (p_info[i].first_sector >= ext_info.first_sector)) {
+ print_p_info_entry(fp,&ext_info);
+ pext = FALSE;
+ }
+ print_p_info_entry(fp, &(p_info[i]));
+ }
+
+ if (to_file) {
+ if (!print_only)
+ fclose(fp);
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ }
+}
+
+void print_part_entry(FILE *fp, int num, partition_info *pi)
+{
+ int first = 0, start = 0, end = 0, size = 0;
+ int ss = 0, sh = 0, sc = 0;
+ int es = 0, eh = 0, ec = 0;
+ int flags = 0, id = 0;
+
+ if (pi != NULL) {
+ flags = pi->flags;
+ id = pi->id;
+
+ if (IS_LOGICAL(num))
+ first = pi->offset;
+ else
+ first = pi->first_sector + pi->offset;
+
+ start = pi->first_sector + pi->offset;
+ end = pi->last_sector;
+ size = end - start + 1;
+ if ((start/(sectors*heads)) > 1023)
+ start = heads*sectors*1024 - 1;
+ if ((end/(sectors*heads)) > 1023)
+ end = heads*sectors*1024 - 1;
+
+ ss = start % sectors + 1;
+ start /= sectors;
+ sh = start % heads;
+ sc = start / heads;
+
+ es = end % sectors + 1;
+ end /= sectors;
+ eh = end % heads;
+ ec = end / heads;
+ }
+
+ fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %7d\n",
+ num+1, flags, sh, ss, sc, id, eh, es, ec, first, size);
+}
+
+
+void print_part_table(void)
+{
+ int i, j, to_file;
+ char fname[LINE_LENGTH];
+ FILE *fp;
+
+ if (print_only) {
+ fp = stdout;
+ to_file = TRUE;
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter filename or press RETURN to display on screen: ");
+
+ if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
+ return;
+
+ if (to_file) {
+ if ((fp = fopen(fname, "w")) == NULL) {
+ char errstr[LINE_LENGTH];
+ sprintf(errstr, PRINT_OPEN_ERR, fname);
+ print_warning(errstr);
+ return;
+ }
+ } else {
+ fp = NULL;
+ erase();
+ move(0, 0);
+ }
+ }
+
+ fp_printf(fp, "Partition Table for %s\n", disk_device);
+ fp_printf(fp, "\n");
+ fp_printf(fp, " ---Starting--- ----Ending---- Start Number\n");
+ fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n");
+ fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- ------- -------\n");
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0;
+ j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i);
+ j++);
+ if (j < num_parts) {
+ print_part_entry(fp, i, &(p_info[j]));
+ } else if (ext_info.id == EXTENDED && ext_info.num == i) {
+ print_part_entry(fp, i, &ext_info);
+ } else {
+ print_part_entry(fp, i, NULL);
+ }
+ }
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_LOGICAL(p_info[i].num))
+ print_part_entry(fp, p_info[i].num, &(p_info[i]));
+
+ if (to_file) {
+ if (!print_only)
+ fclose(fp);
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ }
+}
+
+void print_tables(void)
+{
+ int done = FALSE;
+
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Print format [rst]: ");
+ clrtoeol();
+ refresh();
+
+ while (!done)
+ switch (toupper(getch())) {
+ case 'R':
+ print_raw_table();
+ done = TRUE;
+ break;
+ case 'S':
+ print_p_info();
+ done = TRUE;
+ break;
+ case 'T':
+ print_part_table();
+ done = TRUE;
+ break;
+ case ESC:
+ done = TRUE;
+ break;
+ }
+}
+
+#define END_OF_HELP "EOHS!"
+#define NEW_HELP_SCREEN "SNHS!"
+void display_help()
+{
+ char *help_text[] = {
+ "Help Screen for cfdisk " VERSION,
+ "",
+ "This is cfdisk, a curses based disk partitioning programs, which",
+ "allows you to create, delete and modify partitions on your hard",
+ "disk drive.",
+ "",
+ "Copyright (C) 1994 Kevin E. Martin",
+ "",
+ "Command Meaning",
+ "------- -------",
+ " b Toggle bootable flag of the current partition",
+ " d Delete the current partition",
+ " g Change cylinders, heads, sectors-per-track parameters",
+ " WARNING: This option should only be used by people who",
+ " know what they are doing.",
+ " h Print this screen",
+ " m Maximize disk usage of the current partition",
+ " Note: This may make the partition incompatible with",
+ " DOS, OS/2, ...",
+ " n Create new partition from free space",
+ " p Print partition table to the screen or to a file",
+ " There are several different formats for the partition",
+ " that you can choose from:",
+ " r - Raw data (exactly what would be written to disk)",
+ " s - Table ordered by sectors",
+ " t - Table in raw format",
+ " q Quit program without writing partition table",
+ " t Change the filesystem type",
+ " u Change units of the partition size display",
+ " Rotates through Mb, sectors and cylinders",
+ " W Write partition table to disk (must enter upper case W)",
+ " Since this might destroy data on the disk, you must",
+ " either confirm or deny the write by entering `yes' or",
+ " `no'",
+ "Up Arrow Move cursor to the previous partition",
+ "Down Arrow Move cursor to the next partition",
+ "CTRL-L Redraws the screen",
+ " ? Print this screen",
+ "",
+ "Note: All of the commands can be entered with either upper or lower",
+ "case letters (except for Writes).",
+ END_OF_HELP
+ };
+
+ int cur_line = 0;
+ FILE *fp = NULL;
+
+ erase();
+ move(0, 0);
+ while (strcmp(help_text[cur_line], END_OF_HELP))
+ if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ erase();
+ move(0, 0);
+ cur_line++;
+ } else
+ fp_printf(fp, "%s\n", help_text[cur_line++]);
+
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+}
+
+int change_geometry(void)
+{
+ int ret_val = FALSE;
+ int done = FALSE;
+ char def[LINE_LENGTH];
+ char response[LINE_LENGTH];
+ int tmp_val;
+
+ while (!done) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Change disk geometry information [chs]: ");
+ clrtoeol();
+ refresh();
+
+ clear_warning();
+
+ switch (toupper(getch())) {
+ case 'C':
+ sprintf(def, "%d", cylinders);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter the number of cylinders: ");
+ if (get_string(response, LINE_LENGTH, def) > 0) {
+ tmp_val = atoi(response);
+ if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) {
+ cylinders = tmp_val;
+ ret_val = TRUE;
+ } else
+ print_warning(BAD_CYLINDERS);
+ }
+ break;
+ case 'H':
+ sprintf(def, "%d", heads);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter the number of heads: ");
+ if (get_string(response, LINE_LENGTH, def) > 0) {
+ tmp_val = atoi(response);
+ if (tmp_val > 0 && tmp_val <= MAX_HEADS) {
+ heads = tmp_val;
+ ret_val = TRUE;
+ } else
+ print_warning(BAD_HEADS);
+ }
+ break;
+ case 'S':
+ sprintf(def, "%d", sectors);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter the number of sectors per track: ");
+ if (get_string(response, LINE_LENGTH, def) > 0) {
+ tmp_val = atoi(response);
+ if (tmp_val > 0 && tmp_val <= MAX_SECTORS) {
+ sectors = tmp_val;
+ ret_val = TRUE;
+ } else
+ print_warning(BAD_SECTORS);
+ }
+ break;
+ case ESC:
+ case CR:
+ done = TRUE;
+ break;
+ default:
+ putchar(BELL);
+ break;
+ }
+ }
+
+ if (ret_val) {
+ if (p_info[num_parts-1].last_sector > heads*sectors*cylinders-1) {
+ while (p_info[num_parts-1].first_sector > heads*sectors*cylinders-1) {
+ if (p_info[num_parts-1].id == FREE_SPACE ||
+ p_info[num_parts-1].id == UNUSABLE)
+ remove_part(num_parts-1);
+ else
+ del_part(num_parts-1);
+ }
+
+ p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1;
+
+ if (ext_info.last_sector > heads*sectors*cylinders-1)
+ ext_info.last_sector = heads*sectors*cylinders - 1;
+ } else if (p_info[num_parts-1].last_sector < heads*sectors*cylinders-1) {
+ if (p_info[num_parts-1].id == FREE_SPACE ||
+ p_info[num_parts-1].id == UNUSABLE) {
+ p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1;
+ } else {
+ insert_part(num_parts, PRI_OR_LOG, FREE_SPACE, 0,
+ p_info[num_parts-1].last_sector+1,
+ heads*sectors*cylinders-1, 0);
+ }
+ }
+
+ /* Make sure the partitions are correct */
+ check_part_info();
+ }
+
+ return ret_val;
+}
+
+void change_id(int i)
+{
+ char id[LINE_LENGTH], def[LINE_LENGTH];
+ int num_types = 0;
+ int num_across, num_down;
+ int len, new_id = LINUX;
+ int y_start, y_end;
+ int j, pos;
+
+ for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++)
+ if (partition_type[j])
+ num_types++;
+
+ num_across = COLS/COL_ID_WIDTH;
+ num_down = (((float)num_types)/num_across + 1);
+ y_start = COMMAND_LINE_Y - 1 - num_down;
+ if (y_start > DISK_TABLE_START+cur_part+4)
+ y_start = DISK_TABLE_START+cur_part+4;
+ y_end = y_start + num_down - 1;
+
+ for (j = y_start - 1; j <= y_end + 1; j++) {
+ move(j, 0);
+ clrtoeol();
+ }
+
+ for (pos = 0, j = 1; j < NUM_PART_TYPES; j++)
+ if (partition_type[j]) {
+ move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1);
+ printw("%02X %-16.16s", j, partition_type[j]);
+ pos++;
+ }
+
+ sprintf(def, "%02X", new_id);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: ");
+ if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT)
+ return;
+
+ if (len != GS_DEFAULT) {
+ if (!isxdigit(id[0]))
+ return;
+ new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10);
+ if (len == 2)
+ if (isxdigit(id[1]))
+ new_id = new_id*16 +
+ (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10);
+ else
+ return;
+ }
+
+ if (new_id == 0)
+ print_warning(ID_EMPTY);
+ else if (new_id == EXTENDED)
+ print_warning(ID_EXT);
+ else
+ p_info[i].id = new_id;
+}
+
+void draw_partition(int i)
+{
+ int size, j;
+ int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN;
+
+ if (!arrow_cursor) {
+ move(y, 0);
+ for (j = 0; j < COLS; j++)
+ addch(' ');
+ }
+
+ if (p_info[i].id > 0) {
+ mvprintw(y, NAME_START,
+ "%s%d", disk_device, p_info[i].num+1);
+ if (p_info[i].flags) {
+ if (p_info[i].flags == ACTIVE_FLAG)
+ mvaddstr(y, FLAGS_START, "Boot");
+ else
+ mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags);
+ if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) {
+ if (p_info[i].offset != sectors)
+ addstr(", NC");
+ } else {
+ if (p_info[i].offset != 0)
+ addstr(", NC");
+ }
+ } else {
+ if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) {
+ if (p_info[i].offset != sectors)
+ mvaddstr(y, FLAGS_START, "NC");
+ } else {
+ if (p_info[i].offset != 0)
+ mvaddstr(y, FLAGS_START, "NC");
+ }
+ }
+ }
+ mvaddstr(y, PTYPE_START,
+ (p_info[i].id == UNUSABLE ? "" :
+ (IS_LOGICAL(p_info[i].num) ? "Logical" :
+ (p_info[i].num >= 0 ? "Primary" :
+ (p_info[i].num == PRI_OR_LOG ? "Pri/Log" :
+ (p_info[i].num == PRIMARY ? "Primary" : "Logical"))))));
+ if (p_info[i].id == UNUSABLE)
+ mvaddstr(y, FSTYPE_START, "Unusable");
+ else if (p_info[i].id == FREE_SPACE)
+ mvaddstr(y, FSTYPE_START, "Free Space");
+ else if (partition_type[p_info[i].id])
+ mvaddstr(y, FSTYPE_START, partition_type[p_info[i].id]);
+ else
+ mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id);
+
+ size = p_info[i].last_sector - p_info[i].first_sector + 1;
+ if (display_units == SECTORS)
+ mvprintw(y, SIZE_START, "%9d", size);
+ else if (display_units == CYLINDERS)
+ mvprintw(y, SIZE_START, "%9d", size/(sectors*heads));
+ else
+ mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100);
+ if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) ||
+ ((p_info[i].first_sector/(sectors*heads)) !=
+ ceiling(p_info[i].first_sector/(sectors*heads))))
+ mvprintw(y, COLUMNS-1, "*");
+}
+
+void init_const(void)
+{
+ if (!defined) {
+ NAME_START = (((float)NAME_START)/COLUMNS)*COLS;
+ FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS;
+ PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS;
+ FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS;
+ SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS;
+ COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS;
+
+ COMMAND_LINE_Y = LINES - 4;
+ WARNING_START = LINES - 2;
+
+ if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0)
+ NUM_ON_SCREEN = 1;
+
+ COLUMNS = COLS;
+ defined = TRUE;
+ }
+}
+
+void draw_screen(void)
+{
+ int i;
+ char *line;
+
+ line = (char *)malloc((COLS+1)*sizeof(char));
+
+ if (warning_last_time) {
+ for (i = 0; i < COLS; i++) {
+ move(WARNING_START, i);
+ line[i] = inch();
+ }
+ line[COLS] = 0;
+ }
+
+ erase();
+
+ if (warning_last_time)
+ mvaddstr(WARNING_START, 0, line);
+
+
+ sprintf(line, "cfdisk %s", VERSION);
+ mvaddstr(HEADER_START, (COLS-strlen(line))/2, line);
+ sprintf(line, "Disk Drive: %s", disk_device);
+ mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line);
+ sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d",
+ heads, sectors, cylinders);
+ mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line);
+
+ mvaddstr(DISK_TABLE_START, NAME_START, "Name");
+ mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags");
+ mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type");
+ mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type");
+ if (display_units == SECTORS)
+ mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors");
+ else if (display_units == CYLINDERS)
+ mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders");
+ else
+ mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)");
+
+ move(DISK_TABLE_START+1, 1);
+ for (i = 1; i < COLS-1; i++)
+ addch('-');
+
+ if (NUM_ON_SCREEN >= num_parts)
+ for (i = 0; i < num_parts; i++)
+ draw_partition(i);
+ else
+ for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN;
+ i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN &&
+ i < num_parts;
+ i++)
+ draw_partition(i);
+
+ free(line);
+}
+
+int draw_cursor(int move)
+{
+ if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts))
+ return -1;
+
+ if (arrow_cursor)
+ mvaddstr(DISK_TABLE_START + cur_part + 2
+ - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " ");
+ else
+ draw_partition(cur_part);
+
+ cur_part += move;
+
+ if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN !=
+ (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN)
+ draw_screen();
+
+ if (arrow_cursor)
+ mvaddstr(DISK_TABLE_START + cur_part + 2
+ - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->");
+ else {
+ standout();
+ draw_partition(cur_part);
+ standend();
+ }
+
+ return 0;
+}
+
+void die(int dummy)
+{
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+ mvcur(0, COLS-1, LINES-1, 0);
+ nl();
+ endwin();
+ fdexit(0);
+}
+
+void do_curses_fdisk(void)
+{
+ int done = FALSE;
+ char command;
+
+ initscr();
+ old_SIGINT = signal(SIGINT, die);
+ old_SIGTERM = signal(SIGTERM, die);
+#ifdef DEBUG
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+#endif
+
+ cbreak();
+ noecho();
+ nonl();
+
+ init_const();
+
+ fill_p_info();
+
+ draw_screen();
+
+ while (!done) {
+ (void)draw_cursor(0);
+
+ if (p_info[cur_part].id == FREE_SPACE)
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hnpquW?]: ");
+ else if (p_info[cur_part].id > 0)
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [bdhmpqtuW?]: ");
+ else
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hpquW?]: ");
+
+ clrtoeol();
+ refresh();
+
+ clear_warning();
+
+ switch (command = getch()) {
+ case 'B':
+ case 'b':
+ if (p_info[cur_part].id > 0)
+ p_info[cur_part].flags ^= 0x80;
+ else
+ print_warning(NO_FLAGS);
+ break;
+ case 'D':
+ case 'd':
+ if (p_info[cur_part].id > 0) {
+ del_part(cur_part);
+ if (cur_part >= num_parts)
+ cur_part = num_parts - 1;
+ draw_screen();
+ } else
+ print_warning(DEL_EMPTY);
+ break;
+ case 'G':
+ case 'g':
+ if (change_geometry())
+ draw_screen();
+ break;
+ case 'M':
+ case 'm':
+ if (p_info[cur_part].id > 0) {
+ if (p_info[cur_part].first_sector == 0 ||
+ IS_LOGICAL(p_info[cur_part].num)) {
+ if (p_info[cur_part].offset == sectors)
+ p_info[cur_part].offset = 1;
+ else
+ p_info[cur_part].offset = sectors;
+ draw_screen();
+ } else if (p_info[cur_part].offset != 0)
+ p_info[cur_part].offset = 0;
+ else
+ print_warning(MAX_UNMAXABLE);
+ } else
+ print_warning(MAX_UNMAXABLE);
+ break;
+ case 'N':
+ case 'n':
+ if (p_info[cur_part].id == FREE_SPACE) {
+ new_part(cur_part);
+ draw_screen();
+ } else if (p_info[cur_part].id == UNUSABLE)
+ print_warning(ADD_UNUSABLE);
+ else
+ print_warning(ADD_EXISTS);
+ break;
+ case 'P':
+ case 'p':
+ print_tables();
+ draw_screen();
+ break;
+ case 'Q':
+ case 'q':
+ done = TRUE;
+ break;
+ case 'T':
+ case 't':
+ if (p_info[cur_part].id > 0) {
+ change_id(cur_part);
+ draw_screen();
+ } else
+ print_warning(TYPE_EMPTY);
+ break;
+ case 'U':
+ case 'u':
+ if (display_units == MEGABYTES)
+ display_units = SECTORS;
+ else if (display_units == SECTORS)
+ display_units = CYLINDERS;
+ else if (display_units == CYLINDERS)
+ display_units = MEGABYTES;
+ draw_screen();
+ break;
+ case 'W':
+ write_part_table();
+ break;
+ case 'H':
+ case 'h':
+ case '?':
+ display_help();
+ draw_screen();
+ break;
+ case ESC:
+ if ((command = getch()) == '[') {
+ command = getch();
+ switch (command) {
+ case 'A' : /* Up arrow */
+ if (!draw_cursor(-1))
+ command = 0;
+ else
+ print_warning(NO_MORE_PARTS);
+ break;
+ case 'B' : /* Down arrow */
+ if (!draw_cursor(1))
+ command = 0;
+ else
+ print_warning(NO_MORE_PARTS);
+ break;
+ case 'C' : /* Right arrow */
+ case 'D' : /* Left arrow */
+ }
+ }
+ if (command)
+ putchar(BELL); /* CTRL-G */
+ break;
+ case REDRAWKEY:
+ clear();
+ draw_screen();
+ break;
+ default:
+ print_warning(BAD_COMMAND);
+ putchar(BELL); /* CTRL-G */
+ }
+ }
+
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+ mvcur(0, COLS-1, LINES-1, 0);
+ nl();
+ endwin();
+ fdexit(0);
+}
+
+void copyright(void)
+{
+ fprintf(stderr, "Copyright (C) 1994 Kevin E. Martin\n");
+}
+
+void usage(char *prog_name)
+{
+ fprintf(stderr,
+ "%s: [-avz] [-c # cylinders] [-h # heads] [-s # sectors/track]\n",
+ prog_name);
+ fprintf(stderr,
+ "[ -P opt ] device\n");
+ copyright();
+}
+
+void main(int argc, char **argv)
+{
+ char c;
+ int i, len;
+
+ while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF)
+ switch (c) {
+ case 'a':
+ arrow_cursor = TRUE;
+ break;
+ case 'c':
+ cylinders = atoi(optarg);
+ if (cylinders <= 0 || cylinders > MAX_CYLINDERS) {
+ fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS);
+ exit(1);
+ }
+ break;
+ case 'h':
+ heads = atoi(optarg);
+ if (heads <= 0 || heads > MAX_HEADS) {
+ fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS);
+ exit(1);
+ }
+ break;
+ case 's':
+ sectors = atoi(optarg);
+ if (sectors <= 0 || sectors > MAX_SECTORS) {
+ fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS);
+ exit(1);
+ }
+ break;
+ case 'v':
+ fprintf(stderr, "cfdisk %s\n", VERSION);
+ copyright();
+ exit(0);
+ case 'z':
+ zero_table = TRUE;
+ break;
+ case 'P':
+ len = strlen(optarg);
+ for (i = 0; i < len; i++) {
+ switch (optarg[i]) {
+ case 'r':
+ print_only |= PRINT_RAW_TABLE;
+ break;
+ case 's':
+ print_only |= PRINT_SECTOR_TABLE;
+ break;
+ case 't':
+ print_only |= PRINT_PARTITION_TABLE;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ break;
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+
+ if (argc-optind == 1)
+ disk_device = argv[optind];
+ else if (argc-optind != 0) {
+ usage(argv[0]);
+ exit(1);
+ } else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0)
+ disk_device = ALTERNATE_DEVICE;
+ else close(fd);
+
+ if (print_only) {
+ fill_p_info();
+ if (print_only & PRINT_RAW_TABLE)
+ print_raw_table();
+ if (print_only & PRINT_SECTOR_TABLE)
+ print_p_info();
+ if (print_only & PRINT_PARTITION_TABLE)
+ print_part_table();
+ } else
+ do_curses_fdisk();
+}
--- /dev/null
+/****************************************************************************
+ *
+ * CFDISK
+ *
+ * cfdisk is a curses based disk drive partitioning program that can
+ * create partitions for a wide variety of operating systems including
+ * Linux, MS-DOS and OS/2.
+ *
+ * cfdisk was inspired by the fdisk program, by A. V. Le Blanc
+ * (LeBlanc@mcc.ac.uk).
+ *
+ * Copyright (C) 1994 Kevin E. Martin (martin@cs.unc.edu)
+ *
+ * cfdisk is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * cfdisk is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with cfdisk; if not, write to the Free Software Foundation,
+ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Created: Fri Jan 28 22:46:58 1994, martin@cs.unc.edu
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <curses.h>
+#include <signal.h>
+#include <math.h>
+#include <sys/ioctl.h>
+#include <linux/genhd.h>
+#include <linux/hdreg.h>
+#include <linux/fs.h> /* for BLKRRPART */
+
+typedef long ext2_loff_t;
+extern ext2_loff_t ext2_llseek(unsigned int fd,
+ ext2_loff_t offset,
+ unsigned int origin);
+
+#define VERSION "0.8 BETA (>2GB)"
+
+#define DEFAULT_DEVICE "/dev/hda"
+#define ALTERNATE_DEVICE "/dev/sda"
+
+#define LINE_LENGTH 80
+#define MAXIMUM_PARTS 60
+
+#define SECTOR_SIZE 512
+
+#define MAX_CYLINDERS 65535
+#define MAX_HEADS 255
+#define MAX_SECTORS 63
+
+#define ACTIVE_FLAG 0x80
+#define PART_TABLE_FLAG 0xAA55
+
+#define UNUSABLE -1
+#define FREE_SPACE 0x00
+#define EXTENDED 0x05
+#define LINUX_MINIX 0x81
+#define LINUX_SWAP 0x82
+#define LINUX 0x83
+
+#define ADD_EXISTS "This partition is already in use"
+#define ADD_UNUSABLE "This partition is unusable"
+#define DEL_EMPTY "Cannot delete an empty partition"
+#define ID_EMPTY "Cannot change FS Type to empty"
+#define ID_EXT "Cannot change FS Type to extended"
+#define NEED_EXT "No room to create the extended partition"
+#define NO_FLAGS "Cannot make this partition bootable"
+#define NO_MORE_PARTS "No more partitions"
+#define PRINT_OPEN_ERR "Cannot open file '%s'"
+#define TWO_EXTENDEDS "Cannot create logical drive here -- would create two extended partitions"
+#define TYPE_EMPTY "Cannot change the type of an empty partition"
+#define BAD_COMMAND "Illegal command"
+#define MAX_UNMAXABLE "Cannot maximize this partition"
+#define BAD_OPEN "Cannot open disk drive"
+#define BAD_SEEK "Cannot seek on disk drive"
+#define BAD_READ "Cannot read disk drive"
+#define BAD_WRITE "Cannot write disk drive"
+#define BAD_GEOMETRY "Cannot read disk drive geometry"
+#define BAD_PRIMARY "Bad primary partition"
+#define BAD_LOGICAL "Bad logical partition"
+#define BAD_CYLINDERS "Illegal cylinders value"
+#define BAD_HEADS "Illegal heads value"
+#define BAD_SECTORS "Illegal sectors value"
+#define WRITE_WARN "Warning!! This may destroy data on your disk!"
+#define YES_NO "Please enter `yes' or `no'"
+#define WRITING_PART "Writing partition table to disk..."
+#define YES_WRITE "Wrote partition table to disk"
+#define NO_WRITE "Did not write partition table to disk"
+#define RRPART_FAILED "Wrote partition table, but re-read table failed. Reboot to update table."
+
+#define PRI_OR_LOG -1
+#define PRIMARY -2
+#define LOGICAL -3
+
+#define COL_ID_WIDTH 20
+
+#define CR '\015'
+#define ESC '\033'
+#define DEL '\177'
+#define BELL '\007'
+/* '\014' == ^L */
+#define REDRAWKEY '\014'
+
+/* Display units */
+#define MEGABYTES 1
+#define SECTORS 2
+#define CYLINDERS 3
+
+#define GS_DEFAULT -1
+#define GS_ESCAPE -2
+
+#define PRINT_RAW_TABLE 1
+#define PRINT_SECTOR_TABLE 2
+#define PRINT_PARTITION_TABLE 4
+
+#define IS_PRIMARY(p) ((p) >= 0 && (p) < 4)
+#define IS_LOGICAL(p) ((p) > 3)
+
+#define round_int(d) ((double)((int)(d+0.5)))
+#define ceiling(d) ((double)(((d) != (int)(d)) ? (int)(d+1.0) : (int)(d)))
+
+#define set_hsc(h,s,c,sector) \
+{ \
+ s = sector % sectors + 1; \
+ sector /= sectors; \
+ h = sector % heads; \
+ sector /= heads; \
+ c = sector & 0xFF; \
+ s |= (sector >> 2) & 0xC0;\
+}
+
+#define ALIGNMENT 2
+typedef union {
+ struct {
+ unsigned char align[ALIGNMENT];
+ unsigned char b[SECTOR_SIZE];
+ } c;
+ struct {
+ unsigned char align[ALIGNMENT];
+ unsigned char buffer[0x1BE];
+ struct partition part[4];
+ unsigned short flag;
+ } p;
+} partition_table;
+
+typedef struct {
+ int first_sector; /* first sector in partition */
+ int last_sector; /* last sector in partition */
+ int offset; /* offset from first sector to start of data */
+ int flags; /* active == 0x80 */
+ int id; /* filesystem type */
+ int num; /* number of partition -- primary vs. logical */
+} partition_info;
+
+char *disk_device = DEFAULT_DEVICE;
+int fd;
+int heads = 0;
+int sectors = 0;
+int cylinders = 0;
+int changed = FALSE;
+int opened = FALSE;
+
+partition_info p_info[MAXIMUM_PARTS];
+partition_info ext_info;
+int num_parts = 0;
+
+int logical = 0;
+int logical_sectors[MAXIMUM_PARTS];
+
+__sighandler_t old_SIGINT, old_SIGTERM;
+
+int arrow_cursor = FALSE;
+int display_units = MEGABYTES;
+int zero_table = FALSE;
+int print_only = 0;
+
+/* Curses screen information */
+int cur_part = 0;
+int warning_last_time = FALSE;
+int defined = FALSE;
+int COLUMNS = 80;
+int NUM_ON_SCREEN = 1;
+
+/* Y coordinates */
+int HEADER_START = 0;
+int DISK_TABLE_START = 5;
+int WARNING_START = 23;
+int COMMAND_LINE_Y = 21;
+
+/* X coordinates */
+int NAME_START = 4;
+int FLAGS_START = 16;
+int PTYPE_START = 30;
+int FSTYPE_START = 45;
+int SIZE_START = 70;
+int COMMAND_LINE_X = 5;
+
+#define NUM_PART_TYPES 256
+char *partition_type[NUM_PART_TYPES] = {
+ [LINUX_MINIX] = "Linux/MINIX",
+ [LINUX_SWAP] = "Linux Swap",
+ [LINUX] = "Linux",
+ [FREE_SPACE] = "Free Space",
+ [EXTENDED] = "Extended",
+ [0x01] = "DOS 12-bit FAT",
+ [0x04] = "DOS 16-bit < 32Mb",
+ [0x06] = "DOS 16-bit >=32Mb",
+ [0x07] = "OS/2 HPFS",
+ [0x0A] = "OS/2 Boot Manager",
+ [0xA5] = "BSD/386",
+
+/* The rest of these are taken from A. V. Le Blanc's (LeBlanc@mcc.ac.uk)
+ * fdisk program. I do not know where they came from, but I include
+ * them for completeness.
+ */
+
+ [0x02] = "XENIX root",
+ [0x03] = "XENIX usr",
+ [0x08] = "AIX",
+ [0x09] = "AIX bootable",
+ [0x40] = "Venix 80286",
+ [0x51] = "Novell?",
+ [0x52] = "Microport",
+ [0x63] = "GNU HURD",
+ [0x64] = "Novell",
+ [0x75] = "PC/IX",
+ [0x80] = "Old MINIX",
+ [0x93] = "Amoeba",
+ [0x94] = "Amoeba BBT",
+ [0xB7] = "BSDI fs",
+ [0xB8] = "BSDI swap",
+ [0xC7] = "Syrinx",
+ [0xDB] = "CP/M",
+ [0xE1] = "DOS access",
+ [0xE3] = "DOS R/O",
+ [0xF2] = "DOS secondary",
+ [0xFF] = "BBT"
+};
+
+void fdexit(int ret)
+{
+ if (opened)
+ close(fd);
+
+ if (changed) {
+ fprintf(stderr, "Disk has been changed.\n");
+ fprintf(stderr, "Reboot the system to ensure the partition "
+ "table is correctly updated.\n");
+
+ fprintf( stderr, "\nWARNING: If you have created or modified any\n"
+ "DOS 6.x partitions, please see the cfdisk manual\n"
+ "page for additional information.\n" );
+ }
+
+
+ exit(ret);
+}
+
+int get_string(char *str, int len, char *def)
+{
+ char c;
+ int i = 0;
+ int x, y;
+ int use_def = FALSE;
+
+ getyx(stdscr, y, x);
+ clrtoeol();
+
+ str[i] = 0;
+
+ if (def != NULL) {
+ mvaddstr(y, x, def);
+ move(y, x);
+ use_def = TRUE;
+ }
+
+ refresh();
+ while ((c = getch()) != '\n' && c != CR) {
+ switch (c) {
+ case ESC:
+ move(y, x);
+ clrtoeol();
+ refresh();
+ return GS_ESCAPE;
+ case DEL:
+ case '\b':
+ if (i > 0) {
+ str[--i] = 0;
+ mvaddch(y, x+i, ' ');
+ move(y, x+i);
+ } else if (use_def) {
+ clrtoeol();
+ use_def = FALSE;
+ } else
+ putchar(BELL);
+ break;
+ default:
+ if (i < len && isprint(c)) {
+ mvaddch(y, x+i, c);
+ if (use_def) {
+ clrtoeol();
+ use_def = FALSE;
+ }
+ str[i++] = c;
+ str[i] = 0;
+ } else
+ putchar(BELL);
+ }
+ refresh();
+ }
+
+ if (use_def)
+ return GS_DEFAULT;
+ else
+ return i;
+}
+
+void clear_warning(void)
+{
+ int i;
+
+ if (!warning_last_time)
+ return;
+
+ move(WARNING_START,0);
+ for (i = 0; i < COLS; i++)
+ addch(' ');
+
+ warning_last_time = FALSE;
+}
+
+void print_warning(char *s)
+{
+ mvaddstr(WARNING_START, (COLS-strlen(s))/2, s);
+ putchar(BELL); /* CTRL-G */
+
+ warning_last_time = TRUE;
+}
+
+void fatal(char *s)
+{
+ char str[LINE_LENGTH];
+
+ sprintf(str, "FATAL ERROR: %s", s);
+ mvaddstr(WARNING_START, (COLS-strlen(str))/2, str);
+ sprintf(str, "Press any key to exit fdisk");
+ mvaddstr(WARNING_START+1, (COLS-strlen(str))/2, str);
+ putchar(BELL); /* CTRL-G */
+
+ refresh();
+
+ (void)getch();
+
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+ mvcur(0, COLS-1, LINES-1, 0);
+ nl();
+ endwin();
+ fdexit(1);
+}
+
+void read_sector(char *buffer, int sect_num)
+{
+ if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0)
+ fatal(BAD_SEEK);
+ if (read(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE)
+ fatal(BAD_READ);
+}
+
+void write_sector(char *buffer, int sect_num)
+{
+ if (ext2_llseek(fd, sect_num*SECTOR_SIZE, SEEK_SET) < 0)
+ fatal(BAD_SEEK);
+ if (write(fd, buffer, SECTOR_SIZE) != SECTOR_SIZE)
+ fatal(BAD_WRITE);
+}
+
+void check_part_info(void)
+{
+ int i, pri = 0, log = 0;
+
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
+ pri++;
+ else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num))
+ log++;
+ if (ext_info.id == EXTENDED)
+ if (log > 0)
+ pri++;
+ else {
+ ext_info.first_sector = 0;
+ ext_info.last_sector = 0;
+ ext_info.offset = 0;
+ ext_info.flags = 0;
+ ext_info.id = FREE_SPACE;
+ ext_info.num = PRIMARY;
+ }
+
+ if (pri >= 4)
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].id == FREE_SPACE || p_info[i].id == UNUSABLE)
+ if (ext_info.id == EXTENDED)
+ if (p_info[i].first_sector >= ext_info.first_sector &&
+ p_info[i].last_sector <= ext_info.last_sector) {
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = LOGICAL;
+ } else if (i > 0 &&
+ p_info[i-1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i-1].last_sector <=
+ ext_info.last_sector) {
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = LOGICAL;
+ } else if (i < num_parts-1 &&
+ p_info[i+1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i+1].last_sector <=
+ ext_info.last_sector) {
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = LOGICAL;
+ } else
+ p_info[i].id = UNUSABLE;
+ else /* if (ext_info.id != EXTENDED) */
+ p_info[i].id = UNUSABLE;
+ else /* if (p_info[i].id > 0) */
+ while (0); /* Leave these alone */
+ else /* if (pri < 4) */
+ for (i = 0; i < num_parts; i++) {
+ if (p_info[i].id == UNUSABLE)
+ p_info[i].id = FREE_SPACE;
+ if (p_info[i].id == FREE_SPACE)
+ if (ext_info.id == EXTENDED)
+ if (p_info[i].first_sector >= ext_info.first_sector &&
+ p_info[i].last_sector <= ext_info.last_sector)
+ p_info[i].num = LOGICAL;
+ else if (i > 0 &&
+ p_info[i-1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i-1].last_sector <=
+ ext_info.last_sector)
+ p_info[i].num = PRI_OR_LOG;
+ else if (i < num_parts-1 &&
+ p_info[i+1].first_sector >=
+ ext_info.first_sector &&
+ p_info[i+1].last_sector <=
+ ext_info.last_sector)
+ p_info[i].num = PRI_OR_LOG;
+ else
+ p_info[i].num = PRIMARY;
+ else /* if (ext_info.id != EXTENDED) */
+ p_info[i].num = PRI_OR_LOG;
+ else /* if (p_info[i].id > 0) */
+ while (0); /* Leave these alone */
+ }
+}
+
+void remove_part(int i)
+{
+ int p;
+
+ for (p = i; p < num_parts; p++)
+ p_info[p] = p_info[p+1];
+
+ num_parts--;
+}
+
+void insert_part(int i, int num, int id, int flags, int first, int last,
+ int offset)
+{
+ int p;
+
+ for (p = num_parts; p > i; p--)
+ p_info[p] = p_info[p-1];
+
+ p_info[i].first_sector = first;
+ p_info[i].last_sector = last;
+ p_info[i].offset = offset;
+ p_info[i].flags = flags;
+ p_info[i].id = id;
+ p_info[i].num = num;
+
+ num_parts++;
+}
+
+void del_part(int i)
+{
+ int num = p_info[i].num;
+
+ if (i > 0 && (p_info[i-1].id == FREE_SPACE ||
+ p_info[i-1].id == UNUSABLE)) {
+ /* Merge with previous partition */
+ p_info[i-1].last_sector = p_info[i].last_sector;
+ remove_part(i--);
+ }
+
+ if (i < num_parts - 1 && (p_info[i+1].id == FREE_SPACE ||
+ p_info[i+1].id == UNUSABLE)) {
+ /* Merge with next partition */
+ p_info[i+1].first_sector = p_info[i].first_sector;
+ remove_part(i);
+ }
+
+ if (i > 0)
+ p_info[i].first_sector = p_info[i-1].last_sector + 1;
+ else
+ p_info[i].first_sector = 0;
+
+ if (i < num_parts - 1)
+ p_info[i].last_sector = p_info[i+1].first_sector - 1;
+ else
+ p_info[i].last_sector = sectors*heads*cylinders - 1;
+
+ p_info[i].offset = 0;
+ p_info[i].flags = 0;
+ p_info[i].id = FREE_SPACE;
+ p_info[i].num = PRI_OR_LOG;
+
+ if (IS_LOGICAL(num)) {
+ /* We have a logical partition --> shrink the extended partition
+ * if (1) this is the first logical drive, or (2) this is the
+ * last logical drive; and if there are any other logical drives
+ * then renumber the ones after "num".
+ */
+ if (i == 0 || (i > 0 && IS_PRIMARY(p_info[i-1].num)))
+ ext_info.first_sector = p_info[i].last_sector + 1;
+ if (i == num_parts-1 ||
+ (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)))
+ ext_info.last_sector = p_info[i].first_sector - 1;
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].num > num)
+ p_info[i].num--;
+ }
+
+ /* Clean up the rest of the partitions */
+ check_part_info();
+}
+
+int add_part(int num, int id, int flags, int first, int last, int offset)
+{
+ int i, pri = 0, log = 0;
+
+ if (num_parts == MAXIMUM_PARTS ||
+ first < 0 ||
+ first >= cylinders*heads*sectors ||
+ last < 0 ||
+ last >= cylinders*heads*sectors)
+ return -1;
+
+ for (i = 0; i < num_parts; i++)
+ if (p_info[i].id > 0 && IS_PRIMARY(p_info[i].num))
+ pri++;
+ else if (p_info[i].id > 0 && IS_LOGICAL(p_info[i].num))
+ log++;
+ if (ext_info.id == EXTENDED && log > 0)
+ pri++;
+
+ if (IS_PRIMARY(num))
+ if (pri >= 4)
+ return -1;
+ else
+ pri++;
+
+ for (i = 0; p_info[i].last_sector < first; i++);
+
+ if (p_info[i].id != FREE_SPACE || last > p_info[i].last_sector)
+ return -1;
+
+ if (id == EXTENDED)
+ if (ext_info.id != FREE_SPACE)
+ return -1;
+ else if (IS_PRIMARY(num)) {
+ ext_info.first_sector = first;
+ ext_info.last_sector = last;
+ ext_info.offset = offset;
+ ext_info.flags = flags;
+ ext_info.id = EXTENDED;
+ ext_info.num = num;
+
+ return 0;
+ } else
+ return -1;
+
+ if (IS_LOGICAL(num)) {
+ if (ext_info.id != EXTENDED) {
+ print_warning("!!!! Internal error creating logical "
+ "drive with no extended partition !!!!");
+ } else {
+ /* We might have a logical partition outside of the extended
+ * partition's range --> we have to extend the extended
+ * partition's range to encompass this new partition, but we
+ * must make sure that there are no primary partitions between
+ * it and the closest logical drive in extended partition.
+ */
+ if (first < ext_info.first_sector) {
+ if (i < num_parts-1 && IS_PRIMARY(p_info[i+1].num)) {
+ print_warning(TWO_EXTENDEDS);
+ return -1;
+ } else {
+ if (first == 0) {
+ ext_info.first_sector = 0;
+ ext_info.offset = first = offset;
+ } else
+ ext_info.first_sector = first;
+ }
+ } else if (last > ext_info.last_sector) {
+ if (i > 0 && IS_PRIMARY(p_info[i-1].num)) {
+ print_warning(TWO_EXTENDEDS);
+ return -1;
+ } else
+ ext_info.last_sector = last;
+ }
+ }
+ }
+
+ if (first != p_info[i].first_sector &&
+ !(IS_LOGICAL(num) && first == offset)) {
+ insert_part(i, PRI_OR_LOG, FREE_SPACE, 0,
+ p_info[i].first_sector, first-1, 0);
+ i++;
+ }
+
+ if (last != p_info[i].last_sector)
+ insert_part(i+1, PRI_OR_LOG, FREE_SPACE, 0,
+ last+1, p_info[i].last_sector, 0);
+
+ p_info[i].first_sector = first;
+ p_info[i].last_sector = last;
+ p_info[i].offset = offset;
+ p_info[i].flags = flags;
+ p_info[i].id = id;
+ p_info[i].num = num;
+
+ check_part_info();
+
+ return 0;
+}
+
+int find_primary(void)
+{
+ int num = 0, cur = 0;
+
+ while (cur < num_parts && IS_PRIMARY(num))
+ if ((p_info[cur].id > 0 && p_info[cur].num == num) ||
+ (ext_info.id == EXTENDED && ext_info.num == num)) {
+ num++;
+ cur = 0;
+ } else
+ cur++;
+
+ if (!IS_PRIMARY(num))
+ return -1;
+ else
+ return num;
+}
+
+int find_logical(int i)
+{
+ int num = -1;
+ int j;
+
+ for (j = i; j < num_parts && num == -1; j++)
+ if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num))
+ num = p_info[j].num;
+
+ if (num == -1) {
+ num = 4;
+ for (j = 0; j < num_parts; j++)
+ if (p_info[j].id > 0 && p_info[j].num == num)
+ num++;
+ }
+
+ return num;
+}
+
+void inc_logical(int i)
+{
+ int j;
+
+ for (j = i; j < num_parts; j++)
+ if (p_info[j].id > 0 && IS_LOGICAL(p_info[j].num))
+ p_info[j].num++;
+}
+
+void new_part(int i)
+{
+ char response[LINE_LENGTH], def[LINE_LENGTH];
+ char c;
+ int first = p_info[i].first_sector;
+ int last = p_info[i].last_sector;
+ int offset = 0;
+ int flags = 0;
+ int id = LINUX;
+ int num = -1;
+ int num_sects = last - first + 1;
+ int len, ext, j;
+
+ if (p_info[i].num == PRI_OR_LOG) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Primary or logical [pl]: ");
+ clrtoeol();
+ refresh();
+ while (toupper(c = getch()) != 'P' && toupper(c) != 'L' && c != ESC);
+ if (toupper(c) == 'P')
+ num = find_primary();
+ else if (toupper(c) == 'L')
+ num = find_logical(i);
+ else
+ return;
+ } else if (p_info[i].num == PRIMARY)
+ num = find_primary();
+ else if (p_info[i].num == LOGICAL)
+ num = find_logical(i);
+ else
+ print_warning("!!! Internal error !!!");
+
+ sprintf(def, "%.2f", ceiling(num_sects/20.48)/100);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Size (in MB): ");
+ if ((len = get_string(response, LINE_LENGTH, def)) <= 0 &&
+ len != GS_DEFAULT)
+ return;
+ else if (len > 0) {
+#define num_cyls(bytes) (round_int(bytes/SECTOR_SIZE/(sectors*heads)))
+ for (j = 0;
+ j < len-1 && (isdigit(response[j]) || response[j] == '.');
+ j++);
+ if (toupper(response[j]) == 'K') {
+ num_sects = num_cyls(atof(response)*1024)*sectors*heads;
+ } else if (toupper(response[j]) == 'M') {
+ num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads;
+ } else if (toupper(response[j]) == 'C') {
+ num_sects = round_int(atof(response))*sectors*heads;
+ } else if (toupper(response[j]) == 'S') {
+ num_sects = round_int(atof(response));
+ } else {
+ num_sects = num_cyls(atof(response)*1024*1024)*sectors*heads;
+ }
+ }
+
+ if (num_sects <= 0 ||
+ num_sects > p_info[i].last_sector - p_info[i].first_sector + 1)
+ return;
+
+ if (num_sects < p_info[i].last_sector - p_info[i].first_sector + 1) {
+ /* Determine where inside free space to put partition.
+ */
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Add partition at beginning or end of free space [be]: ");
+ clrtoeol();
+ refresh();
+ while (toupper(c = getch()) != 'B' && toupper(c) != 'E' && c != ESC);
+ if (toupper(c) == 'B')
+ last = first + num_sects - 1;
+ else if (toupper(c) == 'E')
+ first = last - num_sects + 1;
+ else
+ return;
+ }
+
+ if (IS_LOGICAL(num) && ext_info.id != EXTENDED) {
+ /* We want to add a logical partition, but need to create an
+ * extended partition first.
+ */
+ if ((ext = find_primary()) < 0) {
+ print_warning(NEED_EXT);
+ return;
+ }
+ (void)add_part(ext, EXTENDED, 0, first, last,
+ (first == 0 ? sectors : 0));
+ }
+
+ if (IS_LOGICAL(num))
+ inc_logical(i);
+
+ /* Now we have a complete partition to ourselves */
+ if (first == 0 || IS_LOGICAL(num))
+ offset = sectors;
+
+ (void)add_part(num, id, flags, first, last, offset);
+}
+
+void clear_p_info(void)
+{
+ num_parts = 1;
+ p_info[0].first_sector = 0;
+ p_info[0].last_sector = sectors*heads*cylinders - 1;
+ p_info[0].offset = 0;
+ p_info[0].flags = 0;
+ p_info[0].id = FREE_SPACE;
+ p_info[0].num = PRI_OR_LOG;
+
+ ext_info.first_sector = 0;
+ ext_info.last_sector = 0;
+ ext_info.offset = 0;
+ ext_info.flags = 0;
+ ext_info.id = FREE_SPACE;
+ ext_info.num = PRIMARY;
+}
+
+void fill_p_info(void)
+{
+ int p, i;
+ struct hd_geometry geometry;
+ partition_table buffer;
+ partition_info tmp_ext = { 0, 0, 0, 0, FREE_SPACE, PRIMARY };
+
+ if ((fd = open(disk_device, O_RDWR)) < 0)
+ fatal(BAD_OPEN);
+ read_sector(buffer.c.b, 0);
+
+ if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+ if (!heads)
+ heads = geometry.heads;
+ if (!sectors)
+ sectors = geometry.sectors;
+ if (!cylinders)
+ cylinders = geometry.cylinders;
+ }
+
+ if (!heads || !sectors || !cylinders)
+ fatal(BAD_GEOMETRY);
+
+ clear_p_info();
+
+ if (!zero_table) {
+ for (i = 0; i < 4; i++) {
+ if (buffer.p.part[i].sys_ind > 0 &&
+ add_part(i,
+ buffer.p.part[i].sys_ind,
+ buffer.p.part[i].boot_ind,
+ ((buffer.p.part[i].start_sect <= sectors) ?
+ 0 : buffer.p.part[i].start_sect),
+ buffer.p.part[i].start_sect +
+ buffer.p.part[i].nr_sects - 1,
+ ((buffer.p.part[i].start_sect <= sectors) ?
+ buffer.p.part[i].start_sect : 0))) {
+ fatal(BAD_PRIMARY);
+ }
+ if (buffer.p.part[i].sys_ind == EXTENDED)
+ tmp_ext = ext_info;
+ }
+
+ if (tmp_ext.id == EXTENDED) {
+ ext_info = tmp_ext;
+ logical_sectors[logical] = ext_info.first_sector;
+ read_sector(buffer.c.b, logical_sectors[logical++]);
+ i = 4;
+ do {
+ for (p = 0;
+ p < 4 && (!buffer.p.part[p].sys_ind ||
+ buffer.p.part[p].sys_ind == 5);
+ p++);
+ if (p > 3)
+ fatal(BAD_LOGICAL);
+
+ if (add_part(i++,
+ buffer.p.part[p].sys_ind,
+ buffer.p.part[p].boot_ind,
+ logical_sectors[logical-1],
+ logical_sectors[logical-1] +
+ buffer.p.part[p].start_sect +
+ buffer.p.part[p].nr_sects - 1,
+ buffer.p.part[p].start_sect)) {
+ fatal(BAD_LOGICAL);
+ }
+
+ for (p = 0;
+ p < 4 && buffer.p.part[p].sys_ind != 5;
+ p++);
+ if (p < 4) {
+ logical_sectors[logical] =
+ ext_info.first_sector + buffer.p.part[p].start_sect;
+ read_sector(buffer.c.b, logical_sectors[logical++]);
+ }
+ } while (p < 4 && logical < MAXIMUM_PARTS-4);
+ }
+ }
+}
+
+void fill_part_table(struct partition *p, partition_info *pi)
+{
+ int sects;
+
+ p->boot_ind = pi->flags;
+ p->sys_ind = pi->id;
+ if (IS_LOGICAL(pi->num))
+ p->start_sect = pi->offset;
+ else
+ p->start_sect = pi->first_sector + pi->offset;
+ p->nr_sects = pi->last_sector - (pi->first_sector+pi->offset) + 1;
+ sects = (((pi->first_sector+pi->offset)/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->first_sector+pi->offset);
+ set_hsc(p->head, p->sector, p->cyl, sects);
+ sects = ((pi->last_sector/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->last_sector);
+ set_hsc(p->end_head, p->end_sector, p->end_cyl, sects);
+}
+
+void fill_primary_table(partition_table *buffer)
+{
+ int i;
+
+ /* Zero out existing table */
+ for (i = 0x1BE; i < SECTOR_SIZE; i++)
+ buffer->c.b[i] = 0;
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_PRIMARY(p_info[i].num))
+ fill_part_table(&(buffer->p.part[p_info[i].num]), &(p_info[i]));
+
+ if (ext_info.id == EXTENDED)
+ fill_part_table(&(buffer->p.part[ext_info.num]), &ext_info);
+
+ buffer->p.flag = PART_TABLE_FLAG;
+}
+
+void fill_logical_table(partition_table *buffer, partition_info *pi)
+{
+ struct partition *p;
+ int i, sects;
+
+ for (i = 0; i < logical && pi->first_sector != logical_sectors[i]; i++);
+ if (i == logical || buffer->p.flag != (unsigned short)PART_TABLE_FLAG)
+ for (i = 0; i < SECTOR_SIZE; i++)
+ buffer->c.b[i] = 0;
+
+ /* Zero out existing table */
+ for (i = 0x1BE; i < SECTOR_SIZE; i++)
+ buffer->c.b[i] = 0;
+
+ fill_part_table(&(buffer->p.part[0]), pi);
+
+ for (i = 0;
+ i < num_parts && pi->num != p_info[i].num - 1;
+ i++);
+
+ if (i < num_parts) {
+ p = &(buffer->p.part[1]);
+ pi = &(p_info[i]);
+
+ p->boot_ind = 0;
+ p->sys_ind = 5;
+ p->start_sect = pi->first_sector - ext_info.first_sector;
+ p->nr_sects = pi->last_sector - pi->first_sector + 1;
+ sects = ((pi->first_sector/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->first_sector);
+ set_hsc(p->head, p->sector, p->cyl, sects);
+ sects = ((pi->last_sector/(sectors*heads) > 1023) ?
+ heads*sectors*1024 - 1 : pi->last_sector);
+ set_hsc(p->end_head, p->end_sector, p->end_cyl, sects);
+ }
+
+ buffer->p.flag = PART_TABLE_FLAG;
+}
+
+void write_part_table(void)
+{
+ int i, done = FALSE, len;
+ partition_table buffer;
+ char response[LINE_LENGTH];
+
+ print_warning(WRITE_WARN);
+
+ while (!done) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Are you sure you want write the partition table to disk? (yes or no): ");
+
+ len = get_string(response, LINE_LENGTH, NULL);
+
+ clear_warning();
+
+ if (len == GS_ESCAPE)
+ return;
+ else if (len == 2 &&
+ toupper(response[0]) == 'N' &&
+ toupper(response[1]) == 'O') {
+ print_warning(NO_WRITE);
+ return;
+ } else if (len == 3 &&
+ toupper(response[0]) == 'Y' &&
+ toupper(response[1]) == 'E' &&
+ toupper(response[2]) == 'S')
+ done = TRUE;
+ else
+ print_warning(YES_NO);
+ }
+
+ clear_warning();
+ print_warning(WRITING_PART);
+ refresh();
+
+ read_sector(buffer.c.b, 0);
+ fill_primary_table(&buffer);
+ write_sector(buffer.c.b, 0);
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_LOGICAL(p_info[i].num)) {
+ /* Read the extended partition table from disk ??? KEM */
+ read_sector(buffer.c.b, p_info[i].first_sector);
+ fill_logical_table(&buffer, &(p_info[i]));
+ write_sector(buffer.c.b, p_info[i].first_sector);
+ }
+
+ sync();
+ sleep(2);
+ if (!ioctl(fd,BLKRRPART))
+ changed = TRUE;
+ sync();
+ sleep(4);
+
+ clear_warning();
+ if (changed)
+ print_warning(YES_WRITE);
+ else
+ print_warning(RRPART_FAILED);
+}
+
+void fp_printf(FILE *fp, char *format, ...)
+{
+ va_list args;
+ char buf[1024];
+ int y, x;
+
+ va_start(args, format);
+ vsprintf(buf, format, args);
+ va_end(args);
+
+ if (fp == NULL) {
+ /* The following works best if the string to be printed has at
+ most only one newline. */
+ printw("%s", buf);
+ getyx(stdscr, y, x);
+ if (y >= COMMAND_LINE_Y-2) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ erase();
+ move(0, 0);
+ }
+ } else
+ fprintf(fp, "%s", buf);
+}
+
+#define MAX_PER_LINE 16
+void print_file_buffer(FILE *fp, char *buffer)
+{
+ int i,l;
+
+ for (i = 0, l = 0; i < SECTOR_SIZE; i++, l++) {
+ if (l == 0)
+ fp_printf(fp, "0x%03X:", i);
+ fp_printf(fp, " %02X", (unsigned char) buffer[i]);
+ if (l == MAX_PER_LINE - 1) {
+ fp_printf(fp, "\n");
+ l = -1;
+ }
+ }
+ if (l > 0)
+ fp_printf(fp, "\n");
+ fp_printf(fp, "\n");
+}
+
+void print_raw_table(void)
+{
+ int i, to_file;
+ partition_table buffer;
+ char fname[LINE_LENGTH];
+ FILE *fp;
+
+ if (print_only) {
+ fp = stdout;
+ to_file = TRUE;
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter filename or press RETURN to display on screen: ");
+
+ if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
+ return;
+
+ if (to_file) {
+ if ((fp = fopen(fname, "w")) == NULL) {
+ char errstr[LINE_LENGTH];
+ sprintf(errstr, PRINT_OPEN_ERR, fname);
+ print_warning(errstr);
+ return;
+ }
+ } else {
+ fp = NULL;
+ erase();
+ move(0, 0);
+ }
+ }
+
+ fp_printf(fp, "Disk Drive: %s\n", disk_device);
+
+ read_sector(buffer.c.b, 0);
+ fill_primary_table(&buffer);
+ print_file_buffer(fp, buffer.c.b);
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_LOGICAL(p_info[i].num)) {
+ read_sector(buffer.c.b, p_info[i].first_sector);
+ fill_logical_table(&buffer, &(p_info[i]));
+ print_file_buffer(fp, buffer.c.b);
+ }
+
+ if (to_file) {
+ if (!print_only)
+ fclose(fp);
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ }
+}
+
+void print_p_info_entry(FILE *fp, partition_info *p)
+{
+ int size;
+ char part_str[21];
+
+ if (p->id == UNUSABLE)
+ fp_printf(fp, " None ");
+ else if (p->id == FREE_SPACE && p->num == PRI_OR_LOG)
+ fp_printf(fp, " Pri/Log");
+ else if (p->id == FREE_SPACE && p->num == PRIMARY)
+ fp_printf(fp, " Primary");
+ else if (p->id == FREE_SPACE && p->num == LOGICAL)
+ fp_printf(fp, " Logical");
+ else
+ fp_printf(fp, "%2d %-7.7s", p->num+1,
+ IS_LOGICAL(p->num) ? "Logical" : "Primary");
+
+ fp_printf(fp, " ");
+
+ fp_printf(fp, "%7d%c", p->first_sector,
+ ((p->first_sector/(sectors*heads)) !=
+ ((float)p->first_sector/(sectors*heads)) ?
+ '*' : ' '));
+
+ fp_printf(fp, " ");
+
+ fp_printf(fp, "%7d%c", p->last_sector,
+ (((p->last_sector+1)/(sectors*heads)) !=
+ ((float)(p->last_sector+1)/(sectors*heads)) ?
+ '*' : ' '));
+
+ fp_printf(fp, " ");
+
+ fp_printf(fp, "%6d%c", p->offset,
+ ((((p->first_sector == 0 || IS_LOGICAL(p->num)) &&
+ (p->offset != sectors)) ||
+ (p->first_sector != 0 && IS_PRIMARY(p->num) &&
+ p->offset != 0)) ?
+ '#' : ' '));
+
+ fp_printf(fp, " ");
+
+ size = p->last_sector - p->first_sector + 1;
+ fp_printf(fp, "%7d%c", size,
+ ((size/(sectors*heads)) != ((float)size/(sectors*heads)) ?
+ '*' : ' '));
+
+ fp_printf(fp, " ");
+
+ if (p->id == UNUSABLE)
+ sprintf(part_str, "%.16s", "Unusable");
+ else if (p->id == FREE_SPACE)
+ sprintf(part_str, "%.16s", "Free Space");
+ else if (partition_type[p->id])
+ sprintf(part_str, "%.16s (%02X)", partition_type[p->id], p->id);
+ else
+ sprintf(part_str, "%.16s (%02X)", "Unknown", p->id);
+ fp_printf(fp, "%-21.21s", part_str);
+
+ fp_printf(fp, " ");
+
+ if (p->flags == ACTIVE_FLAG)
+ fp_printf(fp, "Boot (%02X)", p->flags);
+ else if (p->flags != 0)
+ fp_printf(fp, "Unknown (%02X)", p->flags);
+ else
+ fp_printf(fp, "None (%02X)", p->flags);
+
+ fp_printf(fp, "\n");
+}
+
+void print_p_info(void)
+{
+ char fname[LINE_LENGTH];
+ FILE *fp;
+ int i, to_file, pext = (ext_info.id == EXTENDED);
+
+ if (print_only) {
+ fp = stdout;
+ to_file = TRUE;
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter filename or press RETURN to display on screen: ");
+
+ if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
+ return;
+
+ if (to_file) {
+ if ((fp = fopen(fname, "w")) == NULL) {
+ char errstr[LINE_LENGTH];
+ sprintf(errstr, PRINT_OPEN_ERR, fname);
+ print_warning(errstr);
+ return;
+ }
+ } else {
+ fp = NULL;
+ erase();
+ move(0, 0);
+ }
+ }
+
+ fp_printf(fp, "Partition Table for %s\n", disk_device);
+ fp_printf(fp, "\n");
+ fp_printf(fp, " First Last\n");
+ fp_printf(fp, " # Type Sector Sector Offset Length Filesystem Type (ID) Flags\n");
+ fp_printf(fp, "-- ------- -------- -------- ------- -------- --------------------- ---------\n");
+
+ for (i = 0; i < num_parts; i++) {
+ if (pext && (p_info[i].first_sector >= ext_info.first_sector)) {
+ print_p_info_entry(fp,&ext_info);
+ pext = FALSE;
+ }
+ print_p_info_entry(fp, &(p_info[i]));
+ }
+
+ if (to_file) {
+ if (!print_only)
+ fclose(fp);
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ }
+}
+
+void print_part_entry(FILE *fp, int num, partition_info *pi)
+{
+ int first = 0, start = 0, end = 0, size = 0;
+ int ss = 0, sh = 0, sc = 0;
+ int es = 0, eh = 0, ec = 0;
+ int flags = 0, id = 0;
+
+ if (pi != NULL) {
+ flags = pi->flags;
+ id = pi->id;
+
+ if (IS_LOGICAL(num))
+ first = pi->offset;
+ else
+ first = pi->first_sector + pi->offset;
+
+ start = pi->first_sector + pi->offset;
+ end = pi->last_sector;
+ size = end - start + 1;
+ if ((start/(sectors*heads)) > 1023)
+ start = heads*sectors*1024 - 1;
+ if ((end/(sectors*heads)) > 1023)
+ end = heads*sectors*1024 - 1;
+
+ ss = start % sectors + 1;
+ start /= sectors;
+ sh = start % heads;
+ sc = start / heads;
+
+ es = end % sectors + 1;
+ end /= sectors;
+ eh = end % heads;
+ ec = end / heads;
+ }
+
+ fp_printf(fp, "%2d 0x%02X %4d %4d %4d 0x%02X %4d %4d %4d %7d %7d\n",
+ num+1, flags, sh, ss, sc, id, eh, es, ec, first, size);
+}
+
+
+void print_part_table(void)
+{
+ int i, j, to_file;
+ char fname[LINE_LENGTH];
+ FILE *fp;
+
+ if (print_only) {
+ fp = stdout;
+ to_file = TRUE;
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter filename or press RETURN to display on screen: ");
+
+ if ((to_file = get_string(fname, LINE_LENGTH, NULL)) < 0)
+ return;
+
+ if (to_file) {
+ if ((fp = fopen(fname, "w")) == NULL) {
+ char errstr[LINE_LENGTH];
+ sprintf(errstr, PRINT_OPEN_ERR, fname);
+ print_warning(errstr);
+ return;
+ }
+ } else {
+ fp = NULL;
+ erase();
+ move(0, 0);
+ }
+ }
+
+ fp_printf(fp, "Partition Table for %s\n", disk_device);
+ fp_printf(fp, "\n");
+ fp_printf(fp, " ---Starting--- ----Ending---- Start Number\n");
+ fp_printf(fp, " # Flags Head Sect Cyl ID Head Sect Cyl Sector Sectors\n");
+ fp_printf(fp, "-- ----- ---- ---- ---- ---- ---- ---- ---- ------- -------\n");
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0;
+ j < num_parts && (p_info[j].id <= 0 || p_info[j].num != i);
+ j++);
+ if (j < num_parts) {
+ print_part_entry(fp, i, &(p_info[j]));
+ } else if (ext_info.id == EXTENDED && ext_info.num == i) {
+ print_part_entry(fp, i, &ext_info);
+ } else {
+ print_part_entry(fp, i, NULL);
+ }
+ }
+
+ for (i = 0; i < num_parts; i++)
+ if (IS_LOGICAL(p_info[i].num))
+ print_part_entry(fp, p_info[i].num, &(p_info[i]));
+
+ if (to_file) {
+ if (!print_only)
+ fclose(fp);
+ } else {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ }
+}
+
+void print_tables(void)
+{
+ int done = FALSE;
+
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Print format [rst]: ");
+ clrtoeol();
+ refresh();
+
+ while (!done)
+ switch (toupper(getch())) {
+ case 'R':
+ print_raw_table();
+ done = TRUE;
+ break;
+ case 'S':
+ print_p_info();
+ done = TRUE;
+ break;
+ case 'T':
+ print_part_table();
+ done = TRUE;
+ break;
+ case ESC:
+ done = TRUE;
+ break;
+ }
+}
+
+#define END_OF_HELP "EOHS!"
+#define NEW_HELP_SCREEN "SNHS!"
+void display_help()
+{
+ char *help_text[] = {
+ "Help Screen for cfdisk " VERSION,
+ "",
+ "This is cfdisk, a curses based disk partitioning programs, which",
+ "allows you to create, delete and modify partitions on your hard",
+ "disk drive.",
+ "",
+ "Copyright (C) 1994 Kevin E. Martin",
+ "",
+ "Command Meaning",
+ "------- -------",
+ " b Toggle bootable flag of the current partition",
+ " d Delete the current partition",
+ " g Change cylinders, heads, sectors-per-track parameters",
+ " WARNING: This option should only be used by people who",
+ " know what they are doing.",
+ " h Print this screen",
+ " m Maximize disk usage of the current partition",
+ " Note: This may make the partition incompatible with",
+ " DOS, OS/2, ...",
+ " n Create new partition from free space",
+ " p Print partition table to the screen or to a file",
+ " There are several different formats for the partition",
+ " that you can choose from:",
+ " r - Raw data (exactly what would be written to disk)",
+ " s - Table ordered by sectors",
+ " t - Table in raw format",
+ " q Quit program without writing partition table",
+ " t Change the filesystem type",
+ " u Change units of the partition size display",
+ " Rotates through Mb, sectors and cylinders",
+ " W Write partition table to disk (must enter upper case W)",
+ " Since this might destroy data on the disk, you must",
+ " either confirm or deny the write by entering `yes' or",
+ " `no'",
+ "Up Arrow Move cursor to the previous partition",
+ "Down Arrow Move cursor to the next partition",
+ "CTRL-L Redraws the screen",
+ " ? Print this screen",
+ "",
+ "Note: All of the commands can be entered with either upper or lower",
+ "case letters (except for Writes).",
+ END_OF_HELP
+ };
+
+ int cur_line = 0;
+ FILE *fp = NULL;
+
+ erase();
+ move(0, 0);
+ while (strcmp(help_text[cur_line], END_OF_HELP))
+ if (!strcmp(help_text[cur_line], NEW_HELP_SCREEN)) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+ erase();
+ move(0, 0);
+ cur_line++;
+ } else
+ fp_printf(fp, "%s\n", help_text[cur_line++]);
+
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Press any key to continue...");
+ clrtoeol();
+ refresh();
+ (void)getch();
+}
+
+int change_geometry(void)
+{
+ int ret_val = FALSE;
+ int done = FALSE;
+ char def[LINE_LENGTH];
+ char response[LINE_LENGTH];
+ int tmp_val;
+
+ while (!done) {
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Change disk geometry information [chs]: ");
+ clrtoeol();
+ refresh();
+
+ clear_warning();
+
+ switch (toupper(getch())) {
+ case 'C':
+ sprintf(def, "%d", cylinders);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter the number of cylinders: ");
+ if (get_string(response, LINE_LENGTH, def) > 0) {
+ tmp_val = atoi(response);
+ if (tmp_val > 0 && tmp_val <= MAX_CYLINDERS) {
+ cylinders = tmp_val;
+ ret_val = TRUE;
+ } else
+ print_warning(BAD_CYLINDERS);
+ }
+ break;
+ case 'H':
+ sprintf(def, "%d", heads);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter the number of heads: ");
+ if (get_string(response, LINE_LENGTH, def) > 0) {
+ tmp_val = atoi(response);
+ if (tmp_val > 0 && tmp_val <= MAX_HEADS) {
+ heads = tmp_val;
+ ret_val = TRUE;
+ } else
+ print_warning(BAD_HEADS);
+ }
+ break;
+ case 'S':
+ sprintf(def, "%d", sectors);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X,
+ "Enter the number of sectors per track: ");
+ if (get_string(response, LINE_LENGTH, def) > 0) {
+ tmp_val = atoi(response);
+ if (tmp_val > 0 && tmp_val <= MAX_SECTORS) {
+ sectors = tmp_val;
+ ret_val = TRUE;
+ } else
+ print_warning(BAD_SECTORS);
+ }
+ break;
+ case ESC:
+ case CR:
+ done = TRUE;
+ break;
+ default:
+ putchar(BELL);
+ break;
+ }
+ }
+
+ if (ret_val) {
+ if (p_info[num_parts-1].last_sector > heads*sectors*cylinders-1) {
+ while (p_info[num_parts-1].first_sector > heads*sectors*cylinders-1) {
+ if (p_info[num_parts-1].id == FREE_SPACE ||
+ p_info[num_parts-1].id == UNUSABLE)
+ remove_part(num_parts-1);
+ else
+ del_part(num_parts-1);
+ }
+
+ p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1;
+
+ if (ext_info.last_sector > heads*sectors*cylinders-1)
+ ext_info.last_sector = heads*sectors*cylinders - 1;
+ } else if (p_info[num_parts-1].last_sector < heads*sectors*cylinders-1) {
+ if (p_info[num_parts-1].id == FREE_SPACE ||
+ p_info[num_parts-1].id == UNUSABLE) {
+ p_info[num_parts-1].last_sector = heads*sectors*cylinders - 1;
+ } else {
+ insert_part(num_parts, PRI_OR_LOG, FREE_SPACE, 0,
+ p_info[num_parts-1].last_sector+1,
+ heads*sectors*cylinders-1, 0);
+ }
+ }
+
+ /* Make sure the partitions are correct */
+ check_part_info();
+ }
+
+ return ret_val;
+}
+
+void change_id(int i)
+{
+ char id[LINE_LENGTH], def[LINE_LENGTH];
+ int num_types = 0;
+ int num_across, num_down;
+ int len, new_id = LINUX;
+ int y_start, y_end;
+ int j, pos;
+
+ for (num_types = 0, j = 1; j < NUM_PART_TYPES; j++)
+ if (partition_type[j])
+ num_types++;
+
+ num_across = COLS/COL_ID_WIDTH;
+ num_down = (((float)num_types)/num_across + 1);
+ y_start = COMMAND_LINE_Y - 1 - num_down;
+ if (y_start > DISK_TABLE_START+cur_part+4)
+ y_start = DISK_TABLE_START+cur_part+4;
+ y_end = y_start + num_down - 1;
+
+ for (j = y_start - 1; j <= y_end + 1; j++) {
+ move(j, 0);
+ clrtoeol();
+ }
+
+ for (pos = 0, j = 1; j < NUM_PART_TYPES; j++)
+ if (partition_type[j]) {
+ move(y_start + pos % num_down, (pos/num_down)*COL_ID_WIDTH + 1);
+ printw("%02X %-16.16s", j, partition_type[j]);
+ pos++;
+ }
+
+ sprintf(def, "%02X", new_id);
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Enter filesystem type: ");
+ if ((len = get_string(id, 2, def)) <= 0 && len != GS_DEFAULT)
+ return;
+
+ if (len != GS_DEFAULT) {
+ if (!isxdigit(id[0]))
+ return;
+ new_id = (isdigit(id[0]) ? id[0] - '0' : tolower(id[0]) - 'a' + 10);
+ if (len == 2)
+ if (isxdigit(id[1]))
+ new_id = new_id*16 +
+ (isdigit(id[1]) ? id[1] - '0' : tolower(id[1]) - 'a' + 10);
+ else
+ return;
+ }
+
+ if (new_id == 0)
+ print_warning(ID_EMPTY);
+ else if (new_id == EXTENDED)
+ print_warning(ID_EXT);
+ else
+ p_info[i].id = new_id;
+}
+
+void draw_partition(int i)
+{
+ int size, j;
+ int y = i + DISK_TABLE_START + 2 - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN;
+
+ if (!arrow_cursor) {
+ move(y, 0);
+ for (j = 0; j < COLS; j++)
+ addch(' ');
+ }
+
+ if (p_info[i].id > 0) {
+ mvprintw(y, NAME_START,
+ "%s%d", disk_device, p_info[i].num+1);
+ if (p_info[i].flags) {
+ if (p_info[i].flags == ACTIVE_FLAG)
+ mvaddstr(y, FLAGS_START, "Boot");
+ else
+ mvprintw(y, FLAGS_START, "Unk(%02X)", p_info[i].flags);
+ if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) {
+ if (p_info[i].offset != sectors)
+ addstr(", NC");
+ } else {
+ if (p_info[i].offset != 0)
+ addstr(", NC");
+ }
+ } else {
+ if (p_info[i].first_sector == 0 || IS_LOGICAL(p_info[i].num)) {
+ if (p_info[i].offset != sectors)
+ mvaddstr(y, FLAGS_START, "NC");
+ } else {
+ if (p_info[i].offset != 0)
+ mvaddstr(y, FLAGS_START, "NC");
+ }
+ }
+ }
+ mvaddstr(y, PTYPE_START,
+ (p_info[i].id == UNUSABLE ? "" :
+ (IS_LOGICAL(p_info[i].num) ? "Logical" :
+ (p_info[i].num >= 0 ? "Primary" :
+ (p_info[i].num == PRI_OR_LOG ? "Pri/Log" :
+ (p_info[i].num == PRIMARY ? "Primary" : "Logical"))))));
+ if (p_info[i].id == UNUSABLE)
+ mvaddstr(y, FSTYPE_START, "Unusable");
+ else if (p_info[i].id == FREE_SPACE)
+ mvaddstr(y, FSTYPE_START, "Free Space");
+ else if (partition_type[p_info[i].id])
+ mvaddstr(y, FSTYPE_START, partition_type[p_info[i].id]);
+ else
+ mvprintw(y, FSTYPE_START, "Unknown (%02X)", p_info[i].id);
+
+ size = p_info[i].last_sector - p_info[i].first_sector + 1;
+ if (display_units == SECTORS)
+ mvprintw(y, SIZE_START, "%9d", size);
+ else if (display_units == CYLINDERS)
+ mvprintw(y, SIZE_START, "%9d", size/(sectors*heads));
+ else
+ mvprintw(y, SIZE_START, "%9.2f", ceiling(size/20.48)/100);
+ if (((size/(sectors*heads)) != ceiling(size/(sectors*(float)heads))) ||
+ ((p_info[i].first_sector/(sectors*heads)) !=
+ ceiling(p_info[i].first_sector/(sectors*heads))))
+ mvprintw(y, COLUMNS-1, "*");
+}
+
+void init_const(void)
+{
+ if (!defined) {
+ NAME_START = (((float)NAME_START)/COLUMNS)*COLS;
+ FLAGS_START = (((float)FLAGS_START)/COLUMNS)*COLS;
+ PTYPE_START = (((float)PTYPE_START)/COLUMNS)*COLS;
+ FSTYPE_START = (((float)FSTYPE_START)/COLUMNS)*COLS;
+ SIZE_START = (((float)SIZE_START)/COLUMNS)*COLS;
+ COMMAND_LINE_X = (((float)COMMAND_LINE_X)/COLUMNS)*COLS;
+
+ COMMAND_LINE_Y = LINES - 4;
+ WARNING_START = LINES - 2;
+
+ if ((NUM_ON_SCREEN = COMMAND_LINE_Y - DISK_TABLE_START - 3) <= 0)
+ NUM_ON_SCREEN = 1;
+
+ COLUMNS = COLS;
+ defined = TRUE;
+ }
+}
+
+void draw_screen(void)
+{
+ int i;
+ char *line;
+
+ line = (char *)malloc((COLS+1)*sizeof(char));
+
+ if (warning_last_time) {
+ for (i = 0; i < COLS; i++) {
+ move(WARNING_START, i);
+ line[i] = inch();
+ }
+ line[COLS] = 0;
+ }
+
+ erase();
+
+ if (warning_last_time)
+ mvaddstr(WARNING_START, 0, line);
+
+
+ sprintf(line, "cfdisk %s", VERSION);
+ mvaddstr(HEADER_START, (COLS-strlen(line))/2, line);
+ sprintf(line, "Disk Drive: %s", disk_device);
+ mvaddstr(HEADER_START+2, (COLS-strlen(line))/2, line);
+ sprintf(line, "Heads: %d Sectors per Track: %d Cylinders: %d",
+ heads, sectors, cylinders);
+ mvaddstr(HEADER_START+3, (COLS-strlen(line))/2, line);
+
+ mvaddstr(DISK_TABLE_START, NAME_START, "Name");
+ mvaddstr(DISK_TABLE_START, FLAGS_START, "Flags");
+ mvaddstr(DISK_TABLE_START, PTYPE_START, "Part Type");
+ mvaddstr(DISK_TABLE_START, FSTYPE_START, "FS Type");
+ if (display_units == SECTORS)
+ mvaddstr(DISK_TABLE_START, SIZE_START, " Sectors");
+ else if (display_units == CYLINDERS)
+ mvaddstr(DISK_TABLE_START, SIZE_START, "Cylinders");
+ else
+ mvaddstr(DISK_TABLE_START, SIZE_START, "Size (MB)");
+
+ move(DISK_TABLE_START+1, 1);
+ for (i = 1; i < COLS-1; i++)
+ addch('-');
+
+ if (NUM_ON_SCREEN >= num_parts)
+ for (i = 0; i < num_parts; i++)
+ draw_partition(i);
+ else
+ for (i = (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN;
+ i < NUM_ON_SCREEN + (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN &&
+ i < num_parts;
+ i++)
+ draw_partition(i);
+
+ free(line);
+}
+
+int draw_cursor(int move)
+{
+ if (move != 0 && (cur_part + move < 0 || cur_part + move >= num_parts))
+ return -1;
+
+ if (arrow_cursor)
+ mvaddstr(DISK_TABLE_START + cur_part + 2
+ - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, " ");
+ else
+ draw_partition(cur_part);
+
+ cur_part += move;
+
+ if (((cur_part - move)/NUM_ON_SCREEN)*NUM_ON_SCREEN !=
+ (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN)
+ draw_screen();
+
+ if (arrow_cursor)
+ mvaddstr(DISK_TABLE_START + cur_part + 2
+ - (cur_part/NUM_ON_SCREEN)*NUM_ON_SCREEN, 0, "-->");
+ else {
+ standout();
+ draw_partition(cur_part);
+ standend();
+ }
+
+ return 0;
+}
+
+void die(int dummy)
+{
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+ mvcur(0, COLS-1, LINES-1, 0);
+ nl();
+ endwin();
+ fdexit(0);
+}
+
+void do_curses_fdisk(void)
+{
+ int done = FALSE;
+ char command;
+
+ initscr();
+ old_SIGINT = signal(SIGINT, die);
+ old_SIGTERM = signal(SIGTERM, die);
+#ifdef DEBUG
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+#endif
+
+ cbreak();
+ noecho();
+ nonl();
+
+ init_const();
+
+ fill_p_info();
+
+ draw_screen();
+
+ while (!done) {
+ (void)draw_cursor(0);
+
+ if (p_info[cur_part].id == FREE_SPACE)
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hnpquW?]: ");
+ else if (p_info[cur_part].id > 0)
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [bdhmpqtuW?]: ");
+ else
+ mvaddstr(COMMAND_LINE_Y, COMMAND_LINE_X, "Command [hpquW?]: ");
+
+ clrtoeol();
+ refresh();
+
+ clear_warning();
+
+ switch (command = getch()) {
+ case 'B':
+ case 'b':
+ if (p_info[cur_part].id > 0)
+ p_info[cur_part].flags ^= 0x80;
+ else
+ print_warning(NO_FLAGS);
+ break;
+ case 'D':
+ case 'd':
+ if (p_info[cur_part].id > 0) {
+ del_part(cur_part);
+ if (cur_part >= num_parts)
+ cur_part = num_parts - 1;
+ draw_screen();
+ } else
+ print_warning(DEL_EMPTY);
+ break;
+ case 'G':
+ case 'g':
+ if (change_geometry())
+ draw_screen();
+ break;
+ case 'M':
+ case 'm':
+ if (p_info[cur_part].id > 0) {
+ if (p_info[cur_part].first_sector == 0 ||
+ IS_LOGICAL(p_info[cur_part].num)) {
+ if (p_info[cur_part].offset == sectors)
+ p_info[cur_part].offset = 1;
+ else
+ p_info[cur_part].offset = sectors;
+ draw_screen();
+ } else if (p_info[cur_part].offset != 0)
+ p_info[cur_part].offset = 0;
+ else
+ print_warning(MAX_UNMAXABLE);
+ } else
+ print_warning(MAX_UNMAXABLE);
+ break;
+ case 'N':
+ case 'n':
+ if (p_info[cur_part].id == FREE_SPACE) {
+ new_part(cur_part);
+ draw_screen();
+ } else if (p_info[cur_part].id == UNUSABLE)
+ print_warning(ADD_UNUSABLE);
+ else
+ print_warning(ADD_EXISTS);
+ break;
+ case 'P':
+ case 'p':
+ print_tables();
+ draw_screen();
+ break;
+ case 'Q':
+ case 'q':
+ done = TRUE;
+ break;
+ case 'T':
+ case 't':
+ if (p_info[cur_part].id > 0) {
+ change_id(cur_part);
+ draw_screen();
+ } else
+ print_warning(TYPE_EMPTY);
+ break;
+ case 'U':
+ case 'u':
+ if (display_units == MEGABYTES)
+ display_units = SECTORS;
+ else if (display_units == SECTORS)
+ display_units = CYLINDERS;
+ else if (display_units == CYLINDERS)
+ display_units = MEGABYTES;
+ draw_screen();
+ break;
+ case 'W':
+ write_part_table();
+ break;
+ case 'H':
+ case 'h':
+ case '?':
+ display_help();
+ draw_screen();
+ break;
+ case ESC:
+ if ((command = getch()) == '[') {
+ command = getch();
+ switch (command) {
+ case 'A' : /* Up arrow */
+ if (!draw_cursor(-1))
+ command = 0;
+ else
+ print_warning(NO_MORE_PARTS);
+ break;
+ case 'B' : /* Down arrow */
+ if (!draw_cursor(1))
+ command = 0;
+ else
+ print_warning(NO_MORE_PARTS);
+ break;
+ case 'C' : /* Right arrow */
+ case 'D' : /* Left arrow */
+ }
+ }
+ if (command)
+ putchar(BELL); /* CTRL-G */
+ break;
+ case REDRAWKEY:
+ clear();
+ draw_screen();
+ break;
+ default:
+ print_warning(BAD_COMMAND);
+ putchar(BELL); /* CTRL-G */
+ }
+ }
+
+ signal(SIGINT, old_SIGINT);
+ signal(SIGTERM, old_SIGTERM);
+ mvcur(0, COLS-1, LINES-1, 0);
+ nl();
+ endwin();
+ fdexit(0);
+}
+
+void copyright(void)
+{
+ fprintf(stderr, "Copyright (C) 1994 Kevin E. Martin\n");
+}
+
+void usage(char *prog_name)
+{
+ fprintf(stderr,
+ "%s: [-avz] [-c # cylinders] [-h # heads] [-s # sectors/track]\n",
+ prog_name);
+ fprintf(stderr,
+ "[ -P opt ] device\n");
+ copyright();
+}
+
+void main(int argc, char **argv)
+{
+ char c;
+ int i, len;
+
+ while ((c = getopt(argc, argv, "ac:h:s:vzP:")) != EOF)
+ switch (c) {
+ case 'a':
+ arrow_cursor = TRUE;
+ break;
+ case 'c':
+ cylinders = atoi(optarg);
+ if (cylinders <= 0 || cylinders > MAX_CYLINDERS) {
+ fprintf(stderr, "%s: %s\n", argv[0], BAD_CYLINDERS);
+ exit(1);
+ }
+ break;
+ case 'h':
+ heads = atoi(optarg);
+ if (heads <= 0 || heads > MAX_HEADS) {
+ fprintf(stderr, "%s: %s\n", argv[0], BAD_HEADS);
+ exit(1);
+ }
+ break;
+ case 's':
+ sectors = atoi(optarg);
+ if (sectors <= 0 || sectors > MAX_SECTORS) {
+ fprintf(stderr, "%s: %s\n", argv[0], BAD_SECTORS);
+ exit(1);
+ }
+ break;
+ case 'v':
+ fprintf(stderr, "cfdisk %s\n", VERSION);
+ copyright();
+ exit(0);
+ case 'z':
+ zero_table = TRUE;
+ break;
+ case 'P':
+ len = strlen(optarg);
+ for (i = 0; i < len; i++) {
+ switch (optarg[i]) {
+ case 'r':
+ print_only |= PRINT_RAW_TABLE;
+ break;
+ case 's':
+ print_only |= PRINT_SECTOR_TABLE;
+ break;
+ case 't':
+ print_only |= PRINT_PARTITION_TABLE;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ break;
+ default:
+ usage(argv[0]);
+ exit(1);
+ }
+
+ if (argc-optind == 1)
+ disk_device = argv[optind];
+ else if (argc-optind != 0) {
+ usage(argv[0]);
+ exit(1);
+ } else if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0)
+ disk_device = ALTERNATE_DEVICE;
+ else close(fd);
+
+ if (print_only) {
+ fill_p_info();
+ if (print_only & PRINT_RAW_TABLE)
+ print_raw_table();
+ if (print_only & PRINT_SECTOR_TABLE)
+ print_p_info();
+ if (print_only & PRINT_PARTITION_TABLE)
+ print_part_table();
+ } else
+ do_curses_fdisk();
+}
argv++;
}
if (argc != 2) usage(name);
- if (lstat(argv[1],&st) < 0) PERROR(argv[1]);
+ if (stat(argv[1],&st) < 0) PERROR(argv[1]);
if (!S_ISBLK(st.st_mode) || MAJOR(st.st_rdev) != FLOPPY_MAJOR) {
fprintf(stderr,"%s: not a floppy device\n",argv[1]);
exit(1);
.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH FDISK 8 "Tue Mar 22 01:00:00 1994" "Linux 1.0" "Linux Programmer's Manual"
+.TH FDISK 8 "3 June 1995" "Linux 1.0" "Linux Programmer's Manual"
.SH NAME
fdisk \- Partition table manipulator for Linux
.SH SYNOPSIS
* Modified, Wed Jun 22 21:05:30 1994, faith@cs.unc.edu:
* Added/changed a few partition type names to conform to cfdisk.
* (suggested by Sujal, smpatel@wam.umd.edu)
+ * Modified 3/5/95 leisner@sdsp.mc.xerox.com -- on -l only open
+ * devices RDONLY (instead of RDWR). This allows you to
+ * have the disks as rw-r----- with group disk (and if you
+ * want is safe to setguid fdisk to disk).
+ * Modified Sat Mar 11 10:02 1995 with more partition types, faith@cs.unc.edu
+ * Modified, Thu May 4 01:11:45 1995, esr@snark.thyrsus.com:
+ * It's user-interface cleanup time.
+ * Actual error messages for out-of-bounds values (what a concept!).
+ * Enable read-only access to partition table for learners.
+ * Smart defaults for most numeric prompts.
+ * Fixed a bug preventing a partition from crossing cylinder 8064, aeb, 950801.
+ * Read partition table twice to avoid kernel bug
+ * (from Daniel Quinlan <quinlan@yggdrasil.com>), Tue Sep 26 10:25:28 1995
+ * Modified, Sat Jul 1 23:43:16 MET DST 1995, fasten@cs.bonn.edu:
+ * editor for NetBSD/i386 (and Linux/Alpha?) disklabels.
+ * Tue Sep 26 17:07:54 1995: More patches from aeb. Fix segfaults, all >4GB.
+ * Don't destroy random data if extd partition starts past 4GB, aeb, 950818.
+ * Don't segfault on bad partition created by previous fdisk.
+ *
*/
#include <linux/hdreg.h>
#include <linux/fs.h>
-#if defined(__GNUC__) || defined(HAS_LONG_LONG)
-typedef long long ext2_loff_t;
-#else
-typedef long ext2_loff_t;
-#endif
-
-extern ext2_loff_t ext2_llseek(unsigned int fd,
- ext2_loff_t offset,
- unsigned int origin);
+#include "fdisk.h"
#define hex_val(c) ({ \
char _c = (c); \
})
-#define VERSION "2.0a (>2GB)"
+#define VERSION "2.1 (>4GB)"
#define DEFAULT_DEVICE "/dev/hda"
#define ALTERNATE_DEVICE "/dev/sda"
#define LINE_LENGTH 80
#define MAXIMUM_PARTS 60
-#define SECTOR_SIZE 512
#define PART_TABLE_FLAG 0xaa55
#define table_check(b) ((unsigned short *)((b) + 0x1fe))
#define offset(b, n) ((struct partition *)((b) + 0x1be + \
s |= (sector >> 2) & 0xc0; \
}
-#define cround(n) (((n) + display_factor * unit_flag) / display_factor)
#define ACTIVE_FLAG 0x80
#define EXTENDED 5
#define LINUX_SWAP 0x82
#define LINUX_NATIVE 0x83
-enum failure {usage, unable_to_open, unable_to_read, unable_to_seek,
- unable_to_write, out_of_memory};
+/* normally O_RDWR, -l option gives O_RDONLY */
+static int type_open = O_RDWR;
char *disk_device = DEFAULT_DEVICE, /* hda, unless specified */
*line_ptr, /* interactive input */
int fd, /* the disk */
ext_index, /* the prime extended partition */
listing = 0, /* no aborts for fdisk -l */
- size_flag = 0,
dos_compatible_flag = ~0,
partitions = 4; /* maximum partition + 1 */
*ext_pointers[MAXIMUM_PARTS] /* link pointers */
= {NULL, NULL, NULL, NULL};
-struct systypes {
- unsigned char index;
- char *name;
- } sys_types[] = {
- {0, "Empty"},
+struct systypes sys_types[] = { /* struct systypes in fdisk.h *//* bf */
+ {0, "Empty"},
{1, "DOS 12-bit FAT"},
{2, "XENIX root"},
{3, "XENIX usr"},
{0x51, "Novell?"},
{0x52, "Microport"}, /* or CPM? */
{0x63, "GNU HURD"}, /* or System V/386? */
- {0x64, "Novell"},
+ {0x64, "Novell Netware 286"},
+ {0x65, "Novell Netware 386"},
{0x75, "PC/IX"},
{0x80, "Old MINIX"}, /* Minix 1.4a and earlier */
{0xff, "BBT"} /* (bad track table) */
};
+int nsys_types = sizeof (sys_types) / sizeof (struct systypes); /* bf */
+
jmp_buf listingbuf;
void fatal(enum failure why)
{
puts("Command action\n"
" a toggle a bootable flag\n"
+ " b edit bsd disklabel\n" /* bf */
" c toggle the dos compatiblity flag\n"
" d delete a partition\n"
" l list known partition types\n"
" q quit without saving changes\n"
" r return to main menu\n"
" s change number of sectors\n"
+ " v verify the partition table\n"
" w write table to disk and exit"
);
}
return NULL;
}
-void list_types(void)
+/* added parameters to list_types() so fdisklabel
+ can pass another list of types.
+*//* bf */
+void list_types(struct systypes *sys, int size)
{
- uint last[4], done = 0, next = 0,
- size = sizeof(sys_types) / sizeof(struct systypes);
+ uint last[4], done = 0, next = 0;
int i;
for (i = 3; i >= 0; i--)
do {
printf("%c%2x %-15.15s", i ? ' ' : '\n',
- sys_types[next].index, sys_types[next].name);
- next = last[i++] + done;
+ sys[next].index, sys[next].name);
+ next = last[i++] + done;
if (i > 3 || next >= last[i]) {
i = 0;
next = ++done;
offsets[partitions] = extended_offset + p->start_sect;
if (!extended_offset)
extended_offset = p->start_sect;
- if (ext2_llseek(fd, offsets[partitions]
+ if (ext2_llseek(fd, (ext2_loff_t)offsets[partitions]
* SECTOR_SIZE, SEEK_SET) < 0)
fatal(unable_to_seek);
if (!(buffers[partitions] = (char *) malloc(SECTOR_SIZE)))
struct hd_geometry geometry;
partitions = 4;
- if ((fd = open(disk_device, O_RDWR)) < 0)
+ if ((fd = open(disk_device, type_open)) < 0)
+ {
+ if ((fd = open(disk_device, O_RDONLY)) < 0)
fatal(unable_to_open);
+ else
+ printf("You will not be able to write the partition table.\n");
+ }
if (SECTOR_SIZE != read(fd, buffer, SECTOR_SIZE))
fatal(unable_to_read);
+#ifdef HDIO_REQ
if (!ioctl(fd, HDIO_REQ, &geometry)) {
+#else
+ if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+#endif
heads = geometry.heads;
sectors = geometry.sectors;
cylinders = geometry.cylinders;
return *line_ptr;
}
-uint read_int(uint low, uint high, char *mesg)
+/* new function *//* bf */
+int read_hex(struct systypes *sys, int size)
{
- uint i;
+ int hex;
+
+ while (1)
+ {
+ read_char("Hex code (type L to list codes): ");
+ if (tolower(*line_ptr) == 'l')
+ list_types(sys, size);
+ else if (isxdigit (*line_ptr))
+ {
+ hex = 0;
+ do
+ hex = hex << 4 | hex_val(*line_ptr++);
+ while (isxdigit(*line_ptr));
+ return hex;
+ }
+ }
+}
+
+
+uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg)
+{
+ uint i, use_default = 1;
char ms[70];
- sprintf(ms, "%s (%d-%d): ", mesg, low, high);
+
+ switch(base) {
+ case lower:
+ sprintf(ms, "%s ([%d]-%d): ", mesg, low, high);
+ break;
+ case upper:
+ sprintf(ms, "%s (%d-[%d]): ", mesg, low, high);
+ break;
+ case deflt:
+ sprintf(ms, "%s (%d-[%d]-%d): ", mesg, low, dflt, high);
+ break;
+ default:
+ sprintf(ms, "%s (%d-%d): ", mesg, low, high);
+ break;
+ }
while (1) {
- while (!isdigit(read_char(ms)) &&
- (!size_flag || *line_ptr != '+'));
- if (*line_ptr == '+') {
- i = atoi(++line_ptr);
- while (isdigit(*line_ptr))
- line_ptr++;
+ while (!isdigit(read_char(ms))
+ && (*line_ptr != '-' && *line_ptr != '+'))
+ continue;
+ if (*line_ptr == '+' || *line_ptr == '-') {
+ if (*line_ptr == '+')
+ ++line_ptr;
+ i = atoi(line_ptr);
+ while (isdigit(*line_ptr))
+ {
+ line_ptr++;
+ use_default = 0;
+ }
switch (*line_ptr) {
case 'c':
case 'C': if (!unit_flag)
break;
default: break;
}
- i += low;
+ switch(base) {
+ case lower: i += low; break;
+ case upper: i += high; break;
+ case deflt: i += dflt; break;
+ }
}
- else i = atoi(line_ptr);
+ else
+ {
+ i = atoi(line_ptr);
+ while (isdigit(*line_ptr))
+ {
+ line_ptr++;
+ use_default = 0;
+ }
+ }
+ if (use_default)
+ printf("Using default value %d\n", i = dflt);
if (i >= low && i <= high)
break;
+ else
+ printf("Value out of range.\n");
}
- size_flag = 0;
return i;
}
int get_partition(int warn, int max)
{
- int i = read_int(1, max, "Partition number") - 1;
+ /*
+ * try to pick a default least likely to do damage,
+ * in case luser just types a newline
+ */
+ int i = read_int(1, max, max, ignore, "Partition number") - 1;
if (warn && !part_table[i]->sys_ind)
fprintf(stderr, "Warning: partition %d has empty type\n",
void change_units(void)
{
- if (unit_flag = !unit_flag)
+ if ((unit_flag = !unit_flag))
display_factor = 1;
else display_factor = heads * sectors;
update_units();
changed[i - 1] = 1;
}
else {
- part_table[5]->start_sect +=
+ if(part_table[5]) /* prevent SEGFAULT */
+ part_table[5]->start_sect +=
offsets[5] - extended_offset;
offsets[5] = extended_offset;
changed[5] = 1;
else if (!sys)
printf("Partition %d does not exist yet!\n", i + 1);
else while (1) {
+#if 0
read_char("Hex code (type L to list codes): ");
if (tolower(*line_ptr) == 'l')
list_types();
do
sys = sys << 4 | hex_val(*line_ptr++);
while (isxdigit(*line_ptr));
+#endif
+ /* The above code has been moved to read_hex ()
+ to avoid having the same code in fdisklabel.
+ *//* bf */
+ sys = read_hex (sys_types, nsys_types); /* bf */
+
if (!sys) {
delete_partition(i);
break;
changed[i] = 1;
break;
}
+#if 0 /* see above *//* bf */
}
+#endif
}
}
printf("logical=(%d, %d, %d)\n",lec, leh, les);
}
+#if 0
/* Beginning on cylinder boundary? */
if (pbh != !pbc || pbs != 1) {
printf("Partition %i does not start on cylinder "
printf(" phys=(%d, %d, %d) ", pbc, pbh, pbs);
printf("should be (%d, %d, 1)\n", pbc, !pbc);
}
+#endif
/* Ending on cylinder boundary? */
if (peh != (heads - 1) || pes != sectors) {
cylinders, str_units(), display_factor);
if (w < 5)
w = 5;
- printf("%*s Boot Begin Start End Blocks Id System\n",
+ printf("%*s Boot Begin Start End Blocks Id System\n",
w + 1, "Device");
for (i = 0 ; i < partitions; i++)
if ((p = part_table[i])->sys_ind) {
- printf("%*s%-2d %c%8d%8d%8d%8d%c %2x %s\n", w,
- disk_device, i + 1,
- !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
+ printf("%*s%-2d %c%9d%9d%9d%9d%c %2x %s\n", w,
+/* device */ disk_device, i + 1,
+/* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
? '*' : '?',
- cround(rounded( calculate(p->head, p->sector, p->cyl),
+/* begin */ cround(rounded( calculate(p->head, p->sector, p->cyl),
p->start_sect + offsets[i])),
- cround(p->start_sect + offsets[i]),
- cround(p->start_sect + offsets[i] + p->nr_sects
+/* start */ cround(p->start_sect + offsets[i]),
+/* end */ cround(p->start_sect + offsets[i] + p->nr_sects
- (p->nr_sects ? 1: 0)),
- p->nr_sects / 2, p->nr_sects & 1 ? '+' : ' ',
- p->sys_ind,
- (type = partition_type(p->sys_ind)) ?
+/* odd flag on end */ p->nr_sects / 2, p->nr_sects & 1 ? '+' : ' ',
+/* type id */ p->sys_ind,
+/* type name */ (type = partition_type(p->sys_ind)) ?
type : "Unknown");
check_consistency(p, i);
}
void check_bounds(uint *first, uint *last)
{
int i;
- uint max = 256 * 63 * 1024;
+ uint max = 0xffffffff; /* used to be 256 * 63 * 1024
+ but that made it impossible to add a
+ partition crossing cylinder 8064 */
struct partition *p = part_table[0];
for (i = 0; i < partitions; p = part_table[++i])
if (real_c >= cylinders)
fprintf(stderr, "Partitions %d: cylinder %d greater than "
"maximum %d\n", n, real_c + 1, cylinders);
- if (start != total)
+ if (cylinders <= 1024 && start != total)
fprintf(stderr,
"Partition %d: previous sectors %d disagrees with "
"total %d\n", n, start, total);
}
if (!read && start == temp) {
uint i;
- temp = 0;
- start = read_int(cround(i = (stop = start) + (n > 4)),
- cround(limit), mesg);
+ i = (stop = start) + (n > 4);
+ start = read_int(cround(i), cround(i), cround(limit),
+ ignore, mesg);
if (unit_flag) {
start = (start - 1) * display_factor;
if (start < i) start = i;
else {
sprintf(mesg, "Last %s or +size or +sizeM or +sizeK",
str_units());
- size_flag = 1;
- stop = read_int(cround(start), cround(limit), mesg);
+ stop = read_int(cround(start), cround(limit), cround(limit),
+ lower, mesg);
if (unit_flag) {
stop = stop * display_factor - 1;
if (stop >limit)
EXTENDED);
return;
}
+ else
+ printf("Invalid partition number "
+ "for type `%c'\n", c);
+
}
}
for (i = 3; i < partitions; i++)
if (changed[i]) {
*table_check(buffers[i]) = PART_TABLE_FLAG;
- if (ext2_llseek(fd, offsets[i]
+ if (ext2_llseek(fd, (ext2_loff_t)offsets[i]
* SECTOR_SIZE, SEEK_SET) < 0)
fatal(unable_to_seek);
if (write(fd, buffers[i], SECTOR_SIZE) != SECTOR_SIZE)
"(Reboot to ensure the partition table has been updated.)\n");
sync();
sleep(2);
- if (i = ioctl(fd, BLKRRPART))
- error = errno;
+ if (i = ioctl(fd, BLKRRPART)) {
+ error = errno;
+ } else {
+ /* some kernel versions (1.2.x) seem to have trouble
+ rereading the partition table, but if asked to do it
+ twice, the second time works. - biro@yggdrasil.com */
+ sync();
+ sleep(2);
+ if(i = ioctl(fd, BLKRRPART))
+ error = errno;
+ }
+
close(fd);
printf("Syncing disks.\n");
sync();
sleep(4); /* for sync() */
- if (i)
+ if (i < 0)
printf("Re-read table failed with error %d: %s.\nReboot your "
"system to ensure the partition table is updated.\n",
error, strerror(error));
}
first = rounded(calculate(p->head, p->sector, p->cyl), p->start_sect +
offsets[i]);
- new = read_int(first, p->start_sect + p->nr_sects + offsets[i] - 1,
- "New beginning of data") - offsets[i];
+ new = read_int(first, first,
+ p->start_sect + p->nr_sects + offsets[i] - 1,
+ lower, "New beginning of data") - offsets[i];
if (new != p->nr_sects) {
first = p->nr_sects + p->start_sect - new;
switch (tolower(read_char("Expert command (m for help): "))) {
case 'b': move_begin(get_partition(0, partitions));
break;
- case 'c': cylinders = read_int(1, 65535,
- "Number of cylinders");
- warn_cylinders();
+ case 'c': cylinders = read_int(1, cylinders, 65535,
+ deflt, "Number of cylinders");
+ warn_cylinders();
break;
case 'd': print_raw();
break;
case 'e': x_list_table(1);
break;
- case 'h': heads = read_int(1, 256, "Number of heads");
+ case 'h': heads = read_int(1, heads, 256, deflt,
+ "Number of heads");
update_units();
break;
case 'p': x_list_table(0);
case 'q': close(fd);
exit(0);
case 'r': return;
- case 's': sectors = read_int(1, 63,
+ case 's': sectors = read_int(1, sectors, 63, deflt,
"Number of sectors");
if (dos_compatible_flag) {
sector_offset = sectors;
}
update_units();
break;
+ case 'v': verify();
+ break;
case 'w': write_table();
default: xmenu();
}
{
disk_device = device;
if (!setjmp(listingbuf))
- if ((fd = open(disk_device, O_RDWR)) >= 0) {
+ if ((fd = open(disk_device, type_open)) >= 0) {
close(fd);
get_boot();
list_table();
if (partitions > 4)
delete_partition(ext_index);
- }
+ } else {
+ /* Ignore other errors, since we try IDE
+ and SCSI hard disks which may not be
+ installed on the system. */
+ if(errno == EACCES) {
+ fprintf(stderr, "Cannot open %s\n", device);
+ exit(1);
+ }
+ }
}
void main(int argc, char **argv)
exit(0);
case 'l':
listing = 1;
+ type_open = O_RDONLY;
try("/dev/hda");
try("/dev/hdb");
try("/dev/hdc");
disk_device = ALTERNATE_DEVICE;
else close(fd);
- get_boot();
if (argc == 1)
printf("Using %s as default device!\n", disk_device);
+ get_boot();
while (1) {
putchar('\n');
switch (tolower(read_char("Command (m for help): "))) {
case 'a': toggle_active(get_partition(1, partitions));
break;
+/* There should be a define which allows to turn off disklabel support so as
+ not to make fdisk larger than necessary on installation boot disks.
+*/
+#if 1 /* #ifndef NO_DISKLABEL_SUPPORT */
+ case 'b': bselect(); /* bf */
+ break;
+#endif
case 'c':
toggle_dos();
break;
case 'd': delete_partition(
get_partition(1, partitions));
break;
- case 'l': list_types();
+ case 'l': list_types(sys_types, nsys_types); /* bf */
break;
case 'n': new_partition();
break;
--- /dev/null
+/*
+ fdisk.h
+*/
+
+#define SECTOR_SIZE 512
+#define NETBSD_PARTITION 0xa5
+#define cround(n) (((n) + display_factor * unit_flag) / display_factor)
+
+#if defined(__GNUC__) || defined(HAS_LONG_LONG)
+typedef long long ext2_loff_t;
+#else
+typedef long ext2_loff_t;
+#endif
+
+extern ext2_loff_t ext2_llseek(unsigned int fd,
+ ext2_loff_t offset,
+ unsigned int origin);
+
+enum failure {usage, unable_to_open, unable_to_read, unable_to_seek,
+ unable_to_write, out_of_memory};
+
+enum offset {ignore, lower, deflt, upper};
+
+struct systypes {
+ unsigned char index;
+ char *name;
+};
+
+/* prototypes for fdisk.c */
+extern char *disk_device,
+ *line_ptr;
+extern int fd,
+ partitions;
+extern uint unit_flag,
+ display_factor;
+extern struct partition *part_table[];
+extern void fatal(enum failure why);
+extern int get_partition(int warn, int max);
+extern void list_types(struct systypes *sys, int size);
+extern int read_line (void);
+extern char read_char(char *mesg);
+extern int read_hex(struct systypes *sys, int size);
+uint read_int(uint low, uint dflt, uint high, enum offset base, char *mesg);
+extern char *const str_units(void);
+
+/* prototypes for fdisklabel.c */
+extern void bselect(void);
--- /dev/null
+/*
+ NetBSD disklabel editor for Linux fdisk
+ Written by Bernhard Fastenrath (fasten@informatik.uni-bonn.de)
+ with code from the NetBSD disklabel command:
+
+ Copyright (c) 1987, 1988 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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <errno.h>
+
+#include <sys/ioctl.h>
+#include <sys/param.h>
+
+#include <linux/genhd.h>
+#include <linux/hdreg.h>
+#include <linux/fs.h>
+
+#include "fdisk.h"
+#define DKTYPENAMES
+#include "fdisklabel.h"
+
+static void bsd_delete_part (void);
+static void bsd_new_part (void);
+static void bsd_print_disklabel (int show_all);
+static void bsd_write_disklabel (void);
+static int bsd_create_disklabel (void);
+static void bsd_edit_disklabel (void);
+static void bsd_write_bootstrap (void);
+static void bsd_change_fstype (void);
+static int bsd_get_part_index (int max);
+static int bsd_check_new_partition (int *i);
+static void bsd_list_types (void);
+static u_short bsd_dkcksum (struct disklabel *lp);
+static int bsd_initlabel (struct partition *p, struct disklabel *d, int pindex);
+static int bsd_readlabel (struct partition *p, struct disklabel *d);
+static int bsd_writelabel (struct partition *p, struct disklabel *d);
+static void sync_disks (void);
+#if defined (i386)
+static int bsd_translate_fstype (int linux_type);
+static void bsd_link_part (void);
+#endif
+#if defined (__alpha__)
+void alpha_bootblock_checksum (char *boot);
+#endif
+
+static struct disklabel bsd_dlabel;
+static char buffer[BSD_BBSIZE];
+#if defined (i386)
+static struct partition *bsd_part;
+static int bsd_part_index;
+#endif
+
+void
+bmenu (void)
+{
+ puts ("Command action\n"
+ " d delete a BSD partition\n"
+ " e edit drive data\n"
+ " i install bootstrap\n"
+ " l list known filesystem types\n"
+ " m print this menu\n"
+ " n add a new BSD partition\n"
+ " p print BSD partition table\n"
+ " q quit without saving changes\n"
+#if defined (i386)
+ " r return to main menu\n"
+#endif
+ " s show complete disklabel\n"
+ " t change a partition's filesystem id\n"
+ " w write disklabel to disk\n"
+#if defined (i386)
+ " x link BSD partition to non-BSD partition"
+#endif
+ );
+}
+
+void
+bselect (void)
+{
+#if defined (i386)
+ int t;
+
+ for (t=0; t<4; t++)
+ if (part_table[t] -> sys_ind == NETBSD_PARTITION)
+ {
+ bsd_part = part_table[t];
+ bsd_part_index = t;
+ if (bsd_part -> start_sect == 0)
+ {
+ fprintf (stderr, "Partition %s%d has invalid starting sector 0.\n",
+ disk_device, t+1);
+ return;
+ }
+ printf ("Reading disklabel of %s%d at sector %d.\n",
+ disk_device, t+1, bsd_part -> start_sect + BSD_LABELSECTOR);
+ if (bsd_readlabel (bsd_part, &bsd_dlabel) == 0)
+ if (bsd_create_disklabel () == 0)
+ return;
+ break;
+ }
+
+ if (t == 4)
+ {
+ printf ("There is no NetBSD partition on %s.\n", disk_device);
+ return;
+ }
+
+#elif defined (__alpha__)
+
+ if (bsd_readlabel (NULL, &bsd_dlabel) == 0)
+ if (bsd_create_disklabel () == 0)
+ exit ( EXIT_SUCCESS );
+
+#endif
+
+ while (1)
+ {
+ putchar ('\n');
+ switch (tolower (read_char ("BSD disklabel command (m for help): ")))
+ {
+ case 'd':
+ bsd_delete_part ();
+ break;
+ case 'e':
+ bsd_edit_disklabel ();
+ break;
+ case 'i':
+ bsd_write_bootstrap ();
+ break;
+ case 'l':
+ bsd_list_types ();
+ break;
+ case 'n':
+ bsd_new_part ();
+ break;
+ case 'p':
+ bsd_print_disklabel (0);
+ break;
+ case 'q':
+ close (fd);
+ exit ( EXIT_SUCCESS );
+ case 's':
+ bsd_print_disklabel (1);
+ break;
+ case 't':
+ bsd_change_fstype ();
+ break;
+ case 'w':
+ bsd_write_disklabel ();
+ break;
+#if defined (i386)
+ case 'r':
+ return;
+ case 'x':
+ bsd_link_part ();
+ break;
+#endif
+ default:
+ bmenu ();
+ break;
+ }
+ }
+}
+
+static void
+bsd_delete_part (void)
+{
+ int i;
+
+ i = bsd_get_part_index (bsd_dlabel.d_npartitions);
+ bsd_dlabel.d_partitions[i].p_size = 0;
+ bsd_dlabel.d_partitions[i].p_offset = 0;
+ bsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
+ if (bsd_dlabel.d_npartitions == i + 1)
+ while (bsd_dlabel.d_partitions[bsd_dlabel.d_npartitions-1].p_size == 0)
+ bsd_dlabel.d_npartitions--;
+}
+
+static void
+bsd_new_part (void)
+{
+ uint begin, end;
+ char mesg[48];
+ int i;
+
+ if (!bsd_check_new_partition (&i))
+ return;
+
+#if defined (i386)
+ begin = bsd_part -> start_sect;
+ end = begin + bsd_part -> nr_sects - 1;
+#elif defined (__alpha__)
+ begin = 0;
+ end = bsd_dlabel.d_secperunit;
+#endif
+
+ sprintf (mesg, "First %s", str_units());
+ begin = read_int (cround (begin), cround (begin), cround (end), ignore, mesg);
+
+ sprintf (mesg, "Last %s or +size or +sizeM or +sizeK", str_units());
+ end = read_int (cround (begin), cround (end), cround (end), ignore, mesg);
+
+ if (unit_flag)
+ {
+ begin = (begin - 1) * display_factor;
+ end = end * display_factor - 1;
+ }
+ bsd_dlabel.d_partitions[i].p_size = end - begin + 1;
+ bsd_dlabel.d_partitions[i].p_offset = begin;
+ bsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
+}
+
+static void
+bsd_print_disklabel (int show_all)
+{
+ struct disklabel *lp = &bsd_dlabel;
+ struct bsd_partition *pp;
+ FILE *f = stdout;
+ int i, j;
+
+ if (show_all)
+ {
+#if defined (i386)
+ fprintf(f, "# %s%d:\n", disk_device, bsd_part_index+1);
+#elif defined (__alpha__)
+ fprintf(f, "# %s:\n", disk_device);
+#endif
+ if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
+ fprintf(f, "type: %s\n", bsd_dktypenames[lp->d_type]);
+ else
+ fprintf(f, "type: %d\n", lp->d_type);
+ fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
+ fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
+ fprintf(f, "flags:");
+ if (lp->d_flags & BSD_D_REMOVABLE)
+ fprintf(f, " removable");
+ if (lp->d_flags & BSD_D_ECC)
+ fprintf(f, " ecc");
+ if (lp->d_flags & BSD_D_BADSECT)
+ fprintf(f, " badsect");
+ fprintf(f, "\n");
+ fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
+ fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
+ fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
+ fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
+ fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
+ fprintf(f, "rpm: %d\n", lp->d_rpm);
+ fprintf(f, "interleave: %d\n", lp->d_interleave);
+ fprintf(f, "trackskew: %d\n", lp->d_trackskew);
+ fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
+ fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
+ fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
+ fprintf(f, "drivedata: ");
+ for (i = NDDATA - 1; i >= 0; i--)
+ if (lp->d_drivedata[i])
+ break;
+ if (i < 0)
+ i = 0;
+ for (j = 0; j <= i; j++)
+ fprintf(f, "%d ", lp->d_drivedata[j]);
+ }
+ fprintf (f, "\n%d partitions:\n", lp->d_npartitions);
+ fprintf (f, "# size offset fstype [fsize bsize cpg]\n");
+ pp = lp->d_partitions;
+ for (i = 0; i < lp->d_npartitions; i++, pp++) {
+ if (pp->p_size) {
+ fprintf(f, " %c: %8d %8d ", 'a' + i,
+ pp->p_size, pp->p_offset);
+ if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
+ fprintf(f, "%8.8s", bsd_fstypes[pp->p_fstype].name);
+ else
+ fprintf(f, "%8x", pp->p_fstype);
+ switch (pp->p_fstype)
+ {
+ case BSD_FS_UNUSED:
+ fprintf(f, " %5d %5d %5.5s ",
+ pp->p_fsize, pp->p_fsize * pp->p_frag, "");
+ break;
+
+ case BSD_FS_BSDFFS:
+ fprintf(f, " %5d %5d %5d ",
+ pp->p_fsize, pp->p_fsize * pp->p_frag,
+ pp->p_cpg);
+ break;
+
+ default:
+ fprintf(f, "%20.20s", "");
+ break;
+ }
+ fprintf(f, "\t# (Cyl. %4d",
+#if 0
+ pp->p_offset / lp->d_secpercyl); /* differs from Linux fdisk */
+#else
+ pp->p_offset / lp->d_secpercyl + 1);
+#endif
+ if (pp->p_offset % lp->d_secpercyl)
+ putc('*', f);
+ else
+ putc(' ', f);
+ fprintf(f, "- %d",
+ (pp->p_offset +
+ pp->p_size + lp->d_secpercyl - 1) /
+#if 0
+ lp->d_secpercyl - 1); /* differs from Linux fdisk */
+#else
+ lp->d_secpercyl);
+#endif
+ if (pp->p_size % lp->d_secpercyl)
+ putc('*', f);
+ fprintf(f, ")\n");
+ }
+ }
+}
+
+static void
+bsd_write_disklabel (void)
+{
+#if defined (i386)
+ printf ("Writing disklabel to %s%d.\n", disk_device, bsd_part_index+1);
+ bsd_writelabel (bsd_part, &bsd_dlabel);
+#elif defined (__alpha__)
+ printf ("Writing disklabel to %s.\n", disk_device);
+ bsd_writelabel (NULL, &bsd_dlabel);
+#endif
+}
+
+static int
+bsd_create_disklabel (void)
+{
+ char c;
+
+#if defined (i386)
+ fprintf (stderr, "%s%d contains no disklabel.\n",
+ disk_device, bsd_part_index+1);
+#elif defined (__alpha__)
+ fprintf (stderr, "%s contains no disklabel.\n", disk_device);
+#endif
+
+ while (1)
+ if ((c = tolower (read_char ("Do you want to create a disklabel? (y/n) "))) == 'y')
+ {
+#if defined (i386)
+ if (bsd_initlabel (bsd_part, &bsd_dlabel, bsd_part_index) == 1)
+#elif defined (__alpha__)
+ if (bsd_initlabel (NULL, &bsd_dlabel, 0) == 1)
+#endif
+ {
+ bsd_print_disklabel (1);
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if (c == 'n')
+ return 0;
+}
+
+static int
+edit_int (int def, char *mesg)
+{
+ do {
+ fputs (mesg, stdout);
+ printf (" (%d): ", def);
+ if (!read_line ())
+ return def;
+ }
+ while (!isdigit (*line_ptr));
+ return atoi (line_ptr);
+}
+
+static void
+bsd_edit_disklabel (void)
+{
+ struct disklabel *d;
+
+ d = &bsd_dlabel;
+
+#ifdef __alpha__
+ d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,"bytes/sector");
+ d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,"sectors/track");
+ d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,"tracks/cylinder");
+ d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,"cylinders");
+#endif
+
+ /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
+ while (1)
+ {
+ d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
+ "sectors/cylinder");
+ if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
+ break;
+
+ printf ("Must be <= sectors/track * tracks/cylinder (default).\n");
+ }
+ d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,"rpm");
+ d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,"interleave");
+ d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,"trackskew");
+ d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,"cylinderskew");
+ d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,"headswitch");
+ d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,"track-to-track seek");
+
+ d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
+}
+
+static int
+bsd_get_bootstrap (char *path, void *ptr, int size)
+{
+ int fd;
+
+ if ((fd = open (path, O_RDONLY)) < 0)
+ {
+ perror (path);
+ return 0;
+ }
+ if (read (fd, ptr, size) < 0)
+ {
+ perror (path);
+ close (fd);
+ return 0;
+ }
+ printf (" ... %s\n", path);
+ close (fd);
+ return 1;
+}
+
+static void
+bsd_write_bootstrap (void)
+{
+ char *bootdir = BSD_LINUX_BOOTDIR;
+ char path[MAXPATHLEN];
+ char *dkbasename;
+ struct disklabel dl;
+ char *d, *p, *e;
+ int sector;
+
+ if (bsd_dlabel.d_type == BSD_DTYPE_SCSI)
+ dkbasename = "sd";
+ else
+ dkbasename = "wd";
+
+ printf ("Bootstrap: %sboot -> boot%s (%s): ", dkbasename, dkbasename, dkbasename);
+ if (read_line ())
+ {
+ line_ptr[strlen (line_ptr)-1] = '\0';
+ dkbasename = line_ptr;
+ }
+ sprintf (path, "%s/%sboot", bootdir, dkbasename);
+ if (!bsd_get_bootstrap (path, buffer, (int) bsd_dlabel.d_secsize))
+ return;
+
+ /* We need a backup of the disklabel (bsd_dlabel might have changed). */
+ d = &buffer[BSD_LABELSECTOR * SECTOR_SIZE];
+ bcopy (d, &dl, sizeof (struct disklabel));
+
+ /* The disklabel will be overwritten by 0's from bootxx anyway */
+ bzero (d, sizeof (struct disklabel));
+
+ sprintf (path, "%s/boot%s", bootdir, dkbasename);
+ if (!bsd_get_bootstrap (path, &buffer[bsd_dlabel.d_secsize],
+ (int) bsd_dlabel.d_bbsize - bsd_dlabel.d_secsize))
+ return;
+
+ e = d + sizeof (struct disklabel);
+ for (p=d; p < e; p++)
+ if (*p)
+ {
+ fprintf (stderr, "Bootstrap overlaps with disk label!\n");
+ exit ( EXIT_FAILURE );
+ }
+
+ bcopy (&dl, d, sizeof (struct disklabel));
+
+#if defined (i386)
+ sector = bsd_part -> start_sect;
+#elif defined (__alpha__)
+ sector = 0;
+ alpha_bootblock_checksum (buffer);
+#endif
+
+ if (ext2_llseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
+ fatal (unable_to_seek);
+ if (BSD_BBSIZE != write (fd, buffer, BSD_BBSIZE))
+ fatal (unable_to_write);
+
+#if defined (i386)
+ printf ("Bootstrap installed on %s%d.\n", disk_device, bsd_part_index+1);
+#elif defined (__alpha__)
+ printf ("Bootstrap installed on %s.\n", disk_device);
+#endif
+
+ sync_disks ();
+}
+
+static void
+bsd_change_fstype (void)
+{
+ int i;
+
+ i = bsd_get_part_index (bsd_dlabel.d_npartitions);
+ bsd_dlabel.d_partitions[i].p_fstype = read_hex (bsd_fstypes, BSD_FSMAXTYPES);
+}
+
+static int
+bsd_get_part_index (int max)
+{
+ char prompt[40];
+ char l;
+
+ sprintf (prompt, "Partition (a-%c): ", 'a' + max - 1);
+ do
+ l = tolower (read_char (prompt));
+ while (l < 'a' || l > 'a' + max - 1);
+ return l - 'a';
+}
+
+static int
+bsd_check_new_partition (int *i)
+{
+ int t;
+
+ if (bsd_dlabel.d_npartitions == BSD_MAXPARTITIONS)
+ {
+ for (t=0; t < BSD_MAXPARTITIONS; t++)
+ if (bsd_dlabel.d_partitions[t].p_size == 0)
+ break;
+
+ if (t == BSD_MAXPARTITIONS)
+ {
+ fprintf (stderr, "The maximum number of partitions has been created\n");
+ return 0;
+ }
+ }
+ *i = bsd_get_part_index (BSD_MAXPARTITIONS);
+
+ if (*i >= bsd_dlabel.d_npartitions)
+ bsd_dlabel.d_npartitions = (*i) + 1;
+
+ if (bsd_dlabel.d_partitions[*i].p_size != 0)
+ {
+ fprintf (stderr, "This partition already exists.\n");
+ return 0;
+ }
+ return 1;
+}
+
+static void
+bsd_list_types (void)
+{
+ list_types (bsd_fstypes, BSD_FSMAXTYPES);
+}
+
+static u_short
+bsd_dkcksum (struct disklabel *lp)
+{
+ register u_short *start, *end;
+ register u_short sum = 0;
+
+ start = (u_short *)lp;
+ end = (u_short *)&lp->d_partitions[lp->d_npartitions];
+ while (start < end)
+ sum ^= *start++;
+ return (sum);
+}
+
+static int
+bsd_initlabel (struct partition *p, struct disklabel *d, int pindex)
+{
+ struct hd_geometry geometry;
+ struct bsd_partition *pp;
+
+ if (ioctl (fd, HDIO_GETGEO, &geometry) == -1)
+ {
+ perror ("ioctl");
+ return 0;
+ }
+ bzero (d, sizeof (struct disklabel));
+
+ d -> d_magic = BSD_DISKMAGIC;
+
+ if (strncmp (disk_device, "/dev/sd", 7) == 0)
+ d -> d_type = BSD_DTYPE_SCSI;
+ else
+ d -> d_type = BSD_DTYPE_ST506;
+
+#if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
+ d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
+#endif
+
+#if defined (i386)
+ d -> d_flags = BSD_D_DOSPART;
+#else
+ d -> d_flags = 0;
+#endif
+ d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
+ d -> d_nsectors = geometry.sectors; /* sectors/track */
+ d -> d_ntracks = geometry.heads; /* tracks/cylinder (heads) */
+ d -> d_ncylinders = geometry.cylinders;
+ d -> d_secpercyl = geometry.sectors * geometry.heads; /* sectors/cylinder */
+ d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
+
+ d -> d_rpm = 3600;
+ d -> d_interleave = 1;
+ d -> d_trackskew = 0;
+ d -> d_cylskew = 0;
+ d -> d_headswitch = 0;
+ d -> d_trkseek = 0;
+
+ d -> d_magic2 = BSD_DISKMAGIC;
+ d -> d_bbsize = BSD_BBSIZE;
+ d -> d_sbsize = BSD_SBSIZE;
+
+#if defined (i386)
+ d -> d_npartitions = 4;
+ pp = &d -> d_partitions[2]; /* Partition C should be the NetBSD partition */
+ pp -> p_offset = p -> start_sect;
+ pp -> p_size = p -> nr_sects;
+ pp -> p_fstype = BSD_FS_UNUSED;
+ pp = &d -> d_partitions[3]; /* Partition D should be the whole disk */
+ pp -> p_offset = 0;
+ pp -> p_size = d -> d_secperunit;
+ pp -> p_fstype = BSD_FS_UNUSED;
+#elif defined (__alpha__)
+ d -> d_npartitions = 3;
+ pp = &d -> d_partitions[2]; /* Partition C should be the whole disk */
+ pp -> p_offset = 0;
+ pp -> p_size = d -> d_secperunit;
+ pp -> p_fstype = BSD_FS_UNUSED;
+#endif
+
+ return 1;
+}
+
+static int
+bsd_readlabel (struct partition *p, struct disklabel *d)
+{
+ int t, sector;
+
+#if defined (i386)
+ sector = p -> start_sect;
+#elif defined (__alpha__)
+ sector = 0;
+#endif
+
+ if (ext2_llseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
+ fatal (unable_to_seek);
+ if (BSD_BBSIZE != read (fd, buffer, BSD_BBSIZE))
+ fatal (unable_to_read);
+
+ bcopy (&buffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
+ d, sizeof (struct disklabel));
+
+ for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++)
+ {
+ d -> d_partitions[t].p_size = 0;
+ d -> d_partitions[t].p_offset = 0;
+ d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
+ }
+ if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
+ return 0;
+
+ if (d -> d_npartitions > BSD_MAXPARTITIONS)
+ fprintf (stderr, "Warning: too many partitions (%d, maximum is %d).\n",
+ d -> d_npartitions, BSD_MAXPARTITIONS);
+ return 1;
+}
+
+static int
+bsd_writelabel (struct partition *p, struct disklabel *d)
+{
+ int sector;
+
+#if defined (i386)
+ sector = p -> start_sect + BSD_LABELSECTOR;
+#elif defined (__alpha__)
+ sector = BSD_LABELSECTOR;
+#endif
+
+ d -> d_checksum = 0;
+ d -> d_checksum = bsd_dkcksum (d);
+
+ /* This is necessary if we want to write the bootstrap later,
+ otherwise we'd write the old disklabel with the bootstrap.
+ */
+ bcopy (d, &buffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
+ sizeof (struct disklabel));
+
+#if defined (__alpha__) && BSD_LABELSECTOR == 0
+ alpha_bootblock_checksum (buffer);
+ if (ext2_llseek (fd, 0, SEEK_SET) == -1)
+ fatal (unable_to_seek);
+ if (BSD_BBSIZE != write (fd, buffer, BSD_BBSIZE))
+ fatal (unable_to_write);
+#else
+ if (ext2_llseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
+ fatal (unable_to_seek);
+ if (sizeof (struct disklabel) != write (fd, d, sizeof (struct disklabel)))
+ fatal (unable_to_write);
+#endif
+
+ sync_disks ();
+
+ return 1;
+}
+
+static void
+sync_disks (void)
+{
+ printf ("\nSyncing disks.\n");
+ sync ();
+ sleep (4);
+}
+
+#if defined (i386)
+static int
+bsd_translate_fstype (int linux_type)
+{
+ switch (linux_type)
+ {
+ case 0x01: /* DOS 12-bit FAT */
+ case 0x04: /* DOS 16-bit <32M */
+ case 0x06: /* DOS 16-bit >=32M */
+ case 0xe1: /* DOS access */
+ case 0xe3: /* DOS R/O */
+ case 0xf2: /* DOS secondary */
+ return BSD_FS_MSDOS;
+ case 0x07: /* OS/2 HPFS */
+ return BSD_FS_HPFS;
+ default:
+ return BSD_FS_OTHER;
+ }
+}
+
+static void
+bsd_link_part (void)
+{
+ int k, i;
+
+ k = get_partition (1, partitions);
+
+ if (!bsd_check_new_partition (&i))
+ return;
+
+ bsd_dlabel.d_partitions[i].p_size = part_table[k] -> nr_sects;
+ bsd_dlabel.d_partitions[i].p_offset = part_table[k] -> start_sect;
+ bsd_dlabel.d_partitions[i].p_fstype =
+ bsd_translate_fstype (part_table[k] -> sys_ind);
+}
+#endif
+
+#if defined (__alpha__)
+typedef unsigned long long u_int64_t;
+
+void
+alpha_bootblock_checksum (char *boot)
+{
+ u_int64_t *dp, sum;
+ int i;
+
+ dp = (u_int64_t *)boot;
+ sum = 0;
+ for (i = 0; i < 63; i++)
+ sum += dp[i];
+ dp[63] = sum;
+}
+#endif /* __alpha__ */
--- /dev/null
+/*
+ * Copyright (c) 1987, 1988 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.
+ */
+
+#define BSD_DISKMAGIC ((u_long) 0x82564557)
+#define BSD_MAXPARTITIONS 8
+#define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
+
+#if defined (i386)
+#define BSD_LABELSECTOR 1
+#define BSD_LABELOFFSET 0
+#define BSD_BBSIZE 8192 /* size of boot area, with label */
+#define BSD_SBSIZE 8192 /* max size of fs superblock */
+#elif defined (__alpha__)
+#error LABELSECTOR, LABELOFFSET, BBSIZE & SBSIZE are undefined for __alpha__
+#define BSD_LABELSECTOR 0
+#define BSD_LABELOFFSET 0
+#define BSD_BBSIZE 0
+#define BSD_SBSIZE 0
+#else
+#error unknown architecture
+#endif
+
+struct disklabel {
+ u_long d_magic; /* the magic number */
+ short d_type; /* drive type */
+ short d_subtype; /* controller/d_type specific */
+ char d_typename[16]; /* type name, e.g. "eagle" */
+ /*
+ * d_packname contains the pack identifier and is returned when
+ * the disklabel is read off the disk or in-core copy.
+ * d_boot0 and d_boot1 are the (optional) names of the
+ * primary (block 0) and secondary (block 1-15) bootstraps
+ * as found in /usr/mdec. These are returned when using
+ * getdiskbyname(3) to retrieve the values from /etc/disktab.
+ */
+#if defined(KERNEL) || defined(STANDALONE)
+ char d_packname[16]; /* pack identifier */
+#else
+ union {
+ char un_d_packname[16]; /* pack identifier */
+ struct {
+ char *un_d_boot0; /* primary bootstrap name */
+ char *un_d_boot1; /* secondary bootstrap name */
+ } un_b;
+ } d_un;
+#define d_packname d_un.un_d_packname
+#define d_boot0 d_un.un_b.un_d_boot0
+#define d_boot1 d_un.un_b.un_d_boot1
+#endif /* ! KERNEL or STANDALONE */
+ /* disk geometry: */
+ u_long d_secsize; /* # of bytes per sector */
+ u_long d_nsectors; /* # of data sectors per track */
+ u_long d_ntracks; /* # of tracks per cylinder */
+ u_long d_ncylinders; /* # of data cylinders per unit */
+ u_long d_secpercyl; /* # of data sectors per cylinder */
+ u_long d_secperunit; /* # of data sectors per unit */
+ /*
+ * Spares (bad sector replacements) below
+ * are not counted in d_nsectors or d_secpercyl.
+ * Spare sectors are assumed to be physical sectors
+ * which occupy space at the end of each track and/or cylinder.
+ */
+ u_short d_sparespertrack; /* # of spare sectors per track */
+ u_short d_sparespercyl; /* # of spare sectors per cylinder */
+ /*
+ * Alternate cylinders include maintenance, replacement,
+ * configuration description areas, etc.
+ */
+ u_long d_acylinders; /* # of alt. cylinders per unit */
+
+ /* hardware characteristics: */
+ /*
+ * d_interleave, d_trackskew and d_cylskew describe perturbations
+ * in the media format used to compensate for a slow controller.
+ * Interleave is physical sector interleave, set up by the formatter
+ * or controller when formatting. When interleaving is in use,
+ * logically adjacent sectors are not physically contiguous,
+ * but instead are separated by some number of sectors.
+ * It is specified as the ratio of physical sectors traversed
+ * per logical sector. Thus an interleave of 1:1 implies contiguous
+ * layout, while 2:1 implies that logical sector 0 is separated
+ * by one sector from logical sector 1.
+ * d_trackskew is the offset of sector 0 on track N
+ * relative to sector 0 on track N-1 on the same cylinder.
+ * Finally, d_cylskew is the offset of sector 0 on cylinder N
+ * relative to sector 0 on cylinder N-1.
+ */
+ u_short d_rpm; /* rotational speed */
+ u_short d_interleave; /* hardware sector interleave */
+ u_short d_trackskew; /* sector 0 skew, per track */
+ u_short d_cylskew; /* sector 0 skew, per cylinder */
+ u_long d_headswitch; /* head switch time, usec */
+ u_long d_trkseek; /* track-to-track seek, usec */
+ u_long d_flags; /* generic flags */
+#define NDDATA 5
+ u_long d_drivedata[NDDATA]; /* drive-type specific information */
+#define NSPARE 5
+ u_long d_spare[NSPARE]; /* reserved for future use */
+ u_long d_magic2; /* the magic number (again) */
+ u_short d_checksum; /* xor of data incl. partitions */
+ /* filesystem and partition information: */
+ u_short d_npartitions; /* number of partitions in following */
+ u_long d_bbsize; /* size of boot area at sn0, bytes */
+ u_long d_sbsize; /* max size of fs superblock, bytes */
+ struct bsd_partition { /* the partition table */
+ u_long p_size; /* number of sectors in partition */
+ u_long p_offset; /* starting sector */
+ u_long p_fsize; /* filesystem basic fragment size */
+ u_char p_fstype; /* filesystem type, see below */
+ u_char p_frag; /* filesystem fragments per block */
+ u_short p_cpg; /* filesystem cylinders per group */
+ } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
+};
+
+/* d_type values: */
+#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
+#define BSD_DTYPE_MSCP 2 /* MSCP */
+#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
+#define BSD_DTYPE_SCSI 4 /* SCSI */
+#define BSD_DTYPE_ESDI 5 /* ESDI interface */
+#define BSD_DTYPE_ST506 6 /* ST506 etc. */
+#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
+#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
+#define BSD_DTYPE_FLOPPY 10 /* floppy */
+
+/* d_subtype values: */
+#define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
+#define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
+#define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
+
+#ifdef DKTYPENAMES
+static char *bsd_dktypenames[] = {
+ "unknown",
+ "SMD",
+ "MSCP",
+ "old DEC",
+ "SCSI",
+ "ESDI",
+ "ST506",
+ "HP-IB",
+ "HP-FL",
+ "type 9",
+ "floppy",
+ 0
+};
+#define BSD_DKMAXTYPES (sizeof(bsd_dktypenames) / sizeof(bsd_dktypenames[0]) - 1)
+#endif
+
+/*
+ * Filesystem type and version.
+ * Used to interpret other filesystem-specific
+ * per-partition information.
+ */
+#define BSD_FS_UNUSED 0 /* unused */
+#define BSD_FS_SWAP 1 /* swap */
+#define BSD_FS_V6 2 /* Sixth Edition */
+#define BSD_FS_V7 3 /* Seventh Edition */
+#define BSD_FS_SYSV 4 /* System V */
+#define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
+#define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
+#define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
+#define BSD_FS_MSDOS 8 /* MS-DOS file system */
+#define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
+#define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
+#define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
+#define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
+#define BSD_FS_ISOFS BSD_FS_ISO9660
+#define BSD_FS_BOOT 13 /* partition contains bootstrap */
+#define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
+#define BSD_FS_HFS 15 /* Macintosh HFS */
+
+#ifdef DKTYPENAMES
+static struct systypes bsd_fstypes[] = {
+ {BSD_FS_UNUSED, "unused"},
+ {BSD_FS_SWAP, "swap"},
+ {BSD_FS_V6, "Version 6"},
+ {BSD_FS_V7, "Version 7"},
+ {BSD_FS_SYSV, "System V"},
+ {BSD_FS_V71K, "4.1BSD"},
+ {BSD_FS_V8, "Eighth Edition"},
+ {BSD_FS_BSDFFS, "4.2BSD"},
+ {BSD_FS_MSDOS, "MS-DOS"},
+ {BSD_FS_BSDLFS, "4.4LFS"},
+ {BSD_FS_OTHER, "unknown"},
+ {BSD_FS_HPFS, "HPFS"},
+ {BSD_FS_ISO9660,"ISO-9660"},
+ {BSD_FS_BOOT, "boot"},
+ {BSD_FS_ADOS, "ADOS"},
+ {BSD_FS_HFS, "HFS"}
+};
+
+#define BSD_FSMAXTYPES (sizeof(bsd_fstypes) / sizeof(struct systypes))
+#endif
+
+/*
+ * flags shared by various drives:
+ */
+#define BSD_D_REMOVABLE 0x01 /* removable media */
+#define BSD_D_ECC 0x02 /* supports ECC */
+#define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
+#define BSD_D_RAMDISK 0x08 /* disk emulator */
+#define BSD_D_CHAIN 0x10 /* can do back-back transfers */
+#define BSD_D_DOSPART 0x20 /* within MSDOS partition */
.br
Added support for file system valid flag: Dr. Wettstein
(greg%wind.uucp@plains.nodak.edu)
+.br
+Check to prevent fsck of mounted filesystem added by Daniel Quinlan
+(quinlan@yggdrasil.com)
* under the terms of the GNU Public License.
*/
+#define FOR_UTIL_LINUX
+
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <linux/unistd.h>
-#if 0
+#ifndef FOR_UTIL_LINUX
#include "et/com_err.h"
#include "ext2fs/io.h"
#endif
+#ifdef FOR_UTIL_LINUX
#if defined(__GNUC__) || defined(HAS_LONG_LONG)
typedef long long ext2_loff_t;
#else
extern ext2_loff_t ext2_llseek(unsigned int fd,
ext2_loff_t offset,
unsigned int origin);
+#endif
#ifdef __linux__
int retval;
static int do_compat = 0;
- if (do_compat)
+ if (do_compat) {
+ compat_lseek:
+ if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
+ (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
+ errno = -EINVAL;
+ return -1;
+ }
return lseek (fd, (off_t) offset, origin);
+ }
offset_high = ((unsigned long long) offset) >> 32;
offset_low = ((unsigned long long) offset) & 0xffffffff;
* which does not support the llseek system call
*/
do_compat++;
- return lseek (fd, (off_t) offset, origin);
+ goto compat_lseek;
}
if (retval == -1)
result = -1;
.\" -*- nroff -*-
-.TH FSCK 8 "Jul 1993" "Version 1.8"
+.TH MKFS 8 "Jun 1995" "Version 1.9"
.SH NAME
-fsck \- check and repair a Linux file system
+mkfs \- build a Linux file system
.SH SYNOPSIS
-.B fsck
-[
-.B \-A
-]
+.B mkfs
[
.B \-V
]
.B fs-options
]
.I filesys
+[
+.I blocks
+]
.SH DESCRIPTION
-.B fsck
-is used to check and optionally repair a Linux file system.
+.B mkfs
+is used to build a Linux file system on a device, usually
+a hard disk partition.
.I filesys
is either the device name (e.g. /dev/hda1, /dev/sdb2) or
the mount point (e.g. /, /usr, /home) for the file system.
+.I blocks
+is the number of blocks to be used for the file system.
.PP
The exit code returned by
-.B fsck
-is the sum of the following conditions:
-.br
-\ 0\ \-\ No errors
-.br
-\ 1\ \-\ File system errors corrected
-.br
-\ 2\ \-\ File system errors corrected, system should
-.br
-\ \ \ \ be rebooted if file system was mounted
-.br
-\ 4\ \-\ File system errors left uncorrected
-.br
-\ 8\ \-\ Operational error
-.br
-\ 16\ \-\ Usage or syntax error
-.br
-\ 128\ \-\ Shared library error
-.br
-The exit code returned when all file systems are checked using the
-.B -A
-option is the bit-wise OR of the exit codes for each
-file system that is checked.
+.B mkfs
+is 0 on success and 1 on failure.
.PP
In actuality,
-.B fsck
-is simply a front-end for the various file system checkers
-(\fBfsck\fR.\fIfstype\fR)
+.B mkfs
+is simply a front-end for the various file system builders
+(\fBmkfs\fR.\fIfstype\fR)
available under Linux.
-The file system-specific checker is searched for in /etc/fs first,
+The file system-specific builder is searched for in /etc/fs first,
then in /etc and finally in the directories listed in the PATH
-environment variable.
-Please see the file system-specific checker manual pages for
+enviroment variable.
+Please see the file system-specific builder manual pages for
further details.
.SH OPTIONS
.TP
-.B -A
-Walk through the
-.I /etc/fstab
-file and try to check all file systems in one run. This option is
-typically used from the
-.I /etc/rc
-system initalization file, instead of multiple commands for checking
-a single file system. Note, that with this option, you cannot give
-the
-.I filesys
-argument as well.
-.TP
.B -V
Produce verbose output, including all file system-specific commands
that are executed.
This is really only useful for testing.
.TP
.BI -t \ fstype
-Specifies the type of file system to be checked.
+Specifies the type of file system to be built.
If not specified, the type is deduced by searching for
.I filesys
in
.TP
.B fs-options
File system-specific options to be passed to the real file
-system checker.
+system builder.
Although not guaranteed, the following options are supported
-by most file system checkers.
-.TP
-.I -a
-Automatically repair the file system without any questions (use
-this option with caution).
-.TP
-.I -l
-List all the file names in the file system.
+by most file system builders.
.TP
-.I -r
-Interactively repair the file system (ask for confirmations).
+.B -c
+Check the device for bad blocks before building the file system.
.TP
-.I -s
-List the super block before checking the file system.
+.BI -l \ filename
+Read the bad blocks list from
+.I filename
.TP
-.I -v
+.B -v
Produce verbose output.
.SH BUGS
All generic options must precede and not be combined with
Some file system-specific programs do not support the
.I -v
(verbose) option, nor return meaningful exit codes.
+Also, some file system-specific programs do not automatically
+detect the device size and require the
+.I blocks
+parameter to be specified.
.SH AUTHORS
David Engel (david@ods.com)
.br
Fred N. van Kempen (waltje@uwalt.nl.mugnet.org)
.br
+Ron Sommeling (sommel@sci.kun.nl)
+.br
The manual page was shamelessly adapted from Remy Card's version
for the ext2 file system.
.SH SEE ALSO
-.BR mkfs (8),
-.BR fsck.minix (8),
-.BR fsck.ext (8),
-.BR fsck.ext2 (8),
-.BR fsck.xiafs (8).
+.BR fsck (8),
+.BR mkfs.minix (8),
+.BR mkfs.ext (8),
+.BR mkfs.ext2 (8),
+.BR mkfs.xiafs (8).
/*
- * fs-util A simple generic frontend for the for the fsck and mkfs
- * programs under Linux. See the manual pages for details.
+ * mkfs A simple generic frontend for the for the mkfs program
+ * under Linux. See the manual page for details.
*
- * Usage: fsck [-AV] [-t fstype] [fs-options] device
- * mkfs [-V] [-t fstype] [fs-options] device< [size]
+ * Usage: mkfs [-V] [-t fstype] [fs-options] device [size]
*
* Authors: David Engel, <david@ods.com>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Ron Sommeling, <sommel@sci.kun.nl>
*/
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <mntent.h>
#include <unistd.h>
#include <getopt.h>
+#include <limits.h>
+#define VERSION "1.9"
+
#ifndef DEFAULT_FSTYPE
-# define DEFAULT_FSTYPE "minix"
+# define DEFAULT_FSTYPE "minix"
#endif
-#define _PATH_PROG "%s.%s"
-#define _PROG_FSCK "fsck"
-
-#define EXIT_OK 0
-#define EXIT_NONDESTRUCT 1
-#define EXIT_DESTRUCT 2
-#define EXIT_UNCORRECTED 4
-#define EXIT_ERROR 8
-#define EXIT_USAGE 16
-#define EXIT_LIBRARY 128
-
-static char *Version = "1.8";
-static char *ignored_types[] = {
- "ignore",
- "iso9660",
- "msdos",
- "nfs",
- "proc",
- "sw",
- "swap",
- NULL
-};
-
-
-/* Execute a program. */
-int do_exec(char *prog, char **argv, int verbose)
-{
- char *args[33];
- register int i;
- int pid, status;
-
- /* Build the vector. */
- i = 0;
- args[i++] = prog;
- while(*argv != NULL && i < 32)
- args[i++] = *argv++;
- args[i] = NULL;
-
- if (verbose) {
- i = 0;
- while(args[i] != NULL) {
- printf("%s ", args[i]);
- i++;
- }
- printf("\n");
- if (verbose > 1)
- return EXIT_OK;
- }
-
- /* Fork and execute the correct program. */
- if ((pid = fork()) < 0) {
- perror("fork");
- status = EXIT_ERROR;
- } else if (pid == 0) {
- (void) execvp(args[0], args);
- perror(args[0]);
- exit(EXIT_ERROR);
- } else {
- while(wait(&status) != pid)
- ;
- status = WEXITSTATUS(status);
- }
-
- return status;
-}
-
-
-/* Check if we have to ignore a file system type. */
-int ignore(char *type, char *opts)
-{
- char *cp;
- char **ip;
-
- ip = ignored_types;
- while (*ip != NULL) {
- if (!strcmp(type, *ip))
- return 1;
- ip++;
- }
-
- for (cp = strtok(opts, ","); cp != NULL; cp = strtok(NULL, ",")) {
- if (!strcmp(cp, "noauto"))
- return 1;
- }
-
- return 0;
-}
-
-
-/* Check all file systems, using the /etc/fstab table. */
-int check_all(int verbose, char **argv)
-{
- char path[PATH_MAX];
- char *args[33];
- FILE *mntfile;
- struct mntent *mp;
- register int i;
- int status = EXIT_OK;
-
- if (verbose)
- printf("Checking all file systems.\n");
-
- /* Create an array of arguments. */
- i = 0;
- while (*argv != NULL && i < 32)
- args[i++] = *argv++;
- args[i] = NULL;
- args[i + 1] = NULL;
-
- /* Open the mount table. */
- if ((mntfile = setmntent(MNTTAB, "r")) == NULL) {
- perror(MNTTAB);
- exit(EXIT_ERROR);
- }
-
- /* Walk through the /etc/fstab file. */
- while ((mp = getmntent(mntfile)) != NULL) {
- if (verbose)
- printf("%-7s %-15s %-15s ", mp->mnt_type,
- mp->mnt_fsname, mp->mnt_dir);
- if (ignore(mp->mnt_type, mp->mnt_opts)) {
- if (verbose)
- printf("(ignored)\n");
- continue;
- }
-
- /* Build program name. */
- sprintf(path, _PATH_PROG, _PROG_FSCK, mp->mnt_type);
- args[i] = mp->mnt_fsname;
- status |= do_exec(path, args, verbose);
- }
-
- (void) endmntent(mntfile);
-
- return status;
-}
-
-
-/* Lookup filesys in /etc/fstab and return the corresponding entry. */
-struct mntent *lookup(char *filesys)
-{
- FILE *mntfile;
- struct mntent *mp;
-
- /* No filesys name given. */
- if (filesys == NULL)
- return NULL;
-
- /* Open the mount table. */
- if ((mntfile = setmntent(MNTTAB, "r")) == NULL) {
- perror(MNTTAB);
- exit(EXIT_ERROR);
- }
-
- while ((mp = getmntent(mntfile)) != NULL) {
- if (!strcmp(filesys, mp->mnt_fsname) ||
- !strcmp(filesys, mp->mnt_dir))
- break;
- }
+#define SEARCH_PATH "PATH=/sbin:/sbin/fs.d:/sbin/fs:/etc/fs:/etc"
+#define PROGNAME "mkfs.%s"
- (void) endmntent(mntfile);
- return mp;
-}
-
-
-void usage(int fsck, char *prog)
+int main(int argc, char *argv[])
{
- if (fsck) {
- fprintf(stderr, "Usage: fsck [-AV] [-t fstype] [fs-options] filesys\n");
- } else {
- fprintf(stderr, "Usage: mkfs [-V] [-t fstype] [fs-options] filesys [size]\n");
- }
-
- exit(EXIT_USAGE);
-}
-
-
-void main(int argc, char *argv[])
-{
- char path[PATH_MAX];
- char *oldpath, newpath[PATH_MAX];
- register char *sp;
- struct mntent *fsent;
- char *fstype = NULL;
- int verbose = 0;
- int doall = 0;
- int i, fsck, more;
-
- /* Must be 1 for "fsck" and 0 for "mkfs". */
- if ((sp = strrchr(argv[0], '/')) != NULL)
- sp++;
- else
- sp = argv[0];
- if (!strcmp(sp, _PROG_FSCK))
- fsck = 1;
- else
- fsck = 0;
-
- /* Check commandline options. */
- opterr = 0;
- more = 0;
- while ((more == 0) && ((i = getopt(argc, argv, "AVt:")) != EOF))
- switch(i) {
- case 'A':
- doall++;
- break;
- case 'V':
- verbose++;
- break;
- case 't':
- if (optarg == NULL)
- usage(fsck, sp);
- fstype = optarg;
- break;
- default:
- more = 1;
- break; /* start of specific arguments */
- }
-
- /* Did we get any specific arguments? */
- if (more)
- optind--;
-
- /* Print our version number if requested. */
- if (verbose)
- printf("%s (fsutil) version %s (%s)\n", argv[0],
- Version, __DATE__);
-
- /* Update our PATH to include /etc/fs and /etc. */
- strcpy(newpath, "PATH=/etc/fs:/etc:");
- if ((oldpath = getenv("PATH")) != NULL)
- strcat(newpath, oldpath);
- putenv(newpath);
-
- /* If -A was specified ("check all"), double-check. */
- if (doall) {
- if (!fsck || (fstype != NULL))
- usage(fsck, sp);
- exit(check_all(verbose, &argv[optind]));
- } else {
- /* If -t wasn't specified, we must deduce fstype. */
- if (fstype == NULL) {
- /* make sure that "filesys" was specified */
- if (optind >= argc)
- usage(fsck, sp);
- /* then try looking for it in /etc/fstab */
- if ((fsent = lookup(argv[argc - 1])) != NULL) {
- argv[argc - 1] = fsent->mnt_fsname;
- fstype = fsent->mnt_type;
- } else {
- if (!fsck && optind < argc-1) {
- if ((fsent = lookup(argv[argc - 2])) != NULL) {
- argv[argc - 2] = fsent->mnt_fsname;
- fstype = fsent->mnt_type;
- }
- }
- }
- /* if we still don't know, use the default */
- if (fstype == NULL) fstype = DEFAULT_FSTYPE;
- }
-
- /* Build program name. */
- sprintf(path, _PATH_PROG, sp, fstype);
- exit(do_exec(path, &argv[optind], verbose));
+ char progname[NAME_MAX];
+ char *fstype = NULL;
+ int i, more = 0, verbose = 0;
+
+ /* Check commandline options. */
+ opterr = 0;
+ while ((more == 0) && ((i = getopt(argc, argv, "Vt:")) != EOF))
+ switch (i) {
+ case 'V':
+ verbose++;
+ break;
+ case 't':
+ fstype = optarg;
+ break;
+ default:
+ more = 1;
+ break; /* start of specific arguments */
}
- /*NOTREACHED*/
+ if (optind == argc) {
+ fprintf(stderr,
+ "Usage: mkfs [-V] [-t fstype] [fs-options] device [size]\n");
+ return -1;
+ }
+
+ /* If -t wasn't specified, use the default */
+ if (fstype == NULL)
+ fstype = DEFAULT_FSTYPE;
+
+ /* Set PATH and program name */
+ putenv(SEARCH_PATH);
+ sprintf(progname, PROGNAME, fstype);
+ argv[--optind] = progname;
+
+ if (verbose) {
+ puts("mkfs version " VERSION " (" __DATE__ ")");
+ i = optind;
+ while (argv[i])
+ printf("%s ", argv[i++]);
+ printf("\n");
+ if (verbose > 1)
+ return 0;
+ }
+
+ /* Execute the program */
+ execvp(progname, argv+optind);
+ perror(progname);
+ return 1;
}
.br
Support for the file system valid flag by Dr. Wettstein
(greg%wind.uucp@plains.nodak.edu)
+.br
+Check to prevent mkfs of mounted filesystem and boot sector clearing
+by Daniel Quinlan (quinlan@yggdrasil.com)
*/
/*
- * 24.11.91 - time began. Used the fsck sources to get started.
+ * DD.MM.YY
*
- * 25.11.91 - corrected some bugs. Added support for ".badblocks"
+ * 24.11.91 - Time began. Used the fsck sources to get started.
+ *
+ * 25.11.91 - Corrected some bugs. Added support for ".badblocks"
* The algorithm for ".badblocks" is a bit weird, but
* it should work. Oh, well.
*
- * 25.01.92 - Added the -l option for getting the list of bad blocks
- * out of a named file. (Dave Rivers, rivers@ponds.uucp)
+ * 25.01.92 - Added the -l option for getting the list of bad blocks
+ * out of a named file. (Dave Rivers, rivers@ponds.uucp)
*
- * 28.02.92 - added %-information when using -c.
+ * 28.02.92 - Added %-information when using -c.
*
- * 28.02.93 - added support for other namelengths than the original
+ * 28.02.93 - Added support for other namelengths than the original
* 14 characters so that I can test the new kernel routines..
*
- * Sat Oct 9 11:48:31 1993, faith@cs.unc.edu: make exit status conform
- * to that required by fsutil
+ * 09.10.93 - Make exit status conform to that required by fsutil
+ * (Rik Faith, faith@cs.unc.edu)
*
- * 31.10.93 - added inode request feature, for backup floppies: use
- * 32 inodes, for a news partition use more.
- * (Scott Heavner, sdh@po.cwru.edu)
+ * 31.10.93 - Added inode request feature, for backup floppies: use
+ * 32 inodes, for a news partition use more.
+ * (Scott Heavner, sdh@po.cwru.edu)
*
- * Mon Jan 3 11:08:49 1994, Dr. Wettstein (greg%wind.uucp@plains.nodak.edu).
- * Added support for file system valid flag.
+ * 03.01.94 - Added support for file system valid flag.
+ * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu)
*
- * 9.11.94 - added test to prevent overwrite of mounted fs adapted
- * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs
- * program. (Daniel Quinlan, quinlan@yggdrasil.com)
+ * 09.11.94 - Added test to prevent overwrite of mounted fs adapted
+ * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs
+ * program. (Daniel Quinlan, quinlan@yggdrasil.com)
+ *
+ * 03.20.95 - Clear first 512 bytes of filesystem to make certain that
+ * the filesystem is not misidentified as a MS-DOS FAT filesystem.
+ * (Daniel Quinlan, quinlan@yggdrasil.com)
*
* Usage: mkfs [-c] [-nXX] [-iXX] device size-in-blocks
* mkfs [-l filename ] device size-in-blocks
static char * inode_buffer = NULL;
#define Inode (((struct minix_inode *) inode_buffer)-1)
static char super_block_buffer[BLOCK_SIZE];
+static char boot_block_buffer[512];
#define Super (*(struct minix_super_block *)super_block_buffer)
#define INODES ((unsigned long)Super.s_ninodes)
#define ZONES ((unsigned long)Super.s_nzones)
Super.s_state |= MINIX_VALID_FS;
Super.s_state &= ~MINIX_ERROR_FS;
+ if (lseek(DEV, 0, SEEK_SET))
+ die("seek to boot block failed in write_tables");
+ if (512 != write(DEV, boot_block_buffer, 512))
+ die("unable to clear boot sector");
if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
die("seek failed in write_tables");
if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
die("unable to write super-block");
if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE))
- die("Unable to write inode map");
+ die("unable to write inode map");
if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE))
- die("Unable to write zone map");
+ die("unable to write zone map");
if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE))
- die("Unable to write inodes");
+ die("unable to write inodes");
+
}
void write_block(int blk, char * buffer)
memset(inode_map,0xff,sizeof(inode_map));
memset(zone_map,0xff,sizeof(zone_map));
memset(super_block_buffer,0,BLOCK_SIZE);
+ memset(boot_block_buffer,0,512);
MAGIC = magic;
ZONESIZE = 0;
MAXSIZE = (7+512+512*512)*1024;
unmark_inode(i);
inode_buffer = malloc(INODE_BUFFER_SIZE);
if (!inode_buffer)
- die("Unable to allocate buffer for inodes");
+ die("unable to allocate buffer for inodes");
memset(inode_buffer,0,INODE_BUFFER_SIZE);
printf("%d inodes\n",INODES);
printf("%d blocks\n",ZONES);
listfile=fopen(filename,"r");
if(listfile == (FILE *)NULL) {
- die("Can't open file of bad blocks");
+ die("can't open file of bad blocks");
}
while(!feof(listfile)) {
fscanf(listfile,"%d\n", &blockno);
if (!S_ISBLK(statbuf.st_mode))
check=0;
else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
- die("Will not try to make filesystem on '%s'");
+ die("will not try to make filesystem on '%s'");
setup_tables();
if (check)
check_blocks();
.\" "
.TH MKSWAP 8 "8 February 1995" "Linux 1.0" "Linux Programmer's Manual"
.SH NAME
-mkswap \- set up a Linux swap device
+mkswap \- set up a Linux swap area
.SH SYNOPSIS
.B "mkswap [ \-c ]"
.IB device " [" size-in-blocks "]"
.SH DESCRIPTION
.B mkswap
-sets up a Linux swap area on a device (usually a disk partition).
+sets up a Linux swap area on a device or in a file.
The
.I device
The
.I size-in-blocks
parameter is the desired size of the file system, in blocks. This
-information is determined automatically by mkswap if it is omitted. Block
-counts are rounded down to pages of 4 kB each. Only block counts equal to
-or greater than 40 and equal to or less than 131072 are allowed. Block
-counts greater than 130752 are (silently) rounded down to 130752.
+information is determined automatically by
+.B mkswap
+if it is omitted. Block counts are rounded down so that the total
+size is an integer multiple of the machine's page size. Only block
+counts in the range MINCOUNT..MAXCOUNT are allowed. If the block count
+exceeds the MAXCOUNT, it is truncated to that value and a warning
+message is issued.
+
+The MINCOUNT and MAXCOUNT values for a swap area are:
-As Nick Holloway explains, the actual maximum for each swap file/partition
-is:
.RS
-(4096 - 10) * 8 * 4096 = 133890048 bytes = 130752 blocks = 127.6875 Mb
+MINCOUNT = 10 * PAGE_SIZE / 1024
+.br
+MAXCOUNT = (PAGE_SIZE - 10) * 8 * PAGE_SIZE / 1024
.RE
-This is because a single page is used to hold the swap bitmap at the
-start of the partition, where each bit is a single 4K page. The reason
-for the -10, is that the signature is "SWAP-SPACE" -- 10 characters.
-.B mkswap
-can also set up swap files, although the file has to be created first. A
-sequence of commands similar to the following is reasonable for this
+For example, on a machine with 4kB pages (e.g., x86), we get:
+
+.RS
+MINCOUNT = 10 * 4096 / 1024 = 40
+.br
+MAXCOUNT = (4096 - 10) * 8 * 4096 / 1024 = 130752
+.RE
+
+As each block is 1kB large, the swap area in this example could have a
+size that is anywhere in the range from 40kB up to 127.6875MB.
+
+If you don't know the page size that your machine uses, you may be
+able to look it up with "cat /proc/cpuinfo".
+
+The reason for the limit on MAXCOUNT is that a single page is used to
+hold the swap bitmap at the start of the swap area, where each bit
+represents a single page. The reason for the -10, is that the
+signature is "SWAP-SPACE" -- 10 characters.
+
+To setup a swap file, it is necessary to create that file before
+running
+.B mkswap .
+A sequence of commands similar to the following is reasonable for this
purpose:
.nf
.RE
.fi
-Note that the regular file has to be created before running
-.B mkswap
-on the file, and that the file must not contain any holes (so, using
+Note that a swap file must not contain any holes (so, using
.BR cp (1)
to create the file is not acceptable).
#include <linux/mm.h>
-#ifndef __GNUC__
-#error "needs gcc for the bitop-__asm__'s"
-#endif
-
#ifndef __linux__
-#define volatile
+# define volatile
#endif
#define TEST_BUFFER_PAGES 8
static int check = 0;
static int badpages = 0;
-static char signature_page[PAGE_SIZE];
+static int signature_page[PAGE_SIZE/sizeof(int)];
-#define bitop(name,op) \
-static inline int name(char * addr,unsigned int nr) \
-{ \
-int __res; \
-__asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
-:"=g" (__res) \
-:"r" (nr),"m" (*(addr)),"0" (0)); \
-return __res; \
+static long bit_test_and_set (unsigned int *addr, unsigned int nr)
+{
+ unsigned int r, m;
+
+ addr += nr / (8 * sizeof(int));
+ r = *addr;
+ m = 1 << (nr & (8 * sizeof(int) - 1));
+ *addr = r | m;
+ return (r & m) != 0;
}
-bitop(bit,"")
-bitop(setbit,"s")
-bitop(clrbit,"r")
+static bit_test_and_clear (unsigned int *addr, unsigned int nr)
+{
+ unsigned int r, m;
+
+ addr += nr / (8 * sizeof(int));
+ r = *addr;
+ m = 1 << (nr & (8 * sizeof(int) - 1));
+ *addr = r & ~m;
+ return (r & m) != 0;
+}
/*
* Volatile to let gcc know that this doesn't return. When trying
current_page = 0;
while (current_page < PAGES) {
if (!check) {
- setbit(signature_page,current_page++);
+ bit_test_and_set(signature_page,current_page++);
continue;
}
if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
current_page*PAGE_SIZE)
die("seek failed in check_blocks");
if (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) {
- clrbit(signature_page,current_page++);
+ bit_test_and_clear(signature_page,current_page++);
badpages++;
continue;
}
- setbit(signature_page,current_page++);
+ bit_test_and_set(signature_page,current_page++);
}
if (badpages)
printf("%d bad page%s\n",badpages,(badpages>1)?"s":"");
argv++;
if (argv[0][0] != '-')
if (device_name) {
- PAGES = strtol(argv[0],&tmp,0)>>2;
+ PAGES = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10);
if (*tmp)
usage();
} else
if (device_name && !PAGES) {
PAGES = get_size(device_name) / PAGE_SIZE;
}
- if (!device_name || PAGES<10)
+ if (!device_name || PAGES<10) {
+ fprintf(stderr,
+ "%s: error: swap area needs to be at least %ldkB\n",
+ program_name, 10 * PAGE_SIZE / 1024);
usage();
- if (PAGES > 32688) /* 130752 blocks */
- PAGES=32688;
-#if 0
- if (PAGES > 32768)
- PAGES=32768;
-#endif
+ }
+ if (PAGES > 8 * (PAGE_SIZE - 10)) {
+ PAGES = 8 * (PAGE_SIZE - 10);
+ fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n",
+ program_name, PAGES * PAGE_SIZE / 1024);
+ }
DEV = open(device_name,O_RDWR);
if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
perror(device_name);
else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
die("Will not try to make swapdevice on '%s'");
check_blocks();
- if (!clrbit(signature_page,0))
+ if (!bit_test_and_clear(signature_page,0))
die("fatal: first page unreadable");
goodpages = PAGES - badpages - 1;
- if (!goodpages)
+ if (goodpages <= 0)
die("Unable to set up swap-space: unreadable");
printf("Setting up swapspace, size = %d bytes\n",goodpages*PAGE_SIZE);
- strncpy(signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
+ strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
if (lseek(DEV, 0, SEEK_SET))
die("unable to rewind swap-device");
if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE))
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Wed Feb 8 20:30:16 1995 by faith@cs.unc.edu
+# Revised: Fri Oct 6 20:27:05 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
+# May be distributed under the GPL
#
include ../MCONFIG
# Where to put man pages?
-MAN6= banner.6 ddate.6
+MAN6= banner.6
# Where to put binaries?
# See the "install" rule for the links. . .
-USRGAMES= banner ddate
+USRGAMES= banner
all: $(USRGAMES)
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
# Rules for everything else
banner: banner.o $(BSD)/getopt.o $(BSD)/err.o
+++ /dev/null
-.\" All Rites Reversed. This file is in the PUBLIC DOMAIN.
-.\" Kallisti.
-.TH DDATE 6 "55 Confusion 3160" "" "Linux Programmer's Manual"
-.SH NAME
-ddate \- converts boring normal dates to fun Discordian Dates
-.SH SYNOPSIS
-.B ddate
-.SH DESCRIPTION
-.B ddate
-prints the date in Discordian Date format.
-.SH AUTHOR
-.nf
-Druel the Chaotic aka Jeremy Johnson (mpython@gnu.ai.mit.edu)
-.br
-Modifications for Unix by Lee Harvey Oswald Smith, K.S.C.
-.br
-Five tons of flax.
+++ /dev/null
-/* ddate.c .. converts boring normal dates to fun Discordian Date -><-
- written the 65th day of The Aftermath in the Year of Our Lady of
- Discord 3157 by Druel the Chaotic aka Jeremy Johnson aka
- mpython@gnu.ai.mit.edu
-
- and I'm not responsible if this program messes anything up (except your
- mind, I'm responsible for that)
-
- Modifications for Unix by Lee Harvey Oswald Smith, K.S.C.
- Five tons of flax.
-*/
-
-#include <time.h>
-#include <string.h>
-#include <stdio.h>
-
-struct disc_time
-{int season; /* 0-4 */
- int day; /* 0-72 */
- int yday; /* 0-365 */
- int year; /* 3066- */
-};
-
-char *ending(int);
-void print(struct disc_time,char **);
-struct disc_time convert(int,int);
-struct disc_time makeday(int,int,int);
-
-main (int argc,char **argv)
-{long t;
- struct tm *eris;
- int bob,raw;
- struct disc_time hastur;
- if (argc==4)
- { int moe,larry,curly;
- moe=atoi(argv[1]);
- larry=atoi(argv[2]);
- curly=atoi(argv[3]);
- hastur=makeday(moe,larry,curly);
- }
- else if (argc!=1)
- { fprintf(stderr,"Syntax: DiscDate [month day year]");
- exit(1);
- }
- else
- {
- t= time(NULL);
- eris=localtime(&t);
- bob=eris->tm_yday; /* days since Jan 1. */
- raw=eris->tm_year; /* years since 1980 */
- hastur=convert(bob,raw);
- }
- print(hastur,argv);
-}
-
-struct disc_time makeday(int imonth,int iday,int iyear) /*i for input */
-{ struct disc_time funkychickens;
-
- int cal[12] =
- {
- 31,28,31,30,31,30,31,31,30,31,30,31
- };
- int dayspast=0;
-
- imonth--;
- funkychickens.year= iyear+1166;
- while(imonth>0)
- {
- dayspast+=cal[--imonth];
- }
- funkychickens.day=dayspast+iday-1;
- funkychickens.season=0;
- if((funkychickens.year%4)==2)
- {
- if (funkychickens.day==59)
- funkychickens.day=-1;
- }
- funkychickens.yday=funkychickens.day;
-/* note: EQUAL SIGN...hopefully that fixes it */
- while(funkychickens.day>=73)
- {
- funkychickens.season++;
- funkychickens.day-=73;
- }
- return funkychickens;
-}
-
-char *ending(int num)
-{
- int temp;
- char *funkychickens;
-
- funkychickens=(char *)malloc(sizeof(char)*3);
-
- temp=num%10; /* get 0-9 */
- switch (temp)
- { case 1:
- strcpy(funkychickens,"st");
- break;
- case 2:
- strcpy(funkychickens,"nd");
- break;
- case 3:
- strcpy(funkychickens,"rd");
- break;
- default:
- strcpy(funkychickens,"th");
- }
- return funkychickens;
-}
-
-struct disc_time convert(int nday, int nyear)
-{ struct disc_time funkychickens;
-
- funkychickens.year = nyear+3066;
- funkychickens.day=nday;
- funkychickens.season=0;
- if ((funkychickens.year%4)==2)
- {if (funkychickens.day==59)
- funkychickens.day=-1;
- else if (funkychickens.day >59)
- funkychickens.day-=1;
- }
- funkychickens.yday=funkychickens.day;
- while (funkychickens.day>=73)
- { funkychickens.season++;
- funkychickens.day-=73;
- }
- return funkychickens;
-
- }
-
-void print(struct disc_time tick, char **args)
-{ char *days[5] = { "Sweetmorn",
- "Boomtime",
- "Pungenday",
- "Prickle-Prickle",
- "Setting Orange"
- };
- char *seasons[5] = { "Chaos",
- "Discord",
- "Confusion",
- "Bureaucracy",
- "The Aftermath"
- };
- char *holidays[5][2] = { "Mungday", "Chaoflux",
- "Mojoday", "Discoflux",
- "Syaday", "Confuflux",
- "Zaraday", "Bureflux",
- "Maladay", "Afflux"
- };
- if (args[1]==NULL)
- printf("Today is ");
- else
- printf("%s-%s-%s is ",args[1],args[2],args[3]);
- if (tick.day==-1) printf("St. Tib's Day!");
- else
- { tick.day++;
- printf("%s",days[tick.yday%5]);
- printf(", the %d", tick.day);
- printf("%s day of %s",ending(tick.day),seasons[tick.season]) ;
- }
- printf(" in the YOLD %d\n",tick.year);
- if ((tick.day==5)||(tick.day==50))
- { printf("Celebrate ");
- if (tick.day==5)
- printf("%s\n",holidays[tick.season][0]);
- else
- printf("%s\n",holidays[tick.season][1]);
- }
-}
--- /dev/null
+.\" Copyright 1992,1993,1994 Rickard E. Faith (faith@cs.unc.edu)
+.\" May be distributed under the GNU General Public License
+.TH FRAG 8 "8 January 1994" "Linux 0.99" "Linux Programmer's Manual"
+.SH NAME
+frag \- simple fragmentation checker
+.SH SYNOPSIS
+.B /usr/sbin/frag
+.B "[ \-s [ \-s ]]"
+filename ...
+.SH DESCRIPTION
+.B frag
+will report the file system fragmentation on a specified
+.IR filename .
+If the
+.I filename
+is a directory,
+.B frag
+will recursively descend the directory.
+.SH OPTIONS
+.TP
+.B \-s
+Silent (may be set to 1 or 2). The first
+.B \-s
+eliminates the file by file statistics, and just prints the
+examined directories and a summary. The second
+.B \-s
+eliminates the printing of the directories, and just prints a
+summary. This option is useful when
+.B frag
+is used on a directory.
+.SH "SEE ALSO"
+.BR mkfs (8),
+.BR fsck (8),
+.BR mkefs (8),
+.BR efsck (8)
+.SH BUGS
+.B frag
+will get caught in an infinite loop in the /proc filesystem.
+.SH AUTHORS
+V1.0 by Werner Almesberger
+.br
+V1.1 by Steffen Zahn, adding directory recursion
+.br
+V1.2 by Rob Hooft, adding hole counts
+.br
+V1.3 by Steffen Zahn, ignore symlinks,
+don't cross filesys borders, get filesystem block size at runtime
--- /dev/null
+/* frag.c - simple fragmentation checker
+ V1.0 by Werner Almesberger
+ V1.1 by Steffen Zahn, adding directory recursion
+ V1.2 by Rob Hooft, adding hole counts
+ V1.3 by Steffen Zahn, email: szahn%masterix@emndev.siemens.co.at
+ 14 Nov 93
+ - ignore symlinks,
+ - don't cross filesys borders
+ - get filesystem block size at runtime
+ V1.4 by Michael Bischoff <mbi@mo.math.nat.tu-bs.de> to handle
+ indirect blocks better, but only for ext2fs
+ (applied by faith@cs.unc.edu, Sat Feb 4 22:06:27 1995)
+
+ TODO: - handle hard links
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <linux/fs.h> /* for FIBMAP */
+
+typedef struct StackElem {
+ struct StackElem *backref, *next;
+ char name[NAME_MAX];
+ char dir_seen;
+ char from_cmd_line;
+} StackElem;
+
+StackElem *top = NULL;
+
+
+void discard( void )
+{
+ StackElem *se = top;
+ if( se == NULL )
+ return ;
+ top = se->next;
+ free(se);
+}
+
+void push( StackElem * se )
+{
+ se -> next = top;
+ top = se;
+}
+
+char *p2s( StackElem *se, char *path )
+{
+ char *s;
+ if( se->backref!=NULL ) {
+ path = p2s( se->backref, path );
+ if( path[-1]!='/' )
+ *path++ = '/';
+ }
+ s = se->name;
+ while( *s )
+ *path++ = *s++;
+ return path;
+}
+
+char *path2str( StackElem *se, char *path )
+{
+ *(p2s( se, path ))=0;
+ return path;
+}
+
+void *xmalloc( size_t size )
+{
+ void *p;
+ if( (p=malloc(size))==NULL ) {
+ fprintf(stderr,"\nvirtual memory exhausted.\n");
+ exit(1);
+ }
+ return p;
+}
+
+int main(int argc,char **argv)
+{
+ int fd,last_phys_block,
+ fragments_in_file, blocks_in_file,
+ blocks,current_phys_block,
+ this_fragment, largest_fragment, i;
+ long sum_blocks=0, sum_frag_blocks=0, sum_files=0, sum_frag_files=0;
+ long num_hole=0, sum_hole=0, hole;
+ struct stat st;
+ struct statfs stfs;
+ StackElem *se, *se1;
+ char path[PATH_MAX], pathlink[PATH_MAX], *p;
+ DIR *dir;
+ struct dirent *de;
+ char silent_flag=0;
+ dev_t local_fs;
+ int block_size;
+
+ if (argc < 2)
+ {
+ fprintf(stderr,"usage: %s [-s [-s]] filename ...\n",argv[0]);
+ exit(1);
+ }
+ argc--; argv++;
+ while (argc>0)
+ {
+ p = *argv;
+ if( *p=='-' )
+ while( *++p )
+ switch( *p )
+ {
+ case 's':
+ silent_flag++; /* may be 1 or 2 */
+ break;
+ default:
+ fprintf(stderr,"\nunknown flag %c\n", *p );
+ exit(1);
+ }
+ else
+ {
+ se = xmalloc( sizeof(StackElem) );
+ se->backref=NULL; se->dir_seen=0; se->from_cmd_line=1;
+ strcpy( se->name, p );
+ push(se);
+ }
+ argc--; argv++;
+ }
+ while ( top != NULL)
+ {
+ se = top;
+ if( se->dir_seen )
+ discard();
+ else
+ {
+ path2str( se, path );
+ if( readlink( path, pathlink, sizeof(pathlink) )>=0 )
+ { /* ignore symlinks */
+ if(silent_flag<1)
+ {
+ printf("symlink %s\n", path );
+ }
+ discard();
+ }
+ else if( stat( path,&st) < 0)
+ {
+ perror( path );
+ discard();
+ }
+ else if( !se->from_cmd_line && (local_fs!=st.st_dev) )
+ { /* do not cross filesystem borders */
+ if(silent_flag<2)
+ {
+ printf("different filesystem %s\n", path );
+ }
+ discard();
+ }
+ else
+ {
+ if( se->from_cmd_line )
+ {
+ local_fs = st.st_dev;
+ if ( statfs( path, &stfs )<0 )
+ {
+ perror( path );
+ block_size = 1024;
+ }
+ else
+ block_size = stfs.f_bsize;
+ }
+ if( S_ISREG(st.st_mode)) /* regular file */
+ {
+ if ( (fd = open( path ,O_RDONLY)) < 0 )
+ {
+ perror( path );
+ discard();
+ }
+ else
+ {
+ last_phys_block = -1;
+ fragments_in_file = 0;
+ hole = 0; this_fragment=0;
+ largest_fragment=0;
+ blocks_in_file = (st.st_size+block_size-1)/block_size;
+ for (blocks = 0; blocks < blocks_in_file; blocks++)
+ {
+ current_phys_block = blocks;
+ if (ioctl(fd,FIBMAP,¤t_phys_block) < 0)
+ {
+ perror(path);
+ break;
+ }
+ if (current_phys_block) { /* no hole here */
+ int indirect;
+ /* indirect is the number of indirection */
+ /* blocks which must be skipped */
+ indirect = 0;
+ /* every 256 blocks there is an indirect block,
+ the first of these is before block 12 */
+ if (blocks >= 12 && (blocks-12) % 256 == 0)
+ ++indirect;
+ /* there is a block pointing to the indirect
+ blocks every 64K blocks */
+ if (blocks >= 256+12 && (blocks-256-12) % 65536 == 0)
+ ++indirect; /* 2nd indirect block */
+ /* there is a single triple indirect block */
+ if (blocks == 65536 + 256 + 12)
+ ++indirect;
+ if (last_phys_block == current_phys_block-1-indirect)
+ this_fragment++;
+ else { /* start of first or new fragment */
+ if( largest_fragment<this_fragment )
+ largest_fragment=this_fragment;
+ this_fragment=1;
+ fragments_in_file++;
+ }
+ last_phys_block = current_phys_block;
+ }
+ else
+ {
+ hole++;
+ }
+ }
+ if( largest_fragment<this_fragment )
+ largest_fragment=this_fragment;
+ blocks_in_file-=hole;
+ /* number of allocated blocks in file */
+ if( !silent_flag )
+ {
+ if( fragments_in_file < 2
+ || blocks_in_file < 2 )
+ i = 0; /* fragmentation 0 % */
+ else
+ i = (fragments_in_file - 1) * 100 /
+ (blocks_in_file-1);
+ /* maximum fragmentation 100%
+ means every block is an fragment */
+ printf(" %3d%% %s (%d block(s), %d fragment(s), largest %d",
+ i, path, blocks_in_file,
+ fragments_in_file,largest_fragment);
+ if (hole)
+ {
+ printf(", %d hole(s))\n",hole);
+ }
+ else
+ {
+ printf(")\n");
+ }
+ }
+ sum_blocks+=blocks_in_file;
+ if (hole)
+ num_hole++;
+ sum_hole+=hole;
+ sum_files++;
+ if( fragments_in_file>1 )
+ {
+ sum_frag_blocks+=blocks_in_file-largest_fragment;
+ sum_frag_files++;
+ }
+ discard();
+ close(fd);
+ }
+ }
+ else if( S_ISDIR( st.st_mode ) ) /* push dir contents */
+ {
+ if( (dir=opendir( path ))==NULL )
+ {
+ perror(path);
+ discard();
+ }
+ else
+ {
+ if( silent_flag<2 )
+ printf("reading %s\n", path);
+ while( (de=readdir(dir))!=NULL )
+ {
+ if( (strcmp(de->d_name,".")!=0)
+ && (strcmp(de->d_name,"..")!=0) )
+ {
+ se1 = xmalloc( sizeof(StackElem) );
+ se1->backref=se; se1->dir_seen=0;
+ se1->from_cmd_line=0;
+ strcpy( se1->name, de->d_name );
+ push(se1);
+ }
+ }
+ closedir( dir );
+ se->dir_seen=1;
+ }
+ }
+ else /* if( S_ISREG(st.st_mode)) */
+ discard();
+ }
+ } /* if( se->dir_seen ) */
+ } /* while ( top != NULL) */
+ if (sum_files>1)
+ {
+ printf("\nsummary:\n");
+ printf(" %3ld%% file fragmentation (%ld of %ld files contain fragments)\n",
+ sum_files<1 ? 0L : sum_frag_files*100/sum_files,
+ sum_frag_files, sum_files);
+ printf(" %3ld%% block fragmentation (%ld of %ld blocks are in fragments)\n",
+ sum_blocks<1 ? 0L : sum_frag_blocks*100/sum_blocks,
+ sum_frag_blocks, sum_blocks);
+ if (num_hole>1)
+ printf(" %ld files contain %ld blocks in holes\n",
+ num_hole,sum_hole);
+ }
+ exit(0);
+}
--- /dev/null
+.\" Public Domain 1994 Rik Faith (faith@cs.unc.edu)
+.\" "
+.TH LPCNTL 8 "18 July 1994" "Linux 1.1" "Linux Programmer's Manual"
+.SH NAME
+lpcntl \- interface to line printer ioctl
+.SH SYNOPSIS
+.BI "lpcntl " device " [ " irq " ]"
+.SH DESCRIPTION
+.B lpcntl
+is used to manipulate the line printer driver.
+.PP
+.I device
+specifies a line printer device (e.g.,
+.IR /dev/lp1 ).
+.PP
+If
+.I irq
+is specified, then the line printer driver is set to use that IRQ. If the
+.I irq
+is zero, then the polling driver is selected. Only the super user may
+change the IRQ.
+.PP
+If no
+.I irq
+is specified, then
+.B lpcntl
+will report the interrupt number currently in use, or will report that the
+polling driver is currently being used.
+.SH AUTHOR
+Nigel Gamble (nigel@gate.net)
--- /dev/null
+/*
+ * Simple command interface to ioctl(fd, LPSETIRQ, irq).
+ * Nigel Gamble (nigel@gate.net)
+ * e.g.
+ * lpcntl /dev/lp1 7
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/lp.h>
+
+int
+main(int argc, char **argv)
+{
+ unsigned int irq;
+ int fd;
+ int ret;
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: %s <lp device> [<irq>]\n", argv[0]);
+ exit(1);
+ }
+
+ fd = open(argv[1], O_RDONLY);
+ if (fd == -1) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ if (argc == 2) {
+ irq = ioctl(fd, LPGETIRQ);
+ if (irq == -1) {
+ perror(argv[1]);
+ exit(1);
+ }
+ if (irq)
+ printf("%s using IRQ %d\n", argv[1], irq);
+ else
+ printf("%s using polling\n", argv[1]);
+ } else {
+ irq = atoi(argv[2]);
+ ret = ioctl(fd, LPSETIRQ, irq);
+ if (ret == -1) {
+ if (errno == EPERM)
+ fprintf(stderr, "%s: only super-user can change the IRQ\n", argv[0]);
+ else
+ perror(argv[1]);
+ exit(1);
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+.\" Original author: Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org
+.\" Updated by faith@cs.unc.edu, Fri Oct 29 23:22:16 1993
+.TH MESG 1 "29 October 1993" "Linux 0.99" "Linux Programmer's Manual"
+.SH NAME
+mesg \- control write access to your terminal
+.SH SYNOPSIS
+.B mesg
+.RB [y|n]
+.br
+.SH DESCRIPTION
+.B Mesg
+controls the access to your terminal by others. It's typically used
+to allow/disallow others users to \fBwrite(1)\fP to your terminal.
+.SH FLAGS
+.IP y
+Allow write access to your terminal.
+.IP n
+Disallow write access to your terminal.
+.IP [none]
+Prints out the current access state of your terminal.
+.SH SEE ALSO
+.BR write (1), wall (1)
+.SH AUTHOR
+Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org
--- /dev/null
+/*
+ * mesg.c The "mesg" utility. Gives / restrict access to
+ * your terminal by others.
+ *
+ * Usage: mesg [y|n].
+ * Without arguments prints out the current settings.
+ */
+#include <stdio.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+char *Version = "@(#) mesg 1.0 08-12-92 MvS";
+
+int main(int argc, char **argv)
+{
+ struct stat st;
+
+ if (!isatty(0)) {
+ /* Or should we look in /etc/utmp? */
+ fprintf(stderr, "stdin: is not a tty");
+ return(1);
+ }
+
+ if (fstat(0, &st) < 0) {
+ perror("fstat");
+ return(1);
+ }
+ if (argc < 2) {
+ printf("Is %s\n", ((st.st_mode & 022) == 022) ? "y" : "n");
+ return(0);
+ }
+ if (argc > 2 || (argv[1][0] != 'y' && argv[1][0] != 'n')) {
+ fprintf(stderr, "Usage: mesg [y|n]\n");
+ return(1);
+ }
+ if (argv[1][0] == 'y')
+ st.st_mode |= 022;
+ else
+ st.st_mode &= ~022;
+ fchmod(0, st.st_mode);
+ return(0);
+}
--- /dev/null
+/*
+ * fs-util A simple generic frontend for the for the fsck and mkfs
+ * programs under Linux. See the manual pages for details.
+ *
+ * Usage: fsck [-AV] [-t fstype] [fs-options] device
+ * mkfs [-V] [-t fstype] [fs-options] device< [size]
+ *
+ * Authors: David Engel, <david@ods.com>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ */
+
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <mntent.h>
+#include <unistd.h>
+#include <getopt.h>
+
+
+#ifndef DEFAULT_FSTYPE
+# define DEFAULT_FSTYPE "minix"
+#endif
+
+#define _PATH_PROG "%s.%s"
+#define _PROG_FSCK "fsck"
+
+#define EXIT_OK 0
+#define EXIT_NONDESTRUCT 1
+#define EXIT_DESTRUCT 2
+#define EXIT_UNCORRECTED 4
+#define EXIT_ERROR 8
+#define EXIT_USAGE 16
+#define EXIT_LIBRARY 128
+
+static char *Version = "1.8";
+static char *ignored_types[] = {
+ "ignore",
+ "iso9660",
+ "msdos",
+ "nfs",
+ "proc",
+ "sw",
+ "swap",
+ NULL
+};
+
+
+/* Execute a program. */
+int do_exec(char *prog, char **argv, int verbose)
+{
+ char *args[33];
+ register int i;
+ int pid, status;
+
+ /* Build the vector. */
+ i = 0;
+ args[i++] = prog;
+ while(*argv != NULL && i < 32)
+ args[i++] = *argv++;
+ args[i] = NULL;
+
+ if (verbose) {
+ i = 0;
+ while(args[i] != NULL) {
+ printf("%s ", args[i]);
+ i++;
+ }
+ printf("\n");
+ if (verbose > 1)
+ return EXIT_OK;
+ }
+
+ /* Fork and execute the correct program. */
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ status = EXIT_ERROR;
+ } else if (pid == 0) {
+ (void) execvp(args[0], args);
+ perror(args[0]);
+ exit(EXIT_ERROR);
+ } else {
+ while(wait(&status) != pid)
+ ;
+ status = WEXITSTATUS(status);
+ }
+
+ return status;
+}
+
+
+/* Check if we have to ignore a file system type. */
+int ignore(char *type, char *opts)
+{
+ char *cp;
+ char **ip;
+
+ ip = ignored_types;
+ while (*ip != NULL) {
+ if (!strcmp(type, *ip))
+ return 1;
+ ip++;
+ }
+
+ for (cp = strtok(opts, ","); cp != NULL; cp = strtok(NULL, ",")) {
+ if (!strcmp(cp, "noauto"))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* Check all file systems, using the /etc/fstab table. */
+int check_all(int verbose, char **argv)
+{
+ char path[PATH_MAX];
+ char *args[33];
+ FILE *mntfile;
+ struct mntent *mp;
+ register int i;
+ int status = EXIT_OK;
+
+ if (verbose)
+ printf("Checking all file systems.\n");
+
+ /* Create an array of arguments. */
+ i = 0;
+ while (*argv != NULL && i < 32)
+ args[i++] = *argv++;
+ args[i] = NULL;
+ args[i + 1] = NULL;
+
+ /* Open the mount table. */
+ if ((mntfile = setmntent(MNTTAB, "r")) == NULL) {
+ perror(MNTTAB);
+ exit(EXIT_ERROR);
+ }
+
+ /* Walk through the /etc/fstab file. */
+ while ((mp = getmntent(mntfile)) != NULL) {
+ if (verbose)
+ printf("%-7s %-15s %-15s ", mp->mnt_type,
+ mp->mnt_fsname, mp->mnt_dir);
+ if (ignore(mp->mnt_type, mp->mnt_opts)) {
+ if (verbose)
+ printf("(ignored)\n");
+ continue;
+ }
+
+ /* Build program name. */
+ sprintf(path, _PATH_PROG, _PROG_FSCK, mp->mnt_type);
+ args[i] = mp->mnt_fsname;
+ status |= do_exec(path, args, verbose);
+ }
+
+ (void) endmntent(mntfile);
+
+ return status;
+}
+
+
+/* Lookup filesys in /etc/fstab and return the corresponding entry. */
+struct mntent *lookup(char *filesys)
+{
+ FILE *mntfile;
+ struct mntent *mp;
+
+ /* No filesys name given. */
+ if (filesys == NULL)
+ return NULL;
+
+ /* Open the mount table. */
+ if ((mntfile = setmntent(MNTTAB, "r")) == NULL) {
+ perror(MNTTAB);
+ exit(EXIT_ERROR);
+ }
+
+ while ((mp = getmntent(mntfile)) != NULL) {
+ if (!strcmp(filesys, mp->mnt_fsname) ||
+ !strcmp(filesys, mp->mnt_dir))
+ break;
+ }
+
+ (void) endmntent(mntfile);
+
+ return mp;
+}
+
+
+void usage(int fsck, char *prog)
+{
+ if (fsck) {
+ fprintf(stderr, "Usage: fsck [-AV] [-t fstype] [fs-options] filesys\n");
+ } else {
+ fprintf(stderr, "Usage: mkfs [-V] [-t fstype] [fs-options] filesys [size]\n");
+ }
+
+ exit(EXIT_USAGE);
+}
+
+
+void main(int argc, char *argv[])
+{
+ char path[PATH_MAX];
+ char *oldpath, newpath[PATH_MAX];
+ register char *sp;
+ struct mntent *fsent;
+ char *fstype = NULL;
+ int verbose = 0;
+ int doall = 0;
+ int i, fsck, more;
+
+ /* Must be 1 for "fsck" and 0 for "mkfs". */
+ if ((sp = strrchr(argv[0], '/')) != NULL)
+ sp++;
+ else
+ sp = argv[0];
+ if (!strcmp(sp, _PROG_FSCK))
+ fsck = 1;
+ else
+ fsck = 0;
+
+ /* Check commandline options. */
+ opterr = 0;
+ more = 0;
+ while ((more == 0) && ((i = getopt(argc, argv, "AVt:")) != EOF))
+ switch(i) {
+ case 'A':
+ doall++;
+ break;
+ case 'V':
+ verbose++;
+ break;
+ case 't':
+ if (optarg == NULL)
+ usage(fsck, sp);
+ fstype = optarg;
+ break;
+ default:
+ more = 1;
+ break; /* start of specific arguments */
+ }
+
+ /* Did we get any specific arguments? */
+ if (more)
+ optind--;
+
+ /* Print our version number if requested. */
+ if (verbose)
+ printf("%s (fsutil) version %s (%s)\n", argv[0],
+ Version, __DATE__);
+
+ /* Update our PATH to include /etc/fs and /etc. */
+ strcpy(newpath, "PATH=/etc/fs:/etc:");
+ if ((oldpath = getenv("PATH")) != NULL)
+ strcat(newpath, oldpath);
+ putenv(newpath);
+
+ /* If -A was specified ("check all"), double-check. */
+ if (doall) {
+ if (!fsck || (fstype != NULL))
+ usage(fsck, sp);
+ exit(check_all(verbose, &argv[optind]));
+ } else {
+ /* If -t wasn't specified, we must deduce fstype. */
+ if (fstype == NULL) {
+ /* make sure that "filesys" was specified */
+ if (optind >= argc)
+ usage(fsck, sp);
+ /* then try looking for it in /etc/fstab */
+ if ((fsent = lookup(argv[argc - 1])) != NULL) {
+ argv[argc - 1] = fsent->mnt_fsname;
+ fstype = fsent->mnt_type;
+ } else {
+ if (!fsck && optind < argc-1) {
+ if ((fsent = lookup(argv[argc - 2])) != NULL) {
+ argv[argc - 2] = fsent->mnt_fsname;
+ fstype = fsent->mnt_type;
+ }
+ }
+ }
+ /* if we still don't know, use the default */
+ if (fstype == NULL) fstype = DEFAULT_FSTYPE;
+ }
+
+ /* Build program name. */
+ sprintf(path, _PATH_PROG, sp, fstype);
+ exit(do_exec(path, &argv[optind], verbose));
+ }
+ /*NOTREACHED*/
+}
--- /dev/null
+.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
+.\" May be distributed under the GNU General Public License
+.\" Modified with suggestions from Linus, Mon Feb 1 21:40:49 1993
+.\" Modified with patches from Kai, Wed Jun 22 21:54:56 1994
+.\" Patches from jaggy@purplet.demon.co.uk (Mike Jagdis), Wed Feb 8 1995
+.\" Added comments from Nick Holloway, Sat Feb 11 1995, faith@cs.unc.edu
+.\" "
+.TH MKSWAP 8 "8 February 1995" "Linux 1.0" "Linux Programmer's Manual"
+.SH NAME
+mkswap \- set up a Linux swap device
+.SH SYNOPSIS
+.B "mkswap [ \-c ]"
+.IB device " [" size-in-blocks "]"
+.SH DESCRIPTION
+.B mkswap
+sets up a Linux swap area on a device (usually a disk partition).
+
+The
+.I device
+is usually of the following form:
+
+.nf
+.RS
+/dev/hda[1-8]
+/dev/hdb[1-8]
+/dev/sda[1-8]
+/dev/sdb[1-8]
+.RE
+.fi
+
+The
+.I size-in-blocks
+parameter is the desired size of the file system, in blocks. This
+information is determined automatically by mkswap if it is omitted. Block
+counts are rounded down to pages of 4 kB each. Only block counts equal to
+or greater than 40 and equal to or less than 131072 are allowed. Block
+counts greater than 130752 are (silently) rounded down to 130752.
+
+As Nick Holloway explains, the actual maximum for each swap file/partition
+is:
+.RS
+(4096 - 10) * 8 * 4096 = 133890048 bytes = 130752 blocks = 127.6875 Mb
+.RE
+This is because a single page is used to hold the swap bitmap at the
+start of the partition, where each bit is a single 4K page. The reason
+for the -10, is that the signature is "SWAP-SPACE" -- 10 characters.
+
+.B mkswap
+can also set up swap files, although the file has to be created first. A
+sequence of commands similar to the following is reasonable for this
+purpose:
+
+.nf
+.RS
+# dd if=/dev/zero of=swapfile bs=1024 count=8192
+# mkswap swapfile 8192
+# sync
+# swapon swapfile
+.RE
+.fi
+
+Note that the regular file has to be created before running
+.B mkswap
+on the file, and that the file must not contain any holes (so, using
+.BR cp (1)
+to create the file is not acceptable).
+
+.SH OPTIONS
+.TP
+.B \-c
+Check the device for bad blocks before creating the file system. If any
+are found, the count is printed. This option is meant to be used for swap
+partitions
+.BR only ,
+and should
+.B not
+be used for regular files! To make sure that regular files do not contain
+bad blocks, the partition that contains the regular file should have been
+created with
+.BR "mkfs -c" .
+.SH "SEE ALSO"
+.BR fsck (8),
+.BR mkfs (8),
+.BR fdisk (8)
+.SH AUTHOR
+Linus Torvalds (torvalds@cs.helsinki.fi)
--- /dev/null
+/*
+ * mkswap.c - set up a linux swap device
+ *
+ * (C) 1991 Linus Torvalds. This file may be redistributed as per
+ * the Linux copyright.
+ */
+
+/*
+ * 20.12.91 - time began. Got VM working yesterday by doing this by hand.
+ *
+ * Usuage: mkswap [-c] device [size-in-blocks]
+ *
+ * -c for readablility checking (use it unless you are SURE!)
+ *
+ * The device may be a block device or a image of one, but this isn't
+ * enforced (but it's not much fun on a character device :-).
+ *
+ * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
+ * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include <linux/mm.h>
+
+#ifndef __GNUC__
+#error "needs gcc for the bitop-__asm__'s"
+#endif
+
+#ifndef __linux__
+#define volatile
+#endif
+
+#define TEST_BUFFER_PAGES 8
+
+static char * program_name = "mkswap";
+static char * device_name = NULL;
+static int DEV = -1;
+static long PAGES = 0;
+static int check = 0;
+static int badpages = 0;
+
+static char signature_page[PAGE_SIZE];
+
+#define bitop(name,op) \
+static inline int name(char * addr,unsigned int nr) \
+{ \
+int __res; \
+__asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \
+:"=g" (__res) \
+:"r" (nr),"m" (*(addr)),"0" (0)); \
+return __res; \
+}
+
+bitop(bit,"")
+bitop(setbit,"s")
+bitop(clrbit,"r")
+
+/*
+ * Volatile to let gcc know that this doesn't return. When trying
+ * to compile this under minix, volatile gives a warning, as
+ * exit() isn't defined as volatile under minix.
+ */
+volatile void fatal_error(const char * fmt_string)
+{
+ fprintf(stderr,fmt_string,program_name,device_name);
+ exit(1);
+}
+
+#define usage() fatal_error("Usage: %s [-c] /dev/name [blocks]\n")
+#define die(str) fatal_error("%s: " str "\n")
+
+void check_blocks(void)
+{
+ unsigned int current_page;
+ int do_seek = 1;
+ static char buffer[PAGE_SIZE];
+
+ current_page = 0;
+ while (current_page < PAGES) {
+ if (!check) {
+ setbit(signature_page,current_page++);
+ continue;
+ }
+ if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) !=
+ current_page*PAGE_SIZE)
+ die("seek failed in check_blocks");
+ if (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) {
+ clrbit(signature_page,current_page++);
+ badpages++;
+ continue;
+ }
+ setbit(signature_page,current_page++);
+ }
+ if (badpages)
+ printf("%d bad page%s\n",badpages,(badpages>1)?"s":"");
+}
+
+static long valid_offset (int fd, int offset)
+{
+ char ch;
+
+ if (lseek (fd, offset, 0) < 0)
+ return 0;
+ if (read (fd, &ch, 1) < 1)
+ return 0;
+ return 1;
+}
+
+static int count_blocks (int fd)
+{
+ int high, low;
+
+ low = 0;
+ for (high = 1; valid_offset (fd, high); high *= 2)
+ low = high;
+ while (low < high - 1)
+ {
+ const int mid = (low + high) / 2;
+
+ if (valid_offset (fd, mid))
+ low = mid;
+ else
+ high = mid;
+ }
+ valid_offset (fd, 0);
+ return (low + 1);
+}
+
+static int get_size(const char *file)
+{
+ int fd;
+ int size;
+
+ fd = open(file, O_RDWR);
+ if (fd < 0) {
+ perror(file);
+ exit(1);
+ }
+ if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
+ close(fd);
+ return (size * 512);
+ }
+
+ size = count_blocks(fd);
+ close(fd);
+ return size;
+}
+
+int main(int argc, char ** argv)
+{
+ char * tmp;
+ struct stat statbuf;
+ int goodpages;
+
+ memset(signature_page,0,PAGE_SIZE);
+ if (argc && *argv)
+ program_name = *argv;
+ while (argc-- > 1) {
+ argv++;
+ if (argv[0][0] != '-')
+ if (device_name) {
+ PAGES = strtol(argv[0],&tmp,0)>>2;
+ if (*tmp)
+ usage();
+ } else
+ device_name = argv[0];
+ else while (*++argv[0])
+ switch (argv[0][0]) {
+ case 'c': check=1; break;
+ default: usage();
+ }
+ }
+ if (device_name && !PAGES) {
+ PAGES = get_size(device_name) / PAGE_SIZE;
+ }
+ if (!device_name || PAGES<10)
+ usage();
+ if (PAGES > 32688) /* 130752 blocks */
+ PAGES=32688;
+#if 0
+ if (PAGES > 32768)
+ PAGES=32768;
+#endif
+ DEV = open(device_name,O_RDWR);
+ if (DEV < 0 || fstat(DEV, &statbuf) < 0) {
+ perror(device_name);
+ exit(1);
+ }
+ if (!S_ISBLK(statbuf.st_mode))
+ check=0;
+ else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
+ die("Will not try to make swapdevice on '%s'");
+ check_blocks();
+ if (!clrbit(signature_page,0))
+ die("fatal: first page unreadable");
+ goodpages = PAGES - badpages - 1;
+ if (!goodpages)
+ die("Unable to set up swap-space: unreadable");
+ printf("Setting up swapspace, size = %d bytes\n",goodpages*PAGE_SIZE);
+ strncpy(signature_page+PAGE_SIZE-10,"SWAP-SPACE",10);
+ if (lseek(DEV, 0, SEEK_SET))
+ die("unable to rewind swap-device");
+ if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE))
+ die("unable to write signature page");
+ return 0;
+}
nroff -man selection.1 > selection.man
install: selection # selection.man
- install -m 755 selection $(BINDIR)/selection
- install -m 644 selection.1 $(MANDIR)/man$(MANEXT)/selection.$(MANEXT)
+ $(INSTALLDIR) $(USRBINDIR) $(MAN1DIR)
+ $(INSTALLBIN) selection $(USRBINDIR)
+ $(INSTALLMAN) selection.1 $(MAN1DIR)
DIST = selection-1.5
DATE = 17th June 1993
--- /dev/null
+/* simple driver for serial mouse */
+/* Andrew Haylett, 17th June 1993 */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mouse.h"
+
+#define DEF_MDEV "/dev/mouse"
+#define DEF_MTYPE P_MS
+#define DEF_MBAUD 1200
+#define DEF_MSAMPLE 100
+#define DEF_MDELTA 25
+#define DEF_MACCEL 2
+
+/* thse settings may be altered by the user */
+static char *mdev = DEF_MDEV; /* mouse device */
+static mouse_type mtype = DEF_MTYPE; /* mouse type */
+static int mbaud = DEF_MBAUD; /* mouse device baud rate */
+static int msample = DEF_MSAMPLE; /* sample rate for Logitech mice */
+static int mdelta = DEF_MDELTA; /* x+y movements more than mdelta pixels..*/
+static int maccel = DEF_MACCEL; /* ..are multiplied by maccel. */
+int ms_copy_button = MS_BUTLEFT,
+ ms_paste_button = MS_BUTRIGHT;
+
+static char *progname;
+
+static void
+ms_usage()
+{
+ printf(
+ "Selection version 1.5, 17th June 1993\n"
+ "Usage: %s [-a accel] [-b baud-rate] [-c l|m|r] [-d delta]\n"
+ " [-m mouse-device] [-p l|m|r] [-s sample-rate] [-t mouse-type]\n\n", progname);
+ printf(
+ " -a accel sets the acceleration (default %d)\n"
+ " -b baud-rate sets the baud rate (default %d)\n"
+ " -c l|m|r sets the copy button (default `l')\n"
+ " -d delta sets the delta value (default %d)\n"
+ " -m mouse-device sets mouse device (default `%s')\n"
+ " -p l|m|r sets the paste button (default `r')\n"
+ " -s sample-rate sets the sample rate (default %d)\n"
+ " -t mouse-type sets mouse type (default `ms')\n"
+ " Microsoft = `ms', Mouse Systems Corp = `msc',\n"
+ " MM Series = `mm', Logitech = `logi', BusMouse = `bm',\n"
+ " MSC 3-bytes = `sun', PS/2 = `ps2')\n",
+ DEF_MACCEL, DEF_MBAUD, DEF_MDELTA, DEF_MDEV, DEF_MSAMPLE);
+ exit(1);
+}
+
+extern int optind;
+extern char *optarg;
+
+void
+ms_params(int argc, char *argv[])
+{
+ int opt;
+
+ progname = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];
+ while ((opt = getopt(argc, argv, "a:b:c:d:m:p:s:t:")) != -1)
+ {
+ switch (opt)
+ {
+ case 'a':
+ maccel = atoi(optarg);
+ if (maccel < 2)
+ ms_usage();
+ break;
+ case 'b':
+ mbaud = atoi(optarg);
+ break;
+ case 'c':
+ switch (*optarg)
+ {
+ case 'l': ms_copy_button = MS_BUTLEFT; break;
+ case 'm': ms_copy_button = MS_BUTMIDDLE; break;
+ case 'r': ms_copy_button = MS_BUTRIGHT; break;
+ default: ms_usage(); break;
+ }
+ break;
+ case 'd':
+ mdelta = atoi(optarg);
+ if (mdelta < 2)
+ ms_usage();
+ break;
+ case 'm':
+ mdev = optarg;
+ break;
+ case 'p':
+ switch (*optarg)
+ {
+ case 'l': ms_paste_button = MS_BUTLEFT; break;
+ case 'm': ms_paste_button = MS_BUTMIDDLE; break;
+ case 'r': ms_paste_button = MS_BUTRIGHT; break;
+ default: ms_usage(); break;
+ }
+ break;
+ case 's':
+ msample = atoi(optarg);
+ break;
+ case 't':
+ if (!strcmp(optarg, "ms"))
+ mtype = P_MS;
+ else if (!strcmp(optarg, "sun"))
+ mtype = P_SUN;
+ else if (!strcmp(optarg, "msc"))
+ mtype = P_MSC;
+ else if (!strcmp(optarg, "mm"))
+ mtype = P_MM;
+ else if (!strcmp(optarg, "logi"))
+ mtype = P_LOGI;
+ else if (!strcmp(optarg, "bm"))
+ mtype = P_BM;
+ else if (!strcmp(optarg, "ps2"))
+ mtype = P_PS2;
+ else
+ ms_usage();
+ break;
+ default:
+ ms_usage();
+ break;
+ }
+ }
+}
+
+#define limit(n,l,u) n = ((n) < (l) ? (l) : ((n) > (u) ? (u) : (n)))
+
+static int mx = 32767;
+static int my = 32767;
+static int x, y;
+static int mfd = -1;
+
+static const unsigned short cflag[NR_TYPES] =
+{
+ (CS7 | CREAD | CLOCAL | HUPCL ), /* MicroSoft */
+ (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems 3 */
+ (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* MouseSystems 5 */
+ (CS8 | PARENB | PARODD | CREAD | CLOCAL | HUPCL ), /* MMSeries */
+ (CS8 | CSTOPB | CREAD | CLOCAL | HUPCL ), /* Logitech */
+ 0, /* BusMouse */
+ 0 /* PS/2 */
+};
+
+static const unsigned char proto[NR_TYPES][5] =
+{
+ /* hd_mask hd_id dp_mask dp_id nobytes */
+ { 0x40, 0x40, 0x40, 0x00, 3 }, /* MicroSoft */
+ { 0xf8, 0x80, 0x00, 0x00, 3 }, /* MouseSystems 3 (Sun) */
+ { 0xf8, 0x80, 0x00, 0x00, 5 }, /* MouseSystems 5 */
+ { 0xe0, 0x80, 0x80, 0x00, 3 }, /* MMSeries */
+ { 0xe0, 0x80, 0x80, 0x00, 3 }, /* Logitech */
+ { 0xf8, 0x80, 0x00, 0x00, 5 }, /* BusMouse */
+ { 0xcc, 0x00, 0x00, 0x00, 3 } /* PS/2 */
+};
+
+static void
+ms_setspeed(const int old, const int new,
+ const unsigned short c_cflag)
+{
+ struct termios tty;
+ char *c;
+
+ tcgetattr(mfd, &tty);
+
+ tty.c_iflag = IGNBRK | IGNPAR;
+ tty.c_oflag = 0;
+ tty.c_lflag = 0;
+ tty.c_line = 0;
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+
+ switch (old)
+ {
+ case 9600: tty.c_cflag = c_cflag | B9600; break;
+ case 4800: tty.c_cflag = c_cflag | B4800; break;
+ case 2400: tty.c_cflag = c_cflag | B2400; break;
+ case 1200:
+ default: tty.c_cflag = c_cflag | B1200; break;
+ }
+
+ tcsetattr(mfd, TCSAFLUSH, &tty);
+
+ switch (new)
+ {
+ case 9600: c = "*q"; tty.c_cflag = c_cflag | B9600; break;
+ case 4800: c = "*p"; tty.c_cflag = c_cflag | B4800; break;
+ case 2400: c = "*o"; tty.c_cflag = c_cflag | B2400; break;
+ case 1200:
+ default: c = "*n"; tty.c_cflag = c_cflag | B1200; break;
+ }
+
+ write(mfd, c, 2);
+ usleep(100000);
+ tcsetattr(mfd, TCSAFLUSH, &tty);
+}
+
+int
+ms_init(const int maxx, const int maxy)
+{
+ if ((mfd = open(mdev, O_RDWR)) < 0)
+ {
+ char buf[32];
+ sprintf(buf, "ms_init: %s", mdev);
+ perror(buf);
+ return -1;
+ }
+
+ if (mtype != P_BM && mtype != P_PS2)
+ {
+ ms_setspeed(9600, mbaud, cflag[mtype]);
+ ms_setspeed(4800, mbaud, cflag[mtype]);
+ ms_setspeed(2400, mbaud, cflag[mtype]);
+ ms_setspeed(1200, mbaud, cflag[mtype]);
+
+ if (mtype == P_LOGI)
+ {
+ write(mfd, "S", 1);
+ ms_setspeed(mbaud, mbaud, cflag[P_MM]);
+ }
+
+ if (msample <= 0) write(mfd, "O", 1);
+ else if (msample <= 15) write(mfd, "J", 1);
+ else if (msample <= 27) write(mfd, "K", 1);
+ else if (msample <= 42) write(mfd, "L", 1);
+ else if (msample <= 60) write(mfd, "R", 1);
+ else if (msample <= 85) write(mfd, "M", 1);
+ else if (msample <= 125) write(mfd, "Q", 1);
+ else write(mfd, "N", 1);
+ }
+
+ mx = maxx;
+ my = maxy;
+ x = mx / 2;
+ y = my / 2;
+ return 0;
+}
+
+int
+get_ms_event(struct ms_event *ev)
+{
+ unsigned char buf[5];
+ char dx, dy;
+ int i, acc;
+
+ if (mfd == -1)
+ return -1;
+ if (mtype != P_BM)
+ {
+ if (read(mfd, &buf[0], 1) != 1)
+ return -1;
+restart:
+ /* find a header packet */
+ while ((buf[0] & proto[mtype][0]) != proto[mtype][1])
+ {
+ if (read(mfd, &buf[0], 1) != 1)
+ {
+ perror("get_ms_event: read");
+ return -1;
+ }
+ }
+
+ /* read in the rest of the packet */
+ for (i = 1; i < proto[mtype][4]; ++i)
+ {
+ if (read(mfd, &buf[i], 1) != 1)
+ {
+ perror("get_ms_event: read");
+ return -1;
+ }
+ /* check whether it's a data packet */
+ if (mtype != P_PS2 && ((buf[i] & proto[mtype][2]) != proto[mtype][3]
+ || buf[i] == 0x80))
+ goto restart;
+ }
+ }
+ else /* bus mouse */
+ {
+ while ((i = read(mfd, buf, 3)) != 3 && errno == EAGAIN)
+ usleep(40000);
+ if (i != 3)
+ {
+ perror("get_ms_event: read");
+ return -1;
+ }
+ }
+
+/* construct the event */
+ switch (mtype)
+ {
+ case P_MS: /* Microsoft */
+ default:
+ ev->ev_butstate = ((buf[0] & 0x20) >> 3) | ((buf[0] & 0x10) >> 4);
+ dx = (char)(((buf[0] & 0x03) << 6) | (buf[1] & 0x3F));
+ dy = (char)(((buf[0] & 0x0C) << 4) | (buf[2] & 0x3F));
+ break;
+ case P_SUN: /* Mouse Systems 3 byte as used in Sun workstations */
+ ev->ev_butstate = (~buf[0]) & 0x07;
+ dx = (char)(buf[1]);
+ dy = -(char)(buf[2]);
+ break;
+ case P_MSC: /* Mouse Systems Corp (5 bytes, PC) */
+ ev->ev_butstate = (~buf[0]) & 0x07;
+ dx = (char)(buf[1]) + (char)(buf[3]);
+ dy = - ((char)(buf[2]) + (char)(buf[4]));
+ break;
+ case P_MM: /* MM Series */
+ case P_LOGI: /* Logitech */
+ ev->ev_butstate = buf[0] & 0x07;
+ dx = (buf[0] & 0x10) ? buf[1] : - buf[1];
+ dy = (buf[0] & 0x08) ? - buf[2] : buf[2];
+ break;
+ case P_BM: /* BusMouse */
+ ev->ev_butstate = (~buf[0]) & 0x07;
+ dx = (char)buf[1];
+ dy = - (char)buf[2];
+ break;
+ case P_PS2: /* PS/2 Mouse */
+ ev->ev_butstate = 0;
+ if (buf[0] & 0x01)
+ ev->ev_butstate |= MS_BUTLEFT;
+ if (buf[0] & 0x02)
+ ev->ev_butstate |= MS_BUTRIGHT;
+ dx = (buf[0] & 0x10) ? buf[1]-256 : buf[1];
+ dy = - ((buf[0] & 0x20) ? buf[2]-256 : buf[2]);
+ break;
+ }
+
+ acc = (abs(ev->ev_dx) + abs(ev->ev_dy) > mdelta) ? maccel : 1;
+ ev->ev_dx = dx * acc;
+ ev->ev_dy = dy * acc;
+ x += ev->ev_dx;
+ y += ev->ev_dy;
+ limit(x, 0, mx);
+ limit(y, 0, my);
+ ev->ev_x = x;
+ ev->ev_y = y;
+ if (dx || dy)
+ {
+ if (ev->ev_butstate)
+ ev->ev_code = MS_DRAG;
+ else
+ ev->ev_code = MS_MOVE;
+ }
+ else
+ {
+ if (ev->ev_butstate)
+ ev->ev_code = MS_BUTDOWN;
+ else
+ ev->ev_code = MS_BUTUP;
+ }
+ return 0;
+}
--- /dev/null
+.\"
+.\" selection.1 - the cut and paste utility for Linux virtual consoles
+.\"
+.\" Modified by faith@cs.unc.edu
+.\"
+.TH SELECTION 1 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
+.SH NAME
+selection - the cut and paste utility for Linux virtual consoles
+.SH SYNTAX
+\fBselection [-a accel] [-b baud-rate] [-c l|m|r] [-d delta] [-m mouse-device] [-p l|m|r] [-s sample-rate] [-t mouse-type]\fR
+.SH DESCRIPTION
+\fBselection\fR is a utility that allows characters to be selected from the
+current Linux virtual console using the mouse and pasted into the current
+console. \fBselection\fR is normally invoked at boot time from /etc/rc.local,
+and runs as a background process.
+.SH OPTIONS
+.IP \fB\-a\fP\fIaccel\fP
+movements of more than \fIdelta\fP pixels are multiplied by \fIaccel\fP (default 2)
+.IP \fB\-b\fP\fIbaud-rate\fP
+set the baud rate of the mouse (default 1200 baud)
+.IP \fB\-c\fP\fIl|m|r\fP
+set the copy button to be the left, middle or right button (default left)
+.IP \fB\-d\fP\fIdelta\fP
+movements of more than \fIdelta\fP pixels are multiplied by \fIaccel\fP
+(default 25)
+.IP \fB\-m\fP\fImouse-device\fP
+specify the mouse device (default /dev/mouse)
+.IP \fB\-p\fP\fIl|m|r\fP
+set the paste button to be the left, middle or right button (default right)
+.IP \fB\-s\fP\fIsample-rate\fP
+set the sample rate of the mouse (default 100)
+.IP \fB\-t\fP\fImouse-type\fP
+specify the mouse type (Microsoft = `ms', Mouse Systems Corp = `msc',
+MM Series = `mm', Logitech = `logi', BusMouse = `bm',
+MSC 3-bytes = `sun', PS/2 = `ps2'; default = ms)
+.SH OPERATION
+To invoke the selection mechanism, press and release the copy button
+(the meaning of the buttons may be set at startup as above). A highlighted
+block will start moving around the screen, correlated with the movement of the
+mouse.
+.PP
+Move the block to the first character of the selection, then press and hold
+down the copy button.
+.PP
+Drag out the selection; the selected text will be highlighted. Then release
+the copy button. You can take the end of the selection to before the start of
+the selection if necessary.
+.PP
+Double-clicking the copy button while the highlighted block is on the
+screen selects text by word boundaries; treble-clicking selects by entire
+lines. If the button is held down after double- or treble-clicking, multiple
+words or lines may be selected. A word consists of a set of alphanumeric
+characters and underscores.
+.PP
+If a trailing space after the contents of a line is highlighted, and if there
+is no other text on the remainder of the line, the rest of the line will be
+selected automatically. If a number of lines are selected, highlighted
+trailing spaces on each line will be removed from the selection buffer.
+.PP
+Pressing the paste button in any virtual console pastes the
+selected text into the read queue of the associated tty.
+.PP
+Any output on the virtual console holding the selection will clear the
+highlighted selection from the screen, to maintain integrity of the display,
+although the contents of the paste buffer will be unaffected.
+.PP
+The selection mechanism is disabled if the controlling virtual console is
+placed in graphics mode, for example when running X11, and is re-enabled when
+text mode is resumed. (But see BUGS section below.)
+.SH FILES
+/dev/mouse - default mouse device
+.br
+/dev/tty0 - current VC device
+.SH DIAGNOSTICS
+\fBselection\fR complains if any of the devices it requires cannot be located.
+.SH BUGS
+The size of the paste buffer is set at 2048 bytes by default. This may be
+changed at compile time; consult the installation notes.
+.PP
+The selection mechanism doesn't work very well with graphics characters, or
+indeed with any characters where a mapping between the typed character and
+the displayed character is performed by the console driver. The selection
+mechanism pastes into the input buffer the character codes as they are
+displayed on the screen, not those originally typed in by the user.
+.PP
+Because of the way that the kernel bus mouse drivers work, allowing only one
+process to have the mouse device open at once, \fBselection\fR cannot
+co-exist with X11 using ATI XL, Logitech and Microsoft bus mice or with a
+PS/2 mouse. The X server will not start while \fBselection\fR is running.
+This problem is not present with serial mice.
+.SH AUTHOR
+.nf
+Andrew Haylett <ajh@gec-mrc.co.uk>
+.SH ACKNOWLEDGEMENTS
+.nf
+Lefty patches originally suggested by:
+.ti +4
+Sotiris C. Vassilopoulos <scv2f@edu.Virginia.acc.honi4>
+.br
+Logitech patches from:
+.ti +4
+Jim Winstead Jr <jwinstea@jarthur.Claremont.EDU>
+.br
+Command line options based on those from:
+.ti +4
+Peter Macdonald <pmacdona@sanjuan>
+.br
+Patches for bus mouse from:
+.br
+.ti +4
+Erik Troan <ewtroan@eos.ncsu.edu>
+.br
+.ti +4
+Christoph Niemann <niemann@rubdv15.etdv.ruhr-uni-bochum.de>
+.br
+.ti +4
+Koen Gadeyne <kmg@barco.be>
+.br
+Patches for PS/2 mouse from:
+.br
+.ti +4
+Hans D. Fink
+.br
+Patches for Sun mouse from:
+.br
+.ti +4
+Michael Haardt <michael@gandalf.moria>
+.br
+Run-time configurable mouse buttons suggested by:
+.br
+.ti +4
+Charlie Brady <charlieb@au.oz.tpl.tplrd>
+.br
+Setsid patches by:
+.bt
+.ti +4
+Rick Sladkey <jrs@world.std.com>
+.sp
+Apologies to any contributors whose names I have omitted.
--- /dev/null
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Wed Feb 22 16:09:31 1995 by faith@cs.unc.edu
+# Revised: Thu Oct 12 10:10:32 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
# Suggested changed from Bauke Jan Douma <bjdouma@xs4all.nl> have been
# Where to put man pages?
-MAN1= last.1 mesg.1 wall.1
+MAN1.MISC= last.1 mesg.1 wall.1
-MAN1.NONSHADOW= chfn.1 chsh.1 login.1 newgrp.1 passwd.1
+MAN1.PUTILS= chfn.1 chsh.1 login.1 newgrp.1
+MAN1.PASSWD= passwd.1
-MAN8= agetty.8 fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 \
- shutdown.8
+MAN8.GETTY= agetty.8
-MAN8.NONSHADOW= vipw.8
+MAN8.INIT= fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 shutdown.8
+
+MAN8.PUTILS= vipw.8
# Where to put binaries?
# See the "install" rule for the links. . .
-SBIN= agetty simpleinit shutdown
+SBIN.GETTY= agetty
-BIN.NONSHADOW= login
+SBIN.INIT= simpleinit shutdown
-USRBIN= last mesg wall
+BIN.PUTILS= login
-USRBIN.NONSHADOW= chfn chsh newgrp passwd
+USRBIN.MISC= last mesg wall
-USRSBIN.NONSHADOW= vipw
+USRBIN.PUTILS= chfn chsh newgrp
+USRBIN.PASSWD= passwd
-PASSWDDIR= /usr/bin
+USRSBIN.PUTILS= vipw
ifeq "$(HAVE_SHADOW)" "no"
-WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-nonshadow
-WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-nonshadow
+ifeq "$(HAVE_PASSWD)" "no"
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-passwd all-putils
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-passwd install-putils
+else
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-putils
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-putils
+endif
endif
ifeq "$(HAVE_SYSVINIT)" "no"
-WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-nonsysvinit
-WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-nonsysvinit
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-init
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-init
endif
-all: $(WHAT_TO_BUILD)
-all-nonshadow: $(BIN.NONSHADOW) $(USRBIN.NONSHADOW) $(USRSBIN.NONSHADOW)
-all-nonsysvinit: $(USRBIN) $(SBIN)
+ifeq "$(HAVE_SYSVINIT_UTILS)" "no"
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-misc
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-misc
+endif
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
+ifeq "$(HAVE_GETTY)" "no"
+WHAT_TO_BUILD:=$(WHAT_TO_BUILD) all-getty
+WHAT_TO_INSTALL:=$(WHAT_TO_INSTALL) install-getty
+endif
+
+all: $(WHAT_TO_BUILD)
+all-passwd: $(USRBIN.PASSWD)
+all-putils: $(BIN.PUTILS) $(USRBIN.PUTILS) $(USRSBIN.PUTILS)
+all-init: $(SBIN.INIT)
+all-getty: $(SBIN.GETTY)
+all-misc: $(USRBIN.MISC)
# Rules for everything else
chsh: chsh.o setpwnam.o
last.o: $(BSD)/pathnames.h
last: last.o $(BSD)/getopt.o
-login.o: $(BSD)/pathnames.h
-login: login.o
-mesg: mesg.o
+login: login.o checktty.o
+mesg: mesg.o $(BSD)/getopt.o $(BSD)/err.o
newgrp.o: $(BSD)/pathnames.h
newgrp: newgrp.o
-passwd: passwd.o islocal.o
+setpwnam.o: $(BSD)/pathnames.h
shutdown.o: $(BSD)/pathnames.h
shutdown: shutdown.o
simpleinit.o: $(BSD)/pathnames.h
vipw: vipw.o
wall: wall.o ttymsg.o
+ifeq "$(USE_TTY_GROUP)" "yes"
+login.o: login.c $(BSD)/pathnames.h
+ $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP login.c
+mesg.o: mesg.c $(BSD)/err.h
+ $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP mesg.c
+else
+login.o: $(BSD)/pathnames.h
+mesg.o: $(BSD)/err.h
+endif
+
+passwd: passwd.o islocal.o setpwnam.o
+passwd.o: passwd.c
+ $(CC) -c $(CFLAGS) -DUSE_SETPWNAM passwd.c
+
+ifeq "$(REQUIRE_PASSWORD)" "yes"
+CHSH_FLAGS:=$(CHSH_FLAGS) -DREQUIRE_PASSWORD
+endif
+
+ifeq "$(ONLY_LISTED_SHELLS)" "yes"
+CHSH_FLAGS:=$(CHSH_FLAGS) -DONLY_LISTED_SHELLS
+endif
+
+chsh.o: chsh.c
+ $(CC) -c $(CFLAGS) $(CHSH_FLAGS) chsh.c
+
+chfn.o: chfn.c
+ $(CC) -c $(CFLAGS) $(CHSH_FLAGS) chfn.c
+
install: all $(WHAT_TO_INSTALL)
-install-nonshadow:
- $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR)
- $(INSTALLBIN) $(BIN.NONSHADOW) $(BINDIR)
- $(INSTALLBIN) $(USRBIN.NONSHADOW) $(USRBINDIR)
- $(INSTALLBIN) $(USRSBIN.NONSHADOW) $(USRSBINDIR)
+install-putils: $(BIN.PUTILS) $(USRBIN.PUTILS) $(USRSBIN.PUTILS)
+ $(INSTALLDIR) $(BINDIR) $(USRBINDIR) $(USRSBINDIR)
+ $(INSTALLSUID) $(BIN.PUTILS) $(BINDIR)
+ $(INSTALLSUID) $(USRBIN.PUTILS) $(USRBINDIR)
+ $(INSTALLBIN) $(USRSBIN.PUTILS) $(USRSBINDIR)
$(INSTALLDIR) $(MAN1DIR) $(MAN8DIR)
- $(INSTALLMAN) $(MAN1.NONSHADOW) $(MAN1DIR)
- $(INSTALLMAN) $(MAN8.NONSHADOW) $(MAN8DIR)
- chown root $(USRBINDIR)/chsh
- chmod u+s $(USRBINDIR)/chsh
- chown root $(USRBINDIR)/chfn
- chmod u+s $(USRBINDIR)/chfn
- chown root $(USRBINDIR)/newgrp
- chmod u+s $(USRBINDIR)/newgrp
- chown root $(PASSWDDIR)/passwd
- chmod u+s $(PASSWDDIR)/passwd
- chown root $(BINDIR)/login
- chmod u+s $(BINDIR)/login
-
-install-nonsysvinit:
- $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRBINDIR)
- $(INSTALLBIN) $(SBIN) $(SBINDIR)
+ $(INSTALLMAN) $(MAN1.PUTILS) $(MAN1DIR)
+ $(INSTALLMAN) $(MAN8.PUTILS) $(MAN8DIR)
+
+install-passwd: $(USRBIN.PASSWD)
+ $(INSTALLDIR) $(USRBINDIR)
+ $(INSTALLSUID) $(USRBIN.PASSWD) $(USRBINDIR)
+ $(INSTALLDIR) $(MAN1DIR)
+ $(INSTALLMAN) $(MAN1.PASSWD) $(MAN1DIR)
+
+install-init: $(SBIN.INIT)
+ $(INSTALLDIR) $(SBINDIR)
+ $(INSTALLBIN) $(SBIN.INIT) $(SBINDIR)
+ $(INSTALLDIR) $(MAN8DIR)
+ $(INSTALLMAN) $(MAN8.INIT) $(MAN8DIR)
+ # Make *relative* links for these
(cd $(SHUTDOWNDIR); ln -sf shutdown reboot)
(cd $(SHUTDOWNDIR); ln -sf shutdown fastboot)
(cd $(SHUTDOWNDIR); ln -sf shutdown halt)
(cd $(SHUTDOWNDIR); ln -sf shutdown fasthalt)
- $(INSTALLBIN) $(USRBIN) $(USRBINDIR)
- $(INSTALLDIR) $(MAN1DIR) $(MAN8DIR)
- $(INSTALLMAN) $(MAN1) $(MAN1DIR)
- $(INSTALLMAN) $(MAN8) $(MAN8DIR)
+
+
+install-getty: $(SBIN.GETTY)
+ $(INSTALLDIR) $(SBINDIR)
+ $(INSTALLBIN) $(SBIN.GETTY) $(SBINDIR)
+ $(INSTALLDIR) $(MAN8DIR)
+ $(INSTALLMAN) $(MAN8.GETTY) $(MAN8DIR)
+
+install-misc: $(USRBIN.MISC)
+ $(INSTALLDIR) $(USRBINDIR)
+ $(INSTALLBIN) $(USRBIN.MISC) $(USRBINDIR)
+ $(INSTALLDIR) $(MAN1DIR)
+ $(INSTALLMAN) $(MAN1.MISC) $(MAN1DIR)
+ifeq "$(USE_TTY_GROUP)" "yes"
+ chgrp tty $(USRBINDIR)/wall
+ chmod g+s $(USRBINDIR)/wall
+endif
.PHONY: clean
clean:
- -rm -f *.o *~ core $(SBIN) $(BIN) $(BIN.NONSHADOW) $(USRBIN) \
- $(USRBIN.NONSHADOW) $(USRSBIN.NONSHADOW)
+ -rm -f *.o *~ core $(BIN.PASSWD) $(SBIN.GETTY) $(SBIN.INIT) \
+ $(USRBIN.MISC) $(USRBIN.PASSWD) $(USRBIN.PUTILS) \
+ $(USRSBIN.PUTILS) $(BIN.PUTILS)
-README file for the admutils V1.14 for Linux.
+README file for the admutils V1.16 for Linux.
See installation instructions at the bottom. Currently the latest versions
of this software is maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/
This software is distributed as is without any warranty what so ever.
With respect to copyrights it is covered by the GNU Public License.
+Version 1.17 (7-Oct-95):
+ Added setrlimit() calls to passwd.c and chsh.c to fix security hole
+ caused by resource limitations. Inspired by Zefram
+ <A.Main@dcs.warwick.ac.uk>. Also beefed up the ptmp locking in
+ chsh.c.
+ Added swap_off() function to shutdown.c by baekgrd@ibm.net
+ (Anders Baekgaard).
+ Bugfix in shutdown.c that makes sure wtmp gets closed. By
+ Alexandre Julliard <julliard@sunsite.unc.edu>.
+ Fixed bug in passwd.c that made it impossible to change from having
+ no password into having one.
+
+Version 1.16 (18-Sep-95):
+ Added feature to passwd.c by Arpad Magossanyi (mag@tas.vein.hu),
+ so root can give a password for a user on the command line. This
+ might be useful in a shell script autogenerating passwords for
+ new users.
+
+ Added and updated manual pages for all commands by Rick Faith.
+
+Version 1.15d (21-Aug-95):
+ Fixed minor nit with salt generation in passwd.c
+ By Steven Reisman <sar@beehive.mn.org>.
+
+Version 1.15c (5-Jul-95):
+ passwd does not allow reuse of the old password when changing.
+ passwd returns 1 if the password is not changed. This was
+ suggested by Anibal Jodorcovsky <anibal@ee.mcgill.ca> who
+ also fixed my initial bug in this feature.
+
+ passwd uses O_EXCL for opening /etc/ptmp instead of access/fopen.
+ This was suggested by jorge@un1.satlink.com (Jorge).
+
+Version 1.15a (12-Jun-95):
+ Fix in last.c so it does not print wtmp entries marked DEAD_PROCESS.
+ By Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+
+Version 1.15 (5-Jun-95):
+ Man-page fixes, fixes in pathnames.h to adhere to the FSSTND.
+ Fix by Rickard Faith <faith@cs.unc.edu> to passwd.c, so sanity
+ checks come before the second entry of the new password.
+ This is for Linux 1.2, GCC 2.6.2 or later.
+
+Version 1.14a (12-Mar-95):
+ Fixed passwd and chsh so a username that is a prefix of another
+ doesn't affect the other's password. After suggested patch
+ by Valtteri J. Karu <vatekaru@tuug.utu.fi>, but differently!
+
Version 1.14 (12-Feb-95):
Added options -l, -y, -i to last.c. See last.man
README for init/getty/login, by poe@daimi.aau.dk
-This package contains init, getty, and login programs for Linux.
+This package contains simpleinit, agetty, and login programs for Linux.
Additional utilities included are: hostname, who, write, wall, users
domainname, hostid, cage and mesg.
About installation: See the bottom of this file. Check the Makefile!
Be sure you know what you are doing! You may well be able to lock
-yourself out from your machine.
+yourself out from your machine. Especially: The init provided here
+(simpleinit) is NOT a SYSV compatible init and the inittab format
+is different.
If you are uncertain whether you got the latest version, check out
ftp://ftp.daimi.aau.dk:/pub/linux/poe/
+Version 1.37 (15-Sep-95):
+ Added -I <initstring> and -w options to agetty.c for those that
+ use agetty with modems.
+
+Version 1.36 (25-Aug-95):
+ Enhanced /etc/usertty features with group support. Moved this part
+ of login.c to checktty.c. One can now define classes of hosts and
+ ttys and do access checking based on unix-group membership. See
+ login.1. Also time ranges for logins can be specified, for example
+ writing the line
+
+ joe [mon:tue:wed:thu:fri:8-16]@barracuda [mon:tue:wed:thu:fri:0-7:17-23]@joes.pc.at.home [sat:sun:0-23]@joes.pc.at.home
+
+ says that during working hours, Joe may rlogin from the host
+ barracuda, whereas outside working hours and in weekends Joe may
+ rlogin from his networked PC at home.
+
+ login.c: failures was not properly initialized, it now is. Also
+ made sure ALL failures are really logged to syslog.
+
+Version 1.35 (7-Aug-95):
+ login.c: Much improved features for the usertty file, allows
+ access control based on both hostnames/addresses and line. See the
+ about.usertty file and the man-page.
+
+ Fixed agetty so it doesn't fiddle with the ut_id field in the
+ utmp record, this should prevent growing utmps on systems with
+ more than 10 login lines. Fix suggested and checked by Alan Wendt
+ <alan@ezlink.com> in his agetty.1.9.1a.
+
+ Agetty now installs as agetty again, not as getty.
+ Updated man-page for login(1) to document /etc/usertty changes.
+
+ This has been tested on Linux 1.2.5 with GCC 2.5.8 and libc 4.5.26.
+
+Version 1.33a (20-Jun-95):
+ rchatfie@cavern.nmsu.edu ("rc.") suggested that I should remove
+ the #ifndef linux around the special logging of dial-up
+ logins. This is now done, so each login via a serial port
+ generates a separate DIALUP syslog entry.
+
+Version 1.33 (5-Jun-95):
+ Patch by Ron Sommeling <sommel@sci.kun.nl> and
+ jlaiho@ichaos.nullnet.fi (Juha Laiho) for agetty.c, used
+ to return a pointer to an automatic variable in get_logname().
+ Many patches from or via Rickard Faith <faith@cs.unc.edu>, fixing
+ man-pages etc, now defaults to using /var/log/wtmp and /var/run/utmp
+ according to the new FSSTND.
+
+ Fix in login.c for CPU eating bug when a remote telnet client dies
+ while logging in.
+
+ This is for Linux 1.2, GCC 2.6.2 or later.
+
+Version 1.32b (12-Mar-95):
+ Login now sets the tty group to "tty" instead of "other". Depending
+ on compile-time define USE_TTY_GROUP the tty mode is set to 0620 or
+ 0600 instead of 0622. All as per suggestion by Rik Faith and the
+ linux-security list.
+ Write/wall now strips control chars except BEL (\007). Again after
+ suggestion by Rik Faith.
+
+Version 1.32a
+ Urgent security patch from Alvaro M. Echevarria incorporated into
+ login.c. This is really needed on machines running YP until
+ the libraries are fixed.
+
Version 1.32
Login now logs the ip-address of the connecting host to utmp as it
should.
.SH SYNOPSIS
.na
.nf
-agetty [-ihL] [-l login_program] [-m] [-t timeout] port baud_rate,... [term]
-agetty [-ihL] [-l login_program] [-m] [-t timeout] baud_rate,... port [term]
+agetty [-ihLmw] [-l login_program] [-I init] [-t timeout] port baud_rate,... [term]
+agetty [-ihLmw] [-l login_program] [-I init] [-t timeout] baud_rate,... port [term]
.SH DESCRIPTION
.ad
.fi
when receiving lots of text at the wrong baud rate; dial-up scripts
may fail if the login prompt is preceded by too much text.
.TP
+-I initstring
+Set an initial string to be sent to the tty or modem before sending
+anything else. This may be used to initialize a modem. Non printable
+characters may be sent by writing their octal code preceded by a
+backslash (\\). For example to send a linefeed character (ASCII 10,
+octal 012) write \\012.
+.PP
+.TP
-l login_program
Invoke the specified \fIlogin_program\fP instead of /bin/login.
This allows the use of a non-standard login program (for example,
Force the line to be local line with no need for carrier detect. This can
be useful when you have locally attached terminal where the serial line
does not set the carrier detect signal.
-
+.TP
+-w
+Wait for the user or the modem to send a carriage-return or a linefeed
+character before sending the /etc/issue file and the login prompt.
+.PP
.SH EXAMPLES
.na
.nf
.SH FILES
.na
.nf
-/etc/utmp, the system status file (System V only).
+/var/run/utmp, the system status file.
/etc/issue, printed before the login prompt (System V only).
/dev/console, problem reports (if syslog(3) is not used).
/etc/inittab (Linux simpleinit(8) configuration file).
Depending on how the program was configured, all diagnostics are
written to the console device or reported via the syslog(3) facility.
Error messages are produced if the \fIport\fP argument does not
-specify a terminal device; if there is no /etc/utmp entry for the
+specify a terminal device; if there is no utmp entry for the
current process (System V only); and so on.
.SH AUTHOR(S)
.na
int numspeed; /* number of baud rates to try */
int speeds[MAX_SPEED]; /* baud rates to be tried */
char *tty; /* name of tty */
+ char *initstring; /* modem init string */
};
#define F_PARSE (1<<0) /* process modem status messages */
#define F_ISSUE (1<<1) /* display /etc/issue */
#define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */
#define F_LOCAL (1<<3) /* force local */
+#define F_INITSTRING (1<<4) /* initstring is set */
+#define F_WAITCRLF (1<<5) /* wait for CR or LF */
/* Storage for things detected while the login name was read. */
char **argv;
{
char *logname; /* login name, given to /bin/login */
- char *get_logname();
struct chardata chardata; /* set by get_logname() */
struct termio termio; /* terminal mode bits */
static struct options options = {
/* Initialize the termio settings (raw mode, eight-bit, blocking i/o). */
termio_init(&termio, options.speeds[FIRST_SPEED], options.flags & F_LOCAL);
-
+
+ /* write the modem init string and flush the buffers */
+ if (options.flags & F_INITSTRING) {
+ write(1, options.initstring, strlen(options.initstring));
+ ioctl(1, TCFLSH, 2);
+ }
+
/* Optionally detect the baud rate from the modem status message. */
if (options.flags & F_PARSE)
if (options.timeout)
(void) alarm((unsigned) options.timeout);
+ /* optionally wait for CR or LF before writing /etc/issue */
+ if (options.flags & F_WAITCRLF) {
+ char ch;
+
+ while(read(0, &ch, 1) == 1) {
+ ch &= 0x7f; /* strip "parity bit" */
+ if (ch == '\n' || ch == '\r') break;
+ }
+ }
+
/* Read the login name. */
while ((logname = get_logname(&options, &chardata, &termio)) == 0)
extern int optind; /* getopt */
int c;
- while (isascii(c = getopt(argc, argv, "Lhil:mt:"))) {
+ while (isascii(c = getopt(argc, argv, "I:Lhil:mt:w"))) {
switch (c) {
+ case 'I':
+ if (!(op->initstring = malloc(strlen(optarg)))) {
+ error("can't malloc initstring");
+ break;
+ }
+ {
+ char ch, *p, *q;
+ int i;
+
+ /* copy optarg into op->initstring decoding \ddd
+ octal codes into chars */
+ q = op->initstring;
+ p = optarg;
+ while (*p) {
+ if (*p == '\\') { /* know \\ means \ */
+ p++;
+ if (*p == '\\') {
+ ch = '\\';
+ p++;
+ } else { /* handle \000 - \177 */
+ ch = 0;
+ for (i = 1; i <= 3; i++) {
+ if (*p >= '0' && *p <= '7') {
+ ch <<= 3;
+ ch += *p - '0';
+ p++;
+ } else
+ break;
+ }
+ }
+ *q++ = ch;
+ } else {
+ *q++ = *p++;
+ }
+ }
+ *q = '\0';
+ }
+ op->flags |= F_INITSTRING;
+ break;
+
case 'L': /* force local */
op->flags |= F_LOCAL;
break;
if ((op->timeout = atoi(optarg)) <= 0)
error("bad timeout value: %s", optarg);
break;
+ case 'w':
+ op->flags |= F_WAITCRLF;
+ break;
default:
usage();
}
long time();
long lseek();
char *strncpy();
+ struct utmp *utp;
/*
* The utmp file holds miscellaneous information about things started by
- * /etc/init and other system-related events. Our purpose is to update
+ * /sbin/init and other system-related events. Our purpose is to update
* the utmp entry for the current process, in particular the process type
* and the tty line we are listening to. Return successfully only if the
* utmp file can be opened for update, and if we are able to find our
*/
#ifdef linux
- utmpname(_PATH_UTMP);
- memset(&ut, 0, sizeof(ut));
- (void) strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
- (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- (void) strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
- (void) time(&ut.ut_time);
- ut.ut_type = LOGIN_PROCESS;
- ut.ut_pid = mypid;
-
- pututline(&ut);
- endutent();
-
- if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
- flock(ut_fd, LOCK_EX);
- write(ut_fd, &ut, sizeof(ut));
- flock(ut_fd, LOCK_UN);
- close(ut_fd);
- }
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent())
+ && !(utp->ut_type == INIT_PROCESS
+ && utp->ut_pid == mypid)) /* nothing */;
+
+ if (utp) {
+ memcpy(&ut, utp, sizeof(ut));
+ } else {
+ /* some inits don't initialize utmp... */
+ memset(&ut, 0, sizeof(ut));
+ strncpy(ut.ut_id, line + 3, sizeof(ut.ut_id));
+ }
+ endutent();
+
+ strncpy(ut.ut_user, "LOGIN", sizeof(ut.ut_user));
+ strncpy(ut.ut_line, line, sizeof(ut.ut_line));
+ time(&ut.ut_time);
+ ut.ut_type = LOGIN_PROCESS;
+ ut.ut_pid = mypid;
+
+ pututline(&ut);
+ endutent();
+
+ if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
+ flock(ut_fd, LOCK_EX);
+ write(ut_fd, &ut, sizeof(ut));
+ flock(ut_fd, LOCK_UN);
+ close(ut_fd);
+ }
#else
if ((ut_fd = open(UTMP_FILE, 2)) < 0) {
error("%s: open for update: %m", UTMP_FILE);
buf[nread] = '\0';
for (bp = buf; bp < buf + nread; bp++) {
if (isascii(*bp) && isdigit(*bp)) {
- if (speed = bcode(bp)) {
+ if ((speed = bcode(bp))) {
tp->c_cflag &= ~CBAUD;
tp->c_cflag |= speed;
}
int users = 0;
struct utmp *ut;
setutent();
- while (ut = getutent())
+ while ((ut = getutent()))
if (ut->ut_type == USER_PROCESS)
users++;
endutent();
struct chardata *cp;
struct termio *tp;
{
- char logname[BUFSIZ];
+ static char logname[BUFSIZ];
char *bp;
char c; /* input character, full eight bits */
char ascval; /* low 7 bits of input character */
}
/* Handle names with upper case and no lower case. */
- if (cp->capslock = caps_lock(logname)) {
+ if ((cp->capslock = caps_lock(logname))) {
for (bp = logname; *bp; bp++)
if (isupper(*bp))
*bp = tolower(*bp); /* map name to lower case */
--- /dev/null
+/* checktty.c - linked into login, checks user against /etc/usertty
+ Created 25-Aug-95 by Peter Orbaek <poe@daimi.aau.dk>
+*/
+
+#include <pwd.h>
+#include <grp.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <malloc.h>
+#include <netdb.h>
+#include <sys/syslog.h>
+
+#ifdef linux
+# include <sys/sysmacros.h>
+# include <linux/major.h>
+#endif
+
+#include "pathnames.h"
+
+/* functions in login.c */
+void badlogin(char *s);
+void sleepexit(int);
+extern struct hostent hostaddress;
+extern char *hostname;
+
+#ifdef TESTING
+struct hostent hostaddress;
+char *hostname;
+
+void
+badlogin(char *s)
+{
+ printf("badlogin: %s\n", s);
+}
+
+void
+sleepexit(int x)
+{
+ printf("sleepexit %d\n", x);
+ exit(1);
+}
+#endif
+
+#define NAMELEN 128
+
+/* linked list of names */
+struct grplist {
+ struct grplist *next;
+ char name[NAMELEN];
+};
+
+struct grplist *mygroups = NULL;
+
+enum State { StateUsers, StateGroups, StateClasses };
+
+#define CLASSNAMELEN 32
+
+struct ttyclass {
+ struct grplist *first;
+ struct ttyclass *next;
+ char classname[CLASSNAMELEN];
+};
+
+struct ttyclass *ttyclasses = NULL;
+
+static void
+add_group(char *group)
+{
+ struct grplist *ge;
+
+ ge = (struct grplist *)malloc(sizeof(struct grplist));
+
+ /* we can't just bail out at this stage! */
+ if (!ge) {
+ printf("login: memory low, login may fail\n");
+ syslog(LOG_WARNING, "can't malloc grplist");
+ return;
+ }
+
+ ge->next = mygroups;
+ strncpy(ge->name, group, NAMELEN);
+ mygroups = ge;
+}
+
+static int
+am_in_group(char *group)
+{
+ struct grplist *ge;
+
+ for (ge = mygroups; ge; ge = ge->next) {
+ if (strcmp(ge->name, group) == 0) return 1;
+ }
+ return 0;
+}
+
+static void
+find_groups(gid_t defgrp, char *user)
+{
+ struct group *gp;
+ char **p;
+
+ setgrent();
+ while ((gp = getgrent())) {
+ if (gp->gr_gid == defgrp) {
+ add_group(gp->gr_name);
+ } else {
+ for(p = gp->gr_mem; *p; p++) {
+ if (strcmp(user, *p) == 0) {
+ add_group(gp->gr_name);
+ break;
+ }
+ }
+ }
+
+ }
+ endgrent();
+}
+
+static struct ttyclass *
+new_class(char *class)
+{
+ struct ttyclass *tc;
+
+ tc = (struct ttyclass *)malloc(sizeof(struct ttyclass));
+ if (tc == NULL) {
+ printf("login: memory low, login may fail\n");
+ syslog(LOG_WARNING, "can't malloc for ttyclass");
+ return NULL;
+ }
+
+ tc->next = ttyclasses;
+ tc->first = NULL;
+ strncpy(tc->classname, class, CLASSNAMELEN);
+ ttyclasses = tc;
+ return tc;
+}
+
+static void
+add_to_class(struct ttyclass *tc, char *tty)
+{
+ struct grplist *ge;
+
+ if (tc == NULL) return;
+
+ ge = (struct grplist *)malloc(sizeof(struct grplist));
+ if (ge == NULL) {
+ printf("login: memory low, login may fail\n");
+ syslog(LOG_WARNING, "can't malloc for grplist");
+ return;
+ }
+
+ ge->next = tc->first;
+ strncpy(ge->name, tty, NAMELEN);
+ tc->first = ge;
+}
+
+
+/* return true if tty is a pty. Very linux dependent */
+static int
+isapty(tty)
+ char *tty;
+{
+ char devname[100];
+ struct stat stb;
+
+#ifdef linux
+ strcpy(devname, "/dev/");
+ strncat(devname, tty, 80);
+ if((stat(devname, &stb) >= 0)
+ && major(stb.st_rdev) == TTY_MAJOR
+ && minor(stb.st_rdev) >= 192) {
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/* match the hostname hn against the pattern pat */
+static int
+hnmatch(hn, pat)
+ char *hn;
+ char *pat;
+{
+ int x1, x2, x3, x4, y1, y2, y3, y4;
+ unsigned long p, mask, a;
+ unsigned char *ha;
+ int n, m;
+
+ if ((hn == NULL) && (strcmp(pat, "localhost") == 0)) return 1;
+ if ((hn == NULL) || hn[0] == 0) return 0;
+
+ if (pat[0] >= '0' && pat[0] <= '9') {
+ /* pattern is an IP QUAD address and a mask x.x.x.x/y.y.y.y */
+ sscanf(pat, "%d.%d.%d.%d/%d.%d.%d.%d", &x1, &x2, &x3, &x4,
+ &y1, &y2, &y3, &y4);
+ p = (((unsigned long)x1<<24)+((unsigned long)x2<<16)
+ +((unsigned long)x3<<8)+((unsigned long)x4));
+ mask = (((unsigned long)y1<<24)+((unsigned long)y2<<16)
+ +((unsigned long)y3<<8)+((unsigned long)y4));
+
+ if (!hostaddress.h_addr_list || !hostaddress.h_addr_list[0])
+ return 0;
+
+ ha = (unsigned char *)hostaddress.h_addr_list[0];
+ a = (((unsigned long)ha[0]<<24)+((unsigned long)ha[1]<<16)
+ +((unsigned long)ha[2]<<8)+((unsigned long)ha[3]));
+ return ((p & mask) == (a & mask));
+ } else {
+ /* pattern is a suffix of a FQDN */
+ n = strlen(pat);
+ m = strlen(hn);
+ if (n > m) return 0;
+ return (strcasecmp(pat, hn + m - n) == 0);
+ }
+}
+
+static char *wdays[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
+
+/* example timespecs:
+
+ mon:tue:wed:8-17
+
+ meaning monday, tuesday or wednesday between 8:00 and 17:59
+
+ 4:5:13:fri
+
+ meaning fridays from 4:00 to 5:59 and from 13:00 to 13:59
+*/
+static int
+timeok(struct tm *t, char *spec)
+{
+ char *p, *q;
+ int dayok = 0;
+ int hourok = 0;
+ int h, h2;
+ char *sp;
+
+ sp = spec;
+ while ((p = strsep(&sp, ":"))) {
+ if (*p >= '0' && *p <= '9') {
+ h = atoi(p);
+ if (h == t->tm_hour) hourok = 1;
+ if ((q = strchr(p, '-')) && (q[1] >= '0' && q[1] <= '9')) {
+ h2 = atoi(q+1);
+ if (h <= t->tm_hour && t->tm_hour <= h2) hourok = 1;
+ }
+ } else if (strcasecmp(wdays[t->tm_wday], p) == 0) {
+ dayok = 1;
+ }
+ }
+
+ return (dayok && hourok);
+}
+
+/* return true if tty equals class or is in the class defined by class.
+ Also return true if hostname matches the hostname pattern, class
+ or a pattern in the class named by class. */
+static int
+in_class(char *tty, char *class)
+{
+ struct ttyclass *tc;
+ struct grplist *ge;
+ time_t t;
+ char *p;
+ char timespec[256];
+ struct tm *tm;
+ char *n;
+
+ time(&t);
+ tm = localtime(&t);
+
+ if (class[0] == '[') {
+ if ((p = strchr(class, ']'))) {
+ *p = 0;
+ strcpy(timespec, class+1);
+ *p = ']';
+ if(!timeok(tm, timespec)) return 0;
+ class = p+1;
+ }
+ /* really ought to warn about syntax error */
+ }
+
+ if (strcmp(tty, class) == 0) return 1;
+
+ if ((class[0] == '@') && isapty(tty)
+ && hnmatch(hostname, class+1)) return 1;
+
+ for (tc = ttyclasses; tc; tc = tc->next) {
+ if (strcmp(tc->classname, class) == 0) {
+ for (ge = tc->first; ge; ge = ge->next) {
+
+ n = ge->name;
+ if (n[0] == '[') {
+ if ((p = strchr(n, ']'))) {
+ *p = 0;
+ strcpy(timespec, n+1);
+ *p = ']';
+ if(!timeok(tm, timespec)) continue;
+ n = p+1;
+ }
+ /* really ought to warn about syntax error */
+ }
+
+ if (strcmp(n, tty) == 0) return 1;
+
+ if ((n[0] == '@') && isapty(tty)
+ && hnmatch(hostname, n+1)) return 1;
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+void
+checktty(user, tty, pwd)
+ char *user;
+ char *tty;
+ struct passwd *pwd;
+{
+ FILE *f;
+ char buf[256], defaultbuf[256];
+ char *ptr;
+ enum State state = StateUsers;
+ int found_match = 0;
+
+ /* no /etc/usertty, default to allow access */
+#ifdef TESTING
+ if (!(f = fopen("usertty", "r"))) return;
+#else
+ if (!(f = fopen(_PATH_USERTTY, "r"))) return;
+#endif
+
+ if (pwd == NULL) return; /* misspelled username handled elsewhere */
+
+ find_groups(pwd->pw_gid, user);
+
+ defaultbuf[0] = 0;
+ while(fgets(buf, 255, f)) {
+
+ /* strip comments */
+ for(ptr = buf; ptr < buf + 256; ptr++)
+ if(*ptr == '#') *ptr = 0;
+
+ if (buf[0] == '*') {
+ strncpy(defaultbuf, buf, 256);
+ continue;
+ }
+
+ if (strncmp("GROUPS", buf, 6) == 0) {
+ state = StateGroups;
+ continue;
+ } else if (strncmp("USERS", buf, 5) == 0) {
+ state = StateUsers;
+ continue;
+ } else if (strncmp("CLASSES", buf, 7) == 0) {
+ state = StateClasses;
+ continue;
+ }
+
+ strtok(buf, " \t");
+ if((state == StateUsers && (strncmp(user, buf, 8) == 0))
+ || (state == StateGroups && am_in_group(buf))) {
+ found_match = 1; /* we found a line matching the user */
+ while((ptr = strtok(NULL, "\t\n "))) {
+ if (in_class(tty, ptr)) {
+ fclose(f);
+ return;
+ }
+ }
+ } else if (state == StateClasses) {
+ /* define a new tty/host class */
+ struct ttyclass *tc = new_class(buf);
+
+ while ((ptr = strtok(NULL, "\t\n "))) {
+ add_to_class(tc, ptr);
+ }
+ }
+ }
+ fclose(f);
+
+ /* user is not explicitly mentioned in /etc/usertty, if there was
+ a default rule, use that */
+ if (defaultbuf[0]) {
+ strtok(defaultbuf, " \t");
+ while((ptr = strtok(NULL, "\t\n "))) {
+ if (in_class(tty, ptr)) return;
+ }
+
+ /* there was a default rule, but user didn't match, reject! */
+ printf("Login on %s from %s denied by default.\n", tty, hostname);
+ badlogin(user);
+ sleepexit(1);
+ }
+
+ if (found_match) {
+ /* if we get here, /etc/usertty exists, there's a line
+ matching our username, but it doesn't contain the
+ name of the tty where the user is trying to log in.
+ So deny access! */
+
+ printf("Login on %s from %s denied.\n", tty, hostname);
+ badlogin(user);
+ sleepexit(1);
+ }
+
+ /* users not matched in /etc/usertty are by default allowed access
+ on all tty's */
+}
+
+#ifdef TESTING
+main(int argc, char *argv[])
+{
+ struct passwd *pw;
+
+ pw = getpwnam(argv[1]);
+ checktty(argv[1], argv[2], pw);
+}
+#endif
.\" modify it under the terms of the gnu general public license.
.\" there is no warranty.
.\"
-.\" faith
-.\" 1.1.1.1
-.\" 1995/02/22 19:09:24
+.\" $Author: faith $
+.\" $Revision: 1.1 $
+.\" $Date: 1995/03/12 01:29:16 $
.\"
.TH CHFN 1 "October 13 1994" "chfn" "Linux Reference Manual"
.SH NAME
* modify it under the terms of the gnu general public license.
* there is no warranty.
*
- * faith
- * 1.1.1.1
- * 1995/02/22 19:09:24
+ * $Author: faith $
+ * $Revision: 1.8 $
+ * $Date: 1995/10/12 14:46:35 $
+ *
+ * Updated Thu Oct 12 09:19:26 1995 by faith@cs.unc.edu with security
+ * patches from Zefram <A.Main@dcs.warwick.ac.uk>
*
*/
-#define _POSIX_SOURCE 1
+static char rcsId[] = "$Version: $Id: chfn.c,v 1.8 1995/10/12 14:46:35 faith Exp $ $";
#include <sys/types.h>
#include <stdio.h>
#define false 0
#define true 1
-static char *version_string = "chfn 0.9 beta";
+static char *version_string = "chfn 0.9a beta";
static char *whoami;
static char buf[1024];
static boolean set_changed_data P((struct finfo *oldfp, struct finfo *newfp));
static int save_new_data P((struct finfo *pinfo));
static void *xmalloc P((int bytes));
+#if 0
extern int strcasecmp P((char *, char *));
extern int setpwnam P((struct passwd *pwd));
+#endif
#define memzero(ptr, size) memset((char *) ptr, 0, size)
int main (argc, argv)
int argc;
char *argv[];
{
- char *cp;
+ char *cp, *pwdstr;
uid_t uid;
struct finfo oldf, newf;
boolean interactive;
for (cp = whoami; *cp; cp++)
if (*cp == '/') whoami = cp + 1;
- umask (022);
-
/*
* "oldf" contains the users original finger information.
* "newf" contains the changed finger information, and contains NULL
perror (whoami);
return (-1);
}
-
+
+ printf ("Changing finger information for %s.\n", oldf.username);
+
+#if REQUIRE_PASSWORD
+ /* require password, unless root */
+ if(uid != 0 && oldf.pw->pw_passwd && oldf.pw->pw_passwd[0]) {
+ pwdstr = getpass("Password: ");
+ if(strncmp(oldf.pw->pw_passwd,
+ crypt(pwdstr, oldf.pw->pw_passwd), 13)) {
+ puts("Incorrect password.");
+ exit(1);
+ }
+ }
+#endif
+
+
if (interactive) ask_info (&oldf, &newf);
if (! set_changed_data (&oldf, &newf)) {
struct finfo *oldfp;
struct finfo *newfp;
{
- printf ("Changing finger information for %s.\n", oldfp->username);
newfp->full_name = prompt ("Name", oldfp->full_name);
newfp->office = prompt ("Office", oldfp->office);
newfp->office_phone = prompt ("Office Phone", oldfp->office_phone);
pinfo->pw->pw_gecos = gecos;
if (setpwnam (pinfo->pw) < 0) {
perror ("setpwnam");
+ printf( "Finger information *NOT* changed. Try again later.\n" );
return (-1);
}
printf ("Finger information changed.\n");
.\" modify it under the terms of the gnu general public license.
.\" there is no warranty.
.\"
-.\" faith
-.\" 1.1.1.1
-.\" 1995/02/22 19:09:23
+.\" $Author: faith $
+.\" $Revision: 1.1 $
+.\" $Date: 1995/03/12 01:28:58 $
.\"
.TH CHSH 1 "October 13 1994" "chsh" "Linux Reference Manual"
.SH NAME
* modify it under the terms of the gnu general public license.
* there is no warranty.
*
- * faith
- * 1.1.1.1
- * 1995/02/22 19:09:23
+ * $Author: faith $
+ * $Revision: 1.8 $
+ * $Date: 1995/10/12 14:46:35 $
+ *
+ * Updated Thu Oct 12 09:33:15 1995 by faith@cs.unc.edu with security
+ * patches from Zefram <A.Main@dcs.warwick.ac.uk>
*
*/
+static char rcsId[] = "$Version: $Id: chsh.c,v 1.8 1995/10/12 14:46:35 faith Exp $ $";
+
+#if 0
#define _POSIX_SOURCE 1
+#endif
#include <sys/types.h>
#include <stdio.h>
#define false 0
#define true 1
-static char *version_string = "chsh 0.9 beta";
+static char *version_string = "chsh 0.9a beta";
static char *whoami;
static char buf[FILENAME_MAX];
int argc;
char *argv[];
{
- char *cp, *shell;
+ char *cp, *shell, *oldshell, *pwdstr;
uid_t uid;
struct sinfo info;
struct passwd *pw;
for (cp = whoami; *cp; cp++)
if (*cp == '/') whoami = cp + 1;
- umask (022);
-
uid = getuid ();
memzero (&info, sizeof (info));
return (-1); }
}
+ oldshell = pw->pw_shell;
+ if (!oldshell[0]) oldshell = "/bin/sh";
+
/* reality check */
+#if 0
+ /* Require current shell to be in list.
+ This is not a reasonable expectation on
+ most Linux systems, and the error is
+ confusing. */
+ if (uid != 0 && (uid != pw->pw_uid || !get_shell_list(oldshell))) {
+#else
if (uid != 0 && uid != pw->pw_uid) {
+#endif
errno = EACCES;
perror (whoami);
return (-1);
}
shell = info.shell;
+
+ printf( "Changing shell for %s.\n", pw->pw_name );
+
+#ifdef REQUIRE_PASSWORD
+ /* require password, unless root */
+ if(uid != 0 && pw->pw_passwd && pw->pw_passwd[0]) {
+ pwdstr = getpass("Password: ");
+ if(strncmp(pw->pw_passwd, crypt(pwdstr, pw->pw_passwd), 13)) {
+ puts("Incorrect password.");
+ exit(1);
+ }
+ }
+#endif
+
if (! shell) {
- printf ("Changing shell for %s.\n", pw->pw_name);
- shell = prompt ("New shell", pw->pw_shell);
+ shell = prompt ("New shell", oldshell);
if (! shell) return 0;
}
+
if (check_shell (shell) < 0) return (-1);
if (! strcmp (pw->pw_shell, shell)) {
printf ("Shell not changed.\n");
return 0;
}
+ if (!strcmp(shell, "/bin/sh")) shell = "";
pw->pw_shell = shell;
if (setpwnam (pw) < 0) {
perror ("setpwnam");
+ printf( "Shell *NOT* changed. Try again later.\n" );
return (-1);
}
printf ("Shell changed.\n");
return (-1);
}
}
- if (! get_shell_list (shell))
- printf ("warning: \"%s\" is not listed as a valid shell.\n", shell);
+#if ONLY_LISTED_SHELLS
+ if (! get_shell_list (shell)) {
+ if (!getuid())
+ printf ("Warning: \"%s\" is not listed as a valid shell.\n", shell);
+ else {
+ printf ("%s: \"%s\" is not listed as a valid shell.\n",
+ whoami, shell);
+ printf( "%s: use -l option to see list\n" );
+ exit(1);
+ }
+ }
+#else
+ if (! get_shell_list (shell)) {
+ printf ("Warning: \"%s\" is not listed as a valid shell.\n", shell);
+ printf( "Use %s -l to see list.\n", whoami );
+ }
+#endif
return 0;
}
limit the number of entries displayed to that specified by \fInumber\fP.
.IP "\fB\-f\fP \fIfilename\fP"
Use \fIfilename\fP as the name of the accounting file instead of
-.BR /etc/wtmp .
+.BR /var/log/wtmp .
.IP "\fB\-h\fP \fIhostname\fP"
List only logins from \fIhostname\fP.
.IP "\fB\-i\fP \fIIP address\fP""
.IP "\fB\-y\fP"
Also report year of dates.
.SH FILES
-/usr/adm/wtmp \(em login data base
+/var/log/wtmp \(em login data base
--- /dev/null
+.TH LAST 1 "20 March 1992"
+.SH NAME
+last \(em indicate last logins by user or terminal
+.SH SYNOPSIS
+.ad l
+.B last
+.RB [ \-\fP\fInumber\fP ]
+.RB [ \-f
+.IR filename ]
+.RB [ \-t
+.IR tty ]
+.RB [ \-h
+.IR hostname ]
+.RI [ name ...]
+.ad b
+.SH DESCRIPTION
+\fBLast\fP looks back in the \fBwtmp\fP file which records all logins
+and logouts for information about a user, a teletype or any group of
+users and teletypes. Arguments specify names of users or teletypes of
+interest. If multiple arguments are given, the information which
+applies to any of the arguments is printed. For example ``\fBlast root
+console\fP'' would list all of root's sessions as well as all sessions
+on the console terminal. \fBLast\fP displays the sessions of the
+specified users and teletypes, most recent first, indicating the times
+at which the session began, the duration of the session, and the
+teletype which the session took place on. If the session is still
+continuing or was cut short by a reboot, \fBlast\fP so indicates.
+.LP
+The pseudo-user \fBreboot\fP logs in at reboots of the system.
+.LP
+\fBLast\fP with no arguments displays a record of all logins and
+logouts, in reverse order.
+.LP
+If \fBlast\fP is interrupted, it indicates how far the search has
+progressed in \fBwtmp\fP. If interrupted with a quit signal \fBlast\fP
+indicates how far the search has progressed so far, and the search
+continues.
+.SH OPTIONS
+.IP \fB\-\fP\fInumber\fP
+limit the number of entries displayed to that specified by \fInumber\fP.
+.IP "\fB\-\fP \fIfilename\fP"
+Use \fIfilename\fP as the name of the accounting file instead of
+.BR /etc/wtmp .
+.IP "\fB\-t\fP \fItty\fP"
+List only logins on \fItty\fP.
+.IP "\fB\-h\fP \fIhostname\fP"
+List only logins from \fhostname\fP.
+.SH FILES
+/etc/wtmp \(em login data base
break;
}
if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS
+ && bp->ut_type != DEAD_PROCESS
&& want(bp, YES)) {
print_partial_line(bp);
--- /dev/null
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1987 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)last.c 5.11 (Berkeley) 6/29/88";
+#endif /* not lint */
+
+/*
+ * last
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+#include <utmp.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pathnames.h"
+
+#define SECDAY (24*60*60) /* seconds in a day */
+#define NO 0 /* false/no */
+#define YES 1 /* true/yes */
+
+static struct utmp buf[1024]; /* utmp read buffer */
+
+#define HMAX (int)sizeof(buf[0].ut_host) /* size of utmp host field */
+#define LMAX (int)sizeof(buf[0].ut_line) /* size of utmp tty field */
+#define NMAX (int)sizeof(buf[0].ut_name) /* size of utmp name field */
+
+typedef struct arg {
+ char *name; /* argument */
+#define HOST_TYPE -2
+#define TTY_TYPE -3
+#define USER_TYPE -4
+ int type; /* type of arg */
+ struct arg *next; /* linked list pointer */
+} ARG;
+ARG *arglist; /* head of linked list */
+
+typedef struct ttytab {
+ long logout; /* log out time */
+ char tty[LMAX + 1]; /* terminal name */
+ struct ttytab *next; /* linked list pointer */
+} TTY;
+TTY *ttylist; /* head of linked list */
+
+static long currentout, /* current logout value */
+ maxrec; /* records to display */
+static char *file = _PATH_WTMP; /* wtmp file */
+
+static void wtmp(), addarg(), hostconv();
+static int want();
+TTY *addtty();
+static char *ttyconv();
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int optind;
+ extern char *optarg;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF)
+ switch((char)ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /*
+ * kludge: last was originally designed to take
+ * a number after a dash.
+ */
+ if (!maxrec)
+ maxrec = atol(argv[optind - 1] + 1);
+ break;
+ case 'f':
+ file = optarg;
+ break;
+ case 'h':
+ hostconv(optarg);
+ addarg(HOST_TYPE, optarg);
+ break;
+ case 't':
+ addarg(TTY_TYPE, ttyconv(optarg));
+ break;
+ case '?':
+ default:
+ fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr);
+ exit(1);
+ }
+ for (argv += optind; *argv; ++argv) {
+#define COMPATIBILITY
+#ifdef COMPATIBILITY
+ /* code to allow "last p5" to work */
+ addarg(TTY_TYPE, ttyconv(*argv));
+#endif
+ addarg(USER_TYPE, *argv);
+ }
+ wtmp();
+ exit(0);
+}
+
+/*
+ * wtmp --
+ * read through the wtmp file
+ */
+static void
+wtmp()
+{
+ register struct utmp *bp; /* current structure */
+ register TTY *T; /* tty list entry */
+ struct stat stb; /* stat of file for size */
+ long bl, delta, /* time difference */
+ lseek(), time();
+ int bytes, wfd;
+ void onintr();
+ char *ct, *crmsg;
+
+ if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) {
+ perror(file);
+ exit(1);
+ }
+ bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf);
+
+ (void)time(&buf[0].ut_time);
+ (void)signal(SIGINT, onintr);
+ (void)signal(SIGQUIT, onintr);
+
+ while (--bl >= 0) {
+ if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 ||
+ (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) {
+ fprintf(stderr, "last: %s: ", file);
+ perror((char *)NULL);
+ exit(1);
+ }
+ for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) {
+ /*
+ * if the terminal line is '~', the machine stopped.
+ * see utmp(5) for more info.
+ */
+ if (!strncmp(bp->ut_line, "~", LMAX)) {
+ /* everybody just logged out */
+ for (T = ttylist; T; T = T->next)
+ T->logout = -bp->ut_time;
+ currentout = -bp->ut_time;
+ crmsg = strncmp(bp->ut_name, "shutdown", NMAX) ? "crash" : "down ";
+ if (!bp->ut_name[0])
+ (void)strcpy(bp->ut_name, "reboot");
+ if (want(bp, NO)) {
+ ct = ctime(&bp->ut_time);
+ if(bp->ut_type != LOGIN_PROCESS)
+ printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11);
+ if (maxrec && !--maxrec)
+ return;
+ }
+ continue;
+ }
+ /* find associated tty */
+ for (T = ttylist;; T = T->next) {
+ if (!T) {
+ /* add new one */
+ T = addtty(bp->ut_line);
+ break;
+ }
+ if (!strncmp(T->tty, bp->ut_line, LMAX))
+ break;
+ }
+ if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS
+ && want(bp, YES)) {
+ ct = ctime(&bp->ut_time);
+ printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11);
+ if (!T->logout)
+ puts(" still logged in");
+ else {
+ if (T->logout < 0) {
+ T->logout = -T->logout;
+ printf("- %s", crmsg);
+ }
+ else
+ printf("- %5.5s", ctime(&T->logout)+11);
+ delta = T->logout - bp->ut_time;
+ if (delta < SECDAY)
+ printf(" (%5.5s)\n", asctime(gmtime(&delta))+11);
+ else
+ printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11);
+ }
+ if (maxrec != -1 && !--maxrec)
+ return;
+ }
+ T->logout = bp->ut_time;
+ }
+ }
+ ct = ctime(&buf[0].ut_time);
+ printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11);
+}
+
+/*
+ * want --
+ * see if want this entry
+ */
+static int
+want(bp, check)
+ register struct utmp *bp;
+ int check;
+{
+ register ARG *step;
+
+ if (check)
+ /*
+ * when uucp and ftp log in over a network, the entry in
+ * the utmp file is the name plus their process id. See
+ * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information.
+ */
+ if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1))
+ bp->ut_line[3] = '\0';
+ else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1))
+ bp->ut_line[4] = '\0';
+ if (!arglist)
+ return(YES);
+
+ for (step = arglist; step; step = step->next)
+ switch(step->type) {
+ case HOST_TYPE:
+ if (!strncmp(step->name, bp->ut_host, HMAX))
+ return(YES);
+ break;
+ case TTY_TYPE:
+ if (!strncmp(step->name, bp->ut_line, LMAX))
+ return(YES);
+ break;
+ case USER_TYPE:
+ if (!strncmp(step->name, bp->ut_name, NMAX))
+ return(YES);
+ break;
+ }
+ return(NO);
+}
+
+/*
+ * addarg --
+ * add an entry to a linked list of arguments
+ */
+static void
+addarg(type, arg)
+ int type;
+ char *arg;
+{
+ register ARG *cur;
+
+ if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) {
+ fputs("last: malloc failure.\n", stderr);
+ exit(1);
+ }
+ cur->next = arglist;
+ cur->type = type;
+ cur->name = arg;
+ arglist = cur;
+}
+
+/*
+ * addtty --
+ * add an entry to a linked list of ttys
+ */
+TTY *
+addtty(ttyname)
+ char *ttyname;
+{
+ register TTY *cur;
+
+ if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) {
+ fputs("last: malloc failure.\n", stderr);
+ exit(1);
+ }
+ cur->next = ttylist;
+ cur->logout = currentout;
+ memcpy(cur->tty, ttyname, LMAX);
+ return(ttylist = cur);
+}
+
+/*
+ * hostconv --
+ * convert the hostname to search pattern; if the supplied host name
+ * has a domain attached that is the same as the current domain, rip
+ * off the domain suffix since that's what login(1) does.
+ */
+static void
+hostconv(arg)
+ char *arg;
+{
+ static int first = 1;
+ static char *hostdot,
+ name[MAXHOSTNAMELEN];
+ char *argdot;
+
+ if (!(argdot = strchr(arg, '.')))
+ return;
+ if (first) {
+ first = 0;
+ if (gethostname(name, sizeof(name))) {
+ perror("last: gethostname");
+ exit(1);
+ }
+ hostdot = strchr(name, '.');
+ }
+ if (hostdot && !strcmp(hostdot, argdot))
+ *argdot = '\0';
+}
+
+/*
+ * ttyconv --
+ * convert tty to correct name.
+ */
+static char *
+ttyconv(arg)
+ char *arg;
+{
+ char *mval;
+
+ /*
+ * kludge -- we assume that all tty's end with
+ * a two character suffix.
+ */
+ if (strlen(arg) == 2) {
+ /* either 6 for "ttyxx" or 8 for "console" */
+ if (!(mval = malloc((unsigned int)8))) {
+ fputs("last: malloc failure.\n", stderr);
+ exit(1);
+ }
+ if (!strcmp(arg, "co"))
+ (void)strcpy(mval, "console");
+ else {
+ (void)strcpy(mval, "tty");
+ (void)strcpy(mval + 3, arg);
+ }
+ return(mval);
+ }
+ if (!strncmp(arg, "/dev/", sizeof("/dev/") - 1))
+ return(arg + 5);
+ return(arg);
+}
+
+/*
+ * onintr --
+ * on interrupt, we inform the user how far we've gotten
+ */
+void
+onintr(signo)
+ int signo;
+{
+ char *ct;
+
+ ct = ctime(&buf[0].ut_time);
+ printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11);
+ if (signo == SIGINT)
+ exit(1);
+ (void)fflush(stdout); /* fix required for rsh */
+}
login is terminated. This is typically used to prevent logins when the
system is being taken down.
+If special access restrictions are specified for the user in
+.IR /etc/usertty ,
+these must be met, or the log in attempt will be denied and a
+.B syslog
+message will be generated. See the section on "Special Access Restrictions".
+
If the user is root, then the login must be occuring on a tty listed in
.IR /etc/securetty .
Failures will be logged with the
exists, then a "quiet" login is performed (this disables the checking of
the checking of mail and the printing of the last login time and message of
the day). Otherwise, if
-.I /var/adm/lastlog
+.I /var/log/lastlog
exists, the last login time is printed (and the current login is recorded).
Random administrative things, such as setting the UID and GID of the tty
.B login
so that it may be placed in utmp and wtmp. Only the superuser may use this
option.
+
+.SH "SPECIAL ACCESS RESTRICTIONS"
+The file
+.I /etc/securetty
+lists the names of the ttys where root is allowed to log in. One name of
+a tty device without the /dev/ prefix must be specified on each line.
+If the file does not exist, root is allowed to log in on any tty.
+.PP
+The file
+.I /etc/usertty
+specifies additional access restrictions for specific users. If this file
+does not exist, no additional access restrictions are imposed. The file
+consists of a sequence of sections. There are three possible section
+types: CLASSES, GROUPS and USERS. A CLASSES section defines classes of
+ttys and hostname patterns, A GROUPS section defines allowed ttys and
+hosts on a per group basis, and a USERS section defines allowed ttys
+and hosts on a per user basis.
+.PP
+Each line in this file in may be no longer than 255 characters. Comments
+start with # character and extend to the end of the line.
+.PP
+.SS "The CLASSES Section"
+A CLASSES section begins with the word CLASSES at the start of a line in all
+upper case. Each following line until the start of a new section or the
+end of the file consists of a sequence of words separated by tabs or
+spaces. Each line defines a class of ttys and host patterns.
+.PP
+The word at
+the beginning of a line becomes defined as a collective name for the
+ttys and host patterns specified at the rest of the line. This collective
+name can be used in any subsequent GROUPS or USERS section. No such class
+name must occur as part of the definition of a class in order to avoid
+problems with recursive classes.
+.PP
+An example CLASSES section:
+.PP
+.nf
+.in +.5
+CLASSES
+myclass1 tty1 tty2
+myclass2 tty3 @.foo.com
+.in -.5
+.fi
+.PP
+This defines the classes
+.I myclass1
+and
+.I myclass2
+as the corresponding right hand sides.
+.PP
+
+.SS "The GROUPS Section
+A GROUPS section defines allowed ttys and hosts on a per Unix group basis. If
+a user is a member of a Unix group according to
+.I /etc/passwd
+and
+.I /etc/group
+and such a group is mentioned in a GROUPS section in
+.I /etc/usertty
+then the user is granted access if the group is.
+.PP
+A GROUPS section starts with the word GROUPS in all upper case at the start of
+a line, and each following line is a sequence of words separated by spaces
+or tabs. The first word on a line is the name of the group and the rest
+of the words on the line specifies the ttys and hosts where members of that
+group are allowed access. These specifications may involve the use of
+classes defined in previous CLASSES sections.
+.PP
+An example GROUPS section.
+.PP
+.nf
+.in +0.5
+GROUPS
+sys tty1 @.bar.edu
+stud myclass1 tty4
+.in -0.5
+.fi
+.PP
+This example specifies that members of group
+.I sys
+may log in on tty1 and from hosts in the bar.edu domain. Users in group
+.I stud
+may log in from hosts/ttys specified in the class myclass1 or from tty4.
+.PP
+
+.SS "The USERS Section"
+A USERS section starts with the word USERS in all upper case at the
+start of a line, and each following line is a sequence of words
+separated by spaces or tabs. The first word on a line is a username
+and that user is allowed to log in on the ttys and from the hosts
+mentioned on the rest of the line. These specifications may involve
+classes defined in previous CLASSES sections. If no section header is
+specified at the top of the file, the first section defaults to be a
+USERS section.
+.PP
+An example USERS section:
+.PP
+.nf
+.in +0.5
+USERS
+zacho tty1 @130.225.16.0/255.255.255.0
+blue tty3 myclass2
+.in -0.5
+.fi
+.PP
+This lets the user zacho login only on tty1 and from hosts with IP addreses
+in the range 130.225.16.0 \- 130.225.16.255, and user blue is allowed to
+log in from tty3 and whatever is specified in the class myclass2.
+.PP
+There may be a line in a USERS section starting with a username of *. This
+is a default rule and it will be applied to any user not matching any other
+line.
+.PP
+If both a USERS line and GROUPS line match a user then the user is allowed
+access from the union of all the ttys/hosts mentioned in these specifications.
+
+.SS Origins
+The tty and host pattern specifications used in the specification of classes,
+group and user access are called origins. An origin string may have
+one of these formats:
+.IP o
+The name of a tty device without the /dev/ prefix, for example tty1 or
+ttyS0.
+.PP
+.IP o
+The string @localhost, meaning that the user is allowed to telnet/rlogin
+from the local host to the same host. This also allows the user to for
+example run the command: xterm -e /bin/login.
+.PP
+.IP o
+A domain name suffix such as @.some.dom, meaning that the user may
+rlogin/telnet from any host whose domain name has the suffix .some.dom.
+.PP
+.IP o
+A range of IPv4 addresses, written @x.x.x.x/y.y.y.y where x.x.x.x
+is the IP address in the usual dotted quad decimal notation, and
+y.y.y.y is a bitmask in the same notation specifying which bits in the
+address to compare with the IP address of the remote host. For example
+@130.225.16.0/255.255.254.0 means that the user may rlogin/telnet from
+any host whose IP address is in the range 130.225.16.0 \- 130.225.17.255.
+.PP
+Any of the above origins may be prefixed by a time specification according
+to the syntax:
+.PP
+.nf
+timespec ::= '[' <day-or-hour> [':' <day-or-hour>]* ']'
+day ::= 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun'
+hour ::= '0' | '1' | ... | '23'
+hourspec ::= <hour> | <hour> '\-' <hour>
+day-or-hour ::= <day> | <hourspec>
+.fi
+.PP
+For example, the origin [mon:tue:wed:thu:fri:8\-17]tty3 means that log in is
+allowed on mondays through fridays between 8:00 and 17:59 (5:59 pm) on tty3.
+This also shows that an hour range a\-b includes all moments between a:00 and
+b:59. A single hour specification (such as 10) means the time span between
+10:00 and 10:59.
+.PP
+Not specifying any time prefix for a tty or host means log in from that origin
+is allowed any time. If you give a time prefix be sure to specify both a set
+of days and one or more hours or hour ranges. A time specification may
+not include any white space.
+.PP
+If no default rule is given then users not matching any line
+.I /etc/usertty
+are allowed to log in from anywhere as is standard behavior.
+.PP
.SH FILES
.nf
-.I /etc/utmp
-.I /etc/wtmp
+.I /var/run/utmp
+.I /var/log/wtmp
+.I /var/log/lastlog
.I /usr/spool/mail/*
.I /etc/motd
.I /etc/passwd
.I /etc/nologin
+.I /etc/usertty
.I .hushlogin
.fi
.SH "SEE ALSO"
#ifndef linux
#include <tzfile.h>
+#endif
#include <lastlog.h>
-#else
+
+#if 0
+/* from before we had a lastlog.h file in linux */
struct lastlog
{ long ll_time;
char ll_line[12];
void dolastlog P_((int quiet));
void badlogin P_((char *name));
char *stypeof P_((char *ttyid));
-void checktty P_((char *user, char *tty));
+void checktty P_((char *user, char *tty, struct passwd *pwd));
void getstr P_((char *buf, int cnt, char *err));
void sleepexit P_((int eval));
#undef P_
int kerror = KSUCCESS, notickets = 1;
#endif
-#ifndef linux
#define TTYGRPNAME "tty" /* name of group to own ttys */
-#else
-# define TTYGRPNAME "other"
-# ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-# endif
+/**# define TTYGRPNAME "other" **/
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
#endif
/*
#endif
struct passwd *pwd;
-int failures;
+int failures = 1;
char term[64], *hostname, *username, *tty;
-
+struct hostent hostaddress;
char thishost[100];
#ifndef linux
(void)strncpy(thishost, tbuf, sizeof(thishost)-1);
domain = index(tbuf, '.');
+ hostname = NULL;
fflag = hflag = pflag = 0;
passwd_req = 1;
while ((ch = getopt(argc, argv, "fh:p")) != EOF)
strcasecmp(p, domain) == 0)
*p = 0;
hostname = optarg;
+ {
+ struct hostent *he = gethostbyname(hostname);
+ if (he) {
+ memcpy(&hostaddress, he, sizeof(hostaddress));
+ } else {
+ memset(&hostaddress, 0, sizeof(hostaddress));
+ }
+ }
break;
case 'p':
tcsetattr(0,TCSAFLUSH,&tt);
}
- if (tty = rindex(ttyn, '/'))
+ if ((tty = rindex(ttyn, '/')))
++tty;
else
tty = ttyn;
getloginname();
}
- checktty(username, tty);
+ /* Dirty patch to fix a gigantic security hole when using
+ yellow pages. This problem should be solved by the
+ libraries, and not by programs, but this must be fixed
+ urgently! If the first char of the username is '+', we
+ avoid login success.
+ Feb 95 <alvaro@etsit.upm.es> */
+
+ if (username[0] == '+') {
+ puts("Illegal username");
+ badlogin(username);
+ sleepexit(1);
+ }
(void)strcpy(tbuf, username);
- if (pwd = getpwnam(username))
+ if ((pwd = getpwnam(username)))
salt = pwd->pw_passwd;
else
salt = "xx";
+ checktty(username, tty, pwd); /* in checktty.c */
+
/* if user not super-user, check for disabled logins */
if (pwd == NULL || pwd->pw_uid)
checknologin();
/* for linux, write entries in utmp and wtmp */
{
struct utmp ut;
- char *ttyabbrev;
int wtmp;
-
- memset((char *)&ut, 0, sizeof(ut));
- ut.ut_type = USER_PROCESS;
- ut.ut_pid = getpid();
- strncpy(ut.ut_line, ttyn + sizeof("/dev/")-1, sizeof(ut.ut_line));
- ttyabbrev = ttyn + sizeof("/dev/tty") - 1;
- strncpy(ut.ut_id, ttyabbrev, sizeof(ut.ut_id));
- (void)time(&ut.ut_time);
+ struct utmp *utp;
+ pid_t mypid = getpid();
+
+ utmpname(_PATH_UTMP);
+ setutent();
+ while ((utp = getutent())
+ && !(utp->ut_pid == mypid)) /* nothing */;
+
+ if (utp) {
+ memcpy(&ut, utp, sizeof(ut));
+ } else {
+ /* some gettys/telnetds don't initialize utmp... */
+ memset(&ut, 0, sizeof(ut));
+ }
+ endutent();
+
+ if (ut.ut_id[0] == 0)
+ strncpy(ut.ut_id, ttyn + 8, sizeof(ut.ut_id));
+
strncpy(ut.ut_user, username, sizeof(ut.ut_user));
-
- /* fill in host and ip-addr fields when we get networking */
+ strncpy(ut.ut_line, ttyn + 5, sizeof(ut.ut_line));
+ time(&ut.ut_time);
+ ut.ut_type = USER_PROCESS;
+ ut.ut_pid = mypid;
if (hostname) {
- struct hostent *he;
-
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
- if ((he = gethostbyname(hostname)))
- memcpy(&ut.ut_addr, he->h_addr_list[0],
+ if (hostaddress.h_addr_list)
+ memcpy(&ut.ut_addr, hostaddress.h_addr_list[0],
sizeof(ut.ut_addr));
}
-
- utmpname(_PATH_UTMP);
- setutent();
+
pututline(&ut);
endutent();
close(wtmp);
}
}
- /* fix_utmp_type_and_user(username, ttyn, LOGIN_PROCESS); */
#endif
dolastlog(quietlog);
(void)chown(ttyn, pwd->pw_uid,
(gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid);
- (void)chmod(ttyn, 0622);
- (void)setgid(pwd->pw_gid);
+#ifdef USE_TTY_GROUP
+ chmod(ttyn, 0620);
+#else
+ chmod(ttyn, 0600);
+#endif
+ setgid(pwd->pw_gid);
initgroups(username, pwd->pw_gid);
#ifdef HAVE_QUOTA
(void)setenv("LOGNAME", pwd->pw_name, 1);
#endif
-#ifndef linux
- if (tty[sizeof("tty")-1] == 'd')
+ if (tty[sizeof("tty")-1] == 'S')
syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name);
-#endif
+
if (pwd->pw_uid == 0)
if (hostname)
syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s",
register int ch;
register char *p;
static char nbuf[UT_NAMESIZE + 1];
+ int cnt, cnt2;
+ cnt2 = 0;
for (;;) {
+ cnt = 0;
(void)printf("\n%s login: ", thishost); fflush(stdout);
for (p = nbuf; (ch = getchar()) != '\n'; ) {
if (ch == EOF) {
- badlogin(username);
+ badlogin("EOF");
exit(0);
}
if (p < nbuf + UT_NAMESIZE)
*p++ = ch;
+
+ cnt++;
+ if (cnt > UT_NAMESIZE + 20) {
+ fprintf(stderr, "login name much too long.\n");
+ badlogin("NAME too long");
+ exit(0);
+ }
}
if (p > nbuf)
if (nbuf[0] == '-')
username = nbuf;
break;
}
+
+ cnt2++;
+ if (cnt2 > 50) {
+ fprintf(stderr, "too many bare linefeeds.\n");
+ badlogin("EXCESSIVE linefeeds");
+ exit(0);
+ }
}
}
badlogin(name)
char *name;
{
- if (failures == 0)
- return;
-
if (hostname)
syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s",
failures, failures > 1 ? "S" : "", hostname, name);
}
#endif
-void
-checktty(user, tty)
- char *user;
- char *tty;
-{
- FILE *f;
- char buf[256];
- char *ptr;
- char devname[50];
- struct stat stb;
-
- /* no /etc/usertty, default to allow access */
- if(!(f = fopen(_PATH_USERTTY, "r"))) return;
-
- while(fgets(buf, 255, f)) {
-
- /* strip comments */
- for(ptr = buf; ptr < buf + 256; ptr++)
- if(*ptr == '#') *ptr = 0;
-
- strtok(buf, " \t");
- if(strncmp(user, buf, 8) == 0) {
- while((ptr = strtok(NULL, "\t\n "))) {
- if(strncmp(tty, ptr, 10) == 0) {
- fclose(f);
- return;
- }
- if(strcmp("PTY", ptr) == 0) {
-#ifdef linux
- sprintf(devname, "/dev/%s", ptr);
- /* VERY linux dependent, recognize PTY as alias
- for all pseudo tty's */
- if((stat(devname, &stb) >= 0)
- && major(stb.st_rdev) == 4
- && minor(stb.st_rdev) >= 192) {
- fclose(f);
- return;
- }
-#endif
- }
- }
- /* if we get here, /etc/usertty exists, there's a line
- beginning with our username, but it doesn't contain the
- name of the tty where the user is trying to log in.
- So deny access! */
- fclose(f);
- printf("Login on %s denied.\n", tty);
- badlogin(user);
- sleepexit(1);
- }
- }
- fclose(f);
- /* users not mentioned in /etc/usertty are by default allowed access
- on all tty's */
-}
-
void
getstr(buf, cnt, err)
char *buf, *err;
-.\" Original author: Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org
-.\" Updated by faith@cs.unc.edu, Fri Oct 29 23:22:16 1993
-.TH MESG 1 "29 October 1993" "Linux 0.99" "Linux Programmer's Manual"
+.\" 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.
+.\"
+.\" @(#)mesg.1 8.1 (Berkeley) 6/6/93
+.\"
+.\" Fri Mar 10 20:31:02 1995, modified for standard man macros,
+.\" faith@cs.unc.edu
+.\"
+.\"
+.\" "
+.TH MESG 1 "10 March 1995" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
-mesg \- control write access to your terminal
+mesg \- display (do not display) messages from other users
.SH SYNOPSIS
-.B mesg
-.RB [y|n]
-.br
+.B mesg [ n ] [ y ]
.SH DESCRIPTION
-.B Mesg
-controls the access to your terminal by others. It's typically used
-to allow/disallow others users to \fBwrite(1)\fP to your terminal.
-.SH FLAGS
-.IP y
-Allow write access to your terminal.
-.IP n
-Disallow write access to your terminal.
-.IP [none]
-Prints out the current access state of your terminal.
-.SH SEE ALSO
-.BR write (1), wall (1)
-.SH AUTHOR
-Miquel van Smoorenburg, miquels@drinkel.nl.mugnet.org
+The
+.B mesg
+utility is invoked by a users to control write access others have to the
+terminal device associated with the standard error output. If write access
+is allowed, then programs such as
+.BR talk (1)
+and
+.BR write (1)
+may display messages on the terminal.
+.PP
+Traditionally, write access is allowed by default. However, as users
+become more conscious of various security risks, there is a trend to remove
+write access by default, at least for the primary login shell. To make
+sure your ttys are set the way you want them to be set,
+.B mesg
+should be executed in your login scripts.
+.PP
+Options available:
+.TP
+.B n
+Disallows messages.
+.TP
+.B y
+Permits messages to be displayed.
+.PP
+If no arguments are given,
+.B mesg
+displays the present message status to the standard error output.
+.PP
+The
+.B mesg
+utility exits with one of the following values:
+.TP
+.I "\ 0"
+Messages are allowed.
+.TP
+.I "\ 1"
+Messages are not allowed.
+.TP
+.I "\>1"
+An error has occurred.
+.SH FILES
+.I /dev/[pt]ty[pq]?
+.SH "SEE ALSO"
+.BR biff (1),
+.BR talk (1),
+.BR write (1),
+.BR wall (1),
+.BR login (1),
+.BR xterm (1)
+.SH HISTORY
+A
+.B mesg
+command appeared in Version 6 AT&T UNIX.
/*
- * mesg.c The "mesg" utility. Gives / restrict access to
- * your terminal by others.
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
*
- * Usage: mesg [y|n].
- * Without arguments prints out the current settings.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Fri Mar 10 20:27:19 1995, faith@cs.unc.edu, for Linux
+ *
*/
-#include <stdio.h>
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)mesg.c 8.2 (Berkeley) 1/21/94";
+#endif /* not lint */
+
+#include <sys/types.h>
#include <sys/stat.h>
-#include <stdlib.h>
+
+#include <err.h>
#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-char *Version = "@(#) mesg 1.0 08-12-92 MvS";
-
-int main(int argc, char **argv)
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
{
- struct stat st;
-
- if (!isatty(0)) {
- /* Or should we look in /etc/utmp? */
- fprintf(stderr, "stdin: is not a tty");
- return(1);
- }
-
- if (fstat(0, &st) < 0) {
- perror("fstat");
- return(1);
- }
- if (argc < 2) {
- printf("Is %s\n", ((st.st_mode & 022) == 022) ? "y" : "n");
- return(0);
- }
- if (argc > 2 || (argv[1][0] != 'y' && argv[1][0] != 'n')) {
- fprintf(stderr, "Usage: mesg [y|n]\n");
- return(1);
- }
- if (argv[1][0] == 'y')
- st.st_mode |= 022;
- else
- st.st_mode &= ~022;
- fchmod(0, st.st_mode);
- return(0);
+ struct stat sb;
+ char *tty;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "")) != EOF)
+ switch (ch) {
+ case '?':
+ default:
+ goto usage;
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((tty = ttyname(STDERR_FILENO)) == NULL)
+ err(1, "ttyname");
+ if (stat(tty, &sb) < 0)
+ err(1, "%s", tty);
+
+ if (*argv == NULL) {
+ if (sb.st_mode & (S_IWGRP | S_IWOTH)) {
+ (void)fprintf(stderr, "is y\n");
+ exit(0);
+ }
+ (void)fprintf(stderr, "is n\n");
+ exit(1);
+ }
+
+ switch (*argv[0]) {
+ case 'y':
+#ifdef USE_TTY_GROUP
+ if (chmod(tty, sb.st_mode | S_IWGRP) < 0)
+ err(1, "%s", tty);
+#else
+ if (chmod(tty, sb.st_mode | S_IWGRP | S_IWOTH) < 0)
+ err(1, "%s", tty);
+#endif
+ exit(0);
+ case 'n':
+ if (chmod(tty, sb.st_mode & ~(S_IWGRP|S_IWOTH)) < 0)
+ err(1, "%s", tty);
+ exit(1);
+ }
+
+usage: (void)fprintf(stderr, "usage: mesg [y | n]\n");
+ exit(2);
}
.\" Original author unknown. This man page is in the public domain.
.\" Modified Sat Oct 9 17:46:48 1993 by faith@cs.unc.edu
-.TH NEWGRP 1 "9 October 1993" "Linux 0.99" "Linux Programmer's Manual"
+.TH NEWGRP 1 "9 October 1993" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
newgrp \- log in to a new group
.SH SYNOPSIS
.SH "SEE ALSO"
.BR login "(1), " group (5)
+
+.SH AUTHOR
+Originally by Michael Haardt. Currently maintained by
+Peter Orbaek (poe@daimi.aau.dk).
.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH PASSWD 1 "22 June 1994" "Linux 1.0" "Linux Programmer's Manual"
+.TH PASSWD 1 "22 June 1994" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
passwd \- change password
.SH SYNOPSIS
-.BR "passwd [ " name " ]"
+.BR "passwd [ " name " [ " password " ] ]"
.SH DESCRIPTION
+Without arguments
.B passwd
-will change the specified user's password. Only the superuser is allowed
-to change other user's passwords. If the user is not root, then the old
-password is prompted for and verified.
+will change the password for the current user. First the user is asked for
+the old password, then prompted twice for the new password in order to
+catch typing errors. The new password must be at least six characters long,
+and have both upper and lower case letters or non-letters. The new password
+must not be equal to the old password, and it must not match the username.
+
+The one and two argument forms may only be used by the superuser. Using the
+one argument form, the superuser may change the password for that user.
+The superuser is not asked for the users old password, and the rules
+for proper passwords are not applied since the superuser may have legitimate
+reasons to choose a non-conformant password.
+
+The two argument form gives the
+.I user
+the password stated as the second argument. This may be useful when
+giving many users an initial generated password.
+
+Giving an empty string as the second argument erases the password for the
+user.
-A new password is prompted for twice, to avoid typing mistakes. Unless the
-user is the superuser, the new password must have more than six characters,
-and must have either both upper and lower case letters, or non-letters.
-Some passwords which are similar to the user's name are not allowed.
.SH FILES
.I /etc/passwd
.br
/* Hacked by Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es,
to allow peaceful coexistence with yp. Nov 94. */
+/* Hacked to allow root to set passwd from command line.
+ by Arpad Magossanyi (mag@tas.vein.hu) */
+/*
+ * Usage: passwd [username [password]]
+ * Only root may use the one and two argument forms.
+ */
+
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
+#include <fcntl.h>
#include <pwd.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
+#include <errno.h>
+#include <sys/resource.h>
extern int is_local(char *);
#define MAX_LENGTH 1024
+static void
+pexit(str)
+ char *str;
+{
+ perror(str);
+ exit(1);
+}
+
int
main(argc, argv)
- int argc;
- char *argv[];
+ int argc;
+ char *argv[];
{
- struct passwd *pe;
- uid_t gotuid = getuid();
- char *pwdstr, *cryptstr;
- char pwdstr1[10];
- int ucase, lcase, other;
- char *p, *q, *user;
- time_t tm;
- char salt[2];
- FILE *fd_in, *fd_out;
- char line[MAX_LENGTH];
- int error=0;
- int r;
-
- umask(022);
+ struct passwd *pe;
+ uid_t gotuid = getuid();
+ char *pwdstr = NULL, *cryptstr, *oldstr;
+ char pwdstr1[10];
+ int ucase, lcase, other;
+ char *p, *q, *user;
+ time_t tm;
+ char salt[2];
+ FILE *fd_in, *fd_out;
+ char line[MAX_LENGTH];
+ char colonuser[16];
+ int error=0;
+ int r;
+ int ptmp;
+#ifndef USE_SETPWNAM
+ struct rlimit rlim;
+#endif
- if(argc > 2) {
- puts("Too many arguments");
- exit(1);
- } else if(argc == 2) {
- if(gotuid) {
- puts("Only root can change the password for others");
- exit(1);
- }
- user = argv[1];
- } else {
- if (!(user = getlogin())) {
- if (!(pe = getpwuid( getuid() ))) {
- puts("Cannot find login name");
- exit(1);
- } else
- user = pe->pw_name;
- }
+ if(argc > 3) {
+ puts("Too many arguments");
+ exit(1);
+ } else if(argc >= 2) {
+ if(gotuid) {
+ puts("Only root can change the password for others");
+ exit(1);
}
-
- if(!(pe = getpwnam(user))) {
- puts("Can't find username anywhere. Are you really a user?");
- exit(1);
+ user = argv[1];
+
+ if (argc == 3) pwdstr = argv[2];
+
+ } else {
+ if (!(user = getlogin())) {
+ if (!(pe = getpwuid( getuid() ))) {
+ pexit("Cannot find login name");
+ } else
+ user = pe->pw_name;
}
+ }
- if (!(is_local(user))) {
- puts("Sorry, I can only change local passwords. Use yppasswd instead.");
- exit(1);
- }
+#ifndef USE_SETPWNAM
+ umask(022);
- /* if somebody got into changing utmp... */
- if(gotuid && gotuid != pe->pw_uid) {
- puts("UID and username does not match, imposter!");
+ rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
+ setrlimit(RLIMIT_CPU, &rlim);
+ setrlimit(RLIMIT_FSIZE, &rlim);
+ setrlimit(RLIMIT_STACK, &rlim);
+ setrlimit(RLIMIT_DATA, &rlim);
+ setrlimit(RLIMIT_RSS, &rlim);
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+#endif
+
+ if(!(pe = getpwnam(user))) {
+ pexit("Can't find username anywhere. Are you really a user?");
+ }
+
+ if (!(is_local(user))) {
+ puts("Sorry, I can only change local passwords. Use yppasswd instead.");
+ exit(1);
+ }
+
+ /* if somebody got into changing utmp... */
+ if(gotuid && gotuid != pe->pw_uid) {
+ puts("UID and username does not match, imposter!");
+ exit(1);
+ }
+
+ printf( "Changing password for %s\n", user );
+
+ if(gotuid && pe->pw_passwd && pe->pw_passwd[0]) {
+ oldstr = getpass("Enter old password: ");
+ if(strncmp(pe->pw_passwd, crypt(oldstr, pe->pw_passwd), 13)) {
+ puts("Illegal password, imposter.");
exit(1);
}
+ }
- printf( "Changing password for %s\n", user );
-
- if(gotuid && pe->pw_passwd && pe->pw_passwd[0]) {
- pwdstr = getpass("Enter old password: ");
- if(strncmp(pe->pw_passwd, crypt(pwdstr, pe->pw_passwd), 13)) {
- puts("Illegal password, imposter.");
- exit(1);
- }
- }
+ if (!pwdstr) {
+ /* password not set on command line by root, ask for it ... */
-redo_it:
+ redo_it:
pwdstr = getpass("Enter new password: ");
- strncpy(pwdstr1, pwdstr, 9);
- pwdstr = getpass("Re-type new password: ");
-
- if(strncmp(pwdstr, pwdstr1, 8)) {
- puts("You misspelled it. Password not changed.");
- exit(0);
+ if (pwdstr[0] == '\0') {
+ puts("Password not changed.");
+ exit(1);
}
if((strlen(pwdstr) < 6) && gotuid) {
- puts("The password must have at least 6 characters, try again.");
- goto redo_it;
+ puts("The password must have at least 6 characters, try again.");
+ goto redo_it;
}
other = ucase = lcase = 0;
for(p = pwdstr; *p; p++) {
- ucase = ucase || isupper(*p);
- lcase = lcase || islower(*p);
- other = other || !isalpha(*p);
+ ucase = ucase || isupper(*p);
+ lcase = lcase || islower(*p);
+ other = other || !isalpha(*p);
}
if((!ucase || !lcase) && !other && gotuid) {
- puts("The password must have both upper- and lowercase");
- puts("letters, or non-letters; try again.");
- goto redo_it;
+ puts("The password must have both upper- and lowercase");
+ puts("letters, or non-letters; try again.");
+ goto redo_it;
+ }
+
+ if (pe->pw_passwd[0]
+ && !strncmp(pe->pw_passwd, crypt(pwdstr, pe->pw_passwd), 13)
+ && gotuid) {
+ puts("You cannot reuse the old password.");
+ goto redo_it;
}
r = 0;
for(p = pwdstr, q = pe->pw_name; *q && *p; q++, p++) {
- if(tolower(*p) != tolower(*q)) {
- r = 1;
- break;
- }
+ if(tolower(*p) != tolower(*q)) {
+ r = 1;
+ break;
+ }
}
-
+
for(p = pwdstr + strlen(pwdstr)-1, q = pe->pw_name;
*q && p >= pwdstr; q++, p--) {
- if(tolower(*p) != tolower(*q)) {
- r += 2;
- break;
- }
+ if(tolower(*p) != tolower(*q)) {
+ r += 2;
+ break;
+ }
}
-
+
if(gotuid && r != 3) {
- puts("Please don't use something like your username as password!");
- goto redo_it;
+ puts("Please don't use something like your username as password!");
+ goto redo_it;
}
-
+
/* do various other checks for stupid passwords here... */
-
- time(&tm);
- salt[0] = bin_to_ascii(tm & 0x3f);
- salt[1] = bin_to_ascii((tm >> 5) & 0x3f);
- cryptstr = crypt(pwdstr, salt);
- if(access("/etc/ptmp", F_OK) == 0) {
- puts("/etc/ptmp exists, can't change password");
- exit(1);
- }
+ strncpy(pwdstr1, pwdstr, 9);
+ pwdstr = getpass("Re-type new password: ");
- if(!(fd_out = fopen("/etc/ptmp", "w"))) {
- puts("Can't open /etc/ptmp, can't update password");
- exit(1);
+ if(strncmp(pwdstr, pwdstr1, 8)) {
+ puts("You misspelled it. Password not changed.");
+ exit(1);
}
+ } /* pwdstr != argv[2] i.e. password set on command line */
+
+ time(&tm);
+ salt[0] = bin_to_ascii(tm & 0x3f);
+ salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
+ cryptstr = crypt(pwdstr, salt);
+
+ if (pwdstr[0] == 0) cryptstr = "";
- if(!(fd_in = fopen("/etc/passwd", "r"))) {
- puts("Can't read /etc/passwd, can't update password");
- exit(1);
+#ifdef USE_SETPWNAM
+ pe->pw_passwd = cryptstr;
+ if (setpwnam( pe ) < 0) {
+ perror( "setpwnam" );
+ printf( "Password *NOT* changed. Try again later.\n" );
+ exit( 1 );
+ }
+#else
+ if ((ptmp = open("/etc/ptmp", O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0) {
+ pexit("Can't exclusively open /etc/ptmp, can't update password");
+ }
+ fd_out = fdopen(ptmp, "w");
+
+ if(!(fd_in = fopen("/etc/passwd", "r"))) {
+ pexit("Can't read /etc/passwd, can't update password");
+ }
+
+ strcpy(colonuser, user);
+ strcat(colonuser, ":");
+ while(fgets(line, sizeof(line), fd_in)) {
+ if(!strncmp(line,colonuser,strlen(colonuser))) {
+ pe->pw_passwd = cryptstr;
+ if(putpwent(pe, fd_out) < 0) {
+ error = 1;
+ }
+ } else {
+ if(fputs(line,fd_out) < 0) {
+ error = 1;
+ }
}
- while(fgets(line, sizeof(line), fd_in)) {
- if(!strncmp(line,user,strlen(user))) {
- pe->pw_passwd = cryptstr;
- if(putpwent(pe, fd_out) < 0) {
- error = 1;
- }
- } else {
- if(fputs(line,fd_out) < 0) {
- error = 1;
- }
- }
- if(error) {
- puts("Error while writing new password file, password not changed.");
- fclose(fd_out);
- endpwent();
- unlink("/etc/ptmp");
- exit(1);
- }
+ if(error) {
+ puts("Error while writing new password file, password not changed.");
+ fclose(fd_out);
+ endpwent();
+ unlink("/etc/ptmp");
+ exit(1);
}
- fclose(fd_in);
- fclose(fd_out);
-
- unlink("/etc/passwd.OLD");
- link("/etc/passwd", "/etc/passwd.OLD");
- unlink("/etc/passwd");
- link("/etc/ptmp", "/etc/passwd");
- unlink("/etc/ptmp");
- chmod("/etc/passwd", 0644);
- chown("/etc/passwd", 0, 0);
-
- puts("Password changed.");
- exit(0);
+ }
+ fclose(fd_in);
+ fclose(fd_out);
+
+ unlink("/etc/passwd.OLD"); /* passwd.OLD not required */
+ if (link("/etc/passwd", "/etc/passwd.OLD"))
+ pexit("link(/etc/passwd, /etc/passwd.OLD) failed: no change");
+ if (unlink("/etc/passwd") < 0)
+ pexit("unlink(/etc/passwd) failed: no change");
+ if (link("/etc/ptmp", "/etc/passwd") < 0)
+ pexit("link(/etc/ptmp, /etc/passwd) failed: PASSWD file DROPPED!!");
+ if (unlink("/etc/ptmp") < 0)
+ pexit("unlink(/etc/ptmp) failed: /etc/ptmp still exists");
+
+ chmod("/etc/passwd", 0644);
+ chown("/etc/passwd", 0, 0);
+#endif
+
+ puts("Password changed.");
+ exit(0);
}
*
* Thanks to "two guys named Ian".
*/
-/* faith
- * 1.1.1.1
- * 1995/02/22 19:09:24
+/* $Author: faith $
+ * $Revision: 1.5 $
+ * $Date: 1995/10/12 14:46:36 $
*/
-#define DEBUG 0
+#undef DEBUG
/* because I use getpwent(), putpwent(), etc... */
#define _SVID_SOURCE
#include <fcntl.h>
#include <pwd.h>
#include <errno.h>
+#include <signal.h>
+#include <sys/resource.h>
#ifdef BSD43
#include <sys/file.h>
#endif
+#include <paths.h>
+
+#include "pathnames.h"
extern int errno;
#define true 1
#ifndef DEBUG
-#define PASSWD_FILE "/etc/passwd"
-#define PTMP_FILE "/etc/ptmp"
+#define PASSWD_FILE _PATH_PASSWD
+#define PTMP_FILE _PATH_PTMP
+#define PTMPTMP_FILE _PATH_PTMPTMP
#else
#define PASSWD_FILE "/tmp/passwd"
#define PTMP_FILE "/tmp/ptmp"
+#define PTMPTMP_FILE "/tmp/ptmptmp"
#endif
static int copy_pwd (struct passwd *src, struct passwd *dest);
static char *xstrdup (char *str);
+static void pw_init(void);
/*
* setpwnam () --
*/
int setpwnam (struct passwd *pwd)
{
- char *passwd = PASSWD_FILE;
- char *ptmp = PTMP_FILE;
FILE *fp;
- int x, save_errno, fd;
+ int x, save_errno, fd, ret;
struct passwd *entry;
boolean found;
- char buf[50];
struct passwd spwd;
+ int oldumask;
/* getpwent() returns a pointer to a static buffer.
* "pwd" might have some from getpwent(), so we have to copy it to
if (copy_pwd (pwd, &spwd) < 0)
return (-1);
+ oldumask = umask(0); /* Create with exact permissions */
+ pw_init();
+
/* sanity check */
for (x = 0; x < 3; x++) {
if (x > 0) sleep (1);
- fd = open (ptmp, O_WRONLY|O_CREAT|O_EXCL, 00644);
- if (fd >= 0) break;
+ fd = open (PTMPTMP_FILE, O_WRONLY|O_CREAT, 0644);
+ if(fd == -1) {
+ perror(PTMPTMP_FILE);
+ umask(oldumask);
+ return (-1);
+ }
+ ret = link(PTMPTMP_FILE, PTMP_FILE);
+ unlink(PTMPTMP_FILE);
+ if(ret == -1)
+ close(fd);
+ else
+ break;
}
- if (fd < 0) return (-1);
+
+ umask(oldumask);
+ if (ret == -1) return (-1);
/* ptmp should be owned by root.root or root.wheel */
- if (chown (ptmp, (uid_t) 0, (gid_t) 0) < 0)
+ if (chown (PTMP_FILE, (uid_t) 0, (gid_t) 0) < 0)
perror ("chown");
/* open ptmp for writing and passwd for reading */
goto fail;
}
- strcpy (buf, passwd);
- strcat (buf, "~");
/* we don't care if we can't remove the backup file */
- remove (buf);
+ unlink (PASSWD_FILE".OLD");
/* we don't care if we can't create the backup file */
- link (passwd, buf);
- /* we DO care if we can't erase the passwd file */
- if (remove (passwd) < 0) {
- /* if the file is still there, fail */
- if (access (passwd, F_OK) == 0) goto fail;
- }
- /* if we can't link ptmp to passwd, all is lost */
- if (link (ptmp, passwd) < 0) {
- /* reinstall_system (); */
- return (-1);
- }
- /* if we can't erase the ptmp file, we simply lose */
- if (remove (ptmp) < 0)
- return (-1);
+ link (PASSWD_FILE, PASSWD_FILE".OLD");
+ /* we DO care if we can't rename to the passwd file */
+ if (rename (PTMP_FILE, PASSWD_FILE) < 0)
+ goto fail;
/* finally: success */
return 0;
if (fp) fclose (fp);
if (fd >= 0) close (fd);
endpwent ();
- remove (ptmp);
+ unlink (PTMP_FILE);
errno = save_errno;
return (-1);
}
}
#endif
+
+static 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(SIGTSTP, SIG_IGN);
+ (void)signal(SIGTTOU, SIG_IGN);
+
+ /* Create with exact permissions. */
+ (void)umask(0);
+}
.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH SHUTDOWN 8 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
+.TH SHUTDOWN 8 "20 November 1993" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
shutdown \- close down the system
.SH SYNOPSIS
not to spawn more
.BR getty (8)'s,
writes the shutdown time into the
-.I /var/adm/wtmp
+.I /var/log/wtmp
file, kills all other processes on the system,
.BR sync (2)'s,
unmounts all the disks,
.I /fastboot
.I /etc/singleboot
.I /etc/nologin
-.I /var/adm/wtmp
+.I /var/log/wtmp
.fi
.SH "SEE ALSO"
.BR umount (8),
.BR shutdown ,
users are notified of shutdown only once or twice, instead of many times,
and at shorter and shorter intervals as "apocalypse approaches."
+Some would construe this as a feature.
.SH AUTHOR
-poe@daimi.aau.dk
+Peter Orbaek (poe@daimi.aau.dk)
.br
Modified by jrs@world.std.com
void usage(), int_handler(), write_user(struct utmp *);
void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves();
+void swap_off();
char *prog; /* name of the program */
int opt_reboot; /* true if -r option or reboot command */
#ifndef DEBUGGING
if(geteuid()) {
- fprintf(stderr, "Only root can shut a system down.\n");
+ fprintf(stderr, "%s: Only root can shut a system down.\n", argv[0]);
exit(1);
}
#endif
if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */
prog = argv[0];
- if(ptr = strrchr(argv[0], '/')) prog = ++ptr;
+ if((ptr = strrchr(argv[0], '/'))) prog = ++ptr;
if(!strcmp("halt", prog)) {
opt_reboot = 0;
struct tm *tt;
int now, then;
- if(colon = strchr(argv[c], ':')) {
+ if((colon = strchr(argv[c], ':'))) {
*colon = '\0';
hour = atoi(argv[c]);
minute = atoi(++colon);
sync();
sleep(2);
+ /* remove swap files and partitions using swapoff */
+ swap_off();
+
/* unmount disks... */
unmount_disks();
sync();
utmpname(_PATH_UTMP);
setutent();
- while(ut = getutent()) {
+ while((ut = getutent())) {
if(ut->ut_type == USER_PROCESS)
write_user(ut);
}
time(&ut.ut_time);
ut.ut_type = BOOT_TIME;
- if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) > 0) {
+ if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) {
write(fd, (char *)&ut, sizeof(ut));
close(fd);
}
}
+void
+swap_off()
+{
+ /* swapoff esp. swap FILES so the underlying partition can be
+ unmounted. It you don't have swapoff(1) or use mount to
+ add swapspace, this may not be necessary, but I guess it
+ won't hurt */
+
+ int pid;
+ int result;
+ int status;
+
+ sync();
+ if ((pid = fork()) < 0) {
+ printf("Cannot fork for swapoff. Shrug!\n");
+ return;
+ }
+ if (!pid) {
+ execl("/sbin/swapoff", SWAPOFF_ARGS, NULL);
+ execl("/etc/swapoff", SWAPOFF_ARGS, NULL);
+ execl("/bin/swapoff", SWAPOFF_ARGS, NULL);
+ execlp("swapoff", SWAPOFF_ARGS, NULL);
+ puts("Cannot exec swapoff, hoping umount will do the trick.");
+ exit(0);
+ }
+ while ((result = wait(&status)) != -1 && result != pid)
+ ;
+}
+
void
unmount_disks()
{
execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL);
printf("Cannot exec %s, trying umount.\n", _PATH_UMOUNT);
execlp("umount", UMOUNT_ARGS, NULL);
- printf("Cannot exec umount, trying manually.\n");
- unmount_disks_ourselves();
+ puts("Cannot exec umount, giving up on umount.");
exit(0);
}
while ((result = wait(&status)) != -1 && result != pid)
;
- if (result == -1 || status) {
- printf("Running umount failed, trying manually.\n");
- unmount_disks_ourselves();
- }
+ puts("Unmounting any remaining filesystems...");
+ unmount_disks_ourselves();
}
void
sync();
if (!(mtab = setmntent(_PATH_MTAB, "r"))) {
- printf("Cannot open %s.\n", _PATH_MTAB);
+ printf("shutdown: Cannot open %s.\n", _PATH_MTAB);
return;
}
n = 0;
printf("umount %s\n", filesys);
#else
if (umount(mntlist[i]) < 0)
- printf("Couldn't umount %s\n", filesys);
+ printf("shutdown: Couldn't umount %s\n", filesys);
#endif
}
}
utmpname(_PATH_UTMP);
setutent();
- while(ut = getutent()) {
+ while((ut = getutent())) {
if(ut->ut_pid == pid) {
time(&ut->ut_time);
memset(&ut->ut_user, 0, UT_NAMESIZE);
} else {
/* this is the child */
char term[40];
+#ifdef SET_TZ
char tz[CMDSIZ];
+#endif
char *env[3];
setsid();
char buf[CMDSIZ];
int i,j,k;
char *ptr, *getty;
+#ifdef SPECIAL_CONSOLE_TERM
char tty[50];
struct stat stb;
+#endif
char *termenv, *getenv();
termenv = getenv("TERM"); /* set by kernel */
(void) strtok(getty, " \t\n");
inittab[i].toks[0] = getty;
j = 1;
- while(ptr = strtok((char *)0, " \t\n"))
+ while((ptr = strtok((char *)0, " \t\n")))
inittab[i].toks[j++] = ptr;
inittab[i].toks[j] = (char *)0;
/*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * 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
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Modified for Linux (which doesn\'t have snprintf()) by faith@cs.unc.edu
- * on Sun Mar 7 16:14:18 1993.
+ * Modified Sun Mar 12 10:39:22 1995, faith@cs.unc.edu for Linux
*
*/
#ifndef lint
-static char sccsid[] = "@(#)ttymsg.c 5.8 (Berkeley) 7/1/91";
+static char sccsid[] = "@(#)ttymsg.c 8.2 (Berkeley) 11/16/93";
#endif /* not lint */
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
+#ifdef __linux__
+#include "pathnames.h"
+#endif
+
/*
- * Display the contents of a uio structure on a terminal. Used by wall(1)
- * and syslogd(8). Forks and finishes in child if write would block, waiting
- * at most five minutes. Returns pointer to error string on unexpected error;
- * string is not newline-terminated. Various "normal" errors are ignored
- * (exclusive-use, lack of permission, etc.).
+ * Display the contents of a uio structure on a terminal. Used by wall(1),
+ * syslogd(8), and talkd(8). Forks and finishes in child if write would block,
+ * waiting up to tmout seconds. Returns pointer to error string on unexpected
+ * error; string is not newline-terminated. Various "normal" errors are
+ * ignored (exclusive-use, lack of permission, etc.).
*/
char *
-ttymsg(iov, iovcnt, line)
+ttymsg(iov, iovcnt, line, tmout)
struct iovec *iov;
int iovcnt;
char *line;
+ int tmout;
{
static char device[MAXNAMLEN] = _PATH_DEV;
static char errbuf[1024];
struct iovec localiov[6];
int forked = 0;
- if (iovcnt > 6)
+ if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
return ("too many iov's (change code in wall/ttymsg.c)");
+
+ (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
+ if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
+ /* A slash is an attempt to break security... */
+#ifdef __linux__
+ (void) sprintf(errbuf, "'/' in \"%s\"", device);
+#else
+ (void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
+ device);
+#endif
+ return (errbuf);
+ }
+
/*
* open will fail on slip lines or exclusive-use lines
* if not running as root; not an error.
*/
- (void) strcpy(device + sizeof(_PATH_DEV) - 1, line);
if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) {
if (errno == EBUSY || errno == EACCES)
return (NULL);
if (wret >= 0) {
left -= wret;
if (iov != localiov) {
- bcopy(iov, localiov,
+ bcopy(iov, localiov,
iovcnt * sizeof(struct iovec));
iov = localiov;
}
return (NULL);
}
forked++;
- /* wait at most 5 minutes */
+ /* wait at most tmout seconds */
(void) signal(SIGALRM, SIG_DFL);
(void) signal(SIGTERM, SIG_DFL); /* XXX */
(void) sigsetmask(0);
- (void) alarm((u_int)(60 * 5));
+ (void) alarm((u_int)tmout);
(void) fcntl(fd, O_NONBLOCK, &off);
continue;
- }
+ }
/*
* We get ENODEV on a slip line if we're running as root,
* and EIO if the line just went away.
.\" SUCH DAMAGE.
.\"
.\" from: @(#)vipw.8 6.7 (Berkeley) 3/16/91
-.\" vipw.8,v 1.1.1.1 1995/02/22 19:09:25 faith Exp
+.\" $Id: vipw.8,v 1.2 1995/03/12 01:33:13 faith Exp $
.\"
.Dd March 16, 1991
.Dt VIPW 8
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * Updated Thu Oct 12 09:56:55 1995 by faith@cs.unc.edu with security
+ * patches from Zefram <A.Main@dcs.warwick.ac.uk>
+ *
*/
#ifndef lint
#ifndef lint
/*static char sccsid[] = "from: @(#)vipw.c 5.16 (Berkeley) 3/3/91";*/
-static char rcsid[] = "vipw.c,v 1.1.1.1 1995/02/22 19:09:25 faith Exp";
+static char rcsid[] = "$Id: vipw.c,v 1.4 1995/10/12 14:46:36 faith Exp $";
#endif /* not lint */
#include <sys/types.h>
int
pw_lock()
{
- static char path[MAXPATHLEN] = _PATH_PTMP;
int lockfd, fd, ret;
char *p;
progname, _PATH_PASSWD, strerror(errno));
exit(1);
}
+#if 0 /* flock()ing is superfluous here, with the ptmp/ptmptmp system. */
if (flock(lockfd, LOCK_EX|LOCK_NB)) {
(void)fprintf(stderr,
"%s: the password file is busy.\n", progname);
exit(1);
}
+#endif
if ((fd = open(_PATH_PTMPTMP, O_WRONLY|O_CREAT, 0644)) == -1) {
(void)fprintf(stderr,
void
pw_unlock()
{
- (void)unlink(_PATH_PASSWD);
- if (link(_PATH_PTMP, _PATH_PASSWD) == -1) {
+ unlink(_PATH_PASSWD ".OLD");
+ link(_PATH_PASSWD, _PATH_PASSWD ".OLD" );
+ if (rename(_PATH_PTMP, _PATH_PASSWD) == -1) {
(void)fprintf(stderr,
"%s: can't unlock %s: %s (your changes are still in %s)\n",
progname, _PATH_PASSWD, strerror(errno), _PATH_PTMP);
if (!(editor = getenv("EDITOR")))
editor = _PATH_VI;
- if ((p = strrchr(editor, '/')) != NULL)
+ if ((p = strrchr(strtok(editor," \t"), '/')) != NULL)
++p;
else
p = editor;
/*
- * Copyright (c) 1988, 1990 Regents of the University of California.
- * All rights reserved.
+ * 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
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * Modified for Linux, Mon Mar 8 18:08:30 1993, faith@cs.unc.edu
+ * Modified Sun Mar 12 10:34:34 1995, faith@cs.unc.edu, for Linux
*/
#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1988, 1990, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)wall.c 5.14 (Berkeley) 3/2/91";
+static char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93";
#endif /* not lint */
/*
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/uio.h>
-#include <utmp.h>
+
+#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
-#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmp.h>
+#ifdef __linux__
+#include <locale.h>
+#include "pathnames.h"
+#endif
+
+void makemsg __P((char *));
#define IGNOREUSER "sleeper"
char *mbuf;
/* ARGSUSED */
+int
main(argc, argv)
int argc;
char **argv;
struct utmp utmp;
FILE *fp;
char *p, *ttymsg();
+ char line[sizeof(utmp.ut_line) + 1];
+#ifdef __linux__
+ setlocale(LC_CTYPE,"");
+#endif
+
while ((ch = getopt(argc, argv, "n")) != EOF)
switch (ch) {
case 'n':
if (argc > 1)
goto usage;
-#ifdef __linux__
- if (argc != 1)
- makemsg("");
- else
-#endif
makemsg(*argv);
if (!(fp = fopen(_PATH_UTMP, "r"))) {
continue;
#ifdef __linux__
if (utmp.ut_type != USER_PROCESS)
- continue;
+ continue;
#endif
- if (p = ttymsg(&iov, 1, utmp.ut_line))
+ strncpy(line, utmp.ut_line, sizeof(utmp.ut_line));
+ line[sizeof(utmp.ut_line)] = '\0';
+ if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
(void)fprintf(stderr, "wall: %s\n", p);
}
exit(0);
}
+void
makemsg(fname)
char *fname;
{
}
(void)fprintf(fp, "%79s\r\n", " ");
- if (*fname && !(freopen(fname, "r", stdin))) {
+ if (fname && !(freopen(fname, "r", stdin))) {
(void)fprintf(stderr, "wall: can't read %s.\n", fname);
exit(1);
}
while (fgets(lbuf, sizeof(lbuf), stdin))
- for (cnt = 0, p = lbuf; ch = *p; ++p, ++cnt) {
+ for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
if (cnt == 79 || ch == '\n') {
for (; cnt < 79; ++cnt)
putc(' ', fp);
putc('\r', fp);
putc('\n', fp);
cnt = 0;
- } else
- putc(ch, fp);
+ } else {
+ /* Test for control chars added Fri Mar 10
+ 19:49:30 1995, faith@cs.unc.edu */
+ if (!isprint(ch) && !isspace(ch) && ch != '\007') {
+ putc('^', fp);
+ putc(ch^0x40,fp); /* DEL to ?, others to alpha */
+ } else
+ putc(ch, fp);
+ }
}
(void)fprintf(fp, "%79s\r\n", " ");
rewind(fp);
+++ /dev/null
-(This license is based on one written by Ian F. Darwin.)
-
-This software is not subject to any export provision of the United
-States Department of Commerce, and may be exported to any country,
-planet, or star system.
-
-Permission is granted to any sentient being to use this software for
-any purpose on any computer system, and to alter it and redistribute
-it freely, subject to the following restrictions:
-
-1. The author is not responsible for the consequences of use of this
- software, no matter how awful, even if they arise from flaws in it.
-
-2. The origin of this software must not be misrepresented, either by
- explicit claim or by omission. Since few users ever read sources,
- credits must appear in the documentation.
-
-3. Altered versions must be plainly marked as such, and must not be
- misrepresented as being the original software. Since few users
- ever read sources, credits must appear in the documentation.
-
-4. This notice may not be removed or altered.
+++ /dev/null
-.\" -*- nroff -*-
-.TH MAKEDEV 8 "January 1995" "Version 1.4"
-.SH NAME
-MAKEDEV \- create and maintain filesystem device entries
-.SH SYNOPSIS
-.B MAKEDEV
-[
-.I \-vcdnhV
-]
-device or device-group name(s)
-.SH DESCRIPTION
-.B MAKEDEV
-is used to maintain the special filesystem entries found in /dev. It
-creates, or optionally removes, one or more device entries. The names
-and device numbers are defined in the DEVINFO file (q.v.);
-site-specific configuration is found in the file MAKEDEV.cfg.
-.B MAKEDEV
-itself has no knowledge of device information.
-.SH OPTIONS
-.TP
-.I -v
-Verbose mode; print out exactly what's being done.
-.TP
-.I -c
-Create; create the specified devices. [default]
-.TP
-.I -d
-Delete; remove the specified devices instead of creating them.
-.TP
-.I -n
-Do nothing; only print what would be done. Implies -v as well.
-.TP
-.I -h
-Print a usage message.
-.TP
-.I -V
-Print the version string.
-.SS " "
-The following targets are special:
-.TP
-.I update
-Run MAKEDEV in update mode. This reads the list of devices currently
-available from /proc/devices, and updates all entries in /dev to match
-the device numbers found there.
-.TP
-.I local
-Run MAKEDEV to create local devices. This option is obsolete and just
-prints a warning message. Use DEVINFO.local and MAKEDEV.cfg to achieve
-the same results.
-.SH FILES
-.TP 20
-.I /etc/devinfo
-If ./DEVINFO is not found
-.TP
-.I /etc/devinfo.local
-Alternate location for local info
-.TP
-.I /etc/makedev.cfg
-If ./MAKEDEV.cfg is not found
-.TP
-.I MAKEDEV.cache
-Cached data for `update'
-.TP
-.I /proc/devices
-The kernel's list of current devices
-.SH AUTHOR
-David A. Holland (dholland@husc.harvard.edu)
-.br
-.br
-Based on the older
-.B MAKEDEV
-shell script written by Nick Holloway.
-Additional ideas were contributed by Rik Faith.
-.SH NOTES
-The LALR(1) parser generator used to build makedev.c from makedev.syn
-is a commercial product. You won't be able to do a complete rebuild
-unless you have it.
-.SH SEE ALSO
-.BR DEVINFO (5),
-.BR MAKEDEV.cfg (5)
+++ /dev/null
-# Makefile -- Makefile for util-linux Linux utilities
-# Created: Sat Feb 11 13:47:13 1995
-# Revised: Wed Feb 22 16:09:38 1995 by faith@cs.unc.edu
-# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
-#
-
-include ../MCONFIG
-
-# Where to put man pages?
-
-MAN5= devinfo.5 makedev.cfg.5
-MAN8= MAKEDEV-C.8
-
-# Where to put binaries?
-# See the "install" rule for the links. . .
-
-DEV= MAKEDEV-C
-
-# Where to put data?
-
-FILES= devinfo makedev.cfg
-
-all: $(DEV)
-
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
-# Rules for everything else
-
-MAKEDEV-C: makedev.o
- $(CC) $(LDFLAGS) $< -o $@
-
-install: all
- $(INSTALLDIR) $(DEVDIR) $(ETCDIR)
- $(INSTALLDAT) $(FILES) $(ETCDIR)
- $(INSTALLBIN) $(DEV) $(DEVDIR)
- $(INSTALLDIR) $(MAN5DIR) $(MAN8DIR)
- $(INSTALLMAN) $(MAN5) $(MAN5DIR)
- $(INSTALLMAN) $(MAN8) $(MAN8DIR)
-
-.PHONY: clean
-clean:
- -rm -f *.o *~ core $(DEV)
+++ /dev/null
-
-Readme file for MAKEDEV-C:
-
-MAKEDEV is a program to create the special file entries found in /dev.
-MAKEDEV-C is a compiled binary that runs from a config file, called
-DEVINFO. The config file is intended to be fairly human-readable, as
-well as machine-readable.
-
-New in release 1.4.1:
-
-Substantial updates to DEVINFO. Most notably:
- - hdc and hdd are now the drives on the 2nd IDE controller.
- This is NOT how it used to be, nor is it how the shell MAKEDEV
- does it, but it's what the kernel source indicates is right.
- - SCSI tapes were totally messed up in the last release.
- - New and more appropriate QIC device names.
- - Assorted fixes. (See DEVINFO itself for more details.)
-
-Some changes to the sample MAKEDEV.cfg:
- - added a class "system" (root.system, mode 660)
- - do not omit hdc and hdd by default, as they now mean
- something more useful than they used to.
-
- ----------------
-
-New in release 1.4:
-
-First general public release.
-Wrote man pages.
-
- ----------------
-
-Release 1.3:
-
-First tentative limited-distribution release.
-
+++ /dev/null
-This version of makedev-1.4 has been altered by Rik Faith
-(faith@cs.unc.edu) to fit in with the util-linux suite of programs.
-
-The Makefile was re-written, a few programs were re-named, and the group
-for printer was changed to daemon, to conform with the original MAKEDEV
-script.
+++ /dev/null
-/*
- * DEVINFO: device information for MAKEDEV
- *
- * MANY THANKS to those who have sent in corrections - I don't have most
- * of the hardware listed in here, so it won't get fixed if nobody tells me.
- * Mail to: David A. Holland <dholland@husc.harvard.edu>
- *
- * Version 1.4: 21-Feb-94 Corrected proc entry for ibcs2.
- * 27-Feb-94 Make 12 VCs by default.
- * Version 1.3: 14-Feb-94 Corrections from perusing the 1.1.91 source tree.
- * hd1[a-b] becomes hd[c-d]; see comments below.
- * Corrected idecd entry. Added entry for Aztech cdrom.
- * Corrected sbpcd entries.
- * Invented new [and better] names for the QIC tape entries.
- * There appear to be up to 32 cyclades devices supported in 1.1.91.
- * Version 1.2: 14-Feb-94 Revisions snarfed from shell MAKEDEV 2.1.
- * Added cyclades, idecd, apm, dcf, /proc entry for joysticks,
- * scanner becomes logiscan/m105scan/ac4096, some new audio devices,
- * high-number floppy entries, scsi tapes+cds now go 0-7,
- * corrected a comment erroneously indicating fd4 was possible,
- * removed default major numbers for cdu31a, pcaudio, ibcs2.
- * Version 1.1: 13-Feb-94 Corrected scsi tapes (which were totally wrong)
- * Version 1.0: 11-Dec-94 Initial version
- */
-
-/* ignore when /proc/devices mentions these: */
-/* (this is how it was before; couldn't we use mem? */
-ignore { mem, tty, pcmcia }
-
-/* make a batch called generic, standard set of stuff */
-batch generic {
- std, fd0, fd1, hda, hdb, xda, xdb, sda, sdb,
- ptyp, ptyq, ptyr, ptys, console, vts, serial,
- busmice, printers, fd
-}
-
-// The "std" group - basic devices */
-char (std, 1) {
- mem (kmem): 1
- kmem (kmem): 2
- null (public) : 3
- port (kmem) : 4
- zero (public) : 5
- core -> "/proc/kcore"
- full (public) : 7
-}
-block (std, 1) {
- ram (disk) : 1
-}
-char (std, 5) {
- tty (public) : 0
-}
-
-/* the "console" group - system console */
-char (consoles,4) {
- console (cons) : 0 # /dev/console
- tty0 (cons) : 0 # tty0 == console
-}
-
-/* VTs tty1-tty63 (tty0 is special) */
-/* group "vts" is tty1-8; "vts2" is the rest */
-char (vts, 4) tty[1-12] (tty) : 1
-char (vts2, 4) tty [13-63] (tty) : 9
-
-
-/* serial ports, ttyS0-ttyS63 and cua0-cua63 */
-/* group "serial" is just ttyS0-3 and cua0-3; "serial2" is the rest */
-char (serial, 4) ttyS[0-3] (tty) : 64
-char (serial2,4) ttyS[4-63] (tty) : 64+4
-char (serial, 5) cua[0-3] (dialout) : 64
-char (serial2,5) cua[4-63] (dialout) : 64 + 4
-
-/* ptys: pty[pqrs][0-9a-f] and tty[pqrs][0-9][a-f] */
-/* grouped as ptyp, ptyq, ptyr, and ptys */
-char (ptyp, 4) {
- ptyp[0x0-f] (pty) : 128+0*16
- ttyp[0x0-f] (tty) : 192+0*16
-}
-char (ptyq, 4) {
- ptyq[0x0-f] (pty) : 128+1*16
- ttyq[0x0-f] (tty) : 192+1*16
-}
-char (ptyr, 4) {
- ptyr[0x0-f] (pty) : 128+2*16
- ttyr[0x0-f] (tty) : 192+2*16
-}
-char (ptys, 4) {
- ptys[0x0-f] (pty) : 128+3*16
- ttys[0x0-f] (tty) : 192+3*16
-}
-
-/* cyclades serial multiplexer */
-char (cyclades=ttyC, 19) {
- ttyC[0-31] (tty) : 32
-}
-char (cyclades=cub, 20) {
- cub[0-31] (dialout) : 32
-}
-
-/* parallel ports par0-3 and printers lp0-3 (which are merely aliases) */
-/* group is "printers" */
-char (printers=lp, 6) {
- par[0-3] (printer) : 0
- lp[0-3] (printer) : 0
-}
-
-/* busmice: logibm, psaux, inportbm, atibm */
-char (busmice=mouse, 10) {
- logibm (mouse) : 0
- psaux (mouse) : 1
- inportbm (mouse) : 2
- atibm (mouse) : 3
- # sejin (mouse) : 4
-}
-
-/* joysticks: js0, js1; group "js" */
-char (js=Joystick) js[0-1] (mouse) : 0
-
-/* floppies: fd0-3, with lots of modes */
-block (floppies=fd, 2) {
- fd[0-3] (floppy) : 0
- fd[0-3]d360 (floppy) : 4
- fd[0-3]h1200 (floppy) : 8
- fd[0-3]D360 (floppy) : 12
- fd[0-3]H360 (floppy) : 12
- fd[0-3]D720 (floppy) : 16
- fd[0-3]H720 (floppy) : 16
- fd[0-3]h360 (floppy) : 20
- fd[0-3]h720 (floppy) : 24
- fd[0-3]H1440 (floppy) : 28
- fd[0-3]H2880 (floppy) : 32
- fd[0-3]CompaQ (floppy) : 36
- fd[0-3]h1440 (floppy) : 40
- fd[0-3]H1680 (floppy) : 44
- fd[0-3]h410 (floppy) : 48
- fd[0-3]H820 (floppy) : 52
- fd[0-3]H1476 (floppy) : 56
- fd[0-3]H1722 (floppy) : 60
- fd[0-3]h420 (floppy) : 64
- fd[0-3]h830 (floppy) : 68
- fd[0-3]h1494 (floppy) : 72
- fd[0-3]h1743 (floppy) : 76
-}
-
-// There is a controversy regarding whether these should be either
-// (1) hda-hdd are major number 3, hda1-hd1d are major number 22
-// (2) hda-hdb are major number 3, hdc-hdd are major number 22
-//
-// Case (1) is commented out, as case (2) seems to be more popular.
-// Case (2) also appears to make more sense in terms of the way
-// the drivers are actually implemented.
-
-// /* AT hard disks hda-hdd (partitions 1-8 and main) */
-// block(hd=hd,3) hd[a-d] 8/64
-// /* AT hard disks on second controller */
-// block(hd1,22) hd1[a-d] 8/64
-
-/* AT hard disks hda-b (partitions 1-8 and main) */
-block(hd=hd,3) hd[a-b] 8/64
-/* and 2nd controller */
-block(hd1,22) hd[c-d] 8/64
-
-// Ordinarily, the use of the syntax above would automatically create
-// this batch. Because of the way it's done (this is a bug, and hopefully
-// will be fixed in a future release) the batch for the hd1 devices is
-// also created as "hd". This cannot be accessed, but does no harm as
-// long as the order of the above two declarations isn't reversed. sigh.
-// Anyway, this line works around the problem.
-batch hd1 { hdc hdd }
-
-
-/* XT hard drives */
-block(xd=xd,13) xd[a-d] 8/64
-
-/* scsi hard disks sda-sdh */
-block(sd=sd,8) sd[a-h] 8/16
-
-/* loopback disk devices; group "loop" */
-block(loop=loop) loop[0-7] (disk) : 0
-
-/* scsi tapes st0-7 */
-char(st=st, 9) {
- st[0-7] (tape) : 0
- nst[0-7] (tape) : 128
-}
-
-/* qic tapes - group "qic" */
-// The following is what came with the shell MAKEDEV.
-//char (qic=tpqic02, 12) {
-// rmt8 (tape) : 6
-// rmt16 (tape) : 8
-// tape-d (tape) : 136
-// tape-reset (tape) : 255
-//}
-// This, on the other hand, appears to be more correct.
-
-/*
- * By the authority vested in me as the maintainer of this file,
- * I have made up the device names. The "n" versions don't rewind,
- * as with other tape devices. The number specifies the model/capacity.
- * There's not really room left for unit numbers, but I suppose there
- * probably aren't many people with multiple QIC drives either...
- */
-char (qic=tpqic02, 12) {
- nqt11 (tape) : 2
- qt11 (tape) : 3
- nqt24 (tape) : 4
- qt24 (tape) : 5
- nqt120 (tape) : 6
- qt120 (tape) : 7
- nqt150 (tape) : 8
- qt150 (tape) : 9
- qt-reset (tape) : 255
-}
-
-/* ftapes - group ftape */
-char (ftape=mt, 27) {
- rft[0-3] (tape) : 0
- nrft[0-3] (tape) : 4
- ftape -> rft0
- nftape -> nrft0
-}
-
-/* scsi cd */
-block(sr=sr, 11) scd[0-7] (cdrom) : 0
-
-/* sony cd */
-block(sonycd=cdu31a) sonycd (cdrom) : 0
-
-/* mitsumi cd */
-block(mcd=mcd, 23) mcd (cdrom) : 0
-
-/* Sony cdu535 */
-block(cdu535="cdu-535", 24) cdu535 (cdrom) : 0
-
-/* LMS/Philips CD player (needs new major number) */
-block(lmscd, 24) lmscd (cdrom) : 0
-
-/* Aztech CDROM */
-block(aztcd, 29) aztcd0 (cdrom) : 0
-
-/* soundblaster CD, 1st controller */
-block(sbpcd=sbpcd, 25) {
- sbpcd (cdrom) : 0
- sbpcd[0-3] (cdrom) : 0
-}
-/* 2nd, 3rd, 4th */
-block(sbpcd=sbpcd2, 26) sbpcd[4-7] (cdrom) : 0
-block(sbpcd=sbpcd3, 27) sbpcd[8-11] (cdrom) : 0
-block(sbpcd=sbpcd4, 28) sbpcd[12-15] (cdrom) : 0
-
-/* ide cd */
-block (idecd=idecd) {
- idecd (cdrom) : 0
-}
-
-/* Logitech scanner */
-char (logiscan=logiscan) {
- logiscan (scanner) : 0
-}
-
-char (m105scan=m105) {
- m105scan (scanner) : 0
-}
-
-char (ac4096=ac4096) {
- ac4096 (scanner) : 0
-}
-
-// this is apparently obsolete?
-//char (scan=Scanner) {
-// scan (scanner) : 0
-// scand (scanner) : 1
-//}
-
-/* audio */
-char (audio=sound, 14) {
- mixer (audio) : 0
- sequencer (audio) : 1
- midi00 (audio) : 2
- midi -> midi00
- dsp (audio) : 3
- audio (audio) : 4
- sndstat (audio) : 6
-# sequencer2(audio) : 8
- mixer1 (audio) : 16
-# patmgr0 (audio) : 17
- midi01 (audio) : 18
- dsp1 (audio) : 19
- audio1 (audio) : 20
-# patmgr1 (audio) : 33
- midi02 (audio) : 34
- midi03 (audio) : 50
-}
-
-/* pcaudio */
-char (pcaudio=pcsp) {
- pcmixer (audio) : 0
- pcsp (audio) : 3
- pcaudio (audio) : 4
-}
-
-/* sg: generic scsi devices */
-char (sg=sg, 21) {
- sga (scsi) : 0
- sgb (scsi) : 1
- sgc (scsi) : 2
- sgd (scsi) : 3
- sge (scsi) : 4
- sgf (scsi) : 5
- sgg (scsi) : 6
- sgh (scsi) : 7
-}
-
-/* fd: file descriptors */
-char (fd, 0) { // the 0 is not used - there are only links in here!
- fd -> "/proc/self/fd"
- stdin -> "fd/0"
- stdout -> "fd/1"
- stderr -> "fd/2"
-}
-
-/* ibcs2: coff emulation stuff */
-char (ibcs2=socksys, 30) {
- socksys (ibcs2) : 0
- spx (ibcs2) : 2
- nfsd -> socksys
- XOR -> null
-}
-
-char (apm=apm_bios) {
- apm (system) : 0
-}
-
-char (dcf=dcf) {
- dcf (system) : 0
-}
-
-/* demo device for module stuff */
-char (hw=hw) {
- helloworld (public) : 0
-}
-
+++ /dev/null
-.\" -*- nroff -*-
-.TH DEVINFO 5 "January 1995" "Version 1.4"
-.SH NAME
-DEVINFO \- device entry database
-.SH DESCRIPTION
-.B DEVINFO
-is a text file that describes all the possible devices for a system.
-It is used by
-.BR MAKEDEV (8)
-to create special file entries in
-.BR /dev .
-It may be named either
-.BR /dev/DEVINFO " or " /etc/devinfo .
-Information about custom local devices, if any, should be placed in
-.BR DEVINFO.local " or " /etc/devinfo.local ,
-which has the same syntax.
-.LP
-The file format is free-form. Both C, C++, and shell comments are
-understood. There are basically four statements:
-.TP
-.RI "ignore { " proc-device... " }"
-This causes the specified names to be ignored if found in
-.BR /proc/devices .
-.TP
-.RI "batch { " device... " }"
-This creates a "batch" \- a collection of devices which will all be
-created when the batch is invoked. For example, in the standard
-.BR DEVINFO ,
-"generic" is a batch.
-.TP
-.RI "block " device-spec
-This defines one or more block devices.
-.TP
-.RI "char " device-spec
-This defines one or more character devices.
-.LP
-Here is a sample
-.IR device-spec :
-.RS
-.nf
-(std, 1) {
- mem (kmem) : 1
- null (public) : 3
- core -> "/proc/kcore"
-}
-.fi
-.RE
-.LP
-This example defines a group of devices called "std", with major
-number 1. Running
-.B "\"MAKEDEV std\""
-will create all the devices in the group; running, for example,
-.B "\"MAKEDEV null\""
-would make just the one device "null".
-.LP
-It is possible to specify, instead of just "std", something like
-"std=foo". In this case, the stuff on the right-hand side of the
-equals sign specifies a name from
-.BR /proc/devices ,
-and the major number will be retrieved from there if present. If an
-entry from
-.BR /proc/devices
-is specified, the explicit major number may be omitted. In this case,
-if the number is not found in /proc/devices, attempts to create the
-device will be rejected.
-.LP
-Inside the braces is a list of specific devices. The name in
-parenthesis is the "class" - this is something specified in
-.B MAKEDEV.cfg
-(q.v.) that determines the ownership and permissions of the special
-file created. In the above example, the device "mem" was set to have
-the class "kmem", but "null" was set to be "public". Ordinarily you'd
-define "public" to be mode 666, but "kmem" to be mode 660 and owned by
-group kmem. The number after the colon is the minor number for this
-particular device \- for instance, 3 for "null".
-.LP
-You may also specify a symbolic link with "->". For instance, above,
-"core" was made a link to
-.BR /proc/kcore .
-Note that names may contain any characters, but names that contain
-things other than alphanumerics, dash, and underscore should be put in
-double quotes.
-.LP
-An entire range of devices can be created: you may specify a range of
-numbers in brackets, like this:
-.RS
-.nf
-
-tty[1-8] (tty) : 1
-
-.fi
-.RE
-This creates tty1\-tty8 with minor device numbers starting with 1.
-If you specify the range in hex (prefixed by 0x) the device names will
-be created numbered in hex, as is normal for ptys. The range may
-appear inside the name string, but there may only be one range.
-.LP
-There is a special syntax for creating the entire banks of devices for
-a hard drive:
-.RS
-.nf
-
- hd[a-d] 8/64
-
-.fi
-.RE
-What this means is as follows: create hda, and 8 partitions on hda
-(hda1 through hda8), starting with minor number 0. Then create hdb,
-and 8 partitions, starting with minor number 64. Then hdc, etc., with
-minor number 64*2 = 128. And so forth. These are automatically placed
-in the class "disk". The necessary groups and batches are created so
-you can ask
-.B MAKEDEV
-to create "hd" or "hda" or "hda1" and expect it to do the correct
-thing.
-.LP
-Note that simple arithmetic is permitted for specifying the minor
-device number, as this often makes things much clearer and less likely
-to be accidentally broken.
-.SH "SEE ALSO"
-.BR MAKEDEV (8),
-.BR MAKEDEV.cfg (5)
+++ /dev/null
-/*
- * makedev.c: Generate /dev entries
- *
- * Based on the MAKEDEV shell script, version 2.0, distributed with
- * util-linux 1.10 and written by Nick Holloway.
- *
- * A number of bugs were fixed, and some additional features added.
- * Written 10-Dec-94 by David A. Holland, dholland@husc.harvard.edu
- *
- * Copyright 1994, 1995. All rights reserved.
- * See the file LEGAL.NOTICE for conditions of redistribution.
- *
- * Bugs:
- * None known right now.
- *
- * History:
- *
- * Version 1.4a: Sun Feb 26 18:08:45 1995, faith@cs.unc.edu
- * Forced devinfo and makedev to be in /etc
- * Version 1.4: 15-Jan-95 Wrote man pages. Now reads DEVINFO.local.
- * Version 1.3: 31-Dec-94 Bug fixes. Added batches. Added omits.
- * Version 1.2: 11-Dec-94 Add configuration file parsing.
- * Version 1.1: 11-Dec-94 Distinguish block and character devices in the
- * table of major device numbers. Changed the name and format of the
- * update cache file to include the type. It appears that the old script
- * was broken in this regard.
- * Version 1.0: 10-Dec-94 Initial version.
- */
-
-static const char *version = "MAKEDEV-C version 1.4a";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/stat.h>
-
-#define YES 1
-#define NO 0
-
-static int isverbose=NO; /* flag: print out what we do? */
-static int deletion=NO; /* flag: delete instead of create */
-static int donothing=NO; /* flag: don't actually do anything */
-
-/*
- * Proto for main operative function.
- */
-typedef enum { M_CREATE, M_OMIT } makeopts;
-static void make(const char *batch_or_grp_or_devname, makeopts);
-
-/*
- * Roll over and die.
- */
-static void crash(const char *msg) {
- fprintf(stderr, "MAKEDEV: %s\n", msg);
- exit(1);
-}
-
-/*
- * Print a warning.
- */
-static void warn(const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "MAKEDEV: ");
- vfprintf(stderr, format, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-/*
- * Translate string name to uid.
- */
-static uid_t name2uid(const char *name) {
- struct passwd *p = getpwnam(name);
- if (!p) warn("undefined user: %s, using uid 0", name);
- return p ? p->pw_uid : 0; /* make things owned by root by default */
-}
-
-/*
- * Translate string name to gid.
- */
-static gid_t name2gid(const char *name) {
- struct group *g = getgrnam(name);
- if (!g) warn("undefined group: %s, using gid 0", name);
- return g ? g->gr_gid : 0; /* group 0 is a good default too */
-}
-
-/*
- * Proto for parser.
- */
-static void doparse(FILE *f, int filetype, const char *filename);
-
-/************************* device classes *************************/
-
-/*
- * A device class is a string attached to the device which tells us
- * what set of permissions and ownership should be used. This is the
- * table of classes.
- */
-
-typedef struct {
- const char *classname;
- const char *owner;
- const char *group;
- int mode;
-} devclass;
-
-#define MAXCLASSES 32
-static devclass classes[MAXCLASSES];
-static int nclasses=0;
-
-static void addclass(const char *name, const char *o, const char *g, int m) {
- if (nclasses>=MAXCLASSES) crash("out of space for device classes");
- classes[nclasses].classname = name;
- classes[nclasses].owner = o;
- classes[nclasses].group = g;
- classes[nclasses].mode = m;
- nclasses++;
- name2uid(o); /* check for undefined users/groups */
- name2gid(g);
-}
-
-static void loadclasses(void) {
- FILE *f = fopen("/etc/makedev.cfg", "r");
- if (!f) crash("can't find makedev.cfg");
- doparse(f, 4, "makedev.cfg");
- fclose(f);
-}
-
-/*
- * Return the index into the above table for a particular class name.
- */
-static int which_class(const char *name) {
- int i;
- for (i=0; i<nclasses; i++)
- if (!strcmp(classes[i].classname, name)) return i;
- return 0;
-}
-
-/*
- * Produce an "ls -l"-ish mode string.
- */
-static const char *modestring(int mode) {
- static char rv[12];
- int i,z;
- strcpy(rv, "rwxrwxrwx");
- for (i=8,z=1; i>=0; i--, z<<=1) if (!(mode&z)) rv[i]='-';
- return rv;
-}
-
-/*
- * Create (or delete, or update) a block or character device.
- */
-static void class_makedev(const char *name, const char *class,
- int major, int minor, char type) {
- int x = which_class(class), mode = classes[x].mode;
- const char *owner = classes[x].owner, *group = classes[x].group;
- if (isverbose) {
- if (deletion) printf("rm -f %s\n", name);
- else printf("%c%s 1 %-8s %-8s %3d, %3d for %s\n", type,
- modestring(mode), owner, group, major, minor, name);
- }
- if (donothing) return;
- if (unlink(name) && deletion) warn("Couldn't remove %s\n", name);
- if (!deletion) {
- dev_t q = (major<<8) | minor;
- if (mknod(name, type=='c' ? S_IFCHR : S_IFBLK, q) ||
- chown(name, name2uid(owner), name2gid(group)) ||
- chmod(name, mode)) {
- warn("couldn't create %s: %s", name, strerror(errno));
- }
- }
-}
-
-/************************* major number list *************************/
-
-/*
- * In Linux device major numbers can be allocated dynamically, so we go
- * look in /proc/devices to see what they are. This keeps track of things.
- */
-
-typedef struct {
- const char *procname;
- int flag;
-} majorentry;
-
-#define MAXMAJORS 256
-static majorentry cmajors[MAXMAJORS]; /* initialized to 0 */
-static majorentry bmajors[MAXMAJORS]; /* initialized to 0 */
-static int no_proc=0; /* true if we didn't find /proc/devices */
-
-/*
- * Store the name associated with a particular major device number.
- */
-static void set_major(const char *procname, int ischar, int num) {
- if (num<0 || num>255) {
- warn("warning: got bogus major number %d for %s", num, procname);
- return;
- }
- if (ischar) cmajors[num].procname=procname;
- else bmajors[num].procname=procname;
-}
-
-/*
- * Look up a major device number by name; return the default value
- * if provided. A default value of -1 implies the device is only
- * dynamic, and so if there's no entry we shouldn't even note its
- * existence.
- */
-static int get_major(const char *procname, int ischar, int defaalt) {
- int i;
- if (!procname) return defaalt;
- if (ischar) {
- for (i=0; i<MAXMAJORS; i++)
- if (cmajors[i].procname && !strcmp(cmajors[i].procname, procname))
- return i;
- }
- else {
- for (i=0; i<MAXMAJORS; i++)
- if (bmajors[i].procname && !strcmp(bmajors[i].procname, procname))
- return i;
- }
- return defaalt;
-}
-
-/*
- * Read /proc/devices.
- */
-static void setup_majors(void) {
- FILE *f = fopen("/proc/devices", "r");
- if (!f) {
- fprintf(stderr, "MAKEDEV: warning: can't read /proc/devices\n");
- no_proc = 1;
- return;
- }
- doparse(f, 1, "/proc/devices");
- fclose(f);
-}
-
-/************************** procname list *************************/
-
-/*
- * The names found in /proc/devices aren't usually quite the same
- * as the names we use. This is a mapping between the two namespaces.
- */
-typedef struct {
- const char *procname;
- const char *groupname;
-} namealias;
-
-#define MAXALIASES 100
-static namealias aliases[MAXALIASES];
-static int naliases=0;
-
-static void addalias(const char *procname, const char *groupname) {
- if (naliases>=MAXALIASES) crash("out of space for aliases");
- aliases[naliases].procname = procname;
- aliases[naliases].groupname = groupname;
- naliases++;
-}
-
-static void ignore_procname(const char *procname) {
- addalias(procname, NULL);
-}
-
-static const char *procnameof(const char *groupname) {
- int i;
- for (i=0; i<naliases; i++) if (!strcmp(groupname, aliases[i].groupname))
- return aliases[i].procname;
- return NULL;
-}
-
-static const char *groupnameof(const char *procname) {
- int i;
- for (i=0; i<naliases; i++) if (!strcmp(procname, aliases[i].procname))
- return aliases[i].groupname;
- return NULL;
-}
-
-/************************* batch list *************************/
-/*
- * Create a device "batch" - a bunch of devices or groups.
- * This is used for "generic" and automatically for disk entries.
- * (Disk entries for "hd" come up with groups hda, hdb, etc., but
- * "hd" itself needs to run these too.)
- */
-#define MAXTARGETS 32
-#define MAXBATCHES 16
-
-typedef struct {
- const char *name; /* name of batch */
- const char *targets[MAXTARGETS];
- int ntargets;
- int busy;
-} batch;
-
-static batch batches[MAXBATCHES];
-static int nbatches=0;
-
-/*
- * Start a new batch.
- */
-static batch *addbatch(const char *name) {
- batch *b;
- if (nbatches>=MAXBATCHES) crash("Out of space for batches");
- b = &batches[nbatches++];
- b->name = name;
- b->busy = NO;
- return b;
-}
-
-/*
- * Add something to a batch.
- */
-static batch *add2batch(batch *b, const char *target) {
- if (b->ntargets>=MAXTARGETS) {
- warn("Too many targets for batch %s (max %d)", b->name, MAXTARGETS);
- return b;
- }
- b->targets[b->ntargets++] = target;
- return b;
-}
-
-/*
- * Run a batch.
- */
-static void run_batch(const batch *b, makeopts m) {
- int i;
- for (i=0; i<b->ntargets; i++) make(b->targets[i], m);
-}
-
-/*
- * Try to run a batch; returns YES if it found one.
- */
-static int try_run_batch(const char *name, makeopts m) {
- int i;
- for (i=0; i<nbatches; i++) {
- if (!strcmp(name, batches[i].name)) {
- if (batches[i].busy) {
- warn("Found recursive batch definition for %s", batches[i].name);
- continue;
- }
- batches[i].busy=YES;
- run_batch(&batches[i], m);
- batches[i].busy=NO;
- return YES;
- }
- }
- return NO;
-}
-
-/************************* device list *************************/
-
-/*
- * Structure to remember the properties of an individual device.
- * NOTE: if the device is actually a symbolic link, the "class"
- * member is used to store the thing it should be linked to.
- */
-typedef struct {
- const char *name; /* file name to create */
- const char *grp; /* device "group" name (e.g. "busmice") */
- const char *class; /* device class ( -> owner and permissions) */
- int major, minor; /* device number */
- char type; /* 'c', 'b', or 'l' for symbolic link */
- int omit; /* don't make me if this is nonzero */
-} device;
-
-/*
- * Create a device (link or actual "special file") - special files are
- * passed on to class_makedev().
- */
-void makedev(device *d, makeopts m) {
- if (m==M_OMIT) {
- d->omit=1;
- }
- if (d->omit==1) return;
- if (d->type=='l') {
- if (isverbose) {
- if (deletion) printf("rm -f %s\n", d->name);
- else printf("lrwxrwxrwx %s -> %s\n", d->name, d->class);
- }
- if (donothing) return;
- if (unlink(d->name) && deletion) warn("Couldn't remove %s\n", d->name);
- if (!deletion) {
- if (symlink(d->class, d->name)) /* class holds thing pointed to */
- warn("couldn't link %s -> %s: %s", d->name, d->class, strerror(errno));
- }
- }
- else class_makedev(d->name, d->class, d->major, d->minor, d->type);
-}
-
-/*
- * Array of devices. We allocate it once from main(); it doesn't grow.
- * Should maybe make it growable sometime. This keeps track of all possible
- * devices. We build this thing first, and then create devices from it as
- * requested.
- */
-static device *devices = NULL;
-static int maxdevices, ndevices;
-
-/*
- * Allocate space for the device array.
- */
-static void allocate_devs(int nd) {
- devices = malloc(nd * sizeof(device));
- if (!devices) crash("Out of memory");
- ndevices = 0;
- maxdevices = nd;
-}
-
-/*
- * Check all the devices for having valid device classes.
- */
-static void check_classes(void) {
- int i;
- const char *q=NULL;
- for (i=0; i<ndevices; i++)
- if (devices[i].type!='l' && !devices[i].omit &&
- which_class(devices[i].class)<0) {
- if (!q || strcmp(q, devices[i].class)) {
- warn("Invalid device class %s for %s",
- devices[i].class, devices[i].name);
- q = devices[i].class;
- }
- devices[i].class = "default";
- }
-}
-
-/*
- * Create an entry in the device table for a single device.
- */
-static void init(const char *name, const char *grp, const char *class,
- int major, int minor, int type) {
- if (major < 0) return;
- if (!strchr("bcl", type)) {
- warn("invalid device type %c for %s (skipping)", type, name);
- return;
- }
- if (ndevices>=maxdevices) crash("out of space for devices");
- devices[ndevices].name = name;
- devices[ndevices].grp = grp;
- devices[ndevices].class = class;
- devices[ndevices].major = major;
- devices[ndevices].minor = minor;
- devices[ndevices].type = type;
- devices[ndevices].omit = 0;
- ndevices++;
-}
-
-/*
- * Create an entry for a symbolic link "device", such as /dev/fd
- * (which is a symbolic link to /proc/self/fd)
- */
-static void initlink(const char *name, const char *grp, const char *target) {
- init(name, grp, target, 0, 0, 'l');
-}
-
-/*
- * Init lots of devices. This creates a number of devices, numbered between
- * lo and hi. The idea is that "base" contains a %d or %x (or something like
- * that) in it which pulls in the number. The device group can also do this,
- * though this will in most cases not be useful. "baseminor" is the minor
- * number of the first device created.
- */
-static void initlots(const char *base, int lo, int hi, const char *grp,
- const char *class,
- int maj, int baseminor, int type) {
- char buf[32], gbuf[32];
- int i;
- if (maj<0) return;
- for (i=lo; i<hi; i++) {
- sprintf(buf, base, i);
- if (grp) sprintf(gbuf, grp, i); /* grp is permitted to contain a %d */
- init(strdup(buf), grp ? strdup(gbuf) : NULL, class,
- maj, baseminor+i-lo, type);
- }
-}
-
-/*
- * Init a whole (hard) disk's worth of devices - given `hd', it makes
- * hda1...hda8 through hdd1...hdd8 in one fell swoop. "low" and "high"
- * are the letters to use ('a' and 'd' for the previous example).
- * "nparts" is the number of partitions to create, ordinarily 8.
- * "maj" is the major device number; minmult is the multiplier for the
- * minor number. That is, if hda starts at 0, and hdb starts at 64, minmult
- * is 64.
- *
- * Note that it creates "hda", "hdb", etc. too, and puts things in the
- * groups "hda", "hdb", etc. as appropriate. The class is set to "disk".
- */
-static void initdisk(const char *base, int low, int high, int nparts,
- int maj, int minmult) {
- char buf[16], buf2[16];
- int i;
- batch *b;
- if (maj<0) return;
- if (low>=high) return;
- b = addbatch(base);
- for (i=low; i<=high; i++) {
- char *q;
- sprintf(buf, "%s%c", base, i);
- q = strdup(buf);
- init(q, q, "disk", maj, (i-low)*minmult, 'b');
- strcpy(buf2, buf);
- strcat(buf2, "%d");
- initlots(buf2, 1, nparts, buf, "disk", maj, (i-low)*minmult+1, 'b');
- add2batch(b, q);
- }
-}
-
-static void initdevs(void) {
- FILE *f = fopen("/etc/devinfo", "r");
- if (!f) crash("Can't find devinfo");
- doparse(f,3, "devinfo");
- fclose(f);
- f = fopen("/etc/devinfo.local", "r");
- if (!f) f = fopen("/usr/local/etc/devinfo.local", "r");
- if (f) {
- doparse(f,3, "devinfo.local");
- fclose(f);
- }
-}
-
-/************************** update *************************/
-
-/*
- * Call make() with our names for something that appeared in /proc/devices.
- */
-
-static void transmake(const char *procname, makeopts m) {
- const char *gname = groupnameof(procname);
- if (gname) make(gname, m);
-}
-
-/*
- * Update a device that appeared in MAKEDEV.cache. Whenever we update,
- * we save what we did into MAKEDEV.cache; this lets us avoid doing
- * them over the next time. We only do something if the device has
- * disappeared or the major number has changed.
- *
- * Note that this caching made the shell version go much faster (it took
- * around 15 seconds with the cache, vs. over a minute if the cache was
- * blown away.) For us, it still does, but it hardly matters: it shaves
- * one second off a two-second execution.
- *
- * Also note the old script used DEVICES instead of MAKEDEV.cache. We
- * changed because the old file didn't record whether something was
- * a block or character device; since the sets of numbers are independent,
- * this was bound to break.
- */
-static void update2(const char *name, int ischar, int major) {
- int now = get_major(name, ischar, -1);
- if (now<0) {
- deletion = 1; /* must have been zero if we're doing an update */
- transmake(name, M_CREATE);
- deletion = 0;
- }
- else if (now!=major) { /* oops, it moved; remake it */
- transmake(name, M_CREATE);
- if (ischar) cmajors[now].flag=1;
- else bmajors[now].flag=1;
- }
- else {
- if (ischar) cmajors[now].flag=1; /* unchanged; inhibit remaking it */
- else bmajors[now].flag=1; /* unchanged; inhibit remaking it */
- }
-}
-
-static void updatefromcache(const char *name, int major, int type) {
- update2(name, type=='c', major);
-}
-
-
-/*
- * Update. Read the information stored in MAKEDEV.cache from the last
- * update; fix anything that changed; then create any new devices that
- * weren't listed the last time. (We use the "flag" field in the
- * majors array to check this.) At that point, write out a new
- * cache file.
- */
-#define CACHEFILE "MAKEDEV.cache"
-
-static void update(void) {
- FILE *f;
- int i;
- if (no_proc) { warn("Couldn't read anything from /proc/devices"); return; }
- if (deletion) { warn("update and -d are incompatible"); return; }
- f = fopen(CACHEFILE, "r");
- if (f) {
- doparse(f, 2, CACHEFILE);
- fclose(f);
- }
- for (i=0; i<MAXMAJORS; i++) {
- if (cmajors[i].procname && !cmajors[i].flag) {
- transmake(cmajors[i].procname, M_CREATE);
- cmajors[i].flag=1;
- }
- if (bmajors[i].procname && !bmajors[i].flag) {
- transmake(bmajors[i].procname, M_CREATE);
- bmajors[i].flag=1;
- }
- }
- if (donothing) return;
- f = fopen(CACHEFILE, "w");
- if (f) {
- for (i=0; i<MAXMAJORS; i++) {
- if (cmajors[i].procname) fprintf(f, "%s %d char\n", cmajors[i].procname, i);
- if (bmajors[i].procname) fprintf(f, "%s %d block\n", bmajors[i].procname, i);
- }
- fclose(f);
- }
- else warn("warning: can't write MAKEDEV.cache");
-}
-
-/************************* work *************************/
-
-/*
- * Create (or delete, etc. according to flags) a device or device group.
- * The "generic" group is handled specially by recursing once.
- * "update" is handled specially; see update() below.
- * "local" issues a warning; people should use DEVINFO.local instead.
- */
-static void make(const char *what, makeopts m) {
- int i;
- if (!strcmp(what, "update")) {
- if (m!=M_CREATE) warn("update not compatible with those options");
- else update();
- }
- else if (!strcmp(what, "local")) {
- warn("The local target is obsolete.");
- }
- else if (!try_run_batch(what, m)) {
- int found=0;
- for (i=0; i<ndevices; i++) {
- if ((devices[i].grp && !strcmp(what, devices[i].grp)) ||
- !strcmp(what, devices[i].name)) {
- makedev(&devices[i], m);
- found = 1;
- }
- }
- if (!found) warn("unknown device or device group %s", what);
- }
-}
-
-/*
- * A major improvement over the shell version...
- */
-static void usage(void) {
- printf("MAKEDEV-C usage:\n");
- printf(" MAKEDEV-C [-vdcn] device [device...]\n");
- printf(" -v Verbose output\n");
- printf(" -d Remove specified devices\n");
- printf(" -c Create devices (default)\n");
- printf(" -n Don't actually do anything (implies -v)\n");
- printf(" -V Print version information\n");
- printf("\n");
-}
-
-/*
- * We should use getopt one of these days.
- */
-int main(int argc, char **argv) {
- int i,j, done=0;
- for (i=1; i<argc && argv[i][0]=='-' && !done; i++)
- for (j=1; argv[i][j] && !done; j++) switch(argv[i][j]) {
- case '-': done=1; break;
- case 'v': isverbose = 1; break;
- case 'd': deletion = 1; break;
- case 'c': deletion = 0; break;
- case 'n': donothing = 1; isverbose = 1; break;
- case 'h': usage(); exit(0);
- case 'V': printf("MAKEDEV-C: %s\n", version); exit(0);
- default: fprintf(stderr, "MAKEDEV-C: unknown flag %c\n", argv[i][j]);
- exit(1);
- }
- setup_majors(); /* read major device numbers from /proc */
- allocate_devs(1500); /* make space to hold devices */
- initdevs(); /* set up device structures */
- loadclasses(); /* load device classes from config file */
- check_classes(); /* make sure no devices have bogus classes */
- if (i==argc) warn("didn't do anything; try -h for help.");
- else for (; i<argc; i++) make(argv[i], M_CREATE);
- return 0;
-}
-
-
-
-/*
-
- AnaGram Parsing Engine
- Copyright (c) 1993, Parsifal Software.
- All Rights Reserved.
- This module may be copied and/or distributed at the discretion of the
- AnaGram licensee.
-
-*/
-
-
-
-#ifndef MAKEDEV_H
-#include "makedev.h"
-#endif
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define RULE_CONTEXT (&((PCB).cs[(PCB).ssx]))
-#define ERROR_CONTEXT ((PCB).cs[(PCB).error_frame_ssx])
-#define CONTEXT ((PCB).cs[(PCB).ssx])
-
-
-
-parse_pcb_type parse_pcb;
-#define PCB parse_pcb
-
-#line 698 "/usr/local/src/makedev/makedev.syn"
-/************************* parsing support *************************/
-
-/*
- * Don't use the built-in error printing.
- */
-#define SYNTAX_ERROR
-#define PARSER_STACK_OVERFLOW
-#define REDUCTION_TOKEN_ERROR
-
-static void doparse(FILE *f, int filetype, const char *filename) {
- char *x;
- int i=0, len;
- if (filetype<1 || filetype>4) crash("tried to parse a bad file type");
- if (filetype!=1) { /* /proc/devices won't stat intelligently */
- struct stat buf;
- if (fstat(fileno(f), &buf)) crash("fstat failed?!?");
- len = buf.st_size;
- }
- else len=1023;
- x = malloc(len+1);
- if (!x) crash("Out of memory");
-
- len = fread(x, 1, len, f); /* it shouldn't return a short count... */
- if (len<0) crash("fread failed?!?");
- x[len]=0;
-
- init_parse();
- PCB.input_code = filetype+'0';
- parse();
- PCB.column--; /* correct for the filetype token */
- while (!PCB.exit_flag) {
- PCB.input_code = x[i++];
- parse();
- }
- if (PCB.exit_flag == AG_SYNTAX_ERROR_CODE) {
- warn("syntax error: %s, line %d, column %d in file %s",
- PCB.error_message, PCB.line, PCB.column, filename);
- crash("Sorry, can't continue.");
- }
- else if (PCB.exit_flag != AG_SUCCESS_CODE) {
- crash("parser stack overflow!");
- }
-}
-
-#define STRINGSIZE 8192
-static char string_space[STRINGSIZE];
-static int stringptr=0;
-
-static const char *string_start(int c) {
- if (stringptr>=STRINGSIZE) crash("out of string space");
- return string_space[stringptr]=c, string_space+stringptr++;
-}
-
-static void string_push(int c) {
- if (stringptr>=STRINGSIZE) crash("out of string space");
- string_space[stringptr++] = c;
-}
-
-static void string_finish(void) {
- string_push(0);
-}
-
-
-#line 790 "makedev.c"
-#line 840 "/usr/local/src/makedev/makedev.syn"
- static const char *cur_group=NULL, *cur_class=NULL;
- static int cur_type;
- static int cur_maj=0, cur_min=0, cur_bot=0, cur_top=0, ishex=0;
-
- static void dhsproc(const char *g, const char *p, int t, int m) {
- cur_group = g;
- cur_type = t;
- cur_maj = get_major(p, (t=='c'), m);
- cur_min = 0;
- cur_bot = cur_top = ishex = 0;
- if (p) addalias(p,g);
- }
-
- static void newdev(const char *n) {
- if (cur_maj<0) return;
- init(n, cur_group, cur_class, cur_maj, cur_min, cur_type);
- }
- static void devrange(const char *n, const char *n1) {
- char temp[32];
- if (cur_maj<0) return;
- sprintf(temp, "%s%%d%s", n, n1 ? n1 : "");
- initlots(temp, cur_bot, cur_top, cur_group, cur_class,
- cur_maj, cur_min, cur_type);
- }
- static void doinitlink(const char *src, const char *tg) {
- if (cur_maj>=0) initlink(src, cur_group, tg);
- }
-
-#line 820 "makedev.c"
-#ifndef CONVERT_CASE
-#define CONVERT_CASE(c) (c)
-#endif
-#ifndef TAB_SPACING
-#define TAB_SPACING 8
-#endif
-
-#define ag_rp_1(n, s) (set_major(s,YES,n))
-
-#define ag_rp_2(n, s) (set_major(s,NO,n))
-
-#define ag_rp_3(n, maj, t) (updatefromcache(n,maj,t))
-
-#define ag_rp_4() ('b')
-
-#define ag_rp_5() ('c')
-
-#define ag_rp_8(n, i) (add2batch(addbatch(n), i))
-
-#define ag_rp_9(b, i) (add2batch(b,i))
-
-#define ag_rp_10(n) (n)
-
-#define ag_rp_11(n) (ignore_procname(n))
-
-#define ag_rp_12(t, g, p) (dhsproc(g,p,t,-1))
-
-#define ag_rp_13(t, g, p, m) (dhsproc(g,p,t,m))
-
-#define ag_rp_14(t, g, m) (dhsproc(g,NULL,t,m))
-
-#define ag_rp_15(classname) (classname)
-
-#define ag_rp_16(c, min) ((cur_class=c, cur_min=min))
-
-#define ag_rp_17(a, b) (cur_bot=a, cur_top=b, ishex=0)
-
-#define ag_rp_18(a, b) (cur_bot=a, cur_top=b, ishex=1)
-
-#define ag_rp_19(n) (newdev(n))
-
-#define ag_rp_20(n, n1) (devrange(n,n1))
-
-#define ag_rp_21(n) (devrange(n,NULL))
-
-#define ag_rp_22(n, a, b, p, m) (initdisk(n, a, b, p, cur_maj, m))
-
-#define ag_rp_23(n, tg) (doinitlink(n, tg))
-
-#define ag_rp_24(n) (n)
-
-#define ag_rp_25(n) (n)
-
-#define ag_rp_26(n) (n)
-
-#define ag_rp_27(n, o, g, m) (addclass(n,o,g,m))
-
-#define ag_rp_28(n) (make(n, M_OMIT))
-
-#define ag_rp_29(n) (make(n, M_OMIT))
-
-#define ag_rp_30(n) (n)
-
-#define ag_rp_31(s) (string_finish(), s)
-
-#define ag_rp_32(s) (s)
-
-#define ag_rp_33(c) (string_start(c))
-
-#define ag_rp_34(s, c) (string_push(c), s)
-
-#define ag_rp_35(s) (string_finish(), s)
-
-#define ag_rp_36(c) (string_start(c))
-
-#define ag_rp_37(s, c) (string_push(c), s)
-
-#define ag_rp_38(c) (c)
-
-#define ag_rp_39() ('\\')
-
-#define ag_rp_40() ('"')
-
-#define ag_rp_41(d) (d-'0')
-
-#define ag_rp_42(n, d) (n*10 + d-'0')
-
-#define ag_rp_43(d) (d)
-
-#define ag_rp_44(n, d) (16*n+d)
-
-#define ag_rp_45(d) (d)
-
-#define ag_rp_46(n, d) (16*n+d)
-
-#define ag_rp_47(d) (d-'0')
-
-#define ag_rp_48(d) (10 + (d&7))
-
-#define ag_rp_49(d) (d-'0')
-
-#define ag_rp_50(n, d) (n*8+d-'0')
-
-#define ag_rp_51(x, t) (x+t)
-
-#define ag_rp_52(x, t) (x-t)
-
-#define ag_rp_53(t, f) (t*f)
-
-#define ag_rp_54(f) (-f)
-
-#define ag_rp_55(x) (x)
-
-
-#define READ_COUNTS
-#define WRITE_COUNTS
-static parse_vs_type ag_null_value;
-#define V(i,t) (*(t *) (&(PCB).vs[(PCB).ssx + i]))
-#define VS(i) (PCB).vs[(PCB).ssx + i]
-
-#ifndef GET_CONTEXT
-#define GET_CONTEXT CONTEXT = (PCB).input_context
-#endif
-
-typedef enum {
- ag_action_1,
- ag_action_2,
- ag_action_3,
- ag_action_4,
- ag_action_5,
- ag_action_6,
- ag_action_7,
- ag_action_8,
- ag_action_9,
- ag_action_10,
- ag_action_11,
- ag_action_12
-} ag_parser_action;
-
-static int ag_ap;
-
-
-
-static const unsigned char ag_rpx[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 0, 0, 0, 3, 4, 5, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 6, 0, 0, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 25, 26, 0, 0, 0, 27, 28,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 0, 41, 42, 43, 44,
- 45, 46, 47, 48, 0, 49, 50, 0, 51, 0, 0, 52, 53
-};
-
-static unsigned char ag_key_itt[] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0
-};
-
-static unsigned short ag_key_pt[] = {
- 1,121, 1,122, 1,125, 1,126, 1,138, 1,139,0
-};
-
-static unsigned char ag_key_ch[] = {
- 0, 47,255, 42,255, 42, 47,255, 88,120,255, 97,108,255,104,108,255, 45,
- 47, 48, 66, 67, 98, 99,105,111,255, 42, 47,255, 47, 99,111,255, 42, 47,
- 255, 97,108,255, 47, 98, 99,105,255, 42, 47,255, 47,255, 42, 47,255, 47,
- 66, 67,255, 47, 99,111,255, 97,108,255, 47, 98, 99,105,255, 47,255, 47,
- 66, 67,255, 42, 47,255, 97,108,255,104,108,255, 47, 66, 67, 98, 99,105,
- 111,255, 97,108,255,104,108,255, 47, 66, 67, 98, 99,105,111,255, 99,111,
- 255, 97,108,255, 98, 99,105,255, 66, 67,255, 42, 47,255, 45, 47,255, 88,
- 120,255, 47, 48,255, 42, 47,255, 47, 98, 99,255, 98, 99,255, 42, 47,255,
- 97,108,255,104,108,255, 47, 98, 99,105,111,255, 45,255, 88,120,255, 48,
- 255
-};
-
-static unsigned char ag_key_act[] = {
- 0,3,4,3,4,0,0,4,0,0,4,7,7,4,7,7,4,3,2,2,3,3,2,2,7,7,4,0,0,4,2,7,7,4,0,
- 0,4,7,7,4,2,2,7,7,4,0,0,4,2,4,0,0,4,2,3,3,4,3,7,7,4,7,7,4,3,2,7,7,4,3,
- 4,3,3,3,4,0,0,4,7,7,4,7,7,4,2,3,3,2,2,7,7,4,7,7,4,7,7,4,3,3,3,2,2,7,7,
- 4,7,7,4,7,7,4,2,7,7,4,3,3,4,0,0,4,3,2,4,0,0,4,3,2,4,0,0,4,2,7,7,4,7,7,
- 4,0,0,4,7,7,4,7,7,4,2,2,2,7,7,4,3,4,0,0,4,2,4
-};
-
-static unsigned char ag_key_parm[] = {
- 0, 80, 0, 84, 0, 80, 86, 0,145,144, 0, 6, 0, 0, 2, 8, 0,137,
- 0, 0,118,117, 0, 0, 4, 10, 0, 80, 86, 0, 0, 8, 10, 0, 80, 86,
- 0, 6, 0, 0, 0, 0, 2, 4, 0, 80, 86, 0, 0, 0, 80, 86, 0, 0,
- 118,117, 0, 86, 8, 10, 0, 6, 0, 0, 86, 0, 2, 4, 0, 86, 0, 86,
- 118,117, 0, 80, 86, 0, 6, 0, 0, 2, 8, 0, 0,118,117, 0, 0, 4,
- 10, 0, 6, 0, 0, 2, 8, 0, 86,118,117, 0, 0, 4, 10, 0, 8, 10,
- 0, 6, 0, 0, 0, 2, 4, 0,118,117, 0, 80, 86, 0,137, 0, 0,145,
- 144, 0, 80, 0, 0, 80, 86, 0, 0, 0, 2, 0, 0, 2, 0, 80, 86, 0,
- 6, 0, 0, 2, 8, 0, 0, 0, 0, 4, 10, 0,137, 0,145,144, 0, 0,
- 0
-};
-
-static unsigned short ag_key_jmp[] = {
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 38, 42, 0, 46, 49, 0, 4,
- 5, 8, 6, 20, 11, 14, 53, 59, 0, 0, 0, 0, 27, 63, 68, 0, 0, 0,
- 0, 72, 76, 0, 34, 37, 80, 84, 0, 0, 0, 0, 45, 0, 0, 0, 0, 50,
- 90,104, 0,122,124,129, 0,135,139, 0,133, 61,143,147, 0,153, 0,155,
- 157,171, 0, 0, 0, 0,221,225, 0,229,232, 0, 75,189,203, 78, 81,236,
- 242, 0,280,284, 0,288,291, 0,246,248,262, 92, 95,295,301, 0,305,310,
- 0,314,318, 0,109,322,326, 0,332,346, 0, 0, 0, 0,364,119, 0, 0,
- 0, 0,366,125, 0, 0, 0, 0,131,368,373, 0,377,382, 0, 0, 0, 0,
- 386,390, 0,394,397, 0,141,144,147,401,407, 0,411, 0, 0, 0, 0,158,
- 0
-};
-
-static unsigned short ag_key_index[] = {
- 1, 3, 17, 0, 3, 3, 30, 40, 48, 53, 57, 64, 69, 71, 0, 0, 84, 98,
- 106,112, 0,116, 0, 1, 1, 0, 0,106, 48, 48, 48, 48, 1, 1, 0, 0,
- 0, 69,112, 0,122, 48, 0, 0, 48, 48, 69, 69,116, 48, 69, 69, 0,128,
- 0, 0, 0, 69, 0, 69, 0, 0,134,138, 0, 0, 0,128, 0, 0, 69, 48,
- 69, 0,150, 64, 0,156, 0, 69, 0,116, 0,116, 69, 0, 0, 0, 1, 0,
- 0, 69, 69, 0, 1, 0,128,161, 0, 0, 0, 0, 0, 69, 69, 0, 57, 0,
- 0, 0, 69, 0, 64, 69, 1, 0, 1, 1, 0, 0, 0, 0, 0,161, 64, 48,
- 69, 69, 48, 0,128, 0, 48, 0, 0,161,161, 69, 69, 69, 69, 0, 0, 0,
- 0, 0,128,161,161,128,161, 1, 0, 69, 69, 0, 1, 0, 69, 0
-};
-
-static unsigned char ag_key_ends[] = {
-42,0, 47,0, 62,0, 108,111,99,107,32,100,101,118,105,99,101,115,58,0,
-104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,58,0,
-116,99,104,0, 111,99,107,0, 97,114,0, 97,115,115,0,
-103,110,111,114,101,0, 109,105,116,0, 108,97,115,115,0,
-109,105,116,0, 116,99,104,0, 111,99,107,0, 104,97,114,0,
-103,110,111,114,101,0, 108,111,99,107,32,100,101,118,105,99,101,115,58,0,
-104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,58,0,
-47,0, 108,97,115,115,0, 109,105,116,0, 47,0, 116,99,104,0,
-111,99,107,0, 104,97,114,0, 103,110,111,114,101,0, 47,0, 47,0,
-108,111,99,107,32,100,101,118,105,99,101,115,58,0,
-104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,58,0,
-108,111,99,107,32,100,101,118,105,99,101,115,58,0,
-104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,58,0,
-116,99,104,0, 111,99,107,0, 97,114,0, 97,115,115,0,
-103,110,111,114,101,0, 109,105,116,0, 47,0,
-108,111,99,107,32,100,101,118,105,99,101,115,58,0,
-104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,58,0,
-116,99,104,0, 111,99,107,0, 97,114,0, 97,115,115,0,
-103,110,111,114,101,0, 109,105,116,0, 108,97,115,115,0,
-109,105,116,0, 116,99,104,0, 111,99,107,0, 104,97,114,0,
-103,110,111,114,101,0, 108,111,99,107,32,100,101,118,105,99,101,115,58,0,
-104,97,114,97,99,116,101,114,32,100,101,118,105,99,101,115,58,0,
-62,0, 42,0, 108,111,99,107,0, 104,97,114,0, 108,111,99,107,0,
-104,97,114,0, 116,99,104,0, 111,99,107,0, 97,114,0, 97,115,115,0,
-103,110,111,114,101,0, 109,105,116,0, 62,0,
-};
-#define AG_TCV(x) (((int)(x) >= -1 && (int)(x) <= 255) ? ag_tcv[(x) + 1] : 0)
-
-static const unsigned char ag_tcv[] = {
- 18, 18,152,152,152,152,152,152,152,152,150, 93,152,152,150,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,151,153, 95,
- 87,153,153,153,153,130,128,149,148,127,133,153,135,154,113,114,115,116,
- 154,154,154,155,155,131,153,153,129,153,153,153,156,156,156,156,156,156,
- 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,
- 157,157,134, 99,132,153,157,153,156,119,120,156,156,156,157,157,157,157,
- 157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,157,124,153,
- 123,153,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152
-};
-
-#ifndef SYNTAX_ERROR
-#define SYNTAX_ERROR fprintf(stderr,"%s, line %d, column %d\n", \
- (PCB).error_message, (PCB).line, (PCB).column)
-#endif
-
-#ifndef FIRST_LINE
-#define FIRST_LINE 1
-#endif
-
-#ifndef FIRST_COLUMN
-#define FIRST_COLUMN 1
-#endif
-
-
-#ifndef PARSER_STACK_OVERFLOW
-#define PARSER_STACK_OVERFLOW {fprintf(stderr, \
- "\nParser stack overflow, line %d, column %d\n",\
- (PCB).line, (PCB).column);}
-#endif
-
-#ifndef REDUCTION_TOKEN_ERROR
-#define REDUCTION_TOKEN_ERROR {fprintf(stderr, \
- "\nReduction token error, line %d, column %d\n", \
- (PCB).line, (PCB).column);}
-#endif
-
-
-typedef enum
- {ag_accept_key, ag_set_key, ag_jmp_key, ag_end_key, ag_no_match_key,
- ag_cf_accept_key, ag_cf_set_key, ag_cf_end_key} key_words;
-
-
-static void ag_track(void) {
- int ag_k = 0;
- while (ag_k < (PCB).rx) {
- int ag_ch = (PCB).lab[ag_k++];
- switch (ag_ch) {
- case '\n':
- (PCB).column = 1, (PCB).line++;
- case '\r':
- case '\f':
- break;
- case '\t':
- (PCB).column += (TAB_SPACING) - ((PCB).column - 1) % (TAB_SPACING);
- break;
- default:
- (PCB).column++;
- }
- }
- ag_k = 0;
- while ((PCB).rx < (PCB).fx) (PCB).lab[ag_k++] = (PCB).lab[(PCB).rx++];
- (PCB).fx = ag_k;
- (PCB).rx = 0;
-}
-
-
-static void ag_prot(void) {
- int ag_k = 38 - ++(PCB).btsx;
- if (ag_k <= (PCB).ssx) {
- (PCB).exit_flag = AG_STACK_ERROR_CODE;
- PARSER_STACK_OVERFLOW;
- return;
- }
- (PCB).bts[(PCB).btsx] = (PCB).sn;
- (PCB).bts[ag_k] = (PCB).ssx;
- (PCB).vs[ag_k] = (PCB).vs[(PCB).ssx];
- (PCB).ss[ag_k] = (PCB).ss[(PCB).ssx];
-}
-
-static void ag_undo(void) {
- if ((PCB).drt == -1) return;
- while ((PCB).btsx) {
- int ag_k = 38 - (PCB).btsx;
- (PCB).sn = (PCB).bts[(PCB).btsx--];
- (PCB).ssx = (PCB).bts[ag_k];
- (PCB).vs[(PCB).ssx] = (PCB).vs[ag_k];
- (PCB).ss[(PCB).ssx] = (PCB).ss[ag_k];
- }
- (PCB).token_number = (parse_token_type) (PCB).drt;
- (PCB).ssx = (PCB).dssx;
- (PCB).sn = (PCB).dsn;
- (PCB).drt = -1;
-}
-
-
-static const unsigned char ag_tstt[] = {
-151,150,80,0,2,111,112,
-157,156,155,154,153,152,151,150,149,148,135,134,133,132,131,130,129,128,127,
- 124,123,120,119,116,115,114,113,99,95,93,87,0,82,83,
-151,150,80,0,2,
-116,115,114,113,0,5,6,8,10,12,
-157,156,155,154,153,152,151,150,149,148,135,134,133,132,131,130,129,128,127,
- 124,123,120,119,116,115,114,113,99,95,93,87,0,
-84,0,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-139,138,93,87,86,0,3,13,14,15,85,88,92,140,
-126,125,122,121,120,119,93,87,86,0,3,11,14,15,85,88,92,140,
-157,156,133,120,119,95,93,87,86,0,3,9,14,15,85,88,92,140,
-118,117,93,87,86,0,3,7,14,15,85,88,92,140,
-157,156,155,154,153,152,151,150,149,148,135,134,133,132,131,130,129,128,127,
- 124,123,120,119,116,115,114,113,99,95,87,18,0,90,91,
-93,0,
-151,150,80,0,2,111,112,
-157,156,155,154,139,138,133,127,126,125,123,122,121,120,119,118,117,116,115,
- 114,113,95,93,87,86,18,0,3,88,92,140,
-139,138,0,69,70,71,72,73,75,
-126,125,122,121,120,119,0,29,30,31,32,33,34,35,36,42,45,
-157,156,133,120,119,95,0,1,4,26,27,28,141,142,
-118,117,0,16,17,19,22,
-157,156,155,154,153,152,151,150,149,148,135,134,133,132,131,130,129,128,127,
- 124,123,120,119,116,115,114,113,99,95,87,18,0,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-157,156,133,124,120,119,95,0,1,4,26,37,141,142,
-157,156,133,120,119,95,0,1,4,26,141,142,
-139,138,18,0,69,71,72,73,75,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-130,0,50,
-157,156,133,120,119,95,0,1,4,26,46,141,142,
-124,0,37,
-157,156,133,124,120,119,95,93,87,86,0,3,14,15,37,85,88,92,140,
-126,125,122,121,120,119,18,0,29,30,31,32,33,34,36,42,45,
-157,156,155,154,153,151,149,148,135,134,133,132,131,130,129,128,127,124,123,
- 120,119,116,115,114,113,99,87,0,96,97,
-151,150,80,0,2,111,112,
-157,156,155,154,151,150,133,120,119,116,115,114,113,80,0,2,111,112,
-155,154,116,115,114,113,0,25,100,
-157,156,133,120,119,95,18,0,1,4,26,27,141,142,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-87,86,0,3,14,85,88,92,140,
-87,86,0,3,14,85,88,92,140,
-118,117,18,0,16,19,22,
-151,150,80,0,2,111,112,
-157,156,133,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-87,86,0,3,14,85,88,92,140,
-131,0,57,
-151,150,80,0,2,111,112,
-157,156,133,120,119,95,0,1,4,26,51,141,142,
-124,0,37,
-127,123,0,41,48,49,
-157,156,133,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-157,156,133,120,119,95,0,1,4,26,38,65,141,142,
-157,156,133,123,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-99,95,0,
-157,156,155,154,153,151,149,148,135,134,133,132,131,130,129,128,127,124,123,
- 120,119,116,115,114,113,99,95,87,0,97,
-151,150,80,0,2,111,112,
-155,154,122,121,120,119,116,115,114,113,0,29,30,31,32,33,100,
-155,154,116,115,114,113,0,23,24,25,100,
-155,154,116,115,114,113,0,20,21,25,100,
-157,156,133,120,119,95,0,1,4,26,76,77,141,142,
-151,150,80,0,2,111,112,
-157,156,133,120,119,95,0,1,4,26,141,142,
-129,127,0,48,52,
-157,156,133,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-151,150,80,0,2,111,112,
-157,156,133,123,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-157,156,133,120,119,95,0,1,4,26,47,141,142,
-151,150,80,0,2,111,112,
-126,125,122,121,120,119,93,87,86,18,0,3,14,15,85,88,92,140,
-157,156,133,120,119,95,0,1,4,26,43,44,141,142,
-137,134,130,0,50,55,56,59,60,68,
-157,156,133,120,119,95,0,1,4,26,38,39,40,65,141,142,
-87,86,0,3,14,85,88,92,140,
-157,156,155,154,133,120,119,116,115,114,113,95,0,1,4,26,100,141,142,
-155,154,116,115,114,113,0,23,25,100,
-157,156,155,154,133,120,119,116,115,114,113,95,0,1,4,26,100,141,142,
-155,154,116,115,114,113,0,20,25,100,
-157,156,133,127,123,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-157,156,133,123,120,119,95,0,1,4,26,41,76,141,142,
-157,156,133,120,119,95,0,1,4,26,141,142,
-155,154,116,115,114,113,0,25,100,
-151,150,80,0,2,111,112,
-157,156,133,120,119,95,0,1,4,26,53,141,142,
-157,156,133,120,119,95,0,1,4,26,47,141,142,
-157,156,133,127,123,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-157,156,133,127,123,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-157,156,133,123,120,119,95,0,1,4,26,41,43,141,142,
-151,150,80,0,2,111,112,
-157,156,133,120,119,95,0,1,4,26,141,142,
-151,150,80,0,2,111,112,
-157,156,155,154,145,144,133,120,119,116,115,114,113,0,25,63,66,100,101,102,
- 103,
-157,156,133,130,120,119,95,0,1,4,26,50,55,56,65,141,142,
-157,156,133,120,119,95,0,1,4,26,141,142,
-131,0,57,
-157,156,133,120,119,95,0,1,4,26,38,65,141,142,
-123,0,41,
-87,86,0,3,14,85,88,92,140,
-87,86,0,3,14,85,88,92,140,
-127,0,48,49,
-139,138,93,87,86,18,0,3,14,15,85,88,92,140,
-154,116,115,114,113,0,74,78,106,
-155,154,128,116,115,114,113,0,54,100,
-128,127,0,48,54,
-157,156,133,127,123,120,119,95,93,87,86,0,3,14,15,85,88,92,140,
-127,0,48,49,
-126,125,122,121,120,119,93,87,86,18,0,3,14,15,85,88,92,140,
-87,86,0,3,14,85,88,92,140,
-151,150,80,0,2,111,112,
-133,0,61,
-151,150,80,0,2,111,112,
-151,150,80,0,2,111,112,
-156,155,154,120,119,116,115,114,113,0,100,104,105,
-156,155,154,133,120,119,116,115,114,113,0,61,100,104,105,
-155,154,133,116,115,114,113,0,61,100,
-130,0,50,55,56,
-128,0,54,
-155,154,145,144,133,130,116,115,114,113,0,25,50,58,61,63,100,101,102,103,
- 107,109,
-126,125,122,121,120,119,93,87,86,18,0,3,14,15,85,88,92,140,
-151,150,80,0,2,111,112,
-154,116,115,114,113,0,106,
-87,86,0,3,14,85,88,92,140,
-151,150,80,0,2,111,112,
-155,154,116,115,114,113,0,25,100,
-151,150,80,0,2,111,112,
-157,156,133,120,119,0,66,
-151,150,80,0,2,111,112,
-156,155,154,120,119,116,115,114,113,0,64,100,104,105,
-155,154,116,115,114,113,0,25,100,
-155,154,145,144,133,130,116,115,114,113,0,25,50,58,61,63,100,101,102,103,
- 107,109,
-155,154,145,144,133,130,116,115,114,113,0,25,50,61,63,100,101,102,103,109,
-156,155,154,120,119,116,115,114,113,0,100,104,105,
-155,154,116,115,114,113,0,100,
-149,0,110,
-148,133,87,86,0,3,14,61,85,88,92,108,140,
-155,154,128,116,115,114,113,0,54,100,
-132,0,62,
-156,155,154,132,120,119,116,115,114,113,0,62,100,104,105,
-155,154,132,116,115,114,113,0,62,100,
-148,133,128,0,54,61,108,
-151,150,80,0,2,111,112,
-155,154,145,144,133,130,116,115,114,113,0,25,50,61,63,100,101,102,103,109,
-155,154,145,144,133,130,116,115,114,113,0,25,50,61,63,100,101,102,103,107,
- 109,
-151,150,80,0,2,111,112,
-155,154,145,144,133,130,116,115,114,113,0,25,50,61,63,100,101,102,103,107,
- 109,
-151,150,80,0,2,111,112,
-155,154,116,115,114,113,0,25,100,
-149,0,110,
-149,0,110,
-155,154,135,116,115,114,113,0,67,100,
-151,150,80,0,2,111,112,
-155,154,116,115,114,113,0,25,100,
-155,154,116,115,114,113,87,86,0,3,14,85,88,92,100,140,
- 0
-};
-
-
-static unsigned char ag_astt[1821] = {
- 1,1,1,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,8,1,1,9,9,1,5,3,1,1,1,1,7,0,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 9,9,9,9,9,9,9,9,9,9,9,9,9,5,3,7,1,1,1,5,1,1,3,1,1,1,5,1,1,3,1,1,1,5,1,1,3,
- 1,1,1,5,1,1,3,8,8,8,1,1,7,1,3,1,1,1,1,1,1,8,8,8,8,8,8,8,1,1,7,1,3,1,1,1,1,
- 1,1,8,8,8,8,8,8,8,1,1,7,1,3,1,1,1,1,1,1,8,8,8,1,1,7,1,3,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,1,3,3,7,1,1,1,5,
- 1,1,3,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,8,1,1,5,7,3,1,1,1,1,1,7,
- 1,1,1,1,1,1,1,1,1,1,1,1,7,1,2,2,2,2,1,1,1,1,1,2,2,2,2,2,1,7,2,2,1,1,1,1,1,
- 1,1,7,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
- 9,5,1,1,1,5,1,1,3,1,1,1,5,1,1,3,2,2,2,1,2,2,1,7,2,2,1,1,1,1,2,2,2,2,2,1,7,
- 2,2,1,1,1,1,1,3,7,3,3,3,1,1,1,1,1,5,1,1,3,1,1,1,5,1,1,3,1,1,1,5,1,1,3,1,1,
- 1,5,1,1,3,1,1,1,5,1,1,3,1,1,1,5,1,1,3,1,7,1,2,2,2,2,2,1,7,2,2,1,1,1,1,1,7,
- 1,8,8,8,1,8,8,8,8,1,1,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,7,1,2,2,2,2,3,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,7,1,2,1,1,1,5,1,1,3,
- 10,10,10,10,1,1,10,10,10,10,10,10,10,1,5,1,1,3,1,1,1,1,1,1,7,1,2,2,2,2,2,2,
- 1,3,7,2,2,1,3,1,1,1,1,1,5,1,1,3,1,1,1,5,1,1,3,1,1,8,1,1,1,1,1,1,1,1,8,1,1,
- 1,1,1,1,1,1,3,7,3,1,1,1,1,1,5,1,1,3,8,8,8,8,8,8,8,1,1,7,1,1,1,1,1,1,1,1,1,
- 8,1,2,1,1,1,1,1,7,1,1,1,1,5,1,1,3,2,2,2,2,2,1,7,2,2,2,1,1,1,1,7,1,1,1,8,1,
- 1,1,8,8,8,8,8,8,8,1,1,7,1,1,1,1,1,1,1,2,2,2,2,2,1,7,2,2,2,3,1,1,1,8,8,8,8,
- 8,8,8,8,1,1,7,1,1,1,1,1,1,1,2,2,7,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 2,2,2,2,2,1,2,2,7,2,1,1,1,5,1,1,3,1,1,1,1,1,1,1,1,1,1,7,1,2,2,2,2,2,1,1,1,
- 1,1,1,7,1,1,1,2,1,1,1,1,1,1,7,1,1,1,2,2,2,2,2,2,1,7,2,2,1,1,1,1,1,1,1,1,5,
- 1,1,3,2,2,2,2,2,1,7,2,2,1,1,1,1,1,7,1,1,8,8,8,8,8,8,8,1,1,7,1,1,1,1,1,1,1,
- 1,1,1,5,1,1,3,5,5,5,5,5,5,5,8,1,1,7,1,3,3,1,1,1,1,2,2,2,2,2,1,7,2,2,2,1,1,
- 1,1,1,1,5,1,1,3,5,5,5,5,5,5,8,1,1,5,7,1,3,3,1,1,1,1,2,2,2,2,2,1,7,2,2,1,1,
- 1,1,1,1,1,1,7,1,1,2,1,1,1,2,2,2,2,2,1,8,2,2,2,1,1,1,1,1,1,1,1,8,1,2,1,1,1,
- 1,2,2,1,1,2,2,2,1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,1,5,3,1,2,2,2,1,1,2,2,2,
- 1,1,1,1,1,7,2,2,1,2,1,1,1,1,1,1,1,1,5,3,1,2,8,8,8,8,8,8,8,8,8,1,1,7,1,1,1,
- 1,1,1,1,2,2,2,1,2,2,1,7,2,2,1,1,3,1,1,2,2,2,2,2,1,7,2,2,1,1,1,1,1,1,1,1,1,
- 7,1,2,1,1,1,5,1,1,3,2,2,2,2,2,1,7,2,2,2,1,1,1,2,2,2,2,2,1,7,2,2,2,1,1,1,5,
- 5,5,5,5,5,5,5,8,1,1,7,1,2,2,1,1,1,1,8,8,8,8,8,8,8,8,8,1,1,7,1,1,1,1,1,1,1,
- 2,2,2,1,2,2,1,7,2,2,1,1,3,1,1,1,1,1,5,1,1,3,2,2,2,2,2,1,7,2,2,1,1,1,1,1,1,
- 5,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,2,1,1,1,2,2,2,1,2,2,1,7,2,2,2,1,
- 1,2,1,1,1,2,2,2,2,2,1,7,2,2,1,1,1,1,7,1,2,2,2,2,2,1,5,2,2,2,3,1,1,1,1,7,1,
- 1,1,8,1,2,1,1,1,1,1,1,8,1,2,1,1,1,1,1,5,1,2,5,5,8,1,1,5,7,1,3,3,1,1,1,1,1,
- 1,1,1,1,7,1,1,2,1,1,1,1,1,1,1,7,2,2,1,1,7,1,2,5,5,5,5,5,5,5,5,8,1,1,7,1,2,
- 2,1,1,1,1,1,5,1,2,5,5,5,5,5,5,8,1,1,5,7,1,3,3,1,1,1,1,1,1,8,1,2,1,1,1,1,1,
- 1,1,5,1,1,3,1,7,1,1,1,1,5,1,1,3,1,1,1,5,1,1,3,1,1,1,1,1,1,1,1,1,7,2,2,2,1,
- 1,1,1,1,1,1,1,1,1,7,1,2,2,2,1,1,1,1,1,1,1,7,1,2,1,7,1,1,2,1,7,2,1,1,1,1,1,
- 1,1,1,1,1,7,1,1,1,1,1,2,1,1,1,1,1,5,5,5,5,5,5,8,1,1,5,7,1,3,3,1,1,1,1,1,1,
- 1,5,1,1,3,1,1,1,1,1,4,2,1,1,8,1,2,1,1,1,1,1,1,1,5,1,1,3,1,1,1,1,1,1,7,1,2,
- 1,1,1,5,1,1,3,1,1,1,1,1,7,1,1,1,1,5,1,1,3,1,1,1,1,1,1,1,1,1,7,1,2,2,2,1,1,
- 1,1,1,1,7,1,2,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 1,1,7,1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,5,2,2,2,1,1,1,1,1,1,5,2,1,5,1,1,
- 1,1,1,8,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,7,2,2,1,7,1,1,1,1,1,1,1,1,1,1,1,7,2,
- 2,2,2,1,1,1,1,1,1,1,7,2,2,1,1,1,7,2,1,1,1,1,1,5,1,1,3,1,1,1,1,1,1,1,1,1,1,
- 7,1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,2,1,1,1,1,1,1,1,1,5,1,1,
- 3,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,2,1,1,1,1,1,1,1,1,5,1,1,3,1,1,1,1,1,1,7,1,
- 2,1,4,1,1,4,1,1,1,1,1,1,1,1,7,1,2,1,1,1,5,1,1,3,1,1,1,1,1,1,7,1,2,1,1,1,1,
- 1,1,1,1,8,1,2,1,1,1,2,1,11
-};
-
-
-static unsigned char ag_pstt[] = {
-2,2,1,3,2,2,3,
-4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,4,5,
-122,122,1,124,122,
-6,7,8,9,3,0,13,12,11,10,
-74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,
- 74,74,74,74,74,74,76,
-77,5,
-2,2,1,123,2,2,128,
-2,2,1,123,2,2,127,
-2,2,1,123,2,2,126,
-2,2,1,123,2,2,125,
-18,18,15,14,14,10,17,4,18,18,17,14,15,16,
-19,19,19,19,19,19,15,14,14,11,17,3,19,19,17,14,15,16,
-20,20,20,20,20,20,15,14,14,12,17,2,20,20,17,14,15,16,
-21,21,15,14,14,13,17,1,21,21,17,14,15,16,
-22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
- 22,22,22,22,22,22,85,22,88,
-89,15,
-2,2,1,123,2,2,152,
-80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,15,14,14,
- 80,17,79,14,15,16,
-23,24,18,27,27,27,27,26,25,
-32,33,28,29,30,31,19,34,22,23,24,25,38,38,37,36,35,
-92,92,92,92,92,39,20,90,91,42,43,43,41,40,
-44,45,21,48,48,47,46,
-84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,
- 84,84,84,84,84,84,86,
-2,2,1,123,2,2,151,
-2,2,1,123,2,2,150,
-92,92,92,49,92,92,39,25,90,91,51,50,41,40,
-92,92,92,92,92,39,26,90,91,52,41,40,
-23,24,62,27,61,61,61,26,25,
-2,2,1,123,2,2,134,
-2,2,1,123,2,2,133,
-2,2,1,123,2,2,132,
-2,2,1,123,2,2,131,
-2,2,1,123,2,2,138,
-2,2,1,123,2,2,137,
-53,34,54,
-92,92,92,92,92,39,35,90,91,55,56,41,40,
-49,36,57,
-58,58,58,49,58,58,58,15,14,14,37,17,58,58,59,17,14,15,16,
-32,33,28,29,30,31,28,38,34,22,23,24,25,27,37,36,35,
-97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
- 60,97,39,61,95,
-2,2,1,123,2,2,154,
-93,93,93,93,2,2,93,93,93,93,93,93,93,1,123,2,2,153,
-62,62,62,62,62,62,42,63,100,
-92,92,92,92,92,39,20,43,90,91,42,19,41,40,
-2,2,1,123,2,2,130,
-2,2,1,123,2,2,129,
-14,14,15,17,64,17,14,15,16,
-14,14,15,17,65,17,14,15,16,
-44,45,9,48,8,47,46,
-2,2,1,123,2,2,136,
-66,66,66,66,66,66,15,14,14,50,17,66,66,17,14,15,16,
-14,14,15,17,66,17,14,15,16,
-67,52,68,
-2,2,1,123,2,2,142,
-92,92,92,92,92,39,54,90,91,58,69,41,40,
-49,55,70,
-71,74,73,75,72,73,
-76,76,76,76,76,76,15,14,14,57,17,76,76,17,14,15,16,
-92,92,92,92,92,39,58,90,91,57,34,77,41,40,
-78,78,78,78,78,78,78,15,14,14,59,17,78,78,17,14,15,16,
-98,99,60,
-97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,97,
- 60,94,97,61,96,
-2,2,1,123,2,2,155,
-62,62,28,29,30,31,62,62,62,62,63,79,22,23,24,25,101,
-62,62,62,62,62,62,64,81,81,80,100,
-62,62,62,62,62,62,65,83,83,82,100,
-92,92,92,92,92,39,66,90,91,84,85,85,41,40,
-2,2,1,123,2,2,143,
-92,92,92,92,92,39,68,90,91,86,41,40,
-88,71,69,87,89,
-90,90,90,90,90,90,15,14,14,70,17,90,90,17,14,15,16,
-2,2,1,123,2,2,139,
-5,5,5,5,5,5,5,15,14,14,72,17,41,41,17,14,15,16,
-92,92,92,92,92,39,73,90,91,43,91,41,40,
-2,2,1,123,2,2,135,
-5,5,5,5,5,5,15,14,14,5,75,17,38,38,17,14,15,16,
-92,92,92,92,92,39,76,90,91,92,93,93,41,40,
-94,96,53,77,99,100,52,98,97,95,
-92,92,92,92,92,39,102,90,91,57,101,101,102,77,41,40,
-14,14,15,17,21,17,14,15,16,
-92,92,62,62,92,92,92,62,62,62,62,39,80,90,91,103,101,41,40,
-62,62,62,62,62,62,15,14,80,100,
-92,92,62,62,92,92,92,62,62,62,62,39,82,90,91,104,101,41,40,
-62,62,62,62,62,62,12,11,82,100,
-105,105,105,105,105,105,105,105,15,14,14,84,17,105,105,17,14,15,16,
-92,92,92,74,92,92,39,85,90,91,84,106,68,41,40,
-92,92,92,92,92,39,86,90,91,107,41,40,
-62,62,62,62,62,62,87,108,100,
-2,2,1,123,2,2,141,
-92,92,92,92,92,39,89,90,91,59,109,41,40,
-92,92,92,92,92,39,90,90,91,43,110,41,40,
-5,5,5,5,5,5,5,5,15,14,14,91,17,42,42,17,14,15,16,
-111,111,111,111,111,111,111,111,15,14,14,92,17,111,111,17,14,15,16,
-92,92,92,74,92,92,39,93,90,91,92,112,36,41,40,
-2,2,1,123,2,2,149,
-92,92,92,92,92,39,95,90,91,113,41,40,
-2,2,1,123,2,2,146,
-114,114,62,62,116,117,114,114,114,62,62,62,62,97,120,119,115,100,118,118,
- 118,
-92,92,92,53,92,92,39,98,90,91,57,99,100,54,121,41,40,
-92,92,92,92,92,39,99,90,91,122,41,40,
-67,100,123,
-92,92,92,92,92,39,32,90,91,57,30,77,41,40,
-74,102,124,
-14,14,15,17,17,17,14,15,16,
-14,14,15,17,16,17,14,15,16,
-71,40,72,70,
-5,5,15,14,14,5,106,17,69,69,17,14,15,16,
-125,125,125,125,125,107,127,126,110,
-62,62,128,62,62,62,62,108,47,101,
-128,71,109,129,45,
-5,5,5,5,5,5,5,5,15,14,14,110,17,39,39,17,14,15,16,
-71,40,72,44,
-5,5,5,5,5,5,15,14,14,5,112,17,37,37,17,14,15,16,
-14,14,15,17,56,17,14,15,16,
-2,2,1,123,2,2,148,
-130,115,131,
-2,2,1,123,2,2,157,
-2,2,1,123,2,2,156,
-132,62,62,132,132,62,62,62,62,118,108,104,109,
-132,62,62,130,132,132,62,62,62,62,119,133,108,105,109,
-62,62,130,62,62,62,62,120,134,101,
-53,121,99,100,53,
-128,122,48,
-62,62,116,117,130,53,62,62,62,62,123,138,135,140,136,137,100,118,118,118,
- 139,139,
-5,5,5,5,5,5,15,14,14,5,124,17,33,33,17,14,15,16,
-2,2,1,123,2,2,159,
-125,125,125,125,125,71,111,
-14,14,15,17,65,17,14,15,16,
-2,2,1,123,2,2,140,
-62,62,62,62,62,62,129,141,100,
-2,2,1,123,2,2,145,
-114,114,114,114,114,131,142,
-2,2,1,123,2,2,158,
-132,62,62,132,132,62,62,62,62,133,143,108,106,109,
-62,62,62,62,62,62,134,144,100,
-62,62,116,117,130,53,62,62,62,62,135,138,135,145,136,137,100,118,118,118,
- 139,139,
-62,62,116,117,130,53,62,62,62,62,136,138,135,136,137,100,118,118,118,119,
-132,62,62,132,132,62,62,62,62,118,108,105,109,
-62,62,62,62,62,62,117,101,
-146,112,147,
-149,130,14,14,15,17,49,148,17,14,15,150,16,
-62,62,128,62,62,62,62,141,46,101,
-151,142,152,
-132,62,62,151,132,132,62,62,62,62,143,51,108,107,109,
-62,62,151,62,62,62,62,144,50,101,
-149,130,128,145,120,148,150,
-2,2,1,123,2,2,161,
-62,62,116,117,130,53,62,62,62,62,147,138,135,136,137,100,118,118,118,116,
-62,62,116,117,130,53,62,62,62,62,148,138,135,136,137,100,118,118,118,153,
- 153,
-2,2,1,123,2,2,160,
-62,62,116,117,130,53,62,62,62,62,150,138,135,136,137,100,118,118,118,154,
- 154,
-2,2,1,123,2,2,144,
-62,62,62,62,62,62,152,155,100,
-146,114,147,
-146,113,147,
-62,62,156,62,62,62,62,155,157,101,
-2,2,1,123,2,2,147,
-62,62,62,62,62,62,157,158,100,
-62,62,62,62,62,62,14,14,15,17,55,17,14,15,101,16,
- 0
-};
-
-
-static const unsigned short ag_sbt[] = {
- 0, 7, 41, 46, 56, 88, 90, 97, 104, 111, 118, 132, 150, 168,
- 182, 216, 218, 225, 256, 265, 282, 296, 303, 335, 342, 349, 363, 375,
- 384, 391, 398, 405, 412, 419, 426, 429, 442, 445, 464, 481, 511, 518,
- 536, 545, 559, 566, 573, 582, 591, 598, 605, 622, 631, 634, 641, 654,
- 657, 663, 680, 694, 712, 715, 745, 752, 769, 780, 791, 805, 812, 824,
- 829, 846, 853, 871, 884, 891, 909, 923, 933, 949, 958, 977, 987,1006,
- 1016,1035,1050,1062,1071,1078,1091,1104,1123,1142,1157,1164,1176,1183,
- 1204,1221,1233,1236,1250,1253,1262,1271,1275,1289,1298,1308,1313,1332,
- 1336,1354,1363,1370,1373,1380,1387,1400,1415,1425,1430,1433,1455,1473,
- 1480,1487,1496,1503,1512,1519,1526,1533,1547,1556,1578,1598,1611,1619,
- 1622,1635,1645,1648,1663,1673,1680,1687,1707,1728,1735,1756,1763,1772,
- 1775,1778,1788,1795,1804,1820
-};
-
-
-static const unsigned short ag_sbe[] = {
- 3, 38, 44, 50, 87, 89, 93, 100, 107, 114, 123, 141, 159, 173,
- 213, 217, 221, 251, 258, 271, 288, 298, 334, 338, 345, 356, 369, 378,
- 387, 394, 401, 408, 415, 422, 427, 435, 443, 455, 471, 508, 514, 532,
- 542, 552, 562, 569, 575, 584, 594, 601, 614, 624, 632, 637, 647, 655,
- 659, 672, 686, 704, 714, 743, 748, 762, 775, 786, 797, 808, 818, 826,
- 838, 849, 863, 877, 887, 901, 915, 926, 939, 951, 970, 983, 999,1012,
- 1027,1042,1056,1068,1074,1084,1097,1115,1134,1149,1160,1170,1179,1196,
- 1211,1227,1234,1242,1251,1255,1264,1272,1281,1294,1305,1310,1324,1333,
- 1346,1356,1366,1371,1376,1383,1396,1410,1422,1426,1431,1443,1465,1476,
- 1485,1489,1499,1509,1515,1524,1529,1542,1553,1566,1588,1607,1617,1620,
- 1626,1642,1646,1658,1670,1676,1683,1697,1717,1731,1745,1759,1769,1773,
- 1776,1785,1791,1801,1812,1820
-};
-
-
-static const unsigned char ag_fl[] = {
- 2,2,2,2,2,0,1,1,2,3,1,2,3,1,2,3,3,3,1,2,3,4,1,1,1,1,1,2,3,1,2,0,1,6,3,
- 1,2,6,4,5,0,2,4,1,3,6,8,6,3,4,5,5,2,4,3,10,4,1,1,1,1,2,3,1,1,7,3,1,2,6,
- 3,1,1,1,2,0,1,3,1,2,1,1,1,1,2,0,1,0,2,2,1,1,1,2,3,1,2,1,2,2,1,2,1,1,2,
- 2,1,2,1,1,1,2,1,3,3,1,3,1,1,2,3,1,2,0,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2
-};
-
-static const unsigned char ag_ptt[] = {
- 0, 5, 5, 5, 5, 15, 15, 17, 17, 7, 21, 21, 16, 24, 24, 16, 20, 23,
- 28, 28, 9, 27, 29, 29, 29, 29, 35, 35, 11, 39, 39, 40, 40, 34, 34, 44,
- 44, 34, 34, 46, 49, 49, 46, 47, 43, 36, 36, 36, 55, 56, 59, 59, 38, 38,
- 38, 38, 38, 65, 51, 53, 70, 70, 13, 69, 69, 71, 72, 77, 77, 72, 76, 74,
- 2, 82, 82, 83, 83, 2, 85, 85, 14, 88, 88, 90, 90, 91, 91, 92, 92,140,
- 26, 26,141,141,142, 96, 96, 97, 97, 97, 25, 25,103,103, 63, 63, 64, 64,
- 104,104, 78, 78, 58, 58, 58,107,107,109,109,109,109,111,111,112,112, 6,
- 8, 10, 12, 19, 22, 30, 31, 32, 33, 41, 37, 42, 45, 48, 54, 52, 50, 57,
- 62, 61, 60, 67, 66, 68, 73, 75, 3, 1, 4,100,101,102,105,106,108,110
-};
-
-
-
-
-static void ag_ra(void)
-{
- switch(ag_rpx[ag_ap]) {
- case 1: ag_rp_1(V(0,int), V(1,const char *)); break;
- case 2: ag_rp_2(V(0,int), V(1,const char *)); break;
- case 3: ag_rp_3(V(0,const char *), V(1,int), V(2,char)); break;
- case 4: V(0,char) = ag_rp_4(); break;
- case 5: V(0,char) = ag_rp_5(); break;
- case 6: V(0,batch *) = ag_rp_8(V(0,const char *), V(3,const char *)); break;
- case 7: V(0,batch *) = ag_rp_9(V(0,batch *), V(2,const char *)); break;
- case 8: V(0,const char *) = ag_rp_10(V(0,const char *)); break;
- case 9: ag_rp_11(V(0,const char *)); break;
- case 10: ag_rp_12(V(0,char), V(2,const char *), V(4,const char *)); break;
- case 11: ag_rp_13(V(0,char), V(2,const char *), V(4,const char *), V(6,int)); break;
- case 12: ag_rp_14(V(0,char), V(2,const char *), V(4,int)); break;
- case 13: V(0,const char *) = ag_rp_15(V(1,const char *)); break;
- case 14: ag_rp_16(V(0,const char *), V(2,int)); break;
- case 15: ag_rp_17(V(1,int), V(3,int)); break;
- case 16: ag_rp_18(V(1,int), V(3,int)); break;
- case 17: ag_rp_19(V(0,const char *)); break;
- case 18: ag_rp_20(V(0,const char *), V(2,const char *)); break;
- case 19: ag_rp_21(V(0,const char *)); break;
- case 20: ag_rp_22(V(0,const char *), V(2,int), V(4,int), V(6,int), V(8,int)); break;
- case 21: ag_rp_23(V(0,const char *), V(2,const char *)); break;
- case 22: V(0,const char *) = ag_rp_24(V(0,const char *)); break;
- case 23: V(0,const char *) = ag_rp_25(V(0,const char *)); break;
- case 24: V(0,const char *) = ag_rp_26(V(0,const char *)); break;
- case 25: ag_rp_27(V(1,const char *), V(3,const char *), V(4,const char *), V(5,int)); break;
- case 26: ag_rp_28(V(1,const char *)); break;
- case 27: ag_rp_29(V(0,const char *)); break;
- case 28: V(0,int) = ag_rp_30(V(0,int)); break;
- case 29: V(0,const char *) = ag_rp_31(V(0,const char *)); break;
- case 30: V(0,const char *) = ag_rp_32(V(0,const char *)); break;
- case 31: V(0,const char *) = ag_rp_33(V(0,int)); break;
- case 32: V(0,const char *) = ag_rp_34(V(0,const char *), V(1,int)); break;
- case 33: V(0,const char *) = ag_rp_35(V(1,const char *)); break;
- case 34: V(0,const char *) = ag_rp_36(V(0,char)); break;
- case 35: V(0,const char *) = ag_rp_37(V(0,const char *), V(1,char)); break;
- case 36: V(0,char) = ag_rp_38(V(0,int)); break;
- case 37: V(0,char) = ag_rp_39(); break;
- case 38: V(0,char) = ag_rp_40(); break;
- case 39: V(0,int) = ag_rp_41(V(0,int)); break;
- case 40: V(0,int) = ag_rp_42(V(0,int), V(1,int)); break;
- case 41: V(0,int) = ag_rp_43(V(1,int)); break;
- case 42: V(0,int) = ag_rp_44(V(0,int), V(1,int)); break;
- case 43: V(0,int) = ag_rp_45(V(0,int)); break;
- case 44: V(0,int) = ag_rp_46(V(0,int), V(1,int)); break;
- case 45: V(0,int) = ag_rp_47(V(0,int)); break;
- case 46: V(0,int) = ag_rp_48(V(0,int)); break;
- case 47: V(0,int) = ag_rp_49(V(0,int)); break;
- case 48: V(0,int) = ag_rp_50(V(0,int), V(1,int)); break;
- case 49: V(0,int) = ag_rp_51(V(0,int), V(2,int)); break;
- case 50: V(0,int) = ag_rp_52(V(0,int), V(2,int)); break;
- case 51: V(0,int) = ag_rp_53(V(0,int), V(2,int)); break;
- case 52: V(0,int) = ag_rp_54(V(1,int)); break;
- case 53: V(0,int) = ag_rp_55(V(1,int)); break;
- }
-}
-
-#define TOKEN_NAMES parse_token_names
-const char *parse_token_names[158] = {
- "file format",
- "identifier",
- "white space",
- "simple eol",
- "quoted string",
- "file format",
- "",
- "devices",
- "",
- "cache",
- "",
- "devinfo",
- "",
- "config",
- "eol",
- "",
- "device list",
- "",
- "eof",
- "",
- "character device",
- "",
- "",
- "block device",
- "",
- "number",
- "name",
- "cachedevice",
- "",
- "devicetype",
- "",
- "",
- "",
- "",
- "device block",
- "",
- "device header spec",
- "",
- "device decl",
- "",
- "",
- "",
- "",
- "ignoramus",
- "",
- "",
- "batch list",
- "batch item",
- "",
- "",
- "",
- "groupname",
- "",
- "procname",
- "",
- "class",
- "device tail",
- "",
- "expr",
- "device range",
- "",
- "",
- "",
- "hex number",
- "auto hex",
- "devname",
- "letter",
- "",
- "",
- "config decl",
- "",
- "class decl",
- "omit decl",
- "",
- "mode",
- "",
- "single omit",
- "",
- "octal number",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "qstring",
- "qstring char",
- "qchar",
- "",
- "digit",
- "",
- "",
- "",
- "hex digit",
- "",
- "octal digit",
- "term",
- "",
- "factor",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "letter",
- "",
- "",
- "",
- "simple eol",
- "identifier",
- "quoted string",
- "digit",
- "",
- "",
- "",
- "octal digit",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
- "",
-
-};
-
-static char ag_msg[82];
-static char ag_mst[] = "Missing %s";
-static char ag_uet[] = "Unexpected %s";
-static char ag_ac[4] = "' '";
-
-static void ag_diagnose(void) {
- int ag_snd = (PCB).sn, ag_k;
- const char *ag_p;
- const char *ag_fmt = ag_uet;
-
- ag_k = ag_sbt[ag_snd];
- if (*TOKEN_NAMES[ag_tstt[ag_k]] && ag_astt[ag_k + 1] == ag_action_8) {
- ag_p = TOKEN_NAMES[ag_tstt[ag_k]];
- ag_fmt = ag_mst;
- }
- else if ((PCB).token_number && *TOKEN_NAMES[(PCB).token_number]) {
- ag_p = TOKEN_NAMES[(PCB).token_number];
- }
- else if (isprint((*(PCB).lab)) && (*(PCB).lab) != '\\') {
- ag_ac[1] = (*(PCB).lab);
- ag_p = ag_ac;
- }
- else ag_p = "input";
- sprintf(ag_msg, ag_fmt, ag_p);
- (PCB).error_message = ag_msg;
-
-
-}
-static int ag_action_1_r_proc(void);
-static int ag_action_2_r_proc(void);
-static int ag_action_3_r_proc(void);
-static int ag_action_4_r_proc(void);
-static int ag_action_1_s_proc(void);
-static int ag_action_3_s_proc(void);
-static int ag_action_1_proc(void);
-static int ag_action_2_proc(void);
-static int ag_action_3_proc(void);
-static int ag_action_4_proc(void);
-static int ag_action_5_proc(void);
-static int ag_action_6_proc(void);
-static int ag_action_7_proc(void);
-static int ag_action_8_proc(void);
-static int ag_action_9_proc(void);
-static int ag_action_10_proc(void);
-static int ag_action_11_proc(void);
-static int ag_action_8_proc(void);
-
-
-static int (*ag_r_procs_scan[])(void) = {
- ag_action_1_r_proc,
- ag_action_2_r_proc,
- ag_action_3_r_proc,
- ag_action_4_r_proc
-};
-
-static int (*ag_s_procs_scan[])(void) = {
- ag_action_1_s_proc,
- ag_action_2_r_proc,
- ag_action_3_s_proc,
- ag_action_4_r_proc
-};
-
-static int (*ag_gt_procs_scan[])(void) = {
- ag_action_1_proc,
- ag_action_2_proc,
- ag_action_3_proc,
- ag_action_4_proc,
- ag_action_5_proc,
- ag_action_6_proc,
- ag_action_7_proc,
- ag_action_8_proc,
- ag_action_9_proc,
- ag_action_10_proc,
- ag_action_11_proc,
- ag_action_8_proc
-};
-
-
-static int ag_action_10_proc(void) {
- (PCB).btsx = 0, (PCB).drt = -1;
- ag_track();
- return 0;
-}
-
-static int ag_action_11_proc(void) {
- (PCB).btsx = 0, (PCB).drt = -1;
- (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab;
- (PCB).ssx--;
- ag_ra();
- (PCB).ssx++;
- ag_track();
- return 0;
-}
-
-static int ag_action_3_r_proc(void) {
- int ag_sd = ag_fl[ag_ap] - 1;
- if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- (PCB).btsx = 0, (PCB).drt = -1;
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- ag_ra();
- return 1;
-}
-
-static int ag_action_3_s_proc(void) {
- int ag_sd = ag_fl[ag_ap] - 1;
- if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- (PCB).btsx = 0, (PCB).drt = -1;
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- ag_ra();
- return 1;
-}
-
-static int ag_action_4_r_proc(void) {
- int ag_sd = ag_fl[ag_ap] - 1;
- if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- return 1;
-}
-
-static int ag_action_2_proc(void) {
- (PCB).btsx = 0, (PCB).drt = -1;
- if ((PCB).ssx >= 38) {
- (PCB).exit_flag = AG_STACK_ERROR_CODE;
- PARSER_STACK_OVERFLOW;
- }
- (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab;
- (PCB).ss[(PCB).ssx] = (PCB).sn;
- (PCB).ssx++;
- (PCB).sn = ag_ap;
- ag_track();
- return 0;
-}
-
-static int ag_action_9_proc(void) {
- if((PCB).drt == -1) {
- (PCB).drt=(PCB).token_number;
- (PCB).dssx=(PCB).ssx;
- (PCB).dsn=(PCB).sn;
- }
- ag_prot();
- (PCB).ss[(PCB).ssx] = (PCB).sn;
- (PCB).ssx++;
- (PCB).sn = ag_ap;
- (PCB).rx = 0;
- return (PCB).exit_flag == AG_RUNNING_CODE;
-}
-
-static int ag_action_2_r_proc(void) {
- (PCB).ssx++;
- (PCB).sn = ag_ap;
- return 0;
-}
-
-static int ag_action_7_proc(void) {
- --(PCB).ssx;
- (PCB).exit_flag = AG_SUCCESS_CODE;
- (PCB).rx = 0;
- return 0;
-}
-
-static int ag_action_1_proc(void) {
- (PCB).exit_flag = AG_SUCCESS_CODE;
- ag_track();
- return 0;
-}
-
-static int ag_action_1_r_proc(void) {
- (PCB).exit_flag = AG_SUCCESS_CODE;
- return 0;
-}
-
-static int ag_action_1_s_proc(void) {
- (PCB).exit_flag = AG_SUCCESS_CODE;
- return 0;
-}
-
-static int ag_action_4_proc(void) {
- int ag_sd = ag_fl[ag_ap] - 1;
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- (PCB).btsx = 0, (PCB).drt = -1;
- (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab;
- if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- else (PCB).ss[(PCB).ssx] = (PCB).sn;
- ag_track();
- while ((PCB).exit_flag == AG_RUNNING_CODE) {
- unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
- unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
- do {
- unsigned ag_tx = (ag_t1 + ag_t2)/2;
- if (ag_tstt[ag_tx] < (const unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
- else ag_t2 = ag_tx;
- } while (ag_t1 < ag_t2);
- ag_ap = ag_pstt[ag_t1];
- if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break;
- }
- return 0;
-}
-
-static int ag_action_3_proc(void) {
- int ag_sd = ag_fl[ag_ap] - 1;
- (PCB).btsx = 0, (PCB).drt = -1;
- (*(int *) &(PCB).vs[(PCB).ssx]) = *(PCB).lab;
- if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- else (PCB).ss[(PCB).ssx] = (PCB).sn;
- ag_track();
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- ag_ra();
- while ((PCB).exit_flag == AG_RUNNING_CODE) {
- unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
- unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
- do {
- unsigned ag_tx = (ag_t1 + ag_t2)/2;
- if (ag_tstt[ag_tx] < (const unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
- else ag_t2 = ag_tx;
- } while (ag_t1 < ag_t2);
- ag_ap = ag_pstt[ag_t1];
- if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break;
- }
- return 0;
-}
-
-static int ag_action_8_proc(void) {
- ag_undo();
- (PCB).rx = 0;
- (PCB).exit_flag = AG_SYNTAX_ERROR_CODE;
- ag_diagnose();
- SYNTAX_ERROR;
- {(PCB).rx = 1; ag_track();}
- return (PCB).exit_flag == AG_RUNNING_CODE;
-}
-
-static int ag_action_5_proc(void) {
- int ag_sd = ag_fl[ag_ap];
- if((PCB).drt == -1) {
- (PCB).drt=(PCB).token_number;
- (PCB).dssx=(PCB).ssx;
- (PCB).dsn=(PCB).sn;
- }
- if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- else {
- ag_prot();
- (PCB).ss[(PCB).ssx] = (PCB).sn;
- }
- (PCB).rx = 0;
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- ag_ra();
- while ((PCB).exit_flag == AG_RUNNING_CODE) {
- unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
- unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
- do {
- unsigned ag_tx = (ag_t1 + ag_t2)/2;
- if (ag_tstt[ag_tx] < (const unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
- else ag_t2 = ag_tx;
- } while (ag_t1 < ag_t2);
- ag_ap = ag_pstt[ag_t1];
- if ((ag_r_procs_scan[ag_astt[ag_t1]])() == 0) break;
- }
- return (PCB).exit_flag == AG_RUNNING_CODE;
-}
-
-static int ag_action_6_proc(void) {
- int ag_sd = ag_fl[ag_ap];
- (PCB).reduction_token = (parse_token_type) ag_ptt[ag_ap];
- if((PCB).drt == -1) {
- (PCB).drt=(PCB).token_number;
- (PCB).dssx=(PCB).ssx;
- (PCB).dsn=(PCB).sn;
- }
- if (ag_sd) {
- (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
- }
- else {
- ag_prot();
- (PCB).vs[(PCB).ssx] = ag_null_value;
- (PCB).ss[(PCB).ssx] = (PCB).sn;
- }
- (PCB).rx = 0;
- while ((PCB).exit_flag == AG_RUNNING_CODE) {
- unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
- unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
- do {
- unsigned ag_tx = (ag_t1 + ag_t2)/2;
- if (ag_tstt[ag_tx] < (const unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
- else ag_t2 = ag_tx;
- } while (ag_t1 < ag_t2);
- ag_ap = ag_pstt[ag_t1];
- if ((ag_r_procs_scan[ag_astt[ag_t1]])() == 0) break;
- }
- return (PCB).exit_flag == AG_RUNNING_CODE;
-}
-
-
-void init_parse(void) {
- unsigned ag_t1 = 0;
- (PCB).rx = (PCB).fx = 0;
- (PCB).ss[0] = (PCB).sn = (PCB).ssx = 0;
- (PCB).exit_flag = AG_RUNNING_CODE;
- (PCB).key_sp = NULL;
- (PCB).key_state = 0;
- (PCB).line = FIRST_LINE;
- (PCB).column = FIRST_COLUMN;
- (PCB).btsx = 0, (PCB).drt = -1;
- while (ag_tstt[ag_t1] == 0) {
- ag_ap = ag_pstt[ag_t1];
- (ag_gt_procs_scan[ag_astt[ag_t1]])();
- ag_t1 = ag_sbt[(PCB).sn];
- }
-}
-
-void parse(void) {
- (PCB).lab[(PCB).fx++] = (PCB).input_code;
- while ((PCB).exit_flag == AG_RUNNING_CODE) {
- while (1) {
- unsigned char *ag_p;
- int ag_ch;
- if ((PCB).rx >= (PCB).fx) return;
- ag_ch = CONVERT_CASE((PCB).lab[(PCB).rx++]);
- if ((PCB).key_sp) {
- if (ag_ch != *(PCB).key_sp++) {
- (PCB).rx = (PCB).save_index;
- (PCB).key_sp = NULL;
- (PCB).key_state = 0;
- break;
- } else if (*(PCB).key_sp) continue;
- if (ag_key_act[(PCB).key_state] == ag_cf_end_key) {
- int ag_k1;
- int ag_k2;
- if ((PCB).rx >= (PCB).fx) {
- (PCB).rx--;
- (PCB).key_sp--;
- return;
- }
- (PCB).key_sp = NULL;
- ag_k1 = ag_key_parm[(PCB).key_state];
- ag_k2 = ag_key_pt[ag_k1];
- if (ag_key_itt[ag_k2 + CONVERT_CASE((PCB).lab[(PCB).rx])])
- (PCB).rx = (PCB).save_index;
- else {
- (PCB).token_number = (parse_token_type) ag_key_pt[ag_k1+1];
- (PCB).key_state = 0;
- }
- break;
- }
- else {
- (PCB).token_number = (parse_token_type) ag_key_parm[(PCB).key_state];
- (PCB).key_state = 0;
- (PCB).key_sp = NULL;
- }
- break;
- }
- if ((PCB).key_state == 0) {
- (PCB).token_number = (parse_token_type) AG_TCV(ag_ch);
- if (((PCB).key_state = ag_key_index[(PCB).sn]) == 0) break;
- (PCB).save_index = 1;
- }
- ag_p = &ag_key_ch[(PCB).key_state];
- while (*ag_p < ag_ch) ag_p++;
- if (*ag_p == ag_ch) {
- (PCB).key_state = (int)(ag_p - ag_key_ch);
- switch (ag_key_act[(PCB).key_state]) {
- case ag_cf_set_key: {
- int ag_k1;
- int ag_k2;
- if ((PCB).rx >= (PCB).fx) {
- (PCB).rx--;
- return;
- }
- ag_k1 = ag_key_parm[(PCB).key_state];
- ag_k2 = ag_key_pt[ag_k1];
- (PCB).key_state = ag_key_jmp[(PCB).key_state];
- if (ag_key_itt[ag_k2 + CONVERT_CASE((PCB).lab[(PCB).rx])]) break;
- (PCB).save_index = (PCB).rx;
- (PCB).token_number = (parse_token_type) ag_key_pt[ag_k1+1];
- break;
- }
- case ag_set_key:
- (PCB).save_index = (PCB).rx;
- (PCB).token_number = (parse_token_type) ag_key_parm[(PCB).key_state];
- case ag_jmp_key:
- (PCB).key_state = ag_key_jmp[(PCB).key_state];
- continue;
- case ag_cf_end_key:
- case ag_end_key:
- (PCB).key_sp = ag_key_ends + ag_key_jmp[(PCB).key_state];
- continue;
- case ag_accept_key:
- (PCB).token_number = (parse_token_type) ag_key_parm[(PCB).key_state];
- (PCB).key_state = 0;
- break;
- case ag_cf_accept_key: {
- int ag_k1;
- int ag_k2;
- if ((PCB).rx >= (PCB).fx) {
- (PCB).rx--;
- return;
- }
- ag_k1 = ag_key_parm[(PCB).key_state];
- ag_k2 = ag_key_pt[ag_k1];
- if (ag_key_itt[ag_k2 + CONVERT_CASE((PCB).lab[(PCB).rx])])
- (PCB).rx = (PCB).save_index;
- else {
- (PCB).rx--;
- (PCB).token_number = (parse_token_type) ag_key_pt[ag_k1+1];
- (PCB).key_state = 0;
- }
- break;
- }
- }
- break;
- } else {
- (PCB).rx = (PCB).save_index;
- (PCB).key_state = 0;
- break;
- }
- }
-
- {
- unsigned ag_t1 = ag_sbt[(PCB).sn];
- unsigned ag_t2 = ag_sbe[(PCB).sn] - 1;
- do {
- unsigned ag_tx = (ag_t1 + ag_t2)/2;
- if (ag_tstt[ag_tx] > (const unsigned char)(PCB).token_number)
- ag_t1 = ag_tx + 1;
- else ag_t2 = ag_tx;
- } while (ag_t1 < ag_t2);
- if (ag_tstt[ag_t1] != (PCB).token_number) ag_t1 = ag_sbe[(PCB).sn];
- ag_ap = ag_pstt[ag_t1];
- (ag_gt_procs_scan[ag_astt[ag_t1]])();
- }
- }
-
-}
-
-
+++ /dev/null
-/*
- * User and group ownerships, and permissions, for device classes.
- */
-
-class default: root system 0640
-class public: root system 0666
-class system: root system 0660
-class kmem: root kmem 0640
-class tty: root tty 0620
-class pty: root root 0666
-class cons: root tty 0622 // 622 for console?
-class dialout: root uucp 0660
-class mouse: root system 0666
-class printer: root daemon 0660
-class floppy: root floppy 0660
-class disk: root disk 0640
-class scsi: root system 0600
-class cdrom: root disk 0660
-class tape: root disk 0660
-class audio: root system 0666
-class ibcs2: root system 0666
-class scanner: root system 0666
-
-/*
- * Things marked as omit will not be created. Ever. Be sure to check
- * here if you try to make something and nothing happens.
- */
-
-omit {
-// hdc hdd // hdc and hdd are now the 2nd controller.
- // They're now made by "hd1", and *not* by "hd".
- xdc xdd
- sdc sdd sde sdf sdg sdh
-}
+++ /dev/null
-.\" -*- nroff -*-
-.TH MAKEDEV.cfg 5 "January 1995" "Version 1.4"
-.SH NAME
-MAKEDEV.cfg \- configuration for MAKEDEV(8)
-.SH DESCRIPTION
-.B MAKEDEV.cfg
-is a text file that tells
-.BR MAKEDEV (8)
-what to do (and, equally importantly, what not to do.)
-Unlike
-.BR DEVINFO (5),
-which is meant to be centrally maintained, it contains all local
-configuration for a particular site and all customization.
-There are basically two kinds of declaration in this file: a "class"
-declaration and an "omit" declaration.
-.LP
-A class declaration has the form
-.RS
-
-.RI class " name " : " owner group-owner permissions"
-
-.RE
-This says that any devices placed in the specified class by
-.B DEVINFO
-should be created with this ownership and these permissions. A sample
-entry might be
-.RS
-.nf
-
-class public: root system 0666
-
-.fi
-.RE
-This says that devices marked "public" should be owned by root.system
-and have mode 666.
-.LP
-An omit declaration has the form
-.RS
-
-.RI "omit { " device... " }"
-
-.RE
-This causes the specified devices to never be created,
-.B "EVEN IF EXPLICITLY SPECIFIED."
-Use caution when setting this up. The intent is to be able to run
-.B "\"MAKEDEV update\""
-and not have it create all sorts of useless devices you'd never use.
-.SH "SEE ALSO"
-.BR MAKEDEV (8),
-.BR DEVINFO (5)
+++ /dev/null
-#ifndef MAKEDEV_H
-#define MAKEDEV_H
-
-void init_parse(void);
-void parse(void);
-typedef union {
- int alignment;
- char ag_vt_2[sizeof(int)];
- char ag_vt_3[sizeof(char)];
- char ag_vt_4[sizeof(batch *)];
- char ag_vt_5[sizeof(const char *)];
-} parse_vs_type;
-
-typedef enum {
- parse_white_space_token = 2, parse_file_format_token = 5,
- parse_devices_token = 7, parse_cache_token = 9, parse_devinfo_token = 11,
- parse_config_token = 13, parse_eol_token, parse_device_list_token = 16,
- parse_eof_token = 18, parse_character_device_token = 20,
- parse_block_device_token = 23, parse_number_token = 25, parse_name_token,
- parse_cachedevice_token, parse_devicetype_token = 29,
- parse_device_block_token = 34, parse_device_header_spec_token = 36,
- parse_device_decl_token = 38, parse_ignoramus_token = 43,
- parse_batch_list_token = 46, parse_batch_item_token,
- parse_groupname_token = 51, parse_procname_token = 53,
- parse_class_token = 55, parse_device_tail_token, parse_expr_token = 58,
- parse_device_range_token, parse_hex_number_token = 63,
- parse_auto_hex_token, parse_devname_token, parse_config_decl_token = 69,
- parse_class_decl_token = 71, parse_omit_decl_token, parse_mode_token = 74,
- parse_single_omit_token = 76, parse_octal_number_token = 78,
- parse_qstring_token = 96, parse_qstring_char_token, parse_qchar_token,
- parse_hex_digit_token = 104, parse_term_token = 107,
- parse_factor_token = 109, parse_letter_token = 136,
- parse_simple_eol_token = 140, parse_identifier_token,
- parse_quoted_string_token, parse_digit_token,
- parse_octal_digit_token = 147
-} parse_token_type;
-
-typedef struct {
- parse_token_type token_number, reduction_token, error_frame_token;
- int input_code;
- int input_value;
- int line, column;
- int ssx, sn, error_frame_ssx;
- int drt, dssx, dsn;
- int ss[38];
- parse_vs_type vs[38];
- int bts[38], btsx;
- unsigned char * pointer;
- unsigned char * la_ptr;
- int lab[19], rx, fx;
- unsigned char *key_sp;
- int save_index, key_state;
- char *error_message;
- char read_flag;
- char exit_flag;
-} parse_pcb_type;
-
-
-#ifndef PRULE_CONTEXT
-#define PRULE_CONTEXT(pcb) (&((pcb).cs[(pcb).ssx]))
-#define PERROR_CONTEXT(pcb) ((pcb).cs[(pcb).error_frame_ssx])
-#define PCONTEXT(pcb) ((pcb).cs[(pcb).ssx])
-#endif
-
-
-#ifndef AG_RUNNING_CODE_CODE
-/* PCB.exit_flag values */
-#define AG_RUNNING_CODE 0
-#define AG_SUCCESS_CODE 1
-#define AG_SYNTAX_ERROR_CODE 2
-#define AG_REDUCTION_ERROR_CODE 3
-#define AG_STACK_ERROR_CODE 4
-#define AG_SEMANTIC_ERROR_CODE 5
-#endif
-
-extern parse_pcb_type parse_pcb;
-#endif
-
+++ /dev/null
-{
-/*
- * makedev.c: Generate /dev entries
- *
- * Based on the MAKEDEV shell script, version 2.0, distributed with
- * util-linux 1.10 and written by Nick Holloway.
- *
- * A number of bugs were fixed, and some additional features added.
- * Written 10-Dec-94 by David A. Holland, dholland@husc.harvard.edu
- *
- * Copyright 1994, 1995. All rights reserved.
- * See the file LEGAL.NOTICE for conditions of redistribution.
- *
- * Bugs:
- * None known right now.
- *
- * History:
- *
- * Version 1.4: 15-Jan-95 Wrote man pages. Now reads DEVINFO.local.
- * Version 1.3: 31-Dec-94 Bug fixes. Added batches. Added omits.
- * Version 1.2: 11-Dec-94 Add configuration file parsing.
- * Version 1.1: 11-Dec-94 Distinguish block and character devices in the
- * table of major device numbers. Changed the name and format of the
- * update cache file to include the type. It appears that the old script
- * was broken in this regard.
- * Version 1.0: 10-Dec-94 Initial version.
- */
-
-static const char *version = "MAKEDEV-C version 1.4";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/stat.h>
-
-#define YES 1
-#define NO 0
-
-static int isverbose=NO; /* flag: print out what we do? */
-static int deletion=NO; /* flag: delete instead of create */
-static int donothing=NO; /* flag: don't actually do anything */
-
-/*
- * Proto for main operative function.
- */
-typedef enum { M_CREATE, M_OMIT } makeopts;
-static void make(const char *batch_or_grp_or_devname, makeopts);
-
-/*
- * Roll over and die.
- */
-static void crash(const char *msg) {
- fprintf(stderr, "MAKEDEV: %s\n", msg);
- exit(1);
-}
-
-/*
- * Print a warning.
- */
-static void warn(const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "MAKEDEV: ");
- vfprintf(stderr, format, ap);
- fprintf(stderr, "\n");
- va_end(ap);
-}
-
-/*
- * Translate string name to uid.
- */
-static uid_t name2uid(const char *name) {
- struct passwd *p = getpwnam(name);
- if (!p) warn("undefined user: %s, using uid 0", name);
- return p ? p->pw_uid : 0; /* make things owned by root by default */
-}
-
-/*
- * Translate string name to gid.
- */
-static gid_t name2gid(const char *name) {
- struct group *g = getgrnam(name);
- if (!g) warn("undefined group: %s, using gid 0", name);
- return g ? g->gr_gid : 0; /* group 0 is a good default too */
-}
-
-/*
- * Proto for parser.
- */
-static void doparse(FILE *f, int filetype, const char *filename);
-
-/************************* device classes *************************/
-
-/*
- * A device class is a string attached to the device which tells us
- * what set of permissions and ownership should be used. This is the
- * table of classes.
- */
-
-typedef struct {
- const char *classname;
- const char *owner;
- const char *group;
- int mode;
-} devclass;
-
-#define MAXCLASSES 32
-static devclass classes[MAXCLASSES];
-static int nclasses=0;
-
-static void addclass(const char *name, const char *o, const char *g, int m) {
- if (nclasses>=MAXCLASSES) crash("out of space for device classes");
- classes[nclasses].classname = name;
- classes[nclasses].owner = o;
- classes[nclasses].group = g;
- classes[nclasses].mode = m;
- nclasses++;
- name2uid(o); /* check for undefined users/groups */
- name2gid(g);
-}
-
-static void loadclasses(void) {
- FILE *f = fopen("MAKEDEV.cfg", "r");
- if (!f) f = fopen("../MAKEDEV.cfg", "r");
- if (!f) f = fopen("/etc/makedev.cfg", "r");
- if (!f) crash("can't find MAKEDEV.cfg");
- doparse(f, 4, "MAKEDEV.cfg");
- fclose(f);
-}
-
-/*
- * Return the index into the above table for a particular class name.
- */
-static int which_class(const char *name) {
- int i;
- for (i=0; i<nclasses; i++)
- if (!strcmp(classes[i].classname, name)) return i;
- return 0;
-}
-
-/*
- * Produce an "ls -l"-ish mode string.
- */
-static const char *modestring(int mode) {
- static char rv[12];
- int i,z;
- strcpy(rv, "rwxrwxrwx");
- for (i=8,z=1; i>=0; i--, z<<=1) if (!(mode&z)) rv[i]='-';
- return rv;
-}
-
-/*
- * Create (or delete, or update) a block or character device.
- */
-static void class_makedev(const char *name, const char *class,
- int major, int minor, char type) {
- int x = which_class(class), mode = classes[x].mode;
- const char *owner = classes[x].owner, *group = classes[x].group;
- if (isverbose) {
- if (deletion) printf("rm -f %s\n", name);
- else printf("%c%s 1 %-8s %-8s %3d, %3d for %s\n", type,
- modestring(mode), owner, group, major, minor, name);
- }
- if (donothing) return;
- if (unlink(name) && deletion) warn("Couldn't remove %s\n", name);
- if (!deletion) {
- dev_t q = (major<<8) | minor;
- if (mknod(name, type=='c' ? S_IFCHR : S_IFBLK, q) ||
- chown(name, name2uid(owner), name2gid(group)) ||
- chmod(name, mode)) {
- warn("couldn't create %s: %s", name, strerror(errno));
- }
- }
-}
-
-/************************* major number list *************************/
-
-/*
- * In Linux device major numbers can be allocated dynamically, so we go
- * look in /proc/devices to see what they are. This keeps track of things.
- */
-
-typedef struct {
- const char *procname;
- int flag;
-} majorentry;
-
-#define MAXMAJORS 256
-static majorentry cmajors[MAXMAJORS]; /* initialized to 0 */
-static majorentry bmajors[MAXMAJORS]; /* initialized to 0 */
-static int no_proc=0; /* true if we didn't find /proc/devices */
-
-/*
- * Store the name associated with a particular major device number.
- */
-static void set_major(const char *procname, int ischar, int num) {
- if (num<0 || num>255) {
- warn("warning: got bogus major number %d for %s", num, procname);
- return;
- }
- if (ischar) cmajors[num].procname=procname;
- else bmajors[num].procname=procname;
-}
-
-/*
- * Look up a major device number by name; return the default value
- * if provided. A default value of -1 implies the device is only
- * dynamic, and so if there's no entry we shouldn't even note its
- * existence.
- */
-static int get_major(const char *procname, int ischar, int defaalt) {
- int i;
- if (!procname) return defaalt;
- if (ischar) {
- for (i=0; i<MAXMAJORS; i++)
- if (cmajors[i].procname && !strcmp(cmajors[i].procname, procname))
- return i;
- }
- else {
- for (i=0; i<MAXMAJORS; i++)
- if (bmajors[i].procname && !strcmp(bmajors[i].procname, procname))
- return i;
- }
- return defaalt;
-}
-
-/*
- * Read /proc/devices.
- */
-static void setup_majors(void) {
- FILE *f = fopen("/proc/devices", "r");
- if (!f) {
- fprintf(stderr, "MAKEDEV: warning: can't read /proc/devices\n");
- no_proc = 1;
- return;
- }
- doparse(f, 1, "/proc/devices");
- fclose(f);
-}
-
-/************************** procname list *************************/
-
-/*
- * The names found in /proc/devices aren't usually quite the same
- * as the names we use. This is a mapping between the two namespaces.
- */
-typedef struct {
- const char *procname;
- const char *groupname;
-} namealias;
-
-#define MAXALIASES 100
-static namealias aliases[MAXALIASES];
-static int naliases=0;
-
-static void addalias(const char *procname, const char *groupname) {
- if (naliases>=MAXALIASES) crash("out of space for aliases");
- aliases[naliases].procname = procname;
- aliases[naliases].groupname = groupname;
- naliases++;
-}
-
-static void ignore_procname(const char *procname) {
- addalias(procname, NULL);
-}
-
-static const char *procnameof(const char *groupname) {
- int i;
- for (i=0; i<naliases; i++) if (!strcmp(groupname, aliases[i].groupname))
- return aliases[i].procname;
- return NULL;
-}
-
-static const char *groupnameof(const char *procname) {
- int i;
- for (i=0; i<naliases; i++) if (!strcmp(procname, aliases[i].procname))
- return aliases[i].groupname;
- return NULL;
-}
-
-/************************* batch list *************************/
-/*
- * Create a device "batch" - a bunch of devices or groups.
- * This is used for "generic" and automatically for disk entries.
- * (Disk entries for "hd" come up with groups hda, hdb, etc., but
- * "hd" itself needs to run these too.)
- */
-#define MAXTARGETS 32
-#define MAXBATCHES 16
-
-typedef struct {
- const char *name; /* name of batch */
- const char *targets[MAXTARGETS];
- int ntargets;
- int busy;
-} batch;
-
-static batch batches[MAXBATCHES];
-static int nbatches=0;
-
-/*
- * Start a new batch.
- */
-static batch *addbatch(const char *name) {
- batch *b;
- if (nbatches>=MAXBATCHES) crash("Out of space for batches");
- b = &batches[nbatches++];
- b->name = name;
- b->busy = NO;
- return b;
-}
-
-/*
- * Add something to a batch.
- */
-static batch *add2batch(batch *b, const char *target) {
- if (b->ntargets>=MAXTARGETS) {
- warn("Too many targets for batch %s (max %d)", b->name, MAXTARGETS);
- return b;
- }
- b->targets[b->ntargets++] = target;
- return b;
-}
-
-/*
- * Run a batch.
- */
-static void run_batch(const batch *b, makeopts m) {
- int i;
- for (i=0; i<b->ntargets; i++) make(b->targets[i], m);
-}
-
-/*
- * Try to run a batch; returns YES if it found one.
- */
-static int try_run_batch(const char *name, makeopts m) {
- int i;
- for (i=0; i<nbatches; i++) {
- if (!strcmp(name, batches[i].name)) {
- if (batches[i].busy) {
- warn("Found recursive batch definition for %s", batches[i].name);
- continue;
- }
- batches[i].busy=YES;
- run_batch(&batches[i], m);
- batches[i].busy=NO;
- return YES;
- }
- }
- return NO;
-}
-
-/************************* device list *************************/
-
-/*
- * Structure to remember the properties of an individual device.
- * NOTE: if the device is actually a symbolic link, the "class"
- * member is used to store the thing it should be linked to.
- */
-typedef struct {
- const char *name; /* file name to create */
- const char *grp; /* device "group" name (e.g. "busmice") */
- const char *class; /* device class ( -> owner and permissions) */
- int major, minor; /* device number */
- char type; /* 'c', 'b', or 'l' for symbolic link */
- int omit; /* don't make me if this is nonzero */
-} device;
-
-/*
- * Create a device (link or actual "special file") - special files are
- * passed on to class_makedev().
- */
-void makedev(device *d, makeopts m) {
- if (m==M_OMIT) {
- d->omit=1;
- }
- if (d->omit==1) return;
- if (d->type=='l') {
- if (isverbose) {
- if (deletion) printf("rm -f %s\n", d->name);
- else printf("lrwxrwxrwx %s -> %s\n", d->name, d->class);
- }
- if (donothing) return;
- if (unlink(d->name) && deletion) warn("Couldn't remove %s\n", d->name);
- if (!deletion) {
- if (symlink(d->class, d->name)) /* class holds thing pointed to */
- warn("couldn't link %s -> %s: %s", d->name, d->class, strerror(errno));
- }
- }
- else class_makedev(d->name, d->class, d->major, d->minor, d->type);
-}
-
-/*
- * Array of devices. We allocate it once from main(); it doesn't grow.
- * Should maybe make it growable sometime. This keeps track of all possible
- * devices. We build this thing first, and then create devices from it as
- * requested.
- */
-static device *devices = NULL;
-static int maxdevices, ndevices;
-
-/*
- * Allocate space for the device array.
- */
-static void allocate_devs(int nd) {
- devices = malloc(nd * sizeof(device));
- if (!devices) crash("Out of memory");
- ndevices = 0;
- maxdevices = nd;
-}
-
-/*
- * Check all the devices for having valid device classes.
- */
-static void check_classes(void) {
- int i;
- const char *q=NULL;
- for (i=0; i<ndevices; i++)
- if (devices[i].type!='l' && !devices[i].omit &&
- which_class(devices[i].class)<0) {
- if (!q || strcmp(q, devices[i].class)) {
- warn("Invalid device class %s for %s",
- devices[i].class, devices[i].name);
- q = devices[i].class;
- }
- devices[i].class = "default";
- }
-}
-
-/*
- * Create an entry in the device table for a single device.
- */
-static void init(const char *name, const char *grp, const char *class,
- int major, int minor, int type) {
- if (major < 0) return;
- if (!strchr("bcl", type)) {
- warn("invalid device type %c for %s (skipping)", type, name);
- return;
- }
- if (ndevices>=maxdevices) crash("out of space for devices");
- devices[ndevices].name = name;
- devices[ndevices].grp = grp;
- devices[ndevices].class = class;
- devices[ndevices].major = major;
- devices[ndevices].minor = minor;
- devices[ndevices].type = type;
- devices[ndevices].omit = 0;
- ndevices++;
-}
-
-/*
- * Create an entry for a symbolic link "device", such as /dev/fd
- * (which is a symbolic link to /proc/self/fd)
- */
-static void initlink(const char *name, const char *grp, const char *target) {
- init(name, grp, target, 0, 0, 'l');
-}
-
-/*
- * Init lots of devices. This creates a number of devices, numbered between
- * lo and hi. The idea is that "base" contains a %d or %x (or something like
- * that) in it which pulls in the number. The device group can also do this,
- * though this will in most cases not be useful. "baseminor" is the minor
- * number of the first device created.
- */
-static void initlots(const char *base, int lo, int hi, const char *grp,
- const char *class,
- int maj, int baseminor, int type) {
- char buf[32], gbuf[32];
- int i;
- if (maj<0) return;
- for (i=lo; i<hi; i++) {
- sprintf(buf, base, i);
- if (grp) sprintf(gbuf, grp, i); /* grp is permitted to contain a %d */
- init(strdup(buf), grp ? strdup(gbuf) : NULL, class,
- maj, baseminor+i-lo, type);
- }
-}
-
-/*
- * Init a whole (hard) disk's worth of devices - given `hd', it makes
- * hda1...hda8 through hdd1...hdd8 in one fell swoop. "low" and "high"
- * are the letters to use ('a' and 'd' for the previous example).
- * "nparts" is the number of partitions to create, ordinarily 8.
- * "maj" is the major device number; minmult is the multiplier for the
- * minor number. That is, if hda starts at 0, and hdb starts at 64, minmult
- * is 64.
- *
- * Note that it creates "hda", "hdb", etc. too, and puts things in the
- * groups "hda", "hdb", etc. as appropriate. The class is set to "disk".
- */
-static void initdisk(const char *base, int low, int high, int nparts,
- int maj, int minmult) {
- char buf[16], buf2[16];
- int i;
- batch *b;
- if (maj<0) return;
- if (low>=high) return;
- b = addbatch(base);
- for (i=low; i<=high; i++) {
- char *q;
- sprintf(buf, "%s%c", base, i);
- q = strdup(buf);
- init(q, q, "disk", maj, (i-low)*minmult, 'b');
- strcpy(buf2, buf);
- strcat(buf2, "%d");
- initlots(buf2, 1, nparts, buf, "disk", maj, (i-low)*minmult+1, 'b');
- add2batch(b, q);
- }
-}
-
-static void initdevs(void) {
- FILE *f = fopen("DEVINFO", "r");
- if (!f) f = fopen("../DEVINFO", "r");
- if (!f) f = fopen("/etc/devinfo", "r");
- if (!f) crash("Can't find DEVINFO");
- doparse(f,3, "DEVINFO");
- fclose(f);
- f = fopen("DEVINFO.local", "r");
- if (!f) f = fopen("../DEVINFO.local", "r");
- if (!f) f = fopen("/etc/devinfo.local", "r");
- if (!f) f = fopen("/usr/local/etc/devinfo.local", "r");
- if (f) {
- doparse(f,3, "DEVINFO.local");
- fclose(f);
- }
-}
-
-/************************** update *************************/
-
-/*
- * Call make() with our names for something that appeared in /proc/devices.
- */
-
-static void transmake(const char *procname, makeopts m) {
- const char *gname = groupnameof(procname);
- if (gname) make(gname, m);
-}
-
-/*
- * Update a device that appeared in MAKEDEV.cache. Whenever we update,
- * we save what we did into MAKEDEV.cache; this lets us avoid doing
- * them over the next time. We only do something if the device has
- * disappeared or the major number has changed.
- *
- * Note that this caching made the shell version go much faster (it took
- * around 15 seconds with the cache, vs. over a minute if the cache was
- * blown away.) For us, it still does, but it hardly matters: it shaves
- * one second off a two-second execution.
- *
- * Also note the old script used DEVICES instead of MAKEDEV.cache. We
- * changed because the old file didn't record whether something was
- * a block or character device; since the sets of numbers are independent,
- * this was bound to break.
- */
-static void update2(const char *name, int ischar, int major) {
- int now = get_major(name, ischar, -1);
- if (now<0) {
- deletion = 1; /* must have been zero if we're doing an update */
- transmake(name, M_CREATE);
- deletion = 0;
- }
- else if (now!=major) { /* oops, it moved; remake it */
- transmake(name, M_CREATE);
- if (ischar) cmajors[now].flag=1;
- else bmajors[now].flag=1;
- }
- else {
- if (ischar) cmajors[now].flag=1; /* unchanged; inhibit remaking it */
- else bmajors[now].flag=1; /* unchanged; inhibit remaking it */
- }
-}
-
-static void updatefromcache(const char *name, int major, int type) {
- update2(name, type=='c', major);
-}
-
-
-/*
- * Update. Read the information stored in MAKEDEV.cache from the last
- * update; fix anything that changed; then create any new devices that
- * weren't listed the last time. (We use the "flag" field in the
- * majors array to check this.) At that point, write out a new
- * cache file.
- */
-#define CACHEFILE "MAKEDEV.cache"
-
-static void update(void) {
- FILE *f;
- int i;
- if (no_proc) { warn("Couldn't read anything from /proc/devices"); return; }
- if (deletion) { warn("update and -d are incompatible"); return; }
- f = fopen(CACHEFILE, "r");
- if (f) {
- doparse(f, 2, CACHEFILE);
- fclose(f);
- }
- for (i=0; i<MAXMAJORS; i++) {
- if (cmajors[i].procname && !cmajors[i].flag) {
- transmake(cmajors[i].procname, M_CREATE);
- cmajors[i].flag=1;
- }
- if (bmajors[i].procname && !bmajors[i].flag) {
- transmake(bmajors[i].procname, M_CREATE);
- bmajors[i].flag=1;
- }
- }
- if (donothing) return;
- f = fopen(CACHEFILE, "w");
- if (f) {
- for (i=0; i<MAXMAJORS; i++) {
- if (cmajors[i].procname) fprintf(f, "%s %d char\n", cmajors[i].procname, i);
- if (bmajors[i].procname) fprintf(f, "%s %d block\n", bmajors[i].procname, i);
- }
- fclose(f);
- }
- else warn("warning: can't write MAKEDEV.cache");
-}
-
-/************************* work *************************/
-
-/*
- * Create (or delete, etc. according to flags) a device or device group.
- * The "generic" group is handled specially by recursing once.
- * "update" is handled specially; see update() below.
- * "local" issues a warning; people should use DEVINFO.local instead.
- */
-static void make(const char *what, makeopts m) {
- int i;
- if (!strcmp(what, "update")) {
- if (m!=M_CREATE) warn("update not compatible with those options");
- else update();
- }
- else if (!strcmp(what, "local")) {
- warn("The local target is obsolete.");
- }
- else if (!try_run_batch(what, m)) {
- int found=0;
- for (i=0; i<ndevices; i++) {
- if ((devices[i].grp && !strcmp(what, devices[i].grp)) ||
- !strcmp(what, devices[i].name)) {
- makedev(&devices[i], m);
- found = 1;
- }
- }
- if (!found) warn("unknown device or device group %s", what);
- }
-}
-
-/*
- * A major improvement over the shell version...
- */
-static void usage(void) {
- printf("MAKEDEV usage:\n");
- printf(" MAKEDEV [-vdcn] device [device...]\n");
- printf(" -v Verbose output\n");
- printf(" -d Remove specified devices\n");
- printf(" -c Create devices (default)\n");
- printf(" -n Don't actually do anything (implies -v)\n");
- printf(" -V Print version information\n");
- printf("\n");
-}
-
-/*
- * We should use getopt one of these days.
- */
-int main(int argc, char **argv) {
- int i,j, done=0;
- for (i=1; i<argc && argv[i][0]=='-' && !done; i++)
- for (j=1; argv[i][j] && !done; j++) switch(argv[i][j]) {
- case '-': done=1; break;
- case 'v': isverbose = 1; break;
- case 'd': deletion = 1; break;
- case 'c': deletion = 0; break;
- case 'n': donothing = 1; isverbose = 1; break;
- case 'h': usage(); exit(0);
- case 'V': printf("MAKEDEV: %s\n", version); exit(0);
- default: fprintf(stderr, "MAKEDEV: unknown flag %c\n", argv[i][j]);
- exit(1);
- }
- setup_majors(); /* read major device numbers from /proc */
- allocate_devs(1500); /* make space to hold devices */
- initdevs(); /* set up device structures */
- loadclasses(); /* load device classes from config file */
- check_classes(); /* make sure no devices have bogus classes */
- if (i==argc) warn("didn't do anything; try -h for help.");
- else for (; i<argc; i++) make(argv[i], M_CREATE);
- return 0;
-}
-
-}
-{
-/************************* parsing support *************************/
-
-/*
- * Don't use the built-in error printing.
- */
-#define SYNTAX_ERROR
-#define PARSER_STACK_OVERFLOW
-#define REDUCTION_TOKEN_ERROR
-
-static void doparse(FILE *f, int filetype, const char *filename) {
- char *x;
- int i=0, len;
- if (filetype<1 || filetype>4) crash("tried to parse a bad file type");
- if (filetype!=1) { /* /proc/devices won't stat intelligently */
- struct stat buf;
- if (fstat(fileno(f), &buf)) crash("fstat failed?!?");
- len = buf.st_size;
- }
- else len=1023;
- x = malloc(len+1);
- if (!x) crash("Out of memory");
-
- len = fread(x, 1, len, f); /* it shouldn't return a short count... */
- if (len<0) crash("fread failed?!?");
- x[len]=0;
-
- init_parse();
- PCB.input_code = filetype+'0';
- parse();
- PCB.column--; /* correct for the filetype token */
- while (!PCB.exit_flag) {
- PCB.input_code = x[i++];
- parse();
- }
- if (PCB.exit_flag == AG_SYNTAX_ERROR_CODE) {
- warn("syntax error: %s, line %d, column %d in file %s",
- PCB.error_message, PCB.line, PCB.column, filename);
- crash("Sorry, can't continue.");
- }
- else if (PCB.exit_flag != AG_SUCCESS_CODE) {
- crash("parser stack overflow!");
- }
-}
-
-#define STRINGSIZE 8192
-static char string_space[STRINGSIZE];
-static int stringptr=0;
-
-static const char *string_start(int c) {
- if (stringptr>=STRINGSIZE) crash("out of string space");
- return string_space[stringptr]=c, string_space+stringptr++;
-}
-
-static void string_push(int c) {
- if (stringptr>=STRINGSIZE) crash("out of string space");
- string_space[stringptr++] = c;
-}
-
-static void string_finish(void) {
- string_push(0);
-}
-
-}
-/************************* syntax begins here *************************/
-
-/*
- * We read four different file formats here:
- * /proc/devices 1
- * MAKEDEV.cache 2
- * DEVINFO 3
- * MAKEDEV.config 4
- */
-
-
-[
- sticky {identifier}
- disregard white space
- lexeme {identifier, simple eol, quoted string}
- distinguish keywords {'a-z' + 'A-Z'}
- event driven
- parser name = parse
- line numbers
-]
-
-(void) file format $
- -> '1', devices
- -> '2', cache
- -> '3', devinfo
- -> '4', config
-
-
-/************************* /proc/devices *************************/
-
-(void) devices
- -> eol?, device list..., eof
-
-(void) device list
- -> "Character devices:", eol, character device...
- -> "Block devices:", eol, block device...
-
-(void) character device
- -> number:n, name:s, eol = set_major(s,YES,n);
-
-(void) block device
- -> number:n, name:s, eol = set_major(s,NO,n);
-
-/************************* cache *************************/
-
-(void) cache
- -> eol?, cachedevice..., eof
-
-(void) cachedevice
- -> name:n, number:maj, devicetype:t, eol = updatefromcache(n,maj,t);
-
-(char) devicetype
- -> 'b' = 'b';
- -> 'c' = 'c';
- -> "block" = 'b';
- -> "char" = 'c';
-
-/************************* devinfo *************************/
-
-(void) devinfo
- -> eol?, device block..., eof
-
-(void) device block
- -> device header spec, '{', eol?, device decl?..., '}', eol?
- -> device header spec, eol?, device decl
- -> "ignore", '{', eol?, ignoramus..., '}', eol?
- -> "batch", batch list, '}', eol?
-
-(batch *) batch list
- -> name:n, '{', eol?, batch item:i, eol? = add2batch(addbatch(n), i);
- -> batch list:b, [',', eol?], batch item:i, eol? = add2batch(b,i);
-
-(const char *) batch item
- -> name:n = n;
-
-(void) ignoramus
- -> name:n, eol?, [',', eol?] = ignore_procname(n);
-
-{
- static const char *cur_group=NULL, *cur_class=NULL;
- static int cur_type;
- static int cur_maj=0, cur_min=0, cur_bot=0, cur_top=0, ishex=0;
-
- static void dhsproc(const char *g, const char *p, int t, int m) {
- cur_group = g;
- cur_type = t;
- cur_maj = get_major(p, (t=='c'), m);
- cur_min = 0;
- cur_bot = cur_top = ishex = 0;
- if (p) addalias(p,g);
- }
-
- static void newdev(const char *n) {
- if (cur_maj<0) return;
- init(n, cur_group, cur_class, cur_maj, cur_min, cur_type);
- }
- static void devrange(const char *n, const char *n1) {
- char temp[32];
- if (cur_maj<0) return;
- sprintf(temp, "%s%%d%s", n, n1 ? n1 : "");
- initlots(temp, cur_bot, cur_top, cur_group, cur_class,
- cur_maj, cur_min, cur_type);
- }
- static void doinitlink(const char *src, const char *tg) {
- if (cur_maj>=0) initlink(src, cur_group, tg);
- }
-}
-
-(void) device header spec
- -> devicetype:t, '(', groupname:g, '=', procname:p, ')' = dhsproc(g,p,t,-1);
- -> devicetype:t, '(', groupname:g, '=', procname:p,
- ',', number:m, ')' = dhsproc(g,p,t,m);
- -> devicetype:t, '(', groupname:g, ',', number:m, ')' = dhsproc(g,NULL,t,m);
-
-(const char *) class
- -> '(', name:classname, ')' = classname;
-
-(void) device tail
- -> class:c, ':', expr:min, eol = (cur_class=c, cur_min=min);
-
-(void) device range
- -> '[', number:a, '-', number:b, ']' = cur_bot=a, cur_top=b, ishex=0;
- -> '[', hex number:a, '-', auto hex:b, ']' = cur_bot=a, cur_top=b, ishex=1;
-
-(void) device decl
- -> devname:n, device tail = newdev(n);
- -> devname:n, device range, devname:n1, device tail = devrange(n,n1);
- -> devname:n, device range, device tail = devrange(n,NULL);
- -> devname:n, '[', letter:a, '-', letter:b,']', number:p,'/',number:m, eol =
- initdisk(n, a, b, p, cur_maj, m);
- -> devname:n, "->", name:tg, eol = doinitlink(n, tg);
-
-(const char *) devname -> name:n = n;
-(const char *) groupname -> name:n = n;
-(const char *) procname -> name:n = n;
-
-
-/************************* config *************************/
-
-(void) config
- -> eol?, config decl..., eof
-
-(void) config decl
- -> class decl
- -> omit decl
-
-(void) class decl
- -> "class", name:n, ':', name:o, name:g, mode:m, eol = addclass(n,o,g,m);
-
-(void) omit decl
- -> "omit", name:n, eol = make(n, M_OMIT);
- -> "omit", '{', eol?, single omit..., '}', eol?
-
-(void) single omit
- -> name:n, eol?, [',', eol?] = make(n, M_OMIT);
-
-(int) mode
- -> octal number:n = n;
-
-/************************* support *************************/
-
-eof = -1 + 0
-digit = '0-9'
-letter = 'a-z' + 'A-Z' + '-' + '_'
-octal digit = '0-7'
-qchar = 32..126 - '\\' - '"'
-
-(void) white space
- -> ' ' + '\t' + '\r'
- -> "/*", ~eof?..., "*/"
-
-
-(void) eol
- -> simple eol...
-
-(void) simple eol
- -> [{"//" | '#'}, ~'\n'?...], '\n'
-
-(const char *) name
- -> identifier:s = string_finish(), s;
- -> quoted string:s = s;
-
-(const char *) identifier
- -> letter:c = string_start(c);
- -> identifier:s, letter+digit:c = string_push(c), s;
-
-(const char *) quoted string
- -> '"', qstring:s, '"' = string_finish(), s;
-
-(const char *) qstring
- -> qstring char:c = string_start(c);
- -> qstring:s, qstring char:c = string_push(c), s;
-
-(char) qstring char
- -> qchar:c = c;
- -> '\\', '\\' = '\\';
- -> '\\', '"' = '"';
-
-(int) number
- -> digit:d = d-'0';
- -> number:n, digit:d = n*10 + d-'0';
-
-(int) hex number
- -> {"0x" | "0X"}, hex digit:d =d;
- -> hex number:n, hex digit:d =16*n+d;
-
-(int) auto hex
- -> hex digit:d =d;
- -> auto hex:n, hex digit:d =16*n+d;
-
-
-(int) hex digit
- -> digit:d =d-'0';
- -> 'a-f' + 'A-F' :d =10 + (d&7);
-
-(int) octal number
- -> octal digit:d = d-'0';
- -> octal number:n, octal digit:d = n*8+d-'0';
-
-(int) expr
- -> term
- -> expr:x, '+', term:t =x+t;
- -> expr:x, '-', term:t =x-t;
-
-(int) term
- -> factor
- -> term:t, '*', factor:f =t*f;
-// -> term:t, '/', factor:f =t/f;
-
-(int) factor
- -> number
- -> hex number
- -> '-', factor:f =-f;
- -> '(', expr:x, ')' =x;
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Thu Feb 16 10:00:24 1995 by faith@cs.unc.edu
+# Revised: Fri Oct 6 20:27:07 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
+# May be distirbuted under the GPL
#
include ../MCONFIG
# Where to put man pages?
-MAN1= cal.1 clear.1 dnsdomainname.1 domainname.1 dsplit.1 \
- hostid.1 hostname.1 kill.1 logger.1 look.1 mcookie.1 \
- md5sum.1 namei.1 reset.1 script.1 setterm.1 tsort.1 \
+MAN1= cal.1 chkdupexe.1 ddate.1 dnsdomainname.1 domainname.1 \
+ dsplit.1 hostid.1 hostname.1 kill.1 logger.1 look.1 mcookie.1 \
+ namei.1 reset.1 script.1 setterm.1 tsort.1 \
whereis.1 write.1
+ifeq "$(HAVE_CLEAR)" "no"
+MAN1:=$(MAN1) clear.1
+endif
+
# Where to put binaries?
# See the "install" rule for the links. . .
BIN= domainname hostname kill
-USRBIN= cal clear dsplit hostid logger look mcookie md5sum namei \
- reset script setterm tsort whereis write
+USRBIN= cal chkdupexe ddate dsplit hostid logger look mcookie \
+ namei reset script setterm tsort whereis write
+
+ifeq "$(HAVE_CLEAR)" "no"
+USRBIN:=$(USRBIN) clear
+endif
# Programs requiring special compilation
NEEDS_TERMCAP= setterm
-SCRIPTS= clear reset
all: $(BIN) $(USRBIN) $(USRBIN.NONSHADOW) $(USRGAMES) getoptprog
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
$(NEEDS_TERMCAP):
$(CC) $(LDFLAGS) $^ -o $@ -ltermcap
-$(SCRIPTS):
+%: %.sh
cp $@.sh $@
+ chmod 755 $@
+
+%: %.pl
+ cp $@.pl $@
+ chmod 755 $@
# Rules for everything else
cal: cal.o $(BSD)/getopt.o $(BSD)/err.o
+chkdupexe: chkdupexe.pl
clear: clear.sh
domainname: domainname.o
dsplit: dsplit.o
hostname: hostname.o
kill: kill.o procs.o
logger: logger.o $(BSD)/getopt.o
-md5sum: md5.o
+mcookie: mcookie.o md5.o
+md5sum: md5sum.o md5.o
md5.o: md5.h
namei: namei.o
reset: reset.sh
$(INSTALLDIR) $(MAN1DIR) $(MAN8DIR)
$(INSTALLMAN) $(MAN1) $(MAN1DIR)
$(INSTALLMAN) getoptprog.1 $(MAN1DIR)/getopt.1
+ifeq "$(USE_TTY_GROUP)" "yes"
+ chgrp tty $(USRBINDIR)/write
+ chmod g+s $(USRBINDIR)/write
+endif
.PHONY: clean
clean:
#include <time.h>
#include <unistd.h>
#include <locale.h>
-#include <localeinfo.h>
+
+#if defined(__linux__) && _LINUX_C_LIB_VERSION_MAJOR > 4
+# include <langinfo.h>
+#else
+# include <localeinfo.h>
+#endif
#define THURSDAY 4 /* for reformation */
#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
};
-char *day_headings = " S M Tu W Th F S ";
-char *j_day_headings = " S M Tu W Th F S ";
+char day_headings[] = " S M Tu W Th F S ";
+char j_day_headings[] = " S M Tu W Th F S ";
+const char *full_month[12];
/* leap year -- account for gregorian reformation in 1752 */
#define leap_year(yr) \
((yr) <= 1752 ? !((yr) % 4) : \
- !((yr) % 4) && ((yr) % 100) || !((yr) % 400))
+ (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
/* number of centuries since 1700, not inclusive */
#define centuries_since_1700(yr) \
int julian;
void ascii_day __P((char *, int));
-void center __P((char *, int, int));
+void center __P((const char *, int, int));
void day_array __P((int, int, int *));
int day_in_week __P((int, int, int));
int day_in_year __P((int, int, int));
int i;
strcpy(day_headings,"");
- for(i = 0 ; i < 7 ; i++ )
- {
- strncat(day_headings,_time_info->abbrev_wkday[i],2);
- strcat(day_headings," ");
- }
strcpy(j_day_headings,"");
- for(i = 0 ; i < 7 ; i++ )
- {
- strcat(j_day_headings,_time_info->abbrev_wkday[i]);
- strcat(j_day_headings," ");
- }
+
+ for(i = 0 ; i < 7 ; i++ ) {
+#if defined(__linux__) && _LINUX_C_LIB_VERSION_MAJOR > 4
+ strncat(day_headings,nl_langinfo(ABDAY_1+i),2);
+ strcat(j_day_headings,nl_langinfo(ABDAY_1+i));
+#else
+ strncat(day_headings,_time_info->abbrev_wkday[i],2);
+ strcat(j_day_headings,_time_info->abbrev_wkday[i]);
+#endif
+ strcat(day_headings," ");
+ strcat(j_day_headings," ");
+ }
+
+ for (i = 0; i < 12; i++) {
+#if defined(__linux__) && _LINUX_C_LIB_VERSION_MAJOR > 4
+ full_month[i] = nl_langinfo(MON_1+i);
+#else
+ full_month[i] = _time_info->full_month[i];
+#endif
+ }
}
void
char *p, lineout[30];
day_array(month, year, days);
- len = sprintf(lineout, "%s %d", _time_info->full_month[month - 1], year);
+ len = sprintf(lineout, "%s %d", full_month[month - 1], year);
(void)printf("%*s%s\n%s\n",
((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "",
lineout, julian ? j_day_headings : day_headings);
(void)memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 2) {
- center(_time_info->full_month[month], J_WEEK_LEN, J_HEAD_SEP);
- center(_time_info->full_month[month + 1], J_WEEK_LEN, 0);
+ center(full_month[month], J_WEEK_LEN, J_HEAD_SEP);
+ center(full_month[month + 1], J_WEEK_LEN, 0);
(void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
j_day_headings);
for (row = 0; row < 6; row++) {
(void)memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 3) {
- center(_time_info->full_month[month], WEEK_LEN, HEAD_SEP);
- center(_time_info->full_month[month + 1], WEEK_LEN, HEAD_SEP);
- center(_time_info->full_month[month + 2], WEEK_LEN, 0);
+ center(full_month[month], WEEK_LEN, HEAD_SEP);
+ center(full_month[month + 1], WEEK_LEN, HEAD_SEP);
+ center(full_month[month + 2], WEEK_LEN, 0);
(void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
"", day_headings, HEAD_SEP, "", day_headings);
for (row = 0; row < 6; row++) {
return;
}
if (julian) {
- if (val = day / 100) {
+ if ((val = day / 100)) {
day %= 100;
*p++ = val + '0';
display = 1;
void
center(str, len, separate)
- char *str;
+ const char *str;
int len;
int separate;
{
--- /dev/null
+.\" chkdupexe.1 --
+.\" Created: Sat Mar 11 18:19:44 1995 by faith@cs.unc.edu
+.\" Revised: Sat Mar 11 19:07:05 1995 by faith@cs.unc.edu
+.\" Revised: Wed Jul 5 01:56:26 1995 by shields@tembel.org
+.\" Copyright 1995 Rickard E. Faith (faith@cs.unc.edu)
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\"
+.TH CHKDUPEXE 1 "11 Mar 1995" "" "Linux Programmer's Manual"
+.SH NAME
+chkdupexe \- find duplicate executables
+.SH SYNOPSIS
+.B chkdupexe
+.SH DESCRIPTION
+.B chkdupexe
+will scan the union of $PATH and a hardcoded list of common locations
+for binaries. It will report dangling symlinks and duplicately-named
+binaries.
+.SH AUTHOR
+Nicolai Langfeldt, Michael Shields.
--- /dev/null
+#!/usr/bin/perl
+#
+# chkdupexe version 2.0
+#
+# Simple script to look for and list duplicate executables and dangling
+# symlinks in the system executable directories.
+#
+# Copyright 1993 Nicolai Langfeldt. Distribute under gnu copyleft
+# (included in perl package)
+#
+# Modified 1995-07-04 Michael Shields <shields@tembel.org>
+# Don't depend on GNU ls.
+# Cleanups.
+# Merge together $ENV{'PATH'} and $execdirs.
+# Don't break if there are duplicates in $PATH.
+#
+
+$execdirs='/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/local/bin:/local/sbin:/usr/X11/bin:/usr/bin/X11:/usr/local/X11/bin:/local/X11/bin:/usr/TeX/bin:/usr/tex/bin:/usr/local/graph/bin:/usr/games:/usr/local/games:/usr/intervies/bin/LINUX';
+
+DIRECTORY:
+foreach $dir (split(/:/, "$execdirs:$ENV{'PATH'}")) {
+
+ # Follow symlinks and make sure we haven't scanned this directory already.
+ while (-l $dir) {
+ $newdir = readlink($dir);
+ print "Dangling symlink: $dir\n" unless $newdir;
+ $dir = $newdir;
+ next DIRECTORY if $seendir{$dir}++;
+ }
+
+ opendir(DIR,$dir) || (warn "Couldn't opendir($dir): $!\n", next);
+ foreach $_ (readdir(DIR)) {
+ lstat("$dir/$_");
+ if (-l _) {
+ ($dum)=stat("$dir/$_");
+ # Might as well report these since we discover them anyway
+ print "Dangling symlink: $dir/$_\n" unless $dum;
+ next;
+ }
+ next unless -f _ && -x _; # Only handle regular executable files
+ if ($count{$_}) {
+ $progs{$_}.=" $dir/$_";
+ $count{$_}++;
+ } else {
+ $progs{$_}="$dir/$_";
+ $count{$_}=1;
+ }
+ }
+ closedir(DIR);
+}
+
+open(LS,"| xargs ls -ldU");
+while (($prog,$paths)=each %progs) {
+ print LS "$paths\n" if ($count{$prog}>1);
+}
+close(LS);
.B tput
to attempt to clear the screen checking the data in
.I /etc/termcap
+(for the GNU or BSD
+.BR tput )
+or in the terminfo database
+(for the
+.B ncurses
+.BR tput )
and sending the appropriate sequence to the terminal. This command can be
redirected to clear the screen of some other terminal.
.SH "SEE ALSO"
--- /dev/null
+.\" All Rites Reversed. This file is in the PUBLIC DOMAIN.
+.\" Kallisti.
+.TH DDATE 1 "59 Bureaucracy 3161" "" "Emperor Norton Utilities"
+.SH NAME
+ddate \- converts Gregorian dates to Discordian dates
+.SH SYNOPSIS
+.B ddate [+format] [date]
+.SH DESCRIPTION
+.B ddate
+prints the date in Discordian date format.
+.PP
+If called with no arguments,
+.B ddate
+will get the current system date, convert this to the Discordian
+date format and print this on the standard output. Alternatively, a
+Gregorian date may be specified on the command line, in the form of a numerical
+day, month and year.
+.PP
+If a format string is specified, the Discordian date will be printed in
+a format specified by the string. This mechanism works similarly to the
+format string mechanism of
+.B date(1),
+only almost completely differently. The fields are:
+.IP %A
+Full name of the day of the week (i.e., Sweetmorn)
+.IP %a
+Abbreviated name of the day of the week (i.e., SM)
+.IP %B
+Full name of the season (i.e., Chaos)
+.IP %b
+Abbreviated name of the season (i.e., Chs)
+.IP %d
+Ordinal number of day in season (i.e., 23)
+.IP %e
+Cardinal number of day in season (i.e., 23rd)
+.IP %H
+Name of current Holyday, if any
+.IP %N
+Magic code to prevent rest of format from being printed unless today is
+a Holyday.
+.IP %n
+Newline
+.IP %t
+Tab
+.IP %X
+Number of days remaining until X-Day. (Not valid if the SubGenius options are not
+compiled in.)
+.IP %{
+.IP %}
+Used to enclose the part of the string which is to be replaced with the
+words "St. Tib's Day" if the current day is St. Tib's Day.
+.IP %\.
+Try it and see.
+.bp
+.SH EXAMPLES
+.nf
+% ddate
+.br
+Sweetmorn, Bureaucracy 42, 3161 YOLD
+.PP
+% ddate +'Today is %{%A, the %e of %B%}, %Y. %N%nCelebrate %H'
+.br
+Today is Sweetmorn, the 42nd of Bureaucracy, 3161.
+.PP
+% ddate +"It's %{%A, the %e of %B%}, %Y. %N%nCelebrate %H" 26 9 1995
+.br
+It's Prickle-Prickle, the 50th of Bureaucracy, 3161.
+.br
+Celebrate Bureflux
+.PP
+% ddate +'Today's %{%A, the %e of %B%}, %Y. %N%nCelebrate %H' 29 2 1996
+.br
+Today's St. Tib's Day, 3162.
+.br
+
+.SH BUGS
+
+.B ddate(1)
+will produce undefined behaviour if asked to produce the date for St. Tib's
+day and its format string does not contain the St. Tib's Day delimiters
+%{ and %}.
+
+.SH AUTHOR
+.nh
+Original program by Druel the Chaotic aka Jeremy Johnson (mpython@gnu.ai.mit.edu)
+.br
+Major rewrite by Lee H:. O:. Smith, KYTP, aka Andrew Bulhak (acb@dev.null.org)
+.br
+Five tons of flax.
+
+.SH DISTRIBUTION POLICY
+
+Public domain. All rites reversed.
+
+.SH SEE ALSO
+
+date(1),
+.br
+Malaclypse the Younger,
+.I "Principia Discordia, Or How I Found Goddess And What I Did To Her When I Found Her"
+
--- /dev/null
+/* $ DVCS ID: $jer|,523/lhos,KYTP!41023161\b"?" <<= DO NOT DELETE! */
+
+/* ddate.c .. converts boring normal dates to fun Discordian Date -><-
+ written the 65th day of The Aftermath in the Year of Our Lady of
+ Discord 3157 by Druel the Chaotic aka Jeremy Johnson aka
+ mpython@gnu.ai.mit.edu
+ 28 Sever St Apt #3
+ Worcester MA 01609
+
+ and I'm not responsible if this program messes anything up (except your
+ mind, I'm responsible for that)
+
+ (k) YOLD 3161 and all time before and after.
+ Reprint, reuse, and recycle what you wish.
+ This program is in the public domain. Distribute freely. Or not.
+
+ Majorly hacked, extended and bogotified/debogotified on
+ Sweetmorn, Bureaucracy 42, 3161 YOLD, by Lee H:. O:. Smith, KYTP,
+ aka Andrew Bulhak, aka acb@dev.null.org
+
+ and I'm not responsible if this program messes anything up (except your
+ mind, I'm responsible for that) (and that goes for me as well --lhos)
+
+ Version history:
+ Bureflux 3161: First release of enhanced ddate with format strings
+ 59 Bcy, 3161: PRAISE_BOB and KILL_BOB options split, other minor
+ changes.
+
+*/
+
+
+/* configuration options VVVVV READ THIS!!! */
+
+/* If you wish ddate(1) to print the date in the same format as Druel's
+ * original ddate when called in immediate mode, define OLD_IMMEDIATE_FMT
+ */
+
+#define OLD_IMMEDIATE_FMT
+
+/* If you wish to use the US format for aneristic dates (m-d-y), as opposed to
+ * the Commonwealth format, define US_FORMAT.
+ */
+
+/* #define US_FORMAT */
+
+/* If you are ideologically, theologically or otherwise opposed to the
+ * Church of the SubGenius and do not wish your copy of ddate(1) to contain
+ * code for counting down to X-Day, undefine KILL_BOB */
+
+#define KILL_BOB 13013
+
+/* If you wish ddate(1) to contain SubGenius slogans, define PRAISE_BOB */
+
+/*#define PRAISE_BOB 13013*/
+
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifndef __GNUC__
+#define inline /* foo */
+#endif
+
+/* string constants */
+
+char *day_long[5] = {
+ "Sweetmorn", "Boomtime", "Pungenday", "Prickle-Prickle", "Setting Orange"
+};
+
+char *day_short[5] = {"SM","BT","PD","PP","SO"};
+
+char *season_long[5] = {
+ "Chaos", "Discord", "Confusion", "Bureaucracy", "The Aftermath"
+};
+
+char *season_short[5] = {"Chs", "Dsc", "Cfn", "Bcy", "Afm"};
+
+char *holyday[5][2] = {
+ "Mungday", "Chaoflux",
+ "Mojoday", "Discoflux",
+ "Syaday", "Confuflux",
+ "Zaraday", "Bureflux",
+ "Maladay", "Afflux"
+};
+
+struct disc_time {
+ int season; /* 0-4 */
+ int day; /* 0-72 */
+ int yday; /* 0-365 */
+ int year; /* 3066- */
+};
+
+char *excl[] = {
+ "Hail Eris!", "All Hail Discordia!", "Kallisti!", "Fnord.", "Or not.",
+ "Wibble.", "Pzat!", "P'tang!", "Frink!",
+#ifdef PRAISE_BOB
+ "Slack!", "Praise \"Bob\"!", "Or kill me.",
+#endif /* PRAISE_BOB */
+ /* randomness, from the Net and other places. Feel free to add (after
+ checking with the relevant authorities, of course). */
+ "Grudnuk demand sustenance!", "Keep the Lasagna flying!",
+ "Umlaut Zebra über alles!", "You are what you see.",
+ "Or is it?", "This statement is false.",
+#if defined(linux) || defined (__linux__) || defined (__linux)
+ "Hail Eris, Hack Linux!",
+#endif
+ ""
+};
+
+char default_fmt[] = "%{%A, %B %d%}, %Y YOLD";
+char *default_immediate_fmt=
+#ifdef OLD_IMMEDIATE_FMT
+"Today is %{%A, the %e day of %B%} in the YOLD %Y%N%nCelebrate %H"
+#else
+default_fmt
+#endif
+;
+
+#define DY(y) (y+1166)
+
+inline char *ending(int i) { return (i%10==1)?"st":(i%10==2?"nd":(i%10==3?"rd":"th"));};
+inline int leapp(int i) { return (!(DY(i)%4))&&((DY(i)%100)||(!(DY(i)%400)));};
+
+void print(struct disc_time,char **); /* old */
+void format(char *buf, const char* fmt, struct disc_time dt);
+/* select a random string */
+inline char *sel(char **strings, int num) {return(strings[random()%num]); };
+/* read a fortune file */
+int load_fortunes(char *fn, char *delim, char** result);
+
+struct disc_time convert(int,int);
+struct disc_time makeday(int,int,int);
+
+main (int argc, char *argv[])
+{
+ long t;
+ struct tm *eris;
+ int bob,raw;
+ struct disc_time hastur;
+ char schwa[23*17], *fnord=0;
+ int pi;
+
+ srandom(time(NULL));
+ /* do args here */
+ for(pi=1; pi<argc; pi++) {
+ switch(argv[pi][0]) {
+ case '+': fnord=argv[pi]+1; break;
+ case '-':
+ switch(argv[pi][1]) {
+ default: goto usage;
+ }
+ default: goto thud;
+ }
+ }
+
+ thud:
+ if (argc-pi==3){
+ int moe=atoi(argv[pi]), larry=atoi(argv[pi+1]), curly=atoi(argv[pi+2]);
+ hastur=makeday(
+#ifdef US_FORMAT
+ moe,larry,
+#else
+ larry,moe,
+#endif
+ curly);
+ fnord=fnord?fnord:default_fmt;
+ } else if (argc!=pi) {
+ usage:
+ fprintf(stderr,"usage: %s [+format] [day month year]\n", argv[0]);
+ exit(1);
+ } else {
+ t= time(NULL);
+ eris=localtime(&t);
+ bob=eris->tm_yday; /* days since Jan 1. */
+ raw=eris->tm_year; /* years since 1980 */
+ hastur=convert(bob,raw);
+ fnord=fnord?fnord:default_immediate_fmt;
+ }
+ format(schwa, fnord, hastur);
+ printf("%s\n", schwa);
+ return 0;
+}
+
+void format(char *buf, const char* fmt, struct disc_time dt)
+{
+ int tib_start=-1, tib_end=0;
+ int i, fmtlen=strlen(fmt);
+ char *bufptr=buf;
+
+/* fprintf(stderr, "format(%p, \"%s\", dt)\n", buf, fmt);*/
+
+ /* first, find extents of St. Tib's Day area, if defined */
+ for(i=0; i<fmtlen; i++) {
+ if(fmt[i]=='%') {
+ switch(fmt[i+1]) {
+ case 'A':
+ case 'a':
+ case 'd':
+ case 'e':
+ if(tib_start>0) tib_end=i+1;
+ else tib_start=i;
+ break;
+ case '{': tib_start=i; break;
+ case '}': tib_end=i+1; break;
+ }
+ }
+ }
+
+ /* now do the formatting */
+ buf[0]=0;
+
+ for(i=0; i<fmtlen; i++) {
+ if((i==tib_start) && (dt.day==-1)) {
+ /* handle St. Tib's Day */
+ strcpy(bufptr, "St. Tib's Day"); bufptr += 13;
+ i=tib_end;
+ } else {
+ if(fmt[i]=='%') {
+ char *wibble=0, snarf[23];
+ switch(fmt[++i]) {
+ case 'A': wibble=day_long[dt.yday%5]; break;
+ case 'a': wibble=day_short[dt.yday%5]; break;
+ case 'B': wibble=season_long[dt.season]; break;
+ case 'b': wibble=season_short[dt.season]; break;
+ case 'd': sprintf(snarf, "%d", dt.day+1); wibble=snarf; break;
+ case 'e': sprintf(snarf, "%d%s", dt.day+1, ending(dt.day+1));
+ wibble=snarf; break;
+ case 'H': if(dt.day==4||dt.day==49)
+ wibble=holyday[dt.season][dt.day==49]; break;
+ case 'N': if(dt.day!=4&&dt.day!=49) goto eschaton; break;
+ case 'n': *(bufptr++)='\n'; break;
+ case 't': *(bufptr++)='\t'; break;
+
+ case 'Y': sprintf(snarf, "%d", dt.year); wibble=snarf; break;
+ case '.': wibble=sel(excl, sizeof(excl)/sizeof(excl[0]));
+ break;
+#ifdef KILL_BOB
+ case 'X': sprintf(snarf, "%d",
+ xday_countdown(dt.yday, dt.year));
+ wibble = snarf; break;
+#endif /* KILL_BOB */
+ }
+ if(wibble) {
+/* fprintf(stderr, "wibble = (%s)\n", wibble);*/
+ strcpy(bufptr, wibble); bufptr+=strlen(wibble);
+ }
+ } else {
+ *(bufptr++) = fmt[i];
+ }
+ }
+ }
+ eschaton:
+ *(bufptr)=0;
+}
+
+struct disc_time makeday(int imonth,int iday,int iyear) /*i for input */
+{
+ struct disc_time funkychickens;
+
+ int cal[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 };
+ int dayspast=0;
+
+ imonth--;
+ funkychickens.year= iyear+1166;
+ while(imonth>0) { dayspast+=cal[--imonth]; }
+ funkychickens.day=dayspast+iday-1;
+ funkychickens.season=0;
+ if((funkychickens.year%4)==2) {
+ if (funkychickens.day==59) funkychickens.day=-1;
+ }
+ funkychickens.yday=funkychickens.day;
+/* note: EQUAL SIGN...hopefully that fixes it */
+ while(funkychickens.day>=73) {
+ funkychickens.season++;
+ funkychickens.day-=73;
+ }
+ return funkychickens;
+}
+
+struct disc_time convert(int nday, int nyear)
+{ struct disc_time funkychickens;
+
+ funkychickens.year = nyear+3066;
+ funkychickens.day=nday;
+ funkychickens.season=0;
+ if ((funkychickens.year%4)==2)
+ {if (funkychickens.day==59)
+ funkychickens.day=-1;
+ else if (funkychickens.day >59)
+ funkychickens.day-=1;
+ }
+ funkychickens.yday=funkychickens.day;
+ while (funkychickens.day>=73)
+ { funkychickens.season++;
+ funkychickens.day-=73;
+ }
+ return funkychickens;
+
+ }
+
+
+#ifdef KILL_BOB
+
+/* Code for counting down to X-Day, X-Day being Cfn 40, 3164 */
+
+int xday_countdown(int yday, int year) {
+ int r=(185-yday)+(((yday<59)&&(leapp(year)))?1:0);
+ while(year<3164) r+=(leapp(++year)?366:365);
+ while(year>3164) r-=(leapp(year--)?366:365);
+ return r;
+}
+
+#endif
-.\" Copyright 1992, 1995 Rickard E. Faith (faith@cs.unc.edu)
+.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH DOMAINNAME 1 "16 February 1995" "Linux 1.0" "Linux Programmer's Manual"
+.TH DOMAINNAME 1 "26 December 1992" "Linux 0.98" "Linux Programmer's Manual"
.SH NAME
-domainname \- set or print NIS domain of current host
+domainname \- set or print domain of current host
.SH SYNOPSIS
.BR "domainname [ " name " ]"
.SH DESCRIPTION
.B domainname
-prints the NIS domainname of the current host, from the
+prints the domainname of the current host, from the
.BR getdomainname (3)
library call. If an argument is present and the effective UID is 0,
.B domainname
-changes the NIS domainname of the host, with the
+changes the name of the host, with the
.BR setdomainname (2)
system call. This is usually done at boot time in the
.I /etc/rc.local
script.
-.PP
-.B Note:
-This command sets the NIS (Network Information Services) domain,
-.I not
-the DNS (Domain Name System) domain. Unless you are running NIS
-(formerly known as Sun Yellow Pages (YP)), you should
-.I not
-use the
-.B domainname
-command to set your domain. You probably want to set the DNS domain, which
-is used to map human-readable machine names into IP addresses on the
-InterNet. See
-.BR dnsdomainname (1)
-for more information.
.SH FILES
.I /etc/rc.local
.SH "SEE ALSO"
-.BR hostname (1),
-.BR dnsdomainname (1),
-.BR named (8),
-.BR sendmail (8),
-.bR ypinit (8)
+.BR getdomainname (3),
+.BR setdomainname (2),
+.BR uname (1),
+.BR uname (2)
.SH AUTHOR
Lars Wirzenius by substituting in hostname.c
#ifdef lint
- static char RCSid[] = "dsplit.c,v 1.1.1.1 1995/02/22 19:09:14";
+ static char RCSid[] = "$RCSfile: dsplit.c,v $ $Revision: 1.9 $ $Date: 1995/03/12 01:31:03 $";
#endif
/*
Program dsplit: Splits a large file into pieces.
--- /dev/null
+/* hostname -- set the host name or show the host/domain name
+
+ Copyright (C) 1994 Peter Tobias
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <netdb.h>
+#include <errno.h>
+#include <sys/param.h>
+
+#define NO_OPT -1
+
+static char *program_name;
+static const char *version_string = "hostname 1.5";
+
+static void sethname(char *);
+static void showhname(char *, int);
+static void usage(void);
+
+static void sethname(char *hname)
+{
+ if(sethostname(hname, strlen(hname))) {
+ switch(errno) {
+ case EPERM:
+ fprintf(stderr,"%s: you must be root to change the host name\n", program_name);
+ break;
+ case EINVAL:
+ fprintf(stderr,"%s: name too long\n", program_name);
+ break;
+ default:
+ }
+ exit(1);
+ };
+}
+
+static void showhname(char *hname, int c)
+{
+ struct hostent *hp;
+ register char *p;
+
+ if (!(hp = gethostbyname(hname))) {
+ herror(program_name);
+ exit(1);
+ }
+
+ if (!(p = strchr(hp->h_name, '.'))) {
+ fprintf(stderr,"%s: can't find a FQDN for the host name `%s'\n", program_name, hname);
+ exit(1);
+ }
+
+ switch(c) {
+ case 'd':
+ printf("%s\n", ++p);
+ break;
+ case 'f':
+ printf("%s\n", hp->h_name);
+ break;
+ case 's':
+ *p = '\0';
+ printf("%s\n", hp->h_name);
+ break;
+ default:
+ }
+}
+
+static void usage(void)
+{
+ printf("Usage: %s [OPTION]... [hostname]\n\n\
+ -d, --domain display the DNS domain name\n\
+ -F, --file filename read the host name from file\n\
+ -f, --fqdn, --long display the long host name (FQDN)\n\
+ -s, --short display the short host name\n\
+ -h, --help display this help and exit\n\
+ -v, --version output version information and exit\n\
+\n\
+ When the program is called without any arguments, it displays the\n\
+ current host name as set by the hostname command. If an argument\n\
+ is given, the program will set the value of the host name to the\n\
+ value specified.\n\
+ Unless you are using bind or NIS for host lookups you can change the\n\
+ FQDN (Fully Qualified Domain Name) and the DNS domain name (which is\n\
+ part of the FQDN) in the /etc/hosts file.\n", program_name);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+ int option_index = 0;
+
+ char myname[MAXHOSTNAMELEN+1];
+
+ static const struct option long_options[] =
+ {
+ {"domain", no_argument, 0, 'd'},
+ {"file", required_argument, 0, 'F'},
+ {"fqdn", no_argument, 0, 'f'},
+ {"help", no_argument, 0, 'h'},
+ {"long", no_argument, 0, 'f'},
+ {"short", no_argument, 0, 's'},
+ {"version", no_argument, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+
+ program_name = (rindex(argv[0], '/')) ? rindex(argv[0], '/') + 1 : argv[0];
+
+ if (strcmp(program_name, "dnsdomainname") == 0) {
+ if (argc > 1) {
+ fprintf(stderr,"%s: You can't change the DNS domainname with this command\n", program_name);
+ fprintf(stderr,"\nUnless you are using bind or NIS for host lookups you can change the DNS\n");
+ fprintf(stderr,"domain name (which is part of the FQDN) in the /etc/hosts file.\n");
+ exit(1);
+ }
+ c = 'd';
+ } else
+ c = getopt_long(argc, argv, "dfF:hsv", long_options, &option_index);
+
+ gethostname(myname, sizeof(myname));
+
+ switch(c)
+ {
+ case 'd':
+ case 'f':
+ case 's':
+ showhname(myname, c);
+ break;
+ case 'F':
+ {
+ register FILE *fd;
+ register char *p;
+ char fline[MAXHOSTNAMELEN];
+
+ if ((fd = fopen(optarg, "r")) != NULL) {
+ while (fgets(fline, sizeof(fline), fd) != NULL)
+ if ((p = index(fline, '\n')) != NULL) {
+ *p = '\0';
+ if (fline[0] == '#')
+ continue;
+ sethname(fline);
+ }
+ (void) fclose(fd);
+ } else {
+ fprintf(stderr,"%s: can't open `%s'\n",
+ program_name, optarg);
+ exit(1);
+ }
+ }
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'v':
+ printf("%s\n", version_string);
+ break;
+ case '?':
+ fprintf(stderr,"Try `%s --help' for more information.\n", program_name);
+ exit(1);
+ break;
+ case NO_OPT:
+ if (optind < argc) {
+ sethname(argv[optind]);
+ exit(0);
+ }
+ default:
+ printf("%s\n", myname);
+
+ };
+ exit(0);
+}
.\" mcookie.1 --
.\" Public Domain 1995 Rickard E. Faith (faith@cs.unc.edu)
-.TH MCOOKIE 1 "12 Feb 1995" "" "Linux Programmer's Manual"
+.TH MCOOKIE 1 "25 September 1995" "" "Linux Programmer's Manual"
.SH NAME
mcookie \- generate magic cookies for xauth
.SH SYNOPSIS
-.B mcookie
+.BI "mcookie [\-v] [\-f " filename " ]"
.SH DESCRIPTION
.B mcookie
generates a 128-bit random hexadecimal number for use with the X authority
.RS
xauth add :0 . `mcookie`
.RE
+.PP
+The "random" number generated is actually the output of the MD5 message
+digest fed with various piece of random information: the current time, the
+process id, the parent process id, the contents of an input file (if
+.B \-f
+is specified), and several bytes of information from the first of the
+following devices which is present:
+.IR /dev/urandom ", " /dev/random ", " /dev/audio .
+Other files in
+.I /proc
+may be used as a last resort.
+.SH BUGS
+The entropy in the generated 128-bit is probably quite small (and,
+therefore, vulnerable to attack) unless a non-pseudorandom number generator
+is used (e.g.,
+.I /dev/random
+under Linux).
+.PP
+It is assumed that none of the devices opened will block.
+.SH FILES
+.I /dev/random
+.br
+.I /dev/urandom
+.br
+.I /dev/audio
+.br
+.I /proc/stat
+.br
+.I /proc/loadavg
.SH "SEE ALSO"
.BR X (1),
-.BR xauth (1)
+.BR xauth (1),
+.BR md5sum (1)
/* mcookie.c -- Generates random numbers for xauth
* Created: Fri Feb 3 10:42:48 1995 by faith@cs.unc.edu
- * Revised: Sun Feb 12 20:29:58 1995 by faith@cs.unc.edu
+ * Revised: Mon Sep 25 23:44:43 1995 by r.faith@ieee.org
* Public Domain 1995 Rickard E. Faith (faith@cs.unc.edu)
* This program comes with ABSOLUTELY NO WARRANTY.
*
- * mcookie.c,v 1.1.1.1 1995/02/22 19:09:16 faith Exp
+ * $Id: mcookie.c,v 1.2 1995/10/07 01:32:00 faith Exp $
+ *
+ * This program gathers some random bits of data and used the MD5
+ * message-digest algorithm to generate a 128-bit hexadecimal number for
+ * use with xauth(1).
+ *
+ * NOTE: Unless /dev/random is available, this program does not actually
+ * gather 128 bits of random information, so the magic cookie generated
+ * will be considerably easier to guess than one might expect.
*/
-#define SECURE 1
+#ifdef __linux__
+#define HAVE_GETTIMEOFDAY 1
+#endif
#include <stdio.h>
#include <stdlib.h>
-#if SECURE
+#include <fcntl.h>
+#include "md5.h"
+#if HAVE_GETTIMEOFDAY
#include <sys/time.h>
#include <unistd.h>
#endif
-int main( void )
+#define MAXBUFFERSIZE 512
+
+struct rngs {
+ const char *path;
+ int length;
+} rngs[] = {
+ { "/dev/random", 16 },
+ { "/dev/urandom", 128 },
+ { "/proc/stat", MAXBUFFERSIZE },
+ { "/proc/loadavg", MAXBUFFERSIZE },
+ { "/dev/audio", MAXBUFFERSIZE },
+};
+#define RNGS (sizeof(rngs)/sizeof(struct rngs))
+
+int Verbose = 0;
+
+int main( int argc, char **argv )
{
- int i;
-#if SECURE
- struct timeval tv;
- struct timezone tz;
+ int i;
+ struct MD5Context ctx;
+ unsigned char digest[16];
+ unsigned char buf[MAXBUFFERSIZE];
+ int fd;
+ int c;
+ pid_t pid;
+ char *file = NULL;
+ int r;
+#if HAVE_GETTIMEOFDAY
+ struct timeval tv;
+ struct timezone tz;
+#else
+ long int t;
+#endif
+ while ((c = getopt( argc, argv, "vf:" )) != EOF)
+ switch (c) {
+ case 'v': ++Verbose; break;
+ case 'f': file = optarg; break;
+ }
+
+ MD5Init( &ctx );
+
+#if HAVE_GETTIMEOFDAY
gettimeofday( &tv, &tz );
- srand( tv.tv_sec + tv.tv_usec );
+ MD5Update( &ctx, (unsigned char *)&tv, sizeof( tv ) );
#else
- long int t;
-
time( &t );
- srand( t );
+ MD5Update( &ctx, (unsigned char *)&t, sizeof( t ) );
#endif
+ pid = getppid();
+ MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
+ pid = getpid();
+ MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
- for (i = 0; i < 32; i++) {
- int r = (rand() & 0x0f0) >> 4;
+ if (file) {
+ int count = 0;
+
+ if (file[0] == '-' && !file[1]) fd = fileno(stdin);
+ else if ((fd = open( file, O_RDONLY )) <0) {
+ fprintf( stderr, "Could not open %s\n" );
+ }
- if (r < 10) putchar( '0' + r );
- else putchar( 'a' + r - 10 );
+ while ((r = read( fd, buf, sizeof( buf ) )) > 0) {
+ MD5Update( &ctx, buf, r );
+ count += r;
+ }
+ if (Verbose)
+ fprintf( stderr, "Got %d bytes from %s\n", count, file );
+
+ if (file[0] != '-' || file[1]) close( fd );
}
+
+ for (i = 0; i < RNGS; i++) {
+ if ((fd = open( rngs[i].path, O_RDONLY )) >= 0) {
+ r = read( fd, buf, sizeof( buf ) );
+ MD5Update( &ctx, buf, r );
+ close( fd );
+ if (Verbose)
+ fprintf( stderr, "Got %d bytes from %s\n", r, rngs[i].path );
+ if (r >= rngs[i].length) break;
+ } else if (Verbose)
+ fprintf( stderr, "Could not open %s\n", rngs[i].path );
+ }
+
+ MD5Final( digest, &ctx );
+ for (i = 0; i < 16; i++) printf( "%02x", digest[i] );
putchar ( '\n' );
return 0;
-------------------------------------------------------------*/
#ifndef lint
-static char *RCSid = "namei.c,v 1.1.1.1 1995/02/22 19:09:16 faith Exp";
+static char *RCSid = "$Id: namei.c,v 1.4 1995/03/12 01:35:45 faith Exp $";
#endif
#include <stdio.h>
* modify it under the terms of the gnu general public license.
* there is no warranty.
*
- * faith
- * 1.2
- * 1995/02/23 01:20:40
+ * $Author: faith $
+ * $Revision: 1.2 $
+ * $Date: 1995/03/12 02:55:24 $
*
*/
arguments. This causes
.B tput
to send appropriate reset strings to the terminal based on information in
-.IR /etc/termcap .
+.I /etc/termcap
+(for the GNU or BSD
+.BR tput )
+or in the terminfo database
+(for the
+.B ncurses
+.BR tput ).
This sequence seems to be sufficient to reset the Linux VC's when they
start printing "funny-looking" characters. For good measure,
.BR stty (1)
-.\" Copyright (c) 1989 The Regents of the University of California.
-.\" All rights reserved.
+.\" Copyright (c) 1989, 1993
+.\" The Regents of the University of California. All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" @(#)write.1 6.5 (Berkeley) 4/24/91
+.\" @(#)write.1 8.1 (Berkeley) 6/6/93
.\"
-.\" Modified for Linux, Mon Mar 8 18:22:44 1993, faith@cs.unc.edu
+.\" Modified for Linux, Sun Mar 12 10:21:01 1995, faith@cs.unc.edu
.\"
-.Dd March 8, 1993
-.Dt WRITE 1
-.Os "Linux 0.99"
-.Sh NAME
-.Nm write
-.Nd send a message to another user
-.Sh SYNOPSIS
-.Nm write
-.Ar user
-.Op Ar ttyname
-.Sh DESCRIPTION
-.Nm Write
+.TH WRITE 1 "12 March 1995" "" "Linux Programmer's Manual"
+.SH NAME
+write \- send a message to another user
+.SH SYNOPSIS
+.BI write " user " [ ttyname ]
+.SH DESCRIPTION
+.B Write
allows you to communicate with other users, by copying lines from
your terminal to theirs.
-.Pp
+.PP
When you run the
-.Nm write
+.B write
command, the user you are writing to gets a message of the form:
-.Pp
-.Dl Message from yourname@yourhost on yourtty at hh:mm ...
-.Pp
+.PP
+.RS
+Message from yourname@yourhost on yourtty at hh:mm ...
+.RE
+.PP
Any further lines you enter will be copied to the specified user's
-terminal.
-If the other user wants to reply, they must run
-.Nm write
+terminal. If the other user wants to reply, they must run
+.B write
as well.
-.Pp
-When you are done, type an end-of-file or interrupt character.
-The other user will see the message
-.Ql EOF
-indicating that the
-conversation is over.
-.Pp
-You can prevent people (other than the super-user) from writing to you
-with the
-.Xr mesg 1
-command.
-Some commands, for example
-.Xr nroff 1
+.PP
+When you are done, type an end-of-file or interrupt character. The other
+user will see the message
+.B EOF
+indicating that the conversation is over.
+.PP
+You can prevent people (other than the super-user) from writing to you with
+the
+.BR mesg (1)
+command. Some commands, for example
+.BR nroff (1)
and
-.Xr pr 1 ,
-disallow writing automatically, so that your output isn't overwritten.
-.Pp
+.BR pr (1),
+may disallow writing automatically, so that your output isn't overwritten.
+.PP
If the user you want to write to is logged in on more than one terminal,
you can specify which terminal to write to by specifying the terminal
name as the second operand to the
-.Nm write
-command.
-Alternatively, you can let
-.Nm write
-select one of the terminals \- it will pick the one with the shortest
-idle time.
-This is so that if the user is logged in at work and also dialed up from
-home, the message will go to the right place.
-.Pp
-The traditional protocol for writing to someone is that the string
-.Ql \-o ,
+.B write
+command. Alternatively, you can let
+.B write
+select one of the terminals \- it will pick the one with the shortest idle
+time. This is so that if the user is logged in at work and also dialed up
+from home, the message will go to the right place.
+.PP
+The traditional protocol for writing to someone is that the string `\-o',
either at the end of a line or on a line by itself, means that it's the
-other person's turn to talk.
-The string
-.Ql oo
-means that the person believes the conversation to be
-over.
-.Sh SEE ALSO
-.Xr mesg 1 ,
-.Xr talk 1 ,
-.Xr who 1
-.Sh HISTORY
+other person's turn to talk. The string `oo' means that the person
+believes the conversation to be over.
+.SH "SEE ALSO"
+.BR mesg (1),
+.BR talk (1),
+.BR who (1)
+.SH HISTORY
A
-.Nm
-command appeared in
-.At v6 .
+.B write
+command appeared in Version 6 AT&T UNIX.
/*
- * Copyright (c) 1989 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
*/
#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
- All rights reserved.\n";
+static char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)write.c 4.22 (Berkeley) 6/1/90";
+static char sccsid[] = "@(#)write.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#include <sys/param.h>
#include <string.h>
#ifdef __linux__
#include <paths.h>
+#include "pathnames.h"
+#include <locale.h>
#endif
extern int errno;
char tty[MAXPATHLEN], *mytty, *ttyname();
void done();
+#ifdef __linux__
+ setlocale(LC_CTYPE,"");
+#endif
+
/* check that sender has write enabled */
if (isatty(fileno(stdin)))
myttyfd = fileno(stdin);
#define PUTC(c) if (putchar(c) == EOF) goto err;
for (; *s != '\0'; ++s) {
- c = toascii(*s);
+ c = *s;
if (c == '\n') {
PUTC('\r');
PUTC('\n');
# To make "ext" the default file system type for mount
# (used when no other type is specified), replace \"minix\" by \"ext2\".
-DEFAULT_FSTYPE=\"minix\"
+# Use iso9660 instead, since CDROMs are popular.
+DEFAULT_FSTYPE=\"iso9660\"
# you need rpcgen and libc-4.2 or rpclib to compile in the NFS support
DEFINES = -DHAVE_NFS -DFSTYPE_DEFAULT=$(DEFAULT_FSTYPE)
$(INSTALLMAN) $(MAN5) $(MAN5DIR)
$(INSTALLMAN) $(MAN8) $(MAN8DIR)
-.c.o:
+%.o: %.c
$(COMPILE) $<
mount: mount.o fstab.o sundries.o version.o $(NFS_OBJS) $(LO_OBJS)
.\" Sat Oct 9 10:07:10 1993: converted to man format by faith@cs.unc.edu
.\" Sat Nov 20 20:47:38 1993: hpfs documentation added
.\" Sat Nov 27 20:23:32 1993: Updated authorship information
+.\" Wed Jul 26 00:00:00 1995: Updated some nfs stuff, joey@infodrom.north.de
.\"
.TH FSTAB 5 "27 November 1993" "Linux 0.99" "Linux Programmer's Manual"
.SH NAME
It is formatted as a comma separated list of options. It contains at least
the type of mount plus any additional options appropriate to the filesystem
-type. For documentation on all of the available options, see
+type. For documentation on the available options for non-nfs file systems,
+see
.BR mount (8).
+For documentation on all nfs-specific options have a look at
+.BR nfs (5).
The fifth field,
.RI ( fs_freq ),
resides in
.IR /etc .
.SH BUGS
-Linux does not, currently, support the special fields for
-.BR dump " and " fsck .
-
The documentation in
.BR mount (8)
is often more up-to-date.
.SH "SEE ALSO"
-.BR getmntent "(3), " mount "(8), " swapon (8)
+.BR getmntent "(3), " mount "(8), " swapon "(8), " nfs (5)
.SH HISTORY
The
.B fstab
-/* /home/faith/cvs/util-linux/mount/fstab.c,v 1.1.1.1 1995/02/22 19:09:21 faith Exp */
+/* $Header: /home/faith/cvs/util-linux/mount/fstab.c,v 1.2 1995/10/07 01:32:03 faith Exp $ */
#include "fstab.h"
#include <stdio.h>
#define streq(s, t) (strcmp ((s), (t)) == 0)
-/* These routines are superceded by mntent(3), but I use them for
+/* These routines are superseded by mntent(3), but I use them for
convenience. Mntent(3) is used in the implementation, so be
very careful about the static buffers that are returned. */
/* The fsent(3) routines are obsoleted by mntent(3). I use them for
convenience. Since the implementation uses mntent(3), be very
careful with the static buffers returned.
- /home/faith/cvs/util-linux/mount/fstab.h,v 1.1.1.1 1995/02/22 19:09:21 faith Exp */
+ $Header: /home/faith/cvs/util-linux/mount/fstab.h,v 1.2 1995/09/25 20:57:42 faith Exp $ */
#ifndef _FSTAB_H
#include <stdio.h>
#define fstab mntent
#define fs_type mnt_type
#define fs_spec mnt_fsname
+#define fs_mntopts mnt_opts
#define FSTAB_SW MNTTYPE_SWAP
struct fstab *getfsent (void);
.\" Youngdale (eric@tantalus.nrl.navy.mil) and Remy Card
.\" (Remy.Card@masi.ibp.fr).
.\" Sun Apr 24 19:25:59 1994: Updated per information supplied by Remy Card.
-.\" Thu Jul 14 07:44:36 1994: Updated absence of -t
-.\" option. (faith@cs.unc.edu)
+.\" Thu Jul 14 07:44:36 1994: Updated absence of -t option.
+.\" (faith@cs.unc.edu)
.\" Thu Jul 14 07:49:14 1994: Updated list of valid filesystems.
.\" Wed Feb 8 09:25:48 1995: Updated man pages for Mike Grupenhoff's changes.
+.\" Sat Jul 22 01:45:58 1995: Updated list of binary extensions for
+.\" msdos conversion. (sl14@cornell.edu)
+.\" Wed Jul 26 00:00:00 1995: Updated by Martin Schulze.
+.\" (joey@infodrom.north.de)
+.\" Tue Sep 26 12:02:03 1995: Updated umount, nfs, proc parts of page.
+.\" (aeb@cwi.nl)
.\"
-.TH MOUNT 8 "8 February 1995" "Linux 1.1" "Linux Programmer's Manual"
+.TH MOUNT 8 "26 September 1995" "Linux 1.3" "Linux Programmer's Manual"
.SH NAME
mount, umount \- mount and dismount file systems
.SH SYNOPSIS
.br
.BI "mount [\-frwun] [\-t " vfstype "] [\-o " options "] " "special node"
.br
-.BI "umount [\-an] [\-t " vfstype ]
+.BI "umount [\-ahvV] [\-t " vfstype ]
.br
-.BI "umount " "special " | " node"
+.BI "umount [\-v] " "special " | " node " [...]
.\" " for hilit19
.SH DESCRIPTION
The
.IR special " or " node
are not provided, the appropriate information is taken from the
.BR fstab (5)
-file. The special keyword
-.I none
+file. The
+.I proc
+file system is not associated with a special device, and when
+mounting it, an arbitrary keyword, such as
+.I proc
can be used instead of a path or
.I node
-specification. This is useful when mounting the
-.I proc
-file system.
+specification. (The customary choice
+.I none
+is less fortunate: the error message `none busy' from umount
+can be confusing.)
The system maintains a list of currently mounted file systems. If no
arguments are given to
Tells the
.I ext2
file sysem kernel code to do some more checks while the file system is
-mounted. Currently (0.99.15), the following values can be specified with
+mounted. Currently (1.3.11), the following values can be specified with
this option:
.RS
.TP
"well-known binary" extension. The list of known extensions can be found at
the beginning of
.I fs/msdos/misc.c
-(as of 09913r, the list is: exe, com, bin, app, sys, drv, ovl, ovr, obj,
+(as of 1.3.11, the list is: exe, com, bin, app, sys, drv, ovl, ovr, obj,
lib, dll, pif, arc, zip, lha, lzh, zoo, tar, z, arj, tz, taz, tzp, tpz,
-gif, bmp, tif, gl, jpg, pcx, tfm, vf, gf, pk, pxl, dvi).
+gz, tgz, deb, gif, bmp, tif, gl, jpg, pcx, tfm, vf, gf, pk, pxl, dvi).
.PP
Programs that do computed lseeks won't like in-kernel text conversion.
+Several people have had their data ruined by this translation. Beware!
For file systems mounted in
.B binary
file systems, give every file a gid equal to
.IR value .
.TP
-B grpid
+.B grpid
Causes the
.I ext2fs
to use the BSD behavior when creating files: file are created with the
flag. Attempts to chown or chmod files do not yield errors, although they
fail. Use with caution!
.TP
+.B soft
+For the
+.IR nfs
+file system this allows the kernel to time out if the nfs server is not
+responding for some time, otherwise it will try forever. The time can be
+specified with
+.BR timeo=time .
+For more information look at
+.IR nfs (5).
+
+This option is useful if your nfs server sometimes doesn't respond or will
+be rebooted while some process tries to get a file from the server.
+.TP
.BI sb= value
For the
.I ext2
is used to indicate the file system type. The file system types which are
currently supported are listed in
.IR linux/fs/filesystems.c :
-.IR minux ", " ext ", " ext2 ", " xiafs ", " msdos ", " hpfs ,
-.IR proc ", " nfs ", " iso9660 ", " sysv ", " xenix ", " coherent .
+.IR minix ", " ext ", " ext2 ", " xiafs ", " msdos ", " umsdos ,
+.IR hpfs ", " proc ", " nfs ", " iso9660 ", " smbfs ,
+.IR sysv ", " xenix ", " coherent .
Note that that last three are equivalent and that "xenix" and "coherent"
will be removed at some point in the future \(em use "sysv" instead.
.I minix
is the default. If no
.B \-t
-option is given, the superblock is probed for the filesystem type (minix,
-ext, ext2, xia are supported). If this probe fails and
+option is given, or if the "auto" type is specified, the superblock is
+probed for the filesystem type (minix, ext, ext2, xia are supported). If
+this probe fails and
.I /proc/filesystems
exists, then all of the filesystems listed will be tried,
.I except
for those that are labeled "nodev" (e.g., "proc" and "nfs").
+Note that the "auto" type may be useful for user-mounted floppies.
+
For example, the
.B mount
command:
.B Umount
removes the
.I special
-device grafted at point
-.I node
-from file system tree.
+device, or the device grafted at point
+.IR node ,
+from the file system tree.
Options for the
.B umount
above for the
.B mount
command.)
+.TP
+.B \-V
+Print version and exit.
+.TP
+.B \-h
+Print help message and exit.
+.TP
+.B \-v
+Verbose mode.
.SH FILES
.I /etc/fstab
.I /etc/mtab.tmp
temporary file
.SH "SEE ALSO"
-.BR mount "(2), " umount "(2), " fstab "(5), " swapon (8)
+.BR mount "(2), " umount "(2), " fstab "(5), " swapon "(8), " nfs (5),
+.BR mountd "(8), " nfsd (8)
.SH BUGS
It is possible for a corrupted file system to cause a crash.
.PP
* A mount(8) for Linux 0.99.
* mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
*
- * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changed from Adam
+ * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changes from Adam
* J. Richter (adam@adam.yggdrasil.com) so that /proc/filesystems is used
* if no -t option is given. I modified his patches so that, if
* /proc/filesystems is not available, the behavior of mount is the same as
* checked.
*
* Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages.
+ * Sat Jun 3 20:44:38 1995: Patches from Andries.Brouwer@cwi.nl applied.
+ * Tue Sep 26 22:38:20 1995: aeb@cwi.nl, many changes
*
*/
#include <sys/stat.h>
#include <unistd.h>
+#define PROC_FILESYSTEMS "/proc/filesystems"
+#define SIZE(a) (sizeof(a)/sizeof(a[0]))
+
int del_loop (const char *);
/* True for fake mount (-f). */
#ifdef MS_NOSUB
{ "sub", 1, MS_NOSUB }, /* allow submounts */
{ "nosub", 0, MS_NOSUB }, /* don't allow submounts */
+#endif
+#ifdef MS_SILENT
+ { "quiet", 0, MS_SILENT }, /* be quiet */
+ { "loud", 1, MS_SILENT }, /* print out messages. */
#endif
{ NULL, 0, 0 }
};
+int mount_quiet=0;
/* Report on a single mount. */
static void
print_one (const struct mntent *mnt)
{
+ if (mount_quiet) return;
printf ("%s on %s", mnt->mnt_fsname, mnt->mnt_dir);
if ((mnt->mnt_type != NULL) && *mnt->mnt_type != '\0')
printf (" type %s", mnt->mnt_type);
*mask |= om->mask;
if (om->mask == MS_USER)
*mask |= MS_SECURE;
+#ifdef MS_SILENT
+ if (om->mask == MS_SILENT && om->inv) {
+ mount_quiet = 1;
+ verbose = 0;
+ }
+#endif
return;
}
if (*extra_opts)
/*
char *fstype(const char *device);
- probes the device and attempts to determine the type of filesystem
+ Probes the device and attempts to determine the type of filesystem
contained within.
Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
+ Read the superblock only once - aeb
+ Added a test for iso9660 - aeb
- Currently supports: minix, ext, ext2, xia
+ Currently supports: minix, ext, ext2, xiafs, iso9660
*/
+char *magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660" };
+
+static int
+tested(const char *device) {
+ char **m;
+
+ for (m = magic_known; m - magic_known < SIZE(magic_known); m++)
+ if (!strcmp(*m, device))
+ return 1;
+ return 0;
+}
static char *
fstype(const char *device)
{
int fd;
-
- /* MINIX */
- struct minix_super_block ms;
- /* extended fs */
- struct ext_super_block es;
- /* 2nd extended fs */
- struct ext2_super_block e2s;
- /* xia fs */
- struct xiafs_super_block xfs;
+ char ifs_magic[8];
+ union {
+ struct minix_super_block ms;
+ struct ext_super_block es;
+ struct ext2_super_block e2s;
+ struct xiafs_super_block xfs;
+ } sb;
+ struct stat statbuf;
+
+ /* opening and reading an arbitrary unknown path can have
+ undesired side effects - first check that `device' refers
+ to a block device */
+ if (stat (device, &statbuf))
+ error("mount: %s does not exist", device);
+ if (!S_ISBLK(statbuf.st_mode))
+ error("mount: %s is not a block device", device);
fd = open(device, O_RDONLY);
- if (fd < 0) {
+ if (fd < 0
+ || lseek(fd, BLOCK_SIZE, SEEK_SET) < 0
+ || read(fd, (char *) &sb, sizeof(sb)) < 0) {
perror(device);
return 0;
}
- lseek(fd, BLOCK_SIZE, SEEK_SET);
- read(fd, (char *) &ms, sizeof(ms));
- if (ms.s_magic == MINIX_SUPER_MAGIC || ms.s_magic == MINIX_SUPER_MAGIC2) {
- close(fd);
+
+ if (sb.ms.s_magic == MINIX_SUPER_MAGIC
+ || sb.ms.s_magic == MINIX_SUPER_MAGIC2) {
+ close (fd);
return("minix");
}
- lseek(fd, BLOCK_SIZE, SEEK_SET);
- read(fd, (char *) &es, sizeof(es));
- if (es.s_magic == EXT_SUPER_MAGIC) {
- close(fd);
+ if (sb.es.s_magic == EXT_SUPER_MAGIC) {
+ close (fd);
return("ext");
}
- lseek(fd, BLOCK_SIZE, SEEK_SET);
- read(fd, (char *) &e2s, sizeof(e2s));
- if (e2s.s_magic == EXT2_SUPER_MAGIC || e2s.s_magic == EXT2_PRE_02B_MAGIC) {
- close(fd);
+#ifndef EXT2_PRE_02B_MAGIC
+#define EXT2_PRE_02B_MAGIC 0xEF51
+#endif
+ if (sb.e2s.s_magic == EXT2_SUPER_MAGIC
+ || sb.e2s.s_magic == EXT2_PRE_02B_MAGIC) {
+ close (fd);
return("ext2");
}
- lseek(fd, 0, SEEK_SET);
- read(fd, (char *) &xfs, sizeof(xfs));
- if (xfs.s_magic == _XIAFS_SUPER_MAGIC) {
- close(fd);
+ if (sb.xfs.s_magic == _XIAFS_SUPER_MAGIC) {
+ close (fd);
return("xiafs");
}
- close(fd);
+ if (lseek (fd, 0100000, SEEK_SET) != -1
+ && read (fd, ifs_magic, 8) == 8
+ && !strncmp(ifs_magic, "\001CD001\001", 8)) { /* ECMA 119 */
+ close (fd);
+ return("iso9660");
+ }
+ close (fd);
return(0);
+}
+FILE *procfs;
+
+static void
+procclose(void) {
+ if (procfs)
+ fclose (procfs);
+ procfs = 0;
+}
+
+static int
+procopen(void) {
+ return ((procfs = fopen(PROC_FILESYSTEMS, "r")) != NULL);
+}
+
+static char *
+procnext(void) {
+ char line[100];
+ static char fsname[50];
+
+ while (fgets(line, sizeof(line), procfs)) {
+ if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue;
+ if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue;
+ return fsname;
+ }
+ return 0;
}
+static int
+is_in_proc(char *type) {
+ char *fsname;
+
+ if (procopen()) {
+ while ((fsname = procnext()) != NULL)
+ if (!strcmp(fsname, type))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+already (char *spec, char *node) {
+ struct mntent *me;
+ int ret = 1;
+
+ if ((me = getmntfile(node)) != NULL)
+ error ("mount: according to mtab, %s is already mounted on %s",
+ me->mnt_fsname, node);
+ else if ((me = getmntfile(spec)) != NULL)
+ error ("mount: according to mtab, %s is mounted on %s",
+ spec, me->mnt_dir);
+ else
+ ret = 0;
+ return ret;
+}
/* Mount a single file system. Return status,
so don't exit on non-fatal errors. */
static int
try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) {
- FILE *procfs_file;
- char line[100];
- char fsname[50];
+ char *fsname;
- if (*type) return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts);
- if (( procfs_file = fopen("/proc/filesystems", "r")) == NULL) {
- /* If /proc/filesystems is not available,
- preserve the old behavior of mount. */
- return mount5 (spec,
- node,
- FSTYPE_DEFAULT,
- flags & ~MS_NOSYS, mount_opts);
+ if (strcasecmp (*type, "auto") == 0)
+ *type = NULL;
+
+ if (!*type) {
+ *type = fstype(spec);
+ if (!*type && !procopen())
+ *type = FSTYPE_DEFAULT;
+ if (verbose) {
+ printf ("mount: you didn't specify a filesystem type for %s\n",
+ spec);
+ if (*type)
+ printf (" I will try type %s\n", *type);
+ else
+ printf (" I will try all types mentioned in %s\n",
+ PROC_FILESYSTEMS);
+ }
}
- while (fgets(line, sizeof(line), procfs_file)) {
- if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue;
- if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue;
+
+ if (*type)
+ return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts);
+
+ while ((fsname = procnext()) != NULL) {
+ if (tested (fsname))
+ continue;
if (mount5 (spec, node, fsname, flags & ~MS_NOSYS, mount_opts) == 0) {
- *type=xstrdup(fsname);
- fclose(procfs_file);
- return 0;
+ *type = xstrdup(fsname);
+ procclose();
+ return 0;
+ } else if (errno != EINVAL) {
+ *type = "guess";
+ procclose();
+ return 1;
}
}
- fclose(procfs_file);
+ procclose();
+ *type = NULL;
+
return -1;
}
int flags;
char *extra_opts;
char *mount_opts;
- int anti_recurse = 0;
+ static int added_ro = 0;
int loop=0;
if (type == NULL)
parse_opts (xstrdup (opts), &flags, &extra_opts);
/* root may allow certain types of mounts by ordinary users */
- if (suid && !(flags & MS_USER))
- die (3, "mount: only root can mount %s on %s", spec, node);
+ if (suid && !(flags & MS_USER)) {
+ if (already (spec, node))
+ die (3, "mount failed");
+ else
+ die (3, "mount: only root can mount %s on %s", spec, node);
+ }
/* quietly succeed for fstab entries that don't get mounted automatically */
if (all && (flags & MS_NOAUTO))
if (nfsmount (spec, node, &flags, &extra_opts, &mount_opts) != 0)
return 1;
#else
- die (1, "mount: this version doesn't support the type `nfs'");
+ die (1, "mount: this version was compiled without support for the type `nfs'");
#endif
- if (!type && !(type = fstype(spec)))
- return 1;
-
block_signals (SIG_BLOCK);
if (fake
{
mnt.mnt_fsname = canonicalize (spec);
mnt.mnt_dir = canonicalize (node);
- mnt.mnt_type = loop?"loop":type;
+ mnt.mnt_type = loop ? "loop" : type;
mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB,
loop?opts:extra_opts);
mnt.mnt_freq = freq;
block_signals (SIG_UNBLOCK);
/* Mount failed, complain, but don't die. */
+
+ if (type == 0)
+ error ("mount: you must specify the filesystem type");
+ else
switch (mnt_err)
{
case EPERM:
break;
case EBUSY:
error ("mount: %s already mounted or %s busy", spec, node);
+ already (spec, node);
break;
case ENOENT:
{ struct stat statbuf;
- if (stat (node, &statbuf))
+ if (lstat (node, &statbuf))
error ("mount: mount point %s does not exist", node);
+ else if (stat (node, &statbuf))
+ error ("mount: mount point %s is a symbolic link to nowhere",
+ node);
else if (stat (spec, &statbuf))
error ("mount: special device %s does not exist", spec);
else {
perror("mount");
}
break;
- }
+ }
case ENOTDIR:
error ("mount: mount point %s is not a directory", node); break;
case EINVAL:
case EIO:
error ("mount: %s: can't read superblock", spec); break;
case ENODEV:
- error ("mount: fs type %s not supported by kernel", type); break;
+ if (is_in_proc(type))
+ error("mount: %s has wrong major or minor number", spec);
+ else if (procfs)
+ error ("mount: fs type %s not supported by kernel", type);
+ else
+ error ("mount: %s has wrong device number or fs type %s not supported",
+ spec, type);
+ break;
case ENOTBLK:
error ("mount: %s is not a block device", spec); break;
case ENXIO:
error ("mount: %s is not a valid block device", spec); break;
case EACCES: /* pre-linux 1.1.38 */
case EROFS: /* linux 1.1.38 and later */
- if (anti_recurse)
- {
- error ("mount: block device %s is not permitted on its filesystem", spec);
+ if (added_ro) {
+ error ("mount: block device %s is not permitted on its filesystem",
+ spec);
break;
- }
- else
- {
- anti_recurse++;
- if (opts)
- {
- opts = realloc(xstrdup(opts), strlen(opts)+3);
+ } else {
+ added_ro = 1;
+ if (opts) {
+ opts = realloc(xstrdup(opts), strlen(opts)+4);
strcat(opts, ",ro");
- }
- else
- opts = "ro";
- error ("mount: block device %s is write-protected, mounting read-only", spec);
- return mount_one (spec, node, type, opts, freq, pass);
- }
+ } else
+ opts = "ro";
+ if (type && !strcmp(type, "guess"))
+ type = 0;
+ error ("mount: block device %s is write-protected, "
+ "mounting read-only", spec);
+ return mount_one (spec, node, type, opts, freq, pass);
+ }
break;
default:
error ("mount: %s", strerror (mnt_err)); break;
}
status = 0;
+ if (!setfsent()) return 1;
while ((fstab = getfsent ()) != NULL)
if (matching_type (fstab->mnt_type, types)
&& !streq (fstab->mnt_dir, "/")
usage (FILE *fp, int n)
{
fprintf (fp, "%s", usage_string);
+ unlock_mtab();
exit (n);
}
++verbose;
break;
case 'V': /* version */
- printf ("%s\n", version);
+ printf ("mount: %s\n", version);
exit (0);
case 'w': /* mount read/write */
++readwrite;
.SH FILES
.I /etc/fstab
.SH "SEE ALSO"
-.BR fstab "(5), " mount "(8), " umount (8)
+.BR fstab "(5), " mount "(8), " umount "(8), " exports (5)
.SH AUTHOR
"Rick Sladkey" <jrs@world.std.com>
.SH BUGS
/*
* Support functions. Exported functions are prototyped in sundries.h.
* sundries.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ *
+ * added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
*/
#include "sundries.h"
+#include "mount.h"
/* File pointer for /etc/mtab. */
FILE *F_mtab = NULL;
/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */
static int lock = -1;
+/* Flag for already existing lock file. */
+static int old_lockfile = 1;
+
/* String list constructor. (car() and cdr() are defined in "sundries.h"). */
string_list
cons (char *a, const string_list b)
{
va_list args;
+ if (mount_quiet) return;
va_start (args, fmt);
vfprintf (stderr, fmt, args);
fprintf (stderr, "\n");
die (2, "%s", sys_siglist[sig]);
}
+static void
+setlkw_timeout (int sig)
+{
+ /* nothing, fcntl will fail anyway */
+}
+
/* Create the lock file. The lock file will be removed if we catch a signal
or when we exit. The value of lock is tested to remove the race. */
void
{
int sig = 0;
struct sigaction sa;
+ struct flock flock;
/* If this is the first time, ensure that the lock will be removed. */
if (lock < 0)
{
+ struct stat st;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigfillset (&sa.sa_mask);
while (sigismember (&sa.sa_mask, ++sig) != -1)
- sigaction (sig, &sa, (struct sigaction *) 0);
-
- if ((lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0)) < 0)
- die (2, "can't create lock file %s: %s",
- MOUNTED_LOCK, strerror (errno));
+ {
+ if (sig == SIGALRM)
+ sa.sa_handler = setlkw_timeout;
+ else
+ sa.sa_handler = handler;
+ sigaction (sig, &sa, (struct sigaction *) 0);
+ }
+
+ /* This stat is performed so we know when not to be overly eager
+ when cleaning up after signals. The window between stat and
+ open is not significant. */
+ if (lstat (MOUNTED_LOCK, &st) < 0 && errno == ENOENT)
+ old_lockfile = 0;
+
+ lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT, 0);
+ if (lock < 0)
+ {
+ die (2, "can't create lock file %s: %s",
+ MOUNTED_LOCK, strerror (errno));
+ }
+
+ flock.l_type = F_WRLCK;
+ flock.l_whence = SEEK_SET;
+ flock.l_start = 0;
+ flock.l_len = 0;
+
+ alarm(LOCK_BUSY);
+ if (fcntl (lock, F_SETLKW, &flock) < 0)
+ {
+ close (lock);
+ /* The file should not be removed */
+ lock = -1;
+ die (2, "can't lock lock file %s: %s",
+ MOUNTED_LOCK, errno == EINTR ? "timed out" : strerror (errno));
+ }
+ /* We have now access to the lock, and it can always be removed */
+ old_lockfile = 0;
}
}
{
if (lock != -1)
{
- close( lock );
- unlink (MOUNTED_LOCK);
+ close (lock);
+ if (!old_lockfile)
+ unlink (MOUNTED_LOCK);
}
}
#include <string.h>
#include <unistd.h>
+#if 0
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= 0x010302
+#define SUPPORT_PRIORITIES
+#endif
+#endif
+
+#ifdef SUPPORT_PRIORITIES
+#include <linux/swap.h>
+#endif
+
#include "fstab.h"
+extern int mount_quiet;
#define streq(s, t) (strcmp ((s), (t)) == 0)
#define MOUNTED_LOCK "/etc/mtab~"
#define MOUNTED_TEMP "/etc/mtab.tmp"
#define _PATH_FSTAB "/etc/fstab"
-#define LOCK_BUSY 3
+#define LOCK_BUSY 10
/* File pointer for /etc/mtab. */
extern FILE *F_mtab;
.\" Sat Mar 6 20:46:02 1993: Modified by faith@cs.unc.edu
.\" Sat Oct 9 09:35:30 1993: Converted to man format by faith@cs.unc.edu
.\" Sat Nov 27 20:22:42 1993: Updated authorship information, faith@cs.unc.edu
+.\" Mon Sep 25 14:12:38 1995: Added -v and -p information
.\"
-.TH SWAPON 8 "27 November 1993" "Linux 0.99" "Linux Programmer's Manual"
+.TH SWAPON 8 "25 September 1995" "Linux 1.x" "Linux Programmer's Manual"
.SH NAME
swapon, swapoff \- enable/disable devices and files for paging and swapping
.SH SYNOPSIS
-.B /etc/swapon \-a
+.B /sbin/swapon [\-h \-V]
.br
-.BI /etc/swapon " specialfile " ...
+.B /sbin/swapon \-a [\-v]
.br
-.B /etc/swapoff \-a
+.BI "/sbin/swapon [\-v] [\-p " "priority" "] " " specialfile " ...
.br
-.BI /etc/swapoff " specialfile " ...
+.B /sbin/swapoff [\-h \-V]
+.br
+.B /sbin/swapoff \-a
+.br
+.BI /sbin/swapoff " specialfile " ...
.SH DESCRIPTION
.B Swapon
is used to specify devices on which paging and swapping are to take place.
Normally, the first form is used:
.TP
+.B \-h
+Provide help
+.TP
+.B \-V
+Display version
+.TP
.B \-a
All devices marked as ``sw'' swap devices in
.I /etc/fstab
are made available.
+.TP
+.BI \-p " priority"
+Specify priority for
+.BR swapon .
+This option is only available if
+.B swapon
+was compiled under and is used under a 1.3.2 or later kernel.
.PP
.B Swapoff
disables swapping on the specified devices and files, or on all swap
.BR swapon "(2), " swapoff "(2), " fstab "(5), " init "(8), " mkswap (8),
.BR rc "(8), " mount (8)
.SH FILES
-.I /dev/hd[ab]?
+.I /dev/hd??
standard paging devices
.br
-.I /dev/sd[ab]?
+.I /dev/sd??
standard (SCSI) paging devices
.br
.I /etc/fstab
/* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */
int verbose = 0;
+#ifdef SUPPORT_PRIORITIES
+int priority = -1; /* non-prioritized swap by default */
+#endif
extern char version[];
static char *program_name;
{
{ "all", 0, 0, 'a' },
{ "help", 0, 0, 'h' },
+#ifdef SUPPORT_PRIORITIES
+ { "priority", required_argument, 0, 'p' },
+#endif
{ "verbose", 0, 0, 'v' },
{ "version", 0, 0, 'V' },
{ NULL, 0, 0, 0 }
};
+#ifdef SUPPORT_PRIORITIES
const char *usage_string = "\
usage: %s [-hV]\n\
%s -a [-v]\n\
- %s [-v] special ...\n\
+ %s [-v] [-p priority] special ...\n\
";
+#else
+const char *usage_string = "\
+usage: %s [-hV]\n\
+ %s -a [-v]\n\
+ %s [-v] [-p priority] special ...\n\
+";
+#endif
static void
usage (FILE *fp, int n)
}
static int
+#ifdef SUPPORT_PRIORITIES
+swap (const char *special, int prio)
+#else
swap (const char *special)
+#endif
{
int status;
+#ifdef SUPPORT_PRIORITIES
+ int flags;
+#endif
if (verbose)
printf("%s on device %s\n", program_name, special);
- if (streq (program_name, "swapon"))
- status = swapon (special);
- else
- status = swapoff (special);
+ if (streq (program_name, "swapon")) {
+#ifdef SUPPORT_PRIORITIES
+ flags = 0;
+ if (prio >= 0) {
+ flags = SWAP_FLAG_PREFER
+ | ((prio & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
+ }
+ status = swapon (special, flags);
+#else
+ status = swapon (special);
+#endif
+ } else
+ status = swapoff (special);
if (status < 0)
fprintf (stderr, "%s: %s: %s\n", program_name, special, strerror (errno));
else
program_name = argv[0];
+#ifdef SUPPORT_PRIORITIES
+ while ((c = getopt_long (argc, argv, "ahp:vV", longopts, NULL)) != EOF)
+#else
while ((c = getopt_long (argc, argv, "ahvV", longopts, NULL)) != EOF)
+#endif
switch (c)
{
case 'a': /* all */
case 'h': /* help */
usage (stdout, 0);
break;
+#ifdef SUPPORT_PRIORITIES
+ case 'p': /* priority */
+ priority = atoi(optarg);
+ break;
+#endif
case 'v': /* be chatty */
++verbose;
break;
case 'V': /* version */
- printf ("%s\n", version);
+ printf ("swapon: %s\n", version);
exit (0);
case 0:
break;
{
while ((fstab = getfsent()) != NULL)
if (streq (fstab->fs_type, FSTAB_SW))
- status |= swap (fstab->fs_spec);
+ {
+#ifdef SUPPORT_PRIORITIES
+ /* parse mount options; */
+ char *opt, *opts = strdup(fstab->fs_mntopts);
+
+ for (opt = strtok (opts, ",");
+ opt != NULL;
+ opt = strtok (NULL, ","))
+ {
+ if (strncmp(opt, "pri=", 4) == 0)
+ {
+ priority = atoi(opt+4);
+ }
+ }
+ status |= swap (fstab->fs_spec, priority);
+#else
+ status |= swap (fstab->fs_spec);
+#endif
+ }
}
else if (*argv == NULL)
{
}
else
{
- while (*argv != NULL)
- status |= swap (*argv++);
+ while (*argv != NULL) {
+#ifdef SUPPORT_PRIORITIES
+ status |= swap (*argv++,priority);
+#else
+ status |= swap (*argv++);
+#endif
+ }
}
return status;
}
* Wed Sep 14 22:43:54 1994: Sebastian Lederer
* (lederer@next-pc.informatik.uni-bonn.de) added support for sending an
* unmount RPC call to the server when an NFS-filesystem is unmounted.
+ *
+ * Tue Sep 26 16:33:09 1995: Added patches from Greg Page (greg@caldera.com)
+ * so that NetWare filesystems can be unmounted.
*/
#include "sundries.h"
/* Umount a single device. Return a status code, so don't exit
on a non-fatal error. We lock/unlock around each umount. */
static int
-umount_one (const char *spec, const char *node)
+umount_one (const char *spec, const char *node, const char *type)
{
int umnt_err;
int isroot;
#ifdef HAVE_NFS
strcpy(buffer,spec);
/* spec is constant so must use own buffer */
- if((p=strchr(buffer,':')))
+ if(!strcasecmp(type, "nfs") && (p=strchr(buffer,':')))
{
*p='\0';
strcpy(hostname,buffer);
case EIO:
error ("umount: %s: can't write superblock", spec); break;
case EBUSY:
- error ("umount: %s: device is busy", spec); break;
+ /* Let us hope fstab has a line "proc /proc ..."
+ and not "none /proc ..."*/
+ error ("umount: %s: device is busy", spec); break;
case ENOENT:
error ("umount: %s: not mounted", spec); break;
case EPERM:
{
string_list spec_list = NULL;
string_list node_list = NULL;
+ string_list type_list = NULL;
struct mntent *mnt;
int errors;
{
spec_list = cons (xstrdup (mnt->mnt_fsname), spec_list);
node_list = cons (xstrdup (mnt->mnt_dir), node_list);
+ type_list = cons (xstrdup (mnt->mnt_type), type_list);
}
close_mtab ();
errors = 0;
while (spec_list != NULL)
{
- errors |= umount_one (car (spec_list), car (node_list));
+ errors |= umount_one (car (spec_list), car (node_list), car (type_list));
spec_list = cdr (spec_list);
node_list = cdr (node_list);
+ type_list = cdr (type_list);
}
sync ();
char *usage_string = "\
usage: umount [-hV]\n\
umount -a [-v] [-t vfstypes]\n\
- umount [-v] special | node\n\
+ umount [-v] special | node...\n\
";
static void
exit (n);
}
+int mount_quiet = 0;
+
int
main (int argc, char *argv[])
{
++verbose;
break;
case 'V': /* version */
- printf ("%s\n", version);
+ printf ("umount: %s\n", version);
exit (0);
case 't': /* specify file system type */
types = parse_list (optarg);
if (all)
result = umount_all (types);
- else if (argc != 1)
+ else if (argc < 1)
usage (stderr, 2);
- else
+ else while (argc--)
{
file = canonicalize (*argv); /* mtab paths are canonicalized */
if (suid)
{
if (!mnt)
- die (2, "umount: %s is not mounted", file);
+ die (2, "umount: %s is not mounted (according to mtab)", file);
if (!(fs = getfsspec (file)) && !(fs = getfsfile (file)))
die (2, "umount: %s is not in the fstab", file);
if (!streq (mnt->mnt_fsname, fs->mnt_fsname)
}
if (mnt)
- result = umount_one (xstrdup (mnt->mnt_fsname), xstrdup(mnt->mnt_dir));
+ result = umount_one (xstrdup (mnt->mnt_fsname), xstrdup(mnt->mnt_dir),
+ xstrdup(mnt->mnt_type));
else
- result = umount_one (*argv, *argv);
+ result = umount_one (*argv, *argv, *argv);
+
}
exit (result);
}
-char version[] = "(u)mount: version from util-linux-2.2";
+char version[] = "version from util-linux-2.5";
+++ /dev/null
-#! /bin/sh -
-
-RCSID='MAKEDEV,v 1.1.1.1 1995/02/22 19:09:11 faith Exp'
-
-#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
-# Customisation:
-# The devices fall into various classes. This section contains the mapping
-# from a class name into a group name and permission.
-# You will almost certainly need to edit the group name to match your
-# system, and you may change the permissions to suit your preference. These
-# lines _must_ be of the format "user group perm".
-
- public=" root system 666"
- system=" root system 660"
- kmem=" root kmem 660"
- tty=" root tty 666"
- cons=" root tty 622" # 622 for console?
-dialout=" root uucp 660"
- mouse=" root system 666"
-printer=" root daemon 660"
- floppy=" root floppy 660"
- disk=" root disk 660"
- scsi=" root system 600"
- cdrom=" root disk 660"
- tape=" root disk 660"
- audio=" root system 666"
- ibcs2=" root system 666"
-scanner=" root system 666"
-
-#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#---#
-
-procfs=/proc
-
-opt_v=
-opt_d=
-opt_n=
-
-while [ $# -ge 1 ]
-do
- case $1 in
- --) shift; break ;;
- -v) shift; opt_v=1 ;;
- -d) shift; opt_d=1 ;;
- -n) shift; opt_n=1; opt_v=1 ;;
- -V) shift; opt_V=1 ;;
- -*) echo "$0: unknown flag \"$1\"" >&2; exit 1 ;;
- *) break ;;
- esac
-done
-
-if [ "$opt_V" ]
-then
- echo "$RCSID"
- exit 0
-fi
-
-opts="${opt_n:+-n} ${opt_v:+-v} ${opt_d:+-d}"
-
-makedev () { # usage: makedev name [bcu] major minor owner group mode
- if [ "$opt_v" ]
- then if [ "$opt_d" ]
- then echo "delete $1"
- else echo "create $1 $2 $3 $4 $5:$6 $7"
- fi
- fi
- if [ ! "$opt_n" ]
- then if [ "$opt_d" ]
- then
- rm -f $1
- else
- mknod $1- $2 $3 $4 &&
- chown $5:$6 $1- &&
- chmod $7 $1- &&
- mv $1- $1
- fi
- fi
-}
-symlink () { # usage: symlink name target
- if [ "$opt_v" ]
- then if [ "$opt_d" ]
- then echo "delete $1"
- else echo "create $1 -> $2"
- fi
- fi
- [ ! "$opt_n" ] && rm -f $1 &&
- [ ! "$opt_d" ] && ln -s $2 $1
-}
-
-devices=
-if [ ! -f $procfs/devices ]
-then
- echo "$0: warning: can't read $procfs/devices" >&2
-else
- exec 3<$procfs/devices
- while read major device <&3
- do
- case "$major" in
- Character|Block|'')
- ;;
- *)
- eval "major_$device=$major"
- devices="$devices $device"
- ;;
- esac
- done
- exec 3<&-
-fi
-
-Major () {
- device=$2
- if [ "$opt_d" ]
- then
- echo -1 # don't care
- else
- eval echo \${major_$1:-\${device:?\"unknown major number for $1\"}}
- fi
-}
-
-cvt () {
- while [ $# -ne 0 ]
- do
- case "$1" in
- mem|tty|ttyp|cua|cub) ;;
- hd) echo hda hdb ;;
- xd) echo xda xdb ;;
- fd) echo fd0 fd1 ;;
- lp) echo lp0 lp1 lp2 ;;
- mt) echo ftape ;;
- loop) echo loop ;;
- ibcs2) echo ibcs2 ;;
- tpqic02) echo qic ;;
- sound) echo audio ;;
- logiscan) echo logiscan ;;
- ac4096) echo ac4096 ;;
- idecd) echo idecd ;;
- hw) echo helloworld ;;
- sbpcd | sbpcd[123]) echo $1 ;;
- Joystick) echo js ;;
- apm_bios) echo apm ;;
- dcf) echo dcf ;;
- pcmcia) ;; # taken care of by its own driver
- ttyC) echo cyclades ;;
- *) echo "$0: don't know what \"$1\" is" >&2 ;;
- esac
- shift
- done
-}
-
-for arg
-do
- case $arg in
- generic)
- $0 $opts std
- $0 $opts fd0 fd1
- $0 $opts hda hdb
- $0 $opts xda xdb
- $0 $opts sda sdb
- $0 $opts ptyp ptyq ptyr ptys
- $0 $opts console tty1 tty2 tty3 tty4 tty5 tty6 tty7 tty8
- $0 $opts ttyS0 ttyS1 ttyS2 ttyS3
- $0 $opts busmice
- $0 $opts lp0 lp1 lp2
- $0 $opts par0 par1 par2
- $0 $opts fd
- ;;
- local)
- $0.local $opts
- ;;
- std)
- makedev mem c 1 1 $kmem
- makedev kmem c 1 2 $kmem
- makedev null c 1 3 $public
- makedev port c 1 4 $kmem
- makedev zero c 1 5 $public
- symlink core $procfs/kcore
- makedev full c 1 7 $public
- makedev ram b 1 1 $disk
- makedev tty c 5 0 $tty
- ;;
- console|tty0)
- makedev $arg c 4 0 $cons
- ;;
- tty[1-9]|tty[1-5][0-9]|tty[6][0-3])
- line=`expr $arg : "tty\(.*\)"`
- makedev tty$line c 4 $line $tty
- ;;
- ttyS[0-9]|ttyS[1-5][0-9]|ttyS[6][0-3])
- line=`expr $arg : "ttyS\(.*\)"`
- minor=`expr 64 + $line`
- makedev ttyS$line c 4 $minor $tty
- makedev cua$line c 5 $minor $dialout
- ;;
- pty[p-s])
- # Currently limited to 64 master/slave pairs.
- bank=`expr $arg : "pty\(.\)"`
- base=`expr \( pqrs : ".*$bank" - 1 \) \* 16`
- for i in 0 1 2 3 4 5 6 7 8 9 a b c d e f
- do
- j=`expr 0123456789abcdef : ".*$i" - 1`
- makedev pty$bank$i c 4 `expr 128 + $base + $j` $tty
- makedev tty$bank$i c 4 `expr 192 + $base + $j` $tty
- done
- ;;
- cyclades)
- major1=`Major ttyC` || continue
- major2=`Major cub` || continue
- for i in 0 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 15
- do
- makedev ttyC$i c $major1 `expr 32 + $i` $tty
- makedev cub$i c $major2 `expr 32 + $i` $dialout
- done
- ;;
- par[0-2])
- major=`Major lp 6` || continue
- port=`expr $arg : "par\(.\)"`
- makedev $arg c $major $port $printer
- ;;
- lp[0-2])
- major=`Major lp 6` || continue
- port=`expr $arg : "lp\(.\)"`
- makedev $arg c $major $port $printer
- ;;
- busmice)
- major=`Major mouse 10` || continue
- makedev logibm c $major 0 $mouse
- makedev psaux c $major 1 $mouse
- makedev inportbm c $major 2 $mouse
- makedev atibm c $major 3 $mouse
- # makedev sejin c $major 4 $mouse
- ;;
- js)
- major=`Major Joystick` || continue
- makedev js0 c $major 0 $mouse
- makedev js1 c $major 1 $mouse
- ;;
- fd[0-4])
- major=`Major fd 2` || continue
- unit=`expr $arg : "fd\(.\)"`
- makedev fd${unit} b $major $unit $floppy
- makedev fd${unit}d360 b $major `expr $unit + 4` $floppy
- makedev fd${unit}h1200 b $major `expr $unit + 8` $floppy
- makedev fd${unit}D360 b $major `expr $unit + 12` $floppy
- symlink fd${unit}H360 fd${unit}D360
- makedev fd${unit}D720 b $major `expr $unit + 16` $floppy
- symlink fd${unit}H720 fd${unit}D720
- makedev fd${unit}h360 b $major `expr $unit + 20` $floppy
- makedev fd${unit}h720 b $major `expr $unit + 24` $floppy
- makedev fd${unit}H1440 b $major `expr $unit + 28` $floppy
- makedev fd${unit}E2880 b $major `expr $unit + 32` $floppy
- makedev fd${unit}CompaQ b $major `expr $unit + 36` $floppy
-
- makedev fd${unit}h1440 b $major `expr $unit + 40` $floppy
- makedev fd${unit}H1680 b $major `expr $unit + 44` $floppy
- makedev fd${unit}h410 b $major `expr $unit + 48` $floppy
- makedev fd${unit}H820 b $major `expr $unit + 52` $floppy
- makedev fd${unit}h1476 b $major `expr $unit + 56` $floppy
- makedev fd${unit}H1722 b $major `expr $unit + 60` $floppy
- makedev fd${unit}h420 b $major `expr $unit + 64` $floppy
- makedev fd${unit}H830 b $major `expr $unit + 68` $floppy
- makedev fd${unit}h1494 b $major `expr $unit + 72` $floppy
- makedev fd${unit}H1743 b $major `expr $unit + 76` $floppy
- ;;
- hd[a-d])
- major=`Major hd 3` || continue
- unit=`expr $arg : "hd\(.\)"`
- base=`expr \( abcd : ".*$unit" - 1 \) \* 64`
- makedev hd$unit b $major $base $disk
- for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16
- do
- makedev hd$unit$part b $major `expr $base + $part` $disk
- done
- ;;
- hd1[a-d])
- unit=`expr $arg : "hd1\(.\)"`
- base=`expr \( abcd : ".*$unit" - 1 \) \* 64`
- makedev hd1$unit b 22 $base $disk
- for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16
- do
- makedev hd1$unit$part b 22 `expr $base + $part` $disk
- done
- ;;
- xd[a-d])
- major=`Major xd 13` || continue
- unit=`expr $arg : "xd\(.\)"`
- base=`expr \( abcd : ".*$unit" - 1 \) \* 64`
- makedev xd$unit b $major $base $disk
- for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15 16
- do
- makedev xd$unit$part b $major `expr $base + $part` $disk
- done
- ;;
- sd[a-h])
- major=`Major sd 8` || continue
- unit=`expr $arg : "sd\(.\)"`
- base=`expr \( abcdefgh : ".*$unit" - 1 \) \* 16`
- makedev sd$unit b $major $base $disk
- for part in 1 2 3 4 5 6 7 8 # 9 10 11 12 13 14 15
- do
- minor=`expr $base + $part`
- makedev sd$unit$part b $major $minor $disk
- done
- ;;
- loop)
- major=`Major loop` || continue
- for part in 0 1 2 3 4 5 6 7
- do
- makedev loop$part b $major $part $disk
- done
- ;;
- st[0-7])
- major=`Major st 9`
- unit=`expr $arg : "st\(.\)"`
- makedev st$unit c $major $unit $tape
- makedev nst$unit c $major `expr 128 + $unit` $tape
- ;;
- qic)
- major=`Major tpqic02 12`
- makedev rmt8 c $major 6 $tape
- makedev rmt16 c $major 8 $tape
- makedev tape-d c $major 136 $tape
- makedev tape-reset c $major 255 $tape
- ;;
- ftape)
- major=`Major mt 27` || continue
- for unit in 0 1 2 3
- do
- makedev rft$unit c $major $unit $tape
- makedev nrft$unit c $major `expr $unit + 4` $tape
- done
- symlink ftape rft0
- symlink nftape nrft0
- ;;
- scd[0-7])
- major=`Major sr 11` || continue
- unit=`expr $arg : "scd\(.\)"`
- makedev scd$unit b $major $unit $cdrom
- ;;
- sonycd)
- major=`Major cdu31a` || continue
- makedev $arg b $major 0 $cdrom
- ;;
- mcd)
- major=`Major mcd 23` || continue
- makedev $arg b $major 0 $cdrom
- ;;
- cdu535)
- makedev $arg b 24 0 $cdrom
- ;;
- lmscd)
- makedev $arg b 24 0 $cdrom
- ;;
- sbpcd|sbpcd[123])
- major=`Major $arg` || continue
- base=`expr ${arg}0 : "sbpcd\(.\)"`
- for minor in 0 1 2 3
- do
- unit=`expr substr 0123456789abcdef \( $base \* 4 + $minor + 1 \) 1`
- makedev spbcd$unit b $major $minor $cdrom
- done
- [ $arg = sbpcd ] && symlink $arg ${arg}0
- ;;
- idecd)
- major=`Major idecd` || continue
- makedev $arg c $major 0 $cdrom
- ;;
- logiscan)
- major=`Major logiscan` || continue
- makedev $arg c $major 0 $scanner
- ;;
- m105scan)
- major=`Major m105` || continue
- makedev $arg c $major 0 $scanner
- ;;
- ac4096)
- major=`Major ac4096` || continue
- makedev $arg c $major 0 $scanner
- ;;
- audio)
- major=`Major sound 14`
- makedev mixer c $major 0 $audio
- makedev sequencer c $major 1 $audio
- makedev midi00 c $major 2 $audio
- makedev dsp c $major 3 $audio
- makedev audio c $major 4 $audio
- makedev sndstat c $major 6 $audio
-# makedev sequencer2 c $major 8 $audio
- makedev mixer1 c $major 16 $audio
-# makedev patmgr0 c $major 17 $audio
- makedev midi01 c $major 18 $audio
- makedev dsp1 c $major 19 $audio
- makedev audio1 c $major 20 $audio
-# makedev patmgr1 c $major 33 $audio
- makedev midi02 c $major 34 $audio
- makedev midi03 c $major 50 $audio
- ;;
- pcaudio)
- major=`Major pcsp` || continue
- makedev pcmixer c $major 0 $audio
- makedev pcsp c $major 3 $audio
- makedev pcaudio c $major 4 $audio
- ;;
- sg)
- major=`Major sg 21`
- for unit in a b c d e f g h
- do
- minor=`expr abcdefgh : ".*$unit" - 1`
- makedev $arg$unit c $major $minor $scsi
- done
- ;;
- fd)
- # not really devices, we use the /proc filesystem
- symlink fd $procfs/self/fd
- symlink stdin fd/0
- symlink stdout fd/1
- symlink stderr fd/2
- ;;
- ibcs2)
- major=`Major ibcs2` || continue
- makedev socksys c $major 0 $ibcs2
- symlink nfsd socksys
- makedev spx c $major 1 $ibcs2
- symlink X0R null
- ;;
- apm)
- major=`Major apm_bios` || continue
- makedev $arg c $major 0 $system
- ;;
- dcf)
- major=`Major dcf` || continue
- makedev $arg c $major 0 $system
- ;;
- helloworld)
- major=`Major hw` || continue
- makedev helloworld c $major 0 $public
- ;;
- update)
- if [ ! "$devices" ]
- then
- echo "$0: don't appear to have any devices" >&2
- continue
- fi
- if [ "$opt_d" ]
- then
- echo "$0: can't delete an update" >&2
- continue
- fi
- create=
- delete=
- devs="$devices"
- if [ -f DEVICES ]
- then
- exec 3<DEVICES
- while read device major <&3
- do
- eval now=\$major_$device
- if [ "$now" = "" ]
- then
- delete="$delete `cvt $device`"
- continue
- elif [ "$now" != $major ]
- then
- create="$create "`cvt $device`
- fi
- devs=`expr "$devs" : "\(.*\) $device"``expr "$devs" : ".* $device\(.*\)"`
- done
- exec 3<&-
- fi
- create="$create "`cvt $devs`
- $0 $opts -d $delete
- $0 $opts $create
- [ "$opt_n" ] && continue
- for device in $devices
- do
- if [ "`cvt $device`" ]
- then
- eval echo $device \$major_$device
- fi
- done > DEVICES
- ;;
- *)
- echo "$0: don't know how to make device \"$arg\"" >&2
- ;;
- esac
-done
-
-exit 0
+++ /dev/null
-.\" MAKEDEV.8,v 1.1.1.1 1995/02/22 19:09:12 faith Exp
-.TH MAKEDEV 8 "14th August 1994" Linux "Linux Programmer's Manual"
-.SH NAME
-MAKEDEV \- create devices
-.SH SYNOPSIS
-.B "cd dev; ./MAKEDEV [ -n ] [ -v ] update"
-.br
-.BI "cd dev; ./MAKEDEV [ -n ] [ -v ]" "device"
-.SH DESCRIPTION
-.B MAKEDEV
-is a script that will create the devices in \fC/dev\fP used to interface
-with drivers in the kernel.
-.PP
-Note that programs giving the error \(*QENOENT: No such file or
-directory\(*U normally means that the device file is missing, whereas
-\(*QENODEV: No such device\(*U normally means the kernel does not have the
-driver configured or loaded.
-.SH OPTIONS
-.TP
-.B \-V
-Print out version (actually RCS version information) and exit.
-.TP
-.B \-n
-Do not actually update the devices, just print the actions that would be
-performed.
-.TP
-.B \-d
-Delete the devices. The main use for this flag is by
-.I MAKEDEV
-itself.
-.TP
-.B \-v
-Be verbose. Print out the actions as they are performed. This is the
-same output as produced by
-.BR \-n .
-.SH CUSTOMISATION
-Since there is no standardisation in what names are used for system users
-and groups, it is possible that you may need to modify
-.B MAKEDEV
-to reflect your site's settings. Near the top of the file is a mapping
-from device type to user, group and permissions (e.g. all CD-ROM devices
-are set from the \fC$cdrom\fP variable). If you wish to change the
-defaults, this is the section to edit.
-.SH DEVICES
-.TP
-.B General Options
-.TP
-.B update
-This only works on kernels which have \fC/proc/interrupts\fP (introduced
-during 1.1.x). This file is scanned to see what devices are currently
-configured into the kernel, and this is compared with the previous
-settings stored in the file called \fCDEVICES\fP.
-Devices which are new since then or have a different major number are
-created, and those which are no longer configured are deleted.
-.TP
-.B generic
-Create a generic subset of devices.
-.TP
-.B
-std
-Standard devices.
-.TP
-.B local
-.TP
-.B Virtual Terminals
-.TP
-.B console
-Also known as tty0.
-.TP
-.B tty{0..63}
-Virtual consoles
-.TP
-.B Serial Devices
-.TP
-.I ttyS{0..63}
-serial ports and corresponding dialout device
-.TP
-.I cyclades
-Dial-in and dial-out devices for the cyclades intelligent I/O serial card.
-.TP
-.B Pseudo Terminals
-.TP
-.I pty[p-s]
-banks of of master and slave pseudo terminals
-.TP
-.B Parallel Ports
-.TP
-.I par[0-3] lp[0-3]
-parallel ports
-.TP
-.B Bus Mice
-.TP
-.I busmice
-The various bus mice devices.
-.TP
-.B Joystick Devices
-.TP
-.I js
-Joystick. Creates \fCjs0\fP and \fCjs1\fP.
-.TP
-.B Disks Devices
-.TP
-.I fd[0-4]
-floppy disks
-.TP
-.I hd[a-d]
-AT hard disks (1st controller)
-.TP
-.I hd1[a-d]
-2nd AT controller hard disks
-.TP
-.I xd[a-d]
-XT hard disks
-.TP
-.I sd[a-i]
-SCSI hard disks
-.TP
-.I loop
-Loopback disk devices
-.TP
-.B Tape Devices
-.TP
-.I st[0-7]
-SCSI tapes
-.TP
-.I qic
-QIC-80 tapes
-.TP
-.I ftape
-floppy driver tapes (QIC-117)
-.TP
-.B CDROM Devices
-.TP
-.I scd[0-7]
-SCSI CD players
-.TP
-.I sonycd
-Sony CDU-31A CD player
-.TP
-.I mcd
-Mitsumi CD player
-.TP
-.I cdu535
-Sony CDU-535 CD player
-.TP
-.I lmscd
-LMS/Philips CD player (nee
\ No newline at end of file
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Sat Feb 11 17:52:09 1995 by faith@cs.unc.edu
+# Revised: Sat Oct 7 19:24:39 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
MAN1= arch.1 readprofile.1
-MAN8= MAKEDEV.8 chroot.8 clock.8 ctrlaltdel.8 dmesg.8 ipcrm.8 \
- ipcs.8 kbdrate.8 lpcntl.8 ramsize.8 rdev.8 renice.8 \
+MAN8= chroot.8 clock.8 ctrlaltdel.8 cytune.8 dmesg.8 \
+ ipcrm.8 ipcs.8 kbdrate.8 ramsize.8 rdev.8 renice.8 \
rootflags.8 setserial.8 setsid.8 swapdev.8 sync.8 tunelp.8 \
- update_state.8 vidmode.8
+ vidmode.8
# Where to put binaries?
# See the "install" rule for the links. . .
-DEV= MAKEDEV
-
-SBIN= clock kbdrate sln
+SBIN= clock ctrlaltdel kbdrate sln
BIN= arch dmesg setserial sync
-USRSBIN= chroot ctrlaltdel update_state
+USRSBIN= chroot
-USRBIN= ipcrm ipcs lpcntl rdev renice readprofile setsid tunelp
+USRBIN= cytune ipcrm ipcs rdev renice readprofile setsid tunelp
# Where to put datebase files?
USRINFO= ipc.info
-SCRIPTS= reset update_state
-
all: $(SBIN) $(BIN) $(USRSBIN) $(USRBIN)
sln: sln.c
$(CC) -static $(CFLAGS) $(LDFLAGS) $< -o $@
sync: sync.S
- /lib/cpp sync.S > sync.s
- as -o sync.o sync.s
- ld -s -N -e _main sync.o -o sync
- -rm sync.s
-
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
-$(SCRIPTS):
- cp $@.sh $@
+ $(CC) -nostdlib $(LDFLAGS) $< -o $@
# Rules for everything else
ipcrm: ipcrm.o
ipcs: ipcs.o
kbdrate: kbdrate.o
-lpcntl: lpcntl.o
rdev: rdev.o
renice: renice.o
readprofile: readprofile.o
setserial: setserial.o
setsid: setsid.o
-update_state: update_state.sh
install: all
- $(INSTALLDIR) $(DEVDIR) $(SBINDIR) $(BINDIR) $(USRSBINDIR) $(USRBINDIR)
- $(INSTALLBIN) $(DEV) $(DEVDIR)
+ $(INSTALLDIR) $(SBINDIR) $(BINDIR) $(USRSBINDIR) $(USRBINDIR)
$(INSTALLBIN) $(SBIN) $(SBINDIR)
$(INSTALLBIN) $(BIN) $(BINDIR)
$(INSTALLBIN) $(USRSBIN) $(USRSBINDIR)
$(INSTALLBIN) $(USRBIN) $(USRBINDIR)
- (cd $(RDEVDIR); ln -sf rdev swapdev)
- (cd $(RDEVDIR); ln -sf rdev ramsize)
- (cd $(RDEVDIR); ln -sf rdev vidmode)
- (cd $(RDEVDIR); ln -sf rdev rootflags)
+ (cd $(USRBINDIR); ln -sf rdev swapdev)
+ (cd $(USRBINDIR); ln -sf rdev ramsize)
+ (cd $(USRBINDIR); ln -sf rdev vidmode)
+ (cd $(USRBINDIR); ln -sf rdev rootflags)
$(INSTALLDIR) $(MAN1DIR) $(MAN8DIR) $(INFODIR)
$(INSTALLMAN) $(MAN1) $(MAN1DIR)
$(INSTALLMAN) $(MAN8) $(MAN8DIR)
-README.MAKEDEV,v 1.1.1.1 1995/02/22 19:09:12 faith Exp
+$Id: README.MAKEDEV,v 2.2 1995/06/04 16:32:02 faith Exp $
Here is the original comment taken from the MAKEDEV script. One day,
I'll do this properly.
Also, if you are a developer who wants your devices supported by MAKEDEV,
let me know.
-Thanks to Ian Jackson for the original help and encouragement.
+Thanks go to many people. Ian Jackson for the original help and
+encouragement, to Matthias Urlichs for plugging "MAKEDEV update", and
+to the many others that have bought errors and omissions to my attention.
Nick Holloway <Nick.Holloway@alfie.demon.co.uk>
.SH NAME
clock \- manipulate the CMOS clock
.SH SYNOPSIS
-.B "/etc/clock [ -u ] -r"
+.B "/sbin/clock [ -u ] -r"
.br
-.B "/etc/clock [ -u ] -w"
+.B "/sbin/clock [ -u ] -w"
.br
-.B "/etc/clock [ -u ] -s"
+.B "/sbin/clock [ -u ] -s"
.br
-.B "/etc/clock [ -u ] -a"
+.B "/sbin/clock [ -u ] -a"
.SH DESCRIPTION
.B clock
manipulates the CMOS clock in variaous ways, allowing it to be read or
.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
.\" May be distributed under the GNU General Public License
-.TH CTRLALTDEL 8 "25 October 1993" "Linux 0.99" "Linux Programmer's Manual"
+.TH CTRLALTDEL 8 "25 October 1993" "Linux 1.2" "Linux Programmer's Manual"
.SH NAME
ctrlaltdel \- set the function of the Ctrl-Alt-Del combination
.SH SYNOPSIS
-.B "ctrlaltdel hard|soft"
+.BR "ctrlaltdel hard" " | " soft
.SH DESCRIPTION
Based on examination of the
.I linux/kernel/sys.c
--- /dev/null
+.\" cytune.8 --
+.\" Created: Sat Mar 4 17:44:53 1995 by faith@cs.unc.edu
+.\" Update: Sat Mar 4 18:22:24 1995 by faith@cs.unc.edu
+.\" Update: Sun Mar 5 06:40:12 1995 by njs@scifi.emi.net
+.\" Copyright 1995 Rickard E. Faith (faith@cs.unc.edu)
+.\"
+.\" Permission is granted to make and distribute verbatim copies of this
+.\" manual provided the copyright notice and this permission notice are
+.\" preserved on all copies.
+.\"
+.\" Permission is granted to copy and distribute modified versions of this
+.\" manual under the conditions for verbatim copying, provided that the
+.\" entire resulting derived work is distributed under the terms of a
+.\" permission notice identical to this one
+.\"
+.\" Since the Linux kernel and libraries are constantly changing, this
+.\" manual page may be incorrect or out-of-date. The author(s) assume no
+.\" responsibility for errors or omissions, or for damages resulting from
+.\" the use of the information contained herein. The author(s) may not
+.\" have taken the same level of care in the production of this manual,
+.\" which is licensed free of charge, as they might when working
+.\" professionally.
+.\"
+.\" Formatted or processed versions of this manual, if unaccompanied by
+.\" the source, must acknowledge the copyright and authors of this work.
+.\" "
+.TH CYTUNE 8 " 4 Mar 1995" "" "Linux Programmer's Manual"
+.SH NAME
+cytune \- Tune Cyclades driver parameters
+.SH SYNOPSIS
+.BI "cytune [-q [-i " interval "]] ([-s " value "]|[-S " value "]) [-g|G] "
+.BI ([-t " timeout" ]|[-T " timeout" ]) " tty" " [" tty " ...]"
+.SH DESCRIPTION
+.B cytune
+queries and modifies the interruption threshold for the Cyclades driver.
+Each serial line on a Cyclades card has a 12-byte FIFO for input (and
+another 12-byte FIFO for output). The "threshold" specifies how many input
+characters must be present in the FIFO before an interruption is raised.
+When a Cyclades tty is opened, this threshold is set to a default value
+based on baud rate:
+.sp
+.RS
+ Baud Threshold
+.sp
+50-4800 10
+.br
+9600 8
+.br
+19200 4
+.br
+38400 2
+.br
+57600-150000 1
+.RE
+.PP
+If the threshold is set too low, the large number of interruptions can load
+the machine and decrease overall system throughput. If the threshold is set too high, the
+FIFO buffer can overflow, and characters will be lost. Slower machines,
+however, may not be able to deal with the interrupt load, and will require
+that the threshold be adjusted upwards.
+.PP
+If the cyclades driver was compiled with
+.B ENABLE_MONITORING
+defined, the cytune command can be used with the
+.B \-q
+option to report interrupts over the monitoring interval and
+characters transferred over the monitoring interval. It will also report
+the state of the FIFO. The maximum number of characters in the FIFO when
+an interrupt occurred, the instantaneous count of characters in the FIFO,
+and how many characters are now in the FIFO are reported. This output might
+look like this:
+.sp
+.RS
+/dev/cubC0: 830 ints, 9130 chars; fifo: 11 threshold, 11 max, 11 now
+.br
+ 166.259866 interrupts/second, 1828.858521 characters/second
+.RE
+.PP
+This output indicates that for this monitoring period, the interrupts were
+always being handled within one character time, because
+.B max
+never rose above
+.BR threshold .
+This is good, and you can probably run this way, provided that a large
+number of samples come out this way. You will lose characters if you
+overrun the FIFO, as the Cyclades hardware does not seem to support
+the RTS RS-232 signal line for hardware flow control from the
+DCE to the DTE.
+.pp
+cytune will in query mode will produce a summary report when ended with
+a SIGINT or when the threshold or timeout is changed.
+.PP
+There may be a responsiveness vs. throughput tradeoff. The Cyclades card,
+at the higher speeds, is capable of putting a very high interrupt load on the
+system. This will reduce the amount of CPU time available for other tasks
+on your system. However, the time it takes to respond to a single character
+may be increased if you increase the threshold. This might be noticed by
+monitoring
+.BR ping (8)
+times on a SLIP link controlled by a Cyclades card. If your SLIP link is
+generally used for interactive work such as
+.BR telnet (1),
+you may want to leave the threshold low, so that characters are responded
+to as quickly as possible. If your SLIP link is generally used for file
+transfer, WWW, and the like, setting the FIFO to a high value is likely to
+reduce the load on your system while not significantly affecting
+throughput. Alternatively, see the
+.B \-t
+or
+.B \-T
+options to adjust the time that the cyclades waits before flushing its
+buffer. Units are 5ms.
+.PP
+If you are running a mouse on a Cyclades port, it is likely that you would
+want to maintain the threshold and timeout at a low value.
+.PP
+.SH OPTIONS
+.TP
+.BI \-s " value"
+Set the current threshold to
+.I value
+characters. Note that if the
+.I tty
+is not being held open by another process, the threshold will be reset on
+the next open. Only values between 1 and 12, inclusive, are permitted.
+.TP
+.BI \-t " value"
+Set the current flush timeout to
+.I value
+units. Note that if the
+.I tty
+is not being held open by another process, the threshold will be reset on
+the next open. Only values between 0 and 255, inclusive, are permitted.
+Setting
+.I value
+to zero forces the default, currently 0x20 (160ms), but soon to be 0x02
+(10ms). Units are 5 ms.
+.TP
+.B \-g
+Get the current threshold and timeout.
+.TP
+.BI \-T " value"
+Set the default flush timeout to
+.I value
+units. When the
+.I tty
+is next opened, this value will be used instead of the default. If
+.I value
+is zero, then the the value will default to 0x20 (160ms), soon to be 0x02
+(10ms).
+.TP
+.B \-G
+Get the default threshold and flush timeout values.
+.TP
+.B \-q
+Gather statistics about the
+.IR tty .
+The results are only valid if the Cyclades driver has been compiled with
+.B ENABLE_MONITORING
+defined. This is probably not the default.
+.TP
+.BI \-i " interval"
+Statistics will be gathered every
+.I interval
+seconds.
+.SH BUGS
+If you run two copies of cytune at the same time to report statistics
+about the same port, the 'ints', 'chars', and 'max' value will be reset
+and not reported
+correctly.
+.BR cytune (8)
+should prevent this, but does not.
+.SH AUTHOR
+Nick Simicich (njs@scifi.emi.net), with modifications by Rik Faith
+(faith@cs.unc.edu)
+.SH FILES
+.I /dev/ttyC[0-8]
+.br
+.I /dev/cubC[0-8]
+.SH "SEE ALSO"
+.BR setserial (8)
--- /dev/null
+/* cytune.c -- Tune Cyclades driver
+ *
+ * Copyright 1995 Nick Simicich (njs@scifi.emi.net)
+ *
+ * Modifications by Rik Faith (faith@cs.unc.edu)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Nick Simicich
+ * 4. Neither the name of the Nick Simicich 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 NICK SIMICICH AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NICK SIMICICH OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 <stdio.h>
+#include <stdlib.h>
+#include <sys/serial.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/tty.h>
+#include <termios.h>
+#include <linux/tqueue.h>
+#include <linux/cyclades.h>
+#include <signal.h>
+
+#if 0
+#ifndef XMIT
+# include <linux/version.h>
+# if LINUX_VERSION_CODE > 66056
+# define XMIT
+# endif
+#endif
+#endif
+ /* Until it gets put in the kernel,
+ toggle by hand. */
+#undef XMIT
+
+struct cyclades_control {
+ struct cyclades_monitor c;
+ int cfile;
+ int maxmax;
+ double maxtran;
+ double maxxmit;
+ unsigned long threshold_value;
+ unsigned long timeout_value;
+};
+struct cyclades_control *cmon;
+int cmon_index;
+
+#define mvtime(tvpto, tvpfrom) (((tvpto)->tv_sec = (tvpfrom)->tv_sec),(tvpto)->tv_usec = (tvpfrom)->tv_usec)
+
+
+inline double dtime(struct timeval * tvpnew, struct timeval * tvpold) {
+ double diff;
+ diff = (double)tvpnew->tv_sec - (double)tvpold->tv_sec;
+ diff += ((double)tvpnew->tv_usec - (double)tvpold->tv_usec)/1000000;
+ return diff;
+}
+
+static int global_argc, global_optind;
+static char ***global_argv;
+
+void summary(int signal) {
+ struct cyclades_control *cc;
+
+ int argc, optind;
+ char **argv;
+
+ int i,j;
+
+ argc = global_argc;
+ argv = *global_argv;
+ optind = global_optind;
+
+ if (signal > 0) {
+ for(i = optind; i < argc; i ++) {
+ j = i - optind;
+ cc = &cmon[cmon_index];
+ fprintf(stderr, "File %s, For threshold value %lu, Maximum characters "
+ "in fifo were %d,\nand the maximum transfer rate in "
+ "characters/second was %f\n",
+ argv[i],
+ cc->threshold_value,
+ cc->maxmax,
+ cc->maxtran);
+ }
+
+ exit(0);
+ }
+ cc = &cmon[cmon_index];
+ if (cc->threshold_value > 0 && signal != -1) {
+ fprintf(stderr, "File %s, For threshold value %lu and timrout value %lu,"
+ " Maximum characters "
+ "in fifo were %d,\nand the maximum transfer rate in "
+ "characters/second was %f\n",
+ argv[cmon_index+optind],
+ cc->threshold_value,
+ cc->timeout_value,
+ cc->maxmax,
+ cc->maxtran);
+ }
+ cc->maxmax = 0;
+ cc->maxtran = 0.0;
+ cc->threshold_value = 0;
+ cc->timeout_value = 0;
+}
+
+static int query = 0;
+static int interval = 1;
+
+static int set = 0;
+static int set_val = -1;
+static int get = 0;
+
+static int set_def = 0;
+static int set_def_val = -1;
+static int get_def = 0;
+
+static int set_time = 0;
+static int set_time_val = -1;
+
+static int set_def_time = 0;
+static int set_def_time_val = -1;
+
+
+int main(int argc, char *argv[]) {
+
+ struct timeval lasttime, thistime;
+ struct timezone tz = {0,DST_NONE};
+ double diff;
+ int errflg = 0;
+ int file;
+ int numfiles;
+ struct cyclades_monitor cywork;
+
+ int i;
+ extern char *optarg;
+ extern int optind;
+ unsigned long threshold_value;
+ unsigned long timeout_value;
+ double xfer_rate;
+#ifdef XMIT
+ double xmit_rate;
+#endif
+
+ global_argc = argc; /* For signal routine. */
+ global_argv = &argv; /* For signal routine. */
+
+ while (EOF != (i = getopt(argc, argv,
+ "qs:S:t:T:gGi:"))) {
+ switch (i) {
+ case 'q':
+ query = 1;
+ break;
+ case 'i':
+ interval = atoi(optarg);
+ if(interval <= 0) {
+ fprintf(stderr, "Invalid interval value: %s\n",optarg);
+ errflg ++;
+ }
+ break;
+ case 's':
+ ++set;
+ set_val = atoi(optarg);
+ if(set_val <= 0 || set_val > 12) {
+ fprintf(stderr, "Invalid set value: %s\n",optarg);
+ errflg ++;
+ }
+ break;
+ case 'S':
+ ++set_def;
+ set_def_val = atoi(optarg);
+ if(set_def_val < 0 || set_def_val > 12) {
+ fprintf(stderr, "Invalid default value: %s\n",optarg);
+ errflg ++;
+ }
+ break;
+ case 't':
+ ++set_time;
+ set_time_val = atoi(optarg);
+ if(set_time_val <= 0 || set_time_val > 255) {
+ fprintf(stderr, "Invalid set time value: %s\n",optarg);
+ errflg ++;
+ }
+ break;
+ case 'T':
+ ++set_def_time;
+ set_def_time_val = atoi(optarg);
+ if(set_def_time_val < 0 || set_def_time_val > 255) {
+ fprintf(stderr, "Invalid default time value: %s\n",optarg);
+ errflg ++;
+ }
+ break;
+ case 'g': ++get; break;
+ case 'G': ++get_def; break;
+ default:
+ errflg ++;
+ }
+ }
+ numfiles = argc - optind;
+ if(errflg || (numfiles == 0)
+ || (!query && !set && !set_def &&
+ !get && !get_def && !set_time && !set_def_time) ||
+ (set && set_def) || (set_time && set_def_time) ||
+ (get && get_def)) {
+ fprintf(stderr,
+ "Usage: %s [-q [-i interval]]"
+ " ([-s value]|[-S value]) ([-t value]|[-T value])"
+ " [-g|-G] file [file...]\n",
+ argv[0]);
+ exit(1);
+ }
+
+ global_optind = optind; /* For signal routine. */
+
+ if (set || set_def) {
+ for(i = optind;i < argc;i ++) {
+ file = open(argv[i],O_RDONLY);
+ if(file == -1) {
+ fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(file,
+ set ? CYSETTHRESH : CYSETDEFTHRESH,
+ set ? set_val : set_def_val)) {
+ fprintf(stderr, "Can't set %s to threshold %d: %s\n",
+ argv[i],set?set_val:set_def_val,strerror(errno));
+ exit(1);
+ }
+ }
+ }
+ if (set_time || set_def_time) {
+ for(i = optind;i < argc;i ++) {
+ file = open(argv[i],O_RDONLY);
+ if(file == -1) {
+ fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(file,
+ set_time ? CYSETTIMEOUT : CYSETDEFTIMEOUT,
+ set_time ? set_time_val : set_def_time_val)) {
+ fprintf(stderr, "Can't set %s to time threshold %d: %s\n",
+ argv[i],set_time?set_time_val:set_def_time_val,strerror(errno));
+ exit(1);
+ }
+ }
+ }
+
+ if (get || get_def) {
+ for(i = optind;i < argc;i ++) {
+ file = open(argv[i],O_RDONLY);
+ if(file == -1) {
+ fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(file, get ? CYGETTHRESH : CYGETDEFTHRESH, &threshold_value)) {
+ fprintf(stderr, "Can't get threshold for %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(file, get ? CYGETTIMEOUT : CYGETDEFTIMEOUT, &timeout_value)) {
+ fprintf(stderr, "Can't get timeout for %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ printf("%s: %ld %s threshold and %ld %s timeout\n",
+ argv[i], threshold_value,
+ get?"current":"default",
+ timeout_value,
+ get?"current":"default");
+ }
+ }
+
+ if(!query) return 0; /* must have been something earlier */
+
+ /* query stuff after this line */
+
+ cmon = (struct cyclades_control *) malloc(sizeof (struct cyclades_control)
+ * numfiles);
+ if(!cmon) {
+ perror("malloc failed");
+ exit(1);
+ }
+ if(signal(SIGINT, summary)||
+ signal(SIGQUIT, summary)||
+ signal(SIGTERM, summary)) {
+ perror("Can't set signal handler");
+ exit(1);
+ }
+ if(gettimeofday(&lasttime,&tz)) {
+ perror("gettimeofday failed");
+ exit(1);
+ }
+ for(i = optind; i < argc; i ++) {
+ cmon_index = i - optind;
+ cmon[cmon_index].cfile = open(argv[i], O_RDONLY);
+ if(-1 == cmon[cmon_index].cfile) {
+ fprintf(stderr, "Can't open %s: %s\n",argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cmon[cmon_index].c)) {
+ fprintf(stderr, "Can't issue CYGETMON on %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ summary(-1);
+ if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) {
+ fprintf(stderr, "Can't get threshold for %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) {
+ fprintf(stderr, "Can't get timeout for %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ }
+ while(1) {
+ sleep(interval);
+
+ if(gettimeofday(&thistime,&tz)) {
+ perror("gettimeofday failed");
+ exit(1);
+ }
+ diff = dtime(&thistime, &lasttime);
+ mvtime(&lasttime, &thistime);
+
+ for(i = optind; i < argc; i ++) {
+ cmon_index = i - optind;
+ if(ioctl(cmon[cmon_index].cfile, CYGETMON, &cywork)) {
+ fprintf(stderr, "Can't issue CYGETMON on %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(cmon[cmon_index].cfile, CYGETTHRESH, &threshold_value)) {
+ fprintf(stderr, "Can't get threshold for %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+ if(ioctl(cmon[cmon_index].cfile, CYGETTIMEOUT, &timeout_value)) {
+ fprintf(stderr, "Can't get timeout for %s: %s\n",
+ argv[i],strerror(errno));
+ exit(1);
+ }
+
+ xfer_rate = cywork.char_count/diff;
+#ifdef XMIT
+ xmit_rate = cywork.send_count/diff;
+#endif
+
+ if(threshold_value != cmon[cmon_index].threshold_value ||
+ timeout_value != cmon[cmon_index].timeout_value) {
+ summary(-2);
+ /* Note that the summary must come before the setting of */
+ /* threshold_value */
+ cmon[cmon_index].threshold_value = threshold_value;
+ cmon[cmon_index].timeout_value = timeout_value;
+ } else {
+ /* Don't record this first cycle after change */
+ if(xfer_rate > cmon[cmon_index].maxtran)
+ cmon[cmon_index].maxtran = xfer_rate;
+#ifdef XMIT
+ if(xmit_rate > cmon[cmon_index].maxxmit)
+ cmon[cmon_index].maxxmit = xmit_rate;
+#endif
+ if(cywork.char_max > cmon[cmon_index].maxmax)
+ cmon[cmon_index].maxmax = cywork.char_max;
+ }
+
+#ifdef XMIT
+ printf("%s: %lu ints, %lu/%lu chars; "
+ "fifo: %lu thresh, %lu tmout, "
+ "%lu max, %lu now\n",
+ argv[i],
+ cywork.int_count,cywork.char_count,cywork.send_count,
+ threshold_value,timeout_value,
+ cywork.char_max,cywork.char_last);
+ printf(" %f int/sec; %f rec, %f send (char/sec)\n",
+ cywork.int_count/diff,
+ xfer_rate,
+ xmit_rate);
+#else
+ printf("%s: %lu ints, %lu chars; "
+ "fifo: %lu thresh, %lu tmout, "
+ "%lu max, %lu now\n",
+ argv[i],
+ cywork.int_count,cywork.char_count,
+ threshold_value,timeout_value,
+ cywork.char_max,cywork.char_last);
+ printf(" %f int/sec; %f rec (char/sec)\n",
+ cywork.int_count/diff,
+ xfer_rate);
+#endif
+ memcpy(&cmon[cmon_index].c, &cywork, sizeof (struct cyclades_monitor));
+ }
+ }
+
+ return 0;
+}
#include <pwd.h>
#include <grp.h>
#define __KERNEL__
+#include <linux/linkage.h>
#include <sys/sem.h>
#include <sys/msg.h>
#include <sys/shm.h>
/* File:
* sync.S
* Compile:
- * /lib/cpp sync.S > sync.s
- * as -o sync.o sync.s
- * ld -s -N -e _main sync.o -o sync
+ * gcc -nostdlib sync.S -o sync
* Author:
* Nick Holloway, with thanks to James Bonfield
+ * Modified for ELF by Michael Shields
+ * Rik Faith added __ASSEMBLY__ for gcc 2.5.8
* Last Changed:
- * September 1993.
+ * 1995-07-04
*/
-# include <sys/syscall.h>
+#include <sys/syscall.h>
+#ifndef __ASSEMBLY__
+#define __ASSEMBLY__
+#endif
+#include <linux/linkage.h>
.text
- .globl _main
-_main:
+ENTRY(_start)
movl $(SYS_sync),%eax /* sync () */
int $0x80
movl $(SYS_exit),%eax /* exit ( 0 ) */
.\" It may be distributed under the GNU Public License, version 2, or
.\" any higher version. See section COPYING of the GNU Public license
.\" for conditions under which this file may be redistributed.
-.\" tunelp.8,v 1.1.1.1 1995/02/22 19:09:12 faith Exp
+.\" $Id: tunelp.8,v 1.5 1995/03/12 01:34:24 faith Exp $
.TH tunelp 8 "26 August 1992" "Cohesive Systems" "Linux Programmer's Manual"
.SH NAME
tunelp \- set various parameters for the lp device
* for information on distribution conditions. *
\****************************************************************************/
-/* tunelp.c,v 1.1.1.1 1995/02/22 19:09:12 faith Exp
- * tunelp.c,v
- * Revision 1.1.1.1 1995/02/22 19:09:12 faith
- * Imported sources
+/* $Id: tunelp.c,v 1.6 1995/06/04 01:47:11 faith Exp $
+ * $Log: tunelp.c,v $
+ * Revision 1.6 1995/06/04 01:47:11 faith
+ * Changes for util-linux-2.4
+ *
+ * Revision 1.5 1995/03/12 01:29:50 faith
+ * util-linux-2.1
*
* Revision 1.5 1995/01/13 10:33:43 johnsonm
* Chris's changes for new ioctl numbers and backwards compatibility
}
/* Allow for binaries compiled under a new kernel to work on the old ones */
- if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ) < 0 && errno == EINVAL)
+ if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0 && errno == EINVAL)
offset = 0x0600; /* We don't understand the new ioctls */
cmds = cmdst;
+++ /dev/null
-.\" Copyright 1994 Rickard E. Faith (faith@cs.unc.edu)
-.\" May be distributed under the GNU General Public License
-.\" "
-.TH update_state 8 "8 July 1994" "Linux 1.0" "Linux Programmer's Manual"
-.SH NAME
-update_state \- update system state
-.SH SYNOPSIS
-.BR update_state
-.SH DESCRIPTION
-.B update_state
-updates a bunch of system state. It takes a long time to execute, and
-would be suitable for execution in a cron job.
-
-Currently,
-.B update_state
-performs the following functions: updates the locate database (in
-.IR /usr/lib/locate ), updates the whatis database (in
-.IR /usr/man ", " /usr/local/man ", " /usr/X386/man ", and "
-.IR /usr/interviews/man ),
-and updates the TeX ls-R cache file (in
-.IR /usr/lib/texmf ).
-.SH BUGS
-The script expects things to be where the FSSTND says they are.
-example, if you have
-.BR makewhatis (8)
-in
-.IR /usr/lib ,
-where it would be traditionally, then you lose, because it should be in
-.IR /usr/bin .
-.SH "SEE ALSO"
-.BR cron(8),
-.BR find(1),
-.BR locate(1),
-.SH AUTHOR
-Rik Faith (faith@cs.unc.edu)
+++ /dev/null
-#!/bin/sh
-
-if test "`whoami`" != "root"; then
- echo "This script must be executed by root"
- exit 1
-fi
-
-if test -x /usr/lib/locate/updatedb; then
- echo "WARNING: The /usr/lib/locate/find.codes file may violate the"
- echo " privacy of your users. Please consider making it"
- echo " readable only by root."
- echo ""
- echo "Updating locate database"
-
- /usr/lib/locate/updatedb
-fi
-
-if test -d /usr/lib/texmf; then
- echo "Building ls-R cache file for TeX"
- /bin/ls -LR /usr/lib/texmf > /tmp/ls-R.$$
- if test -f /usr/lib/texmf/ls-R; then
- cp /usr/lib/texmf/ls-R /usr/lib/texmf/ls-R.old
- fi
- mv /tmp/ls-R.$$ /usr/lib/texmf/ls-R
-fi
-
-if test -x /usr/bin/makewhatis; then
- for i in /usr/man /usr/local/man /usr/X386/man /usr/interviews/man; do
- if test -d $i; then
- echo "Building whatis database in $i"
- /usr/bin/makewhatis $i
- fi
- done
-fi
-
-if test -x /usr/bin/mandb; then
- echo "Updating manpage database"
- /usr/bin/mandb
-fi
-
-exit 0
# Makefile -- Makefile for syslogd utility for Linux
# Created: Sat Oct 9 10:25:19 1993
-# Revised: Sat Feb 11 19:35:52 1995 by faith@cs.unc.edu
+# Revised: Fri Mar 10 21:21:51 1995 by faith@cs.unc.edu
# Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu)
#
all: $(ETC)
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
$(ETC):
$(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)
.Em action
field which specifies the action to be taken if a message
.Xr syslogd
-received matches the selection criteria.
+received matches the selection criteria. There may not be
+.Em any
+spaces in the action field.
The
.Em selector
field is separated from the
.Em action
-field by one or more tab characters.
+field by one or more tab or space characters (this is a departure from the
+standard BSD way of doing things: both tabs
+.Em and
+spaces may be used to separate the selector from the action).
.Pp
The
.Em Selector
* messages at a particular priority level, rather that all messages
* at or above a given priority level.
*
- */
+ * Sat Jun 3 12:48:16 1995: Applied patches from
+ * Jochen.Hein@informatik.tu-clausthal.de to allow spaces *AND* tabs to
+ * separate the selector from the action. This means that no whitespace is
+ * allowed inside the selector.
+ * */
#ifndef lint
char copyright[] =
* Rick <pclink@qus102.qld.npb.telecom.com.au>. Anyone else
* named Rick who wants to chip in? :-)
* More corrections by Neal Becker <neal@ctd.comsat.com> Sun Jan 16, 1994
+ * Patches from Jochen Hein (Jochen.Hein@informatik.tu-clausthal.de) to treat
+ * spaces and tabs the same, applied Sat Mar 11 10:09:24 1995
*/
#ifdef __linux__
#ifdef __linux__
#define CONFORM_TO_FSSTND
+#include "pathnames.h"
#endif
+
#ifdef CONFORM_TO_FSSTND
char *PidFile = "/var/run/syslog.pid";
#else
i = read(fd, line, MAXLINE);
if (i > 0) {
line[i] = '\0';
- printline(LocalHostName, line);
+ printmulti(LocalHostName, line, i);
}
else if (i == 0) {
dprintf("stream closed (%d)\n", fd);
(struct sockaddr *) &fromunix, &len);
if (i > 0) {
line[i] = '\0';
- printline(LocalHostName, line);
+ printmulti(LocalHostName, line,i);
} else if (i < 0 && errno != EINTR)
logerror("recvfrom unix");
}
extern char *cvthname();
line[i] = '\0';
- printline(cvthname(&frominet), line);
+ printmulti(cvthname(&frominet), line,i);
} else if (i < 0 && errno != EINTR)
logerror("recvfrom inet");
}
exit(1);
}
+/*
+ * Break up null terminated lines for printline.
+ */
+
+printmulti(hname, msg, len)
+ char *hname;
+ char *msg;
+ int len;
+{
+ int i;
+ char *pt;
+
+ dprintf("strlen = %d, len = %d\n", strlen(msg), len );
+ for (pt = msg, i = 0; i < len; i++) {
+ if (msg[i] == '\0') {
+ printline(hname,pt);
+ pt = &msg[i+1];
+ }
+ }
+}
+
/*
* Take a raw input line, decode the message, and print the message
* on the appropriate log files.
f->f_pmask[i] = 0;
/* scan through the list of selectors */
- for (p = line; *p && *p != '\t';) {
+ for (p = line; *p && *p != '\t' && *p != ' ';) {
/* find the end of this facility name list */
- for (q = p; *q && *q != '\t' && *q++ != '.'; )
+ for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; )
continue;
/* collect priority name */
- for (bp = buf; *q && !index("\t,;", *q); )
+ for (bp = buf; *q && !index("\t,; ", *q); )
*bp++ = *q++;
*bp = '\0';
/* skip cruft */
- while (index(", ;", *q))
+ while (index(",;", *q)) /* spaces no longer allowed! */
q++;
/* decode priority name */
}
/* scan facilities */
- while (*p && !index("\t.;", *p)) {
- for (bp = buf; *p && !index("\t,;.", *p); )
+ while (*p && !index("\t.; ", *p)) {
+ for (bp = buf; *p && !index("\t,;. ", *p); )
*bp++ = *p++;
*bp = '\0';
if (*buf == '*')
}
/* skip to action part */
- while (*p == '\t')
+ while (*p == '\t' || *p == ' ')
p++;
switch (*p)
--- /dev/null
+/*
+ * Copyright (c) 1983, 1988 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) 1983, 1988 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)syslogd.c 5.45 (Berkeley) 3/2/91";
+#endif /* not lint */
+
+/*
+ * syslogd -- log system messages
+ *
+ * This program implements a system log. It takes a series of lines.
+ * Each line may have a priority, signified as "<n>" as
+ * the first characters of the line. If this is
+ * not present, a default priority is used.
+ *
+ * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
+ * cause it to reread its configuration file.
+ *
+ * Defined Constants:
+ *
+ * MAXLINE -- the maximimum line length that can be handled.
+ * DEFUPRI -- the default priority for user messages
+ * DEFSPRI -- the default priority for kernel messages
+ *
+ * Author: Eric Allman
+ * extensive changes by Ralph Campbell
+ * more extensive changes by Eric Allman (again)
+ *
+ * Modified, Sun Mar 7 15:21:13 1993, faith@cs.unc.edu for Linux:
+ *
+ * SUN_LEN_MISSING: struct sockaddr does not have sun_len
+ * SYSLOG_STREAM: syslog is implemented using stream sockets
+ * SYSLOG_INET: support inet logging
+ * KLOG_STREAM: kernel logging uses a stream device
+ * STATUS_BROKEN: use "int status" instead of "union wait status"
+ * RE_INSTALL_SIGNAL: signal() does *not* remain installed
+ * SYS_MSGBUF_H_MISSING: sys/msgbuf.h is missing
+ * FSYNC_MISSING: fsync() is missing
+ * KERNEL_NAME: what the kernel is usually called
+ *
+ * Original Linux version by Rik Faith <faith@cs.unc.edu>
+ * with changes by Rick Sladkey <jrs@world.std.com> and
+ * Rick <pclink@qus102.qld.npb.telecom.com.au>. Anyone else
+ * named Rick who wants to chip in? :-)
+ */
+
+#ifdef __linux__
+#define SUN_LEN_MISSING
+#define SYSLOG_STREAM
+#define SYSLOG_INET
+#define KLOG_STREAM
+#undef STATUS_BROKEN
+#define RE_INSTALL_SIGNAL
+#define SYS_MSGBUF_H_MISSING
+#undef FSYNC_MISSING
+#define KERNEL_NAME "linux"
+#endif
+
+#define MAXLINE 1024 /* maximum line length */
+#define MAXSVLINE 120 /* maximum saved line length */
+#define DEFUPRI (LOG_USER|LOG_NOTICE)
+#define DEFSPRI (LOG_KERN|LOG_CRIT)
+#define TIMERINTVL 30 /* interval for checking flush, mark */
+
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#ifdef SYS_MSGBUF_H_MISSING
+#define MSG_BSIZE (MAXLINE*2)
+#else
+#include <sys/msgbuf.h>
+#endif
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/signal.h>
+
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <utmp.h>
+#include <setjmp.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <paths.h>
+
+#define SYSLOG_NAMES
+#include <sys/syslog.h>
+
+char *LogName = _PATH_LOG;
+char *ConfFile = _PATH_LOGCONF;
+char *PidFile = _PATH_LOGPID;
+char ctty[] = _PATH_CONSOLE;
+
+#define FDMASK(fd) (1 << (fd))
+
+#define dprintf if (Debug) printf
+
+#define MAXUNAMES 20 /* maximum number of user names */
+
+/*
+ * Flags to logmsg().
+ */
+
+#define IGN_CONS 0x001 /* don't print on console */
+#define SYNC_FILE 0x002 /* do fsync on file after printing */
+#define ADDDATE 0x004 /* add a date to the message */
+#define MARK 0x008 /* this message is a mark */
+
+/*
+ * This structure represents the files that will have log
+ * copies printed.
+ */
+
+struct filed {
+ struct filed *f_next; /* next in linked list */
+ short f_type; /* entry type, see below */
+ short f_file; /* file descriptor */
+ time_t f_time; /* time this was last written */
+ u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
+ union {
+ char f_uname[MAXUNAMES][UT_NAMESIZE+1];
+ struct {
+ char f_hname[MAXHOSTNAMELEN+1];
+ struct sockaddr_in f_addr;
+ } f_forw; /* forwarding address */
+ char f_fname[MAXPATHLEN];
+ } f_un;
+ char f_prevline[MAXSVLINE]; /* last message logged */
+ char f_lasttime[16]; /* time of last occurrence */
+ char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */
+ int f_prevpri; /* pri of f_prevline */
+ int f_prevlen; /* length of f_prevline */
+ int f_prevcount; /* repetition cnt of prevline */
+ int f_repeatcount; /* number of "repeated" msgs */
+};
+
+/*
+ * Intervals at which we flush out "message repeated" messages,
+ * in seconds after previous message is logged. After each flush,
+ * we move to the next interval until we reach the largest.
+ */
+int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */
+#define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1)
+#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount])
+#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \
+ (f)->f_repeatcount = MAXREPEAT; \
+ }
+
+/* values for f_type */
+#define F_UNUSED 0 /* unused entry */
+#define F_FILE 1 /* regular file */
+#define F_TTY 2 /* terminal */
+#define F_CONSOLE 3 /* console terminal */
+#define F_FORW 4 /* remote machine */
+#define F_USERS 5 /* list of users */
+#define F_WALL 6 /* everyone logged on */
+
+char *TypeNames[7] = {
+ "UNUSED", "FILE", "TTY", "CONSOLE",
+ "FORW", "USERS", "WALL"
+};
+
+struct filed *Files;
+struct filed consfile;
+
+int Debug; /* debug flag */
+char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
+char *LocalDomain; /* our local domain name */
+int InetInuse = 0; /* non-zero if INET sockets are being used */
+#ifdef SYSLOG_INET
+int finet; /* Internet datagram socket */
+#endif /* SYSLOG_INET */
+int LogPort; /* port number for INET connections */
+int Initialized = 0; /* set when we have initialized ourselves */
+int MarkInterval = 20 * 60; /* interval between marks in seconds */
+int MarkSeq = 0; /* mark sequence number */
+
+extern int errno;
+extern char *ctime(), *index(), *calloc();
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ register int i;
+ register char *p;
+ int funix, fklog, len;
+ struct sockaddr_un sunx, fromunix;
+ struct sockaddr_in sin, frominet;
+ FILE *fp;
+ int ch;
+ char line[MSG_BSIZE + 1];
+ extern int optind;
+ extern char *optarg;
+ void die(), domark(), init(), reapchild();
+#ifdef SYSLOG_STREAM
+ fd_set unixm;
+ int fd;
+#endif /* SYSLOG_STREAM */
+
+ while ((ch = getopt(argc, argv, "df:m:p:")) != EOF)
+ switch((char)ch) {
+ case 'd': /* debug */
+ Debug++;
+ break;
+ case 'f': /* configuration file */
+ ConfFile = optarg;
+ break;
+ case 'm': /* mark interval */
+ MarkInterval = atoi(optarg) * 60;
+ break;
+ case 'p': /* path */
+ LogName = optarg;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ if (argc -= optind)
+ usage();
+
+ if (!Debug)
+ daemon(0, 0);
+ else
+ setlinebuf(stdout);
+
+ consfile.f_type = F_CONSOLE;
+ (void) strcpy(consfile.f_un.f_fname, ctty);
+ (void) gethostname(LocalHostName, sizeof LocalHostName);
+ if (p = index(LocalHostName, '.')) {
+ *p++ = '\0';
+ LocalDomain = p;
+ }
+ else
+ LocalDomain = "";
+ (void) signal(SIGTERM, die);
+ (void) signal(SIGINT, Debug ? die : SIG_IGN);
+ (void) signal(SIGQUIT, Debug ? die : SIG_IGN);
+ (void) signal(SIGCHLD, reapchild);
+ (void) signal(SIGALRM, domark);
+ (void) alarm(TIMERINTVL);
+ (void) unlink(LogName);
+
+ bzero((char *)&sunx, sizeof(sunx));
+ sunx.sun_family = AF_UNIX;
+ (void) strncpy(sunx.sun_path, LogName, sizeof sunx.sun_path);
+#ifdef SYSLOG_STREAM
+ funix = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (funix < 0 || bind(funix, (struct sockaddr *) &sunx,
+ sizeof(sunx)) < 0 || listen(funix, 5) < 0 ||
+#else /* !SYSLOG_STREAM */
+ funix = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (funix < 0 || bind(funix, (struct sockaddr *) &sunx,
+ sizeof(sunx.sun_family)+sizeof(sunx.sun_len)+
+ strlen(sunx.sun_path)) < 0 ||
+#endif /* !SYSLOG_STREAM */
+ chmod(LogName, 0666) < 0) {
+ (void) sprintf(line, "cannot create %s", LogName);
+ logerror(line);
+ dprintf("cannot create %s (%d)\n", LogName, errno);
+ die(0);
+ }
+#ifdef SYSLOG_INET
+ finet = socket(AF_INET, SOCK_DGRAM, 0);
+ if (finet >= 0) {
+ struct servent *sp;
+
+ sp = getservbyname("syslog", "udp");
+ if (sp == NULL) {
+ errno = 0;
+ logerror("syslog/udp: unknown service");
+ }
+ else {
+ bzero((char *) &sin, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = LogPort = sp->s_port;
+ if (bind(finet, (struct sockaddr *) &sin,
+ sizeof(sin)) < 0)
+ logerror("bind");
+ else {
+ finet = -1;
+ InetInuse = 1;
+ }
+ }
+ }
+#endif /* SYSLOG_INET */
+ if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0)
+ dprintf("can't open %s (%d)\n", _PATH_KLOG, errno);
+
+ /* tuck my process id away */
+ fp = fopen(PidFile, "w");
+ if (fp != NULL) {
+ fprintf(fp, "%d\n", getpid());
+ (void) fclose(fp);
+ }
+
+ dprintf("off & running....\n");
+
+ init();
+ (void) signal(SIGHUP, init);
+#ifdef SYSLOG_STREAM
+ FD_ZERO(&unixm);
+#endif /* SYSLOG_STREAM */
+
+ for (;;) {
+ int nfds;
+ fd_set readfds;
+
+#ifdef SYSLOG_STREAM
+ readfds = unixm;
+#else /* !SYSLOG_STREAM */
+ FD_ZERO(&readfds);
+#endif /* !SYSLOG_STREAM */
+ if (funix >= 0)
+ FD_SET(funix, &readfds);
+ if (fklog >= 0)
+ FD_SET(fklog, &readfds);
+#ifdef SYSLOG_INET
+ if (finet >= 0)
+ FD_SET(finet, &readfds);
+#endif /* SYSLOG_INET */
+
+ errno = 0;
+ dprintf("readfds = %#x\n", *((long *)&readfds));
+ nfds = select(FD_SETSIZE, &readfds, (fd_set *) NULL,
+ (fd_set *) NULL, (struct timeval *) NULL);
+ if (nfds == 0)
+ continue;
+ if (nfds < 0) {
+ if (errno != EINTR)
+ logerror("select");
+ continue;
+ }
+ dprintf("got a message (%d, %#x)\n", nfds, *((long *)&readfds));
+
+#ifdef KLOG_STREAM
+ if (FD_ISSET(fklog, &readfds)) {
+ nfds--;
+ for (;;) {
+ i = klogread(fklog, line, sizeof(line) - 1);
+ if (i > 0) {
+ line[i] = '\0';
+ printsys(line);
+ }
+ else {
+ if (i < 0 && errno != EINTR) {
+ logerror("klog");
+ fklog = -1;
+ }
+ break;
+ }
+ }
+ }
+#else /* !KLOG_STREAM */
+ if (FD_ISSET(fklog, &readfds)) {
+ nfds--;
+ i = read(fklog, line, sizeof(line) - 1);
+ if (i > 0) {
+ line[i] = '\0';
+ printsys(line);
+ } else if (i < 0 && errno != EINTR) {
+ logerror("klog");
+ fklog = -1;
+ }
+ }
+#endif /* !KLOG_STREAM */
+
+#ifdef SYSLOG_STREAM
+ /* Accept a new unix connection. */
+ if (FD_ISSET(funix, &readfds)) {
+ nfds--;
+ len = sizeof fromunix;
+ if ((fd = accept(funix, (struct sockaddr *) &fromunix,
+ &len)) >= 0) {
+ FD_SET(fd, &unixm);
+ dprintf("new stream connect (%d)\n", fd);
+ FD_SET(fd, &readfds);
+ nfds++;
+ }
+ }
+ /* Recv from existing connections. */
+ for (fd = 0; nfds > 0 && fd < FD_SETSIZE; fd++) {
+ if (FD_ISSET(fd, &unixm) && FD_ISSET(fd, &readfds)) {
+ nfds--;
+ dprintf("message from stream (%d)\n", fd);
+ i = read(fd, line, MAXLINE);
+ if (i > 0) {
+ line[i] = '\0';
+ printline(LocalHostName, line);
+ }
+ else if (i == 0) {
+ dprintf("stream closed (%d)\n", fd);
+ close(fd);
+ FD_CLR(fd, &unixm);
+ }
+ else if (i < 0 && errno != EINTR) {
+ logerror("recv stream");
+ close(fd);
+ FD_CLR(fd, &unixm);
+ }
+ }
+ }
+#else /* !SYSLOG_STREAM */
+ if (FD_ISSET(funix, &readfds)) {
+ nfds--;
+ len = sizeof fromunix;
+ i = recvfrom(funix, line, MAXLINE, 0,
+ (struct sockaddr *) &fromunix, &len);
+ if (i > 0) {
+ line[i] = '\0';
+ printline(LocalHostName, line);
+ } else if (i < 0 && errno != EINTR)
+ logerror("recvfrom unix");
+ }
+#endif /* !SYSLOG_STREAM */
+
+#ifdef SYSLOG_INET
+ if (FD_ISSET(finet, &readfds)) {
+ nfds--;
+ len = sizeof frominet;
+ i = recvfrom(finet, line, MAXLINE, 0,
+ (struct sockaddr *) &frominet, &len);
+ if (i > 0) {
+ extern char *cvthname();
+
+ line[i] = '\0';
+ printline(cvthname(&frominet), line);
+ } else if (i < 0 && errno != EINTR)
+ logerror("recvfrom inet");
+ }
+#endif /* SYSLOG_INET */
+ if (nfds != 0)
+ logerror("loose cannon");
+ }
+}
+
+usage()
+{
+ (void) fprintf(stderr,
+ "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n");
+ exit(1);
+}
+
+/*
+ * Take a raw input line, decode the message, and print the message
+ * on the appropriate log files.
+ */
+
+printline(hname, msg)
+ char *hname;
+ char *msg;
+{
+ register char *p, *q;
+ register int c;
+ char line[MAXLINE + 1];
+ int pri;
+
+ /* test for special codes */
+ pri = DEFUPRI;
+ p = msg;
+ if (*p == '<') {
+ pri = 0;
+ while (isdigit(*++p))
+ pri = 10 * pri + (*p - '0');
+ if (*p == '>')
+ ++p;
+ }
+ if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+ pri = DEFUPRI;
+
+ /* don't allow users to log kernel messages */
+ if (LOG_FAC(pri) == LOG_KERN)
+ pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
+
+ q = line;
+
+ while ((c = *p++ & 0177) != '\0' &&
+ q < &line[sizeof(line) - 1])
+ if (iscntrl(c)) {
+ if (c == '\n')
+ *q++ = ' ';
+ else if (c == '\r')
+ *q++ = ' ';
+ else if (c == '\t')
+ *q++ = '\t';
+ else {
+ *q++ = '^';
+ *q++ = c ^ 0100;
+ }
+ }
+ else
+ *q++ = c;
+ *q = '\0';
+
+ logmsg(pri, line, hname, 0);
+}
+
+/*
+ * Take a raw input line from /dev/klog, split and format similar to syslog().
+ */
+
+printsys(msg)
+ char *msg;
+{
+ register char *p, *q;
+ register int c;
+ char line[MAXLINE + 1];
+ int pri, flags;
+ char *lp;
+
+#ifdef KERNEL_NAME
+ (void) sprintf(line, "%s: ", KERNEL_NAME);
+#else /* !KERNEL_NAME */
+ (void) strcpy(line, "vmunix: ");
+#endif /* !KERNEL_NAME */
+
+ lp = line + strlen(line);
+ for (p = msg; *p != '\0'; ) {
+ flags = SYNC_FILE | ADDDATE; /* fsync file after write */
+ pri = DEFSPRI;
+ if (*p == '<') {
+ pri = 0;
+ while (isdigit(*++p))
+ pri = 10 * pri + (*p - '0');
+ if (*p == '>')
+ ++p;
+ } else {
+ /* kernel printf's come out on console */
+ flags |= IGN_CONS;
+ }
+ if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
+ pri = DEFSPRI;
+ q = lp;
+ while (*p != '\0' && (c = *p++) != '\n' &&
+ q < &line[MAXLINE])
+ if (iscntrl(c)) {
+ if (c == '\n')
+ *q++ = ' ';
+ else if (c == '\r')
+ *q++ = ' ';
+ else if (c == '\t')
+ *q++ = '\t';
+ else {
+ *q++ = '^';
+ *q++ = c ^ 0100;
+ }
+ }
+ else
+ *q++ = c;
+ *q = '\0';
+ logmsg(pri, line, LocalHostName, flags);
+ }
+}
+
+time_t now;
+
+/*
+ * Log a message to the appropriate log files, users, etc. based on
+ * the priority.
+ */
+
+logmsg(pri, msg, from, flags)
+ int pri;
+ char *msg, *from;
+ int flags;
+{
+ register struct filed *f;
+ int fac, prilev;
+ int omask, msglen;
+ char *timestamp;
+ time_t time();
+
+ dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n",
+ pri, flags, from, msg);
+
+ omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
+
+ /*
+ * Check to see if msg looks non-standard.
+ */
+ msglen = strlen(msg);
+ if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
+ msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
+ flags |= ADDDATE;
+
+ (void) time(&now);
+ if (flags & ADDDATE)
+ timestamp = ctime(&now) + 4;
+ else {
+ timestamp = msg;
+ msg += 16;
+ msglen -= 16;
+ }
+
+ /* extract facility and priority level */
+ if (flags & MARK)
+ fac = LOG_NFACILITIES;
+ else
+ fac = LOG_FAC(pri);
+ prilev = LOG_PRI(pri);
+
+ /* log the message to the particular outputs */
+ if (!Initialized) {
+ f = &consfile;
+#ifdef O_NOCTTY
+ f->f_file = open(ctty, O_WRONLY|O_NOCTTY, 0);
+#else /* !O_NOCTTY */
+ f->f_file = open(ctty, O_WRONLY, 0);
+#endif /* !O_NOCTTY */
+
+ if (f->f_file >= 0) {
+ fprintlog(f, flags, msg);
+ (void) close(f->f_file);
+ }
+ (void) sigsetmask(omask);
+ return;
+ }
+ for (f = Files; f; f = f->f_next) {
+ /* skip messages that are incorrect priority */
+ if (f->f_pmask[fac] < prilev ||
+ f->f_pmask[fac] == INTERNAL_NOPRI)
+ continue;
+
+ if (f->f_type == F_CONSOLE && (flags & IGN_CONS))
+ continue;
+
+ /* don't output marks to recently written files */
+ if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
+ continue;
+
+ /*
+ * suppress duplicate lines to this file
+ */
+ if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
+ !strcmp(msg, f->f_prevline) &&
+ !strcmp(from, f->f_prevhost)) {
+ (void) strncpy(f->f_lasttime, timestamp, 15);
+ f->f_prevcount++;
+ dprintf("msg repeated %d times, %ld sec of %d\n",
+ f->f_prevcount, now - f->f_time,
+ repeatinterval[f->f_repeatcount]);
+ /*
+ * If domark would have logged this by now,
+ * flush it now (so we don't hold isolated messages),
+ * but back off so we'll flush less often
+ * in the future.
+ */
+ if (now > REPEATTIME(f)) {
+ fprintlog(f, flags, (char *)NULL);
+ BACKOFF(f);
+ }
+ } else {
+ /* new line, save it */
+ if (f->f_prevcount)
+ fprintlog(f, 0, (char *)NULL);
+ f->f_repeatcount = 0;
+ (void) strncpy(f->f_lasttime, timestamp, 15);
+ (void) strncpy(f->f_prevhost, from,
+ sizeof(f->f_prevhost));
+ if (msglen < MAXSVLINE) {
+ f->f_prevlen = msglen;
+ f->f_prevpri = pri;
+ (void) strcpy(f->f_prevline, msg);
+ fprintlog(f, flags, (char *)NULL);
+ } else {
+ f->f_prevline[0] = 0;
+ f->f_prevlen = 0;
+ fprintlog(f, flags, msg);
+ }
+ }
+ }
+ (void) sigsetmask(omask);
+}
+
+fprintlog(f, flags, msg)
+ register struct filed *f;
+ int flags;
+ char *msg;
+{
+ struct iovec iov[6];
+ register struct iovec *v;
+ register int l;
+ char line[MAXLINE + 1], repbuf[80], greetings[200];
+
+ v = iov;
+ if (f->f_type == F_WALL) {
+ v->iov_base = greetings;
+ v->iov_len = sprintf(greetings,
+ "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
+ f->f_prevhost, ctime(&now));
+ v++;
+ v->iov_base = "";
+ v->iov_len = 0;
+ v++;
+ } else {
+ v->iov_base = f->f_lasttime;
+ v->iov_len = 15;
+ v++;
+ v->iov_base = " ";
+ v->iov_len = 1;
+ v++;
+ }
+ v->iov_base = f->f_prevhost;
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ v->iov_base = " ";
+ v->iov_len = 1;
+ v++;
+
+ if (msg) {
+ v->iov_base = msg;
+ v->iov_len = strlen(msg);
+ } else if (f->f_prevcount > 1) {
+ v->iov_base = repbuf;
+ v->iov_len = sprintf(repbuf, "last message repeated %d times",
+ f->f_prevcount);
+ } else {
+ v->iov_base = f->f_prevline;
+ v->iov_len = f->f_prevlen;
+ }
+ v++;
+
+ dprintf("Logging to %s", TypeNames[f->f_type]);
+ f->f_time = now;
+
+ switch (f->f_type) {
+ case F_UNUSED:
+ dprintf("\n");
+ break;
+
+ case F_FORW:
+ dprintf(" %s\n", f->f_un.f_forw.f_hname);
+ l = sprintf(line, "<%d>%.15s %s", f->f_prevpri,
+ iov[0].iov_base, iov[4].iov_base);
+ if (l > MAXLINE)
+ l = MAXLINE;
+ if (sendto(finet, line, l, 0,
+ (struct sockaddr *)&f->f_un.f_forw.f_addr,
+ sizeof f->f_un.f_forw.f_addr) != l) {
+ int e = errno;
+ (void) close(f->f_file);
+ f->f_type = F_UNUSED;
+ errno = e;
+ logerror("sendto");
+ }
+ break;
+
+ case F_CONSOLE:
+ if (flags & IGN_CONS) {
+ dprintf(" (ignored)\n");
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case F_TTY:
+ case F_FILE:
+ dprintf(" %s\n", f->f_un.f_fname);
+ if (f->f_type != F_FILE) {
+ v->iov_base = "\r\n";
+ v->iov_len = 2;
+ } else {
+ v->iov_base = "\n";
+ v->iov_len = 1;
+ }
+ again:
+ if (writev(f->f_file, iov, 6) < 0) {
+ int e = errno;
+ (void) close(f->f_file);
+ /*
+ * Check for errors on TTY's due to loss of tty
+ */
+ if ((e == EIO || e == EBADF) && f->f_type != F_FILE) {
+ f->f_file = open(f->f_un.f_fname,
+ O_WRONLY|O_APPEND, 0);
+ if (f->f_file < 0) {
+ f->f_type = F_UNUSED;
+ logerror(f->f_un.f_fname);
+ } else
+ goto again;
+ } else {
+ f->f_type = F_UNUSED;
+ errno = e;
+ logerror(f->f_un.f_fname);
+ }
+ }
+#ifdef FSYNC_MISSING
+ else if (flags & SYNC_FILE)
+ (void) sync();
+#else
+ else if (flags & SYNC_FILE)
+ (void) fsync(f->f_file);
+#endif
+ break;
+
+ case F_USERS:
+ case F_WALL:
+ dprintf("\n");
+ v->iov_base = "\r\n";
+ v->iov_len = 2;
+ wallmsg(f, iov);
+ break;
+ }
+ f->f_prevcount = 0;
+}
+
+/*
+ * WALLMSG -- Write a message to the world at large
+ *
+ * Write the specified message to either the entire
+ * world, or a list of approved users.
+ */
+
+wallmsg(f, iov)
+ register struct filed *f;
+ struct iovec *iov;
+{
+ static int reenter; /* avoid calling ourselves */
+ register FILE *uf;
+ register int i;
+ struct utmp ut;
+ char *p, *ttymsg();
+
+ if (reenter++)
+ return;
+ if ((uf = fopen(_PATH_UTMP, "r")) == NULL) {
+ logerror(_PATH_UTMP);
+ reenter = 0;
+ return;
+ }
+ /* NOSTRICT */
+ while (fread((char *) &ut, sizeof ut, 1, uf) == 1) {
+ if (ut.ut_name[0] == '\0')
+ continue;
+#ifdef USER_PROCESS
+ if (ut.ut_type != USER_PROCESS)
+ continue;
+#endif
+ if (f->f_type == F_WALL) {
+ if (p = ttymsg(iov, 6, ut.ut_line, 1)) {
+ errno = 0; /* already in msg */
+ logerror(p);
+ }
+ continue;
+ }
+ /* should we send the message to this user? */
+ for (i = 0; i < MAXUNAMES; i++) {
+ if (!f->f_un.f_uname[i][0])
+ break;
+ if (!strncmp(f->f_un.f_uname[i], ut.ut_name,
+ UT_NAMESIZE)) {
+ if (p = ttymsg(iov, 6, ut.ut_line, 1)) {
+ errno = 0; /* already in msg */
+ logerror(p);
+ }
+ break;
+ }
+ }
+ }
+ (void) fclose(uf);
+ reenter = 0;
+}
+
+void
+reapchild()
+{
+#ifdef STATUS_BROKEN
+ int status;
+#else
+ union wait status;
+#endif
+
+ while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
+ ;
+}
+
+/*
+ * Return a printable representation of a host address.
+ */
+char *
+cvthname(f)
+ struct sockaddr_in *f;
+{
+ struct hostent *hp;
+ register char *p;
+ extern char *inet_ntoa();
+
+ dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr));
+
+ if (f->sin_family != AF_INET) {
+ dprintf("Malformed from address\n");
+ return ("???");
+ }
+ hp = gethostbyaddr((char *)&f->sin_addr,
+ sizeof(struct in_addr), f->sin_family);
+ if (hp == 0) {
+ dprintf("Host name for your address (%s) unknown\n",
+ inet_ntoa(f->sin_addr));
+ return (inet_ntoa(f->sin_addr));
+ }
+ if ((p = index(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
+ *p = '\0';
+ return ((char *) hp->h_name);
+}
+
+void
+domark()
+{
+ register struct filed *f;
+ time_t time();
+
+ now = time((time_t *)NULL);
+ MarkSeq += TIMERINTVL;
+ if (MarkSeq >= MarkInterval) {
+ logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
+ MarkSeq = 0;
+ }
+
+ for (f = Files; f; f = f->f_next) {
+ if (f->f_prevcount && now >= REPEATTIME(f)) {
+ dprintf("flush %s: repeated %d times, %d sec.\n",
+ TypeNames[f->f_type], f->f_prevcount,
+ repeatinterval[f->f_repeatcount]);
+ fprintlog(f, 0, (char *)NULL);
+ BACKOFF(f);
+ }
+ }
+#ifdef RE_INSTALL_SIGNAL
+ (void) signal(SIGALRM, domark);
+#endif
+ (void) alarm(TIMERINTVL);
+}
+
+/*
+ * Print syslogd errors some place.
+ */
+logerror(type)
+ char *type;
+{
+ char buf[100], *strerror();
+
+ if (errno)
+ (void) sprintf(buf, "syslogd: %s: %s", type, strerror(errno));
+ else
+ (void) sprintf(buf, "syslogd: %s", type);
+ errno = 0;
+ dprintf("%s\n", buf);
+ logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
+}
+
+void
+die(sig)
+{
+ register struct filed *f;
+ char buf[100];
+
+ for (f = Files; f != NULL; f = f->f_next) {
+ /* flush any pending output */
+ if (f->f_prevcount)
+ fprintlog(f, 0, (char *)NULL);
+ }
+ if (sig) {
+ dprintf("syslogd: exiting on signal %d\n", sig);
+ (void) sprintf(buf, "exiting on signal %d", sig);
+ errno = 0;
+ logerror(buf);
+ }
+ (void) unlink(LogName);
+ exit(0);
+}
+
+/*
+ * INIT -- Initialize syslogd from configuration table
+ */
+
+void
+init()
+{
+ register int i;
+ register FILE *cf;
+ register struct filed *f, *next, **nextp;
+ register char *p;
+ char cline[BUFSIZ];
+
+ dprintf("init\n");
+
+ /*
+ * Close all open log files.
+ */
+ Initialized = 0;
+ for (f = Files; f != NULL; f = next) {
+ /* flush any pending output */
+ if (f->f_prevcount)
+ fprintlog(f, 0, (char *)NULL);
+
+ switch (f->f_type) {
+ case F_FILE:
+ case F_TTY:
+ case F_CONSOLE:
+ case F_FORW:
+ (void) close(f->f_file);
+ break;
+ }
+ next = f->f_next;
+ free((char *) f);
+ }
+ Files = NULL;
+ nextp = &Files;
+
+ /* open the configuration file */
+ if ((cf = fopen(ConfFile, "r")) == NULL) {
+ dprintf("cannot open %s\n", ConfFile);
+ *nextp = (struct filed *)calloc(1, sizeof(*f));
+ cfline("*.ERR\t/dev/console", *nextp);
+ (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f));
+ cfline("*.PANIC\t*", (*nextp)->f_next);
+ Initialized = 1;
+ return;
+ }
+
+ /*
+ * Foreach line in the conf table, open that file.
+ */
+ f = NULL;
+ while (fgets(cline, sizeof cline, cf) != NULL) {
+ /*
+ * check for end-of-section, comments, strip off trailing
+ * spaces and newline character.
+ */
+ for (p = cline; isspace(*p); ++p);
+ if (*p == '\0' || *p == '#')
+ continue;
+ for (p = index(cline, '\0'); isspace(*--p););
+ *++p = '\0';
+ f = (struct filed *)calloc(1, sizeof(*f));
+ *nextp = f;
+ nextp = &f->f_next;
+ cfline(cline, f);
+ }
+
+ /* close the configuration file */
+ (void) fclose(cf);
+
+ Initialized = 1;
+
+ if (Debug) {
+ for (f = Files; f; f = f->f_next) {
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ if (f->f_pmask[i] == INTERNAL_NOPRI)
+ printf("X ");
+ else
+ printf("%d ", f->f_pmask[i]);
+ printf("%s: ", TypeNames[f->f_type]);
+ switch (f->f_type) {
+ case F_FILE:
+ case F_TTY:
+ case F_CONSOLE:
+ printf("%s", f->f_un.f_fname);
+ break;
+
+ case F_FORW:
+ printf("%s", f->f_un.f_forw.f_hname);
+ break;
+
+ case F_USERS:
+ for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
+ printf("%s, ", f->f_un.f_uname[i]);
+ break;
+ }
+ printf("\n");
+ }
+ }
+
+ logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
+ dprintf("syslogd: restarted\n");
+}
+
+/*
+ * Crack a configuration file line
+ */
+
+cfline(line, f)
+ char *line;
+ register struct filed *f;
+{
+ register char *p;
+ register char *q;
+ register int i;
+ char *bp;
+ int pri;
+ struct hostent *hp;
+ char buf[MAXLINE], ebuf[100];
+
+ dprintf("cfline(%s)\n", line);
+
+ errno = 0; /* keep strerror() stuff out of logerror messages */
+
+ /* clear out file entry */
+ bzero((char *) f, sizeof *f);
+ for (i = 0; i <= LOG_NFACILITIES; i++)
+ f->f_pmask[i] = INTERNAL_NOPRI;
+
+ /* scan through the list of selectors */
+ for (p = line; *p && *p != '\t';) {
+
+ /* find the end of this facility name list */
+ for (q = p; *q && *q != '\t' && *q++ != '.'; )
+ continue;
+
+ /* collect priority name */
+ for (bp = buf; *q && !index("\t,;", *q); )
+ *bp++ = *q++;
+ *bp = '\0';
+
+ /* skip cruft */
+ while (index(", ;", *q))
+ q++;
+
+ /* decode priority name */
+ if (*buf == '*')
+ pri = LOG_PRIMASK + 1;
+ else {
+ pri = decode(buf, prioritynames);
+ if (pri < 0) {
+ (void) sprintf(ebuf,
+ "unknown priority name \"%s\"", buf);
+ logerror(ebuf);
+ return;
+ }
+ }
+
+ /* scan facilities */
+ while (*p && !index("\t.;", *p)) {
+ for (bp = buf; *p && !index("\t,;.", *p); )
+ *bp++ = *p++;
+ *bp = '\0';
+ if (*buf == '*')
+ for (i = 0; i < LOG_NFACILITIES; i++)
+ f->f_pmask[i] = pri;
+ else {
+ i = decode(buf, facilitynames);
+ if (i < 0) {
+ (void) sprintf(ebuf,
+ "unknown facility name \"%s\"",
+ buf);
+ logerror(ebuf);
+ return;
+ }
+ f->f_pmask[i >> 3] = pri;
+ }
+ while (*p == ',' || *p == ' ')
+ p++;
+ }
+
+ p = q;
+ }
+
+ /* skip to action part */
+ while (*p == '\t')
+ p++;
+
+ switch (*p)
+ {
+ case '@':
+ if (!InetInuse)
+ break;
+ (void) strcpy(f->f_un.f_forw.f_hname, ++p);
+ hp = gethostbyname(p);
+ if (hp == NULL) {
+ extern int h_errno, h_nerr;
+ extern char **h_errlist;
+
+ logerror((u_int)h_errno < h_nerr ?
+ h_errlist[h_errno] : "Unknown error");
+ break;
+ }
+ bzero((char *) &f->f_un.f_forw.f_addr,
+ sizeof f->f_un.f_forw.f_addr);
+ f->f_un.f_forw.f_addr.sin_family = AF_INET;
+ f->f_un.f_forw.f_addr.sin_port = LogPort;
+ bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length);
+ f->f_type = F_FORW;
+ break;
+
+ case '/':
+ (void) strcpy(f->f_un.f_fname, p);
+#ifdef O_NOCTTY
+ if ((f->f_file = open(p, O_WRONLY|O_APPEND|O_NOCTTY, 0)) < 0) {
+#else /* !O_NOCTTY */
+ if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) {
+#endif /* !O_NOCTTY */
+ f->f_file = F_UNUSED;
+ logerror(p);
+ break;
+ }
+ if (isatty(f->f_file))
+ f->f_type = F_TTY;
+ else
+ f->f_type = F_FILE;
+ if (strcmp(p, ctty) == 0)
+ f->f_type = F_CONSOLE;
+ break;
+
+ case '*':
+ f->f_type = F_WALL;
+ break;
+
+ default:
+ for (i = 0; i < MAXUNAMES && *p; i++) {
+ for (q = p; *q && *q != ','; )
+ q++;
+ (void) strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE);
+ if ((q - p) > UT_NAMESIZE)
+ f->f_un.f_uname[i][UT_NAMESIZE] = '\0';
+ else
+ f->f_un.f_uname[i][q - p] = '\0';
+ while (*q == ',' || *q == ' ')
+ q++;
+ p = q;
+ }
+ f->f_type = F_USERS;
+ break;
+ }
+}
+
+
+/*
+ * Decode a symbolic name to a numeric value
+ */
+
+decode(name, codetab)
+ char *name;
+ CODE *codetab;
+{
+ register CODE *c;
+ register char *p;
+ char buf[40];
+
+ if (isdigit(*name))
+ return (atoi(name));
+
+ (void) strcpy(buf, name);
+ for (p = buf; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+ for (c = codetab; c->c_name; c++)
+ if (!strcmp(buf, c->c_name))
+ return (c->c_val);
+
+ return (-1);
+}
+
+#ifdef KLOG_STREAM
+
+int klogread(fd, buf, size)
+ int fd;
+ char *buf;
+ int size;
+{
+ static char line[MAXLINE];
+ static char *pos = line;
+
+ int i;
+ char *obuf = buf;
+ char *s;
+ char *end;
+ *pos = '\0';
+ if (!(end = strchr(line, '\n'))) {
+ struct timeval tv;
+ fd_set readfds;
+
+ tv.tv_sec = tv.tv_usec = 0;
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+ i = select(fd + 1, (fd_set *) &readfds, (fd_set *) NULL,
+ (fd_set *) NULL, &tv);
+ if (i <= 0)
+ return i;
+ i = read(fd, pos, sizeof(line) - 1 - (pos - line));
+ if (i <= 0)
+ return i;
+ pos += i;
+ *pos = '\0';
+ if (!(end = strchr(line, '\n')))
+ return 0;
+ }
+ for (s = line; s < end; s++)
+ if (*s != '\r')
+ *buf++ = *s;
+ end++;
+ for (s = line; end < pos; s++)
+ *s = *end++;
+ pos = s;
+ return (buf - obuf);
+}
+
+#endif /* KLOG_STREAM */
# Makefile -- Makefile for util-linux Linux utilities
# Created: Sat Dec 26 20:09:40 1992
-# Revised: Sun Feb 26 16:55:46 1995 by faith@cs.unc.edu
+# Revised: Sat Jun 3 14:11:08 1995 by r.faith@ieee.org
# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu)
#
all: $(BIN) $(USRBIN)
-%.o: %.c
- $(CC) -c $(CFLAGS) $< -o $@
-
$(NEEDS_TERMCAP):
$(CC) $(LDFLAGS) $^ -o $@ -ltermcap
ul: ul.o
install install.shadow install.text-utils: all
- install -d -m 755 /bin /usr/bin /usr/lib /usr/man/man1
- install -m 755 $(BIN) /bin
- install -m 755 $(USRBIN) /usr/bin
- install -m 644 $(USRLIB) /usr/lib
- install -m 644 $(MAN1) /usr/man/man1
+ $(INSTALLDIR) $(BINDIR) $(USRBINDIR) $(USRLIBDIR) $(MAN1DIR)
+ $(INSTALLBIN) $(BIN) $(BINDIR)
+ $(INSTALLBIN) $(USRBIN) $(USRBINDIR)
+ $(INSTALLDAT) $(USRLIB) $(USRLIBDIR)
+ $(INSTALLMAN) $(MAN1) $(MAN1DIR)
.PHONY: clean distclean
clean:
.\" from: @(#)rev.1 6.3 (Berkeley) 3/21/92
.\" Modified for Linux by Charles Hannum (mycroft@gnu.ai.mit.edu)
.\" and Brian Koehmstedt (bpk@gnu.ai.mit.edu)
-.\" rev.1,v 1.1.1.1 1995/02/22 19:09:19 faith Exp
+.\" $Id: rev.1,v 1.2 1995/03/12 01:33:24 faith Exp $
.\"
.Dd March 21, 1992
.Dt REV 1
#ifndef lint
/*static char sccsid[] = "from: @(#)rev.c 5.2 (Berkeley) 3/21/92";*/
-static char rcsid[] = "rev.c,v 1.1.1.1 1995/02/22 19:09:19 faith Exp";
+static char rcsid[] = "$Id: rev.c,v 1.3 1995/10/07 01:32:14 faith Exp $";
#endif /* not lint */
#include <sys/types.h>
t = p + len - 1 - (*(p+len-1)=='\r'
|| *(p+len-1)=='\n');
for ( ; t >= p; --t)
- if(strcmp(t, '\0') != 0)
+ if(strcmp(t, "\0") != 0)
putchar(*t);
#endif /* linux */
putchar('\n');
+++ /dev/null
-# @(#)Makefile 7.29
-# Revised: Sun Feb 26 22:05:06 1995 by faith@cs.unc.edu
-# FOR LINUX
-
-include ../MCONFIG
-
-# Change the line below for your time zone (after finding the zone you want in
-# the time zone files, or adding it to a time zone file).
-# Alternately, if you discover you've got the wrong time zone, you can just
-# zic -l rightzone
-# to correct things.
-# Use the command
-# make zonenames
-# to get a list of the values you can use for LOCALTIME.
-
-LOCALTIME= US/Eastern # Factory
-
-# If you want something other than Eastern United States time as a template
-# for handling POSIX-style time zone environment variables,
-# change the line below (after finding the zone you want in the
-# time zone files, or adding it to a time zone file).
-# (When a POSIX-style environment variable is handled, the rules in the template
-# file are used to determine "spring forward" and "fall back" days and
-# times; the environment variable itself specifies GMT offsets of standard and
-# summer time.)
-# Alternately, if you discover you've got the wrong time zone, you can just
-# zic -p rightzone
-# to correct things.
-# Use the command
-# make zonenames
-# to get a list of the values you can use for POSIXRULES.
-# If you want POSIX compatibility, use "America/New_York".
-
-POSIXRULES= America/New_York
-
-# Everything gets put in subdirectories of. . .
-
-TOPDIR= /usr
-
-# "Compiled" time zone information is placed in the "TZDIR" directory
-# (and subdirectories).
-# Use an absolute path name for TZDIR unless you're just testing the software.
-
-TZDIR= $(TOPDIR)/lib/zoneinfo
-
-LIBDIR= $(TOPDIR)/lib
-TZLIB= $(LIBDIR)/libz.a
-
-# 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.
-# POSIX mandates that leap seconds not be counted; for compatibility with it,
-# use either "posix_only" or "posix_right".
-
-REDO= posix_right
-
-# Since "." may not be in PATH...
-
-YEARISTYPE= ./yearistype
-
-# If you're on an AT&T-based system (rather than a BSD-based system), add
-# -DUSG
-# to the end of the "CFLAGS=" line.
-#
-# If you're running on a system where "strchr" is known as "index"
-# (for example, a 4.[012]BSD system), add
-# -Dstrchr=index
-# to the end of the "CFLAGS=" line.
-#
-# If you're running on a system with a "mkdir" function, feel free to add
-# -Demkdir=mkdir
-# to the end of the "CFLAGS=" line
-#
-# If you want to use System V compatibility code, add
-# -DUSG_COMPAT
-# to the end of the "CFLAGS=" line. This arrange for "timezone" and "daylight"
-# variables to be kept up-to-date by the time conversion functions. Neither
-# "timezone" nor "daylight" is described in X3J11's work.
-#
-# If your system has a "GMT offset" field in its "struct tm"s
-# (or if you decide to add such a field in your system's "time.h" file),
-# add the name to a define such as
-# -DTM_GMTOFF=tm_gmtoff
-# or
-# -DTM_GMTOFF=_tm_gmtoff
-# to the end of the "CFLAGS=" line.
-# Neither tm_gmtoff nor _tm_gmtoff is described in X3J11's work;
-# in its work, use of "tm_gmtoff" is described as non-conforming.
-# Both UCB and Sun have done the equivalent of defining TM_GMTOFF in
-# their recent releases.
-#
-# If your system has a "zone abbreviation" field in its "struct tm"s
-# (or if you decide to add such a field in your system's "time.h" file),
-# add the name to a define such as
-# -DTM_ZONE=tm_zone
-# or
-# -DTM_ZONE=_tm_zone
-# to the end of the "CFLAGS=" line.
-# Neither tm_zone nor _tm_zone is described in X3J11's work;
-# in its work, use of "tm_zone" is described as non-conforming.
-# Both UCB and Sun have done the equivalent of defining TM_ZONE in
-# their recent releases.
-#
-# If you want functions that were inspired by early versions of X3J11's work,
-# add
-# -DSTD_INSPIRED
-# to the end of the "CFLAGS=" line. This arranges for the functions
-# "tzsetwall", "offtime", "timelocal", "timegm", "timeoff",
-# "posix2time", and "time2posix" to be added to the time conversion library.
-# "tzsetwall" is like "tzset" except that it arranges for local wall clock
-# time (rather than the time specified in the TZ environment variable)
-# to be used.
-# "offtime" is like "gmtime" except that it accepts a second (long) argument
-# that gives an offset to add to the time_t when converting it.
-# "timelocal" is equivalent to "mktime".
-# "timegm" is like "timelocal" except that it turns a struct tm into
-# a time_t using GMT (rather than local time as "timelocal" does).
-# "timeoff" is like "timegm" except that it accepts a second (long) argument
-# that gives an offset to use when converting to a time_t.
-# "posix2time" and "time2posix" are described in an included manual page.
-# None of these functions are described in X3J11's current work.
-# Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0.
-# These functions may well disappear in future releases of the time
-# conversion package.
-#
-# If you want Source Code Control System ID's left out of object modules, add
-# -DNOID
-# to the end of the "CFLAGS=" line.
-#
-# If you'll never want to handle solar-time-based time zones, add
-# -DNOSOLAR
-# to the end of the "CFLAGS=" line
-# (and comment out the "SDATA=" line below).
-# This reduces (slightly) the run-time data-space requirements of
-# the time conversion functions; it may reduce the acceptability of your system
-# to folks in oil- and cash-rich places.
-#
-# If you want to allocate state structures in localtime, add
-# -DALL_STATE
-# to the end of the "CFLAGS=" line. Storage is obtained by calling malloc.
-#
-# If you want an "altzone" variable (a la System V Release 3.1), add
-# -DALTZONE
-# to the end of the "CFLAGS=" line.
-# This variable is not described in X3J11's work.
-#
-# If you want a "gtime" function (a la MACH), add
-# -DCMUCS
-# to the end of the "CFLAGS=" line
-# This function is not described in X3J11's work.
-#
-# NIST-PCTS:151-2, Version 1.4, (1993-12-03) is a test suite put
-# out by the National Institute of Standards and Technology
-# which claims to test C and Posix conformance. If you want to pass PCTS, add
-# -DPCTS
-# to the end of the "CFLAGS=" line.
-#
-# If you want strict compliance with XPG4 as of April 9, 1994, add
-# -DXPG4_1994_04_09
-# to the end of the "CFLAGS=" line. This causes "strftime" to always return
-# 53 as a week number (rather than 52 or 53) for those days in January that
-# before the first Monday in January when a "%V" format is used and January 1
-# falls on a Friday, Saturday, or Sunday.
-#
-# If your compiler supports the `long double' type, add
-# -DHAVE_LONG_DOUBLE
-# to the end of the "CFLAGS=" line.
-#
-# XXX--note about LOCALE_HOME here
-# XXX--note about HAVE_SETLOCALE here
-
-LFLAGS=$(LDFLAGS)
-
-################################################################################
-
-CC= gcc -DTZDIR=\"$(TZDIR)\"
-
-TZCSRCS= \
- zic.c localtime.c asctime.c scheck.c ialloc.c emkdir.c getopt.c optind.c
-TZCOBJS= \
- zic.o localtime.o asctime.o scheck.o ialloc.o emkdir.o getopt.o optind.o
-TZDSRCS= zdump.c localtime.c asctime.c ialloc.c getopt.c optind.c
-TZDOBJS= zdump.o localtime.o asctime.o ialloc.o getopt.o optind.o
-DATESRCS= \
- date.c localtime.c getopt.c optind.c logwtmp.c strftime.c asctime.c
-DATEOBJS= \
- date.o localtime.o getopt.o optind.o logwtmp.o strftime.o asctime.o
-LIBSRCS= localtime.c asctime.c difftime.c
-LIBOBJS= localtime.o asctime.o difftime.o
-HEADERS= tzfile.h private.h
-NONLIBSRCS= zic.c zdump.c scheck.c ialloc.c emkdir.c getopt.c optind.c
-NEWUCBSRCS= date.c logwtmp.c strftime.c
-SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS)
-MANS= newctime.3 newtzset.3 time2posix.3 tzfile.5 zic.8 zdump.8
-DOCS= README Theory $(MANS) date.1 Makefile
-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 usno1989a
-ENCHILADA= $(DOCS) $(SOURCES) $(DATA) $(USNO)
-
-# And for the benefit of csh users on systems that assume the user
-# shell should be used to handle commands in Makefiles. . .
-
-SHELL= /bin/sh
-
-all: zic zdump $(LIBOBJS)
-
-ALL: all date
-
-install: all $(DATA) $(REDO) $(TZLIB) $(MANS)
- ./zic -y $(YEARISTYPE) \
- -d $(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES)
- $(INSTALLDIR) $(USRSBINDIR)
- $(INSTALLBIN) zic zdump $(USRSBINDIR)
- $(INSTALLDIR) $(MAN3DIR) $(MAN5DIR) $(MAN8DIR)
- -rm -f $(MAN3DIR)/newctime.3 \
- $(MAN3DIR)/newtzset.3 \
- $(MAN5DIR)/tzfile.5 \
- $(MAN8DIR)/zdump.8 \
- $(MAN8DIR)/zic.8
- $(INSTALLMAN) newctime.3 newtzset.3 $(MAN3DIR)
- $(INSTALLMAN) tzfile.5 $(MAN5DIR)
- $(INSTALLMAN) zdump.8 zic.8 $(MAN8DIR)
-
-INSTALL: ALL install date.1
- $(INSTALLDIR) $(BINDIR)
- $(INSTALLBIN) date $(BINDIR)
- $(INSTALLDIR) $(MAN1DIR)
- -rm -f $(MAN1DIR)/date.1
- $(INSTALLMAN) date.1 $(MAN1DIR)
-
-zdump: $(TZDOBJS)
- $(CC) $(CFLAGS) $(LFLAGS) $(TZDOBJS) -o $@
-
-zic: $(TZCOBJS) yearistype
- $(CC) $(CFLAGS) $(LFLAGS) $(TZCOBJS) -o $@
-
-yearistype: yearistype.sh
- cp yearistype.sh yearistype
- chmod +x yearistype
-
-posix_only: zic $(TDATA)
- ./zic -y $(YEARISTYPE) -d $(TZDIR) -L /dev/null $(TDATA)
-
-right_only: zic leapseconds $(TDATA)
- ./zic -y $(YEARISTYPE) -d $(TZDIR) -L leapseconds $(TDATA)
-
-other_two: zic leapseconds $(TDATA)
- ./zic -y $(YEARISTYPE) -d $(TZDIR)/posix -L /dev/null $(TDATA)
- ./zic -y $(YEARISTYPE) \
- -d $(TZDIR)/right -L leapseconds $(TDATA)
-
-posix_right: posix_only other_two
-
-right_posix: right_only other_two
-
-# The "ar d"s below ensure that obsolete object modules
-# (based on source provided with earlier versions of the time conversion stuff)
-# are removed from the library.
-
-$(TZLIB): $(LIBOBJS)
- -mkdir $(TOPDIR) $(LIBDIR)
- sleep 3
- ar ru $@ $(LIBOBJS)
- if ar t $@ timemk.o 2>/dev/null ; then ar d $@ timemk.o ; fi
- if ar t $@ ctime.o 2>/dev/null ; then ar d $@ ctime.o ; fi
- if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \
- then ranlib $@ ; fi
-
-# We use the system's getopt and logwtmp in preference to ours if available.
-
-date: $(DATEOBJS)
- ar r ,lib.a getopt.o optind.o logwtmp.o
- if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \
- then ranlib ,lib.a ; fi
- $(CC) $(CFLAGS) date.o localtime.o asctime.o strftime.o \
- -lc ,lib.a -o $@
- rm -f ,lib.a
-
-clean:
- rm -f core *~ *.o *.out zdump zic yearistype date ,* *.tar.gz
-
-names:
- @echo $(ENCHILADA)
-
-public: $(ENCHILADA)
- tar cf - $(DOCS) $(SOURCES) $(USNO) | gzip -9 > tzcode.tar.gz
- tar cf - $(DATA) | gzip -9 > tzdata.tar.gz
-
-zonenames: $(TDATA)
- @awk '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA)
-
-asctime.o: private.h tzfile.h
-date.o: private.h
-difftime.o: private.h
-emkdir.o: private.h
-ialloc.o: private.h
-localtime.o: private.h tzfile.h
-scheck.o: private.h
-strftime.o: tzfile.h
-zic.o: private.h tzfile.h
-
-.KEEP_STATE:
+++ /dev/null
-@(#)README 7.6
-
-"What time is it?" -- Richard Deacon as The King
-"Any time you want it to be." -- Frank Baxter as The Scientist
- (from the Bell System film on time)
-
-The 1989 update of the time zone package featured
-
-* POSIXization (including interpretation of POSIX-style TZ environment
- variables, provided by Guy Harris),
-* ANSIfication (including versions of "mktime" and "difftime"),
-* SVIDulation (an "altzone" variable)
-* MACHination (the "gtime" function)
-* corrections to some time zone data (including corrections to the rules
- for Great Britain and New Zealand)
-* reference data from the United States Naval Observatory for folks who
- want to do additional time zones
-* and the 1989 data for Saudi Arabia.
-
-(Since this code will be treated as "part of the implementation" in some places
-and as "part of the application" in others, there's no good way to name
-functions, such as timegm, that are not part of the proposed ANSI C standard;
-such functions have kept their old, underscore-free names in this update.)
-
-Support for the tz_abbr variable has been eliminated from this version
-(to forestall "kitchen sink" complaints from certain quarters :-).
-
-Support for Turbo C compilation has also been eliminated; it was present to
-allow checking in an ANSI-style environment, and such checking is now done with
-gcc.
-
-And the "dysize" function has disappeared; it was present to allow compilation
-of the "date" command on old BSD systems, and a version of "date" is now
-provided in the package. The "date" command is not created when you "make all"
-since it may lack options provided by the version distributed with your
-operating system, or may not interact with the system in the same way the
-native version does.
-
-Since POSIX frowns on correct leap second handling, the default behavior of
-the "zic" command (in the absence of a "-L" option) has been changed to omit
-leap second information from its output files.
-
-Be sure to read the comments in "Makefile" and make any changes
-needed to make things right for your system.
-
-To use the new functions, use a "-lz" option when compiling or linking.
-
-Historical local time information has been included here not because it
-is particularly useful, but rather to:
-
-* give an idea of the variety of local time rules that have
- existed in the past and thus an idea of the variety that may be
- expected in the future;
-
-* provide a test of the generality of the local time rule description
- system.
-
-The information in the time zone data files is by no means authoritative;
-if you know that the rules are different from those in a file, by all means
-feel free to change file (and please send the changed version to
-tz@elsie.nci.nih.gov for use in the future). Europeans take note!
-
-Thanks to these Timezone Caballeros who've made major contributions to the
-time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
-Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to
-Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales
-for testing work, and to Gwillim Law for checking local mean time data.
-None of them are responsible for remaining errors.
-
-Look in the ~ftp/pub directory of elsie.nci.nih.gov
-for updated versions of these files.
-
-Please send comments or information to tz@elsie.nci.nih.gov.
+++ /dev/null
-@(#)Theory 7.2
-
-These time and date functions are much like the System V Release 2.0 (SVR2)
-time and date functions; there are a few additions and changes to extend
-the usefulness of the SVR2 functions:
-
-* In SVR2, time display in a process is controlled by the environment
- variable TZ, which "must be a three-letter time zone name, followed
- by a number representing the difference between local time and
- Greenwich Mean Time in hours, followed by an optional three-letter
- name for a daylight time zone;" when the optional daylight time zone is
- present, "standard U.S.A. Daylight Savings Time conversion is applied."
- This means that SVR2 can't deal with other (for example, Australian)
- daylight savings time rules, or situations where more than two
- time zone abbreviations are used in an area.
-
-* In SVR2, time conversion information is compiled into each program
- that does time conversion. This means that when time conversion
- rules change (as in the United States in 1987), all programs that
- do time conversion must be recompiled to ensure proper results.
-
-* In SVR2, time conversion fails for near-minimum or near-maximum
- time_t values when doing conversions for places that don't use GMT.
-
-* In SVR2, there's no tamper-proof way for a process to learn the
- system's best idea of local wall clock. (This is important for
- applications that an administrator wants used only at certain times--
- without regard to whether the user has fiddled the "TZ" environment
- variable. While an administrator can "do everything in GMT" to get
- around the problem, doing so is inconvenient and precludes handling
- daylight savings time shifts--as might be required to limit phone
- calls to off-peak hours.)
-
-* These functions can account for leap seconds, thanks to Bradley White
- (bww@k.cs.cmu.edu).
-
-These are the changes that have been made to the SVR2 functions:
-
-* The "TZ" environment variable is used in generating the name of a file
- from which time zone information is read (or is interpreted a la
- POSIX); "TZ" is no longer constrained to be a three-letter time zone
- name followed by a number of hours and an optional three-letter
- daylight time zone name. The daylight saving time rules to be used
- for a particular time zone are encoded in the time zone file;
- the format of the file allows U.S., Australian, and other rules to be
- encoded, and allows for situations where more than two time zone
- abbreviations are used.
-
- It was recognized that allowing the "TZ" environment variable to
- take on values such as "US/Eastern" might cause "old" programs
- (that expect "TZ" to have a certain form) to operate incorrectly;
- consideration was given to using some other environment variable
- (for example, "TIMEZONE") to hold the string used to generate the
- time zone information file name. In the end, however, it was decided
- to continue using "TZ": it is widely used for time zone purposes;
- separately maintaining both "TZ" and "TIMEZONE" seemed a nuisance;
- and systems where "new" forms of "TZ" might cause problems can simply
- use TZ values such as "EST5EDT" which can be used both by
- "new" programs (a la POSIX) and "old" programs (as zone names and
- offsets).
-
-* To handle places where more than two time zone abbreviations are used,
- the functions "localtime" and "gmtime" set tzname[tmp->tm_isdst]
- (where "tmp" is the value the function returns) to the time zone
- abbreviation to be used. This differs from SVR2, where the elements
- of tzname are only changed as a result of calls to tzset.
-
-* Since the "TZ" environment variable can now be used to control time
- conversion, the "daylight" and "timezone" variables are no longer
- needed or supported. (You can use a compile-time option to cause
- these variables to be defined and to be set by "tzset"; however, their
- values will not be used by "localtime.")
-
-* The "localtime" function has been set up to deliver correct results
- for near-minimum or near-maximum time_t values. (A comment in the
- source code tells how to get compatibly wrong results).
-
-* A function "tzsetwall" has been added to arrange for the system's
- best approximation to local wall clock time to be delivered by
- subsequent calls to "localtime." Source code for portable
- applications that "must" run on local wall clock time should call
- "tzsetwall();" if such code is moved to "old" systems that don't provide
- tzsetwall, you won't be able to generate an executable program.
- (These time zone functions also arrange for local wall clock time to be
- used if tzset is called--directly or indirectly--and there's no "TZ"
- environment variable; portable applications should not, however, rely
- on this behavior since it's not the way SVR2 systems behave.)
-
-Points of interest to folks with Version 7 or BSD systems:
-
-* The BSD "timezone" function is not present in this package;
- it's impossible to reliably map timezone's arguments (a "minutes west
- of GMT" value and a "daylight saving time in effect" flag) to a
- time zone abbreviation, and we refuse to guess.
- Programs that in the past used the timezone function may now examine
- tzname[localtime(&clock)->tm_isdst] to learn the correct time
- zone abbreviation to use. Alternatively, use localtime(&clock)->tm_zone
- if this has been enabled.
-
-* The BSD gettimeofday function is not used in this package;
- this lets users control the time zone used in doing time conversions.
- Users who don't try to control things (that is, users who do not set
- the environment variable TZ) get the time conversion specified in the
- file "/etc/zoneinfo/localtime"; see the time zone compiler writeup for
- information on how to initialize this file.
-
-The functions that are conditionally compiled if STD_INSPIRED is defined should,
-at this point, be looked on primarily as food for thought. They are not in
-any sense "standard compatible"--some are not, in fact, specified in *any*
-standard. They do, however, represent responses of various authors to
-standardization proposals.
-
-Other time conversion proposals, in particular the one developed by folks at
-Hewlett Packard, offer a wider selection of functions that provide capabilities
-beyond those provided here. The absence of such functions from this package
-is not meant to discourage the development, standardization, or use of such
-functions. Rather, their absence reflects the decision to make this package
-close to SVR2 (with the exceptions outlined above) to ensure its broad
-acceptability. If more powerful time conversion functions can be standardized,
-so much the better.
+++ /dev/null
-# @(#)africa 7.6
-
-# 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> (November 18, 1993):
-#
-# 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.
-#
-# 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 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 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'.
-#
-# We typically use traditional English time zone abbreviations,
-# and assume that applications translate them to other languages
-# as part of the normal localization process.
-#
-# I made up the following time zone abbreviations; corrections are welcome!
-# LMT Local Mean Time
-# -2:00 CVT Cape Verde Time (no longer used)
-# -1:00 AAT Atlantic Africa Time
-# 0:00 WAT West Africa Time
-# 1:00 CAT Central Africa Time
-# 2:00 SAT South Africa Time
-# 3:00 EAT East Africa Time
-# 4:00 SMT Seychelles and Mascarene 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 1911 only - Jan 1 0:00s 0 -
-Rule Algeria 1916 only - Jun 14 23:00s 1:00 " DST"
-Rule Algeria 1916 1919 - Oct Sun<=7 23:00s 0 -
-Rule Algeria 1917 only - Mar 24 23:00s 1:00 " DST"
-Rule Algeria 1918 only - Mar 9 23:00s 1:00 " DST"
-Rule Algeria 1919 only - Mar 1 23:00s 1:00 " DST"
-Rule Algeria 1920 only - Feb 14 23:00s 1:00 " DST"
-Rule Algeria 1920 only - Oct 23 23:00s 0 -
-Rule Algeria 1921 only - Mar 14 23:00s 1:00 " DST"
-Rule Algeria 1921 only - Jun 21 23:00s 0 -
-Rule Algeria 1939 only - Sep 11 23:00s 1:00 " DST"
-Rule Algeria 1939 only - Nov 19 1:00 0 -
-Rule Algeria 1944 1945 - Apr Mon<=7 2:00 1:00 " DST"
-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 " DST"
-Rule Algeria 1971 only - Sep 26 23:00s 0 -
-Rule Algeria 1977 only - May 6 0:00 1:00 " DST"
-Rule Algeria 1977 only - Oct 21 0:00 0 -
-Rule Algeria 1978 only - Mar 24 1:00 1:00 " DST"
-Rule Algeria 1978 only - Sep 22 3:00 0 -
-Rule Algeria 1980 only - Apr 25 0:00 1:00 " DST"
-Rule Algeria 1980 only - Oct 31 2:00 0 -
-# Shanks gives 0:09 for Paris Mean Time; go with Whitman's more precise 0:09:05.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01
- 0:09:05 - PMT 1911 Mar 11 # Paris Mean Time
- 0:00 Algeria WET%s 1940 Feb 25 2:00
- 1:00 Algeria MET%s 1946 Oct 7
- 0:00 - WET 1956 Jan 29
- 1:00 - MET 1963 Apr 14
- 0:00 Algeria WET%s 1977 Oct 21
- 1:00 Algeria MET%s 1979 Oct 26
- 0:00 Algeria WET%s 1981 May
- 1:00 - MET
-
-# Angola
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Luanda 0:52:56 - LMT 1892
- 0:52 - LMT 1911 May 26 # Luanda Mean Time
- 1:00 - CAT
-
-# 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 - AAT
-
-# 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 (January 28, 1988):
-# 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 (January 19, 1989):
-# 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 1900 only - Oct 1 0:00 0 -
-Rule Egypt 1940 only - Jul 15 0:00 1:00 " DST"
-Rule Egypt 1940 only - Oct 1 0:00 0 -
-Rule Egypt 1941 only - Apr 15 0:00 1:00 " DST"
-Rule Egypt 1941 only - Sep 16 0:00 0 -
-Rule Egypt 1942 1944 - Apr 1 0:00 1:00 " DST"
-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 " DST"
-Rule Egypt 1957 only - May 10 0:00 1:00 " DST"
-Rule Egypt 1957 1958 - Oct 1 0:00 0 -
-Rule Egypt 1958 only - May 1 0:00 1:00 " DST"
-Rule Egypt 1959 1981 - May 1 1:00 1:00 " DST"
-Rule Egypt 1959 1965 - Sep 30 3:00 0 -
-Rule Egypt 1966 max - Oct 1 3:00 0 -
-Rule Egypt 1982 only - Jul 25 1:00 1:00 " DST"
-Rule Egypt 1983 only - Jul 12 1:00 1:00 " DST"
-Rule Egypt 1984 1988 - May 1 1:00 1:00 " DST"
-Rule Egypt 1989 only - May 6 1:00 1:00 " DST"
-Rule Egypt 1990 max - May 1 1:00 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Cairo 2:05:00 - LMT 1900 Oct
- 2:00 Egypt EET%s
-
-# 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:36 - AMT 1890 # Asmera Mean Time
- 2:35 - 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 - AAMT 1936 May 5 # Addis Ababa MT
- 3:00 - EAT
-
-# 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:07 - BMT 1935 # Banjul Mean Time
- -1:00 - AAT 1964
- 0:00 - WAT
-
-# Ghana
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# WATDT is my invention for ``West Africa one-Third Daylight Time''.
-# From Shanks (1991):
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Ghana 1918 only - Jan 1 0:00 0 WAT
-# Whitman says DST was observed from 1931 to ``the present''; go with Shanks.
-Rule Ghana 1936 1942 - Sep 1 0:00 0:20 WATDT
-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
-
-# 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
-
-# Kenya
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# 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> (November 18, 1993):
-# In 1972 Liberia was the last country to switch
-# from a GMT offset that was not a multiple of 15 minutes.
-# Time magazine reported that it was in honor of their leader's birthday.
-# For Liberia before 1972, Shanks reports -0:44, and Whitman reports -0:44:30;
-# go with Whitman.
-#
-# 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 - LST 1972 May # Liberia Standard Time
- 0:00 - WAT
-
-###############################################################################
-
-# Libya
-
-# From Bob Devine (January 28 1988):
-# Libya: Since 1982 April 1st to September 30th (?)
-
-# From U. S. Naval Observatory (January 19, 1989):
-# 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 1920 only - Jan 1 0:00 0 -
-Rule Libya 1951 only - Oct 14 2:00 1:00 " DST"
-Rule Libya 1952 only - Jan 1 0:00 0 -
-Rule Libya 1953 only - Oct 9 2:00 1:00 " DST"
-Rule Libya 1954 only - Jan 1 0:00 0 -
-Rule Libya 1955 only - Sep 30 0:00 1:00 " DST"
-Rule Libya 1956 only - Jan 1 0:00 0 -
-Rule Libya 1982 1984 - Apr 1 0:00 1:00 " DST"
-Rule Libya 1982 1985 - Oct 1 0:00 0 -
-Rule Libya 1985 only - Apr 6 0:00 1:00 " DST"
-Rule Libya 1986 only - Apr 4 0:00 1:00 " DST"
-Rule Libya 1986 only - Oct 3 0:00 0 -
-Rule Libya 1987 1989 - Apr 1 0:00 1:00 " DST"
-Rule Libya 1987 1990 - Oct 1 0:00 0 -
-Rule Libya 1990 only - May 4 0:00 1:00 " DST"
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# Here's a guess for years starting with 1991.
-Rule Libya 1991 max - Apr 1 0:00 1:00 " DST"
-Rule Libya 1991 max - Oct 1 0:00 0 -
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Tripoli 0:52:44 - LMT 1920
- 1:00 Libya MET%s 1959
- 2:00 - EET 1982
- 1:00 Libya MET%s
-
-# 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 - SMT
-# Agalega Is, Rodriguez
-# no information; probably like Indian/Mauritius
-
-# Mayotte
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Mayotte 3:01:08 - LMT 1911 Jul # Dzaoudzi
- 3:00 - EAT
-
-# Morocco
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Morocco 1913 only - Oct 26 0:00 0 -
-Rule Morocco 1939 only - Sep 12 0:00 1:00 " DST"
-Rule Morocco 1939 only - Nov 19 0:00 0 -
-Rule Morocco 1940 only - Feb 25 0:00 1:00 " DST"
-Rule Morocco 1945 only - Nov 18 0:00 0 -
-Rule Morocco 1950 only - Jun 11 0:00 1:00 " DST"
-Rule Morocco 1950 only - Oct 29 0:00 0 -
-Rule Morocco 1967 only - Jun 3 12:00 1:00 " DST"
-Rule Morocco 1967 only - Oct 1 0:00 0 -
-Rule Morocco 1974 only - Jun 24 0:00 1:00 " DST"
-Rule Morocco 1974 only - Sep 1 0:00 0 -
-Rule Morocco 1976 1977 - May 1 0:00 1:00 " DST"
-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 " DST"
-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 WET%s 1984 Mar 16
- 1:00 - MET 1986
- 0:00 - WET
-# The following are controlled by Spain, and are like Europe/Madrid:
-# Alboran, Alhucemas Is, Ceuta, Chafarinas Is, Mellila.
-
-# Mozambique
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Maputo 2:10:20 - LMT 1903 Mar
- 2:00 - SAT
-
-# Namibia
-# 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 - SAT
-
-# 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 # St Denis
- 4:00 - SMT
-
-# 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 - ?MT 1951 # a typo in Shanks?
- 0:00 - GMT
-# Whitman says Tristan da Cunha is on GMT, like Atlantic/St_Helena.
-#
-# Ascension, Gough, Inaccessible, Nightingale
-# no information; probably like Atlantic/St_Helena
-
-# Sao Tome and Principe
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Sao_Tome 0:26:56 - LMT 1884
- -0:37 - ?MT 1912 # a typo in Shanks?
- 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 - SMT
-
-# Sierra Leone
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule SL 1913 only - Oct 26 0:00 0 -
-# 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 - FMT 1913 Jun
- -1:00 SL AA%sT 1957
- 0:00 SL WA%sT
-
-# Somalia
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# 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 1892 only - Feb 8 0:00 0 -
-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
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Sudan 1931 only - Feb 8 0:00 0 -
-Rule Sudan 1970 only - May 1 0:00 1:00 " DST"
-Rule Sudan 1970 max - Oct 15 0:00 0 -
-Rule Sudan 1971 only - Apr 30 0:00 1:00 " DST"
-Rule Sudan 1972 max - Apr lastSun 0:00 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Khartoum 2:10:08 - LMT 1931
- 2:00 Sudan EET%s
-
-# 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
-
-# Tunisia
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Tunisia 1911 only - Mar 9 0:00 0 -
-Rule Tunisia 1939 only - Apr 15 23:00s 1:00 " DST"
-Rule Tunisia 1939 only - Nov 18 23:00s 0 -
-Rule Tunisia 1940 only - Feb 25 23:00s 1:00 " DST"
-Rule Tunisia 1941 only - Oct 6 0:00 0 -
-Rule Tunisia 1942 only - Mar 9 0:00 1:00 " DST"
-Rule Tunisia 1942 only - Nov 2 3:00 0 -
-Rule Tunisia 1943 only - Mar 29 2:00 1:00 " DST"
-Rule Tunisia 1943 only - Apr 17 2:00 0 -
-Rule Tunisia 1943 only - Apr 25 2:00 1:00 " DST"
-Rule Tunisia 1943 only - Oct 4 2:00 0 -
-Rule Tunisia 1944 1945 - Apr Mon>=1 2:00 1:00 " DST"
-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 " DST"
-Rule Tunisia 1977 only - Sep 24 0:00s 0 -
-Rule Tunisia 1978 only - May 1 0:00s 1:00 " DST"
-Rule Tunisia 1978 only - Oct 1 0:00s 0 -
-Rule Tunisia 1988 only - Jun 1 0:00s 1:00 " DST"
-Rule Tunisia 1988 max - Sep lastSun 0:00s 0 -
-Rule Tunisia 1989 only - Mar 26 0:00s 1:00 " DST"
-Rule Tunisia 1990 only - May 1 0:00s 1:00 " DST"
-Rule Tunisia 1991 max - Mar lastSun 0:00s 1:00 " DST"
-# Shanks gives 0:09 for Paris Mean Time; go with Whitman's more precise 0:09:05.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Africa/Tunis 0:40:44 - LMT 1881 May 12
- 0:09:05 - PMT 1911 Mar 9 # Paris Mean Time
- 1:00 Tunisia MET%s
-
-# 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/Lumumbashi 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
-# @(#)antarctica 7.2
-
-# From Arthur David Olson (February 13, 1988):
-# No data available.
-
-# Balleny Is
-
-# British Antarctic Territories include
-# South Orkney Is
-# South Shetland Is
-
-# Amsterdam Island
-# Bouvet
-# Crozet Is
-# Heard and McDonald Is
-# Kerguelen Is
-# St Paul Island
-# Peter I Island
-# Scott Island
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)asctime.c 7.6";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-#include "tzfile.h"
-
-/*
-** A la X3J11, with core dump avoidance.
-*/
-
-char *
-asctime(timeptr)
-register const struct tm * timeptr;
-{
- static const char wday_name[][3] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
- static const char mon_name[][3] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- /*
- ** Big enough for something such as
- ** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
- ** (two three-character abbreviations, five strings denoting integers,
- ** three explicit spaces, two explicit colons, a newline,
- ** and a trailing ASCII nul).
- */
- static char result[3 * 2 + 5 * INT_STRLEN_MAXIMUM(int) +
- 3 + 2 + 1 + 1];
- register const char * wn;
- register const char * mn;
-
- if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
- wn = "???";
- else wn = wday_name[timeptr->tm_wday];
- if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
- mn = "???";
- else mn = mon_name[timeptr->tm_mon];
- /*
- ** The X3J11-suggested format is
- ** "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %d\n"
- ** Since the .2 in 02.2d is ignored, we drop it.
- */
- (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n",
- wn, mn,
- timeptr->tm_mday, timeptr->tm_hour,
- timeptr->tm_min, timeptr->tm_sec,
- TM_YEAR_BASE + timeptr->tm_year);
- return result;
-}
+++ /dev/null
-# @(#)asia 7.12
-
-# 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> (August 18, 1994):
-#
-# 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.
-#
-# 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
-# LST Local Star Time (Russian ``mestnoe zvezdnoe vremya'')
-# 2:00 EET EET DST Eastern European Time
-# 2:00 IST IDT Israel
-# 3:00 AST ADT Arabia*
-# 3:00 MSK MSD Moscow
-# 3:30 IST IDT Iran
-# 4:00 BSK BSD Baku*
-# 4:00 GST GDT Gulf*
-# 4:30 AFT Afghanistan*
-# 5:00 ASK ASD Ashkhabad*
-# 5:00 PKT Pakistan*
-# 5:30 IST IST India
-# 5:45 NPT Nepal*
-# 6:00 BGT Bengal, Bangladesh*
-# 6:00 TSK TSD Tashkent*
-# 6:30 BMT Burma*
-# 7:00 ICT Indochina*
-# 7:00 JVT Java*
-# 8:00 BNT Borneo, Brunei*
-# 8:00 CST CDT China
-# 8:00 HKT HKST Hong Kong
-# 8:00 PST PDT Philippines*
-# 8:00 SGT Singapore
-# 8:00 UST UDT Ulan Bator*
-# 9:00 JST Japan
-# 9:00 KST KDT Korea
-# 9:00 MLT Moluccas*
-# 9:30 CST Australian Central Standard Time
-#
-# See the `europe' file for Russia and Turkey in Asia.
-#
-# See the `africa' file for Zone naming 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.
-
-###############################################################################
-
-# From Paul Eggert <eggert@twinsun.com> (May 28, 1994):
-# We don't know what happened to the clocks in the Caucausus and the ex-Soviet
-# Central Asia after 1990. Until we get more info, stick with the pre-1991 rules.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Russia 1981 1984 - Apr 1 0:00 1:00 D
-Rule Russia 1981 1983 - Oct 1 0:00 0 K
-Rule Russia 1984 max - Sep lastSun 3:00 0 K
-Rule Russia 1985 max - Mar lastSun 2:00 1:00 D
-
-# Afghanistan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Kabul 4:36:48 - LMT 1890
- 4:00 - GST 1945
- 4:30 - AFT
-
-# Armenia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2
- 3:00 - MSK 1957 Mar
- 4:00 Russia BS%s
-
-# Azerbaijan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Baku 3:19:24 - LMT 1924 May 2
- 3:00 - MSK 1957 Mar
- 4:00 Russia BS%s
-
-# 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 - CMT 1941 Oct # Calcutta Mean Time
- 6:30 - BMT 1942 May 15
- 5:30 - IST 1942 Sep
- 6:30 - BMT 1951 Sep 30
- 6:00 - BGT
-
-# Bhutan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Thimbu 5:58:36 - LMT 1947 Aug 15
- 5:30 - IST 1987 Oct
- 6:00 - BGT
-
-# British Indian Ocean Territory
-# From Whitman:
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Chagos 5:00 - PKT
-
-# 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
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Rangoon 6:24:40 - LMT 1880
- 6:25 - RMT 1920
- 6:30 - BMT 1942 May
- 9:00 - JST 1945 May 3
- 6:30 - BMT
-
-# Cambodia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Phnom_Penh 6:59:40 - LMT 1906 Jun 9
- 7:06 - 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 (January 28, 1988):
-# No they don't. See TIME mag, February 17, 1986 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 Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# According to Shanks, China started using DST in 1986,
-# but it's still all one big happy time zone.
-
-# From U. S. Naval Observatory (January 19, 1989):
-# 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> (November 18, 1993):
-# Shanks writes that China switched from the Chinese calendar on 1912 Feb 12.
-# He also writes that China has had a single time zone since 1980 May 1,
-# and that they instituted DST on 1986 May 4; this contradicts Devine's
-# note about Time magazine, though apparently _something_ happened in 1986.
-
-# From Shanks (1991):
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Shang 1928 only - Jan 1 0:00 0 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 max - Sep Sun>=11 0:00 0 S
-Rule PRC 1987 max - Apr Sun>=10 0:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Shanghai 8:05:52 - LMT 1928
- 8:00 Shang C%sT 1949
- 8:00 PRC C%sT
-
-###############################################################################
-
-# Republic of China
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Taiwan 1896 only - Jan 1 0:00 0 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
-# Presumably Hong Kong will have DST again when it merges with China,
-# but it's too early to predict the details.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule HK 1904 only - Oct 30 0:00 0 -
-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
-
-# Macao
-# Presumably Macao will have DST again when it merges with China,
-# but it's too early to predict the details.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Macao 1912 only - Jan 1 0:00 0 S
-Rule Macao 1961 1962 - Mar Sun>=16 3:30 1:00 D
-Rule Macao 1961 1964 - Nov Sun>=1 3:30 0 S
-Rule Macao 1963 only - Mar Sun>=16 0:00 1:00 D
-Rule Macao 1964 only - Mar Sun>=16 3:30 1:00 D
-Rule Macao 1965 only - Mar Sun>=16 0:00 1:00 D
-Rule Macao 1965 only - Oct 31 0:00 0 S
-Rule Macao 1966 1971 - Apr Sun>=16 3:30 1:00 D
-Rule Macao 1966 1971 - Oct Sun>=16 3:30 0 S
-Rule Macao 1972 1974 - Apr Sun>=15 0:00 1:00 D
-Rule Macao 1972 1973 - Oct Sun>=15 0:00 0 S
-Rule Macao 1974 1977 - Oct Sun>=15 3:30 0 S
-Rule Macao 1975 1977 - Apr Sun>=15 3:30 1:00 D
-Rule Macao 1978 1980 - Apr Sun>=15 0:00 1:00 D
-Rule Macao 1978 1980 - Oct Sun>=15 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Macao 7:34:20 - LMT 1912
- 8:00 Macao C%sT
-
-
-###############################################################################
-
-# Cyprus
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Cyprus 1921 only - Nov 14 0:00 0 -
-Rule Cyprus 1975 only - Apr 13 0:00 1:00 " DST"
-Rule Cyprus 1975 only - Oct 12 0:00 0 -
-Rule Cyprus 1976 only - May 15 0:00 1:00 " DST"
-Rule Cyprus 1976 only - Oct 11 0:00 0 -
-Rule Cyprus 1977 1980 - Apr Sun>=1 0:00 1:00 " DST"
-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 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14
- 2:00 Cyprus EET%s
-
-# 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!
-# Alas, we have no details.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Tbilisi 2:59:16 - LMT 1880
- 2:59 - LST 1924 May 2
- 3:00 - MSK 1957 Mar
- 4:00 Russia BS%s
-
-# India
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Calcutta 5:53:28 - LMT 1880
- 5:53 - CMT 1941 Oct # Calcutta Mean Time
- 6:30 - BMT 1942 May 15
- 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 - JMT 1924 Jan 1 0:13
- 7:20 - JVT 1932 Nov
- 7:30 - JVT 1942 Mar 23
- 9:00 - JST 1945 Aug
- 7:30 - JVT 1948 May
- 8:00 - JVT 1950 May
- 7:30 - JVT 1964
- 7:00 - JVT
-Zone Asia/Ujung_Pandang 7:57:36 - LMT 1920
- 7:58 - MMT 1932 Nov # Macassar Mean Time
- 8:00 - BNT 1942 Feb 9
- 9:00 - JST 1945 Aug
- 8:00 - BNT
-Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
- 9:00 - MLT 1944
- 9:30 - CST 1964
- 9:00 - MLT
-
-# Iran
-
-# Shanks has no record of DST after 1980.
-
-# From Bob Devine (January 28, 1988):
-# Iran: Last Sunday in March to third (?) Sunday in
-# September. Since the revolution, the official calendar is Monarchic
-# calendar; I have no idea what the correspondence between dates are.
-
-# From U. S. Naval Observatory (January 19, 1989):
-# IRAN 3.5H AHEAD OF UTC
-
-# From Shanks (1991), with corrections from Devine:
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Iran 1977 only - Nov 1 0:00 0 S
-Rule Iran 1978 1980 - Mar 21 0:00 1:00 D
-Rule Iran 1978 only - Oct 21 0:00 0 S
-Rule Iran 1979 only - Sep 19 0:00 0 S
-Rule Iran 1980 only - Sep 23 0:00 0 S
-Rule Iran 1988 max - Mar lastSun 2:00 1:00 D
-Rule Iran 1988 max - Sep Sun>=15 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Tehran 3:25:44 - LMT 1916
- 3:26 - TMT 1946
- 3:30 - IST 1977 Nov
- 4:00 Iran G%sT 1979
- 3:30 Iran I%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 max - Sep lastSun 1:00s 0 S
-Rule Iraq 1986 max - Mar lastSun 1:00s 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Baghdad 2:57:40 - LMT 1890
- 2:58 - BMT 1918 # Baghdad Mean Time
- 3:00 - AST 1982 May
- 3:00 Iraq A%sT
-
-
-###############################################################################
-
-# Israel
-
-# From U. S. Naval Observatory (January 19, 1989):
-# ISRAEL 2 H AHEAD OF UTC
-# ISRAEL 3 H AHEAD OF UTC APR 10 - SEP 3
-
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-#
-# 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 1918 only - Jan 1 0:00 0 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
-#Rule Zion 1989 only - Apr 29 0:00 1:00 D
-#Rule Zion 1989 only - Sep 2 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 10 0:00 1:00 D
-#Rule Zion 1991 only - Sep 1 0:00 0 S
-
-# From Ephraim Silverberg (September 5, 1993):
-#
-# 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 on daylight savings
-# time annually.
-
-# 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:00 S
-Rule Zion 1990 only - Mar 25 0:00 1:00 D
-Rule Zion 1990 only - Aug 26 0:00 0:00 S
-Rule Zion 1991 only - Mar 24 0:00 1:00 D
-Rule Zion 1991 only - Sep 1 0:00 0:00 S
-Rule Zion 1992 only - Mar 29 0:00 1:00 D
-Rule Zion 1992 only - Sep 6 0:00 0:00 S
-Rule Zion 1993 only - Apr 2 0:00 1:00 D
-Rule Zion 1993 only - Sep 5 0:00 0:00 S
-
-# The dates for 1994-1995 were obtained from Office of the Spokeswoman for
-# the Ministry of Interior, Jerusalem. There are no dates yet for 1996 and
-# beyond so your guess is as good as theirs (those who are interested can
-# call 972-2-701411 and ask 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:00 S
-Rule Zion 1995 only - Mar 31 0:00 1:00 D
-Rule Zion 1995 only - Aug 27 0:00 0:00 S
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Tel_Aviv 2:19:04 - LMT 1880
- 2:21 - JMT 1918
- 2:00 Zion I%sT
-
-
-###############################################################################
-
-# Japan
-
-# `9:00' and `JST' is from Guy Harris.
-
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# Shanks says that the far southern Ryukyu Is (Nansei-Shoto) are 8:00,
-# but we don't have a good location name for them;
-# we don't even know the name of the principal town.
-# There is no information for Marcus.
-# Other Japanese possessions are probably like Asia/Tokyo.
-
-# From Shanks (1991):
-# Japan switched from the Japanese calendar on 1893 Jan 1.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Tokyo 9:19:04 - LMT 1896
- 9:00 - JST
-#Zone Asia/South_Ryukyu 8:14:44 - LMT 1896 # Amitori
-# 8:00 - CST
-
-# Jordan
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# Most likely Shanks is merely guessing dates from 1992 on.
-# From Shanks (1991):
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Jordan 1931 only - Jan 1 0:00 0 -
-Rule Jordan 1973 only - Jun 6 0:00 1:00 " DST"
-Rule Jordan 1973 1975 - Oct 1 0:00 0 -
-Rule Jordan 1974 1977 - May 1 0:00 1:00 " DST"
-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 " DST"
-Rule Jordan 1978 only - Sep 30 0:00 0 -
-Rule Jordan 1985 only - Apr 1 0:00 1:00 " DST"
-Rule Jordan 1985 only - Oct 1 0:00 0 -
-Rule Jordan 1986 1988 - Apr Fri>=1 0:00 1:00 " DST"
-Rule Jordan 1986 1990 - Oct Fri>=1 0:00 0 -
-Rule Jordan 1989 only - May 8 0:00 1:00 " DST"
-Rule Jordan 1990 only - Apr 27 0:00 1:00 " DST"
-Rule Jordan 1991 only - Apr 19 0:00 1:00 " DST"
-Rule Jordan 1991 only - Sep 27 0:00 0 -
-Rule Jordan 1992 max - Apr Fri>=1 0:00 1:00 " DST"
-Rule Jordan 1992 max - Oct Fri>=1 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Amman 2:23:44 - LMT 1931
- 2:00 Jordan EET%s
-
-# Kazakhstan
-# From Shanks (1991):
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Alma-Ata 5:07:48 - LMT 1924 May 2
- 5:00 - TSK 1957 Mar
- 6:00 Russia TS%s
-
-# Kirgizstan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
- 5:00 - TSK 1957 Mar
- 6:00 Russia TS%s
-
-###############################################################################
-
-# 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 - 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 1880 only - Jan 1 0:00 0 -
-Rule Lebanon 1920 only - Mar 28 0:00 1:00 " DST"
-Rule Lebanon 1920 only - Oct 25 0:00 0 -
-Rule Lebanon 1921 only - Apr 3 0:00 1:00 " DST"
-Rule Lebanon 1921 only - Oct 3 0:00 0 -
-Rule Lebanon 1922 only - Mar 26 0:00 1:00 " DST"
-Rule Lebanon 1922 only - Oct 8 0:00 0 -
-Rule Lebanon 1923 only - Apr 22 0:00 1:00 " DST"
-Rule Lebanon 1923 only - Sep 16 0:00 0 -
-Rule Lebanon 1957 1961 - May 1 0:00 1:00 " DST"
-Rule Lebanon 1957 1961 - Oct 1 0:00 0 -
-Rule Lebanon 1972 only - Jun 22 0:00 1:00 " DST"
-Rule Lebanon 1972 1977 - Oct 1 0:00 0 -
-Rule Lebanon 1973 1977 - May 1 0:00 1:00 " DST"
-Rule Lebanon 1978 only - Apr 30 0:00 1:00 " DST"
-Rule Lebanon 1978 only - Sep 30 0:00 0 -
-Rule Lebanon 1984 1987 - May 1 0:00 1:00 " DST"
-Rule Lebanon 1984 max - Oct 16 0:00 0 -
-Rule Lebanon 1988 only - Jun 1 0:00 1:00 " DST"
-Rule Lebanon 1989 only - May 10 0:00 1:00 " DST"
-Rule Lebanon 1990 max - May 1 0:00 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Beirut 2:22:00 - LMT 1880
- 2:00 Lebanon EET%s
-
-# Malaysia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Kuala_Lumpur 6:46:48 - LMT 1880
- 6:55 - SMT 1905 Jun
- 7:00 - SGT 1933
- 7:20 - SGT 1942 Feb 15
- 9:00 - JST 1945 Sep 2
- 7:20 - SGT 1950
- 7:30 - SGT 1982 May
- 8:00 - SGT
-
-# Maldives
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Maldives 4:54:00 - LMT 1880 # Male
- 4:54 - MMT 1960
- 5:00 - PKT
-
-# Mongolia
-# 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 1978 only - Jan 1 0:00 0 S
-Rule Mongol 1981 1984 - Apr 1 0:00 1:00 T
-Rule Mongol 1981 1984 - Oct 1 0:00 0 S
-Rule Mongol 1985 max - Mar lastSun 2:00 1:00 T
-Rule Mongol 1985 max - Sep lastSun 3:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-#Zone Asia/Dariv 6:14:32 - LMT 1905 Aug
-# 6:00 - DST 1978
-# 7:00 Mongol D%sT
-Zone Asia/Ulan_Bator 7:07:32 - LMT 1905 Aug
- 7:00 - UST 1978
- 8:00 Mongol U%sT
-#Zone Asia/Baruun-Urt 7:33:00 - LMT 1905 Aug
-# 8:00 - BST 1978
-# 9:00 Mongol B%sT
-
-# Nepal
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Katmandu 5:41:16 - LMT 1920
- 5:30 - IST 1986
- 5:45 - NPT
-
-# 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 - PKT
-
-# Palestine
-# These rules for Egypt are stolen from the `africa' file.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Egypt 1957 only - May 10 0:00 1:00 " DST"
-Rule Egypt 1957 1958 - Oct 1 0:00 0 -
-Rule Egypt 1958 only - May 1 0:00 1:00 " DST"
-Rule Egypt 1959 1981 - May 1 1:00 1:00 " DST"
-Rule Egypt 1959 1965 - Sep 30 3:00 0 -
-Rule Egypt 1966 max - 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 Egypt EET%s 1967 Jun 30
- 2:00 Zion I%sT
-# This will undoubtedly change soon.
-
-# 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 1899 only - May 11 0:00 0 S
-Rule Phil 1936 only - Nov 1 0:00 1:00 D
-Rule Phil 1937 only - Feb 1 0:00 0 S
-Rule Phil 1954 only - Apr 12 0:00 1:00 D
-Rule Phil 1954 only - Jul 1 0:00 0 S
-Rule Phil 1978 only - Mar 22 0:00 1:00 D
-Rule Phil 1978 only - Sep 21 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Manila -15:56:00 - LMT 1844
- 8:04:00 - LMT 1899 May 11
- 8:00 Phil P%sT 1942 May
- 9:00 - JST 1944 Nov
- 8:00 Phil P%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 - SMT 1905 Jun
- 7:00 - SGT 1933
- 7:20 - SGT 1942 Feb 15
- 9:00 - JST 1945 Sep 2
- 7:20 - SGT 1950
- 7:30 - SGT 1982 May
- 8:00 - SGT
-
-# Sri Lanka
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Colombo 5:19:24 - LMT 1880
- 5:20 - JMT 1906
- 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
-
-# Syria
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Syria 1920 only - Jan 1 0:00 0 -
-Rule Syria 1920 1923 - Apr Sun>=15 2:00 1:00 " DST"
-Rule Syria 1920 1923 - Oct Sun>=1 2:00 0 -
-Rule Syria 1962 only - Apr 29 2:00 1:00 " DST"
-Rule Syria 1962 only - Oct 1 2:00 0 -
-Rule Syria 1963 1965 - May 1 2:00 1:00 " DST"
-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 " DST"
-Rule Syria 1966 1976 - Oct 1 2:00 0 -
-Rule Syria 1967 1978 - May 1 2:00 1:00 " DST"
-Rule Syria 1977 1978 - Sep 1 2:00 0 -
-Rule Syria 1983 1984 - Apr 9 2:00 1:00 " DST"
-Rule Syria 1983 1984 - Oct 1 2:00 0 -
-Rule Syria 1986 only - Feb 16 2:00 1:00 " DST"
-Rule Syria 1986 only - Oct 9 2:00 0 -
-Rule Syria 1987 only - Mar 1 2:00 1:00 " DST"
-Rule Syria 1987 1988 - Oct 31 2:00 0 -
-Rule Syria 1988 only - Mar 15 2:00 1:00 " DST"
-Rule Syria 1989 only - Mar 31 2:00 1:00 " DST"
-Rule Syria 1989 only - Oct 1 2:00 0 -
-Rule Syria 1990 max - Apr 1 2:00 1:00 " DST"
-Rule Syria 1990 max - Sep 30 2:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Damascus 2:25:12 - LMT 1920
- 2:00 Syria EET%s
-
-# Tajikistan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2
- 5:00 - TSK 1957 Mar
- 6:00 Russia TS%s
-
-# Thailand
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Bangkok 6:42:04 - LMT 1880
- 6:42 - BMT 1920 Apr
- 7:00 - ICT
-
-# Turkmenistan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Ashkhabad 3:53:32 - LMT 1924 May 2
- 4:00 - ASK 1957 Mar
- 5:00 Russia AS%s
-
-# 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 - TSK 1957 Mar
- 6:00 Russia TS%s
-
-# Vietnam
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# 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 - 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
-# @(#)australasia 7.21
-# 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
-Rule Aus 1895 only - Jan 1 0:00 0 -
-# 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:00
- 8:00 1:00 WST 1975 Mar Sun>=1 3:00
- 8:00 - WST 1983 Oct lastSun 2:00
- 8:00 1:00 WST 1984 Mar Sun>=1 3:00
- 8:00 - WST 1991 Nov 17 2:00
- 8:00 1:00 WST 1992 Mar Sun>=1 3:00
- 8:00 - WST
-# Queensland
-Zone Australia/Brisbane 10:12:08 - LMT 1895
- 10:00 - EST 1917 Jan 1 0:01
- 10:00 Aus EST 1971 Oct lastSun 2:00
- 10:00 1:00 EST 1972 Feb lastSun 3:00
- 10:00 - EST 1989 Oct lastSun 2:00
- 10:00 1:00 EST 1990 Mar Sun>=1 3:00
- 10:00 - EST 1990 Oct lastSun 2:00
- 10:00 1:00 EST 1991 Mar Sun>=1 3:00
- 10:00 - EST 1991 Oct lastSun 2:00
- 10:00 1:00 EST 1992 Mar Sun>=1 3:00
- 10:00 - EST
-
-# South Australia
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule AS 1971 1985 - Oct lastSun 2:00 1:00 -
-Rule AS 1986 only - Oct 19 2:00 1:00 -
-Rule AS 1987 max - Oct lastSun 2:00 1:00 -
-Rule AS 1972 only - Feb 27 3:00 0 -
-Rule AS 1973 1985 - Mar Sun>=1 3:00 0 -
-Rule AS 1986 1989 - Mar Sun>=15 3:00 0 -
-Rule AS 1990 1994 even Mar Sun>=18 3:00 0 -
-Rule AS 1990 1994 odd Mar Sun>=1 3:00 0 -
-Rule AS 1995 max - Mar lastSun 3:00 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:00
- 9:30 AS CST
-
-# Tasmania
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule AT 1967 only - Oct 1 2:00 1:00 -
-Rule AT 1968 only - Mar 31 3:00 0 -
-Rule AT 1968 1985 - Oct lastSun 2:00 1:00 -
-Rule AT 1969 1971 - Mar Sun>=8 3:00 0 -
-Rule AT 1972 only - Feb 27 3:00 0 -
-Rule AT 1973 1981 - Mar Sun>=1 3:00 0 -
-Rule AT 1982 1983 - Mar lastSun 3:00 0 -
-Rule AT 1984 1986 - Mar Sun>=1 3:00 0 -
-Rule AT 1986 only - Oct 19 2:00 1:00 -
-Rule AT 1987 1990 - Mar Sun>=15 3:00 0 -
-Rule AT 1987 1990 - Oct lastSun 2:00 1:00 -
-Rule AT 1991 max - Oct Sun>=1 2:00 1:00 -
-Rule AT 1991 max - Mar lastSun 3:00 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:00
- 10:00 AT EST
-
-# Victoria
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule AV 1971 1985 - Oct lastSun 2:00 1:00 -
-Rule AV 1972 only - Feb 27 3:00 0 -
-Rule AV 1973 1985 - Mar Sun>=1 3:00 0 -
-Rule AV 1986 1990 - Mar Sun>=15 3:00 0 -
-Rule AV 1986 only - Oct 19 2:00 1:00 -
-Rule AV 1987 max - Oct lastSun 2:00 1:00 -
-Rule AV 1991 1994 - Mar Sun>=1 3:00 0 -
-Rule AV 1995 max - Mar lastSun 3:00 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:00
- 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:00 1:00 -
-Rule AN 1972 only - Feb 27 3:00 0 -
-Rule AN 1973 1985 - Mar Sun>=1 3:00 0 -
-Rule AN 1986 1989 - Mar Sun>=15 3:00 0 -
-Rule AN 1986 only - Oct 19 2:00 1:00 -
-Rule AN 1987 max - Oct lastSun 2:00 1:00 -
-Rule AN 1990 max - Mar Sun>=1 3:00 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:00
- 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:00
- 9:30 AN CST
-
-# Australian Capital Territory
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Australia/Canberra 9:56:32 - LMT 1895 Feb
- 10:00 - EST 1917 Jan 1 0:01
- 10:00 Aus EST 1971 Oct 31 2:00
- 10:00 AN EST 1981 Oct 25 2:00
- 10:00 1:00 EST 1982 Apr 4 3:00
- 10:00 AN EST
-
-# Australian miscellany
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Australia/Lord_Howe 10:36:20 - LMT 1895 Feb
- 10:00 - EST 1981 Mar
- 10:30 AN LHST
-Zone Indian/Christmas 7:02:52 - LMT 1895 Feb
- 7:00 - JVT
-#
-# Ashmore Is, Cartier
-# no information; probably like Australia/Perth
-#
-# 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 HD
-Rule Cook 1979 max - Mar Sun>=1 0:00 0 H
-Rule Cook 1979 max - Oct lastSun 0:00 0:30 HD
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Rarotonga -10:39:04 - LMT 1901 # Avarua
- -10:30 - CIST 1978 Nov 12 # Cook Is ST
- -10:00 Cook T%sT
-
-# Cocos
-# From USNO (1989):
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Indian/Cocos 6:30 - CCT
-
-# Fiji
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva
- 12:00 - NZST
-
-# French Polynesia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Gambier -8:59:48 - LMT 1912 Oct # Rikitea
- -9:00 - GBT
-Zone Pacific/Marquesas -9:18:00 - LMT 1912 Oct
- -9:30 - MQT
-Zone Pacific/Tahiti -9:58:16 - LMT 1912 Oct # Papeete
- -10:00 - THT
-
-# Guam
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Guam 9:39:00 - LMT 1901 # Agana
- 10:00 - GST
-
-# Howland, Baker
-# no information; probably like Pacific/Samoa
-
-# Jarvis
-# no information; probably like Pacific/Kiritimati
-
-# Johnston
-# no information; probably like Pacific/Honolulu
-
-# Kiribati
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Tarawa 11:32:04 - LMT 1901 # Bairiki
- 12:00 - NZST
-Zone Pacific/Enderbury -11:24:20 - LMT 1901
- -12:00 - KJT 1979 Oct
- -11:00 - SST
-Zone Pacific/Kiritimati -10:29:20 - LMT 1901
- -10:40 - LIT 1979 Oct # Line Is Time
- -10:00 - THT
-
-# Nauru
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Nauru 11:07:40 - LMT 1921 Jan 15 # Uaobe
- 11:30 - NST 1942 Mar 15
- 9:00 - JST 1944 Aug 15
- 11:30 - NST 1979 May
- 12:00 - NZST
-
-# New Caledonia
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule NC 1912 only - Jan 13 0:00 0 S
-Rule NC 1977 1978 - Dec Sun>=1 0:00 1:00 D
-Rule NC 1978 1979 - Feb 27 0:00 0 S
-# 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
-Rule NZ 1868 only - Jan 1 0:00 0 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 1:00 D
-Rule NZ 1928 1929 - Mar Sun>=1 2:00 0 S
-Rule NZ 1928 only - Nov 4 2:00 1:00 D
-Rule NZ 1929 only - Oct 30 2:00 1:00 D
-Rule NZ 1930 1933 - Mar Sun>=15 2:00 0 S
-Rule NZ 1930 1933 - Oct Sun>=8 2:00 1:00 D
-# Shanks says DST stopped 1940 Sep lastSun; go with Whitman for war years.
-Rule NZ 1934 1944 - Apr lastSun 2:00 0 S
-Rule NZ 1934 1944 - Sep lastSun 2:00 1:00 D
-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
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Auckland 11:39:04 - LMT 1868
- # Shanks gives 1940 Sep 29 2:00;
- # go with Whitman.
- 11:30 NZ NZ%sT 1945 Apr 29 2:00
- 12:00 NZ NZ%sT
-Zone Pacific/Chatham 12:45 - NZ-CHAT
-
-
-# Antipodes Is, Kermadec Is
-# no information; probably like Pacific/Auckland
-
-###############################################################################
-
-
-# Niue
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Niue -11:19:40 - LMT 1901 # Alofi
- -11:20 - NIT 1951 # Niue I Time
- -11:30 - NIT 1978 Oct 1
- -11:00 - SST
-
-# Norfolk
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Norfolk 11:11:52 - LMT 1901 # Kingston
- 11:12 - NMT 1951
- 11:30 - NRFT
-
-# Pacific Islands Trust Territories
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Majuro 11:24:48 - LMT 1901
- 11:00 - NCST 1969 Oct
- 12:00 - NZST
-Zone Pacific/Kwajalein 11:09:20 - LMT 1901
- 11:00 - NCST 1969 Oct
- -12:00 - KJT 1993 Aug 20
- 12:00 - NZST
-Zone Pacific/Truk 10:07:08 - LMT 1901
- 10:00 - GST 1978 Oct
- 11:00 - NCST
-Zone Pacific/Ponape 10:33:00 - LMT 1901
- 11:00 - NCST
-Zone Pacific/Yap 9:12:24 - LMT 1901
- 9:00 - PLT 1969 Oct
- 10:00 - GST
-
-# Palau
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Palau 8:57:56 - LMT 1901 # Koror
- 9:00 - PLT
-
-# Palmyra
-# no information; probably like Pacific/Kiritmati
-
-# Papua New Guinea
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
- 9:49 - PMMT 1895
- 10:00 - EST
-
-# Pitcairn
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Pitcairn -8:40:20 - LMT 1901 # Adamstown
- -8:30 - PIT
-
-# 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 - NCST
-
-# Tokelau Is
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Fakaofo -11:24:56 - LMT 1901
- -10:00 - THT
-
-# Tonga
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Tongatapu 12:19:20 - LMT 1901
- 12:20 - TMT 1968 Oct
- 13:00 - TGT
-
-# Tuvalu
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Funafuti 11:56:52 - LMT 1901
- 12:00 - NZST
-
-# Vanuatu
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Vanuatu 1912 only - Jan 13 0:00 0 S
-Rule Vanuatu 1983 only - Sep 25 0:00 1:00 D
-Rule Vanuatu 1984 max - Mar Sun>=23 0:00 0 S
-Rule Vanuatu 1984 only - Oct 23 0:00 1:00 D
-Rule Vanuatu 1985 max - Sep Sun>=23 0:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila
- 11:00 - NCST
-
-# Wake
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Wake 11:06:28 - LMT 1901
- 12:00 - NZST
-
-# Wallis and Futuna
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Wallis 12:15:20 - LMT 1901
- 12:00 - NZST
-
-# Western Samoa
-# See Pacific/Samoa in the `northamerica' file, of all places.
-
-###############################################################################
-
-# 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> (August 18, 1994):
-# 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 noted, it is the source for the data above.
-#
-# 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
-# 6:30 CCT Cocos*
-# 7:00 JVT Java*
-# 8:00 WST WST Western Australia
-# 9:00 JST Japan
-# 9:00 PLT Palau*
-# 9:30 CST CST Central Australia
-# 10:00 EST EST Eastern Australia
-# 10:00 GST Guam*
-# 10:30 LHST LHST Lord Howe*
-# 11:00 NCST NCDT New Caledonia*
-# 11:30 NRFT Norfolk*
-# 12:00 NZST NZDT New Zealand
-# 12:45 NZ-CHAT Chatham
-# 13:00 TGT Tongatapu*
-# -12:00 KJT Kwajalein (no longer used)*
-# -11:00 SST Samoa
-# -10:40 LIT Line Is (no longer used)*
-# -10:00 THT Tahiti*
-# - 9:30 MQT Marquesas*
-# - 9:00 GBT Gambier*
-# - 8:30 PIT Pitcairn*
-#
-# See the `northamerica' file for Hawaii and Samoa.
-# See the `southamerica' file for Easter I and the Galapagos Is.
-#
-# See the `africa' file for Zone naming conventions.
-
-###############################################################################
-
-# Australia
-
-# From John Mackin (March 6, 1991):
-# 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 (November 8, 1994):
-# 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.
-# And Robert Uzgalis <buz@cs.aukuni.ac.nz> says 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.
-# For now we'll continue to assume 3:00 for changes since 1970.
-
-# Northern Territory
-
-# From George Shepherd via Simon Woodhead via Robert Elz (March 6, 1991):
-# # 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 (March 4, 1991):
-# 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 (March 6, 1991):
-# # 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 (March 4, 1991):
-# A recent excerpt from an Australian newspaper...
-# Western Australia...do[es] not have daylight saving.
-
-# From John D. Newman via Bradley White (November 2, 1991):
-# 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 (March 8, 1992):
-# 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 (March 6, 1991):
-# # 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 (December 24, 1989):
-# "Australia/Queensland" now observes daylight time (i.e. from
-# October 1989).
-
-# From Bradley White (March 4, 1991):
-# A recent excerpt from an Australian newspaper...
-# ...Queensland...[has] agreed to end daylight saving
-# at 3am tomorrow (March 3)...
-
-# From John Mackin (March 6, 1991):
-# 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 (March 8, 1992):
-# ...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 (March 8, 1992):
-# The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
-
-# South Australia, Tasmania, Victoria
-
-# From Arthur David Olson (March 8, 1992):
-# 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 (March 6, 1991):
-# 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 (March 4, 1991):
-# 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 (March 6, 1991):
-# # 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 (March 11, 1992):
-# 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 (March 13, 1992):
-# 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 (March 16, 1992, 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 (April 11, 1994):
-# 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 (March 4, 1991):
-# 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 (March 6, 1991):
-# # 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 (October 10, 1991):
-# 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 (October 10, 1991):
-# 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 (March 4, 1991):
-# 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 (March 6, 1991):
-# # 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 (March 3, 1990):
-# Rule NSW 1988 only - Mar Sun>=1 3:00 0 -
-# Rule NSW 1989 only - Mar Sun<=21 3:00 0 -
-
-# From Bradley White (March 4, 1991):
-# 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 (March 6, 1991):
-# # 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 (March 9, 1991)
-# I have confirmed the accuracy of the historical data for NSW in the
-# file Robert forwarded
-
-# From Arthur David Olson (March 8, 1992):
-# Sources differ on whether DST ended March 6 or March 20 in 1988;
-# March 20 (the "confirmed" date) is in the chosen rules.
-
-# Yancowinna
-
-# From John Basser (January 4, 1989):
-# `Broken Hill' means the County of Yancowinna.
-
-# From George Shepherd via Simon Woodhead via Robert Elz (March 6, 1991):
-# # 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 (March 6, 1991):
-# 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.
-
-###############################################################################
-
-# New Zealand, from Elz' asia 1.1
-# Elz says "no guarantees"
-
-# From Mark Davies (October 3, 1990):
-# 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 (March 6, 1991):
-# # 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 (March 8, 1992):
-# The chosen rules use the Davies October 8 values for the start of DST in 1989
-# rather than the October 1 value.
-
-###############################################################################
-
-# 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.
-
-# Kwajalein
-
-# In comp.risks 14.87 (26 August 1993), Peter Neumann writes:
-# I wonder what happened in Kwajalein, where there was NO Friday,
-# August 20, 1993. 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.
-
-# Pacific Islands Trust Territories
-
-# 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.
+++ /dev/null
-# @(#)backward 7.6
-
-# This file provides links between late-1993-vintage names for time zones
-# and their previous names.
-
-Link Australia/Sydney Australia/ACT
-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/Tel_Aviv 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 Pacific/Auckland NZ
-Link Pacific/Chatham NZ-CHAT
-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/Atka US/Aleutian
-Link America/Phoenix US/Arizona
-Link America/Chicago US/Central
-Link America/Fort_Wayne US/East-Indiana
-Link America/New_York US/Eastern
-Link Pacific/Honolulu US/Hawaii
-Link America/Knox_IN US/Indiana-Starke
-Link America/Detroit US/Michigan
-Link America/Denver US/Mountain
-Link America/Los_Angeles US/Pacific
-Link Pacific/Samoa US/Samoa
-Link Etc/UTC UTC
-Link Etc/Universal Universal
-Link Etc/Zulu Zulu
+++ /dev/null
-.TH DATE 1
-.SH NAME
-date \- show and set date and time
-.SH SYNOPSIS
-.if n .nh
-.if n .na
-.B date
-[
-.B \-u
-] [
-.B \-c
-] [
-.B \-n
-] [
-.B \-d
-dsttype
-] [
-.B \-t
-minutes-west
-] [
-\fB\-a \fR[\fB+\fR|\fB-]\fIsss\fB.\fIfff\fR
-] [
-.BI + format
-] [
-\fR[\fIyyyy\fR]\fImmddhhmm\fR[\fIyy\fR][\fB.\fIss\fR]
-]
-.SH DESCRIPTION
-.I Date
-without arguments writes the date and time to the standard output in
-the form
-.ce 1
-Wed Mar 8 14:54:40 EST 1989
-.br
-with
-.B EST
-replaced by the local time zone's abbreviation
-(or by the abbreviation for the time zone specified in the
-.B TZ
-environment variable if set).
-.PP
-If a command-line argument starts with a plus sign
-.RB (` + '),
-the rest of the argument is used as a
-.I format
-that controls what appears in the output.
-In the format, when a percent sign
-.RB (` % ')
-appears,
-it and the character after it are not output,
-but rather identify part of the date or time
-to be output in a particular way
-(or identify a special character to output):
-.nf
-.if t .in +.5i
-.if n .in +2
-.ta \w'%M\0\0'u +\w'Wed Mar 8 14:54:40 1989\0\0'u
- Sample output Explanation
-%a Wed Abbreviated weekday name
-%A Wednesday Full weekday name
-%b Mar Abbreviated month name
-%B March Full month name
-%c 03/08/89 14:54:40 Month/day/year Hour:minute:second
-%C Wed Mar 8 14:54:40 1989 a la \fIasctime\^\fP(3)
-%d 08 Day of month (always two digits)
-%D 03/08/89 Month/day/year (eight characters)
-%e 8 Day of month (leading zero blanked)
-%h Mar Abbreviated month name
-%H 14 24-hour-clock hour (two digits)
-%I 02 12-hour-clock hour (two digits)
-%j 067 Julian day number (three digits)
-%k 2 12-hour-clock hour (leading zero blanked)
-%l 14 24-hour-clock hour (leading zero blanked)
-%m 03 Month number (two digits)
-%M 54 Minute (two digits)
-%n \\n newline character
-%p PM AM/PM designation
-%r 02:54:40 PM Hour:minute:second AM/PM designation
-%R 14:54 Hour:minute
-%S 40 Second (two digits)
-%t \\t tab character
-%T 14:54:40 Hour:minute:second
-%U 10 Sunday-based week number (two digits)
-%w 3 Day number (one digit, Sunday is 0)
-%W 10 Monday-based week number (two digits)
-%x 03/08/89 Month/day/year (eight characters)
-%X 14:54:40 Hour:minute:second
-%y 89 Last two digits of year
-%Y 1989 Year in full
-%Z EST Time zone abbreviation
-.if t .in -.5i
-.if n .in -2
-.fi
-If a character other than one of those shown above appears after
-a percent sign in the format,
-that following character is output.
-All other characters in the format are copied unchanged to the output;
-a newline character is always added at the end of the output.
-.PP
-In Sunday-based week numbering,
-the first Sunday of the year begins week 1;
-days preceding it are part of ``week 0.''
-In Monday-based week numbering,
-the first Monday of the year begins week 1.
-.PP
-To set the date, use a command line argument with one of the following forms:
-.nf
-.if t .in +.5i
-.if n .in +2
-.ta \w'198903081454\0'u
-1454 24-hour-clock hours (first two digits) and minutes
-081454 Month day (first two digits), hours, and minutes
-03081454 Month (two digits, January is 01), month day, hours, minutes
-8903081454 Year, month, month day, hours, minutes
-0308145489 Month, month day, hours, minutes, year
- (on System V-compatible systems)
-030814541989 Month, month day, hours, minutes, four-digit year
-198903081454 Four-digit year, month, month day, hours, minutes
-.if t .in -.5i
-.if n .in -2
-.fi
-If the century, year, month, or month day is not given,
-the current value is used.
-Any of the above forms may be followed by a period and two digits that give
-the seconds part of the new time; if no seconds are given, zero is assumed.
-.PP
-These options are available:
-.TP
-.BR \-u " or " \-c
-Use GMT when setting and showing the date and time.
-.TP
-.B \-n
-Do not notify other networked systems of the time change.
-.TP
-.BI "\-d " dsttype
-Set the kernel-stored Daylight Saving Time type to the given value.
-(The kernel-stored DST type is used mostly by ``old'' binaries.)
-.TP
-.BI "\-t " minutes-west
-Set the kernel-stored ``minutes west of GMT'' value to the one given on the
-command line.
-(The kernel-stored DST type is used mostly by ``old'' binaries.)
-.TP
-.BI "\-a " adjustment
-Change the time forward (or backward) by the number of seconds
-(and fractions thereof) specified in the
-.I adjustment\^
-argument.
-Either the seconds part or the fractions part of the argument (but not both)
-may be omitted.
-On BSD-based systems,
-the adjustment is made by changing the rate at which time advances;
-on System-V-based systems, the adjustment is made by changing the time.
-.\" @(#)date.1 7.2
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)date.c 7.13";
-/*
-** Modified from the UCB version with the SCCS ID appearing below.
-*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
- * Copyright (c) 1985, 1987, 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANT[A]BILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)date.c 4.23 (Berkeley) 9/20/88";
-#endif /* not lint */
-
-#ifndef USG
-#include "sys/time.h" /* for DST_NONE */
-#endif /* !defined USG */
-#include "private.h"
-#include "utmp.h" /* for OLD_TIME (or its absence) */
-
-/*
-** The two things date knows about time are. . .
-*/
-
-#ifndef TM_YEAR_BASE
-#define TM_YEAR_BASE 1900
-#endif /* !defined TM_YEAR_BASE */
-
-#ifndef SECSPERMIN
-#define SECSPERMIN 60
-#endif /* !defined SECSPERMIN */
-
-extern double atof();
-extern char ** environ;
-extern char * getlogin();
-extern int logwtmp();
-extern time_t mktime();
-extern char * optarg;
-extern int optind;
-extern char * strchr();
-extern time_t time();
-extern char * tzname[2];
-
-static int retval = EXIT_SUCCESS;
-
-static void checkfinal P((const char *, int, time_t, time_t));
-static int comptm P((const struct tm *, const struct tm *));
-static time_t convert P((const char *, int, time_t));
-static void display P((const char *));
-static void dogmt P((void));
-static void errensure P((void));
-static void iffy P((time_t, time_t, const char *, const char *));
-int main P((int, char**));
-static const char * nondigit P((const char *));
-static void oops P((const char *));
-static void reset P((time_t, int));
-static void timeout P((FILE *, const char *, const struct tm *));
-static void usage P((void));
-static void wildinput P((const char *, const char *, const char *));
-
-int
-main(argc, argv)
-const int argc;
-char * argv[];
-{
- register const char * format;
- register const char * value;
- register const char * cp;
- register int ch;
- register int dousg;
- register int aflag = 0;
- register int dflag = 0;
- register int nflag = 0;
- register int tflag = 0;
- register int minuteswest;
- register int dsttime;
- register float adjust;
- time_t now;
- time_t t;
-
- INITIALIZE(dousg);
- INITIALIZE(minuteswest);
- INITIALIZE(dsttime);
- INITIALIZE(adjust);
- INITIALIZE(t);
- (void) time(&now);
- format = value = NULL;
- while ((ch = getopt(argc, argv, "ucnd:t:a:")) != EOF) {
- switch (ch) {
- default:
- usage();
- case 'u': /* do it in GMT */
- case 'c':
- dogmt();
- break;
- case 'n': /* don't set network */
- nflag = 1;
- break;
- case 'd': /* daylight savings time */
- if (dflag) {
- (void) fprintf(stderr,
- "date: error: multiple -d's used");
- usage();
- }
- dflag = 1;
- cp = optarg;
- dsttime = atoi(cp);
- if (*cp == '\0' || *nondigit(cp) != '\0')
- wildinput("-t value", optarg,
- "must be a non-negative number");
- break;
- case 't': /* minutes west of GMT */
- if (tflag) {
- (void) fprintf(stderr,
- "date: error: multiple -t's used");
- usage();
- }
- tflag = 1;
- cp = optarg;
- minuteswest = atoi(cp);
- if (*cp == '+' || *cp == '-')
- ++cp;
- if (*cp == '\0' || *nondigit(cp) != '\0')
- wildinput("-d value", optarg,
- "must be a number");
- break;
- case 'a': /* adjustment */
- if (aflag) {
- (void) fprintf(stderr,
- "date: error: multiple -a's used");
- usage();
- }
- aflag = 1;
- cp = optarg;
- adjust = atof(cp);
- if (*cp == '+' || *cp == '-')
- ++cp;
- if (*cp == '\0' || strcmp(cp, ".") == 0)
- wildinput("-a value", optarg,
- "must be a number");
- cp = nondigit(cp);
- if (*cp == '.')
- ++cp;
- if (*nondigit(cp) != '\0')
- wildinput("-a value", optarg,
- "must be a number");
- break;
- }
- }
- while (optind < argc) {
- cp = argv[optind++];
- if (*cp == '+')
- if (format == NULL)
- format = cp + 1;
- else {
- (void) fprintf(stderr,
-"date: error: multiple formats in command line\n");
- usage();
- }
- else if (value == NULL)
- value = cp;
- else {
- (void) fprintf(stderr,
-"date: error: multiple values in command line\n");
- usage();
- }
- }
- if (value != NULL) {
- /*
- ** This order ensures that "reasonable" twelve-digit inputs
- ** (such as 120203042006) won't be misinterpreted
- ** even if time_t's range all the way back to the thirteenth
- ** century. Do not change the order.
- */
- t = convert(value, (dousg = TRUE), now);
- if (t == -1)
- t = convert(value, (dousg = FALSE), now);
- if (t == -1) {
- /*
- ** Out of range values,
- ** or time that falls in a DST transition hole?
- */
- if ((cp = strchr(value, '.')) != NULL) {
- /*
- ** Ensure that the failure of
- ** TZ=US/Eastern date 8712312359.60
- ** doesn't get misdiagnosed. (It was
- ** TZ=US/Eastern date 8712311859.60
- ** when the leap second was inserted.)
- ** The normal check won't work since
- ** the given time is valid in GMT.
- */
- if (atoi(cp + 1) >= SECSPERMIN)
- wildinput("time", value,
- "out of range seconds given");
- }
- dogmt();
- t = convert(value, FALSE, now);
- if (t == -1)
- t = convert(value, TRUE, now);
- wildinput("time", value,
- (t == -1) ?
- "out of range value given" :
- "time skipped when clock springs forward");
- }
- }
- /*
- ** Entire command line has now been checked.
- */
- if (aflag) {
-#ifdef DST_NONE
- struct timeval tv;
-
- tv.tv_sec = (int) adjust;
- tv.tv_usec = (int) ((adjust - tv.tv_sec) * 1000000);
- if (adjtime(&tv, (struct timeval *) NULL) != 0)
- oops("date: error: adjtime");
-#endif /* defined DST_NONE */
-#ifndef DST_NONE
- reset((time_t) (now + adjust), nflag);
-#endif /* !defined DST_NONE */
- /*
- ** Sun silently ignores everything else; we follow suit.
- */
- (void) exit(retval);
- }
- if (dflag || tflag) {
-#ifdef DST_NONE
- struct timezone tz;
-
- if (!dflag || !tflag)
- if (gettimeofday((struct timeval *) NULL, &tz) != 0)
- oops("date: error: gettimeofday");
- if (dflag)
- tz.tz_dsttime = dsttime;
- if (tflag)
- tz.tz_minuteswest = minuteswest;
- if (settimeofday((struct timeval *) NULL, &tz) != 0)
- oops("date: error: settimeofday");
-#endif /* defined DST_NONE */
-#ifndef DST_NONE
- (void) fprintf(stderr,
-"date: warning: kernel doesn't keep -d/-t information, option ignored\n");
-#endif /* !defined DST_NONE */
- }
-
- if (value == NULL)
- display(format);
-
- reset(t, nflag);
-
- checkfinal(value, dousg, t, now);
-
-#ifdef EBUG
- {
- struct tm tm;
-
- tm = *localtime(&t);
- timeout(stdout, "%c\n", &tm);
- (void) exit(retval);
- }
-#endif /* defined EBUG */
-
- display(format);
-
- /* gcc -Wall pacifier */
- for ( ; ; )
- continue;
-}
-
-static void
-dogmt()
-{
- static char ** fakeenv;
-
- if (fakeenv == NULL) {
- register int from, to, n;
-
- for (n = 0; environ[n] != NULL; ++n)
- continue;
- fakeenv = (char **) malloc((alloc_size_T) (n + 2) *
- sizeof *fakeenv);
- if (fakeenv == NULL) {
- (void) perror("Memory exhausted");
- errensure();
- (void) exit(retval);
- }
- to = 0;
- fakeenv[to++] = "TZ=GMT0";
- for (from = 1; environ[from] != NULL; ++from)
- if (strncmp(environ[from], "TZ=", 3) != 0)
- fakeenv[to++] = environ[from];
- fakeenv[to] = NULL;
- environ = fakeenv;
- }
-}
-
-#ifdef OLD_TIME
-
-/*
-** We assume we're on a System-V-based system,
-** should use stime,
-** should write System-V-format utmp entries,
-** and don't have network notification to worry about.
-*/
-
-#include "fcntl.h" /* for O_WRONLY, O_APPEND */
-
-/*ARGSUSED*/
-static void
-reset(newt, nflag)
-const time_t newt;
-const int nflag;
-{
- register int fid;
- time_t oldt;
- static struct {
- struct utmp before;
- struct utmp after;
- } s;
-
- /*
- ** Wouldn't it be great if stime returned the old time?
- */
- (void) time(&oldt);
- if (stime(&newt) != 0)
- oops("date: error: stime");
- s.before.ut_type = OLD_TIME;
- s.before.ut_time = oldt;
- (void) strcpy(s.before.ut_line, OTIME_MSG);
- s.after.ut_type = NEW_TIME;
- s.after.ut_time = newt;
- (void) strcpy(s.after.ut_line, NTIME_MSG);
- fid = open(WTMP_FILE, O_WRONLY | O_APPEND);
- if (fid < 0)
- oops("date: error: log file open");
- if (write(fid, (char *) &s, sizeof s) != sizeof s)
- oops("date: error: log file write");
- if (close(fid) != 0)
- oops("date: error: log file close");
- pututline(&s.before);
- pututline(&s.after);
-}
-
-#endif /* defined OLD_TIME */
-#ifndef OLD_TIME
-
-/*
-** We assume we're on a BSD-based system,
-** should use settimeofday,
-** should write BSD-format utmp entries (using logwtmp),
-** and may get to worry about network notification.
-** The "time name" changes between 4.3-tahoe and 4.4;
-** we include sys/param.h to determine which we should use.
-*/
-
-#ifndef TIME_NAME
-#include "sys/param.h"
-#ifdef BSD4_4
-#define TIME_NAME "date"
-#endif /* defined BSD4_4 */
-#ifndef BSD4_4
-#define TIME_NAME ""
-#endif /* !defined BSD4_4 */
-#endif /* !defined TIME_NAME */
-
-#include "syslog.h"
-#include "sys/socket.h"
-#include "netinet/in.h"
-#include "netdb.h"
-#define TSPTYPES
-#include "protocols/timed.h"
-
-#ifndef TSP_SETDATE
-/*ARGSUSED*/
-#endif /* !defined TSP_SETDATE */
-static void
-reset(newt, nflag)
-const time_t newt;
-const int nflag;
-{
- register const char * username;
- static struct timeval tv; /* static so tv_usec is 0 */
-
-#ifdef EBUG
- return;
-#endif /* defined EBUG */
- username = getlogin();
- if (username == NULL || *username == '\0') /* single-user or no tty */
- username = "root";
- tv.tv_sec = newt;
-#ifdef TSP_SETDATE
- if (nflag || !netsettime(tv))
-#endif /* defined TSP_SETDATE */
- {
- /*
- ** "old" entry is always written, for compatibility.
- */
- logwtmp("|", TIME_NAME, "");
- if (settimeofday(&tv, (struct timezone *) NULL) == 0) {
- logwtmp("{", TIME_NAME, ""); /* } */
- syslog(LOG_AUTH | LOG_NOTICE, "date set by %s",
- username);
- } else oops("date: error: settimeofday");
- }
-}
-
-#endif /* !defined OLD_TIME */
-
-static void
-wildinput(item, value, reason)
-const char * const item;
-const char * const value;
-const char * const reason;
-{
- (void) fprintf(stderr, "date: error: bad command line %s \"%s\", %s\n",
- item, value, reason);
- usage();
-}
-
-static void
-errensure P((void))
-{
- if (retval == EXIT_SUCCESS)
- retval = EXIT_FAILURE;
-}
-
-static const char *
-nondigit(cp)
-register const char * cp;
-{
- while (isdigit(*cp))
- ++cp;
- return cp;
-}
-
-static void
-usage P((void))
-{
- (void) fprintf(stderr, "date: usage is date ");
- (void) fprintf(stderr, "[-u] ");
- (void) fprintf(stderr, "[-c] ");
- (void) fprintf(stderr, "[-n] ");
- (void) fprintf(stderr, "[-d dst] ");
- (void) fprintf(stderr, "[-t min-west] ");
- (void) fprintf(stderr, "[-a sss.fff] ");
- (void) fprintf(stderr, "[[yyyy]mmddhhmm[yyyy][.ss]] ");
- (void) fprintf(stderr, "[+format]\n");
- errensure();
- (void) exit(retval);
-}
-
-static void
-oops(string)
-const char * const string;
-{
- (void) perror(string);
- errensure();
- display((char *) NULL);
-}
-
-static void
-display(format)
-const char * const format;
-{
- struct tm tm;
- time_t now;
-
- (void) time(&now);
- tm = *localtime(&now);
- if (format == NULL) {
- timeout(stdout, "%a %b ", &tm);
- (void) printf("%2d ", tm.tm_mday);
- timeout(stdout, "%X %Z %Y", &tm);
- } else timeout(stdout, format, &tm);
- (void) putchar('\n');
- (void) fflush(stdout);
- (void) fflush(stderr);
- if (ferror(stdout) || ferror(stderr)) {
- (void) fprintf(stderr,
- "date: error: couldn't write results\n");
- errensure();
- }
- (void) exit(retval);
-}
-
-extern size_t strftime();
-
-#define INCR 1024
-
-static void
-timeout(fp, format, tmp)
-FILE * const fp;
-const char * const format;
-const struct tm * const tmp;
-{
- char * cp;
- size_t result;
- size_t size;
-
- if (*format == '\0')
- return;
- size = INCR;
- cp = malloc((alloc_size_T) size);
- for ( ; ; ) {
- if (cp == NULL) {
- (void) fprintf(stderr,
- "date: error: can't get memory\n");
- errensure();
- (void) exit(retval);
- }
- result = strftime(cp, size, format, tmp);
- if (result != 0)
- break;
- size += INCR;
- cp = realloc(cp, (alloc_size_T) size);
- }
- (void) fwrite(cp, 1, result, fp);
- free(cp);
-}
-
-static int
-comptm(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
-{
- register int result;
-
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
-}
-
-/*
-** convert --
-** convert user's input into a time_t.
-*/
-
-#define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2;
-
-static time_t
-convert(value, dousg, t)
-register const char * const value;
-const int dousg;
-const time_t t;
-{
- register const char * cp;
- register char * dotp;
- register int cent, year_in_cent, month, hour, day, mins, secs;
- struct tm tm, outtm;
- time_t outt;
-
- tm = *localtime(&t);
- cent = (tm.tm_year + TM_YEAR_BASE) / 100;
- year_in_cent = (tm.tm_year + TM_YEAR_BASE) - cent * 100;
- month = tm.tm_mon + 1;
- day = tm.tm_mday;
- hour = tm.tm_hour;
- mins = tm.tm_min;
- secs = 0;
-
- dotp = strchr(value, '.');
- for (cp = value; *cp != '\0'; ++cp)
- if (!isdigit(*cp) && cp != dotp)
- wildinput("time", value, "contains a nondigit");
-
- if (dotp == NULL)
- dotp = strchr(value, '\0');
- else {
- cp = dotp + 1;
- if (strlen(cp) != 2)
- wildinput("time", value,
- "seconds part is not two digits");
- secs = ATOI2(cp);
- }
-
- cp = value;
- switch (dotp - cp) {
- default:
- wildinput("time", value, "main part is wrong length");
- case 12:
- if (!dousg) {
- cent = ATOI2(cp);
- year_in_cent = ATOI2(cp);
- }
- month = ATOI2(cp);
- day = ATOI2(cp);
- hour = ATOI2(cp);
- mins = ATOI2(cp);
- if (dousg) {
- cent = ATOI2(cp);
- year_in_cent = ATOI2(cp);
- }
- break;
- case 8: /* mmddhhmm */
- month = ATOI2(cp);
- /* fall through to. . . */
- case 6: /* ddhhmm */
- day = ATOI2(cp);
- /* fall through to. . . */
- case 4: /* hhmm */
- hour = ATOI2(cp);
- mins = ATOI2(cp);
- break;
- case 10:
- if (!dousg) {
- year_in_cent = ATOI2(cp);
- }
- month = ATOI2(cp);
- day = ATOI2(cp);
- hour = ATOI2(cp);
- mins = ATOI2(cp);
- if (dousg) {
- year_in_cent = ATOI2(cp);
- }
- break;
- }
-
- tm.tm_year = cent * 100 + year_in_cent - TM_YEAR_BASE;
- tm.tm_mon = month - 1;
- tm.tm_mday = day;
- tm.tm_hour = hour;
- tm.tm_min = mins;
- tm.tm_sec = secs;
- tm.tm_isdst = -1;
- outtm = tm;
- outt = mktime(&outtm);
- return (comptm(&tm, &outtm) == 0) ? outt : -1;
-}
-
-/*
-** Code from here on out is either based on code provided by UCB
-** or is only called just before the program exits.
-*/
-
-/*
-** Check for iffy input.
-*/
-
-static void
-checkfinal(value, didusg, t, oldnow)
-const char * const value;
-const int didusg;
-const time_t t;
-const time_t oldnow;
-{
- time_t othert;
- struct tm tm;
- struct tm othertm;
- register int pass;
- register long offset;
-
- /*
- ** See if there's both a USG and a BSD interpretation.
- */
- othert = convert(value, !didusg, oldnow);
- if (othert != -1 && othert != t)
- iffy(t, othert, value, "year could be at start or end");
- /*
- ** See if there's both a DST and a STD version.
- */
- tm = *localtime(&t);
- othertm = tm;
- othertm.tm_isdst = !tm.tm_isdst;
- othert = mktime(&othertm);
- if (othert != -1 && othertm.tm_isdst != tm.tm_isdst &&
- comptm(&tm, &othertm) == 0)
- iffy(t, othert, value,
- "both standard and summer time versions exist");
-/*
-** Final check.
-**
-** If a jurisdiction shifts time *without* shifting whether time is
-** summer or standard (as Hawaii, the United Kingdom, and Saudi Arabia
-** have done), routine checks for iffy times may not work.
-** So we perform this final check, deferring it until after the time has
-** been set--it may take a while, and we don't want to introduce an unnecessary
-** lag between the time the user enters their command and the time that
-** stime/settimeofday is called.
-**
-** We just check nearby times to see if any have the same representation
-** as the time that convert returned. We work our way out from the center
-** for quick response in solar time situations. We only handle common cases--
-** offsets of at most a minute, and offsets of exact numbers of minutes
-** and at most an hour.
-*/
- for (offset = 1; offset <= 60; ++offset)
- for (pass = 1; pass <= 4; ++pass) {
- if (pass == 1)
- othert = t + offset;
- else if (pass == 2)
- othert = t - offset;
- else if (pass == 3)
- othert = t + 60 * offset;
- else othert = t - 60 * offset;
- othertm = *localtime(&othert);
- if (comptm(&tm, &othertm) == 0)
- iffy(t, othert, value,
- "multiple matching times exist");
- }
-}
-
-static void
-iffy(thist, thatt, value, reason)
-const time_t thist;
-const time_t thatt;
-const char * const value;
-const char * const reason;
-{
- struct tm tm;
-
- (void) fprintf(stderr, "date: warning: ambiguous time \"%s\", %s.\n",
- value, reason);
- tm = *gmtime(&thist);
- (void) fprintf(stderr, "Time was set as if you used\n");
- /*
- ** Avoid running afoul of SCCS!
- */
- timeout(stderr, "\tdate -u ", &tm);
- timeout(stderr, "%m%d%H", &tm);
- timeout(stderr, "%M", &tm);
- timeout(stderr, "%Y.%S\n", &tm);
- tm = *localtime(&thist);
- timeout(stderr, "to get %c", &tm);
- (void) fprintf(stderr, " (%s time)",
- tm.tm_isdst ? "summer" : "standard");
- (void) fprintf(stderr, ". Use\n");
- tm = *gmtime(&thatt);
- timeout(stderr, "\tdate -u ", &tm);
- timeout(stderr, "%m%d%H", &tm);
- timeout(stderr, "%M", &tm);
- timeout(stderr, "%Y.%S\n", &tm);
- tm = *localtime(&thatt);
- timeout(stderr, "to get %c", &tm);
- (void) fprintf(stderr, " (%s time)",
- tm.tm_isdst ? "summer" : "standard");
- (void) fprintf(stderr, ".\n");
- errensure();
- (void) exit(retval);
-}
-
-#ifdef TSP_SETDATE
-#define WAITACK 2 /* seconds */
-#define WAITDATEACK 5 /* seconds */
-
-#ifndef errno
-extern int errno;
-#endif /* !defined errno */
-/*
- * Set the date in the machines controlled by timedaemons
- * by communicating the new date to the local timedaemon.
- * If the timedaemon is in the master state, it performs the
- * correction on all slaves. If it is in the slave state, it
- * notifies the master that a correction is needed.
- * Returns 1 on success, 0 on failure.
- */
-netsettime(ntv)
- struct timeval ntv;
-{
- int s, length, port, timed_ack, found, err;
- long waittime;
- fd_set ready;
- char hostname[MAXHOSTNAMELEN];
- struct timeval tout;
- struct servent *sp;
- struct tsp msg;
- struct sockaddr_in sin, dest, from;
-
- sp = getservbyname("timed", "udp");
- if (sp == 0) {
- fputs("udp/timed: unknown service\n", stderr);
- retval = 2;
- return (0);
- }
- dest.sin_port = sp->s_port;
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- if (errno != EPROTONOSUPPORT)
- perror("date: socket");
- goto bad;
- }
- bzero((char *)&sin, sizeof (sin));
- sin.sin_family = AF_INET;
- for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
- sin.sin_port = htons((u_short)port);
- if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
- break;
- if (errno != EADDRINUSE) {
- if (errno != EADDRNOTAVAIL)
- perror("date: bind");
- goto bad;
- }
- }
- if (port == IPPORT_RESERVED / 2) {
- fputs("date: All ports in use\n", stderr);
- goto bad;
- }
- msg.tsp_type = TSP_SETDATE;
- msg.tsp_vers = TSPVERSION;
- if (gethostname(hostname, sizeof (hostname))) {
- perror("gethostname");
- goto bad;
- }
- (void) strncpy(msg.tsp_name, hostname, sizeof (hostname));
- msg.tsp_seq = htons((u_short)0);
- msg.tsp_time.tv_sec = htonl((u_long)ntv.tv_sec);
- msg.tsp_time.tv_usec = htonl((u_long)ntv.tv_usec);
- length = sizeof (struct sockaddr_in);
- if (connect(s, &dest, length) < 0) {
- perror("date: connect");
- goto bad;
- }
- if (send(s, (char *)&msg, sizeof (struct tsp), 0) < 0) {
- if (errno != ECONNREFUSED)
- perror("date: send");
- goto bad;
- }
- timed_ack = -1;
- waittime = WAITACK;
-loop:
- tout.tv_sec = waittime;
- tout.tv_usec = 0;
- FD_ZERO(&ready);
- FD_SET(s, &ready);
- found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
- length = sizeof(err);
- if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length) == 0
- && err) {
- errno = err;
- if (errno != ECONNREFUSED)
- perror("date: send (delayed error)");
- goto bad;
- }
- if (found > 0 && FD_ISSET(s, &ready)) {
- length = sizeof (struct sockaddr_in);
- if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &from,
- &length) < 0) {
- if (errno != ECONNREFUSED)
- perror("date: recvfrom");
- goto bad;
- }
- msg.tsp_seq = ntohs(msg.tsp_seq);
- msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
- msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
- switch (msg.tsp_type) {
-
- case TSP_ACK:
- timed_ack = TSP_ACK;
- waittime = WAITDATEACK;
- goto loop;
-
- case TSP_DATEACK:
- (void)close(s);
- return (1);
-
- default:
- fprintf(stderr,
- "date: Wrong ack received from timed: %s\n",
- tsptype[msg.tsp_type]);
- timed_ack = -1;
- break;
- }
- }
- if (timed_ack == -1)
- fputs("date: Can't reach time daemon, time set locally.\n",
- stderr);
-bad:
- (void)close(s);
- retval = 2;
- return (0);
-}
-#endif /* defined TSP_SETDATE */
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)difftime.c 7.5";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-
-/*
-** Algorithm courtesy Paul Eggert (eggert@twinsun.com).
-*/
-
-#ifdef HAVE_LONG_DOUBLE
-#define long_double long double
-#endif /* defined HAVE_LONG_DOUBLE */
-#ifndef HAVE_LONG_DOUBLE
-#define long_double double
-#endif /* !defined HAVE_LONG_DOUBLE */
-
-double
-difftime(time1, time0)
-const time_t time1;
-const time_t time0;
-{
- time_t delta;
- time_t hibit;
-
- if (sizeof(time_t) < sizeof(double))
- return (double) time1 - (double) time0;
- if (sizeof(time_t) < sizeof(long_double))
- return (long_double) time1 - (long_double) time0;
- if (time1 < time0)
- return -difftime(time0, time1);
- /*
- ** As much as possible, avoid loss of precision
- ** by computing the difference before converting to double.
- */
- delta = time1 - time0;
- if (delta >= 0)
- return delta;
- /*
- ** Repair delta overflow.
- */
- hibit = 1;
- while ((hibit <<= 1) > 0)
- continue;
- /*
- ** The following expression rounds twice, which means
- ** the result may not be the closest to the true answer.
- ** For example, suppose time_t is 64-bit signed int,
- ** long_double is IEEE 754 double with default rounding,
- ** time1 = 9223372036854775807 and time0 = -1536.
- ** Then the true difference is 9223372036854777343,
- ** which rounds to 9223372036854777856
- ** with a total error of 513.
- ** But delta overflows to -9223372036854774273,
- ** which rounds to -9223372036854774784, and correcting
- ** this by subtracting 2 * (long_double) hibit
- ** (i.e. by adding 2**64 = 18446744073709551616)
- ** yields 9223372036854776832, which
- ** rounds to 9223372036854775808
- ** with a total error of 1535 instead.
- ** This problem occurs only with very large differences.
- ** It's too painful to fix this portably.
- ** We are not alone in this problem;
- ** many C compilers round twice when converting
- ** large unsigned types to small floating types,
- ** so if time_t is unsigned the "return delta" above
- ** has the same double-rounding problem.
- */
- return delta - 2 * (long_double) hibit;
-}
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)emkdir.c 8.23";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#ifndef emkdir
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-
-extern char * imalloc P((int n));
-extern void ifree P((char * p));
-
-static char *
-quoted(name)
-register const char * name;
-{
- register char * result;
- register char * cp;
- register int c;
-
- if (name == NULL)
- name = "";
- result = imalloc((int) (4 * strlen(name) + 3));
- if (result == NULL)
- return NULL;
- cp = result;
-#ifdef unix
- *cp++ = '\'';
- while ((c = *name++) != '\0')
- if (c == '\'') {
- *cp++ = c;
- *cp++ = '\\';
- *cp++ = c;
- *cp++ = c;
- } else *cp++ = c;
- *cp++ = '\'';
-#endif /* defined unix */
-#ifndef unix
- while ((c = *name++) != '\0')
- if (c == '/')
- *cp++ = '\\';
- else *cp++ = c;
-#endif /* !defined unix */
- *cp = '\0';
- return result;
-}
-
-int
-emkdir(name, mode)
-const char * name;
-const int mode;
-{
- register int result;
- register const char * format;
- register char * command;
- register char * qname;
-
- if ((qname = quoted(name)) == NULL)
- return -1;
-#ifdef unix
- format = "mkdir 2>&- %s && chmod 2>&- %o %s";
-#endif /* defined unix */
-#ifndef unix
- format = "mkdir %s";
-#endif /* !defined unix */
- command = imalloc((int) (strlen(format) + 2 * strlen(qname) + 20 + 1));
- if (command == NULL) {
- ifree(qname);
- return -1;
- }
- (void) sprintf(command, format, qname, mode, qname);
- ifree(qname);
- result = system(command);
- ifree(command);
- return (result == 0) ? 0 : -1;
-}
-
-/*
-** UNIX was a registered trademark of UNIX System Laboratories in 1993.
-*/
-
-#endif /* !defined emkdir */
+++ /dev/null
-# @(#)etcetera 7.4
-
-# All of these are set up just so people can "zic -l" to a timezone
-# that's right for their area, even if it doesn't have a name or DST rules
-# (half hour zones are too much to bother with -- when someone asks!)
-
-Zone Etc/GMT 0 - GMT
-Link Etc/GMT Etc/UTC
-Link Etc/GMT Etc/UCT
-Link Etc/GMT Etc/Universal
-Link Etc/GMT Etc/Greenwich
-Link Etc/GMT Etc/Zulu
-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-13 13 - GMT-13 # 12 hours ahead of GMT, plus DST
-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
-# @(#)europe 7.17
-
-# 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> (November 18, 1993):
-# 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.
-#
-# 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.
-# The starred Russian names are dubious. Corrections are welcome!
-# std dst
-# LMT Local Mean Time
-# LST Local Star Time (Russian ``mestnoe zvezdnoe vremya'')
-# -4:00 AST Atlantic
-# -3:00 WGT+DST Western Greenland*
-# -2:00 MGT+DST Middle Greenland*
-# -1:00 EGT+DST Eastern Greenland*
-# -1:00 ACT+DST Azores and Canaries*
-# -1:00 IST IDT Iceland (no longer used)*
-# 0:00 GMT BST Greenwich, British Summer
-# 0:00 WET+DST Western Europe
-# 1:00 MET+DST Middle Europe
-# 2:00 EET+DST Eastern Europe
-# 3:00 MSK MSD Moscow
-# 3:00 TUR+DST Turkey (no longer used)*
-# 4:00 KSK KSD Kuybyshev*
-# 5:00 ESK ESD Yekaterinburg*
-# 6:00 OSK OSD Omsk*
-# 6:00 NSK NSD Novosibirsk (was 7:00 until 1994)
-# 7:00 TSK TSD Tomsk*
-# 8:00 ISK ISD Irkutsk*
-# 9:00 YSK YSD Yakutsk*
-# 10:00 VSK VSD Vladivostok*
-# 11:00 GSK GSD Magadan*
-# 12:00 PSK PSD Petropavlovsk-Kamchatski*
-# 13:00 ASK ASD Anadyr*
-#
-# See the `africa' file for Zone naming 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 Andrew A. Chernov <ache@astral.msk.su> (November 12, 1993):
-# LST is Local Star Time (``mestnoe zvezdnoe vremya'').
-
-# From Peter Ilieve <peter@memex.co.uk> (December 4, 1994),
-# The original six [EU members]: Belguim, 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.)
-# ...
-# The only [current nonmember using EU rules] I can speak for is Estonia,
-# which 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
-
-# From Peter Ilieve <peter@memex.co.uk> (July 6, 1994):
-#
-# 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 longditude
-# 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 longditude 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> (November 18, 1993):
-#
-# 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 Arthur David Olson (January 19, 1989):
-#
-# 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> (September 3, 1993):
-#
-# 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 Statutary Instrument, the SI thing mentioned above)
-# to specify the EC specified dates.
-
-# From Peter Ilieve <peter@memex.co.uk> (October 18, 1993):
-#
-# 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 Peter Ilieve <peter@memex.co.uk> (September 3, 1993):
-#
-# > # 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> (October 22, 1993):
-#
-# 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> (October 28, 1993):
-#
-# 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> (October 29, 1993):
-#
-# 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 == Statutary 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 == Statutary 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@memex.co.uk> (November 18, 1993)
-#
-# 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> (August 18, 1994):
-# 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@memex.co.uk> (March 28, 1994):
-# The UK/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> (November 18, 1993):
-#
-# 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.
-#
-# The following claim by Shanks is possible though doubtful;
-# we'll ignore it 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.
-#
-# Whitman says Dublin Mean Time was -0:25:21, which is more precise than Shanks.
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule GB-Eire 1847 only - Sep 22 0:00 0 GMT
-# 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 DST
-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 DST
-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 DST
-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 DST
-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 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 1967 - Oct Sun>=23 2:00s 0 GMT
-Rule GB-Eire 1971 only - Oct 31 3:00 0 GMT
-Rule GB-Eire 1972 1980 - Oct Sun>=23 2:00s 0 GMT
-# 1981 on
-Rule GB-Eire 1981 max - Mar lastSun 1:00s 1:00 BST
-Rule GB-Eire 1981 1989 - Oct Sun>=23 1:00s 0 GMT
-Rule GB-Eire 1990 1995 - Oct Sun>=22 1:00s 0 GMT
-Rule GB-Eire 1996 max - Oct lastSun 1:00s 0 GMT
-#Rule GB-Eire 1981 max - 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
-#Rule GB-Eire 1996 max - Oct lastSun 1:00u 0 GMT
-# Also see W-Eur, which (starting 1996) differs only in LETTER/S.
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/London -0:01:15 - LMT 1847 Sep 22
- 0:00 GB-Eire %s 1968 Feb 18 2:00
- 1:00 - BST 1971 Oct 31 2:00
- 0:00 GB-Eire %s
-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 DST 1916 Oct 1 3:00
- 0:00 GB-Eire %s 1968 Feb 18 2:00
- 1:00 - BST 1971 Oct 31 3:00
- 0:00 GB-Eire %s
-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 DST 1916 Oct 1 3:00
- 0:00 GB-Eire %s 1940 Feb 25 2:00
- 0:00 1:00 BST 1946 Oct 6 2:00
- 0:00 - GMT 1947 Mar 16 2:00
- 0:00 1:00 BST 1947 Nov 2 2:00
- 0:00 - GMT 1948 Apr 18 2:00
- 0:00 GB-Eire %s 1968 Feb 18 2:00
- 1:00 - BST 1971 Oct 31 3:00
- 0:00 GB-Eire %s
-
-###############################################################################
-
-# Continental Europe
-
-# The *-Eur rules now correspond to the European Community (EC).
-# Three rulesets are used because the EC changes at 01:00 UTC, not local time.
-# Older *-Eur rules are for convenience in the tables.
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule W-Eur 1800 only - Jan 1 0:00 0 -
-Rule W-Eur 1977 1980 - Apr Sun>=1 1:00s 1:00 " DST"
-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 " DST"
-Rule W-Eur 1996 max - Oct lastSun 1:00s 0 -
-# Also see GB-Eire, which (starting 1996) differs only in LETTER/S.
-
-Rule M-Eur 1800 only - Jan 1 0:00 0 -
-Rule M-Eur 1916 only - Apr 30 23:00 1:00 " DST"
-Rule M-Eur 1916 only - Oct 1 1:00 0 -
-Rule M-Eur 1917 1918 - Apr Mon>=15 2:00s 1:00 " DST"
-Rule M-Eur 1917 1918 - Sep Mon>=15 2:00s 0 -
-Rule M-Eur 1940 only - Apr 1 2:00s 1:00 " DST"
-# Shanks says DST was continuous from 1940 Apr 1 to 1942 Nov 2; go with Whitman.
-Rule M-Eur 1940 only - Dec 31 2:00s 0 -
-Rule M-Eur 1941 only - Feb 25 2:00s 1:00 " DST"
-Rule M-Eur 1941 only - Oct 5 2:00s 0 -
-Rule M-Eur 1942 only - Jan 1 2:00s 1:00 " DST"
-Rule M-Eur 1942 only - Nov 2 2:00s 0 -
-Rule M-Eur 1943 only - Mar 29 2:00s 1:00 " DST"
-Rule M-Eur 1943 only - Oct 4 2:00s 0 -
-Rule M-Eur 1944 only - Apr 3 2:00s 1:00 " DST"
-# Whitman gives 1944 Oct 7; go with Shanks.
-Rule M-Eur 1944 only - Oct 2 2:00s 0 -
-Rule M-Eur 1977 1980 - Apr Sun>=1 2:00s 1:00 " DST"
-Rule M-Eur 1977 only - Sep lastSun 2:00s 0 -
-Rule M-Eur 1978 only - Oct 1 2:00s 0 -
-Rule M-Eur 1979 1995 - Sep lastSun 2:00s 0 -
-Rule M-Eur 1981 max - Mar lastSun 2:00s 1:00 " DST"
-Rule M-Eur 1996 max - Oct lastSun 2:00s 0 -
-
-Rule E-Eur 1981 max - Mar lastSun 3:00s 1:00 " DST"
-Rule E-Eur 1981 1995 - Sep lastSun 3:00s 0 -
-Rule E-Eur 1996 max - Oct lastSun 3:00s 0 -
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Russia 1880 only - Jan 1 0:00 0 -
-Rule Russia 1917 only - Jul 1 23:00 1:00 " DST"
-Rule Russia 1917 only - Dec 28 0:00 0 -
-Rule Russia 1918 only - May 31 22:00 2:00 " DDST"
-Rule Russia 1918 only - Sep 17 0:00 1:00 " DST"
-Rule Russia 1919 only - May 31 23:00 2:00 " DDST"
-Rule Russia 1919 only - Jul 1 2:00 1:00 D
-Rule Russia 1919 only - Aug 16 0:00 0 K
-Rule Russia 1921 only - Feb 14 23:00 1:00 D
-# Shanks gives 1921 Mar 21 for the following transition.
-# From Andrew A. Chernov <ache@astral.msk.su> (November 12, 1993):
-# My sources says, that it is Mar 20, not 21.
-Rule Russia 1921 only - Mar 20 23:00 2:00 DD
-Rule Russia 1921 only - Sep 1 0:00 1:00 D
-Rule Russia 1921 only - Oct 1 0:00 0 K
-Rule Russia 1981 1984 - Apr 1 0:00 1:00 D
-Rule Russia 1981 1983 - Oct 1 0:00 0 K
-Rule Russia 1984 max - Sep lastSun 2:00s 0 K
-Rule Russia 1985 max - Mar lastSun 2:00s 1:00 D
-
-# These are for backward compatibility with older versions.
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone WET 0:00 W-Eur WET%s
-Zone MET 1:00 M-Eur MET%s
-Zone EET 2:00 E-Eur EET%s
-Zone W-SU 3:00 M-Eur ????
-
-# Tom Hoffman says that MET is also known as Central European Time
-
-Link MET CET
-
-# Albania
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Albania 1940 only - Jun 16 0:00 1:00 " DST"
-Rule Albania 1942 only - Nov 2 3:00 0 -
-Rule Albania 1943 only - Mar 29 2:00 1:00 " DST"
-Rule Albania 1943 only - Apr 10 3:00 0 -
-Rule Albania 1974 only - May 4 0:00 1:00 " DST"
-Rule Albania 1974 only - Oct 2 0:00 0 -
-Rule Albania 1975 only - May 1 0:00 1:00 " DST"
-Rule Albania 1975 only - Oct 2 0:00 0 -
-Rule Albania 1976 only - May 2 0:00 1:00 " DST"
-Rule Albania 1976 only - Oct 3 0:00 0 -
-Rule Albania 1977 only - May 8 0:00 1:00 " DST"
-Rule Albania 1977 only - Oct 2 0:00 0 -
-Rule Albania 1978 only - May 6 0:00 1:00 " DST"
-Rule Albania 1978 only - Oct 1 0:00 0 -
-Rule Albania 1979 only - May 5 0:00 1:00 " DST"
-Rule Albania 1979 only - Sep 30 0:00 0 -
-Rule Albania 1980 only - May 3 0:00 1:00 " DST"
-Rule Albania 1980 only - Oct 4 0:00 0 -
-Rule Albania 1981 only - Apr 26 0:00 1:00 " DST"
-Rule Albania 1981 only - Sep 27 0:00 0 -
-Rule Albania 1982 only - May 2 0:00 1:00 " DST"
-Rule Albania 1982 only - Oct 3 0:00 0 -
-Rule Albania 1983 only - Apr 18 0:00 1:00 " DST"
-Rule Albania 1983 only - Oct 1 0:00 0 -
-Rule Albania 1984 only - Apr 1 0:00 1:00 " DST"
-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 - MET 1940 Jun 16
- 1:00 Albania MET%s 1985 Mar 31 1:00
- 1:00 W-Eur MET%s
-# This may change to `M-Eur' soon, for EC compatibility.
-
-# Andorra
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Andorra 0:06:04 - LMT 1901
- 0:00 - WET 1946 Sep 30
- 1:00 - MET 1985 Mar 31 2:00
- 1:00 M-Eur MET%s
-
-# Austria
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Austria 1918 only - Jun 16 3:00 0 -
-Rule Austria 1920 only - Apr 5 2:00s 1:00 " DST"
-Rule Austria 1920 only - Sep 13 2:00s 0 -
-Rule Austria 1945 only - Apr 2 2:00s 1:00 " DST"
-Rule Austria 1945 only - Nov 18 2:00s 0 -
-Rule Austria 1946 only - Apr 14 2:00s 1:00 " DST"
-Rule Austria 1946 1948 - Oct Sun>=1 2:00s 0 -
-Rule Austria 1947 only - Apr 6 2:00s 1:00 " DST"
-Rule Austria 1948 only - Apr 18 2:00s 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Vienna 1:05:20 - LMT 1893 Apr
- 1:00 M-Eur MET%s 1918 Jun 16 3:00
- 1:00 Austria MET%s 1940 Apr 1 2:00
- 1:00 M-Eur MET%s 1945 Apr 2 2:00
- 1:00 Austria MET%s 1981 Mar 29 2:00
- 1:00 M-Eur MET%s
-
-# Belarus
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Minsk 1:50:16 - LMT 1880
- 2:31 Russia LST%s 1919 Jul 1 2:00
- 3:00 Russia MS%s 1922 Oct
- 2:00 - EET 1930 Jun 21
- 3:00 Russia MS%s 1991 Mar 31 2:00s
-# From Paul Eggert <eggert@twinsun.com> (May 28, 1994): A guess at recent dates:
- 2:00 1:00 "EET DST" 1991 Sep 29 2:00s
- 2:00 - EET 1992 Jan 19 2:00s
- 3:00 Russia MS%s
-
-# 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 " DST"
-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 " DST"
-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 " DST"
-# 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 " DST"
-Rule Belgium 1924 only - Mar 29 23:00s 1:00 " DST"
-Rule Belgium 1925 only - Apr 4 23:00s 1:00 " DST"
-Rule Belgium 1926 only - Apr 17 23:00s 1:00 " DST"
-Rule Belgium 1927 only - Apr 9 23:00s 1:00 " DST"
-Rule Belgium 1928 only - Apr 14 23:00s 1:00 " DST"
-Rule Belgium 1929 only - Apr 21 2:00s 1:00 " DST"
-Rule Belgium 1929 1938 - Oct Sun>=2 2:00s 0 -
-Rule Belgium 1930 only - Apr 13 2:00s 1:00 " DST"
-Rule Belgium 1931 only - Apr 19 2:00s 1:00 " DST"
-Rule Belgium 1932 only - Apr 17 2:00s 1:00 " DST"
-Rule Belgium 1933 only - Mar 26 2:00s 1:00 " DST"
-Rule Belgium 1934 only - Apr 8 2:00s 1:00 " DST"
-Rule Belgium 1935 only - Mar 31 2:00s 1:00 " DST"
-Rule Belgium 1936 only - Apr 19 2:00s 1:00 " DST"
-# Whitman says 1937 Apr 18 2:00s; go with Shanks.
-Rule Belgium 1937 only - Apr 4 2:00s 1:00 " DST"
-# Whitman says 1938 Apr 10 2:00s; go with Shanks.
-Rule Belgium 1938 only - Mar 27 2:00s 1:00 " DST"
-Rule Belgium 1939 only - Apr 16 2:00s 1:00 " DST"
-Rule Belgium 1939 only - Nov 19 2:00s 0 -
-Rule Belgium 1945 only - Apr 2 2:00s 1:00 " DST"
-Rule Belgium 1945 only - Sep 16 2:00s 0 -
-Rule Belgium 1946 only - May 19 2:00s 1:00 " DST"
-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 - BST 1892 May 1 12:00
- 0:00 - WET 1914 Aug 4
- 1:00 M-Eur MET%s 1919 Mar 1 23:00
- 0:00 Belgium WET%s 1940 Feb 24 23:00
- 1:00 M-Eur MET%s 1945 Apr 2 2:00
- 1:00 Belgium MET%s 1977 Apr 3 2:00
- 1:00 M-Eur MET%s
-
-# Bosnia and Herzegovina
-# They switched from the Julian to the Gregorian calendar on 1918 Mar 18.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Sarajevo 1:13:40 - LMT 1884
- 1:00 - MET 1941 Apr 18 23:00
- 1:00 M-Eur MET%s 1945 May 8 2:00s
- 1:00 1:00 "MET DST" 1945 Sep 16 2:00s
- 1:00 - MET 1983 Mar 27 2:00s
- 1:00 M-Eur MET%s
-
-# Bulgaria
-# Part switched from the Julian to the Gregorian calendar on 1915 Nov 14;
-# the rest switched on 1920 Sep 17.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Bulg 1979 only - Mar 31 23:00 1:00 " DST"
-Rule Bulg 1979 only - Oct 1 1:00 0 -
-Rule Bulg 1980 1982 - Apr Sat<=7 23:00 1:00 " DST"
-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:57 - TST 1894 Nov 30
- 2:00 - EET 1942 Nov 2 3:00
- 1:00 M-Eur MET%s 1945 Apr 2 3:00
- 2:00 - EET 1979 Mar 31 23:00
- 2:00 Bulg EET%s 1982 Sep 26 2:00
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-
-# Croatia
-# They switched from the Julian to the Gregorian calendar on 1918 Mar 18.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Zagreb 1:03:52 - LMT 1884
- 1:00 - MET 1941 Apr 18 23:00
- 1:00 M-Eur MET%s 1945 May 8 2:00s
- 1:00 1:00 "MET DST" 1945 Sep 16 2:00s
- 1:00 - MET 1983 Mar 27 2:00s
- 1:00 M-Eur MET%s
-
-# Czech Republic
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Czech 1944 only - Sep 17 2:00s 0 -
-Rule Czech 1945 only - Apr 8 2:00s 1:00 " DST"
-Rule Czech 1945 only - Nov 18 2:00s 0 -
-Rule Czech 1946 only - May 6 2:00s 1:00 " DST"
-Rule Czech 1946 1949 - Oct Sun>=1 2:00s 0 -
-Rule Czech 1947 only - Apr 20 2:00s 1:00 " DST"
-Rule Czech 1948 only - Apr 18 2:00s 1:00 " DST"
-Rule Czech 1949 only - Apr 9 2:00s 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Prague 0:57:44 - LMT 1850
- 0:58 - PMT 1891 Oct # Prague Mean Time
- 1:00 M-Eur MET%s 1944 Sep 17 2:00s
- 1:00 Czech MET%s 1979 Apr 1 2:00
- 1:00 M-Eur MET%s
-
-# Denmark
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Denmark 1916 only - May 14 23:00 1:00 " DST"
-Rule Denmark 1916 only - Sep 30 23:00 0 -
-Rule Denmark 1940 only - May 15 0:00 1:00 " DST"
-Rule Denmark 1945 only - Apr 2 2:00s 1:00 " DST"
-Rule Denmark 1945 only - Aug 15 2:00s 0 -
-Rule Denmark 1946 only - May 1 2:00s 1:00 " DST"
-Rule Denmark 1946 only - Sep 1 2:00s 0 -
-Rule Denmark 1947 only - May 4 2:00s 1:00 " DST"
-Rule Denmark 1947 only - Aug 10 2:00s 0 -
-Rule Denmark 1948 only - May 9 2:00s 1:00 " DST"
-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 - CMT 1894 Apr # Copenhagen Mean Time
- 1:00 Denmark MET%s 1942 Nov 2 2:00s
- 1:00 M-Eur MET%s 1945 Apr 2 2:00
- 1:00 Denmark MET%s 1980 Apr 6 2:00
- 1:00 M-Eur MET%s
-Zone Atlantic/Faeroe -0:27:04 - LMT 1908 Jan 11 # Torshavn
- 0:00 - WET 1981 Mar 29 1:00
- 0:00 W-Eur WET%s
-Zone America/Scoresbysund -1:29:00 - LMT 1916 Jul 28
- -2:00 - MGT 1980 Apr 6 2:00
- -2:00 M-Eur MGT%s 1981 Mar 29
- -1:00 M-Eur EGT%s
-Zone America/Godthab -3:26:56 - LMT 1916 Jul 28
- -3:00 - WGT 1980 Apr 6 2:00
- -3:00 M-Eur WGT%s
-Zone America/Thule -4:35:08 - LMT 1916 Jul 28
- -4:00 - AST
-
-# Estonia
-# They switched from the Julian to the Gregorian calendar on 1918 Feb 15.
-#
-# 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....
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Tallinn 1:39:00 - LMT 1880
- 1:39 - LST 1918 Feb
- 1:00 M-Eur MET%s 1919 Jul
- 1:39 - LST 1921 May
- 2:00 - EET 1940 Aug 6
- 3:00 - MSK 1941 Sep 15
- 1:00 M-Eur MET%s 1944 Sep 22
- 3:00 Russia MS%s 1989 Mar 26 2:00s
- 2:00 1:00 "EET DST" 1989 Sep 24 2:00s
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-
-# Finland
-#
-# 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 1921 only - May 1 0:00 0 -
-Rule Finland 1942 only - Apr 3 0:00 1:00 " DST"
-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:40 - HMT 1921 May # Helsinki Mean Time
- 2:00 Finland EET%s 1981 Mar 29 2:00
- 2:00 E-Eur EET%s
-
-# France
-# 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 1911 only - Jan 1 0:00 0 -
-Rule France 1916 only - Jun 14 23:00s 1:00 " DST"
-Rule France 1916 1919 - Oct Sun>=1 0:00 0 -
-Rule France 1917 only - Mar 24 23:00s 1:00 " DST"
-Rule France 1918 only - Mar 9 23:00s 1:00 " DST"
-Rule France 1919 only - Mar 1 23:00s 1:00 " DST"
-Rule France 1920 only - Feb 14 23:00s 1:00 " DST"
-Rule France 1920 only - Oct 23 23:00s 0 -
-Rule France 1921 only - Mar 14 23:00s 1:00 " DST"
-Rule France 1921 only - Oct 25 23:00s 0 -
-Rule France 1922 only - Mar 25 23:00s 1:00 " DST"
-Rule France 1922 1938 - Oct Sat>=1 23:00s 0 -
-Rule France 1923 only - May 26 23:00s 1:00 " DST"
-Rule France 1924 only - Mar 29 23:00s 1:00 " DST"
-Rule France 1925 only - Apr 4 23:00s 1:00 " DST"
-Rule France 1926 only - Apr 17 23:00s 1:00 " DST"
-Rule France 1927 only - Apr 9 23:00s 1:00 " DST"
-Rule France 1928 only - Apr 14 23:00s 1:00 " DST"
-Rule France 1929 only - Apr 20 23:00s 1:00 " DST"
-Rule France 1930 only - Apr 12 23:00s 1:00 " DST"
-Rule France 1931 only - Apr 18 23:00s 1:00 " DST"
-Rule France 1932 only - Apr 2 23:00s 1:00 " DST"
-Rule France 1933 only - Mar 25 23:00s 1:00 " DST"
-Rule France 1934 only - Apr 7 23:00s 1:00 " DST"
-Rule France 1935 only - Mar 30 23:00s 1:00 " DST"
-Rule France 1936 only - Apr 18 23:00s 1:00 " DST"
-Rule France 1937 only - Apr 3 23:00s 1:00 " DST"
-Rule France 1938 only - Mar 26 23:00s 1:00 " DST"
-Rule France 1939 only - Apr 15 23:00s 1:00 " DST"
-Rule France 1939 only - Nov 18 23:00s 0 -
-Rule France 1940 only - Feb 25 2:00 1:00 " DST"
-# 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 " DDST"
-Rule France 1941 only - Oct 6 1:00 1:00 " DST"
-Rule France 1942 only - Mar 8 0:00 2:00 " DDST"
-Rule France 1942 only - Nov 2 3:00 1:00 " DST"
-Rule France 1943 only - Mar 29 2:00 2:00 " DDST"
-Rule France 1943 only - Nov 4 3:00 1:00 " DST"
-Rule France 1944 only - Apr 3 2:00 2:00 " DDST"
-Rule France 1944 only - Oct 8 1:00 1:00 " DST"
-Rule France 1945 only - Apr 2 2:00 2:00 " DDST"
-Rule France 1945 only - Sep 16 3:00 0 -
-# From Paul Eggert <eggert@twinsun.com) (November 18, 1993):
-# Shanks gives no times for 1975, but according to Cm722,
-# France introduced summer time in 1975 from 20 March to 22 September.
-Rule France 1975 only - Mar 20 2:00s 1:00 " DST"
-Rule France 1975 only - Sep 22 2:00s 0 -
-Rule France 1976 only - Mar 28 2:00s 1:00 " DST"
-Rule France 1976 only - Sep lastSun 2:00s 0 -
-# Shanks gives 0:09 for Paris Mean Time; go with Whitman's more precise 0:09:05.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Paris 0:09:05 - LMT 1891 Mar 15 0:01
- 0:09:05 - PMT 1911 Mar 11 # Paris Mean Time
- 0:00 France WET%s 1940 Jun 14
- 1:00 M-Eur MET%s 1944 Aug 25
- 0:00 France WET%s 1945 Sep 16 3:00
- 1:00 France MET%s 1977 Apr Sun>=1 2:00
- 1:00 M-Eur MET%s
-
-# Germany
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Germany 1945 only - Apr 2 2:00s 1:00 " DST"
-Rule Germany 1945 only - May 24 2:00 2:00 " DDST"
-Rule Germany 1945 only - Sep 24 3:00 1:00 " DST"
-Rule Germany 1945 only - Nov 18 2:00s 0 -
-Rule Germany 1946 only - Apr 14 2:00s 1:00 " DST"
-# 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 " DST"
-Rule Germany 1947 only - May 11 2:00s 2:00 " DDST"
-Rule Germany 1947 only - Jun 29 3:00 1:00 " DST"
-Rule Germany 1948 only - Apr 18 2:00s 1:00 " DST"
-Rule Germany 1949 only - Apr 10 2:00s 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Berlin 0:53:28 - LMT 1893 Apr
- 1:00 M-Eur MET%s 1945 Apr 2 2:00
- 1:00 Germany MET%s 1980 Apr 6 2:00
- 1:00 M-Eur MET%s
-
-# 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 - MET 1982 Mar 28 2:00
- 1:00 M-Eur MET%s
-
-# Greece
-# They adopted the Julian calendar in 1846.
-# Part switched to the Gregorian calendar on 1916 Jul 28.
-# The rest switched on 1920 Mar 18.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Greece 1916 only - July 28 0:01 0 -
-# Whitman gives 1932 Jul 5 - Nov 1; go with Shanks.
-Rule Greece 1932 only - Jul 7 0:00 1:00 " DST"
-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 " DST"
-# 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 " DST"
-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 " DST"
-Rule Greece 1952 only - Nov 2 0:00 0 -
-Rule Greece 1975 only - Apr 12 0:00s 1:00 " DST"
-Rule Greece 1975 only - Nov 26 0:00s 0 -
-Rule Greece 1976 only - Apr 11 2:00s 1:00 " DST"
-Rule Greece 1976 only - Oct 10 2:00s 0 -
-Rule Greece 1977 1978 - Apr Sun>=1 2:00s 1:00 " DST"
-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 " DST"
-Rule Greece 1979 only - Sep 29 2:00 0 -
-Rule Greece 1980 only - Apr 1 0:00 1:00 " DST"
-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:35 - AMT 1916 Jul 28 0:01 # Athens MT
- 2:00 Greece EET%s 1941 Apr 30
- 1:00 Greece MET%s 1944 Apr 4
- 2:00 Greece EET%s 1981 Mar 29 2:00
-# Greece must change by 1996 for EC compatibility.
- 2:00 M-Eur EET%s 1996 # Guess the last minute.
- 2:00 E-Eur EET%s
-
-# Hungary
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Hungary 1918 only - Sep 29 2:00s 0 -
-Rule Hungary 1919 only - Apr 15 3:00 1:00 " DST"
-Rule Hungary 1919 only - Sep 15 3:00 0 -
-Rule Hungary 1920 only - Apr 5 3:00 1:00 " DST"
-Rule Hungary 1920 only - Sep 30 3:00 0 -
-Rule Hungary 1945 only - May 1 23:00 1:00 " DST"
-Rule Hungary 1945 only - Nov 3 0:00 0 -
-Rule Hungary 1946 only - Mar 31 2:00s 1:00 " DST"
-Rule Hungary 1946 1949 - Oct Sun>=1 2:00s 0 -
-Rule Hungary 1947 1949 - Apr Sun>=4 2:00s 1:00 " DST"
-Rule Hungary 1950 only - Apr 17 2:00s 1:00 " DST"
-Rule Hungary 1950 only - Oct 23 2:00s 0 -
-Rule Hungary 1954 1955 - May 23 0:00 1:00 " DST"
-Rule Hungary 1954 1955 - Oct 3 0:00 0 -
-Rule Hungary 1956 only - Jun Sun>=1 0:00 1:00 " DST"
-Rule Hungary 1956 only - Sep lastSun 0:00 0 -
-Rule Hungary 1957 only - Jun Sun>=1 1:00 1:00 " DST"
-Rule Hungary 1957 only - Sep lastSun 3:00 0 -
-Rule Hungary 1980 only - Apr 6 1:00 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Budapest 1:16:20 - LMT 1890 Oct
- 1:00 M-Eur MET%s 1918 Jul
- 1:00 Hungary MET%s 1941 Apr 6 2:00
- 1:00 M-Eur MET%s 1945 May 1 23:00
- 1:00 Hungary MET%s 1980 Sep 28 2:00s
- 1:00 M-Eur MET%s
-
-# Iceland
-#
-# From Adam David <adam@veda.is> (November 6, 1993):
-# The name of the timezone in Iceland for system / mail / news purposes is GMT.
-#
-# (December 5, 1993):
-# 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.
-#
-# (December 10, 1993):
-# 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 (???). The Gregorian calendar was not introduced
-# in Iceland until 1700.
-#
-# From Paul Eggert <eggert@twinsun.com> (December 9, 1993):
-# 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 1908 only - Jan 1 0:00 0 S
-Rule Iceland 1917 1918 - Feb 19 23:00 1:00 D
-Rule Iceland 1917 only - Oct 21 1:00 0 S
-Rule Iceland 1918 only - Nov 16 1:00 0 S
-Rule Iceland 1939 only - Apr 29 23:00 1:00 D
-Rule Iceland 1939 only - Nov 29 2:00 0 S
-Rule Iceland 1940 only - Feb 25 2:00 1:00 D
-Rule Iceland 1940 only - Nov 3 2:00 0 S
-Rule Iceland 1941 only - Mar 2 1:00s 1:00 D
-Rule Iceland 1941 only - Nov 2 1:00s 0 S
-Rule Iceland 1942 only - Mar 8 1:00s 1:00 D
-Rule Iceland 1942 only - Oct 25 1:00s 0 S
-# 1943-1946 - first Sunday in March until first Sunday in winter
-Rule Iceland 1943 1946 - Mar Sun>=1 1:00s 1:00 D
-Rule Iceland 1943 1948 - Oct Sun>=22 1:00s 0 S
-# 1947-1967 - first Sunday in April until first Sunday in winter
-Rule Iceland 1947 1967 - Apr Sun>=1 1:00s 1:00 D
-# 1949 Oct transition delayed by 1 week
-Rule Iceland 1949 only - Oct 30 1:00s 0 S
-Rule Iceland 1950 1966 - Oct Sun>=22 1:00s 0 S
-Rule Iceland 1967 only - Oct 29 1:00s 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/Reykjavik -1:27:24 - LMT 1837
- -1:28 - RMT 1908 # Reykjavik Mean Time
- -1:00 Iceland I%sT 1968 Apr 7 1:00s
- 0:00 - GMT
-
-# Italy
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Italy 1893 only - Nov 1 0:00s 0 S
-# Shanks gives transition times of 1916-1920 as 24:00; go with Whitman.
-Rule Italy 1916 only - Jun 3 0:00s 1:00 " DST"
-Rule Italy 1916 only - Sep 30 0:00s 0 -
-Rule Italy 1917 only - Mar 31 0:00s 1:00 " DST"
-Rule Italy 1917 only - Sep 30 0:00s 0 -
-Rule Italy 1918 only - Mar 9 0:00s 1:00 " DST"
-Rule Italy 1918 1919 - Oct Sun>=1 0:00s 0 -
-Rule Italy 1919 only - Mar 1 0:00s 1:00 " DST"
-Rule Italy 1920 only - Mar 20 0:00s 1:00 " DST"
-# Shanks gives 1920 Sep 18; go with Whitman.
-Rule Italy 1920 only - Oct 1 0:00s 0 -
-Rule Italy 1940 only - Jun 15 0:00 1:00 " DST"
-Rule Italy 1945 only - Apr 2 2:00 1:00 " DST"
-Rule Italy 1945 only - Sep 17 0:00 0 -
-Rule Italy 1946 only - Mar 17 2:00s 1:00 " DST"
-Rule Italy 1946 only - Oct 6 2:00s 0 -
-Rule Italy 1947 only - Mar 16 0:00s 1:00 " DST"
-Rule Italy 1947 only - Oct 5 0:00s 0 -
-Rule Italy 1948 only - Feb 29 2:00s 1:00 " DST"
-Rule Italy 1948 only - Oct 3 2:00s 0 -
-Rule Italy 1966 1968 - May Sun>=22 0:00 1:00 " DST"
-Rule Italy 1966 1969 - Sep Sun>=22 0:00 0 -
-Rule Italy 1969 only - Jun 1 0:00 1:00 " DST"
-Rule Italy 1970 only - May 31 0:00 1:00 " DST"
-Rule Italy 1970 only - Sep lastSun 0:00 0 -
-Rule Italy 1971 1972 - May Sun>=22 0:00 1:00 " DST"
-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 " DST"
-Rule Italy 1973 1974 - Sep lastSun 0:00 0 -
-Rule Italy 1974 only - May 26 0:00 1:00 " DST"
-Rule Italy 1975 only - Jun 1 0:00s 1:00 " DST"
-Rule Italy 1975 1977 - Sep lastSun 0:00s 0 -
-Rule Italy 1976 only - May 30 0:00s 1:00 " DST"
-Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 " DST"
-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:50 - RMT 1893 Nov # Rome Mean Time
- 1:00 Italy MET%s 1942 Nov 2 2:00s
- 1:00 M-Eur MET%s 1945 Apr 2 2:00s
- 1:00 Italy MET%s 1980 Apr 6 2:00
- 1:00 M-Eur MET%s
-# Vatican is identical to Europe/Rome; San Marino is like Europe/Rome.
-
-# Latvia
-# They switched from the Julian to the Gregorian calendar on 1918 Feb 15.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Riga 1:36:24 - LMT 1880
- 1:36 - LST 1918 Apr 15 2:00
- 1:36 M-Eur LST%s 1919 Apr 1 2:00
- 1:36 1:00 "LST DST" 1919 May 22 3:00
- 1:36 - LST 1926 May 11
- 2:00 - EET 1940 Aug 5
- 3:00 - MSK 1941 Jul
- 1:00 M-Eur MET%s 1944 Aug 8
- 3:00 Russia MS%s 1991 Mar 31 2:00s
- 2:00 1:00 "EET DST" 1991 Sep 29 2:00s
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-
-# Liechtenstein
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Vaduz 0:38:04 - LMT 1894 Jun
- 1:00 - MET 1981 Mar 29 2:00
- 1:00 M-Eur MET%s
-
-# Lithuania
-# They switched from the Julian to the Gregorian calendar on 1918 Feb 15.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Vilnius 1:41:16 - LMT 1880
- 1:24 - LST 1917 # Kaunas
- 1:36 - LST 1919 Oct 10
- 1:00 - MET 1920 Jul 12
- 2:00 - EET 1920 Oct 9
- 1:00 - MET 1940 Aug 3
- 3:00 - MSK 1941 Jun 24
- 1:00 M-Eur MET%s 1944 Aug
- 3:00 Russia MS%s 1991 Mar 31 2:00s
- 2:00 1:00 "EET DST" 1991 Sep 29 2:00s
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-
-# 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 1904 only - Jun 1 0:00 0 -
-Rule Lux 1916 only - May 14 23:00 1:00 " DST"
-Rule Lux 1916 only - Oct 1 1:00 0 -
-Rule Lux 1917 only - Apr 28 23:00 1:00 " DST"
-Rule Lux 1917 only - Sep 17 1:00 0 -
-Rule Lux 1918 only - Apr Mon>=15 2:00s 1:00 " DST"
-Rule Lux 1918 only - Sep Mon>=15 2:00s 0 -
-Rule Lux 1919 only - Mar 1 23:00 1:00 " DST"
-Rule Lux 1919 only - Oct 5 3:00 0 -
-Rule Lux 1920 only - Feb 14 23:00 1:00 " DST"
-Rule Lux 1920 only - Oct 24 2:00 0 -
-Rule Lux 1921 only - Mar 14 23:00 1:00 " DST"
-Rule Lux 1921 only - Oct 26 2:00 0 -
-Rule Lux 1922 only - Mar 25 23:00 1:00 " DST"
-Rule Lux 1922 only - Oct Sun>=2 1:00 0 -
-Rule Lux 1923 only - Apr 21 23:00 1:00 " DST"
-Rule Lux 1923 only - Oct Sun>=2 2:00 0 -
-Rule Lux 1924 only - Mar 29 23:00 1:00 " DST"
-Rule Lux 1924 1928 - Oct Sun>=2 1:00 0 -
-Rule Lux 1925 only - Apr 5 23:00 1:00 " DST"
-Rule Lux 1926 only - Apr 17 23:00 1:00 " DST"
-Rule Lux 1927 only - Apr 9 23:00 1:00 " DST"
-Rule Lux 1928 only - Apr 14 23:00 1:00 " DST"
-Rule Lux 1929 only - Apr 20 23:00 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
- 1:00 Lux MET%s 1918 Nov 25
- 0:00 Lux WET%s 1929 Oct 6 2:00s
- 0:00 Belgium WET%s 1940 May 14 3:00
- 1:00 M-Eur WET%s 1944 Sep 18 3:00
- 1:00 Belgium MET%s 1979 Apr 1 2:00
- 1:00 M-Eur MET%s
-
-# Macedonia
-# They switched from the Julian to the Gregorian calendar on 1918 Mar 18.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Skopje 1:25:44 - LMT 1884
- 1:00 - MET 1941 Apr 18 23:00
- 1:00 M-Eur MET%s 1945 May 8 2:00s
- 1:00 1:00 "MET DST" 1945 Sep 16 2:00s
- 1:00 - MET 1983 Mar 27 2:00s
- 1:00 M-Eur MET%s
-
-# Malta
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Malta 1973 only - Mar 31 0:00s 1:00 " DST"
-Rule Malta 1973 only - Sep 29 0:00s 0 -
-Rule Malta 1974 only - Apr 21 0:00s 1:00 " DST"
-Rule Malta 1974 only - Sep 16 0:00s 0 -
-Rule Malta 1975 1979 - Apr Sun>=15 2:00 1:00 " DST"
-Rule Malta 1975 1980 - Sep Sun>=15 2:00 0 -
-Rule Malta 1980 only - Mar 31 2:00 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 # Valletta
- 1:00 Italy MET%s 1942 Nov 2 2:00s
- 1:00 M-Eur MET%s 1945 Apr 2 2:00s
- 1:00 Italy MET%s 1973 Mar 31
- 1:00 Malta MET%s 1981 Mar 29 2:00s
- 1:00 M-Eur MET%s
-
-# Moldova
-# They switched from the Julian to the Gregorian calendar on 1919 Mar 18.
-# 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 MS%s 1991 Mar 31 2:00s
- 2:00 1:00 "EET DST" 1991 Sep 29 2:00s
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-
-# Monaco
-# Shanks gives 0:09 for Paris Mean Time; go with Whitman's more precise 0:09:05.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
- 0:09:05 - PMT 1911 Mar 11 # Paris Mean Time
- 0:00 France WET%s 1945 Sep 16 3:00
- 1:00 France MET%s 1977 Apr Sun>=1 2:00
- 1:00 M-Eur MET%s
-
-# Netherlands
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Neth 1892 only - May 1 0:00 0 AMT
-# 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
-Rule Neth 1916 only - Oct 2 2:00s 0 AMT
-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 1939 - 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
-# Whitman gives 1939 Apr 15 and 1940 Apr 19; go with Shanks.
-Rule Neth 1938 1939 - May 15 2:00s 1:00 NST
-Rule Neth 1945 only - Apr 2 2:00s 1:00 -
-Rule Neth 1945 only - May 20 2:00s 0 " DST"
-# 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 %s 1940 May 16 0:40
- 1:00 M-Eur MET%s 1945 Apr 2 2:00
- 1:00 Neth MET%s 1977 Apr Sun>=1 2:00
- 1:00 M-Eur MET%s
-
-# Norway
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Norway 1892 only - May 1 0:00 0 -
-# Whitman gives 1916 May 21 - 1916 Oct 21; go with Shanks.
-Rule Norway 1916 only - May 22 1:00 1:00 " DST"
-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 " DST"
-# 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 " DST"
-Rule Norway 1945 only - Oct 1 2:00s 0 -
-Rule Norway 1959 1964 - Mar Sun>=15 2:00s 1:00 " DST"
-Rule Norway 1959 1965 - Sep Sun>=15 2:00s 0 -
-Rule Norway 1965 only - Apr 25 2:00s 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Oslo 0:43:00 - LMT 1895
- 1:00 Norway MET%s 1940 Aug 10 23:00
- 1:00 M-Eur MET%s 1945 Apr 2 2:00
- 1:00 Norway MET%s 1980 Apr 6 2:00
- 1:00 M-Eur MET%s
-# Svalbard is like Europe/Oslo.
-#
-# From Whitman:
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/Jan_Mayen -1:00 - EGT
-
-# Poland
-# Austrian and German Poland switched from the Julian to the Gregorian calendar
-# on 1582 Oct 15. Russian Poland switched on 1918 Jan 14.
-# 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 " DST"
-# 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 " DST"
-Rule Poland 1945 only - Nov 1 0:00 0 -
-Rule Poland 1946 only - Apr 14 0:00 1:00 " DST"
-Rule Poland 1946 only - Sep 7 0:00 0 -
-Rule Poland 1947 only - May 4 0:00 1:00 " DST"
-Rule Poland 1947 1948 - Oct Sun>=1 0:00 0 -
-Rule Poland 1948 only - Apr 18 0:00 1:00 " DST"
-# Whitman also gives 1949 Apr 9 - 1949 Oct 1; go with Shanks.
-Rule Poland 1957 only - Jun 2 1:00s 1:00 " DST"
-Rule Poland 1957 1958 - Sep lastSun 1:00s 0 -
-Rule Poland 1958 only - Mar 30 1:00s 1:00 " DST"
-Rule Poland 1959 only - May 31 1:00s 1:00 " DST"
-Rule Poland 1959 1961 - Oct Sun>=1 1:00s 0 -
-Rule Poland 1960 only - Apr 3 1:00s 1:00 " DST"
-Rule Poland 1961 1964 - May Sun>=25 1:00s 1:00 " DST"
-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 - WMT 1915 Aug 5 # Warsaw Mean Time
- 1:00 M-Eur MET%s 1918 Sep 16 3:00
- 2:00 Poland EET%s 1922 Jun
- 1:00 Poland MET%s 1940 Jun 23 2:00
- 1:00 M-Eur MET%s 1944 Oct
- 1:00 Poland MET%s 1977 Apr 3 1:00
- 1:00 W-Eur MET%s
-# This may change to `M-Eur' soon, for EC compatibility.
-
-# Portugal
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Port 1911 only - May 24 0:00 0 -
-Rule Port 1916 only - Jun 17 23:00 1:00 " DST"
-# 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 " DST"
-Rule Port 1917 1921 - Oct 14 23:00s 0 -
-Rule Port 1918 only - Mar 1 23:00s 1:00 " DST"
-Rule Port 1919 only - Feb 28 23:00s 1:00 " DST"
-Rule Port 1920 only - Feb 29 23:00s 1:00 " DST"
-Rule Port 1921 only - Feb 28 23:00s 1:00 " DST"
-Rule Port 1924 only - Apr 16 23:00s 1:00 " DST"
-Rule Port 1924 only - Oct 14 23:00s 0 -
-Rule Port 1926 only - Apr 17 23:00s 1:00 " DST"
-Rule Port 1926 1929 - Oct Sat>=1 23:00s 0 -
-Rule Port 1927 only - Apr 9 23:00s 1:00 " DST"
-Rule Port 1928 only - Apr 14 23:00s 1:00 " DST"
-Rule Port 1929 only - Apr 20 23:00s 1:00 " DST"
-Rule Port 1931 only - Apr 18 23:00s 1:00 " DST"
-# 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 " DST"
-# Shanks gives 1934 Apr 4; go with Whitman.
-Rule Port 1934 only - Apr 7 23:00s 1:00 " DST"
-# 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 " DST"
-Rule Port 1936 only - Apr 18 23:00s 1:00 " DST"
-# Whitman gives 1937 Apr 2; go with Shanks.
-Rule Port 1937 only - Apr 3 23:00s 1:00 " DST"
-Rule Port 1938 only - Mar 26 23:00s 1:00 " DST"
-Rule Port 1939 only - Apr 15 23:00s 1:00 " DST"
-# 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 " DST"
-# 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 " DST"
-Rule Port 1942 1945 - Mar Sat>=8 23:00s 1:00 " DST"
-Rule Port 1942 only - Apr 25 22:00s 2:00 " DDST"
-Rule Port 1942 only - Aug 15 22:00s 1:00 " DST"
-Rule Port 1942 1945 - Oct Sat>=24 23:00s 0 -
-Rule Port 1943 only - Apr 17 22:00s 2:00 " DDST"
-Rule Port 1943 1945 - Aug Sat>=25 22:00s 1:00 " DST"
-Rule Port 1944 1945 - Apr Sat>=21 22:00s 2:00 " DDST"
-Rule Port 1946 only - Apr Sat>=1 23:00s 1:00 " DST"
-Rule Port 1946 only - Oct Sat>=1 23:00s 0 -
-Rule Port 1947 1949 - Apr Sun>=1 2:00s 1:00 " DST"
-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 " DST"
-Rule Port 1951 1965 - Oct Sun>=1 2:00s 0 -
-Rule Port 1977 only - Mar 27 0:00s 1:00 " DST"
-Rule Port 1977 only - Sep 25 0:00s 0 -
-Rule Port 1978 1979 - Apr Sun>=1 0:00s 1:00 " DST"
-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 " DST"
-Rule Port 1981 1982 - Mar lastSun 1:00s 1:00 " DST"
-Rule Port 1983 only - Mar lastSun 2:00s 1:00 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Lisbon -0:36:32 - LMT 1884
- -0:37 - LMT 1911 May 24 # Lisbon Mean Time
- 0:00 Port WET%s 1966 Apr 3 2:00
- 1:00 - MET 1976 Sep 26 1:00
- 0:00 Port WET%s 1983 Sep 25 1:00s
- 0:00 W-Eur WET%s 1992 Sep 27 1:00s
-# From Rui Pedro Salgueiro <rps@inescca.inescc.pt> (November 12, 1992):
-# Portugal has recently (September, 27) changed timezone
-# (from WET to MET or CET) to harmonize with EEC.
- 1:00 M-Eur MET%s
-# We don't know what happened to Madeira or the Azores,
-# so we'll just use Shanks for now.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/Azores -1:42:40 - LMT 1884 # Ponta Delgada
- -1:55 - HMT 1911 May 24 # Horta Mean Time
- -2:00 Port ACT%s 1966 Apr 3 2:00
- -1:00 - ACT 1977 Mar 27
- -1:00 - ACT 1983 Sep 25 1:00s
- -1:00 W-Eur ACT%s
-Zone Atlantic/Madeira -1:07:36 - LMT 1884 # Funchal
- -1:08 - FMT 1911 May 24 # Funchal Mean Time
- -1:00 Port ACT%s 1966 Apr 3 2:00
- 0:00 - WET 1977 Mar 27
- 0:00 Port WET%s 1983 Sep 25 1:00s
- 0:00 W-Eur WET%s
-
-# Slovakia
-Link Europe/Prague Europe/Bratislava
-
-# Romania
-# Catholic Romania switched from the Julian to the Gregorian calendar on
-# on 1919 Mar 18. Greek Orthodox Romania switched on 1920 Mar 18.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Romania 1931 only - Jul 24 0:00 0 -
-Rule Romania 1932 only - May 21 0:00s 1:00 " DST"
-Rule Romania 1932 1939 - Oct Sun>=1 0:00s 0 -
-Rule Romania 1933 1939 - Apr Sun>=2 0:00s 1:00 " DST"
-Rule Romania 1979 only - May 27 0:00 1:00 " DST"
-Rule Romania 1979 only - Sep lastSun 0:00 0 -
-Rule Romania 1980 only - Apr 5 23:00 1:00 " DST"
-Rule Romania 1980 only - Sep lastSun 1:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
- 1:44 - BMT 1931 Jul 24 # Bucharest MT
- 2:00 Romania EET%s 1981 Mar 29 2:00s
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-
-# Russia
-# From Paul Eggert <eggert@twinsun.com> (May 28, 1994):
-# Moscow and Novosibirsk time zone names, and Moscow rules after 1991,
-# are from Andrew A. Chernov <ache@astral.msk.su>.
-# I invented the other time zone names, and (unless otherwise specified)
-# guessed what happened after 1991; the clocks were chaotic, and we know little.
-# The rest is from Shanks.
-#
-# From Shanks (1991):
-# Western Russia switched from the Julian to the Gregorian calendar
-# on 1918 Jan 14. Eastern Russia switched on 1920 Mar 18.
-# In 1929 the Soviet Union instituted a 5 day week; in 1932 it instituted
-# a 6 day week; on 1940 Jun 27 it returned to the Gregorian week.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Moscow 2:30:20 - LMT 1880
- 2:31 Russia LST%s 1919 Jul 1 2:00
- 3:00 Russia MS%s 1922 Oct
- 2:00 - EET 1930 Jun 21
- 3:00 Russia MS%s 1991 Mar 31 2:00s
- 2:00 1:00 "EET DST" 1991 Sep 29 2:00s
- 2:00 - EET 1992 Jan 19 2:00s
- 3:00 Russia MS%s
-Zone Europe/Kuybyshev 3:20:36 - LMT 1924 May 2
- 3:00 - KSK 1957 Mar
- 4:00 Russia KS%s 1991 Mar 31 2:00s
- 3:00 1:00 KSD 1991 Sep 29 2:00s
- 3:00 - KSK 1992 Jan 19 2:00s
- 4:00 Russia KS%s
-Zone Asia/Yekaterinburg 4:02:34 - LMT 1924 May 2
- 4:00 - SSK 1957 Mar
- 5:00 Russia SS%s 1991 Mar 31 2:00s
- 4:00 1:00 SSD 1991 Sep 29 2:00s
- 4:00 - SSK 1992 Jan 19 2:00s
- 5:00 Russia ES%s # name change from Sverdlovsk
-Zone Asia/Omsk 4:53:36 - LMT 1924 May 2
- 5:00 - OSK 1957 Mar
- 6:00 Russia OS%s 1991 Mar 31 2:00s
- 5:00 1:00 OSD 1991 Sep 29 2:00s
- 5:00 - OSK 1992 Jan 19 2:00s
- 6:00 Russia OS%s
-# From Stanislaw A. Kuzikowski <S.A.Kuz@iae.nsk.su> (June 29, 1994):
-# 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.
-# Tomsk is still 4 hours ahead of Moscow.
-Zone Asia/Novosibirsk 5:31:40 - LMT 1924 May 2
- 6:00 - NSK 1957 Mar
- 7:00 Russia NS%s 1991 Mar 31 2:00s
- 6:00 1:00 NSD 1991 Sep 29 2:00s
- 6:00 - NSK 1992 Jan 19 2:00s
- 7:00 Russia NS%s 1994 Mar 27 2:00s
- 6:00 1:00 NSD 1994 Sep 25 2:00s
- 6:00 Russia NS%s
-Zone Asia/Tomsk 5:39:52 - LMT 1924 May 2
- 6:00 - TSK 1957 Mar
- 7:00 Russia TS%s 1991 Mar 31 2:00s
- 6:00 1:00 TSD 1991 Sep 29 2:00s
- 6:00 - TSK 1992 Jan 19 2:00s
- 7:00 Russia TS%s
-Zone Asia/Irkutsk 6:57:20 - LMT 1880
- 6:57 - LST 1924 May 2
- 7:00 - ISK 1957 Mar
- 8:00 Russia IS%s 1991 Mar 31 2:00s
- 7:00 1:00 ISD 1991 Sep 29 2:00s
- 7:00 - ISK 1992 Jan 19 2:00s
- 8:00 Russia IS%s
-Zone Asia/Yakutsk 8:38:40 - LMT 1924 May 2
- 8:00 - YSK 1957 Mar
- 9:00 Russia YS%s 1991 Mar 31 2:00s
- 8:00 1:00 YSD 1991 Sep 29 2:00s
- 8:00 - YSK 1992 Jan 19 2:00s
- 9:00 Russia YS%s
-Zone Asia/Vladivostok 8:47:44 - LMT 1880
- 8:48 - LST 1924 May 2
- 9:00 - VSK 1957 Mar
- 10:00 Russia VS%s 1991 Mar 31 2:00s
- 9:00 1:00 VSD 1991 Sep 29 2:00s
- 9:00 - VSK 1992 Jan 19 2:00s
- 10:00 Russia VS%s
-# MSK is taken; settle for GSK.
-Zone Asia/Magadan 10:03:12 - LMT 1924 May 2
- 10:00 - GSK 1957 Mar
- 11:00 Russia GS%s 1991 Mar 31 2:00s
- 10:00 1:00 GSD 1991 Sep 29 2:00s
- 10:00 - GSK 1992 Jan 19 2:00s
- 11:00 Russia GS%s
-# This name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
-Zone Asia/Kamchatka 10:34:36 - LMT 1924 May 2
- 11:00 - PSK 1957 Mar
- 12:00 Russia PS%s 1991 Mar 31 2:00s
- 11:00 1:00 PSD 1991 Sep 29 2:00s
- 11:00 - PSK 1992 Jan 19 2:00s
- 12:00 Russia PS%s
-Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2
- 12:00 - ASK 1957 Mar
- 13:00 Russia AS%s 1991 Mar 31 2:00s
- 12:00 1:00 ASD 1991 Sep 29 2:00s
- 12:00 - ASK 1992 Jan 19 2:00s
- 13:00 Russia AS%s
-
-# Serbia
-# They switched from the Julian to the Gregorian calendar on 1918 Mar 18.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Belgrade 1:22:00 - LMT 1884
- 1:00 - MET 1941 Apr 18 23:00
- 1:00 M-Eur MET%s 1945 May 8 2:00s
- 1:00 1:00 "MET DST" 1945 Sep 16 2:00s
- 1:00 - MET 1983 Mar 27 2:00s
- 1:00 M-Eur MET%s
-
-# Slovenia
-# They switched from the Julian to the Gregorian calendar on 1918 Mar 18.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Ljubljana 0:58:04 - LMT 1884
- 1:00 - MET 1941 Apr 18 23:00
- 1:00 M-Eur MET%s 1945 May 8 2:00s
- 1:00 1:00 "MET DST" 1945 Sep 16 2:00s
- 1:00 - MET 1983 Mar 27 2:00s
- 1:00 M-Eur MET%s
-
-# Spain
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Spain 1901 only - Jan 1 0:00 0 -
-# For 1917-1919 Whitman gives Apr Sat>=1 - Oct Sat>=1; go with Shanks.
-Rule Spain 1917 only - May 5 23:00s 1:00 " DST"
-Rule Spain 1917 1919 - Oct 6 23:00s 0 -
-Rule Spain 1918 only - Apr 15 23:00s 1:00 " DST"
-Rule Spain 1919 only - Apr 5 23:00s 1:00 " DST"
-# Whitman gives 1921 Feb 28 - Oct 14; go with Shanks.
-Rule Spain 1924 only - Apr 16 23:00s 1:00 " DST"
-# 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 " DST"
-# 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 " DST"
-Rule Spain 1928 only - Apr 14 23:00s 1:00 " DST"
-Rule Spain 1929 only - Apr 20 23:00s 1:00 " DST"
-# Whitman gives 1937 Jun 16, 1938 Apr 16, 1940 Apr 13; go with Shanks.
-Rule Spain 1937 only - May 22 23:00s 1:00 " DST"
-Rule Spain 1937 1939 - Oct Sat>=1 23:00s 0 -
-Rule Spain 1938 only - Mar 22 23:00s 1:00 " DST"
-Rule Spain 1939 only - Apr 15 23:00s 1:00 " DST"
-Rule Spain 1940 only - Mar 16 23:00s 1:00 " DST"
-# Whitman says no DST 1942-1945; go with Shanks.
-Rule Spain 1942 only - May 2 22:00s 2:00 " DDST"
-Rule Spain 1942 only - Sep 1 22:00s 1:00 " DST"
-Rule Spain 1943 1946 - Apr Sat>=13 22:00s 2:00 " DDST"
-Rule Spain 1943 only - Oct 3 22:00s 1:00 " DST"
-Rule Spain 1944 only - Oct 10 22:00s 1:00 " DST"
-Rule Spain 1945 only - Sep 30 1:00 1:00 " DST"
-Rule Spain 1949 only - Apr 30 23:00 1:00 " DST"
-Rule Spain 1949 only - Sep 30 1:00 0 -
-Rule Spain 1974 1975 - Apr Sat>=13 23:00 1:00 " DST"
-Rule Spain 1974 1975 - Oct Sun>=1 1:00 0 -
-Rule Spain 1976 only - Mar 27 23:00 1:00 " DST"
-Rule Spain 1976 1977 - Sep lastSun 1:00 0 -
-Rule Spain 1977 1978 - Apr 2 23:00 1:00 " DST"
-Rule Spain 1978 only - Oct 1 1:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Madrid -0:14:44 - LMT 1901
- 0:00 Spain WET%s 1946 Sep 30
- 1:00 Spain MET%s 1979 Apr 1 2:00
- 1:00 M-Eur MET%s
-Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C.
- -1:00 - ACT 1946 Sep 30 1:00
- 0:00 - WET 1980 Apr 6 0:00s
- 0:00 1:00 "WET DST" 1980 Sep 28 0:00s
- 0:00 W-Eur WET%s
-
-# Sweden
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Stockholm 1:12:12 - LMT 1878 May 31
- 1:12 - SMT 1900 Jan 1 1:00 # Stockholm MT
- 1:00 - MET 1916 Apr 14 23:00s
- 1:00 1:00 "MET DST" 1916 Sep 30 23:00s
- 1:00 - MET 1980 Apr 6 2:00
- 1:00 M-Eur MET%s
-
-# 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
-Rule Swiss 1894 only - Jun 1 0:00 0 -
-# From Whitman (who writes ``Midnight?''):
-Rule Swiss 1940 only - Nov 2 0:00 1:00 " DST"
-Rule Swiss 1940 only - Dec 31 0:00 0 " DST"
-# From Shanks (1991):
-Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 " DST"
-Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 " DST"
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12
- 0:30 - SST 1894 Jun # Swiss Standard Time
- 1:00 Swiss MET%s 1981 Mar 29 2:00
- 1:00 M-Eur MET%s
-
-# Turkey
-# European Turkey switched to the Gregorian calendar in 1908.
-# Asian Turkey switched in 1914.
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Turkey 1910 only - Oct 1 0:00 0 -
-Rule Turkey 1916 only - May 1 0:00 1:00 " DST"
-Rule Turkey 1916 only - Oct 1 0:00 0 -
-Rule Turkey 1920 only - Mar 28 0:00 1:00 " DST"
-Rule Turkey 1920 only - Oct 25 0:00 0 -
-Rule Turkey 1921 only - Apr 3 0:00 1:00 " DST"
-Rule Turkey 1921 only - Oct 3 0:00 0 -
-Rule Turkey 1922 only - Mar 26 0:00 1:00 " DST"
-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 " DST"
-Rule Turkey 1924 1925 - Oct 1 0:00 0 -
-Rule Turkey 1925 only - May 1 0:00 1:00 " DST"
-# Shanks omits the first two transitions in 1940; go with Whitman.
-Rule Turkey 1940 only - Jun 30 0:00 1:00 " DST"
-Rule Turkey 1940 only - Oct 5 0:00 0 -
-Rule Turkey 1940 only - Dec 1 0:00 1:00 " DST"
-Rule Turkey 1941 only - Sep 21 0:00 0 -
-Rule Turkey 1942 only - Apr 1 0:00 1:00 " DST"
-# 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 " DST"
-Rule Turkey 1945 only - Oct 8 0:00 0 -
-Rule Turkey 1946 only - Jun 1 0:00 1:00 " DST"
-Rule Turkey 1946 only - Oct 1 0:00 0 -
-Rule Turkey 1947 1948 - Apr Sun>=16 0:00 1:00 " DST"
-Rule Turkey 1947 1950 - Oct Sun>=2 0:00 0 -
-Rule Turkey 1949 only - Apr 10 0:00 1:00 " DST"
-Rule Turkey 1950 only - Apr 19 0:00 1:00 " DST"
-Rule Turkey 1951 only - Apr 22 0:00 1:00 " DST"
-Rule Turkey 1951 only - Oct 8 0:00 0 -
-Rule Turkey 1962 only - Jul 15 0:00 1:00 " DST"
-Rule Turkey 1962 only - Oct 8 0:00 0 -
-Rule Turkey 1964 only - May 15 0:00 1:00 " DST"
-Rule Turkey 1964 only - Oct 1 0:00 0 -
-Rule Turkey 1970 1972 - May Sun>=2 0:00 1:00 " DST"
-Rule Turkey 1970 1972 - Oct Sun>=2 0:00 0 -
-Rule Turkey 1973 only - Jun 3 1:00 1:00 " DST"
-Rule Turkey 1973 only - Nov 4 3:00 0 -
-Rule Turkey 1974 only - Mar 31 2:00 1:00 " DST"
-Rule Turkey 1974 only - Nov 3 5:00 0 -
-Rule Turkey 1975 only - Mar 30 0:00 1:00 " DST"
-Rule Turkey 1975 1976 - Oct lastSun 0:00 0 -
-Rule Turkey 1976 only - Jun 1 0:00 1:00 " DST"
-Rule Turkey 1977 1978 - Apr Sun>=1 0:00 1:00 " DST"
-Rule Turkey 1977 only - Oct 16 0:00 0 -
-Rule Turkey 1979 1980 - Apr Sun>=1 3:00 1:00 " DST"
-Rule Turkey 1979 1982 - Oct Mon>=11 0:00 0 -
-Rule Turkey 1981 1982 - Mar lastSun 3:00 1:00 " DST"
-Rule Turkey 1983 only - Jul 31 0:00 1:00 " DST"
-Rule Turkey 1983 only - Oct 2 0:00 0 -
-Rule Turkey 1985 only - Apr 20 0:00 1:00 " DST"
-Rule Turkey 1985 only - Sep 28 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Istanbul 1:55:52 - LMT 1880
- 1:57 - OMT 1910 Oct # Ottoman Mean Time
- 2:00 Turkey EET%s 1978 Oct 15
- 3:00 Turkey TUR%s 1985 Apr 20
- 2:00 Turkey EET%s 1986
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
-
-# Ukraine
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Ukraine 1919 only - Jul 1 2:00 1:00 " DST"
-Rule Ukraine 1919 only - Aug 16 0:00 0 -
-Rule Ukraine 1921 only - Feb 14 23:00 1:00 " DST"
-Rule Ukraine 1921 only - Mar 21 23:00 2:00 " DDST"
-Rule Ukraine 1921 only - Sep 1 0:00 1:00 " DST"
-Rule Ukraine 1921 only - Oct 1 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Kiev 2:02:04 - LMT 1880
- 2:02 Russia LST%s 1919 Jul 1 2:00
- 2:02 Ukraine LST%s 1924 May 2
- 2:00 - EET 1930 Jun 21
- 3:00 Russia MS%s 1990 Jul 17
- 2:00 M-Eur EET%s
-# This may change to `E-Eur' soon, for EC compatibility.
-Zone Europe/Simferopol 2:16:24 - LMT 1880
- 2:08 Russia LST%s 1919 Jul 1 2:00
- 2:08 Ukraine LST%s 1924 May 2
- 2:00 - EET 1930 Jun 21
- 3:00 Russia MS%s 1991 Mar 31 2:00s
- 2:00 1:00 "EET DST" 1991 Sep 29 2:00s
-# From Paul Eggert <eggert@twinsun.com> (May 28, 1994):
-# Today's _Economist_ (p 45) reports that Crimea switched
-# from Kiev to Moscow time sometime after the January elections.
-# For now, we'll guess that there was a 2-hour leap forward on March 27.
- 2:00 M-Eur EET%s 1994 Mar 27 2:00s
- 3:00 Russia MS%s
-
-###############################################################################
-
-# 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 (January 28, 1988):
-# ...
-# 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
-# @(#)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
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)getopt.c 7.5";
-/* Modified from the UCB version with the SCCS ID appearing below. */
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*LINTLIBRARY*/
-
-/*
- * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific written prior permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#ifdef LIBC_SCCS
-#ifndef lint
-static char sccsid[] = "@(#)getopt.c 4.5 (Berkeley) 11/24/87";
-#endif /* !defined lint */
-#endif /* defined LIBC_SCCS */
-
-#include <stdio.h>
-
-/*
- * get option letter from argument vector
- */
-extern int opterr; /* if error message should be printed */
-extern int optind; /* index into parent argv vector */
-extern int optopt; /* character checked for validity */
-extern char * optarg; /* argument associated with option */
-
-#define BADCH (int)'?'
-static char EMSG[1];
-#define tell(s) { \
- if (opterr) { \
- (void) fputs(*nargv, stderr); \
- (void) fputs(s, stderr); \
- (void) fputc(optopt, stderr); \
- (void) fputc((int)'\n', stderr); \
- } \
- return(BADCH); \
-}
-
-extern char * strchr();
-
-int
-getopt(nargc, nargv, ostr)
- int nargc;
- char **nargv, *ostr;
-{
- static char *place = EMSG; /* option letter processing */
- register char *oli; /* option letter list index */
-
- if (!*place) { /* update scanning pointer */
- if (optind >= nargc || *(place = nargv[optind]) != '-' ||
- !*++place)
- return(EOF);
- if (*place == '-') { /* found "--" */
- ++optind;
- return(EOF);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' ||
- !(oli = strchr(ostr, optopt))) {
- if (!*place)
- ++optind;
- tell(": illegal option -- ");
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place)
- ++optind;
- }
- else { /* need an argument */
- if (*place) /* no white space */
- optarg = place;
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- tell(": option requires an argument -- ");
- }
- else /* white space */
- optarg = nargv[optind];
- place = EMSG;
- ++optind;
- }
- return(optopt); /* dump back option letter */
-}
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)ialloc.c 8.24";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-
-#ifdef MAL
-#define NULLMAL(x) ((x) == NULL || (x) == MAL)
-#endif /* defined MAL */
-#ifndef MAL
-#define NULLMAL(x) ((x) == NULL)
-#endif /* !defined MAL */
-
-#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;
-{
-#ifdef MAL
- register char * result;
-
- result = malloc((alloc_size_T) nonzero(n));
- return NULLMAL(result) ? NULL : result;
-#endif /* defined MAL */
-#ifndef MAL
- return malloc((alloc_size_T) nonzero(n));
-#endif /* !defined MAL */
-}
-
-char *
-icalloc(nelem, elsize)
-int nelem;
-int elsize;
-{
- if (nelem == 0 || elsize == 0)
- nelem = elsize = 1;
- return calloc((alloc_size_T) nelem, (alloc_size_T) elsize);
-}
-
-void *
-irealloc(pointer, size)
-void * const pointer;
-const int size;
-{
- if (NULLMAL(pointer))
- return imalloc(size);
- return realloc((genericptr_T) pointer, (alloc_size_T) nonzero(size));
-}
-
-char *
-icatalloc(old, new)
-char * const old;
-const char * const new;
-{
- register char * result;
- register int oldsize, newsize;
-
- newsize = NULLMAL(new) ? 0 : strlen(new);
- if (NULLMAL(old))
- oldsize = 0;
- else if (newsize == 0)
- return old;
- else oldsize = strlen(old);
- if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
- if (!NULLMAL(new))
- (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 (!NULLMAL(p))
- (void) free(p);
-}
-
-void
-icfree(p)
-char * const p;
-{
- if (!NULLMAL(p))
- (void) free(p);
-}
+++ /dev/null
-# @(#)leapseconds 7.7
-
-# 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
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)localtime.c 7.26";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
-** POSIX-style TZ environment variable handling from Guy Harris
-** (guy@auspex.com).
-*/
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-#include "tzfile.h"
-#include "fcntl.h"
-
-#define ACCESS_MODE O_RDONLY
-
-#ifdef O_BINARY
-#define OPEN_MODE (O_RDONLY | O_BINARY)
-#endif /* defined O_BINARY */
-#ifndef O_BINARY
-#define OPEN_MODE O_RDONLY
-#endif /* !defined O_BINARY */
-
-#ifndef WILDABBR
-/*
-** Someone might make incorrect use of a time zone abbreviation:
-** 1. They might reference tzname[0] before calling tzset (explicitly
-** or implicitly).
-** 2. They might reference tzname[1] before calling tzset (explicitly
-** or implicitly).
-** 3. They might reference tzname[1] after setting to a time zone
-** in which Daylight Saving Time is never observed.
-** 4. They might reference tzname[0] after setting to a time zone
-** in which Standard Time is never observed.
-** 5. They might reference tm.TM_ZONE after calling offtime.
-** What's best to do in the above cases is open to debate;
-** for now, we just set things up so that in any of the five cases
-** WILDABBR is used. Another possibility: initialize tzname[0] to the
-** string "tzname[0] used before set", and similarly for the other cases.
-** And another: initialize tzname[0] to "ERA", with an explanation in the
-** manual page of what this "time zone abbreviation" means (doing this so
-** that tzname[0] has the "normal" length of three characters).
-*/
-#define WILDABBR " "
-#endif /* !defined WILDABBR */
-
-static char wildabbr[] = "WILDABBR";
-
-static const char gmt[] = "GMT";
-
-struct ttinfo { /* time type information */
- long tt_gmtoff; /* GMT offset in seconds */
- int tt_isdst; /* used to set tm_isdst */
- int tt_abbrind; /* abbreviation list index */
- int tt_ttisstd; /* TRUE if transition is std time */
-};
-
-struct lsinfo { /* leap second information */
- time_t ls_trans; /* transition time */
- long ls_corr; /* correction to apply */
-};
-
-#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
-
-#ifdef TZNAME_MAX
-#define MY_TZNAME_MAX TZNAME_MAX
-#endif /* defined TZNAME_MAX */
-#ifndef TZNAME_MAX
-#define MY_TZNAME_MAX 255
-#endif /* !defined TZNAME_MAX */
-
-struct state {
- int leapcnt;
- int timecnt;
- int typecnt;
- int charcnt;
- time_t ats[TZ_MAX_TIMES];
- unsigned char types[TZ_MAX_TIMES];
- struct ttinfo ttis[TZ_MAX_TYPES];
- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
- (2 * (MY_TZNAME_MAX + 1)))];
- struct lsinfo lsis[TZ_MAX_LEAPS];
-};
-
-struct rule {
- int r_type; /* type of rule--see below */
- int r_day; /* day number of rule */
- int r_week; /* week number of rule */
- int r_mon; /* month number of rule */
- long r_time; /* transition time of rule */
-};
-
-#define JULIAN_DAY 0 /* Jn - Julian day */
-#define DAY_OF_YEAR 1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
-
-/*
-** Prototypes for static functions.
-*/
-
-static long detzcode P((const char * codep));
-static const char * getzname P((const char * strp));
-static const char * getnum P((const char * strp, int * nump, int min,
- int max));
-static const char * getsecs P((const char * strp, long * secsp));
-static const char * getoffset P((const char * strp, long * offsetp));
-static const char * getrule P((const char * strp, struct rule * rulep));
-static void gmtload P((struct state * sp));
-static void gmtsub P((const time_t * timep, long offset,
- struct tm * tmp));
-static void localsub P((const time_t * timep, long offset,
- struct tm * tmp));
-static int increment_overflow P((int * number, int delta));
-static int normalize_overflow P((int * tensptr, int * unitsptr,
- int base));
-static void settzname P((void));
-static time_t time1 P((struct tm * tmp, void (* funcp)(),
- long offset));
-static time_t time2 P((struct tm *tmp, void (* funcp)(),
- long offset, int * okayp));
-static void timesub P((const time_t * timep, long offset,
- const struct state * sp, struct tm * tmp));
-static int tmcomp P((const struct tm * atmp,
- const struct tm * btmp));
-static time_t transtime P((time_t janfirst, int year,
- const struct rule * rulep, long offset));
-static int tzload P((const char * name, struct state * sp));
-static int tzparse P((const char * name, struct state * sp,
- int lastditch));
-
-#ifdef ALL_STATE
-static struct state * lclptr;
-static struct state * gmtptr;
-#endif /* defined ALL_STATE */
-
-#ifndef ALL_STATE
-static struct state lclmem;
-static struct state gmtmem;
-#define lclptr (&lclmem)
-#define gmtptr (&gmtmem)
-#endif /* State Farm */
-
-#ifndef TZ_STRLEN_MAX
-#define TZ_STRLEN_MAX 255
-#endif
-
-static char lcl_TZname[TZ_STRLEN_MAX + 1];
-static int lcl_is_set;
-static int gmt_is_set;
-
-char * tzname[2] = {
- wildabbr,
- wildabbr
-};
-
-/*
-** Section 4.12.3 of X3.159-1989 requires that
-** Except for the strftime function, these functions [asctime,
-** ctime, gmtime, localtime] return values in one of two static
-** objects: a broken-down time structure and an array of char.
-** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
-*/
-
-static struct tm tm;
-
-#ifdef USG_COMPAT
-time_t timezone = 0;
-int daylight = 0;
-#endif /* defined USG_COMPAT */
-
-#ifdef ALTZONE
-time_t altzone = 0;
-#endif /* defined ALTZONE */
-
-static long
-detzcode(codep)
-const char * const codep;
-{
- register long result;
- register int i;
-
- result = 0;
- for (i = 0; i < 4; ++i)
- result = (result << 8) | (codep[i] & 0xff);
- return result;
-}
-
-static void
-settzname P((void))
-{
- register const struct state * const sp = lclptr;
- register int i;
-
- tzname[0] = wildabbr;
- tzname[1] = wildabbr;
-#ifdef USG_COMPAT
- daylight = 0;
- timezone = 0;
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
- altzone = 0;
-#endif /* defined ALTZONE */
-#ifdef ALL_STATE
- if (sp == NULL) {
- tzname[0] = tzname[1] = gmt;
- return;
- }
-#endif /* defined ALL_STATE */
- for (i = 0; i < sp->typecnt; ++i) {
- register const struct ttinfo * const ttisp = &sp->ttis[i];
-
- tzname[ttisp->tt_isdst] =
- (char *) &sp->chars[ttisp->tt_abbrind];
-#ifdef USG_COMPAT
- if (ttisp->tt_isdst)
- daylight = 1;
- if (i == 0 || !ttisp->tt_isdst)
- timezone = -(ttisp->tt_gmtoff);
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
- if (i == 0 || ttisp->tt_isdst)
- altzone = -(ttisp->tt_gmtoff);
-#endif /* defined ALTZONE */
- }
- /*
- ** And to get the latest zone names into tzname. . .
- */
- for (i = 0; i < sp->timecnt; ++i) {
- register const struct ttinfo * const ttisp =
- &sp->ttis[
- sp->types[i]];
-
- tzname[ttisp->tt_isdst] =
- (char *) &sp->chars[ttisp->tt_abbrind];
- }
-}
-
-static int
-tzload(name, sp)
-register const char * name;
-register struct state * const sp;
-{
- register const char * p;
- register int i;
- register int fid;
-
- if (name == NULL && (name = TZDEFAULT) == NULL)
- return -1;
- {
- register int doaccess;
- char fullname[FILENAME_MAX + 1];
-
- if (name[0] == ':')
- ++name;
- doaccess = name[0] == '/';
- if (!doaccess) {
- if ((p = TZDIR) == NULL)
- return -1;
- if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
- return -1;
- (void) strcpy(fullname, p);
- (void) strcat(fullname, "/");
- (void) strcat(fullname, name);
- /*
- ** Set doaccess if '.' (as in "../") shows up in name.
- */
- if (strchr(name, '.') != NULL)
- doaccess = TRUE;
- name = fullname;
- }
- if (doaccess && access(name, ACCESS_MODE) != 0)
- return -1;
- if ((fid = open(name, OPEN_MODE)) == -1)
- return -1;
- }
- {
- register const struct tzhead * tzhp;
- char buf[sizeof *sp + sizeof *tzhp];
- int ttisstdcnt;
-
- i = read(fid, buf, sizeof buf);
- if (close(fid) != 0 || i < sizeof *tzhp)
- return -1;
- tzhp = (struct tzhead *) buf;
- ttisstdcnt = (int) detzcode(tzhp->tzh_ttisstdcnt);
- sp->leapcnt = (int) detzcode(tzhp->tzh_leapcnt);
- sp->timecnt = (int) detzcode(tzhp->tzh_timecnt);
- sp->typecnt = (int) detzcode(tzhp->tzh_typecnt);
- sp->charcnt = (int) detzcode(tzhp->tzh_charcnt);
- if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
- sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
- sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
- sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
- (ttisstdcnt != sp->typecnt && ttisstdcnt != 0))
- return -1;
- if (i < sizeof *tzhp +
- sp->timecnt * (4 + sizeof (char)) +
- sp->typecnt * (4 + 2 * sizeof (char)) +
- sp->charcnt * sizeof (char) +
- sp->leapcnt * 2 * 4 +
- ttisstdcnt * sizeof (char))
- return -1;
- p = buf + sizeof *tzhp;
- for (i = 0; i < sp->timecnt; ++i) {
- sp->ats[i] = detzcode(p);
- p += 4;
- }
- for (i = 0; i < sp->timecnt; ++i) {
- sp->types[i] = (unsigned char) *p++;
- if (sp->types[i] >= sp->typecnt)
- return -1;
- }
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- ttisp->tt_gmtoff = detzcode(p);
- p += 4;
- ttisp->tt_isdst = (unsigned char) *p++;
- if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
- return -1;
- ttisp->tt_abbrind = (unsigned char) *p++;
- if (ttisp->tt_abbrind < 0 ||
- ttisp->tt_abbrind > sp->charcnt)
- return -1;
- }
- for (i = 0; i < sp->charcnt; ++i)
- sp->chars[i] = *p++;
- sp->chars[i] = '\0'; /* ensure '\0' at end */
- for (i = 0; i < sp->leapcnt; ++i) {
- register struct lsinfo * lsisp;
-
- lsisp = &sp->lsis[i];
- lsisp->ls_trans = detzcode(p);
- p += 4;
- lsisp->ls_corr = detzcode(p);
- p += 4;
- }
- for (i = 0; i < sp->typecnt; ++i) {
- register struct ttinfo * ttisp;
-
- ttisp = &sp->ttis[i];
- if (ttisstdcnt == 0)
- ttisp->tt_ttisstd = FALSE;
- else {
- ttisp->tt_ttisstd = *p++;
- if (ttisp->tt_ttisstd != TRUE &&
- ttisp->tt_ttisstd != FALSE)
- return -1;
- }
- }
- }
- return 0;
-}
-
-static const int mon_lengths[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 year_lengths[2] = {
- DAYSPERNYEAR, DAYSPERLYEAR
-};
-
-/*
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-** character.
-*/
-
-static const char *
-getzname(strp)
-register const char * strp;
-{
- register char c;
-
- while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' &&
- c != '+')
- ++strp;
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract a number from that string.
-** Check that the number is within a specified range; if it is not, return
-** NULL.
-** Otherwise, return a pointer to the first character not part of the number.
-*/
-
-static const char *
-getnum(strp, nump, min, max)
-register const char * strp;
-int * const nump;
-const int min;
-const int max;
-{
- register char c;
- register int num;
-
- if (strp == NULL || !isdigit(*strp))
- return NULL;
- num = 0;
- while ((c = *strp) != '\0' && isdigit(c)) {
- num = num * 10 + (c - '0');
- if (num > max)
- return NULL; /* illegal value */
- ++strp;
- }
- if (num < min)
- return NULL; /* illegal value */
- *nump = num;
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract a number of seconds,
-** in hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the number
-** of seconds.
-*/
-
-static const char *
-getsecs(strp, secsp)
-register const char * strp;
-long * const secsp;
-{
- int num;
-
- /*
- ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
- ** "M10.4.6/26", which does not conform to Posix,
- ** but which specifies the equivalent of
- ** ``02:00 on the first Sunday on or after 23 Oct''.
- */
- strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
- if (strp == NULL)
- return NULL;
- *secsp = num * (long) SECSPERHOUR;
- if (*strp == ':') {
- ++strp;
- strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
- if (strp == NULL)
- return NULL;
- *secsp += num * SECSPERMIN;
- if (*strp == ':') {
- ++strp;
- /* `SECSPERMIN' allows for leap seconds. */
- strp = getnum(strp, &num, 0, SECSPERMIN);
- if (strp == NULL)
- return NULL;
- *secsp += num;
- }
- }
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract an offset, in
-** [+-]hh[:mm[:ss]] form, from the string.
-** If any error occurs, return NULL.
-** Otherwise, return a pointer to the first character not part of the time.
-*/
-
-static const char *
-getoffset(strp, offsetp)
-register const char * strp;
-long * const offsetp;
-{
- register int neg;
-
- if (*strp == '-') {
- neg = 1;
- ++strp;
- } else if (isdigit(*strp) || *strp++ == '+')
- neg = 0;
- else return NULL; /* illegal offset */
- strp = getsecs(strp, offsetp);
- if (strp == NULL)
- return NULL; /* illegal time */
- if (neg)
- *offsetp = -*offsetp;
- return strp;
-}
-
-/*
-** Given a pointer into a time zone string, extract a rule in the form
-** date[/time]. See POSIX section 8 for the format of "date" and "time".
-** If a valid rule is not found, return NULL.
-** Otherwise, return a pointer to the first character not part of the rule.
-*/
-
-static const char *
-getrule(strp, rulep)
-const char * strp;
-register struct rule * const rulep;
-{
- if (*strp == 'J') {
- /*
- ** Julian day.
- */
- rulep->r_type = JULIAN_DAY;
- ++strp;
- strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
- } else if (*strp == 'M') {
- /*
- ** Month, week, day.
- */
- rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
- ++strp;
- strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
- if (strp == NULL)
- return NULL;
- if (*strp++ != '.')
- return NULL;
- strp = getnum(strp, &rulep->r_week, 1, 5);
- if (strp == NULL)
- return NULL;
- if (*strp++ != '.')
- return NULL;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
- } else if (isdigit(*strp)) {
- /*
- ** Day of year.
- */
- rulep->r_type = DAY_OF_YEAR;
- strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
- } else return NULL; /* invalid format */
- if (strp == NULL)
- return NULL;
- if (*strp == '/') {
- /*
- ** Time specified.
- */
- ++strp;
- strp = getsecs(strp, &rulep->r_time);
- } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
- return strp;
-}
-
-/*
-** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the
-** year, a rule, and the offset from GMT at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
-*/
-
-static time_t
-transtime(janfirst, year, rulep, offset)
-const time_t janfirst;
-const int year;
-register const struct rule * const rulep;
-const long offset;
-{
- register int leapyear;
- register time_t value;
- register int i;
- int d, m1, yy0, yy1, yy2, dow;
-
- INITIALIZE(value);
- leapyear = isleap(year);
- switch (rulep->r_type) {
-
- case JULIAN_DAY:
- /*
- ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
- ** years.
- ** In non-leap years, or if the day number is 59 or less, just
- ** add SECSPERDAY times the day number-1 to the time of
- ** January 1, midnight, to get the day.
- */
- value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
- if (leapyear && rulep->r_day >= 60)
- value += SECSPERDAY;
- break;
-
- case DAY_OF_YEAR:
- /*
- ** n - day of year.
- ** Just add SECSPERDAY times the day number to the time of
- ** January 1, midnight, to get the day.
- */
- value = janfirst + rulep->r_day * SECSPERDAY;
- break;
-
- case MONTH_NTH_DAY_OF_WEEK:
- /*
- ** Mm.n.d - nth "dth day" of month m.
- */
- value = janfirst;
- for (i = 0; i < rulep->r_mon - 1; ++i)
- value += mon_lengths[leapyear][i] * SECSPERDAY;
-
- /*
- ** Use Zeller's Congruence to get day-of-week of first day of
- ** month.
- */
- m1 = (rulep->r_mon + 9) % 12 + 1;
- yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
- yy1 = yy0 / 100;
- yy2 = yy0 % 100;
- dow = ((26 * m1 - 2) / 10 +
- 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
- if (dow < 0)
- dow += DAYSPERWEEK;
-
- /*
- ** "dow" is the day-of-week of the first day of the month. Get
- ** the day-of-month (zero-origin) of the first "dow" day of the
- ** month.
- */
- d = rulep->r_day - dow;
- if (d < 0)
- d += DAYSPERWEEK;
- for (i = 1; i < rulep->r_week; ++i) {
- if (d + DAYSPERWEEK >=
- mon_lengths[leapyear][rulep->r_mon - 1])
- break;
- d += DAYSPERWEEK;
- }
-
- /*
- ** "d" is the day-of-month (zero-origin) of the day we want.
- */
- value += d * SECSPERDAY;
- break;
- }
-
- /*
- ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in
- ** question. To get the Epoch-relative time of the specified local
- ** time on that day, add the transition time and the current offset
- ** from GMT.
- */
- return value + rulep->r_time + offset;
-}
-
-/*
-** Given a POSIX section 8-style TZ string, fill in the rule tables as
-** appropriate.
-*/
-
-static int
-tzparse(name, sp, lastditch)
-const char * name;
-register struct state * const sp;
-const int lastditch;
-{
- const char * stdname;
- const char * dstname;
- size_t stdlen;
- size_t dstlen;
- long stdoffset;
- long dstoffset;
- register time_t * atp;
- register unsigned char * typep;
- register char * cp;
- register int load_result;
-
- INITIALIZE(dstname);
- stdname = name;
- if (lastditch) {
- stdlen = strlen(name); /* length of standard zone name */
- name += stdlen;
- if (stdlen >= sizeof sp->chars)
- stdlen = (sizeof sp->chars) - 1;
- } else {
- name = getzname(name);
- stdlen = name - stdname;
- if (stdlen < 3)
- return -1;
- }
- if (*name == '\0')
- return -1; /* was "stdoffset = 0;" */
- else {
- name = getoffset(name, &stdoffset);
- if (name == NULL)
- return -1;
- }
- load_result = tzload(TZDEFRULES, sp);
- if (load_result != 0)
- sp->leapcnt = 0; /* so, we're off a little */
- if (*name != '\0') {
- dstname = name;
- name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
- if (dstlen < 3)
- return -1;
- if (*name != '\0' && *name != ',' && *name != ';') {
- name = getoffset(name, &dstoffset);
- if (name == NULL)
- return -1;
- } else dstoffset = stdoffset - SECSPERHOUR;
- if (*name == ',' || *name == ';') {
- struct rule start;
- struct rule end;
- register int year;
- register time_t janfirst;
- time_t starttime;
- time_t endtime;
-
- ++name;
- if ((name = getrule(name, &start)) == NULL)
- return -1;
- if (*name++ != ',')
- return -1;
- if ((name = getrule(name, &end)) == NULL)
- return -1;
- if (*name != '\0')
- return -1;
- sp->typecnt = 2; /* standard time and DST */
- /*
- ** Two transitions per year, from EPOCH_YEAR to 2037.
- */
- sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
- if (sp->timecnt > TZ_MAX_TIMES)
- return -1;
- sp->ttis[0].tt_gmtoff = -dstoffset;
- sp->ttis[0].tt_isdst = 1;
- sp->ttis[0].tt_abbrind = stdlen + 1;
- sp->ttis[1].tt_gmtoff = -stdoffset;
- sp->ttis[1].tt_isdst = 0;
- sp->ttis[1].tt_abbrind = 0;
- atp = sp->ats;
- typep = sp->types;
- janfirst = 0;
- for (year = EPOCH_YEAR; year <= 2037; ++year) {
- starttime = transtime(janfirst, year, &start,
- stdoffset);
- endtime = transtime(janfirst, year, &end,
- dstoffset);
- if (starttime > endtime) {
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- } else {
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- }
- janfirst += year_lengths[isleap(year)] *
- SECSPERDAY;
- }
- } else {
- int sawstd;
- int sawdst;
- long stdfix;
- long dstfix;
- long oldfix;
- int isdst;
- register int i;
-
- if (*name != '\0')
- return -1;
- if (load_result != 0)
- return -1;
- /*
- ** Compute the difference between the real and
- ** prototype standard and summer time offsets
- ** from GMT, and put the real standard and summer
- ** time offsets into the rules in place of the
- ** prototype offsets.
- */
- sawstd = FALSE;
- sawdst = FALSE;
- stdfix = 0;
- dstfix = 0;
- for (i = 0; i < sp->typecnt; ++i) {
- if (sp->ttis[i].tt_isdst) {
- oldfix = dstfix;
- dstfix = sp->ttis[i].tt_gmtoff +
- dstoffset;
- if (sawdst && (oldfix != dstfix))
- return -1;
- sp->ttis[i].tt_gmtoff = -dstoffset;
- sp->ttis[i].tt_abbrind = stdlen + 1;
- sawdst = TRUE;
- } else {
- oldfix = stdfix;
- stdfix = sp->ttis[i].tt_gmtoff +
- stdoffset;
- if (sawstd && (oldfix != stdfix))
- return -1;
- sp->ttis[i].tt_gmtoff = -stdoffset;
- sp->ttis[i].tt_abbrind = 0;
- sawstd = TRUE;
- }
- }
- /*
- ** Make sure we have both standard and summer time.
- */
- if (!sawdst || !sawstd)
- return -1;
- /*
- ** Now correct the transition times by shifting
- ** them by the difference between the real and
- ** prototype offsets. Note that this difference
- ** can be different in standard and summer time;
- ** the prototype probably has a 1-hour difference
- ** between standard and summer time, but a different
- ** difference can be specified in TZ.
- */
- isdst = FALSE; /* we start in standard time */
- for (i = 0; i < sp->timecnt; ++i) {
- register const struct ttinfo * ttisp;
-
- /*
- ** If summer time is in effect, and the
- ** transition time was not specified as
- ** standard time, add the summer time
- ** offset to the transition time;
- ** otherwise, add the standard time offset
- ** to the transition time.
- */
- ttisp = &sp->ttis[sp->types[i]];
- sp->ats[i] +=
- (isdst && !ttisp->tt_ttisstd) ?
- dstfix : stdfix;
- isdst = ttisp->tt_isdst;
- }
- }
- } else {
- dstlen = 0;
- sp->typecnt = 1; /* only standard time */
- sp->timecnt = 0;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = 0;
- sp->ttis[0].tt_abbrind = 0;
- }
- sp->charcnt = stdlen + 1;
- if (dstlen != 0)
- sp->charcnt += dstlen + 1;
- if (sp->charcnt > sizeof sp->chars)
- return -1;
- cp = sp->chars;
- (void) strncpy(cp, stdname, stdlen);
- cp += stdlen;
- *cp++ = '\0';
- if (dstlen != 0) {
- (void) strncpy(cp, dstname, dstlen);
- *(cp + dstlen) = '\0';
- }
- return 0;
-}
-
-static void
-gmtload(sp)
-struct state * const sp;
-{
- if (tzload(gmt, sp) != 0)
- (void) tzparse(gmt, sp, TRUE);
-}
-
-#ifndef STD_INSPIRED
-/*
-** A non-static declaration of tzsetwall in a system header file
-** may cause a warning about this upcoming static declaration...
-*/
-static
-#endif /* !defined STD_INSPIRED */
-void
-tzsetwall P((void))
-{
- if (lcl_is_set < 0)
- return;
- lcl_is_set = -1;
-
-#ifdef ALL_STATE
- if (lclptr == NULL) {
- lclptr = (struct state *) malloc(sizeof *lclptr);
- if (lclptr == NULL) {
- settzname(); /* all we can do */
- return;
- }
- }
-#endif /* defined ALL_STATE */
- if (tzload((char *) NULL, lclptr) != 0)
- gmtload(lclptr);
- settzname();
-}
-
-void
-tzset P((void))
-{
- register const char * name;
-
- name = getenv("TZ");
- if (name == NULL) {
- tzsetwall();
- return;
- }
-
- if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
- return;
- lcl_is_set = (strlen(name) < sizeof(lcl_TZname));
- if (lcl_is_set)
- (void) strcpy(lcl_TZname, name);
-
-#ifdef ALL_STATE
- if (lclptr == NULL) {
- lclptr = (struct state *) malloc(sizeof *lclptr);
- if (lclptr == NULL) {
- settzname(); /* all we can do */
- return;
- }
- }
-#endif /* defined ALL_STATE */
- if (*name == '\0') {
- /*
- ** User wants it fast rather than right.
- */
- lclptr->leapcnt = 0; /* so, we're off a little */
- lclptr->timecnt = 0;
- lclptr->ttis[0].tt_gmtoff = 0;
- lclptr->ttis[0].tt_abbrind = 0;
- (void) strcpy(lclptr->chars, gmt);
- } else if (tzload(name, lclptr) != 0)
- if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
- (void) gmtload(lclptr);
- settzname();
-}
-
-/*
-** The easy way to behave "as if no library function calls" localtime
-** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
-** but it *is* desirable.)
-**
-** The unused offset argument is for the benefit of mktime variants.
-*/
-
-/*ARGSUSED*/
-static void
-localsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
-{
- register const struct state * sp;
- register const struct ttinfo * ttisp;
- register int i;
- const time_t t = *timep;
-
- sp = lclptr;
-#ifdef ALL_STATE
- if (sp == NULL) {
- gmtsub(timep, offset, tmp);
- return;
- }
-#endif /* defined ALL_STATE */
- if (sp->timecnt == 0 || t < sp->ats[0]) {
- i = 0;
- while (sp->ttis[i].tt_isdst)
- if (++i >= sp->typecnt) {
- i = 0;
- break;
- }
- } else {
- for (i = 1; i < sp->timecnt; ++i)
- if (t < sp->ats[i])
- break;
- i = sp->types[i - 1];
- }
- ttisp = &sp->ttis[i];
- /*
- ** To get (wrong) behavior that's compatible with System V Release 2.0
- ** you'd replace the statement below with
- ** t += ttisp->tt_gmtoff;
- ** timesub(&t, 0L, sp, tmp);
- */
- timesub(&t, ttisp->tt_gmtoff, sp, tmp);
- tmp->tm_isdst = ttisp->tt_isdst;
- tzname[tmp->tm_isdst] = (char *) &sp->chars[ttisp->tt_abbrind];
-#ifdef TM_ZONE
- tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
-#endif /* defined TM_ZONE */
-}
-
-struct tm *
-localtime(timep)
-const time_t * const timep;
-{
- tzset();
- localsub(timep, 0L, &tm);
- return &tm;
-}
-
-/*
-** gmtsub is to gmtime as localsub is to localtime.
-*/
-
-static void
-gmtsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
-{
- if (!gmt_is_set) {
- gmt_is_set = TRUE;
-#ifdef ALL_STATE
- gmtptr = (struct state *) malloc(sizeof *gmtptr);
- if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
- gmtload(gmtptr);
- }
- timesub(timep, offset, gmtptr, tmp);
-#ifdef TM_ZONE
- /*
- ** Could get fancy here and deliver something such as
- ** "GMT+xxxx" or "GMT-xxxx" if offset is non-zero,
- ** but this is no time for a treasure hunt.
- */
- if (offset != 0)
- tmp->TM_ZONE = wildabbr;
- else {
-#ifdef ALL_STATE
- if (gmtptr == NULL)
- tmp->TM_ZONE = gmt;
- else tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- tmp->TM_ZONE = gmtptr->chars;
-#endif /* State Farm */
- }
-#endif /* defined TM_ZONE */
-}
-
-struct tm *
-gmtime(timep)
-const time_t * const timep;
-{
- gmtsub(timep, 0L, &tm);
- return &tm;
-}
-
-#ifdef STD_INSPIRED
-
-struct tm *
-offtime(timep, offset)
-const time_t * const timep;
-const long offset;
-{
- gmtsub(timep, offset, &tm);
- return &tm;
-}
-
-#endif /* defined STD_INSPIRED */
-
-static void
-timesub(timep, offset, sp, tmp)
-const time_t * const timep;
-const long offset;
-register const struct state * const sp;
-register struct tm * const tmp;
-{
- register const struct lsinfo * lp;
- register long days;
- register long rem;
- register int y;
- register int yleap;
- register const int * ip;
- register long corr;
- register int hit;
- register int i;
-
- corr = 0;
- hit = 0;
-#ifdef ALL_STATE
- i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- i = sp->leapcnt;
-#endif /* State Farm */
- while (--i >= 0) {
- lp = &sp->lsis[i];
- if (*timep >= lp->ls_trans) {
- if (*timep == lp->ls_trans) {
- hit = ((i == 0 && lp->ls_corr > 0) ||
- lp->ls_corr > sp->lsis[i - 1].ls_corr);
- if (hit)
- while (i > 0 &&
- sp->lsis[i].ls_trans ==
- sp->lsis[i - 1].ls_trans + 1 &&
- sp->lsis[i].ls_corr ==
- sp->lsis[i - 1].ls_corr + 1) {
- ++hit;
- --i;
- }
- }
- corr = lp->ls_corr;
- break;
- }
- }
- days = *timep / SECSPERDAY;
- rem = *timep % SECSPERDAY;
-#ifdef mc68k
- if (*timep == 0x80000000) {
- /*
- ** A 3B1 muffs the division on the most negative number.
- */
- days = -24855;
- rem = -11648;
- }
-#endif /* mc68k */
- rem += (offset - corr);
- while (rem < 0) {
- rem += SECSPERDAY;
- --days;
- }
- while (rem >= SECSPERDAY) {
- rem -= SECSPERDAY;
- ++days;
- }
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
- rem = rem % SECSPERHOUR;
- tmp->tm_min = (int) (rem / SECSPERMIN);
- tmp->tm_sec = (int) (rem % SECSPERMIN);
- if (hit)
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec += hit;
- tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
- if (tmp->tm_wday < 0)
- tmp->tm_wday += DAYSPERWEEK;
- y = EPOCH_YEAR;
- if (days >= 0)
- for ( ; ; ) {
- yleap = isleap(y);
- if (days < (long) year_lengths[yleap])
- break;
- ++y;
- days = days - (long) year_lengths[yleap];
- }
- else do {
- --y;
- yleap = isleap(y);
- days = days + (long) year_lengths[yleap];
- } while (days < 0);
- tmp->tm_year = y - TM_YEAR_BASE;
- tmp->tm_yday = (int) days;
- ip = mon_lengths[yleap];
- for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
- days = days - (long) ip[tmp->tm_mon];
- tmp->tm_mday = (int) (days + 1);
- tmp->tm_isdst = 0;
-#ifdef TM_GMTOFF
- tmp->TM_GMTOFF = offset;
-#endif /* defined TM_GMTOFF */
-}
-
-char *
-ctime(timep)
-const time_t * const timep;
-{
-/*
-** Section 4.12.3.2 of X3.159-1989 requires that
-** The ctime funciton converts the calendar time pointed to by timer
-** to local time in the form of a string. It is equivalent to
-** asctime(localtime(timer))
-*/
- return asctime(localtime(timep));
-}
-
-/*
-** Adapted from code provided by Robert Elz, who writes:
-** The "best" way to do mktime I think is based on an idea of Bob
-** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now).
-** It does a binary search of the time_t space. Since time_t's are
-** just 32 bits, its a max of 32 iterations (even at 64 bits it
-** would still be very reasonable).
-*/
-
-#ifndef WRONG
-#define WRONG (-1)
-#endif /* !defined WRONG */
-
-/*
-** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
-*/
-
-static int
-increment_overflow(number, delta)
-int * number;
-int delta;
-{
- int number0;
-
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
-}
-
-static int
-normalize_overflow(tensptr, unitsptr, base)
-int * const tensptr;
-int * const unitsptr;
-const int base;
-{
- register int tensdelta;
-
- tensdelta = (*unitsptr >= 0) ?
- (*unitsptr / base) :
- (-1 - (-1 - *unitsptr) / base);
- *unitsptr -= tensdelta * base;
- return increment_overflow(tensptr, tensdelta);
-}
-
-static int
-tmcomp(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
-{
- register int result;
-
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
-}
-
-static time_t
-time2(tmp, funcp, offset, okayp)
-struct tm * const tmp;
-void (* const funcp)();
-const long offset;
-int * const okayp;
-{
- register const struct state * sp;
- register int dir;
- register int bits;
- register int i, j ;
- register int saved_seconds;
- time_t newt;
- time_t t;
- struct tm yourtm, mytm;
-
- *okayp = FALSE;
- yourtm = *tmp;
- if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
- return WRONG;
- if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
- return WRONG;
- if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
- return WRONG;
- /*
- ** Turn yourtm.tm_year into an actual year number for now.
- ** It is converted back to an offset from TM_YEAR_BASE later.
- */
- if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
- return WRONG;
- while (yourtm.tm_mday <= 0) {
- if (increment_overflow(&yourtm.tm_year, -1))
- return WRONG;
- yourtm.tm_mday += year_lengths[isleap(yourtm.tm_year)];
- }
- while (yourtm.tm_mday > DAYSPERLYEAR) {
- yourtm.tm_mday -= year_lengths[isleap(yourtm.tm_year)];
- if (increment_overflow(&yourtm.tm_year, 1))
- return WRONG;
- }
- for ( ; ; ) {
- i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
- if (yourtm.tm_mday <= i)
- break;
- yourtm.tm_mday -= i;
- if (++yourtm.tm_mon >= MONSPERYEAR) {
- yourtm.tm_mon = 0;
- if (increment_overflow(&yourtm.tm_year, 1))
- return WRONG;
- }
- }
- if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
- return WRONG;
- if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR) {
- /*
- ** We can't set tm_sec to 0, because that might push the
- ** time below the minimum representable time.
- ** Set tm_sec to 59 instead.
- ** This assumes that the minimum representable time is
- ** not in the same minute that a leap second was deleted from,
- ** which is a safer assumption than using 58 would be.
- */
- if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
- return WRONG;
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = SECSPERMIN - 1;
- } else {
- saved_seconds = yourtm.tm_sec;
- yourtm.tm_sec = 0;
- }
- /*
- ** Calculate the number of magnitude bits in a time_t
- ** (this works regardless of whether time_t is
- ** signed or unsigned, though lint complains if unsigned).
- */
- for (bits = 0, t = 1; t > 0; ++bits, t <<= 1)
- continue;
- /*
- ** If time_t is signed, then 0 is the median value,
- ** if time_t is unsigned, then 1 << bits is median.
- */
- t = (t < 0) ? 0 : ((time_t) 1 << bits);
- for ( ; ; ) {
- (*funcp)(&t, offset, &mytm);
- dir = tmcomp(&mytm, &yourtm);
- if (dir != 0) {
- if (bits-- < 0)
- return WRONG;
- if (bits < 0)
- --t;
- else if (dir > 0)
- t -= (time_t) 1 << bits;
- else t += (time_t) 1 << bits;
- continue;
- }
- if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
- break;
- /*
- ** Right time, wrong type.
- ** Hunt for right time, right type.
- ** It's okay to guess wrong since the guess
- ** gets checked.
- */
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
- sp = (const struct state *)
- (((void *) funcp == (void *) localsub) ?
- lclptr : gmtptr);
-#ifdef ALL_STATE
- if (sp == NULL)
- return WRONG;
-#endif /* defined ALL_STATE */
- for (i = 0; i < sp->typecnt; ++i) {
- if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
- continue;
- for (j = 0; j < sp->typecnt; ++j) {
- if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
- continue;
- newt = t + sp->ttis[j].tt_gmtoff -
- sp->ttis[i].tt_gmtoff;
- (*funcp)(&newt, offset, &mytm);
- if (tmcomp(&mytm, &yourtm) != 0)
- continue;
- if (mytm.tm_isdst != yourtm.tm_isdst)
- continue;
- /*
- ** We have a match.
- */
- t = newt;
- goto label;
- }
- }
- return WRONG;
- }
-label:
- newt = t + saved_seconds;
- if ((newt < t) != (saved_seconds < 0))
- return WRONG;
- t = newt;
- (*funcp)(&t, offset, tmp);
- *okayp = TRUE;
- return t;
-}
-
-static time_t
-time1(tmp, funcp, offset)
-struct tm * const tmp;
-void (* const funcp)();
-const long offset;
-{
- register time_t t;
- register const struct state * sp;
- register int samei, otheri;
- int okay;
-
- if (tmp->tm_isdst > 1)
- tmp->tm_isdst = 1;
- t = time2(tmp, funcp, offset, &okay);
-#ifdef PCTS
- /*
- ** PCTS code courtesy Grant Sullivan (grant@osf.org).
- */
- if (okay)
- return t;
- if (tmp->tm_isdst < 0)
- tmp->tm_isdst = 0; /* reset to std and try again */
-#endif /* defined PCTS */
-#ifndef PCTS
- if (okay || tmp->tm_isdst < 0)
- return t;
-#endif /* !defined PCTS */
- /*
- ** We're supposed to assume that somebody took a time of one type
- ** and did some math on it that yielded a "struct tm" that's bad.
- ** We try to divine the type they started from and adjust to the
- ** type they need.
- */
- /*
- ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
- */
- sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
- lclptr : gmtptr);
-#ifdef ALL_STATE
- if (sp == NULL)
- return WRONG;
-#endif /* defined ALL_STATE */
- for (samei = 0; samei < sp->typecnt; ++samei) {
- if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
- continue;
- for (otheri = 0; otheri < sp->typecnt; ++otheri) {
- if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
- continue;
- tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
- tmp->tm_isdst = !tmp->tm_isdst;
- t = time2(tmp, funcp, offset, &okay);
- if (okay)
- return t;
- tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
- tmp->tm_isdst = !tmp->tm_isdst;
- }
- }
- return WRONG;
-}
-
-time_t
-mktime(tmp)
-struct tm * const tmp;
-{
- tzset();
- return time1(tmp, localsub, 0L);
-}
-
-#ifdef STD_INSPIRED
-
-time_t
-timelocal(tmp)
-struct tm * const tmp;
-{
- tmp->tm_isdst = -1; /* in case it wasn't initialized */
- return mktime(tmp);
-}
-
-time_t
-timegm(tmp)
-struct tm * const tmp;
-{
- tmp->tm_isdst = 0;
- return time1(tmp, gmtsub, 0L);
-}
-
-time_t
-timeoff(tmp, offset)
-struct tm * const tmp;
-const long offset;
-{
- tmp->tm_isdst = 0;
- return time1(tmp, gmtsub, offset);
-}
-
-#endif /* defined STD_INSPIRED */
-
-#ifdef CMUCS
-
-/*
-** The following is supplied for compatibility with
-** previous versions of the CMUCS runtime library.
-*/
-
-long
-gtime(tmp)
-struct tm * const tmp;
-{
- const time_t t = mktime(tmp);
-
- if (t == WRONG)
- return -1;
- return t;
-}
-
-#endif /* defined CMUCS */
-
-/*
-** XXX--is the below the right way to conditionalize??
-*/
-
-#ifdef STD_INSPIRED
-
-/*
-** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
-** shall correspond to "Wed Dec 31 23:59:59 GMT 1986", which
-** is not the case if we are accounting for leap seconds.
-** So, we provide the following conversion routines for use
-** when exchanging timestamps with POSIX conforming systems.
-*/
-
-static long
-leapcorr(timep)
-time_t * timep;
-{
- register struct state * sp;
- register struct lsinfo * lp;
- register int i;
-
- sp = lclptr;
- i = sp->leapcnt;
- while (--i >= 0) {
- lp = &sp->lsis[i];
- if (*timep >= lp->ls_trans)
- return lp->ls_corr;
- }
- return 0;
-}
-
-time_t
-time2posix(t)
-time_t t;
-{
- tzset();
- return t - leapcorr(&t);
-}
-
-time_t
-posix2time(t)
-time_t t;
-{
- time_t x;
- time_t y;
-
- tzset();
- /*
- ** For a positive leap second hit, the result
- ** is not unique. For a negative leap second
- ** hit, the corresponding time doesn't exist,
- ** so we return an adjacent second.
- */
- x = t + leapcorr(&t);
- y = x - leapcorr(&x);
- if (y < t) {
- do {
- x++;
- y = x - leapcorr(&x);
- } while (y < t);
- if (t != y)
- return x - 1;
- } else if (y > t) {
- do {
- --x;
- y = x - leapcorr(&x);
- } while (y > t);
- if (t != y)
- return x + 1;
- }
- return x;
-}
-
-#endif /* defined STD_INSPIRED */
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)logwtmp.c 7.4";
-/* As received from UCB, with include reordering and OLD_TIME condition. */
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
- * Copyright (c) 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANT[A]BILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-#ifdef LIBC_SCCS
-static char sccsid[] = "@(#)logwtmp.c 5.2 (Berkeley) 9/20/88";
-#endif /* defined LIBC_SCCS */
-#endif /* !defined lint */
-
-#include <sys/types.h>
-#include <utmp.h>
-
-#ifndef OLD_TIME
-
-#include <sys/file.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-
-#define WTMPFILE "/usr/adm/wtmp"
-
-logwtmp(line, name, host)
- char *line, *name, *host;
-{
- struct utmp ut;
- struct stat buf;
- int fd;
- time_t time();
- char *strncpy();
-
- if ((fd = open(WTMPFILE, O_WRONLY|O_APPEND, 0)) < 0)
- return;
- if (!fstat(fd, &buf)) {
- (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
- (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
- (void)time(&ut.ut_time);
- if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
- sizeof(struct utmp))
- (void)ftruncate(fd, buf.st_size);
- }
- (void)close(fd);
-}
-
-#endif /* !defined OLD_TIME */
+++ /dev/null
-.TH NEWCTIME 3
-.SH NAME
-asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time to ASCII
-.SH SYNOPSIS
-.nf
-.B extern char *tzname[2];
-.PP
-.B void tzset()
-.PP
-.B #include <sys/types.h>
-.PP
-.B char *ctime(clock)
-.B time_t *clock;
-.PP
-.B double difftime(time1, time0)
-.B time_t time1;
-.B time_t time0;
-.PP
-.B #include <time.h>
-.PP
-.B char *asctime(tm)
-.B struct tm *tm;
-.PP
-.B struct tm *localtime(clock)
-.B long *clock;
-.PP
-.B struct tm *gmtime(clock)
-.B long *clock;
-.PP
-.B time_t mktime(tm)
-.B struct tm *tm;
-.PP
-.B cc ... -lz
-.fi
-.SH DESCRIPTION
-.I Ctime\^
-converts a long integer, pointed to by
-.IR clock ,
-representing the time in seconds since
-00:00:00 UTC, January 1, 1970,
-and returns a pointer to a
-26-character string
-of the form
-.br
-.ce
-.eo
-Thu Nov 24 18:22:48 1986\n\0
-.ec
-.br
-All the fields have constant width.
-.PP
-.IR Localtime\^
-and
-.I gmtime\^
-return pointers to ``tm'' structures, described below.
-.I Localtime\^
-corrects for the time zone and any time zone adjustments
-(such as Daylight Saving Time in the U.S.A.).
-Before doing so,
-.I localtime\^
-calls
-.I tzset\^
-(if
-.I tzset\^
-has not been called in the current process).
-After filling in the ``tm'' structure,
-.I localtime
-sets the
-.BR tm_isdst 'th
-element of
-.B tzname
-to a pointer to an
-ASCII string that's the time zone abbreviation to be used with
-.IR localtime 's
-return value.
-.PP
-.I Gmtime\^
-converts to Coordinated Universal Time.
-.PP
-.I Asctime\^
-converts a time value contained in a
-``tm'' structure to a 26-character string,
-as shown in the above example,
-and returns a pointer
-to the string.
-.PP
-.I Mktime\^
-converts the broken-down time,
-expressed as local time,
-in the structure pointed to by
-.I tm
-into a calendar time value with the same encoding as that of the values
-returned by the
-.I time
-function.
-The original values of the
-.B tm_wday
-and
-.B tm_yday
-components of the structure are ignored,
-and the original values of the other components are not restricted
-to their normal ranges.
-(A positive or zero value for
-.B tm_isdst
-causes
-.I mktime
-to presume initially that summer time (for example, Daylight Saving Time
-in the U.S.A.)
-respectively,
-is or is not in effect for the specified time.
-A negative value for
-.B tm_isdst
-causes the
-.I mktime
-function to attempt to divine whether summer time is in effect
-for the specified time.)
-On successful completion, the values of the
-.B tm_wday
-and
-.B tm_yday
-components of the structure are set appropriately,
-and the other components are set to represent the specified calendar time,
-but with their values forced to their normal ranges; the final value of
-.B tm_mday
-is not set until
-.B tm_mon
-and
-.B tm_year
-are determined.
-.I Mktime\^
-returns the specified calendar time;
-If the calendar time cannot be represented,
-it returns
-.BR -1 .
-.PP
-.I Difftime\^
-returns the difference between two calendar times,
-.RI ( time1
--
-.IR time0 ),
-expressed in seconds.
-.PP
-Declarations of all the functions and externals, and the ``tm'' structure,
-are in the
-.B <time.h>\^
-header file.
-The structure (of type)
-.B struct tm
-includes the following fields:
-.RS
-.PP
-.nf
-.ta .5i +\w'long tm_gmtoff;\0\0'u
- int tm_sec; /\(** seconds (0 - 60) \(**/
- int tm_min; /\(** minutes (0 - 59) \(**/
- int tm_hour; /\(** hours (0 - 23) \(**/
- int tm_mday; /\(** day of month (1 - 31) \(**/
- int tm_mon; /\(** month of year (0 - 11) \(**/
- int tm_year; /\(** year \- 1900 \(**/
- int tm_wday; /\(** day of week (Sunday = 0) \(**/
- int tm_yday; /\(** day of year (0 - 365) \(**/
- int tm_isdst; /\(** is summer time in effect? \(**/
- char \(**tm_zone; /\(** abbreviation of timezone name \(**/
- long tm_gmtoff; /\(** offset from UTC in seconds \(**/
-.fi
-.RE
-.PP
-The
-.I tm_zone
-and
-.I tm_gmtoff
-fields exist, and are filled in, only if arrangements to do
-so were made when the library containing these functions was
-created.
-There is no guarantee that these fields will continue to exist
-in this form in future releases of this code.
-.PP
-.I Tm_isdst\^
-is non-zero if summer time is in effect.
-.PP
-.I Tm_gmtoff
-is the offset (in seconds) of the time represented
-from UTC, with positive values indicating east
-of the Prime Meridian.
-.SH FILES
-.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u
-/usr/local/etc/zoneinfo time zone information directory
-.br
-/usr/local/etc/zoneinfo/localtime local time zone file
-.br
-/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's
-.br
-/usr/local/etc/zoneinfo/GMT for UTC leap seconds
-.sp
-If
-.B /usr/local/etc/zoneinfo/GMT
-is absent,
-UTC leap seconds are loaded from
-.BR /usr/local/etc/zoneinfo/posixrules .
-.SH SEE ALSO
-getenv(3),
-newtzset(3),
-time(2),
-tzfile(5)
-.SH NOTES
-The return values point to static data;
-the data is overwritten by each call.
-The
-.B tm_zone
-field of a returned
-.B "struct tm"
-points to a static array of characters, which
-will also be overwritten at the next call
-(and by calls to
-.IR tzset ).
-.PP
-Avoid using out-of-range values with
-.I mktime
-when setting up lunch with promptness sticklers in Riyadh.
-.\" @(#)newctime.3 7.9
+++ /dev/null
-.TH NEWTZSET 3
-.SH NAME
-tzset \- initialize time conversion information
-.SH SYNOPSIS
-.nf
-.B void tzset()
-.PP
-.B cc ... -lz
-.fi
-.SH DESCRIPTION
-.I Tzset
-uses the value of the environment variable
-.B TZ
-to set time conversion information used by
-.IR localtime .
-If
-.B TZ
-does not appear in the environment,
-the best available approximation to local wall clock time, as specified
-by the
-.IR tzfile (5)-format
-file
-.B localtime
-in the system time conversion information directory, is used by
-.IR localtime .
-If
-.B TZ
-appears in the environment but its value is a null string,
-Coordinated Universal Time (UTC) is used (without leap second
-correction). If
-.B TZ
-appears in the environment and its value is not a null string:
-.IP
-if the value begins with a colon, it is used as a pathname of a file
-from which to read the time conversion information;
-.IP
-if the value does not begin with a colon, it is first used as the
-pathname of a file from which to read the time conversion information,
-and, if that file cannot be read, is used directly as a specification of
-the time conversion information.
-.PP
-When
-.B TZ
-is used as a pathname, if it begins with a slash,
-it is used as an absolute pathname; otherwise,
-it is used as a pathname relative to a system time conversion information
-directory.
-The file must be in the format specified in
-.IR tzfile (5).
-.PP
-When
-.B TZ
-is used directly as a specification of the time conversion information,
-it must have the following syntax (spaces inserted for clarity):
-.IP
-\fIstd\|offset\fR[\fIdst\fR[\fIoffset\fR][\fB,\fIrule\fR]]
-.PP
-Where:
-.RS
-.TP 15
-.IR std " and " dst
-Three or more bytes that are the designation for the standard
-.RI ( std )
-or summer
-.RI ( dst )
-time zone. Only
-.I std
-is required; if
-.I dst
-is missing, then summer time does not apply in this locale.
-Upper- and lowercase letters are explicitly allowed. Any characters
-except a leading colon
-.RB ( : ),
-digits, comma
-.RB ( , ),
-minus
-.RB ( \(mi ),
-plus
-.RB ( \(pl ),
-and ASCII NUL are allowed.
-.TP
-.I offset
-Indicates the value one must add to the local time to arrive at
-Coordinated Universal Time. The
-.I offset
-has the form:
-.RS
-.IP
-\fIhh\fR[\fB:\fImm\fR[\fB:\fIss\fR]]
-.RE
-.IP
-The minutes
-.RI ( mm )
-and seconds
-.RI ( ss )
-are optional. The hour
-.RI ( hh )
-is required and may be a single digit. The
-.I offset
-following
-.I std
-is required. If no
-.I offset
-follows
-.IR dst ,
-summer time is assumed to be one hour ahead of standard time. One or
-more digits may be used; the value is always interpreted as a decimal
-number. The hour must be between zero and 24, and the minutes (and
-seconds) \(em if present \(em between zero and 59. If preceded by a
-.RB `` \(mi '',
-the time zone shall be east of the Prime Meridian; otherwise it shall be
-west (which may be indicated by an optional preceding
-.RB `` \(pl '').
-.TP
-.I rule
-Indicates when to change to and back from summer time. The
-.I rule
-has the form:
-.RS
-.IP
-\fIdate\fB/\fItime\fB,\fIdate\fB/\fItime\fR
-.RE
-.IP
-where the first
-.I date
-describes when the change from standard to summer time occurs and the
-second
-.I date
-describes when the change back happens. Each
-.I time
-field describes when, in current local time, the change to the other
-time is made.
-.IP
-The format of
-.I date
-is one of the following:
-.RS
-.TP 10
-.BI J n
-The Julian day
-.I n
-.RI "(1\ \(<=" "\ n\ " "\(<=\ 365).
-Leap days are not counted; that is, in all years \(em including leap
-years \(em February 28 is day 59 and March 1 is day 60. It is
-impossible to explicitly refer to the occasional February 29.
-.TP
-.I n
-The zero-based Julian day
-.RI "(0\ \(<=" "\ n\ " "\(<=\ 365).
-Leap days are counted, and it is possible to refer to February 29.
-.TP
-.BI M m . n . d
-The
-.IR d' th
-day
-.RI "(0\ \(<=" "\ d\ " "\(<=\ 6)
-of week
-.I n
-of month
-.I m
-of the year
-.RI "(1\ \(<=" "\ n\ " "\(<=\ 5,
-.RI "1\ \(<=" "\ m\ " "\(<=\ 12,
-where week 5 means ``the last
-.I d
-day in month
-.IR m ''
-which may occur in either the fourth or the fifth week). Week 1 is the
-first week in which the
-.IR d' th
-day occurs. Day zero is Sunday.
-.RE
-.IP "" 15
-The
-.I time
-has the same format as
-.I offset
-except that no leading sign
-.RB (`` \(mi ''
-or
-.RB `` \(pl '')
-is allowed. The default, if
-.I time
-is not given, is
-.BR 02:00:00 .
-.RE
-.LP
-If no
-.I rule
-is present in
-.BR TZ ,
-the rules specified
-by the
-.IR tzfile (5)-format
-file
-.B posixrules
-in the system time conversion information directory are used, with the
-standard and summer time offsets from UTC replaced by those specified by
-the
-.I offset
-values in
-.BR TZ .
-.PP
-For compatibility with System V Release 3.1, a semicolon
-.RB ( ; )
-may be used to separate the
-.I rule
-from the rest of the specification.
-.PP
-If the
-.B TZ
-environment variable does not specify a
-.IR tzfile (5)-format
-and cannot be interpreted as a direct specification,
-UTC is used.
-.SH FILES
-.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u
-/usr/local/etc/zoneinfo time zone information directory
-.br
-/usr/local/etc/zoneinfo/localtime local time zone file
-.br
-/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's
-.br
-/usr/local/etc/zoneinfo/GMT for UTC leap seconds
-.sp
-If
-.B /usr/local/etc/zoneinfo/GMT
-is absent,
-UTC leap seconds are loaded from
-.BR /usr/local/etc/zoneinfo/posixrules .
-.SH SEE ALSO
-getenv(3),
-newctime(3),
-time(2),
-tzfile(5)
-.\" @(#)newtzset.3 7.3
+++ /dev/null
-# @(#)northamerica 7.12
-# 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> (August 17, 1994):
-# 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 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, October 26, 1974
-# and Sunday, October 27, 1974 editions of the Washington Post.
-
-# From seismo!munnari!kre:
-# I recall also being told by someone once that Canada didn't have
-# the DST variations in 74/75 that the US did, but I am not nearly
-# sure enough of this to add anything.
-
-# From Arthur David Olson:
-# The above has been confirmed by Bob Devine; we'll go with it here.
-
-# 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 D
-Rule US 1918 1919 - Oct lastSun 2:00 0 S
-Rule US 1942 only - Feb 9 2:00 1:00 W # War
-Rule US 1945 only - 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 (January 28, 1988):
-# ...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 U. S. Naval Observatory (January 19, 1989):
-# 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 (January 21, 1989):
-# 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 (February 13, 1988):
-# 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 April 1, 1967 (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 April 1, 1967 until November 30, 1983 (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 November 30, 1983:
-# 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 <eggert@twinsun.com> (August 16, 1994):
-# Howse writes that Alaska switched from the Julian to the Gregorian calendar,
-# and from east-of-GMT to west-of-GMT days, in 1867 when the US purchased it
-# from Russia. We don't have this data pinned down yet, though.
-
-# Easy stuff first--including Alaska, where we ignore history (since we
-# can't tell if we should give Yukon time or Alaska-Hawaii time for "old"
-# times).
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/New_York -5:00 US E%sT
-Zone America/Chicago -6:00 US C%sT
-Zone America/Denver -7:00 US M%sT
-Zone America/Los_Angeles -8:00 US P%sT
-Zone America/Anchorage -9:00 US AK%sT
- # AK%sT is the abbreviation per USNO
-
-# Mainland US areas that are always Standard as of 1986.
-
-Zone America/Fort_Wayne -5:00 US E%sT 1946
- -5:00 - EST # Always EST as of 1986
-# From Arthur David Olson (October 28, 1991):
-# An article on page A3 of the Sunday, October 27, 1991 Washington Post
-# notes that Starke County switched from Central time to Eastern time as of
-# October 27, 1991.
-Zone America/Knox_IN -6:00 US C%sT 1991 Oct 27 2:00
- -5:00 - EST # Always EST as of 1991
-Zone America/Phoenix -7:00 US M%sT 1946
- -7:00 - MST # Always MST as of 1986
-
-# From Arthur David Olson (February 13, 1988):
-# However. . .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 Navajo
-
-# From Bob Devine (January 28, 1988):
-# Michigan didn't observe DST from 1968 to 1973.
-
-Zone America/Detroit -5:00 US E%sT 1968
- -5:00 - EST 1973
- -5:00 US E%sT
-
-# Samoa just changes names. No DST, per Naval Observatory.
-#
-# 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.''
-
-Zone Pacific/Samoa 12:37:12 - LMT 1879 Jul 5
- -11:22:48 - LMT 1911
- -11:30 - SST 1950
- -11:00 - NST 1967 Apr # N=Nome
- -11:00 - BST 1983 Nov 30 # B=Bering
- -11:00 - SST # S=Samoa
-
-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
-
-# Aleutian has a name change. DST, per Naval Observatory.
-
-Zone America/Atka -10:00 US AH%sT 1983 Nov 30
- -10:00 US HA%sT
-
-# From Arthur David Olson:
-# And then there's Hawaii.
-# DST was observed for one day in 1933;
-# Standard time was change by half an hour in 1947;
-# it's always standard as of 1986.
-
-Zone Pacific/Honolulu -10:30 US H%sT 1933 Apr 30 2:00
- -10:30 1:00 HDT 1933 May 1 2:00
- -10:30 US H%sT 1947 Jun 8 2:00
- -10:00 - HST
-
-# Navassa
-# no information; probably like US/Eastern
-
-
-# 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/Fort_Wayne EST
-Link America/Phoenix MST
-Link Pacific/Honolulu HST
-
-################################################################################
-
-
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# 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.
-#
-# 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 abbreviation SPST for St Pierre Standard Time; SPDT likewise.
-# Corrections are welcome!
-#
-# See the `europe' file for Greenland.
-#
-# See the `africa' file for Zone naming conventions.
-
-
-
-# Canada
-
-# Canada is reportedly lots easier than the US--leastways since 1951.
-# I don't know what they did before then.
-# 4.3BSD claims that it's perfectly regular.
-# According to a posting in "comp.bugs.misc", "comp.unix.wizards", etc.
-# on February 8, 1987, by Dave Sherman of the Law Society of Upper Canada,
-# "...Canada (well, Ontario and at least some of the other provinces) are
-# adopting the new daylight savings time rules...". We assume all of
-# Canada is doing so.
-
-# From Bob Devine (January 28, 1988):
-# All of Canada did have DST from your first rule except Saskatchewan.
-# Which parts did not observe DST is hard to pinpoint but most of the
-# province follows the rules.
-# NOTE: those that didn't have DST for that rule, also
-# probably did not have it for several years previous.
-
-# From U. S. Naval Observatory (January 19, 1989):
-# CANADA NEW FDL 3.5H BEHIND UTC ST.JOHN'S
-# CANADA NEW FDL 1.5H BEHIND UTC APR 3 - OCT 29
-# CANADA ATLANTIC 4 H BEHIND UTC HALIFAX
-# CANADA ATLANTIC 3 H BEHIND UTC APR 3 - OCT 29
-# CANADA EASTERN 5 H BEHIND UTC TORONTO, MONTREAL, OTTAWA
-# CANADA EASTERN 4 H BEHIND UTC APR 3 - OCT 29
-# CANADA CENTRAL 6 H BEHIND UTC REGINA, WINNIPEG
-# CANADA CENTRAL 5 H BEHIND UTC APR 3 - OCT 29
-# CANADA MOUNTAIN 7 H BEHIND UTC CALGARY, EDMONTON
-# CANADA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 29
-# CANADA PACIFIC 8 H BEHIND UTC VANCOUVER
-# CANADA PACIFIC 7 H BEHIND UTC APR 3 - OCT 29
-# CANADA YUKON SAME AS PACIFIC DAWSON
-
-# From Arthur David Olson (January 21, 1989):
-# April 3 fell on a Sunday in 1988; October 29 fell on a Sunday in 1989. Ahem.
-# Note claim that there's double DST in Newfoundland and that Yukon should
-# be same as Pacific.
-
-# From W. Jones (jones@skdad.usask.ca) (November 6, 1992):
-# 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.
-#
-# Here's how I would summarize things. Establish a "Saskatchewan" CST
-# time zone, and note that it officially exists as of 15 April 1966. Any
-# current exceptions can put themselves in the "Mountain" zone, since
-# those are the rules they follow. Any past exceptions can be forgotten,
-# since that's what those who live here have done.
-
-# From Arthur David Olson (November 21, 1992):
-# East-Saskatchewan kept to avoid problems for folks using that zone by name;
-# plain Saskatchewan added.
-
-# 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.
-
-
-
-# From Shanks (1991):
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule StJohns 1884 only - Jan 1 0:00 0 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 D
-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:31 StJohns N%sT 1935 Mar 30
- -3:30 StJohns N%sT
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Halifax 1902 only - Jun 15 0:00 0 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
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Mont 1884 only - Jan 1 0:00 0 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
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Winn 1887 only - Jul 16 0:00 0 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 23 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 1958 - Sep lastSun 2:00 0 S
-Rule Winn 1948 only - May 1 2:00 1:00 D
-Rule Winn 1948 1960 - Apr lastSun 2:00 1:00 D
-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 lastSun 2:00 0 S
-Rule Winn 1966 1986 - Apr lastSun 2:00 1:00 D
-Rule Winn 1966 max - Sep 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
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Regina 1905 only - Sep 1 0:00 0 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 14 2:00 1:00 D
-Rule Regina 1946 only - Oct 13 2:00 0 S
-Rule Regina 1947 1960 - Apr lastSun 2:00 1:00 D
-Rule Regina 1947 1959 - 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 1966 Apr 15
- -6:00 - CST
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Edm 1906 only - Sep 1 0:00 0 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
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Vanc 1884 only - Jan 1 0:00 0 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
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Yukon 1900 only - Jan 1 0:00 0 S
-Rule Yukon 1918 only - Apr 14 2:00 1:00 D
-Rule Yukon 1918 only - Oct 27 2:00 0 S
-Rule Yukon 1919 only - May 25 2:00 1:00 D
-Rule Yukon 1919 only - Nov 1 0:00 0 S
-Rule Yukon 1942 only - Feb 9 2:00 1:00 D
-Rule Yukon 1965 only - Apr 25 0:00 1:00 D
-Rule Yukon 1965 only - Oct 31 2:00 0 S
-Rule Yukon 1980 1986 - Apr lastSun 2:00 1:00 D
-Rule Yukon 1980 max - Oct lastSun 2:00 0 S
-Rule Yukon 1987 max - Apr Sun>=1 2:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Whitehorse -9:00:12 - LMT 1900 Aug 20
- -9:00 Yukon Y%sT 1966 Jul
- -8:00 Yukon P%sT
-# Parts of Yukon (e.g. Dawson) didn't switch to -8:00 until 1973 Oct 28.
-
-###############################################################################
-
-# 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; Mexico/BajaSur is for "Baja California Sur and N. Pacific
-# Coast (States of Sinaloa and Sonora)."
-
-# From Bob Devine (January 28, 1988):
-# 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 (February 13, 1988)
-# Since the 1981 starting date is only "probable," we'll keep the 1987
-# starting date below.
-
-# From U. S. Naval Observatory (January 19, 1989):
-# 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 PARALLAL APR 3
-# MEXICO BAJA CAL N - OCT 29
-# MEXICO BAJA CAL N 7 H BEHIND UTC ABOVE 28TH PARALLAL 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 (January 21, 1989):
-# 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> (November 18, 1993):
-# 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 Shanks (1991):
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Mexico 1922 only - Jan 1 0:00 0 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 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 - MST
-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
-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
-#
-# 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 1912 only - Mar 2 0:00 0 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 1932 only - Jan 1 0:00 0 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 1912 only - Apr 1 0:00 0 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
-# no information
-
-# 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 1921 only - Jan 15 0:00 0 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 only - Jan 19 0:00 1:00 D
-Rule CR 1991 only - Jul 1 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 (January 28, 1988):
-# . . .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 (January 19, 1989):
-# 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 1925 only - Jul 19 12:00 0 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 max - Oct Sun>=8 0:00 0 S
-Rule Cuba 1986 1989 - Mar Sun>=14 0:00 1:00 D
-Rule Cuba 1990 only - Apr 1 0:00 1:00 D
-Rule Cuba 1991 max - Mar Sun>=14 0:00 1:00 D
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Havana -5:29:28 - LMT 1890
- -5:30 - HMT 1925 Jul 19 12:00 # Havana MT
- -5: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 1933 only - Apr 1 12:00 0 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 1921 only - Jan 1 0:00 0 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
- -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 1918 only - Oct 5 0:00 0 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
-# 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 1917 only - Jan 24 12:00 0 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
-Rule Haiti 1988 max - Apr Sun>=1 2:00 1:00 D
-Rule Haiti 1988 max - Oct lastSun 2:00 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 (January 28, 1988):
-# Follows US rules.
-
-# From U. S. Naval Observatory (January 19, 1989):
-# 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
-
-# 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 1975 only - Feb 16 0:00 0 S
-Rule Nic 1979 1980 - Mar Sun>=16 0:00 1:00 D
-Rule Nic 1979 1980 - Jun Mon>=23 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
-
-# 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:28 - LMT 1899 Mar 28 12:00 # San Juan
- -4:00 - AST 1942 May 3
- -4:00 1:00 ADT 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 SP%sT
-
-# 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
-# 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 - EST 1979 Apr 29 2:00
- -5:00 US E%sT
-
-# Virgin Is (British and US)
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Virgin -4:19:44 - LMT 1911 Jul # Charlotte Amalie
- -4:00 - AST
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)optind.c 7.3";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-int opterr = 1, /* if error message should be printed */
- optind = 1; /* index into parent argv vector */
-char *optarg; /* argument associated with option */
-int optopt;
+++ /dev/null
-# @(#)pacificnew 7.6
-
-# From Arthur David Olson (April 5, 1989):
-# On April 5, 1989, 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 US/Pacific-PET -8:00 US P%sT XXXX
-## -8:00 Twilite P%sT
-
-# For now...
-Link America/Los_Angeles US/Pacific-New ##
+++ /dev/null
-#ifndef PRIVATE_H
-
-#define PRIVATE_H
-
-/*
-** 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
-*/
-
-#ifndef lint
-#ifndef NOID
-static char privatehid[] = "@(#)private.h 7.10";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** const
-*/
-
-#ifndef const
-#ifndef __STDC__
-#define const
-#endif /* !defined __STDC__ */
-#endif /* !defined const */
-
-/*
-** void
-*/
-
-#ifndef void
-#ifndef __STDC__
-#ifndef vax
-#ifndef sun
-#define void char
-#endif /* !defined sun */
-#endif /* !defined vax */
-#endif /* !defined __STDC__ */
-#endif /* !defined void */
-
-/*
-** INITIALIZE
-*/
-
-#ifndef GNUC_or_lint
-#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#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 */
-
-/*
-** P((args))
-*/
-
-#ifndef P
-#ifdef __STDC__
-#define P(x) x
-#endif /* defined __STDC__ */
-#ifndef __STDC__
-#define P(x) ()
-#endif /* !defined __STDC__ */
-#endif /* !defined P */
-
-/*
-** genericptr_T
-*/
-
-#ifdef __STDC__
-typedef void * genericptr_T;
-#endif /* defined __STDC__ */
-#ifndef __STDC__
-typedef char * genericptr_T;
-#endif /* !defined __STDC__ */
-
-#include "sys/types.h" /* for time_t */
-#include "stdio.h"
-#include "ctype.h"
-#include "errno.h"
-#include "string.h"
-#include "limits.h" /* for CHAR_BIT */
-#ifndef _TIME_
-#include "time.h"
-#endif /* !defined _TIME_ */
-
-#ifndef remove
-extern int unlink P((const char * filename));
-#define remove unlink
-#endif /* !defined remove */
-
-#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 */
-
-#ifndef EXIT_SUCCESS
-#define EXIT_SUCCESS 0
-#endif /* !defined EXIT_SUCCESS */
-
-#ifndef EXIT_FAILURE
-#define EXIT_FAILURE 1
-#endif /* !defined EXIT_FAILURE */
-
-#ifdef __STDC__
-
-#define alloc_size_T size_t
-#define qsort_size_T size_t
-#define fwrite_size_T size_t
-
-#endif /* defined __STDC__ */
-#ifndef __STDC__
-
-#ifndef alloc_size_T
-#define alloc_size_T unsigned
-#endif /* !defined alloc_size_T */
-
-#ifndef qsort_size_T
-#ifdef USG
-#define qsort_size_T unsigned
-#endif /* defined USG */
-#ifndef USG
-#define qsort_size_T int
-#endif /* !defined USG */
-#endif /* !defined qsort_size_T */
-
-#ifndef fwrite_size_T
-#define fwrite_size_T int
-#endif /* !defined fwrite_size_T */
-
-#ifndef USG
-extern char * sprintf P((char * buf, const char * format, ...));
-#endif /* !defined USG */
-
-#endif /* !defined __STDC__ */
-
-/*
-** Ensure that these are declared--redundantly declaring them shouldn't hurt.
-*/
-
-extern char * getenv P((const char * name));
-extern genericptr_T malloc P((alloc_size_T size));
-extern genericptr_T calloc P((alloc_size_T nelem, alloc_size_T elsize));
-extern genericptr_T realloc P((genericptr_T oldptr, alloc_size_T newsize));
-
-#ifdef USG
-extern void exit P((int s));
-extern void qsort P((genericptr_T base, qsort_size_T nelem,
- qsort_size_T elsize, int (*comp)()));
-extern void perror P((const char * string));
-extern void free P((char * buf));
-#endif /* defined USG */
-
-#ifndef TRUE
-#define TRUE 1
-#endif /* !defined TRUE */
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* !defined FALSE */
-
-#ifndef INT_STRLEN_MAXIMUM
-/*
-** 302 / 1000 is log10(2.0) rounded up.
-** Subtract one for the sign bit;
-** add one for integer division truncation;
-** add one more for a minus sign.
-*/
-#define INT_STRLEN_MAXIMUM(type) \
- ((sizeof(type) * CHAR_BIT - 1) * 302 / 1000 + 2)
-#endif /* !defined INT_STRLEN_MAXIMUM */
-
-#ifndef LOCALE_HOME
-#define LOCALE_HOME "/usr/lib/locale"
-#endif /* !defined LOCALE_HOME */
-
-/*
-** UNIX was a registered trademark of UNIX System Laboratories in 1993.
-** VAX is a trademark of Digital Equipment Corporation.
-*/
-
-#endif /* !defined PRIVATE_H */
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)scheck.c 8.12";
-#endif /* !defined lint */
-#endif /* !defined NOID */
-
-/*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 (isascii(*fp) && isdigit(*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
-# @(#)solar87 7.2
-
-# 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 Mideast/Riyadh87 3:07:04 - ?? 1987
- 3:07:04 sol87 ?? 1988
- 3:07:04 - ??
+++ /dev/null
-# @(#)solar88 7.2
-
-# 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 Mideast/Riyadh88 3:07:04 - ?? 1988
- 3:07:04 sol88 ?? 1989
- 3:07:04 - ??
+++ /dev/null
-# @(#)solar89 7.2
-
-# 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 Mideast/Riyadh89 3:07:04 - ?? 1989
- 3:07:04 sol89 ?? 1990
- 3:07:04 - ??
+++ /dev/null
-# @(#)southamerica 7.6
-
-# 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> (November 18, 1993):
-# 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.
-#
-# I invented the abbreviations marked `*' in the following table;
-# the rest are from earlier versions of this file, or from other sources.
-# Some of these are just plausible excuses for common English abbreviations.
-# Corrections are welcome!
-# std dst
-# LMT Local Mean Time
-# -2:00 FST FDT Fernando de Noronha
-# -3:00 EST EDT Eastern South America (conflicts with -5:00)
-# -4:00 AST ADT Andes*, Antilles*, Asuncion*, Atlantic
-# -4:00 CST CDT Chile (conflicts with -6:00)
-# -4:00 WST WDT Western Brazil
-# -5:00 AST ADT Acre (conflicts with -4:00)
-# -5:00 EST EDT Eastern, Ecuador*
-# -6:00 CST CDT Archipelago of Columbus*, Central
-# -7:00 MST MDT Mataveri*, Mountain
-#
-# See the `africa' file for Zone naming conventions.
-
-# 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 (January 28, 1988):
-# 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 (January 19, 19889):
-# ARGENTINA 3 H BEHIND UTC
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Arg 1930 only - Dec 1 0:00 1:00 D
-Rule Arg 1931 only - Apr 1 0:00 0 S
-Rule Arg 1931 only - Oct 15 0:00 1:00 D
-Rule Arg 1932 1940 - Mar 1 0:00 0 S
-Rule Arg 1932 1939 - Nov 1 0:00 1:00 D
-Rule Arg 1940 only - Jul 1 0:00 1:00 D
-Rule Arg 1941 only - Jun 15 0:00 0 S
-Rule Arg 1941 only - Oct 15 0:00 1:00 D
-Rule Arg 1943 only - Aug 1 0:00 0 S
-Rule Arg 1943 only - Oct 15 0:00 1:00 D
-Rule Arg 1946 only - Mar 1 0:00 0 S
-Rule Arg 1946 only - Oct 1 0:00 1:00 D
-Rule Arg 1963 only - Oct 1 0:00 0 S
-Rule Arg 1963 only - Dec 15 0:00 1:00 D
-Rule Arg 1964 1966 - Mar 1 0:00 0 S
-Rule Arg 1964 1966 - Oct 15 0:00 1:00 D
-Rule Arg 1967 only - Apr 1 0:00 0 S
-Rule Arg 1967 1968 - Oct Sun<=7 0:00 1:00 D
-Rule Arg 1968 1969 - Apr Sun<=7 0:00 0 S
-Rule Arg 1974 only - Jan 23 0:00 1:00 D
-Rule Arg 1974 only - May 1 0:00 0 S
-Rule Arg 1974 1976 - Oct Sun<=7 0:00 1:00 D
-Rule Arg 1975 1977 - Apr Sun<=7 0:00 0 S
-Rule Arg 1985 only - Nov 2 0:00 1:00 D
-Rule Arg 1986 only - Mar 14 0:00 0 S
-Rule Arg 1986 1987 - Oct 25 0:00 1:00 D
-Rule Arg 1987 only - Feb 13 0:00 0 S
-Rule Arg 1988 only - Feb 7 0:00 0 S
-Rule Arg 1988 only - Dec 1 0:00 1:00 D
-Rule Arg 1989 only - Mar 16 0:00 0 S
-Rule Arg 1989 only - Oct 15 0:00 1:00 D
-Rule Arg 1990 only - Mar 4 0:00 0 S
-# _The Economist_ (8 Jan 1994, p 42) reports that Argentina
-# had DST in 1991-2 and 1992-3, but not in 1990-1 or in 1993-4.
-# It has something to do with electricity companies meeting demand in summer.
-# We don't know the 1991-3 transition times, unfortunately.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Buenos_Aires -3:53:48 - LMT 1894 Nov
- -4:17 - CMT 1920 May # Cordoba Mean Time
- -4:00 - AST 1930 Dec
- -4:00 Arg A%sT 1969 Oct 5
- -3:00 Arg E%sT
-
-# Bolivia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/La_Paz -4:32:36 - LMT 1890
- -4:33 - LPMT 1931 Oct 15 # La Paz Mean Time
- -4:33 1:00 LPDT 1932 Mar 21
- -4:00 - AST
-
-# Brazil
-
-# From Guy Harris:
-# The OAG lists October 25, 1987 and February 12, 1988 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.
-# "Brazil/Acre" is for the Territory of Acre; "Brazil/DeNoronha" is for
-# Fernando De Noronha.
-
-# From Bob Devine (January 28, 1988):
-# The only information I found is that there was no DST up to 1985.
-# But there was some before 1952!
-
-# From U. S. Naval Observatory (January 16, 1989):
-# BRAZIL WEST 5 H BEHIND UTC TERRITORY OF ACRE
-# BRAZIL WEST 4 H BEHIND UTC ACRE OCT 23, '88-FEB 11,
-# BRAZIL '89 (ESTIMATED)
-# BRAZIL CENTRAL 4 H BEHIND UTC MANAUS
-# BRAZIL CENTRAL 3 H BEHIND UTC MANAUS OCT 23, '88-FEB 11,
-# BRAZIL CENTRAL '89 (ESTIMATED)
-# BRAZIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SAO
-# BRAZIL EAST PAULO, BRASILIA
-# BRAZIL EAST 2 H BEHIND UTC COASTAL STATES, RIO, SAO
-# BRAZIL PAULO, BRASILIA OCT 23,
-# BRAZIL '88-FEB 11, '89
-# BRAZIL (ESTIMATED)
-# BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS, FERNANDO
-# BRAZIL DE NORONHA
-# BRAZIL 1 H BEHIND UTC OCT 23, '88-FEB 11, '89
-# BRAZIL (ESTIMATED)
-# BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS.
-
-# From Paul Eggert <eggert@twinsun.com> (November 18, 1993):
-# 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.
-# Shanks claims Acre stopped observing DST after 1988 Feb 7, but it
-# could just be that his table ran out of room. We're extrapolating
-# about time zone changes after 1990 Feb 11.
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Brazil 1914 only - Jan 1 0:00 0 S
-Rule Brazil 1931 only - Oct 3 11:00 1 D
-Rule Brazil 1932 1933 - Apr 1 0:00 0 S
-Rule Brazil 1932 only - Oct 3 0:00 1 D
-Rule Brazil 1949 1952 - Dec 1 0:00 1 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 D
-Rule Brazil 1964 only - Mar 1 0:00 0 S
-Rule Brazil 1965 only - Jan 31 0:00 1 D
-Rule Brazil 1965 only - Apr 1 0:00 0 S
-Rule Brazil 1965 only - Dec 1 0:00 1 D
-Rule Brazil 1966 1968 - Mar 1 0:00 0 S
-Rule Brazil 1966 1967 - Nov 1 0:00 1 D
-Rule Brazil 1985 only - Nov 2 0:00 1 D
-Rule Brazil 1986 only - Mar 15 0:00 0 S
-Rule Brazil 1986 1987 - Oct Sat<=28 0:00 1 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 max - Oct Sun>=15 0:00 1 D
-Rule Brazil 1990 max - Feb Sun>=8 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Noronha -2:09:40 - LMT 1914
- -2:00 - FST 1963 Dec 9
- -2:00 Brazil F%sT
-Zone America/Sao_Paulo -3:06:28 - LMT 1914
- -3:00 Brazil E%sT
-Zone America/Manaus -4:00:04 - LMT 1914
- -4:00 - WST 1963 Dec 9
- -4:00 Brazil W%sT
-# 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
-#
-# Martin Vaz and Trinidade are like America/Noronha.
-
-
-# Chile
-
-# From Guy Harris:
-# The OAG lists October 11, 1987 and March 12, 1988 as the starting and
-# ending dates, giving them as "estimated date(s) based on previous year."
-
-# From Bob Devine (January 28, 1988):
-# Chile has had 2nd Sunday in October to 2nd Sunday in March DST since 1977.
-# Switch is at midnight. OAG is right.
-
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Chile 1918 only - Sep 1 0:00 1:00 D
-Rule Chile 1919 only - Jul 2 0:00 0 S
-Rule Chile 1927 1931 - Sep 1 0:00 1:00 D
-Rule Chile 1928 1932 - Apr 1 0:00 0 S
-Rule Chile 1969 max - Oct Sun>=8 0:00 1:00 D
-Rule Chile 1970 max - Mar Sun>=8 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Santiago -4:42:40 - LMT 1890
- -4:43 - SMT 1910 # Santiago Mean Time
- -5:00 Chile C%sT 1932 Sep
- -4:00 Chile C%sT
-Zone Pacific/Easter -7:17:28 - LMT 1890 # Mataveri
- -7:17 - MMT 1932 Sep # Mataveri Mean Time
- -7:00 Chile M%sT 1982 Mar 14
- -6:00 Chile C%sT
-#
-# Whitman says Juan Fernandez Is are like America/Santiago.
-# San Ambrosio, San Felix
-# no information; probably like America/Santiago
-
-
-# Colombia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Bogota -4:56:20 - LMT 1884 Mar 13
- -4:56 - BMT 1914 Nov 23 # Bogota Mean Time
- -5:00 - EST
-# 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 - NAST 1965 # Netherlands Antilles
- -4:00 - AST
-
-# Ecuador
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Guayaquil -5:19:20 - LMT 1890
- -5:14 - QMT 1931 # Quito Mean Time
- -5:00 - EST
-Zone Pacific/Galapagos -5:58:24 - LMT 1931 # Puerto Baquerizo Moreno
- -5:00 - EST 1986
- -6:00 - CST
-
-# Falklands
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Falk 1912 only - Mar 12 0:00 0 S
-Rule Falk 1937 1938 - Sep lastSun 0:00 1:00 D
-Rule Falk 1938 1942 - Mar Sun>=19 0:00 0 S
-Rule Falk 1939 only - Oct 1 0:00 1:00 D
-Rule Falk 1940 1942 - Sep lastSun 0:00 1:00 D
-Rule Falk 1943 only - Jan 1 0:00 0 S
-Rule Falk 1983 only - Sep lastSun 0:00 1:00 D
-Rule Falk 1984 1985 - Apr lastSun 0:00 0 S
-Rule Falk 1984 only - Sep 16 0:00 1:00 D
-Rule Falk 1985 max - Sep Sun>=9 0:00 1:00 D
-Rule Falk 1986 max - Apr Sun>=16 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/Stanley -3:51:24 - LMT 1890
- -3:51 - SMT 1912 Mar 12 # Stanley Mean Time
- -4:00 Falk A%sT 1983 May
- -3:00 Falk E%sT 1985 Sep 15
- -4:00 Falk A%sT
-
-# French Guiana
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Cayenne -3:29:20 - LMT 1911 Jul
- -4:00 - AST 1967 Oct
- -3:00 - EST
-
-# Guyana
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Guyana -3:52:40 - LMT 1915 Mar # Georgetown
- -3:45 - BGST 1975 Jul 31 # British Guiana ST
- -3:00 - EST
-
-
-# Paraguay
-
-# From Bob Devine (January 28, 1988):
-# Paraguay: First day in October to last in March. Midnight switch??
-# Since 1980.
-
-# From U. S. Naval Observatory (January 19, 1989):
-# 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 1974 only - Apr 1 0:00 0 S
-Rule Para 1975 1978 - Oct 1 0:00 1:00 D
-Rule Para 1975 1978 - Mar 1 0:00 0 S
-# Shanks says 1979 was all DST.
-Rule Para 1980 max - Apr 1 0:00 0 S
-Rule Para 1980 1988 - Oct 1 0:00 1:00 D
-Rule Para 1989 only - Oct 22 0:00 1:00 D
-Rule Para 1990 max - Oct 1 0:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Asuncion -3:50:40 - LMT 1890
- -3:51 - AMT 1931 Oct 10 # Asuncion Mean Time
- -4:00 - AST 1972 Oct
- -3:00 - EST 1974 Apr
- -4:00 Para A%sT
-
-# Peru
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Peru 1908 only - Jul 28 0:00 0 S
-Rule Peru 1938 only - Jan 1 0:00 1:00 D
-Rule Peru 1938 only - Apr 1 0:00 0 S
-Rule Peru 1938 1939 - Sep lastSun 0:00 1:00 D
-Rule Peru 1939 1940 - Mar Sun>=24 0:00 0 S
-Rule Peru 1987 only - Jan 1 0:00 1:00 D
-Rule Peru 1987 only - Apr 1 0:00 0 S
-Rule Peru 1990 only - Jan 1 0:00 1:00 D
-Rule Peru 1990 only - Apr 1 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Lima -5:08:12 - LMT 1890
- -5:09 - LMT 1908 Jul 28
- -5:00 Peru E%sT
-
-# South Georgia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/South_Georgia -2:26:08 - LMT 1890 # Grytviken
- -2:00 - FST
-
-# South Sandwich Is
-# no information
-
-# 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 - DGST 1984 Oct # Dutch Guiana Std Time
- -3:00 - EST
-
-# 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> (November 18, 1993):
-# Uruguay wins the prize for the strangest peacetime manipulation of the rules.
-# Your guess is as good as mine for what happened after 1989.
-# From Shanks (1991):
-# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Uruguay 1920 only - May 1 0:00 0 S
-# Whitman gives 1923 Oct 1; go with Shanks.
-Rule Uruguay 1923 only - Oct 2 0:00 0:30 HD
-Rule Uruguay 1924 1926 - Apr 1 0:00 0 S
-Rule Uruguay 1924 1925 - Oct 1 0:00 0:30 HD
-Rule Uruguay 1933 1935 - Oct lastSun 0:00 0:30 HD
-# 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 S
-Rule Uruguay 1936 only - Nov 1 0:00 0:30 HD
-Rule Uruguay 1937 1941 - Mar lastSun 0:00 0 S
-# Whitman gives 1937 Oct 3; go with Shanks.
-Rule Uruguay 1937 1940 - Oct lastSun 0:00 0:30 HD
-# 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 S
-Rule Uruguay 1942 only - Jan 1 0:00 0:30 HD
-Rule Uruguay 1942 only - Dec 14 0:00 1:00 D
-Rule Uruguay 1943 only - Mar 14 0:00 0 S
-Rule Uruguay 1959 only - May 24 0:00 1:00 D
-Rule Uruguay 1959 only - Nov 15 0:00 0 S
-Rule Uruguay 1960 only - Jan 17 0:00 1:00 D
-Rule Uruguay 1960 only - Mar 6 0:00 0 S
-Rule Uruguay 1965 1967 - Apr Sun>=1 0:00 1:00 D
-Rule Uruguay 1965 only - Sep 26 0:00 0 S
-Rule Uruguay 1966 1967 - Oct 31 0:00 0 S
-Rule Uruguay 1968 1970 - May 27 0:00 0:30 HD
-Rule Uruguay 1968 1970 - Dec 2 0:00 0 S
-Rule Uruguay 1972 only - Apr 24 0:00 1:00 D
-Rule Uruguay 1972 only - Aug 15 0:00 0 S
-Rule Uruguay 1974 only - Mar 10 0:00 0:30 HD
-Rule Uruguay 1974 only - Dec 22 0:00 1:00 D
-Rule Uruguay 1976 only - Oct 1 0:00 0 S
-Rule Uruguay 1977 only - Dec 4 0:00 1:00 D
-Rule Uruguay 1978 only - Apr 1 0:00 0 S
-Rule Uruguay 1979 only - Oct 1 0:00 1:00 D
-Rule Uruguay 1980 only - May 1 0:00 0 S
-Rule Uruguay 1987 only - Dec 14 0:00 1:00 D
-Rule Uruguay 1988 only - Mar 14 0:00 0 S
-Rule Uruguay 1988 only - Dec 11 0:00 1:00 D
-Rule Uruguay 1989 only - Mar 12 0:00 0 S
-Rule Uruguay 1989 only - Oct 29 0:00 1:00 D
-Rule Uruguay 1990 only - Mar 4 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Montevideo -3:44:44 - LMT 1898 Jun 28
- -3:45 - MMT 1920 May 1 # Montevideo MT
- -3:30 Uruguay U%sT 1942 Dec 14 # Uruguay ST
- -3:00 Uruguay E%sT
-
-# Venezuela
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone America/Caracas -4:27:44 - LMT 1890
- -4:28 - CMT 1912 Feb 12 # Caracas Mean Time
- -4:30 - VZT 1965 # Venezuela Time
- -4:00 - AST
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)strftime.c 7.33";
-/*
-** Based on the UCB version with the ID appearing below.
-** This is ANSIish only when "multibyte character == plain character".
-*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#include "private.h"
-
-/*
-** Copyright (c) 1989 The Regents of the University of California.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms are permitted
-** provided that the above copyright notice and this paragraph are
-** duplicated in all such forms and that any documentation,
-** advertising materials, and other materials related to such
-** distribution and use acknowledge that the software was developed
-** by the University of California, Berkeley. The name of the
-** University may not be used to endorse or promote products derived
-** from this software without specific prior written permission.
-** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-#ifndef LIBC_SCCS
-#ifndef lint
-static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
-#endif /* !defined lint */
-#endif /* !defined LIBC_SCCS */
-
-#include "tzfile.h"
-#include "fcntl.h"
-#if HAVE_SETLOCALE - 0
-#include "locale.h"
-#endif /* HAVE_SETLOCALE - 0 */
-
-struct lc_time_T {
- const char * mon[12];
- const char * month[12];
- const char * wday[7];
- const char * weekday[7];
- const char * X_fmt;
- const char * x_fmt;
- const char * c_fmt;
- const char * am;
- const char * pm;
- const char * date_fmt;
-};
-
-#ifdef LOCALE_HOME
-static struct lc_time_T localebuf;
-static struct lc_time_T * _loc P((void));
-#define Locale _loc()
-#endif /* defined LOCALE_HOME */
-#ifndef LOCALE_HOME
-#define Locale (&C_time_locale)
-#endif /* !defined LOCALE_HOME */
-
-static const struct lc_time_T C_time_locale = {
- {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- }, {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December"
- }, {
- "Sun", "Mon", "Tue", "Wed",
- "Thu", "Fri", "Sat"
- }, {
- "Sunday", "Monday", "Tuesday", "Wednesday",
- "Thursday", "Friday", "Saturday"
- },
-
- /* X_fmt */
- "%H:%M:%S",
-
- /*
- ** x_fmt
- ** Since the C language standard calls for
- ** "date, using locale's date format," anything goes.
- ** Using just numbers (as here) makes Quakers happier;
- ** it's also compatible with SVR4.
- */
- "%m/%d/%y",
-
- /*
- ** c_fmt
- ** Note that
- ** "%a %b %d %H:%M:%S %Y"
- ** is used by Solaris 2.3.
- */
- "%D %X", /* %m/%d/%y %H:%M:%S */
-
- /* am */
- "AM",
-
- /* pm */
- "PM",
-
- /* date_fmt */
- "%a %b %e %H:%M:%S %Z %Y"
-};
-
-static char * _add P((const char *, char *, const char *));
-static char * _conv P((int, const char *, char *, const char *));
-static char *_fmt P((const char *, const struct tm *, char *, const char *));
-
-size_t strftime P((char *, size_t, const char *, const struct tm *));
-
-extern char * tzname[];
-
-size_t
-strftime(s, maxsize, format, t)
-char * const s;
-const size_t maxsize;
-const char * const format;
-const struct tm * const t;
-{
- char * p;
-
- tzset();
-#ifdef LOCALE_HOME
- localebuf.mon[0] = 0;
-#endif /* defined LOCALE_HOME */
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize);
- if (p == s + maxsize)
- return 0;
- *p = '\0';
- return p - s;
-}
-
-static char *
-_fmt(format, t, pt, ptlim)
-const char * format;
-const struct tm * const t;
-char * pt;
-const char * const ptlim;
-{
- for ( ; *format; ++format) {
- if (*format == '%') {
-label:
- switch (*++format) {
- case '\0':
- --format;
- break;
- case 'A':
- pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
- "?" : Locale->weekday[t->tm_wday],
- pt, ptlim);
- continue;
- case 'a':
- pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
- "?" : Locale->wday[t->tm_wday],
- pt, ptlim);
- continue;
- case 'B':
- pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
- "?" : Locale->month[t->tm_mon],
- pt, ptlim);
- continue;
- case 'b':
- case 'h':
- pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
- "?" : Locale->mon[t->tm_mon],
- pt, ptlim);
- continue;
- case 'C':
- /*
- ** %C used to do a...
- ** _fmt("%a %b %e %X %Y", t);
- ** ...whereas now POSIX 1003.2 calls for
- ** something completely different.
- ** (ado, 5/24/93)
- */
- pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
- "%02d", pt, ptlim);
- continue;
- case 'c':
- pt = _fmt(Locale->c_fmt, t, pt, ptlim);
- continue;
- case 'D':
- pt = _fmt("%m/%d/%y", t, pt, ptlim);
- continue;
- case 'd':
- pt = _conv(t->tm_mday, "%02d", pt, ptlim);
- continue;
- case 'E':
- case 'O':
- /*
- ** POSIX locale extensions, a la
- ** Arnold Robbins' strftime version 3.0.
- ** The sequences
- ** %Ec %EC %Ex %Ey %EY
- ** %Od %oe %OH %OI %Om %OM
- ** %OS %Ou %OU %OV %Ow %OW %Oy
- ** are supposed to provide alternate
- ** representations.
- ** (ado, 5/24/93)
- */
- goto label;
- case 'e':
- pt = _conv(t->tm_mday, "%2d", pt, ptlim);
- continue;
- case 'H':
- pt = _conv(t->tm_hour, "%02d", pt, ptlim);
- continue;
- case 'I':
- pt = _conv((t->tm_hour % 12) ?
- (t->tm_hour % 12) : 12,
- "%02d", pt, ptlim);
- continue;
- case 'j':
- pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
- continue;
- case 'k':
- /*
- ** This used to be...
- ** _conv(t->tm_hour % 12 ?
- ** t->tm_hour % 12 : 12, 2, ' ');
- ** ...and has been changed to the below to
- ** match SunOS 4.1.1 and Arnold Robbins'
- ** strftime version 3.0. That is, "%k" and
- ** "%l" have been swapped.
- ** (ado, 5/24/93)
- */
- pt = _conv(t->tm_hour, "%2d", pt, ptlim);
- continue;
-#ifdef KITCHEN_SINK
- case 'K':
- /*
- ** After all this time, still unclaimed!
- */
- pt = _add("kitchen sink", pt, ptlim);
- continue;
-#endif /* defined KITCHEN_SINK */
- case 'l':
- /*
- ** This used to be...
- ** _conv(t->tm_hour, 2, ' ');
- ** ...and has been changed to the below to
- ** match SunOS 4.1.1 and Arnold Robbin's
- ** strftime version 3.0. That is, "%k" and
- ** "%l" have been swapped.
- ** (ado, 5/24/93)
- */
- pt = _conv((t->tm_hour % 12) ?
- (t->tm_hour % 12) : 12,
- "%2d", pt, ptlim);
- continue;
- case 'M':
- pt = _conv(t->tm_min, "%02d", pt, ptlim);
- continue;
- case 'm':
- pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
- continue;
- case 'n':
- pt = _add("\n", pt, ptlim);
- continue;
- case 'p':
- pt = _add((t->tm_hour >= 12) ?
- Locale->pm :
- Locale->am,
- pt, ptlim);
- continue;
- case 'R':
- pt = _fmt("%H:%M", t, pt, ptlim);
- continue;
- case 'r':
- pt = _fmt("%I:%M:%S %p", t, pt, ptlim);
- continue;
- case 'S':
- pt = _conv(t->tm_sec, "%02d", pt, ptlim);
- continue;
- case 'T':
- pt = _fmt("%H:%M:%S", t, pt, ptlim);
- continue;
- case 't':
- pt = _add("\t", pt, ptlim);
- continue;
- case 'U':
- pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7,
- "%02d", pt, ptlim);
- continue;
- case 'u':
- /*
- ** From Arnold Robbins' strftime version 3.0:
- ** "ISO 8601: Weekday as a decimal number
- ** [1 (Monday) - 7]"
- ** (ado, 5/24/93)
- */
- pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
- "%d", pt, ptlim);
- continue;
- case 'V':
- /*
- ** From Arnold Robbins' strftime version 3.0:
- ** "the week number of the year (the first
- ** Monday as the first day of week 1) as a
- ** decimal number (01-53). The method for
- ** determining the week number is as specified
- ** by ISO 8601 (to wit: if the week containing
- ** January 1 has four or more days in the new
- ** year, then it is week 1, otherwise it is
- ** week 53 of the previous year and the next
- ** week is week 1)."
- ** (ado, 5/24/93)
- */
- /*
- ** XXX--If January 1 falls on a Friday,
- ** January 1-3 are part of week 53 of the
- ** previous year. By analogy, if January
- ** 1 falls on a Thursday, are December 29-31
- ** of the PREVIOUS year part of week 1???
- ** (ado 5/24/93)
- */
- /*
- ** You are understood not to expect this.
- */
- {
- int i;
-
- i = (t->tm_yday + 10 - (t->tm_wday ?
- (t->tm_wday - 1) : 6)) / 7;
- if (i == 0) {
- /*
- ** What day of the week does
- ** January 1 fall on?
- */
- i = t->tm_wday -
- (t->tm_yday - 1);
- /*
- ** Fri Jan 1: 53
- ** Sun Jan 1: 52
- ** Sat Jan 1: 53 if previous
- ** year a leap
- ** year, else 52
- */
- if (i == TM_FRIDAY)
- i = 53;
- else if (i == TM_SUNDAY)
- i = 52;
- else i = isleap(t->tm_year +
- TM_YEAR_BASE) ?
- 53 : 52;
-#ifdef XPG4_1994_04_09
- /*
- ** As of 4/9/94, though,
- ** XPG4 calls for 53
- ** unconditionally.
- */
- i = 53;
-#endif /* defined XPG4_1994_04_09 */
- }
- pt = _conv(i, "%02d", pt, ptlim);
- }
- continue;
- case 'v':
- /*
- ** From Arnold Robbins' strftime version 3.0:
- ** "date as dd-bbb-YYYY"
- ** (ado, 5/24/93)
- */
- pt = _fmt("%e-%b-%Y", t, pt, ptlim);
- continue;
- case 'W':
- pt = _conv((t->tm_yday + 7 -
- (t->tm_wday ?
- (t->tm_wday - 1) : 6)) / 7,
- "%02d", pt, ptlim);
- continue;
- case 'w':
- pt = _conv(t->tm_wday, "%d", pt, ptlim);
- continue;
- case 'X':
- pt = _fmt(Locale->X_fmt, t, pt, ptlim);
- continue;
- case 'x':
- pt = _fmt(Locale->x_fmt, t, pt, ptlim);
- continue;
- case 'y':
- pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
- "%02d", pt, ptlim);
- continue;
- case 'Y':
- pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
- pt, ptlim);
- continue;
- case 'Z':
-#ifdef TM_ZONE
- if (t->TM_ZONE != NULL)
- pt = _add(t->TM_ZONE, pt, ptlim);
- else
-#endif /* defined TM_ZONE */
- if (t->tm_isdst == 0 || t->tm_isdst == 1) {
- pt = _add(tzname[t->tm_isdst],
- pt, ptlim);
- } else pt = _add("?", pt, ptlim);
- continue;
- case '+':
- pt = _fmt(Locale->date_fmt, t, pt, ptlim);
- continue;
- case '%':
- /*
- * X311J/88-090 (4.12.3.5): if conversion char is
- * undefined, behavior is undefined. Print out the
- * character itself as printf(3) also does.
- */
- default:
- break;
- }
- }
- if (pt == ptlim)
- break;
- *pt++ = *format;
- }
- return pt;
-}
-
-static char *
-_conv(n, format, pt, ptlim)
-const int n;
-const char * const format;
-char * const pt;
-const char * const ptlim;
-{
- char buf[INT_STRLEN_MAXIMUM(int) + 1];
-
- (void) sprintf(buf, format, n);
- return _add(buf, pt, ptlim);
-}
-
-static char *
-_add(str, pt, ptlim)
-const char * str;
-char * pt;
-const char * const ptlim;
-{
- while (pt < ptlim && (*pt = *str++) != '\0')
- ++pt;
- return pt;
-}
-
-#ifdef LOCALE_HOME
-static struct lc_time_T *
-_loc P((void))
-{
- static const char locale_home[] = LOCALE_HOME;
- static const char lc_time[] = "LC_TIME";
- static char * locale_buf;
- static char locale_buf_C[] = "C";
-
- int fd;
- int oldsun; /* "...ain't got nothin' to do..." */
- char * lbuf;
- char * name;
- char * p;
- const char ** ap;
- const char * plim;
- char filename[FILENAME_MAX];
- struct stat st;
- size_t namesize;
- size_t bufsize;
-
- /*
- ** Use localebuf.mon[0] to signal whether locale is already set up.
- */
- if (localebuf.mon[0])
- return &localebuf;
-#if HAVE_SETLOCALE - 0
- name = setlocale(LC_TIME, (char *) NULL);
-#endif /* HAVE_SETLOCALE - 0 */
-#if !(HAVE_SETLOCALE - 0)
- if ((name = getenv("LC_ALL")) == NULL || *name == '\0')
- if ((name = getenv(lc_time)) == NULL || *name == '\0')
- name = getenv("LANG");
-#endif /* !(HAVE_SETLOCALE - 0) */
- if (name == NULL || *name == '\0')
- goto no_locale;
- /*
- ** If the locale name is the same as our cache, use the cache.
- */
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- p = lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap)
- *ap = p += strlen(p) + 1;
- return &localebuf;
- }
- /*
- ** Slurp the locale file into the cache.
- */
- namesize = strlen(name) + 1;
- if (sizeof(filename) <
- sizeof(locale_home) + namesize + sizeof(lc_time))
- goto no_locale;
- oldsun = 0;
- (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- /*
- ** Old Sun systems have a different naming and data convention.
- */
- oldsun = 1;
- (void) sprintf(filename, "%s/%s/%s", locale_home,
- lc_time, name);
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- goto no_locale;
- }
- if (fstat(fd, &st) != 0)
- goto bad_locale;
- if (st.st_size <= 0)
- goto bad_locale;
- bufsize = namesize + st.st_size;
- locale_buf = NULL;
- lbuf = (lbuf == NULL || lbuf == locale_buf_C) ?
- malloc(bufsize) : realloc(lbuf, bufsize);
- if (lbuf == NULL)
- goto bad_locale;
- (void) strcpy(lbuf, name);
- p = lbuf + namesize;
- plim = p + st.st_size;
- if (read(fd, p, (size_t) st.st_size) != st.st_size)
- goto bad_lbuf;
- if (close(fd) != 0)
- goto bad_lbuf;
- /*
- ** Parse the locale file into localebuf.
- */
- if (plim[-1] != '\n')
- goto bad_lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap) {
- if (p == plim)
- goto bad_lbuf;
- *ap = p;
- while (*p != '\n')
- ++p;
- *p++ = '\0';
- }
- if (oldsun) {
- /*
- ** SunOS 4 used an obsolescent format; see localdtconv(3).
- ** c_fmt had the ``short format for dates and times together''
- ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
- ** date_fmt had the ``long format for dates''
- ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
- ** Discard the latter in favor of the former.
- */
- localebuf.date_fmt = localebuf.c_fmt;
- }
- /*
- ** Record the successful parse in the cache.
- */
- locale_buf = lbuf;
-
- return &localebuf;
-
-bad_lbuf:
- free(lbuf);
-bad_locale:
- (void) close(fd);
-no_locale:
- localebuf = C_time_locale;
- locale_buf = locale_buf_C;
- return &localebuf;
-}
-#endif /* defined LOCALE_HOME */
+++ /dev/null
-# @(#)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
-.TH TIME2POSIX 3
-.SH NAME
-time2posix, posix2time \- convert seconds since the Epoch
-.SH SYNOPSIS
-.nf
-.B #include <sys/types.h>
-.B #include <time.h>
-.PP
-.B time_t time2posix(t)
-.B time_t t
-.PP
-.B time_t posix2time(t)
-.B time_t t
-.PP
-.B cc ... -lz
-.fi
-.SH DESCRIPTION
-IEEE Standard 1003.1
-(POSIX)
-legislates that a time_t value of
-536457599 shall correspond to "Wed Dec 31 23:59:59 GMT 1986."
-This effectively implies that POSIX time_t's cannot include leap
-seconds and,
-therefore,
-that the system time must be adjusted as each leap occurs.
-.PP
-If the time package is configured with leap-second support
-enabled,
-however,
-no such adjustment is needed and
-time_t values continue to increase over leap events
-(as a true `seconds since...' value).
-This means that these values will differ from those required by POSIX
-by the net number of leap seconds inserted since the Epoch.
-.PP
-Typically this is not a problem as the type time_t is intended
-to be
-(mostly)
-opaque\(emtime_t values should only be obtained-from and
-passed-to functions such as
-.IR time(2) ,
-.IR localtime(3) ,
-.IR mktime(3) ,
-and
-.IR difftime(3) .
-However,
-POSIX gives an arithmetic
-expression for directly computing a time_t value from a given date/time,
-and the same relationship is assumed by some
-(usually older)
-applications.
-Any programs creating/dissecting time_t's
-using such a relationship will typically not handle intervals
-over leap seconds correctly.
-.PP
-The
-.I time2posix
-and
-.I posix2time
-functions are provided to address this time_t mismatch by converting
-between local time_t values and their POSIX equivalents.
-This is done by accounting for the number of time-base changes that
-would have taken place on a POSIX system as leap seconds were inserted
-or deleted.
-These converted values can then be used in lieu of correcting the older
-applications,
-or when communicating with POSIX-compliant systems.
-.PP
-.I Time2posix
-is single-valued.
-That is,
-every local time_t
-corresponds to a single POSIX time_t.
-.I Posix2time
-is less well-behaved:
-for a positive leap second hit the result is not unique,
-and for a negative leap second hit the corresponding
-POSIX time_t doesn't exist so an adjacent value is returned.
-Both of these are good indicators of the inferiority of the
-POSIX representation.
-.PP
-The following table summarizes the relationship between a time
-T and it's conversion to,
-and back from,
-the POSIX representation over the leap second inserted at the end of June,
-1993.
-.nf
-.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u
-DATE TIME T X=time2posix(T) posix2time(X)
-93/06/30 23:59:59 A+0 B+0 A+0
-93/06/30 23:59:60 A+1 B+1 A+1 or A+2
-93/07/01 00:00:00 A+2 B+1 A+1 or A+2
-93/07/01 00:00:01 A+3 B+2 A+3
-
-A leap second deletion would look like...
-
-DATE TIME T X=time2posix(T) posix2time(X)
-??/06/30 23:59:58 A+0 B+0 A+0
-??/07/01 00:00:00 A+1 B+2 A+1
-??/07/01 00:00:01 A+2 B+3 A+2
-.sp
-.ce
- [Note: posix2time(B+1) => A+0 or A+1]
-.fi
-.PP
-If leap-second support is not enabled,
-local time_t's and
-POSIX time_t's are equivalent,
-and both
-.I time2posix
-and
-.I posix2time
-degenerate to the identity function.
-.SH SEE ALSO
-difftime(3),
-localtime(3),
-mktime(3),
-time(2)
-.\" @(#)time2posix.3 7.3
+++ /dev/null
-.TH TZFILE 5
-.SH NAME
-tzfile \- time zone information
-.SH SYNOPSIS
-.B
-#include <tzfile.h>
-.SH DESCRIPTION
-The time zone information files used by
-.IR tzset (3)
-begin with bytes reserved for future use,
-followed by four four-byte values of type
-.BR long ,
-written in a ``standard'' byte order
-(the high-order byte of the value is written first).
-These values are,
-in order:
-.TP
-.I tzh_ttisstdcnt
-The number of standard/wall indicators stored in the file.
-.TP
-.I tzh_leapcnt
-The number of leap seconds for which data is stored in the file.
-.TP
-.I tzh_timecnt
-The number of "transition times" for which data is stored
-in the file.
-.TP
-.I tzh_typecnt
-The number of "local time types" for which data is stored
-in the file (must not be zero).
-.TP
-.I tzh_charcnt
-The number of characters of "time zone abbreviation strings"
-stored in the file.
-.PP
-The above header is followed by
-.I tzh_timecnt
-four-byte values of type
-.BR long ,
-sorted in ascending order.
-These values are written in ``standard'' byte order.
-Each is used as a transition time (as returned by
-.IR time (2))
-at which the rules for computing local time change.
-Next come
-.I tzh_timecnt
-one-byte values of type
-.BR "unsigned char" ;
-each one tells which of the different types of ``local time'' types
-described in the file is associated with the same-indexed transition time.
-These values serve as indices into an array of
-.I ttinfo
-structures that appears next in the file;
-these structures are defined as follows:
-.in +.5i
-.sp
-.nf
-.ta .5i +\w'unsigned int\0\0'u
-struct ttinfo {
- long tt_gmtoff;
- int tt_isdst;
- unsigned int tt_abbrind;
-};
-.in -.5i
-.fi
-.sp
-Each structure is written as a four-byte value for
-.I tt_gmtoff
-of type
-.BR long ,
-in a standard byte order, followed by a one-byte value for
-.I tt_isdst
-and a one-byte value for
-.IR tt_abbrind .
-In each structure,
-.I tt_gmtoff
-gives the number of seconds to be added to GMT,
-.I tt_isdst
-tells whether
-.I tm_isdst
-should be set by
-.I localtime (3)
-and
-.I tt_abbrind
-serves as an index into the array of time zone abbreviation characters
-that follow the
-.I ttinfo
-structure(s) in the file.
-.PP
-Then there are
-.I tzh_leapcnt
-pairs of four-byte values, written in standard byte order;
-the first value of each pair gives the time
-(as returned by
-.IR time(2))
-at which a leap second occurs;
-the second gives the
-.I total
-number of leap seconds to be applied after the given time.
-The pairs of values are sorted in ascending order by time.
-.PP
-Finally there are
-.I tzh_ttisstdcnt
-standard/wall indicators, each stored as a one-byte value;
-they tell whether the transition times associated with local time types
-were specified as standard time or wall clock time,
-and are used when a time zone file is used in handling POSIX-style
-time zone environment variables.
-.PP
-.I Localtime
-uses the first standard-time
-.I ttinfo
-structure in the file
-(or simply the first
-.I ttinfo
-structure in the absence of a standard-time structure)
-if either
-.I tzh_timecnt
-is zero or the time argument is less than the first transition time recorded
-in the file.
-.SH SEE ALSO
-newctime(3)
-.\" @(#)tzfile.5 7.2
+++ /dev/null
-#ifndef TZFILE_H
-
-#define TZFILE_H
-
-/*
-** 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
-*/
-
-#ifndef lint
-#ifndef NOID
-static char tzfilehid[] = "@(#)tzfile.h 7.4";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Information about time zone files.
-*/
-
-#ifndef TZDIR
-#define TZDIR "/usr/local/etc/zoneinfo" /* Time zone object file directory */
-#endif /* !defined TZDIR */
-
-#ifndef TZDEFAULT
-#define TZDEFAULT "localtime"
-#endif /* !defined TZDEFAULT */
-
-#ifndef TZDEFRULES
-#define TZDEFRULES "posixrules"
-#endif /* !defined TZDEFRULES */
-
-/*
-** Each file begins with. . .
-*/
-
-struct tzhead {
- char tzh_reserved[24]; /* reserved for future use */
- 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
-*/
-
-/*
-** 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
-#define TZ_MAX_TYPES 10 /* 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
-# @(#)usno1988 7.1
-#
-# From Arthur David Olson (January 19, 1989):
-#
-# Here's some United States Naval Observatory time zone data from
-# February 1988. It's here mostly to convince you that the USNO has indeed
-# been updating its files (see its 1989 data elsewhere).
-#
-ANDORRA 1 H AHEAD OF UTC
-ARGENTINA 3 H BEHIND UTC
-BRASIL WEST 5 H BEHIND UTC (CRUZEIRO DO SUL)
-BRASIL CENTRAL 4 H BEHIND UTC (MANAUS)
-BRASIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SP, BRASILIA
-BRASIL 2 H BEHIND UTC ATLANTIC ISLANDS
-BRAZIL 5 H BEHIND UTC WEST (CRUZEIRO DO SUL)
-BRAZIL 4 H BEHIND UTC CENTRAL (MANAUS)
-BRAZIL 3 H BEHIND UTC COASTAL STATES, RIO, SP, BRASILIA
-BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS.
-BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS
-BULGARIA 2 H AHEAD OF UTC WINTER
-BULGARIA 3 H AHEAD OF UTC SUMMER MAR31 - SEP 85, 0100 LOCAL
-CHINA 8 H AHEAD OF UTC; ALL OF CHINA, INCL TAIWAN
-CUBA 5 H BEHIND UTC IN WINTER
-CUBA 4 H BEHIND UTC MAY 8 - OCT 8
-CYPRUS 2 H AHEAD UTC IN WINTER
-CYPRUS 3 H AHEAD UTC MAR 25 - SEP 30
-DENMARK 1 H AHEAD UTC IN WINTER
-DENMARK 2 H AHEAD UTC MAR 31 - SEP 30 , 0200 LOCAL
-DENMK. FAEROE IS 1 H AHEAD UTC MAR 31 - SEP 30 , 0200 LOCAL
-EGYPT 2 H AHEAD UTC
-EGYPT 3 H AHEAD UTC SUMMER (AFTER RAMADAN)
-ENGLAND ON UTC IN WINTER; WALES, SCOTLAND, N.I., CH.IS.
-ENGLAND 1 H AHEAD OF UTC; SUMMER TIL 28 OCT 0200 LOCAL
-FINLAND 2 H AHEAD OF UTC IN WINTER
-FINLAND 3 H AHEAD OF UTC MAR 25 - SEP 30
-FRANCE 1 H AHEAD OF UTC IN WINTER
-FRANCE 2 H AHEAD OF UTC MAR 31 - SEP 30 , 0100 LOCAL
-GREECE 2 H AHEAD OF UTC IN WINTER
-GREECE 3 H AHEAD OF UTC IN SUMMER EFF. 31MAR85 02/03 LOCAL
-GREECE 3 H AHEAD OF UTC MAR 25 - SEP 30
-GREENLAND 4 H BEHIND UTC IN THULE AIRBASE YEAR ROUND
-GREENLAND 3 H BEHIND UTC IN WINTER AT SONDRESTROM
-GREENLAND 2 H BEHIND UTC 30 MAR - 30 SEP 2200 LOCAL AT -"-
-GREENLAND 2 H BEHIND UTC AROUND SCORESBY SUND
-ICELAND ON UTC
-IRAN 3.5H AHEAD OF UTC
-IRELAND ON UTC IN WINTER
-IRELAND 1 H AHEAD OF UTC MAR 31 - OCT 23 0200 LOCAL
-ITALY 1 H AHEAD OF UTC IN WINTER
-ITALY 2 H AHEAD OF UTC MAR 31 - SEP 30, 0030 LOCAL
-JAMAICA 5 H BEHIND UTC IN WINTER
-JAMAICA 4 H BEHIND UTC APR 29 - OCT 29
-LIBYA 2 H AHEAD OF UTC
-MEXICO BAJA CAL N 8 H BEHIND UTC IN WINTER; NORTH BAJA CAL, TIJUANA
-MEXICO BAJA CAL N 7 H BEHIND UTC APR 29 - OCT 29
-MEXICO BAJA CAL S 7 H BEHIND UTC ALL YEAR; MAZATLAN
-MEXICO CENTRAL 6 H BEHIND UTC ALL YEAR; MEXICO CITY
-MONACO 1 H AHEAD UTC IN WINTER
-MONACO 2 H AHEAD UTC MAR 25 - SEP30
-PARAGUAY 4 H BEHIND UTC IN WINTER
-PARAGUAY 3 H BEHIND UTC SEP 30 - MAR 30
-POLAND 1 H AHEAD OF UTC IN WINTER
-POLAND 2 H AHEAD OF UTC MAR 24 - SEP 0200 LOCAL
-PORTUGAL ON UTC IN WINTER
-PORTUGAL 1 H AHEAD OF UTC IN SUMMER MAR 31 - SEP 29 0100 LOCAL
-PORTUGAL AZORES 1 H BEHIND UTC IN WINTER
-PORTUGAL AZORES ON UTC IN SUMMER MAR 31 - SEP 29
-PORTUGAL MADEIRA ON UTC ALL YEAR;
-ROMANIA 2 H AHEAD OF UTC IN WINTER
-ROMANIA 3 H AHEAD OF UTC APR 3 - SEP 24
-SCOTLAND SEE ENGLAND
-SWITZERLAND 1 H AHEAD OF UTC IN WINTER
-SWITZERLAND 2 H AHEAD OF UTC MAR 31 - SEP 30 0200 LOCAL
-TURKEY 3 H AHEAD OF UTC
-USA EASTERN 5 H BEHIND UTC IN WINTER; NEW YORK, WASHINGTON
-USA EASTERN 4 H BEHIND UTC APR 29 - OCT 29
-USA CENTRAL 6 H BEHIND UTC IN WINTER; CHICAGO, HOUSTON
-USA CENTRAL 5 H BEHIND UTC APR 29 - OCT 29
-USA MOUNTAIN 7 H BEHIND UTC IN WINTER; DENVER
-USA MOUNTAIN 6 H BEHIND UTC APR 29 - OCT 29
-USA PACIFIC 8 H BEHIND UTC IN WINTER; L.A., SAN FRANCISCO
-USA PACIFIC 7 H BEHIND UTC APR 29 - OCT 29
-USA ALASKA STD 9 H BEHIND UTC IN WINTER; MOST OF ALASKA (AKST)
-USA ALASKA STD 8 H BEHIND UTC APR 29 - OCT 29 (AKDT)
-USA ALEUTIAN 10 H BEHIND UTC IN WINTER; ISLANDS WEST OF 170W
-USA - " - 9 H BEHIND UTC APR 29 - OCT 29
-USA HAWAII 10 H BEHIND UTC ALL YEAR;
-USA BERING 11 H BEHIND UTC ALL YEAR; SAMOA, MIDWAY
-USSR WEST EUROP 3 H AHEAD OF UTC IN WINTER; LENINGRAD, MOSCOW
-USSR WEST EUROP 4 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL EUR 4 H AHEAD OF UTC IN WINTER; ROSTOV, BAKU
-USSR CENTRAL EUR 5 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST EUROP 5 H AHEAD OF UTC IN WINTER; SVERDLOVSK
-USSR EAST EUROP 6 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST SIBERIAN 6 H AHEAD OF UTC IN WINTER; TASHKENT, ALMA ATA
-USSR WEST SIBERIAN 7 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST-CENTRAL 7 H AHEAD OF UTC IN WINTER; NOVOSIBIRSK
-USSR WEST-CENTRAL 8 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST-CENTRAL 8 H AHEAD OF UTC IN WINTER; IRKUTSK
-USSR WEST-CENTRAL 9 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL SIB 9 H AHEAD OF UTC IN WINTER; YAKUTSK
-USSR CENTRAL SIB 10 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL SIB 10 H AHEAD OF UTC IN WINTER; VLADIVOSTOK
-USSR CENTRAL SIB 11 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 11 H AHEAD OF UTC IN WINTER; MAGADAN
-USSR EAST SIBERIA 12 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 12 H AHEAD OF UTC IN WINTER; PETROPAVLOVSK
-USSR EAST SIBERIA 13 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 13 H AHEAD OF UTC IN WINTER; UELEN
-USSR EAST SIBERIA 14 H AHEAD OF UTC APR 1 - SEP 30
-WALES SEE ENGLAND
+++ /dev/null
-# @(#)usno1989 7.1
-#
-# From Arthur David Olson (January 19, 1989):
-#
-# Here's time zone information from the United States Naval Observatory;
-# no corrections have been made, and there are some obvious challenges.
-# The USNO warns:
-# DUE TO FREQUENT CHANGES IN THE LOCAL LAWS GOVERNING DAYLIGHT
-# SAVING TIME, WE CANNOT GUARANTEE THE ACCURACY OF THIS
-# INFORMATION. PLEASE ALERT US TO ANY DISCREPANCY YOU MAY
-# DISCOVER.
-#
-AFGHANISTAN 4.5H AHEAD OF UTC
-ALBANIA 1 H AHEAD OF UTC
-ALBANIA 2 H AHEAD OF UTC MAR 27 - SEP 24
-ALBANIA (ESTIMATED)
-ALGERIA 1 H AHEAD OF UTC
-AMERICAN SAMOA 11 H BEHIND UTC
-ANDORRA 1 H AHEAD OF UTC
-ANDORRA 2 H AHEAD OF UTC MAR 27 - SEP 24
-ANDORRA (ESTIMATED)
-ANGOLA 1 H AHEAD OF UTC
-ARGENTINA 3 H BEHIND UTC
-ARUBA 4 H BEHIND UTC ALSO BONAIRE, CURACAO,
-ARUBA ST.MAARTEN
-AUSTRALIA WEST 8 H AHEAD OF UTC PERTH, EXMOUTH
-AUSTRALIA N.T. 9.5H AHEAD OF UTC DARWIN NO ADVANCED TIME
-AUSTRALIA N.T. IN SUMMER
-AUSTRALIA SOUTH 9.5H AHEAD OF UTC ADELAIDE
-AUSTRALIA INCLUDING BROKEN HILL, NSW
-AUSTRALIA SOUTH 10.5H AHEAD OF UTC ADELAIDE OCT 30, '88-MAR
-AUSTRALIA SOUTH 18, '89 INCLUDING BROKEN
-AUSTRIALIA SOUTH HILL, NSW
-AUSTRALIA QUEENL 10 H AHEAD OF UTC
-AUSTRALIA NSW 10 H AHEAD OF UTC SYDNEY
-AUSTRALIA NSW 11 H AHEAD OF UTC SYDNEY OCT 30, '88-MAR 18,
-AUSTRALIA NSW '89
-AUSTRALIA TASM. 10 H AHEAD OF UTC HOBART
-AUSTRALIA TASM. 11 H AHEAD OF UTC HOBART OCT 30, '88-MAR 18,
-AUSTRALIA TASM. '89
-AUSTRIA 1 H AHEAD OF UTC
-AUSTRIA 2 H AHEAD OF UTC MAR 27 - SEPT 24
-AZORES SEE PORTUGAL
-BAHAMAS 5 H BEHIND UTC EXCLUDING TURKS AND CAICOS
-BAHAMAS ISLANDS)
-BAHAMAS 4 H BEHIND UTC APR 3 - OCT 29 (SAME
-BAHAMAS EXCLUSION)
-BAHRAIN 3 H AHEAD OF UTC
-BANGLADESH 6 H AHEAD OF UTC
-BARBADOS 4 H BEHIND UTC
-BELGIUM 1 H AHEAD OF UTC
-BELGIUM 2 H AHEAD OF UTC MAR 27 - SEP 24
-BELIZE 6 H BEHIND UTC
-BENIN PEOPLES REP 1 H AHEAD OF UTC DAHOMEY
-BERMUDA 4 H BEHIND UTC
-BERMUDA 3 H BEHIND UTC APR 3 - OCT 29
-BHUTAN 6 H AHEAD OF UTC
-BOLIVIA 4 H BEHIND UTC
-BONAIRE 4 H BEHIND UTC ALSO ARUBA,CURACAO,
-BONAIRE ST.MAARTEN, SABA
-BOTSWANA 2 H AHEAD OF UTC
-BRAZIL WEST 5 H BEHIND UTC TERRITORY OF ACRE
-BRAZIL WEST 4 H BEHIND UTC ACRE OCT 23, '88-FEB 11,
-BRAZIL '89 (ESTIMATED)
-BRAZIL CENTRAL 4 H BEHIND UTC MANAUS
-BRAZIL CENTRAL 3 H BEHIND UTC MANAUS OCT 23, '88-FEB 11,
-BRAZIL CENTRAL '89 (ESTIMATED)
-BRAZIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SAO
-BRAZIL EAST PAULO, BRASILIA
-BRAZIL EAST 2 H BEHIND UTC COASTAL STATES, RIO, SAO
-BRAZIL PAULO, BRASILIA OCT 23,
-BRAZIL '88-FEB 11, '89
-BRAZIL (ESTIMATED)
-BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS, FERNANDO
-BRAZIL DE NORONHA
-BRAZIL 1 H BEHIND UTC OCT 23, '88-FEB 11, '89
-BRAZIL (ESTIMATED)
-BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS.
-BRITISH VIRGIN I. 4 H BEHIND UTC
-BRUNEI 8 H AHEAD OF UTC
-BULGARIA 2 H AHEAD OF UTC
-BULGARIA 3 H AHEAD OF UTC MAR 27 - SEP 24
-BURKINA FASO ON UTC
-BURMA 6.5H AHEAD OF UTC
-BURUNDI 2 H AHEAD OF UTC
-CAMBODIA SEE KAMPUCHEA
-CAMEROON 1 H AHEAD OF UTC
-CANADA NEW FDL 3.5H BEHIND UTC ST.JOHN'S
-CANADA NEW FDL 1.5H BEHIND UTC APR 3 - OCT 29
-CANADA ATLANTIC 4 H BEHIND UTC HALIFAX
-CANADA ATLANTIC 3 H BEHIND UTC APR 3 - OCT 29
-CANADA EASTERN 5 H BEHIND UTC TORONTO, MONTREAL, OTTAWA
-CANADA EASTERN 4 H BEHIND UTC APR 3 - OCT 29
-CANADA CENTRAL 6 H BEHIND UTC REGINA, WINNIPEG
-CANADA CENTRAL 5 H BEHIND UTC APR 3 - OCT 29
-CANADA MOUNTAIN 7 H BEHIND UTC CALGARY, EDMONTON
-CANADA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 29
-CANADA PACIFIC 8 H BEHIND UTC VANCOUVER
-CANADA PACIFIC 7 H BEHIND UTC APR 3 - OCT 29
-CANADA YUKON SAME AS PACIFIC DAWSON
-CAPE VERDE 1 H BEHIND UTC
-CAYMAN ISLANDS 5 H BEHIND UTC
-CAROLINE ISLAND 10 H AHEAD OF UTC EXCLUDING PONAPE IS.,
-CAROLINE ISLAND KUSAIE, AND PINGELAP
-CENTRAL AFRICA 1 H AHEAD OF UTC
-CEYLON 5.5H AHEAD OF UTC, SEE SRI LANKA
-CHAD 1 H AHEAD OF UTC
-CHANNEL ISLANDS SEE ENGLAND
-CHILE 4 H BEHIND UTC CONTINENTAL
-CHILE 3 H BEHIND UTC OCT 9, '88-MAR 11, '89
-CHILE 6 H BEHIND UTC EASTER ISLAND
-CHILE 5 H BEHIND UTC OCT 9, '88-MAR 11, '89
-CHINA 8 H AHEAD OF UTC ALL OF CHINA, INCL TAIWAN
-CHINA 9 H AHEAD OF UTC APR 17 - SEP 10
-COCOS (Keeling) I. 6.5H AHEAD OF UTC
-COLOMBIA 5 H BEHIND UTC
-COMOROS 3 H AHEAD OF UTC
-CONGO 1 H AHEAD OF UTC
-COOK ISLANDS 10 H BEHIND UTC
-COOK ISLANDS 9.5H BEHIND UTC OCT 30, '88-MAR 24, '89
-COOK ISLANDS (ESTIMATED)
-COSTA RICA 6 H BEHIND UTC
-COTE D'IVOIRE ON UTC
-CUBA 5 H BEHIND UTC
-CUBA 4 H BEHIND UTC MAR 20 - OCT 8
-CURACAO 4 H BEHIND UTC ALSO BONAIRE, ARUBA,
-CURACAO ST.MAARTEN
-CYPRUS 2 H AHEAD OF UTC
-CYPRUS 3 H AHEAD OF UTC MAR 27 - SEP 24
-CZECHOSLOVAKIA 1 H AHEAD OF UTC
-CZECHOSLOVAKIA 2 H AHEAD OF UTC MAR 27 - SEP 24
-DENMARK 1 H AHEAD OF UTC
-DENMARK 2 H AHEAD OF UTC MAR 27 - SEP 24
-DENMK. FAEROE IS 1 H AHEAD OF UTC MAR 27 - SEP 24
-DJIBOUTI 3 H AHEAD OF UTC
-DOMINICA 4 H BEHIND UTC
-DOMINICAN REP 4 H BEHIND UTC
-ECUADOR 5 H BEHIND UTC CONTINENTAL
-ECUADOR 6 H BEHIND UTC GALAPAGOS ISLANDS
-EGYPT 2 H AHEAD OF UTC
-EGYPT 3 H AHEAD OF UTC MAY 17 - SEP 30 (AFTER
-EGYPT RAMADAN)
-EL SALVADOR 6 H BEHIND UTC
-ENGLAND ON UTC (WALES, SCOTLAND, N.I.,
-ENGLAND CH. IS.)
-ENGLAND 1 H AHEAD OF UTC MAR 27 - OCT 22
-ENEZUELA 4 H BEHIND UTC
-EQUITORIAL GUINEA 1 H AHEAD OF UTC
-ETHIOPIA 3 H AHEAD OF UTC
-FALKLAND ISLANDS 4 H BEHIND UTC
-FALKLAND ISLANDS 3 H BEHIND UTC SEP 11, '88-APR 15, '89
-FALKLAND ISLANDS (ESTIMATED)
-FAROE ISLAND ON UTC
-FAROE ISLAND 1 H AHEAD OF UTC MAR 27 - SEP 24
-FIJI 12 H AHEAD OF UTC
-FINLAND 2 H AHEAD OF UTC
-FINLAND 3 H AHEAD OF UTC MAR 27 - SEP 24
-FRANCE 1 H AHEAD OF UTC
-FRANCE 2 H AHEAD OF UTC MAR 27 - SEP 24
-FRENCH GUIANA 3 H BEHIND UTC
-FRENCH POLYNESIA 9 H BEHIND UTC GAMBIER ISLAND
-FRENCH POLYNESIA 9.5H BEHIND UTC MARQUESAS ISLANDS
-FRENCH POLYNESIA 10 H BEHIND UTC SOCIETY ISLANDS, TUBUAI
-FRENCH POLYNESIA ISLANDS, TUAMOTU ISLAND,
-FRENCH POLYNESIA TAHITI
-GABON 1 H AHEAD OF UTC
-GAMBIA ON UTC
-GERMANY ALL 1 H AHEAD OF UTC
-GERMANY ALL 2 H AHEAD OF UTC MAR 27 - SEP 24
-GHANA ON UTC
-GIBRALTAR 1 H AHEAD OF UTC
-GIBRALTAR 2 H AHEAD OF UTC MAR 27 - SEP 24
-GREECE 2 H AHEAD OF UTC
-GREECE 3 H AHEAD OF UTC MAR 27 - SEP 24
-GREENLAND 4 H BEHIND UTC THULE AIRBASE YEAR ROUND
-GREENLAND 3 H BEHIND UTC ANGMAGSSALIK AND W. COAST
-GREENLAND 2 H BEHIND UTC MAR 27 - SEP 24
-GREENLAND 1 H BEHIND UTC SCORESBYSUND
-GREENLAND ON UTC MAR 27 - SEP 24
-GRENADA 4 H BEHIND UTC
-GUADELOUPE 4 H BEHIND UTC ST. BARTHELEMY, NORTHERN
-GUADELOUPE ST. MARTIN MARTINIQUE
-GUAM 10 H AHEAD OF UTC
-GUATEMALA 6 H BEHIND UTC
-GUINEA ON UTC
-GUINEA BISSAU ON UTC
-GUINEA REPUBLIC ON UTC
-GUINEA EQUATORIAL 1 H AHEAD OF UTC
-GUYANA 3 H BEHIND UTC
-HAITI 5 H BEHIND UTC
-HAITI 4 H BEHIND UTC APR 3 - OCT 29
-HOLLAND SEE NETHERLANDS
-HONDURAS 6 H BEHIND UTC
-HONG KONG 8 H AHEAD OF UTC
-HUNGARY 1 H AHEAD OF UTC
-HUNGARY 2 H AHEAD OF UTC MAR 27 - SEP 24
-ICELAND ON UTC
-INDIA 5.5H AHEAD OF UTC INCLUDING ANDAMAN ISLANDS
-INDONESIA WEST 7 H AHEAD OF UTC SUMATRA, JAVA, BALI,
-INDONESIA WEST JAKARTA
-INDONESIA CENTRAL 8 H AHEAD OF UTC KALIMANTAN, SULAWESI
-INDONESIA EAST 9 H AHEAD OF UTC IRIAN, BARAT
-IRAN 3.5H AHEAD OF UTC
-IRAQ 3 H AHEAD OF UTC
-IRAQ 4 H AHEAD OF UTC APR 1 - SEP 30
-IRELAND ON UTC
-IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22
-ISRAEL 2 H AHEAD OF UTC
-ISRAEL 3 H AHEAD OF UTC APR 10 - SEP 3
-ITALY 1 H AHEAD OF UTC
-ITALY 2 H AHEAD OF UTC MAR 27 - SEP 24
-IVORY COAST ON UTC
-IWAN 8 H AHEAD OF UTC
-JAMAICA 5 H BEHIND UTC
-JAPAN 9 H AHEAD OF UTC
-JOHNSTON ISLAND 10 H BEHIND UTC
-JORDAN 2 H AHEAD OF UTC
-JORDAN 3 H AHEAD OF UTC APR 1 - OCT 6
-KAMPUCHEA 7 H AHEAD OF UTC
-KENYA 3 H AHEAD OF UTC
-KIRIBATI, REP OF 12 H AHEAD OF UTC CANTON, ENDERBURY ISLANDS
-KIRIBATI, REP OF 11 H AHEAD OF UTC CHRISTMAS ISLAND
-KOREA 9 H AHEAD OF UTC
-KOREA, REP OF 9 H AHEAD OF UTC
-KOREA, REP OF 10 H AHEAD OF UTC MAY 8 - OCT 8
-KUWAIT 3 H AHEAD OF UTC
-KUSAIE, PINGELAP 12 H AHEAD OF UTC INCLUDING MARSHALL IS.,
-KUSAIE, PINGELAP EXCLUDING KWAJALEIN)
-KWAJALEIN 12 H BEHIND UTC
-LAOS 7 H AHEAD OF UTC
-LEBANON 2 H AHEAD OF UTC
-LEBANON 3 H AHEAD OF UTC JUN 1 - OCT 31
-LEEWARD ISLANDS 4 H BEHIND UTC ANTIGUA, DOMINICA,
-LEEWARD ISLANDS MONTSERRAT, ST.
-LEEWARD ISLAANDS CHRISTOPHER, ST. KITTS,
-LEEWARD ISLANDS NEVIS, ANGUILLA
-LESOTHO 2 H AHEAD OF UTC
-LIBERIA ON UTC
-LIBYAN ARAB 1 H AHEAD OF UTC JAMAHIRIYA/LIBYA
-LIBYAN ARAB 2 H AHEAD OF UTC APR 1 - SEP 30 JAMAHIRIYA/LIBYA
-LIECHTENSTEIN 1 H AHEAD OF UTC
-LIECHTENSTEIN 2 H AHEAD OF UTC MAR 27 - SEP 24
-LUXEMBOURG 1 H AHEAD OF UTC
-LUXEMBOURG 2 H AHEAD OF UTC MAR 27 - SEP 24
-MACAO 8 H AHEAD OF UTC
-MADAGASCAR 3 H AHEAD OF UTC
-MADEIRA SEE PORTUGAL
-MALAWI 2 H AHEAD OF UTC
-MALAYSIA 8 H AHEAD OF UTC
-MALDIVES 5 H AHEAD OF UTC
-MALI ON UTC
-MALTA 1 H AHEAD OF UTC
-MALTA 2 H AHEAD OF UTC MAR 27 - SEP 24
-MARTINIQUE 4 H BEHIND UTC
-MAURITANIA ON UTC
-MAURITIUS 4 H AHEAD OF UTC
-MARIANA ISLAND 10 H AHEAD OF UTC EXCLUDING GUAM
-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 PARALLAL APR 3
-MEXICO BAJA CAL N - OCT 29
-MEXICO BAJA CAL N 7 H BEHIND UTC ABOVE 28TH PARALLAL 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
-MIDWAY ISLAND 11 H BEHIND UTC
-MONACO 1 H AHEAD OF UTC
-MONACO 2 H AHEAD OF UTC MAR 27 - SEP 24
-MONGOLIA 8 H AHEAD OF UTC
-MONGOLIA 9 H AHEAD OF UTC MAR 27 - SEP 24
-MONTSERRAT 4 H BEHIND UTC
-MOROCCO ON UTC
-MOZAMBIQUE 2 H AHEAD OF UTC
-NAMIBIA 2 H AHEAD OF UTC
-NAURU, REP OF 12 H AHEAD OF UTC
-NEPAL 5H45M AHEAD OF UTC
-NETHERLANDS 1 H AHEAD OF UTC
-NETHERLANDS 2 H AHEAD OF UTC MAR 27 - SEP 24
-NETHERLANDS 4 H BEHIND UTC ANTILLES AND SOUTHERN ST.
-NETHERLANDS MAARTEN
-NEW CALEDONIA 11 H AHEAD OF UTC
-NEW HEBRIDES SEE VANUATU
-NEW ZEALAND 12 H AHEAD OF UTC (EXCLUDING CHATHAM ISLAND)
-NEW ZEALAND 13 H AHEAD OF UTC OCT 30, '88-MAR 4, '89
-NEW ZEALAND 12H45M AHEAD OF UTC CHATHAM ISLAND
-NICARAGUA 6 H BEHIND UTC
-NIGER 1 H AHEAD OF UTC
-NIGERIA 1 H AHEAD OF UTC
-NIUE ISLAND 11 H BEHIND UTC
-NORFOLK ISLAND 11H30M AHEAD OF UTC
-NORTHERN IRELAND ON UTC WALES, SCOTLAND, N.I.,
-NORTHERN IRELAND CH.IS.
-NORTHERN IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22
-NORWAY 1 H AHEAD OF UTC
-NORWAY 2 H AHEAD OF UTC MAR 27 - SEP 24
-OGO ON UTC
-OMAN 4 H AHEAD OF UTC
-PACIFIC ISLAND T.T.
-PALAU ISLAND 9 H AHEAD OF UTC
-PAKISTAN 5 H AHEAD OF UTC
-PANAMA 5 H BEHIND UTC
-PAPUA NEW GUINEA 10 H AHEAD OF UTC INCLUDING BOUGAINVILLE
-PAPUA NEW GUINEA ISLAND
-PARAGUAY 4 H BEHIND UTC
-PARAGUAY 3 H BEHIND UTC OCT 1, '88-MAR 31, '89
-PERU 5 H BEHIND UTC
-PHILIPPINES 8 H AHEAD OF UTC
-PONAPE ISLAND 11 H AHEAD OF UTC
-POLAND 1 H AHEAD OF UTC
-POLAND 2 H AHEAD OF UTC MAR 27 - SEP 24
-PORTUGAL MAINLAND ON UTC
-PORTUGAL MAINLAND 1 H AHEAD OF UTC MAR 27 - SEP 24
-PORTUGAL AZORES 1 H BEHIND UTC
-PORTUGAL AZORES ON UTC MAR 27 - SEP 24
-PORTUGAL MADEIRA ON UTC
-PORTUGAL MADEIRA 1 H AHEAD OF UTC MAR 27 - SEP 24
-PUERTO RICO 4 H BEHIND UTC
-QATAR 3 H AHEAD OF UTC
-ROMANIA 2 H AHEAD OF UTC
-ROMANIA 3 H AHEAD OF UTC MAR 27 - SEP 24
-RUSSIA SEE USSR
-RWANDA 2 H AHEAD OF UTC
-SABA 4 H BEHIND UTC ALSO BONAIRE, CURACAO,
-SAMOA 11 H BEHIND UTC
-SAN MARINO 1 H AHEAD OF UTC
-SAN MARINO 2 H AHEAD OF UTC MAR 27 - SEP 24
-SAN SALVADOR 6 H BEHIND UTC
-SAO TOME ISLAND ON UTC AND PRINCIPE ISLAND
-SAUDI ARABIA 3 H AHEAD OF UTC
-SCOTLAND SEE ENGLAND
-SENEGAL ON UTC
-SEYCHELLES 4 H AHEAD OF UTC
-SIERRA LEONE ON UTC
-SINGAPORE 8 H AHEAD OF UTC
-SOLOMON ISLANDS 11 H AHEAD OF UTC EXCLUDING BOUGAINVILLE
-SOLOMON ISLANDS ISLAND
-SOMALI 3 H AHEAD OF UTC
-SOUTH AFRICA 2 H AHEAD OF UTC
-SPAIN CANARY IS ON UTC
-SPAIN CANARY IS 1 H AHEAD OF UTC MAR 27 - SEP 24
-SPAIN 1 H AHEAD OF UTC CONTINENTAL, BALEARIC AND
-SPAIN MALLORCA ISLANDS
-SPAIN 2 H AHEAD OF UTC CONTINENTAL, BALEARIC AND
-SPAIN MALLORCA ISLANDS MAR 27 -
-SPAIN SEP 24
-SPAIN MAINLAND 1 H AHEAD OF UTC MELILLA
-SPAIN MAINLAND 2 H AHEAD OF UTC MAR 27 - SEP 24
-SRI LANKA 5H30M AHEAD OF UTC
-ST.MAARTEN
-ST.KITTS-NEVIS 4 H BEHIND UTC
-ST.LUCIA 4 H BEHIND UTC
-ST.PIERRE 3 H BEHIND UTC INCLUDING MIQUELON
-ST.PIERRE 2 H BEHIND UTC INLCUDING MIQUELON APR 3
-ST.PIERRE - OCT 29
-ST.VINCENT 4 H BEHIND UTC INCLUDING THE GRENADINES
-ST. HELENA ON UTC
-SURINAME 3 H BEHIND UTC
-SWAZILAND 2 H AHEAD OF UTC
-SWEDEN 1 H AHEAD OF UTC
-SWEDEN 2 H AHEAD OF UTC MAR 27 - SEP 24
-SWITZERLAND 1 H AHEAD OF UTC
-SWITZERLAND 2 H AHEAD OF UTC MAR 27 - SEP 24
-SYRIA 2 H AHEAD OF UTC
-SYRIA 3 H AHEAD OF UTC MAR 15 - OCT 30
-TAHITI 10 H BEHIND UTC
-TANZANIA 3 H AHEAD OF UTC
-THAILAND 7 H AHEAD OF UTC
-TRINIDAD / TOBAGO 4 H BEHIND UTC
-TUNISIA 1 H AHEAD OF UTC
-TUNISIA 2 H AHEAD OF UTC APR 10 - SEP 24
-TURKEY 2 H AHEAD OF UTC
-TURKEY 3 H AHEAD OF UTC MAR 27 - SEP 24
-TURKS AND CAICOS 5 H BEHIND UTC
-TURKS AND CAICOS 4 H BEHIND UTC APR 3 - OCT 29
-TUVALU 12 H AHEAD OF UTC
-UDAN 2 H AHEAD OF UTC
-UGANDA 3 H AHEAD OF UTC
-UNITED ARAB EMIR. 4 H AHEAD OF UTC ABU DHABI, DUBAI, SHARJAH,
-UNITED ARAB EMIR RAS AL KHAIMAH
-UNITED KINGDOM ON UTC WALES, SCOTLAND, N.I., CH.
-UNITED KINGDOM IS.
-UNITED KINGDOM 1 H AHEAD OF UTC MAR 27 - OCT 22
-UNITED STATES SEE USA
-UPPER VOLTA ON UTC
-URUGUAY 3 H BEHIND UTC
-URUGUAY 2 H BEHIND UTC DEC 11, '88-FEB 25, '89
-URAGUAY (ESTIMATED)
-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
-USA FOR SPECIFIC INFO ON USA ZONES/TIMES CALL DOT 202-426-4520
-USSR WEST EUROP 3 H AHEAD OF UTC LENINGRAD, MOSCOW
-USSR WEST EUROP 4 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL EUR 4 H AHEAD OF UTC ROSTOV, BAKU
-USSR CENTRAL EUR 5 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST EUROP 5 H AHEAD OF UTC SVERDLOVSK
-USSR EAST EUROP 6 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST SIBERIAN 6 H AHEAD OF UTC TASHKENT, ALMA ATA
-USSR WEST SIBERIAN 7 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST-CENTRAL 7 H AHEAD OF UTC NOVOSIBIRSK
-USSR WEST-CENTRAL 8 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST-CENTRAL 8 H AHEAD OF UTC IRKUTSK
-USSR WEST-CENTRAL 9 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL SIB 9 H AHEAD OF UTC YAKUTSK
-USSR CENTRAL SIB 10 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL SIB 10 H AHEAD OF UTC VLADIVOSTOK
-USSR CENTRAL SIB 11 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 11 H AHEAD OF UTC MAGADAN
-USSR EAST SIBERIA 12 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 12 H AHEAD OF UTC PETROPAVLOVSK
-USSR EAST SIBERIA 13 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 13 H AHEAD OF UTC UELEN
-USSR EAST SIBERIA 14 H AHEAD OF UTC APR 1 - SEP 30
-VANUATU 11 H AHEAD OF UTC (NEW HEBRIDES)
-VANUATU 12 H AHEAD OF UTC SEP 25, '88-MAR 25, '89
-VANUATU (ESTIMATED)
-VATICAN 1 H AHEAD OF UTC
-VATICAN 2 H AHEAD OF UTC MAR 27 - SEP 24
-VIETNAM 7 H AHEAD OF UTC
-VIRGIN ISLANDS 4 H BEHIND UTC ST.CROIX, ST.THOMAS,
-VIRGIN ISLANDS ST.JOHN
-WAKE ISLAND 12 H AHEAD OF UTC
-WALES SEE ENGLAND
-WALLIS/FUTUNA IS. 12 H AHEAD OF UTC
-WINDWARD ISLANDS 4 H BEHIND UTC GRENADA, ST. LUCIA
-YEMEN 3 H AHEAD OF UTC BOTH REPUBLICS
-YUGOSLAVIA 1 H AHEAD OF UTC
-YUGOSLAVIA 2 H AHEAD OF UTC MAR 27 - SEP 24
-ZAIRE EAST 1 H AHEAD OF UTC KINSHASA MBANDAKA
-ZAIRE WEST 2 H AHEAD OF UTC LUBUMBASHI, KASAI, KIVU,
-ZAIRE WEST HAUT-ZAIRE, SHABA
-ZAMBIA 2 H AHEAD OF UTC
-ZIMBABWE 2 H AHEAD OF UTC
+++ /dev/null
-# @(#)usno1989a 7.2
-#
-# From Arthur David Olson (February 7, 1994):
-#
-# Here's time zone information from the United States Naval Observatory,
-# with corrections from Paul Eggert (eggert@twinsun.com).
-# The USNO warns:
-# DUE TO FREQUENT CHANGES IN THE LOCAL LAWS GOVERNING DAYLIGHT
-# SAVING TIME, WE CANNOT GUARANTEE THE ACCURACY OF THIS
-# INFORMATION. PLEASE ALERT US TO ANY DISCREPANCY YOU MAY
-# DISCOVER.
-#
-AFGHANISTAN 4.5H AHEAD OF UTC
-ALBANIA 1 H AHEAD OF UTC
-ALBANIA 2 H AHEAD OF UTC MAR 27 - SEP 24
-ALBANIA (ESTIMATED)
-ALGERIA 1 H AHEAD OF UTC
-AMERICAN SAMOA 11 H BEHIND UTC
-ANDORRA 1 H AHEAD OF UTC
-ANDORRA 2 H AHEAD OF UTC MAR 27 - SEP 24
-ANDORRA (ESTIMATED)
-ANGOLA 1 H AHEAD OF UTC
-ARGENTINA 3 H BEHIND UTC
-ARUBA 4 H BEHIND UTC ALSO BONAIRE, CURACAO,
-ARUBA ST.MAARTEN
-AUSTRALIA WEST 8 H AHEAD OF UTC PERTH, EXMOUTH
-AUSTRALIA N.T. 9.5H AHEAD OF UTC DARWIN NO ADVANCED TIME
-AUSTRALIA N.T. IN SUMMER
-AUSTRALIA SOUTH 9.5H AHEAD OF UTC ADELAIDE
-AUSTRALIA INCLUDING BROKEN HILL, NSW
-AUSTRALIA SOUTH 10.5H AHEAD OF UTC ADELAIDE OCT 30, '88-MAR
-AUSTRALIA SOUTH 18, '89 INCLUDING BROKEN
-AUSTRIALIA SOUTH HILL, NSW
-AUSTRALIA QUEENL 10 H AHEAD OF UTC
-AUSTRALIA NSW 10 H AHEAD OF UTC SYDNEY
-AUSTRALIA NSW 11 H AHEAD OF UTC SYDNEY OCT 30, '88-MAR 18,
-AUSTRALIA NSW '89
-AUSTRALIA TASM. 10 H AHEAD OF UTC HOBART
-AUSTRALIA TASM. 11 H AHEAD OF UTC HOBART OCT 30, '88-MAR 18,
-AUSTRALIA TASM. '89
-AUSTRIA 1 H AHEAD OF UTC
-AUSTRIA 2 H AHEAD OF UTC MAR 27 - SEPT 24
-AZORES SEE PORTUGAL
-BAHAMAS 5 H BEHIND UTC EXCLUDING TURKS AND CAICOS
-BAHAMAS ISLANDS)
-BAHAMAS 4 H BEHIND UTC APR 3 - OCT 29 (SAME
-BAHAMAS EXCLUSION)
-BAHRAIN 3 H AHEAD OF UTC
-BANGLADESH 6 H AHEAD OF UTC
-BARBADOS 4 H BEHIND UTC
-BELGIUM 1 H AHEAD OF UTC
-BELGIUM 2 H AHEAD OF UTC MAR 27 - SEP 24
-BELIZE 6 H BEHIND UTC
-BENIN PEOPLES REP 1 H AHEAD OF UTC DAHOMEY
-BERMUDA 4 H BEHIND UTC
-BERMUDA 3 H BEHIND UTC APR 3 - OCT 29
-BHUTAN 6 H AHEAD OF UTC
-BOLIVIA 4 H BEHIND UTC
-BONAIRE 4 H BEHIND UTC ALSO ARUBA,CURACAO,
-BONAIRE ST.MAARTEN, SABA
-BOTSWANA 2 H AHEAD OF UTC
-BRAZIL WEST 5 H BEHIND UTC TERRITORY OF ACRE
-BRAZIL WEST 4 H BEHIND UTC ACRE OCT 23, '88-FEB 11,
-BRAZIL '89 (ESTIMATED)
-BRAZIL CENTRAL 4 H BEHIND UTC MANAUS
-BRAZIL CENTRAL 3 H BEHIND UTC MANAUS OCT 23, '88-FEB 11,
-BRAZIL CENTRAL '89 (ESTIMATED)
-BRAZIL EAST 3 H BEHIND UTC COASTAL STATES, RIO, SAO
-BRAZIL EAST PAULO, BRASILIA
-BRAZIL EAST 2 H BEHIND UTC COASTAL STATES, RIO, SAO
-BRAZIL PAULO, BRASILIA OCT 23,
-BRAZIL '88-FEB 11, '89
-BRAZIL (ESTIMATED)
-BRAZIL 2 H BEHIND UTC ATLANTIC ISLANDS, FERNANDO
-BRAZIL DE NORONHA
-BRAZIL 1 H BEHIND UTC OCT 23, '88-FEB 11, '89
-BRAZIL (ESTIMATED)
-BRAZIL 3 H BEHIND UTC FOR MOST MAJOR AIRPORTS.
-BRITISH VIRGIN I. 4 H BEHIND UTC
-BRUNEI 8 H AHEAD OF UTC
-BULGARIA 2 H AHEAD OF UTC
-BULGARIA 3 H AHEAD OF UTC MAR 27 - SEP 24
-BURKINA FASO ON UTC
-BURMA 6.5H AHEAD OF UTC
-BURUNDI 2 H AHEAD OF UTC
-CAMBODIA SEE KAMPUCHEA
-CAMEROON 1 H AHEAD OF UTC
-CANADA NEW FDL 3.5H BEHIND UTC ST.JOHN'S
-CANADA NEW FDL 1.5H BEHIND UTC APR 3 - OCT 29
-CANADA ATLANTIC 4 H BEHIND UTC HALIFAX
-CANADA ATLANTIC 3 H BEHIND UTC APR 3 - OCT 29
-CANADA EASTERN 5 H BEHIND UTC TORONTO, MONTREAL, OTTAWA
-CANADA EASTERN 4 H BEHIND UTC APR 3 - OCT 29
-CANADA CENTRAL 6 H BEHIND UTC REGINA, WINNIPEG
-CANADA CENTRAL 5 H BEHIND UTC APR 3 - OCT 29
-CANADA MOUNTAIN 7 H BEHIND UTC CALGARY, EDMONTON
-CANADA MOUNTAIN 6 H BEHIND UTC APR 3 - OCT 29
-CANADA PACIFIC 8 H BEHIND UTC VANCOUVER
-CANADA PACIFIC 7 H BEHIND UTC APR 3 - OCT 29
-CANADA YUKON SAME AS PACIFIC DAWSON
-CAPE VERDE 1 H BEHIND UTC
-CAYMAN ISLANDS 5 H BEHIND UTC
-CAROLINE ISLAND 10 H AHEAD OF UTC EXCLUDING PONAPE IS.,
-CAROLINE ISLAND KUSAIE, AND PINGELAP
-CENTRAL AFRICA 1 H AHEAD OF UTC
-CEYLON 5.5H AHEAD OF UTC, SEE SRI LANKA
-CHAD 1 H AHEAD OF UTC
-CHANNEL ISLANDS SEE ENGLAND
-CHILE 4 H BEHIND UTC CONTINENTAL
-CHILE 3 H BEHIND UTC OCT 9, '88-MAR 11, '89
-CHILE 6 H BEHIND UTC EASTER ISLAND
-CHILE 5 H BEHIND UTC OCT 9, '88-MAR 11, '89
-CHINA 8 H AHEAD OF UTC ALL OF CHINA, INCL TAIWAN
-CHINA 9 H AHEAD OF UTC APR 17 - SEP 10
-COCOS (Keeling) I. 6.5H AHEAD OF UTC
-COLOMBIA 5 H BEHIND UTC
-COMOROS 3 H AHEAD OF UTC
-CONGO 1 H AHEAD OF UTC
-COOK ISLANDS 10 H BEHIND UTC
-COOK ISLANDS 9.5H BEHIND UTC OCT 30, '88-MAR 24, '89
-COOK ISLANDS (ESTIMATED)
-COSTA RICA 6 H BEHIND UTC
-COTE D'IVOIRE ON UTC
-CUBA 5 H BEHIND UTC
-CUBA 4 H BEHIND UTC MAR 20 - OCT 8
-CURACAO 4 H BEHIND UTC ALSO BONAIRE, ARUBA,
-CURACAO ST.MAARTEN
-CYPRUS 2 H AHEAD OF UTC
-CYPRUS 3 H AHEAD OF UTC MAR 27 - SEP 24
-CZECHOSLOVAKIA 1 H AHEAD OF UTC
-CZECHOSLOVAKIA 2 H AHEAD OF UTC MAR 27 - SEP 24
-DENMARK 1 H AHEAD OF UTC
-DENMARK 2 H AHEAD OF UTC MAR 27 - SEP 24
-DENMK. FAEROE IS 1 H AHEAD OF UTC MAR 27 - SEP 24
-DJIBOUTI 3 H AHEAD OF UTC
-DOMINICA 4 H BEHIND UTC
-DOMINICAN REP 4 H BEHIND UTC
-ECUADOR 5 H BEHIND UTC CONTINENTAL
-ECUADOR 6 H BEHIND UTC GALAPAGOS ISLANDS
-EGYPT 2 H AHEAD OF UTC
-EGYPT 3 H AHEAD OF UTC MAY 17 - SEP 30 (AFTER
-EGYPT RAMADAN)
-EL SALVADOR 6 H BEHIND UTC
-ENGLAND ON UTC (WALES, SCOTLAND, N.I.,
-ENGLAND CH. IS.)
-ENGLAND 1 H AHEAD OF UTC MAR 27 - OCT 22
-EQUATORIAL GUINEA 1 H AHEAD OF UTC
-ETHIOPIA 3 H AHEAD OF UTC
-FALKLAND ISLANDS 4 H BEHIND UTC
-FALKLAND ISLANDS 3 H BEHIND UTC SEP 11, '88-APR 15, '89
-FALKLAND ISLANDS (ESTIMATED)
-FAROE ISLAND ON UTC
-FAROE ISLAND 1 H AHEAD OF UTC MAR 27 - SEP 24
-FIJI 12 H AHEAD OF UTC
-FINLAND 2 H AHEAD OF UTC
-FINLAND 3 H AHEAD OF UTC MAR 27 - SEP 24
-FRANCE 1 H AHEAD OF UTC
-FRANCE 2 H AHEAD OF UTC MAR 27 - SEP 24
-FRENCH GUIANA 3 H BEHIND UTC
-FRENCH POLYNESIA 9 H BEHIND UTC GAMBIER ISLAND
-FRENCH POLYNESIA 9.5H BEHIND UTC MARQUESAS ISLANDS
-FRENCH POLYNESIA 10 H BEHIND UTC SOCIETY ISLANDS, TUBUAI
-FRENCH POLYNESIA ISLANDS, TUAMOTU ISLAND,
-FRENCH POLYNESIA TAHITI
-GABON 1 H AHEAD OF UTC
-GAMBIA ON UTC
-GERMANY ALL 1 H AHEAD OF UTC
-GERMANY ALL 2 H AHEAD OF UTC MAR 27 - SEP 24
-GHANA ON UTC
-GIBRALTAR 1 H AHEAD OF UTC
-GIBRALTAR 2 H AHEAD OF UTC MAR 27 - SEP 24
-GREECE 2 H AHEAD OF UTC
-GREECE 3 H AHEAD OF UTC MAR 27 - SEP 24
-GREENLAND 4 H BEHIND UTC THULE AIRBASE YEAR ROUND
-GREENLAND 3 H BEHIND UTC ANGMAGSSALIK AND W. COAST
-GREENLAND 2 H BEHIND UTC MAR 27 - SEP 24
-GREENLAND 1 H BEHIND UTC SCORESBYSUND
-GREENLAND ON UTC MAR 27 - SEP 24
-GRENADA 4 H BEHIND UTC
-GUADELOUPE 4 H BEHIND UTC ST. BARTHELEMY, NORTHERN
-GUADELOUPE ST. MARTIN MARTINIQUE
-GUAM 10 H AHEAD OF UTC
-GUATEMALA 6 H BEHIND UTC
-GUINEA ON UTC
-GUINEA BISSAU ON UTC
-GUINEA REPUBLIC ON UTC
-GUINEA EQUATORIAL 1 H AHEAD OF UTC
-GUYANA 3 H BEHIND UTC
-HAITI 5 H BEHIND UTC
-HAITI 4 H BEHIND UTC APR 3 - OCT 29
-HOLLAND SEE NETHERLANDS
-HONDURAS 6 H BEHIND UTC
-HONG KONG 8 H AHEAD OF UTC
-HUNGARY 1 H AHEAD OF UTC
-HUNGARY 2 H AHEAD OF UTC MAR 27 - SEP 24
-ICELAND ON UTC
-INDIA 5.5H AHEAD OF UTC INCLUDING ANDAMAN ISLANDS
-INDONESIA WEST 7 H AHEAD OF UTC SUMATRA, JAVA, BALI,
-INDONESIA WEST JAKARTA
-INDONESIA CENTRAL 8 H AHEAD OF UTC KALIMANTAN, SULAWESI
-INDONESIA EAST 9 H AHEAD OF UTC IRIAN, BARAT
-IRAN 3.5H AHEAD OF UTC
-IRAQ 3 H AHEAD OF UTC
-IRAQ 4 H AHEAD OF UTC APR 1 - SEP 30
-IRELAND ON UTC
-IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22
-ISRAEL 2 H AHEAD OF UTC
-ISRAEL 3 H AHEAD OF UTC APR 10 - SEP 3
-ITALY 1 H AHEAD OF UTC
-ITALY 2 H AHEAD OF UTC MAR 27 - SEP 24
-IVORY COAST ON UTC
-JAMAICA 5 H BEHIND UTC
-JAPAN 9 H AHEAD OF UTC
-JOHNSTON ISLAND 10 H BEHIND UTC
-JORDAN 2 H AHEAD OF UTC
-JORDAN 3 H AHEAD OF UTC APR 1 - OCT 6
-KAMPUCHEA 7 H AHEAD OF UTC
-KENYA 3 H AHEAD OF UTC
-KIRIBATI, REP OF 12 H AHEAD OF UTC CANTON, ENDERBURY ISLANDS
-KIRIBATI, REP OF 11 H AHEAD OF UTC CHRISTMAS ISLAND
-KOREA 9 H AHEAD OF UTC
-KOREA, REP OF 9 H AHEAD OF UTC
-KOREA, REP OF 10 H AHEAD OF UTC MAY 8 - OCT 8
-KUWAIT 3 H AHEAD OF UTC
-KUSAIE, PINGELAP 12 H AHEAD OF UTC INCLUDING MARSHALL IS.,
-KUSAIE, PINGELAP EXCLUDING KWAJALEIN)
-KWAJALEIN 12 H BEHIND UTC
-LAOS 7 H AHEAD OF UTC
-LEBANON 2 H AHEAD OF UTC
-LEBANON 3 H AHEAD OF UTC JUN 1 - OCT 31
-LEEWARD ISLANDS 4 H BEHIND UTC ANTIGUA, DOMINICA,
-LEEWARD ISLANDS MONTSERRAT, ST.
-LEEWARD ISLAANDS CHRISTOPHER, ST. KITTS,
-LEEWARD ISLANDS NEVIS, ANGUILLA
-LESOTHO 2 H AHEAD OF UTC
-LIBERIA ON UTC
-LIBYAN ARAB 1 H AHEAD OF UTC JAMAHIRIYA/LIBYA
-LIBYAN ARAB 2 H AHEAD OF UTC APR 1 - SEP 30 JAMAHIRIYA/LIBYA
-LIECHTENSTEIN 1 H AHEAD OF UTC
-LIECHTENSTEIN 2 H AHEAD OF UTC MAR 27 - SEP 24
-LUXEMBOURG 1 H AHEAD OF UTC
-LUXEMBOURG 2 H AHEAD OF UTC MAR 27 - SEP 24
-MACAO 8 H AHEAD OF UTC
-MADAGASCAR 3 H AHEAD OF UTC
-MADEIRA SEE PORTUGAL
-MALAWI 2 H AHEAD OF UTC
-MALAYSIA 8 H AHEAD OF UTC
-MALDIVES 5 H AHEAD OF UTC
-MALI ON UTC
-MALTA 1 H AHEAD OF UTC
-MALTA 2 H AHEAD OF UTC MAR 27 - SEP 24
-MARTINIQUE 4 H BEHIND UTC
-MAURITANIA ON UTC
-MAURITIUS 4 H AHEAD OF UTC
-MARIANA ISLANDS 10 H AHEAD OF UTC EXCLUDING GUAM
-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 PARALLAL APR 3
-MEXICO BAJA CAL N - OCT 29
-MEXICO BAJA CAL N 7 H BEHIND UTC ABOVE 28TH PARALLAL 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
-MIDWAY ISLAND 11 H BEHIND UTC
-MONACO 1 H AHEAD OF UTC
-MONACO 2 H AHEAD OF UTC MAR 27 - SEP 24
-MONGOLIA 8 H AHEAD OF UTC
-MONGOLIA 9 H AHEAD OF UTC MAR 27 - SEP 24
-MONTSERRAT 4 H BEHIND UTC
-MOROCCO ON UTC
-MOZAMBIQUE 2 H AHEAD OF UTC
-NAMIBIA 2 H AHEAD OF UTC
-NAURU, REP OF 12 H AHEAD OF UTC
-NEPAL 5H45M AHEAD OF UTC
-NETHERLANDS 1 H AHEAD OF UTC
-NETHERLANDS 2 H AHEAD OF UTC MAR 27 - SEP 24
-NETHERLANDS 4 H BEHIND UTC ANTILLES AND SOUTHERN ST.
-NETHERLANDS MAARTEN
-NEW CALEDONIA 11 H AHEAD OF UTC
-NEW HEBRIDES SEE VANUATU
-NEW ZEALAND 12 H AHEAD OF UTC (EXCLUDING CHATHAM ISLAND)
-NEW ZEALAND 13 H AHEAD OF UTC OCT 30, '88-MAR 4, '89
-NEW ZEALAND 12H45M AHEAD OF UTC CHATHAM ISLAND
-NICARAGUA 6 H BEHIND UTC
-NIGER 1 H AHEAD OF UTC
-NIGERIA 1 H AHEAD OF UTC
-NIUE ISLAND 11 H BEHIND UTC
-NORFOLK ISLAND 11H30M AHEAD OF UTC
-NORTHERN IRELAND ON UTC WALES, SCOTLAND, N.I.,
-NORTHERN IRELAND CH.IS.
-NORTHERN IRELAND 1 H AHEAD OF UTC MAR 27 - OCT 22
-NORWAY 1 H AHEAD OF UTC
-NORWAY 2 H AHEAD OF UTC MAR 27 - SEP 24
-OMAN 4 H AHEAD OF UTC
-PACIFIC ISLAND T.T.
-PALAU ISLANDS 9 H AHEAD OF UTC
-PAKISTAN 5 H AHEAD OF UTC
-PANAMA 5 H BEHIND UTC
-PAPUA NEW GUINEA 10 H AHEAD OF UTC INCLUDING BOUGAINVILLE
-PAPUA NEW GUINEA ISLAND
-PARAGUAY 4 H BEHIND UTC
-PARAGUAY 3 H BEHIND UTC OCT 1, '88-MAR 31, '89
-PERU 5 H BEHIND UTC
-PHILIPPINES 8 H AHEAD OF UTC
-PONAPE ISLAND 11 H AHEAD OF UTC
-POLAND 1 H AHEAD OF UTC
-POLAND 2 H AHEAD OF UTC MAR 27 - SEP 24
-PORTUGAL MAINLAND ON UTC
-PORTUGAL MAINLAND 1 H AHEAD OF UTC MAR 27 - SEP 24
-PORTUGAL AZORES 1 H BEHIND UTC
-PORTUGAL AZORES ON UTC MAR 27 - SEP 24
-PORTUGAL MADEIRA ON UTC
-PORTUGAL MADEIRA 1 H AHEAD OF UTC MAR 27 - SEP 24
-PUERTO RICO 4 H BEHIND UTC
-QATAR 3 H AHEAD OF UTC
-ROMANIA 2 H AHEAD OF UTC
-ROMANIA 3 H AHEAD OF UTC MAR 27 - SEP 24
-RUSSIA SEE USSR
-RWANDA 2 H AHEAD OF UTC
-SABA 4 H BEHIND UTC ALSO BONAIRE, CURACAO,
-SAMOA 11 H BEHIND UTC
-SAN MARINO 1 H AHEAD OF UTC
-SAN MARINO 2 H AHEAD OF UTC MAR 27 - SEP 24
-SAN SALVADOR 6 H BEHIND UTC
-SAO TOME ISLAND ON UTC AND PRINCIPE ISLAND
-SAUDI ARABIA 3 H AHEAD OF UTC
-SCOTLAND SEE ENGLAND
-SENEGAL ON UTC
-SEYCHELLES 4 H AHEAD OF UTC
-SIERRA LEONE ON UTC
-SINGAPORE 8 H AHEAD OF UTC
-SOLOMON ISLANDS 11 H AHEAD OF UTC EXCLUDING BOUGAINVILLE
-SOLOMON ISLANDS ISLAND
-SOMALI 3 H AHEAD OF UTC
-SOUTH AFRICA 2 H AHEAD OF UTC
-SPAIN CANARY IS ON UTC
-SPAIN CANARY IS 1 H AHEAD OF UTC MAR 27 - SEP 24
-SPAIN 1 H AHEAD OF UTC CONTINENTAL, BALEARIC AND
-SPAIN MALLORCA ISLANDS
-SPAIN 2 H AHEAD OF UTC CONTINENTAL, BALEARIC AND
-SPAIN MALLORCA ISLANDS MAR 27 -
-SPAIN SEP 24
-SPAIN MAINLAND 1 H AHEAD OF UTC MELILLA
-SPAIN MAINLAND 2 H AHEAD OF UTC MAR 27 - SEP 24
-SRI LANKA 5H30M AHEAD OF UTC
-ST. MAARTEN
-ST. KITTS-NEVIS 4 H BEHIND UTC
-ST. LUCIA 4 H BEHIND UTC
-ST. PIERRE 3 H BEHIND UTC INCLUDING MIQUELON
-ST. PIERRE 2 H BEHIND UTC INLCUDING MIQUELON APR 3
-ST. PIERRE - OCT 29
-ST. VINCENT 4 H BEHIND UTC INCLUDING THE GRENADINES
-ST. HELENA ON UTC
-SUDAN 2 H AHEAD OF UTC
-SURINAME 3 H BEHIND UTC
-SWAZILAND 2 H AHEAD OF UTC
-SWEDEN 1 H AHEAD OF UTC
-SWEDEN 2 H AHEAD OF UTC MAR 27 - SEP 24
-SWITZERLAND 1 H AHEAD OF UTC
-SWITZERLAND 2 H AHEAD OF UTC MAR 27 - SEP 24
-SYRIA 2 H AHEAD OF UTC
-SYRIA 3 H AHEAD OF UTC MAR 15 - OCT 30
-TAHITI 10 H BEHIND UTC
-TAIWAN 8 H AHEAD OF UTC
-TANZANIA 3 H AHEAD OF UTC
-THAILAND 7 H AHEAD OF UTC
-TOGO ON UTC
-TRINIDAD / TOBAGO 4 H BEHIND UTC
-TUNISIA 1 H AHEAD OF UTC
-TUNISIA 2 H AHEAD OF UTC APR 10 - SEP 24
-TURKEY 2 H AHEAD OF UTC
-TURKEY 3 H AHEAD OF UTC MAR 27 - SEP 24
-TURKS AND CAICOS 5 H BEHIND UTC
-TURKS AND CAICOS 4 H BEHIND UTC APR 3 - OCT 29
-TUVALU 12 H AHEAD OF UTC
-UGANDA 3 H AHEAD OF UTC
-UNITED ARAB EMIR. 4 H AHEAD OF UTC ABU DHABI, DUBAI, SHARJAH,
-UNITED ARAB EMIR RAS AL KHAIMAH
-UNITED KINGDOM ON UTC WALES, SCOTLAND, N.I., CH.
-UNITED KINGDOM IS.
-UNITED KINGDOM 1 H AHEAD OF UTC MAR 27 - OCT 22
-UNITED STATES SEE USA
-UPPER VOLTA ON UTC
-URUGUAY 3 H BEHIND UTC
-URUGUAY 2 H BEHIND UTC DEC 11, '88-FEB 25, '89
-URAGUAY (ESTIMATED)
-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
-USA FOR SPECIFIC INFO ON USA ZONES/TIMES CALL DOT 202-426-4520
-USSR WEST EUROP 3 H AHEAD OF UTC LENINGRAD, MOSCOW
-USSR WEST EUROP 4 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL EUR 4 H AHEAD OF UTC ROSTOV, BAKU
-USSR CENTRAL EUR 5 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST EUROP 5 H AHEAD OF UTC SVERDLOVSK
-USSR EAST EUROP 6 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST SIBERIAN 6 H AHEAD OF UTC TASHKENT, ALMA ATA
-USSR WEST SIBERIAN 7 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST-CENTRAL 7 H AHEAD OF UTC NOVOSIBIRSK
-USSR WEST-CENTRAL 8 H AHEAD OF UTC APR 1 - SEP 30
-USSR WEST-CENTRAL 8 H AHEAD OF UTC IRKUTSK
-USSR WEST-CENTRAL 9 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL SIB 9 H AHEAD OF UTC YAKUTSK
-USSR CENTRAL SIB 10 H AHEAD OF UTC APR 1 - SEP 30
-USSR CENTRAL SIB 10 H AHEAD OF UTC VLADIVOSTOK
-USSR CENTRAL SIB 11 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 11 H AHEAD OF UTC MAGADAN
-USSR EAST SIBERIA 12 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 12 H AHEAD OF UTC PETROPAVLOVSK
-USSR EAST SIBERIA 13 H AHEAD OF UTC APR 1 - SEP 30
-USSR EAST SIBERIA 13 H AHEAD OF UTC UELEN
-USSR EAST SIBERIA 14 H AHEAD OF UTC APR 1 - SEP 30
-VANUATU 11 H AHEAD OF UTC (NEW HEBRIDES)
-VANUATU 12 H AHEAD OF UTC SEP 25, '88-MAR 25, '89
-VANUATU (ESTIMATED)
-VATICAN 1 H AHEAD OF UTC
-VATICAN 2 H AHEAD OF UTC MAR 27 - SEP 24
-VENEZUELA 4 H BEHIND UTC
-VIETNAM 7 H AHEAD OF UTC
-VIRGIN ISLANDS 4 H BEHIND UTC ST.CROIX, ST.THOMAS,
-VIRGIN ISLANDS ST.JOHN
-WAKE ISLAND 12 H AHEAD OF UTC
-WALES SEE ENGLAND
-WALLIS/FUTUNA IS. 12 H AHEAD OF UTC
-WINDWARD ISLANDS 4 H BEHIND UTC GRENADA, ST. LUCIA
-YEMEN 3 H AHEAD OF UTC BOTH REPUBLICS
-YUGOSLAVIA 1 H AHEAD OF UTC
-YUGOSLAVIA 2 H AHEAD OF UTC MAR 27 - SEP 24
-ZAIRE EAST 1 H AHEAD OF UTC KINSHASA MBANDAKA
-ZAIRE WEST 2 H AHEAD OF UTC LUBUMBASHI, KASAI, KIVU,
-ZAIRE WEST HAUT-ZAIRE, SHABA
-ZAMBIA 2 H AHEAD OF UTC
-ZIMBABWE 2 H AHEAD OF UTC
+++ /dev/null
-#! /bin/sh
-
-: '@(#)yearistype.sh 7.3'
-
-case $#-$2 in
- 2-even) case $1 in
- *[24680]) exit 0 ;;
- *) exit 1 ;;
- esac ;;
- 2-nonpres) case $1 in
- *[02468][048]|*[13567][26]) exit 1 ;;
- *) exit 0 ;;
- esac ;;
- 2-odd) case $1 in
- *[13579]) exit 0 ;;
- *) exit 1 ;;
- esac ;;
- 2-uspres) case $1 in
- *[02468][048]|*[13567][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
-.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 current time,
-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"
-newctime(3), tzfile(5), zic(8)
-.\" @(#)zdump.8 7.2
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)zdump.c 7.12";
-#endif /* !defined NOID */
-#endif /* !defined 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 */
-#include "string.h" /* for strcpy */
-#include "sys/types.h" /* for time_t */
-#include "time.h" /* for struct tm */
-
-#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 */
-
-#ifndef GNUC_or_lint
-#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#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 */
-
-extern char ** environ;
-extern int getopt();
-extern char * optarg;
-extern int optind;
-extern time_t time();
-extern char * tzname[2];
-
-#ifdef USG
-extern void exit();
-extern void perror();
-#endif /* defined USG */
-
-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, c;
- register int vflag;
- register char * cutoff;
- register int cutyear;
- register long cuttime;
- char ** fakeenv;
- time_t now;
- time_t t, newt;
- time_t hibit;
- struct tm tm, newtm;
-
- INITIALIZE(cuttime);
- 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, to;
-
- for (i = 0; environ[i] != NULL; ++i)
- continue;
- fakeenv = (char **) malloc((i + 2) * sizeof *fakeenv);
- if (fakeenv == NULL ||
- (fakeenv[0] = (char *) malloc(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);
- 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
-.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 (2)
-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.
-.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.
-.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
-.if t .ta \w'Link\0\0'u +\w'LINK-FROM\0\0'u
-.if n .ta \w'Link\0\0'u +\w'US/Eastern\0\0'u
-Link LINK-FROM LINK-TO
-.sp
-For example:
-.sp
-.ti +.5i
-Link US/Eastern EST5EDT
-.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/local/etc/zoneinfo standard directory used for created files
-.SH "SEE ALSO"
-newctime(3), tzfile(5), zdump(8)
-.\" @(#)zic.8 7.10
+++ /dev/null
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)zic.c 7.28";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-#include "private.h"
-#include "tzfile.h"
-
-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_todisuniv; /* above is universal time 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 emkdir P((const char * name, int mode));
-extern int getopt P((int argc, char * 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));
-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 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 genericptr_T leftp, const genericptr_T 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));
-
-static int charcnt;
-static int errors;
-static const char * filename;
-static int leapcnt;
-static int linenum;
-static int max_int;
-static time_t max_time;
-static int max_year;
-static int min_int;
-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;
-static int tt_signed;
-
-/*
-** 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 time_t ats[TZ_MAX_TIMES];
-static unsigned char types[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 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) {
- (void) perror(progname);
- (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.
-*/
-
-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
-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, j;
- register int c;
-
-#ifdef unix
- (void) umask(umask(022) | 022);
-#endif /* defined unix */
- progname = argv[0];
- while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF)
- 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) {
- (void) fprintf(stderr, "%s: Can't link from %s to ",
- progname, fromname);
- (void) perror(toname);
- (void) exit(EXIT_FAILURE);
- }
- }
- ifree(fromname);
- ifree(toname);
-}
-
-static void
-setboundaries P((void))
-{
- register time_t bit;
- register int bii;
-
- for (bit = 1; bit > 0; bit <<= 1)
- continue;
- if (bit == 0) { /* time_t is an unsigned type */
- tt_signed = FALSE;
- min_time = 0;
- max_time = ~(time_t) 0;
- if (sflag)
- max_time >>= 1;
- } else {
- tt_signed = TRUE;
- min_time = bit;
- max_time = bit;
- ++max_time;
- max_time = -max_time;
- if (sflag)
- min_time = 0;
- }
- min_year = TM_YEAR_BASE + gmtime(&min_time)->tm_year;
- max_year = TM_YEAR_BASE + gmtime(&max_time)->tm_year;
-
- for (bii = 1; bii > 0; bii <<= 1)
- continue;
- min_int = bii;
- max_int = -1 - bii;
-}
-
-static int
-itsdir(name)
-const char * const name;
-{
- register char * myname;
- register int accres;
-
- myname = ecpyalloc(name);
- myname = ecatalloc(myname, "/.");
- accres = access(myname, 0);
- ifree(myname);
- return accres == 0;
-}
-
-/*
-** Associate sets of rules with zones.
-*/
-
-/*
-** Sort by rule name.
-*/
-
-static int
-rcomp(cp1, cp2)
-const genericptr_T cp1;
-const genericptr_T cp2;
-{
- return strcmp(((struct rule *) cp1)->r_name,
- ((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;
-
- if (nrules != 0)
- (void) qsort((genericptr_T) rules,
- (qsort_size_T) nrules,
- (qsort_size_T) sizeof *rules, rcomp);
- 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) {
- (void) fprintf(stderr, "%s: Can't open ", progname);
- (void) perror(name);
- (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 (ciequal(fields[nfields], "-"))
- 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 ", progname);
- (void) perror(filename);
- (void) exit(EXIT_FAILURE);
- }
- if (fp != stdin && fclose(fp)) {
- (void) fprintf(stderr, "%s: Error closing ", progname);
- (void) perror(filename);
- (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 && !tt_signed) {
- 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_todisuniv = FALSE;
- dp = ecpyalloc(timep);
- if (*dp != '\0') {
- ep = dp + strlen(dp) - 1;
- switch (lowerit(*ep)) {
- case 's': /* Standard */
- rp->r_todisstd = TRUE;
- rp->r_todisuniv = FALSE;
- *ep = '\0';
- break;
- case 'w': /* Wall */
- rp->r_todisstd = FALSE;
- rp->r_todisuniv = FALSE;
- *ep = '\0';
- case 'g': /* Greenwich */
- case 'u': /* Universal */
- case 'z': /* Zulu */
- rp->r_todisstd = TRUE;
- rp->r_todisuniv = TRUE;
- *ep = '\0';
- break;
- }
- }
- rp->r_tod = gethms(dp, "invalid time of day", FALSE);
- ifree(dp);
- /*
- ** Year work.
- */
- cp = loyearp;
- if ((lp = byword(cp, begin_years)) != NULL) switch ((int) lp->l_value) {
- case YR_MINIMUM:
- rp->r_loyear = min_int;
- break;
- case YR_MAXIMUM:
- rp->r_loyear = max_int;
- 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 = min_int;
- break;
- case YR_MAXIMUM:
- rp->r_hiyear = max_int;
- 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((genericptr_T) buf,
- (fwrite_size_T) sizeof buf,
- (fwrite_size_T) 1, fp);
-}
-
-static void
-writezone(name)
-const char * const name;
-{
- register FILE * fp;
- register int i, j;
- static char * fullname;
- static struct tzhead tzh;
-
- fullname = erealloc(fullname,
- (int) (strlen(directory) + 1 + strlen(name) + 1));
- (void) sprintf(fullname, "%s/%s", directory, name);
- if ((fp = fopen(fullname, "wb")) == NULL) {
- if (mkdirs(fullname) != 0)
- (void) exit(EXIT_FAILURE);
- if ((fp = fopen(fullname, "wb")) == NULL) {
- (void) fprintf(stderr, "%s: Can't create ", progname);
- (void) perror(fullname);
- (void) exit(EXIT_FAILURE);
- }
- }
- 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);
- (void) fwrite((genericptr_T) &tzh,
- (fwrite_size_T) sizeof tzh,
- (fwrite_size_T) 1, fp);
- 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((genericptr_T) types,
- (fwrite_size_T) sizeof types[0],
- (fwrite_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((genericptr_T) chars,
- (fwrite_size_T) sizeof chars[0],
- (fwrite_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);
- if (ferror(fp) || fclose(fp)) {
- (void) fprintf(stderr, "%s: Write error on ", progname);
- (void) perror(fullname);
- (void) exit(EXIT_FAILURE);
- }
-}
-
-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 startisdst;
- register int startttisstd;
- register int type;
- char startbuf[BUFSIZ];
-
- INITIALIZE(untiltime);
- INITIALIZE(starttime);
- INITIALIZE(startoff);
- /*
- ** 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;
-#ifdef lint
- starttime = 0;
-#endif /* defined lint */
- 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);
- startisdst = -1;
- if (zp->z_nrules == 0) {
- stdoff = zp->z_stdoff;
- (void) strcpy(startbuf, zp->z_format);
- type = addtype(oadd(zp->z_gmtoff, stdoff),
- startbuf, stdoff != 0, startttisstd);
- if (usestart)
- addtt(starttime, type);
- 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_todisuniv)
- 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;
-#ifdef lint
- ktime = 0;
-#endif /* defined lint */
- 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_todisuniv ? 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;
- if (usestart) {
- if (ktime < starttime) {
- stdoff = rp->r_stdoff;
- startoff = oadd(zp->z_gmtoff,
- rp->r_stdoff);
- (void) sprintf(startbuf, zp->z_format,
- rp->r_abbrvar);
- startisdst = rp->r_stdoff != 0;
- continue;
- }
- usestart = FALSE;
- if (ktime != starttime) {
- if (startisdst < 0 &&
- zp->z_gmtoff !=
- (zp - 1)->z_gmtoff) {
- type = (timecnt == 0) ? 0 :
- types[timecnt - 1];
- startoff = oadd(gmtoffs[type],
- -(zp - 1)->z_gmtoff);
- startisdst = startoff != 0;
- startoff = oadd(startoff,
- zp->z_gmtoff);
- (void) strcpy(startbuf,
- &chars[abbrinds[type]]);
- }
- if (startisdst >= 0)
-addtt(starttime, addtype(startoff, startbuf, startisdst, startttisstd));
- }
- }
- eats(zp->z_filename, zp->z_linenum,
- rp->r_filename, rp->r_linenum);
- (void) sprintf(buf, zp->z_format,
- rp->r_abbrvar);
- offset = oadd(zp->z_gmtoff, rp->r_stdoff);
- type = addtype(offset, buf, rp->r_stdoff != 0,
- rp->r_todisstd);
- addtt(ktime, type);
- stdoff = rp->r_stdoff;
- }
- }
- /*
- ** Now we may get to set starttime for the next zone line.
- */
- if (useuntil) {
- starttime = tadd(zp->z_untiltime, -gmtoff);
- startttisstd = zp->z_untilrule.r_todisstd;
- if (!startttisstd)
- starttime = tadd(starttime, -stdoff);
- }
- }
- writezone(zpfirst->z_name);
-}
-
-static void
-addtt(starttime, type)
-const time_t starttime;
-const int type;
-{
- if (timecnt != 0 && type == types[timecnt - 1])
- return; /* easy enough! */
- if (timecnt == 0 && type == 0 && isdsts[0] == 0)
- return; /* handled by default rule */
- if (timecnt >= TZ_MAX_TIMES) {
- error("too many transitions?!");
- (void) exit(EXIT_FAILURE);
- }
- ats[timecnt] = starttime;
- types[timecnt] = type;
- ++timecnt;
-}
-
-static int
-addtype(gmtoff, abbr, isdst, ttisstd)
-const long gmtoff;
-const char * const abbr;
-const int isdst;
-const int ttisstd;
-{
- register int i, j;
-
- /*
- ** 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])
- 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;
-
- 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)
-const int 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(*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(*cp)));
- if (isascii(*cp) && isspace(*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 == min_int)
- return min_time;
- if (wantedy == max_int)
- 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 && !tt_signed)
- 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
- /*
- ** MS-DOS drive specifier?
- */
- if (strlen(name) == 2 && isascii(name[0]) &&
- isalpha(name[0]) && name[1] == ':') {
- *cp = '/';
- continue;
- }
-#endif /* !defined unix */
- if (!itsdir(name)) {
- /*
- ** It doesn't seem to exist, so we try to create it.
- */
- if (emkdir(name, 0755) != 0) {
- (void) fprintf(stderr,
- "%s: Can't create directory ",
- progname);
- (void) perror(name);
- 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
+--- /usr/include/sys/uio.h~ Sun Jan 24 20:02:24 1993
++++ /usr/include/sys/uio.h Thu Oct 12 12:29:00 1995
+@@ -32,6 +32,7 @@
+
+ /* Structure describing a section of memory. */
+
++#if 0
+ struct iovec
+ {
+ /* Starting address. */
+@@ -39,6 +40,9 @@
+ /* Length in bytes. */
+ size_t iov_len;
+ };
++#else
++#include <linux/uio.h>
++#endif
+
+
+ __BEGIN_DECLS
--- /dev/null
+
+util-linux-2.1.tar.gz (source distribution)
+util-linux-2.1.bin.tar.gz (binary distribution)
+
+ WARNING: THIS COLLECTION DOES *NOT* SUPPORT SHADOW PASSWORDS.
+
+ WARNING: THIS COLLECTION DOES *NOT* SUPPORT SYSTEM V INITTAB.
+
+ WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY!
+
+ WARNING: DO *NOT* INSTALL WITHOUT THINKING.
+
+ WARNING: *READ* the util-linux-2.1.bin.Notes file *BEFORE* and *AFTER*
+ installation: there are a few links you must make by hand.
+
+ This is a collection of many assorted utilities for Linux. Some are
+ system utilities that are not easily available anywhere elsewhere
+ (e.g., mkfs.minix, mkswap); others are BSD ports of common utilities
+ that are not yet contained in any FSF package (e.g., col); others are
+ non-System-V alternatives to common utilities (e.g., simpleinit,
+ agetty, login, passwd).
+
+ The arrangement, as nearly as I can determine, conforms to the Linux
+ Filesystem Structure, Interim Release 1.1, October 9, 1994, with *NO*
+ exceptions. A copy of the standards document can be found at
+ tsx-11.mit.edu:/pub/linux/docs/linux-standards/fsstnd/*.
+
+ Many people provided patches and suggestions. I deeply appreciate
+ this.
+
+
+HIGHLIGHTS for version 2.1:
+
+1) Directory structure rearrange, with configuration support for those who
+ use shadow passwords and System V init (no support is provided for these
+ things, but your utilities won't get overwritten if you do a "make
+ install" after you properly edit MCONFIG).
+2) fdisk and cfdisk should work as expected with 2GB+ disk drives
+3) As usual, lots of stuff was updated and added, including mount, vipw,
+ readprofile
+4) Some stuff was also deleted, and can now be found elsewhere:
+ fsck wrapper: tsx-11.mit.edu:/pub/linux/ALPHA/ext2fs/e2fsprogs*
+ pwd, su: prep.ai.mit.edu:/pub/gnu/sh-utils*
+ ed: prep.ai.mit.edu:/pub/gnu/ed*
+ od: prep.ai.mit.edu:/pub/gnu/textutils*
+ uudecode/uuencode: prep.ai.mit.edu:/pub/gnu/sharutils*
+ bdflush/update: ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/v1.1/bdflush*
+
--- /dev/null
+util-linux: Miscellaneous utilities for Linux
+%n util-linux
+%v 2.1
+%c *
+%l *
+%b *
+%d *
+%f ftp.cs.unc.edu:/pub/users/faith/linux/utils
+%t util-linux-2.1.tar.gz
+%w utils
+%%
+# These lines describe an automated build procedure, please ignore them.
+%setup
+make
+%doc COPYING.GPL COPYING.UCB
+%doc ./time/README.time ./disk-utils/README.cfdisk
+%doc ./disk-utils/README.fdisk ./disk-utils/README.bootutils-0.1
+%doc ./sys-utils/README.setserial ./makedev-1.4.1/README.MAKEDEV-C
+%doc ./misc-utils/README.script ./misc-utils/README.hostname
+%doc ./misc-utils/README.namei ./misc-utils/README.cal
+%doc ./misc-utils/README1.namei ./text-utils/README.col
+%doc ./mount/README.mount ./selection/README.selection
+%doc ./login-utils/README.getty ./login-utils/README.admutil
+%doc ./login-utils/README.poeigl
+%doc util-linux-$VERSION.Announce util-linux-$VERSION.lsm
+cp -a $BUILDDIR/$NAME-$VERSION/example.files /usr/doc/$WHERE/$NAME-$VERSION
+* rm -rf /usr/lib/zoneinfo
+* make install
+%i set -x
+%i /usr/sbin/zic -l US/Eastern
+%i /usr/sbin/zic -p America/New_York
+%i set +x
+%i echo 'WARNING: Check time zone! (If necessary, change with zic).'
+%i echo 'WARNING: Check /etc/rc for initalization of /var/adm/utmp'
+%i echo 'WARNING: /etc/rc should run /sbin/update, *NOT* /sbin/bdflush'
+exit
+# Please ignore the previous lines. . .
+# The informative part of the notes file starts here:
+
+WARNING: THE PROGRAMS IN THIS SUITE DO *NOT* SUPPORT SHADOW PASSWORD FILES!
+
+WARNING: THIS COLLECTION DOES *NOT* SUPPORT SYSTEM V INITTAB.
+
+WARNING: USE GNU TAR -- OTHER TARS WILL FAIL SILENTLY!
+
+WARNING: DO *NOT* INSTALL WITHOUT THINKING.
+
+WARNING: Read the util-linux-2.1.bin.Notes file *BEFORE* and *AFTER*
+ installation: there are a few links you must make by hand.
+
+WARNING: The agetty, simpleinit, login, passwd, and other programs in this
+ package are *NOT* System V compliant. These utilities are meant
+ to be used by people who build their own systems. If you are not
+ a wizard, do *NOT* blindly install these utilities: they could
+ prevent you from logging into your system. Have a boot floppy
+ ready, especially if you don't know what you are doing.
+
+WARNING: The binary distribution was tarred using GNU TAR AND THE -S OPTION!
+ This means that holes will be preserved, but that ONLY GNU TAR
+ WILL WORK ON THE BINARY DISTRIBUTION (in fact, other, inferior,
+ tar programs will fail silently). YOU HAVE BEEN WARNED!
+
+WARNING: localtime and posixtime default to US/Eastern -- change these now.
+
+
+
+To install from the binary distribution:
+
+1) Get binary distribution (see the .lsm file for locations)
+2) cd /
+3) gtar zpxvf util-linux-2.1.bin.tar.gz
+ (or: pms -i util-linux-2.1.bin.tar.gz)
+4) *IF* you want to use agetty and simpleinit, then make softlinks from
+ /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure
+ that your /etc/inittab is set up right (this is *NOT* the System V
+ compatible init!), or you will be hosed.
+5) Run zic -l and/or zic -p to set your timezone. The distribution is set
+ up to use /usr/lib/zoneinfo/US/Eastern as the default. This was
+ installed with "zic -l US/Eastern"
+6) Remove all the old binaries from previous locations.
+
+
+
+To install from source:
+
+1) Get source distribution (see the .lsm file for locations)
+2) Untar util-linux-2.1.tar.gz in /usr/src
+3) cd util-linux-2.1
+4) Edit MCONFIG:
+
+ If you use the shadow password suite and do _not_ want to install
+ programs like login and passwd that do not support shadow passwords,
+ then set HAVE_SHADOW to yes
+
+ If you use the System V init suite and do _not_ want to install programs
+ like agetty, simpleinit, and shutdown, then set HAVE_SYSVINIT to yes
+
+ If you don't like the compile-time options or the directories, then
+ change them. Note that you also can say something like "make OPT=-g
+ LDFLAGS=" in order to make a complete debugging version without editing
+ the MCONFIG at all.
+
+5) make
+6) make install
+7) If you want to use simpleinit and agetty, then make softlinks from
+ /sbin/init to simpleinit and from /sbin/getty to agetty, but make sure
+ that your /etc/inittab is set up right (this is *NOT* the System V
+ compatible init!), or you will be hosed. If you are using the SysV
+ init and/or some other getty, they you can keep using those.
+8) Run zic -l and/or zic -p to set your timezone. The distribution is set
+ up to use /usr/lib/zoneinfo/US/Eastern as the default. This was
+ installed with "zic -l US/Eastern"
+9) Remove all the old binaries from previous locations.
+
+
+
+HIGHLIGHTS for version 2.1:
+
+1) Directory structure rearrange, with configuration support for those who
+ use shadow passwords and System V init (no support is provided for these
+ things, but your utilities won't get overwritten if you do a "make
+ install" after you properly edit MCONFIG).
+2) fdisk and cfdisk should work as expected with 2GB+ disk drives
+3) As usual, lots of stuff was updated and added, including mount, vipw,
+ readprofile
+4) Some stuff was also deleted, and can now be found elsewhere:
+ fsck wrapper: tsx-11.mit.edu:/pub/linux/ALPHA/ext2fs/e2fsprogs*
+ pwd, su: prep.ai.mit.edu:/pub/gnu/sh-utils*
+ ed: prep.ai.mit.edu:/pub/gnu/ed*
+ od: prep.ai.mit.edu:/pub/gnu/textutils*
+ uudecode/uuencode: prep.ai.mit.edu:/pub/gnu/sharutils*
+ bdflush/update: ftp.funet.fi:/pub/OS/Linux/PEOPLE/Linus/v1.1/bdflush*
+
+
+
+PARTIAL HISTORY OF UTIL-LINUX:
+
+bsd:
+ Nothing in this directory gets installed, but some BSD programs need
+ this support:
+ err.c: 8.1 (Berkeley) 6/4/93
+ err.h: 8.1 (Berkeley) 6/2/93
+ getopt.c: 4.13 (Berkeley) 2/23/91
+ pathnames.h: 5.3 (Berkeley) 5/9/89 with extensive modifications for
+ Linux
+
+disk-utils:
+ cfdisk: 0.8 BETA (>2GB) from Kevin E. Martin (martin@cs.unc.edu) with
+ modifications for disks > 2GB.
+ ftp.cs.unc.edu:/pub/users/martin/linux/cfdisk-0.8.tar.gz
+ fdformat: Werner Almesberger (almesber@nessie.cs.id.ethz.ch), with
+ modifications by Marcel Mol (marcel@dutecad.et.tudelft.nl)).
+ Later, updated with a September 1992 version by Werner.
+ fdisk: A. V. Le Blanc (LeBlanc@mcc.ac.uk) fdisk 1.5 release, with
+ patched from Kevin Martin for DOS and OS/2 compatibility (1.5a);
+ Rik Faith (1.5b, 2.0).
+ frag: Werner Almesberger (1.0), Steffen Zahn (1.1), Rob Hooft (1.2),
+ Steffen Zahn (szahn%masterix@emndev.siemens.co.at) (1.3), Michael
+ Bischoff <mbi@mo.math.nat.tu-bs.de> (1.4).
+ fsck.minix, mkfs.minix: Linus Torvalds, with modifications by: Rik
+ Faith (faith@cs.unc.edu), Scott Heavner
+ (sdh@po.cwru.edu), Dr. Wettstein
+ (greg%wind.uucp@plains.nodak.edu), Daniel
+ Quinlan (quinlan@yggdrasil.com).
+ mkswap: Linus Torvalds, with modifications by Mike Jagdis
+ (jaggy@purplet.demon.co.uk. )
+ setfdprm: Werner Almesberger (almesber@nessie.cs.id.ethz.ch)
+ llseek.c: from Remy Card's e2fsprogs-0.5b-WIP.tar.gz
+
+games:
+ banner: (8.3 (Berkeley) 4/2/94)
+ ddate: Druel the Chaotic aka Jeremy Johnson aka mpython@gnu.ai.mit.edu,
+ with modifications by Lee Harvey Oswald Smith, K.S.C.
+
+login-utils:
+ agetty: W. Z. Venema, ported by Peter Orbaek <poe@daimi.aau.dk>.
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ chfn: Salvatore Valente <svalente@athena.mit.edu>
+ chsh: Salvatore Valente <svalente@athena.mit.edu>
+ last: 5.11 w/year (Berkeley) 6/29/88; Port by Michael Haardt with
+ changes by Peter Orbaek.
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ login: 5.40 (Berkeley) 5/9/89; with ports by Michael Glad and Peter Orbaek
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ mesg: Miquel van Smoorenburg (miquels@htsa.aha.nl,
+ miquels@drinkel.nl.mugnet.org). From his sysvinit.tar.Z package.
+ newgrp: Michael Haardt, with modifications by Peter Orbaek.
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ passwd: Peter Orbaek, with yp modifications by Alvaro Martinez
+ Echevarria (alvaro@enano.etsit.upm.es)
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ shutdown: Peter Orbaek, with new modifications by Stephen Tweedie, Rik
+ Faith, and Dave (gentzel@nova.enet.dec.com).
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ simpleinit: Peter Orbaek
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ vipw: 5.16 (Berkeley) 3/3/91, with modifications by Mike Grupenhoff
+ <kashmir@umiacs.UMD.EDU>
+ wall: 5.14 (Berkeley) 3/2/91 [From the BSD NET-2 (4.3bsd-reno)
+ distribution at wuarchive.wustl.edu:/mirrors/4.3-reno]
+
+makedev-1.4:
+ MAKEDEV-C: David A. Holland (dholland@husc.harvard.edu)
+ This version MODIFIED by Rik Faith (faith@cs.unc.edu)
+ sunsite.unc.edu:/pub/Linux/system/Admin/MAKEDEV-C-1.4.tar.gz
+
+
+misc-utils:
+ cal: 8.4 (Berkeley) 4/2/94, with modifications by Rik Faith and
+ Hein@student.tu-clausthal.de (Jochen Hein).
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ clear: Rik Faith
+ domainname: Peter Orbaek
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ dsplit: David Arnstein (arnstein@netcom.com)
+ gatekeeper.dec.com:/pub/usenet/comp.sources.misc/volume40/dsplit
+ getopt (getoptprog): jhunix.hcf.jhu.edu:
+ /pub/public_domain_software/NetBSD/usr/src/usr.bin/getopt
+ hostid: Mitch DSouza (m.dsouza@mrc-apu.cam.ac.uk)
+ ftp.daimi.aau.dk:/pub/linux/poe/poeigl-1.32.tar.gz
+ hostname/dnsdomainname: Peter Tobias <tobias@server.et-inf.fho-emden.de>
+ This version (1.6) should also be available soon in:
+ nic.funet.fi:/pub/OS/Linux/PEOPLE/Linus/net-source/base/NetKit-A*
+ kill: BSD version, modified by Salvatore Valente <svalente@mit.edu>
+ logger: 8.1 (Berkeley) 6/6/93, with modifications by Rik Faith
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ look.c: 8.1 (Berkeley) 6/14/93, with modifications by Rik Faith
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ mcookie: Rik Faith (faith@cs.unc.edu)
+ md5sum: Branki Lankester and Colin Plumb. The MD5 message-digest
+ algorithm is in the Public Domain. This implementation
+ calculates message-digest information only, and can NOT be used
+ for encryption. Therefore it is exportable from the USA.
+ Original sources in the MIT version of PGP 2.6.2.
+ namei: Roger S. Southwick, with modifications by Steve Tell.
+ reset: Rik Faith
+ script: 5.13 (Berkeley) 3/5/91, with modifications by Rick Sladkey
+ (jrs@world.std.com), Harald Koenig
+ (koenig@nova.tat.physik.uni-tuebingen.de).
+ setterm: Gordon Irlam (gordoni@cs.ua.oz.au), with modifications by
+ Peter MacDonald, Mika Liljeberg (liljeber@cs.Helsinki.FI),
+ John Walder (j-walder@uiuc.edu) [for dosemu].
+ tsort: 5.3 (Berkeley) 6/1/90
+ wuarchive.wustl.edu:/mirrors/4.3-reno
+ whereis: 5.5 (Berkeley) 4/18/91
+ wuarchive.wustl.edu:/mirrors/4.3-reno
+ write: 4.22 (Berkeley) 6/1/90, with modifications by Mike Grupenhoff
+ (kashmir@umiacs.umd.edu) .
+ wuarchive.wustl.edu:/mirrors/4.3-reno
+
+mount:
+ mount, umount, swapon
+
+ Rick Sladkey put together the mount-0.99.6.tar.Z package, and Stephen
+ Tweedie provided updates. The utilities were originally from that
+ package (all appear to be by Doug Quale (quale@saavik.cs.wisc.edu),
+ with modifications by H. J. Lu (hlu@eecs.wsu.edu) on 11/25/92; Rick
+ Sladkey (jrs@world.std.com) in January 1993; and Stephen Tweedie
+ <sct@dcs.ed.ac.uk> on 8 October 1993. This distribution mount now
+ supports NFS stuff. I have modified the man pages. I have also added
+ a small patch from Hamish Glen Coleman (t933093@minyos.xx.rmit.OZ.AU)
+ which restores the -o semantics.
+
+ Updated with Rick Sladkey's mount-0.99.14.tar.gz package, and with
+ extra patches from Rick. Adam J. Richter allowed -t option to be
+ optional. Patrick J. Volkerding (volkerdi@mhd1.moorhead.msus.edu) and
+ Mitchum DSouza both provided patches that fixed the (null) problem when
+ not using -t. Mitchum DSouza
+ (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for loop
+ device mounts. Sebastian Lederer
+ (lederer@next-pc.informatik.uni-bonn.de) added support for sending an
+ unmount RPC call to the server when an NFS-filesystem is unmounted.
+ Sander van Malssen (svm@kozmix.hacktic.nl) added support for remounting
+ readonly file systems readonly. Mike Grupenhoff
+ <kashmir@umiacs.UMD.EDU> added a probe of the superblock for the type
+ before /proc/filesystems is checked. Andries.Brouwer@cwi.nl fixed up
+ error reporting.
+
+selection:
+ The complete selection-1.5 package, by Andrew Haylett
+ <ajh@gec-mrc.co.uk>, 17th June 1993, is included. Kernel patches are
+ no longer necessary for modern kernels, but these were tiny so I left
+ them in for historical reasons. The Makefile was modified for this
+ distribution. With changes from Rick Sladkey.
+
+sys-utils:
+ MAKEDEV: Nick Holloway <Nick.Holloway@alfie.demon.co.uk>
+ arch: Rik Faith <faith@cs.unc.edu>
+ chroot: Rick Sladkey <jrs@world.std.com>
+ clock: Originally from the timesrc-1.2.tar.Z package, Charles Hedrick,
+ hedrick@cs.rutgers.edu (V1.0); Rob Hooft, hooft@chem.ruu.nl
+ (V1.1); Harald Koenig (koenig@nova.tat.physik.uni-tuebingen.de)
+ (V1.2). With additional changes: Hamish Coleman
+ (hamish@zot.apana.org.au) (V1.2a); Alan Modra
+ (alan@spri.levels.unisa.edu.au (V1.3, V1.4).
+ ctrlaltdel: Peter Orbaek <poe@daimi.aau.dk>
+ ftp://ftp.daimi.aau.dk/pub/linux/poe/admutil-1.14.tar.gz
+ dmesg: Theodore Ts'o (tytso@athena.mit.edu); Rick Sladkey
+ (jrs@world.std.com)
+ ipcrm: From the ipcdelta.tar.z distribution by krishna
+ balasub@cis.ohio-state.edu on 3/15/93. ipc.info and ipc.texi
+ are also from that distribution.
+ ipcs: Also from the ipcdelta.tar.z distribution by krishna
+ balasub@cis.ohio-state.edu, with patches from Mike Jagdis
+ (jaggy@purplet.demon.co.uk)
+ kbdrate: Rik Faith (faith@cs.unc.edu), with patches from
+ Andries.Brouwer@cwi.nl and John Bowman
+ (bowman@hagar.ph.utexas.edu)
+ lpcntl: Nigel Gamble (nigel@gate.net)
+ rdev: almesber@nessie.cs.id.ethz.ch (Werner Almesberger), with
+ modifications from Peter MacDonald, Stephen Tweedie
+ (sct@dcs.ed.ac.uk), and Dave (gentzel@nova.enet.dec.com)
+ readprofile: Alessandro Rubini
+ renice: 8.1 (Berkeley) 6/9/93
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ setserial: Michael K. Johnson (johnsonm@stolaf.edu) re-released Rick
+ Sladkey's setserial in January 1993, with changes by
+ Theodore Ts'o (tytso@mit.edu). I think that Theodore also
+ did extensive changes for version 2.01, I can't find any
+ notes about this in the documentation. However, Theodore
+ Ts'o (tytso@ATHENA.MIT.EDU) released version 2.10, and that
+ is now included.
+ setsid: Rick Sladkey <jrs@world.std.com>
+ sln: Mike Parker and David MacKenzie (from Linux's libc)
+ sync: Nick Holloway, with thanks to James Bonfield
+ tunelp: Michael K. Johnson (johnsonm@nigel.vnet.net)
+ update_state: Rik Faith (faith@cs.unc.edu)
+
+syslogd:
+ 5.45 (Berkeley) 3/2/91
+
+ Most of the changes for syslogd come from Rick Sladkey
+ (jrs@world.std.com), but I'd like to thank other people who sent in
+ changes (which usually got forwarded to Rick): Carsten Paeth
+ (calle@calle.in-berlin.de) and Kaz Sasayama (kaz@lilia.iijnet.or.jp).
+
+text-utils:
+ col: 5.3 (Berkeley) 2/2/91; with patches from Andries.Brouwer@cwi.nl
+ and Carl Christofferson (cchris@connected.com)
+ wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin}
+ colcrt: 8.1 (Berkeley) 6/6/93 (Bill Joy)
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ colrm: 5.4 (Berkeley) 6/1/90 (Jeff Schriebman)
+ column: 8.3 (Berkeley) 4/2/94
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+ hexdump: 5.5 (Berkeley) 6/1/90
+ wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin}
+ more: 5.19 (Berkeley) 6/29/88 (Eric Shienbrood, Geoff Peck, John Foderaro)
+ rev: 5.2 (Berkeley) 3/21/92; with modifications by Charles Hannum
+ (mycroft@gnu.ai.mit.edu), Brian Koehmstedt (bpk@gnu.ai.mit.edu),
+ bjdouma@xs4all.nl
+ wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin}
+ strings: 5.10 (Berkeley) 5/23/91; with patches from Vitor Duarte
+ <vad@fct.unl.pt>
+ wuarchive.wustl.edu:/mirrors/4.3-reno/{bin,usr.bin}
+ ul: 8.1 (Berkeley) 6/6/93
+ ftp.cdrom.com:/pub/bsd-sources/4.4BSD-Lite/usr/src/usr.bin
+
+time:
+ elsie.nci.nih.gov:/pub/classictzcode.tar.gz
+ elsie.nci.nih.gov:/pub/classictzdata.tar.gz
+ (The zoneinfo database was updated Dec 1994.)
+
+%%
+* bin/arch
+* bin/dmesg
+* bin/dnsdomainname
+* bin/domainname
+* bin/hostname
+* bin/kill
+* bin/login
+* bin/more
+* bin/mount
+* bin/setserial
+* bin/sync
+* bin/umount
+* dev/MAKEDEV
+* dev/MAKEDEV-C
+* etc/DEVINFO
+* etc/MAKEDEV.cfg
+* etc/fdprm
+* sbin/agetty
+* sbin/cfdisk
+* sbin/clock
+* sbin/fastboot
+* sbin/fasthalt
+* sbin/fdisk
+* sbin/fsck.minix
+* sbin/halt
+* sbin/kbdrate
+* sbin/mkfs.minix
+* sbin/mkswap
+* sbin/reboot
+* sbin/shutdown
+* sbin/simpleinit
+* sbin/sln
+* sbin/swapoff
+* sbin/swapon
+* usr/bin/cal
+* usr/bin/chfn
+* usr/bin/chsh
+* usr/bin/clear
+* usr/bin/col
+* usr/bin/colcrt
+* usr/bin/colrm
+* usr/bin/column
+* usr/bin/dsplit
+* usr/bin/fdformat
+* usr/bin/getopt
+* usr/bin/hexdump
+* usr/bin/hostid
+* usr/bin/ipcrm
+* usr/bin/ipcs
+* usr/bin/last
+* usr/bin/logger
+* usr/bin/look
+* usr/bin/lpcntl
+* usr/bin/mcookie
+* usr/bin/md5sum
+* usr/bin/mesg
+* usr/bin/namei
+* usr/bin/newgrp
+* usr/bin/passwd
+* usr/bin/ramsize
+* usr/bin/rdev
+* usr/bin/readprofile
+* usr/bin/renice
+* usr/bin/reset
+* usr/bin/rev
+* usr/bin/rootflags
+* usr/bin/script
+* usr/bin/selection
+* usr/bin/setfdprm
+* usr/bin/setsid
+* usr/bin/setterm
+* usr/bin/strings
+* usr/bin/swapdev
+* usr/bin/tsort
+* usr/bin/tunelp
+* usr/bin/ul
+* usr/bin/vidmode
+* usr/bin/wall
+* usr/bin/whereis
+* usr/bin/write
+* usr/info/ipc.info
+* usr/lib/libz.a
+* usr/lib/more.help
+* usr/lib/zoneinfo
+* usr/man/man1/arch.1
+* usr/man/man1/cal.1
+* usr/man/man1/chfn.1
+* usr/man/man1/chsh.1
+* usr/man/man1/clear.1
+* usr/man/man1/col.1
+* usr/man/man1/colcrt.1
+* usr/man/man1/colrm.1
+* usr/man/man1/column.1
+* usr/man/man1/dnsdomainname.1
+* usr/man/man1/domainname.1
+* usr/man/man1/dsplit.1
+* usr/man/man1/getopt.1
+* usr/man/man1/hexdump.1
+* usr/man/man1/hostid.1
+* usr/man/man1/hostname.1
+* usr/man/man1/kill.1
+* usr/man/man1/last.1
+* usr/man/man1/logger.1
+* usr/man/man1/login.1
+* usr/man/man1/look.1
+* usr/man/man1/md5sum.1
+* usr/man/man1/mesg.1
+* usr/man/man1/more.1
+* usr/man/man1/namei.1
+* usr/man/man1/newgrp.1
+* usr/man/man1/passwd.1
+* usr/man/man1/readprofile.1
+* usr/man/man1/reset.1
+* usr/man/man1/rev.1
+* usr/man/man1/script.1
+* usr/man/man1/selection.1
+* usr/man/man1/setterm.1
+* usr/man/man1/strings.1
+* usr/man/man1/tsort.1
+* usr/man/man1/ul.1
+* usr/man/man1/wall.1
+* usr/man/man1/whereis.1
+* usr/man/man1/write.1
+* usr/man/man3/newctime.3
+* usr/man/man3/newtzset.3
+* usr/man/man5/DEVINFO.5
+* usr/man/man5/MAKEDEV.cfg.5
+* usr/man/man5/fstab.5
+* usr/man/man5/nfs.5
+* usr/man/man5/syslog.conf.5
+* usr/man/man5/tzfile.5
+* usr/man/man6/banner.6
+* usr/man/man6/ddate.6
+* usr/man/man8/MAKEDEV-C.8
+* usr/man/man8/MAKEDEV.8
+* usr/man/man8/agetty.8
+* usr/man/man8/cfdisk.8
+* usr/man/man8/chroot.8
+* usr/man/man8/clock.8
+* usr/man/man8/ctrlaltdel.8
+* usr/man/man8/dmesg.8
+* usr/man/man8/fastboot.8
+* usr/man/man8/fasthalt.8
+* usr/man/man8/fdformat.8
+* usr/man/man8/fdisk.8
+* usr/man/man8/frag.8
+* usr/man/man8/fsck.minix.8
+* usr/man/man8/halt.8
+* usr/man/man8/ipcrm.8
+* usr/man/man8/ipcs.8
+* usr/man/man8/kbdrate.8
+* usr/man/man8/lpcntl.8
+* usr/man/man8/mkfs.minix.8
+* usr/man/man8/mkswap.8
+* usr/man/man8/mount.8
+* usr/man/man8/ramsize.8
+* usr/man/man8/rdev.8
+* usr/man/man8/reboot.8
+* usr/man/man8/renice.8
+* usr/man/man8/rootflags.8
+* usr/man/man8/setfdprm.8
+* usr/man/man8/setserial.8
+* usr/man/man8/setsid.8
+* usr/man/man8/shutdown.8
+* usr/man/man8/simpleinit.8
+* usr/man/man8/swapdev.8
+* usr/man/man8/swapoff.8
+* usr/man/man8/swapon.8
+* usr/man/man8/sync.8
+* usr/man/man8/syslogd.8
+* usr/man/man8/tunelp.8
+* usr/man/man8/umount.8
+* usr/man/man8/update_state.8
+* usr/man/man8/vidmode.8
+* usr/man/man8/vipw.8
+* usr/man/man8/zdump.8
+* usr/man/man8/zic.8
+* usr/sbin/chroot
+* usr/sbin/ctrlaltdel
+* usr/sbin/frag
+* usr/sbin/syslogd
+* usr/sbin/update_state
+* usr/sbin/vipw
+* usr/sbin/zdump
+* usr/sbin/zic
--- /dev/null
+Begin3
+Title: util-linux: Miscellaneous utilities for Linux
+Version: 2.1
+Entered-date: Thu Feb 16 09:23:18 1995
+Description: reboot shutdown simpleinit sln swapoff swapon cal chfn chsh
+ clear col colcrt colrm column dnsdomainname domainname
+ dsplit fdformat getopt hexdump hostid hostname ipcrm ipcs
+ last logger look lpcntl mcookie md5sum mesg namei newgrp
+ passwd ramsize rdev readprofile renice reset rev rootflags
+ script selection setfdprm setsid setterm strings swapdev
+ tsort tunelp ul vidmode wall whereis write chroot
+ ctrlaltdel frag syslogd update_state vipw zdump zic
+Keywords: essential utilities
+Author: several
+Maintained-by: faith@cs.unc.edu (Rik Faith)
+Primary-site: ftp.cs.unc.edu /pub/users/faith/linux
+ 640k util-linux-2.1.tar.gz
+ 570k util-linux-2.1.bin.tar.gz
+Alternate-site: tsx-11.mit.edu /pub/linux/packages/utils
+Alternate-site: sunsite.unc.edu /pub/Linux/system/Misc
+Platforms: Linux 1.1.8x, GNU tar
+Copying-policy: GPL, BSD, others
+End
+++ /dev/null
-README
\ No newline at end of file