home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
nisttime.carsoncity.k12.mi.us
/
nisttime.carsoncity.k12.mi.us.tar
/
nisttime.carsoncity.k12.mi.us
/
pub
/
daytime
/
nistimep.c
< prev
next >
Wrap
Text File
|
2002-01-02
|
11KB
|
381 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dos.h>
#include <math.h>
void main(argc,argv)
int argc;
char *argv[];
{
/*
client process to connect to the daytime service via port 13.
The client process uses the time message received to check (and
optionally to set) the time of the local clock. This version
is for the MSDOS environment and it uses the DOS and BIOS
interrupt system to get and set the clock.
This version also uses the WATTCP library of functions to
interface to an existing packet driver.
This software was developed with US Government support
and it may not be sold, restricted or licensed. You
may duplicate this program provided that this notice
remains in all of the copies, and you may give it to
others provided they understand and agree to this
condition.
This program and the time protocol it uses are under
development and the implementation may change without
notice.
For questions or additional information, contact:
Judah Levine
Time and Frequency Division
NIST/847
325 Broadway
Boulder, Colorado 80303
(303) 492 7785
jlevine@time_a.timefreq.bldrdoc.gov
*/
#include "tcp.h"
long int address; /* holds ip address */
int pserv = 13; /* daytime port number on server */
char *cp = "132.163.4.101"; /* server address in . notation */
tcp_Socket sin; /* socket address structure */
int length; /* size of time message */
char buf[132]; /* holds time message */
long int mjd; /* holds parsed received mjd*/
int yr,mo,dy,hr,min,sec; /* holds parsed received time */
int dst,ls,health; /* received flags: dst, ls and health */
long int diff; /* time difference, local - NIST */
long int diffat; /* time difference, CMOS - NIST */
double xdiff; /* floating value of time diff */
char cc; /* response to set query */
int sw(int, char*[],char *, long int *); /*parses command-line switches*/
long int cvt2jd(int, int, int); /*computes MJD from yr-mo-dy */
int unpbcd(int); /*unpacks bcd from cmos clock */
void adjclk(double, int, int); /*adjusts local time */
char let; /*command-line letter*/
long int val; /*command line value*/
int jlen = 0; /*index into received message */
int j;
int yribm,moibm,dayibm,hribm,minibm,secibm,hunibm; /*local time*/
int yrat,moat,dayat,hrat,minat,secat; /*local CMOS time*/
/*
the following variables define what this program
should do and what output should be produced. The
values below are the defaults which may be changed
by characters on the command line as described below.
The effect of each variable is as follows:
Command-Line Switch effect
-m0 msg = 0 Do not produce any messages;
only time difference is written to
standard output in integer seconds.
-m1 or -M = 1 Produce short messages.
-m2 = 2 Produce longer messages.
-s0 set = 0 Do not adjust local time.
-s1 or -S = 1 Adjust local time if server is healthy.
-s2 = 2 Adjust local time even if server is
unhealthy.
-s3 = 3 Ask operator first.
-c1 or -C cmos clock present (default).
-c0 cmos clock not present.
-z<val> zone = <val> time zone, as follows:
this switch specifies that the received time message in
UTC is to be corrected for the time-zone of the user. If
the absolute value of <val> is less than 13, it represents
the time difference between the Universal Time (formerly
called GMT) and the user's time in hours, where positive
values mean that the user is West of Greenwich and negative
values are for locations East of Greenwich. The US time
zones are therefore specified by:
-z5 Eastern Time
-z6 Central Time
-z7 Mountain Time
-z8 Pacific Time
etc.
Universal Time (GMT) would be specified by:
-z0
and the time in Western Europe by:
-z-1
If the absolute value of <val> is greater than 12, then it
represents the time difference as above, but the units are
in minutes rather than hours so that zones whose time does
not differ by an integral number of hours can be specified
in this way. The sign convention is the same as above.
Thus US Mountain Time could also be specified using:
-z420
If the switch is not present, then US Mountain Time
is assumed by default.
-d0 ldst=0 Do not correct time difference
for Daylight Saving Time.
-d1 or -D ldst=1 Correct for daylight Saving
time using the US transition
dates. (default)
*/
int msg =1; /*default is short messages */
int set =3; /*default is ask before setting clock */
int cmos =1; /*default is CMOS clock */
int zone = 420; /*default is Mountain Standard Time */
int ldst = 1; /*default is daylight saving time enabled*/
/*
parse command line
*/
while( sw(argc,argv,&let,&val) != 0) /*switch is present*/
{
switch(let)
{
case 'm':
msg= (int) val;
break;
case 's':
set= (int) val;
break;
case 'S':
set=1;
break;
case 'M':
msg=1;
break;
case 'c':
cmos= (int) val;
break;
case 'C':
cmos=1;
break;
case 'z': /*read time zone, convert to minutes*/
zone= (int) val;
if(abs(zone) < 13) zone *= 60;
break;
case 'd':
ldst= (int) val;
break;
case 'D':
ldst=1;
break;
default:
fprintf(stderr,"\nSwitch %c not recognized.",let);
break;
}
argc--; /*decrement argument counter */
argv++; /*and increment pointer */
}
sock_init(); /*initialize Waterloo TCP */
/*
server is named time_a.timefreq.bldrdoc.gov and has
an internet address of 132.163.4.101 as defined above.
Convert this address to internal format.
*/
address=inet_addr(cp);
/*
open a connection to port pserv on the server
this open does not use a signal handler
*/
if(tcp_open(&sin,0,address,pserv,NULL) == 0) goto sock_err;
/*
wait up to 30 seconds for the connection to be
established. returns to sock_err on a problem.
then wait up to 30 more seconds for the time message
to be received. returns to sock_err on a problem.
note that the message is sent via a tcp stream socket
and in principle it may arrive in more than one piece.
see if we got the On-Time-Marker at the end of the
message and loop around to get the rest of the message
if we did not. The search for the OTM starts at the
end of the bit just received since it will likely be
close to the end. Note that the OTM is always a *.
*/
sock_wait_established(&sin,30,NULL,NULL);
more: /*wait until more stuff is received */
sock_wait_input( (void *) &sin,30,NULL,NULL);
length=sock_fastread( (void *) &sin,(unsigned char *) &buf[jlen],80);
for(j=jlen+length-1; j >= jlen; j--)
if(buf[j] == '*') goto gotit;
jlen += length;
goto more; /*another bit of the message is coming*/
gotit:
/*
get local time as soon as read completes
*/
_AH=0x2c;
geninterrupt(0x21);
hribm=_CH;
minibm=_CL;
secibm=_DH;
hunibm=_DL;
_AH=0x2a;
geninterrupt(0x21);
yribm=_CX;
moibm=_DH;
dayibm=_DL;
/*
if a CMOS clock exists, read its time too
*/
if(cmos != 0)
{
_AH=2;
geninterrupt(0x1a);
hrat=_CH;
minat=_CL;
secat=_DH;
_AH=4;
geninterrupt(0x1a);
yrat=_CL;
moat=_DH;
dayat=_DL;
}
buf[length]= '\0'; /*add terminating null */
if(msg != 0)
{
printf("\n Time message received:");
printf("\n D L");
printf("\n MJD YY MM DD HH MM SS ST S H Adv.");
printf("%s\n",buf);
}
sock_close(&sin);
/*
now compute difference between local time and
received time.
*/
sscanf(buf," %ld %2d-%2d-%2d %2d:%2d:%2d %d %d %d",
&mjd,&yr,&mo,&dy,&hr,&min,&sec,&dst,&ls,&health);
if(msg == 2) /*longer messages selected */
{
if( (dst == 0) || (dst > 51) )
{
printf("\nStandard Time now in effect.");
if(dst > 51)
printf("\nChange to Daylight Saving Time in %d days.",dst-51);
}
if( (dst <= 50) && (dst > 1) )
{
printf("\nDaylight Saving Time now in effect.");
if( (dst > 1) && (dst < 50) )
printf("\nChange to Standard Time in %d days.",dst-1);
}
if(dst == 1) printf("\nStandard time begins at 2am today.");
if(dst == 51)printf("\nDaylight Saving Time begins at 2am today.");
if(ls ==1) printf("\nLeap Second to be added at end of month.");
if(ls ==2) printf("\nSecond to be dropped at end of month.");
}
/*
compute difference local time - NIST time including
correction for local time as specified by zone. Note
that the zone correction is made assuming that standard
time is in effect.
*/
diff=86400l*(cvt2jd(yribm-1900,moibm,dayibm) - mjd) +
3600l*(long int)(hribm -hr) +
60l*(long int)(minibm + zone - min) +
(long int)(secibm - sec);
/*
if CMOS clock is present, compute its time difference
too. note that CMOS time is received in packed BCD
mode and must be split apart
*/
if(cmos != 0)
{
yrat=unpbcd(yrat);
moat=unpbcd(moat);
dayat=unpbcd(dayat);
hrat=unpbcd(hrat);
minat=unpbcd(minat);
secat=unpbcd(secat);
diffat=86400l*(cvt2jd(yrat,moat,dayat) - mjd) +
3600l*(long int)(hrat - hr) +
60l*(long int)(minat + zone - min) +
(long int)(secat - sec);
}
else diffat = 0;
/*
now correct both difference for the daylight saving
time if requested and if it is in effect
*/
if(ldst == 1) /*dst correction requested */
{
if( (dst <= 50) && (dst > 1) ) /*dst solidly on*/
{
diff -= 3600l;
if(cmos == 1) diffat -= 3600l;
}
/*
dst=51 means today is transition day in the Spring.
dst begins at 2 am local standard time.
*/
if( (dst == 51) && ( (60*hr - zone) >= 120) )
{
diff -= 3600l;
if(cmos == 1) diffat -= 3600l;
}
/*
dst=1 means today is transition day in the Fall.
dst ends at 2am local daylight time. Note that
the zone parameter is specified using local standard
time so that the test is for 1 am.
*/
if( (dst == 1) && ( (60*hr - zone) < 60) )
{
diff -= 3600l;
if(cmos == 1) diffat -=3600l;
}
} /* end of daylight saving time corrections */
xdiff=diff;
if(hunibm > 50) diff++; /*round up integer difference*/
xdiff += 0.01*(float) hunibm;
if(msg == 0) /*no messages except time diff.*/
printf("%ld",diff);
else
printf("\nLocal Clock - NIST = %.2lf second(s).",xdiff);
if(cmos != 0)
printf("\n CMOS Clock - NIST = %ld second(s).",diffat);
if( (diffat == 0) && (fabs(xdiff) < 0.1) )
{
if(msg != 0) printf("\n No adjustment is needed.\n");
exit(0);
}
if(set == 0) exit(0);
if( (health != 0) && (msg != 0) )
printf("\n Server is not healthy, adjustment not recommended.");
cc = 'n'; /*default is not to set */
if(set == 3) /*action depends on answer to query*/
{
printf("\n Do you want to adjust the local clock ? [y/n] ");
cc=getchar();
}
if( (set == 2) || /*always set */
( (set == 1) && (health == 0) ) || /*set if healthy*/
(cc == 'y') || /*set if response yes*/
(cc == 'Y') )
{
adjclk(-xdiff,cmos,ldst); /*adjust time by xdiff*/
if(msg != 0) printf("\n Local clock has been set.");
}
exit(0);
sock_err: /* errors result in a jump to here */
printf("\n Network or socket error \n %s",sockerr(&sin));
exit(1);
}