home *** CD-ROM | disk | FTP | other *** search
- /*
- * Mach Operating System
- * Copyright (c) 1992 Carnegie Mellon University
- * All Rights Reserved.
- *
- * Permission to use, copy, modify and distribute this software and its
- * documentation is hereby granted, provided that both the copyright
- * notice and this permission notice appear in all copies of the
- * software, derivative works or modified versions, and any portions
- * thereof, and that both notices appear in supporting documentation.
- *
- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
- *
- * Carnegie Mellon requests users of this software to return to
- *
- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
- * School of Computer Science
- * Carnegie Mellon University
- * Pittsburgh PA 15213-3890
- *
- * any improvements or extensions that they make and grant Carnegie Mellon
- * the rights to redistribute these changes.
- */
- /*
- * HISTORY
- * $Log: inittodr.c,v $
- * Revision 2.1 92/04/21 17:10:58 rwd
- * BSDSS
- *
- *
- */
-
- /*
- * Routines to guess the time.
- */
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/param.h>
- #include <sys/kernel.h>
-
- /*
- * Time conversion.
- */
-
- #define SECS_PER_MIN 60
- #define MINS_PER_HOUR 60
- #define HOURS_PER_DAY 24
- #define DAYS_PER_WEEK 7
- #define DAYS_PER_NYEAR 365
- #define DAYS_PER_LYEAR 366
- #define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)
- #define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY)
- #define MONS_PER_YEAR 12
-
- #define TM_SUNDAY 0
- #define TM_MONDAY 1
- #define TM_TUESDAY 2
- #define TM_WEDNESDAY 3
- #define TM_THURSDAY 4
- #define TM_FRIDAY 5
- #define TM_SATURDAY 6
-
- #define TM_JANUARY 0
- #define TM_FEBRUARY 1
- #define TM_MARCH 2
- #define TM_APRIL 3
- #define TM_MAY 4
- #define TM_JUNE 5
- #define TM_JULY 6
- #define TM_AUGUST 7
- #define TM_SEPTEMBER 8
- #define TM_OCTOBER 9
- #define TM_NOVEMBER 10
- #define TM_DECEMBER 11
-
- #define TM_YEAR_BASE 1900
-
- #define EPOCH_YEAR 1970
- #define EPOCH_WDAY TM_THURSDAY
-
- /*
- ** Accurate only for the past couple of centuries;
- ** that will probably do.
- */
-
- #define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0)
-
- int mon_lengths[2][MONS_PER_YEAR] = {
- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
- 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- };
-
- int year_lengths[2] = {
- DAYS_PER_NYEAR, DAYS_PER_LYEAR
- };
-
-
- cvttime(clock, tmp)
- time_t clock; /* seconds since 1 Jan 1970 */
- register struct tm * tmp;
- {
- register long days;
- register long rem;
- register int y;
- register int yleap;
- register int * ip;
- struct tm tm;
-
- days = (clock - tz.tz_minuteswest*SECS_PER_MIN) / SECS_PER_DAY;
- rem = (clock - tz.tz_minuteswest*SECS_PER_MIN) % SECS_PER_DAY;
- while (rem < 0) {
- rem += SECS_PER_DAY;
- --days;
- }
- while (rem >= SECS_PER_DAY) {
- rem -= SECS_PER_DAY;
- ++days;
- }
-
- tm.tm_hour = (int) (rem / SECS_PER_HOUR);
- rem = rem % SECS_PER_HOUR;
- tm.tm_min = (int) (rem / SECS_PER_MIN);
- tm.tm_sec = (int) (rem % SECS_PER_MIN);
-
- tm.tm_wday = (int) ((EPOCH_WDAY + days) % DAYS_PER_WEEK);
- if (tm.tm_wday < 0)
- tm.tm_wday += DAYS_PER_WEEK;
-
- y = EPOCH_YEAR;
- if (days >= 0) {
- for (;;) {
- yleap = isleap(y);
- if (days < (long) year_lengths[yleap])
- break;
- ++y;
- days = days - (long) year_lengths[yleap];
- }
- }
- else {
- do {
- --y;
- yleap = isleap(y);
- days = days + (long) year_lengths[yleap];
- } while (days < 0);
- }
- tm.tm_year = y - TM_YEAR_BASE;
- tm.tm_yday = (int) days;
-
- ip = mon_lengths[yleap];
- for (tm.tm_mon = 0;
- days >= (long) ip[tm.tm_mon];
- ++tm.tm_mon) {
- days = days - (long) ip[tm.tm_mon];
- }
- tm.tm_mday = (int) (days + 1);
- tm.tm_isdst = 0;
-
- *tmp = tm;
- }
-
- fmttime(timeptr, str)
- register struct tm *timeptr;
- char str[26];
- {
- static char wday_name[DAYS_PER_WEEK][4] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
- static char mon_name[MONS_PER_YEAR][4] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
-
- sprintf(str, "%s %s %d %d:%d:%d %d",
- wday_name[timeptr->tm_wday],
- mon_name[timeptr->tm_mon],
- timeptr->tm_mday, timeptr->tm_hour,
- timeptr->tm_min, timeptr->tm_sec,
- TM_YEAR_BASE + timeptr->tm_year);
- }
-
- print_time(fmt, clock)
- char * fmt;
- time_t clock;
- {
- struct tm tm;
- char timestr[26];
-
- cvttime(clock, &tm);
- fmttime(&tm, timestr);
- printf(fmt, timestr);
- }
-
- /*
- * Initialize the time of day.
- */
- #define SECYR ((unsigned)(365*SECS_PER_DAY)) /* per common year */
-
- /*
- * If the hardware clock does not keep the current year, it
- * sets the year to 1982. If there is no hardware clock at all,
- * the year will be about 1970.
- */
- #define NOYEAR ((1982 - EPOCH_YEAR) * SECYR + 3 * SECS_PER_DAY)
- /* 1972, 1976, 1980 were leap years */
-
- /*
- * Initialze the time of day register, based on the time base which is, e.g.
- * from a filesystem. Base provides the time to within six months,
- * and the time of year clock provides the rest.
- */
- inittodr(base)
- time_t base;
- {
- register u_int todr;
- long deltat;
- int year = EPOCH_YEAR;
-
- struct timeval cur_time, time;
-
- time.tv_usec = 0;
-
- print_time("Base is %s\n", base);
-
- if (base < 5*SECYR) {
- printf("WARNING: preposterous time in file system");
- time.tv_sec = 6*SECYR + 186*SECS_PER_DAY + SECS_PER_DAY/2;
- goto check;
- }
-
- get_time(&cur_time);
- boottime = cur_time;
-
- print_time("Current time is %s\n", cur_time.tv_sec);
- /*
- * If the hardware does not provide the year,
- * the time will be stuck at 1982. XXX
- */
- if (cur_time.tv_sec < NOYEAR) {
- printf("WARNING: hardware does not know what time it is");
- /*
- * Believe the time in the file system for lack of
- * anything better.
- */
- time.tv_sec = base;
- time.tv_usec = 0;
- goto check;
- }
-
- /*
- * Sneak to within 6 month of the time in the filesystem,
- * by starting with the time of the year suggested by the TODR,
- * and advancing through succesive years. Adding the number of
- * seconds in the current year takes us to the end of the current year
- * and then around into the next year to the same position.
- */
- time.tv_sec = cur_time.tv_sec - NOYEAR;
- while (time.tv_sec < base-SECYR/2) {
- if (isleap(year))
- time.tv_sec += SECS_PER_DAY;
- year++;
- time.tv_sec += SECYR;
- }
-
- /*
- * See if we gained/lost two or more days;
- * if so, assume something is amiss.
- */
- deltat = time.tv_sec - base;
- if (deltat < 0)
- deltat = -deltat;
- if (deltat < 2*SECS_PER_DAY) {
- /*
- * Time seems to correspond.
- */
- goto set_the_time;
- }
-
- printf("WARNING: clock %s %d days",
- time.tv_sec < base ? "lost" : "gained", deltat / SECS_PER_DAY);
- check:
- printf(" -- CHECK AND RESET THE DATE!\n");
- boottime.tv_sec = time.tv_sec;
-
- set_the_time:
- print_time("Time is set to %s\n", time.tv_sec);
- set_time(&time);
- }
-
-