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
/
vms_tcp_time_client.c
< prev
next >
Wrap
C/C++ Source or Header
|
2002-01-02
|
11KB
|
338 lines
#include stsdef
#include stdio
#include types
#include socket
#include time
#include inet
#include string
#include ctype
#include <sys$library:ucx$inetdef.h>
#define OK(x) $VMS_STATUS_SUCCESS(x)
int vxc$cmd$getopt(int argc, char *argv[], char *let, long int *val);
main(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. The comparison assumes that the local clock keeps
time in seconds from 1/1/70 which is the UNIX standard, and it computes the
time difference by converting the received MJD to seconds since 1/1/70 and
adding the received hr, min and sec, also converted to seconds. If the local
machine keeps time in some other way, then the comparison method will have to
change, but the rest should be okay.
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
****
Revised 17-Feb-1994 by Alan Zonderman for VMS using TCP/IP Services for VMS (UCX V2.0D)
Requires both OPER (operator) and LOG_IO (logical I/O) privileges to set system
clock under VMS.
Although setting clock backwards under VMS may yield strange uptime values,
this routine does not restrict setting an absolute time.
Program accepts all of the original flags except that time differences are not
reported by any -m? setting.
Command procedure to compile and link:
$ cc vms_tcp_time_client
$ link vms_tcp_time_client, sys$input/opt
sys$library:ucx$ipc/lib
sys$share:vaxcrtl.exe/share
To synchronize time on all cluster members: Run vms_tcp_time_client, then use
SYSMAN to set cluster time.
For example,
$ vms_tcp_time_client == "$user$disk:[time]vms_tcp_time_client"
$ vms_tcp_time_client
$ mcr sysman
config set time
The "config set time" without a parameter uses the time on the local node to
set the time on all cluster members.
This revision 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.
*/
long int address; /* holds ip address */
int pserv = 13; /* daytime port number on server */
char *cp; /* server address in . notation */
struct sockaddr_in sin; /* socket address structure */
int s; /* socket number */
int length; /* size of message */
char buf[132]; /* holds 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 */
char cc;
int stat;
char let; /*command-line letter*/
long int val; /*command line value*/
char whn$bin[8];
unsigned short whn$buf[7];
int ios;
/*
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.
-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.
-l# lto = 5 Difference between local & UDT (VMS doesn't know about UDT)
*/
int msg =2; /*default is long messages */
int set =1; /*default is to set clock if server is healthy */
int lto =5; /*local time offset from UDT (5 for UDT-5 or EST) */
/*
parse command line
*/
while( vxc$cmd$getopt(argc,argv,&let,&val) != 0) /*switch is present*/
{
switch(let)
{
case 'l':
lto=val;
break;
case 'm':
msg=val;
break;
case 's':
set=val;
break;
case 'S':
set=1;
break;
case 'M':
msg=1;
break;
default:
fprintf(stderr,"\nSwitch %c not recognized.",let);
break;
}
argc--; /*decrement argument counter */
argv++; /*and increment pointer */
}
printf("\nLocal time offset = %d\n", lto);
cp = "132.163.4.101"; /* internet address of server named time_a.timefreq.bldrdoc.gov */
if ((address=inet_addr(cp)) == -1) { /* convert address to internal format */
fprintf(stderr,"\n Internet address error.");
exit(1);
}
/*==> bzero( (char *)&sin,sizeof(sin));*/
sin.sin_addr.s_addr = address;
sin.sin_family = AF_INET;
sin.sin_port = htons(pserv);
/*
Create the socket and then connect to the server note that this is a stream
socket and that record boundaries are not preserved.
*/
if ((s = socket(AF_INET,SOCK_STREAM, 0)) < 0) {
fprintf(stderr,"\n Socket creation error.");
exit(1);
}
if (connect(s, (struct sockaddr *) &sin, sizeof(sin) ) < 0) {
perror(" time server Connect failed --");
exit(1);
}
length = read(s,buf,80);
close(s);
if (length <= 0) {
fprintf(stderr,"\n No response from server.");
exit(1);
}
buf[length] = '\0'; /*add terminating null */
sscanf(buf," %ld %2d-%2d-%2d %2d:%2d:%2d %d %d %d", &mjd,&yr,&mo,&dy,&hr,&min,&sec,&dst,&ls,&health);
/*
Subtract an hour to the local time offset during daylight savings - but there's
a problem on the days of transition to and from standard time. The DST flag
changes state at 0000 and at 2AM server local time on the day of standard time
transition. Running the program too early relative to the time in Boulder will
set the transition a day late. The simplest solution (for now) is to run the
program late enough in the morning (e.g., after 4AM eastern) so that the clock
is correct when I wake up Sunday morning. If I still lived in Berkeley this
wouldn't be a problem.
*/
if ((dst <= 51) && (dst > 1)) lto--;
whn$buf[0] = 1900 + yr; /* change this on 1-Jan-2000 ??? */
whn$buf[1] = mo;
whn$buf[2] = dy;
whn$buf[3] = hr - lto;
whn$buf[4] = min;
whn$buf[5] = sec;
whn$buf[6] = 0; /* assume zero milliseconds... */
/*
This is definitely an early-hours-just-before-the-dawn program... If the
program is run too late (local time + lto > 24) then the clock will be set
incorrectly (for lto=5, when hr=2359, hr-lto = 1859, but when hr=0000,
hr-lto=-5, an hour setting that will give VMS indigestion -- not to mention
that dy will be one too many). The solution is to ALWAYS run the program
between local AM and noon, or to fix up the hour and the day number when the
program is run later. This is not a simple fix because if the program is run
too late on the last day of the month local time then the day number decrement
will have to know the last day of the previous month. The program will also
have to know about leap years (what if the program is run on Feb 29 at 11PM?).
I leave to ambitious VMS programers a general solution to this problem. The
easy way out is to just quit when the time is negative and to run the program
earlier in the day. It's not satisfying, but at least the time will be accurate
when I wake up in the morning.
Note that lib$cvt_vectim generates a VMS error message via lib$signal and
aborts when the time is incorrect (e.g., hr<0). */
ios = lib$cvt_vectim(&whn$buf, whn$bin); /* convert to VMS 64-bit binary time */
if (OK(ios)) {
if ((set == 2) || /* always set */
((set == 1) && (health == 0))) { /* set if healthy*/
ios = sys$setime(whn$bin);
if (OK(ios)) {
printf("\nTime set\n");
}
else {
lib$signal(ios);
}
}
}
else {
if (whn$buf[3] < 0) printf("\nIt's too late to set the time today, try again after midnight.\n");
lib$signal(ios);
}
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);
}
if (health != 0) printf("\n Server wasn't healthy, check adjustment carefully.");
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 <= 51) && (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 began at 2am today.");
if (dst == 51) printf("\nDaylight Saving Time began 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.");
}
exit(0);
}
/*
This subroutine parses switches on the command line. Switches are of the form
-<letter><value>. If one is found, a pointer to the letter is returned in let
and a pointer to the value in val as a long integer.
Parameters argc and argv are passed in from the main calling program. Note that
if argc = 1 then only the command is left and the line is empty. If a switch is
decoded, the value of the function is 1 otherwise it is zero.
A number following the letter is decoded as a decimal value unless it has a
leading x in which case it is decoded as hexadecimal.
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. 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
*/
int vxc$cmd$getopt(int argc, char *argv[], char *let, long int *val) {
long int atol();
int sscanf();
/* either nothing is left or what is left is not a switch */
if ((argc == 1) || (*argv[1] != '-')) {
*let='\0';
*val=0;
return(0);
}
*let= *++argv[1]; /*get the letter after the - character*/
if (*++argv[1] != 'x') /*if next char is not x, decode number*/
*val=atol(argv[1]);
else {
argv[1]++; /*skip over x and decode value in hex */
sscanf(argv[1]," %lx ",val);
}
return(1);
}