Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <stdlib.h>
2
#include <sys/types.h>
3
#include <fcntl.h>
4
#include <time.h>
5
#include <ctype.h>
6
#include <string.h>
7
#include <unistd.h>
8
 
9
#define TZFILE	"/etc/TZ"
10
 
11
static char TZ[128];
12
static char std[32] = "GMT0";
13
static char dst[32];
14
char *tzname[2] = {
15
	std, dst
16
};
17
time_t tzoffset, tzdstoffset;
18
int tzdst = 0;
19
 
20
static int
21
offset(char *env, time_t *off)
22
{
23
	int n, sign;
24
	size_t len, retlen;
25
 
26
	retlen = 0;
27
	sign = 1;
28
	/*
29
	 * strictly, no sign is allowed in the 'time' part of the
30
	 * dst start/stop rules, but who cares?
31
	 */
32
	if (*env == '-' || *env == '+') {
33
		if (*env++ == '-')
34
			sign = -1;
35
		retlen++;
36
	}
37
	if ((len = strspn(env, ":0123456789")) == 0)
38
		return 0;
39
	retlen += len;
40
	for (*off = 0; len && isdigit(*env); len--)		/* hours */
41
		*off = *off*10 + (*env++ - '0')*60*60;
42
	if (len) {
43
		if (*env++ != ':')
44
			return 0;
45
		len--;
46
	}
47
	for (n = 0; len && isdigit(*env); len--)		/* minutes */
48
		n = n*10 + (*env++ - '0')*60;
49
	*off += n;
50
	if (len) {
51
		if (*env++ != ':')
52
			return 0;
53
		len--;
54
	}
55
	for (n = 0; len && isdigit(*env); len--)		/* seconds */
56
		n = n*10 + (*env++ - '0');
57
	*off = (*off + n)*sign;
58
	return retlen;
59
}
60
 
61
/*
62
 * TZ=stdoffset[dst[offset][,start[/time],end[/time]]]
63
 */
64
void
65
tzset(void)
66
{
67
	char *env, *p, envbuf[128];
68
	int fd, i;
69
	size_t len, retlen;
70
	time_t off;
71
 
72
	/*
73
	 * get the TZ environment variable and check for validity.
74
	 * the implementation-defined manner for dealing with the
75
	 * leading ':' format is to reject it.
76
	 * if it's ok, stash a copy away for quick comparison next time.
77
	 */
78
	if ((env = getenv("TZ")) == 0) {
79
		if ((fd = open(TZFILE, O_RDONLY)) == -1)
80
			return;
81
		if (read(fd, envbuf, sizeof(envbuf)-1) == -1) {
82
			close(fd);
83
			return;
84
		}
85
		close(fd);
86
		for (i = 0; i < sizeof(envbuf); i++) {
87
			if (envbuf[i] != '\n')
88
				continue;
89
			envbuf[i] = '\0';
90
			break;
91
		}
92
		env = envbuf;
93
	}
94
	if (strcmp(env, TZ) == 0)
95
		return;
96
	if (*env == 0 || *env == ':')
97
		return;
98
	strncpy(TZ, env, sizeof(TZ)-1);
99
	TZ[sizeof(TZ)-1] = 0;
100
	/*
101
	 * get the 'std' string.
102
	 * before committing, check there is a valid offset.
103
	 */
104
	if ((len = strcspn(env, ":0123456789,-+")) == 0)
105
		return;
106
	if ((retlen = offset(env+len, &off)) == 0)
107
		return;
108
	for (p = std, i = len+retlen; i; i--)
109
		*p++ = *env++;
110
	*p = 0;
111
	tzoffset = -off;
112
	/*
113
	 * get the 'dst' string (if any).
114
	 */
115
	if (*env == 0 || (len = strcspn(env, ":0123456789,-+")) == 0)
116
		return;
117
	for (p = dst; len; len--)
118
		*p++ = *env++;
119
	*p = 0;
120
	/*
121
	 * optional dst offset.
122
	 * default is one hour.
123
	 */
124
	tzdst = 1;
125
	if (retlen = offset(env+len, &off)) {
126
		tzdstoffset = -off;
127
		env += retlen;
128
	}
129
	else
130
		tzdstoffset = tzoffset + 60*60;
131
	/*
132
	 * optional rule(s) for start/end of dst.
133
	 */
134
	if (*env == 0 || *env != ',' || *(env+1) == 0)
135
		return;
136
	env++;
137
	/*
138
	 * we could go on...
139
	 * but why bother?
140
	 */
141
	USED(env);
142
}