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 >
C/C++ Source or Header  |  2002-01-02  |  11KB  |  338 lines

  1. #include stsdef
  2. #include stdio
  3. #include types
  4. #include socket
  5. #include time
  6. #include inet
  7. #include string
  8. #include ctype
  9. #include <sys$library:ucx$inetdef.h>
  10.  
  11. #define OK(x) $VMS_STATUS_SUCCESS(x)
  12.  
  13. int vxc$cmd$getopt(int argc, char *argv[], char *let, long int *val);
  14.  
  15. main(int argc, char *argv[]) {
  16.  
  17. /*
  18. Client process to connect to the daytime service via port 13. The client
  19. process uses the time message received to check (and optionally to set) the
  20. time of the local clock. The comparison assumes that the local clock keeps
  21. time in seconds from 1/1/70 which is the UNIX standard, and it computes the
  22. time difference by converting the received MJD to seconds since 1/1/70 and
  23. adding the received hr, min and sec, also converted to seconds. If the local
  24. machine keeps time in some other way, then the comparison method will have to
  25. change, but the rest should be okay.
  26.  
  27. This software was developed with US Government support and it may not be sold,
  28. restricted or licensed. You may duplicate this program provided that this
  29. notice remains in all of the copies, and you may give it to others provided
  30. they understand and agree to this condition.
  31.  
  32. This program and the time protocol it uses are under development and the
  33. implementation may change without notice.
  34.  
  35. For questions or additional information, contact:
  36.  
  37.     Judah Levine
  38.     Time and Frequency Division
  39.     NIST/847
  40.     325 Broadway
  41.     Boulder, Colorado 80303
  42.     (303) 492 7785
  43.     jlevine@time_a.timefreq.bldrdoc.gov
  44.  
  45. ****
  46. Revised 17-Feb-1994 by Alan Zonderman for VMS using TCP/IP Services for VMS (UCX V2.0D)
  47.  
  48. Requires both OPER (operator) and LOG_IO (logical I/O) privileges to set system
  49. clock under VMS.
  50.  
  51. Although setting clock backwards under VMS may yield strange uptime values,
  52. this routine does not restrict setting an absolute time.
  53.  
  54. Program accepts all of the original flags except that time differences are not
  55. reported by any -m? setting.
  56.  
  57. Command procedure to compile and link:
  58.  
  59.     $ cc    vms_tcp_time_client
  60.     $ link    vms_tcp_time_client, sys$input/opt
  61.     sys$library:ucx$ipc/lib
  62.     sys$share:vaxcrtl.exe/share
  63.  
  64. To synchronize time on all cluster members: Run vms_tcp_time_client, then use
  65. SYSMAN to set cluster time.
  66.  
  67. For example,
  68.  
  69.     $ vms_tcp_time_client == "$user$disk:[time]vms_tcp_time_client"
  70.     $ vms_tcp_time_client
  71.     $ mcr sysman
  72.     config set time
  73.  
  74. The "config set time" without a parameter uses the time on the local node to
  75. set the time on all cluster members.
  76.  
  77. This revision was developed with US Government support and it may not be sold,
  78. restricted or licensed. You may duplicate this program provided that this
  79. notice remains in all of the copies, and you may give it to others provided
  80. they understand and agree to this condition.
  81. */
  82.  
  83. long int address;        /* holds ip address */
  84. int pserv = 13;            /* daytime port number on server */
  85. char *cp;            /* server address in . notation */
  86. struct sockaddr_in sin;        /* socket address structure */
  87. int s;                /* socket number */
  88. int length;            /* size of message */
  89. char buf[132];            /* holds message */
  90. long int mjd;            /* holds parsed received mjd*/
  91. int yr,mo,dy,hr,min,sec;    /* holds parsed received time */
  92. int dst,ls,health;        /* received flags: dst, ls and health */
  93. char cc;
  94. int stat;
  95. char let;            /*command-line letter*/
  96. long int val;            /*command line value*/
  97.  
  98. char        whn$bin[8];
  99. unsigned short    whn$buf[7];
  100. int        ios;
  101.  
  102. /*
  103. The following variables define what this program should do and what output
  104. should be produced. The values below are the defaults which may be changed by
  105. characters on the command line as described below. The effect of each variable
  106. is as follows:
  107.  
  108. Command-Line Switch    effect
  109.     -m0        msg  = 0    Do not produce any messages;
  110.                     only time difference is written to
  111.                     standard output.
  112.  
  113.     -m1 or -M         = 1    Produce short messages.
  114.     -m2             = 2    Produce longer messages.
  115.  
  116.     -s0        set  = 0    Do not adjust local time.
  117.     -s1 or -S         = 1    Adjust local time if server is healthy.
  118.     -s2                 = 2    Adjust local time even if server is 
  119.                     unhealthy.
  120.     -s3             = 3    Ask operator first.
  121.  
  122.     -l#        lto  = 5    Difference between local & UDT (VMS doesn't know about UDT)
  123. */
  124. int msg =2;        /*default is long messages */
  125. int set =1;        /*default is to set clock if server is healthy */
  126. int lto =5;        /*local time offset from UDT (5 for UDT-5 or EST) */
  127. /*
  128.     parse command line 
  129. */
  130.     while( vxc$cmd$getopt(argc,argv,&let,&val) != 0) /*switch is present*/
  131.        {
  132.        switch(let)
  133.           {
  134.           case 'l':
  135.         lto=val;
  136.         break;
  137.           case 'm':
  138.         msg=val;
  139.         break;
  140.           case 's':
  141.         set=val;
  142.         break;
  143.           case 'S':
  144.         set=1;
  145.         break;
  146.           case 'M':
  147.         msg=1;
  148.         break;
  149.           default:
  150.         fprintf(stderr,"\nSwitch %c not recognized.",let);
  151.         break;
  152.        }
  153.        argc--;    /*decrement argument counter */
  154.        argv++;    /*and increment pointer */
  155.     }
  156.  
  157.     printf("\nLocal time offset = %d\n", lto);
  158.  
  159.     cp = "132.163.4.101";    /* internet address of server named time_a.timefreq.bldrdoc.gov */
  160.  
  161.     if    ((address=inet_addr(cp)) == -1) {        /* convert address to internal format */
  162.         fprintf(stderr,"\n Internet address error.");
  163.         exit(1);
  164.         }
  165.  
  166. /*==>    bzero( (char *)&sin,sizeof(sin));*/
  167.  
  168.     sin.sin_addr.s_addr = address;
  169.     sin.sin_family = AF_INET;
  170.     sin.sin_port = htons(pserv);
  171. /*
  172. Create the socket and then connect to the server note that this is a stream
  173. socket and that record boundaries are not preserved.
  174. */
  175.     if    ((s = socket(AF_INET,SOCK_STREAM, 0)) < 0) {
  176.         fprintf(stderr,"\n Socket creation error.");
  177.         exit(1);
  178.         }
  179.  
  180.     if    (connect(s, (struct sockaddr *) &sin, sizeof(sin) ) < 0) {
  181.         perror(" time server Connect failed --");
  182.         exit(1);
  183.         }
  184.  
  185.     length = read(s,buf,80);
  186.     close(s);
  187.  
  188.     if    (length <= 0)  {
  189.         fprintf(stderr,"\n No response from server.");
  190.         exit(1);
  191.         }
  192.  
  193.     buf[length] = '\0';                    /*add terminating null */
  194.  
  195.     sscanf(buf," %ld %2d-%2d-%2d %2d:%2d:%2d %d %d %d", &mjd,&yr,&mo,&dy,&hr,&min,&sec,&dst,&ls,&health);
  196.  
  197. /*
  198. Subtract an hour to the local time offset during daylight savings - but there's
  199. a problem on the days of transition to and from standard time. The DST flag
  200. changes state at 0000 and at 2AM server local time on the day of standard time
  201. transition. Running the program too early relative to the time in Boulder will
  202. set the transition a day late. The simplest solution (for now) is to run the
  203. program late enough in the morning (e.g., after 4AM eastern) so that the clock
  204. is correct when I wake up Sunday morning. If I still lived in Berkeley this
  205. wouldn't be a problem.
  206. */
  207.     if ((dst <= 51) && (dst > 1)) lto--;
  208.  
  209.     whn$buf[0] = 1900 + yr;                    /* change this on 1-Jan-2000 ??? */
  210.     whn$buf[1] = mo;
  211.     whn$buf[2] = dy;
  212.     whn$buf[3] = hr - lto;
  213.     whn$buf[4] = min;
  214.     whn$buf[5] = sec;
  215.     whn$buf[6] = 0;                        /* assume zero milliseconds... */
  216.  
  217. /*
  218. This is definitely an early-hours-just-before-the-dawn program... If the
  219. program is run too late (local time + lto > 24) then the clock will be set
  220. incorrectly (for lto=5, when hr=2359, hr-lto = 1859, but when hr=0000,
  221. hr-lto=-5, an hour setting that will give VMS indigestion -- not to mention
  222. that dy will be one too many). The solution is to ALWAYS run the program
  223. between local AM and noon, or to fix up the hour and the day number when the
  224. program is run later. This is not a simple fix because if the program is run
  225. too late on the last day of the month local time then the day number decrement
  226. will have to know the last day of the previous month. The program will also
  227. have to know about leap years (what if the program is run on Feb 29 at 11PM?).
  228.  
  229. I leave to ambitious VMS programers a general solution to this problem. The
  230. easy way out is to just quit when the time is negative and to run the program
  231. earlier in the day. It's not satisfying, but at least the time will be accurate
  232. when I wake up in the morning.
  233.  
  234. Note that lib$cvt_vectim generates a VMS error message via lib$signal and
  235. aborts when the time is incorrect (e.g., hr<0). */
  236.  
  237.     ios = lib$cvt_vectim(&whn$buf, whn$bin);        /* convert to VMS 64-bit binary time */
  238.  
  239.     if    (OK(ios)) {
  240.  
  241.         if    ((set == 2) ||                /* always set */
  242.             ((set == 1) && (health == 0))) {    /* set if healthy*/
  243.             ios = sys$setime(whn$bin);
  244.  
  245.             if (OK(ios)) {
  246.                 printf("\nTime set\n");
  247.                 }
  248.                 else {
  249.                 lib$signal(ios);
  250.                 }
  251.             }
  252.         }
  253.         else {
  254.         if (whn$buf[3] < 0) printf("\nIt's too late to set the time today, try again after midnight.\n");
  255.         lib$signal(ios);
  256.         }
  257.  
  258.     if    (msg != 0) {
  259.         printf("\n Time message received:");
  260.         printf("\n                        D  L");
  261.         printf("\n MJD  YY MM DD HH MM SS ST S H  Adv.");
  262.         printf("%s\n",buf);
  263.         }
  264.  
  265.     if    (health != 0) printf("\n Server wasn't healthy, check adjustment carefully.");
  266.  
  267.     if    (msg == 2) {                    /*longer messages selected */
  268.  
  269.         if    ((dst == 0)  || (dst > 51)) {
  270.             printf("\nStandard Time now in effect.");
  271.             if (dst > 51) printf("\nChange to Daylight Saving Time in %d days.",dst-51);
  272.             }
  273.  
  274.         if    ((dst <= 51) && (dst > 1)) {
  275.             printf("\nDaylight Saving Time now in effect.");
  276.             if ((dst > 1)  && (dst < 50)) printf("\nChange to Standard Time in %d days.",dst-1);
  277.             }
  278.  
  279.         if    (dst ==  1) printf("\nStandard time began at 2am today.");
  280.         if    (dst == 51) printf("\nDaylight Saving Time began at 2am today.");
  281.         if    (ls  ==  1) printf("\nLeap Second to be added at end of month.");
  282.         if    (ls ==   2) printf("\nSecond to be dropped at end of month.");
  283.         }
  284.  
  285.     exit(0);
  286. }
  287. /*
  288. This subroutine parses switches on the command line. Switches are of the form
  289. -<letter><value>.  If one is found, a pointer to the letter is returned in let 
  290. and a pointer to the value in val as a long integer. 
  291.  
  292. Parameters argc and argv are passed in from the main calling program. Note that
  293. if argc = 1 then only the command is left and the line is empty. If a switch is
  294. decoded, the value of the function is 1 otherwise it is zero.
  295.     
  296. A number following the letter is decoded as a decimal value unless it has a
  297. leading x in which case it is decoded as hexadecimal.
  298.  
  299. This software was developed with US Government support and it may not be sold,
  300. restricted or licensed.  You  may duplicate this program provided that this
  301. notice remains in all of the copies, and you may give it to others provided
  302. they understand and agree to this condition. For questions or additional
  303. information, contact:
  304.  
  305.     Judah Levine
  306.     Time and Frequency Division
  307.     NIST/847
  308.     325 Broadway
  309.     Boulder, Colorado 80303
  310.     (303) 492 7785
  311.     jlevine@time_a.timefreq.bldrdoc.gov
  312. */
  313.  
  314. int vxc$cmd$getopt(int argc, char *argv[], char *let, long int *val) {
  315.  
  316. long int    atol();
  317. int        sscanf();
  318.  
  319. /* either nothing is left or what is left is not a switch */
  320.  
  321. if    ((argc == 1)  ||  (*argv[1] != '-')) {
  322.     *let='\0';
  323.     *val=0;
  324.     return(0);
  325.     }
  326.  
  327. *let= *++argv[1];            /*get the letter after the - character*/
  328.  
  329. if    (*++argv[1] != 'x')        /*if next char is not x, decode number*/
  330.     *val=atol(argv[1]);
  331.     else {
  332.     argv[1]++;            /*skip over x and decode value in hex */
  333.     sscanf(argv[1]," %lx ",val);
  334.     }
  335.  
  336. return(1);
  337. }
  338.