home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / bsdss4.tz / bsdss4 / bsdss / server / uxkern / inittodr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-22  |  6.7 KB  |  291 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1992 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon 
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    inittodr.c,v $
  29.  * Revision 2.1  92/04/21  17:10:58  rwd
  30.  * BSDSS
  31.  * 
  32.  *
  33.  */
  34.  
  35. /*
  36.  * Routines to guess the time.
  37.  */
  38. #include <sys/types.h>
  39. #include <sys/time.h>
  40. #include <sys/param.h>
  41. #include <sys/kernel.h>
  42.  
  43. /*
  44.  * Time conversion.
  45.  */
  46.  
  47. #define    SECS_PER_MIN    60
  48. #define    MINS_PER_HOUR    60
  49. #define    HOURS_PER_DAY    24
  50. #define    DAYS_PER_WEEK    7
  51. #define    DAYS_PER_NYEAR    365
  52. #define    DAYS_PER_LYEAR    366
  53. #define    SECS_PER_HOUR    (SECS_PER_MIN * MINS_PER_HOUR)
  54. #define    SECS_PER_DAY    ((long) SECS_PER_HOUR * HOURS_PER_DAY)
  55. #define    MONS_PER_YEAR    12
  56.  
  57. #define    TM_SUNDAY    0
  58. #define    TM_MONDAY    1
  59. #define    TM_TUESDAY    2
  60. #define    TM_WEDNESDAY    3
  61. #define    TM_THURSDAY    4
  62. #define    TM_FRIDAY    5
  63. #define    TM_SATURDAY    6
  64.  
  65. #define    TM_JANUARY    0
  66. #define    TM_FEBRUARY    1
  67. #define    TM_MARCH    2
  68. #define    TM_APRIL    3
  69. #define    TM_MAY        4
  70. #define    TM_JUNE        5
  71. #define    TM_JULY        6
  72. #define    TM_AUGUST    7
  73. #define    TM_SEPTEMBER    8
  74. #define    TM_OCTOBER    9
  75. #define    TM_NOVEMBER    10
  76. #define    TM_DECEMBER    11
  77.  
  78. #define    TM_YEAR_BASE    1900
  79.  
  80. #define    EPOCH_YEAR    1970
  81. #define    EPOCH_WDAY    TM_THURSDAY
  82.  
  83. /*
  84. ** Accurate only for the past couple of centuries;
  85. ** that will probably do.
  86. */
  87.  
  88. #define    isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0)
  89.  
  90. int    mon_lengths[2][MONS_PER_YEAR] = {
  91.     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
  92.     31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  93. };
  94.  
  95. int    year_lengths[2] = {
  96.     DAYS_PER_NYEAR, DAYS_PER_LYEAR
  97. };
  98.  
  99.  
  100. cvttime(clock, tmp)
  101. time_t            clock;        /* seconds since 1 Jan 1970 */
  102. register struct tm *    tmp;
  103. {
  104.     register long        days;
  105.     register long        rem;
  106.     register int        y;
  107.     register int        yleap;
  108.     register int *        ip;
  109.     struct tm        tm;
  110.  
  111.     days = (clock - tz.tz_minuteswest*SECS_PER_MIN) / SECS_PER_DAY;
  112.     rem  = (clock - tz.tz_minuteswest*SECS_PER_MIN) % SECS_PER_DAY;
  113.     while (rem < 0) {
  114.         rem += SECS_PER_DAY;
  115.         --days;
  116.     }
  117.     while (rem >= SECS_PER_DAY) {
  118.         rem -= SECS_PER_DAY;
  119.         ++days;
  120.     }
  121.  
  122.     tm.tm_hour = (int) (rem / SECS_PER_HOUR);
  123.     rem = rem % SECS_PER_HOUR;
  124.     tm.tm_min = (int) (rem / SECS_PER_MIN);
  125.     tm.tm_sec = (int) (rem % SECS_PER_MIN);
  126.  
  127.     tm.tm_wday = (int) ((EPOCH_WDAY + days) % DAYS_PER_WEEK);
  128.     if (tm.tm_wday < 0)
  129.         tm.tm_wday += DAYS_PER_WEEK;
  130.  
  131.     y = EPOCH_YEAR;
  132.     if (days >= 0) {
  133.         for (;;) {
  134.         yleap = isleap(y);
  135.         if (days < (long) year_lengths[yleap])
  136.             break;
  137.         ++y;
  138.         days = days - (long) year_lengths[yleap];
  139.         }
  140.     }
  141.     else {
  142.         do {
  143.         --y;
  144.         yleap = isleap(y);
  145.         days = days + (long) year_lengths[yleap];
  146.         } while (days < 0);
  147.     }
  148.     tm.tm_year = y - TM_YEAR_BASE;
  149.     tm.tm_yday = (int) days;
  150.  
  151.     ip = mon_lengths[yleap];
  152.     for (tm.tm_mon = 0;
  153.          days >= (long) ip[tm.tm_mon];
  154.          ++tm.tm_mon) {
  155.         days = days - (long) ip[tm.tm_mon];
  156.     }
  157.     tm.tm_mday = (int) (days + 1);
  158.     tm.tm_isdst = 0;
  159.  
  160.     *tmp = tm;
  161. }
  162.  
  163. fmttime(timeptr, str)
  164. register struct tm *timeptr;
  165. char        str[26];
  166. {
  167.     static char    wday_name[DAYS_PER_WEEK][4] = {
  168.         "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  169.     };
  170.     static char    mon_name[MONS_PER_YEAR][4] = {
  171.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  172.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  173.     };
  174.  
  175.     sprintf(str, "%s %s %d %d:%d:%d %d",
  176.         wday_name[timeptr->tm_wday],
  177.         mon_name[timeptr->tm_mon],
  178.         timeptr->tm_mday, timeptr->tm_hour,
  179.         timeptr->tm_min, timeptr->tm_sec,
  180.         TM_YEAR_BASE + timeptr->tm_year);
  181. }    
  182.  
  183. print_time(fmt, clock)
  184.     char *    fmt;
  185.     time_t    clock;
  186. {
  187.     struct tm    tm;
  188.     char        timestr[26];
  189.  
  190.     cvttime(clock, &tm);
  191.     fmttime(&tm, timestr);
  192.     printf(fmt, timestr);
  193. }
  194.  
  195. /*
  196.  * Initialize the time of day.
  197.  */
  198. #define    SECYR        ((unsigned)(365*SECS_PER_DAY))    /* per common year */
  199.  
  200. /*
  201.  * If the hardware clock does not keep the current year, it
  202.  * sets the year to 1982.  If there is no hardware clock at all,
  203.  * the year will be about 1970.
  204.  */
  205. #define    NOYEAR        ((1982 - EPOCH_YEAR) * SECYR + 3 * SECS_PER_DAY)
  206.             /* 1972, 1976, 1980 were leap years */
  207.  
  208. /*
  209.  * Initialze the time of day register, based on the time base which is, e.g.
  210.  * from a filesystem.  Base provides the time to within six months,
  211.  * and the time of year clock provides the rest.
  212.  */
  213. inittodr(base)
  214.     time_t base;
  215. {
  216.     register u_int    todr;
  217.     long        deltat;
  218.     int        year = EPOCH_YEAR;
  219.  
  220.     struct timeval    cur_time, time;
  221.  
  222.     time.tv_usec = 0;
  223.  
  224.   print_time("Base is %s\n", base);
  225.  
  226.     if (base < 5*SECYR) {
  227.         printf("WARNING: preposterous time in file system");
  228.         time.tv_sec = 6*SECYR + 186*SECS_PER_DAY + SECS_PER_DAY/2;
  229.         goto check;
  230.     }
  231.  
  232.     get_time(&cur_time);
  233.     boottime = cur_time;
  234.  
  235.   print_time("Current time is %s\n", cur_time.tv_sec);
  236.     /*
  237.      * If the hardware does not provide the year,
  238.      * the time will be stuck at 1982.    XXX
  239.      */
  240.     if (cur_time.tv_sec < NOYEAR) {
  241.         printf("WARNING: hardware does not know what time it is");
  242.         /*
  243.          * Believe the time in the file system for lack of
  244.          * anything better.
  245.          */
  246.         time.tv_sec = base;
  247.         time.tv_usec = 0;
  248.         goto check;
  249.     }
  250.  
  251.     /*
  252.      * Sneak to within 6 month of the time in the filesystem,
  253.      * by starting with the time of the year suggested by the TODR,
  254.      * and advancing through succesive years.  Adding the number of
  255.      * seconds in the current year takes us to the end of the current year
  256.      * and then around into the next year to the same position.
  257.      */
  258.     time.tv_sec = cur_time.tv_sec - NOYEAR;
  259.     while (time.tv_sec < base-SECYR/2) {
  260.         if (isleap(year))
  261.         time.tv_sec += SECS_PER_DAY;
  262.         year++;
  263.         time.tv_sec += SECYR;
  264.     }
  265.  
  266.     /*
  267.      * See if we gained/lost two or more days;
  268.      * if so, assume something is amiss.
  269.      */
  270.     deltat = time.tv_sec - base;
  271.     if (deltat < 0)
  272.         deltat = -deltat;
  273.     if (deltat < 2*SECS_PER_DAY) {
  274.         /*
  275.          * Time seems to correspond.
  276.          */
  277.         goto set_the_time;
  278.     }
  279.  
  280.     printf("WARNING: clock %s %d days",
  281.         time.tv_sec < base ? "lost" : "gained", deltat / SECS_PER_DAY);
  282. check:
  283.     printf(" -- CHECK AND RESET THE DATE!\n");
  284.     boottime.tv_sec = time.tv_sec;
  285.  
  286. set_the_time:
  287.   print_time("Time is set to %s\n", time.tv_sec);
  288.     set_time(&time);
  289. }
  290.  
  291.