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 / nistimen.c < prev    next >
C/C++ Source or Header  |  2002-01-02  |  9KB  |  342 lines

  1. #include <4bsddefs.h>
  2. #include <stdio.h>
  3. #include <sys/socket.h>
  4. #include <sys/time.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include <errno.h>
  10. #include <dos.h>
  11. void main(argc,argv)
  12. int argc;
  13. char *argv[];
  14. {
  15. /*
  16.     client process to connect to  the daytime service via port 13.
  17.     The client process uses the time message received to check (and
  18.     optionally to set) the time of the local clock.  the comparison 
  19.     assumes that the local clock keeps time in seconds from 1/1/70 
  20.     which is the UNIX standard, and it computes the time difference 
  21.     by converting the received MJD to seconds since 1/1/70 and adding 
  22.     the received hr, min and sec, also converted to seconds.  If the
  23.     local machine keeps time in some other way, then the comparison
  24.     method will have to change, but the rest should be okay.
  25.  
  26.     This software was developed with US Government support
  27.     and it may not be sold, restricted or licensed.  You 
  28.     may duplicate this program provided that this notice
  29.     remains in all of the copies, and you may give it to
  30.     others provided they understand and agree to this
  31.     condition.
  32.  
  33.     This program and the time protocol it uses are under 
  34.     development and the implementation may change without 
  35.     notice.
  36.  
  37.     For questions or additional information, contact:
  38.  
  39.     Judah Levine
  40.     Time and Frequency Division
  41.     NIST/847
  42.     325 Broadway
  43.     Boulder, Colorado 80303
  44.     (303) 492 7785
  45.     jlevine@boulder.nist.gov
  46. */
  47. long int address;        /* holds ip address */
  48. int pserv = 13;        /* daytime port number on server */
  49. char *cp;            /* server address in . notation */
  50. struct sockaddr_in sin;        /* socket address structure */
  51. int s;                /* socket number */
  52. int length;            /* size of message */
  53. char buf[132];            /* holds message */
  54. long int mjd0 = 40587l;        /* MJD of 1/1/70 = origin of UNIX time system*/
  55. struct timeval tvv,tgg;        /* holds local time */
  56. struct timezone tzp;        /* holds local time zone information*/
  57. long int mjd;            /* holds parsed received mjd*/
  58. int yr,mo,dy,hr,min,sec;    /* holds parsed received time */
  59. int dst,ls,health;        /* received flags: dst, ls and health */
  60. long int diff;            /* time difference, local - NIST */
  61. char cc;
  62. int stat;
  63. int isw();            /*parses command-line switches*/
  64. char let;            /*command-line letter*/
  65. long int val;            /*command line value*/
  66. int hrat,minat,secat;        /*cmos time */
  67. int yrat,moat,dayat;        /*cmos date */
  68. int hribm,minibm,secibm;    /*memory time */
  69. int yribm,moibm,dayibm;        /*memory date */
  70. long int diffat;        /*cmos clock difference */
  71. int unpbcd();            /*unpacks BCD time from cmos clock*/
  72. long int cvt2jd();        /*converts yr-mo-day to mjd */
  73. void adjtime();            /*adjusts time on local system*/
  74. /*
  75.     the following variables define what this program
  76.     should do and what output should be produced.  The
  77.     values below are the defaults which may be changed
  78.     by characters on the command line as described below.
  79.     The effect of each variable is as follows:
  80.  
  81. Command-Line Switch    effect
  82.     -m0        msg  = 0    Do not produce any messages;
  83.                     only time difference is written to
  84.                     standard output.
  85.  
  86.     -m1 or -M         = 1    Produce short messages.
  87.     -m2             = 2    Produce longer messages.
  88.  
  89.     -s0        set  = 0    Do not adjust local time.
  90.     -s1 or -S         = 1    Adjust local time if server is healthy.
  91.     -s2                 = 2    Adjust local time even if server is 
  92.                     unhealthy.
  93.     -s3             = 3    Ask operator first.
  94.  
  95.     -c or -C            cmos clock present
  96. */
  97. int msg =1;        /*default is short messages */
  98. int set =3;        /*default is ask before setting clock */
  99. int cmos = 0;        /*default is no CMOS clock */
  100. /*
  101.     parse command line 
  102. */
  103.     while( sw(argc,argv,&let,&val) != 0) /*switch is present*/
  104.        {
  105.        switch(let)
  106.           {
  107.           case 'm':
  108.         msg=val;
  109.         break;
  110.           case 's':
  111.         set=val;
  112.         break;
  113.           case 'S':
  114.         set=1;
  115.         break;
  116.           case 'M':
  117.         msg=1;
  118.         break;
  119.           case 'c':
  120.           case 'C':
  121.          cmos=1;
  122.          break;
  123.           default:
  124.         fprintf(stderr,"\nSwitch %c not recognized.",let);
  125.         break;
  126.        }
  127.        argc--;    /*decrement argument counter */
  128.        argv++;    /*and increment pointer */
  129.     }
  130. /*
  131.     internet address of server named time_a.timefreq.bldrdoc.gov
  132. */
  133.     cp="132.163.4.101";
  134. /*
  135.     convert address to internal format
  136. */
  137.     if( (address=inet_addr(cp) ) == -1)
  138.        {
  139.        fprintf(stderr,"\n Internet address error.");
  140.        exit(1);
  141.     }
  142.     bzero( (char *)&sin,sizeof(sin));
  143.     sin.sin_addr.s_addr=address;
  144.     sin.sin_family=AF_INET;
  145.     sin.sin_port=htons(pserv);
  146. /*
  147.     create the socket and then connect to the server
  148.     note that this is a stream socket and that record
  149.     boundaries are not preserved.
  150. */
  151.     if( (s=socket(AF_INET,SOCK_STREAM,0) ) < 0)
  152.        {
  153.        fprintf(stderr,"\n Socket creation error.");
  154.        exit(1);
  155.     }
  156.     if(connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0)
  157.        {
  158.        perror(" time server Connect failed --");
  159.        exit(1);
  160.     }
  161.     length=read(s,buf,80);
  162.     gettimeofday(&tvv,&tzp);    /*get time as soon as read completes*/
  163.     if(cmos != 0)
  164.        {
  165.        _AH=0x2c;
  166.        geninterrupt(0x21);        /*get memory clock time*/
  167.        hribm=_CH;
  168.        minibm=_CL;
  169.        secibm=_DH;
  170.        _AH=0x2a;
  171.        geninterrupt(0x21);
  172.        yribm=_CX;
  173.        moibm=_DH;
  174.        dayibm=_DL;
  175.        yribm -= 1900;
  176.        _AH=2;
  177.        geninterrupt(0x1a);        /*get cmos time*/
  178.        hrat=_CH;
  179.        minat=_CL;
  180.        secat=_DH;
  181.        _AH=4;
  182.        geninterrupt(0x1a);        /*and cmos date*/
  183.        yrat=_CL;
  184.        moat=_DH;
  185.        dayat=_DL;
  186.        yrat=unpbcd(yrat);
  187.        moat=unpbcd(moat);
  188.        dayat=unpbcd(dayat);
  189.        hrat=unpbcd(hrat);
  190.        minat=unpbcd(minat);
  191.        secat=unpbcd(secat);
  192.     }
  193.     if(length <= 0)
  194.        {
  195.        fprintf(stderr,"\n No response from server.");
  196.        close(s);
  197.        exit(1);
  198.     }
  199.     buf[length]= '\0';   /*add terminating null */
  200.     if(msg != 0)
  201.        {
  202.        printf("\n Time message received:");
  203.        printf("\n                        D  L");
  204.        printf("\n MJD  YY MM DD HH MM SS ST S H  Adv.");
  205.        printf("%s\n",buf);
  206.     }
  207.     close(s);
  208. /*
  209.     now compute difference between local time and
  210.     received time.
  211. */
  212.     sscanf(buf," %ld %2d-%2d-%2d %2d:%2d:%2d %d %d %d",
  213.         &mjd,&yr,&mo,&dy,&hr,&min,&sec,&dst,&ls,&health);
  214.     if(msg == 2)        /*longer messages selected */
  215.        {
  216.        if( (dst == 0)  || (dst > 51) )
  217.           {
  218.           printf("\nStandard Time now in effect.");
  219.           if(dst > 51) 
  220.         printf("\nChange to Daylight Saving Time in %d days.",dst-51);
  221.        }
  222.        if( (dst <= 50) && (dst > 1) )
  223.           {
  224.           printf("\nDaylight Saving Time now in effect.");
  225.           if( (dst > 1) && (dst < 50) )
  226.         printf("\nChange to Standard Time in %d days.",dst-1);
  227.        }
  228.        if(dst == 1) printf("\nStandard time begins at 2am today.");
  229.        if(dst == 51)printf("\nDaylight Saving Time begins at 2am today.");
  230.        switch (ls)
  231.          {
  232.          case 1:
  233.            printf("\nLeap Second to be added at the end of this month.");
  234.            break;
  235.          case 2:
  236.            printf("\nSecond to be dropped at the end of this month.");
  237.            break;
  238.          default:
  239.            printf("\nNo leap second is scheduled.");
  240.        }
  241.        switch(health)
  242.          {
  243.          case 0:
  244.           printf("\nServer reports fully healthy status.");
  245.           break;
  246.          case 1:
  247.           printf("\nCaution -- Server may not be on time.");
  248.           break;
  249.          case 2:
  250.           printf("\nWarning -- Server may have large time error.");
  251.           break;
  252.          default:
  253.           printf("\nServer time error is not known.");
  254.           break;
  255.        }
  256.     }
  257. /*
  258.     convert received time to seconds since 1/1/70 and subtract
  259.     this from the local time in the same units.
  260.     Since no correction has been made for the network delay,
  261.     this difference cannot be taken too seriously, although
  262.     the delay in a local network should be no more than about
  263.     0.05 seconds.
  264. */
  265.     diff=tvv.tv_sec - 86400l*(mjd-mjd0) - 3600l*(long int)hr
  266.             -60l*(long int) min -(long int) sec;
  267.     if(tvv.tv_usec >= 500000l) diff++;    /*round microseconds */
  268. /*
  269.     test the cmos clock by computing the difference between
  270.     the cmos clock and the local RAM clock and then adding
  271.     the difference between the RAM clock and NIST.  This
  272.     gets around the need to do a time-zone conversion in
  273.     this comparison.
  274. */
  275.     if(cmos != 0)        /*test CMOS clock too */
  276.        {
  277.        diffat=86400l*(cvt2jd(yrat,moat,dayat) -
  278.               cvt2jd(yribm,moibm,dayibm)) + 3600l*(hrat-hribm)
  279.           + 60l*(minat-minibm) +(secat-secibm) + diff;
  280.     }
  281.     else diffat = 0;        /*cmos clock not tested*/
  282.     if(msg == 0)        /*no messages except time diff.*/
  283.        printf("%ld",diff);
  284.     else
  285.        printf("\nSystem Clock - NIST = % ld second(s).",diff);
  286.        if(cmos != 0)
  287.        printf("\nCMOS Clock   - NIST = % ld second(s).",diffat);
  288.     if( (diff == 0) && (diffat == 0) )
  289.       {
  290.       if(msg != 0) printf("\n No adjustment is needed.\n");
  291.       exit(0);
  292.     }
  293.     if(set == 0) exit(0);
  294.     if( (health != 0) && (msg != 0) )
  295.        printf("\n Server is not healthy, adjustment not recommended.");
  296.     cc = 'n';    /*default is not to set */
  297.     if(set == 3)    /*action depends on answer to query*/
  298.        {
  299.        printf("\n Do you want to adjust the time ? [y/n] ");
  300.        cc=getchar();
  301.     }
  302.     if( (set == 2) ||              /*always set */
  303.         ( (set == 1) && (health == 0) ) ||   /*set if healthy*/
  304.         (cc == 'y') ||             /*set if response yes*/
  305.         (cc == 'Y') )
  306.        {
  307.        adjtime(-diff);
  308.     }
  309.     exit(0);
  310. }
  311. /*
  312. */
  313. int sopen(path,access,shflag,mode)
  314. char *path;
  315. int access;
  316. int shflag;
  317. int mode;
  318. {
  319. int j;
  320.     j=open(path,access | shflag,mode);
  321.     return(j);
  322. }
  323. void adjtime(isec)
  324. long int isec;
  325. {
  326. /*
  327.     adjusts time of the local clock by isec
  328.     seconds.  time is changed in 1 step
  329.  
  330.     note that for versions of DOS after 3.3,
  331.     this call also sets the CMOS clock if it
  332.     is present.
  333. */
  334. struct timeval tpa;
  335. struct timezone tza;
  336. int hr,min,sec;        /*time*/
  337. int yr,mo,day;        /*date*/
  338.     gettimeofday(&tpa,&tza);
  339.     isec += tpa.tv_sec;
  340.     stime(&isec);
  341. }
  342.