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 >
Text File  |  2002-01-02  |  11KB  |  381 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <dos.h>
  6. #include <math.h>
  7. void main(argc,argv)
  8. int argc;
  9. char *argv[];
  10. {
  11. /*
  12.     client process to connect to the daytime service via port 13.
  13.     The client process uses the time message received to check (and
  14.     optionally to set) the time of the local clock.  This version
  15.     is for the MSDOS environment and it uses the DOS and BIOS
  16.     interrupt system to get and set the clock.
  17.  
  18.     This version also uses the WATTCP library of functions to
  19.     interface to an existing packet driver.
  20.  
  21.     This software was developed with US Government support
  22.     and it may not be sold, restricted or licensed.  You
  23.     may duplicate this program provided that this notice
  24.     remains in all of the copies, and you may give it to
  25.     others provided they understand and agree to this
  26.     condition.
  27.  
  28.     This program and the time protocol it uses are under
  29.     development and the implementation may change without
  30.     notice.
  31.  
  32.     For questions or additional information, contact:
  33.  
  34.     Judah Levine
  35.     Time and Frequency Division
  36.     NIST/847
  37.     325 Broadway
  38.     Boulder, Colorado 80303
  39.     (303) 492 7785
  40.     jlevine@time_a.timefreq.bldrdoc.gov
  41. */
  42. #include "tcp.h"
  43. long int address;        /* holds ip address */
  44. int pserv = 13;        /* daytime port number on server */
  45. char *cp = "132.163.4.101";    /* server address in . notation */
  46. tcp_Socket sin;            /* socket address structure */
  47. int length;            /* size of time message */
  48. char buf[132];            /* holds time message */
  49. long int mjd;            /* holds parsed received mjd*/
  50. int yr,mo,dy,hr,min,sec;    /* holds parsed received time */
  51. int dst,ls,health;        /* received flags: dst, ls and health */
  52. long int diff;            /* time difference, local - NIST */
  53. long int diffat;        /* time difference, CMOS - NIST */
  54. double xdiff;            /* floating value of time diff */
  55. char cc;            /* response to set query */
  56. int sw(int, char*[],char *, long int *);            /*parses command-line switches*/
  57. long int cvt2jd(int, int, int);        /*computes MJD from yr-mo-dy */
  58. int unpbcd(int);            /*unpacks bcd from cmos clock */
  59. void adjclk(double, int, int);            /*adjusts local time */
  60. char let;            /*command-line letter*/
  61. long int val;            /*command line value*/
  62. int jlen = 0;            /*index into received message */
  63. int j;
  64. int yribm,moibm,dayibm,hribm,minibm,secibm,hunibm;    /*local time*/
  65. int yrat,moat,dayat,hrat,minat,secat;        /*local CMOS time*/
  66. /*
  67.     the following variables define what this program
  68.     should do and what output should be produced.  The
  69.     values below are the defaults which may be changed
  70.     by characters on the command line as described below.
  71.     The effect of each variable is as follows:
  72.  
  73. Command-Line Switch    effect
  74.     -m0        msg  = 0    Do not produce any messages;
  75.                     only time difference is written to
  76.                     standard output in integer seconds.
  77.  
  78.     -m1 or -M         = 1    Produce short messages.
  79.     -m2             = 2    Produce longer messages.
  80.  
  81.     -s0        set  = 0    Do not adjust local time.
  82.     -s1 or -S         = 1    Adjust local time if server is healthy.
  83.     -s2                 = 2    Adjust local time even if server is
  84.                     unhealthy.
  85.     -s3             = 3    Ask operator first.
  86.  
  87.     -c1 or -C            cmos clock present (default).
  88.  
  89.     -c0                cmos clock not present.
  90.  
  91.     -z<val>        zone = <val>    time zone, as follows:
  92.  
  93.         this switch specifies that the received time message in
  94.         UTC is to be corrected for the time-zone of the user.  If
  95.         the absolute value of <val> is less than 13, it represents
  96.         the time difference between the Universal Time (formerly
  97.         called GMT) and the user's time in hours, where positive
  98.         values mean that the user is West of Greenwich and negative
  99.         values are for locations East of Greenwich.  The US time
  100.         zones are therefore specified by:
  101.  
  102.         -z5        Eastern Time
  103.         -z6        Central Time
  104.         -z7        Mountain Time
  105.         -z8        Pacific Time
  106.             etc.
  107.         Universal Time (GMT) would be specified by:
  108.  
  109.         -z0
  110.  
  111.         and the time in Western Europe by:
  112.  
  113.         -z-1
  114.  
  115.         If the absolute value of <val> is greater than 12, then it
  116.         represents the time difference as above, but the units are
  117.         in minutes rather than hours so that zones whose time does
  118.         not differ by an integral number of hours can be specified
  119.         in this way.  The sign convention is the same as above.
  120.         Thus US Mountain Time could also be specified using:
  121.  
  122.         -z420
  123.  
  124.         If the switch is not present, then US Mountain Time
  125.         is assumed by default.
  126.  
  127.     -d0        ldst=0        Do not correct time difference
  128.                     for Daylight Saving Time.
  129.  
  130.     -d1 or -D    ldst=1        Correct for daylight Saving
  131.                     time using the US transition
  132.                     dates. (default)
  133. */
  134. int msg =1;        /*default is short messages */
  135. int set =3;        /*default is ask before setting clock */
  136. int cmos =1;        /*default is CMOS clock */
  137. int zone = 420;        /*default is Mountain Standard Time */
  138. int ldst = 1;        /*default is daylight saving time enabled*/
  139. /*
  140.     parse command line
  141. */
  142.     while( sw(argc,argv,&let,&val) != 0) /*switch is present*/
  143.         {
  144.         switch(let)
  145.             {
  146.             case 'm':
  147.                 msg= (int) val;
  148.                 break;
  149.             case 's':
  150.                 set= (int) val;
  151.                 break;
  152.             case 'S':
  153.                 set=1;
  154.                 break;
  155.             case 'M':
  156.                 msg=1;
  157.                 break;
  158.             case 'c':
  159.                 cmos= (int) val;
  160.                 break;
  161.             case 'C':
  162.                 cmos=1;
  163.                 break;
  164.             case 'z':        /*read time zone, convert to minutes*/
  165.                 zone= (int) val;
  166.                 if(abs(zone) < 13) zone *= 60;
  167.                 break;
  168.             case 'd':
  169.                 ldst= (int) val;
  170.                 break;
  171.             case 'D':
  172.                 ldst=1;
  173.                 break;
  174.             default:
  175.                 fprintf(stderr,"\nSwitch %c not recognized.",let);
  176.                 break;
  177.        }
  178.        argc--;    /*decrement argument counter */
  179.        argv++;    /*and increment pointer */
  180.     }
  181.     sock_init();        /*initialize Waterloo TCP */
  182. /*
  183.     server is named time_a.timefreq.bldrdoc.gov and has
  184.     an internet address of 132.163.4.101 as defined above.
  185.     Convert this address to internal format.
  186. */
  187.     address=inet_addr(cp);
  188. /*
  189.     open a connection to port pserv on the server
  190.     this open does not use a signal handler
  191. */
  192.     if(tcp_open(&sin,0,address,pserv,NULL) == 0) goto sock_err;
  193. /*
  194.     wait up to 30 seconds for the connection to be
  195.     established. returns to sock_err on a problem.
  196.  
  197.     then wait up to 30 more seconds for the time message
  198.     to be received.  returns to sock_err on a problem.
  199.  
  200.     note that the message is sent via a tcp stream socket
  201.     and in principle it may arrive in more than one piece.
  202.     see if we got the On-Time-Marker at the end of the
  203.     message and loop around to get the rest of the message
  204.     if we did not.  The search for the OTM starts at the
  205.     end of the bit just received since it will likely be
  206.     close to the end.  Note that the OTM is always a *.
  207.  
  208. */
  209.     sock_wait_established(&sin,30,NULL,NULL);
  210. more:            /*wait until more stuff is received */
  211.     sock_wait_input( (void *) &sin,30,NULL,NULL);
  212.     length=sock_fastread( (void *) &sin,(unsigned char *) &buf[jlen],80);
  213.     for(j=jlen+length-1; j >= jlen; j--)
  214.         if(buf[j] == '*') goto gotit;
  215.     jlen += length;
  216.     goto more;        /*another bit of the message is coming*/
  217. gotit:
  218. /*
  219.     get local time as soon as read completes
  220. */
  221.     _AH=0x2c;
  222.     geninterrupt(0x21);
  223.     hribm=_CH;
  224.     minibm=_CL;
  225.     secibm=_DH;
  226.     hunibm=_DL;
  227.     _AH=0x2a;
  228.     geninterrupt(0x21);
  229.     yribm=_CX;
  230.     moibm=_DH;
  231.     dayibm=_DL;
  232. /*
  233.     if a CMOS clock exists, read its time too
  234. */
  235.     if(cmos != 0)
  236.        {
  237.        _AH=2;
  238.        geninterrupt(0x1a);
  239.        hrat=_CH;
  240.         minat=_CL;
  241.        secat=_DH;
  242.        _AH=4;
  243.        geninterrupt(0x1a);
  244.        yrat=_CL;
  245.        moat=_DH;
  246.        dayat=_DL;
  247.     }
  248.     buf[length]= '\0';   /*add terminating null */
  249.     if(msg != 0)
  250.         {
  251.        printf("\n Time message received:");
  252.        printf("\n                        D  L");
  253.        printf("\n MJD  YY MM DD HH MM SS ST S H  Adv.");
  254.        printf("%s\n",buf);
  255.     }
  256.     sock_close(&sin);
  257. /*
  258.     now compute difference between local time and
  259.     received time.
  260. */
  261.     sscanf(buf," %ld %2d-%2d-%2d %2d:%2d:%2d %d %d %d",
  262.         &mjd,&yr,&mo,&dy,&hr,&min,&sec,&dst,&ls,&health);
  263.     if(msg == 2)        /*longer messages selected */
  264.        {
  265.        if( (dst == 0)  || (dst > 51) )
  266.           {
  267.           printf("\nStandard Time now in effect.");
  268.           if(dst > 51)
  269.         printf("\nChange to Daylight Saving Time in %d days.",dst-51);
  270.        }
  271.        if( (dst <= 50) && (dst > 1) )
  272.             {
  273.           printf("\nDaylight Saving Time now in effect.");
  274.           if( (dst > 1)  && (dst < 50) )
  275.         printf("\nChange to Standard Time in %d days.",dst-1);
  276.        }
  277.        if(dst == 1) printf("\nStandard time begins at 2am today.");
  278.        if(dst == 51)printf("\nDaylight Saving Time begins at 2am today.");
  279.        if(ls ==1) printf("\nLeap Second to be added at end of month.");
  280.        if(ls ==2) printf("\nSecond to be dropped at end of month.");
  281.     }
  282. /*
  283.     compute difference local time - NIST time including
  284.     correction for local time as specified by zone.  Note
  285.     that the zone correction is made assuming that standard
  286.     time is in effect.
  287. */
  288.     diff=86400l*(cvt2jd(yribm-1900,moibm,dayibm) - mjd) +
  289.        3600l*(long int)(hribm -hr) +
  290.        60l*(long int)(minibm + zone - min) +
  291.        (long int)(secibm - sec);
  292. /*
  293.     if CMOS clock is present, compute its time difference
  294.     too.  note that CMOS time is received in packed BCD
  295.     mode and must be split apart
  296. */
  297.     if(cmos != 0)
  298.        {
  299.        yrat=unpbcd(yrat);
  300.        moat=unpbcd(moat);
  301.        dayat=unpbcd(dayat);
  302.        hrat=unpbcd(hrat);
  303.        minat=unpbcd(minat);
  304.        secat=unpbcd(secat);
  305.        diffat=86400l*(cvt2jd(yrat,moat,dayat) - mjd) +
  306.           3600l*(long int)(hrat - hr) +
  307.          60l*(long int)(minat + zone - min)  +
  308.          (long int)(secat - sec);
  309.     }
  310.     else diffat = 0;
  311. /*
  312.     now correct both difference for the daylight saving
  313.     time if requested and if it is in effect
  314. */
  315.     if(ldst == 1)        /*dst correction requested */
  316.         {
  317.        if( (dst <= 50) && (dst > 1) )    /*dst solidly on*/
  318.           {
  319.           diff -= 3600l;
  320.           if(cmos == 1) diffat -= 3600l;
  321.        }
  322. /*
  323.     dst=51 means today is transition day in the Spring.
  324.     dst begins at 2 am local standard time.
  325. */
  326.        if( (dst == 51) && ( (60*hr - zone) >= 120) )
  327.           {
  328.             diff -= 3600l;
  329.           if(cmos == 1) diffat -= 3600l;
  330.        }
  331. /*
  332.     dst=1 means today is transition day in the Fall.
  333.     dst ends at 2am local daylight time.  Note that
  334.     the zone parameter is specified using local standard
  335.     time so that the test is for 1 am.
  336. */
  337.        if( (dst == 1) && ( (60*hr - zone) < 60) )
  338.             {
  339.           diff -= 3600l;
  340.           if(cmos == 1) diffat -=3600l;
  341.        }
  342.     }    /* end of daylight saving time corrections */
  343.     xdiff=diff;
  344.     if(hunibm > 50)  diff++;    /*round up integer difference*/
  345.     xdiff += 0.01*(float) hunibm;
  346.     if(msg == 0)        /*no messages except time diff.*/
  347.        printf("%ld",diff);
  348.     else
  349.         printf("\nLocal Clock - NIST = %.2lf second(s).",xdiff);
  350.         if(cmos != 0)
  351.         printf("\n CMOS Clock - NIST = %ld second(s).",diffat);
  352.     if( (diffat == 0) && (fabs(xdiff) < 0.1) )
  353.       {
  354.       if(msg != 0) printf("\n No adjustment is needed.\n");
  355.       exit(0);
  356.     }
  357.     if(set == 0) exit(0);
  358.     if( (health != 0) && (msg != 0) )
  359.         printf("\n Server is not healthy, adjustment not recommended.");
  360.     cc = 'n';    /*default is not to set */
  361.     if(set == 3)    /*action depends on answer to query*/
  362.         {
  363.         printf("\n Do you want to adjust the local clock ? [y/n] ");
  364.         cc=getchar();
  365.     }
  366.     if( (set == 2) ||              /*always set */
  367.          ( (set == 1) && (health == 0) ) ||   /*set if healthy*/
  368.          (cc == 'y') ||             /*set if response yes*/
  369.          (cc == 'Y') )
  370.         {
  371.         adjclk(-xdiff,cmos,ldst);        /*adjust time by xdiff*/
  372.         if(msg != 0) printf("\n Local clock has been set.");
  373.     }
  374.     exit(0);
  375. sock_err:        /* errors result in a jump to here */
  376.     printf("\n Network or socket error \n %s",sockerr(&sin));
  377.     exit(1);
  378. }
  379.  
  380. 
  381.