|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1987 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Arthur Olson. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that the above copyright notice and this paragraph are ! 10: * duplicated in all such forms and that any documentation, ! 11: * advertising materials, and other materials related to such ! 12: * distribution and use acknowledge that the software was developed ! 13: * by the University of California, Berkeley. The name of the ! 14: * University may not be used to endorse or promote products derived ! 15: * from this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 17: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 18: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: */ ! 20: ! 21: #if defined(LIBC_SCCS) && !defined(lint) ! 22: static char sccsid[] = "@(#)ctime.c 5.14 (Berkeley) 7/6/88"; ! 23: #endif /* LIBC_SCCS and not lint */ ! 24: ! 25: #include "sys/param.h" ! 26: #include "sys/time.h" ! 27: #include "tzfile.h" ! 28: ! 29: char * ! 30: ctime(t) ! 31: time_t *t; ! 32: { ! 33: struct tm *localtime(); ! 34: char *asctime(); ! 35: ! 36: return(asctime(localtime(t))); ! 37: } ! 38: ! 39: /* ! 40: ** A la X3J11 ! 41: */ ! 42: ! 43: char * ! 44: asctime(timeptr) ! 45: register struct tm * timeptr; ! 46: { ! 47: static char wday_name[DAYS_PER_WEEK][3] = { ! 48: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ! 49: }; ! 50: static char mon_name[MONS_PER_YEAR][3] = { ! 51: "Jan", "Feb", "Mar", "Apr", "May", "Jun", ! 52: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ! 53: }; ! 54: static char result[26]; ! 55: ! 56: (void) sprintf(result, "%.3s %.3s%3d %02d:%02d:%02d %d\n", ! 57: wday_name[timeptr->tm_wday], ! 58: mon_name[timeptr->tm_mon], ! 59: timeptr->tm_mday, timeptr->tm_hour, ! 60: timeptr->tm_min, timeptr->tm_sec, ! 61: TM_YEAR_BASE + timeptr->tm_year); ! 62: return result; ! 63: } ! 64: ! 65: #ifndef TRUE ! 66: #define TRUE 1 ! 67: #define FALSE 0 ! 68: #endif /* !TRUE */ ! 69: ! 70: extern char * getenv(); ! 71: extern char * strcpy(); ! 72: extern char * strcat(); ! 73: struct tm * offtime(); ! 74: ! 75: struct ttinfo { /* time type information */ ! 76: long tt_gmtoff; /* GMT offset in seconds */ ! 77: int tt_isdst; /* used to set tm_isdst */ ! 78: int tt_abbrind; /* abbreviation list index */ ! 79: }; ! 80: ! 81: struct state { ! 82: int timecnt; ! 83: int typecnt; ! 84: int charcnt; ! 85: time_t ats[TZ_MAX_TIMES]; ! 86: unsigned char types[TZ_MAX_TIMES]; ! 87: struct ttinfo ttis[TZ_MAX_TYPES]; ! 88: char chars[TZ_MAX_CHARS + 1]; ! 89: }; ! 90: ! 91: static struct state s; ! 92: ! 93: static int tz_is_set; ! 94: ! 95: char * tzname[2] = { ! 96: "GMT", ! 97: "GMT" ! 98: }; ! 99: ! 100: #ifdef USG_COMPAT ! 101: time_t timezone = 0; ! 102: int daylight = 0; ! 103: #endif /* USG_COMPAT */ ! 104: ! 105: static long ! 106: detzcode(codep) ! 107: char * codep; ! 108: { ! 109: register long result; ! 110: register int i; ! 111: ! 112: result = 0; ! 113: for (i = 0; i < 4; ++i) ! 114: result = (result << 8) | (codep[i] & 0xff); ! 115: return result; ! 116: } ! 117: ! 118: static ! 119: tzload(name) ! 120: register char * name; ! 121: { ! 122: register int i; ! 123: register int fid; ! 124: ! 125: if (name == 0 && (name = TZDEFAULT) == 0) ! 126: return -1; ! 127: { ! 128: register char * p; ! 129: register int doaccess; ! 130: char fullname[MAXPATHLEN]; ! 131: ! 132: doaccess = name[0] == '/'; ! 133: if (!doaccess) { ! 134: if ((p = TZDIR) == 0) ! 135: return -1; ! 136: if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) ! 137: return -1; ! 138: (void) strcpy(fullname, p); ! 139: (void) strcat(fullname, "/"); ! 140: (void) strcat(fullname, name); ! 141: /* ! 142: ** Set doaccess if '.' (as in "../") shows up in name. ! 143: */ ! 144: while (*name != '\0') ! 145: if (*name++ == '.') ! 146: doaccess = TRUE; ! 147: name = fullname; ! 148: } ! 149: if (doaccess && access(name, 4) != 0) ! 150: return -1; ! 151: if ((fid = open(name, 0)) == -1) ! 152: return -1; ! 153: } ! 154: { ! 155: register char * p; ! 156: register struct tzhead * tzhp; ! 157: char buf[sizeof s]; ! 158: ! 159: i = read(fid, buf, sizeof buf); ! 160: if (close(fid) != 0 || i < sizeof *tzhp) ! 161: return -1; ! 162: tzhp = (struct tzhead *) buf; ! 163: s.timecnt = (int) detzcode(tzhp->tzh_timecnt); ! 164: s.typecnt = (int) detzcode(tzhp->tzh_typecnt); ! 165: s.charcnt = (int) detzcode(tzhp->tzh_charcnt); ! 166: if (s.timecnt > TZ_MAX_TIMES || ! 167: s.typecnt == 0 || ! 168: s.typecnt > TZ_MAX_TYPES || ! 169: s.charcnt > TZ_MAX_CHARS) ! 170: return -1; ! 171: if (i < sizeof *tzhp + ! 172: s.timecnt * (4 + sizeof (char)) + ! 173: s.typecnt * (4 + 2 * sizeof (char)) + ! 174: s.charcnt * sizeof (char)) ! 175: return -1; ! 176: p = buf + sizeof *tzhp; ! 177: for (i = 0; i < s.timecnt; ++i) { ! 178: s.ats[i] = detzcode(p); ! 179: p += 4; ! 180: } ! 181: for (i = 0; i < s.timecnt; ++i) ! 182: s.types[i] = (unsigned char) *p++; ! 183: for (i = 0; i < s.typecnt; ++i) { ! 184: register struct ttinfo * ttisp; ! 185: ! 186: ttisp = &s.ttis[i]; ! 187: ttisp->tt_gmtoff = detzcode(p); ! 188: p += 4; ! 189: ttisp->tt_isdst = (unsigned char) *p++; ! 190: ttisp->tt_abbrind = (unsigned char) *p++; ! 191: } ! 192: for (i = 0; i < s.charcnt; ++i) ! 193: s.chars[i] = *p++; ! 194: s.chars[i] = '\0'; /* ensure '\0' at end */ ! 195: } ! 196: /* ! 197: ** Check that all the local time type indices are valid. ! 198: */ ! 199: for (i = 0; i < s.timecnt; ++i) ! 200: if (s.types[i] >= s.typecnt) ! 201: return -1; ! 202: /* ! 203: ** Check that all abbreviation indices are valid. ! 204: */ ! 205: for (i = 0; i < s.typecnt; ++i) ! 206: if (s.ttis[i].tt_abbrind >= s.charcnt) ! 207: return -1; ! 208: /* ! 209: ** Set tzname elements to initial values. ! 210: */ ! 211: tzname[0] = tzname[1] = &s.chars[0]; ! 212: #ifdef USG_COMPAT ! 213: timezone = -s.ttis[0].tt_gmtoff; ! 214: daylight = 0; ! 215: #endif /* USG_COMPAT */ ! 216: for (i = 1; i < s.typecnt; ++i) { ! 217: register struct ttinfo * ttisp; ! 218: ! 219: ttisp = &s.ttis[i]; ! 220: if (ttisp->tt_isdst) { ! 221: tzname[1] = &s.chars[ttisp->tt_abbrind]; ! 222: #ifdef USG_COMPAT ! 223: daylight = 1; ! 224: #endif /* USG_COMPAT */ ! 225: } else { ! 226: tzname[0] = &s.chars[ttisp->tt_abbrind]; ! 227: #ifdef USG_COMPAT ! 228: timezone = -ttisp->tt_gmtoff; ! 229: #endif /* USG_COMPAT */ ! 230: } ! 231: } ! 232: return 0; ! 233: } ! 234: ! 235: static ! 236: tzsetkernel() ! 237: { ! 238: struct timeval tv; ! 239: struct timezone tz; ! 240: char *_tztab(); ! 241: ! 242: if (gettimeofday(&tv, &tz)) ! 243: return -1; ! 244: s.timecnt = 0; /* UNIX counts *west* of Greenwich */ ! 245: s.ttis[0].tt_gmtoff = tz.tz_minuteswest * -SECS_PER_MIN; ! 246: s.ttis[0].tt_abbrind = 0; ! 247: (void)strcpy(s.chars, _tztab(tz.tz_minuteswest, 0)); ! 248: tzname[0] = tzname[1] = s.chars; ! 249: #ifdef USG_COMPAT ! 250: timezone = tz.tz_minuteswest * 60; ! 251: daylight = tz.tz_dsttime; ! 252: #endif /* USG_COMPAT */ ! 253: return 0; ! 254: } ! 255: ! 256: static ! 257: tzsetgmt() ! 258: { ! 259: s.timecnt = 0; ! 260: s.ttis[0].tt_gmtoff = 0; ! 261: s.ttis[0].tt_abbrind = 0; ! 262: (void) strcpy(s.chars, "GMT"); ! 263: tzname[0] = tzname[1] = s.chars; ! 264: #ifdef USG_COMPAT ! 265: timezone = 0; ! 266: daylight = 0; ! 267: #endif /* USG_COMPAT */ ! 268: } ! 269: ! 270: void ! 271: tzset() ! 272: { ! 273: register char * name; ! 274: ! 275: tz_is_set = TRUE; ! 276: name = getenv("TZ"); ! 277: if (!name || *name) { /* did not request GMT */ ! 278: if (name && !tzload(name)) /* requested name worked */ ! 279: return; ! 280: if (!tzload((char *)0)) /* default name worked */ ! 281: return; ! 282: if (!tzsetkernel()) /* kernel guess worked */ ! 283: return; ! 284: } ! 285: tzsetgmt(); /* GMT is default */ ! 286: } ! 287: ! 288: struct tm * ! 289: localtime(timep) ! 290: time_t * timep; ! 291: { ! 292: register struct ttinfo * ttisp; ! 293: register struct tm * tmp; ! 294: register int i; ! 295: time_t t; ! 296: ! 297: if (!tz_is_set) ! 298: (void) tzset(); ! 299: t = *timep; ! 300: if (s.timecnt == 0 || t < s.ats[0]) { ! 301: i = 0; ! 302: while (s.ttis[i].tt_isdst) ! 303: if (++i >= s.timecnt) { ! 304: i = 0; ! 305: break; ! 306: } ! 307: } else { ! 308: for (i = 1; i < s.timecnt; ++i) ! 309: if (t < s.ats[i]) ! 310: break; ! 311: i = s.types[i - 1]; ! 312: } ! 313: ttisp = &s.ttis[i]; ! 314: /* ! 315: ** To get (wrong) behavior that's compatible with System V Release 2.0 ! 316: ** you'd replace the statement below with ! 317: ** tmp = offtime((time_t) (t + ttisp->tt_gmtoff), 0L); ! 318: */ ! 319: tmp = offtime(&t, ttisp->tt_gmtoff); ! 320: tmp->tm_isdst = ttisp->tt_isdst; ! 321: tzname[tmp->tm_isdst] = &s.chars[ttisp->tt_abbrind]; ! 322: tmp->tm_zone = &s.chars[ttisp->tt_abbrind]; ! 323: return tmp; ! 324: } ! 325: ! 326: struct tm * ! 327: gmtime(clock) ! 328: time_t * clock; ! 329: { ! 330: register struct tm * tmp; ! 331: ! 332: tmp = offtime(clock, 0L); ! 333: tzname[0] = "GMT"; ! 334: tmp->tm_zone = "GMT"; /* UCT ? */ ! 335: return tmp; ! 336: } ! 337: ! 338: static int mon_lengths[2][MONS_PER_YEAR] = { ! 339: 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ! 340: 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ! 341: }; ! 342: ! 343: static int year_lengths[2] = { ! 344: DAYS_PER_NYEAR, DAYS_PER_LYEAR ! 345: }; ! 346: ! 347: struct tm * ! 348: offtime(clock, offset) ! 349: time_t * clock; ! 350: long offset; ! 351: { ! 352: register struct tm * tmp; ! 353: register long days; ! 354: register long rem; ! 355: register int y; ! 356: register int yleap; ! 357: register int * ip; ! 358: static struct tm tm; ! 359: ! 360: tmp = &tm; ! 361: days = *clock / SECS_PER_DAY; ! 362: rem = *clock % SECS_PER_DAY; ! 363: rem += offset; ! 364: while (rem < 0) { ! 365: rem += SECS_PER_DAY; ! 366: --days; ! 367: } ! 368: while (rem >= SECS_PER_DAY) { ! 369: rem -= SECS_PER_DAY; ! 370: ++days; ! 371: } ! 372: tmp->tm_hour = (int) (rem / SECS_PER_HOUR); ! 373: rem = rem % SECS_PER_HOUR; ! 374: tmp->tm_min = (int) (rem / SECS_PER_MIN); ! 375: tmp->tm_sec = (int) (rem % SECS_PER_MIN); ! 376: tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYS_PER_WEEK); ! 377: if (tmp->tm_wday < 0) ! 378: tmp->tm_wday += DAYS_PER_WEEK; ! 379: y = EPOCH_YEAR; ! 380: if (days >= 0) ! 381: for ( ; ; ) { ! 382: yleap = isleap(y); ! 383: if (days < (long) year_lengths[yleap]) ! 384: break; ! 385: ++y; ! 386: days = days - (long) year_lengths[yleap]; ! 387: } ! 388: else do { ! 389: --y; ! 390: yleap = isleap(y); ! 391: days = days + (long) year_lengths[yleap]; ! 392: } while (days < 0); ! 393: tmp->tm_year = y - TM_YEAR_BASE; ! 394: tmp->tm_yday = (int) days; ! 395: ip = mon_lengths[yleap]; ! 396: for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) ! 397: days = days - (long) ip[tmp->tm_mon]; ! 398: tmp->tm_mday = (int) (days + 1); ! 399: tmp->tm_isdst = 0; ! 400: tmp->tm_zone = ""; ! 401: tmp->tm_gmtoff = offset; ! 402: return tmp; ! 403: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.