Annotation of 43BSDTahoe/lib/libc/gen/ctime.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.