📄 tzset.c
字号:
/* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#ifndef lintstatic char *sccsid = "@(#)tzset.c 4.1 (ULTRIX) 7/3/90";#endif lint/************************************************************************ * * * Copyright (c) 1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * * 005 Jon Reeves, 16-Jan-1990 * Fix handling of DST with negative offset, mktime w/o rules * * 004 Jon Reeves, 20-Nov-1989 * Added missing set of timezone/daylight; added _last_tz_set * * 003 Ken Lesniak, 03-Nov-1989 * Conditionalized for X/Open * * 002 Ken Lesniak, 17-Jul-1989 * Moved tz_is_set flag here from ctime.c and set flag in tzset() * * 001 Ken Lesniak, 11-Apr-1989 * Moved here from ctime.c. * Added support for POSIX 1003.1 compliancy. * * Based on Berkeley ctime.c 1.2 ************************************************************************/#undef _POSIX_SOURCE /* namespace protection is deadly to this file */#include <sys/param.h>#include <sys/time.h>#include <tzfile.h>#include <string.h>#include <stdlib.h>#include "tzs.h"#ifndef TRUE#define TRUE 1#define FALSE 0#endifstruct state _tzs;int _tz_is_set = FALSE;char _last_tz_set[LAST_TZ_LEN]='\0';/* * For both system V and X/Open, the variables timezone and daylight * are defined as macros. This is because for X/Open, the names * must not be in the ANSI/POSIX name space. There is a special assembler * module with duplicate definitions for the names for those users * that really want to use them. */#ifdef SYSTEM_FIVE/* Ideally, the initial values of these should be unimportant, because *//* a program should call tzset() first before accessing them. But, *//* since they have always initialized this way, I'm sure there are *//* programs that exploit that fact. */#define TIMEZONE timezone#define DAYLIGHT daylighttime_t TIMEZONE = 5*60*60;int DAYLIGHT = 1;char *tzname[2] = {"EST", "EDT"};#else /* SYSTEM_FIVE */#ifdef _XOPEN_SOURCE#define TIMEZONE __timezone#define DAYLIGHT __daylighttime_t TIMEZONE;int DAYLIGHT;#endif /* _XOPEN_SOURCE */char *tzname[2] = {"GMT", "GMT"};#endif /* SYSTEM_FIVE */static longdetzcode(codep)char * codep;{ register long result; register int i; result = 0; for (i = 0; i < 4; ++i) result = (result << 8) | (codep[i] & 0xff); return result;}/* * Attempt to load time conversion information from a tzfile formatted file. */statictzload(name)register char * name;{ register int i; register int fid; int charcnt; int typecnt; if (name == 0 && (name = TZDEFAULT) == 0) return -1; { register char * p; register int doaccess; char fullname[MAXPATHLEN]; doaccess = name[0] == '/'; if (!doaccess) { if ((p = TZDIR) == 0) return -1; if ((strlen(p) + strlen(name) + 1) >= sizeof fullname) return -1; (void) strcpy(fullname, p); (void) strcat(fullname, "/"); (void) strcat(fullname, name); /* ** Set doaccess if '.' (as in "../") shows up in name. */ while (*name != '\0') if (*name++ == '.') doaccess = TRUE; name = fullname; } if (doaccess && access(name, 4) != 0) return -1; if ((fid = open(name, 0)) == -1) return -1; } { register char * p; register struct tzhead * tzhp; char buf[sizeof _tzs]; i = read(fid, buf, sizeof buf); if (close(fid) != 0 || i < sizeof *tzhp) return -1; tzhp = (struct tzhead *) buf; _tzs.timecnt = (int) detzcode(tzhp->tzh_timecnt); typecnt = (int) detzcode(tzhp->tzh_typecnt); charcnt = (int) detzcode(tzhp->tzh_charcnt); if (_tzs.timecnt > TZ_MAX_TIMES || typecnt == 0 || typecnt > TZ_MAX_TYPES || charcnt > TZ_MAX_CHARS) return -1; if (i < sizeof *tzhp + _tzs.timecnt * (4 + sizeof (char)) + typecnt * (4 + 2 * sizeof (char)) + charcnt * sizeof (char)) return -1; p = buf + sizeof *tzhp; for (i = 0; i < _tzs.timecnt; ++i) { _tzs.ats[i] = detzcode(p); p += 4; } for (i = 0; i < _tzs.timecnt; ++i) _tzs.types[i] = (unsigned char) *p++; for (i = 0; i < typecnt; ++i) { register struct ttinfo * ttisp; ttisp = &_tzs.ttis[i]; ttisp->tt_gmtoff = detzcode(p); p += 4; ttisp->tt_isdst = (unsigned char) *p++; ttisp->tt_abbrind = (unsigned char) *p++; } for (i = 0; i < charcnt; ++i) _tzs.chars[i] = *p++; _tzs.chars[i] = '\0'; /* ensure '\0' at end */ } /* ** Check that all the local time type indices are valid. */ for (i = 0; i < _tzs.timecnt; ++i) if (_tzs.types[i] >= typecnt) return -1; /* ** Check that all abbreviation indices are valid. */ for (i = 0; i < typecnt; ++i) if (_tzs.ttis[i].tt_abbrind >= charcnt) return -1; /* ** Set tzname elements to initial values. */ tzname[0] = tzname[1] = _tzs.chars;#if defined(SYSTEM_FIVE) || defined(_XOPEN_SOURCE) TIMEZONE = -_tzs.ttis[0].tt_gmtoff; DAYLIGHT = 0;#endif for (i = 1; i < typecnt; ++i) { register struct ttinfo * ttisp; ttisp = &_tzs.ttis[i]; if (ttisp->tt_isdst) { tzname[1] = &_tzs.chars[ttisp->tt_abbrind];#if defined(SYSTEM_FIVE) || defined(_XOPEN_SOURCE) DAYLIGHT = 1;#endif } else { tzname[0] = &_tzs.chars[ttisp->tt_abbrind];#if defined(SYSTEM_FIVE) || defined(_XOPEN_SOURCE) TIMEZONE = -ttisp->tt_gmtoff;#endif } } return 0;}/* * Set time conversion information based on GMT. */statictzsetgmt(){ _tzs.timecnt = 0; _tzs.ttis[0].tt_gmtoff = 0; _tzs.ttis[0].tt_isdst = 0; _tzs.ttis[0].tt_abbrind = 0; tzname[0] = tzname[1] = strcpy(_tzs.chars, "GMT");#if defined(SYSTEM_FIVE) || defined(_XOPEN_SOURCE) TIMEZONE = 0; DAYLIGHT = 0;#endif}/* * The following tables are used for setting the time conversion * information in a manner which is backwards compatible with older * versions of BSD and System V ctime.c. * * Please, DO NOT FIX THE TABLES. They may be wrong, but the must match * the behavior of the old routines. * * Now, they are only used if the tzfile formatted files cannot be * accessed, as is the case if the program is run on a system which * has not yet been upgraded. */struct dstab { /* describe change to and from dst */ int dayyr; /* year being described */ int daylb; /* begin: first Sunday after change */ int dayle; /* end: first Sunday after chagne */};struct dayrule { int dst_type; /* number obtained from system */ int dst_hrs; /* hours to add when dst on */ struct dstab * dst_rules; /* one of the above */ enum {STH, NTH} dst_hemi; /* southern, northern hemisphere */};static struct dstab usdaytab[] = { 0, 96, 303, /* all other years: beg Apr - end Oct */ 1974, 5, 333, /* 1974: Jan 6 - last Sun. in Nov */ 1975, 58, 303, /* 1975: Last Sun. in Feb - last Sun in Oct */ 1976, 119, 303, /* 1976: end Apr - end Oct */ 1977, 119, 303, /* 1977: end Apr - end Oct */ 1978, 119, 303, /* 1978: end Apr - end Oct */ 1979, 119, 303, /* 1979: end Apr - end Oct */ 1980, 119, 303, /* 1980: end Apr - end Oct */ 1981, 119, 303, /* 1981: end Apr - end Oct */ 1982, 119, 303, /* 1982: end Apr - end Oct */ 1983, 119, 303, /* 1983: end Apr - end Oct */ 1984, 119, 303, /* 1984: end Apr - end Oct */ 1985, 119, 303, /* 1985: end Apr - end Oct */ 1986, 119, 303, /* 1986: end Apr - end Oct */};#ifdef SYSTEM_FIVEstatic struct dayrule dayrules[] ={ DST_USA, 1, usdaytab, NTH, -1};#elsestatic struct dstab ausdaytab[] = { 0, 65, 303, /* others: -> Mar 7, Oct 31 -> */ 1970, 0, 400, /* 1970: no daylight saving at all */ 1971, 0, 303, /* 1971: daylight saving from Oct 31 */ 1972, 58, 303, /* 1972: Jan 1 -> Feb 27 & Oct 31 -> dec 31 */};/* * The European tables ... based on hearsay * Believed correct for: * WE: Great Britain, Ireland, Portugal * ME: Belgium, Luxembourg, Netherlands, Denmark, Norway, * Austria, Poland, Czechoslovakia, Sweden, Switzerland, * DDR, DBR, France, Spain, Hungary, Italy, Jugoslavia * Eastern European dst is unknown, we'll make it ME until someone speaks up. * EE: Bulgaria, Finland, Greece, Rumania, Turkey, Western Russia */static struct dstab wedaytab[] = { 0, 86, 303, /* others: end March - end Oct */ 1983, 86, 303, /* 1983: end March - end Oct */ 1984, 86, 303, /* 1984: end March - end Oct */ 1985, 86, 303, /* 1985: end March - end Oct */};static struct dstab medaytab[] = { 0, 86, 272, /* others: saving end March - end Sep */ 1983, 86, 272, /* 1983: end March - end Sep */ 1984, 86, 272, /* 1984: end March - end Sep */ 1985, 86, 272, /* 1985: end March - end Sep */};static struct dayrule dayrules[] = { DST_USA, 1, usdaytab, NTH, DST_AUST, 1, ausdaytab, STH, DST_WET, 1, wedaytab, NTH, DST_MET, 1, medaytab, NTH, DST_EET, 1, medaytab, NTH, -1,};#endif/* * This routine sets the time conversion information in a way which produces * compatible behavior of localtime() with older versions. */statictzset_compat(dr, sw, std, dst)struct dayrule *dr;int sw; /* seconds west of gmt */char *std; /* standard time zone name */char *dst; /* daylight savings time zone name */{ register int tc; register time_t ytt; register int tday; register int wday; int y; int ly; struct dstab *dp, *dp0, *dpyr; int i; int chars; int type; _tzs.timecnt = 0; /* Copy "std" designation */ tzname[0] = tzname[1] = _tzs.chars; chars = 0; while (_tzs.chars[chars++] = *std++) ; /* Fill in the time type information */ _tzs.ttis[0].tt_gmtoff = -sw; _tzs.ttis[0].tt_isdst = 0; _tzs.ttis[0].tt_abbrind = 0; /* If "dst" is specified, create the transtion time table */ if (dr->dst_type >= 0) { /* Fill in the time type information */ _tzs.ttis[1].tt_gmtoff = (dr->dst_hrs * SECS_PER_HOUR) - sw; _tzs.ttis[1].tt_abbrind = chars; _tzs.ttis[1].tt_isdst = 1; /* Copy the "dst" designation */ tzname[1] += chars; while (_tzs.chars[chars++] = *dst++) ; /* Now for every year that is representable by a time_t */ /* value, create a pair of transition times. One for the */ /* start and one for the end of summer time. The transition */ /* times are used by localtime() in determining whether */ /* standard or summer time is in effect. */ /* The following *_year symbols, represent the minimum */ /* and maximum whole years representable by the time_t */ /* type. These definitions assume that time_t is a */ /* signed long */#define t_min_year (time_t)0x8017e880 /* Minimum year in time_t format */#define min_year 1902 /* Minimum year */#define max_year 2037 /* Maximum year */#define feb28_day0 (31 + 28 - 1) /* Julian day (0 based) of Feb 28th */ tc = 0; ytt = t_min_year; dp0 = dr->dst_rules; dpyr = dp0 + 1; /* Create a pair of transition times for each year */ for (y = min_year; y < max_year; y++) { ly = isleap(y); /* Point to the begin and end days for this year */ dp = (y == dpyr->dayyr ? dpyr++ : dp0); tday = dp->daylb; for (i = 0; i < 2; i++) { /* Compute the transition time */ if (ly && tday >= feb28_day0) tday++; wday = ((ytt / SECS_PER_DAY) + EPOCH_WDAY + tday) % DAYS_PER_WEEK; if (wday < 0) wday += DAYS_PER_WEEK; tday -= wday; /* Store the transition time and type index */ type = i; if (dr->dst_hemi != STH) type ^= 1; _tzs.ats[tc] = ytt + (tday * SECS_PER_DAY) + (2 * SECS_PER_HOUR) - _tzs.ttis[type ^ 1].tt_gmtoff; _tzs.types[tc] = type; tc++; tday = dp->dayle; }; ytt += DAYS_PER_NYEAR * SECS_PER_DAY; if (ly) ytt += SECS_PER_DAY; }; _tzs.timecnt = tc; }; }/* * Set the time conversion information based on the kernel's idea * of local time. Changes to and from daylight savings time are * handled in a backwards compatible fashion. */statictzsetkernel(){ time_t sw; /* seconds west */ register struct dayrule *dr; struct timeval tv; struct timezone tz; char *_tztab();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -