[net.sources] Setclock for SysIII and SysV Xenix for IBM PC

buz@ucla-cs.UUCP (02/22/87)

Setclock is a standard Xenix program which allows the super user to
read and set the IBM PC/AT hardware battery-backup clock.  This is
a replacement for the setclock supplied with both the Xenix based
on System III and the one based on System V.  It provides additional
functions.

: 'using /bin/sh'
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	setclock.7t
#	syncclock.mdl
#	:setclock.manpg
#	Makefile
#	setclock.c
# This archive created: Sat Feb 21 20:13:18 1987
export PATH; PATH=/bin:$PATH
echo cshar: extracting "'README'" '(2967 characters)'
if test -f 'README'
then
	echo cshar: over-writing existing file "'README'"
fi
sed 's/^X//' << \SHAR_EOF > 'README'
XSetclock is a standard Xenix program which allows the super user to
Xread and set the IBM PC/AT hardware battery-backup clock.  This is
Xa replacement for the setclock supplied with both the Xenix based
Xon System III and the one based on System V.
X
XThis version of setclock was motivated by three reasons:
X
X1. Unix handles Daylight Savings time automatically.  Yet in Xenix, a Unix
Xclone, one must manually change to Daylight Savings Time.  This setclock
Xinterface requires no manual intervention.
X
X2. All Unix systems released before November 1986 will not know when
XDaylight Savings Time begins because Congress moved the starting time
Xthree or four weeks earlier to the first rather than the last Sunday
Xin April 1987.  This version of setclock produces the right local
Xtime even if ctime fails -- although it does mean that the system will run
Xan hour off GMT for three weeks and say it is standard time when it is really
Xdaylight savings time.  This is the fault of ctime.
X
X3. It would be nice to synchronize the clock more accurately than somewhere
Xwithin a minute.  Therefore this setclock allows waiting until the minute
Xchanges before it returns.  This will synchronize to within about a second.
XIt is not clear to me that setting the time in the hardware clock resets
Xthe seconds on the clock to zero, but that is yet another problem and requires
Xfixing the clock driver.
X
X
XTo install setclock:
X
X    0.  Unpack the shar file.
X
X    1.  Checkout the make file and make appropriate local changes.
X        In particular make sure that the OFF flag is the proper value
X        in hours and fractions of an hour from Greenwich.  See the
X        man page.  It is distributed with a value for US West Coast Time.
X        If your Xenix ctime knows about the new 1987 daylight savings
X        time rules then delete the -DBADDST flag from CFLAGS.
X
X    2.  Run `make'.  This compiles and links the program.
X
X    3.  Go su.  From here on be careful (huh?).
X
X    4.  Run `make save' to save copies of /etc/setclock and /usr/lib/syncclock
X        These will be overwritten by the next step.  Once you have a copy of
X        the distributed system programs, you should not redo this step.
X
X    5.  Run `make install'.  It will copy the new setclock into /etc and
X        the manual page into /usr/man/man7.  It will also create a new
X        shell script and copy it to /usr/lib/syncclock.
X
X    6.  By hand you will have to change /etc/rc so that it uses the
X        proper flags in its call to setclock.   For example on the US
X        West Coast `setclock' should be changed to `setclock -s 8.0'.
X
X    7.  You're done with the installation.
X
XAuthor:        Robert Uzgalis
XOrganization:  Tigertail Associates
X               320 North Bundy Drive
X               Los Angeles, California 90049
X               USA
X
XArpa address:  buz@ucla-cs.arpa
X               buz@locus.ucla.edu
Xuucp address:  ucla-cs!buz
X
XCopyright (C) 1986, 1987 Tigertail Associates, All rights reserved.
SHAR_EOF
if test 2967 -ne "`wc -c 'README'`"
then
	echo cshar: error transmitting "'README'" '(should have been 2967 characters)'
fi
echo cshar: extracting "'setclock.7t'" '(5093 characters)'
if test -f 'setclock.7t'
then
	echo cshar: over-writing existing file "'setclock.7t'"
fi
sed 's/^X//' << \SHAR_EOF > 'setclock.7t'
X'\" t
X.TH SETCLOCK 7T 
X.SH NAME
Xsetclock \- Set or Read the IBM PC/AT clock
X.SH SYNOPSIS
X.B /etc/setclock
XMMddhhmm[yy]
X.br
X.B /etc/setclock
X[\-{u|g|l|s|d}[x] [+\-hh.hh]]
X.br
X.B /usr/lib/syncclock
X.SH DESCRIPTION
XThe first form of
X.I /etc/setclock
Xsets the IBM PC/AT battery hardware clock to the month, day, hour,
Xminute, and year indicated as the argument.
XThis command can only be given by the superuser.
XThe year is defaulted to the current year in the battery hardware clock.
XNote that one usually sets the clock to standard time and keeps it
Xthere, if you are setting the hardware clock in the summer during
Xdaylight savings time remember to subtract an hour before you set
Xthe clock to get standard time.
X.PP
XThe second form of
X.I /etc/setclock
Xreads the IBM PC/AT clock and converts the result to system
Xtime (seconds since Jan 0, 1970 at Greenwich).
XIt then formats this time as local time and prints out a
Xstring that date can use to set the Xenix system time.
XThe time stored in the IBM PC/AT clock is described by the argument flags:
X
X.TS
Xcenter box;
Xl l.
X\-z	Greenwich Mean Time (Zooloo).
X
X\-u	Greenwich Mean Time (Universal).
X
X\-g	Greenwich Mean Time (GMT).
X
X\-s +\-hh.hh	Standard Time +\-hh.hh is time offset
X
X\-d +\-hh.hh	Daylight time +\-hh.hh is time offset
X
X\-l	Local time
X.TE
X
X.PP
XFor the options
X.I -z, -u, -g, -s,
Xand
X.I -d
Xone should never change the IBM PC/AT clock,
X.I /etc/setclock
Xwill adjust for daylight savings time as the need arises.
XNote that
X.I -s
Xand
X.I -d
Xdo exactly the same operation and depend on you to place the
Xright offset following them.
XThe argument flags
X.I -z, -u,
Xand
X.I -g
Xall do the same thing, they set the offset from Greenwich to zero.
X.PP
X.I Setclock
Xwith
X.I -l
Xreturns the current value of the IBM PC/AT clock without any
Xmodification.
XUsing this option one must change the hardware clock,
Xif one wants daylight savings time to be observed.
XOne use of the
X.I -l
Xoption is for people who want to run both DOS and Xenix;
Xone must change the system clock because DOS is brain damaged.
XAnother reason one might want to use
X.I -l
Xis if you are in a location
Xthat never goes on daylight savings time.
XThus used in this peculiar way
X.I setclock
Xwill always produce standard time.
X.PP
XTime offsets are given in hours and fractions the offset 1.5 means
X1 hour and 30 minutes.
XTime offsets are positive for positions west of Greenwich England.
XThus European time will have a negative offset and American times will
Xhave positive ones.
X.PP
XThe exact modifier, the character
X.I x
Xas the second byte of the flag, causes the program to wait until
Xthe minute advances on the AT hardware clock to synchronize
Xthe program's answer to within a second or two of the hardware clock.
XThis means that the system time will be set accurate to about a second.
XIt may also cause the execution of
X.I setclock
Xto take up to a minute.
X.br
X.ne 3.5i
X
XExample time offsets:
X
X.TS
Xcenter box;
Xl n | l n.
XArea	Offset	Area	Offset
X	(hrs)		(hrs)
X_
XEngland	0.0 	West Africa	0.0 
XEurope	-1.0 	Guinea-Bissau	0.75
XSouth Africa	-2.0 	Argentina	3.0
XAfrica	-2.0 	Newfoundland	3.5
XMid-east 	-2.0 	Guyana	3.75
XGreece & Turkey	-2.0 	NA Atlantic	4.0
XEast Africa	-3.0 	NA Eastern	5.0
XArabia	sun-time
XIran 	-3.5	NA Central	6.0
XMoscow	-4.0 	NA Mountain	7.0
XAfghanistan	-4.5 	NA Pacific	8.0
XIndia	-5.5 	NA Alaska	10.0
XChina	-8.0 	Hawaii	10.0
XPerth	-8.0	Pago Pago	11.0
XJapan	-9.0
XAdelaide	-9.5
XSydney	-10.0 
XNew Zealand	-12.0 
XVrangelya	-13.0 
X.TE
X
X.PP
XThis routine is not accessible to normal users, it should never be linked into
XXenix programs or be used in shell scripts, except for ones that need access
Xto the battery backup clock of the IBM PC/AT and run as root.
XThere are plenty of time service routines for normal users see
X.I date(1), ndate(1t), ftime(2), time(3), ctime(3), localtime(3),
Xand
X.I gmtime(3).
X.I Setclock
Xis used by the system initialization script
X.I "( /etc/rc )"
Xto pickup the
Xcurrent time from an external source.
X.PP
XThe shell script
X.I /usr/lib/syncclock
Xis used to resynchronize the Xenix clock with the external battery clock
Xat 1:00am every morning, it is run by root using
X.I cron.
X.I Syncclock
Xuses
X.I setclock
Xto access the hardware clock.
X.I /usr/lib/syncclock
Xcan only be run by root.
X.SH SEE ALSO
X/etc/rc   \-\-  The system initialization shell file which uses
X.I setclock.
X.SH FILES
X/dev/clock \-\- The IBM PC/AT hardware clock.
X.br
X/usr/lib/syncclock   \-\-  The system shell file which synchronizes the clock once a day.
X.SH BUGS
X.br
XThe program defaults to Pacific Standard Time for no reason but lazyness
Xand fault tolerance for the author, who resides there.
X.PP
XThe program correctly uses the new 1987 daylight savings time rules and
Xmoves to daylight savings time on the first Sunday in April, it falls
Xback to standard time the last Sunday in October.  Your Unix system may
Xhowever use the old daylight savings time rules, so for three weeks in
XApril your system may tell you the correct time while incorrectly telling
Xyou that it is standard time (it's not).
X.SH AUTHOR
XR. Uzgalis, Tigertail Associates, 320 North Bundy Drive, Los Angeles, CA
SHAR_EOF
if test 5093 -ne "`wc -c 'setclock.7t'`"
then
	echo cshar: error transmitting "'setclock.7t'" '(should have been 5093 characters)'
fi
echo cshar: extracting "'syncclock.mdl'" '(253 characters)'
if test -f 'syncclock.mdl'
then
	echo cshar: over-writing existing file "'syncclock.mdl'"
fi
sed 's/^X//' << \SHAR_EOF > 'syncclock.mdl'
X:
X#
X#   Due to the granularity of the crystal in the hardware and the 8254 timer,
X#   Xenix runs 1 minute or so slow every few days.   This script synchronises
X#   Xenix with the PC/AT real-time battery-backup clock.
X#
X/bin/date `/etc/setclock -sx OFF`
SHAR_EOF
if test 253 -ne "`wc -c 'syncclock.mdl'`"
then
	echo cshar: error transmitting "'syncclock.mdl'" '(should have been 253 characters)'
fi
chmod +x 'syncclock.mdl'
echo cshar: extracting "':setclock.manpg'" '(7919 characters)'
if test -f ':setclock.manpg'
then
	echo cshar: over-writing existing file "':setclock.manpg'"
fi
sed 's/^X//' << \SHAR_EOF > ':setclock.manpg'
X
X
X
X     SSSSEEEETTTTCCCCLLLLOOOOCCCCKKKK((((7777TTTT))))	     TTTTiiiiggggeeeerrrrttttaaaaiiiillll AAAAssssssssoooocccc....		  SSSSEEEETTTTCCCCLLLLOOOOCCCCKKKK((((7777TTTT))))
X
X
X
X     NNNNAAAAMMMMEEEE
X	  setclock - Set or Read the IBM PC/AT clock
X
X     SSSSYYYYNNNNOOOOPPPPSSSSIIIISSSS
X	  ////eeeettttcccc////sssseeeettttcccclllloooocccckkkk	MMddhhmm[yy]
X	  ////eeeettttcccc////sssseeeettttcccclllloooocccckkkk	[-{u|g|l|s|d}[x] [+-hh.hh]]
X	  ////uuuussssrrrr////lllliiiibbbb////ssssyyyynnnncccccccclllloooocccckkkk
X
X     DDDDEEEESSSSCCCCRRRRIIIIPPPPTTTTIIIIOOOONNNN
X	  The first form of /_e_t_c/_s_e_t_c_l_o_c_k sets the IBM PC/AT battery
X	  hardware clock to the	month, day, hour, minute, and year
X	  indicated as the argument.  This command can only be given
X	  by the superuser.  The year is defaulted to the current year
X	  in the battery hardware clock.  Note that one	usually	sets
X	  the clock to standard	time and keeps it there, if you	are
X	  setting the hardware clock in	the summer during daylight
X	  savings time remember	to subtract an hour before you set the
X	  clock	to get standard	time.
X
X	  The second form of /_e_t_c/_s_e_t_c_l_o_c_k reads the IBM PC/AT clock
X	  and converts the result to system time (seconds since	Jan 0,
X	  1970 at Greenwich).  It then formats this time as local time
X	  and prints out a string that date can	use to set the Xenix
X	  system time.	The time stored	in the IBM PC/AT clock is
X	  described by the argument flags:
X
X	      ___________________________________________________
X	      |-z	    Greenwich Mean Time	(Zooloo).	 |
X	      |							 |
X	      |-u	    Greenwich Mean Time	(Universal).	 |
X	      |							 |
X	      |-g	    Greenwich Mean Time	(GMT).		 |
X	      |							 |
X	      |-s +-hh.hh   Standard Time +-hh.hh is time offset |
X	      |							 |
X	      |-d +-hh.hh   Daylight time +-hh.hh is time offset |
X	      |							 |
X	      _||-_l____________L_o_c_a_l__t_i_m_e____________________________||
X
X
X	  For the options -_z, -_u, -_g, -_s, and -_d one should never
X	  change the IBM PC/AT clock, /_e_t_c/_s_e_t_c_l_o_c_k will adjust	for
X	  daylight savings time	as the need arises.  Note that -_s and
X	  -_d do	exactly	the same operation and depend on you to	place
X	  the right offset following them.  The	argument flags -_z, -_u,
X	  and -_g all do	the same thing,	they set the offset from
X	  Greenwich to zero.
X
X	  _S_e_t_c_l_o_c_k with	-_l returns the current value of	the IBM	PC/AT
X	  clock	without	any modification.  Using this option one must
X	  change the hardware clock, if	one wants daylight savings
X	  time to be observed.	One use	of the -_l option is for	people
X
X
X
X     Page 1					     (printed 2/21/87)
X
X
X
X
X
X
X     SSSSEEEETTTTCCCCLLLLOOOOCCCCKKKK((((7777TTTT))))	     TTTTiiiiggggeeeerrrrttttaaaaiiiillll AAAAssssssssoooocccc....		  SSSSEEEETTTTCCCCLLLLOOOOCCCCKKKK((((7777TTTT))))
X
X
X
X	  who want to run both DOS and Xenix; one must change the
X	  system clock because DOS is brain damaged.  Another reason
X	  one might want to use	-_l is if you are in a location that
X	  never	goes on	daylight savings time.	Thus used in this
X	  peculiar way _s_e_t_c_l_o_c_k	will always produce standard time.
X
X	  Time offsets are given in hours and fractions	the offset 1.5
X	  means	1 hour and 30 minutes.	Time offsets are positive for
X	  positions west of Greenwich England.	Thus European time
X	  will have a negative offset and American times will have
X	  positive ones.
X
X	  The exact modifier, the character _x as the second byte of
X	  the flag, causes the program to wait until the minute
X	  advances on the AT hardware clock to synchronize the
X	  program's answer to within a second or two of	the hardware
X	  clock.  This means that the system time will be set accurate
X	  to about a second.  It may also cause	the execution of
X	  _s_e_t_c_l_o_c_k to take up to a minute.
X
X	  Example time offsets:
X
X	     _____________________________________________________
X	     |Area		 Offset	 | Area		   Offset |
X	     _|___________________(_h_r_s_)_____|_________________(_h_r_s_)___|
X	     |England		   0.0	 | West	Africa	    0.0	  |
X	     |Europe		  -1.0	 | Guinea-Bissau    0.75  |
X	     |South Africa	  -2.0	 | Argentina	    3.0	  |
X	     |Africa		  -2.0	 | Newfoundland	    3.5	  |
X	     |Mid-east		  -2.0	 | Guyana	    3.75  |
X	     |Greece & Turkey	  -2.0	 | NA Atlantic	    4.0	  |
X	     |East Africa	  -3.0	 | NA Eastern	    5.0	  |
X	     |Arabia		sun-time |			  |
X	     |Iran		  -3.5	 | NA Central	    6.0	  |
X	     |Moscow		  -4.0	 | NA Mountain	    7.0	  |
X	     |Afghanistan	  -4.5	 | NA Pacific	    8.0	  |
X	     |India		  -5.5	 | NA Alaska	   10.0	  |
X	     |China		  -8.0	 | Hawaii	   10.0	  |
X	     |Perth		  -8.0	 | Pago	Pago	   11.0	  |
X	     |Japan		  -9.0	 |			  |
X	     |Adelaide		  -9.5	 |			  |
X	     |Sydney		 -10.0	 |			  |
X	     |New Zealand	 -12.0	 |			  |
X	     |Vrangelya		 -13.0	 |			  |
X	     _|____________________________|________________________|
X
X
X	  This routine is not accessible to normal users, it should
X	  never	be linked into Xenix programs or be used in shell
X	  scripts, except for ones that	need access to the battery
X	  backup clock of the IBM PC/AT	and run	as root.  There	are
X	  plenty of time service routines for normal users see
X	  _d_a_t_e(_1), _n_d_a_t_e(_1_t), _f_t_i_m_e(_2),	_t_i_m_e(_3), _c_t_i_m_e(_3),
X
X
X     Page 2					     (printed 2/21/87)
X
X
X
X
X
X
X     SSSSEEEETTTTCCCCLLLLOOOOCCCCKKKK((((7777TTTT))))	     TTTTiiiiggggeeeerrrrttttaaaaiiiillll AAAAssssssssoooocccc....		  SSSSEEEETTTTCCCCLLLLOOOOCCCCKKKK((((7777TTTT))))
X
X
X
X	  _l_o_c_a_l_t_i_m_e(_3),	and _g_m_t_i_m_e(_3). _S_e_t_c_l_o_c_k	is used	by the system
X	  initialization script	( /_e_t_c/_r_c ) to pickup the current time
X	  from an external source.
X
X	  The shell script /_u_s_r/_l_i_b/_s_y_n_c_c_l_o_c_k is used to resynchronize
X	  the Xenix clock with the external battery clock at 1:00am
X	  every	morning, it is run by root using _c_r_o_n. _S_y_n_c_c_l_o_c_k uses
X	  _s_e_t_c_l_o_c_k to access the hardware clock.  /_u_s_r/_l_i_b/_s_y_n_c_c_l_o_c_k
X	  can only be run by root.
X
X     SSSSEEEEEEEE AAAALLLLSSSSOOOO
X	  /etc/rc   --	The system initialization shell	file which
X	  uses _s_e_t_c_l_o_c_k.
X
X     FFFFIIIILLLLEEEESSSS
X	  /dev/clock --	The IBM	PC/AT hardware clock.
X	  /usr/lib/syncclock   --  The system shell file which
X	  synchronizes the clock once a	day.
X
X     BBBBUUUUGGGGSSSS
X	  The program defaults to Pacific Standard Time	for no reason
X	  but lazyness and fault tolerance for the author, who resides
X	  there.
X
X	  The program correctly	uses the new 1987 daylight savings
X	  time rules and moves to daylight savings time	on the first
X	  Sunday in April, it falls back to standard time the last
X	  Sunday in October.  Your Unix	system may however use the old
X	  daylight savings time	rules, so for three weeks in April
X	  your system may tell you the correct time while incorrectly
X	  telling you that it is standard time (it's not).
X
X     AAAAUUUUTTTTHHHHOOOORRRR
X	  R. Uzgalis, Tigertail	Associates, 320	North Bundy Drive, Los
X	  Angeles, CA
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X     Page 3					     (printed 2/21/87)
X
X
X
SHAR_EOF
if test 7919 -ne "`wc -c ':setclock.manpg'`"
then
	echo cshar: error transmitting "':setclock.manpg'" '(should have been 7919 characters)'
fi
echo cshar: extracting "'Makefile'" '(1713 characters)'
if test -f 'Makefile'
then
	echo cshar: over-writing existing file "'Makefile'"
fi
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#                  Makefile for setclock Program 
X#
X#      General Files
X
XMAIN    =	setclock
XSYS     =   XENIX
XMANP    =   $(MAIN).7t
XDOCS    =	README $(MANP) syncclock.mdl
X
X#
X#      General Flags
X
XDEFS    =   -D$(SYS) -DBADDST
XCFLAGS  =	-O -i $(DEFS)
XLDFLAGS = 	-i -lx
XTEXT    =	$(HDRS) $(MAIN).c $(SRCS)
XOFF     =   8.0
X
X#
X#      General Programs
X
XLINT    =	/usr/bin/lint -hp
XPR      =	@print1
XSED     =	sed
XSPELL   =	spell
XTBL     =	tbl
XNROFF   =	nroff
XSHAR    =	cshar -a
XCC      =	/bin/cc
X
X$(MAIN): $(MAIN).o $(OBJS)
X		$(CC) $(LDFLAGS) -o $(MAIN) $(MAIN).o $(OBJS) $(LIBS)
X
X$(OBJS) $(MAIN).o: $(HDRS)
X
Xsave:
X		mv /etc/setclock          /etc/setclock.old
X		cp /etc/setclock.old      /etc/setclock
X		mv /usr/lib/syncclock     /usr/lib/syncclock.old
X		cp /usr/lib/syncclock.old /usr/lib/syncclock
X
Xinstall: setclock
X		cp setclock  /etc/setclock
X		chmod 700    /etc/setclock
X		chown bin    /etc/setclock
X		chgrp bin    /etc/setclock
X		$(SED) "s/OFF/$(OFF)/" syncclock.mdl >syncclock
X		cp syncclock /usr/lib/syncclock
X		chmod 700    /usr/lib/syncclock
X		chown bin    /usr/lib/syncclock
X		chgrp bin    /usr/lib/syncclock
X		if [ -d /usr/man/man7 ]  ; \
X		then \
X			cp $(MANP)   /usr/man/man7  ; \
X			chmod 644    /usr/man/man7/$(MANP)  ; \
X			chown bin    /usr/man/man7/$(MANP)  ; \
X			chgrp bin    /usr/man/man7/$(MANP)  ; \
X			rm -f /usr/man/man7/syncclock.7t ; \
X			ln /usr/man/man7/$(MANP) /usr/man/man7/syncclock.7t  ; \
X			fi
X
Xprint:
X		$(PR) $(TEXT)
X
Xlint:
X		$(LINT) $(MAIN).c $(SRC)
X
Xman:
X		$(TBL) $(MANP) | $(NROFF) -man | col >:$(MAIN).manpg
X
Xspell:
X		$(SPELL) $(DOCS)
X
Xarchive:
X		$(SHAR) $(DOCS) :setclock.manpg Makefile $(TEXT) >setclock.shar
X
Xclean:
X		rm -f *.o core *.out :*
X
X.PRECIOUS: $(TEXT) $(DOCS)
SHAR_EOF
if test 1713 -ne "`wc -c 'Makefile'`"
then
	echo cshar: error transmitting "'Makefile'" '(should have been 1713 characters)'
fi
echo cshar: extracting "'setclock.c'" '(8257 characters)'
if test -f 'setclock.c'
then
	echo cshar: over-writing existing file "'setclock.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'setclock.c'
X/*vi:set tabstops=4 */
X/*
X *                    S E T C L O C K    C O M M A N D 
X *
X *                                Version 2
X *
X *
X *
X *                setclock MMddhhmm[yy]
X *                setclock [-{lds}{x} [offset] | -{zu}[x]]
X *
X *   
X *  The first form of setclock takes a date and time to set the hardware
X *  clock in an IBM PC/AT.  If the year is not specified the current year
X *  in the hardware clock is used.  Alternatively, and more commonly,
X *  setclock takes a flag describing the kind of time stored in the PC/AT
X *  hardware clock and it converts it to something useful to set the 
X *  internal UNIX clock which runs in GMT.  The AT hardware clock returns:
X *                           0216141486
X *                           mmddhhmmyy
X *  If this is not local time then the hours need to be incremented or
X *  decremented depending on daylight savings time and an adjustment to
X *  local time if the clock is running on some other timezone.  This process
X *  asumes that the PC/AT clock runs on one time all year around.  It can be:
X *
X *          flag   Time
X *           u     GMT (universal time)
X *           z     GMT (zooloo)
X *           g     GMT
X *           l     Local Time (hardware changes when going on DST)
X *           d     Daylight Time (hardware always runs on DST)
X *           s     Standard Time (hardware always runs of ST)
X *
X *  For the l, d, and s flags there is an offset argument giving the
X *  number of hours and fractions of an hour from Greewich.  Both d
X *  and s are treated identically so the offset must be set properly
X *  to make them work. An offset should be positive for places west of
X *  Greenwich.  Therefore European offsets will be negative and American
X *  offsets positive.  The default offset is 8.0 h or PST.
X *
X *  If the x modifier is given then the program waits until the minutes change
X *  in the hardware clock before the function returns its value.  This means
X *  that the clock is set within a second or so provided the AT hardware clock
X *  has been set accurate to the second.  It also means that the function may
X *  take up to a minute to return a value.
X *
X *  Added kluge to handle new 1987 DST rules to compensate for local time
X *  not knowing the real time DST goes into effect.  Should be recompiled
X *  when a new local time shows up.  BADDST is the compile time flag.
X *
X *  Author:       Robert Uzgalis
X *  Organization: Tigertail Associates
X *                320 North Bundy Drive
X *                Los Angeles, Califonia 90049
X *                USA
X *
X *  Program Copyright (c) 1986, 1987 Tigertail Associates. All rights reserved.
X *
X */
X
X#include <time.h>
X#include <stdio.h>
X
X#define PROC
X#define then
X#define Bool	int
X#define TRUE	1
X#define FALSE	0
X#define NULLF   ((FILE *) NULL)
X#define RES     250L   /* 1/4 second */
X#define sec_min (long)60
X#define sec_hr  (long)60*60
X#define sec_day (long)60*60*24
X#define sec_yr  (long)60*60*24*365
X
Xlong nap();
Xchar *strcat();
Xstruct tm *localtime();
Xlong time();
X
X
X
X
X
Xlong PROC yrday (m, d, y)
Xint        m, d, y;
X{  static int dtab[] =
X           { /* jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec );
X              *  31,  28,  31,  30,  31,  30,  31,  31,  30,  31,  30,  31 */
X                  0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 365
X           };
X    long days;
X
X    days = dtab[m-1];
X    if (((y+1900)%4)==0 && ((m>2) || (m==2 && d>28)))
X    then days += d;
X    else days += (d - 1);
X
X    return ( days );
X}
X
X
X
XPROC main (argc, argv)
Xint        argc;
Xchar           **argv;
X
X{ int        mo, day, hr, imin, min, yr, rc;
X  float      offset;
X#ifdef BADDST
X  long       dst_beg, sys_dst_beg, aprilfools, first_sun_apr;
X  struct tm *gmtime();
X  Bool       dst;
X#endif
X  long       off, sec_sofar, yrs_sofar, ysec, nld;
X  static char d[30] = " ";
X  static char y[2] = " ";
X  char cr;
X  struct tm *tn;
X  FILE      *fd;
X
X  /*  Pickup AT/PC battery backup clock time */
X
X  fd = fopen ("/dev/clock", "r");
X  if (fd == NULLF)
X  {  fprintf( stderr, "setclock: no access to /dev/clock\n" );
X     exit( -1 ); }
X  fscanf ( fd, "%2d%2d%2d%2d%2d", &mo, &day, &hr, &min, &yr );
X  fclose (fd);
X
X
X
X/*        SET IBM PC/AT HARDWARE CLOCK TIME       */
X
X  if (argc >= 2 && argv[1][0] >= '0' && argv[1][0] <= '9')
X  {    rc = sscanf( argv[1], "%[0-9]%c", d, &cr );
X	   if (rc == 1)
X	   {  if (strlen(d) == 8)
X		  {   sprintf( y, "%2d", yr );
X		      strcat( d, y ); }
X	      if (strlen(d) == 10)
X          {   fd = fopen( "/dev/clock", "w" );
X              if (fd == NULLF)
X              {  fprintf( stderr, "setclock: no write access to /dev/clock\n" );
X                 exit( -1 ); }
X			  fprintf( fd, "%s", d );
X			  fclose (fd);
X			  exit (0); }
X		  }
X	  fprintf ( stderr, "setclock: wrong length for date/time\n" );
X	  fprintf ( stderr, "usage: setclock MMddhhmm[yy]\n" );
X	  exit (1);
X	  }
X
X/*        GET IBM PC/AT HARDWARE TIME TO SET UNIX CLOCK     */
X
X
X  /* Convert PC/AT time to GMT in seconds since 1970 */
X
X  /* If no argument then assume that clock is running on PST */
X
X  offset = 8.0;  /* hours from GMT; default PST */
X
X  /*  Synchronize processing with change in minute */
X
X  if (argc >= 2 && (argv[1][2] == 'x'))
X  {  imin = min;
X     while (min == imin)
X     {  fd = fopen ("/dev/clock", "r");
X	    if (fd == NULLF)
X  	    {  fprintf( stderr, "setclock: error on /dev/clock" );
X   	       exit( -1 ); }
X        fscanf ( fd, "%2d%2d%2d%2d%2d", &mo, &day, &hr, &min, &yr );
X        fclose (fd);
X        nap ( RES );
X	 }                   }
X
X	
X  if (argc >= 2 )
X  switch ( argv[1][1] )
X  { case 'l':   /* Local Time -- assume AT clock changes properly itself */
X                   printf ( "%02d%02d%02d%02d%02d\n", mo, day, hr, min, yr );
X                   exit( 0 );
X
X    case 'd':   /* Daylight time (offset in hours next argument) */
X    case 's':   /* Standard time (offset in hours next argument) */
X                   if (argc >= 2) rc = sscanf ( argv[2], "%f%c", &offset, &cr);
X                   break;
X
X    default:    /* Greenwich Mean Time (GMT) any other character */
X                   offset = 0.0; /* hours from Greenwich */ }
X
X
X  offset     *= sec_hr;
X  off         = (long) offset;
X
X  nld         = (yr - 69) / 4;  /* num of full leap days excluding this year */
X
X  sec_sofar   = yrday(mo,day,yr) * sec_day ;   /* do days this year      */
X  sec_sofar  +=              hr  * sec_hr  ;   /* hours in today         */
X  sec_sofar  +=              min * sec_min ;   /* minutes in today       */
X  ysec        = sec_sofar;
X
X  yrs_sofar   =       (yr - 70)  * sec_yr  ;   /* full years so far      */
X  yrs_sofar  +=             nld  * sec_day ;   /* account for leap days  */
X
X
X  /* Output Local Time corrected for Daylight Savings etc */
X
X#ifdef BADDST
X
X  /* This code is dedicated to the fools in the US Congress who changed when
X   * daylight savings time starts.... when a new correct version of
X   * localtime shows up that takes care of the 1987 rules this code should
X   * go away.
X   */
X
X  sec_sofar     = ysec + yrs_sofar;              /* play date/time as gmt */
X
X  aprilfools    = yrday(4,1,yr) * sec_day;
X
X  tn            = gmtime( &aprilfools );
X  first_sun_apr = aprilfools + ((7L - (tn->tm_wday))%7L) * sec_day;
X
X  dst_beg       = first_sun_apr + 1L * sec_hr;  /* Make it 1am */
X
X  sys_dst_beg   = dst_beg + ((tn->tm_wday==0)?28L:21L) * sec_day + sec_hr; 
X
X  if ( ysec >= dst_beg && ysec < sys_dst_beg )
X  then dst = TRUE;
X
X  if (dst)
X  { sec_sofar += sec_hr;            /* correct for when localtime doesn't work*/
X  	tn         = gmtime( &sec_sofar );
X  	printf ( "%02d%02d%02d%02d%02d\n", tn->tm_mon+1, tn->tm_mday,
X                                       tn->tm_hour, tn->tm_min, tn->tm_year ); }
X  else
X  { sec_sofar += off;               /* correct for timezone     */
X  	tn         = localtime( &sec_sofar );
X  	printf ( "%02d%02d%02d%02d%02d\n", tn->tm_mon+1, tn->tm_mday,
X                                       tn->tm_hour, tn->tm_min, tn->tm_year ); }
X
X#else
X  sec_sofar   = ysec + yrs_sofar + off;   /* correct for timezone     */
X
X  tn = localtime( &sec_sofar );
X  printf ( "%02d%02d%02d%02d%02d\n", tn->tm_mon+1, tn->tm_mday,
X                                     tn->tm_hour, tn->tm_min, tn->tm_year );
X#endif
X
X  return( 0 );
X}
SHAR_EOF
if test 8257 -ne "`wc -c 'setclock.c'`"
then
	echo cshar: error transmitting "'setclock.c'" '(should have been 8257 characters)'
fi
#	End of shell archive
exit 0