home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d09xx / d0950.lha / ClockTool / ClockTool.c < prev    next >
C/C++ Source or Header  |  1993-12-20  |  26KB  |  1,493 lines

  1. #define VERSION "1.0"
  2.  
  3. #define EARLIEST_LIB    37    /* 2.04 and above */
  4.  
  5. /*
  6.  *
  7.  * ClockTool.c
  8.  *
  9.  *  Displays/adjusts/sets times of battery clock and/or system clock
  10.  *  from one or the other.
  11.  *
  12.  * Options:
  13.  *
  14.  *    -b       ; battery clock
  15.  *    -s       ; system  clock
  16.  *    -annnn   ; adjust battery clock time by -nnnn millisecs",
  17.  *    +annnn   ; adjust battery clock time by +nnnn millisecs",
  18.  *    -l<file> ; log system time to <file> , (default LOG_CLOCKTOOL:)
  19.  *    -n<str>  ; append the <str> to log file entry, e.g. "reboot"
  20.  *
  21.  *  (see Usage () )
  22.  *
  23.  * Runs under AmigaDOS 2.04+, and only machines containing
  24.  * a battery clock.
  25.  *
  26.  *
  27.  *
  28.  *****    Written by Gary Duncan
  29.  *
  30.  *    Bug reports etc via e-mail to gduncan@philips.oz.au) , or mail to
  31.  *
  32.  *Work:    Gary Duncan
  33.  *    Philips PTS
  34.  *      23 Lakeside Dr
  35.  *    Tally-Ho Technology Park
  36.  *    Burwood East Vic 3151
  37.  *    Australia
  38.  *
  39.  *Home:    Gary Duncan
  40.  *    57 Melbourne Hill Rd
  41.  *    Warrandyte
  42.  *    Vic 3113
  43.  *     Australia
  44.  *
  45.  *
  46.  *
  47.  *****    Freely distributable for non-commercial purposes.
  48.  *    Please keep this header intact.
  49.  *
  50.  *
  51.  *    Compiles under SAS 6.2
  52.  *
  53.  *    Formatted with 'indent -gnu' ; a big time-saving program.
  54.  *
  55.  * Functions:-
  56.  
  57.     main
  58.     tv2dss
  59.     tv2str
  60.     dss2tv
  61.     dss2str
  62.     str2dss
  63.     Init_Timer
  64.     hexit
  65.     DeleteTimer
  66.     usage
  67.     scan_args
  68.     tv_diff
  69.     tv_diff_str
  70.     format_diff_str
  71.     set_system_time
  72.     get_system_time
  73.     get_battclock_time
  74.     set_battclock_time
  75.     tv_update
  76.     check4battclock
  77.     get_syncd_batt_time
  78.     get_syncd_sys_time
  79.     print_clock
  80.     display_clocks
  81.     adjust_clock
  82.     set_syncd_system_time
  83.     set_syncd_battclock_time
  84.     wait_for_timer
  85.     pause
  86.  
  87.  */
  88.  
  89. #include "ClockTool.h"
  90.  
  91.  
  92. /*
  93.  * string for AmigaDOS Version Command
  94.  */
  95. char A_vers[] = "\0$VER: clocktool\t" VERSION " (" __DATE__ " " __TIME__ ")";
  96.  
  97.  
  98. LIBRARY *UtilityBase = NULL;
  99. LIBRARY *BattClockBase;
  100.  
  101. TIMEVAL tv_sysclock;
  102. TIMEVAL tv_battclock;
  103. TIMEVAL tv_tmp;
  104.  
  105. DATESTAMP dss_sysclock;
  106. DATESTAMP dss_battclock;
  107.  
  108. LONG adjust;
  109. LONG temp;
  110.  
  111. MSGPORT *TimeP = NULL;
  112. TIMERREQUEST *Timermsg;
  113. IOREQUEST *Timer = NULL;
  114.  
  115. BOOL a_flag = FALSE;
  116. BOOL b_flag = FALSE;
  117. BOOL l_flag = FALSE;
  118. BOOL n_flag = FALSE;
  119. BOOL s_flag = FALSE;
  120.  
  121. char buf[80];
  122. char *xstr = "";
  123.  
  124. int opt_count = 0;
  125.  
  126. char *logfile;
  127. FILE *fp = NULL;
  128. char log_buf[80];
  129.  
  130. /*
  131.  * used by date conversion functions
  132.  */
  133.  
  134. DM days_month[] =
  135. {
  136.   31, "Jan",
  137.   28, "Feb",
  138.   31, "Mar",
  139.   30, "Apr",
  140.   31, "May",
  141.   30, "Jun",
  142.   31, "Jul",
  143.   31, "Aug",
  144.   30, "Sep",
  145.   31, "Oct",
  146.   30, "Nov",
  147.   31, "Dec",
  148. };
  149.  
  150. /*
  151.  *********************************************************************
  152.  */
  153.  
  154. VOID
  155. main (int argc, char **argv)
  156. {
  157.  
  158.   /*
  159.    * abort if no battclock and not AmigaDos 2.xx
  160.    */
  161.   if (check4battclock () == FALSE)
  162.     {
  163.       hexit (1);
  164.     }
  165.  
  166.   scan_args (argc, argv);
  167.  
  168.   Init_Timer ();
  169.  
  170.   /*
  171.    ***** Mode (1) ? - just display both clocks ?
  172.    */
  173.   if (opt_count == 0)
  174.     {
  175.       get_syncd_batt_time (&tv_battclock);
  176.       get_system_time (&tv_sysclock);
  177.  
  178.       display_clocks (&tv_battclock, &tv_sysclock);
  179.       hexit (1);
  180.     }
  181.   /*
  182.    * check that there is at least only one b or s option
  183.    */
  184.  
  185.   if ((b_flag == TRUE) && (s_flag == TRUE))
  186.     {
  187.       usage ("both b and s options set");
  188.       hexit (1);
  189.     }
  190.  
  191.   if ((b_flag == FALSE) && (s_flag == FALSE))
  192.     {
  193.       usage ("need either b or s option");
  194.       hexit (1);
  195.     }
  196.  
  197.   /*
  198.    ***** Mode (2) -  just a s or b option ?
  199.    */
  200.  
  201.   if (opt_count == 1)
  202.     {
  203.       /*
  204.        * just set one clock from the other
  205.        */
  206.       if (s_flag == TRUE)
  207.     {
  208.       (void) set_syncd_system_time ();
  209.  
  210.       print_old_new ("system", &tv_sysclock, &tv_battclock);
  211.     }
  212.       else
  213.     /* set battclock from system time */
  214.     {
  215.       (void) set_syncd_battclock_time ();
  216.  
  217.       print_old_new ("battery", &tv_sysclock, &tv_battclock);
  218.     }
  219.  
  220.       hexit (1);
  221.     }
  222.  
  223.   /*
  224.    ***** Mode (3) - adjust a clock ?
  225.    */
  226.   if ((n_flag == TRUE) && (l_flag == FALSE))
  227.     {
  228.       usage ("need l option");
  229.       hexit (1);
  230.     }
  231.  
  232.   if (a_flag == TRUE)
  233.     {
  234.       adjust_clock (adjust, &tv_tmp);
  235.     }
  236.  
  237.   if (l_flag == FALSE)
  238.     {
  239.       if (s_flag == TRUE)
  240.     {
  241.       print_old_new ("system", &tv_sysclock, &tv_tmp);
  242.     }
  243.       else
  244.     {
  245.       print_old_new ("battery", &tv_battclock, &tv_tmp);
  246.     }
  247.       hexit (1);
  248.     }
  249.  
  250.   /*
  251.    ***** Mode (4) - log selected clock time  ?
  252.    */
  253.  
  254.  
  255.   /*
  256.    * we have l option here...
  257.    */
  258.  
  259.   if (s_flag == TRUE)
  260.     {
  261.       temp = set_syncd_system_time ();
  262.  
  263.       sprintf (log_buf, "S: %s %s", tv2str (&tv_sysclock),
  264.            format_diff_str (temp, "(%s secs)  "));
  265.     }
  266.   else
  267.     /* set battclock from system time */
  268.     {
  269.       temp = set_syncd_battclock_time ();
  270.  
  271.       sprintf (log_buf, "B: %s %s", tv2str (&tv_battclock),
  272.            format_diff_str (temp, "(%s secs)  "));
  273.     }
  274.  
  275.   if (n_flag == TRUE)
  276.     {
  277.       strcat (log_buf, xstr);
  278.     }
  279.  
  280.   strcat (log_buf, "\n");
  281.  
  282.   printf ("%s", log_buf);
  283.  
  284. #if 1
  285.   /*
  286.    * now log message , maybe
  287.    */
  288.   if (fp)
  289.     {
  290.       int rote;
  291.       int len = strlen (log_buf);
  292.  
  293.       if ((rote = fwrite (log_buf, 1, len, fp)) != len)
  294.     {
  295.       fprintf (stderr, "fwrite error (wanted=%d),(actual=%d)\n",
  296.            len, rote);
  297.     }
  298.     }
  299. #endif
  300.  
  301.   hexit (1);
  302. }
  303.  
  304.  
  305. /***************************************************************************
  306.  
  307.  
  308.   Function :      tv2dss
  309.  
  310.   Purpose:    given a Timeval structure , returns Datestamp
  311.  
  312.   Entry    :    ptr to Timeval
  313.         ptr to Datestamp
  314.  
  315.   Returns  :
  316.  
  317.  
  318. ****************************************************************************/
  319.  
  320.  
  321. void
  322. tv2dss (TIMEVAL * tv, DATESTAMP * dss)
  323.  
  324. {
  325.   long rem;
  326.  
  327.   dss->ds_Days = tv->tv_secs / (24 * 60 * 60);
  328.   rem = tv->tv_secs % (24 * 60 * 60);    /* secs in last day */
  329.  
  330.   dss->ds_Minute = rem / 60;
  331.   rem = rem % 60;        /* secs in last minute */
  332.  
  333.   rem = (rem * 1000) + (tv->tv_micro / 1000);    /* msecs in last minute */
  334.  
  335.   dss->ds_Tick = rem / (1000 / TICKS_PER_SECOND);    /* ticks in last minute */
  336. }
  337.  
  338. /***************************************************************************
  339.  
  340.  
  341.   Function :      tv2str
  342.  
  343.   Purpose:    given a Timeval structure , returns date string
  344.  
  345.   Entry    :    ptr to Timeval
  346.  
  347.   Returns  :
  348.  
  349.  
  350. ****************************************************************************/
  351.  
  352.  
  353. char *
  354. tv2str (TIMEVAL * tv)
  355.  
  356. {
  357.   static char tbuf[40];
  358.   DATESTAMP dss;
  359.  
  360.   tv2dss (tv, &dss);
  361.   dss2str (&dss, tbuf);
  362.   return tbuf;
  363. }
  364.  
  365. /***************************************************************************
  366.  
  367.  
  368.   Function :       dss2tv
  369.  
  370.   Purpose:    given a DateStamp structure , returns an updated TIMEVAL
  371.  
  372.   Entry    :    ptr to DateStamp structure
  373.  
  374.   Returns  :
  375.  
  376.  
  377. ****************************************************************************/
  378.  
  379.  
  380. void
  381. dss2tv (DATESTAMP * t1, TIMEVAL * tv)
  382.  
  383. {
  384.   ULONG secs;
  385.  
  386.   secs = t1->ds_Days * 24 * 60 * 60;
  387.   secs += t1->ds_Minute * 60;
  388.   secs += t1->ds_Tick / TICKS_PER_SECOND;
  389.  
  390.   tv->tv_secs = secs;
  391.   tv->tv_micro = (t1->ds_Tick % TICKS_PER_SECOND) * (1000000 / TICKS_PER_SECOND);
  392.  
  393. }
  394.  
  395. /***************************************************************************
  396.  
  397.  
  398.   Function :      dss2str
  399.  
  400.   Purpose:    generates a date string given a DateStamp
  401.  
  402.   Entry    :    ptr to Datestamp
  403.  
  404.  
  405.   Returns  :    ptr to date string
  406.  
  407.  
  408.  
  409. ****************************************************************************/
  410.  
  411.  
  412. void
  413. dss2str (DATESTAMP * dss, char *str)
  414.  
  415. {
  416.   static TIMEVAL tv;
  417.   struct tm Time;
  418.   int j;
  419.   long time, ago;
  420.  
  421.  
  422.   dss2tv (dss, &tv);        /* date to secs/usecs since 01 Jan 78 */
  423.   time = tv.tv_secs;
  424.  
  425.   Time.tm_sec = time % 60;
  426.   time /= 60;
  427.   Time.tm_min = time % 60;
  428.   time /= 60;
  429.   Time.tm_hour = time % 24;
  430.   time /= 24;
  431.   Time.tm_wday = time % 7;
  432.   Time.tm_year = 78 + (time / (4 * 365 + 1)) * 4;
  433.   time %= 4 * 365 + 1;
  434.  
  435.  
  436.   while (time)
  437.     {
  438.       ago = 365;
  439.       if ((Time.tm_year & 3) == 0)    /* leap year */
  440.     ago++;
  441.       if (time < ago)
  442.     break;
  443.       time -= ago;
  444.       Time.tm_year++;
  445.     }
  446.   Time.tm_yday = ++time;
  447.  
  448.   for (j = 0; j < 12; j++)
  449.     {
  450.       ago = days_month[j].days;
  451.       if (j == 1 && (Time.tm_year & 3) == 0)    /* Feb , and leap year ? */
  452.     ago++;
  453.       if (time <= ago)
  454.     break;
  455.       time -= ago;
  456.     }
  457.   Time.tm_mon = j;
  458.   Time.tm_mday = time;
  459.  
  460.   /* date format : 23-dec-88 22:33:01  */
  461.  
  462.   sprintf (str, "%02d-%s-%2d %02d:%02d:%02d.%03d",
  463.        Time.tm_mday,
  464.        days_month[Time.tm_mon].months,
  465.        Time.tm_year,
  466.        Time.tm_hour,
  467.        Time.tm_min,
  468.        Time.tm_sec,
  469.        tv.tv_micro / 1000
  470.     );
  471.  
  472. }
  473.  
  474.  
  475.  
  476. /***************************************************************************
  477.  
  478.  
  479.   Function :   str2dss
  480.  
  481.  
  482.   Purpose  :   converts a truncated Amiga date string to a Datestamp
  483.  
  484.         e.g.     "22-Dec-92 08:10:26" , no leading day
  485.   Entry    :
  486.  
  487.  
  488.   Returns  :   TRUE if succssful, FALSE otherwise
  489.  
  490.  
  491.  
  492. ****************************************************************************/
  493.  
  494. BOOLEAN
  495. str2dss (char *str, DATESTAMP * ds)
  496.  
  497. {
  498. /* 012345678901234567 */
  499. /* 22-Dec-92 08:10:26 */
  500.  
  501.   char *p = str;
  502.   ULONG dss_days;
  503.  
  504.   int day, month, year, hour, min, sec, diy, j, k, rem;
  505.  
  506.   p[2] = '\0';
  507.   p[6] = '\0';
  508.   p[9] = '\0';
  509.   p[12] = '\0';
  510.   p[15] = '\0';
  511.  
  512.   day = atoi (&p[0]);
  513.   year = atoi (&p[7]) + 1900;
  514.   hour = atoi (&p[10]);
  515.   min = atoi (&p[13]);
  516.   sec = atoi (&p[16]);
  517.  
  518.   /*
  519.    * compute days-in-year from month
  520.    * - may be incremented later if a leap year
  521.    */
  522.   for (p = str + 3, j = 0, diy = 0;; ++j)
  523.     {
  524.       if (j == 12)
  525.     return FALSE;
  526.       if (strcmp (p, days_month[j].months) == 0)
  527.     {
  528.       month = j + 1;
  529.       break;
  530.     }
  531.       diy += days_month[j].days;
  532.     }
  533.  
  534.   /*
  535.    * tricky bit ; adjust for leap years
  536.    */
  537.   dss_days = diy + day - 1;
  538.   dss_days += 2 * 365;        /* 1978, 1979 */
  539.   for (j = 1980, k = 0;;)
  540.     {
  541.       dss_days += 365;
  542.       if ((rem = (k++ % 4)) == 0)
  543.     dss_days += 1;        /* leap year */
  544.  
  545.       if (++j == year)
  546.     {
  547.       if (((rem = (k++ % 4)) == 0) && (month > 2))
  548.         {
  549.           dss_days += 1;
  550.         }
  551.       break;
  552.     }
  553.     }
  554.  
  555.   ds->ds_Days = dss_days;
  556.   /*
  557.    * now fill in mins, ticks in min
  558.    */
  559.   ds->ds_Minute = (60 * hour) + min;
  560.   ds->ds_Tick = sec * TICKS_PER_SECOND;
  561.  
  562.   return TRUE;
  563. }
  564.  
  565. /***************************************************************************
  566.  
  567.  
  568.   Function :    Init_Timer
  569.  
  570.   Purpose:    Inits timer
  571.  
  572.   Entry    :
  573.  
  574.  
  575.   Returns  :
  576.  
  577.  
  578.  
  579. ****************************************************************************/
  580.  
  581.  
  582. void
  583. Init_Timer (void)
  584. {
  585.  
  586.   int error;
  587.  
  588.   TimeP = CreatePort (0, 0);
  589.   if (TimeP == NULL)
  590.     hexit (1);
  591.  
  592.   Timermsg = (TIMERREQUEST *) CreateExtIO (TimeP, sizeof (TIMERREQUEST));
  593.   if (Timermsg == NULL)
  594.     {
  595.       hexit (1);
  596.     }
  597.  
  598.   error = OpenDevice (TIMERNAME, UNIT_MICROHZ, (IOREQUEST *) Timermsg, 0);
  599.   if (error != 0)
  600.     {
  601.       DeleteExtIO ((IOREQUEST *) Timermsg);
  602.       hexit (1);
  603.     }
  604. }
  605.  
  606.  
  607. /***************************************************************************
  608.  
  609.  
  610.   Function :      hexit
  611.  
  612.  
  613.   Purpose  :      cleans up and exits
  614.  
  615.  
  616.   Entry    :
  617.  
  618.  
  619.   Returns  :
  620.  
  621.  
  622.  
  623. ****************************************************************************/
  624.  
  625.  
  626. void
  627. hexit (int fred)
  628. {
  629.  
  630.   if (UtilityBase)
  631.     {
  632.       CloseLibrary (UtilityBase);
  633.     }
  634.  
  635.   if (Timermsg != NULL)
  636.     {
  637.       DeleteTimer (Timermsg);
  638.     }
  639.   /*
  640.    * close log file if open
  641.    */
  642.   if (fp)
  643.     fclose (fp);
  644.  
  645.   exit (0);
  646. }
  647.  
  648. /***************************************************************************
  649.  
  650.  
  651.   Function :       DeleteTimer
  652.  
  653.   Purpose:    Deletes Timer
  654.  
  655.   Entry    :
  656.  
  657.  
  658.   Returns  :
  659.  
  660.  
  661.  
  662. ****************************************************************************/
  663.  
  664.  
  665. void
  666. DeleteTimer (TIMERREQUEST * tr)
  667. {
  668.   MSGPORT *tp;
  669.  
  670.   tp = tr->tr_node.io_Message.mn_ReplyPort;
  671.   if (tr != 0)
  672.     {
  673.       CloseDevice ((IOREQUEST *) tr);
  674.       DeleteExtIO ((IOREQUEST *) tr);
  675.     }
  676.   if (tp != 0)
  677.     DeletePort (tp);
  678. }
  679.  
  680. /***************************************************************************
  681.  
  682.  
  683.   Function :      usage
  684.  
  685.   Purpose:    prints invocation parameters
  686.  
  687.   Entry    :
  688.  
  689.  
  690.   Returns  :
  691.  
  692.  
  693.  
  694. ****************************************************************************/
  695.  
  696. void
  697. usage (char *p)
  698.  
  699.  
  700. {
  701.   static char *rats[] =
  702.   {
  703.     "Usage modes :-",
  704.     " 1) display clocks : clocktool",
  705.     " 2) set clock from",
  706.     "     other clock   : clocktool -[b | s]",
  707.     " 3) adjust clock   : clocktool -[b | s] [+|-a<n>]",
  708.     " 4) log    clock   : clocktool -[b | s] -l<file> [-n<str>] [+|-a<n>]",
  709.     "\nOptions:",
  710.     "    -b         : battery clock",
  711.     "    -s         : system  clock",
  712.     "    +|-a<n>    : change selected clock by + or - <n> millisecs",
  713.     "",
  714.     "    -l<file>   : log time of selected clock to <file>",
  715.     "                     (default file =  LOG_CLOCKTOOL:)",
  716.     "    -n<str>    : append the <str> to log file entry, e.g. \"reboot\"",
  717.     NULL
  718.   };
  719.   int j = 0;
  720.   char *ptr;
  721.  
  722.  
  723.  
  724.   if (*p)
  725.     printf ("Error: %s\n\n", p);
  726.  
  727.   printf (
  728.   "%s: Displays/adjusts/sets times of battery clock and/or system clock\n\n",
  729.        "ClockTool");
  730.   printf (
  731.        "Version %s [%s : %s] written by gduncan\n\n",
  732.        VERSION, __DATE__, __TIME__);
  733.  
  734.   while (ptr = rats[j++])
  735.     printf ("%s\n", ptr);
  736. }
  737.  
  738. /***************************************************************************
  739.  
  740.  
  741.   Function :        scan_args
  742.  
  743.   Purpose:    scans and validates command line
  744.  
  745.   Entry    :
  746.  
  747.  
  748.   Returns  :
  749.  
  750.  
  751.  
  752. ****************************************************************************/
  753.  
  754.  
  755.  
  756. void
  757. scan_args (int argc, char **argv)
  758.  
  759. {
  760.   char *ptr;
  761.   char arch;
  762.   char plusminus;
  763.  
  764.   while (--argc)
  765.     {
  766.       ptr = *++argv;
  767.       plusminus = *ptr++;
  768.       /*
  769.        * now look for options
  770.        */
  771.       if ((plusminus == '-') || (plusminus == '+'))
  772.     {
  773.       ++opt_count;
  774.       arch = *ptr++;
  775.  
  776.       switch (arch)
  777.         {
  778.  
  779.         case 'a':        /* adjust clock time */
  780.           a_flag = TRUE;
  781.           if (sscanf (ptr, "%d", &adjust) != 1)
  782.         {
  783.           fprintf (stderr, "bad -a option value\n");
  784.           hexit (1);
  785.         }
  786.           if (plusminus == '-')
  787.         adjust = -adjust;
  788.  
  789.           break;
  790.  
  791.         case 'b':
  792.           b_flag = TRUE;
  793.           break;
  794.  
  795.         case 's':
  796.           s_flag = TRUE;
  797.           break;
  798.  
  799.         case 'h':        /*      */
  800.           usage ("");    /* help    */
  801.           hexit (1);
  802.  
  803.         case 'l':
  804.           l_flag = TRUE;
  805.           logfile = (*ptr) ? ptr : "LOG_CLOCKTOOL:";
  806.           if ((fp = fopen (logfile, "a")) == NULL)
  807.         {
  808.           fprintf (stderr, "Can't open %s\n", logfile);
  809.           hexit (1);
  810.         }
  811.           break;
  812.  
  813.         case 'n':        /* put str in log file entry     */
  814.           n_flag = TRUE;
  815.           xstr = ptr;
  816.           break;
  817.  
  818.         default:
  819.           usage ("unknown option");    /* bad option    */
  820.           hexit (1);
  821.  
  822.         }
  823.     }
  824.       else
  825.     {
  826.       usage ("not an option");
  827.       hexit (1);
  828.     }
  829.     }
  830.   if (b_flag && s_flag)
  831.     {
  832.       usage ("only one -b or -s option");    /* bad option    */
  833.       hexit (1);
  834.     }
  835. }
  836.  
  837. /***************************************************************************
  838.  
  839.  
  840.   Function :      tv_diff
  841.  
  842.  
  843.   Purpose  :    returns difference in msecs between two TIMEVALS
  844.  
  845.   Entry    :
  846.  
  847.  
  848.   Returns  :
  849.  
  850.  
  851.  
  852. ****************************************************************************/
  853.  
  854. LONG
  855. tv_diff (TIMEVAL * tv1, TIMEVAL * tv2)
  856. {
  857.   LONG val;
  858.  
  859.   val = ((LONG) tv2->tv_secs - (LONG) tv1->tv_secs) * 1000;
  860.   val += (((LONG) tv2->tv_micro) - ((LONG) tv1->tv_micro)) / 1000;
  861.  
  862.   return val;
  863. }
  864.  
  865. /***************************************************************************
  866.  
  867.  
  868.   Function :      tv_diff_str
  869.  
  870.  
  871.   Purpose  :    returns difference in msecs between two TIMEVALS
  872.         expressed as secs.msecs string
  873.  
  874.   Entry    :
  875.  
  876.  
  877.   Returns  :
  878.  
  879.  
  880.  
  881. ****************************************************************************/
  882.  
  883. char *
  884. tv_diff_str (TIMEVAL * tv1, TIMEVAL * tv2)
  885. {
  886.   LONG val;
  887.  
  888.   val = tv_diff (tv1, tv2);
  889.  
  890.   return (format_diff_str (val, " (%s)"));
  891. }
  892.  
  893. /***************************************************************************
  894.  
  895.  
  896.   Function :      format_diff_str
  897.  
  898.  
  899.   Purpose  :    formats diff string
  900.  
  901.   Entry    :
  902.  
  903.  
  904.   Returns  :
  905.  
  906.  
  907.  
  908. ****************************************************************************/
  909.  
  910. char *
  911. format_diff_str (LONG val, char *form)
  912. {
  913.   static char mbuf[80];
  914.   char tmp[80];
  915.  
  916.   tmp[0] = ' ';
  917.  
  918.   if (val < 0)
  919.     {
  920.       tmp[0] = '-';
  921.       val = -val;
  922.     }
  923.   else if (val > 0)
  924.     {
  925.       tmp[0] = '+';
  926.     }
  927.   if (val > 999999)
  928.     {
  929.       return " ( >999.999 ) ";
  930.     }
  931.  
  932.   sprintf (&tmp[1], " %3d.%03d", val / 1000, val % 1000);
  933.  
  934.   sprintf (mbuf, form, tmp);
  935.   return mbuf;
  936. }
  937.  
  938. /***************************************************************************
  939.  
  940.  
  941.   Function :       set_system_time
  942.  
  943.   Purpose:    sets system date/time
  944.         
  945.   Entry    :    TIMEVAL
  946.  
  947.  
  948.   Returns  :    void
  949.  
  950.  
  951. ****************************************************************************/
  952.  
  953. void
  954. set_system_time (TIMEVAL * tv)
  955. {
  956.  
  957.   Timermsg->tr_node.io_Command = TR_SETSYSTIME;
  958.   Timermsg->tr_time.tv_secs = tv->tv_secs;
  959.   Timermsg->tr_time.tv_micro = tv->tv_micro;
  960.  
  961.   if (DoIO ((IOREQUEST *) Timermsg))
  962.     {
  963.       fprintf (stderr, "set_system_time() - DoIO fail\n");
  964.       hexit (1);
  965.     }
  966. }
  967.  
  968. /***************************************************************************
  969.  
  970.  
  971.   Function :       get_system_time
  972.  
  973.   Purpose:    gets system date/time
  974.         
  975.   Entry    :    ptr to TIMEVAL
  976.  
  977.  
  978.   Returns  :    void
  979.  
  980.  
  981. ****************************************************************************/
  982.  
  983. void
  984. get_system_time (TIMEVAL * tv)
  985. {
  986.  
  987.   Timermsg->tr_node.io_Command = TR_GETSYSTIME;
  988.  
  989.   if (DoIO ((IOREQUEST *) Timermsg))
  990.     {
  991.       fprintf (stderr, "get_time() - DoIO fail\n");
  992.       hexit (1);
  993.     }
  994.   tv->tv_secs = Timermsg->tr_time.tv_secs;
  995.   tv->tv_micro = Timermsg->tr_time.tv_micro;
  996. }
  997.  
  998. /***************************************************************************
  999.  
  1000.  
  1001.   Function :       get_battclock_time
  1002.  
  1003.   Purpose:    Get Battery Backed-up Clock time
  1004.  
  1005.   Entry    :    ptr to TIMEVAL structure
  1006.  
  1007.   Returns  :
  1008.  
  1009.  
  1010. ****************************************************************************/
  1011.  
  1012.  
  1013. void
  1014. get_battclock_time (TIMEVAL * tv)
  1015.  
  1016. {
  1017.  
  1018.   tv->tv_secs = ReadBattClock ();
  1019.   tv->tv_micro = 0;
  1020. }
  1021.  
  1022. /***************************************************************************
  1023.  
  1024.  
  1025.   Function :       set_battclock_time
  1026.  
  1027.   Purpose:    Set Battery Backed-up Clock time
  1028.  
  1029.   Entry    :    ptr to TIMEVAL structure
  1030.  
  1031.   Returns  :
  1032.  
  1033.  
  1034. ****************************************************************************/
  1035.  
  1036.  
  1037. void
  1038. set_battclock_time (TIMEVAL * tv)
  1039.  
  1040. {
  1041.   WriteBattClock (tv->tv_secs);
  1042. }
  1043.  
  1044. /***************************************************************************
  1045.  
  1046.  
  1047.   Function :      tv_update
  1048.  
  1049.  
  1050.   Purpose  :    updates a TIMEVAL with nnn msecs
  1051.  
  1052.   Entry    :
  1053.  
  1054.  
  1055.   Returns  :
  1056.  
  1057.  
  1058.  
  1059. ****************************************************************************/
  1060.  
  1061. void
  1062. tv_update (TIMEVAL * tv, LONG msecs)
  1063. {
  1064.   LONG t_secs, t_msecs;
  1065.   TIMEVAL tv_tmp = *tv;
  1066.   BOOL flag = TRUE;
  1067.  
  1068.   if (msecs < 0)
  1069.     {
  1070.       flag = FALSE;
  1071.       msecs = -msecs;
  1072.     }
  1073.   t_secs = msecs / 1000;
  1074.   t_msecs = msecs % 1000;
  1075.  
  1076.   /*
  1077.    * conv microsecs field to msecs
  1078.    */
  1079.   tv_tmp.tv_micro %= 1000;
  1080.  
  1081.   if (flag == TRUE)
  1082.     {
  1083.       /* add */
  1084.  
  1085.       tv_tmp.tv_micro += t_msecs;
  1086.       if (tv_tmp.tv_micro >= 1000)
  1087.     {
  1088.       tv_tmp.tv_micro %= 1000;
  1089.       tv_tmp.tv_secs += 1;
  1090.     }
  1091.       tv_tmp.tv_secs += t_secs;
  1092.     }
  1093.   else
  1094.     {
  1095.       /* subtract */
  1096.  
  1097.       if (tv_tmp.tv_micro < t_msecs)
  1098.     {
  1099.       tv_tmp.tv_micro += 1000 - t_msecs;
  1100.       tv_tmp.tv_secs -= 1;
  1101.     }
  1102.       tv_tmp.tv_secs -= t_secs;
  1103.     }
  1104.   /*
  1105.    * conv  msecs back to microsecs
  1106.    */
  1107.   tv_tmp.tv_micro *= 1000;
  1108.   /*
  1109.    * update given TIMEVAL
  1110.    */
  1111.  
  1112.   *tv = tv_tmp;
  1113. }
  1114.  
  1115. /***************************************************************************
  1116.  
  1117.  
  1118.   Function :    check4battclock
  1119.  
  1120.   Purpose:    Inits other stuff
  1121.  
  1122.   Entry    :
  1123.  
  1124.  
  1125.   Returns  :
  1126.  
  1127.  
  1128.  
  1129. ****************************************************************************/
  1130.  
  1131.  
  1132. BOOL
  1133. check4battclock (void)
  1134. {
  1135.  
  1136.   UtilityBase = (LIBRARY *) OpenLibrary ("utility.library", EARLIEST_LIB);
  1137.  
  1138.   if (UtilityBase == NULL)
  1139.     {
  1140.       fprintf (stderr, "Abort: only runs under AmigaDOS 2.04 and above\n");
  1141.       return FALSE;
  1142.     }
  1143.   /*
  1144.    * see if Battery Clock there
  1145.    */
  1146.   BattClockBase = OpenResource (BATTCLOCKNAME);
  1147.   if (BattClockBase == NULL)
  1148.     {
  1149.       fprintf (stderr, "Abort: can't find a Battery Clock\n");
  1150.       return FALSE;
  1151.     }
  1152.   return TRUE;
  1153. }
  1154.  
  1155. /***************************************************************************
  1156.  
  1157.  
  1158.   Function :    get_syncd_batt_time
  1159.  
  1160.   Purpose:    reads battclock and returns when sec just ticked over
  1161.  
  1162.   Entry    :
  1163.  
  1164.  
  1165.   Returns  :
  1166.  
  1167.  
  1168.  
  1169. ****************************************************************************/
  1170.  
  1171. void
  1172. get_syncd_batt_time (TIMEVAL * tv)
  1173. {
  1174.   TIMEVAL tv_tmp;
  1175.  
  1176.   get_battclock_time (&tv_tmp);
  1177.   do
  1178.     {
  1179.       get_battclock_time (tv);
  1180.   } while (tv_tmp.tv_secs == tv->tv_secs);
  1181. }
  1182.  
  1183. /***************************************************************************
  1184.  
  1185.  
  1186.   Function :    get_syncd_sys_time
  1187.  
  1188.   Purpose:    reads sysclock and returns when sec just ticked over
  1189.  
  1190.   Entry    :
  1191.  
  1192.  
  1193.   Returns  :
  1194.  
  1195.  
  1196.  
  1197. ****************************************************************************/
  1198.  
  1199. void
  1200. get_syncd_sys_time (TIMEVAL * tv)
  1201. {
  1202.   TIMEVAL tv_tmp;
  1203.  
  1204.   get_system_time (&tv_tmp);
  1205.   do
  1206.     {
  1207.       get_system_time (tv);
  1208.   } while (tv_tmp.tv_secs == tv->tv_secs);
  1209. }
  1210.  
  1211. /***************************************************************************
  1212.  
  1213.  
  1214.   Function :    print_clock
  1215.  
  1216.   Purpose:    prints clock time surrounded by given strings
  1217.  
  1218.   Entry    :
  1219.  
  1220.  
  1221.   Returns  :
  1222.  
  1223.  
  1224.  
  1225. ****************************************************************************/
  1226.  
  1227. void
  1228. print_clock (char *pre, TIMEVAL * tv, char *post)
  1229. {
  1230.  
  1231.   /*
  1232.    * print results
  1233.    */
  1234.   printf ("%s%s%s", pre, tv2str (tv), post);
  1235.   fflush (stdout);
  1236. }
  1237.  
  1238. /***************************************************************************
  1239.  
  1240.  
  1241.   Function :    display both clocks
  1242.  
  1243.   Purpose:    as the name suggests
  1244.  
  1245.   Entry    :
  1246.  
  1247.  
  1248.   Returns  :
  1249.  
  1250.  
  1251.  
  1252. ****************************************************************************/
  1253.  
  1254. void
  1255. display_clocks (TIMEVAL * tv_b, TIMEVAL * tv_s)
  1256. {
  1257.  
  1258.   print_clock ("Battery clock time = ", tv_b, "\n");
  1259.   print_clock ("System  clock time = ", tv_s, tv_diff_str (tv_b, tv_s));
  1260.   printf ("\n");
  1261.  
  1262. }
  1263.  
  1264. /***************************************************************************
  1265.  
  1266.  
  1267.   Function :    adjust a clock
  1268.  
  1269.   Purpose:    adjusts either system clock or  battclock by given
  1270.         number of millisecs
  1271.  
  1272.   Entry    :
  1273.  
  1274.  
  1275.   Returns  :
  1276.  
  1277.  
  1278.  
  1279. ****************************************************************************/
  1280.  
  1281. void
  1282. adjust_clock (LONG msecs, TIMEVAL * tv)
  1283. {
  1284.   static TIMEVAL tv_tmpx;
  1285.  
  1286.   /*
  1287.    * wait until given clock wraps over a second
  1288.    */
  1289.   if (s_flag == TRUE)
  1290.     {
  1291.       get_syncd_sys_time (&tv_sysclock);
  1292.       tv_tmpx = tv_sysclock;
  1293.       tv_update (&tv_tmpx, msecs);
  1294.  
  1295.       set_system_time (&tv_tmpx);
  1296.     }
  1297.   else
  1298.     {
  1299.       LONG res;
  1300.       /*
  1301.        * battclock here
  1302.        */
  1303.       get_syncd_batt_time (&tv_battclock);
  1304.       tv_tmpx = tv_battclock;
  1305.       tv_update (&tv_tmpx, msecs);
  1306.  
  1307.       res = 1000 - (tv_tmpx.tv_micro / 1000);
  1308.       tv_update (&tv_battclock, 1000);
  1309.       ++tv_tmpx.tv_secs;
  1310.  
  1311.       /*
  1312.        * - wait a bit to account for fraction of a sec
  1313.        */
  1314.       pause (res);
  1315.  
  1316.       set_battclock_time (&tv_tmpx);
  1317.     }
  1318.   *tv = tv_tmpx;
  1319.  
  1320. }
  1321.  
  1322. /***************************************************************************
  1323.  
  1324.  
  1325.   Function :    print_old_new
  1326.  
  1327.   Purpose:    as the name suggests
  1328.  
  1329.   Entry    :
  1330.  
  1331.  
  1332.   Returns  :
  1333.  
  1334.  
  1335.  
  1336. ****************************************************************************/
  1337.  
  1338. void
  1339. print_old_new (char *ptr, TIMEVAL * tv_old, TIMEVAL * tv_new)
  1340. {
  1341.   printf ("Old %s clock time = ", ptr);
  1342.   print_clock ("", tv_old, "\n");
  1343.  
  1344.   printf ("New %s clock time = ", ptr);
  1345.   print_clock ("", tv_new, tv_diff_str (tv_old, tv_new));
  1346.   printf ("\n");
  1347.  
  1348. }
  1349.  
  1350. /***************************************************************************
  1351.  
  1352.  
  1353.   Function :    set_syncd_system_time
  1354.  
  1355.   Purpose:    sets system clock to battclock time when it ticks
  1356.         over a second.
  1357.  
  1358.   Entry    :
  1359.  
  1360.  
  1361.   Returns  :
  1362.  
  1363.  
  1364.  
  1365. ****************************************************************************/
  1366.  
  1367. LONG
  1368. set_syncd_system_time ()
  1369. {
  1370.   get_syncd_batt_time (&tv_battclock);
  1371.   get_system_time (&tv_sysclock);
  1372.   set_system_time (&tv_battclock);
  1373.  
  1374.   return (tv_diff (&tv_battclock, &tv_sysclock));
  1375. }
  1376.  
  1377. /***************************************************************************
  1378.  
  1379.  
  1380.   Function :    set_syncd_battclock_time
  1381.  
  1382.   Purpose:    sets battery clock to system time when it ticks
  1383.         over a second.
  1384.  
  1385.   Entry    :
  1386.  
  1387.  
  1388.   Returns  :
  1389.  
  1390.  
  1391.  
  1392. ****************************************************************************/
  1393.  
  1394. LONG
  1395. set_syncd_battclock_time ()
  1396. {
  1397.   TIMEVAL tv_tmp;
  1398.   LONG diff;
  1399.  
  1400.   /*
  1401.    * we need to mess around a bit to get diff
  1402.    * between batt and system clock because batt clock
  1403.    * is only accurate to 1 sec
  1404.    */
  1405.   get_syncd_batt_time (&tv_battclock);
  1406.   get_system_time (&tv_tmp);
  1407.   diff = tv_diff (&tv_battclock, &tv_tmp);
  1408.  
  1409.   get_syncd_sys_time (&tv_sysclock);
  1410.   set_battclock_time (&tv_sysclock);
  1411.  
  1412.   /*
  1413.    * now correct battclock time to give msecs precision
  1414.    */
  1415.   tv_battclock = tv_sysclock;
  1416.   tv_update (&tv_battclock, diff);
  1417.  
  1418.   return (-diff);
  1419. }
  1420.  
  1421. /***************************************************************************
  1422.  
  1423.  
  1424.   Function :      wait_for_timer
  1425.  
  1426.   Purpose:    Waits until given time expires
  1427.  
  1428.   Entry    :
  1429.  
  1430.  
  1431.   Returns  :
  1432.  
  1433.  
  1434.  
  1435. ****************************************************************************/
  1436.  
  1437.  
  1438. void
  1439. wait_for_timer (TIMERREQUEST * tr, TIMEVAL * tv)
  1440.  
  1441. {
  1442.   MSGPORT *tp;
  1443.   ULONG flags;
  1444.  
  1445.   tp = tr->tr_node.io_Message.mn_ReplyPort;
  1446.  
  1447.   tr->tr_node.io_Command = TR_ADDREQUEST;
  1448.   tr->tr_time.tv_secs = tv->tv_secs;
  1449.   tr->tr_time.tv_micro = tv->tv_micro;
  1450.   SendIO ((IOREQUEST *) tr);
  1451.  
  1452.  
  1453.   flags = Wait ((1L << tp->mp_SigBit) | SIGBREAKF_CTRL_C);
  1454.   if (flags & SIGBREAKF_CTRL_C)
  1455.     {
  1456.       AbortIO ((IOREQUEST *) tr);
  1457.       WaitIO ((IOREQUEST *) tr);
  1458.       hexit (1);
  1459.     }
  1460. }
  1461.  
  1462. /***************************************************************************
  1463.  
  1464.  
  1465.   Function :      pause
  1466.  
  1467.  
  1468.   Purpose  :      waits for given millisecs
  1469.           ( or until ^C hit )
  1470.  
  1471.   Entry    :
  1472.  
  1473.  
  1474.   Returns  :
  1475.  
  1476.  
  1477.  
  1478. ****************************************************************************/
  1479.  
  1480.  
  1481. void
  1482. pause (int millisecs)
  1483. {
  1484.   static TIMEVAL tv;
  1485.  
  1486.   tv.tv_secs = millisecs / 1000;
  1487.   tv.tv_micro = (millisecs % 1000) * 1000;
  1488.  
  1489.   wait_for_timer (Timermsg, &tv);
  1490. }
  1491.  
  1492. /**/
  1493.